@leofcoin/peernet 0.10.8 → 0.11.0
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/LICENSE +1 -1
- package/README.md +49 -49
- package/dist/browser/peernet.js +101813 -92946
- package/dist/commonjs/client-bd0caeb7.js +324 -0
- package/dist/commonjs/{codec-6367213c.js → codec-4a768e5e.js} +99 -89
- package/dist/commonjs/codec-format-interface.js +41 -24
- package/dist/commonjs/codec.js +3 -3
- package/dist/commonjs/dht-response.js +3 -3
- package/dist/commonjs/dht.js +23 -23
- package/dist/commonjs/hash.js +17 -7
- package/dist/commonjs/{http-42a6e555.js → http-2b0735ef.js} +19 -15
- package/dist/commonjs/peernet-message.js +12 -12
- package/dist/commonjs/peernet.js +1162 -964
- package/dist/commonjs/request.js +12 -12
- package/dist/commonjs/response.js +12 -12
- package/dist/module/peernet.js +1323 -1118
- package/index.html +4 -6
- package/package.json +31 -7
- package/rollup.config.js +33 -5
- package/rollup0.config.js +7 -0
- package/src/codec/codec-format-interface.js +40 -23
- package/src/codec/codec.js +21 -11
- package/src/codec/codecs.js +79 -79
- package/src/handlers/message.js +52 -52
- package/src/hash/hash.js +16 -6
- package/src/http/client/http-client.js +1 -1
- package/src/messages/chat-message.js +14 -14
- package/src/messages/data-response.js +14 -14
- package/src/messages/data.js +18 -18
- package/src/messages/dht-response.js +0 -1
- package/src/messages/dht.js +25 -25
- package/src/messages/peer-response.js +14 -14
- package/src/messages/peer.js +14 -14
- package/src/messages/peernet-message.js +14 -14
- package/src/messages/ps.js +14 -14
- package/src/messages/request.js +14 -14
- package/src/messages/response.js +14 -14
- package/src/peernet.js +29 -114
- package/test/codec.js +3 -2
- package/test/messages.js +7 -4
- package/test.js +11 -4
- package/webpack.config.js +35 -0
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -79
- package/coverage/lcov-report/codec-format-interface.js.html +0 -533
- package/coverage/lcov-report/codec.js.html +0 -677
- package/coverage/lcov-report/dht-response.js.html +0 -188
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/hash.js.html +0 -551
- package/coverage/lcov-report/index.html +0 -156
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -170
- package/coverage/lcov.info +0 -459
- package/debug.log +0 -3
- package/dist/browser/peernet.js.tmp-browserify-14074318104595318069 +0 -0
- package/dist/browser/peernet.js.tmp-browserify-45407634493269122267 +0 -0
- package/dist/browser/peernet.js.tmp-browserify-53722389064799025427 +0 -0
- package/dist/browser/peernet.js.tmp-browserify-96323030449218949300 +0 -0
- package/dist/codec/codec-format-interface.js +0 -433
- package/dist/codec/codec.js +0 -199
- package/dist/commonjs/codec-73adfc0f.js +0 -205
- package/dist/commonjs/http-2c603501.js +0 -324
- package/dist/commonjs/http-43f4fafe.js +0 -324
- package/dist/commonjs/http-a94c5a81.js +0 -324
- package/dist/commonjs/peernet-message-b6925673.js +0 -32
- package/dist/hash/hash.js +0 -340
- package/dist/messages/dht-response.js +0 -454
- package/dist/messages/dht.js +0 -453
- package/dist/messages/peernet.js +0 -456
- package/dist/module/http-273664bd.js +0 -317
- package/dist/module/http-8fe3c0d7.js +0 -317
- package/dist/module/http-c780c991.js +0 -317
- package/dist/module/http-f13e0d77.js +0 -317
package/dist/commonjs/peernet.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var sha256 = require('crypto-js/sha256');
|
|
5
|
-
var P2P = require('p2pt');
|
|
6
|
-
var LeofcoinStorage$1 = require('@leofcoin/storage');
|
|
7
|
-
var websocket = require('websocket');
|
|
8
|
-
var http$1 = require('http');
|
|
9
|
-
var Koa = require('koa');
|
|
3
|
+
var LeofcoinStorage = require('@leofcoin/storage');
|
|
10
4
|
var peernetMessage = require('./peernet-message.js');
|
|
11
5
|
var dht = require('./dht.js');
|
|
12
6
|
var dhtResponse = require('./dht-response.js');
|
|
@@ -14,782 +8,620 @@ var protons = require('protons');
|
|
|
14
8
|
var codecFormatInterface = require('./codec-format-interface.js');
|
|
15
9
|
var request = require('./request.js');
|
|
16
10
|
var response = require('./response.js');
|
|
17
|
-
var fetch
|
|
18
|
-
var codec = require('./codec-
|
|
11
|
+
var fetch = require('node-fetch');
|
|
12
|
+
var codec = require('./codec-4a768e5e.js');
|
|
19
13
|
var hash = require('./hash.js');
|
|
20
|
-
var
|
|
21
|
-
require('
|
|
22
|
-
require('
|
|
14
|
+
var generateAccount = require('@leofcoin/generate-account');
|
|
15
|
+
var bs58check = require('bs58check');
|
|
16
|
+
var bip39 = require('bip39');
|
|
17
|
+
var bip32 = require('bip32');
|
|
18
|
+
var createKeccakHash = require('keccak');
|
|
19
|
+
var secp256k1 = require('secp256k1');
|
|
20
|
+
var ecc = require('tiny-secp256k1');
|
|
21
|
+
var MultiSignature = require('multi-signature');
|
|
22
|
+
var varint = require('varint');
|
|
23
|
+
var AES = require('crypto-js/aes.js');
|
|
24
|
+
require('crypto-js/sha512.js');
|
|
25
|
+
var ENC = require('crypto-js/enc-utf8.js');
|
|
26
|
+
require('@vandeurenglenn/base32');
|
|
27
|
+
require('@vandeurenglenn/base58');
|
|
23
28
|
require('is-hex');
|
|
24
|
-
require('varint');
|
|
25
|
-
require('keccak');
|
|
26
29
|
|
|
27
30
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
var
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
var
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.bw = {
|
|
42
|
-
up: 0,
|
|
43
|
-
down: 0,
|
|
44
|
-
};
|
|
45
|
-
this.id = id;
|
|
46
|
-
this.connection = connection;
|
|
47
|
-
|
|
48
|
-
this.connection.on('data', (message) => {
|
|
49
|
-
this.bw.down += message.length;
|
|
50
|
-
pubsub.publish('peernet.data', JSON.parse(message.toString()));
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
request(data) {
|
|
55
|
-
return new Promise((resolve, reject) => {
|
|
56
|
-
const id = Math.random().toString(36).slice(-12);
|
|
57
|
-
data = Buffer.from(JSON.stringify({id, data}));
|
|
58
|
-
const _onData = (message) => {
|
|
59
|
-
if (message.id !== id) return
|
|
60
|
-
|
|
61
|
-
resolve(message.data);
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
pubsub.subscribe('peernet.data', _onData);
|
|
65
|
-
|
|
66
|
-
// cleanup subscriptions
|
|
67
|
-
setTimeout(() => {
|
|
68
|
-
pubsub.unsubscribe('peernet.data', _onData);
|
|
69
|
-
}, 5000);
|
|
70
|
-
|
|
71
|
-
this.write(data);
|
|
32
|
+
function _interopNamespace(e) {
|
|
33
|
+
if (e && e.__esModule) return e;
|
|
34
|
+
var n = Object.create(null);
|
|
35
|
+
if (e) {
|
|
36
|
+
Object.keys(e).forEach(function (k) {
|
|
37
|
+
if (k !== 'default') {
|
|
38
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
39
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
get: function () { return e[k]; }
|
|
42
|
+
});
|
|
43
|
+
}
|
|
72
44
|
});
|
|
73
45
|
}
|
|
46
|
+
n["default"] = e;
|
|
47
|
+
return Object.freeze(n);
|
|
48
|
+
}
|
|
74
49
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
50
|
+
var LeofcoinStorage__default = /*#__PURE__*/_interopDefaultLegacy(LeofcoinStorage);
|
|
51
|
+
var protons__default = /*#__PURE__*/_interopDefaultLegacy(protons);
|
|
52
|
+
var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
|
|
53
|
+
var generateAccount__default = /*#__PURE__*/_interopDefaultLegacy(generateAccount);
|
|
54
|
+
var bs58check__default = /*#__PURE__*/_interopDefaultLegacy(bs58check);
|
|
55
|
+
var bs58check__namespace = /*#__PURE__*/_interopNamespace(bs58check);
|
|
56
|
+
var bip32__namespace = /*#__PURE__*/_interopNamespace(bip32);
|
|
57
|
+
var createKeccakHash__default = /*#__PURE__*/_interopDefaultLegacy(createKeccakHash);
|
|
58
|
+
var ecc__default = /*#__PURE__*/_interopDefaultLegacy(ecc);
|
|
59
|
+
var MultiSignature__default = /*#__PURE__*/_interopDefaultLegacy(MultiSignature);
|
|
60
|
+
var varint__default = /*#__PURE__*/_interopDefaultLegacy(varint);
|
|
61
|
+
var AES__default = /*#__PURE__*/_interopDefaultLegacy(AES);
|
|
62
|
+
var ENC__default = /*#__PURE__*/_interopDefaultLegacy(ENC);
|
|
63
|
+
|
|
64
|
+
/* socket-request-client version 1.6.1 */
|
|
65
|
+
|
|
66
|
+
class LittlePubSub {
|
|
67
|
+
constructor(verbose = true) {
|
|
68
|
+
this.subscribers = {};
|
|
69
|
+
this.verbose = verbose;
|
|
70
|
+
}
|
|
71
|
+
subscribe(event, handler, context) {
|
|
72
|
+
if (typeof context === 'undefined') {
|
|
73
|
+
context = handler;
|
|
74
|
+
}
|
|
75
|
+
this.subscribers[event] = this.subscribers[event] || { handlers: [], value: null};
|
|
76
|
+
this.subscribers[event].handlers.push(handler.bind(context));
|
|
91
77
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
pubsub.unsubscribe(event, this._events[event]);
|
|
78
|
+
unsubscribe(event, handler, context) {
|
|
79
|
+
if (typeof context === 'undefined') {
|
|
80
|
+
context = handler;
|
|
96
81
|
}
|
|
97
|
-
this.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
this.
|
|
82
|
+
if (this.subscribers[event]) {
|
|
83
|
+
const index = this.subscribers[event].handlers.indexOf(handler.bind(context));
|
|
84
|
+
this.subscribers[event].handlers.splice(index);
|
|
85
|
+
if (this.subscribers[event].handlers.length === 0) delete this.subscribers[event];
|
|
101
86
|
}
|
|
102
|
-
this.connection.destroy();
|
|
103
87
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
globalThis.connections = new Map();
|
|
112
|
-
globalThis.recentConnections = new Map();
|
|
113
|
-
globalThis.pubsub = globalThis.pubsub || new PubSub__default["default"]({verbose: false});
|
|
114
|
-
|
|
115
|
-
class PeernetClient {
|
|
116
|
-
constructor(options = {}) {
|
|
117
|
-
if (!options.id) options.id = Buffer.from('00000000000000000000000000000000');
|
|
118
|
-
if (!options.networkVersion) options.networkVersion = 'v0.1.0';
|
|
119
|
-
if (!options.networkName) options.networkName = 'peernet';
|
|
120
|
-
this.id = options.id;
|
|
121
|
-
|
|
122
|
-
this.topic = Buffer.from(sha256__default["default"](`${options.networkName}-${options.networkVersion}`).toString());
|
|
123
|
-
|
|
124
|
-
const trackers = [
|
|
125
|
-
'wss://star.leofcoin.org',
|
|
126
|
-
'wss://tracker.openwebtorrent.com',
|
|
127
|
-
// 'wss://tracker.sloppyta.co:443/announce',
|
|
128
|
-
];
|
|
129
|
-
this.p2p = new P2P__default["default"](trackers, this.topic.slice(0, 20));
|
|
130
|
-
this.p2p.on('peerconnect', (peer) => {
|
|
131
|
-
peer = new PeernetPeer(peer.id, peer);
|
|
132
|
-
connections.set(peer.id, peer);
|
|
133
|
-
pubsub.publish('peer:discovered', peer);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
this.p2p.on('peerclose', (peer) => {
|
|
137
|
-
// TODO: close peernetPeer
|
|
138
|
-
const peernetPeer = connections.get(peer.id);
|
|
139
|
-
if (peernetPeer) {
|
|
140
|
-
peernetPeer.close();
|
|
88
|
+
publish(event, change) {
|
|
89
|
+
if (this.subscribers[event]) {
|
|
90
|
+
if (this.verbose || this.subscribers[event].value !== change) {
|
|
91
|
+
this.subscribers[event].value = change;
|
|
92
|
+
this.subscribers[event].handlers.forEach(handler => {
|
|
93
|
+
handler(change, this.subscribers[event].value);
|
|
94
|
+
});
|
|
141
95
|
}
|
|
142
|
-
connections.delete(peer.id);
|
|
143
|
-
pubsub.publish('peer:disconnected', peer);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
this.p2p.start();
|
|
147
|
-
|
|
148
|
-
if (globalThis.process) {
|
|
149
|
-
process.on('SIGINT', async () => {
|
|
150
|
-
console.log('Caught interrupt signal');
|
|
151
|
-
this.close();
|
|
152
|
-
setTimeout(async () => {
|
|
153
|
-
process.exit();
|
|
154
|
-
}, 100);
|
|
155
|
-
});
|
|
156
|
-
} else {
|
|
157
|
-
globalThis.onbeforeunload = () => {
|
|
158
|
-
this.close();
|
|
159
|
-
};
|
|
160
96
|
}
|
|
161
|
-
//
|
|
162
|
-
// this.sw.on('close', () => {
|
|
163
|
-
// })
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
close() {
|
|
167
|
-
return this.p2p.destroy()
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
_peers() {
|
|
171
|
-
return this.p2p.getPeers()
|
|
172
97
|
}
|
|
173
98
|
}
|
|
174
99
|
|
|
175
|
-
var
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
return
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return
|
|
195
|
-
}
|
|
196
|
-
if (method === 'remove') {
|
|
197
|
-
await globalThis[name].remove(key, value);
|
|
198
|
-
return send('ok')
|
|
199
|
-
}
|
|
200
|
-
value = await globalThis[name].get(key);
|
|
201
|
-
return send(value)
|
|
202
|
-
} catch (e) {
|
|
203
|
-
return error(e)
|
|
204
|
-
}
|
|
205
|
-
},
|
|
206
|
-
getConfig: async (params, {send, error}) => {
|
|
207
|
-
try {
|
|
208
|
-
const config = await api.getConfig(params);
|
|
209
|
-
send(config);
|
|
210
|
-
} catch (e) {
|
|
211
|
-
error(e);
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
setMinerConfig: async (params, {send, error}) => {
|
|
215
|
-
try {
|
|
216
|
-
await api.setMinerConfig(params);
|
|
217
|
-
send('ok');
|
|
218
|
-
} catch (e) {
|
|
219
|
-
error(e);
|
|
100
|
+
var clientApi = _pubsub => {
|
|
101
|
+
const subscribe = (topic, cb) => {
|
|
102
|
+
_pubsub.subscribe(topic, cb);
|
|
103
|
+
};
|
|
104
|
+
const unsubscribe = (topic, cb) => {
|
|
105
|
+
_pubsub.unsubscribe(topic, cb);
|
|
106
|
+
};
|
|
107
|
+
const publish = (topic, value) => {
|
|
108
|
+
_pubsub.publish(topic, value);
|
|
109
|
+
};
|
|
110
|
+
const _connectionState = (state) => {
|
|
111
|
+
switch (state) {
|
|
112
|
+
case 0:
|
|
113
|
+
return 'connecting'
|
|
114
|
+
case 1:
|
|
115
|
+
return 'open'
|
|
116
|
+
case 2:
|
|
117
|
+
return 'closing'
|
|
118
|
+
case 3:
|
|
119
|
+
return 'closed'
|
|
220
120
|
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
121
|
+
};
|
|
122
|
+
const request = (client, request) => {
|
|
123
|
+
return new Promise((resolve, reject) => {
|
|
124
|
+
const state = _connectionState(client.readyState);
|
|
125
|
+
if (state !== 'open') return reject(`coudn't send request to ${client.id}, no open connection found.`)
|
|
126
|
+
request.id = Math.random().toString(36).slice(-12);
|
|
127
|
+
const handler = result => {
|
|
128
|
+
if (result && result.error) return reject(result.error)
|
|
129
|
+
resolve({result, id: request.id, handler});
|
|
130
|
+
unsubscribe(request.id, handler);
|
|
131
|
+
};
|
|
132
|
+
subscribe(request.id, handler);
|
|
133
|
+
send(client, request);
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
const send = async (client, request) => {
|
|
137
|
+
return client.send(JSON.stringify(request))
|
|
138
|
+
};
|
|
139
|
+
const pubsub = client => {
|
|
140
|
+
return {
|
|
141
|
+
publish: (topic = 'pubsub', value) => {
|
|
142
|
+
return send(client, {url: 'pubsub', params: { topic, value }})
|
|
143
|
+
},
|
|
144
|
+
subscribe: (topic = 'pubsub', cb) => {
|
|
145
|
+
subscribe(topic, cb);
|
|
146
|
+
return send(client, {url: 'pubsub', params: { topic, subscribe: true }})
|
|
147
|
+
},
|
|
148
|
+
unsubscribe: (topic = 'pubsub', cb) => {
|
|
149
|
+
unsubscribe(topic, cb);
|
|
150
|
+
return send(client, {url: 'pubsub', params: { topic, unsubscribe: true }})
|
|
151
|
+
},
|
|
152
|
+
subscribers: _pubsub.subscribers
|
|
228
153
|
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
154
|
+
};
|
|
155
|
+
const server = (client) => {
|
|
156
|
+
return {
|
|
157
|
+
uptime: async () => {
|
|
158
|
+
try {
|
|
159
|
+
const { result, id, handler } = await request(client, {url: 'uptime'});
|
|
160
|
+
unsubscribe(id, handler);
|
|
161
|
+
return result
|
|
162
|
+
} catch (e) {
|
|
163
|
+
throw e
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
ping: async () => {
|
|
167
|
+
try {
|
|
168
|
+
const now = new Date().getTime();
|
|
169
|
+
const { result, id, handler } = await request(client, {url: 'ping'});
|
|
170
|
+
unsubscribe(id, handler);
|
|
171
|
+
return (Number(result) - now)
|
|
172
|
+
} catch (e) {
|
|
173
|
+
throw e
|
|
174
|
+
}
|
|
175
|
+
}
|
|
240
176
|
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
177
|
+
};
|
|
178
|
+
const peernet = (client) => {
|
|
179
|
+
return {
|
|
180
|
+
join: async (params) => {
|
|
181
|
+
try {
|
|
182
|
+
params.join = true;
|
|
183
|
+
const requested = { url: 'peernet', params };
|
|
184
|
+
const { result, id, handler } = await request(client, requested);
|
|
185
|
+
unsubscribe(id, handler);
|
|
186
|
+
return result
|
|
187
|
+
} catch (e) {
|
|
188
|
+
throw e
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
leave: async (params) => {
|
|
192
|
+
try {
|
|
193
|
+
params.join = false;
|
|
194
|
+
const requested = { url: 'peernet', params };
|
|
195
|
+
const { result, id, handler } = await request(client, requested);
|
|
196
|
+
unsubscribe(id, handler);
|
|
197
|
+
return result
|
|
198
|
+
} catch (e) {
|
|
199
|
+
throw e
|
|
200
|
+
}
|
|
201
|
+
}
|
|
248
202
|
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
} catch (e) {
|
|
265
|
-
console.log(e);
|
|
266
|
-
error(e);
|
|
203
|
+
};
|
|
204
|
+
return { send, request, pubsub, server, subscribe, unsubscribe, publish, peernet }
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
if (!globalThis.PubSub) globalThis.PubSub = LittlePubSub;
|
|
208
|
+
if (!globalThis.pubsub) globalThis.pubsub = new LittlePubSub({verbose: false});
|
|
209
|
+
const socketRequestClient = (url, protocols = 'echo-protocol', options = { retry: false }) => {
|
|
210
|
+
const { retry } = options;
|
|
211
|
+
const api = clientApi(pubsub);
|
|
212
|
+
let tries = 0;
|
|
213
|
+
const onerror = error => {
|
|
214
|
+
if (pubsub.subscribers['error']) {
|
|
215
|
+
pubsub.publish('error', error);
|
|
216
|
+
} else {
|
|
217
|
+
console.error(error);
|
|
267
218
|
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
219
|
+
};
|
|
220
|
+
const onmessage = message => {
|
|
221
|
+
const {value, url, status, id} = JSON.parse(message.data.toString());
|
|
222
|
+
const publisher = id ? id : url;
|
|
223
|
+
if (status === 200) {
|
|
224
|
+
pubsub.publish(publisher, value);
|
|
225
|
+
} else {
|
|
226
|
+
pubsub.publish(publisher, {error: value});
|
|
275
227
|
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
228
|
+
};
|
|
229
|
+
const clientConnection = client => {
|
|
230
|
+
const startTime = new Date().getTime();
|
|
231
|
+
return {
|
|
232
|
+
client,
|
|
233
|
+
request: async req => {
|
|
234
|
+
const { result, id, handler } = await api.request(client, req);
|
|
235
|
+
pubsub.unsubscribe(id, handler);
|
|
236
|
+
return result
|
|
237
|
+
},
|
|
238
|
+
send: req => api.send(client, req),
|
|
239
|
+
subscribe: api.subscribe,
|
|
240
|
+
unsubscribe: api.unsubscribe,
|
|
241
|
+
subscribers: api.subscribers,
|
|
242
|
+
publish: api.publish,
|
|
243
|
+
pubsub: api.pubsub(client),
|
|
244
|
+
uptime: () => {
|
|
245
|
+
const now = new Date().getTime();
|
|
246
|
+
return (now - startTime)
|
|
247
|
+
},
|
|
248
|
+
peernet: api.peernet(client),
|
|
249
|
+
server: api.server(client),
|
|
250
|
+
close: exit => {
|
|
251
|
+
client.onclose = message => {
|
|
252
|
+
if (exit) process.exit();
|
|
253
|
+
};
|
|
254
|
+
client.close();
|
|
255
|
+
}
|
|
287
256
|
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
257
|
+
};
|
|
258
|
+
return new Promise((resolve, reject) => {
|
|
259
|
+
const init = () => {
|
|
260
|
+
let ws;
|
|
261
|
+
if (typeof process === 'object' && !globalThis.WebSocket) {
|
|
262
|
+
ws = require('websocket').w3cwebsocket;
|
|
263
|
+
} else {
|
|
264
|
+
ws = WebSocket;
|
|
265
|
+
}
|
|
266
|
+
const client = new ws(url, protocols);
|
|
267
|
+
client.onmessage = onmessage;
|
|
268
|
+
client.onerror = onerror;
|
|
269
|
+
client.onopen = () => {
|
|
270
|
+
tries = 0;
|
|
271
|
+
resolve(clientConnection(client));
|
|
272
|
+
};
|
|
273
|
+
client.onclose = message => {
|
|
274
|
+
tries++;
|
|
275
|
+
if (!retry) return reject(options)
|
|
276
|
+
if (tries > 5) {
|
|
277
|
+
console.log(`${protocols} Client Closed`);
|
|
278
|
+
console.error(`could not connect to - ${url}/`);
|
|
279
|
+
return resolve(clientConnection(client))
|
|
280
|
+
}
|
|
281
|
+
if (message.code === 1006) {
|
|
282
|
+
console.log('Retrying in 10 seconds');
|
|
283
|
+
setTimeout(() => {
|
|
284
|
+
return init();
|
|
285
|
+
}, retry);
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
return init();
|
|
290
|
+
});
|
|
293
291
|
};
|
|
294
292
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
293
|
+
class Peer {
|
|
294
|
+
#connection
|
|
295
|
+
#ready = false
|
|
296
|
+
#connecting = false
|
|
297
|
+
#connected = false
|
|
298
|
+
#channelReady = false
|
|
299
|
+
#destroying = false
|
|
300
|
+
#destroyed = false
|
|
301
|
+
#isNegotiating = false
|
|
302
|
+
#firstNegotiation = true
|
|
303
|
+
#iceComplete = false
|
|
304
|
+
#remoteTracks = []
|
|
305
|
+
#remoteStreams = []
|
|
306
|
+
#pendingCandidates = []
|
|
307
|
+
#senderMap = new Map()
|
|
308
|
+
#iceCompleteTimer
|
|
309
|
+
#channel
|
|
310
|
+
|
|
311
|
+
get connection() {
|
|
312
|
+
return this.#connection
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
get connected() {
|
|
316
|
+
return this.#connected
|
|
317
|
+
}
|
|
300
318
|
|
|
301
319
|
/**
|
|
302
|
-
* @
|
|
303
|
-
*
|
|
304
|
-
* @param {object} connection socket connection
|
|
305
|
-
* @param {string} route the route to handle
|
|
306
|
-
*/
|
|
307
|
-
var socketConnection = (request, protocol, origin) => {
|
|
308
|
-
if (origin && !originIsAllowed(request.origin, origin)) {
|
|
309
|
-
// Make sure we only accept requests from an allowed origin
|
|
310
|
-
request.reject();
|
|
311
|
-
fullLog(`Connection from origin ${request.origin} rejected.`);
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
// console.log(request);
|
|
315
|
-
const connection = request.accept(protocol, request.origin);
|
|
316
|
-
fullLog(`Connection accepted @${protocol}`);
|
|
317
|
-
return connection;
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* @module socketResponse
|
|
322
|
-
*
|
|
323
|
-
* @param {object} connection socket connection
|
|
324
|
-
* @param {string} url the request url
|
|
320
|
+
* @params {Object} options
|
|
321
|
+
* @params {string} options.channelName - this peerid : otherpeer id
|
|
325
322
|
*/
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
const socketRequestServer = (options, routes = {}) => {
|
|
339
|
-
// if (!routes && !routes.port && options) routes = options;
|
|
340
|
-
// else if (!options && !routes) return console.error('no routes defined');
|
|
341
|
-
|
|
342
|
-
let {httpServer, httpsServer, port, protocol, credentials, origin, pubsub } = options;
|
|
343
|
-
if (!pubsub) pubsub = new PubSub__default["default"]({verbose: false});
|
|
344
|
-
if (!port) port = 6000;
|
|
345
|
-
const connections = [];
|
|
346
|
-
let connection;
|
|
347
|
-
const startTime = new Date().getTime();
|
|
348
|
-
// default routes
|
|
349
|
-
if (!routes.ping) routes.ping = (response) => response.send(new Date().getTime());
|
|
350
|
-
if (!routes.uptime) routes.uptime = (response) => {
|
|
351
|
-
const now = new Date().getTime();
|
|
352
|
-
response.send(now - startTime);
|
|
323
|
+
constructor(options = {}) {
|
|
324
|
+
this._in = this._in.bind(this);
|
|
325
|
+
this.offerOptions = options.offerOptions;
|
|
326
|
+
this.initiator = options.initiator;
|
|
327
|
+
this.streams = options.streams;
|
|
328
|
+
this.socketClient = options.socketClient;
|
|
329
|
+
this.id = options.id;
|
|
330
|
+
this.to = options.to;
|
|
331
|
+
this.bw = {
|
|
332
|
+
up: 0,
|
|
333
|
+
down: 0
|
|
353
334
|
};
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
335
|
+
|
|
336
|
+
this.channelName = options.channelName || Buffer.from(Math.random().toString(36).slice(-12)).toString('hex');
|
|
337
|
+
console.log(this.channelName);
|
|
338
|
+
this.options = options;
|
|
339
|
+
this.#init();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
set socketClient(value) {
|
|
343
|
+
// this.socketClient?.pubsub.unsubscribe('signal', this._in)
|
|
344
|
+
this._socketClient = value;
|
|
345
|
+
this._socketClient.pubsub.subscribe('signal', this._in);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
get socketClient() {
|
|
349
|
+
return this._socketClient
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
send(message) {
|
|
353
|
+
this.bw.up += message.length;
|
|
354
|
+
this.channel.send(message);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
request(data) {
|
|
358
|
+
return new Promise((resolve, reject) => {
|
|
359
|
+
const id = Math.random().toString(36).slice(-12);
|
|
360
|
+
data = new TextEncoder().encode(JSON.stringify({id, data}));
|
|
361
|
+
const _onData = message => {
|
|
362
|
+
message = JSON.parse(new TextDecoder().decode(message.data));
|
|
363
|
+
if (message.id === id) {
|
|
364
|
+
resolve(message.data);
|
|
365
|
+
pubsub.unsubscribe('peer:data', _onData);
|
|
379
366
|
}
|
|
380
|
-
else if (params.value !== undefined)
|
|
381
|
-
// should only be send raw to stars
|
|
382
|
-
// for (const connection of connections) {
|
|
383
|
-
// if (connection !== response.connection) connection.send(JSON.stringify({
|
|
384
|
-
// url: topic, status: 200, value: params
|
|
385
|
-
// }));
|
|
386
|
-
// }
|
|
387
|
-
pubsub.publish(topic, params.value);
|
|
388
|
-
response.send('ok', 200);
|
|
389
367
|
};
|
|
390
|
-
|
|
368
|
+
|
|
369
|
+
pubsub.subscribe('peer:data', _onData);
|
|
370
|
+
|
|
371
|
+
// cleanup subscriptions
|
|
372
|
+
setTimeout(() => {
|
|
373
|
+
pubsub.unsubscribe('peer:data', _onData);
|
|
374
|
+
}, 5000);
|
|
375
|
+
|
|
376
|
+
this.send(data);
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async #init() {
|
|
381
|
+
try {
|
|
382
|
+
const iceServers = [{
|
|
383
|
+
urls: 'stun:stun.l.google.com:19302' // Google's public STUN server
|
|
384
|
+
}];
|
|
385
|
+
|
|
386
|
+
this.#connection = new wrtc.RTCPeerConnection();
|
|
387
|
+
this.#connection.onicecandidate = ({ candidate }) => {
|
|
388
|
+
if (candidate) {
|
|
389
|
+
this.address = candidate.address;
|
|
390
|
+
this.port = candidate.port;
|
|
391
|
+
this.protocol = candidate.protocol;
|
|
392
|
+
this.ipFamily = this.address.includes('::') ? 'ipv6': 'ipv4';
|
|
393
|
+
this._sendMessage({candidate});
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
// if (this.initiator) this.#connection.onnegotiationneeded = () => {
|
|
397
|
+
// console.log('create offer');
|
|
398
|
+
this.#connection.ondatachannel = (message) => {
|
|
399
|
+
message.channel.onopen = () => {
|
|
400
|
+
this.#connected = true;
|
|
401
|
+
pubsub.publish('peer:connected', this);
|
|
402
|
+
};
|
|
403
|
+
message.channel.onclose = () => console.log('close');
|
|
404
|
+
message.channel.onmessage = (message) => {
|
|
405
|
+
if (message.to) {
|
|
406
|
+
if (message.to === this.id) pubsub.publish('peer:data', message);
|
|
407
|
+
} else pubsub.publish('peer:data', message);
|
|
408
|
+
this.bw.down += message.length;
|
|
409
|
+
};
|
|
410
|
+
this.channel = message.channel;
|
|
411
|
+
};
|
|
412
|
+
if (this.initiator) {
|
|
413
|
+
|
|
414
|
+
this.channel = this.#connection.createDataChannel('messageChannel');
|
|
415
|
+
this.channel.onopen = () => {
|
|
416
|
+
this.#connected = true;
|
|
417
|
+
pubsub.publish('peer:connected', this);
|
|
418
|
+
// this.channel.send('hi')
|
|
419
|
+
};
|
|
420
|
+
this.channel.onclose = () => this.close.bind(this);
|
|
421
|
+
|
|
422
|
+
this.channel.onmessage = (message) => {
|
|
423
|
+
if (message.to) {
|
|
424
|
+
if (message.to === this.id) pubsub.publish('peer:data', message);
|
|
425
|
+
} else pubsub.publish('peer:data', message);
|
|
426
|
+
this.bw.down += message.length;
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
const offer = await this.#connection.createOffer();
|
|
430
|
+
await this.#connection.setLocalDescription(offer);
|
|
431
|
+
|
|
432
|
+
this._sendMessage({'sdp': this.#connection.localDescription});
|
|
433
|
+
}
|
|
434
|
+
// }
|
|
435
|
+
|
|
436
|
+
} catch (e) {
|
|
437
|
+
console.log(e);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
_sendMessage(message) {
|
|
442
|
+
this.socketClient.send({url: 'signal', params: {
|
|
443
|
+
to: this.to,
|
|
444
|
+
from: this.id,
|
|
445
|
+
channelName: this.options.channelName,
|
|
446
|
+
...message
|
|
447
|
+
}});
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
async _in(message, data) {
|
|
451
|
+
// message = JSON.parse(message);
|
|
452
|
+
if (message.to !== this.id) return
|
|
453
|
+
// if (data.videocall) return this._startStream(true, false); // start video and audio stream
|
|
454
|
+
// if (data.call) return this._startStream(true, true); // start audio stream
|
|
455
|
+
if (message.candidate) {
|
|
456
|
+
this.remoteAddress = message.candidate.address;
|
|
457
|
+
this.remotePort = message.candidate.port;
|
|
458
|
+
this.remoteProtocol = message.candidate.protocol;
|
|
459
|
+
this.remoteIpFamily = this.remoteAddress?.includes('::') ? 'ipv6': 'ipv4';
|
|
460
|
+
return this.#connection.addIceCandidate(new wrtc.RTCIceCandidate(message.candidate));
|
|
391
461
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
if (connection !== response.connection)
|
|
400
|
-
socketResponse(connection, 'peernet', 'peernet').send({discovered: params.address});
|
|
401
|
-
}
|
|
402
|
-
return
|
|
462
|
+
try {
|
|
463
|
+
if (message.sdp) {
|
|
464
|
+
if (message.sdp.type === 'offer') {
|
|
465
|
+
await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
|
|
466
|
+
const answer = await this.#connection.createAnswer();
|
|
467
|
+
await this.#connection.setLocalDescription(answer);
|
|
468
|
+
this._sendMessage({'sdp': this.#connection.localDescription});
|
|
403
469
|
}
|
|
404
|
-
if (
|
|
405
|
-
|
|
406
|
-
return response.send()
|
|
470
|
+
if (message.sdp.type === 'answer') {
|
|
471
|
+
await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
|
|
407
472
|
}
|
|
408
|
-
|
|
473
|
+
}
|
|
474
|
+
} catch (e) {
|
|
475
|
+
console.log(e);
|
|
409
476
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
close() {
|
|
480
|
+
this.channel?.close();
|
|
481
|
+
this.#connection?.close();
|
|
482
|
+
|
|
483
|
+
this.socketClient.pubsub.unsubscribe('signal', this._in);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
class Client {
|
|
488
|
+
#peerConnection
|
|
489
|
+
#connections = {}
|
|
490
|
+
#stars = {}
|
|
491
|
+
|
|
492
|
+
get connections() {
|
|
493
|
+
return { ...this.#connections }
|
|
419
494
|
}
|
|
420
495
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
connection = socketConnection(request, protocol, origin);
|
|
429
|
-
connections.push(connection);
|
|
430
|
-
|
|
431
|
-
const routeHandler = message => {
|
|
432
|
-
let data;
|
|
433
|
-
if (message.type) {
|
|
434
|
-
switch (message.type) {
|
|
435
|
-
case 'binary':
|
|
436
|
-
data = message.binaryData.toString();
|
|
437
|
-
break;
|
|
438
|
-
case 'utf8':
|
|
439
|
-
data = message.utf8Data;
|
|
440
|
-
break;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
const { route, params, url, id, customEvent } = JSON.parse(data);
|
|
444
|
-
// ignore api when customEvent is defined
|
|
445
|
-
if (customEvent) return;
|
|
446
|
-
if (routes[url]) {
|
|
447
|
-
if (!params) return routes[url](socketResponse(connection, url, id));
|
|
448
|
-
return routes[url](params, socketResponse(connection, url, id));
|
|
449
|
-
}
|
|
450
|
-
else return socketResponse(connection, url, id).error(`nop handler found for '${message.url}'`);
|
|
451
|
-
};
|
|
496
|
+
constructor(id, identifiers = ['peernet-v0.1.0'], stars = []) {
|
|
497
|
+
this.id = id || Math.random().toString(36).slice(-12);
|
|
498
|
+
if (!Array.isArray(identifiers)) identifiers = [identifiers];
|
|
499
|
+
this.peerJoined = this.peerJoined.bind(this);
|
|
500
|
+
this.peerLeft = this.peerLeft.bind(this);
|
|
501
|
+
this.starLeft = this.starLeft.bind(this);
|
|
502
|
+
this.starJoined = this.starJoined.bind(this);
|
|
452
503
|
|
|
453
|
-
|
|
454
|
-
|
|
504
|
+
this._init(identifiers, stars);
|
|
505
|
+
}
|
|
455
506
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
};
|
|
461
|
-
|
|
462
|
-
var http = (config = {}) => {
|
|
463
|
-
if (typeof config !== 'object') config = {};
|
|
464
|
-
if (!config.protocol) config.protocol = 'peernet-v0.1.0';
|
|
465
|
-
if (!config.port) config.port = 2000;
|
|
466
|
-
if (!config.host) config.host = '127.0.0.1';
|
|
467
|
-
|
|
468
|
-
const app = new Koa__default["default"]();
|
|
469
|
-
|
|
470
|
-
app.use(async (ctx) => {
|
|
471
|
-
const url = ctx.url.split('/api/')[1];
|
|
472
|
-
if (url === 'version') ctx.body = {client: '@peernet/api/http', version};
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
const httpServer = http$1.createServer(app.callback());
|
|
476
|
-
|
|
477
|
-
config.httpServer = httpServer;
|
|
478
|
-
|
|
479
|
-
httpServer.listen(config.port, () => {
|
|
480
|
-
console.log(`listening on ${config.port}`);
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
return socketRequestServer(config, api$1)
|
|
484
|
-
};
|
|
485
|
-
|
|
486
|
-
var clientApi = _pubsub => {
|
|
487
|
-
|
|
488
|
-
const subscribe = (topic, cb) => {
|
|
489
|
-
_pubsub.subscribe(topic, cb);
|
|
490
|
-
};
|
|
491
|
-
|
|
492
|
-
const unsubscribe = (topic, cb) => {
|
|
493
|
-
_pubsub.unsubscribe(topic, cb);
|
|
494
|
-
};
|
|
495
|
-
|
|
496
|
-
const publish = (topic, value) => {
|
|
497
|
-
_pubsub.publish(topic, value);
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
const _connectionState = (state) => {
|
|
501
|
-
switch (state) {
|
|
502
|
-
case 0:
|
|
503
|
-
return 'connecting'
|
|
504
|
-
case 1:
|
|
505
|
-
return 'open'
|
|
506
|
-
case 2:
|
|
507
|
-
return 'closing'
|
|
508
|
-
case 3:
|
|
509
|
-
return 'closed'
|
|
507
|
+
async _init(identifiers, stars = []) {
|
|
508
|
+
if (stars.length === 0) {
|
|
509
|
+
stars.push('wss://star.leofcoin.org');
|
|
510
|
+
stars.push('ws://localhost:44444');
|
|
510
511
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
512
|
+
this.identifiers = identifiers;
|
|
513
|
+
this.starsConfig = stars;
|
|
514
|
+
// reconnectJob()
|
|
515
|
+
|
|
516
|
+
globalThis.wrtc = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('wrtc')); });
|
|
517
|
+
for (const star of stars) {
|
|
518
|
+
try {
|
|
519
|
+
this.socketClient = await socketRequestClient(star, identifiers[0]);
|
|
520
|
+
const id = await this.socketClient.request({url: 'id', params: {from: this.id}});
|
|
521
|
+
this.socketClient.peerId = id;
|
|
522
|
+
this.#stars[id] = this.socketClient;
|
|
523
|
+
} catch (e) {
|
|
524
|
+
if (stars.indexOf(star) === stars.length -1 && !this.socketClient) throw new Error(`No star available to connect`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
const peers = await this.socketClient.peernet.join({id: this.id});
|
|
528
|
+
for (const id of peers) {
|
|
529
|
+
if (id !== this.id && !this.#connections[id]) this.#connections[id] = new Peer({channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id});
|
|
530
|
+
}
|
|
531
|
+
this.setupListeners();
|
|
532
|
+
|
|
533
|
+
pubsub.subscribe('peer:connected', (peer) => {
|
|
534
|
+
// peer.send(JSON.stringify({data: 'hello', from: this.id, to: peer.to}))
|
|
535
|
+
console.log({peer: peer.to});
|
|
536
|
+
console.log({id: peer.id});
|
|
537
|
+
console.log({id: this.id});
|
|
530
538
|
});
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
return send(client, {url: 'pubsub', params: { topic, subscribe: true }})
|
|
545
|
-
},
|
|
546
|
-
unsubscribe: (topic = 'pubsub', cb) => {
|
|
547
|
-
unsubscribe(topic, cb);
|
|
548
|
-
return send(client, {url: 'pubsub', params: { topic, unsubscribe: true }})
|
|
549
|
-
},
|
|
550
|
-
subscribers: _pubsub.subscribers
|
|
539
|
+
// pubsub.subscribe('peer:data', (data) => console.log({data}))
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
setupListeners() {
|
|
543
|
+
this.socketClient.subscribe('peer:joined', this.peerJoined);
|
|
544
|
+
this.socketClient.subscribe('peer:left', this.peerLeft);
|
|
545
|
+
this.socketClient.subscribe('star:left', this.starLeft);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
starJoined(id) {
|
|
549
|
+
if (this.#stars[id]) {
|
|
550
|
+
this.#stars[id].close();
|
|
551
|
+
delete this.#stars[id];
|
|
551
552
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
unsubscribe(id, handler);
|
|
560
|
-
return result
|
|
561
|
-
} catch (e) {
|
|
562
|
-
throw e
|
|
563
|
-
}
|
|
564
|
-
},
|
|
565
|
-
ping: async () => {
|
|
566
|
-
try {
|
|
567
|
-
const now = new Date().getTime();
|
|
568
|
-
const { result, id, handler } = await request(client, {url: 'ping'});
|
|
569
|
-
unsubscribe(id, handler);
|
|
570
|
-
return (Number(result) - now)
|
|
571
|
-
} catch (e) {
|
|
572
|
-
throw e
|
|
573
|
-
}
|
|
574
|
-
}
|
|
553
|
+
console.log(`star ${id} joined`);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
async starLeft(id) {
|
|
557
|
+
if (this.#stars[id]) {
|
|
558
|
+
this.#stars[id].close();
|
|
559
|
+
delete this.#stars[id];
|
|
575
560
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
unsubscribe(id, handler);
|
|
586
|
-
return result
|
|
587
|
-
} catch (e) {
|
|
588
|
-
throw e
|
|
589
|
-
}
|
|
590
|
-
},
|
|
591
|
-
leave: async (params) => {
|
|
561
|
+
if (this.socketClient?.peerId === id) {
|
|
562
|
+
|
|
563
|
+
this.socketClient.unsubscribe('peer:joined', this.peerJoined);
|
|
564
|
+
this.socketClient.unsubscribe('peer:left', this.peerLeft);
|
|
565
|
+
this.socketClient.unsubscribe('star:left', this.starLeft);
|
|
566
|
+
this.socketClient.close();
|
|
567
|
+
this.socketClient = undefined;
|
|
568
|
+
|
|
569
|
+
for (const star of this.starsConfig) {
|
|
592
570
|
try {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
|
|
571
|
+
this.socketClient = await socketRequestClient(star, this.identifiers[0]);
|
|
572
|
+
if (!this.socketClient?.client?._connection.connected) return
|
|
573
|
+
const id = await this.socketClient.request({url: 'id', params: {from: this.id}});
|
|
574
|
+
this.#stars[id] = this.socketClient;
|
|
575
|
+
|
|
576
|
+
this.socketClient.peerId = id;
|
|
577
|
+
|
|
578
|
+
const peers = await this.socketClient.peernet.join({id: this.id});
|
|
579
|
+
this.setupListeners();
|
|
580
|
+
for (const id of peers) {
|
|
581
|
+
if (id !== this.id) {
|
|
582
|
+
// close connection
|
|
583
|
+
if (this.#connections[id]) {
|
|
584
|
+
if (this.#connections[id].connected) await this.#connections[id].close();
|
|
585
|
+
delete this.#connections[id];
|
|
586
|
+
}
|
|
587
|
+
// reconnect
|
|
588
|
+
if (id !== this.id) this.#connections[id] = new Peer({channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id});
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
}
|
|
598
592
|
} catch (e) {
|
|
599
|
-
|
|
593
|
+
console.log(e);
|
|
594
|
+
if (this.starsConfig.indexOf(star) === this.starsConfig.length -1 && !this.socketClient) throw new Error(`No star available to connect`);
|
|
600
595
|
}
|
|
601
596
|
}
|
|
602
597
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
let tries = 0;
|
|
615
|
-
|
|
616
|
-
const onerror = error => {
|
|
617
|
-
if (pubsub.subscribers['error']) {
|
|
618
|
-
pubsub.publish('error', error);
|
|
619
|
-
} else {
|
|
620
|
-
console.error(error);
|
|
621
|
-
}
|
|
622
|
-
};
|
|
623
|
-
|
|
624
|
-
const onmessage = message => {
|
|
625
|
-
const {value, url, status, id} = JSON.parse(message.data.toString());
|
|
626
|
-
const publisher = id ? id : url;
|
|
627
|
-
if (status === 200) {
|
|
628
|
-
pubsub.publish(publisher, value);
|
|
629
|
-
} else {
|
|
630
|
-
pubsub.publish(publisher, {error: value});
|
|
598
|
+
|
|
599
|
+
console.log(`star ${id} left`);
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
peerLeft(id) {
|
|
605
|
+
if (this.#connections[id]) {
|
|
606
|
+
this.#connections[id].close();
|
|
607
|
+
delete this.#connections[id];
|
|
631
608
|
}
|
|
609
|
+
console.log(`peer ${id} left`);
|
|
610
|
+
}
|
|
632
611
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
return {
|
|
638
|
-
client,
|
|
639
|
-
request: async req => {
|
|
640
|
-
const { result, id, handler } = await api.request(client, req);
|
|
641
|
-
pubsub.unsubscribe(id, handler);
|
|
642
|
-
return result
|
|
643
|
-
},
|
|
644
|
-
send: req => api.send(client, req),
|
|
645
|
-
subscribe: api.subscribe,
|
|
646
|
-
unsubscribe: api.unsubscribe,
|
|
647
|
-
subscribers: api.subscribers,
|
|
648
|
-
publish: api.publish,
|
|
649
|
-
pubsub: api.pubsub(client),
|
|
650
|
-
uptime: () => {
|
|
651
|
-
const now = new Date().getTime();
|
|
652
|
-
return (now - startTime)
|
|
653
|
-
},
|
|
654
|
-
peernet: api.peernet(client),
|
|
655
|
-
server: api.server(client),
|
|
656
|
-
close: exit => {
|
|
657
|
-
client.onclose = message => {
|
|
658
|
-
if (exit) process.exit();
|
|
659
|
-
};
|
|
660
|
-
client.close();
|
|
661
|
-
}
|
|
612
|
+
peerJoined(id, signal) {
|
|
613
|
+
if (this.#connections[id]) {
|
|
614
|
+
if (this.#connections[id].connected) this.#connections[id].close();
|
|
615
|
+
delete this.#connections[id];
|
|
662
616
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
if (typeof process === 'object') {
|
|
669
|
-
ws = require('websocket').w3cwebsocket;
|
|
670
|
-
} else {
|
|
671
|
-
ws = WebSocket;
|
|
672
|
-
}
|
|
673
|
-
const client = new ws(url, protocols);
|
|
617
|
+
// RTCPeerConnection
|
|
618
|
+
this.#connections[id] = new Peer({initiator: true, channelName: `${this.id}:${id}`, socketClient: this.socketClient, id: this.id, to: id});
|
|
619
|
+
console.log(`peer ${id} joined`);
|
|
620
|
+
}
|
|
621
|
+
|
|
674
622
|
|
|
675
|
-
client.onmessage = onmessage;
|
|
676
|
-
client.onerror = onerror;
|
|
677
|
-
client.onopen = () => {
|
|
678
|
-
tries = 0;
|
|
679
|
-
resolve(clientConnection(client));
|
|
680
|
-
};
|
|
681
|
-
client.onclose = message => {
|
|
682
|
-
tries++;
|
|
683
|
-
if (!retry) return reject(options)
|
|
684
|
-
if (tries > 5) {
|
|
685
|
-
console.log(`${protocols} Client Closed`);
|
|
686
|
-
console.error(`could not connect to - ${url}/`);
|
|
687
|
-
return resolve(clientConnection(client))
|
|
688
|
-
}
|
|
689
|
-
if (message.code === 1006) {
|
|
690
|
-
console.log('Retrying in 10 seconds');
|
|
691
|
-
setTimeout(() => {
|
|
692
|
-
return init();
|
|
693
|
-
}, retry);
|
|
694
|
-
}
|
|
695
|
-
};
|
|
696
|
-
};
|
|
697
|
-
return init();
|
|
698
|
-
});
|
|
699
|
-
};
|
|
700
|
-
|
|
701
|
-
class HttpClientApi$1 {
|
|
702
|
-
constructor(config = {}) {
|
|
703
|
-
if (!config.apiPath) config.apiPath = 'api';
|
|
704
|
-
|
|
705
|
-
const address = `ws://${config.host}:${config.port}`;
|
|
706
|
-
|
|
707
|
-
this.apiUrl = (url) => `${address}/${url}`;
|
|
708
|
-
return (async () => {
|
|
709
|
-
this.client = await socketRequestClient(address, config.protocol, {pubsub: config.pubsub, retry: 3000});
|
|
710
|
-
return this
|
|
711
|
-
})()
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
async get(url, obj) {
|
|
715
|
-
const headers = {};
|
|
716
|
-
let body = null;
|
|
717
|
-
let method = 'GET';
|
|
718
|
-
if (obj) {
|
|
719
|
-
method = 'POST';
|
|
720
|
-
headers['Content-Type'] = 'application/json';
|
|
721
|
-
body = JSON.stringify(obj);
|
|
722
|
-
}
|
|
723
|
-
let response = await this.client.request(url, {headers, body, method});
|
|
724
|
-
const type = response.headers.get('content-type').split(';')[0];
|
|
725
|
-
if (type==='application/json') response = await response.json();
|
|
726
|
-
return response
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
async put(url, obj) {
|
|
730
|
-
const headers = {};
|
|
731
|
-
let body = {};
|
|
732
|
-
if (obj) {
|
|
733
|
-
headers['Content-Type'] = 'application/json';
|
|
734
|
-
body = JSON.stringify(obj);
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
let response = await fetch(this.apiUrl(url), {method: 'PUT', headers, body});
|
|
738
|
-
const type = response.headers.get('content-type').split(';')[0];
|
|
739
|
-
if (type==='application/json') response = await response.json();
|
|
740
|
-
return response
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
class HttpClientApi extends HttpClientApi$1 {
|
|
745
|
-
constructor(config = {}) {
|
|
746
|
-
config.apiPath = 'api';
|
|
747
|
-
return (async () => {
|
|
748
|
-
await super(config);
|
|
749
|
-
|
|
750
|
-
this.properties = {
|
|
751
|
-
wallet: 'get',
|
|
752
|
-
version: 'get',
|
|
753
|
-
addresses: 'get',
|
|
754
|
-
config: 'get',
|
|
755
|
-
account: 'get',
|
|
756
|
-
accounts: 'get',
|
|
757
|
-
transaction: 'any',
|
|
758
|
-
transactions: 'get',
|
|
759
|
-
block: 'get',
|
|
760
|
-
blocks: 'get',
|
|
761
|
-
};
|
|
762
|
-
this.keys = Object.keys(this.properties);
|
|
763
|
-
return this
|
|
764
|
-
})()
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
async request(url, data) {
|
|
768
|
-
return await this.client.request({url, params: data})
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
async ready() {
|
|
772
|
-
return await this.request('ready')
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
async version() {
|
|
776
|
-
return await this.request('version')
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
async account(index) {
|
|
780
|
-
return await this.request('account', {index})
|
|
781
|
-
}
|
|
782
623
|
}
|
|
783
624
|
|
|
784
|
-
var httpClient = (config = {}) => {
|
|
785
|
-
if (typeof config !== 'object') config = {};
|
|
786
|
-
if (!config.protocol) config.protocol = 'peernet-v0.1.0';
|
|
787
|
-
if (!config.port) config.port = 1000;
|
|
788
|
-
if (!config.host) config.host = '127.0.0.1';
|
|
789
|
-
|
|
790
|
-
return new HttpClientApi(config)
|
|
791
|
-
};
|
|
792
|
-
|
|
793
625
|
class LeofcoinStorageClient {
|
|
794
626
|
constructor(name, root) {
|
|
795
627
|
this.name = name;
|
|
@@ -835,19 +667,19 @@ message PeernetDataMessage {
|
|
|
835
667
|
}
|
|
836
668
|
`;
|
|
837
669
|
|
|
838
|
-
/**
|
|
839
|
-
* @extends {CodecFormat}
|
|
840
|
-
*/
|
|
841
|
-
class DataMessage extends codecFormatInterface {
|
|
842
|
-
get keys() {
|
|
843
|
-
return ['hash', 'store']
|
|
844
|
-
}
|
|
845
|
-
/**
|
|
846
|
-
* @param {Buffer|String|Object|DataMessage} data - The data needed to create the DataMessage
|
|
847
|
-
*/
|
|
848
|
-
constructor(data) {
|
|
849
|
-
super(data, protons__default["default"](proto$5).PeernetDataMessage, {name: 'peernet-data'});
|
|
850
|
-
}
|
|
670
|
+
/**
|
|
671
|
+
* @extends {CodecFormat}
|
|
672
|
+
*/
|
|
673
|
+
class DataMessage extends codecFormatInterface {
|
|
674
|
+
get keys() {
|
|
675
|
+
return ['hash', 'store']
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* @param {Buffer|String|Object|DataMessage} data - The data needed to create the DataMessage
|
|
679
|
+
*/
|
|
680
|
+
constructor(data) {
|
|
681
|
+
super(data, protons__default["default"](proto$5).PeernetDataMessage, {name: 'peernet-data'});
|
|
682
|
+
}
|
|
851
683
|
}
|
|
852
684
|
|
|
853
685
|
var proto$4 = `
|
|
@@ -857,15 +689,15 @@ message PsMessage {
|
|
|
857
689
|
required bytes topic = 2;
|
|
858
690
|
}`;
|
|
859
691
|
|
|
860
|
-
class PsMessage extends codecFormatInterface {
|
|
861
|
-
get keys() {
|
|
862
|
-
return ['data', 'topic']
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
constructor(buffer) {
|
|
866
|
-
const name = 'peernet-ps';
|
|
867
|
-
super(buffer, protons__default["default"](proto$4).PsMessage, {name});
|
|
868
|
-
}
|
|
692
|
+
class PsMessage extends codecFormatInterface {
|
|
693
|
+
get keys() {
|
|
694
|
+
return ['data', 'topic']
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
constructor(buffer) {
|
|
698
|
+
const name = 'peernet-ps';
|
|
699
|
+
super(buffer, protons__default["default"](proto$4).PsMessage, {name});
|
|
700
|
+
}
|
|
869
701
|
}
|
|
870
702
|
|
|
871
703
|
var proto$3 = `
|
|
@@ -875,15 +707,15 @@ message PeernetPeerMessage {
|
|
|
875
707
|
}
|
|
876
708
|
`;
|
|
877
709
|
|
|
878
|
-
class PeerMessage extends codecFormatInterface {
|
|
879
|
-
get keys() {
|
|
880
|
-
return ['id']
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
constructor(data) {
|
|
884
|
-
const name = 'peernet-peer';
|
|
885
|
-
super(data, protons__default["default"](proto$3).PeernetPeerMessage, {name});
|
|
886
|
-
}
|
|
710
|
+
class PeerMessage extends codecFormatInterface {
|
|
711
|
+
get keys() {
|
|
712
|
+
return ['id']
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
constructor(data) {
|
|
716
|
+
const name = 'peernet-peer';
|
|
717
|
+
super(data, protons__default["default"](proto$3).PeernetPeerMessage, {name});
|
|
718
|
+
}
|
|
887
719
|
}
|
|
888
720
|
|
|
889
721
|
var proto$2 = `
|
|
@@ -893,15 +725,15 @@ message PeernetPeerMessageResponse {
|
|
|
893
725
|
}
|
|
894
726
|
`;
|
|
895
727
|
|
|
896
|
-
class PeerMessageResponse extends codecFormatInterface {
|
|
897
|
-
get keys() {
|
|
898
|
-
return ['id']
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
constructor(data) {
|
|
902
|
-
const name = 'peernet-peer-response';
|
|
903
|
-
super(data, protons__default["default"](proto$2).PeernetPeerMessageResponse, {name});
|
|
904
|
-
}
|
|
728
|
+
class PeerMessageResponse extends codecFormatInterface {
|
|
729
|
+
get keys() {
|
|
730
|
+
return ['id']
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
constructor(data) {
|
|
734
|
+
const name = 'peernet-peer-response';
|
|
735
|
+
super(data, protons__default["default"](proto$2).PeernetPeerMessageResponse, {name});
|
|
736
|
+
}
|
|
905
737
|
}
|
|
906
738
|
|
|
907
739
|
var proto$1 = `
|
|
@@ -912,15 +744,15 @@ message PeernetDataMessageResponse {
|
|
|
912
744
|
}
|
|
913
745
|
`;
|
|
914
746
|
|
|
915
|
-
class DataMessageResponse extends codecFormatInterface {
|
|
916
|
-
get keys() {
|
|
917
|
-
return ['hash', 'data']
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
constructor(data) {
|
|
921
|
-
const name = 'peernet-data-response';
|
|
922
|
-
super(data, protons__default["default"](proto$1).PeernetDataMessageResponse, {name});
|
|
923
|
-
}
|
|
747
|
+
class DataMessageResponse extends codecFormatInterface {
|
|
748
|
+
get keys() {
|
|
749
|
+
return ['hash', 'data']
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
constructor(data) {
|
|
753
|
+
const name = 'peernet-data-response';
|
|
754
|
+
super(data, protons__default["default"](proto$1).PeernetDataMessageResponse, {name});
|
|
755
|
+
}
|
|
924
756
|
}
|
|
925
757
|
|
|
926
758
|
var proto = `
|
|
@@ -931,15 +763,15 @@ message ChatMessage {
|
|
|
931
763
|
repeated string files = 4;
|
|
932
764
|
}`;
|
|
933
765
|
|
|
934
|
-
class ChatMessage extends codecFormatInterface {
|
|
935
|
-
get keys() {
|
|
936
|
-
return ['author', 'value', 'timestamp', 'files']
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
constructor(buffer) {
|
|
940
|
-
const name = 'chat-message';
|
|
941
|
-
super(buffer, protons__default["default"](proto).ChatMessage, {name});
|
|
942
|
-
}
|
|
766
|
+
class ChatMessage extends codecFormatInterface {
|
|
767
|
+
get keys() {
|
|
768
|
+
return ['author', 'value', 'timestamp', 'files']
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
constructor(buffer) {
|
|
772
|
+
const name = 'chat-message';
|
|
773
|
+
super(buffer, protons__default["default"](proto).ChatMessage, {name});
|
|
774
|
+
}
|
|
943
775
|
}
|
|
944
776
|
|
|
945
777
|
const debug = (log) => {
|
|
@@ -1197,93 +1029,441 @@ class DhtEarth {
|
|
|
1197
1029
|
}
|
|
1198
1030
|
}
|
|
1199
1031
|
|
|
1032
|
+
var testnets = {
|
|
1033
|
+
'leofcoin:olivia': {
|
|
1034
|
+
messagePrefix: '\u0019Leofcoin Signed Message:',
|
|
1035
|
+
pubKeyHash: 0x73, // o
|
|
1036
|
+
scriptHash: 0x76, // p
|
|
1037
|
+
multiTxHash: 0x8b4125, // omtx
|
|
1038
|
+
payments: {
|
|
1039
|
+
version: 0,
|
|
1040
|
+
unspent: 0x1fa443d7 // ounsp
|
|
1041
|
+
},
|
|
1042
|
+
wif: 0x7D, // s
|
|
1043
|
+
multiCodec: 0x7c4,
|
|
1044
|
+
bip32: { public: 0x13BBF2D5, private: 0x13BBCBC5 }
|
|
1045
|
+
},
|
|
1046
|
+
'bitcoin:testnet': {
|
|
1047
|
+
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
|
1048
|
+
bech32: 'tb',
|
|
1049
|
+
pubKeyHash: 0x6f,
|
|
1050
|
+
scriptHash: 0xc4,
|
|
1051
|
+
wif: 0xef,
|
|
1052
|
+
bip32: {
|
|
1053
|
+
public: 0x043587cf,
|
|
1054
|
+
private: 0x04358394
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
};
|
|
1059
|
+
|
|
1060
|
+
// https://en.bitcoin.it/wiki/List_of_address_prefixes
|
|
1200
1061
|
/**
|
|
1201
|
-
*
|
|
1202
|
-
* @return {
|
|
1062
|
+
* Main network
|
|
1063
|
+
* @return {messagePrefix, pubKeyHash, scriptHash, wif, bip32}
|
|
1203
1064
|
*/
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1065
|
+
const leofcoin = {
|
|
1066
|
+
messagePrefix: '\u0019Leofcoin Signed Message:',
|
|
1067
|
+
pubKeyHash: 0x30, // L
|
|
1068
|
+
scriptHash: 0x37, // P
|
|
1069
|
+
multiTxHash: 0x3adeed, // Lmtx
|
|
1070
|
+
payments: {
|
|
1071
|
+
version: 0,
|
|
1072
|
+
unspent: 0x0d6e0327 // Lunsp
|
|
1073
|
+
},
|
|
1074
|
+
coin_type: 640,
|
|
1075
|
+
wif: 0x3F, // S
|
|
1076
|
+
multiCodec: 0x3c4,
|
|
1077
|
+
bip32: { public: 0x13BBF2D4, private: 0x13BBCBC4 },
|
|
1078
|
+
testnet: testnets['leofcoin:olivia']
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1081
|
+
const bitcoin = {
|
|
1082
|
+
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
|
1083
|
+
bech32: 'bc',
|
|
1084
|
+
pubKeyHash: 0x00,
|
|
1085
|
+
scriptHash: 0x05,
|
|
1086
|
+
wif: 0x80,
|
|
1087
|
+
coin_type: 0,
|
|
1088
|
+
bip32: {
|
|
1089
|
+
public: 0x0488b21e, private: 0x0488ade4
|
|
1090
|
+
},
|
|
1091
|
+
testnet: testnets['bitcoin:testnet']
|
|
1092
|
+
};
|
|
1093
|
+
|
|
1094
|
+
const litecoin = {
|
|
1095
|
+
messagePrefix: '\x19Litecoin Signed Message:\n',
|
|
1096
|
+
pubKeyHash: 0x30,
|
|
1097
|
+
scriptHash: 0x32,
|
|
1098
|
+
wif: 0xb0,
|
|
1099
|
+
bip32: {
|
|
1100
|
+
public: 0x019da462,
|
|
1101
|
+
private: 0x019d9cfe
|
|
1102
|
+
}
|
|
1103
|
+
};
|
|
1104
|
+
|
|
1105
|
+
const ethereum = {
|
|
1106
|
+
messagePrefix: '\x19Ethereum Signed Message:\n',
|
|
1107
|
+
pubKeyHash: 0x30,
|
|
1108
|
+
scriptHash: 0x32,
|
|
1109
|
+
bip32: {
|
|
1110
|
+
private: 0x0488ADE4, public: 0x0488B21E
|
|
1111
|
+
},
|
|
1112
|
+
coin_type: 60,
|
|
1113
|
+
wif: 0x45,//E
|
|
1114
|
+
multiCodec: 0x3c5
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* Our & supported networks
|
|
1119
|
+
* @return {leofcoin, olivia}
|
|
1120
|
+
*/
|
|
1121
|
+
var networks = {
|
|
1122
|
+
leofcoin,
|
|
1123
|
+
bitcoin,
|
|
1124
|
+
litecoin,
|
|
1125
|
+
ethereum
|
|
1126
|
+
};
|
|
1239
1127
|
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
* @param {string} message.data Peernet message
|
|
1251
|
-
* (PeernetMessage excluded) encoded as a string
|
|
1252
|
-
* @return signature
|
|
1253
|
-
*/
|
|
1254
|
-
async hashAndSignMessage(message) {
|
|
1255
|
-
const hasher = new hash(message, {name: 'peernet-message'});
|
|
1256
|
-
const identity = await walletStore.get('identity');
|
|
1128
|
+
const fromNetworkString = network => {
|
|
1129
|
+
const parts = network.split(':');
|
|
1130
|
+
network = networks[parts[0]];
|
|
1131
|
+
if (parts[1]) {
|
|
1132
|
+
if (network[parts[1]]) network = network[parts[1]];
|
|
1133
|
+
|
|
1134
|
+
network.coin_type = 1;
|
|
1135
|
+
}
|
|
1136
|
+
return network;
|
|
1137
|
+
};
|
|
1257
1138
|
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1139
|
+
const { encode: encode$1, decode: decode$1 } = bs58check__default["default"];
|
|
1140
|
+
class HDWallet {
|
|
1141
|
+
|
|
1142
|
+
get chainCodeBuffer() {
|
|
1143
|
+
return this.ifNotLocked(() => this.hdnode.chainCode)
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
get chainCode() {
|
|
1147
|
+
return this.ifNotLocked(() => this.chainCodeBuffer.toString('hex'))
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
get privateKeyBuffer() {
|
|
1151
|
+
return this.ifNotLocked(() => this.hdnode.privateKey)
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
get privateKey() {
|
|
1155
|
+
return this.ifNotLocked(() => this.privateKeyBuffer.toString('hex'))
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
get publicKeyBuffer() {
|
|
1159
|
+
return this.ifNotLocked(() => this.hdnode.publicKey)
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
get publicKey() {
|
|
1163
|
+
return this.ifNotLocked(() => this.publicKeyBuffer.toString('hex'))
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
get address() {
|
|
1167
|
+
// override testnet coin_type
|
|
1168
|
+
let coin_type = this.hdnode.network.coin_type;
|
|
1169
|
+
if (coin_type === 1) {
|
|
1170
|
+
if (this.networkName?.split(':')[0] === 'ethereum') coin_type = 60;
|
|
1171
|
+
if (this.networkName?.split(':')[0] === 'leofcoin') coin_type = 640;
|
|
1172
|
+
}
|
|
1173
|
+
if (coin_type === 60 || coin_type === 640) {
|
|
1174
|
+
let buffer = ecc__default["default"].pointFromScalar(this.hdnode.__D, false);
|
|
1175
|
+
buffer = Buffer.from(secp256k1.publicKeyConvert(buffer, false)).slice(1);
|
|
1176
|
+
let hash = createKeccakHash__default["default"]('keccak256').update(buffer).digest();
|
|
1177
|
+
return hash.slice(-20).toString('hex')
|
|
1178
|
+
}
|
|
1179
|
+
return encode$1(this.neutered.publicKeyBuffer)
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
get accountAddress() {
|
|
1183
|
+
return this.ifNotLocked(() => encode$1(this.hdnode.publicKeyBuffer))
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
get isTestnet() {
|
|
1187
|
+
if (typeof network === 'string')
|
|
1188
|
+
this.hdnode.network = fromNetworkString(network);
|
|
1189
|
+
|
|
1190
|
+
return Boolean(this.hdnode.network.coin_type === 1)
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
constructor(network, hdnode) {
|
|
1194
|
+
if (typeof network === 'string') {
|
|
1195
|
+
this.networkName = network;
|
|
1196
|
+
this.network = fromNetworkString(network);
|
|
1197
|
+
} else if (typeof network === 'object')
|
|
1198
|
+
this.network = network;
|
|
1199
|
+
|
|
1200
|
+
if (hdnode) this.defineHDNode(hdnode);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
ifNotLocked(fn, params) {
|
|
1204
|
+
if (!this.locked) return fn(params);
|
|
1205
|
+
return null
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
defineHDNode(value) {
|
|
1209
|
+
Object.defineProperty(this, 'hdnode', {
|
|
1210
|
+
configurable: false,
|
|
1211
|
+
writable: false,
|
|
1212
|
+
value: value
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
validateNetwork(network) {
|
|
1217
|
+
if (!network && !this.network) return console.error(`expected network to be defined`);
|
|
1218
|
+
if (!network && this.network) network = this.network;
|
|
1219
|
+
if (typeof network === 'string') network = fromNetworkString(network);
|
|
1220
|
+
if (typeof network !== 'object') return console.error('network not found');
|
|
1221
|
+
return network;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
async generate(network) {
|
|
1225
|
+
network = this.validateNetwork(network);
|
|
1226
|
+
const mnemonic = bip39.generateMnemonic();
|
|
1227
|
+
const seed = await bip39.mnemonicToSeed(mnemonic);
|
|
1228
|
+
this.defineHDNode(bip32__namespace.fromSeed(seed, network));
|
|
1229
|
+
return mnemonic; // userpw
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
/**
|
|
1233
|
+
* recover using mnemonic (recovery word list)
|
|
1234
|
+
*/
|
|
1235
|
+
async recover(mnemonic, network) {
|
|
1236
|
+
network = this.validateNetwork(network);
|
|
1237
|
+
const seed = await bip39.mnemonicToSeed(mnemonic);
|
|
1238
|
+
this.defineHDNode(bip32__namespace.fromSeed(seed, network));
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
load(base58, network) {
|
|
1242
|
+
network = this.validateNetwork(network);
|
|
1243
|
+
this.defineHDNode(bip32__namespace.fromBase58(base58, network));
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
save() {
|
|
1247
|
+
return this.hdnode.toBase58();
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
fromAddress(address, chainCode, network) {
|
|
1251
|
+
network = this.validateNetwork(network);
|
|
1252
|
+
// if (network.coin_type === 60) {
|
|
1253
|
+
// address = Buffer.from(address, 'hex')
|
|
1254
|
+
// } else {
|
|
1255
|
+
address = decode$1(address);
|
|
1256
|
+
// }
|
|
1257
|
+
|
|
1258
|
+
if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = address.slice(1);
|
|
1259
|
+
this.defineHDNode(bip32__namespace.fromPublicKey(address, chainCode, network));
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
fromPublicKey(hex, chainCode, network) {
|
|
1263
|
+
network = this.validateNetwork(network);
|
|
1264
|
+
if (!Buffer.isBuffer(hex)) hex = Buffer.from(hex, 'hex');
|
|
1265
|
+
if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = hex.slice(1);
|
|
1266
|
+
this.defineHDNode(bip32__namespace.fromPublicKey(hex, chainCode, network));
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1262
1269
|
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1270
|
+
const { encode, decode } = bs58check__namespace;
|
|
1271
|
+
|
|
1272
|
+
// TODO: multihash addresses
|
|
1273
|
+
class HDAccount {
|
|
1274
|
+
/**
|
|
1275
|
+
* @param {number} depth - acount depth
|
|
1276
|
+
*/
|
|
1277
|
+
constructor(node, depth = 0) {
|
|
1278
|
+
this.node = node;
|
|
1279
|
+
this.depth = depth;
|
|
1280
|
+
this._prefix = `m/44'/${node.network.coin_type}'/${depth}'/`;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* @param {number} index - address index
|
|
1285
|
+
*/
|
|
1286
|
+
internal(index = 0) {
|
|
1287
|
+
return this.node.derivePath(`${this._prefix}1/${index}`)
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
/**
|
|
1291
|
+
* @param {number} index - address index
|
|
1292
|
+
*/
|
|
1293
|
+
external(index = 0) {
|
|
1294
|
+
return this.node.derivePath(`${this._prefix}0/${index}`)
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
class MultiWallet extends HDWallet {
|
|
1299
|
+
constructor(network, hdnode) {
|
|
1300
|
+
const networkName = network;
|
|
1301
|
+
super(network, hdnode);
|
|
1302
|
+
if (typeof networkName === 'string') this.networkName = networkName;
|
|
1303
|
+
this.multiCodec = this.network.multiCodec;
|
|
1304
|
+
this.version = 0x00;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
get id() {
|
|
1308
|
+
const buffer = Buffer.concat([
|
|
1309
|
+
Buffer.from(varint__default["default"].encode(this.multiCodec)),
|
|
1310
|
+
Buffer.from(this.account(0).node.neutered.publicKey, 'hex')
|
|
1311
|
+
]);
|
|
1312
|
+
return encode(buffer)
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
get multiWIF() {
|
|
1316
|
+
return this.ifNotLocked(() => this.encode())
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
get neutered() {
|
|
1320
|
+
const neutered = this.ifNotLocked(() => new MultiWallet(this.network, this.hdnode.neutered()));
|
|
1321
|
+
if (neutered) this._neutered = neutered;
|
|
1322
|
+
return this._neutered
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
fromId(id) {
|
|
1326
|
+
let buffer = decode(id);
|
|
1327
|
+
varint__default["default"].decode(buffer);
|
|
1328
|
+
buffer = buffer.slice(varint__default["default"].decode.bytes);
|
|
1329
|
+
this.fromPublicKey(buffer, null, this.network);
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
lock(key, multiWIF) {
|
|
1333
|
+
if (!multiWIF) multiWIF = this.multiWIF;
|
|
1334
|
+
this.encrypted = AES__default["default"].encrypt(multiWIF.toString('hex'), key).toString();
|
|
1335
|
+
this.locked = true;
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
unlock(key, encrypted) {
|
|
1339
|
+
if (!encrypted) encrypted = this.encrypted;
|
|
1340
|
+
this.import(AES__default["default"].decrypt(encrypted, key).toString(ENC__default["default"]));
|
|
1341
|
+
this.locked = false;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
export() {
|
|
1345
|
+
return this.encode();
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
/**
|
|
1349
|
+
* encodes the multiWIF and loads wallet from bs58
|
|
1350
|
+
*
|
|
1351
|
+
* @param {multiWIF} multiWIF - note a multiWIF is not the same as a wif
|
|
1352
|
+
*/
|
|
1353
|
+
import(multiWIF) {
|
|
1354
|
+
const { bs58, version, multiCodec } = this.decode(multiWIF);
|
|
1355
|
+
this.network = Object.values(networks).reduce((p, c) => {
|
|
1356
|
+
if (c.multiCodec===multiCodec) return c
|
|
1357
|
+
else if (c.testnet && c.testnet.multiCodec === multiCodec) return c.testnet
|
|
1358
|
+
else return p
|
|
1359
|
+
}, networks['leofcoin']);
|
|
1360
|
+
this.load(bs58, this.network);
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
/**
|
|
1364
|
+
* @return base58Check encoded string
|
|
1365
|
+
*/
|
|
1366
|
+
encode() {
|
|
1367
|
+
const buffer = Buffer.concat([
|
|
1368
|
+
Buffer.from(varint__default["default"].encode(this.version)),
|
|
1369
|
+
Buffer.from(varint__default["default"].encode(this.multiCodec)),
|
|
1370
|
+
decode(this.save())
|
|
1371
|
+
]);
|
|
1372
|
+
return encode(buffer);
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
decode(bs58) {
|
|
1376
|
+
let buffer = decode(bs58);
|
|
1377
|
+
const version = varint__default["default"].decode(buffer);
|
|
1378
|
+
buffer = buffer.slice(varint__default["default"].decode.bytes);
|
|
1379
|
+
const multiCodec = varint__default["default"].decode(buffer);
|
|
1380
|
+
buffer = buffer.slice(varint__default["default"].decode.bytes);
|
|
1381
|
+
bs58 = encode(buffer);
|
|
1382
|
+
if (version !== this.version) throw TypeError('Invalid version');
|
|
1383
|
+
if (this.multiCodec !== multiCodec) throw TypeError('Invalid multiCodec');
|
|
1384
|
+
return { version, multiCodec, bs58 };
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
sign(hash) {
|
|
1388
|
+
return new MultiSignature__default["default"](this.version, this.network.multiCodec)
|
|
1389
|
+
.sign(hash, this.privateKeyBuffer);
|
|
1390
|
+
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
verify(multiSignature, hash) {
|
|
1394
|
+
return new MultiSignature__default["default"](this.version, this.network.multiCodec)
|
|
1395
|
+
.verify(multiSignature, hash, this.publicKeyBuffer)
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
/**
|
|
1399
|
+
* @param {number} account - account to return chain for
|
|
1400
|
+
* @return { internal(addressIndex), external(addressIndex) }
|
|
1401
|
+
*/
|
|
1402
|
+
account(index) {
|
|
1403
|
+
return new HDAccount(new MultiWallet(this.network, this.hdnode), index);
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
/**
|
|
1407
|
+
* m / purpose' / coin_type' / account' / change / aadress_index
|
|
1408
|
+
*
|
|
1409
|
+
* see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
|
|
1410
|
+
*/
|
|
1411
|
+
derivePath(path) {
|
|
1412
|
+
return new MultiWallet(this.network, this.hdnode.derivePath(path))
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
derive(index) {
|
|
1416
|
+
return new MultiWallet(this.network, this.hdnode.derive(index));
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1284
1419
|
|
|
1285
|
-
|
|
1286
|
-
|
|
1420
|
+
class MessageHandler {
|
|
1421
|
+
constructor(network) {
|
|
1422
|
+
this.network = network;
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* hash and sign message
|
|
1426
|
+
*
|
|
1427
|
+
* @param {object} message
|
|
1428
|
+
* @param {Buffer} message.from peer id
|
|
1429
|
+
* @param {Buffer} message.to peer id
|
|
1430
|
+
* @param {string} message.data Peernet message
|
|
1431
|
+
* (PeernetMessage excluded) encoded as a string
|
|
1432
|
+
* @return signature
|
|
1433
|
+
*/
|
|
1434
|
+
async hashAndSignMessage(message) {
|
|
1435
|
+
const hasher = new hash(message, {name: 'peernet-message'});
|
|
1436
|
+
const identity = await walletStore.get('identity');
|
|
1437
|
+
|
|
1438
|
+
const wallet = new MultiWallet(this.network);
|
|
1439
|
+
wallet.import(identity.multiWIF);
|
|
1440
|
+
return wallet.sign(hasher.hash.slice(0, 32))
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
/**
|
|
1444
|
+
* @param {String} from - peer id
|
|
1445
|
+
* @param {String} to - peer id
|
|
1446
|
+
* @param {String|PeernetMessage} data - data encoded message string
|
|
1447
|
+
* or the messageNode itself
|
|
1448
|
+
*/
|
|
1449
|
+
async prepareMessage(from, to, data, id) {
|
|
1450
|
+
if (!Buffer.isBuffer(from)) from = new Buffer.from(from);
|
|
1451
|
+
if (!Buffer.isBuffer(to)) to = new Buffer.from(to);
|
|
1452
|
+
if (data.encoded) data = data.encoded;
|
|
1453
|
+
|
|
1454
|
+
const message = {
|
|
1455
|
+
from,
|
|
1456
|
+
to,
|
|
1457
|
+
data,
|
|
1458
|
+
};
|
|
1459
|
+
const signature = await this.hashAndSignMessage(message);
|
|
1460
|
+
const node = new peernetMessage({
|
|
1461
|
+
...message,
|
|
1462
|
+
signature,
|
|
1463
|
+
});
|
|
1464
|
+
|
|
1465
|
+
return node
|
|
1466
|
+
}
|
|
1287
1467
|
}
|
|
1288
1468
|
|
|
1289
1469
|
const encapsulatedError = () => {
|
|
@@ -1300,7 +1480,7 @@ const nothingFoundError = (hash) => {
|
|
|
1300
1480
|
};
|
|
1301
1481
|
|
|
1302
1482
|
globalThis.leofcoin = globalThis.leofcoin || {};
|
|
1303
|
-
globalThis.globalSub = globalThis.globalSub || new
|
|
1483
|
+
globalThis.globalSub = globalThis.globalSub || new PubSub({verbose: true});
|
|
1304
1484
|
|
|
1305
1485
|
/**
|
|
1306
1486
|
* @access public
|
|
@@ -1445,12 +1625,14 @@ class Peernet {
|
|
|
1445
1625
|
this.hasDaemon = daemon;
|
|
1446
1626
|
|
|
1447
1627
|
if (this.hasDaemon) {
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1628
|
+
const httpClient = await Promise.resolve().then(function () { return require('./client-bd0caeb7.js'); });
|
|
1629
|
+
globalThis.peernet.client = await httpClient.default({
|
|
1630
|
+
protocol: 'peernet-v0.1.0', host: '127.0.0.1', port: options.port
|
|
1631
|
+
});
|
|
1632
|
+
} else {
|
|
1633
|
+
const http = await Promise.resolve().then(function () { return require('./http-2b0735ef.js'); });
|
|
1634
|
+
if (environment !== 'browser') http.default(options);
|
|
1635
|
+
}
|
|
1454
1636
|
|
|
1455
1637
|
for (const store of this.defaultStores) {
|
|
1456
1638
|
await this.addStore(store, options.storePrefix, options.root);
|
|
@@ -1462,7 +1644,7 @@ class Peernet {
|
|
|
1462
1644
|
} catch (e) {
|
|
1463
1645
|
if (e.code === 'ERR_NOT_FOUND') {
|
|
1464
1646
|
const wallet = {};
|
|
1465
|
-
const {identity, accounts, config} = await
|
|
1647
|
+
const {identity, accounts, config} = await generateAccount__default["default"](this.network);
|
|
1466
1648
|
wallet.identity = identity;
|
|
1467
1649
|
wallet.accounts = accounts;
|
|
1468
1650
|
wallet.version = 1;
|
|
@@ -1476,42 +1658,41 @@ class Peernet {
|
|
|
1476
1658
|
}
|
|
1477
1659
|
}
|
|
1478
1660
|
this._peerHandler = new PeerDiscovery(this.id);
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
else this.peerMap.set(id, peerIds);
|
|
1512
|
-
});
|
|
1661
|
+
this.peerId = this.id;
|
|
1662
|
+
|
|
1663
|
+
// pubsub.subscribe('peer:discovered', async (peer) => {
|
|
1664
|
+
// peer.on('peernet.data', async (message) => {
|
|
1665
|
+
// const id = message.id;
|
|
1666
|
+
// message = new PeernetMessage(Buffer.from(message.data.data));
|
|
1667
|
+
// const proto = protoFor(message.decoded.data);
|
|
1668
|
+
// await this._protoHandler({id, proto}, peer);
|
|
1669
|
+
// });
|
|
1670
|
+
// await this._peerHandler.discover(peer);
|
|
1671
|
+
// const fulldId = this._getPeerId(peer.id);
|
|
1672
|
+
// if (fulldId && this._discovered.indexOf(peer.id) === -1) {
|
|
1673
|
+
// this._discovered.push(peer.id);
|
|
1674
|
+
// pubsub.publish('peer:connected', peer);
|
|
1675
|
+
// }
|
|
1676
|
+
// });
|
|
1677
|
+
// pubsub.subscribe('peer:disconnected', async (peer) => {
|
|
1678
|
+
// let index = this._discovered.indexOf(peer.id)
|
|
1679
|
+
// if (index !== -1) this._discovered.splice(index, 1)
|
|
1680
|
+
// const id = this._getPeerId(peer.id)
|
|
1681
|
+
// let peerIds = this.peerMap.get(id)
|
|
1682
|
+
//
|
|
1683
|
+
// if (peerIds) {
|
|
1684
|
+
// index = peerIds.indexOf(peer.id)
|
|
1685
|
+
// if (index !== -1) peerIds.splice(index, 1)
|
|
1686
|
+
// } else {
|
|
1687
|
+
// peerIds = []
|
|
1688
|
+
// }
|
|
1689
|
+
//
|
|
1690
|
+
// if (peerIds.length === 0) this.peerMap.delete(id)
|
|
1691
|
+
// else this.peerMap.set(id, peerIds)
|
|
1692
|
+
// })
|
|
1513
1693
|
pubsub.subscribe('peer:connected', async (peer) => {
|
|
1514
|
-
console.log(
|
|
1694
|
+
console.log(peer);
|
|
1695
|
+
// console.log({connected: peer.id, as: this._getPeerId(peer.id) });
|
|
1515
1696
|
// peer.on('peernet.data', async (message) => {
|
|
1516
1697
|
// const id = message.id
|
|
1517
1698
|
// message = new PeernetMessage(Buffer.from(message.data.data))
|
|
@@ -1520,11 +1701,27 @@ class Peernet {
|
|
|
1520
1701
|
// })
|
|
1521
1702
|
});
|
|
1522
1703
|
|
|
1704
|
+
pubsub.subscribe('peer:data', async message => {
|
|
1705
|
+
console.log({message});
|
|
1706
|
+
if (!message.data) return
|
|
1707
|
+
const {id, data} = JSON.parse(new TextDecoder().decode(message.data));
|
|
1708
|
+
const uint8Array = new Uint8Array(Object.keys(data).length);
|
|
1709
|
+
for (var i = 0; i < Object.keys(data).length; i++) {
|
|
1710
|
+
uint8Array[i] = data[i];
|
|
1711
|
+
}
|
|
1712
|
+
message = new peernetMessage(uint8Array);
|
|
1713
|
+
const proto = protoFor(message.decoded.data);
|
|
1714
|
+
|
|
1715
|
+
console.log(message.decoded);
|
|
1716
|
+
const from = new TextDecoder().decode(message.decoded.from);
|
|
1717
|
+
this._protoHandler({id, proto}, this.client.connections[from], from);
|
|
1718
|
+
});
|
|
1719
|
+
|
|
1523
1720
|
/**
|
|
1524
1721
|
* @access public
|
|
1525
1722
|
* @type {PeernetClient}
|
|
1526
1723
|
*/
|
|
1527
|
-
this.client = new
|
|
1724
|
+
this.client = new Client(this.id);
|
|
1528
1725
|
if (globalThis.onbeforeunload) {
|
|
1529
1726
|
globalThis.addEventListener('beforeunload', async () => this.client.close());
|
|
1530
1727
|
}
|
|
@@ -1549,55 +1746,56 @@ class Peernet {
|
|
|
1549
1746
|
* @param {Buffer} message - peernet message
|
|
1550
1747
|
* @param {PeernetPeer} peer - peernet peer
|
|
1551
1748
|
*/
|
|
1552
|
-
async _protoHandler(message, peer) {
|
|
1749
|
+
async _protoHandler(message, peer, from) {
|
|
1553
1750
|
const {id, proto} = message;
|
|
1751
|
+
console.log(message);
|
|
1554
1752
|
this.bw.down += proto.encoded.length;
|
|
1555
|
-
if (proto.name === 'peernet-peer') {
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
} else if (proto.name === 'peernet-peer-response') {
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
} else {
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1753
|
+
// if (proto.name === 'peernet-peer') {
|
|
1754
|
+
// const from = proto.decoded.id
|
|
1755
|
+
// if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id])
|
|
1756
|
+
// else {
|
|
1757
|
+
// const connections = this.peerMap.get(from)
|
|
1758
|
+
// if (connections.indexOf(peer.id) === -1) {
|
|
1759
|
+
// connections.push(peer.id)
|
|
1760
|
+
// this.peerMap.set(from, connections)
|
|
1761
|
+
// }
|
|
1762
|
+
// }
|
|
1763
|
+
// const data = new PeerMessageResponse({id: this.id})
|
|
1764
|
+
// const node = await this.prepareMessage(from, data.encoded)
|
|
1765
|
+
//
|
|
1766
|
+
// peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})))
|
|
1767
|
+
// this.bw.up += node.encoded.length
|
|
1768
|
+
// } else if (proto.name === 'peernet-peer-response') {
|
|
1769
|
+
// const from = proto.decoded.id
|
|
1770
|
+
// if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id])
|
|
1771
|
+
// else {
|
|
1772
|
+
// const connections = this.peerMap.get(from)
|
|
1773
|
+
// if (connections.indexOf(peer.id) === -1) {
|
|
1774
|
+
// connections.push(peer.id)
|
|
1775
|
+
// this.peerMap.set(from, connections)
|
|
1776
|
+
// }
|
|
1777
|
+
// }
|
|
1778
|
+
// } else {
|
|
1779
|
+
// let from = this._getPeerId(peer.id)
|
|
1780
|
+
// if (!from) {
|
|
1781
|
+
// const data = new PeerMessage({id: this.id})
|
|
1782
|
+
// const node = await this.prepareMessage(peer.id, data.encoded)
|
|
1783
|
+
// this.bw.up += node.encoded.length
|
|
1784
|
+
// let response = await peer.request(node.encoded)
|
|
1785
|
+
// response = protoFor(response)
|
|
1786
|
+
//
|
|
1787
|
+
// response = new PeerMessageResponse(response.decoded.data)
|
|
1788
|
+
//
|
|
1789
|
+
// from = response.decoded.id
|
|
1790
|
+
// if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id])
|
|
1791
|
+
// else {
|
|
1792
|
+
// const connections = this.peerMap.get(from)
|
|
1793
|
+
// if (connections.indexOf(peer.id) === -1) {
|
|
1794
|
+
// connections.push(peer.id)
|
|
1795
|
+
// this.peerMap.set(from, connections)
|
|
1796
|
+
// }
|
|
1797
|
+
// }
|
|
1798
|
+
// }
|
|
1601
1799
|
if (proto.name === 'peernet-dht') {
|
|
1602
1800
|
let { hash, store } = proto.decoded;
|
|
1603
1801
|
let has;
|
|
@@ -1612,7 +1810,7 @@ class Peernet {
|
|
|
1612
1810
|
const data = new dhtResponse({hash, has});
|
|
1613
1811
|
const node = await this.prepareMessage(from, data.encoded);
|
|
1614
1812
|
|
|
1615
|
-
peer.
|
|
1813
|
+
peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
|
|
1616
1814
|
this.bw.up += node.encoded.length;
|
|
1617
1815
|
} else if (proto.name === 'peernet-data') {
|
|
1618
1816
|
let { hash, store } = proto.decoded;
|
|
@@ -1629,7 +1827,7 @@ class Peernet {
|
|
|
1629
1827
|
data = new DataMessageResponse({hash, data: data.decoded ? Buffer.from(JSON.stringify(data)) : Buffer.from(data)});
|
|
1630
1828
|
|
|
1631
1829
|
const node = await this.prepareMessage(from, data.encoded);
|
|
1632
|
-
peer.
|
|
1830
|
+
peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
|
|
1633
1831
|
this.bw.up += node.encoded.length;
|
|
1634
1832
|
}
|
|
1635
1833
|
}
|
|
@@ -1645,7 +1843,7 @@ class Peernet {
|
|
|
1645
1843
|
const data = new PeerMessage({id: this.id});
|
|
1646
1844
|
const node = await this.prepareMessage(from, data.encoded);
|
|
1647
1845
|
|
|
1648
|
-
peer.
|
|
1846
|
+
peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
|
|
1649
1847
|
this.bw.up += node.encoded.length;
|
|
1650
1848
|
} else if (proto.name === 'peernet-request') {
|
|
1651
1849
|
// TODO: make dynamic
|
|
@@ -1654,14 +1852,14 @@ class Peernet {
|
|
|
1654
1852
|
if (method) {
|
|
1655
1853
|
const data = await method();
|
|
1656
1854
|
const node = await this.prepareMessage(from, data.encoded);
|
|
1657
|
-
peer.
|
|
1855
|
+
peer.send(new TextEncoder().encode(JSON.stringify({id, data: node.encoded})));
|
|
1658
1856
|
this.bw.up += node.encoded.length;
|
|
1659
1857
|
}
|
|
1660
1858
|
} else if (proto.name === 'peernet-ps' &&
|
|
1661
1859
|
this._getPeerId(peer.id) !== this.id.toString()) {
|
|
1662
1860
|
globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
|
|
1663
1861
|
}
|
|
1664
|
-
}
|
|
1862
|
+
// }
|
|
1665
1863
|
}
|
|
1666
1864
|
|
|
1667
1865
|
/**
|
|
@@ -1926,7 +2124,7 @@ class Peernet {
|
|
|
1926
2124
|
if (peer.connection._connected) {
|
|
1927
2125
|
if (peer.id.toString() !== this.peerId.toString()) {
|
|
1928
2126
|
const node = await this.prepareMessage(peer.id, data.encoded);
|
|
1929
|
-
peer.
|
|
2127
|
+
peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
|
|
1930
2128
|
}
|
|
1931
2129
|
} else {
|
|
1932
2130
|
this.removePeer(peer);
|