@leofcoin/peernet 0.11.24 → 0.11.27

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 (39) hide show
  1. package/dist/browser/peernet.js +1873 -1849
  2. package/dist/commonjs/dht-response.js +2 -9
  3. package/dist/commonjs/dht.js +2 -9
  4. package/dist/commonjs/{http-b45d1330.js → http-997ec597.js} +1 -1
  5. package/dist/commonjs/peernet-message.js +2 -9
  6. package/dist/commonjs/peernet.js +27 -22
  7. package/dist/commonjs/request.js +2 -9
  8. package/dist/commonjs/response.js +2 -9
  9. package/dist/module/peernet.js +18 -544
  10. package/package.json +3 -2
  11. package/rollup.config.js +3 -11
  12. package/src/handlers/message.js +1 -1
  13. package/src/messages/chat-message.js +2 -2
  14. package/src/messages/data-response.js +2 -2
  15. package/src/messages/data.js +2 -2
  16. package/src/messages/dht-response.js +2 -2
  17. package/src/messages/dht.js +2 -2
  18. package/src/messages/peer-response.js +2 -2
  19. package/src/messages/peer.js +2 -2
  20. package/src/messages/peernet-message.js +2 -2
  21. package/src/messages/ps.js +2 -2
  22. package/src/messages/request.js +2 -2
  23. package/src/messages/response.js +2 -2
  24. package/src/peernet.js +1 -2
  25. package/src/utils/utils.js +2 -1
  26. package/dist/commonjs/codec-45796010.js +0 -215
  27. package/dist/commonjs/codec-format-interface.js +0 -206
  28. package/dist/commonjs/codec.js +0 -11
  29. package/dist/commonjs/hash.js +0 -164
  30. package/src/codec/codec-format-interface.js +0 -194
  31. package/src/codec/codec.js +0 -124
  32. package/src/codec/codecs.js +0 -79
  33. package/src/hash/hash.js +0 -152
  34. package/src/http/api.js +0 -115
  35. package/src/http/client/api.js +0 -41
  36. package/src/http/client/client.js +0 -10
  37. package/src/http/client/http-client.js +0 -44
  38. package/src/http/client/storage.js +0 -36
  39. package/src/http/http.js +0 -28
@@ -13,17 +13,15 @@ __webpack_require__(307);
13
13
  var pako = __webpack_require__(9591);
14
14
  var LeofcoinStorage = __webpack_require__(1116);
15
15
  var protons = __webpack_require__(7160);
16
- var bs32 = __webpack_require__(103);
17
- var bs58 = __webpack_require__(158);
18
- var isHex = __webpack_require__(6187);
19
- var varint = __webpack_require__(4676);
20
- var createKeccakHash = __webpack_require__(5811);
16
+ var codecFormatInterface = __webpack_require__(5698);
21
17
  var MultiWallet$1 = __webpack_require__(9755);
22
18
  var bs58check = __webpack_require__(8334);
23
19
  var bip32 = __webpack_require__(7786);
20
+ var createKeccakHash = __webpack_require__(5811);
24
21
  var ecc = __webpack_require__(5892);
25
22
  var Mnemonic = __webpack_require__(4911);
26
23
  var MultiSignature = __webpack_require__(6697);
24
+ var varint = __webpack_require__(4676);
27
25
  var randombytes = __webpack_require__(1798);
28
26
 
