@leofcoin/peernet 0.10.6 → 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.
Files changed (75) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +49 -49
  3. package/dist/browser/peernet.js +101814 -92947
  4. package/dist/commonjs/client-bd0caeb7.js +324 -0
  5. package/dist/commonjs/{codec-6367213c.js → codec-4a768e5e.js} +99 -89
  6. package/dist/commonjs/codec-format-interface.js +41 -24
  7. package/dist/commonjs/codec.js +3 -3
  8. package/dist/commonjs/dht-response.js +3 -3
  9. package/dist/commonjs/dht.js +23 -23
  10. package/dist/commonjs/hash.js +17 -7
  11. package/dist/commonjs/{http-42a6e555.js → http-2b0735ef.js} +19 -15
  12. package/dist/commonjs/peernet-message.js +12 -12
  13. package/dist/commonjs/peernet.js +1164 -966
  14. package/dist/commonjs/request.js +12 -12
  15. package/dist/commonjs/response.js +12 -12
  16. package/dist/module/peernet.js +1325 -1120
  17. package/index.html +4 -6
  18. package/package.json +31 -7
  19. package/rollup.config.js +33 -5
  20. package/rollup0.config.js +7 -0
  21. package/src/codec/codec-format-interface.js +40 -23
  22. package/src/codec/codec.js +21 -11
  23. package/src/codec/codecs.js +79 -79
  24. package/src/handlers/message.js +52 -52
  25. package/src/hash/hash.js +16 -6
  26. package/src/http/client/http-client.js +1 -1
  27. package/src/messages/chat-message.js +14 -14
  28. package/src/messages/data-response.js +14 -14
  29. package/src/messages/data.js +18 -18
  30. package/src/messages/dht-response.js +0 -1
  31. package/src/messages/dht.js +25 -25
  32. package/src/messages/peer-response.js +14 -14
  33. package/src/messages/peer.js +14 -14
  34. package/src/messages/peernet-message.js +14 -14
  35. package/src/messages/ps.js +14 -14
  36. package/src/messages/request.js +14 -14
  37. package/src/messages/response.js +14 -14
  38. package/src/peernet.js +31 -116
  39. package/test/codec.js +3 -2
  40. package/test/messages.js +7 -4
  41. package/test.js +11 -4
  42. package/webpack.config.js +35 -0
  43. package/coverage/lcov-report/base.css +0 -224
  44. package/coverage/lcov-report/block-navigation.js +0 -79
  45. package/coverage/lcov-report/codec-format-interface.js.html +0 -533
  46. package/coverage/lcov-report/codec.js.html +0 -677
  47. package/coverage/lcov-report/dht-response.js.html +0 -188
  48. package/coverage/lcov-report/favicon.png +0 -0
  49. package/coverage/lcov-report/hash.js.html +0 -551
  50. package/coverage/lcov-report/index.html +0 -156
  51. package/coverage/lcov-report/prettify.css +0 -1
  52. package/coverage/lcov-report/prettify.js +0 -2
  53. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  54. package/coverage/lcov-report/sorter.js +0 -170
  55. package/coverage/lcov.info +0 -459
  56. package/debug.log +0 -3
  57. package/dist/browser/peernet.js.tmp-browserify-14074318104595318069 +0 -0
  58. package/dist/browser/peernet.js.tmp-browserify-45407634493269122267 +0 -0
  59. package/dist/browser/peernet.js.tmp-browserify-53722389064799025427 +0 -0
  60. package/dist/browser/peernet.js.tmp-browserify-96323030449218949300 +0 -0
  61. package/dist/codec/codec-format-interface.js +0 -433
  62. package/dist/codec/codec.js +0 -199
  63. package/dist/commonjs/codec-73adfc0f.js +0 -205
  64. package/dist/commonjs/http-2c603501.js +0 -324
  65. package/dist/commonjs/http-43f4fafe.js +0 -324
  66. package/dist/commonjs/http-a94c5a81.js +0 -324
  67. package/dist/commonjs/peernet-message-b6925673.js +0 -32
  68. package/dist/hash/hash.js +0 -340
  69. package/dist/messages/dht-response.js +0 -454
  70. package/dist/messages/dht.js +0 -453
  71. package/dist/messages/peernet.js +0 -456
  72. package/dist/module/http-273664bd.js +0 -317
  73. package/dist/module/http-8fe3c0d7.js +0 -317
  74. package/dist/module/http-c780c991.js +0 -317
  75. package/dist/module/http-f13e0d77.js +0 -317
@@ -1,774 +1,584 @@
1
- import PubSub from '@vandeurenglenn/little-pubsub';
2
- import sha256 from 'crypto-js/sha256';
3
- import P2P from 'p2pt';
4
- import LeofcoinStorage$1 from '@leofcoin/storage';
5
- import { server } from 'websocket';
6
- import { createServer } from 'http';
7
- import Koa from 'koa';
1
+ import LeofcoinStorage from '@leofcoin/storage';
8
2
  import protons from 'protons';
9
- import bs32 from 'bs32';
10
- import bs58 from 'bs58';
3
+ import bs32 from '@vandeurenglenn/base32';
4
+ import bs58 from '@vandeurenglenn/base58';
11
5
  import isHex from 'is-hex';
12
6
  import varint from 'varint';
13
7
  import createKeccakHash from 'keccak';
