@leofcoin/peernet 1.1.56 → 1.1.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.esdoc.json +10 -10
- package/.eslintrc.json +24 -24
- package/.gitattributes +2 -2
- package/.travis.yml +27 -27
- package/BREAKING_CHANGES.md +34 -34
- package/LICENSE +21 -21
- package/README.md +72 -72
- package/deploy.js +8 -8
- package/exports/browser/browser-store.js +4 -3
- package/exports/browser/identity.d.ts +18 -0
- package/exports/browser/{index-9c85cd32.js → index-8868bdd8.js} +1 -1
- package/exports/browser/messages/chat.d.ts +1 -1
- package/exports/browser/messages/data-response.d.ts +1 -1
- package/exports/browser/messages/dht-response.d.ts +1 -1
- package/exports/browser/messages/dht.d.ts +1 -1
- package/exports/browser/messages/peer-response.d.ts +1 -1
- package/exports/browser/messages/peer.d.ts +1 -1
- package/exports/browser/messages/peernet.d.ts +1 -1
- package/exports/browser/messages/ps.d.ts +1 -1
- package/exports/browser/messages/request.d.ts +1 -1
- package/exports/browser/messages/response.d.ts +1 -1
- package/exports/browser/{messages-b66f5393.js → messages-eb6e5c71.js} +174 -174
- package/exports/browser/{peernet-2797014a.js → peernet-87ea02a4.js} +1402 -1334
- package/exports/browser/peernet.d.ts +43 -23
- package/exports/browser/peernet.js +1 -1
- package/exports/{messages-dc960cb3.js → messages-b9a32987.js} +173 -173
- package/exports/peernet.js +305 -251
- package/exports/src/prompts/password.js +3 -3
- package/exports/store.js +15 -14
- package/exports/types/identity.d.ts +18 -0
- package/exports/types/messages/chat.d.ts +1 -1
- package/exports/types/messages/data-response.d.ts +1 -1
- package/exports/types/messages/dht-response.d.ts +1 -1
- package/exports/types/messages/dht.d.ts +1 -1
- package/exports/types/messages/peer-response.d.ts +1 -1
- package/exports/types/messages/peer.d.ts +1 -1
- package/exports/types/messages/peernet.d.ts +1 -1
- package/exports/types/messages/ps.d.ts +1 -1
- package/exports/types/messages/request.d.ts +1 -1
- package/exports/types/messages/response.d.ts +1 -1
- package/exports/types/peernet.d.ts +43 -23
- package/index.html +19 -19
- package/package.json +70 -69
- package/rollup.config.js +76 -69
- package/src/dht/dht.ts +141 -141
- package/src/discovery/peer-discovery.js +75 -75
- package/src/errors/errors.js +12 -12
- package/src/handlers/data.js +11 -11
- package/src/handlers/message.js +34 -34
- package/src/identity.ts +101 -94
- package/src/messages/chat.js +14 -14
- package/src/messages/data-response.js +14 -14
- package/src/messages/data.js +18 -18
- package/src/messages/dht-response.js +14 -14
- package/src/messages/dht.js +22 -22
- package/src/messages/file-link.js +18 -18
- package/src/messages/file.js +18 -18
- package/src/messages/peer-response.js +14 -14
- package/src/messages/peer.js +13 -13
- package/src/messages/peernet.js +14 -14
- package/src/messages/ps.js +13 -13
- package/src/messages/request.js +14 -14
- package/src/messages/response.js +14 -14
- package/src/messages.js +13 -13
- package/src/peer-info.js +9 -9
- package/src/peernet.ts +848 -753
- package/src/prompts/password/node.js +5 -5
- package/src/proto/chat-message.proto.js +6 -6
- package/src/proto/data-response.proto.js +4 -4
- package/src/proto/data.proto.js +4 -4
- package/src/proto/dht-response.proto.js +4 -4
- package/src/proto/dht.proto.js +4 -4
- package/src/proto/file-link.proto.js +5 -5
- package/src/proto/file.proto.js +5 -5
- package/src/proto/peer-response.proto.js +3 -3
- package/src/proto/peer.proto.js +3 -3
- package/src/proto/peernet.proto.js +7 -7
- package/src/proto/ps.proto.js +4 -4
- package/src/proto/request.proto.js +4 -4
- package/src/proto/response.proto.js +3 -3
- package/src/types.ts +27 -27
- package/src/utils/utils.js +78 -78
- package/test/client.js +14 -14
- package/test/codec.js +56 -56
- package/test/hash.js +13 -13
- package/test/index.js +3 -3
- package/test/lastBlock.js +7 -7
- package/test/messages.js +26 -26
- package/test/peernet.js +17 -17
- package/test.js +64 -64
- package/test2.js +9 -9
- package/test3.js +15 -15
- package/test4.js +7 -7
- package/tsconfig.json +12 -12
package/exports/peernet.js
CHANGED
|
@@ -9,140 +9,140 @@ import { decrypt } from '@leofcoin/identity-utils';
|
|
|
9
9
|
import QrScanner from 'qr-scanner';
|
|
10
10
|
import qrcode from 'qrcode';
|
|
11
11
|
|
|
12
|
-
const BufferToUint8Array = data => {
|
|
13
|
-
if (data.type === 'Buffer') {
|
|
14
|
-
data = new Uint8Array(data.data);
|
|
15
|
-
}
|
|
16
|
-
return data
|
|
12
|
+
const BufferToUint8Array = data => {
|
|
13
|
+
if (data.type === 'Buffer') {
|
|
14
|
+
data = new Uint8Array(data.data);
|
|
15
|
+
}
|
|
16
|
+
return data
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const protoFor = (message) => {
|
|
20
|
+
const codec = new Codec(message);
|
|
21
|
+
if (!codec.name) throw new Error('proto not found')
|
|
22
|
+
const Proto = globalThis.peernet.protos[codec.name];
|
|
23
|
+
if (!Proto) throw (new Error(`No proto defined for ${codec.name}`))
|
|
24
|
+
return new Proto(message)
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* wether or not a peernet daemon is active
|
|
29
|
+
* @return {Boolean}
|
|
30
|
+
*/
|
|
31
|
+
const hasDaemon = async () => {
|
|
32
|
+
try {
|
|
33
|
+
let response = await fetch('http://127.0.0.1:1000/api/version');
|
|
34
|
+
response = await response.json();
|
|
35
|
+
return Boolean(response.client === '@peernet/api/http')
|
|
36
|
+
} catch (e) {
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const https = () => {
|
|
42
|
+
if (!globalThis.location) return false;
|
|
43
|
+
return Boolean(globalThis.location.protocol === 'https:')
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get current environment
|
|
48
|
+
* @return {String} current environment [node, electron, browser]
|
|
49
|
+
*/
|
|
50
|
+
const environment = () => {
|
|
51
|
+
const _navigator = globalThis.navigator;
|
|
52
|
+
if (!_navigator) {
|
|
53
|
+
return 'node'
|
|
54
|
+
} else if (_navigator && /electron/i.test(_navigator.userAgent)) {
|
|
55
|
+
return 'electron'
|
|
56
|
+
} else {
|
|
57
|
+
return 'browser'
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* * Get current environment
|
|
63
|
+
* @return {Object} result
|
|
64
|
+
* @property {Boolean} reult.daemon whether or not daemon is running
|
|
65
|
+
* @property {Boolean} reult.environment Current environment
|
|
66
|
+
*/
|
|
67
|
+
const target = async () => {
|
|
68
|
+
let daemon = false;
|
|
69
|
+
if (!https()) daemon = await hasDaemon();
|
|
70
|
+
|
|
71
|
+
return {daemon, environment: environment()}
|
|
17
72
|
};
|
|
18
73
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (id) return id
|
|
92
|
-
const data = await new peernet.protos['peernet-peer']({id: this.id});
|
|
93
|
-
const node = await peernet.prepareMessage(peer.id, data.encoded);
|
|
94
|
-
|
|
95
|
-
let response = await peer.request(node.encoded);
|
|
96
|
-
response = await protoFor(response);
|
|
97
|
-
response = await new peernet.protos['peernet-peer-response'](response.decoded.data);
|
|
98
|
-
|
|
99
|
-
id = response.decoded.id;
|
|
100
|
-
if (id === this.id) return;
|
|
101
|
-
|
|
102
|
-
if (!peernet.peerMap.has(id)) peernet.peerMap.set(id, [peer.id]);
|
|
103
|
-
else {
|
|
104
|
-
const connections = peernet.peerMap.get(id);
|
|
105
|
-
if (connections.indexOf(peer.id) === -1) {
|
|
106
|
-
connections.push(peer.id);
|
|
107
|
-
peernet.peerMap.set(peer.id, connections);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return id
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async discoverHandler(message, peer) {
|
|
114
|
-
const {id, proto} = message;
|
|
115
|
-
// if (typeof message.data === 'string') message.data = Buffer.from(message.data)
|
|
116
|
-
if (proto.name === 'peernet-peer') {
|
|
117
|
-
const from = proto.decoded.id;
|
|
118
|
-
if (from === this.id) return;
|
|
119
|
-
|
|
120
|
-
if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
|
|
121
|
-
else {
|
|
122
|
-
const connections = peernet.peerMap.get(from);
|
|
123
|
-
if (connections.indexOf(peer.id) === -1) {
|
|
124
|
-
connections.push(peer.id);
|
|
125
|
-
peernet.peerMap.set(from, connections);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
const data = await new peernet.protos['peernet-peer-response']({id: this.id});
|
|
129
|
-
const node = await peernet.prepareMessage(from, data.encoded);
|
|
130
|
-
|
|
131
|
-
peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
|
|
132
|
-
} else if (proto.name === 'peernet-peer-response') {
|
|
133
|
-
const from = proto.decoded.id;
|
|
134
|
-
if (from === this.id) return;
|
|
135
|
-
|
|
136
|
-
if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
|
|
137
|
-
else {
|
|
138
|
-
const connections = peernet.peerMap.get(from);
|
|
139
|
-
if (connections.indexOf(peer.id) === -1) {
|
|
140
|
-
connections.push(peer.id);
|
|
141
|
-
peernet.peerMap.set(from, connections);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
74
|
+
class PeerDiscovery {
|
|
75
|
+
constructor(id) {
|
|
76
|
+
this.id = id;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
_getPeerId(id) {
|
|
80
|
+
if (!peernet.peerMap || peernet.peerMap && peernet.peerMap.size === 0) return false
|
|
81
|
+
|
|
82
|
+
for (const entry of [...peernet.peerMap.entries()]) {
|
|
83
|
+
for (const _id of entry[1]) {
|
|
84
|
+
if (_id === id) return entry[0]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async discover(peer) {
|
|
90
|
+
let id = this._getPeerId(peer.id);
|
|
91
|
+
if (id) return id
|
|
92
|
+
const data = await new peernet.protos['peernet-peer']({id: this.id});
|
|
93
|
+
const node = await peernet.prepareMessage(peer.id, data.encoded);
|
|
94
|
+
|
|
95
|
+
let response = await peer.request(node.encoded);
|
|
96
|
+
response = await protoFor(response);
|
|
97
|
+
response = await new peernet.protos['peernet-peer-response'](response.decoded.data);
|
|
98
|
+
|
|
99
|
+
id = response.decoded.id;
|
|
100
|
+
if (id === this.id) return;
|
|
101
|
+
|
|
102
|
+
if (!peernet.peerMap.has(id)) peernet.peerMap.set(id, [peer.id]);
|
|
103
|
+
else {
|
|
104
|
+
const connections = peernet.peerMap.get(id);
|
|
105
|
+
if (connections.indexOf(peer.id) === -1) {
|
|
106
|
+
connections.push(peer.id);
|
|
107
|
+
peernet.peerMap.set(peer.id, connections);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return id
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async discoverHandler(message, peer) {
|
|
114
|
+
const {id, proto} = message;
|
|
115
|
+
// if (typeof message.data === 'string') message.data = Buffer.from(message.data)
|
|
116
|
+
if (proto.name === 'peernet-peer') {
|
|
117
|
+
const from = proto.decoded.id;
|
|
118
|
+
if (from === this.id) return;
|
|
119
|
+
|
|
120
|
+
if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
|
|
121
|
+
else {
|
|
122
|
+
const connections = peernet.peerMap.get(from);
|
|
123
|
+
if (connections.indexOf(peer.id) === -1) {
|
|
124
|
+
connections.push(peer.id);
|
|
125
|
+
peernet.peerMap.set(from, connections);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const data = await new peernet.protos['peernet-peer-response']({id: this.id});
|
|
129
|
+
const node = await peernet.prepareMessage(from, data.encoded);
|
|
130
|
+
|
|
131
|
+
peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
|
|
132
|
+
} else if (proto.name === 'peernet-peer-response') {
|
|
133
|
+
const from = proto.decoded.id;
|
|
134
|
+
if (from === this.id) return;
|
|
135
|
+
|
|
136
|
+
if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
|
|
137
|
+
else {
|
|
138
|
+
const connections = peernet.peerMap.get(from);
|
|
139
|
+
if (connections.indexOf(peer.id) === -1) {
|
|
140
|
+
connections.push(peer.id);
|
|
141
|
+
peernet.peerMap.set(from, connections);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
/**
|
|
@@ -252,62 +252,63 @@ class DhtEarth {
|
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
class MessageHandler {
|
|
256
|
-
constructor(network) {
|
|
257
|
-
this.network = network;
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* hash and sign message
|
|
261
|
-
*
|
|
262
|
-
* @param {object} message
|
|
263
|
-
* @param {Buffer} message.from peer id
|
|
264
|
-
* @param {Buffer} message.to peer id
|
|
265
|
-
* @param {string} message.data Peernet message
|
|
266
|
-
* (PeernetMessage excluded) encoded as a string
|
|
267
|
-
* @return message
|
|
268
|
-
*/
|
|
269
|
-
async hashAndSignMessage(message) {
|
|
270
|
-
const hash = await message.peernetHash;
|
|
271
|
-
message.decoded.signature = globalThis.identity.sign(hash.buffer);
|
|
272
|
-
return message
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* @param {String} from - peer id
|
|
277
|
-
* @param {String} to - peer id
|
|
278
|
-
* @param {String|PeernetMessage} data - data encoded message string
|
|
279
|
-
* or the messageNode itself
|
|
280
|
-
*/
|
|
281
|
-
async prepareMessage(message) {
|
|
282
|
-
if (message.keys.includes('signature')) {
|
|
283
|
-
message = await this.hashAndSignMessage(message);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
return message
|
|
287
|
-
}
|
|
255
|
+
class MessageHandler {
|
|
256
|
+
constructor(network) {
|
|
257
|
+
this.network = network;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* hash and sign message
|
|
261
|
+
*
|
|
262
|
+
* @param {object} message
|
|
263
|
+
* @param {Buffer} message.from peer id
|
|
264
|
+
* @param {Buffer} message.to peer id
|
|
265
|
+
* @param {string} message.data Peernet message
|
|
266
|
+
* (PeernetMessage excluded) encoded as a string
|
|
267
|
+
* @return message
|
|
268
|
+
*/
|
|
269
|
+
async hashAndSignMessage(message) {
|
|
270
|
+
const hash = await message.peernetHash;
|
|
271
|
+
message.decoded.signature = globalThis.identity.sign(hash.buffer);
|
|
272
|
+
return message
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* @param {String} from - peer id
|
|
277
|
+
* @param {String} to - peer id
|
|
278
|
+
* @param {String|PeernetMessage} data - data encoded message string
|
|
279
|
+
* or the messageNode itself
|
|
280
|
+
*/
|
|
281
|
+
async prepareMessage(message) {
|
|
282
|
+
if (message.keys.includes('signature')) {
|
|
283
|
+
message = await this.hashAndSignMessage(message);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return message
|
|
287
|
+
}
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
-
const dataHandler = async message => {
|
|
291
|
-
if (!message) return
|
|
292
|
-
|
|
293
|
-
const {data, id, from, peer} = message;
|
|
294
|
-
const proto = await protoFor(data);
|
|
295
|
-
peernet._protoHandler({id, proto}, peernet.connections[from] || peer, from);
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
const dhtError = (proto) => {
|
|
299
|
-
const text = `Received proto ${proto.name} expected peernet-dht-response`;
|
|
300
|
-
return new Error(`Routing error: ${text}`)
|
|
290
|
+
const dataHandler = async message => {
|
|
291
|
+
if (!message) return
|
|
292
|
+
|
|
293
|
+
const {data, id, from, peer} = message;
|
|
294
|
+
const proto = await protoFor(data);
|
|
295
|
+
peernet._protoHandler({id, proto}, peernet.connections[from] || peer, from);
|
|
301
296
|
};
|
|
302
297
|
|
|
303
|
-
const
|
|
304
|
-
|
|
298
|
+
const dhtError = (proto) => {
|
|
299
|
+
const text = `Received proto ${proto.name} expected peernet-dht-response`;
|
|
300
|
+
return new Error(`Routing error: ${text}`)
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const nothingFoundError = (hash) => {
|
|
304
|
+
return new Error(`nothing found for ${hash}`)
|
|
305
305
|
};
|
|
306
306
|
|
|
307
307
|
class Identity {
|
|
308
308
|
#wallet;
|
|
309
309
|
network;
|
|
310
310
|
id;
|
|
311
|
+
selectedAccount;
|
|
311
312
|
constructor(network) {
|
|
312
313
|
this.network = network;
|
|
313
314
|
}
|
|
@@ -330,6 +331,7 @@ class Identity {
|
|
|
330
331
|
}
|
|
331
332
|
}
|
|
332
333
|
if (!password) {
|
|
334
|
+
// @ts-ignore
|
|
333
335
|
const importee = await import('./src/prompts/password.js');
|
|
334
336
|
password = await importee.default();
|
|
335
337
|
}
|
|
@@ -338,7 +340,7 @@ class Identity {
|
|
|
338
340
|
const pub = await globalThis.accountStore.get('public');
|
|
339
341
|
this.id = JSON.parse(new TextDecoder().decode(pub)).walletId;
|
|
340
342
|
const selected = await globalThis.walletStore.get('selected-account');
|
|
341
|
-
|
|
343
|
+
this.selectedAccount = new TextDecoder().decode(selected);
|
|
342
344
|
}
|
|
343
345
|
else {
|
|
344
346
|
const importee = await import(/* webpackChunkName: "generate-account" */ '@leofcoin/generate-account');
|
|
@@ -348,7 +350,7 @@ class Identity {
|
|
|
348
350
|
await globalThis.walletStore.put('accounts', JSON.stringify(accounts));
|
|
349
351
|
await globalThis.walletStore.put('selected-account', accounts[0][1]);
|
|
350
352
|
await globalThis.walletStore.put('identity', JSON.stringify(identity));
|
|
351
|
-
|
|
353
|
+
this.selectedAccount = accounts[0][1];
|
|
352
354
|
this.id = identity.walletId;
|
|
353
355
|
}
|
|
354
356
|
const identity = JSON.parse(new TextDecoder().decode(await globalThis.walletStore.get('identity')));
|
|
@@ -356,6 +358,10 @@ class Identity {
|
|
|
356
358
|
const multiWIF = await decrypt(password, base58.decode(identity.multiWIF));
|
|
357
359
|
await this.#wallet.fromMultiWif(multiWIF);
|
|
358
360
|
}
|
|
361
|
+
selectAccount(account) {
|
|
362
|
+
this.selectedAccount = account;
|
|
363
|
+
return walletStore.put('selected-account', account);
|
|
364
|
+
}
|
|
359
365
|
sign(hash) {
|
|
360
366
|
return this.#wallet.sign(hash.subarray(0, 32));
|
|
361
367
|
}
|
|
@@ -376,7 +382,7 @@ class Identity {
|
|
|
376
382
|
return globalThis.navigator ? await qrcode.toDataURL(exported) : await qrcode.toString(exported, { type: 'terminal' });
|
|
377
383
|
}
|
|
378
384
|
async importQR(image, password) {
|
|
379
|
-
const multiWIF = QrScanner.scanImage(image);
|
|
385
|
+
const multiWIF = await QrScanner.default.scanImage(image);
|
|
380
386
|
return this.import(password, multiWIF);
|
|
381
387
|
}
|
|
382
388
|
}
|
|
@@ -433,17 +439,20 @@ class Peernet {
|
|
|
433
439
|
/**
|
|
434
440
|
* @property {String} network - current network
|
|
435
441
|
*/
|
|
436
|
-
this.network = options.network ||
|
|
442
|
+
this.network = options.network || "leofcoin";
|
|
437
443
|
this.autoStart = options.autoStart === undefined ? true : options.autoStart;
|
|
438
444
|
this.stars = options.stars;
|
|
439
|
-
const parts = this.network.split(
|
|
440
|
-
this.networkVersion =
|
|
445
|
+
const parts = this.network.split(":");
|
|
446
|
+
this.networkVersion =
|
|
447
|
+
options.networkVersion || parts.length > 1 ? parts[1] : "mainnet";
|
|
441
448
|
if (!options.storePrefix)
|
|
442
|
-
options.storePrefix =
|
|
449
|
+
options.storePrefix = "lfc";
|
|
443
450
|
if (!options.port)
|
|
444
451
|
options.port = 2000;
|
|
445
452
|
if (!options.root) {
|
|
446
|
-
parts[1]
|
|
453
|
+
parts[1]
|
|
454
|
+
? (options.root = `.${parts[0]}/${parts[1]}`)
|
|
455
|
+
: (options.root = `.${this.network}`);
|
|
447
456
|
}
|
|
448
457
|
globalThis.peernet = this;
|
|
449
458
|
this.bw = {
|
|
@@ -456,11 +465,25 @@ class Peernet {
|
|
|
456
465
|
get id() {
|
|
457
466
|
return this.identity.id;
|
|
458
467
|
}
|
|
468
|
+
get selectedAccount() {
|
|
469
|
+
return this.identity.selectedAccount;
|
|
470
|
+
}
|
|
459
471
|
get accounts() {
|
|
460
472
|
return this.identity.accounts;
|
|
461
473
|
}
|
|
462
474
|
get defaultStores() {
|
|
463
|
-
return [
|
|
475
|
+
return [
|
|
476
|
+
"account",
|
|
477
|
+
"wallet",
|
|
478
|
+
"block",
|
|
479
|
+
"transaction",
|
|
480
|
+
"chain",
|
|
481
|
+
"data",
|
|
482
|
+
"message",
|
|
483
|
+
];
|
|
484
|
+
}
|
|
485
|
+
selectAccount(account) {
|
|
486
|
+
return this.identity.selectAccount(account);
|
|
464
487
|
}
|
|
465
488
|
addProto(name, proto) {
|
|
466
489
|
if (!globalThis.peernet.protos[name])
|
|
@@ -470,11 +493,16 @@ class Peernet {
|
|
|
470
493
|
return utils.addCodec(codec);
|
|
471
494
|
}
|
|
472
495
|
async addStore(name, prefix, root, isPrivate = true) {
|
|
473
|
-
if (name ===
|
|
474
|
-
name ===
|
|
496
|
+
if (name === "block" ||
|
|
497
|
+
name === "transaction" ||
|
|
498
|
+
name === "chain" ||
|
|
499
|
+
name === "data" ||
|
|
500
|
+
name === "message")
|
|
475
501
|
isPrivate = false;
|
|
476
502
|
let Storage;
|
|
477
|
-
this.hasDaemon
|
|
503
|
+
this.hasDaemon
|
|
504
|
+
? (Storage = LeofcoinStorageClient)
|
|
505
|
+
: (Storage = LeofcoinStorage);
|
|
478
506
|
if (!globalThis[`${name}Store`]) {
|
|
479
507
|
globalThis[`${name}Store`] = new Storage(name, root);
|
|
480
508
|
await globalThis[`${name}Store`].init();
|
|
@@ -507,7 +535,7 @@ class Peernet {
|
|
|
507
535
|
* @return {String} id - peerId
|
|
508
536
|
*/
|
|
509
537
|
getConnection(id) {
|
|
510
|
-
return this.
|
|
538
|
+
return this.connections[id];
|
|
511
539
|
}
|
|
512
540
|
/**
|
|
513
541
|
* @private
|
|
@@ -520,9 +548,9 @@ class Peernet {
|
|
|
520
548
|
async _init(options, password) {
|
|
521
549
|
this.storePrefix = options.storePrefix;
|
|
522
550
|
this.root = options.root;
|
|
523
|
-
const { RequestMessage, ResponseMessage, PeerMessage, PeerMessageResponse, PeernetMessage, DHTMessage, DHTMessageResponse, DataMessage, DataMessageResponse, PsMessage, ChatMessage, PeernetFile
|
|
551
|
+
const { RequestMessage, ResponseMessage, PeerMessage, PeerMessageResponse, PeernetMessage, DHTMessage, DHTMessageResponse, DataMessage, DataMessageResponse, PsMessage, ChatMessage, PeernetFile,
|
|
524
552
|
// FolderMessageResponse
|
|
525
|
-
} = await import(/* webpackChunkName: "messages" */ './messages-
|
|
553
|
+
} = await import(/* webpackChunkName: "messages" */ './messages-b9a32987.js');
|
|
526
554
|
/**
|
|
527
555
|
* proto Object containing protos
|
|
528
556
|
* @type {Object}
|
|
@@ -533,18 +561,18 @@ class Peernet {
|
|
|
533
561
|
* @property {DataMessageResponse} protos[peernet-data-response] messageNode
|
|
534
562
|
*/
|
|
535
563
|
globalThis.peernet.protos = {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
564
|
+
"peernet-request": RequestMessage,
|
|
565
|
+
"peernet-response": ResponseMessage,
|
|
566
|
+
"peernet-peer": PeerMessage,
|
|
567
|
+
"peernet-peer-response": PeerMessageResponse,
|
|
568
|
+
"peernet-message": PeernetMessage,
|
|
569
|
+
"peernet-dht": DHTMessage,
|
|
570
|
+
"peernet-dht-response": DHTMessageResponse,
|
|
571
|
+
"peernet-data": DataMessage,
|
|
572
|
+
"peernet-data-response": DataMessageResponse,
|
|
573
|
+
"peernet-ps": PsMessage,
|
|
574
|
+
"chat-message": ChatMessage,
|
|
575
|
+
"peernet-file": PeernetFile,
|
|
548
576
|
};
|
|
549
577
|
this._messageHandler = new MessageHandler(this.network);
|
|
550
578
|
const { daemon, environment } = await target();
|
|
@@ -556,38 +584,44 @@ class Peernet {
|
|
|
556
584
|
await this.identity.load(password);
|
|
557
585
|
this._peerHandler = new PeerDiscovery(this.id);
|
|
558
586
|
this.peerId = this.id;
|
|
559
|
-
this.addRequestHandler(
|
|
560
|
-
return new peernet.protos[
|
|
587
|
+
this.addRequestHandler("handshake", () => {
|
|
588
|
+
return new peernet.protos["peernet-response"]({
|
|
589
|
+
response: { peerId: this.id },
|
|
590
|
+
});
|
|
561
591
|
});
|
|
562
|
-
pubsub.subscribe(
|
|
592
|
+
pubsub.subscribe("peer:discovered", async (peer) => {
|
|
563
593
|
// console.log(peer);
|
|
564
|
-
if (this.requestProtos[
|
|
565
|
-
let data = await new globalThis.peernet.protos[
|
|
594
|
+
if (this.requestProtos["version"]) {
|
|
595
|
+
let data = await new globalThis.peernet.protos["peernet-request"]({
|
|
596
|
+
request: "version",
|
|
597
|
+
});
|
|
566
598
|
let node = await globalThis.peernet.prepareMessage(data);
|
|
567
599
|
let response = await peer.request(node.encoded);
|
|
568
|
-
response = await new globalThis.peernet.protos[
|
|
600
|
+
response = await new globalThis.peernet.protos["peernet-response"](new Uint8Array(Object.values(response)));
|
|
569
601
|
peer.version = response.decoded.response.version;
|
|
570
602
|
}
|
|
571
|
-
let data = await new globalThis.peernet.protos[
|
|
603
|
+
let data = await new globalThis.peernet.protos["peernet-request"]({
|
|
604
|
+
request: "handshake",
|
|
605
|
+
});
|
|
572
606
|
let node = await globalThis.peernet.prepareMessage(data);
|
|
573
607
|
let response = await peer.request(node.encoded);
|
|
574
|
-
response = await new globalThis.peernet.protos[
|
|
608
|
+
response = await new globalThis.peernet.protos["peernet-response"](new Uint8Array(Object.values(response)));
|
|
575
609
|
// todo: response.decoded should be the response and not response.peerId
|
|
576
610
|
this.#connections[response.decoded.response.peerId] = peer;
|
|
577
|
-
pubsub.publish(
|
|
611
|
+
pubsub.publish("peer:connected", peer);
|
|
578
612
|
// todo: cleanup discovered
|
|
579
613
|
});
|
|
580
|
-
pubsub.subscribe(
|
|
614
|
+
pubsub.subscribe("peer:left", this.#peerLeft.bind(this));
|
|
581
615
|
/**
|
|
582
616
|
* converts data -> message -> proto
|
|
583
617
|
* @see DataHandler
|
|
584
618
|
*/
|
|
585
|
-
pubsub.subscribe(
|
|
619
|
+
pubsub.subscribe("peer:data", dataHandler);
|
|
586
620
|
if (globalThis.navigator) {
|
|
587
|
-
globalThis.addEventListener(
|
|
621
|
+
globalThis.addEventListener("beforeunload", async () => this.client.destroy());
|
|
588
622
|
}
|
|
589
623
|
else {
|
|
590
|
-
process.on(
|
|
624
|
+
process.on("SIGTERM", async () => {
|
|
591
625
|
process.stdin.resume();
|
|
592
626
|
try {
|
|
593
627
|
await this.client.destroy();
|
|
@@ -618,7 +652,9 @@ class Peernet {
|
|
|
618
652
|
}
|
|
619
653
|
#peerLeft(peer) {
|
|
620
654
|
for (const [id, _peer] of Object.entries(this.#connections)) {
|
|
621
|
-
if (_peer.id === peer.id &&
|
|
655
|
+
if (_peer.id === peer.id &&
|
|
656
|
+
this.#connections[id] &&
|
|
657
|
+
!this.#connections[id].connected) {
|
|
622
658
|
delete this.#connections[id];
|
|
623
659
|
this.removePeer(_peer);
|
|
624
660
|
}
|
|
@@ -645,18 +681,26 @@ class Peernet {
|
|
|
645
681
|
else {
|
|
646
682
|
has = await this.has(hash);
|
|
647
683
|
}
|
|
648
|
-
const data = await new globalThis.peernet.protos[
|
|
684
|
+
const data = await new globalThis.peernet.protos["peernet-dht-response"]({
|
|
685
|
+
hash,
|
|
686
|
+
has,
|
|
687
|
+
});
|
|
649
688
|
const node = await this.prepareMessage(data);
|
|
650
689
|
this.sendMessage(peer, id, node.encoded);
|
|
651
690
|
}
|
|
652
691
|
async handleData(peer, id, proto) {
|
|
653
692
|
let { hash, store } = proto.decoded;
|
|
654
693
|
let data;
|
|
655
|
-
store =
|
|
694
|
+
store =
|
|
695
|
+
globalThis[`${store}Store`] ||
|
|
696
|
+
(await this.whichStore([...this.stores], hash));
|
|
656
697
|
if (store && !store.private) {
|
|
657
698
|
data = await store.get(hash);
|
|
658
699
|
if (data) {
|
|
659
|
-
data = await new globalThis.peernet.protos[
|
|
700
|
+
data = await new globalThis.peernet.protos["peernet-data-response"]({
|
|
701
|
+
hash,
|
|
702
|
+
data,
|
|
703
|
+
});
|
|
660
704
|
const node = await this.prepareMessage(data);
|
|
661
705
|
this.sendMessage(peer, id, node.encoded);
|
|
662
706
|
}
|
|
@@ -680,21 +724,20 @@ class Peernet {
|
|
|
680
724
|
const { id, proto } = message;
|
|
681
725
|
this.bw.down += proto.encoded.length;
|
|
682
726
|
switch (proto.name) {
|
|
683
|
-
case
|
|
727
|
+
case "peernet-dht": {
|
|
684
728
|
this.handleDHT(peer, id, proto);
|
|
685
729
|
break;
|
|
686
730
|
}
|
|
687
|
-
case
|
|
731
|
+
case "peernet-data": {
|
|
688
732
|
this.handleData(peer, id, proto);
|
|
689
733
|
break;
|
|
690
734
|
}
|
|
691
|
-
case
|
|
735
|
+
case "peernet-request": {
|
|
692
736
|
this.handleRequest(peer, id, proto);
|
|
693
737
|
break;
|
|
694
738
|
}
|
|
695
|
-
case
|
|
696
|
-
|
|
697
|
-
globalSub.publish(proto.decoded.topic, proto.decoded.data);
|
|
739
|
+
case "peernet-ps": {
|
|
740
|
+
globalSub.publish(new TextDecoder().decode(proto.decoded.topic), proto.decoded.data);
|
|
698
741
|
}
|
|
699
742
|
}
|
|
700
743
|
}
|
|
@@ -705,14 +748,14 @@ class Peernet {
|
|
|
705
748
|
*/
|
|
706
749
|
async walk(hash) {
|
|
707
750
|
if (!hash)
|
|
708
|
-
throw new Error(
|
|
709
|
-
const data = await new globalThis.peernet.protos[
|
|
751
|
+
throw new Error("hash expected, received undefined");
|
|
752
|
+
const data = await new globalThis.peernet.protos["peernet-dht"]({ hash });
|
|
710
753
|
const walk = async (peer, peerId) => {
|
|
711
754
|
const node = await this.prepareMessage(data);
|
|
712
755
|
let result = await peer.request(node.encoded);
|
|
713
756
|
result = new Uint8Array(Object.values(result));
|
|
714
757
|
const proto = await protoFor(result);
|
|
715
|
-
if (proto.name !==
|
|
758
|
+
if (proto.name !== "peernet-dht-response")
|
|
716
759
|
throw dhtError(proto.name);
|
|
717
760
|
const peerInfo = {
|
|
718
761
|
...peer.connectionStats,
|
|
@@ -738,7 +781,8 @@ class Peernet {
|
|
|
738
781
|
let providers = this.dht.providersFor(hash);
|
|
739
782
|
// walk the network to find a provider
|
|
740
783
|
let tries = 0;
|
|
741
|
-
while (!providers && tries < 3 ||
|
|
784
|
+
while ((!providers && tries < 3) ||
|
|
785
|
+
(Object.keys(providers).length === 0 && tries < 3)) {
|
|
742
786
|
tries += 1;
|
|
743
787
|
await this.walk(hash);
|
|
744
788
|
providers = this.dht.providersFor(hash);
|
|
@@ -752,14 +796,14 @@ class Peernet {
|
|
|
752
796
|
const data = await blockStore.has(hash);
|
|
753
797
|
if (data)
|
|
754
798
|
return blockStore.get(hash);
|
|
755
|
-
return this.requestData(hash,
|
|
799
|
+
return this.requestData(hash, "block");
|
|
756
800
|
},
|
|
757
801
|
put: async (hash, data) => {
|
|
758
802
|
if (await blockStore.has(hash))
|
|
759
803
|
return;
|
|
760
804
|
return await blockStore.put(hash, data);
|
|
761
805
|
},
|
|
762
|
-
has: async (hash) => await blockStore.has(hash
|
|
806
|
+
has: async (hash) => await blockStore.has(hash),
|
|
763
807
|
};
|
|
764
808
|
}
|
|
765
809
|
get transaction() {
|
|
@@ -768,7 +812,7 @@ class Peernet {
|
|
|
768
812
|
const data = await transactionStore.has(hash);
|
|
769
813
|
if (data)
|
|
770
814
|
return await transactionStore.get(hash);
|
|
771
|
-
return this.requestData(hash,
|
|
815
|
+
return this.requestData(hash, "transaction");
|
|
772
816
|
},
|
|
773
817
|
put: async (hash, data) => {
|
|
774
818
|
if (await transactionStore.has(hash))
|
|
@@ -780,7 +824,7 @@ class Peernet {
|
|
|
780
824
|
}
|
|
781
825
|
async requestData(hash, store) {
|
|
782
826
|
const providers = await this.providersFor(hash);
|
|
783
|
-
if (!providers || providers && Object.keys(providers).length === 0)
|
|
827
|
+
if (!providers || (providers && Object.keys(providers).length === 0))
|
|
784
828
|
throw nothingFoundError(hash);
|
|
785
829
|
debug(`found ${Object.keys(providers).length} provider(s) for ${hash}`);
|
|
786
830
|
// get closest peer on earth
|
|
@@ -791,7 +835,10 @@ class Peernet {
|
|
|
791
835
|
const id = closestPeer.id;
|
|
792
836
|
const peer = this.#connections[id];
|
|
793
837
|
if (peer?.connected) {
|
|
794
|
-
let data = await new globalThis.peernet.protos[
|
|
838
|
+
let data = await new globalThis.peernet.protos["peernet-data"]({
|
|
839
|
+
hash,
|
|
840
|
+
store: store?.name || store,
|
|
841
|
+
});
|
|
795
842
|
const node = await this.prepareMessage(data);
|
|
796
843
|
if (peer)
|
|
797
844
|
data = await peer.request(node.encoded);
|
|
@@ -830,7 +877,7 @@ class Peernet {
|
|
|
830
877
|
const message = await messageStore.has(hash);
|
|
831
878
|
if (message)
|
|
832
879
|
return await messageStore.get(hash);
|
|
833
|
-
return this.requestData(hash,
|
|
880
|
+
return this.requestData(hash, "message");
|
|
834
881
|
},
|
|
835
882
|
/**
|
|
836
883
|
* put message content
|
|
@@ -858,7 +905,7 @@ class Peernet {
|
|
|
858
905
|
const data = await dataStore.has(hash);
|
|
859
906
|
if (data)
|
|
860
907
|
return await dataStore.get(hash);
|
|
861
|
-
return this.requestData(hash,
|
|
908
|
+
return this.requestData(hash, "data");
|
|
862
909
|
},
|
|
863
910
|
/**
|
|
864
911
|
* put data content
|
|
@@ -886,7 +933,7 @@ class Peernet {
|
|
|
886
933
|
const data = await dataStore.has(hash);
|
|
887
934
|
if (data)
|
|
888
935
|
return await dataStore.get(hash);
|
|
889
|
-
return this.requestData(hash,
|
|
936
|
+
return this.requestData(hash, "data");
|
|
890
937
|
},
|
|
891
938
|
/**
|
|
892
939
|
* put data content
|
|
@@ -905,12 +952,15 @@ class Peernet {
|
|
|
905
952
|
async addFolder(files) {
|
|
906
953
|
const links = [];
|
|
907
954
|
for (const file of files) {
|
|
908
|
-
const fileNode = await new globalThis.peernet.protos[
|
|
955
|
+
const fileNode = await new globalThis.peernet.protos["peernet-file"](file);
|
|
909
956
|
const hash = await fileNode.hash;
|
|
910
957
|
await dataStore.put(hash, fileNode.encoded);
|
|
911
958
|
links.push({ hash, path: file.path });
|
|
912
959
|
}
|
|
913
|
-
const node = await new globalThis.peernet.protos[
|
|
960
|
+
const node = await new globalThis.peernet.protos["peernet-file"]({
|
|
961
|
+
path: "/",
|
|
962
|
+
links,
|
|
963
|
+
});
|
|
914
964
|
const hash = await node.hash;
|
|
915
965
|
await dataStore.put(hash, node.encoded);
|
|
916
966
|
return hash;
|
|
@@ -918,8 +968,10 @@ class Peernet {
|
|
|
918
968
|
async ls(hash, options) {
|
|
919
969
|
let data;
|
|
920
970
|
const has = await dataStore.has(hash);
|
|
921
|
-
data = has
|
|
922
|
-
|
|
971
|
+
data = has
|
|
972
|
+
? await dataStore.get(hash)
|
|
973
|
+
: await this.requestData(hash, "data");
|
|
974
|
+
const node = await new peernet.protos["peernet-file"](data);
|
|
923
975
|
await node.decode();
|
|
924
976
|
console.log(data);
|
|
925
977
|
const paths = [];
|
|
@@ -935,8 +987,10 @@ class Peernet {
|
|
|
935
987
|
async cat(hash, options) {
|
|
936
988
|
let data;
|
|
937
989
|
const has = await dataStore.has(hash);
|
|
938
|
-
data = has
|
|
939
|
-
|
|
990
|
+
data = has
|
|
991
|
+
? await dataStore.get(hash)
|
|
992
|
+
: await this.requestData(hash, "data");
|
|
993
|
+
const node = await new peernet.protos["peernet-file"](data);
|
|
940
994
|
if (node.decoded?.links.length > 0)
|
|
941
995
|
throw new Error(`${hash} is a directory`);
|
|
942
996
|
if (options?.pin)
|
|
@@ -974,7 +1028,7 @@ class Peernet {
|
|
|
974
1028
|
store = globalThis[`${store}Store`];
|
|
975
1029
|
if (!store)
|
|
976
1030
|
store = await this.whichStore([...this.stores], hash);
|
|
977
|
-
if (store && await store.has(hash))
|
|
1031
|
+
if (store && (await store.has(hash)))
|
|
978
1032
|
data = await store.get(hash);
|
|
979
1033
|
if (data)
|
|
980
1034
|
return data;
|
|
@@ -987,7 +1041,7 @@ class Peernet {
|
|
|
987
1041
|
* @param {Buffer} data
|
|
988
1042
|
* @param {String} storeName - storeName to access
|
|
989
1043
|
*/
|
|
990
|
-
async put(hash, data, storeName =
|
|
1044
|
+
async put(hash, data, storeName = "data") {
|
|
991
1045
|
const store = globalThis[`${storeName}Store`];
|
|
992
1046
|
return store.put(hash, data);
|
|
993
1047
|
}
|
|
@@ -1010,7 +1064,7 @@ class Peernet {
|
|
|
1010
1064
|
async publish(topic, data) {
|
|
1011
1065
|
// globalSub.publish(topic, data)
|
|
1012
1066
|
const id = Math.random().toString(36).slice(-12);
|
|
1013
|
-
data = await new globalThis.peernet.protos[
|
|
1067
|
+
data = await new globalThis.peernet.protos["peernet-ps"]({ data, topic });
|
|
1014
1068
|
for (const [peerId, peer] of Object.entries(this.#connections)) {
|
|
1015
1069
|
if (peerId !== this.id) {
|
|
1016
1070
|
const node = await this.prepareMessage(data);
|
|
@@ -1032,7 +1086,7 @@ class Peernet {
|
|
|
1032
1086
|
globalSub.subscribe(topic, callback);
|
|
1033
1087
|
}
|
|
1034
1088
|
async removePeer(peer) {
|
|
1035
|
-
console.log(
|
|
1089
|
+
console.log("removepeer", peer.id);
|
|
1036
1090
|
const id = peer.id;
|
|
1037
1091
|
await this.client._removePeer(peer);
|
|
1038
1092
|
if (this.client.peers[id]) {
|
|
@@ -1040,7 +1094,7 @@ class Peernet {
|
|
|
1040
1094
|
// if (this.client.peers[id][connection].connected === false) delete this.client.peers[id][connection]
|
|
1041
1095
|
// @ts-ignore
|
|
1042
1096
|
if (this.client.peers[id][connection].connected)
|
|
1043
|
-
return this.client.emit(
|
|
1097
|
+
return this.client.emit("peerconnect", connection);
|
|
1044
1098
|
}
|
|
1045
1099
|
}
|
|
1046
1100
|
}
|