29
27
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -49,18 +47,15 @@ function _interopNamespace(e) {
49
47
  var pako__default = /*#__PURE__*/_interopDefaultLegacy(pako);
50
48
  var LeofcoinStorage__default = /*#__PURE__*/_interopDefaultLegacy(LeofcoinStorage);
51
49
  var protons__default = /*#__PURE__*/_interopDefaultLegacy(protons);
52
- var bs32__default = /*#__PURE__*/_interopDefaultLegacy(bs32);
53
- var bs58__default = /*#__PURE__*/_interopDefaultLegacy(bs58);
54
- var isHex__default = /*#__PURE__*/_interopDefaultLegacy(isHex);
55
- var varint__default = /*#__PURE__*/_interopDefaultLegacy(varint);
56
- var createKeccakHash__default = /*#__PURE__*/_interopDefaultLegacy(createKeccakHash);
57
50
  var MultiWallet__default = /*#__PURE__*/_interopDefaultLegacy(MultiWallet$1);
58
51
  var bs58check__default = /*#__PURE__*/_interopDefaultLegacy(bs58check);
59
52
  var bs58check__namespace = /*#__PURE__*/_interopNamespace(bs58check);
60
53
  var bip32__namespace = /*#__PURE__*/_interopNamespace(bip32);
54
+ var createKeccakHash__default = /*#__PURE__*/_interopDefaultLegacy(createKeccakHash);
61
55
  var ecc__default = /*#__PURE__*/_interopDefaultLegacy(ecc);
62
56
  var Mnemonic__default = /*#__PURE__*/_interopDefaultLegacy(Mnemonic);
63
57
  var MultiSignature__default = /*#__PURE__*/_interopDefaultLegacy(MultiSignature);
58
+ var varint__default = /*#__PURE__*/_interopDefaultLegacy(varint);
64
59
  var randombytes__default = /*#__PURE__*/_interopDefaultLegacy(randombytes);
65
60
 
66
61
  /* socket-request-client version 1.6.3 */
@@ -454,10 +449,20 @@ class Peer {
454
449
  async #init() {
455
450
  try {
456
451
  const iceServers = [{
457
- urls: 'stun:stun.l.google.com:19302' // Google's public STUN server
452
+ urls: 'stun:stun.l.google.com:19302' // Google's public STUN server
453
+ }, {
454
+ urls: "stun:openrelay.metered.ca:80",
455
+ }, {
456
+ urls: "turn:openrelay.metered.ca:443",
457
+ username: "openrelayproject",
458
+ credential: "openrelayproject",
459
+ }, {
460
+ urls: "turn:openrelay.metered.ca:443?transport=tcp",
461
+ username: "openrelayproject",
462
+ credential: "openrelayproject",
458
463
  }];
459
464
 
460
- this.#connection = new wrtc.RTCPeerConnection();
465
+ this.#connection = new wrtc.RTCPeerConnection({iceServers});
461
466
 
462
467
  this.#connection.onicecandidate = ({ candidate }) => {
463
468
  if (candidate) {
@@ -771,1425 +776,891 @@ message PeernetMessage {
771
776
  optional string id = 5;
772
777
  }`;
773
778
 
774
- var codecs = {
775
- // just a hash
776
- 'disco-hash': {
777
- codec: parseInt('30', 16),
778
- hashAlg: 'dbl-keccak-256', // ,
779
- // testnet: 'olivia'
780
- },
781
- 'peernet-peer-response': {
782
- codec: parseInt('707072', 16),
783
- hashAlg: 'keccak-256',
784
- },
785
- 'peernet-peer': {
786
- codec: parseInt('7070', 16),
787
- hashAlg: 'keccak-256',
788
- },
789
- 'peernet-dht': {
790
- codec: parseInt('706468', 16),
791
- hashAlg: 'keccak-256',
792
- },
793
- 'peernet-dht-response': {
794
- codec: parseInt('706472', 16),
795
- hashAlg: 'keccak-256',
796
- },
797
- // data
798
- 'peernet-data': {
799
- codec: parseInt('706461', 16),
800
- hashAlg: 'keccak-256',
801
- },
802
- 'peernet-data-response': {
803
- codec: parseInt('70646172', 16),
804
- hashAlg: 'keccak-256',
805
- },
806
- // message
807
- 'peernet-message': {
808
- codec: parseInt('706d65', 16),
809
- hashAlg: 'keccak-256',
810
- },
811
- // pubsub
812
- 'peernet-ps': {
813
- codec: parseInt('707073', 16),
814
- hashAlg: 'keccak-256',
815
- },
816
- 'peernet-response': {
817
- codec: parseInt('7072', 16),
818
- hashAlg: 'keccak-256',
819
- },
820
- 'peernet-request': {
821
- codec: parseInt('707271', 16),
822
- hashAlg: 'keccak-256',
823
- },
824
- // normal block
825
- 'leofcoin-block': {
826
- codec: parseInt('6c62', 16),
827
- hashAlg: 'dbl-keccak-512', // ,
828
- // testnet: 'olivia'
829
- },
830
- 'leofcoin-tx': {
831
- codec: parseInt('6c74', 16),
832
- hashAlg: 'dbl-keccak-512', // ,
833
- // testnet: 'olivia'
834
- },
835
- // itx
836
- 'leofcoin-itx': {
837
- codec: parseInt('6c69', 16),
838
- hashAlg: 'keccak-512', // ,
839
- // testnet: 'olivia'
840
- },
841
- // peer reputation
842
- 'leofcoin-pr': {
843
- codec: parseInt('6c70', 16),
844
- hashAlg: 'keccak-256', // ,
845
- // testnet: 'olivia'
846
- },
847
- // chat message
848
- 'chat-message': {
849
- codec: parseInt('636d', 16),
850
- hashAlg: 'dbl-keccak-256',
851
- },
852
- };
853
-
854
- class PeernetCodec {
855
- get codecs() {
856
- return {...globalThis.peernet.codecs, ...codecs}
779
+ class PeernetMessage extends codecFormatInterface.FormatInterface {
780
+ get keys() {
781
+ return ['data', 'signature', 'from', 'to', 'id']
857
782
  }
858
- constructor(buffer) {
859
- if (buffer) {
860
- if (buffer instanceof Uint8Array) {
861
- const codec = varint__default["default"].decode(buffer);
862
- const name = this.getCodecName(codec);
863
- if (name) {
864
- this.name = name;
865
- this.encoded = buffer;
866
- this.decode(buffer);
867
- } else {
868
- this.encode(buffer);
869
- }
870
- } else if (buffer instanceof ArrayBuffer) {
871
- const encoded = new Uint8Array(buffer.byteLength);
872
783
 
873
- for (let i = 0; i < buffer.byteLength; i++) {
874
- encoded[i] = buffer[i];
875
- }
876
- this.encoded = encoded;
877
- // this.encoded = new Uint8Array(buffer, buffer.byteOffset, buffer.byteLength)
878
- this.decode(buffer);
879
- return
880
- }
881
- if (typeof buffer === 'string') {
882
- if (this.codecs[buffer]) this.fromName(buffer);
883
- else if (isHex__default["default"](buffer)) this.fromHex(buffer);
884
- else if (bs32__default["default"].isBase32(buffer)) this.fromBs32(buffer);
885
- else if (bs58__default["default"].isBase58(buffer)) this.fromBs58(buffer);
886
- else throw new Error(`unsupported string ${buffer}`)
887
- }
888
- if (!isNaN(buffer)) if (this.codecs[this.getCodecName(buffer)]) this.fromCodec(buffer);
889
- }
784
+ constructor(buffer) {
785
+ const name = 'peernet-message';
786
+ super(buffer, protons__default["default"](proto$a).PeernetMessage, {name});
890
787
  }
891
-
892
- fromEncoded(encoded) {
893
- const codec = varint__default["default"].decode(encoded);
894
- const name = this.getCodecName(codec);
895
- this.name = name;
896
- this.encoded = encoded;
897
- this.decode(encoded);
788
+ }
789
+
790
+ var proto$9 = `
791
+ // PeernetDHTMessage
792
+ message PeernetDHTMessage {
793
+ required string hash = 1;
794
+ optional string store = 2;
795
+ }
796
+ `;
797
+
798
+ /**
799
+ * @example `
800
+ new DHTMessage(hash, store)
801
+ // store = optional if not set, peernet checks every store
802
+ let message = new DHTMessage('hashmvbs124xcfd...', 'transaction')
803
+ message = new DHTMessage('hashmvbs124xcfd...', 'block')
804
+ `
805
+ */
806
+ class DHTMessage extends codecFormatInterface.FormatInterface {
807
+ /**
808
+ *
809
+ */
810
+ get keys() {
811
+ return ['hash', 'store']
898
812
  }
899
813
 
900
- fromHex(hex) {
901
- this.encoded = Buffer.from(hex, 'hex');
902
- this.decode();
814
+ constructor(data) {
815
+ const name = 'peernet-dht';
816
+ super(data, protons__default["default"](proto$9).PeernetDHTMessage, {name});
903
817
  }
904
-
905
- fromBs32(input) {
906
- this.encoded = bs32__default["default"].decode(input);
907
- this.decode();
818
+ }
819
+
820
+ var proto$8 = `
821
+ // PeernetDHTMessageResponse
822
+ message PeernetDHTMessageResponse {
823
+ required string hash = 1;
824
+ required bool has = 2;
825
+ }
826
+ `;
827
+
828
+ class DHTMessageResponse extends codecFormatInterface.FormatInterface {
829
+ get keys() {
830
+ return ['hash', 'has']
908
831
  }
909
832
 
910
- fromBs58(input) {
911
- this.encoded = bs58__default["default"].decode(input);
912
- this.decode();
833
+ constructor(data) {
834
+ const name = 'peernet-dht-response';
835
+ super(data, protons__default["default"](proto$8).PeernetDHTMessageResponse, {name});
913
836
  }
914
-
915
- getCodec(name) {
916
- return this.codecs[name].codec
837
+ }
838
+
839
+ var proto$7 = `
840
+ // PeernetDataMessage
841
+ message PeernetDataMessage {
842
+ required string hash = 1;
843
+ optional string store = 2;
844
+ }
845
+ `;
846
+
847
+ /**
848
+ * @extends {CodecFormat}
849
+ */
850
+ class DataMessage extends codecFormatInterface.FormatInterface {
851
+ get keys() {
852
+ return ['hash', 'store']
917
853
  }
918
-
919
- getCodecName(codec) {
920
- return Object.keys(this.codecs).reduce((p, c) => {
921
- const item = this.codecs[c];
922
- if (item.codec === codec) return c;
923
- else return p;
924
- }, undefined)
854
+ /**
855
+ * @param {Buffer|String|Object|DataMessage} data - The data needed to create the DataMessage
856
+ */
857
+ constructor(data) {
858
+ super(data, protons__default["default"](proto$7).PeernetDataMessage, {name: 'peernet-data'});
925
859
  }
926
-
927
- getHashAlg(name) {
928
- return this.codecs[name].hashAlg
860
+ }
861
+
862
+ var proto$6 = `
863
+ // PsMessage
864
+ message PsMessage {
865
+ required bytes data = 1;
866
+ required bytes topic = 2;
867
+ }`;
868
+
869
+ class PsMessage extends codecFormatInterface.FormatInterface {
870
+ get keys() {
871
+ return ['data', 'topic']
929
872
  }
930
873
 
931
- fromCodec(codec) {
932
- this.name = this.getCodecName(codec);
933
- this.hashAlg = this.getHashAlg(this.name);
934
-
935
- this.codec = this.getCodec(this.name);
936
- this.codecBuffer = varint__default["default"].encode(codec);
874
+ constructor(buffer) {
875
+ const name = 'peernet-ps';
876
+ super(buffer, protons__default["default"](proto$6).PsMessage, {name});
937
877
  }
938
-
939
- fromName(name) {
940
- const codec = this.getCodec(name);
941
- this.name = name;
942
- this.codec = codec;
943
- this.hashAlg = this.getHashAlg(name);
944
- this.codecBuffer = varint__default["default"].encode(codec);
878
+ }
879
+
880
+ var proto$5 = `
881
+ // PeernetPeerMessage
882
+ message PeernetPeerMessage {
883
+ required string id = 1;
884
+ }
885
+ `;
886
+
887
+ class PeerMessage extends codecFormatInterface.FormatInterface {
888
+ get keys() {
889
+ return ['id']
945
890
  }
946
891
 
947
- toBs32() {
948
- this.encode();
949
- return bs32__default["default"].encode(this.encoded)
892
+ constructor(data) {
893
+ const name = 'peernet-peer';
894
+ super(data, protons__default["default"](proto$5).PeernetPeerMessage, {name});
950
895
  }
951
-
952
- toBs58() {
953
- this.encode();
954
- return bs58__default["default"].encode(this.encoded)
896
+ }
897
+
898
+ var proto$4 = `
899
+ // PeernetRequestMessage
900
+ message PeernetRequestMessage {
901
+ required string request = 1;
902
+ }
903
+ `;
904
+
905
+ class RequestMessage extends codecFormatInterface.FormatInterface {
906
+ get keys() {
907
+ return ['request']
955
908
  }
956
909
 
957
- toHex() {
958
- return this.encoded.toString('hex')
910
+ constructor(data) {
911
+ const name = 'peernet-request';
912
+ super(data, protons__default["default"](proto$4).PeernetRequestMessage, {name});
959
913
  }
960
-
961
- decode() {
962
- const codec = varint__default["default"].decode(this.encoded);
963
- this.fromCodec(codec);
914
+ }
915
+
916
+ var proto$3 = `
917
+ // PeernetResponseMessage
918
+ message PeernetResponseMessage {
919
+ required bytes response = 1;
920
+ }
921
+ `;
922
+
923
+ class ResponseMessage extends codecFormatInterface.FormatInterface {
924
+ get keys() {
925
+ return ['response']
964
926
  }
965
927
 
966
- encode() {
967
- const codec = varint__default["default"].encode(this.decoded);
968
- this.encoded = codec;
969
- return this.encoded
928
+ constructor(data) {
929
+ const name = 'peernet-response';
930
+ super(data, protons__default["default"](proto$3).PeernetResponseMessage, {name});
970
931
  }
971
932
  }
972
933
 
973
- class PeernetHash {
974
- constructor(buffer, options = {}) {
975
- if (options.name) this.name = options.name;
976
- else this.name = 'disco-hash';
977
- if (options.codecs) this.codecs = options.codecs;
978
- if (buffer) {
979
- if (buffer instanceof Uint8Array) {
980
- this.discoCodec = new PeernetCodec(buffer, this.codecs);
981
- const name = this.discoCodec.name;
982
-
983
- if (name) {
984
- this.name = name;
985
- this.decode(buffer);
986
- } else {
987
- this.encode(buffer);
988
- }
989
- }
990
-
991
- if (typeof buffer === 'string') {
992
- if (isHex__default["default"](buffer)) this.fromHex(buffer);
993
- if (bs32__default["default"].isBase32(buffer)) this.fromBs32(buffer);
994
- else if (bs58__default["default"].isBase58(buffer)) this.fromBs58(buffer);
995
- else throw new Error(`unsupported string ${buffer}`)
996
- } else if (typeof buffer === 'object') this.fromJSON(buffer);
997
- }
934
+ var proto$2 = `
935
+ // PeernetPeerMessageResponse
936
+ message PeernetPeerMessageResponse {
937
+ required string id = 1;
938
+ }
939
+ `;
940
+
941
+ class PeerMessageResponse extends codecFormatInterface.FormatInterface {
942
+ get keys() {
943
+ return ['id']
998
944
  }
999
945
 
1000
- get prefix() {
1001
- const length = this.length;
1002
- const uint8Array = new Uint8Array(length.length + this.discoCodec.codecBuffer.length);
1003
- uint8Array.set(length);
1004
- uint8Array.set(this.discoCodec.codecBuffer, length.length);
1005
-
1006
- return uint8Array
946
+ constructor(data) {
947
+ const name = 'peernet-peer-response';
948
+ super(data, protons__default["default"](proto$2).PeernetPeerMessageResponse, {name});
1007
949
  }
1008
-
1009
- get length() {
1010
- return varint__default["default"].encode(this.size)
950
+ }
951
+
952
+ var proto$1 = `
953
+ // PeernetDataMessageResponse
954
+ message PeernetDataMessageResponse {
955
+ required string hash = 1;
956
+ required bytes data = 2;
957
+ }
958
+ `;
959
+
960
+ class DataMessageResponse extends codecFormatInterface.FormatInterface {
961
+ get keys() {
962
+ return ['hash', 'data']
1011
963
  }
1012
964
 
1013
- get buffer() {
1014
- return this.hash
965
+ constructor(data) {
966
+ const name = 'peernet-data-response';
967
+ super(data, protons__default["default"](proto$1).PeernetDataMessageResponse, {name});
1015
968
  }
1016
-
1017
- toHex() {
1018
- return this.hash.toString('hex')
969
+ }
970
+
971
+ var proto = `
972
+ message ChatMessage {
973
+ required string value = 1;
974
+ required string author = 2;
975
+ required uint64 timestamp = 3;
976
+ repeated string files = 4;
977
+ }`;
978
+
979
+ class ChatMessage extends codecFormatInterface.FormatInterface {
980
+ get keys() {
981
+ return ['author', 'value', 'timestamp', 'files']
1019
982
  }
1020
983
 
1021
- fromHex(hex) {
1022
- return this.decode(Buffer.from(hex, 'hex'))
984
+ constructor(buffer) {
985
+ const name = 'chat-message';
986
+ super(buffer, protons__default["default"](proto).ChatMessage, {name});
1023
987
  }
988
+ }
989
+
990
+ const protoFor = (data) => {
991
+ if (!Buffer.isBuffer(data)) data = Buffer.from(data);
992
+ const codec = new codecFormatInterface.Codec(data);
993
+ if (!codec.name) throw new Error('proto not found')
994
+ const Proto = globalThis.peernet.protos[codec.name];
995
+ if (!Proto) throw (new Error(`No proto defined for ${codec.name}`))
996
+ return new Proto(data)
997
+ };
1024
998
 
1025
- fromJSON(json) {
1026
- return this.encode(Buffer.from(JSON.stringify(json)))
999
+ /**
1000
+ * wether or not a peernet daemon is active
1001
+ * @return {Boolean}
1002
+ */
1003
+ const hasDaemon = async () => {
1004
+ try {
1005
+ let response = await fetch('http://127.0.0.1:1000/api/version');
1006
+ response = await response.json();
1007
+ return Boolean(response.client === '@peernet/api/http')
1008
+ } catch (e) {
1009
+ return false
1027
1010
  }
1011
+ };
1028
1012
 
1029
- toBs32() {
1030
- return bs32__default["default"].encode(this.hash)
1031
- }
1013
+ const https = () => {
1014
+ if (!globalThis.location) return false;
1015
+ return Boolean(globalThis.location.protocol === 'https:')
1016
+ };
1032
1017
 
1033
- fromBs32(bs) {
1034
- return this.decode(bs32__default["default"].decode(bs))
1018
+ /**
1019
+ * Get current environment
1020
+ * @return {String} current environment [node, electron, browser]
1021
+ */
1022
+ const environment = () => {
1023
+ const _navigator = globalThis.navigator;
1024
+ if (!_navigator) {
1025
+ return 'node'
1026
+ } else if (_navigator && /electron/i.test(_navigator.userAgent)) {
1027
+ return 'electron'
1028
+ } else {
1029
+ return 'browser'
1035
1030
  }
1031
+ };
1036
1032
 
1037
- toBs58() {
1038
- return bs58__default["default"].encode(this.hash)
1039
- }
1033
+ /**
1034
+ * * Get current environment
1035
+ * @return {Object} result
1036
+ * @property {Boolean} reult.daemon whether or not daemon is running
1037
+ * @property {Boolean} reult.environment Current environment
1038
+ */
1039
+ const target = async () => {
1040
+ let daemon = false;
1041
+ const env = await environment();
1042
+ if (!https()) daemon = await hasDaemon();
1040
1043
 
1041
- fromBs58(bs) {
1042
- return this.decode(bs58__default["default"].decode(bs))
1044
+ return {daemon, environment: env}
1045
+ };
1046
+
1047
+ class PeerDiscovery {
1048
+ constructor(id) {
1049
+ this.id = id;
1043
1050
  }
1044
1051
 
1045
- toString(encoding = 'utf8') {
1046
- return this.hash.toString(encoding)
1047
- }
1052
+ _getPeerId(id) {
1053
+ if (!peernet.peerMap || peernet.peerMap && peernet.peerMap.size === 0) return false
1048
1054
 
1049
- encode(buffer, name) {
1050
- if (!this.name && name) this.name = name;
1051
- if (!buffer) buffer = this.buffer;
1052
- this.discoCodec = new PeernetCodec(this.name, this.codecs);
1053
- this.discoCodec.fromName(this.name);
1054
- let hashAlg = this.discoCodec.hashAlg;
1055
- if (hashAlg.includes('dbl')) {
1056
- hashAlg = hashAlg.replace('dbl-', '');
1057
- buffer = createKeccakHash__default["default"](hashAlg.replace('-', '')).update(buffer).digest();
1055
+ for (const entry of [...peernet.peerMap.entries()]) {
1056
+ for (const _id of entry[1]) {
1057
+ if (_id === id) return entry[0]
1058
+ }
1058
1059
  }
1059
- this.digest = createKeccakHash__default["default"](hashAlg.replace('-', '')).update(buffer).digest();
1060
- this.size = this.digest.length;
1060
+ }
1061
1061
 
1062
- this.codec = this.discoCodec.encode();
1063
- this.codec = this.discoCodec.codecBuffer;
1064
- const uint8Array = new Uint8Array(this.digest.length + this.prefix.length);
1065
- uint8Array.set(this.prefix);
1066
- uint8Array.set(this.digest, this.prefix.length);
1062
+ async discover(peer) {
1063
+ let id = this._getPeerId(peer.id);
1064
+ if (id) return id
1065
+ const data = new peernet.protos['peernet-peer']({id: this.id});
1066
+ const node = await peernet.prepareMessage(peer.id, data.encoded);
1067
1067
 
1068
- this.hash = uint8Array;
1068
+ let response = await peer.request(node.encoded);
1069
+ response = protoFor(response);
1070
+ response = new peernet.protos['peernet-peer-response'](response.decoded.data);
1069
1071
 
1070
- return this.hash
1071
- }
1072
+ id = response.decoded.id;
1073
+ if (id === this.id) return;
1072
1074
 
1073
- validate(buffer) {
1074
- if (Buffer.isBuffer(buffer)) {
1075
- const codec = varint__default["default"].decode(buffer);
1076
- if (this.codecs[codec]) {
1077
- this.decode(buffer);
1078
- } else {
1079
- this.encode(buffer);
1075
+ if (!peernet.peerMap.has(id)) peernet.peerMap.set(id, [peer.id]);
1076
+ else {
1077
+ const connections = peernet.peerMap.get(id);
1078
+ if (connections.indexOf(peer.id) === -1) {
1079
+ connections.push(peer.id);
1080
+ peernet.peerMap.set(peer.id, connections);
1080
1081
  }
1081
1082
  }
1082
- if (typeof buffer === 'string') {
1083
- if (isHex__default["default"](buffer)) this.fromHex(buffer);
1084
- if (bs32__default["default"].test(buffer)) this.fromBs32(buffer);
1085
- }
1086
- if (typeof buffer === 'object') this.fromJSON(buffer);
1083
+ return id
1087
1084
  }
1088
1085
 
1089
- decode(buffer) {
1090
- this.hash = buffer;
1091
- const codec = varint__default["default"].decode(buffer);
1092
-
1093
- this.discoCodec = new PeernetCodec(codec, this.codecs);
1094
- // TODO: validate codec
1095
- buffer = buffer.slice(varint__default["default"].decode.bytes);
1096
- this.size = varint__default["default"].decode(buffer);
1097
- this.digest = buffer.slice(varint__default["default"].decode.bytes);
1098
- if (this.digest.length !== this.size) {
1099
- throw new Error(`hash length inconsistent: 0x${this.hash.toString('hex')}`)
1100
- }
1101
-
1102
- // const discoCodec = new Codec(codec, this.codecs)
1103
-
1104
- this.name = this.discoCodec.name;
1086
+ async discoverHandler(message, peer) {
1087
+ const {id, proto} = message;
1088
+ // if (typeof message.data === 'string') message.data = Buffer.from(message.data)
1089
+ if (proto.name === 'peernet-peer') {
1090
+ const from = proto.decoded.id;
1091
+ if (from === this.id) return;
1105
1092
 
1093
+ if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
1094
+ else {
1095
+ const connections = peernet.peerMap.get(from);
1096
+ if (connections.indexOf(peer.id) === -1) {
1097
+ connections.push(peer.id);
1098
+ peernet.peerMap.set(from, connections);
1099
+ }
1100
+ }
1101
+ const data = new peernet.protos['peernet-peer-response']({id: this.id});
1102
+ const node = await peernet.prepareMessage(from, data.encoded);
1106
1103
 
1107
- this.size = this.digest.length;
1104
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1105
+ } else if (proto.name === 'peernet-peer-response') {
1106
+ const from = proto.decoded.id;
1107
+ if (from === this.id) return;
1108
1108
 
1109
- return {
1110
- codec: this.codec,
1111
- name: this.name,
1112
- size: this.size,
1113
- length: this.length,
1114
- digest: this.digest,
1109
+ if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
1110
+ else {
1111
+ const connections = peernet.peerMap.get(from);
1112
+ if (connections.indexOf(peer.id) === -1) {
1113
+ connections.push(peer.id);
1114
+ peernet.peerMap.set(from, connections);
1115
+ }
1116
+ }
1115
1117
  }
1116
1118
  }
1117
1119
  }
1118
1120
 
1119
- class FormatInterface {
1120
- /**
1121
- * @param {Buffer|String|Object} buffer - data - The data needed to create the desired message
1122
- * @param {Object} proto - {encode, decode}
1123
- * @param {Object} options - {hashFormat, name}
1124
- */
1125
- constructor(buffer, proto, options = {}) {
1126
- this.protoEncode = proto.encode;
1127
- this.protoDecode = proto.decode;
1128
- this.hashFormat = options.hashFormat || 'bs32';
1129
- if (options.name) this.name = options.name;
1130
- if (buffer instanceof Uint8Array) this.fromUint8Array(buffer);
1131
- else if (buffer instanceof ArrayBuffer) this.fromArrayBuffer(buffer);
1132
- else if (buffer.name === options.name) return buffer
1133
- else if (buffer instanceof String) {
1134
- if (isHex__default["default"](buffer)) this.fromHex(buffer);
1135
- else if (bs32__default["default"].isBase32(buffer)) this.fromBs32(buffer);
1136
- else if (bs58__default["default"].isBase58(buffer)) this.fromBs58(buffer);
1137
- else throw new Error(`unsupported string ${buffer}`)
1138
- } else {
1139
- this.create(buffer);
1140
- }
1141
- }
1121
+ /**
1122
+ * Keep history of fetched address and ptr
1123
+ * @property {Object} address
1124
+ * @property {Object} ptr
1125
+ */
1126
+ const lastFetched = {
1127
+ address: {
1128
+ value: undefined,
1129
+ timestamp: 0,
1130
+ },
1131
+ ptr: {
1132
+ value: undefined,
1133
+ timestamp: 0,
1134
+ },
1135
+ };
1142
1136
 
1143
- /**
1144
- * @return {PeernetHash}
1145
- */
1146
- get peernetHash() {
1147
- return new PeernetHash(this.decoded, {name: this.name})
1137
+ const getAddress = async () => {
1138
+ const {address} = lastFetched;
1139
+ const now = Math.round(new Date().getTime() / 1000);
1140
+ if (now - address.timestamp > 1200000) {
1141
+ address.value = await fetch('https://icanhazip.com/');
1142
+ address.value = await address.value.text();
1143
+ address.timestamp = Math.round(new Date().getTime() / 1000);
1144
+ lastFetched.address = address;
1148
1145
  }
1149
1146
 
1150
- /**
1151
- * @return {peernetHash}
1152
- */
1153
- get hash() {
1154
- const upper = this.hashFormat.charAt(0).toUpperCase();
1155
- const format = `${upper}${this.hashFormat.substring(1, this.hashFormat.length)}`;
1156
- return this.peernetHash[`to${format}`]()
1157
- }
1147
+ return address.value
1148
+ };
1158
1149
 
1159
- /**
1160
- * @return {Object}
1161
- */
1162
- decode() {
1163
- let encoded = this.encoded;
1164
- const discoCodec = new PeernetCodec(this.encoded);
1165
- encoded = encoded.slice(discoCodec.codecBuffer.length);
1166
- this.name = discoCodec.name;
1167
- this.decoded = this.protoDecode(encoded);
1168
- return this.decoded
1169
- }
1150
+ const degreesToRadians = (degrees) => {
1151
+ return degrees * Math.PI / 180;
1152
+ };
1170
1153
 
1171
- /**
1172
- * @return {Buffer}
1173
- */
1174
- encode(decoded) {
1175
- if (!decoded) decoded = this.decoded;
1176
- const codec = new PeernetCodec(this.name);
1177
- const encoded = this.protoEncode(decoded);
1178
- const uint8Array = new Uint8Array(encoded.length + codec.codecBuffer.length);
1179
- uint8Array.set(codec.codecBuffer);
1180
- uint8Array.set(encoded, codec.codecBuffer.length);
1181
- this.encoded = uint8Array;
1182
- return this.encoded
1183
- }
1184
-
1185
- hasCodec() {
1186
- if (!this.encoded) return false
1187
- const codec = new PeernetCodec(this.encoded);
1188
- if (codec.name) return true
1189
- }
1190
-
1191
- fromUint8Array(buffer) {
1192
- this.encoded = buffer;
1193
- if (!this.hasCodec()) this.create(
1194
- JSON.parse(new TextDecoder().decode(this.encoded))
1195
- );
1196
- else this.decode();
1197
- }
1198
-
1199
- fromArrayBuffer(buffer) {
1200
- this.encoded = new Uint8Array(buffer, buffer.byteOffset, buffer.byteLength);
1201
- if (!this.hasCodec()) this.create(
1202
- JSON.parse(new TextDecoder().decode(this.encoded))
1203
- );
1204
- else this.decode();
1205
- }
1206
-
1207
- toString() {
1208
- return this.encoded.toString()
1209
- }
1210
-
1211
- async toArray() {
1212
- const array = [];
1213
- for await (const value of this.encoded.values()) {
1214
- array.push(value);
1215
- }
1216
- return array
1217
- }
1154
+ const distanceInKmBetweenEarthCoordinates = (lat1, lon1, lat2, lon2) => {
1155
+ const earthRadiusKm = 6371;
1218
1156
 
1219
- fromString(string) {
1220
- this.encoded = new Uint8Array(string.split(','));
1221
- this.decode();
1222
- }
1157
+ const dLat = degreesToRadians(lat2-lat1);
1158
+ const dLon = degreesToRadians(lon2-lon1);
1223
1159
 
1224
- fromArray(array) {
1225
- this.encoded = new Uint8Array([...array]);
1226
- this.decode();
1227
- }
1160
+ lat1 = degreesToRadians(lat1);
1161
+ lat2 = degreesToRadians(lat2);
1162
+ const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
1163
+ Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
1164
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
1165
+ return earthRadiusKm * c;
1166
+ };
1228
1167
 
1168
+ class DhtEarth {
1229
1169
  /**
1230
- * @param {Buffer} encoded
1170
+ *
1231
1171
  */
1232
- fromEncoded(encoded) {
1233
- this.encoded = encoded;
1234
- this.decode();
1172
+ constructor() {
1173
+ this.providerMap = new Map();
1235
1174
  }
1236
1175
 
1237
1176
  /**
1238
- * @param {String} encoded
1177
+ * @param {Object} address
1178
+ * @return {Object} {latitude: lat, longitude: lon}
1239
1179
  */
1240
- fromHex(encoded) {
1241
- this.encoded = Buffer.from(encoded, 'hex');
1242
- this.decode();
1180
+ async getCoordinates(address) {
1181
+ // const {address} = parseAddress(provider)
1182
+ const request = `https://whereis.leofcoin.org/?ip=${address}`;
1183
+ let response = await fetch(request);
1184
+ response = await response.json();
1185
+ const {lat, lon} = response;
1186
+ return {latitude: lat, longitude: lon}
1243
1187
  }
1244
1188
 
1245
1189
  /**
1246
- * @param {String} encoded
1190
+ * @param {Object} peer
1191
+ * @param {Object} provider
1192
+ * @return {Object} {provider, distance}
1247
1193
  */
1248
- fromBs32(encoded) {
1249
- this.encoded = bs32__default["default"].decode(encoded);
1250
- this.decode();
1194
+ async getDistance(peer, provider) {
1195
+ const {latitude, longitude} = await this.getCoordinates(provider.address);
1196
+ return {provider, distance: distanceInKmBetweenEarthCoordinates(peer.latitude, peer.longitude, latitude, longitude)}
1251
1197
  }
1252
1198
 
1253
1199
  /**
1254
- * @param {String} encoded
1200
+ * @param {Array} providers
1201
+ * @return {Object} closestPeer
1255
1202
  */
1256
- fromBs58(encoded) {
1257
- this.encoded = bs58__default["default"].decode(encoded);
1258
- this.decode();
1259
- }
1203
+ async closestPeer(providers) {
1204
+ let all = [];
1205
+ const address = await getAddress();
1206
+ const peerLoc = await this.getCoordinates(address);
1260
1207
 
1261
- /**
1262
- * @return {String} encoded
1263
- */
1264
- toHex() {
1265
- if (!this.encoded) this.encode();
1266
- return this.encoded.toString('hex')
1267
- }
1208
+ for (const provider of providers) {
1209
+ if (provider.address === '127.0.0.1') all.push({provider, distance: 0});
1210
+ else all.push(this.getDistance(peerLoc, provider));
1211
+ }
1268
1212
 
1269
- /**
1270
- * @return {String} encoded
1271
- */
1272
- toBs32() {
1273
- if (!this.encoded) this.encode();
1274
- return bs32__default["default"].encode(this.encoded)
1213
+ all = await Promise.all(all);
1214
+ all = all.sort((previous, current) => previous.distance - current.distance);
1215
+ return all[0].provider;
1275
1216
  }
1276
1217
 
1277
1218
  /**
1278
- * @return {String} encoded
1219
+ * @param {String} hash
1220
+ * @return {Array} providers
1279
1221
  */
1280
- toBs58() {
1281
- if (!this.encoded) this.encode();
1282
- return bs58__default["default"].encode(this.encoded)
1222
+ providersFor(hash) {
1223
+ return this.providerMap.get(hash);
1283
1224
  }
1284
1225
 
1285
1226
  /**
1286
- * @param {Object} data
1227
+ * @param {String} address
1228
+ * @param {String} hash
1229
+ * @return {Array} providers
1287
1230
  */
1288
- create(data) {
1289
- const decoded = {};
1290
- if (this.keys?.length > 0) {
1291
- for (const key of this.keys) {
1292
- Object.defineProperties(decoded, {
1293
- [key]: {
1294
- enumerable: true,
1295
- configurable: true,
1296
- set: (val) => value = data[key],
1297
- get: () => data[key]
1298
- }
1299
- });
1300
- }
1301
-
1302
- this.decoded = decoded;
1303
- this.encode();
1304
- }
1305
- }
1306
- }
1307
-
1308
- class PeernetMessage extends FormatInterface {
1309
- get keys() {
1310
- return ['data', 'signature', 'from', 'to', 'id']
1311
- }
1231
+ async addProvider(address, hash) {
1232
+ let providers = [];
1233
+ if (this.providerMap.has(hash)) providers = this.providerMap.get(hash);
1312
1234
 
1313
- constructor(buffer) {
1314
- const name = 'peernet-message';
1315
- super(buffer, protons__default["default"](proto$a).PeernetMessage, {name});
1235
+ providers = new Set([...providers, address]);
1236
+ this.providerMap.set(hash, providers);
1237
+ return providers;
1316
1238
  }
1317
1239
  }
1318
1240
 
1319
- var proto$9 = `
1320
- // PeernetDHTMessage
1321
- message PeernetDHTMessage {
1322
- required string hash = 1;
1323
- optional string store = 2;
1324
- }
1325
- `;
1326
-
1327
1241
  /**
1328
- * @example `
1329
- new DHTMessage(hash, store)
1330
- // store = optional if not set, peernet checks every store
1331
- let message = new DHTMessage('hashmvbs124xcfd...', 'transaction')
1332
- message = new DHTMessage('hashmvbs124xcfd...', 'block')
1333
- `
1242
+ * @params {String} network
1243
+ * @return {object} { identity, accounts, config }
1334
1244
  */
1335
- class DHTMessage extends FormatInterface {
1336
- /**
1337
- *
1338
- */
1339
- get keys() {
1340
- return ['hash', 'store']
1341
- }
1245
+ var generateAccount = async network => {
1246
+ let wallet = new MultiWallet__default["default"](network);
1247
+ /**
1248
+ * @type {string}
1249
+ */
1250
+ const mnemonic = await wallet.generate();
1342
1251
 
1343
- constructor(data) {
1344
- const name = 'peernet-dht';
1345
- super(data, protons__default["default"](proto$9).PeernetDHTMessage, {name});
1346
- }
1347
- }
1348
-
1349
- var proto$8 = `
1350
- // PeernetDHTMessageResponse
1351
- message PeernetDHTMessageResponse {
1352
- required string hash = 1;
1353
- required bool has = 2;
1354
- }
1355
- `;
1252
+ wallet = new MultiWallet__default["default"](network);
1253
+ await wallet.recover(mnemonic, network);
1254
+ /**
1255
+ * @type {object}
1256
+ */
1257
+ const account = wallet.account(0);
1258
+ /**
1259
+ * @type {object}
1260
+ */
1261
+ const external = account.external(0);
1262
+ const internal = account.internal(0);
1263
+
1264
+ return {
1265
+ identity: {
1266
+ mnemonic,
1267
+ // multiWIF: wallet.export(),
1268
+ publicKey: external.publicKey,
1269
+ privateKey: external.privateKey,
1270
+ walletId: external.id
1271
+ },
1272
+ accounts: [['main account', external.address, internal.address]]
1273
+ // config: {
1274
+ // }
1275
+ }
1276
+ };
1356
1277
 
1357
- class DHTMessageResponse extends FormatInterface {
1358
- get keys() {
1359
- return ['hash', 'has']
1278
+ var testnets = {
1279
+ 'leofcoin:olivia': {
1280
+ messagePrefix: '\u0019Leofcoin Signed Message:',
1281
+ pubKeyHash: 0x73, // o
1282
+ scriptHash: 0x76, // p
1283
+ multiTxHash: 0x8b4125, // omtx
1284
+ payments: {
1285
+ version: 0,
1286
+ unspent: 0x1fa443d7 // ounsp
1287
+ },
1288
+ wif: 0x7D, // s
1289
+ multiCodec: 0x7c4,
1290
+ bip32: { public: 0x13BBF2D5, private: 0x13BBCBC5 }
1291
+ },
1292
+ 'bitcoin:testnet': {
1293
+ messagePrefix: '\x18Bitcoin Signed Message:\n',
1294
+ bech32: 'tb',
1295
+ pubKeyHash: 0x6f,
1296
+ scriptHash: 0xc4,
1297
+ wif: 0xef,
1298
+ bip32: {
1299
+ public: 0x043587cf,
1300
+ private: 0x04358394
1301
+ }
1360
1302
  }
1361
1303
 
1362
- constructor(data) {
1363
- const name = 'peernet-dht-response';
1364
- super(data, protons__default["default"](proto$8).PeernetDHTMessageResponse, {name});
1365
- }
1366
- }
1367
-
1368
- var proto$7 = `
1369
- // PeernetDataMessage
1370
- message PeernetDataMessage {
1371
- required string hash = 1;
1372
- optional string store = 2;
1373
- }
1374
- `;
1304
+ };
1375
1305
 
1306
+ // https://en.bitcoin.it/wiki/List_of_address_prefixes
1376
1307
  /**
1377
- * @extends {CodecFormat}
1308
+ * Main network
1309
+ * @return {messagePrefix, pubKeyHash, scriptHash, wif, bip32}
1378
1310
  */
1379
- class DataMessage extends FormatInterface {
1380
- get keys() {
1381
- return ['hash', 'store']
1382
- }
1383
- /**
1384
- * @param {Buffer|String|Object|DataMessage} data - The data needed to create the DataMessage
1385
- */
1386
- constructor(data) {
1387
- super(data, protons__default["default"](proto$7).PeernetDataMessage, {name: 'peernet-data'});
1388
- }
1389
- }
1390
-
1391
- var proto$6 = `
1392
- // PsMessage
1393
- message PsMessage {
1394
- required bytes data = 1;
1395
- required bytes topic = 2;
1396
- }`;
1397
-
1398
- class PsMessage extends FormatInterface {
1399
- get keys() {
1400
- return ['data', 'topic']
1401
- }
1402
-
1403
- constructor(buffer) {
1404
- const name = 'peernet-ps';
1405
- super(buffer, protons__default["default"](proto$6).PsMessage, {name});
1406
- }
1407
- }
1408
-
1409
- var proto$5 = `
1410
- // PeernetPeerMessage
1411
- message PeernetPeerMessage {
1412
- required string id = 1;
1413
- }
1414
- `;
1415
-
1416
- class PeerMessage extends FormatInterface {
1417
- get keys() {
1418
- return ['id']
1419
- }
1420
-
1421
- constructor(data) {
1422
- const name = 'peernet-peer';
1423
- super(data, protons__default["default"](proto$5).PeernetPeerMessage, {name});
1424
- }
1425
- }
1426
-
1427
- var proto$4 = `
1428
- // PeernetRequestMessage
1429
- message PeernetRequestMessage {
1430
- required string request = 1;
1431
- }
1432
- `;
1433
-
1434
- class RequestMessage extends FormatInterface {
1435
- get keys() {
1436
- return ['request']
1437
- }
1438
-
1439
- constructor(data) {
1440
- const name = 'peernet-request';
1441
- super(data, protons__default["default"](proto$4).PeernetRequestMessage, {name});
1442
- }
1443
- }
1444
-
1445
- var proto$3 = `
1446
- // PeernetResponseMessage
1447
- message PeernetResponseMessage {
1448
- required bytes response = 1;
1449
- }
1450
- `;
1451
-
1452
- class ResponseMessage extends FormatInterface {
1453
- get keys() {
1454
- return ['response']
1455
- }
1456
-
1457
- constructor(data) {
1458
- const name = 'peernet-response';
1459
- super(data, protons__default["default"](proto$3).PeernetResponseMessage, {name});
1460
- }
1461
- }
1462
-
1463
- var proto$2 = `
1464
- // PeernetPeerMessageResponse
1465
- message PeernetPeerMessageResponse {
1466
- required string id = 1;
1467
- }
1468
- `;
1469
-
1470
- class PeerMessageResponse extends FormatInterface {
1471
- get keys() {
1472
- return ['id']
1473
- }
1474
-
1475
- constructor(data) {
1476
- const name = 'peernet-peer-response';
1477
- super(data, protons__default["default"](proto$2).PeernetPeerMessageResponse, {name});
1478
- }
1479
- }
1480
-
1481
- var proto$1 = `
1482
- // PeernetDataMessageResponse
1483
- message PeernetDataMessageResponse {
1484
- required string hash = 1;
1485
- required bytes data = 2;
1486
- }
1487
- `;
1488
-
1489
- class DataMessageResponse extends FormatInterface {
1490
- get keys() {
1491
- return ['hash', 'data']
1492
- }
1493
-
1494
- constructor(data) {
1495
- const name = 'peernet-data-response';
1496
- super(data, protons__default["default"](proto$1).PeernetDataMessageResponse, {name});
1497
- }
1498
- }
1499
-
1500
- var proto = `
1501
- message ChatMessage {
1502
- required string value = 1;
1503
- required string author = 2;
1504
- required uint64 timestamp = 3;
1505
- repeated string files = 4;
1506
- }`;
1507
-
1508
- class ChatMessage extends FormatInterface {
1509
- get keys() {
1510
- return ['author', 'value', 'timestamp', 'files']
1511
- }
1512
-
1513
- constructor(buffer) {
1514
- const name = 'chat-message';
1515
- super(buffer, protons__default["default"](proto).ChatMessage, {name});
1516
- }
1517
- }
1518
-
1519
- const protoFor = (data) => {
1520
- if (!Buffer.isBuffer(data)) data = Buffer.from(data);
1521
- const codec = new PeernetCodec(data);
1522
- if (!codec.name) throw new Error('proto not found')
1523
- const Proto = globalThis.peernet.protos[codec.name];
1524
- if (!Proto) throw (new Error(`No proto defined for ${codec.name}`))
1525
- return new Proto(data)
1311
+ const leofcoin = {
1312
+ messagePrefix: '\u0019Leofcoin Signed Message:',
1313
+ pubKeyHash: 0x30, // L
1314
+ scriptHash: 0x37, // P
1315
+ multiTxHash: 0x3adeed, // Lmtx
1316
+ payments: {
1317
+ version: 0,
1318
+ unspent: 0x0d6e0327 // Lunsp
1319
+ },
1320
+ coin_type: 640,
1321
+ wif: 0x3F, // S
1322
+ multiCodec: 0x3c4,
1323
+ bip32: { public: 0x13BBF2D4, private: 0x13BBCBC4 },
1324
+ testnet: testnets['leofcoin:olivia']
1526
1325
  };
1527
1326
 
1528
- /**
1529
- * wether or not a peernet daemon is active
1530
- * @return {Boolean}
1531
- */
1532
- const hasDaemon = async () => {
1533
- try {
1534
- let response = await fetch('http://127.0.0.1:1000/api/version');
1535
- response = await response.json();
1536
- return Boolean(response.client === '@peernet/api/http')
1537
- } catch (e) {
1538
- return false
1539
- }
1327
+ const bitcoin = {
1328
+ messagePrefix: '\x18Bitcoin Signed Message:\n',
1329
+ bech32: 'bc',
1330
+ pubKeyHash: 0x00,
1331
+ multiCodec: 0x00,
1332
+ scriptHash: 0x05,
1333
+ wif: 0x80,
1334
+ coin_type: 0,
1335
+ bip32: {
1336
+ public: 0x0488b21e, private: 0x0488ade4
1337
+ },
1338
+ testnet: testnets['bitcoin:testnet']
1540
1339
  };
1541
1340
 
1542
- const https = () => {
1543
- if (!globalThis.location) return false;
1544
- return Boolean(globalThis.location.protocol === 'https:')
1341
+ const litecoin = {
1342
+ messagePrefix: '\x19Litecoin Signed Message:\n',
1343
+ pubKeyHash: 0x30,
1344
+ scriptHash: 0x32,
1345
+ wif: 0xb0,
1346
+ bip32: {
1347
+ public: 0x019da462,
1348
+ private: 0x019d9cfe
1349
+ }
1545
1350
  };
1546
1351
 
1547
- /**
1548
- * Get current environment
1549
- * @return {String} current environment [node, electron, browser]
1550
- */
1551
- const environment = () => {
1552
- const _navigator = globalThis.navigator;
1553
- if (!_navigator) {
1554
- return 'node'
1555
- } else if (_navigator && /electron/i.test(_navigator.userAgent)) {
1556
- return 'electron'
1557
- } else {
1558
- return 'browser'
1559
- }
1352
+ const ethereum = {
1353
+ messagePrefix: '\x19Ethereum Signed Message:\n',
1354
+ pubKeyHash: 0x30,
1355
+ scriptHash: 0x32,
1356
+ bip32: {
1357
+ private: 0x0488ADE4, public: 0x0488B21E
1358
+ },
1359
+ coin_type: 60,
1360
+ wif: 0x45,//E
1361
+ multiCodec: 0x3c5
1560
1362
  };
1561
1363
 
1562
1364
  /**
1563
- * * Get current environment
1564
- * @return {Object} result
1565
- * @property {Boolean} reult.daemon whether or not daemon is running
1566
- * @property {Boolean} reult.environment Current environment
1365
+ * Our & supported networks
1366
+ * @return {leofcoin, olivia}
1567
1367
  */
1568
- const target = async () => {
1569
- let daemon = false;
1570
- const env = await environment();
1571
- if (!https()) daemon = await hasDaemon();
1572
-
1573
- return {daemon, environment: env}
1368
+ var networks = {
1369
+ leofcoin,
1370
+ bitcoin,
1371
+ litecoin,
1372
+ ethereum
1574
1373
  };
1575
1374
 
1576
- class PeerDiscovery {
1577
- constructor(id) {
1578
- this.id = id;
1579
- }
1580
-
1581
- _getPeerId(id) {
1582
- if (!peernet.peerMap || peernet.peerMap && peernet.peerMap.size === 0) return false
1375
+ const fromNetworkString = network => {
1376
+ const parts = network.split(':');
1377
+ network = networks[parts[0]];
1378
+ if (parts[1]) {
1379
+ if (network[parts[1]]) network = network[parts[1]];
1583
1380
 
1584
- for (const entry of [...peernet.peerMap.entries()]) {
1585
- for (const _id of entry[1]) {
1586
- if (_id === id) return entry[0]
1587
- }
1588
- }
1381
+ network.coin_type = 1;
1589
1382
  }
1383
+ return network;
1384
+ };
1385
+
1386
+ // import { createHash } from 'crypto'
1387
+ // import { createHash as _createHash } from './hash'
1590
1388
 
1591
- async discover(peer) {
1592
- let id = this._getPeerId(peer.id);
1593
- if (id) return id
1594
- const data = new peernet.protos['peernet-peer']({id: this.id});
1595
- const node = await peernet.prepareMessage(peer.id, data.encoded);
1389
+ const { encode: encode$1, decode: decode$1 } = bs58check__default["default"];
1390
+ class HDWallet {
1596
1391
 
1597
- let response = await peer.request(node.encoded);
1598
- response = protoFor(response);
1599
- response = new peernet.protos['peernet-peer-response'](response.decoded.data);
1392
+ get chainCodeBuffer() {
1393
+ return this.ifNotLocked(() => this.hdnode.chainCode)
1394
+ }
1600
1395
 
1601
- id = response.decoded.id;
1602
- if (id === this.id) return;
1396
+ get chainCode() {
1397
+ return this.ifNotLocked(() => this.chainCodeBuffer.toString('hex'))
1398
+ }
1603
1399
 
1604
- if (!peernet.peerMap.has(id)) peernet.peerMap.set(id, [peer.id]);
1605
- else {
1606
- const connections = peernet.peerMap.get(id);
1607
- if (connections.indexOf(peer.id) === -1) {
1608
- connections.push(peer.id);
1609
- peernet.peerMap.set(peer.id, connections);
1610
- }
1611
- }
1612
- return id
1613
- }
1400
+ get privateKeyBuffer() {
1401
+ return this.ifNotLocked(() => this.hdnode.privateKey)
1402
+ }
1614
1403
 
1615
- async discoverHandler(message, peer) {
1616
- const {id, proto} = message;
1617
- // if (typeof message.data === 'string') message.data = Buffer.from(message.data)
1618
- if (proto.name === 'peernet-peer') {
1619
- const from = proto.decoded.id;
1620
- if (from === this.id) return;
1404
+ get privateKey() {
1405
+ return this.ifNotLocked(() => this.privateKeyBuffer.toString('hex'))
1406
+ }
1621
1407
 
1622
- if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
1623
- else {
1624
- const connections = peernet.peerMap.get(from);
1625
- if (connections.indexOf(peer.id) === -1) {
1626
- connections.push(peer.id);
1627
- peernet.peerMap.set(from, connections);
1628
- }
1629
- }
1630
- const data = new peernet.protos['peernet-peer-response']({id: this.id});
1631
- const node = await peernet.prepareMessage(from, data.encoded);
1408
+ get publicKeyBuffer() {
1409
+ return this.ifNotLocked(() => this.hdnode.publicKey)
1410
+ }
1632
1411
 
1633
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1634
- } else if (proto.name === 'peernet-peer-response') {
1635
- const from = proto.decoded.id;
1636
- if (from === this.id) return;
1412
+ get publicKey() {
1413
+ return this.ifNotLocked(() => this.publicKeyBuffer.toString('hex'))
1414
+ }
1637
1415
 
1638
- if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
1639
- else {
1640
- const connections = peernet.peerMap.get(from);
1641
- if (connections.indexOf(peer.id) === -1) {
1642
- connections.push(peer.id);
1643
- peernet.peerMap.set(from, connections);
1644
- }
1645
- }
1646
- }
1647
- }
1648
- }
1649
-
1650
- /**
1651
- * Keep history of fetched address and ptr
1652
- * @property {Object} address
1653
- * @property {Object} ptr
1654
- */
1655
- const lastFetched = {
1656
- address: {
1657
- value: undefined,
1658
- timestamp: 0,
1659
- },
1660
- ptr: {
1661
- value: undefined,
1662
- timestamp: 0,
1663
- },
1664
- };
1416
+ get ethereumAddress() {
1417
+ const buffer = ecc__default["default"].pointFromScalar(this.hdnode.__D, false);
1418
+ let hash = createKeccakHash__default["default"]('keccak256').update(buffer.slice(1)).digest();
1419
+ return `0x${hash.slice(-20).toString('hex')}`
1420
+ }
1665
1421
 
1666
- const getAddress = async () => {
1667
- const {address} = lastFetched;
1668
- const now = Math.round(new Date().getTime() / 1000);
1669
- if (now - address.timestamp > 1200000) {
1670
- address.value = await fetch('https://icanhazip.com/');
1671
- address.value = await address.value.text();
1672
- address.timestamp = Math.round(new Date().getTime() / 1000);
1673
- lastFetched.address = address;
1674
- }
1422
+ // async bitcoinAddress() {
1423
+ // const chainCode = this.privateKeyBuffer
1424
+ //
1425
+ // const node = bip32.fromPrivateKey(this.privateKeyBuffer, chainCode, networks['bitcoin'])
1426
+ // let buffer = await _createHash(node.publicKey, 'SHA-256')
1427
+ // buffer = createHash('ripemd160').update(buffer).digest()
1428
+ // // buffer = Buffer.from(`0x00${buffer.toString('hex')}`, 'hex')
1429
+ // // buffer = createHash('sha256').update(buffer).digest()
1430
+ // // const mainHash = buffer
1431
+ // // buffer = createHash('sha256').update(buffer).digest()
1432
+ // // const checksum = buffer.toString('hex').substring(0, 8)
1433
+ // // return base58.encode(Buffer.concat([mainHash, Buffer.from(checksum, 'hex')]))
1434
+ // const payload = Buffer.allocUnsafe(21)
1435
+ // payload.writeUInt8(networks['bitcoin'].pubKeyHash, 0)
1436
+ // buffer.copy(payload, 1)
1437
+ //
1438
+ // return encode(payload)
1439
+ // }
1675
1440
 
1676
- return address.value
1677
- };
1441
+ get leofcoinAddress() {
1442
+ return encode$1(this.neutered.publicKeyBuffer)
1443
+ }
1678
1444
 
1679
- const degreesToRadians = (degrees) => {
1680
- return degrees * Math.PI / 180;
1681
- };
1445
+ get address() {
1446
+ return this.getAddressForCoin()
1447
+ }
1682
1448
 
1683
- const distanceInKmBetweenEarthCoordinates = (lat1, lon1, lat2, lon2) => {
1684
- const earthRadiusKm = 6371;
1449
+ getAddressForCoin(coin_type) {
1450
+ if (!coin_type) coin_type = this.hdnode.network.coin_type;
1451
+ if (coin_type === 1) {
1452
+ if (this.networkName?.split(':')[0] === 'ethereum') coin_type = 60;
1453
+ if (this.networkName?.split(':')[0] === 'leofcoin') coin_type = 640;
1454
+ }
1455
+ // if (coin_type === 0) return this.bitcoinAddress
1456
+ if (coin_type === 60) return this.ethereumAddress
1457
+ if (coin_type === 640) return this.leofcoinAddress
1458
+ }
1685
1459
 
1686
- const dLat = degreesToRadians(lat2-lat1);
1687
- const dLon = degreesToRadians(lon2-lon1);
1460
+ get accountAddress() {
1461
+ return this.ifNotLocked(() => encode$1(this.hdnode.publicKeyBuffer))
1462
+ }
1688
1463
 
1689
- lat1 = degreesToRadians(lat1);
1690
- lat2 = degreesToRadians(lat2);
1691
- const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
1692
- Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
1693
- const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
1694
- return earthRadiusKm * c;
1695
- };
1464
+ get isTestnet() {
1465
+ if (typeof network === 'string')
1466
+ this.hdnode.network = fromNetworkString(network);
1696
1467
 
1697
- class DhtEarth {
1698
- /**
1699
- *
1700
- */
1701
- constructor() {
1702
- this.providerMap = new Map();
1703
- }
1468
+ return Boolean(this.hdnode.network.coin_type === 1)
1469
+ }
1704
1470
 
1705
- /**
1706
- * @param {Object} address
1707
- * @return {Object} {latitude: lat, longitude: lon}
1708
- */
1709
- async getCoordinates(address) {
1710
- // const {address} = parseAddress(provider)
1711
- const request = `https://whereis.leofcoin.org/?ip=${address}`;
1712
- let response = await fetch(request);
1713
- response = await response.json();
1714
- const {lat, lon} = response;
1715
- return {latitude: lat, longitude: lon}
1716
- }
1471
+ constructor(network, hdnode) {
1472
+ if (typeof network === 'string') {
1473
+ this.networkName = network;
1474
+ this.network = fromNetworkString(network);
1475
+ } else if (typeof network === 'object')
1476
+ this.network = network;
1717
1477
 
1718
- /**
1719
- * @param {Object} peer
1720
- * @param {Object} provider
1721
- * @return {Object} {provider, distance}
1722
- */
1723
- async getDistance(peer, provider) {
1724
- const {latitude, longitude} = await this.getCoordinates(provider.address);
1725
- return {provider, distance: distanceInKmBetweenEarthCoordinates(peer.latitude, peer.longitude, latitude, longitude)}
1726
- }
1478
+ if (hdnode) this.defineHDNode(hdnode);
1479
+ }
1727
1480
 
1728
- /**
1729
- * @param {Array} providers
1730
- * @return {Object} closestPeer
1731
- */
1732
- async closestPeer(providers) {
1733
- let all = [];
1734
- const address = await getAddress();
1735
- const peerLoc = await this.getCoordinates(address);
1481
+ ifNotLocked(fn, params) {
1482
+ if (!this.locked) return fn(params);
1483
+ return null
1484
+ }
1736
1485
 
1737
- for (const provider of providers) {
1738
- if (provider.address === '127.0.0.1') all.push({provider, distance: 0});
1739
- else all.push(this.getDistance(peerLoc, provider));
1740
- }
1486
+ defineHDNode(value) {
1487
+ Object.defineProperty(this, 'hdnode', {
1488
+ configurable: false,
1489
+ writable: false,
1490
+ value: value
1491
+ });
1492
+ }
1741
1493
 
1742
- all = await Promise.all(all);
1743
- all = all.sort((previous, current) => previous.distance - current.distance);
1744
- return all[0].provider;
1745
- }
1494
+ validateNetwork(network) {
1495
+ if (!network && !this.network) return console.error(`expected network to be defined`);
1496
+ if (!network && this.network) network = this.network;
1497
+ if (typeof network === 'string') network = fromNetworkString(network);
1498
+ if (typeof network !== 'object') return console.error('network not found');
1499
+ return network;
1500
+ }
1746
1501
 
1747
- /**
1748
- * @param {String} hash
1749
- * @return {Array} providers
1750
- */
1751
- providersFor(hash) {
1752
- return this.providerMap.get(hash);
1753
- }
1502
+ async generate(password, network) {
1503
+ network = this.validateNetwork(network);
1504
+ const mnemonic = new Mnemonic__default["default"]().generate();
1505
+ const seed = new Mnemonic__default["default"]().seedFromMnemonic(mnemonic, password);
1506
+ this.defineHDNode(bip32__namespace.fromSeed(seed, network));
1507
+ return mnemonic;
1508
+ }
1754
1509
 
1755
- /**
1756
- * @param {String} address
1757
- * @param {String} hash
1758
- * @return {Array} providers
1510
+ /**
1511
+ * recover using mnemonic (recovery word list)
1759
1512
  */
1760
- async addProvider(address, hash) {
1761
- let providers = [];
1762
- if (this.providerMap.has(hash)) providers = this.providerMap.get(hash);
1763
-
1764
- providers = new Set([...providers, address]);
1765
- this.providerMap.set(hash, providers);
1766
- return providers;
1767
- }
1768
- }
1769
-
1770
- /**
1771
- * @params {String} network
1772
- * @return {object} { identity, accounts, config }
1773
- */
1774
- var generateAccount = async network => {
1775
- let wallet = new MultiWallet__default["default"](network);
1776
- /**
1777
- * @type {string}
1778
- */
1779
- const mnemonic = await wallet.generate();
1513
+ async recover(mnemonic, password, network) {
1514
+ network = this.validateNetwork(network, password);
1515
+ const seed = new Mnemonic__default["default"]().seedFromMnemonic(mnemonic, password);
1516
+ this.defineHDNode(bip32__namespace.fromSeed(seed, network));
1517
+ }
1780
1518
 
1781
- wallet = new MultiWallet__default["default"](network);
1782
- await wallet.recover(mnemonic, network);
1783
- /**
1784
- * @type {object}
1785
- */
1786
- const account = wallet.account(0);
1787
- /**
1788
- * @type {object}
1789
- */
1790
- const external = account.external(0);
1791
- const internal = account.internal(0);
1519
+ load(base58, network) {
1520
+ network = this.validateNetwork(network);
1521
+ this.defineHDNode(bip32__namespace.fromBase58(base58, network));
1522
+ }
1792
1523
 
1793
- return {
1794
- identity: {
1795
- mnemonic,
1796
- // multiWIF: wallet.export(),
1797
- publicKey: external.publicKey,
1798
- privateKey: external.privateKey,
1799
- walletId: external.id
1800
- },
1801
- accounts: [['main account', external.address, internal.address]]
1802
- // config: {
1803
- // }
1804
- }
1805
- };
1806
-
1807
- var testnets = {
1808
- 'leofcoin:olivia': {
1809
- messagePrefix: '\u0019Leofcoin Signed Message:',
1810
- pubKeyHash: 0x73, // o
1811
- scriptHash: 0x76, // p
1812
- multiTxHash: 0x8b4125, // omtx
1813
- payments: {
1814
- version: 0,
1815
- unspent: 0x1fa443d7 // ounsp
1816
- },
1817
- wif: 0x7D, // s
1818
- multiCodec: 0x7c4,
1819
- bip32: { public: 0x13BBF2D5, private: 0x13BBCBC5 }
1820
- },
1821
- 'bitcoin:testnet': {
1822
- messagePrefix: '\x18Bitcoin Signed Message:\n',
1823
- bech32: 'tb',
1824
- pubKeyHash: 0x6f,
1825
- scriptHash: 0xc4,
1826
- wif: 0xef,
1827
- bip32: {
1828
- public: 0x043587cf,
1829
- private: 0x04358394
1830
- }
1831
- }
1524
+ save() {
1525
+ return this.hdnode.toBase58();
1526
+ }
1832
1527
 
1833
- };
1528
+ fromAddress(address, chainCode, network) {
1529
+ network = this.validateNetwork(network);
1530
+ // if (network.coin_type === 60) {
1531
+ // address = Buffer.from(address, 'hex')
1532
+ // } else {
1533
+ address = decode$1(address);
1534
+ // }
1535
+
1536
+ if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = address.slice(1);
1537
+ this.defineHDNode(bip32__namespace.fromPublicKey(address, chainCode, network));
1538
+ }
1539
+
1540
+ fromPublicKey(hex, chainCode, network) {
1541
+ network = this.validateNetwork(network);
1542
+ if (!Buffer.isBuffer(hex)) hex = Buffer.from(hex, 'hex');
1543
+ if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = hex.slice(1);
1544
+ this.defineHDNode(bip32__namespace.fromPublicKey(hex, chainCode, network));
1545
+ }
1546
+ }
1834
1547
 
1835
- // https://en.bitcoin.it/wiki/List_of_address_prefixes
1836
- /**
1837
- * Main network
1838
- * @return {messagePrefix, pubKeyHash, scriptHash, wif, bip32}
1839
- */
1840
- const leofcoin = {
1841
- messagePrefix: '\u0019Leofcoin Signed Message:',
1842
- pubKeyHash: 0x30, // L
1843
- scriptHash: 0x37, // P
1844
- multiTxHash: 0x3adeed, // Lmtx
1845
- payments: {
1846
- version: 0,
1847
- unspent: 0x0d6e0327 // Lunsp
1848
- },
1849
- coin_type: 640,
1850
- wif: 0x3F, // S
1851
- multiCodec: 0x3c4,
1852
- bip32: { public: 0x13BBF2D4, private: 0x13BBCBC4 },
1853
- testnet: testnets['leofcoin:olivia']
1854
- };
1548
+ const { subtle } = crypto;
1855
1549
 
1856
- const bitcoin = {
1857
- messagePrefix: '\x18Bitcoin Signed Message:\n',
1858
- bech32: 'bc',
1859
- pubKeyHash: 0x00,
1860
- multiCodec: 0x00,
1861
- scriptHash: 0x05,
1862
- wif: 0x80,
1863
- coin_type: 0,
1864
- bip32: {
1865
- public: 0x0488b21e, private: 0x0488ade4
1866
- },
1867
- testnet: testnets['bitcoin:testnet']
1550
+ const generateAesKey = async (length = 256) => {
1551
+ const key = await subtle.generateKey({
1552
+ name: 'AES-CBC',
1553
+ length
1554
+ }, true, ['encrypt', 'decrypt']);
1555
+
1556
+ return key;
1868
1557
  };
1869
1558
 
1870
- const litecoin = {
1871
- messagePrefix: '\x19Litecoin Signed Message:\n',
1872
- pubKeyHash: 0x30,
1873
- scriptHash: 0x32,
1874
- wif: 0xb0,
1875
- bip32: {
1876
- public: 0x019da462,
1877
- private: 0x019d9cfe
1878
- }
1559
+ const importAesKey = async (exported, format = 'raw', length = 256) => {
1560
+ return await subtle.importKey(format, exported, {
1561
+ name: 'AES-CBC',
1562
+ length
1563
+ }, true, ['encrypt', 'decrypt'])
1879
1564
  };
1880
1565
 
1881
- const ethereum = {
1882
- messagePrefix: '\x19Ethereum Signed Message:\n',
1883
- pubKeyHash: 0x30,
1884
- scriptHash: 0x32,
1885
- bip32: {
1886
- private: 0x0488ADE4, public: 0x0488B21E
1887
- },
1888
- coin_type: 60,
1889
- wif: 0x45,//E
1890
- multiCodec: 0x3c5
1566
+ const exportAesKey = async (key, format = 'raw') => {
1567
+ return await subtle.exportKey(format, key)
1891
1568
  };
1892
1569
 
1893
- /**
1894
- * Our & supported networks
1895
- * @return {leofcoin, olivia}
1896
- */
1897
- var networks = {
1898
- leofcoin,
1899
- bitcoin,
1900
- litecoin,
1901
- ethereum
1902
- };
1903
-
1904
- const fromNetworkString = network => {
1905
- const parts = network.split(':');
1906
- network = networks[parts[0]];
1907
- if (parts[1]) {
1908
- if (network[parts[1]]) network = network[parts[1]];
1570
+ const encryptAes = async (uint8Array, key, iv) => subtle.encrypt({
1571
+ name: 'AES-CBC',
1572
+ iv,
1573
+ }, key, uint8Array);
1909
1574
 
1910
- network.coin_type = 1;
1575
+ const uint8ArrayToHex = uint8Array =>
1576
+ [...uint8Array].map(x => x.toString(16).padStart(2, '0')).join('');
1577
+
1578
+ const arrayBufferToHex = arrayBuffer =>
1579
+ uint8ArrayToHex(new Uint8Array(arrayBuffer));
1580
+
1581
+ const hexToUint8Array = hex =>
1582
+ new Uint8Array(hex.match(/[\da-f]{2}/gi).map(x => parseInt(x, 16)));
1583
+
1584
+ const encrypt = async string => {
1585
+ const ec = new TextEncoder();
1586
+ const key = await generateAesKey();
1587
+ const iv = await randombytes__default["default"](16);
1588
+
1589
+ const ciphertext = await encryptAes(ec.encode(string), key, iv);
1590
+ const exported = await exportAesKey(key);
1591
+
1592
+ return {
1593
+ key: arrayBufferToHex(exported),
1594
+ iv: iv.toString('hex'),
1595
+ cipher: arrayBufferToHex(ciphertext)
1911
1596
  }
1912
- return network;
1597
+ };
1598
+
1599
+ const decrypt = async (cipher, key, iv) => {
1600
+ if (!key.type) key = await importAesKey(hexToUint8Array(key));
1601
+ cipher = new Uint8Array(hexToUint8Array(cipher));
1602
+ iv = new Uint8Array(hexToUint8Array(iv));
1603
+
1604
+ const dec = new TextDecoder();
1605
+ const plaintext = await subtle.decrypt({
1606
+ name: 'AES-CBC',
1607
+ iv,
1608
+ }, key, cipher);
1609
+
1610
+ return dec.decode(plaintext);
1913
1611
  };
1914
1612
 
1915
- // import { createHash } from 'crypto'
1916
- // import { createHash as _createHash } from './hash'
1613
+ const { encode, decode } = bs58check__namespace;
1917
1614
 
1918
- const { encode: encode$1, decode: decode$1 } = bs58check__default["default"];
1919
- class HDWallet {
1615
+ // TODO: multihash addresses
1616
+ class HDAccount {
1617
+ /**
1618
+ * @param {number} depth - acount depth
1619
+ */
1620
+ constructor(node, depth = 0) {
1621
+ this.node = node;
1622
+ this.depth = depth;
1623
+ this._prefix = `m/44'/${node.network.coin_type}'/${depth}'/`;
1624
+ }
1920
1625
 
1921
- get chainCodeBuffer() {
1922
- return this.ifNotLocked(() => this.hdnode.chainCode)
1626
+ /**
1627
+ * @param {number} index - address index
1628
+ */
1629
+ internal(index = 0) {
1630
+ return this.node.derivePath(`${this._prefix}1/${index}`)
1923
1631
  }
1924
1632
 
1925
- get chainCode() {
1926
- return this.ifNotLocked(() => this.chainCodeBuffer.toString('hex'))
1633
+ /**
1634
+ * @param {number} index - address index
1635
+ */
1636
+ external(index = 0) {
1637
+ return this.node.derivePath(`${this._prefix}0/${index}`)
1927
1638
  }
1639
+ }
1928
1640
 
1929
- get privateKeyBuffer() {
1930
- return this.ifNotLocked(() => this.hdnode.privateKey)
1641
+ class MultiWallet extends HDWallet {
1642
+ constructor(network, hdnode) {
1643
+ super(network, hdnode);
1644
+ this.multiCodec = this.network.multiCodec;
1645
+ this.version = 0x00;
1931
1646
  }
1932
1647
 
1933
- get privateKey() {
1934
- return this.ifNotLocked(() => this.privateKeyBuffer.toString('hex'))
1648
+ get id() {
1649
+ const buffer = Buffer.concat([
1650
+ Buffer.from(varint__default["default"].encode(this.multiCodec)),
1651
+ Buffer.from(this.account(0).node.neutered.publicKey, 'hex')
1652
+ ]);
1653
+ return encode(buffer)
1935
1654
  }
1936
1655
 
1937
- get publicKeyBuffer() {
1938
- return this.ifNotLocked(() => this.hdnode.publicKey)
1656
+ get multiWIF() {
1657
+ return this.ifNotLocked(() => this.encode())
1939
1658
  }
1940
1659
 
1941
- get publicKey() {
1942
- return this.ifNotLocked(() => this.publicKeyBuffer.toString('hex'))
1943
- }
1944
-
1945
- get ethereumAddress() {
1946
- const buffer = ecc__default["default"].pointFromScalar(this.hdnode.__D, false);
1947
- let hash = createKeccakHash__default["default"]('keccak256').update(buffer.slice(1)).digest();
1948
- return `0x${hash.slice(-20).toString('hex')}`
1949
- }
1950
-
1951
- // async bitcoinAddress() {
1952
- // const chainCode = this.privateKeyBuffer
1953
- //
1954
- // const node = bip32.fromPrivateKey(this.privateKeyBuffer, chainCode, networks['bitcoin'])
1955
- // let buffer = await _createHash(node.publicKey, 'SHA-256')
1956
- // buffer = createHash('ripemd160').update(buffer).digest()
1957
- // // buffer = Buffer.from(`0x00${buffer.toString('hex')}`, 'hex')
1958
- // // buffer = createHash('sha256').update(buffer).digest()
1959
- // // const mainHash = buffer
1960
- // // buffer = createHash('sha256').update(buffer).digest()
1961
- // // const checksum = buffer.toString('hex').substring(0, 8)
1962
- // // return base58.encode(Buffer.concat([mainHash, Buffer.from(checksum, 'hex')]))
1963
- // const payload = Buffer.allocUnsafe(21)
1964
- // payload.writeUInt8(networks['bitcoin'].pubKeyHash, 0)
1965
- // buffer.copy(payload, 1)
1966
- //
1967
- // return encode(payload)
1968
- // }
1969
-
1970
- get leofcoinAddress() {
1971
- return encode$1(this.neutered.publicKeyBuffer)
1972
- }
1973
-
1974
- get address() {
1975
- return this.getAddressForCoin()
1976
- }
1977
-
1978
- getAddressForCoin(coin_type) {
1979
- if (!coin_type) coin_type = this.hdnode.network.coin_type;
1980
- if (coin_type === 1) {
1981
- if (this.networkName?.split(':')[0] === 'ethereum') coin_type = 60;
1982
- if (this.networkName?.split(':')[0] === 'leofcoin') coin_type = 640;
1983
- }
1984
- // if (coin_type === 0) return this.bitcoinAddress
1985
- if (coin_type === 60) return this.ethereumAddress
1986
- if (coin_type === 640) return this.leofcoinAddress
1987
- }
1988
-
1989
- get accountAddress() {
1990
- return this.ifNotLocked(() => encode$1(this.hdnode.publicKeyBuffer))
1991
- }
1992
-
1993
- get isTestnet() {
1994
- if (typeof network === 'string')
1995
- this.hdnode.network = fromNetworkString(network);
1996
-
1997
- return Boolean(this.hdnode.network.coin_type === 1)
1998
- }
1999
-
2000
- constructor(network, hdnode) {
2001
- if (typeof network === 'string') {
2002
- this.networkName = network;
2003
- this.network = fromNetworkString(network);
2004
- } else if (typeof network === 'object')
2005
- this.network = network;
2006
-
2007
- if (hdnode) this.defineHDNode(hdnode);
2008
- }
2009
-
2010
- ifNotLocked(fn, params) {
2011
- if (!this.locked) return fn(params);
2012
- return null
2013
- }
2014
-
2015
- defineHDNode(value) {
2016
- Object.defineProperty(this, 'hdnode', {
2017
- configurable: false,
2018
- writable: false,
2019
- value: value
2020
- });
2021
- }
2022
-
2023
- validateNetwork(network) {
2024
- if (!network && !this.network) return console.error(`expected network to be defined`);
2025
- if (!network && this.network) network = this.network;
2026
- if (typeof network === 'string') network = fromNetworkString(network);
2027
- if (typeof network !== 'object') return console.error('network not found');
2028
- return network;
2029
- }
2030
-
2031
- async generate(password, network) {
2032
- network = this.validateNetwork(network);
2033
- const mnemonic = new Mnemonic__default["default"]().generate();
2034
- const seed = new Mnemonic__default["default"]().seedFromMnemonic(mnemonic, password);
2035
- this.defineHDNode(bip32__namespace.fromSeed(seed, network));
2036
- return mnemonic;
2037
- }
2038
-
2039
- /**
2040
- * recover using mnemonic (recovery word list)
2041
- */
2042
- async recover(mnemonic, password, network) {
2043
- network = this.validateNetwork(network, password);
2044
- const seed = new Mnemonic__default["default"]().seedFromMnemonic(mnemonic, password);
2045
- this.defineHDNode(bip32__namespace.fromSeed(seed, network));
2046
- }
2047
-
2048
- load(base58, network) {
2049
- network = this.validateNetwork(network);
2050
- this.defineHDNode(bip32__namespace.fromBase58(base58, network));
2051
- }
2052
-
2053
- save() {
2054
- return this.hdnode.toBase58();
2055
- }
2056
-
2057
- fromAddress(address, chainCode, network) {
2058
- network = this.validateNetwork(network);
2059
- // if (network.coin_type === 60) {
2060
- // address = Buffer.from(address, 'hex')
2061
- // } else {
2062
- address = decode$1(address);
2063
- // }
2064
-
2065
- if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = address.slice(1);
2066
- this.defineHDNode(bip32__namespace.fromPublicKey(address, chainCode, network));
2067
- }
2068
-
2069
- fromPublicKey(hex, chainCode, network) {
2070
- network = this.validateNetwork(network);
2071
- if (!Buffer.isBuffer(hex)) hex = Buffer.from(hex, 'hex');
2072
- if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = hex.slice(1);
2073
- this.defineHDNode(bip32__namespace.fromPublicKey(hex, chainCode, network));
2074
- }
2075
- }
2076
-
2077
- const { subtle } = crypto;
2078
-
2079
- const generateAesKey = async (length = 256) => {
2080
- const key = await subtle.generateKey({
2081
- name: 'AES-CBC',
2082
- length
2083
- }, true, ['encrypt', 'decrypt']);
2084
-
2085
- return key;
2086
- };
2087
-
2088
- const importAesKey = async (exported, format = 'raw', length = 256) => {
2089
- return await subtle.importKey(format, exported, {
2090
- name: 'AES-CBC',
2091
- length
2092
- }, true, ['encrypt', 'decrypt'])
2093
- };
2094
-
2095
- const exportAesKey = async (key, format = 'raw') => {
2096
- return await subtle.exportKey(format, key)
2097
- };
2098
-
2099
- const encryptAes = async (uint8Array, key, iv) => subtle.encrypt({
2100
- name: 'AES-CBC',
2101
- iv,
2102
- }, key, uint8Array);
2103
-
2104
- const uint8ArrayToHex = uint8Array =>
2105
- [...uint8Array].map(x => x.toString(16).padStart(2, '0')).join('');
2106
-
2107
- const arrayBufferToHex = arrayBuffer =>
2108
- uint8ArrayToHex(new Uint8Array(arrayBuffer));
2109
-
2110
- const hexToUint8Array = hex =>
2111
- new Uint8Array(hex.match(/[\da-f]{2}/gi).map(x => parseInt(x, 16)));
2112
-
2113
- const encrypt = async string => {
2114
- const ec = new TextEncoder();
2115
- const key = await generateAesKey();
2116
- const iv = await randombytes__default["default"](16);
2117
-
2118
- const ciphertext = await encryptAes(ec.encode(string), key, iv);
2119
- const exported = await exportAesKey(key);
2120
-
2121
- return {
2122
- key: arrayBufferToHex(exported),
2123
- iv: iv.toString('hex'),
2124
- cipher: arrayBufferToHex(ciphertext)
2125
- }
2126
- };
2127
-
2128
- const decrypt = async (cipher, key, iv) => {
2129
- if (!key.type) key = await importAesKey(hexToUint8Array(key));
2130
- cipher = new Uint8Array(hexToUint8Array(cipher));
2131
- iv = new Uint8Array(hexToUint8Array(iv));
2132
-
2133
- const dec = new TextDecoder();
2134
- const plaintext = await subtle.decrypt({
2135
- name: 'AES-CBC',
2136
- iv,
2137
- }, key, cipher);
2138
-
2139
- return dec.decode(plaintext);
2140
- };
2141
-
2142
- const { encode, decode } = bs58check__namespace;
2143
-
2144
- // TODO: multihash addresses
2145
- class HDAccount {
2146
- /**
2147
- * @param {number} depth - acount depth
2148
- */
2149
- constructor(node, depth = 0) {
2150
- this.node = node;
2151
- this.depth = depth;
2152
- this._prefix = `m/44'/${node.network.coin_type}'/${depth}'/`;
2153
- }
2154
-
2155
- /**
2156
- * @param {number} index - address index
2157
- */
2158
- internal(index = 0) {
2159
- return this.node.derivePath(`${this._prefix}1/${index}`)
2160
- }
2161
-
2162
- /**
2163
- * @param {number} index - address index
2164
- */
2165
- external(index = 0) {
2166
- return this.node.derivePath(`${this._prefix}0/${index}`)
2167
- }
2168
- }
2169
-
2170
- class MultiWallet extends HDWallet {
2171
- constructor(network, hdnode) {
2172
- super(network, hdnode);
2173
- this.multiCodec = this.network.multiCodec;
2174
- this.version = 0x00;
2175
- }
2176
-
2177
- get id() {
2178
- const buffer = Buffer.concat([
2179
- Buffer.from(varint__default["default"].encode(this.multiCodec)),
2180
- Buffer.from(this.account(0).node.neutered.publicKey, 'hex')
2181
- ]);
2182
- return encode(buffer)
2183
- }
2184
-
2185
- get multiWIF() {
2186
- return this.ifNotLocked(() => this.encode())
2187
- }
2188
-
2189
- get neutered() {
2190
- const neutered = this.ifNotLocked(() => new MultiWallet(this.networkName, this.hdnode.neutered()));
2191
- if (neutered) this._neutered = neutered;
2192
- return this._neutered
1660
+ get neutered() {
1661
+ const neutered = this.ifNotLocked(() => new MultiWallet(this.networkName, this.hdnode.neutered()));
1662
+ if (neutered) this._neutered = neutered;
1663
+ return this._neutered
2193
1664
  }
2194
1665
 
2195
1666
  fromId(id) {
@@ -2243,707 +1714,1272 @@ class MultiWallet extends HDWallet {
2243
1714
  return encode(buffer);
2244
1715
  }
2245
1716
 
2246
- decode(bs58) {
2247
- let buffer = decode(bs58);
2248
- const version = varint__default["default"].decode(buffer);
2249
- buffer = buffer.slice(varint__default["default"].decode.bytes);
2250
- const multiCodec = varint__default["default"].decode(buffer);
2251
- buffer = buffer.slice(varint__default["default"].decode.bytes);
2252
- bs58 = encode(buffer);
2253
- if (version !== this.version) throw TypeError('Invalid version');
2254
- if (this.multiCodec !== multiCodec) throw TypeError('Invalid multiCodec');
2255
- return { version, multiCodec, bs58 };
2256
- }
1717
+ decode(bs58) {
1718
+ let buffer = decode(bs58);
1719
+ const version = varint__default["default"].decode(buffer);
1720
+ buffer = buffer.slice(varint__default["default"].decode.bytes);
1721
+ const multiCodec = varint__default["default"].decode(buffer);
1722
+ buffer = buffer.slice(varint__default["default"].decode.bytes);
1723
+ bs58 = encode(buffer);
1724
+ if (version !== this.version) throw TypeError('Invalid version');
1725
+ if (this.multiCodec !== multiCodec) throw TypeError('Invalid multiCodec');
1726
+ return { version, multiCodec, bs58 };
1727
+ }
1728
+
1729
+ sign(hash) {
1730
+ return new MultiSignature__default["default"](this.version, this.network.multiCodec)
1731
+ .sign(hash, this.privateKeyBuffer);
1732
+
1733
+ }
1734
+
1735
+ verify(multiSignature, hash) {
1736
+ return new MultiSignature__default["default"](this.version, this.network.multiCodec)
1737
+ .verify(multiSignature, hash, this.publicKeyBuffer)
1738
+ }
1739
+
1740
+ /**
1741
+ * @param {number} account - account to return chain for
1742
+ * @return { internal(addressIndex), external(addressIndex) }
1743
+ */
1744
+ account(index) {
1745
+ return new HDAccount(new MultiWallet(this.networkName, this.hdnode), index);
1746
+ }
1747
+
1748
+ /**
1749
+ * m / purpose' / coin_type' / account' / change / aadress_index
1750
+ *
1751
+ * see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
1752
+ */
1753
+ derivePath(path) {
1754
+ return new MultiWallet(this.networkName, this.hdnode.derivePath(path))
1755
+ }
1756
+
1757
+ derive(index) {
1758
+ return new MultiWallet(this.networkName, this.hdnode.derive(index));
1759
+ }
1760
+ }
1761
+
1762
+ class MessageHandler {
1763
+ constructor(network) {
1764
+ this.network = network;
1765
+ }
1766
+ /**
1767
+ * hash and sign message
1768
+ *
1769
+ * @param {object} message
1770
+ * @param {Buffer} message.from peer id
1771
+ * @param {Buffer} message.to peer id
1772
+ * @param {string} message.data Peernet message
1773
+ * (PeernetMessage excluded) encoded as a string
1774
+ * @return signature
1775
+ */
1776
+ async hashAndSignMessage(message) {
1777
+ const hasher = new codecFormatInterface.CodecHash(message, {name: 'peernet-message'});
1778
+ let identity = await walletStore.get('identity');
1779
+ identity = JSON.parse(new TextDecoder().decode(identity));
1780
+ const wallet = new MultiWallet(this.network);
1781
+ wallet.recover(identity.mnemonic);
1782
+ return wallet.sign(Buffer.from(hasher.hash).slice(0, 32))
1783
+ }
1784
+
1785
+ /**
1786
+ * @param {String} from - peer id
1787
+ * @param {String} to - peer id
1788
+ * @param {String|PeernetMessage} data - data encoded message string
1789
+ * or the messageNode itself
1790
+ */
1791
+ async prepareMessage(from, to, data, id) {
1792
+ if (data.encoded) data = data.encoded;
1793
+
1794
+ const message = {
1795
+ from,
1796
+ to,
1797
+ data,
1798
+ };
1799
+ const signature = await this.hashAndSignMessage(message);
1800
+ const node = new PeernetMessage({
1801
+ ...message,
1802
+ signature,
1803
+ });
1804
+
1805
+ return node
1806
+ }
1807
+ }
1808
+
1809
+ const dataHandler = async message => {
1810
+ if (!message) return
1811
+
1812
+ const {data, id} = message;
1813
+
1814
+ message = protoFor(data);
1815
+ const proto = protoFor(message.decoded.data);
1816
+ const from = message.decoded.from;
1817
+
1818
+ peernet._protoHandler({id, proto}, peernet.client.connections[from], from);
1819
+ };
1820
+
1821
+ const encapsulatedError = () => {
1822
+ return new Error('Nodes/Data should be send encapsulated by peernet-message')
1823
+ };
1824
+
1825
+ const dhtError = (proto) => {
1826
+ const text = `Received proto ${proto.name} expected peernet-dht-response`;
1827
+ return new Error(`Routing error: ${text}`)
1828
+ };
1829
+
1830
+ const nothingFoundError = (hash) => {
1831
+ return new Error(`nothing found for ${hash}`)
1832
+ };
1833
+
1834
+ globalThis.leofcoin = globalThis.leofcoin || {};
1835
+ globalThis.globalSub = globalThis.globalSub || new PubSub({verbose: true});
1836
+
1837
+ /**
1838
+ * @access public
1839
+ * @example
1840
+ * const peernet = new Peernet();
1841
+ */
1842
+ class Peernet {
1843
+ /**
1844
+ * @access public
1845
+ * @param {Object} options
1846
+ * @param {String} options.network - desired network
1847
+ * @param {String} options.root - path to root directory
1848
+ * @param {String} options.storePrefix - prefix for datatores (lfc)
1849
+ *
1850
+ * @return {Promise} instance of Peernet
1851
+ *
1852
+ * @example
1853
+ * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
1854
+ */
1855
+ constructor(options = {}) {
1856
+ this._discovered = [];
1857
+ /**
1858
+ * @property {String} network - current network
1859
+ */
1860
+ this.network = options.network || 'leofcoin';
1861
+ const parts = this.network.split(':');
1862
+
1863
+ if (!options.storePrefix) options.storePrefix = 'lfc';
1864
+ if (!options.port) options.port = 2000;
1865
+ if (!options.root) {
1866
+ if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
1867
+ else options.root = `.${this.network}/peernet`;
1868
+ }
1869
+ globalThis.peernet = this;
1870
+ this.bw = {
1871
+ up: 0,
1872
+ down: 0,
1873
+ };
1874
+ return this._init(options)
1875
+ }
1876
+
1877
+ get defaultStores() {
1878
+ return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
1879
+ }
1880
+
1881
+ addProto(name, proto) {
1882
+ if (!this.protos[name]) this.protos[name] = proto;
1883
+ }
1884
+
1885
+ addCodec(name, codec) {
1886
+ if (!this.codecs[name]) this.codecs[name] = codec;
1887
+ }
1888
+
1889
+ async addStore(name, prefix, root, isPrivate = true) {
1890
+ if (name === 'block' || name === 'transaction' || name === 'chain' ||
1891
+ name === 'data' || name === 'message') isPrivate = false;
1892
+
1893
+ let Storage;
1894
+ if (this.hasDaemon) {
1895
+ Storage = LeofcoinStorageClient;
1896
+ } else {
1897
+ Storage = globalThis.LeofcoinStorage?.default ? globalThis.LeofcoinStorage.default : LeofcoinStorage__default["default"];
1898
+ }
1899
+ globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
1900
+ await new Storage(name, root);
1901
+
1902
+ globalThis[`${name}Store`].private = isPrivate;
1903
+ if (!isPrivate) this.stores.push(name);
1904
+ }
1905
+
1906
+
1907
+ /**
1908
+ * @see MessageHandler
1909
+ */
1910
+ prepareMessage(to, data) {
1911
+ return this._messageHandler.prepareMessage(this.id, to, data)
1912
+ }
1913
+
1914
+ /**
1915
+ * @access public
1916
+ *
1917
+ * @return {Array} peerId
1918
+ */
1919
+ get peers() {
1920
+ return Object.keys(this.client.connections)
1921
+ }
1922
+
1923
+ get connections() {
1924
+ return Object.values(this.client.connections)
1925
+ }
1926
+
1927
+ get peerEntries() {
1928
+ return Object.entries(this.client.connections)
1929
+ }
1930
+
1931
+ /**
1932
+ * @return {String} id - peerId
1933
+ */
1934
+ getConnection(id) {
1935
+ return this.client.connections[id]
1936
+ }
1937
+
1938
+ /**
1939
+ * @private
1940
+ *
1941
+ * @param {Object} options
1942
+ * @param {String} options.root - path to root directory
1943
+ *
1944
+ * @return {Promise} instance of Peernet
1945
+ */
1946
+ async _init(options) {
1947
+ // peernetDHT aka closesPeer by coordinates
1948
+ /**
1949
+ * @type {Object}
1950
+ * @property {Object} peer Instance of Peer
1951
+ */
1952
+ this.dht = new DhtEarth();
1953
+ /**
1954
+ * @type {Map}
1955
+ * @property {Object} peer Instance of Peer
1956
+ */
1957
+ this.stores = [];
1958
+ this.requestProtos = {};
1959
+ this.storePrefix = options.storePrefix;
1960
+ this.root = options.root;
1961
+
1962
+ /**
1963
+ * proto Object containing protos
1964
+ * @type {Object}
1965
+ * @property {PeernetMessage} protos[peernet-message] messageNode
1966
+ * @property {DHTMessage} protos[peernet-dht] messageNode
1967
+ * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
1968
+ * @property {DataMessage} protos[peernet-data] messageNode
1969
+ * @property {DataMessageResponse} protos[peernet-data-response] messageNode
1970
+ */
1971
+ globalThis.peernet.protos = {
1972
+ 'peernet-request': RequestMessage,
1973
+ 'peernet-response': ResponseMessage,
1974
+ 'peernet-peer': PeerMessage,
1975
+ 'peernet-peer-response': PeerMessageResponse,
1976
+ 'peernet-message': PeernetMessage,
1977
+ 'peernet-dht': DHTMessage,
1978
+ 'peernet-dht-response': DHTMessageResponse,
1979
+ 'peernet-data': DataMessage,
1980
+ 'peernet-data-response': DataMessageResponse,
1981
+ 'peernet-ps': PsMessage,
1982
+ 'chat-message': ChatMessage,
1983
+ };
1984
+
1985
+ this.protos = globalThis.peernet.protos;
1986
+ this.codecs = codecFormatInterface.codecs;
1987
+
1988
+ this._messageHandler = new MessageHandler(this.network);
1989
+
1990
+ const {daemon, environment} = await target();
1991
+ this.hasDaemon = daemon;
1992
+
1993
+
1994
+
1995
+ for (const store of this.defaultStores) {
1996
+ await this.addStore(store, options.storePrefix, options.root);
1997
+ }
1998
+
1999
+ try {
2000
+ const pub = await accountStore.get('public');
2001
+ this.id = JSON.parse(new TextDecoder().decode(pub)).walletId;
2002
+ } catch (e) {
2003
+ if (e.code === 'ERR_NOT_FOUND') {
2004
+ const {identity, accounts, config} = await generateAccount(this.network);
2005
+ walletStore.put('version', new TextEncoder().encode(1));
2006
+ walletStore.put('accounts', new TextEncoder().encode(accounts));
2007
+ walletStore.put('identity', new TextEncoder().encode(JSON.stringify(identity)));
2008
+ await accountStore.put('config', new TextEncoder().encode(JSON.stringify(config)));
2009
+ await accountStore.put('public', new TextEncoder().encode(JSON.stringify({walletId: identity.walletId})));
2010
+
2011
+ this.id = identity.walletId;
2012
+ } else {
2013
+ throw e
2014
+ }
2015
+ }
2016
+ this._peerHandler = new PeerDiscovery(this.id);
2017
+ this.peerId = this.id;
2018
+
2019
+ pubsub.subscribe('peer:connected', async (peer) => {
2020
+ console.log(peer);
2021
+ // console.log({connected: peer.id, as: this._getPeerId(peer.id) });
2022
+ // peer.on('peernet.data', async (message) => {
2023
+ // const id = message.id
2024
+ // message = new PeernetMessage(Buffer.from(message.data.data))
2025
+ // const proto = protoFor(message.decoded.data)
2026
+ // this._protoHandler({id, proto}, peer)
2027
+ // })
2028
+ });
2029
+
2030
+ /**
2031
+ * converts data -> message -> proto
2032
+ * @see DataHandler
2033
+ */
2034
+ pubsub.subscribe('peer:data', dataHandler);
2035
+
2036
+ /**
2037
+ * @access public
2038
+ * @type {PeernetClient}
2039
+ */
2040
+ this.client = new Client(this.id);
2041
+ if (globalThis.onbeforeunload) {
2042
+ globalThis.addEventListener('beforeunload', async () => this.client.close());
2043
+ }
2044
+ return this
2045
+ }
2046
+
2047
+ addRequestHandler(name, method) {
2048
+ this.requestProtos[name] = method;
2049
+ }
2050
+
2051
+ sendMessage(peer, id, data) {
2052
+ if (peer.readyState === 'open') {
2053
+ peer.send(data, id);
2054
+ this.bw.up += data.length;
2055
+ } else if (peer.readyState === 'closed') ;
2056
+
2057
+ }
2058
+
2059
+ /**
2060
+ * @private
2061
+ *
2062
+ * @param {Buffer} message - peernet message
2063
+ * @param {PeernetPeer} peer - peernet peer
2064
+ */
2065
+ async _protoHandler(message, peer, from) {
2066
+
2067
+ const {id, proto} = message;
2068
+ this.bw.down += proto.encoded.length;
2069
+ if (proto.name === 'peernet-dht') {
2070
+ let { hash, store } = proto.decoded;
2071
+ let has;
2072
+
2073
+ if (!store) {
2074
+ has = await this.has(hash);
2075
+ } else {
2076
+ store = globalThis[`${store}Store`];
2077
+ if (store.private) has = false;
2078
+ else has = await store.has(hash);
2079
+ }
2080
+ const data = new DHTMessageResponse({hash, has});
2081
+ const node = await this.prepareMessage(from, data.encoded);
2082
+
2083
+ this.sendMessage(peer, id, node.encoded);
2084
+ } else if (proto.name === 'peernet-data') {
2085
+ let { hash, store } = proto.decoded;
2086
+ let data;
2087
+ if (!store) {
2088
+ store = await this.whichStore([...this.stores], hash);
2089
+ } else {
2090
+ store = globalThis[`${store}Store`];
2091
+ }
2092
+ if (store && !store.private) {
2093
+ data = await store.get(hash);
2094
+
2095
+ if (data) {
2096
+ data = new DataMessageResponse({hash, data});
2097
+
2098
+ const node = await this.prepareMessage(from, data.encoded);
2099
+ this.sendMessage(peer, id, node.encoded);
2100
+ }
2101
+ }
2102
+
2103
+ } else if (proto.name === 'peernet-request') {
2104
+ const method = this.requestProtos[proto.decoded.request];
2105
+ if (method) {
2106
+ const data = await method();
2107
+ const node = await this.prepareMessage(from, data.encoded);
2108
+ this.sendMessage(peer, id, node.encoded);
2109
+ }
2110
+ } else if (proto.name === 'peernet-ps' && peer.peerId !== this.id) {
2111
+ globalSub.publish(new TextDecoder().decode(proto.decoded.topic), proto.decoded.data);
2112
+ }
2113
+ // }
2114
+ }
2115
+
2116
+ /**
2117
+ * performs a walk and resolves first encounter
2118
+ *
2119
+ * @param {String} hash
2120
+ */
2121
+ async walk(hash) {
2122
+ if (!hash) throw new Error('hash expected, received undefined')
2123
+ const data = new DHTMessage({hash});
2124
+ this.client.id;
2125
+ const walk = async peer => {
2126
+ const node = await this.prepareMessage(peer.peerId, data.encoded);
2127
+ let result = await peer.request(node.encoded);
2128
+ result = new Uint8Array(Object.values(result));
2129
+ let proto = protoFor(result);
2130
+ if (proto.name !== 'peernet-message') throw encapsulatedError()
2131
+ const from = proto.decoded.from;
2132
+ proto = protoFor(proto.decoded.data);
2133
+ if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
2134
+
2135
+ // TODO: give ip and port (just used for location)
2136
+ if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
2137
+ peer.connection.remoteFamily = 'ipv4';
2138
+ peer.connection.remoteAddress = '127.0.0.1';
2139
+ peer.connection.remotePort = '0000';
2140
+ }
2141
+
2142
+ const peerInfo = {
2143
+ family: peer.connection.remoteFamily || peer.connection.localFamily,
2144
+ address: peer.connection.remoteAddress || peer.connection.localAddress,
2145
+ port: peer.connection.remotePort || peer.connection.localPort,
2146
+ id: from,
2147
+ };
2148
+
2149
+ if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
2150
+ };
2151
+ let walks = [];
2152
+ for (const peer of this.connections) {
2153
+ if (peer.peerId !== this.id) {
2154
+ walks.push(walk(peer));
2155
+ }
2156
+ }
2157
+ return Promise.all(walks)
2158
+ }
2159
+
2160
+ /**
2161
+ * Override DHT behavior, try's finding the content three times
2162
+ *
2163
+ * @param {String} hash
2164
+ */
2165
+ async providersFor(hash) {
2166
+ let providers = await this.dht.providersFor(hash);
2167
+ // walk the network to find a provider
2168
+ if (!providers || providers.length === 0) {
2169
+ await this.walk(hash);
2170
+ providers = await this.dht.providersFor(hash);
2171
+ // second walk the network to find a provider
2172
+ if (!providers || providers.length === 0) {
2173
+ await this.walk(hash);
2174
+ providers = await this.dht.providersFor(hash);
2175
+ }
2176
+ // last walk
2177
+ if (!providers || providers.length === 0) {
2178
+ await this.walk(hash);
2179
+ providers = await this.dht.providersFor(hash);
2180
+ }
2181
+ }
2182
+ // undefined if no providers given
2183
+ return providers
2184
+ }
2185
+
2186
+ get block() {
2187
+ return {
2188
+ get: async (hash) => {
2189
+ const data = await blockStore.has(hash);
2190
+ if (data) return await blockStore.get(hash)
2191
+ return this.requestData(hash, 'block')
2192
+ },
2193
+ put: async (hash, data) => {
2194
+ if (await blockStore.has(hash)) return
2195
+ return await blockStore.put(hash, data)
2196
+ },
2197
+ has: async (hash) => await blockStore.has(hash, 'block'),
2198
+ }
2199
+ }
2200
+
2201
+ get transaction() {
2202
+ return {
2203
+ get: async (hash) => {
2204
+ const data = await transactionStore.has(hash);
2205
+ if (data) return await transactionStore.get(hash)
2206
+ return this.requestData(hash, 'transaction')
2207
+ },
2208
+ put: async (hash, data) => {
2209
+ if (await transactionStore.has(hash)) return
2210
+ return await transactionStore.put(hash, data)
2211
+ },
2212
+ has: async (hash) => await transactionStore.has(hash),
2213
+ }
2214
+ }
2215
+
2216
+ async requestData(hash, store) {
2217
+ const providers = await this.providersFor(hash);
2218
+ if (!providers || providers.size === 0) throw nothingFoundError(hash)
2219
+ debug(`found ${providers.size} provider(s) for ${hash}`);
2220
+ // get closest peer on earth
2221
+ const closestPeer = await this.dht.closestPeer(providers);
2222
+ // get peer instance by id
2223
+ if (!closestPeer || !closestPeer.id) return this.requestData(hash, store?.name ? store?.name : store)
2224
+
2225
+ const id = closestPeer.id;
2226
+ if (this.connections) {
2227
+ let closest = this.connections.filter((peer) => {
2228
+ if (peer.peerId === id) return peer
2229
+ });
2257
2230
 
2258
- sign(hash) {
2259
- return new MultiSignature__default["default"](this.version, this.network.multiCodec)
2260
- .sign(hash, this.privateKeyBuffer);
2231
+ let data = new DataMessage({hash, store: store?.name ? store?.name : store});
2261
2232
 
2262
- }
2233
+ const node = await this.prepareMessage(id, data.encoded);
2234
+ if (closest[0]) data = await closest[0].request(node.encoded);
2235
+ else {
2236
+ closest = this.connections.filter((peer) => {
2237
+ if (peer.peerId === id) return peer
2238
+ });
2239
+ if (closest[0]) data = await closest[0].request(node.encoded);
2240
+ }
2241
+ data = new Uint8Array(Object.values(data));
2242
+ let proto = protoFor(data);
2243
+ proto = protoFor(proto.decoded.data);
2244
+ // TODO: store data automaticly or not
2245
+ return proto.decoded.data
2263
2246
 
2264
- verify(multiSignature, hash) {
2265
- return new MultiSignature__default["default"](this.version, this.network.multiCodec)
2266
- .verify(multiSignature, hash, this.publicKeyBuffer)
2267
- }
2247
+ // this.put(hash, proto.decoded.data)
2248
+ }
2249
+ return null
2250
+ }
2268
2251
 
2269
- /**
2270
- * @param {number} account - account to return chain for
2271
- * @return { internal(addressIndex), external(addressIndex) }
2272
- */
2273
- account(index) {
2274
- return new HDAccount(new MultiWallet(this.networkName, this.hdnode), index);
2275
- }
2276
2252
 
2277
- /**
2278
- * m / purpose' / coin_type' / account' / change / aadress_index
2279
- *
2280
- * see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
2281
- */
2282
- derivePath(path) {
2283
- return new MultiWallet(this.networkName, this.hdnode.derivePath(path))
2284
- }
2253
+ get message() {
2254
+ return {
2255
+ /**
2256
+ * Get content for given message hash
2257
+ *
2258
+ * @param {String} hash
2259
+ */
2260
+ get: async (hash) => {
2261
+ debug(`get message ${hash}`);
2262
+ const message = await messageStore.has(hash);
2263
+ if (message) return await messageStore.get(hash)
2264
+ return this.requestData(hash, 'message')
2265
+ },
2266
+ /**
2267
+ * put message content
2268
+ *
2269
+ * @param {String} hash
2270
+ * @param {Buffer} message
2271
+ */
2272
+ put: async (hash, message) => await messageStore.put(hash, message),
2273
+ /**
2274
+ * @param {String} hash
2275
+ * @return {Boolean}
2276
+ */
2277
+ has: async (hash) => await messageStore.has(hash),
2278
+ }
2279
+ }
2285
2280
 
2286
- derive(index) {
2287
- return new MultiWallet(this.networkName, this.hdnode.derive(index));
2288
- }
2289
- }
2290
-
2291
- class MessageHandler {
2292
- constructor(network) {
2293
- this.network = network;
2281
+ get data() {
2282
+ return {
2283
+ /**
2284
+ * Get content for given data hash
2285
+ *
2286
+ * @param {String} hash
2287
+ */
2288
+ get: async (hash) => {
2289
+ debug(`get data ${hash}`);
2290
+ const data = await dataStore.has(hash);
2291
+ if (data) return await dataStore.get(hash)
2292
+ return this.requestData(hash, 'data')
2293
+ },
2294
+ /**
2295
+ * put data content
2296
+ *
2297
+ * @param {String} hash
2298
+ * @param {Buffer} data
2299
+ */
2300
+ put: async (hash, data) => await dataStore.put(hash, data),
2301
+ /**
2302
+ * @param {String} hash
2303
+ * @return {Boolean}
2304
+ */
2305
+ has: async (hash) => await dataStore.has(hash),
2306
+ }
2294
2307
  }
2308
+
2295
2309
  /**
2296
- * hash and sign message
2297
- *
2298
- * @param {object} message
2299
- * @param {Buffer} message.from peer id
2300
- * @param {Buffer} message.to peer id
2301
- * @param {string} message.data Peernet message
2302
- * (PeernetMessage excluded) encoded as a string
2303
- * @return signature
2310
+ * goes trough given stores and tries to find data for given hash
2311
+ * @param {Array} stores
2312
+ * @param {string} hash
2304
2313
  */
2305
- async hashAndSignMessage(message) {
2306
- const hasher = new PeernetHash(message, {name: 'peernet-message'});
2307
- let identity = await walletStore.get('identity');
2308
- identity = JSON.parse(new TextDecoder().decode(identity));
2309
- const wallet = new MultiWallet(this.network);
2310
- wallet.recover(identity.mnemonic);
2311
- return wallet.sign(Buffer.from(hasher.hash).slice(0, 32))
2314
+ async whichStore(stores, hash) {
2315
+ let store = stores.pop();
2316
+ store = globalThis[`${store}Store`];
2317
+ if (store) {
2318
+ const has = await store.has(hash);
2319
+ if (has) return store
2320
+ if (stores.length > 0) return this.whichStore(stores, hash)
2321
+ } else return null
2312
2322
  }
2313
2323
 
2314
2324
  /**
2315
- * @param {String} from - peer id
2316
- * @param {String} to - peer id
2317
- * @param {String|PeernetMessage} data - data encoded message string
2318
- * or the messageNode itself
2325
+ * Get content for given hash
2326
+ *
2327
+ * @param {String} hash - the hash of the wanted data
2328
+ * @param {String} store - storeName to access
2319
2329
  */
2320
- async prepareMessage(from, to, data, id) {
2321
- if (data.encoded) data = data.encoded;
2330
+ async get(hash, store) {
2331
+ debug(`get ${hash}`);
2332
+ let data;
2333
+ if (store) store = globalThis[`${store}Store`];
2334
+ if (!store) store = await this.whichStore([...this.stores], hash);
2335
+ if (store && await store.has(hash)) data = await store.get(hash);
2336
+ if (data) return data
2322
2337
 
2323
- const message = {
2324
- from,
2325
- to,
2326
- data,
2327
- };
2328
- const signature = await this.hashAndSignMessage(message);
2329
- const node = new PeernetMessage({
2330
- ...message,
2331
- signature,
2332
- });
2338
+ return this.requestData(hash, store?.name ? store.name : store)
2339
+ }
2333
2340
 
2334
- return node
2341
+ /**
2342
+ * put content
2343
+ *
2344
+ * @param {String} hash
2345
+ * @param {Buffer} data
2346
+ * @param {String} store - storeName to access
2347
+ */
2348
+ async put(hash, data, store = 'data') {
2349
+ store = globalThis[`${store}Store`];
2350
+ return store.put(hash, data)
2335
2351
  }
2336
- }
2337
-
2338
- const dataHandler = async message => {
2339
- if (!message) return
2340
2352
 
2341
- const {data, id} = message;
2353
+ /**
2354
+ * @param {String} hash
2355
+ * @return {Boolean}
2356
+ */
2357
+ async has(hash) {
2358
+ const store = await this.whichStore([...this.stores], hash);
2359
+ if (store) {
2360
+ if (store.private) return false
2361
+ else return true
2362
+ }
2363
+ return false
2364
+ }
2342
2365
 
2343
- message = protoFor(data);
2344
- const proto = protoFor(message.decoded.data);
2345
- const from = message.decoded.from;
2366
+ /**
2367
+ *
2368
+ * @param {String} topic
2369
+ * @param {String|Object|Array|Boolean|Buffer} data
2370
+ */
2371
+ async publish(topic, data) {
2372
+ // globalSub.publish(topic, data)
2373
+ if (topic instanceof Uint8Array === false) topic = new TextEncoder().encode(topic);
2374
+ if (data instanceof Uint8Array === false) data = new TextEncoder().encode(JSON.stringify(data));
2375
+ const id = Math.random().toString(36).slice(-12);
2376
+ data = new PsMessage({data, topic});
2377
+ for (const peer of this.connections) {
2378
+ if (peer.peerId !== this.peerId) {
2379
+ const node = await this.prepareMessage(peer.peerId, data.encoded);
2380
+ this.sendMessage(peer, id, node.encoded);
2381
+ }
2382
+ // TODO: if peer subscribed
2383
+ }
2384
+ }
2346
2385
 
2347
- peernet._protoHandler({id, proto}, peernet.client.connections[from], from);
2348
- };
2349
-
2350
- const encapsulatedError = () => {
2351
- return new Error('Nodes/Data should be send encapsulated by peernet-message')
2352
- };
2353
-
2354
- const dhtError = (proto) => {
2355
- const text = `Received proto ${proto.name} expected peernet-dht-response`;
2356
- return new Error(`Routing error: ${text}`)
2357
- };
2358
-
2359
- const nothingFoundError = (hash) => {
2360
- return new Error(`nothing found for ${hash}`)
2361
- };
2362
-
2363
- globalThis.leofcoin = globalThis.leofcoin || {};
2364
- globalThis.globalSub = globalThis.globalSub || new PubSub({verbose: true});
2386
+ createHash(data, name) {
2387
+ return new codecFormatInterface.CodecHash(data, {name})
2388
+ }
2365
2389
 
2366
- /**
2367
- * @access public
2368
- * @example
2369
- * const peernet = new Peernet();
2370
- */
2371
- class Peernet {
2372
2390
  /**
2373
- * @access public
2374
- * @param {Object} options
2375
- * @param {String} options.network - desired network
2376
- * @param {String} options.root - path to root directory
2377
- * @param {String} options.storePrefix - prefix for datatores (lfc)
2378
- *
2379
- * @return {Promise} instance of Peernet
2380
2391
  *
2381
- * @example
2382
- * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
2392
+ * @param {String} topic
2393
+ * @param {Method} cb
2383
2394
  */
2384
- constructor(options = {}) {
2385
- this._discovered = [];
2386
- /**
2387
- * @property {String} network - current network
2388
- */
2389
- this.network = options.network || 'leofcoin';
2390
- const parts = this.network.split(':');
2395
+ async subscribe(topic, cb) {
2396
+ // TODO: if peer subscribed
2397
+ globalSub.subscribe(topic, cb);
2398
+ }
2391
2399
 
2392
- if (!options.storePrefix) options.storePrefix = 'lfc';
2393
- if (!options.port) options.port = 2000;
2394
- if (!options.root) {
2395
- if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
2396
- else options.root = `.${this.network}/peernet`;
2397
- }
2398
- globalThis.peernet = this;
2399
- this.bw = {
2400
- up: 0,
2401
- down: 0,
2402
- };
2403
- return this._init(options)
2400
+ async removePeer(peer) {
2401
+ return this.client.removePeer(peer)
2404
2402
  }
2405
2403
 
2406
- get defaultStores() {
2407
- return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
2404
+ get Buffer() {
2405
+ return Buffer
2408
2406
  }
2407
+ // async block(index) {
2408
+ // const _values = []
2409
+ // for (const peer of this.peers) {
2410
+ // const value = await peer.request({type: 'block', index})
2411
+ // console.log(value);
2412
+ // }
2413
+ //
2414
+ // }
2415
+ }
2416
+
2417
+ module.exports = Peernet;
2418
+
2419
+
2420
+ /***/ }),
2421
+
2422
+ /***/ 5698:
2423
+ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
2424
+
2425
+ "use strict";
2426
+ // ESM COMPAT FLAG
2427
+ __webpack_require__.r(__webpack_exports__);
2428
+
2429
+ // EXPORTS
2430
+ __webpack_require__.d(__webpack_exports__, {
2431
+ "default": function() { return /* binding */ src; }
2432
+ });
2433
+
2434
+ // EXTERNAL MODULE: ./node_modules/@vandeurenglenn/base32/src/base32.js
2435
+ var src_base32 = __webpack_require__(103);
2436
+ // EXTERNAL MODULE: ./node_modules/@vandeurenglenn/base58/src/base58.js
2437
+ var src_base58 = __webpack_require__(158);
2438
+ ;// CONCATENATED MODULE: ./node_modules/@vandeurenglenn/is-hex/is-hex.js
2439
+ /* harmony default export */ var is_hex = (string => /^[A-F0-9]+$/i.test(string));
2440
+
2441
+ ;// CONCATENATED MODULE: ./node_modules/@leofcoin/codec-format-interface/src/basic-interface.js
2442
+ /* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"];
2409
2443
 
2410
- addProto(name, proto) {
2411
- if (!this.protos[name]) this.protos[name] = proto;
2444
+
2445
+
2446
+
2447
+ class BasicInterface {
2448
+ #handleDecode() {
2449
+ if (!this.decode) throw new Error('bad implementation: needs decode func')
2450
+ this.decode()
2412
2451
  }
2413
2452
 
2414
- addCodec(name, codec) {
2415
- if (!this.codecs[name]) this.codecs[name] = codec;
2453
+ #handleEncode() {
2454
+ if (!this.encode) throw new Error('bad implementation: needs encode func')
2455
+ this.encode()
2456
+ }
2457
+ isHex(string) {
2458
+ return is_hex(string)
2459
+ }
2460
+ isBase32(string) {
2461
+ return base32.isBase32(string)
2462
+ }
2463
+ isBase58(string) {
2464
+ return base58.isBase32(string)
2465
+ }
2466
+ /**
2467
+ * @param {String} encoded
2468
+ */
2469
+ fromBs32(encoded) {
2470
+ this.encoded = src_base32/* default.decode */.Z.decode(encoded)
2471
+ return this.#handleDecode()
2416
2472
  }
2417
2473
 
2418
- async addStore(name, prefix, root, isPrivate = true) {
2419
- if (name === 'block' || name === 'transaction' || name === 'chain' ||
2420
- name === 'data' || name === 'message') isPrivate = false;
2474
+ /**
2475
+ * @param {String} encoded
2476
+ */
2477
+ fromBs58(encoded) {
2478
+ this.encoded = src_base58/* default.decode */.Z.decode(encoded)
2479
+ return this.#handleDecode()
2480
+ }
2421
2481
 
2422
- let Storage;
2423
- if (this.hasDaemon) {
2424
- Storage = LeofcoinStorageClient;
2425
- } else {
2426
- Storage = globalThis.LeofcoinStorage?.default ? globalThis.LeofcoinStorage.default : LeofcoinStorage__default["default"];
2482
+ async toArray() {
2483
+ const array = []
2484
+ for await (const value of this.encoded.values()) {
2485
+ array.push(value)
2427
2486
  }
2428
- globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
2429
- await new Storage(name, root);
2487
+ return array
2488
+ }
2430
2489
 
2431
- globalThis[`${name}Store`].private = isPrivate;
2432
- if (!isPrivate) this.stores.push(name);
2490
+ fromString(string) {
2491
+ this.encoded = new Uint8Array(string.split(','))
2492
+ return this.#handleDecode()
2433
2493
  }
2434
2494
 
2495
+ fromArray(array) {
2496
+ this.encoded = new Uint8Array([...array])
2497
+ return this.#handleDecode()
2498
+ }
2435
2499
 
2436
2500
  /**
2437
- * @see MessageHandler
2501
+ * @param {Buffer} encoded
2438
2502
  */
2439
- prepareMessage(to, data) {
2440
- return this._messageHandler.prepareMessage(this.id, to, data)
2503
+ fromEncoded(encoded) {
2504
+ this.encoded = encoded
2505
+ return this.#handleDecode()
2441
2506
  }
2442
2507
 
2443
2508
  /**
2444
- * @access public
2445
- *
2446
- * @return {Array} peerId
2509
+ * @param {String} encoded
2447
2510
  */
2448
- get peers() {
2449
- return Object.keys(this.client.connections)
2511
+ fromHex(encoded) {
2512
+ this.encoded = Buffer.from(encoded, 'hex')
2513
+ return this.#handleDecode()
2450
2514
  }
2451
2515
 
2452
- get connections() {
2453
- return Object.values(this.client.connections)
2516
+ toString(encoding = 'utf8') {
2517
+ if (!this.encoded) this.#handleEncode()
2518
+ return this.encoded.toString(encoding)
2454
2519
  }
2455
2520
 
2456
- get peerEntries() {
2457
- return Object.entries(this.client.connections)
2521
+ /**
2522
+ * @return {String} encoded
2523
+ */
2524
+ toHex() {
2525
+ return this.toString('hex')
2458
2526
  }
2459
2527
 
2460
2528
  /**
2461
- * @return {String} id - peerId
2529
+ * @return {String} encoded
2462
2530
  */
2463
- getConnection(id) {
2464
- return this.client.connections[id]
2531
+ toBs32() {
2532
+ if (!this.encoded) this.#handleEncode()
2533
+ return src_base32/* default.encode */.Z.encode(this.encoded)
2465
2534
  }
2466
2535
 
2467
2536
  /**
2468
- * @private
2469
- *
2470
- * @param {Object} options
2471
- * @param {String} options.root - path to root directory
2472
- *
2473
- * @return {Promise} instance of Peernet
2537
+ * @return {String} encoded
2474
2538
  */
2475
- async _init(options) {
2476
- // peernetDHT aka closesPeer by coordinates
2477
- /**
2478
- * @type {Object}
2479
- * @property {Object} peer Instance of Peer
2480
- */
2481
- this.dht = new DhtEarth();
2482
- /**
2483
- * @type {Map}
2484
- * @property {Object} peer Instance of Peer
2485
- */
2486
- this.stores = [];
2487
- this.requestProtos = {};
2488
- this.storePrefix = options.storePrefix;
2489
- this.root = options.root;
2490
-
2491
- /**
2492
- * proto Object containing protos
2493
- * @type {Object}
2494
- * @property {PeernetMessage} protos[peernet-message] messageNode
2495
- * @property {DHTMessage} protos[peernet-dht] messageNode
2496
- * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
2497
- * @property {DataMessage} protos[peernet-data] messageNode
2498
- * @property {DataMessageResponse} protos[peernet-data-response] messageNode
2499
- */
2500
- globalThis.peernet.protos = {
2501
- 'peernet-request': RequestMessage,
2502
- 'peernet-response': ResponseMessage,
2503
- 'peernet-peer': PeerMessage,
2504
- 'peernet-peer-response': PeerMessageResponse,
2505
- 'peernet-message': PeernetMessage,
2506
- 'peernet-dht': DHTMessage,
2507
- 'peernet-dht-response': DHTMessageResponse,
2508
- 'peernet-data': DataMessage,
2509
- 'peernet-data-response': DataMessageResponse,
2510
- 'peernet-ps': PsMessage,
2511
- 'chat-message': ChatMessage,
2512
- };
2539
+ toBs58() {
2540
+ if (!this.encoded) this.#handleEncode()
2541
+ return src_base58/* default.encode */.Z.encode(this.encoded)
2542
+ }
2513
2543
 
2514
- this.protos = globalThis.peernet.protos;
2515
- this.codecs = codecs;
2544
+ /**
2545
+ * @param {Object} data
2546
+ */
2547
+ create(data) {
2548
+ const decoded = {}
2549
+ if (this.keys?.length > 0) {
2550
+ for (const key of this.keys) {
2551
+ Object.defineProperties(decoded, {
2552
+ [key]: {
2553
+ enumerable: true,
2554
+ configurable: true,
2555
+ set: (val) => value = data[key],
2556
+ get: () => data[key]
2557
+ }
2558
+ })
2559
+ }
2516
2560
 
2517
- this._messageHandler = new MessageHandler(this.network);
2561
+ this.decoded = decoded
2562
+ this.encode()
2563
+ }
2564
+ }
2565
+ }
2566
+
2567
+ // EXTERNAL MODULE: ./node_modules/varint/index.js
2568
+ var varint = __webpack_require__(4676);
2569
+ var varint_default = /*#__PURE__*/__webpack_require__.n(varint);
2570
+ ;// CONCATENATED MODULE: ./node_modules/@leofcoin/codec-format-interface/src/codecs.js
2571
+ /* harmony default export */ var codecs = ({
2572
+ // just a hash
2573
+ 'disco-hash': {
2574
+ codec: parseInt('30', 16),
2575
+ hashAlg: 'dbl-keccak-256', // ,
2576
+ // testnet: 'olivia'
2577
+ },
2578
+ 'peernet-peer-response': {
2579
+ codec: parseInt('707072', 16),
2580
+ hashAlg: 'keccak-256',
2581
+ },
2582
+ 'peernet-peer': {
2583
+ codec: parseInt('7070', 16),
2584
+ hashAlg: 'keccak-256',
2585
+ },
2586
+ 'peernet-dht': {
2587
+ codec: parseInt('706468', 16),
2588
+ hashAlg: 'keccak-256',
2589
+ },
2590
+ 'peernet-dht-response': {
2591
+ codec: parseInt('706472', 16),
2592
+ hashAlg: 'keccak-256',
2593
+ },
2594
+ // data
2595
+ 'peernet-data': {
2596
+ codec: parseInt('706461', 16),
2597
+ hashAlg: 'keccak-256',
2598
+ },
2599
+ 'peernet-data-response': {
2600
+ codec: parseInt('70646172', 16),
2601
+ hashAlg: 'keccak-256',
2602
+ },
2603
+ // message
2604
+ 'peernet-message': {
2605
+ codec: parseInt('706d65', 16),
2606
+ hashAlg: 'keccak-256',
2607
+ },
2608
+ // pubsub
2609
+ 'peernet-ps': {
2610
+ codec: parseInt('707073', 16),
2611
+ hashAlg: 'keccak-256',
2612
+ },
2613
+ 'peernet-response': {
2614
+ codec: parseInt('7072', 16),
2615
+ hashAlg: 'keccak-256',
2616
+ },
2617
+ 'peernet-request': {
2618
+ codec: parseInt('707271', 16),
2619
+ hashAlg: 'keccak-256',
2620
+ },
2621
+ // normal block
2622
+ 'leofcoin-block': {
2623
+ codec: parseInt('6c62', 16),
2624
+ hashAlg: 'dbl-keccak-512', // ,
2625
+ // testnet: 'olivia'
2626
+ },
2627
+ 'leofcoin-tx': {
2628
+ codec: parseInt('6c74', 16),
2629
+ hashAlg: 'dbl-keccak-512', // ,
2630
+ // testnet: 'olivia'
2631
+ },
2632
+ // itx
2633
+ 'leofcoin-itx': {
2634
+ codec: parseInt('6c69', 16),
2635
+ hashAlg: 'keccak-512', // ,
2636
+ // testnet: 'olivia'
2637
+ },
2638
+ // peer reputation
2639
+ 'leofcoin-pr': {
2640
+ codec: parseInt('6c70', 16),
2641
+ hashAlg: 'keccak-256', // ,
2642
+ // testnet: 'olivia'
2643
+ },
2644
+ // chat message
2645
+ 'chat-message': {
2646
+ codec: parseInt('636d', 16),
2647
+ hashAlg: 'dbl-keccak-256',
2648
+ },
2649
+ });
2650
+
2651
+ ;// CONCATENATED MODULE: ./node_modules/@leofcoin/codec-format-interface/src/codec.js
2518
2652
 
2519
- const {daemon, environment} = await target();
2520
- this.hasDaemon = daemon;
2521
2653
 
2522
-
2523
2654
 
2524
- for (const store of this.defaultStores) {
2525
- await this.addStore(store, options.storePrefix, options.root);
2526
- }
2527
2655
 
2528
- try {
2529
- const pub = await accountStore.get('public');
2530
- this.id = JSON.parse(new TextDecoder().decode(pub)).walletId;
2531
- } catch (e) {
2532
- if (e.code === 'ERR_NOT_FOUND') {
2533
- const {identity, accounts, config} = await generateAccount(this.network);
2534
- walletStore.put('version', new TextEncoder().encode(1));
2535
- walletStore.put('accounts', new TextEncoder().encode(accounts));
2536
- walletStore.put('identity', new TextEncoder().encode(JSON.stringify(identity)));
2537
- await accountStore.put('config', new TextEncoder().encode(JSON.stringify(config)));
2538
- await accountStore.put('public', new TextEncoder().encode(JSON.stringify({walletId: identity.walletId})));
2656
+ class PeernetCodec extends BasicInterface {
2657
+ get codecs() {
2658
+ return {...globalThis.peernet.codecs, ...codecs}
2659
+ }
2660
+ constructor(buffer) {
2661
+ super()
2662
+ if (buffer) {
2663
+ if (buffer instanceof Uint8Array) {
2664
+ const codec = varint_default().decode(buffer);
2665
+ const name = this.getCodecName(codec)
2666
+ if (name) {
2667
+ this.name = name
2668
+ this.encoded = buffer
2669
+ this.decode(buffer)
2670
+ } else {
2671
+ this.encode(buffer)
2672
+ }
2673
+ } else if (buffer instanceof ArrayBuffer) {
2674
+ const encoded = new Uint8Array(buffer.byteLength)
2539
2675
 
2540
- this.id = identity.walletId;
2541
- } else {
2542
- throw e
2676
+ for (let i = 0; i < buffer.byteLength; i++) {
2677
+ encoded[i] = buffer[i]
2678
+ }
2679
+ this.encoded = encoded
2680
+ // this.encoded = new Uint8Array(buffer, buffer.byteOffset, buffer.byteLength)
2681
+ this.decode(buffer)
2682
+ return
2683
+ }
2684
+ if (typeof buffer === 'string') {
2685
+ if (this.codecs[buffer]) this.fromName(buffer)
2686
+ else if (this.isHex(buffer)) this.fromHex(buffer)
2687
+ else if (this.isBase32(buffer)) this.fromBs32(buffer)
2688
+ else if (this.isBase58(buffer)) this.fromBs58(buffer)
2689
+ else throw new Error(`unsupported string ${buffer}`)
2543
2690
  }
2691
+ if (!isNaN(buffer)) if (this.codecs[this.getCodecName(buffer)]) this.fromCodec(buffer)
2544
2692
  }
2545
- this._peerHandler = new PeerDiscovery(this.id);
2546
- this.peerId = this.id;
2693
+ }
2547
2694
 
2548
- pubsub.subscribe('peer:connected', async (peer) => {
2549
- console.log(peer);
2550
- // console.log({connected: peer.id, as: this._getPeerId(peer.id) });
2551
- // peer.on('peernet.data', async (message) => {
2552
- // const id = message.id
2553
- // message = new PeernetMessage(Buffer.from(message.data.data))
2554
- // const proto = protoFor(message.decoded.data)
2555
- // this._protoHandler({id, proto}, peer)
2556
- // })
2557
- });
2695
+ fromEncoded(encoded) {
2696
+ const codec = varint_default().decode(encoded);
2697
+ const name = this.getCodecName(codec)
2698
+ this.name = name
2699
+ this.encoded = encoded
2700
+ this.decode(encoded)
2701
+ }
2558
2702
 
2559
- /**
2560
- * converts data -> message -> proto
2561
- * @see DataHandler
2562
- */
2563
- pubsub.subscribe('peer:data', dataHandler);
2703
+ getCodec(name) {
2704
+ return this.codecs[name].codec
2705
+ }
2564
2706
 
2565
- /**
2566
- * @access public
2567
- * @type {PeernetClient}
2568
- */
2569
- this.client = new Client(this.id);
2570
- if (globalThis.onbeforeunload) {
2571
- globalThis.addEventListener('beforeunload', async () => this.client.close());
2572
- }
2573
- return this
2707
+ getCodecName(codec) {
2708
+ return Object.keys(this.codecs).reduce((p, c) => {
2709
+ const item = this.codecs[c]
2710
+ if (item.codec === codec) return c;
2711
+ else return p;
2712
+ }, undefined)
2574
2713
  }
2575
2714
 
2576
- addRequestHandler(name, method) {
2577
- this.requestProtos[name] = method;
2715
+ getHashAlg(name) {
2716
+ return this.codecs[name].hashAlg
2578
2717
  }
2579
2718
 
2580
- sendMessage(peer, id, data) {
2581
- if (peer.readyState === 'open') {
2582
- peer.send(data, id);
2583
- this.bw.up += data.length;
2584
- } else if (peer.readyState === 'closed') ;
2719
+ fromCodec(codec) {
2720
+ this.name = this.getCodecName(codec)
2721
+ this.hashAlg = this.getHashAlg(this.name)
2585
2722
 
2723
+ this.codec = this.getCodec(this.name)
2724
+ this.codecBuffer = varint_default().encode(codec)
2586
2725
  }
2587
2726
 
2588
- /**
2589
- * @private
2590
- *
2591
- * @param {Buffer} message - peernet message
2592
- * @param {PeernetPeer} peer - peernet peer
2593
- */
2594
- async _protoHandler(message, peer, from) {
2727
+ fromName(name) {
2728
+ const codec = this.getCodec(name)
2729
+ this.name = name
2730
+ this.codec = codec
2731
+ this.hashAlg = this.getHashAlg(name)
2732
+ this.codecBuffer = varint_default().encode(codec)
2733
+ }
2595
2734
 
2596
- const {id, proto} = message;
2597
- this.bw.down += proto.encoded.length;
2598
- if (proto.name === 'peernet-dht') {
2599
- let { hash, store } = proto.decoded;
2600
- let has;
2735
+ decode() {
2736
+ const codec = varint_default().decode(this.encoded);
2737
+ this.fromCodec(codec)
2738
+ }
2601
2739
 
2602
- if (!store) {
2603
- has = await this.has(hash);
2604
- } else {
2605
- store = globalThis[`${store}Store`];
2606
- if (store.private) has = false;
2607
- else has = await store.has(hash);
2608
- }
2609
- const data = new DHTMessageResponse({hash, has});
2610
- const node = await this.prepareMessage(from, data.encoded);
2740
+ encode() {
2741
+ const codec = varint_default().encode(this.decoded)
2742
+ this.encoded = codec
2743
+ return this.encoded
2744
+ }
2745
+ }
2746
+
2747
+ // EXTERNAL MODULE: ./node_modules/keccak/js.js
2748
+ var js = __webpack_require__(5811);
2749
+ var js_default = /*#__PURE__*/__webpack_require__.n(js);
2750
+ ;// CONCATENATED MODULE: ./node_modules/@leofcoin/codec-format-interface/src/codec-hash.js
2751
+ /* provided dependency */ var codec_hash_Buffer = __webpack_require__(8764)["Buffer"];
2611
2752
 
2612
- this.sendMessage(peer, id, node.encoded);
2613
- } else if (proto.name === 'peernet-data') {
2614
- let { hash, store } = proto.decoded;
2615
- let data;
2616
- if (!store) {
2617
- store = await this.whichStore([...this.stores], hash);
2618
- } else {
2619
- store = globalThis[`${store}Store`];
2620
- }
2621
- if (store && !store.private) {
2622
- data = await store.get(hash);
2623
2753
 
2624
- if (data) {
2625
- data = new DataMessageResponse({hash, data});
2626
2754
 
2627
- const node = await this.prepareMessage(from, data.encoded);
2628
- this.sendMessage(peer, id, node.encoded);
2629
- }
2630
- }
2631
2755
 
2632
- } else if (proto.name === 'peernet-request') {
2633
- const method = this.requestProtos[proto.decoded.request];
2634
- if (method) {
2635
- const data = await method();
2636
- const node = await this.prepareMessage(from, data.encoded);
2637
- this.sendMessage(peer, id, node.encoded);
2756
+
2757
+ class CodecHash extends BasicInterface {
2758
+ constructor(buffer, options = {}) {
2759
+ super()
2760
+ if (options.name) this.name = options.name
2761
+ else this.name = 'disco-hash'
2762
+ if (options.codecs) this.codecs = options.codecs
2763
+ if (buffer) {
2764
+ if (buffer instanceof Uint8Array) {
2765
+ this.discoCodec = new PeernetCodec(buffer, this.codecs)
2766
+ const name = this.discoCodec.name
2767
+
2768
+ if (name) {
2769
+ this.name = name
2770
+ this.decode(buffer)
2771
+ } else {
2772
+ this.encode(buffer)
2638
2773
  }
2639
- } else if (proto.name === 'peernet-ps' && peer.peerId !== this.id) {
2640
- globalSub.publish(new TextDecoder().decode(proto.decoded.topic), proto.decoded.data);
2641
2774
  }
2642
- // }
2643
- }
2644
2775
 
2645
- /**
2646
- * performs a walk and resolves first encounter
2647
- *
2648
- * @param {String} hash
2649
- */
2650
- async walk(hash) {
2651
- if (!hash) throw new Error('hash expected, received undefined')
2652
- const data = new DHTMessage({hash});
2653
- this.client.id;
2654
- const walk = async peer => {
2655
- const node = await this.prepareMessage(peer.peerId, data.encoded);
2656
- let result = await peer.request(node.encoded);
2657
- result = new Uint8Array(Object.values(result));
2658
- let proto = protoFor(result);
2659
- if (proto.name !== 'peernet-message') throw encapsulatedError()
2660
- const from = proto.decoded.from;
2661
- proto = protoFor(proto.decoded.data);
2662
- if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
2776
+ if (typeof buffer === 'string') {
2777
+ if (this.isHex(buffer)) this.fromHex(buffer)
2778
+ if (this.isBase32(buffer)) this.fromBs32(buffer)
2779
+ else if (this.isBase58(buffer)) this.fromBs58(buffer)
2780
+ else throw new Error(`unsupported string ${buffer}`)
2781
+ } else if (typeof buffer === 'object') this.fromJSON(buffer)
2782
+ }
2783
+ }
2663
2784
 
2664
- // TODO: give ip and port (just used for location)
2665
- if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
2666
- peer.connection.remoteFamily = 'ipv4';
2667
- peer.connection.remoteAddress = '127.0.0.1';
2668
- peer.connection.remotePort = '0000';
2669
- }
2785
+ get prefix() {
2786
+ const length = this.length
2787
+ const uint8Array = new Uint8Array(length.length + this.discoCodec.codecBuffer.length)
2788
+ uint8Array.set(length)
2789
+ uint8Array.set(this.discoCodec.codecBuffer, length.length)
2670
2790
 
2671
- const peerInfo = {
2672
- family: peer.connection.remoteFamily || peer.connection.localFamily,
2673
- address: peer.connection.remoteAddress || peer.connection.localAddress,
2674
- port: peer.connection.remotePort || peer.connection.localPort,
2675
- id: from,
2676
- };
2791
+ return uint8Array
2792
+ }
2677
2793
 
2678
- if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
2679
- };
2680
- let walks = [];
2681
- for (const peer of this.connections) {
2682
- if (peer.peerId !== this.id) {
2683
- walks.push(walk(peer));
2684
- }
2685
- }
2686
- return Promise.all(walks)
2794
+ get length() {
2795
+ return varint_default().encode(this.size)
2687
2796
  }
2688
2797
 
2689
- /**
2690
- * Override DHT behavior, try's finding the content three times
2691
- *
2692
- * @param {String} hash
2693
- */
2694
- async providersFor(hash) {
2695
- let providers = await this.dht.providersFor(hash);
2696
- // walk the network to find a provider
2697
- if (!providers || providers.length === 0) {
2698
- await this.walk(hash);
2699
- providers = await this.dht.providersFor(hash);
2700
- // second walk the network to find a provider
2701
- if (!providers || providers.length === 0) {
2702
- await this.walk(hash);
2703
- providers = await this.dht.providersFor(hash);
2704
- }
2705
- // last walk
2706
- if (!providers || providers.length === 0) {
2707
- await this.walk(hash);
2708
- providers = await this.dht.providersFor(hash);
2709
- }
2710
- }
2711
- // undefined if no providers given
2712
- return providers
2798
+ get buffer() {
2799
+ return this.encoded
2713
2800
  }
2714
2801
 
2715
- get block() {
2716
- return {
2717
- get: async (hash) => {
2718
- const data = await blockStore.has(hash);
2719
- if (data) return await blockStore.get(hash)
2720
- return this.requestData(hash, 'block')
2721
- },
2722
- put: async (hash, data) => {
2723
- if (await blockStore.has(hash)) return
2724
- return await blockStore.put(hash, data)
2725
- },
2726
- has: async (hash) => await blockStore.has(hash, 'block'),
2727
- }
2802
+ get hash() {
2803
+ return this.encoded
2728
2804
  }
2729
2805
 
2730
- get transaction() {
2731
- return {
2732
- get: async (hash) => {
2733
- const data = await transactionStore.has(hash);
2734
- if (data) return await transactionStore.get(hash)
2735
- return this.requestData(hash, 'transaction')
2736
- },
2737
- put: async (hash, data) => {
2738
- if (await transactionStore.has(hash)) return
2739
- return await transactionStore.put(hash, data)
2740
- },
2741
- has: async (hash) => await transactionStore.has(hash),
2742
- }
2806
+ fromJSON(json) {
2807
+ return this.encode(codec_hash_Buffer.from(JSON.stringify(json)))
2743
2808
  }
2744
2809
 
2745
- async requestData(hash, store) {
2746
- const providers = await this.providersFor(hash);
2747
- if (!providers || providers.size === 0) throw nothingFoundError(hash)
2748
- debug(`found ${providers.size} provider(s) for ${hash}`);
2749
- // get closest peer on earth
2750
- const closestPeer = await this.dht.closestPeer(providers);
2751
- // get peer instance by id
2752
- if (!closestPeer || !closestPeer.id) return this.requestData(hash, store?.name ? store?.name : store)
2810
+ encode(buffer, name) {
2811
+ if (!this.name && name) this.name = name;
2812
+ if (!buffer) buffer = this.buffer;
2813
+ this.discoCodec = new PeernetCodec(this.name, this.codecs)
2814
+ this.discoCodec.fromName(this.name)
2815
+ let hashAlg = this.discoCodec.hashAlg
2816
+ if (hashAlg.includes('dbl')) {
2817
+ hashAlg = hashAlg.replace('dbl-', '')
2818
+ buffer = js_default()(hashAlg.replace('-', '')).update(buffer).digest()
2819
+ }
2820
+ this.digest = js_default()(hashAlg.replace('-', '')).update(buffer).digest()
2821
+ this.size = this.digest.length
2753
2822
 
2754
- const id = closestPeer.id;
2755
- if (this.connections) {
2756
- let closest = this.connections.filter((peer) => {
2757
- if (peer.peerId === id) return peer
2758
- });
2823
+ this.codec = this.discoCodec.encode();
2824
+ this.codec = this.discoCodec.codecBuffer
2825
+ const uint8Array = new Uint8Array(this.digest.length + this.prefix.length)
2826
+ uint8Array.set(this.prefix)
2827
+ uint8Array.set(this.digest, this.prefix.length)
2759
2828
 
2760
- let data = new DataMessage({hash, store: store?.name ? store?.name : store});
2829
+ this.encoded = uint8Array
2761
2830
 
2762
- const node = await this.prepareMessage(id, data.encoded);
2763
- if (closest[0]) data = await closest[0].request(node.encoded);
2764
- else {
2765
- closest = this.connections.filter((peer) => {
2766
- if (peer.peerId === id) return peer
2767
- });
2768
- if (closest[0]) data = await closest[0].request(node.encoded);
2769
- }
2770
- data = new Uint8Array(Object.values(data));
2771
- let proto = protoFor(data);
2772
- proto = protoFor(proto.decoded.data);
2773
- // TODO: store data automaticly or not
2774
- return proto.decoded.data
2831
+ return this.encoded
2832
+ }
2775
2833
 
2776
- // this.put(hash, proto.decoded.data)
2834
+ validate(buffer) {
2835
+ if (codec_hash_Buffer.isBuffer(buffer)) {
2836
+ const codec = varint_default().decode(buffer);
2837
+ if (this.codecs[codec]) {
2838
+ this.decode(buffer)
2839
+ } else {
2840
+ this.encode(buffer)
2841
+ }
2777
2842
  }
2778
- return null
2843
+ if (typeof buffer === 'string') {
2844
+ if (this.isHex(buffer)) this.fromHex(buffer)
2845
+ if (this.isBase32(buffer)) this.fromBs32(buffer)
2846
+ }
2847
+ if (typeof buffer === 'object') this.fromJSON(buffer)
2779
2848
  }
2780
2849
 
2850
+ decode(buffer) {
2851
+ this.encoded = buffer
2852
+ const codec = varint_default().decode(buffer);
2781
2853
 
2782
- get message() {
2783
- return {
2784
- /**
2785
- * Get content for given message hash
2786
- *
2787
- * @param {String} hash
2788
- */
2789
- get: async (hash) => {
2790
- debug(`get message ${hash}`);
2791
- const message = await messageStore.has(hash);
2792
- if (message) return await messageStore.get(hash)
2793
- return this.requestData(hash, 'message')
2794
- },
2795
- /**
2796
- * put message content
2797
- *
2798
- * @param {String} hash
2799
- * @param {Buffer} message
2800
- */
2801
- put: async (hash, message) => await messageStore.put(hash, message),
2802
- /**
2803
- * @param {String} hash
2804
- * @return {Boolean}
2805
- */
2806
- has: async (hash) => await messageStore.has(hash),
2854
+ this.discoCodec = new PeernetCodec(codec, this.codecs)
2855
+ // TODO: validate codec
2856
+ buffer = buffer.slice((varint_default()).decode.bytes);
2857
+ this.size = varint_default().decode(buffer);
2858
+ this.digest = buffer.slice((varint_default()).decode.bytes);
2859
+ if (this.digest.length !== this.size) {
2860
+ throw new Error(`hash length inconsistent: 0x${this.encoded.toString('hex')}`)
2807
2861
  }
2808
- }
2809
2862
 
2810
- get data() {
2863
+ // const discoCodec = new Codec(codec, this.codecs)
2864
+
2865
+ this.name = this.discoCodec.name
2866
+
2867
+
2868
+ this.size = this.digest.length
2869
+
2811
2870
  return {
2812
- /**
2813
- * Get content for given data hash
2814
- *
2815
- * @param {String} hash
2816
- */
2817
- get: async (hash) => {
2818
- debug(`get data ${hash}`);
2819
- const data = await dataStore.has(hash);
2820
- if (data) return await dataStore.get(hash)
2821
- return this.requestData(hash, 'data')
2822
- },
2823
- /**
2824
- * put data content
2825
- *
2826
- * @param {String} hash
2827
- * @param {Buffer} data
2828
- */
2829
- put: async (hash, data) => await dataStore.put(hash, data),
2830
- /**
2831
- * @param {String} hash
2832
- * @return {Boolean}
2833
- */
2834
- has: async (hash) => await dataStore.has(hash),
2871
+ codec: this.codec,
2872
+ name: this.name,
2873
+ size: this.size,
2874
+ length: this.length,
2875
+ digest: this.digest,
2835
2876
  }
2836
2877
  }
2878
+ }
2879
+
2880
+ ;// CONCATENATED MODULE: ./node_modules/@leofcoin/codec-format-interface/src/codec-format-interface.js
2881
+
2837
2882
 
2883
+
2884
+
2885
+ class FormatInterface extends BasicInterface {
2838
2886
  /**
2839
- * goes trough given stores and tries to find data for given hash
2840
- * @param {Array} stores
2841
- * @param {string} hash
2887
+ * @param {Buffer|String|Object} buffer - data - The data needed to create the desired message
2888
+ * @param {Object} proto - {encode, decode}
2889
+ * @param {Object} options - {hashFormat, name}
2842
2890
  */
2843
- async whichStore(stores, hash) {
2844
- let store = stores.pop();
2845
- store = globalThis[`${store}Store`];
2846
- if (store) {
2847
- const has = await store.has(hash);
2848
- if (has) return store
2849
- if (stores.length > 0) return this.whichStore(stores, hash)
2850
- } else return null
2891
+ constructor(buffer, proto, options = {}) {
2892
+ super()
2893
+ this.protoEncode = proto.encode
2894
+ this.protoDecode = proto.decode
2895
+ this.hashFormat = options.hashFormat || 'bs32'
2896
+ if (options.name) this.name = options.name
2897
+ if (buffer instanceof Uint8Array) this.fromUint8Array(buffer)
2898
+ else if (buffer instanceof ArrayBuffer) this.fromArrayBuffer(buffer)
2899
+ else if (buffer.name === options.name) return buffer
2900
+ else if (buffer instanceof String) {
2901
+ if (this.isHex(buffer)) this.fromHex(buffer)
2902
+ else if (this.isBase32(buffer)) this.fromBs32(buffer)
2903
+ else if (this.isBase58(buffer)) this.fromBs58(buffer)
2904
+ else throw new Error(`unsupported string ${buffer}`)
2905
+ } else {
2906
+ this.create(buffer)
2907
+ }
2851
2908
  }
2852
2909
 
2853
2910
  /**
2854
- * Get content for given hash
2855
- *
2856
- * @param {String} hash - the hash of the wanted data
2857
- * @param {String} store - storeName to access
2911
+ * @return {PeernetHash}
2858
2912
  */
2859
- async get(hash, store) {
2860
- debug(`get ${hash}`);
2861
- let data;
2862
- if (store) store = globalThis[`${store}Store`];
2863
- if (!store) store = await this.whichStore([...this.stores], hash);
2864
- if (store && await store.has(hash)) data = await store.get(hash);
2865
- if (data) return data
2866
-
2867
- return this.requestData(hash, store?.name ? store.name : store)
2913
+ get peernetHash() {
2914
+ return new CodecHash(this.decoded, {name: this.name})
2868
2915
  }
2869
2916
 
2870
2917
  /**
2871
- * put content
2872
- *
2873
- * @param {String} hash
2874
- * @param {Buffer} data
2875
- * @param {String} store - storeName to access
2918
+ * @return {peernetHash}
2876
2919
  */
2877
- async put(hash, data, store = 'data') {
2878
- store = globalThis[`${store}Store`];
2879
- return store.put(hash, data)
2920
+ get hash() {
2921
+ const upper = this.hashFormat.charAt(0).toUpperCase()
2922
+ const format = `${upper}${this.hashFormat.substring(1, this.hashFormat.length)}`
2923
+ return this.peernetHash[`to${format}`]()
2880
2924
  }
2881
2925
 
2882
2926
  /**
2883
- * @param {String} hash
2884
- * @return {Boolean}
2927
+ * @return {Object}
2885
2928
  */
2886
- async has(hash) {
2887
- const store = await this.whichStore([...this.stores], hash);
2888
- if (store) {
2889
- if (store.private) return false
2890
- else return true
2891
- }
2892
- return false
2929
+ decode() {
2930
+ let encoded = this.encoded;
2931
+ const discoCodec = new PeernetCodec(this.encoded)
2932
+ encoded = encoded.slice(discoCodec.codecBuffer.length)
2933
+ this.name = discoCodec.name
2934
+ this.decoded = this.protoDecode(encoded)
2935
+ return this.decoded
2893
2936
  }
2894
2937
 
2895
2938
  /**
2896
- *
2897
- * @param {String} topic
2898
- * @param {String|Object|Array|Boolean|Buffer} data
2939
+ * @return {Buffer}
2899
2940
  */
2900
- async publish(topic, data) {
2901
- // globalSub.publish(topic, data)
2902
- if (topic instanceof Uint8Array === false) topic = new TextEncoder().encode(topic);
2903
- if (data instanceof Uint8Array === false) data = new TextEncoder().encode(JSON.stringify(data));
2904
- const id = Math.random().toString(36).slice(-12);
2905
- data = new PsMessage({data, topic});
2906
- for (const peer of this.connections) {
2907
- if (peer.peerId !== this.peerId) {
2908
- const node = await this.prepareMessage(peer.peerId, data.encoded);
2909
- this.sendMessage(peer, id, node.encoded);
2910
- }
2911
- // TODO: if peer subscribed
2912
- }
2913
- }
2914
-
2915
- createHash(data, name) {
2916
- return new PeernetHash(data, {name})
2941
+ encode(decoded) {
2942
+ if (!decoded) decoded = this.decoded;
2943
+ const codec = new PeernetCodec(this.name)
2944
+ const encoded = this.protoEncode(decoded)
2945
+ const uint8Array = new Uint8Array(encoded.length + codec.codecBuffer.length)
2946
+ uint8Array.set(codec.codecBuffer)
2947
+ uint8Array.set(encoded, codec.codecBuffer.length)
2948
+ this.encoded = uint8Array
2949
+ return this.encoded
2917
2950
  }
2918
2951
 
2919
- /**
2920
- *
2921
- * @param {String} topic
2922
- * @param {Method} cb
2923
- */
2924
- async subscribe(topic, cb) {
2925
- // TODO: if peer subscribed
2926
- globalSub.subscribe(topic, cb);
2952
+ hasCodec() {
2953
+ if (!this.encoded) return false
2954
+ const codec = new PeernetCodec(this.encoded)
2955
+ if (codec.name) return true
2927
2956
  }
2928
2957
 
2929
- async removePeer(peer) {
2930
- return this.client.removePeer(peer)
2958
+ fromUint8Array(buffer) {
2959
+ this.encoded = buffer
2960
+ if (!this.hasCodec()) this.create(
2961
+ JSON.parse(new TextDecoder().decode(this.encoded))
2962
+ )
2963
+ else this.decode()
2931
2964
  }
2932
2965
 
2933
- get Buffer() {
2934
- return Buffer
2966
+ fromArrayBuffer(buffer) {
2967
+ this.encoded = new Uint8Array(buffer, buffer.byteOffset, buffer.byteLength)
2968
+ if (!this.hasCodec()) this.create(
2969
+ JSON.parse(new TextDecoder().decode(this.encoded))
2970
+ )
2971
+ else this.decode()
2935
2972
  }
2936
- // async block(index) {
2937
- // const _values = []
2938
- // for (const peer of this.peers) {
2939
- // const value = await peer.request({type: 'block', index})
2940
- // console.log(value);
2941
- // }
2942
- //
2943
- // }
2944
- }
2973
+ }
2945
2974
 
2946
- module.exports = Peernet;
2975
+ ;// CONCATENATED MODULE: ./node_modules/@leofcoin/codec-format-interface/src/index.js
2976
+
2977
+
2978
+
2979
+
2980
+
2981
+
2982
+ /* harmony default export */ var src = ({ codecs: codecs, Codec: PeernetCodec, CodecHash: CodecHash, FormatInterface: FormatInterface, BasicInterface: BasicInterface });
2947
2983
 
2948
2984
 
2949
2985
  /***/ }),
@@ -3185,7 +3221,6 @@ const base = ALPHABET => {
3185
3221
  /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
3186
3222
 
3187
3223
  "use strict";
3188
- __webpack_require__.r(__webpack_exports__);
3189
3224
  /* harmony import */ var _vandeurenglenn_base_x__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2353);
3190
3225
 
3191
3226
 
@@ -3197,7 +3232,7 @@ const decode = (uint8Array, hex = false) => {
3197
3232
  return decoder.decode(uint8Array)
3198
3233
  }
3199
3234
 
3200
- /* harmony default export */ __webpack_exports__["default"] = ({
3235
+ /* harmony default export */ __webpack_exports__["Z"] = ({
3201
3236
  encode: (uint8Array, hex = false) => {
3202
3237
  const encoder = hex ? (0,_vandeurenglenn_base_x__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(base32Hex) : (0,_vandeurenglenn_base_x__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(base32)
3203
3238
  return encoder.encode(uint8Array)
@@ -3220,7 +3255,6 @@ const decode = (uint8Array, hex = false) => {
3220
3255
  /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
3221
3256
 
3222
3257
  "use strict";
3223
- __webpack_require__.r(__webpack_exports__);
3224
3258
  /* harmony import */ var _vandeurenglenn_base_x__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2353);
3225
3259
 
3226
3260
 
@@ -3228,7 +3262,7 @@ const base58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
3228
3262
 
3229
3263
  const decode = uint8Array => (0,_vandeurenglenn_base_x__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(base58).decode(uint8Array)
3230
3264
 
3231
- /* harmony default export */ __webpack_exports__["default"] = ({
3265
+ /* harmony default export */ __webpack_exports__["Z"] = ({
3232
3266
  encode: uint8Array => (0,_vandeurenglenn_base_x__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(base58).encode(uint8Array),
3233
3267
  decode,
3234
3268
  isBase58: uint8Array => {
@@ -3256,16 +3290,6 @@ globalThis.debug = text => {
3256
3290
  }
3257
3291
 
3258
3292
 
3259
- /***/ }),
3260
-
3261
- /***/ 6187:
3262
- /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
3263
-
3264
- "use strict";
3265
- __webpack_require__.r(__webpack_exports__);
3266
- /* harmony default export */ __webpack_exports__["default"] = (string => /^[A-F0-9]+$/i.test(string));
3267
-
3268
-
3269
3293
  /***/ }),
3270
3294
 
3271
3295
  /***/ 8162:
@@ -16966,11 +16990,11 @@ class MultiSignature {
16966
16990
  }
16967
16991
 
16968
16992
  export() {
16969
- return _vandeurenglenn_base58__WEBPACK_IMPORTED_MODULE_0__["default"].encode(this.multiSignature);
16993
+ return _vandeurenglenn_base58__WEBPACK_IMPORTED_MODULE_0__/* ["default"].encode */ .Z.encode(this.multiSignature);
16970
16994
  }
16971
16995
 
16972
16996
  import(encoded) {
16973
- return _vandeurenglenn_base58__WEBPACK_IMPORTED_MODULE_0__["default"].decode(this.decode(encoded));
16997
+ return _vandeurenglenn_base58__WEBPACK_IMPORTED_MODULE_0__/* ["default"].decode */ .Z.decode(this.decode(encoded));
16974
16998
  }
16975
16999
 
16976
17000
  sign(hash, privateKey) {
@@ -17047,23 +17071,23 @@ class MultiSignature {
17047
17071
  }
17048
17072
 
17049
17073
  fromHex(hex) {
17050
- return _vandeurenglenn_base58__WEBPACK_IMPORTED_MODULE_0__["default"].decode(Buffer.from(hex, 'hex'))
17074
+ return _vandeurenglenn_base58__WEBPACK_IMPORTED_MODULE_0__/* ["default"].decode */ .Z.decode(Buffer.from(hex, 'hex'))
17051
17075
  }
17052
17076
 
17053
17077
  toBs58() {
17054
- return _vandeurenglenn_base58__WEBPACK_IMPORTED_MODULE_0__["default"].encode(this.multiSignature)
17078
+ return _vandeurenglenn_base58__WEBPACK_IMPORTED_MODULE_0__/* ["default"].encode */ .Z.encode(this.multiSignature)
17055
17079
  }
17056
17080
 
17057
17081
  fromBs58(multiSignature) {
17058
- return _vandeurenglenn_base58__WEBPACK_IMPORTED_MODULE_0__["default"].decode(multiSignature)
17082
+ return _vandeurenglenn_base58__WEBPACK_IMPORTED_MODULE_0__/* ["default"].decode */ .Z.decode(multiSignature)
17059
17083
  }
17060
17084
 
17061
17085
  toBs32() {
17062
- return _vandeurenglenn_base32__WEBPACK_IMPORTED_MODULE_1__["default"].encode(this.multiSignature)
17086
+ return _vandeurenglenn_base32__WEBPACK_IMPORTED_MODULE_1__/* ["default"].encode */ .Z.encode(this.multiSignature)
17063
17087
  }
17064
17088
 
17065
17089
  fromBs32(multiSignature) {
17066
- return _vandeurenglenn_base32__WEBPACK_IMPORTED_MODULE_1__["default"].decode(multiSignature)
17090
+ return _vandeurenglenn_base32__WEBPACK_IMPORTED_MODULE_1__/* ["default"].decode */ .Z.decode(multiSignature)
17067
17091
  }
17068
17092
  }
17069
17093