14
- import fetch$1 from 'node-fetch';
15
- import MultiWallet from '@leofcoin/multi-wallet';
16
-
17
- class PeernetPeer {
18
- constructor(id, connection) {
19
- this._events = {};
20
- this.bw = {
21
- up: 0,
22
- down: 0,
23
- };
24
- this.id = id;
25
- this.connection = connection;
26
-
27
- this.connection.on('data', (message) => {
28
- this.bw.down += message.length;
29
- pubsub.publish('peernet.data', JSON.parse(message.toString()));
30
- });
31
- }
32
-
33
- request(data) {
34
- return new Promise((resolve, reject) => {
35
- const id = Math.random().toString(36).slice(-12);
36
- data = Buffer.from(JSON.stringify({id, data}));
37
- const _onData = (message) => {
38
- if (message.id !== id) return
39
-
40
- resolve(message.data);
41
- };
42
-
43
- pubsub.subscribe('peernet.data', _onData);
44
-
45
- // cleanup subscriptions
46
- setTimeout(() => {
47
- pubsub.unsubscribe('peernet.data', _onData);
48
- }, 5000);
49
-
50
- this.write(data);
51
- });
52
- }
53
-
54
- write(data) {
55
- if (!Buffer.isBuffer(data)) data = Buffer.from(data);
56
-
57
- this.bw.up += data.length;
58
- this.connection.write(data);
59
- }
60
-
61
- on(event = 'peernet.data', cb) {
62
- this._events[event] = cb;
63
- pubsub.subscribe(event, cb);
64
- // this.connection.on(event, cb)
65
- }
66
-
67
- removeListener(event = 'data', cb) {
68
- delete this._events[event];
69
- pubsub.unsubscribe(event, cb);
8
+ import fetch from 'node-fetch';
9
+ import generateAccount from '@leofcoin/generate-account';
10
+ import * as bs58check from 'bs58check';
11
+ import bs58check__default from 'bs58check';
12
+ import { generateMnemonic, mnemonicToSeed } from 'bip39';
13
+ import * as bip32 from 'bip32';
14
+ import { publicKeyConvert } from 'secp256k1';
15
+ import ecc from 'tiny-secp256k1';
16
+ import MultiSignature from 'multi-signature';
17
+ import AES from 'crypto-js/aes.js';
18
+ import 'crypto-js/sha512.js';
19
+ import ENC from 'crypto-js/enc-utf8.js';
20
+
21
+ /* socket-request-client version 1.6.1 */
22
+
23
+ class LittlePubSub {
24
+ constructor(verbose = true) {
25
+ this.subscribers = {};
26
+ this.verbose = verbose;
27
+ }
28
+ subscribe(event, handler, context) {
29
+ if (typeof context === 'undefined') {
30
+ context = handler;
31
+ }
32
+ this.subscribers[event] = this.subscribers[event] || { handlers: [], value: null};
33
+ this.subscribers[event].handlers.push(handler.bind(context));
70
34
  }
71
-
72
- close() {
73
- for (const event of Object.keys(this._events)) {
74
- pubsub.unsubscribe(event, this._events[event]);
35
+ unsubscribe(event, handler, context) {
36
+ if (typeof context === 'undefined') {
37
+ context = handler;
75
38
  }
76
- this._events = [];
77
-
78
- for (const event of this.connection._events.data) {
79
- this.connection.removeListener('data', event);
39
+ if (this.subscribers[event]) {
40
+ const index = this.subscribers[event].handlers.indexOf(handler.bind(context));
41
+ this.subscribers[event].handlers.splice(index);
42
+ if (this.subscribers[event].handlers.length === 0) delete this.subscribers[event];
80
43
  }
81
- this.connection.destroy();
82
44
  }
83
- }
84
-
85
- /**
86
- * Array of peers
87
- * @type {Array}
88
- * @property {PeernetPeer} peer Instance of Peer
89
- */
90
- globalThis.connections = new Map();
91
- globalThis.recentConnections = new Map();
92
- globalThis.pubsub = globalThis.pubsub || new PubSub({verbose: false});
93
-
94
- class PeernetClient {
95
- constructor(options = {}) {
96
- if (!options.id) options.id = Buffer.from('00000000000000000000000000000000');
97
- if (!options.networkVersion) options.networkVersion = 'v0.1.0';
98
- if (!options.networkName) options.networkName = 'peernet';
99
- this.id = options.id;
100
-
101
- this.topic = Buffer.from(sha256(`${options.networkName}-${options.networkVersion}`).toString());
102
-
103
- const trackers = [
104
- 'wss://star.leofcoin.org',
105
- 'wss://tracker.openwebtorrent.com',
106
- // 'wss://tracker.sloppyta.co:443/announce',
107
- ];
108
- this.p2p = new P2P(trackers, this.topic.slice(0, 20));
109
- this.p2p.on('peerconnect', (peer) => {
110
- peer = new PeernetPeer(peer.id, peer);
111
- connections.set(peer.id, peer);
112
- pubsub.publish('peer:discovered', peer);
113
- });
114
-
115
- this.p2p.on('peerclose', (peer) => {
116
- // TODO: close peernetPeer
117
- const peernetPeer = connections.get(peer.id);
118
- if (peernetPeer) {
119
- peernetPeer.close();
45
+ publish(event, change) {
46
+ if (this.subscribers[event]) {
47
+ if (this.verbose || this.subscribers[event].value !== change) {
48
+ this.subscribers[event].value = change;
49
+ this.subscribers[event].handlers.forEach(handler => {
50
+ handler(change, this.subscribers[event].value);
51
+ });
120
52
  }
121
- connections.delete(peer.id);
122
- pubsub.publish('peer:disconnected', peer);
123
- });
124
-
125
- this.p2p.start();
126
-
127
- if (globalThis.process) {
128
- process.on('SIGINT', async () => {
129
- console.log('Caught interrupt signal');
130
- this.close();
131
- setTimeout(async () => {
132
- process.exit();
133
- }, 100);
134
- });
135
- } else {
136
- globalThis.onbeforeunload = () => {
137
- this.close();
138
- };
139
53
  }
140
- //
141
- // this.sw.on('close', () => {
142
- // })
143
- }
144
-
145
- close() {
146
- return this.p2p.destroy()
147
- }
148
-
149
- _peers() {
150
- return this.p2p.getPeers()
151
54
  }
152
55
  }
153
56
 
154
- var version = "0.10.5";
155
-
156
- var api$1 = {
157
- version: ({send}) => send({client: '@peernet/api/http', version}),
158
- ready: ({send}) => {
159
- if (globalThis.states.ready) send(true);
160
- else pubsub.subscribe('ready', () => send(true));
161
- },
162
- storage: async (params, {send, error}) => {
163
- console.log(params);
164
- const {name, root, key, value, method} = params;
165
- try {
166
- if (name && root) {
167
- globalThis[name] = globalThis[name] || await new LeofcoinStorage(name, root);
168
- } else {
169
- return error('Expected name & root')
170
- }
171
- if (method === 'put') {
172
- await globalThis[name].put(key, value);
173
- return send('ok')
174
- }
175
- if (method === 'remove') {
176
- await globalThis[name].remove(key, value);
177
- return send('ok')
178
- }
179
- value = await globalThis[name].get(key);
180
- return send(value)
181
- } catch (e) {
182
- return error(e)
183
- }
184
- },
185
- getConfig: async (params, {send, error}) => {
186
- try {
187
- const config = await api.getConfig(params);
188
- send(config);
189
- } catch (e) {
190
- error(e);
191
- }
192
- },
193
- setMinerConfig: async (params, {send, error}) => {
194
- try {
195
- await api.setMinerConfig(params);
196
- send('ok');
197
- } catch (e) {
198
- error(e);
57
+ var clientApi = _pubsub => {
58
+ const subscribe = (topic, cb) => {
59
+ _pubsub.subscribe(topic, cb);
60
+ };
61
+ const unsubscribe = (topic, cb) => {
62
+ _pubsub.unsubscribe(topic, cb);
63
+ };
64
+ const publish = (topic, value) => {
65
+ _pubsub.publish(topic, value);
66
+ };
67
+ const _connectionState = (state) => {
68
+ switch (state) {
69
+ case 0:
70
+ return 'connecting'
71
+ case 1:
72
+ return 'open'
73
+ case 2:
74
+ return 'closing'
75
+ case 3:
76
+ return 'closed'
199
77
  }
200
- },
201
- getMinerConfig: async ({send, error}) => {
202
- try {
203
- const config = await api.getMinerConfig();
204
- send(config);
205
- } catch (e) {
206
- error(e);
78
+ };
79
+ const request = (client, request) => {
80
+ return new Promise((resolve, reject) => {
81
+ const state = _connectionState(client.readyState);
82
+ if (state !== 'open') return reject(`coudn't send request to ${client.id}, no open connection found.`)
83
+ request.id = Math.random().toString(36).slice(-12);
84
+ const handler = result => {
85
+ if (result && result.error) return reject(result.error)
86
+ resolve({result, id: request.id, handler});
87
+ unsubscribe(request.id, handler);
88
+ };
89
+ subscribe(request.id, handler);
90
+ send(client, request);
91
+ });
92
+ };
93
+ const send = async (client, request) => {
94
+ return client.send(JSON.stringify(request))
95
+ };
96
+ const pubsub = client => {
97
+ return {
98
+ publish: (topic = 'pubsub', value) => {
99
+ return send(client, {url: 'pubsub', params: { topic, value }})
100
+ },
101
+ subscribe: (topic = 'pubsub', cb) => {
102
+ subscribe(topic, cb);
103
+ return send(client, {url: 'pubsub', params: { topic, subscribe: true }})
104
+ },
105
+ unsubscribe: (topic = 'pubsub', cb) => {
106
+ unsubscribe(topic, cb);
107
+ return send(client, {url: 'pubsub', params: { topic, unsubscribe: true }})
108
+ },
109
+ subscribers: _pubsub.subscribers
207
110
  }
208
- },
209
- wallet: async ({send}) => {
210
- const wallet = await walletStore.get();
211
- send(wallet);
212
- },
213
- addresses: async ({send, error}) => {
214
- try {
215
- const adresses = await api.addresses();
216
- send(adresses);
217
- } catch (e) {
218
- error(e);
111
+ };
112
+ const server = (client) => {
113
+ return {
114
+ uptime: async () => {
115
+ try {
116
+ const { result, id, handler } = await request(client, {url: 'uptime'});
117
+ unsubscribe(id, handler);
118
+ return result
119
+ } catch (e) {
120
+ throw e
121
+ }
122
+ },
123
+ ping: async () => {
124
+ try {
125
+ const now = new Date().getTime();
126
+ const { result, id, handler } = await request(client, {url: 'ping'});
127
+ unsubscribe(id, handler);
128
+ return (Number(result) - now)
129
+ } catch (e) {
130
+ throw e
131
+ }
132
+ }
219
133
  }
220
- },
221
- accountNames: async (params, {send, error}) => {
222
- try {
223
- const adresses = await api.accountNames(params.index);
224
- send(adresses);
225
- } catch (e) {
226
- error(e);
134
+ };
135
+ const peernet = (client) => {
136
+ return {
137
+ join: async (params) => {
138
+ try {
139
+ params.join = true;
140
+ const requested = { url: 'peernet', params };
141
+ const { result, id, handler } = await request(client, requested);
142
+ unsubscribe(id, handler);
143
+ return result
144
+ } catch (e) {
145
+ throw e
146
+ }
147
+ },
148
+ leave: async (params) => {
149
+ try {
150
+ params.join = false;
151
+ const requested = { url: 'peernet', params };
152
+ const { result, id, handler } = await request(client, requested);
153
+ unsubscribe(id, handler);
154
+ return result
155
+ } catch (e) {
156
+ throw e
157
+ }
158
+ }
227
159
  }
228
- },
229
- accounts: async ({send}) => {
230
- const accounts = await accountStore.get();
231
- send(accounts);
232
- },
233
- account: async (params, {send}) => {
234
- const account = await accountStore.get(params);
235
- send(account);
236
- },
237
- balance: async (params, {send, error}) => {
238
- console.log('balance');
239
- try {
240
- console.log(await api.getBalanceForAddress(params.address));
241
- const value = await api.getBalanceForAddress(params.address);
242
- send(value);
243
- } catch (e) {
244
- console.log(e);
245
- error(e);
160
+ };
161
+ return { send, request, pubsub, server, subscribe, unsubscribe, publish, peernet }
162
+ };
163
+
164
+ if (!globalThis.PubSub) globalThis.PubSub = LittlePubSub;
165
+ if (!globalThis.pubsub) globalThis.pubsub = new LittlePubSub({verbose: false});
166
+ const socketRequestClient = (url, protocols = 'echo-protocol', options = { retry: false }) => {
167
+ const { retry } = options;
168
+ const api = clientApi(pubsub);
169
+ let tries = 0;
170
+ const onerror = error => {
171
+ if (pubsub.subscribers['error']) {
172
+ pubsub.publish('error', error);
173
+ } else {
174
+ console.error(error);
246
175
  }
247
- },
248
- balanceAfter: async (params, {send, error}) => {
249
- try {
250
- const value = await api.getBalanceForAddressAfter(params.address, params.index);
251
- send(value);
252
- } catch (e) {
253
- error(e);
176
+ };
177
+ const onmessage = message => {
178
+ const {value, url, status, id} = JSON.parse(message.data.toString());
179
+ const publisher = id ? id : url;
180
+ if (status === 200) {
181
+ pubsub.publish(publisher, value);
182
+ } else {
183
+ pubsub.publish(publisher, {error: value});
254
184
  }
255
- },
256
- mine: async (params, {send, error}) => {
257
- api.mine(params);
258
- send('ok');
259
- },
260
- lastBlock: async ({send, error}) => {
261
- try {
262
- const value = await api.lastBlock();
263
- send(value);
264
- } catch (e) {
265
- error(e);
185
+ };
186
+ const clientConnection = client => {
187
+ const startTime = new Date().getTime();
188
+ return {
189
+ client,
190
+ request: async req => {
191
+ const { result, id, handler } = await api.request(client, req);
192
+ pubsub.unsubscribe(id, handler);
193
+ return result
194
+ },
195
+ send: req => api.send(client, req),
196
+ subscribe: api.subscribe,
197
+ unsubscribe: api.unsubscribe,
198
+ subscribers: api.subscribers,
199
+ publish: api.publish,
200
+ pubsub: api.pubsub(client),
201
+ uptime: () => {
202
+ const now = new Date().getTime();
203
+ return (now - startTime)
204
+ },
205
+ peernet: api.peernet(client),
206
+ server: api.server(client),
207
+ close: exit => {
208
+ client.onclose = message => {
209
+ if (exit) process.exit();
210
+ };
211
+ client.close();
212
+ }
266
213
  }
267
- },
268
- };
269
-
270
- const fullLog = text => {
271
- return console.log(`${new Date()}: ${text}`)
214
+ };
215
+ return new Promise((resolve, reject) => {
216
+ const init = () => {
217
+ let ws;
218
+ if (typeof process === 'object' && !globalThis.WebSocket) {
219
+ ws = require('websocket').w3cwebsocket;
220
+ } else {
221
+ ws = WebSocket;
222
+ }
223
+ const client = new ws(url, protocols);
224
+ client.onmessage = onmessage;
225
+ client.onerror = onerror;
226
+ client.onopen = () => {
227
+ tries = 0;
228
+ resolve(clientConnection(client));
229
+ };
230
+ client.onclose = message => {
231
+ tries++;
232
+ if (!retry) return reject(options)
233
+ if (tries > 5) {
234
+ console.log(`${protocols} Client Closed`);
235
+ console.error(`could not connect to - ${url}/`);
236
+ return resolve(clientConnection(client))
237
+ }
238
+ if (message.code === 1006) {
239
+ console.log('Retrying in 10 seconds');
240
+ setTimeout(() => {
241
+ return init();
242
+ }, retry);
243
+ }
244
+ };
245
+ };
246
+ return init();
247
+ });
272
248
  };
273
249
 
274
- const originIsAllowed = (requestOrigin, origin) => {
275
- // put logic here to detect whether the specified origin is allowed.
276
- if (origin && requestOrigin !== origin) return false;
277
- return true;
278
- };
250
+ class Peer {
251
+ #connection
252
+ #ready = false
253
+ #connecting = false
254
+ #connected = false
255
+ #channelReady = false
256
+ #destroying = false
257
+ #destroyed = false
258
+ #isNegotiating = false
259
+ #firstNegotiation = true
260
+ #iceComplete = false
261
+ #remoteTracks = []
262
+ #remoteStreams = []
263
+ #pendingCandidates = []
264
+ #senderMap = new Map()
265
+ #iceCompleteTimer
266
+ #channel
267
+
268
+ get connection() {
269
+ return this.#connection
270
+ }
271
+
272
+ get connected() {
273
+ return this.#connected
274
+ }
279
275
 
280
276
  /**
281
- * @module socketResponse
282
- *
283
- * @param {object} connection socket connection
284
- * @param {string} route the route to handle
285
- */
286
- var socketConnection = (request, protocol, origin) => {
287
- if (origin && !originIsAllowed(request.origin, origin)) {
288
- // Make sure we only accept requests from an allowed origin
289
- request.reject();
290
- fullLog(`Connection from origin ${request.origin} rejected.`);
291
- return;
292
- }
293
- // console.log(request);
294
- const connection = request.accept(protocol, request.origin);
295
- fullLog(`Connection accepted @${protocol}`);
296
- return connection;
297
- };
298
-
299
- /**
300
- * @module socketResponse
301
- *
302
- * @param {object} connection socket connection
303
- * @param {string} url the request url
277
+ * @params {Object} options
278
+ * @params {string} options.channelName - this peerid : otherpeer id
304
279
  */
305
- var socketResponse = (connection, url, id, customEvent) => {
306
- const send = (data = 'ok', status = 200) => connection.send(
307
- JSON.stringify({url, status, value: data, id, customEvent})
308
- );
309
- const error = data => connection.send(JSON.stringify({url, value: data}));
310
- return {
311
- connection,
312
- send,
313
- error
314
- }
315
- };
316
-
317
- const socketRequestServer = (options, routes = {}) => {
318
- // if (!routes && !routes.port && options) routes = options;
319
- // else if (!options && !routes) return console.error('no routes defined');
320
-
321
- let {httpServer, httpsServer, port, protocol, credentials, origin, pubsub } = options;
322
- if (!pubsub) pubsub = new PubSub({verbose: false});
323
- if (!port) port = 6000;
324
- const connections = [];
325
- let connection;
326
- const startTime = new Date().getTime();
327
- // default routes
328
- if (!routes.ping) routes.ping = (response) => response.send(new Date().getTime());
329
- if (!routes.uptime) routes.uptime = (response) => {
330
- const now = new Date().getTime();
331
- response.send(now - startTime);
280
+ constructor(options = {}) {
281
+ this._in = this._in.bind(this);
282
+ this.offerOptions = options.offerOptions;
283
+ this.initiator = options.initiator;
284
+ this.streams = options.streams;
285
+ this.socketClient = options.socketClient;
286
+ this.id = options.id;
287
+ this.to = options.to;
288
+ this.bw = {
289
+ up: 0,
290
+ down: 0
332
291
  };
333
- if (!routes.pubsub) {
334
- routes.pubsub = (params, response) => {
335
- if (!response) {
336
- response = params;
337
- params = {};
338
- }
339
-
340
- if (!params.topic) params.topic = 'pubsub';
341
-
342
- const topic = params.topic;
343
- delete params.topic;
344
-
345
- if (params.subscribe) {
346
- pubsub.subscribe(topic, message => {
347
- response.connection.send(JSON.stringify({url: topic, status: 200, value: message}));
348
- });
349
- response.send('ok', 200);
350
- } else if (params.unsubscribe) {
351
- pubsub.unsubscribe(topic, message => {
352
- response.connection.send(JSON.stringify({url: topic, status: 200, value: message}));
353
- });
354
- for (const connection of connections) {
355
- if (connection !== response.connection) connection.send(JSON.stringify({url: topic, status: 200, value: params}));
356
- }
357
- response.send('ok', 200);
292
+
293
+ this.channelName = options.channelName || Buffer.from(Math.random().toString(36).slice(-12)).toString('hex');
294
+ console.log(this.channelName);
295
+ this.options = options;
296
+ this.#init();
297
+ }
298
+
299
+ set socketClient(value) {
300
+ // this.socketClient?.pubsub.unsubscribe('signal', this._in)
301
+ this._socketClient = value;
302
+ this._socketClient.pubsub.subscribe('signal', this._in);
303
+ }
304
+
305
+ get socketClient() {
306
+ return this._socketClient
307
+ }
308
+
309
+ send(message) {
310
+ this.bw.up += message.length;
311
+ this.channel.send(message);
312
+ }
313
+
314
+ request(data) {
315
+ return new Promise((resolve, reject) => {
316
+ const id = Math.random().toString(36).slice(-12);
317
+ data = new TextEncoder().encode(JSON.stringify({id, data}));
318
+ const _onData = message => {
319
+ message = JSON.parse(new TextDecoder().decode(message.data));
320
+ if (message.id === id) {
321
+ resolve(message.data);
322
+ pubsub.unsubscribe('peer:data', _onData);
358
323
  }
359
- else if (params.value !== undefined)
360
- // should only be send raw to stars
361
- // for (const connection of connections) {
362
- // if (connection !== response.connection) connection.send(JSON.stringify({
363
- // url: topic, status: 200, value: params
364
- // }));
365
- // }
366
- pubsub.publish(topic, params.value);
367
- response.send('ok', 200);
368
324
  };
369
-
325
+
326
+ pubsub.subscribe('peer:data', _onData);
327
+
328
+ // cleanup subscriptions
329
+ setTimeout(() => {
330
+ pubsub.unsubscribe('peer:data', _onData);
331
+ }, 5000);
332
+
333
+ this.send(data);
334
+ });
335
+ }
336
+
337
+ async #init() {
338
+ try {
339
+ const iceServers = [{
340
+ urls: 'stun:stun.l.google.com:19302' // Google's public STUN server
341
+ }];
342
+
343
+ this.#connection = new wrtc.RTCPeerConnection();
344
+ this.#connection.onicecandidate = ({ candidate }) => {
345
+ if (candidate) {
346
+ this.address = candidate.address;
347
+ this.port = candidate.port;
348
+ this.protocol = candidate.protocol;
349
+ this.ipFamily = this.address.includes('::') ? 'ipv6': 'ipv4';
350
+ this._sendMessage({candidate});
351
+ }
352
+ };
353
+ // if (this.initiator) this.#connection.onnegotiationneeded = () => {
354
+ // console.log('create offer');
355
+ this.#connection.ondatachannel = (message) => {
356
+ message.channel.onopen = () => {
357
+ this.#connected = true;
358
+ pubsub.publish('peer:connected', this);
359
+ };
360
+ message.channel.onclose = () => console.log('close');
361
+ message.channel.onmessage = (message) => {
362
+ if (message.to) {
363
+ if (message.to === this.id) pubsub.publish('peer:data', message);
364
+ } else pubsub.publish('peer:data', message);
365
+ this.bw.down += message.length;
366
+ };
367
+ this.channel = message.channel;
368
+ };
369
+ if (this.initiator) {
370
+
371
+ this.channel = this.#connection.createDataChannel('messageChannel');
372
+ this.channel.onopen = () => {
373
+ this.#connected = true;
374
+ pubsub.publish('peer:connected', this);
375
+ // this.channel.send('hi')
376
+ };
377
+ this.channel.onclose = () => this.close.bind(this);
378
+
379
+ this.channel.onmessage = (message) => {
380
+ if (message.to) {
381
+ if (message.to === this.id) pubsub.publish('peer:data', message);
382
+ } else pubsub.publish('peer:data', message);
383
+ this.bw.down += message.length;
384
+ };
385
+
386
+ const offer = await this.#connection.createOffer();
387
+ await this.#connection.setLocalDescription(offer);
388
+
389
+ this._sendMessage({'sdp': this.#connection.localDescription});
390
+ }
391
+ // }
392
+
393
+ } catch (e) {
394
+ console.log(e);
395
+ }
396
+ }
397
+
398
+ _sendMessage(message) {
399
+ this.socketClient.send({url: 'signal', params: {
400
+ to: this.to,
401
+ from: this.id,
402
+ channelName: this.options.channelName,
403
+ ...message
404
+ }});
405
+ }
406
+
407
+ async _in(message, data) {
408
+ // message = JSON.parse(message);
409
+ if (message.to !== this.id) return
410
+ // if (data.videocall) return this._startStream(true, false); // start video and audio stream
411
+ // if (data.call) return this._startStream(true, true); // start audio stream
412
+ if (message.candidate) {
413
+ this.remoteAddress = message.candidate.address;
414
+ this.remotePort = message.candidate.port;
415
+ this.remoteProtocol = message.candidate.protocol;
416
+ this.remoteIpFamily = this.remoteAddress?.includes('::') ? 'ipv6': 'ipv4';
417
+ return this.#connection.addIceCandidate(new wrtc.RTCIceCandidate(message.candidate));
370
418
  }
371
- globalThis.peerMap = new Map();
372
- if (!routes.peernet) {
373
- routes.peernet = (params, response) => {
374
- if (params.join) {
375
- peerMap.set(params.peerId, params.address);
376
- response.send([...peerMap.values()]);
377
- for (const connection of connections) {
378
- if (connection !== response.connection)
379
- socketResponse(connection, 'peernet', 'peernet').send({discovered: params.address});
380
- }
381
- return
419
+ try {
420
+ if (message.sdp) {
421
+ if (message.sdp.type === 'offer') {
422
+ await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
423
+ const answer = await this.#connection.createAnswer();
424
+ await this.#connection.setLocalDescription(answer);
425
+ this._sendMessage({'sdp': this.#connection.localDescription});
382
426
  }
383
- if (!params.join) {
384
- peerMap.delete(params.peerId);
385
- return response.send()
427
+ if (message.sdp.type === 'answer') {
428
+ await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
386
429
  }
387
- };
430
+ }
431
+ } catch (e) {
432
+ console.log(e);
388
433
  }
389
- // if (!protocol) protocol = 'echo-protocol';
390
- if (!httpServer && !httpsServer) {
391
- const { createServer } = credentials ? require('https') : require('http');
392
- if (credentials) httpServer = createServer(credentials);
393
- else httpServer = createServer();
394
-
395
- httpServer.listen(port, () => {
396
- console.log(`listening on ${port}`);
397
- });
434
+ }
435
+
436
+ close() {
437
+ this.channel?.close();
438
+ this.#connection?.close();
439
+
440
+ this.socketClient.pubsub.unsubscribe('signal', this._in);
441
+ }
442
+ }
443
+
444
+ class Client {
445
+ #peerConnection
446
+ #connections = {}
447
+ #stars = {}
448
+
449
+ get connections() {
450
+ return { ...this.#connections }
398
451
  }
399
452
 
400
- const socketServer = new server({
401
- httpServer,
402
- autoAcceptConnections: false
403
- });
404
-
405
- socketServer.on('request', request => {
406
-
407
- connection = socketConnection(request, protocol, origin);
408
- connections.push(connection);
409
-
410
- const routeHandler = message => {
411
- let data;
412
- if (message.type) {
413
- switch (message.type) {
414
- case 'binary':
415
- data = message.binaryData.toString();
416
- break;
417
- case 'utf8':
418
- data = message.utf8Data;
419
- break;
420
- }
421
- }
422
- const { route, params, url, id, customEvent } = JSON.parse(data);
423
- // ignore api when customEvent is defined
424
- if (customEvent) return;
425
- if (routes[url]) {
426
- if (!params) return routes[url](socketResponse(connection, url, id));
427
- return routes[url](params, socketResponse(connection, url, id));
428
- }
429
- else return socketResponse(connection, url, id).error(`nop handler found for '${message.url}'`);
430
- };
453
+ constructor(id, identifiers = ['peernet-v0.1.0'], stars = []) {
454
+ this.id = id || Math.random().toString(36).slice(-12);
455
+ if (!Array.isArray(identifiers)) identifiers = [identifiers];
456
+ this.peerJoined = this.peerJoined.bind(this);
457
+ this.peerLeft = this.peerLeft.bind(this);
458
+ this.starLeft = this.starLeft.bind(this);
459
+ this.starJoined = this.starJoined.bind(this);
431
460
 
432
- connection.on('message', routeHandler);
433
- });
461
+ this._init(identifiers, stars);
462
+ }
434
463
 
435
- return {
436
- close: () => socketServer.shutDown(),
437
- connections
438
- };
439
- };
440
-
441
- var http = (config = {}) => {
442
- if (typeof config !== 'object') config = {};
443
- if (!config.protocol) config.protocol = 'peernet-v0.1.0';
444
- if (!config.port) config.port = 2000;
445
- if (!config.host) config.host = '127.0.0.1';
446
-
447
- const app = new Koa();
448
-
449
- app.use(async (ctx) => {
450
- const url = ctx.url.split('/api/')[1];
451
- if (url === 'version') ctx.body = {client: '@peernet/api/http', version};
452
- });
453
-
454
- const httpServer = createServer(app.callback());
455
-
456
- config.httpServer = httpServer;
457
-
458
- httpServer.listen(config.port, () => {
459
- console.log(`listening on ${config.port}`);
460
- });
461
-
462
- return socketRequestServer(config, api$1)
463
- };
464
-
465
- var clientApi = _pubsub => {
466
-
467
- const subscribe = (topic, cb) => {
468
- _pubsub.subscribe(topic, cb);
469
- };
470
-
471
- const unsubscribe = (topic, cb) => {
472
- _pubsub.unsubscribe(topic, cb);
473
- };
474
-
475
- const publish = (topic, value) => {
476
- _pubsub.publish(topic, value);
477
- };
478
-
479
- const _connectionState = (state) => {
480
- switch (state) {
481
- case 0:
482
- return 'connecting'
483
- case 1:
484
- return 'open'
485
- case 2:
486
- return 'closing'
487
- case 3:
488
- return 'closed'
464
+ async _init(identifiers, stars = []) {
465
+ if (stars.length === 0) {
466
+ stars.push('wss://star.leofcoin.org');
467
+ stars.push('ws://localhost:44444');
489
468
  }
490
- };
491
- /**
492
- * @param {string} type
493
- * @param {string} name
494
- * @param {object} params
495
- */
496
- const request = (client, request) => {
497
- return new Promise((resolve, reject) => {
498
-
499
- const state = _connectionState(client.readyState);
500
- if (state !== 'open') return reject(`coudn't send request to ${client.id}, no open connection found.`)
501
-
502
- request.id = Math.random().toString(36).slice(-12);
503
- const handler = result => {
504
- if (result && result.error) return reject(result.error)
505
- resolve({result, id: request.id, handler});
506
- };
507
- subscribe(request.id, handler);
508
- send(client, request);
469
+ this.identifiers = identifiers;
470
+ this.starsConfig = stars;
471
+ // reconnectJob()
472
+
473
+ globalThis.wrtc = await import('wrtc');
474
+ for (const star of stars) {
475
+ try {
476
+ this.socketClient = await socketRequestClient(star, identifiers[0]);
477
+ const id = await this.socketClient.request({url: 'id', params: {from: this.id}});
478
+ this.socketClient.peerId = id;
479
+ this.#stars[id] = this.socketClient;
480
+ } catch (e) {
481
+ if (stars.indexOf(star) === stars.length -1 && !this.socketClient) throw new Error(`No star available to connect`);
482
+ }
483
+ }
484
+ const peers = await this.socketClient.peernet.join({id: this.id});
485
+ for (const id of peers) {
486
+ if (id !== this.id && !this.#connections[id]) this.#connections[id] = new Peer({channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id});
487
+ }
488
+ this.setupListeners();
489
+
490
+ pubsub.subscribe('peer:connected', (peer) => {
491
+ // peer.send(JSON.stringify({data: 'hello', from: this.id, to: peer.to}))
492
+ console.log({peer: peer.to});
493
+ console.log({id: peer.id});
494
+ console.log({id: this.id});
509
495
  });
510
- };
511
-
512
- const send = async (client, request) => {
513
- return client.send(JSON.stringify(request))
514
- };
515
-
516
- const pubsub = client => {
517
- return {
518
- publish: (topic = 'pubsub', value) => {
519
- return send(client, {url: 'pubsub', params: { topic, value }})
520
- },
521
- subscribe: (topic = 'pubsub', cb) => {
522
- subscribe(topic, cb);
523
- return send(client, {url: 'pubsub', params: { topic, subscribe: true }})
524
- },
525
- unsubscribe: (topic = 'pubsub', cb) => {
526
- unsubscribe(topic, cb);
527
- return send(client, {url: 'pubsub', params: { topic, unsubscribe: true }})
528
- },
529
- subscribers: _pubsub.subscribers
496
+ // pubsub.subscribe('peer:data', (data) => console.log({data}))
497
+ }
498
+
499
+ setupListeners() {
500
+ this.socketClient.subscribe('peer:joined', this.peerJoined);
501
+ this.socketClient.subscribe('peer:left', this.peerLeft);
502
+ this.socketClient.subscribe('star:left', this.starLeft);
503
+ }
504
+
505
+ starJoined(id) {
506
+ if (this.#stars[id]) {
507
+ this.#stars[id].close();
508
+ delete this.#stars[id];
530
509
  }
531
- };
532
-
533
- const server = (client) => {
534
- return {
535
- uptime: async () => {
536
- try {
537
- const { result, id, handler } = await request(client, {url: 'uptime'});
538
- unsubscribe(id, handler);
539
- return result
540
- } catch (e) {
541
- throw e
542
- }
543
- },
544
- ping: async () => {
545
- try {
546
- const now = new Date().getTime();
547
- const { result, id, handler } = await request(client, {url: 'ping'});
548
- unsubscribe(id, handler);
549
- return (Number(result) - now)
550
- } catch (e) {
551
- throw e
552
- }
553
- }
510
+ console.log(`star ${id} joined`);
511
+ }
512
+
513
+ async starLeft(id) {
514
+ if (this.#stars[id]) {
515
+ this.#stars[id].close();
516
+ delete this.#stars[id];
554
517
  }
555
- };
556
-
557
- const peernet = (client) => {
558
- return {
559
- join: async (params) => {
560
- try {
561
- params.join = true;
562
- const requested = { url: 'peernet', params };
563
- const { result, id, handler } = await request(client, requested);
564
- unsubscribe(id, handler);
565
- return result
566
- } catch (e) {
567
- throw e
568
- }
569
- },
570
- leave: async (params) => {
518
+ if (this.socketClient?.peerId === id) {
519
+
520
+ this.socketClient.unsubscribe('peer:joined', this.peerJoined);
521
+ this.socketClient.unsubscribe('peer:left', this.peerLeft);
522
+ this.socketClient.unsubscribe('star:left', this.starLeft);
523
+ this.socketClient.close();
524
+ this.socketClient = undefined;
525
+
526
+ for (const star of this.starsConfig) {
571
527
  try {
572
- params.join = false;
573
- const requested = { url: 'peernet', params };
574
- const { result, id, handler } = await request(client, requested);
575
- unsubscribe(id, handler);
576
- return result
528
+ this.socketClient = await socketRequestClient(star, this.identifiers[0]);
529
+ if (!this.socketClient?.client?._connection.connected) return
530
+ const id = await this.socketClient.request({url: 'id', params: {from: this.id}});
531
+ this.#stars[id] = this.socketClient;
532
+
533
+ this.socketClient.peerId = id;
534
+
535
+ const peers = await this.socketClient.peernet.join({id: this.id});
536
+ this.setupListeners();
537
+ for (const id of peers) {
538
+ if (id !== this.id) {
539
+ // close connection
540
+ if (this.#connections[id]) {
541
+ if (this.#connections[id].connected) await this.#connections[id].close();
542
+ delete this.#connections[id];
543
+ }
544
+ // reconnect
545
+ if (id !== this.id) this.#connections[id] = new Peer({channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id});
546
+ }
547
+
548
+ }
577
549
  } catch (e) {
578
- throw e
550
+ console.log(e);
551
+ if (this.starsConfig.indexOf(star) === this.starsConfig.length -1 && !this.socketClient) throw new Error(`No star available to connect`);
579
552
  }
580
553
  }
581
554
  }
582
- };
583
-
584
- return { send, request, pubsub, server, subscribe, unsubscribe, publish, peernet }
585
- };
586
-
587
- const socketRequestClient = (url, protocols = 'echo-protocol', options = { retry: false, pubsub: false }) => {
588
- let { pubsub, retry } = options;
589
- if (!pubsub) pubsub = new PubSub({verbose: false});
590
-
591
- const api = clientApi(pubsub);
592
-
593
- let tries = 0;
594
-
595
- const onerror = error => {
596
- if (pubsub.subscribers['error']) {
597
- pubsub.publish('error', error);
598
- } else {
599
- console.error(error);
600
- }
601
- };
602
-
603
- const onmessage = message => {
604
- const {value, url, status, id} = JSON.parse(message.data.toString());
605
- const publisher = id ? id : url;
606
- if (status === 200) {
607
- pubsub.publish(publisher, value);
608
- } else {
609
- pubsub.publish(publisher, {error: value});
555
+
556
+ console.log(`star ${id} left`);
557
+
558
+
559
+ }
560
+
561
+ peerLeft(id) {
562
+ if (this.#connections[id]) {
563
+ this.#connections[id].close();
564
+ delete this.#connections[id];
610
565
  }
566
+ console.log(`peer ${id} left`);
567
+ }
611
568
 
612
- };
613
-
614
- const clientConnection = client => {
615
- const startTime = new Date().getTime();
616
- return {
617
- client,
618
- request: async req => {
619
- const { result, id, handler } = await api.request(client, req);
620
- pubsub.unsubscribe(id, handler);
621
- return result
622
- },
623
- send: req => api.send(client, req),
624
- subscribe: api.subscribe,
625
- unsubscribe: api.unsubscribe,
626
- subscribers: api.subscribers,
627
- publish: api.publish,
628
- pubsub: api.pubsub(client),
629
- uptime: () => {
630
- const now = new Date().getTime();
631
- return (now - startTime)
632
- },
633
- peernet: api.peernet(client),
634
- server: api.server(client),
635
- close: exit => {
636
- client.onclose = message => {
637
- if (exit) process.exit();
638
- };
639
- client.close();
640
- }
569
+ peerJoined(id, signal) {
570
+ if (this.#connections[id]) {
571
+ if (this.#connections[id].connected) this.#connections[id].close();
572
+ delete this.#connections[id];
641
573
  }
642
- };
643
-
644
- return new Promise((resolve, reject) => {
645
- const init = () => {
646
- let ws;
647
- if (typeof process === 'object') {
648
- ws = require('websocket').w3cwebsocket;
649
- } else {
650
- ws = WebSocket;
651
- }
652
- const client = new ws(url, protocols);
574
+ // RTCPeerConnection
575
+ this.#connections[id] = new Peer({initiator: true, channelName: `${this.id}:${id}`, socketClient: this.socketClient, id: this.id, to: id});
576
+ console.log(`peer ${id} joined`);
577
+ }
578
+
653
579
 
654
- client.onmessage = onmessage;
655
- client.onerror = onerror;
656
- client.onopen = () => {
657
- tries = 0;
658
- resolve(clientConnection(client));
659
- };
660
- client.onclose = message => {
661
- tries++;
662
- if (!retry) return reject(options)
663
- if (tries > 5) {
664
- console.log(`${protocols} Client Closed`);
665
- console.error(`could not connect to - ${url}/`);
666
- return resolve(clientConnection(client))
667
- }
668
- if (message.code === 1006) {
669
- console.log('Retrying in 10 seconds');
670
- setTimeout(() => {
671
- return init();
672
- }, retry);
673
- }
674
- };
675
- };
676
- return init();
677
- });
678
- };
679
-
680
- class HttpClientApi$1 {
681
- constructor(config = {}) {
682
- if (!config.apiPath) config.apiPath = 'api';
683
-
684
- const address = `ws://${config.host}:${config.port}`;
685
-
686
- this.apiUrl = (url) => `${address}/${url}`;
687
- return (async () => {
688
- this.client = await socketRequestClient(address, config.protocol, {pubsub: config.pubsub, retry: 3000});
689
- return this
690
- })()
691
- }
692
-
693
- async get(url, obj) {
694
- const headers = {};
695
- let body = null;
696
- let method = 'GET';
697
- if (obj) {
698
- method = 'POST';
699
- headers['Content-Type'] = 'application/json';
700
- body = JSON.stringify(obj);
701
- }
702
- let response = await this.client.request(url, {headers, body, method});
703
- const type = response.headers.get('content-type').split(';')[0];
704
- if (type==='application/json') response = await response.json();
705
- return response
706
- }
707
-
708
- async put(url, obj) {
709
- const headers = {};
710
- let body = {};
711
- if (obj) {
712
- headers['Content-Type'] = 'application/json';
713
- body = JSON.stringify(obj);
714
- }
715
-
716
- let response = await fetch(this.apiUrl(url), {method: 'PUT', headers, body});
717
- const type = response.headers.get('content-type').split(';')[0];
718
- if (type==='application/json') response = await response.json();
719
- return response
720
- }
721
- }
722
-
723
- class HttpClientApi extends HttpClientApi$1 {
724
- constructor(config = {}) {
725
- config.apiPath = 'api';
726
- return (async () => {
727
- await super(config);
728
-
729
- this.properties = {
730
- wallet: 'get',
731
- version: 'get',
732
- addresses: 'get',
733
- config: 'get',
734
- account: 'get',
735
- accounts: 'get',
736
- transaction: 'any',
737
- transactions: 'get',
738
- block: 'get',
739
- blocks: 'get',
740
- };
741
- this.keys = Object.keys(this.properties);
742
- return this
743
- })()
744
- }
745
-
746
- async request(url, data) {
747
- return await this.client.request({url, params: data})
748
- }
749
-
750
- async ready() {
751
- return await this.request('ready')
752
- }
753
-
754
- async version() {
755
- return await this.request('version')
756
- }
757
-
758
- async account(index) {
759
- return await this.request('account', {index})
760
- }
761
580
  }
762
581
 
763
- var httpClient = (config = {}) => {
764
- if (typeof config !== 'object') config = {};
765
- if (!config.protocol) config.protocol = 'peernet-v0.1.0';
766
- if (!config.port) config.port = 1000;
767
- if (!config.host) config.host = '127.0.0.1';
768
-
769
- return new HttpClientApi(config)
770
- };
771
-
772
582
  class LeofcoinStorageClient {
773
583
  constructor(name, root) {
774
584
  this.name = name;
@@ -816,84 +626,84 @@ message PeernetMessage {
816
626
  optional string id = 5;
817
627
  }`;
818
628
 
819
- var codecs = {
820
- // just a hash
821
- 'disco-hash': {
822
- codec: '30',
823
- hashAlg: 'dbl-keccak-512', // ,
824
- // testnet: 'olivia'
825
- },
826
- 'peernet-peer-response': {
827
- codec: '707072',
828
- hashAlg: 'keccak-256',
829
- },
830
- 'peernet-peer': {
831
- codec: '7070',
832
- hashAlg: 'keccak-256',
833
- },
834
- 'peernet-dht': {
835
- codec: '706468',
836
- hashAlg: 'keccak-256',
837
- },
838
- 'peernet-dht-response': {
839
- codec: '706472',
840
- hashAlg: 'keccak-256',
841
- },
842
- // data
843
- 'peernet-data': {
844
- codec: '706461',
845
- hashAlg: 'keccak-256',
846
- },
847
- 'peernet-data-response': {
848
- codec: '70646172',
849
- hashAlg: 'keccak-256',
850
- },
851
- // message
852
- 'peernet-message': {
853
- codec: '706d65',
854
- hashAlg: 'keccak-512',
855
- },
856
- // pubsub
857
- 'peernet-ps': {
858
- codec: '707073',
859
- hashAlg: 'keccak-256',
860
- },
861
- 'peernet-response': {
862
- codec: '7072',
863
- hashAlg: 'keccak-256',
864
- },
865
- 'peernet-request': {
866
- codec: '707271',
867
- hashAlg: 'keccak-256',
868
- },
869
- // normal block
870
- 'leofcoin-block': {
871
- codec: '6c62',
872
- hashAlg: 'dbl-keccak-512', // ,
873
- // testnet: 'olivia'
874
- },
875
- 'leofcoin-tx': {
876
- codec: '6c74',
877
- hashAlg: 'dbl-keccak-512', // ,
878
- // testnet: 'olivia'
879
- },
880
- // itx
881
- 'leofcoin-itx': {
882
- codec: '6c69',
883
- hashAlg: 'keccak-512', // ,
884
- // testnet: 'olivia'
885
- },
886
- // peer reputation
887
- 'leofcoin-pr': {
888
- codec: '6c70',
889
- hashAlg: 'keccak-256', // ,
890
- // testnet: 'olivia'
891
- },
892
- // chat message
893
- 'chat-message': {
894
- codec: '636d',
895
- hashAlg: 'dbl-keccak-512',
896
- },
629
+ var codecs = {
630
+ // just a hash
631
+ 'disco-hash': {
632
+ codec: parseInt('30', 16),
633
+ hashAlg: 'dbl-keccak-512', // ,
634
+ // testnet: 'olivia'
635
+ },
636
+ 'peernet-peer-response': {
637
+ codec: parseInt('707072', 16),
638
+ hashAlg: 'keccak-256',
639
+ },
640
+ 'peernet-peer': {
641
+ codec: parseInt('7070', 16),
642
+ hashAlg: 'keccak-256',
643
+ },
644
+ 'peernet-dht': {
645
+ codec: parseInt('706468', 16),
646
+ hashAlg: 'keccak-256',
647
+ },
648
+ 'peernet-dht-response': {
649
+ codec: parseInt('706472', 16),
650
+ hashAlg: 'keccak-256',
651
+ },
652
+ // data
653
+ 'peernet-data': {
654
+ codec: parseInt('706461', 16),
655
+ hashAlg: 'keccak-256',
656
+ },
657
+ 'peernet-data-response': {
658
+ codec: parseInt('70646172', 16),
659
+ hashAlg: 'keccak-256',
660
+ },
661
+ // message
662
+ 'peernet-message': {
663
+ codec: parseInt('706d65', 16),
664
+ hashAlg: 'keccak-512',
665
+ },
666
+ // pubsub
667
+ 'peernet-ps': {
668
+ codec: parseInt('707073', 16),
669
+ hashAlg: 'keccak-256',
670
+ },
671
+ 'peernet-response': {
672
+ codec: parseInt('7072', 16),
673
+ hashAlg: 'keccak-256',
674
+ },
675
+ 'peernet-request': {
676
+ codec: parseInt('707271', 16),
677
+ hashAlg: 'keccak-256',
678
+ },
679
+ // normal block
680
+ 'leofcoin-block': {
681
+ codec: parseInt('6c62', 16),
682
+ hashAlg: 'dbl-keccak-512', // ,
683
+ // testnet: 'olivia'
684
+ },
685
+ 'leofcoin-tx': {
686
+ codec: parseInt('6c74', 16),
687
+ hashAlg: 'dbl-keccak-512', // ,
688
+ // testnet: 'olivia'
689
+ },
690
+ // itx
691
+ 'leofcoin-itx': {
692
+ codec: parseInt('6c69', 16),
693
+ hashAlg: 'keccak-512', // ,
694
+ // testnet: 'olivia'
695
+ },
696
+ // peer reputation
697
+ 'leofcoin-pr': {
698
+ codec: parseInt('6c70', 16),
699
+ hashAlg: 'keccak-256', // ,
700
+ // testnet: 'olivia'
701
+ },
702
+ // chat message
703
+ 'chat-message': {
704
+ codec: parseInt('636d', 16),
705
+ hashAlg: 'dbl-keccak-512',
706
+ },
897
707
  };
898
708
 
899
709
  class PeernetCodec {
@@ -902,10 +712,9 @@ class PeernetCodec {
902
712
  }
903
713
  constructor(buffer) {
904
714
  if (buffer) {
905
- if (Buffer.isBuffer(buffer)) {
715
+ if (buffer instanceof Uint8Array) {
906
716
  const codec = varint.decode(buffer);
907
717
  const name = this.getCodecName(codec);
908
-
909
718
  if (name) {
910
719
  this.name = name;
911
720
  this.encoded = buffer;
@@ -913,12 +722,23 @@ class PeernetCodec {
913
722
  } else {
914
723
  this.encode(buffer);
915
724
  }
725
+ } else if (buffer instanceof ArrayBuffer) {
726
+ const encoded = new Uint8Array(buffer.byteLength);
727
+
728
+ for (let i = 0; i < buffer.byteLength; i++) {
729
+ encoded[i] = buffer[i];
730
+ }
731
+ this.encoded = encoded;
732
+ // this.encoded = new Uint8Array(buffer, buffer.byteOffset, buffer.byteLength)
733
+ this.decode(buffer);
734
+ return
916
735
  }
917
736
  if (typeof buffer === 'string') {
918
737
  if (this.codecs[buffer]) this.fromName(buffer);
919
738
  else if (isHex(buffer)) this.fromHex(buffer);
920
- else if (bs32.test(buffer)) this.fromBs32(buffer);
921
- else this.fromBs58(buffer);
739
+ else if (bs32.isBase32(buffer)) this.fromBs32(buffer);
740
+ else if (bs58.isBase58(buffer)) this.fromBs58(buffer);
741
+ else throw new Error(`unsupported string ${buffer}`)
922
742
  }
923
743
  if (!isNaN(buffer)) if (this.codecs[this.getCodecName(buffer)]) this.fromCodec(buffer);
924
744
  }
@@ -953,7 +773,8 @@ class PeernetCodec {
953
773
 
954
774
  getCodecName(codec) {
955
775
  return Object.keys(this.codecs).reduce((p, c) => {
956
- if (parseInt(Buffer.from(`${this.getCodec(c)}`, 'hex').toString('hex'), 16) === codec) return c;
776
+ const item = this.codecs[c];
777
+ if (item.codec === codec) return c;
957
778
  else return p;
958
779
  }, undefined)
959
780
  }
@@ -967,7 +788,7 @@ class PeernetCodec {
967
788
  this.hashAlg = this.getHashAlg(this.name);
968
789
 
969
790
  this.codec = this.getCodec(this.name);
970
- this.codecBuffer = Buffer.from(varint.encode(parseInt(Buffer.from(`${this.codec}`, 'hex').toString('hex'), 16)), 'hex');
791
+ this.codecBuffer = varint.encode(codec);
971
792
  }
972
793
 
973
794
  fromName(name) {
@@ -975,7 +796,7 @@ class PeernetCodec {
975
796
  this.name = name;
976
797
  this.codec = codec;
977
798
  this.hashAlg = this.getHashAlg(name);
978
- this.codecBuffer = Buffer.from(varint.encode(parseInt(Buffer.from(`${codec}`, 'hex').toString('hex'), 16)), 'hex');
799
+ this.codecBuffer = varint.encode(codec);
979
800
  }
980
801
 
981
802
  toBs32() {
@@ -995,11 +816,10 @@ class PeernetCodec {
995
816
  decode() {
996
817
  const codec = varint.decode(this.encoded);
997
818
  this.fromCodec(codec);
998
- this.name = this.getCodecName(codec);
999
819
  }
1000
820
 
1001
821
  encode() {
1002
- const codec = Buffer.from(varint.encode(parseInt(Buffer.from(`${this.codec}`, 'hex').toString('hex'), 16)), 'hex');
822
+ const codec = varint.encode(this.decoded);
1003
823
  this.encoded = codec;
1004
824
  return this.encoded
1005
825
  }
@@ -1025,18 +845,28 @@ class PeernetHash {
1025
845
 
1026
846
  if (typeof buffer === 'string') {
1027
847
  if (isHex(buffer)) this.fromHex(buffer);
1028
- if (bs32.test(buffer)) this.fromBs32(buffer);
1029
- else this.fromBs58(buffer);
848
+ if (bs32.isBase32(buffer)) this.fromBs32(buffer);
849
+ else if (bs58.isBase58(buffer)) this.fromBs58(buffer);
850
+ else throw new Error(`unsupported string ${buffer}`)
1030
851
  } else if (typeof buffer === 'object') this.fromJSON(buffer);
1031
852
  }
1032
853
  }
1033
854
 
1034
855
  get prefix() {
1035
- return Buffer.concat([this.discoCodec.codecBuffer, this.length])
856
+ const length = this.length;
857
+ const uint8Array = new Uint8Array(length.length + this.discoCodec.codecBuffer.length);
858
+ for (let i = 0; i < this.discoCodec.codecBuffer.length; i++) {
859
+ uint8Array[i] = this.discoCodec.codecBuffer[i];
860
+ }
861
+
862
+ for (let i = uint8Array.length - 1; i < length.length; i++) {
863
+ uint8Array[i] = length[i];
864
+ }
865
+ return uint8Array
1036
866
  }
1037
867
 
1038
868
  get length() {
1039
- return Buffer.from(varint.encode(this.size))
869
+ return varint.encode(this.size)
1040
870
  }
1041
871
 
1042
872
  get buffer() {
@@ -1153,25 +983,18 @@ class FormatInterface {
1153
983
  constructor(buffer, proto, options = {}) {
1154
984
  this.protoEncode = proto.encode;
1155
985
  this.protoDecode = proto.decode;
1156
- if (options.name) this.name = options.name;
1157
986
  this.hashFormat = options.hashFormat || 'bs32';
1158
- if (buffer.name === options.name) {
1159
- return buffer
1160
- } else if (Buffer.isBuffer(buffer)) {
1161
- const codec = new PeernetCodec(buffer);
1162
- if (codec.name) {
1163
- this.fromEncoded(buffer);
1164
- } else {
1165
- this.create(buffer);
1166
- }
1167
- } else {
1168
- if (typeof buffer === 'string') {
987
+ if (options.name) this.name = options.name;
988
+ if (buffer instanceof Uint8Array) return this.fromUint8Array(buffer)
989
+ else if (buffer instanceof ArrayBuffer) return this.fromArrayBuffer(buffer)
990
+ else if (buffer.name === options.name) return buffer
991
+ else if (typeof buffer === 'string') {
1169
992
  if (isHex(buffer)) this.fromHex(buffer);
1170
- else if (bs32.test(buffer)) this.fromBs32(buffer);
1171
- else this.fromBs58(buffer);
1172
- } else if (typeof buffer === 'object' && !Array.isArray(buffer)) {
1173
- this.create(buffer);
1174
- }
993
+ else if (bs32.isBase32(buffer)) this.fromBs32(buffer);
994
+ else if (bs58.isBase58(buffer)) this.fromBs58(buffer);
995
+ else throw new Error(`unsupported string ${buffer}`)
996
+ } else {
997
+ this.create(buffer);
1175
998
  }
1176
999
  }
1177
1000
 
@@ -1196,7 +1019,7 @@ class FormatInterface {
1196
1019
  */
1197
1020
  decode() {
1198
1021
  let encoded = this.encoded;
1199
- const discoCodec = new PeernetCodec(this.encoded.toString('hex'));
1022
+ const discoCodec = new PeernetCodec(this.encoded);
1200
1023
  encoded = encoded.slice(discoCodec.codecBuffer.length);
1201
1024
  this.name = discoCodec.name;
1202
1025
  this.decoded = this.protoDecode(encoded);
@@ -1209,16 +1032,40 @@ class FormatInterface {
1209
1032
  encode(decoded) {
1210
1033
  if (!decoded) decoded = this.decoded;
1211
1034
  const codec = new PeernetCodec(this.name);
1212
- this.encoded = Buffer.concat([codec.codecBuffer, this.protoEncode(decoded)]);
1035
+ const encoded = this.protoEncode(decoded);
1036
+ const uint8Array = new Uint8Array(encoded.length + codec.codecBuffer.length);
1037
+ uint8Array.set(codec.codecBuffer);
1038
+ uint8Array.set(encoded, codec.codecBuffer.length);
1039
+ this.encoded = uint8Array;
1213
1040
  return this.encoded
1214
1041
  }
1215
1042
 
1043
+ hasCodec() {
1044
+ if (!this.encoded) return false
1045
+ const codec = new PeernetCodec(this.encoded);
1046
+ if (codec.name) return true
1047
+ }
1048
+
1049
+ fromUint8Array(buffer) {
1050
+ this.encoded = buffer;
1051
+ if (!this.hasCodec()) this.create(
1052
+ JSON.parse(new TextDecoder().decode(this.encoded))
1053
+ );
1054
+ else this.decode();
1055
+ }
1056
+
1057
+ fromArrayBuffer(buffer) {
1058
+ this.encoded = new Uint8Array(buffer, buffer.byteOffset, buffer.byteLength);
1059
+ if (!this.hasCodec()) this.create(
1060
+ JSON.parse(new TextDecoder().decode(this.encoded))
1061
+ );
1062
+ else this.decode();
1063
+ }
1064
+
1216
1065
  /**
1217
1066
  * @param {Buffer} encoded
1218
1067
  */
1219
1068
  fromEncoded(encoded) {
1220
- const codec = new PeernetCodec(encoded);
1221
- this.name = codec.name;
1222
1069
  this.encoded = encoded;
1223
1070
  this.decode();
1224
1071
  }
@@ -1294,15 +1141,15 @@ class FormatInterface {
1294
1141
  }
1295
1142
  }
1296
1143
 
1297
- class PeernetMessage extends FormatInterface {
1298
- get keys() {
1299
- return ['data', 'signature', 'from', 'to', 'id']
1300
- }
1301
-
1302
- constructor(buffer) {
1303
- const name = 'peernet-message';
1304
- super(buffer, protons(proto$a).PeernetMessage, {name});
1305
- }
1144
+ class PeernetMessage extends FormatInterface {
1145
+ get keys() {
1146
+ return ['data', 'signature', 'from', 'to', 'id']
1147
+ }
1148
+
1149
+ constructor(buffer) {
1150
+ const name = 'peernet-message';
1151
+ super(buffer, protons(proto$a).PeernetMessage, {name});
1152
+ }
1306
1153
  }
1307
1154
 
1308
1155
  var proto$9 = `
@@ -1313,26 +1160,26 @@ message PeernetDHTMessage {
1313
1160
  }
1314
1161
  `;
1315
1162
 
1316
- /**
1317
- * @example `
1318
- new DHTMessage(hash, store)
1319
- // store = optional if not set, peernet checks every store
1320
- let message = new DHTMessage('hashmvbs124xcfd...', 'transaction')
1321
- message = new DHTMessage('hashmvbs124xcfd...', 'block')
1322
- `
1323
- */
1324
- class DHTMessage extends FormatInterface {
1325
- /**
1326
- *
1327
- */
1328
- get keys() {
1329
- return ['hash', 'store']
1330
- }
1331
-
1332
- constructor(data) {
1333
- const name = 'peernet-dht';
1334
- super(data, protons(proto$9).PeernetDHTMessage, {name});
1335
- }
1163
+ /**
1164
+ * @example `
1165
+ new DHTMessage(hash, store)
1166
+ // store = optional if not set, peernet checks every store
1167
+ let message = new DHTMessage('hashmvbs124xcfd...', 'transaction')
1168
+ message = new DHTMessage('hashmvbs124xcfd...', 'block')
1169
+ `
1170
+ */
1171
+ class DHTMessage extends FormatInterface {
1172
+ /**
1173
+ *
1174
+ */
1175
+ get keys() {
1176
+ return ['hash', 'store']
1177
+ }
1178
+
1179
+ constructor(data) {
1180
+ const name = 'peernet-dht';
1181
+ super(data, protons(proto$9).PeernetDHTMessage, {name});
1182
+ }
1336
1183
  }
1337
1184
 
1338
1185
  var proto$8 = `
@@ -1362,19 +1209,19 @@ message PeernetDataMessage {
1362
1209
  }
1363
1210
  `;
1364
1211
 
1365
- /**
1366
- * @extends {CodecFormat}
1367
- */
1368
- class DataMessage extends FormatInterface {
1369
- get keys() {
1370
- return ['hash', 'store']
1371
- }
1372
- /**
1373
- * @param {Buffer|String|Object|DataMessage} data - The data needed to create the DataMessage
1374
- */
1375
- constructor(data) {
1376
- super(data, protons(proto$7).PeernetDataMessage, {name: 'peernet-data'});
1377
- }
1212
+ /**
1213
+ * @extends {CodecFormat}
1214
+ */
1215
+ class DataMessage extends FormatInterface {
1216
+ get keys() {
1217
+ return ['hash', 'store']
1218
+ }
1219
+ /**
1220
+ * @param {Buffer|String|Object|DataMessage} data - The data needed to create the DataMessage
1221
+ */
1222
+ constructor(data) {
1223
+ super(data, protons(proto$7).PeernetDataMessage, {name: 'peernet-data'});
1224
+ }
1378
1225
  }
1379
1226
 
1380
1227
  var proto$6 = `
@@ -1384,15 +1231,15 @@ message PsMessage {
1384
1231
  required bytes topic = 2;
1385
1232
  }`;
1386
1233
 
1387
- class PsMessage extends FormatInterface {
1388
- get keys() {
1389
- return ['data', 'topic']
1390
- }
1391
-
1392
- constructor(buffer) {
1393
- const name = 'peernet-ps';
1394
- super(buffer, protons(proto$6).PsMessage, {name});
1395
- }
1234
+ class PsMessage extends FormatInterface {
1235
+ get keys() {
1236
+ return ['data', 'topic']
1237
+ }
1238
+
1239
+ constructor(buffer) {
1240
+ const name = 'peernet-ps';
1241
+ super(buffer, protons(proto$6).PsMessage, {name});
1242
+ }
1396
1243
  }
1397
1244
 
1398
1245
  var proto$5 = `
@@ -1402,15 +1249,15 @@ message PeernetPeerMessage {
1402
1249
  }
1403
1250
  `;
1404
1251
 
1405
- class PeerMessage extends FormatInterface {
1406
- get keys() {
1407
- return ['id']
1408
- }
1409
-
1410
- constructor(data) {
1411
- const name = 'peernet-peer';
1412
- super(data, protons(proto$5).PeernetPeerMessage, {name});
1413
- }
1252
+ class PeerMessage extends FormatInterface {
1253
+ get keys() {
1254
+ return ['id']
1255
+ }
1256
+
1257
+ constructor(data) {
1258
+ const name = 'peernet-peer';
1259
+ super(data, protons(proto$5).PeernetPeerMessage, {name});
1260
+ }
1414
1261
  }
1415
1262
 
1416
1263
  var proto$4 = `
@@ -1420,15 +1267,15 @@ message PeernetRequestMessage {
1420
1267
  }
1421
1268
  `;
1422
1269
 
1423
- class RequestMessage extends FormatInterface {
1424
- get keys() {
1425
- return ['request']
1426
- }
1427
-
1428
- constructor(data) {
1429
- const name = 'peernet-request';
1430
- super(data, protons(proto$4).PeernetRequestMessage, {name});
1431
- }
1270
+ class RequestMessage extends FormatInterface {
1271
+ get keys() {
1272
+ return ['request']
1273
+ }
1274
+
1275
+ constructor(data) {
1276
+ const name = 'peernet-request';
1277
+ super(data, protons(proto$4).PeernetRequestMessage, {name});
1278
+ }
1432
1279
  }
1433
1280
 
1434
1281
  var proto$3 = `
@@ -1438,15 +1285,15 @@ message PeernetResponseMessage {
1438
1285
  }
1439
1286
  `;
1440
1287
 
1441
- class ResponseMessage extends FormatInterface {
1442
- get keys() {
1443
- return ['response']
1444
- }
1445
-
1446
- constructor(data) {
1447
- const name = 'peernet-response';
1448
- super(data, protons(proto$3).PeernetResponseMessage, {name});
1449
- }
1288
+ class ResponseMessage extends FormatInterface {
1289
+ get keys() {
1290
+ return ['response']
1291
+ }
1292
+
1293
+ constructor(data) {
1294
+ const name = 'peernet-response';
1295
+ super(data, protons(proto$3).PeernetResponseMessage, {name});
1296
+ }
1450
1297
  }
1451
1298
 
1452
1299
  var proto$2 = `
@@ -1456,15 +1303,15 @@ message PeernetPeerMessageResponse {
1456
1303
  }
1457
1304
  `;
1458
1305
 
1459
- class PeerMessageResponse extends FormatInterface {
1460
- get keys() {
1461
- return ['id']
1462
- }
1463
-
1464
- constructor(data) {
1465
- const name = 'peernet-peer-response';
1466
- super(data, protons(proto$2).PeernetPeerMessageResponse, {name});
1467
- }
1306
+ class PeerMessageResponse extends FormatInterface {
1307
+ get keys() {
1308
+ return ['id']
1309
+ }
1310
+
1311
+ constructor(data) {
1312
+ const name = 'peernet-peer-response';
1313
+ super(data, protons(proto$2).PeernetPeerMessageResponse, {name});
1314
+ }
1468
1315
  }
1469
1316
 
1470
1317
  var proto$1 = `
@@ -1475,15 +1322,15 @@ message PeernetDataMessageResponse {
1475
1322
  }
1476
1323
  `;
1477
1324
 
1478
- class DataMessageResponse extends FormatInterface {
1479
- get keys() {
1480
- return ['hash', 'data']
1481
- }
1482
-
1483
- constructor(data) {
1484
- const name = 'peernet-data-response';
1485
- super(data, protons(proto$1).PeernetDataMessageResponse, {name});
1486
- }
1325
+ class DataMessageResponse extends FormatInterface {
1326
+ get keys() {
1327
+ return ['hash', 'data']
1328
+ }
1329
+
1330
+ constructor(data) {
1331
+ const name = 'peernet-data-response';
1332
+ super(data, protons(proto$1).PeernetDataMessageResponse, {name});
1333
+ }
1487
1334
  }
1488
1335
 
1489
1336
  var proto = `
@@ -1494,15 +1341,15 @@ message ChatMessage {
1494
1341
  repeated string files = 4;
1495
1342
  }`;
1496
1343
 
1497
- class ChatMessage extends FormatInterface {
1498
- get keys() {
1499
- return ['author', 'value', 'timestamp', 'files']
1500
- }
1501
-
1502
- constructor(buffer) {
1503
- const name = 'chat-message';
1504
- super(buffer, protons(proto).ChatMessage, {name});
1505
- }
1344
+ class ChatMessage extends FormatInterface {
1345
+ get keys() {
1346
+ return ['author', 'value', 'timestamp', 'files']
1347
+ }
1348
+
1349
+ constructor(buffer) {
1350
+ const name = 'chat-message';
1351
+ super(buffer, protons(proto).ChatMessage, {name});
1352
+ }
1506
1353
  }
1507
1354
 
1508
1355
  const debug = (log) => {
@@ -1524,7 +1371,7 @@ const protoFor = (data) => {
1524
1371
  */
1525
1372
  const hasDaemon = async () => {
1526
1373
  try {
1527
- let response = await fetch$1('http://127.0.0.1:1000/api/version');
1374
+ let response = await fetch('http://127.0.0.1:1000/api/version');
1528
1375
  response = await response.json();
1529
1376
  return Boolean(response.client === '@peernet/api/http')
1530
1377
  } catch (e) {
@@ -1660,7 +1507,7 @@ const getAddress = async () => {
1660
1507
  const {address} = lastFetched;
1661
1508
  const now = Math.round(new Date().getTime() / 1000);
1662
1509
  if (now - address.timestamp > 1200000) {
1663
- address.value = await fetch$1('https://icanhazip.com/');
1510
+ address.value = await fetch('https://icanhazip.com/');
1664
1511
  address.value = await address.value.text();
1665
1512
  address.timestamp = Math.round(new Date().getTime() / 1000);
1666
1513
  lastFetched.address = address;
@@ -1702,7 +1549,7 @@ class DhtEarth {
1702
1549
  async getCoordinates(address) {
1703
1550
  // const {address} = parseAddress(provider)
1704
1551
  const request = `https://whereis.leofcoin.org/?ip=${address}`;
1705
- let response = await fetch$1(request);
1552
+ let response = await fetch(request);
1706
1553
  response = await response.json();
1707
1554
  const {lat, lon} = response;
1708
1555
  return {latitude: lat, longitude: lon}
@@ -1760,93 +1607,441 @@ class DhtEarth {
1760
1607
  }
1761
1608
  }
1762
1609
 
1610
+ var testnets = {
1611
+ 'leofcoin:olivia': {
1612
+ messagePrefix: '\u0019Leofcoin Signed Message:',
1613
+ pubKeyHash: 0x73, // o
1614
+ scriptHash: 0x76, // p
1615
+ multiTxHash: 0x8b4125, // omtx
1616
+ payments: {
1617
+ version: 0,
1618
+ unspent: 0x1fa443d7 // ounsp
1619
+ },
1620
+ wif: 0x7D, // s
1621
+ multiCodec: 0x7c4,
1622
+ bip32: { public: 0x13BBF2D5, private: 0x13BBCBC5 }
1623
+ },
1624
+ 'bitcoin:testnet': {
1625
+ messagePrefix: '\x18Bitcoin Signed Message:\n',
1626
+ bech32: 'tb',
1627
+ pubKeyHash: 0x6f,
1628
+ scriptHash: 0xc4,
1629
+ wif: 0xef,
1630
+ bip32: {
1631
+ public: 0x043587cf,
1632
+ private: 0x04358394
1633
+ }
1634
+ }
1635
+
1636
+ };
1637
+
1638
+ // https://en.bitcoin.it/wiki/List_of_address_prefixes
1763
1639
  /**
1764
- * @params {String} network
1765
- * @return {object} { identity, accounts, config }
1640
+ * Main network
1641
+ * @return {messagePrefix, pubKeyHash, scriptHash, wif, bip32}
1766
1642
  */
1767
- var generateAccount = async network => {
1768
- const wallet = new MultiWallet(network);
1769
- /**
1770
- * @type {string}
1771
- */
1772
- const mnemonic = await wallet.generate();
1773
- /**
1774
- * @type {object}
1775
- */
1776
- const account = wallet.account(0);
1777
- /**
1778
- * @type {object}
1779
- */
1780
- const external = account.external(0);
1781
- const internal = account.internal(0);
1782
-
1783
- return {
1784
- identity: {
1785
- mnemonic,
1786
- multiWIF: wallet.export(),
1787
- publicKey: external.publicKey,
1788
- privateKey: external.privateKey,
1789
- walletId: external.id
1790
- },
1791
- accounts: [['main account', external.address, internal.address]],
1792
- config: {
1793
- miner: {
1794
- intensity: 1,
1795
- address: external.address,
1796
- donationAddress: undefined,
1797
- donationAmount: 1 //percent
1798
- }
1799
- }
1800
- }
1801
- };
1643
+ const leofcoin = {
1644
+ messagePrefix: '\u0019Leofcoin Signed Message:',
1645
+ pubKeyHash: 0x30, // L
1646
+ scriptHash: 0x37, // P
1647
+ multiTxHash: 0x3adeed, // Lmtx
1648
+ payments: {
1649
+ version: 0,
1650
+ unspent: 0x0d6e0327 // Lunsp
1651
+ },
1652
+ coin_type: 640,
1653
+ wif: 0x3F, // S
1654
+ multiCodec: 0x3c4,
1655
+ bip32: { public: 0x13BBF2D4, private: 0x13BBCBC4 },
1656
+ testnet: testnets['leofcoin:olivia']
1657
+ };
1658
+
1659
+ const bitcoin = {
1660
+ messagePrefix: '\x18Bitcoin Signed Message:\n',
1661
+ bech32: 'bc',
1662
+ pubKeyHash: 0x00,
1663
+ scriptHash: 0x05,
1664
+ wif: 0x80,
1665
+ coin_type: 0,
1666
+ bip32: {
1667
+ public: 0x0488b21e, private: 0x0488ade4
1668
+ },
1669
+ testnet: testnets['bitcoin:testnet']
1670
+ };
1671
+
1672
+ const litecoin = {
1673
+ messagePrefix: '\x19Litecoin Signed Message:\n',
1674
+ pubKeyHash: 0x30,
1675
+ scriptHash: 0x32,
1676
+ wif: 0xb0,
1677
+ bip32: {
1678
+ public: 0x019da462,
1679
+ private: 0x019d9cfe
1680
+ }
1681
+ };
1682
+
1683
+ const ethereum = {
1684
+ messagePrefix: '\x19Ethereum Signed Message:\n',
1685
+ pubKeyHash: 0x30,
1686
+ scriptHash: 0x32,
1687
+ bip32: {
1688
+ private: 0x0488ADE4, public: 0x0488B21E
1689
+ },
1690
+ coin_type: 60,
1691
+ wif: 0x45,//E
1692
+ multiCodec: 0x3c5
1693
+ };
1694
+
1695
+ /**
1696
+ * Our & supported networks
1697
+ * @return {leofcoin, olivia}
1698
+ */
1699
+ var networks = {
1700
+ leofcoin,
1701
+ bitcoin,
1702
+ litecoin,
1703
+ ethereum
1704
+ };
1802
1705
 
1803
- class MessageHandler {
1804
- constructor(network) {
1805
- this.network = network;
1806
- }
1807
- /**
1808
- * hash and sign message
1809
- *
1810
- * @param {object} message
1811
- * @param {Buffer} message.from peer id
1812
- * @param {Buffer} message.to peer id
1813
- * @param {string} message.data Peernet message
1814
- * (PeernetMessage excluded) encoded as a string
1815
- * @return signature
1816
- */
1817
- async hashAndSignMessage(message) {
1818
- const hasher = new PeernetHash(message, {name: 'peernet-message'});
1819
- const identity = await walletStore.get('identity');
1706
+ const fromNetworkString = network => {
1707
+ const parts = network.split(':');
1708
+ network = networks[parts[0]];
1709
+ if (parts[1]) {
1710
+ if (network[parts[1]]) network = network[parts[1]];
1711
+
1712
+ network.coin_type = 1;
1713
+ }
1714
+ return network;
1715
+ };
1820
1716
 
1821
- const wallet = new MultiWallet(this.network);
1822
- wallet.import(identity.multiWIF);
1823
- return wallet.sign(hasher.hash.slice(0, 32))
1824
- }
1717
+ const { encode: encode$1, decode: decode$1 } = bs58check__default;
1718
+ class HDWallet {
1719
+
1720
+ get chainCodeBuffer() {
1721
+ return this.ifNotLocked(() => this.hdnode.chainCode)
1722
+ }
1723
+
1724
+ get chainCode() {
1725
+ return this.ifNotLocked(() => this.chainCodeBuffer.toString('hex'))
1726
+ }
1727
+
1728
+ get privateKeyBuffer() {
1729
+ return this.ifNotLocked(() => this.hdnode.privateKey)
1730
+ }
1731
+
1732
+ get privateKey() {
1733
+ return this.ifNotLocked(() => this.privateKeyBuffer.toString('hex'))
1734
+ }
1735
+
1736
+ get publicKeyBuffer() {
1737
+ return this.ifNotLocked(() => this.hdnode.publicKey)
1738
+ }
1739
+
1740
+ get publicKey() {
1741
+ return this.ifNotLocked(() => this.publicKeyBuffer.toString('hex'))
1742
+ }
1743
+
1744
+ get address() {
1745
+ // override testnet coin_type
1746
+ let coin_type = this.hdnode.network.coin_type;
1747
+ if (coin_type === 1) {
1748
+ if (this.networkName?.split(':')[0] === 'ethereum') coin_type = 60;
1749
+ if (this.networkName?.split(':')[0] === 'leofcoin') coin_type = 640;
1750
+ }
1751
+ if (coin_type === 60 || coin_type === 640) {
1752
+ let buffer = ecc.pointFromScalar(this.hdnode.__D, false);
1753
+ buffer = Buffer.from(publicKeyConvert(buffer, false)).slice(1);
1754
+ let hash = createKeccakHash('keccak256').update(buffer).digest();
1755
+ return hash.slice(-20).toString('hex')
1756
+ }
1757
+ return encode$1(this.neutered.publicKeyBuffer)
1758
+ }
1759
+
1760
+ get accountAddress() {
1761
+ return this.ifNotLocked(() => encode$1(this.hdnode.publicKeyBuffer))
1762
+ }
1763
+
1764
+ get isTestnet() {
1765
+ if (typeof network === 'string')
1766
+ this.hdnode.network = fromNetworkString(network);
1767
+
1768
+ return Boolean(this.hdnode.network.coin_type === 1)
1769
+ }
1770
+
1771
+ constructor(network, hdnode) {
1772
+ if (typeof network === 'string') {
1773
+ this.networkName = network;
1774
+ this.network = fromNetworkString(network);
1775
+ } else if (typeof network === 'object')
1776
+ this.network = network;
1777
+
1778
+ if (hdnode) this.defineHDNode(hdnode);
1779
+ }
1780
+
1781
+ ifNotLocked(fn, params) {
1782
+ if (!this.locked) return fn(params);
1783
+ return null
1784
+ }
1785
+
1786
+ defineHDNode(value) {
1787
+ Object.defineProperty(this, 'hdnode', {
1788
+ configurable: false,
1789
+ writable: false,
1790
+ value: value
1791
+ });
1792
+ }
1793
+
1794
+ validateNetwork(network) {
1795
+ if (!network && !this.network) return console.error(`expected network to be defined`);
1796
+ if (!network && this.network) network = this.network;
1797
+ if (typeof network === 'string') network = fromNetworkString(network);
1798
+ if (typeof network !== 'object') return console.error('network not found');
1799
+ return network;
1800
+ }
1801
+
1802
+ async generate(network) {
1803
+ network = this.validateNetwork(network);
1804
+ const mnemonic = generateMnemonic();
1805
+ const seed = await mnemonicToSeed(mnemonic);
1806
+ this.defineHDNode(bip32.fromSeed(seed, network));
1807
+ return mnemonic; // userpw
1808
+ }
1809
+
1810
+ /**
1811
+ * recover using mnemonic (recovery word list)
1812
+ */
1813
+ async recover(mnemonic, network) {
1814
+ network = this.validateNetwork(network);
1815
+ const seed = await mnemonicToSeed(mnemonic);
1816
+ this.defineHDNode(bip32.fromSeed(seed, network));
1817
+ }
1818
+
1819
+ load(base58, network) {
1820
+ network = this.validateNetwork(network);
1821
+ this.defineHDNode(bip32.fromBase58(base58, network));
1822
+ }
1823
+
1824
+ save() {
1825
+ return this.hdnode.toBase58();
1826
+ }
1827
+
1828
+ fromAddress(address, chainCode, network) {
1829
+ network = this.validateNetwork(network);
1830
+ // if (network.coin_type === 60) {
1831
+ // address = Buffer.from(address, 'hex')
1832
+ // } else {
1833
+ address = decode$1(address);
1834
+ // }
1835
+
1836
+ if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = address.slice(1);
1837
+ this.defineHDNode(bip32.fromPublicKey(address, chainCode, network));
1838
+ }
1839
+
1840
+ fromPublicKey(hex, chainCode, network) {
1841
+ network = this.validateNetwork(network);
1842
+ if (!Buffer.isBuffer(hex)) hex = Buffer.from(hex, 'hex');
1843
+ if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = hex.slice(1);
1844
+ this.defineHDNode(bip32.fromPublicKey(hex, chainCode, network));
1845
+ }
1846
+ }
1825
1847
 
1826
- /**
1827
- * @param {String} from - peer id
1828
- * @param {String} to - peer id
1829
- * @param {String|PeernetMessage} data - data encoded message string
1830
- * or the messageNode itself
1831
- */
1832
- async prepareMessage(from, to, data) {
1833
- if (!Buffer.isBuffer(from)) from = new Buffer.from(from);
1834
- if (!Buffer.isBuffer(to)) to = new Buffer.from(to);
1835
- if (data.encoded) data = data.encoded;
1836
-
1837
- const message = {
1838
- from,
1839
- to,
1840
- data,
1841
- };
1842
- const signature = await this.hashAndSignMessage(message);
1843
- const node = new PeernetMessage({
1844
- ...message,
1845
- signature,
1846
- });
1848
+ const { encode, decode } = bs58check;
1849
+
1850
+ // TODO: multihash addresses
1851
+ class HDAccount {
1852
+ /**
1853
+ * @param {number} depth - acount depth
1854
+ */
1855
+ constructor(node, depth = 0) {
1856
+ this.node = node;
1857
+ this.depth = depth;
1858
+ this._prefix = `m/44'/${node.network.coin_type}'/${depth}'/`;
1859
+ }
1860
+
1861
+ /**
1862
+ * @param {number} index - address index
1863
+ */
1864
+ internal(index = 0) {
1865
+ return this.node.derivePath(`${this._prefix}1/${index}`)
1866
+ }
1867
+
1868
+ /**
1869
+ * @param {number} index - address index
1870
+ */
1871
+ external(index = 0) {
1872
+ return this.node.derivePath(`${this._prefix}0/${index}`)
1873
+ }
1874
+ }
1875
+
1876
+ class MultiWallet extends HDWallet {
1877
+ constructor(network, hdnode) {
1878
+ const networkName = network;
1879
+ super(network, hdnode);
1880
+ if (typeof networkName === 'string') this.networkName = networkName;
1881
+ this.multiCodec = this.network.multiCodec;
1882
+ this.version = 0x00;
1883
+ }
1884
+
1885
+ get id() {
1886
+ const buffer = Buffer.concat([
1887
+ Buffer.from(varint.encode(this.multiCodec)),
1888
+ Buffer.from(this.account(0).node.neutered.publicKey, 'hex')
1889
+ ]);
1890
+ return encode(buffer)
1891
+ }
1892
+
1893
+ get multiWIF() {
1894
+ return this.ifNotLocked(() => this.encode())
1895
+ }
1896
+
1897
+ get neutered() {
1898
+ const neutered = this.ifNotLocked(() => new MultiWallet(this.network, this.hdnode.neutered()));
1899
+ if (neutered) this._neutered = neutered;
1900
+ return this._neutered
1901
+ }
1902
+
1903
+ fromId(id) {
1904
+ let buffer = decode(id);
1905
+ varint.decode(buffer);
1906
+ buffer = buffer.slice(varint.decode.bytes);
1907
+ this.fromPublicKey(buffer, null, this.network);
1908
+ }
1909
+
1910
+ lock(key, multiWIF) {
1911
+ if (!multiWIF) multiWIF = this.multiWIF;
1912
+ this.encrypted = AES.encrypt(multiWIF.toString('hex'), key).toString();
1913
+ this.locked = true;
1914
+ }
1915
+
1916
+ unlock(key, encrypted) {
1917
+ if (!encrypted) encrypted = this.encrypted;
1918
+ this.import(AES.decrypt(encrypted, key).toString(ENC));
1919
+ this.locked = false;
1920
+ }
1921
+
1922
+ export() {
1923
+ return this.encode();
1924
+ }
1925
+
1926
+ /**
1927
+ * encodes the multiWIF and loads wallet from bs58
1928
+ *
1929
+ * @param {multiWIF} multiWIF - note a multiWIF is not the same as a wif
1930
+ */
1931
+ import(multiWIF) {
1932
+ const { bs58, version, multiCodec } = this.decode(multiWIF);
1933
+ this.network = Object.values(networks).reduce((p, c) => {
1934
+ if (c.multiCodec===multiCodec) return c
1935
+ else if (c.testnet && c.testnet.multiCodec === multiCodec) return c.testnet
1936
+ else return p
1937
+ }, networks['leofcoin']);
1938
+ this.load(bs58, this.network);
1939
+ }
1940
+
1941
+ /**
1942
+ * @return base58Check encoded string
1943
+ */
1944
+ encode() {
1945
+ const buffer = Buffer.concat([
1946
+ Buffer.from(varint.encode(this.version)),
1947
+ Buffer.from(varint.encode(this.multiCodec)),
1948
+ decode(this.save())
1949
+ ]);
1950
+ return encode(buffer);
1951
+ }
1952
+
1953
+ decode(bs58) {
1954
+ let buffer = decode(bs58);
1955
+ const version = varint.decode(buffer);
1956
+ buffer = buffer.slice(varint.decode.bytes);
1957
+ const multiCodec = varint.decode(buffer);
1958
+ buffer = buffer.slice(varint.decode.bytes);
1959
+ bs58 = encode(buffer);
1960
+ if (version !== this.version) throw TypeError('Invalid version');
1961
+ if (this.multiCodec !== multiCodec) throw TypeError('Invalid multiCodec');
1962
+ return { version, multiCodec, bs58 };
1963
+ }
1964
+
1965
+ sign(hash) {
1966
+ return new MultiSignature(this.version, this.network.multiCodec)
1967
+ .sign(hash, this.privateKeyBuffer);
1968
+
1969
+ }
1970
+
1971
+ verify(multiSignature, hash) {
1972
+ return new MultiSignature(this.version, this.network.multiCodec)
1973
+ .verify(multiSignature, hash, this.publicKeyBuffer)
1974
+ }
1975
+
1976
+ /**
1977
+ * @param {number} account - account to return chain for
1978
+ * @return { internal(addressIndex), external(addressIndex) }
1979
+ */
1980
+ account(index) {
1981
+ return new HDAccount(new MultiWallet(this.network, this.hdnode), index);
1982
+ }
1983
+
1984
+ /**
1985
+ * m / purpose' / coin_type' / account' / change / aadress_index
1986
+ *
1987
+ * see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
1988
+ */
1989
+ derivePath(path) {
1990
+ return new MultiWallet(this.network, this.hdnode.derivePath(path))
1991
+ }
1992
+
1993
+ derive(index) {
1994
+ return new MultiWallet(this.network, this.hdnode.derive(index));
1995
+ }
1996
+ }
1847
1997
 
1848
- return node
1849
- }
1998
+ class MessageHandler {
1999
+ constructor(network) {
2000
+ this.network = network;
2001
+ }
2002
+ /**
2003
+ * hash and sign message
2004
+ *
2005
+ * @param {object} message
2006
+ * @param {Buffer} message.from peer id
2007
+ * @param {Buffer} message.to peer id
2008
+ * @param {string} message.data Peernet message
2009
+ * (PeernetMessage excluded) encoded as a string
2010
+ * @return signature
2011
+ */
2012
+ async hashAndSignMessage(message) {
2013
+ const hasher = new PeernetHash(message, {name: 'peernet-message'});
2014
+ const identity = await walletStore.get('identity');
2015
+
2016
+ const wallet = new MultiWallet(this.network);
2017
+ wallet.import(identity.multiWIF);
2018
+ return wallet.sign(hasher.hash.slice(0, 32))
2019
+ }
2020
+
2021
+ /**
2022
+ * @param {String} from - peer id
2023
+ * @param {String} to - peer id
2024
+ * @param {String|PeernetMessage} data - data encoded message string
2025
+ * or the messageNode itself
2026
+ */
2027
+ async prepareMessage(from, to, data, id) {
2028
+ if (!Buffer.isBuffer(from)) from = new Buffer.from(from);
2029
+ if (!Buffer.isBuffer(to)) to = new Buffer.from(to);
2030
+ if (data.encoded) data = data.encoded;
2031
+
2032
+ const message = {
2033
+ from,
2034
+ to,
2035
+ data,
2036
+ };
2037
+ const signature = await this.hashAndSignMessage(message);
2038
+ const node = new PeernetMessage({
2039
+ ...message,
2040
+ signature,
2041
+ });
2042
+
2043
+ return node
2044
+ }
1850
2045
  }
1851
2046
 
1852
2047
  const encapsulatedError = () => {
@@ -1925,7 +2120,7 @@ class Peernet {
1925
2120
  if (this.hasDaemon) {
1926
2121
  Storage = LeofcoinStorageClient;
1927
2122
  } else {
1928
- Storage = LeofcoinStorage$1;
2123
+ Storage = LeofcoinStorage;
1929
2124
  }
1930
2125
  globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
1931
2126
  await new Storage(`${prefix}-${name}`, root);
@@ -2007,13 +2202,7 @@ class Peernet {
2007
2202
  const {daemon, environment} = await target();
2008
2203
  this.hasDaemon = daemon;
2009
2204
 
2010
- if (this.hasDaemon) {
2011
- globalThis.peernet.client = await httpClient({
2012
- protocol: 'peernet-v0.1.0', host: '127.0.0.1', port: options.port,
2013
- });
2014
- } else {
2015
- if (environment !== 'browser') http(options);
2016
- }
2205
+ HTTP_IMPORT;
2017
2206
 
2018
2207
  for (const store of this.defaultStores) {
2019
2208
  await this.addStore(store, options.storePrefix, options.root);
@@ -2039,42 +2228,41 @@ class Peernet {
2039
2228
  }
2040
2229
  }
2041
2230
  this._peerHandler = new PeerDiscovery(this.id);
2042
- // peernet id
2043
- const id = Buffer.from(this.id.slice(0, 32));
2044
- this.peerId = id;
2045
-
2046
- pubsub.subscribe('peer:discovered', async (peer) => {
2047
- peer.on('peernet.data', async (message) => {
2048
- const id = message.id;
2049
- message = new PeernetMessage(Buffer.from(message.data.data));
2050
- const proto = protoFor(message.decoded.data);
2051
- await this._protoHandler({id, proto}, peer);
2052
- });
2053
- await this._peerHandler.discover(peer);
2054
- const fulldId = this._getPeerId(peer.id);
2055
- if (fulldId && this._discovered.indexOf(peer.id) === -1) {
2056
- this._discovered.push(peer.id);
2057
- pubsub.publish('peer:connected', peer);
2058
- }
2059
- });
2060
- pubsub.subscribe('peer:disconnected', async (peer) => {
2061
- let index = this._discovered.indexOf(peer.id);
2062
- if (index !== -1) this._discovered.splice(index, 1);
2063
- const id = this._getPeerId(peer.id);
2064
- let peerIds = this.peerMap.get(id);
2065
-
2066
- if (peerIds) {
2067
- index = peerIds.indexOf(peer.id);
2068
- if (index !== -1) peerIds.splice(index, 1);
2069
- } else {
2070
- peerIds = [];
2071
- }
2072
-
2073
- if (peerIds.length === 0) this.peerMap.delete(id);
2074
- else this.peerMap.set(id, peerIds);
2075
- });
2231
+ this.peerId = this.id;
2232
+
2233
+ // pubsub.subscribe('peer:discovered', async (peer) => {
2234
+ // peer.on('peernet.data', async (message) => {
2235
+ // const id = message.id;
2236
+ // message = new PeernetMessage(Buffer.from(message.data.data));
2237
+ // const proto = protoFor(message.decoded.data);
2238
+ // await this._protoHandler({id, proto}, peer);
2239
+ // });
2240
+ // await this._peerHandler.discover(peer);
2241
+ // const fulldId = this._getPeerId(peer.id);
2242
+ // if (fulldId && this._discovered.indexOf(peer.id) === -1) {
2243
+ // this._discovered.push(peer.id);
2244
+ // pubsub.publish('peer:connected', peer);
2245
+ // }
2246
+ // });
2247
+ // pubsub.subscribe('peer:disconnected', async (peer) => {
2248
+ // let index = this._discovered.indexOf(peer.id)
2249
+ // if (index !== -1) this._discovered.splice(index, 1)
2250
+ // const id = this._getPeerId(peer.id)
2251
+ // let peerIds = this.peerMap.get(id)
2252
+ //
2253
+ // if (peerIds) {
2254
+ // index = peerIds.indexOf(peer.id)
2255
+ // if (index !== -1) peerIds.splice(index, 1)
2256
+ // } else {
2257
+ // peerIds = []
2258
+ // }
2259
+ //
2260
+ // if (peerIds.length === 0) this.peerMap.delete(id)
2261
+ // else this.peerMap.set(id, peerIds)
2262
+ // })
2076
2263
  pubsub.subscribe('peer:connected', async (peer) => {
2077
- console.log({connected: peer.id, as: this._getPeerId(peer.id) });
2264
+ console.log(peer);
2265
+ // console.log({connected: peer.id, as: this._getPeerId(peer.id) });
2078
2266
  // peer.on('peernet.data', async (message) => {
2079
2267
  // const id = message.id
2080
2268
  // message = new PeernetMessage(Buffer.from(message.data.data))
@@ -2083,11 +2271,27 @@ class Peernet {
2083
2271
  // })
2084
2272
  });
2085
2273
 
2274
+ pubsub.subscribe('peer:data', async message => {
2275
+ console.log({message});
2276
+ if (!message.data) return
2277
+ const {id, data} = JSON.parse(new TextDecoder().decode(message.data));
2278
+ const uint8Array = new Uint8Array(Object.keys(data).length);
2279
+ for (var i = 0; i < Object.keys(data).length; i++) {
2280
+ uint8Array[i] = data[i];
2281
+ }
2282
+ message = new PeernetMessage(uint8Array);
2283
+ const proto = protoFor(message.decoded.data);
2284
+
2285
+ console.log(message.decoded);
2286
+ const from = new TextDecoder().decode(message.decoded.from);
2287
+ this._protoHandler({id, proto}, this.client.connections[from], from);
2288
+ });
2289
+
2086
2290
  /**
2087
2291
  * @access public
2088
2292
  * @type {PeernetClient}
2089
2293
  */
2090
- this.client = new PeernetClient({...options, id});
2294
+ this.client = new Client(this.id);
2091
2295
  if (globalThis.onbeforeunload) {
2092
2296
  globalThis.addEventListener('beforeunload', async () => this.client.close());
2093
2297
  }
@@ -2112,55 +2316,56 @@ class Peernet {
2112
2316
  * @param {Buffer} message - peernet message
2113
2317
  * @param {PeernetPeer} peer - peernet peer
2114
2318
  */
2115
- async _protoHandler(message, peer) {
2319
+ async _protoHandler(message, peer, from) {
2116
2320
  const {id, proto} = message;
2321
+ console.log(message);
2117
2322
  this.bw.down += proto.encoded.length;
2118
- if (proto.name === 'peernet-peer') {
2119
- const from = proto.decoded.id;
2120
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2121
- else {
2122
- const connections = this.peerMap.get(from);
2123
- if (connections.indexOf(peer.id) === -1) {
2124
- connections.push(peer.id);
2125
- this.peerMap.set(from, connections);
2126
- }
2127
- }
2128
- const data = new PeerMessageResponse({id: this.id});
2129
- const node = await this.prepareMessage(from, data.encoded);
2130
-
2131
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2132
- this.bw.up += node.encoded.length;
2133
- } else if (proto.name === 'peernet-peer-response') {
2134
- const from = proto.decoded.id;
2135
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2136
- else {
2137
- const connections = this.peerMap.get(from);
2138
- if (connections.indexOf(peer.id) === -1) {
2139
- connections.push(peer.id);
2140
- this.peerMap.set(from, connections);
2141
- }
2142
- }
2143
- } else {
2144
- let from = this._getPeerId(peer.id);
2145
- if (!from) {
2146
- const data = new PeerMessage({id: this.id});
2147
- const node = await this.prepareMessage(peer.id, data.encoded);
2148
- this.bw.up += node.encoded.length;
2149
- let response = await peer.request(node.encoded);
2150
- response = protoFor(response);
2151
-
2152
- response = new PeerMessageResponse(response.decoded.data);
2153
-
2154
- from = response.decoded.id;
2155
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2156
- else {
2157
- const connections = this.peerMap.get(from);
2158
- if (connections.indexOf(peer.id) === -1) {
2159
- connections.push(peer.id);
2160
- this.peerMap.set(from, connections);
2161
- }
2162
- }
2163
- }
2323
+ // if (proto.name === 'peernet-peer') {
2324
+ // const from = proto.decoded.id
2325
+ // if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id])
2326
+ // else {
2327
+ // const connections = this.peerMap.get(from)
2328
+ // if (connections.indexOf(peer.id) === -1) {
2329
+ // connections.push(peer.id)
2330
+ // this.peerMap.set(from, connections)
2331
+ // }
2332
+ // }
2333
+ // const data = new PeerMessageResponse({id: this.id})
2334
+ // const node = await this.prepareMessage(from, data.encoded)
2335
+ //
2336
+ // peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})))
2337
+ // this.bw.up += node.encoded.length
2338
+ // } else if (proto.name === 'peernet-peer-response') {
2339
+ // const from = proto.decoded.id
2340
+ // if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id])
2341
+ // else {
2342
+ // const connections = this.peerMap.get(from)
2343
+ // if (connections.indexOf(peer.id) === -1) {
2344
+ // connections.push(peer.id)
2345
+ // this.peerMap.set(from, connections)
2346
+ // }
2347
+ // }
2348
+ // } else {
2349
+ // let from = this._getPeerId(peer.id)
2350
+ // if (!from) {
2351
+ // const data = new PeerMessage({id: this.id})
2352
+ // const node = await this.prepareMessage(peer.id, data.encoded)
2353
+ // this.bw.up += node.encoded.length
2354
+ // let response = await peer.request(node.encoded)
2355
+ // response = protoFor(response)
2356
+ //
2357
+ // response = new PeerMessageResponse(response.decoded.data)
2358
+ //
2359
+ // from = response.decoded.id
2360
+ // if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id])
2361
+ // else {
2362
+ // const connections = this.peerMap.get(from)
2363
+ // if (connections.indexOf(peer.id) === -1) {
2364
+ // connections.push(peer.id)
2365
+ // this.peerMap.set(from, connections)
2366
+ // }
2367
+ // }
2368
+ // }
2164
2369
  if (proto.name === 'peernet-dht') {
2165
2370
  let { hash, store } = proto.decoded;
2166
2371
  let has;
@@ -2175,7 +2380,7 @@ class Peernet {
2175
2380
  const data = new DHTMessageResponse({hash, has});
2176
2381
  const node = await this.prepareMessage(from, data.encoded);
2177
2382
 
2178
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2383
+ peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
2179
2384
  this.bw.up += node.encoded.length;
2180
2385
  } else if (proto.name === 'peernet-data') {
2181
2386
  let { hash, store } = proto.decoded;
@@ -2183,7 +2388,7 @@ class Peernet {
2183
2388
  if (!store) {
2184
2389
  store = await this.whichStore([...this.stores], hash);
2185
2390
  } else {
2186
- store = globalThis.stores[`${store}Store`];
2391
+ store = globalThis[`${store}Store`];
2187
2392
  }
2188
2393
  if (store && !store.private) {
2189
2394
  data = await store.get(hash);
@@ -2192,7 +2397,7 @@ class Peernet {
2192
2397
  data = new DataMessageResponse({hash, data: data.decoded ? Buffer.from(JSON.stringify(data)) : Buffer.from(data)});
2193
2398
 
2194
2399
  const node = await this.prepareMessage(from, data.encoded);
2195
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2400
+ peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
2196
2401
  this.bw.up += node.encoded.length;
2197
2402
  }
2198
2403
  }
@@ -2208,7 +2413,7 @@ class Peernet {
2208
2413
  const data = new PeerMessage({id: this.id});
2209
2414
  const node = await this.prepareMessage(from, data.encoded);
2210
2415
 
2211
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2416
+ peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
2212
2417
  this.bw.up += node.encoded.length;
2213
2418
  } else if (proto.name === 'peernet-request') {
2214
2419
  // TODO: make dynamic
@@ -2217,14 +2422,14 @@ class Peernet {
2217
2422
  if (method) {
2218
2423
  const data = await method();
2219
2424
  const node = await this.prepareMessage(from, data.encoded);
2220
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2425
+ peer.send(new TextEncoder().encode(JSON.stringify({id, data: node.encoded})));
2221
2426
  this.bw.up += node.encoded.length;
2222
2427
  }
2223
2428
  } else if (proto.name === 'peernet-ps' &&
2224
2429
  this._getPeerId(peer.id) !== this.id.toString()) {
2225
2430
  globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
2226
2431
  }
2227
- }
2432
+ // }
2228
2433
  }
2229
2434
 
2230
2435
  /**
@@ -2339,7 +2544,7 @@ class Peernet {
2339
2544
  if (this._getPeerId(peer.id) === id) return peer
2340
2545
  });
2341
2546
 
2342
- let data = new DataMessage({hash, store});
2547
+ let data = new DataMessage({hash, store: store.name ? store.name : store});
2343
2548
 
2344
2549
  const node = await this.prepareMessage(id, data.encoded);
2345
2550
  if (closest[0]) data = await closest[0].request(node.encoded);
@@ -2489,7 +2694,7 @@ class Peernet {
2489
2694
  if (peer.connection._connected) {
2490
2695
  if (peer.id.toString() !== this.peerId.toString()) {
2491
2696
  const node = await this.prepareMessage(peer.id, data.encoded);
2492
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2697
+ peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
2493
2698
  }
2494
2699
  } else {
2495
2700
  this.removePeer(peer);