@leofcoin/peernet 2.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/docs/automatic-transport.md +37 -0
- package/exports/browser/{client-CAC7RVMf.js → client-DKKzPSlb.js} +252 -76
- package/exports/browser/{messages-Dw86z0zq.js → messages-DCePyqKC.js} +1 -1
- package/exports/browser/{peernet-B2jRhqGI.js → peernet-DjddqiXc.js} +460 -18
- package/exports/browser/peernet.js +1 -1
- package/exports/peernet.js +445 -3
- package/exports/types/archive.d.ts +69 -0
- package/exports/types/peernet.d.ts +7 -1
- package/package.json +9 -5
- package/.esdoc.json +0 -10
- package/.gitattributes +0 -2
- package/.github/workflows/release.yml +0 -34
- package/.prettierrc +0 -7
- package/.travis.yml +0 -27
- package/BREAKING_CHANGES.md +0 -35
- package/deploy.js +0 -8
- package/exports/browser/browser-D-r0O9Qn.js +0 -53
- package/exports/browser/browser-DvU1xNFS.js +0 -147
- package/exports/browser/browser-_hiyXwPp.js +0 -147
- package/exports/browser/client-86Tnax66.js +0 -2224
- package/exports/browser/client-BFxJts6j.js +0 -2224
- package/exports/browser/client-BVhUamQG.js +0 -2200
- package/exports/browser/client-BzvWzzLv.js +0 -2224
- package/exports/browser/client-C9GBz2Tf.js +0 -2224
- package/exports/browser/client-CQzuu6At.js +0 -2224
- package/exports/browser/client-CVkFejdx.js +0 -2224
- package/exports/browser/client-Cj_UUO8W.js +0 -2224
- package/exports/browser/client-CrGaeBjj.js +0 -2224
- package/exports/browser/client-DDC8C510.js +0 -2224
- package/exports/browser/client-ERocgKET.js +0 -2224
- package/exports/browser/client-a8rws3cu.js +0 -2224
- package/exports/browser/identity-CYVPDmkf.js +0 -8402
- package/exports/browser/identity-ChyyZSve.js +0 -8397
- package/exports/browser/index-BD0Anx7_.js +0 -37
- package/exports/browser/index-Bxr5Iztg.js +0 -37
- package/exports/browser/messages-BFCmg6Vb.js +0 -212
- package/exports/browser/messages-BHIC2mQu.js +0 -212
- package/exports/browser/messages-CimzJ4wr.js +0 -210
- package/exports/browser/messages-Cjoa_LGO.js +0 -210
- package/exports/browser/messages-D7JxkkDW.js +0 -212
- package/exports/browser/messages-DH0tgNM9.js +0 -207
- package/exports/browser/messages-DVHcNvs_.js +0 -212
- package/exports/browser/messages-DqL_g2qw.js +0 -210
- package/exports/browser/messages-UKnuelZ7.js +0 -207
- package/exports/browser/messages-XgZZUMma.js +0 -212
- package/exports/browser/messages-kfFyctPL.js +0 -210
- package/exports/browser/messages-psROnfRi.js +0 -212
- package/exports/browser/peernet-B9VL4Xwe.js +0 -9522
- package/exports/browser/peernet-C-HNdrcd.js +0 -9528
- package/exports/browser/peernet-C4rOvyyU.js +0 -9661
- package/exports/browser/peernet-Ca1iM2tN.js +0 -9336
- package/exports/browser/peernet-CbI0-jFn.js +0 -9651
- package/exports/browser/peernet-CtHScDyh.js +0 -9524
- package/exports/browser/peernet-DfuxUK3u.js +0 -9525
- package/exports/browser/peernet-DiEcNDLD.js +0 -9655
- package/exports/browser/peernet-DtuRXOzP.js +0 -9653
- package/exports/browser/peernet-r_9IyzTe.js +0 -9336
- package/exports/browser/peernet-rcD5XL1y.js +0 -9590
- package/exports/browser/peernet-rw8HJGOz.js +0 -9597
- package/exports/messages-CHKVVTVE.js +0 -204
- package/exports/messages-DaUtFfBh.js +0 -207
- package/index.html +0 -19
- package/rollup.config.js +0 -143
- package/src/dht/dht.ts +0 -142
- package/src/discovery/peer-discovery.js +0 -75
- package/src/errors/errors.js +0 -12
- package/src/file-transfer.ts +0 -194
- package/src/handlers/data.js +0 -15
- package/src/handlers/message.js +0 -34
- package/src/identity.ts +0 -172
- package/src/messages/chat.ts +0 -13
- package/src/messages/data-response.ts +0 -13
- package/src/messages/data.ts +0 -17
- package/src/messages/dht-response.ts +0 -13
- package/src/messages/dht.ts +0 -21
- package/src/messages/file-link.ts +0 -17
- package/src/messages/file.ts +0 -17
- package/src/messages/peer-response.ts +0 -13
- package/src/messages/peer.ts +0 -13
- package/src/messages/peernet.ts +0 -13
- package/src/messages/ps.ts +0 -13
- package/src/messages/request.ts +0 -13
- package/src/messages/response.ts +0 -13
- package/src/messages.js +0 -12
- package/src/peer-info.js +0 -9
- package/src/peernet.ts +0 -1113
- package/src/prompts/password/browser.js +0 -1
- package/src/prompts/password/node.js +0 -6
- package/src/prompts/password.js +0 -1
- package/src/proto/chat-message.proto.js +0 -6
- package/src/proto/data-response.proto.js +0 -4
- package/src/proto/data.proto.js +0 -4
- package/src/proto/dht-response.proto.js +0 -4
- package/src/proto/dht.proto.js +0 -4
- package/src/proto/file-link.proto.js +0 -5
- package/src/proto/file.proto.js +0 -10
- package/src/proto/peer-response.proto.js +0 -3
- package/src/proto/peer.proto.js +0 -3
- package/src/proto/peernet.proto.js +0 -7
- package/src/proto/ps.proto.js +0 -4
- package/src/proto/request.proto.js +0 -4
- package/src/proto/response.proto.js +0 -3
- package/src/types.ts +0 -25
- package/src/utils/utils.js +0 -77
- package/test/all.js +0 -5
- package/test/client.js +0 -15
- package/test/codec.js +0 -56
- package/test/file-transfer.test.js +0 -81
- package/test/fresh-empty-store.js +0 -15
- package/test/hash.js +0 -14
- package/test/index.js +0 -6
- package/test/lastBlock.js +0 -7
- package/test/messages.js +0 -26
- package/test/peer-data-exchange.test.js +0 -52
- package/test/peer-file-exchange.test.js +0 -78
- package/test/peernet.js +0 -17
- package/test/peernet.test.js +0 -477
- package/test-output.log +0 -84
- package/test.js +0 -63
- package/test2.js +0 -13
- package/test3.js +0 -16
- package/test4.js +0 -7
- package/tsconfig.json +0 -13
package/test/peernet.test.js
DELETED
|
@@ -1,477 +0,0 @@
|
|
|
1
|
-
import test from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import { readFile } from 'node:fs/promises'
|
|
4
|
-
import { execFile } from 'node:child_process'
|
|
5
|
-
import { mkdtemp, rm } from 'node:fs/promises'
|
|
6
|
-
import { tmpdir } from 'node:os'
|
|
7
|
-
import { join } from 'node:path'
|
|
8
|
-
import { promisify } from 'node:util'
|
|
9
|
-
|
|
10
|
-
import Peernet from '../exports/peernet.js'
|
|
11
|
-
import Identity, { resolveAccountWallets } from '../exports/identity.js'
|
|
12
|
-
import MultiWallet from '@leofcoin/multi-wallet'
|
|
13
|
-
import { Codec, CodecHash } from '@leofcoin/codec-format-interface'
|
|
14
|
-
import { fromBase58, toBase58 } from '@vandeurenglenn/typed-array-utils'
|
|
15
|
-
|
|
16
|
-
const options = {
|
|
17
|
-
network: 'leofcoin:peach',
|
|
18
|
-
stars: [],
|
|
19
|
-
root: `.testnet-${process.pid}`,
|
|
20
|
-
version: '1.0.0',
|
|
21
|
-
storePrefix: 'test',
|
|
22
|
-
autoStart: false
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const password = 'password'
|
|
26
|
-
const peernet = await new Peernet(options, password)
|
|
27
|
-
const execFileAsync = promisify(execFile)
|
|
28
|
-
|
|
29
|
-
test('freshIdentity initializes against a completely empty store root', async () => {
|
|
30
|
-
const root = await mkdtemp(join(tmpdir(), 'peernet-fresh-identity-'))
|
|
31
|
-
try {
|
|
32
|
-
const { stdout } = await execFileAsync(process.execPath, ['test/fresh-empty-store.js', root], {
|
|
33
|
-
cwd: new URL('..', import.meta.url),
|
|
34
|
-
timeout: 20_000
|
|
35
|
-
})
|
|
36
|
-
assert.match(stdout, /FRESH_IDENTITY_READY/)
|
|
37
|
-
} finally {
|
|
38
|
-
await rm(root, { recursive: true, force: true })
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
test('node bundle uses a portable password prompt import', async () => {
|
|
43
|
-
const identityBundle = await readFile(new URL('../exports/identity.js', import.meta.url), 'utf8')
|
|
44
|
-
assert.match(identityBundle, /import\(['"]\.\/prompts\/password\.js['"]\)/)
|
|
45
|
-
assert.doesNotMatch(identityBundle, /(?:\/home\/|\/Users\/|[A-Za-z]:\\)/)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
test('initializes with provided options', () => {
|
|
49
|
-
assert.equal(peernet.network, options.network)
|
|
50
|
-
assert.equal(peernet.version, options.version)
|
|
51
|
-
assert.equal(peernet.storePrefix, options.storePrefix)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test('exposes identity instance', () => {
|
|
55
|
-
assert.ok(peernet.identity instanceof Identity)
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
test('built peernet messages use canonical codec-first hashes', async () => {
|
|
59
|
-
const message = new peernet.protos['peernet-ps']({ data: new Uint8Array([1, 2, 3]), topic: new Uint8Array([4]) })
|
|
60
|
-
const hash = new CodecHash()
|
|
61
|
-
hash.fromBs32(await message.hash())
|
|
62
|
-
assert.equal(hash.name, 'peernet-ps')
|
|
63
|
-
assert.equal(hash.size, hash.digest.length)
|
|
64
|
-
const codec = new Codec('peernet-ps').encode()
|
|
65
|
-
assert.deepEqual(hash.encoded.subarray(0, codec.length), codec)
|
|
66
|
-
assert.deepEqual(hash.encoded, new Uint8Array([...codec, ...hash.length, ...hash.digest]))
|
|
67
|
-
const roundTrip = new peernet.protos['peernet-ps'](message.encoded)
|
|
68
|
-
assert.equal(await roundTrip.hash(), hash.toBs32())
|
|
69
|
-
assert.deepEqual(roundTrip.decoded.data, message.decoded.data)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
test('hash parser rejects old length-first peernet content addresses', async () => {
|
|
73
|
-
const message = new peernet.protos['peernet-ps']({ data: new Uint8Array([1, 2, 3]), topic: new Uint8Array([4]) })
|
|
74
|
-
const hash = new CodecHash()
|
|
75
|
-
hash.fromBs32(await message.hash())
|
|
76
|
-
const previousFormat = new Uint8Array([...hash.length, ...hash.codec, ...hash.digest])
|
|
77
|
-
assert.throws(() => new CodecHash().decode(previousFormat))
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
test('release dependency graph contains only codec 2.x and no Git varint fallback', async () => {
|
|
81
|
-
const manifest = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'))
|
|
82
|
-
const lock = JSON.parse(await readFile(new URL('../package-lock.json', import.meta.url), 'utf8'))
|
|
83
|
-
assert.equal(manifest.dependencies['@leofcoin/codec-format-interface'], '^2.0.0')
|
|
84
|
-
assert.equal(lock.packages[''].version, manifest.version)
|
|
85
|
-
const codecs = Object.entries(lock.packages).filter(([name]) => name.endsWith('/@leofcoin/codec-format-interface'))
|
|
86
|
-
assert.equal(codecs.length, 1)
|
|
87
|
-
assert.equal(codecs[0][1].version, '2.0.0')
|
|
88
|
-
for (const [name, entry] of Object.entries(lock.packages)) {
|
|
89
|
-
assert.ok(!name.endsWith('/varint'), name)
|
|
90
|
-
assert.ok(!/^(git\+|git:|github:|file:)/.test(entry.resolved ?? ''), name)
|
|
91
|
-
}
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
test('freshIdentity replaces a persisted identity and signer', async () => {
|
|
95
|
-
const originalId = peernet.id
|
|
96
|
-
const originalAccount = peernet.selectedAccount
|
|
97
|
-
const replacement = await new Peernet({ ...options, freshIdentity: true }, password)
|
|
98
|
-
|
|
99
|
-
assert.notEqual(replacement.id, originalId)
|
|
100
|
-
assert.notEqual(replacement.selectedAccount, originalAccount)
|
|
101
|
-
assert.equal(new TextDecoder().decode(await globalThis.walletStore.get('selected-account')), replacement.selectedAccount)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
test('has a DHT instance', () => {
|
|
105
|
-
assert.ok(peernet.dht)
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
test('returns peers and connections safely', () => {
|
|
109
|
-
assert.deepEqual(peernet.peers, [])
|
|
110
|
-
assert.deepEqual(peernet.connections, {})
|
|
111
|
-
assert.equal(peernet.getConnection('missing'), undefined)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
test('provides callable helpers', () => {
|
|
115
|
-
assert.equal(typeof peernet.addProto, 'function')
|
|
116
|
-
assert.equal(typeof peernet.addCodec, 'function')
|
|
117
|
-
assert.equal(typeof peernet.prepareMessage, 'function')
|
|
118
|
-
assert.equal(typeof peernet.publish, 'function')
|
|
119
|
-
assert.equal(typeof peernet.subscribe, 'function')
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
test('pubsub subscribe registers callback', async () => {
|
|
123
|
-
const topic = 'test-topic'
|
|
124
|
-
let callbackCalled = false
|
|
125
|
-
|
|
126
|
-
const callback = () => {
|
|
127
|
-
callbackCalled = true
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Subscribe to topic
|
|
131
|
-
await peernet.subscribe(topic, callback)
|
|
132
|
-
|
|
133
|
-
// Manually publish to globalSub to test subscription registration
|
|
134
|
-
globalThis.globalSub.publish(topic, 'test-data')
|
|
135
|
-
|
|
136
|
-
// Give async operation a moment to process
|
|
137
|
-
await new Promise((resolve) => setTimeout(resolve, 10))
|
|
138
|
-
|
|
139
|
-
assert.ok(callbackCalled)
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
test('addProto registers protocol', () => {
|
|
143
|
-
const protoName = 'test-protocol'
|
|
144
|
-
const protoObject = { test: 'data' }
|
|
145
|
-
|
|
146
|
-
peernet.addProto(protoName, protoObject)
|
|
147
|
-
|
|
148
|
-
assert.equal(globalThis.peernet.protos[protoName], protoObject)
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
test('addProto does not overwrite existing protocol', () => {
|
|
152
|
-
const protoName = 'existing-proto'
|
|
153
|
-
const originalProto = { original: true }
|
|
154
|
-
const newProto = { new: true }
|
|
155
|
-
|
|
156
|
-
peernet.addProto(protoName, originalProto)
|
|
157
|
-
const firstRegistered = globalThis.peernet.protos[protoName]
|
|
158
|
-
|
|
159
|
-
peernet.addProto(protoName, newProto)
|
|
160
|
-
const afterSecondAdd = globalThis.peernet.protos[protoName]
|
|
161
|
-
|
|
162
|
-
assert.equal(firstRegistered, originalProto)
|
|
163
|
-
assert.equal(afterSecondAdd, originalProto)
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
test('addCodec is callable', () => {
|
|
167
|
-
const mockCodec = { name: 'test-codec' }
|
|
168
|
-
// addCodec may return undefined, just verify it doesn't throw
|
|
169
|
-
assert.equal(typeof peernet.addCodec, 'function')
|
|
170
|
-
peernet.addCodec(mockCodec)
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
test('selectAccount delegates to identity', () => {
|
|
174
|
-
const accountName = 'test-account'
|
|
175
|
-
// selectAccount may return undefined, just verify it doesn't throw
|
|
176
|
-
assert.equal(typeof peernet.selectAccount, 'function')
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
test('identity has loaded account data', () => {
|
|
180
|
-
assert.ok(peernet.identity.accounts !== undefined)
|
|
181
|
-
assert.ok(peernet.identity.selectedAccount !== undefined)
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
test('peerId matches identity id', () => {
|
|
185
|
-
assert.equal(peernet.peerId, peernet.identity.id)
|
|
186
|
-
assert.equal(peernet.id, peernet.identity.id)
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
test('data store operations', () => {
|
|
190
|
-
const hash = 'test-hash-123'
|
|
191
|
-
const testData = new Uint8Array([1, 2, 3, 4, 5])
|
|
192
|
-
|
|
193
|
-
// Test put operation - may hang, so just verify method exists
|
|
194
|
-
assert.equal(typeof peernet.put, 'function')
|
|
195
|
-
|
|
196
|
-
// Test has operation - verify method exists
|
|
197
|
-
assert.equal(typeof peernet.has, 'function')
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
test('get attempts to retrieve from store', async () => {
|
|
201
|
-
const hash = 'nonexistent-hash'
|
|
202
|
-
// Just verify method exists
|
|
203
|
-
assert.equal(typeof peernet.get, 'function')
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
test('message object provides get/put/has', () => {
|
|
207
|
-
const messageObj = peernet.message
|
|
208
|
-
assert.equal(typeof messageObj.get, 'function')
|
|
209
|
-
assert.equal(typeof messageObj.put, 'function')
|
|
210
|
-
assert.equal(typeof messageObj.has, 'function')
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
test('data object provides get/put/has', () => {
|
|
214
|
-
const dataObj = peernet.data
|
|
215
|
-
assert.equal(typeof dataObj.get, 'function')
|
|
216
|
-
assert.equal(typeof dataObj.put, 'function')
|
|
217
|
-
assert.equal(typeof dataObj.has, 'function')
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
test('block object provides get/put/has', () => {
|
|
221
|
-
const blockObj = peernet.block
|
|
222
|
-
assert.equal(typeof blockObj.get, 'function')
|
|
223
|
-
assert.equal(typeof blockObj.put, 'function')
|
|
224
|
-
assert.equal(typeof blockObj.has, 'function')
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
test('large blocks are chunked internally and reconstructed transparently', async () => {
|
|
228
|
-
const previousThreshold = peernet.blockChunkThreshold
|
|
229
|
-
const previousChunkSize = peernet.blockChunkSize
|
|
230
|
-
peernet.blockChunkThreshold = 512
|
|
231
|
-
peernet.blockChunkSize = 256
|
|
232
|
-
try {
|
|
233
|
-
const hash = `chunked-block-${Date.now()}`
|
|
234
|
-
const block = new Uint8Array(1537)
|
|
235
|
-
for (let index = 0; index < block.length; index++) block[index] = index % 251
|
|
236
|
-
|
|
237
|
-
await peernet.block.put(hash, block)
|
|
238
|
-
const stored = await globalThis.blockStore.get(hash)
|
|
239
|
-
const manifest = new peernet.protos['peernet-file'](stored)
|
|
240
|
-
await manifest.decode()
|
|
241
|
-
|
|
242
|
-
assert.equal(manifest.decoded.kind, 'block')
|
|
243
|
-
assert.equal(manifest.decoded.blockHash, hash)
|
|
244
|
-
assert.equal(manifest.decoded.links.length, 7)
|
|
245
|
-
assert.deepEqual(await peernet.block.get(hash), block)
|
|
246
|
-
} finally {
|
|
247
|
-
peernet.blockChunkThreshold = previousThreshold
|
|
248
|
-
peernet.blockChunkSize = previousChunkSize
|
|
249
|
-
}
|
|
250
|
-
})
|
|
251
|
-
|
|
252
|
-
test('transaction object provides get/put/has', () => {
|
|
253
|
-
const txObj = peernet.transaction
|
|
254
|
-
assert.equal(typeof txObj.get, 'function')
|
|
255
|
-
assert.equal(typeof txObj.put, 'function')
|
|
256
|
-
assert.equal(typeof txObj.has, 'function')
|
|
257
|
-
})
|
|
258
|
-
|
|
259
|
-
test('folder object provides get/put/has', () => {
|
|
260
|
-
const folderObj = peernet.folder
|
|
261
|
-
assert.equal(typeof folderObj.get, 'function')
|
|
262
|
-
assert.equal(typeof folderObj.put, 'function')
|
|
263
|
-
assert.equal(typeof folderObj.has, 'function')
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
test('Buffer property is available', () => {
|
|
267
|
-
assert.ok(peernet.Buffer)
|
|
268
|
-
assert.equal(peernet.Buffer, Buffer)
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
test('handleData is callable', () => {
|
|
272
|
-
assert.equal(typeof peernet.handleData, 'function')
|
|
273
|
-
})
|
|
274
|
-
|
|
275
|
-
test('handleDHT is callable', () => {
|
|
276
|
-
assert.equal(typeof peernet.handleDHT, 'function')
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
test('handleRequest is callable', () => {
|
|
280
|
-
assert.equal(typeof peernet.handleRequest, 'function')
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
test('walk is callable', () => {
|
|
284
|
-
assert.equal(typeof peernet.walk, 'function')
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
test('providersFor is callable', () => {
|
|
288
|
-
assert.equal(typeof peernet.providersFor, 'function')
|
|
289
|
-
})
|
|
290
|
-
|
|
291
|
-
test('addRequestHandler is callable', () => {
|
|
292
|
-
assert.equal(typeof peernet.addRequestHandler, 'function')
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
test('sendMessage is callable', () => {
|
|
296
|
-
assert.equal(typeof peernet.sendMessage, 'function')
|
|
297
|
-
})
|
|
298
|
-
|
|
299
|
-
test('start method exists', () => {
|
|
300
|
-
// Just verify method exists and is callable
|
|
301
|
-
assert.equal(typeof peernet.start, 'function')
|
|
302
|
-
})
|
|
303
|
-
|
|
304
|
-
test('default stores are initialized', () => {
|
|
305
|
-
const defaultStores = peernet.defaultStores
|
|
306
|
-
assert.ok(Array.isArray(defaultStores))
|
|
307
|
-
assert.ok(defaultStores.includes('account'))
|
|
308
|
-
assert.ok(defaultStores.includes('wallet'))
|
|
309
|
-
assert.ok(defaultStores.includes('block'))
|
|
310
|
-
assert.ok(defaultStores.includes('transaction'))
|
|
311
|
-
assert.ok(defaultStores.includes('chain'))
|
|
312
|
-
assert.ok(defaultStores.includes('data'))
|
|
313
|
-
assert.ok(defaultStores.includes('message'))
|
|
314
|
-
assert.ok(defaultStores.includes('share'))
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
test('identity has all expected methods', () => {
|
|
318
|
-
assert.equal(typeof peernet.identity.sign, 'function')
|
|
319
|
-
assert.equal(typeof peernet.identity.export, 'function')
|
|
320
|
-
assert.equal(typeof peernet.identity.import, 'function')
|
|
321
|
-
assert.equal(typeof peernet.identity.lock, 'function')
|
|
322
|
-
assert.equal(typeof peernet.identity.unlock, 'function')
|
|
323
|
-
assert.equal(typeof peernet.identity.getAccounts, 'function')
|
|
324
|
-
})
|
|
325
|
-
|
|
326
|
-
test('identity wallet is loaded', () => {
|
|
327
|
-
assert.ok(peernet.identity.id)
|
|
328
|
-
assert.ok(typeof peernet.identity.id === 'string')
|
|
329
|
-
assert.ok(peernet.identity.id.length > 0)
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
test('selected account is set', () => {
|
|
333
|
-
assert.ok(peernet.identity.selectedAccount)
|
|
334
|
-
assert.ok(typeof peernet.identity.selectedAccount === 'string')
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
test('identity signatures authenticate the selected account', async () => {
|
|
338
|
-
const payload = new Uint8Array(32).fill(7)
|
|
339
|
-
const signature = toBase58(await peernet.identity.sign(payload))
|
|
340
|
-
const verifier = new MultiWallet(peernet.network)
|
|
341
|
-
await verifier.fromAddress(peernet.selectedAccount, null, peernet.network)
|
|
342
|
-
assert.equal(await verifier.verify(fromBase58(signature), payload), true)
|
|
343
|
-
})
|
|
344
|
-
|
|
345
|
-
test('legacy account(0)/address(0) identities keep their original signer', async () => {
|
|
346
|
-
const wallet = new MultiWallet(peernet.network)
|
|
347
|
-
await wallet.generate()
|
|
348
|
-
const legacyAccount = wallet.account(0)
|
|
349
|
-
const external = await legacyAccount.external(0)
|
|
350
|
-
const internal = await legacyAccount.internal(0)
|
|
351
|
-
const externalAddress = await external.address
|
|
352
|
-
const wallets = await resolveAccountWallets(wallet, [
|
|
353
|
-
['legacy account', externalAddress, await internal.address]
|
|
354
|
-
])
|
|
355
|
-
const payload = new Uint8Array(32).fill(9)
|
|
356
|
-
const signature = toBase58(await wallets.get(externalAddress).sign(payload))
|
|
357
|
-
const verifier = new MultiWallet(peernet.network)
|
|
358
|
-
await verifier.fromAddress(externalAddress, null, peernet.network)
|
|
359
|
-
assert.equal(await verifier.verify(fromBase58(signature), payload), true)
|
|
360
|
-
})
|
|
361
|
-
|
|
362
|
-
test('error handling methods exist', () => {
|
|
363
|
-
assert.equal(typeof peernet.handleDHT, 'function')
|
|
364
|
-
assert.equal(typeof peernet.handleData, 'function')
|
|
365
|
-
assert.equal(typeof peernet.handleRequest, 'function')
|
|
366
|
-
})
|
|
367
|
-
|
|
368
|
-
test('in-memory broadcast and handleData returns correct data', async () => {
|
|
369
|
-
// Broadcast a valid file object with path
|
|
370
|
-
const testString = 'hello in-memory world'
|
|
371
|
-
const path = '/test'
|
|
372
|
-
const content = new TextEncoder().encode(testString)
|
|
373
|
-
|
|
374
|
-
const hash = await peernet.broadcast(path, { content })
|
|
375
|
-
|
|
376
|
-
// Prepare a mock peer and capture sendMessage output
|
|
377
|
-
let sentNode = null
|
|
378
|
-
const mockPeer = {
|
|
379
|
-
connected: true,
|
|
380
|
-
send: async (data, id) => {
|
|
381
|
-
sentNode = { data, id }
|
|
382
|
-
return Promise.resolve()
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
const proto = {
|
|
386
|
-
decoded: { hash }
|
|
387
|
-
}
|
|
388
|
-
await peernet.handleData(mockPeer, 'test-id', proto)
|
|
389
|
-
|
|
390
|
-
assert.ok(sentNode)
|
|
391
|
-
const DataResponseProto = globalThis.peernet.protos['peernet-data-response']
|
|
392
|
-
const decodedProto = await new DataResponseProto(sentNode.data)
|
|
393
|
-
await decodedProto.decode()
|
|
394
|
-
const FileProto = globalThis.peernet.protos['peernet-file']
|
|
395
|
-
const decodedFile = new FileProto(decodedProto.decoded.data)
|
|
396
|
-
await decodedFile.decode()
|
|
397
|
-
const decodedContent = new TextDecoder().decode(decodedFile.decoded.content)
|
|
398
|
-
assert.equal(decodedProto.decoded.hash, hash)
|
|
399
|
-
assert.equal(decodedContent, testString)
|
|
400
|
-
})
|
|
401
|
-
|
|
402
|
-
test('in-memory broadcast and handleData supports large binary data', async () => {
|
|
403
|
-
// Create a large binary buffer (e.g., 1MB)
|
|
404
|
-
const size = 1024 * 1024 // 1MB
|
|
405
|
-
const largeBuffer = new Uint8Array(size)
|
|
406
|
-
for (let i = 0; i < size; i++) largeBuffer[i] = i % 256
|
|
407
|
-
const path = '/large-binary'
|
|
408
|
-
const content = largeBuffer
|
|
409
|
-
const hash = await peernet.broadcast(path, { content })
|
|
410
|
-
|
|
411
|
-
// Prepare a mock peer and capture sendMessage output
|
|
412
|
-
let sentNode = null
|
|
413
|
-
const mockPeer = {
|
|
414
|
-
connected: true,
|
|
415
|
-
send: async (data, id) => {
|
|
416
|
-
sentNode = { data, id }
|
|
417
|
-
return Promise.resolve()
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
const proto = {
|
|
421
|
-
decoded: { hash }
|
|
422
|
-
}
|
|
423
|
-
await peernet.handleData(mockPeer, 'test-id', proto)
|
|
424
|
-
|
|
425
|
-
assert.ok(sentNode)
|
|
426
|
-
const DataResponseProto = globalThis.peernet.protos['peernet-data-response']
|
|
427
|
-
const decodedProto = await new DataResponseProto(sentNode.data)
|
|
428
|
-
await decodedProto.decode()
|
|
429
|
-
assert.equal(decodedProto.decoded.hash, hash)
|
|
430
|
-
const transfer = peernet.download(hash)
|
|
431
|
-
const receivedBuffer = Buffer.from(await transfer.result)
|
|
432
|
-
const originalBuffer = Buffer.from(largeBuffer)
|
|
433
|
-
assert.equal(Buffer.compare(receivedBuffer, originalBuffer), 0)
|
|
434
|
-
})
|
|
435
|
-
|
|
436
|
-
test('share object provides get/put/has', () => {
|
|
437
|
-
const shareObj = peernet.share
|
|
438
|
-
assert.equal(typeof shareObj.get, 'function')
|
|
439
|
-
assert.equal(typeof shareObj.put, 'function')
|
|
440
|
-
assert.equal(typeof shareObj.has, 'function')
|
|
441
|
-
})
|
|
442
|
-
|
|
443
|
-
test('allSharedHashes method exists and is callable', () => {
|
|
444
|
-
assert.equal(typeof peernet.allSharedHashes, 'function')
|
|
445
|
-
})
|
|
446
|
-
|
|
447
|
-
test('broadcast persists to share store', async () => {
|
|
448
|
-
const testString = 'test broadcast content'
|
|
449
|
-
const path = '/broadcast-test'
|
|
450
|
-
const content = new TextEncoder().encode(testString)
|
|
451
|
-
|
|
452
|
-
const hash = await peernet.broadcast(path, { content })
|
|
453
|
-
|
|
454
|
-
// Verify it was stored in share store
|
|
455
|
-
assert.ok(hash)
|
|
456
|
-
const hasInShare = await peernet.share.has(hash)
|
|
457
|
-
assert.equal(hasInShare, true)
|
|
458
|
-
})
|
|
459
|
-
|
|
460
|
-
test('share store can retrieve broadcasted content', async () => {
|
|
461
|
-
const testString = 'retrievable broadcast content'
|
|
462
|
-
const path = '/retrievable-test'
|
|
463
|
-
const content = new TextEncoder().encode(testString)
|
|
464
|
-
|
|
465
|
-
const hash = await peernet.broadcast(path, { content })
|
|
466
|
-
|
|
467
|
-
// Verify we can retrieve it from share store
|
|
468
|
-
const storedData = await peernet.share.get(hash)
|
|
469
|
-
assert.ok(storedData)
|
|
470
|
-
})
|
|
471
|
-
|
|
472
|
-
test('allSharedHashes returns array of hashes', async () => {
|
|
473
|
-
const hashes = await peernet.allSharedHashes()
|
|
474
|
-
assert.ok(Array.isArray(hashes))
|
|
475
|
-
// Should contain at least the hashes we broadcasted in previous tests
|
|
476
|
-
assert.ok(hashes.length >= 0)
|
|
477
|
-
})
|
package/test-output.log
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
✔ initializes with provided options (0.407125ms)
|
|
2
|
-
✔ exposes identity instance (0.051667ms)
|
|
3
|
-
✔ has a DHT instance (0.04425ms)
|
|
4
|
-
✔ returns peers and connections safely (0.267542ms)
|
|
5
|
-
✔ provides callable helpers (0.048958ms)
|
|
6
|
-
✔ pubsub subscribe registers callback (10.395584ms)
|
|
7
|
-
✔ addProto registers protocol (0.160417ms)
|
|
8
|
-
✔ addProto does not overwrite existing protocol (0.057709ms)
|
|
9
|
-
✔ addCodec is callable (0.063084ms)
|
|
10
|
-
✔ selectAccount delegates to identity (0.068584ms)
|
|
11
|
-
✔ identity has loaded account data (0.241875ms)
|
|
12
|
-
✔ peerId matches identity id (0.031375ms)
|
|
13
|
-
✔ data store operations (0.030125ms)
|
|
14
|
-
✔ get attempts to retrieve from store (0.035667ms)
|
|
15
|
-
✔ message object provides get/put/has (0.053917ms)
|
|
16
|
-
✔ data object provides get/put/has (0.045833ms)
|
|
17
|
-
✔ block object provides get/put/has (0.067375ms)
|
|
18
|
-
✔ transaction object provides get/put/has (0.042333ms)
|
|
19
|
-
✔ folder object provides get/put/has (0.034167ms)
|
|
20
|
-
✔ Buffer property is available (0.024417ms)
|
|
21
|
-
✔ handleData is callable (0.017709ms)
|
|
22
|
-
✔ handleDHT is callable (0.016167ms)
|
|
23
|
-
✔ handleRequest is callable (0.016417ms)
|
|
24
|
-
✔ walk is callable (0.015459ms)
|
|
25
|
-
✔ providersFor is callable (0.015583ms)
|
|
26
|
-
✔ addRequestHandler is callable (0.015375ms)
|
|
27
|
-
✔ sendMessage is callable (0.01625ms)
|
|
28
|
-
✔ start method exists (0.02675ms)
|
|
29
|
-
✔ default stores are initialized (0.0275ms)
|
|
30
|
-
✔ identity has all expected methods (0.020084ms)
|
|
31
|
-
✔ identity wallet is loaded (0.019333ms)
|
|
32
|
-
✔ selected account is set (0.016208ms)
|
|
33
|
-
✔ error handling methods exist (0.017083ms)
|
|
34
|
-
DEBUG_HANDLE_DATA: entering in-memory branch { hash: 'BA43QACTNQLBH6SW7NO7ZQ63I3USRUBTD5DOWLEUFJGMY6JN2BSUAES54X' }
|
|
35
|
-
DEBUG_HANDLE_DATA: got from _inMemoryBroadcasts {
|
|
36
|
-
type: 'object',
|
|
37
|
-
isUint8Array: true,
|
|
38
|
-
length: 34,
|
|
39
|
-
slice: [
|
|
40
|
-
230, 224, 1, 5, 47,
|
|
41
|
-
116, 101, 115, 116, 21,
|
|
42
|
-
104, 101, 108, 108, 111,
|
|
43
|
-
32
|
|
44
|
-
]
|
|
45
|
-
}
|
|
46
|
-
✔ in-memory broadcast and handleData returns correct data (4.52275ms)
|
|
47
|
-
DEBUG_HANDLE_DATA: entering in-memory branch { hash: 'BA43QACYLVOY2HRRGV4NOUDQ3GWPQ7YZVBBM5DOKGZIY4UOYMS3K3JSCVV' }
|
|
48
|
-
DEBUG_HANDLE_DATA: got from _inMemoryBroadcasts {
|
|
49
|
-
type: 'object',
|
|
50
|
-
isUint8Array: true,
|
|
51
|
-
length: 1048599,
|
|
52
|
-
slice: [
|
|
53
|
-
230, 224, 1, 13, 47, 108,
|
|
54
|
-
97, 114, 103, 101, 45, 98,
|
|
55
|
-
105, 110, 97, 114
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
DEBUG_TEST receivedBuffer {
|
|
59
|
-
type: 'object',
|
|
60
|
-
isUint8Array: true,
|
|
61
|
-
length: 1048576,
|
|
62
|
-
slice: [
|
|
63
|
-
0, 1, 2, 3, 4, 5,
|
|
64
|
-
6, 7, 8, 9, 10, 11,
|
|
65
|
-
12, 13, 14, 15
|
|
66
|
-
]
|
|
67
|
-
}
|
|
68
|
-
DEBUG_TEST originalBuffer {
|
|
69
|
-
length: 1048576,
|
|
70
|
-
slice: [
|
|
71
|
-
0, 1, 2, 3, 4, 5,
|
|
72
|
-
6, 7, 8, 9, 10, 11,
|
|
73
|
-
12, 13, 14, 15
|
|
74
|
-
]
|
|
75
|
-
}
|
|
76
|
-
✔ in-memory broadcast and handleData supports large binary data (163.195292ms)
|
|
77
|
-
ℹ tests 35
|
|
78
|
-
ℹ suites 0
|
|
79
|
-
ℹ pass 35
|
|
80
|
-
ℹ fail 0
|
|
81
|
-
ℹ cancelled 0
|
|
82
|
-
ℹ skipped 0
|
|
83
|
-
ℹ todo 0
|
|
84
|
-
ℹ duration_ms 366.132458
|
package/test.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import Client from './exports/peernet.js'
|
|
2
|
-
|
|
3
|
-
const client = await new Client({
|
|
4
|
-
network: 'leofcoin:peach',
|
|
5
|
-
networkVersion: 'peach',
|
|
6
|
-
stars: ['wss://star.leofcoin.org'],
|
|
7
|
-
version: '0.1.0'
|
|
8
|
-
})
|
|
9
|
-
console.log(pubsub.subscribers)
|
|
10
|
-
pubsub.subscribe('peer:discovered', (data) => {
|
|
11
|
-
// console.log(data);
|
|
12
|
-
console.log(`discovered: ${Object.keys(peernet.client.discovered).length}`)
|
|
13
|
-
console.log(Object.keys(peernet.client.discovered))
|
|
14
|
-
})
|
|
15
|
-
pubsub.subscribe('peer:connected', (data) => {
|
|
16
|
-
// console.log(data);
|
|
17
|
-
console.log(`connections: ${peernet.connections.length}`)
|
|
18
|
-
})
|
|
19
|
-
pubsub.subscribe('peer:left', (data) => {
|
|
20
|
-
console.log(`connections: ${peernet.connections.length}`)
|
|
21
|
-
console.log(`discovered: ${Object.keys(peernet.client.discovered).length}`)
|
|
22
|
-
// console.log(data);
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
// peernet.addFolder([{
|
|
26
|
-
// path: 'assets/asset.png',
|
|
27
|
-
// content: Buffer.from('png')
|
|
28
|
-
// }, {
|
|
29
|
-
// path: 'index.html',
|
|
30
|
-
// content: Buffer.from('html')
|
|
31
|
-
// }]).then(hash => peernet.ls(hash).then(paths => peernet.cat(paths[0].hash).then(content => console.log(content))))
|
|
32
|
-
|
|
33
|
-
// pubsub.subscribe('peer:connected', async peer => {
|
|
34
|
-
// chainStore.put('localBlock', '00000')
|
|
35
|
-
// const request = await new globalThis.peernet.protos['peernet-request']({
|
|
36
|
-
// request:'lastBlock'
|
|
37
|
-
// })
|
|
38
|
-
// const to = peer.id
|
|
39
|
-
// await peernet.data.put('hello', 'hi')
|
|
40
|
-
// console.log({request});
|
|
41
|
-
// const node = await peernet.prepareMessage(request)
|
|
42
|
-
// console.log({node});
|
|
43
|
-
// let response = await peer.request(node.encoded)
|
|
44
|
-
// console.log({response});
|
|
45
|
-
// const keys = Object.keys(response)
|
|
46
|
-
// const uint8Array = new Uint8Array(keys.length)
|
|
47
|
-
// for (const key of keys) {
|
|
48
|
-
// uint8Array[Number(key)] = response[key]
|
|
49
|
-
// }
|
|
50
|
-
// // const proto = await new globalThis.peernet.protos['peernet-message'](uint8Array)
|
|
51
|
-
// // console.log(proto.decoded.data);
|
|
52
|
-
// response = await new globalThis.peernet.protos['peernet-response'](uint8Array)
|
|
53
|
-
// console.log({response});
|
|
54
|
-
|
|
55
|
-
// const block = new TextDecoder().decode(response.decoded.response)
|
|
56
|
-
// console.log(block);
|
|
57
|
-
// const task = () => setTimeout(() => {
|
|
58
|
-
// console.log(peernet.connections[0]?.connected);
|
|
59
|
-
// console.log(pubsub.subscribers);
|
|
60
|
-
// task()
|
|
61
|
-
// }, 5000);
|
|
62
|
-
// task()
|
|
63
|
-
// })
|
package/test2.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import Client from './exports/peernet.js'
|
|
2
|
-
;(async () => {
|
|
3
|
-
const client = await new Client({
|
|
4
|
-
root: '.peernet/test2',
|
|
5
|
-
network: 'peach',
|
|
6
|
-
networkVersion: 'peach',
|
|
7
|
-
stars: [['wss://star.leofcoin.org']]
|
|
8
|
-
})
|
|
9
|
-
const job = () => client.publish('socket-data', 'hello')
|
|
10
|
-
setTimeout(async () => {
|
|
11
|
-
job()
|
|
12
|
-
}, 10000)
|
|
13
|
-
})()
|
package/test3.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const Client = require('./dist/commonjs/peernet.js')
|
|
2
|
-
const PeernetMessage = require('./dist/messages/peernet.js');
|
|
3
|
-
const DHTMessage = require('./dist/messages/dht.js');
|
|
4
|
-
|
|
5
|
-
globalThis.DEBUG = true;
|
|
6
|
-
const client = new Client({root: '.peernet/test3'})
|
|
7
|
-
|
|
8
|
-
pubsub.subscribe('peer:connected', async peer => setInterval(async () => {
|
|
9
|
-
// const dhtMessage = new DHTMessage({hash: 'hello'})
|
|
10
|
-
// console.log(dhtMessage.encoded);
|
|
11
|
-
// const message = new PeernetMessage({ from: client.id, to: peer.id, data: dhtMessage.encoded, signature: Buffer.from('pnsig') })
|
|
12
|
-
// console.log(message.encoded);
|
|
13
|
-
// console.log(await peer.request(message.encoded));
|
|
14
|
-
const data = await client.get('hello')
|
|
15
|
-
console.log(data.toString())
|
|
16
|
-
}, 5000))
|
package/test4.js
DELETED
package/tsconfig.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"module": "NodeNext",
|
|
4
|
-
"target": "ESNext",
|
|
5
|
-
"declaration": true,
|
|
6
|
-
"outDir": "./exports",
|
|
7
|
-
"rootDir": "./src",
|
|
8
|
-
"moduleResolution": "NodeNext",
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
"skipLibCheck": true
|
|
11
|
-
},
|
|
12
|
-
"include": ["./src/**/*"]
|
|
13
|
-
}
|