helia-coord 1.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.
Files changed (57) hide show
  1. package/.on-save.json +8 -0
  2. package/PEDIGREE.md +3 -0
  3. package/README.md +3 -0
  4. package/config/bootstrap-circuit-relays.js +48 -0
  5. package/examples/start-external.js +56 -0
  6. package/index.js +129 -0
  7. package/lib/adapters/bch-adapter.js +94 -0
  8. package/lib/adapters/encryption-adapter.js +123 -0
  9. package/lib/adapters/gist.js +42 -0
  10. package/lib/adapters/index.js +66 -0
  11. package/lib/adapters/ipfs-adapter.js +263 -0
  12. package/lib/adapters/logs-adapter.js +44 -0
  13. package/lib/adapters/pubsub-adapter/README.md +86 -0
  14. package/lib/adapters/pubsub-adapter/about-adapter.js +117 -0
  15. package/lib/adapters/pubsub-adapter/index.js +275 -0
  16. package/lib/adapters/pubsub-adapter/messaging.js +389 -0
  17. package/lib/adapters/pubsub-adapter/msg-router.js +58 -0
  18. package/lib/adapters/pubsub-adapter/resend-msg.js +58 -0
  19. package/lib/controllers/index.js +24 -0
  20. package/lib/controllers/timer-controller.js +417 -0
  21. package/lib/entities/this-node-entity.js +102 -0
  22. package/lib/use-cases/index.js +36 -0
  23. package/lib/use-cases/peer-use-cases.js +146 -0
  24. package/lib/use-cases/pubsub-use-cases.js +56 -0
  25. package/lib/use-cases/relay-use-cases.js +479 -0
  26. package/lib/use-cases/schema.js +158 -0
  27. package/lib/use-cases/this-node-use-cases.js +443 -0
  28. package/lib/util/utils.js +12 -0
  29. package/package.json +52 -0
  30. package/test/mocks/adapter-mock.js +119 -0
  31. package/test/mocks/circuit-relay-mocks.js +67 -0
  32. package/test/mocks/ipfs-mock.js +46 -0
  33. package/test/mocks/peers-mock.js +75 -0
  34. package/test/mocks/pubsub-mocks.js +37 -0
  35. package/test/mocks/thisnode-mocks.js +82 -0
  36. package/test/mocks/use-case-mocks.js +24 -0
  37. package/test/unit/adapters/bch-adapter-unit.js +96 -0
  38. package/test/unit/adapters/encryption-adapter-unit.js +129 -0
  39. package/test/unit/adapters/gist.unit.adapters.js +58 -0
  40. package/test/unit/adapters/index-adapters-unit.js +79 -0
  41. package/test/unit/adapters/ipfs-adapter-unit.js +215 -0
  42. package/test/unit/adapters/logs-adapter-unit.js +55 -0
  43. package/test/unit/adapters/pubsub/about-adapter-unit.js +129 -0
  44. package/test/unit/adapters/pubsub/messaging-adapter-unit.js +576 -0
  45. package/test/unit/adapters/pubsub/pubsub-adapter-unit.js +367 -0
  46. package/test/unit/adapters/pubsub/resend-msg-adapter-unit.js +58 -0
  47. package/test/unit/controllers/controllers-index-unit.js +30 -0
  48. package/test/unit/controllers/timer-controller-unit.js +261 -0
  49. package/test/unit/entities/this-node.unit.entity.js +157 -0
  50. package/test/unit/index-unit.js +160 -0
  51. package/test/unit/use-cases/peer.unit.use-cases.js +186 -0
  52. package/test/unit/use-cases/pubsub.unit.use-cases.js +114 -0
  53. package/test/unit/use-cases/relay-use-cases-unit.js +658 -0
  54. package/test/unit/use-cases/schema-use-case-unit.js +101 -0
  55. package/test/unit/use-cases/this-node-use-cases-unit.js +427 -0
  56. package/test/unit/use-cases/use-cases-index-unit.js +47 -0
  57. package/test/unit/util/utils-unit.js +31 -0
@@ -0,0 +1,119 @@
1
+ /*
2
+ A mocked version of the adapters library.
3
+ */
4
+
5
+ class AdaptersMock {
6
+ constructor () {
7
+ this.ipfs = {
8
+ ipfsPeerId: 'fake-id',
9
+ ipfsMultiaddrs: ['addr1', 'addr2'],
10
+ ipfs: {
11
+ pubsub: {
12
+ subscribe: () => {},
13
+ ls: async () => {}
14
+ },
15
+ libp2p: {
16
+ getMultiaddrs: () => [],
17
+ dial: async () => {},
18
+ getPeers: async () => [],
19
+ services: {
20
+ pubsub: {
21
+ publish: async () => {},
22
+ subscribe: async () => {},
23
+ subscriptions: []
24
+ }
25
+ }
26
+ }
27
+ },
28
+ getPeers: () => {
29
+ },
30
+ connectToPeer: () => {
31
+ },
32
+ disconnectFromPeer: () => {
33
+ },
34
+ disconnectFromMultiaddr: () => {
35
+ }
36
+ }
37
+
38
+ this.bchjs = {}
39
+
40
+ this.type = 'node.js'
41
+
42
+ this.bch = {
43
+ generateBchId: () => {
44
+ return {
45
+ cashAddress: 'cashAddress',
46
+ slpAddress: 'slpAddress',
47
+ publicKey: 'public-key'
48
+ }
49
+ },
50
+ bchjs: {
51
+ Util: {
52
+ sleep: () => {
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ this.pubsub = {
59
+ subscribeToPubsubChannel: () => {
60
+ },
61
+ publishToPubsubChannel: () => {
62
+ },
63
+ messaging: {
64
+ publishToPubsubChannel: () => {
65
+ },
66
+ generateMsgObj: () => {
67
+ },
68
+ generateAckMsg: () => {
69
+ },
70
+ sendMsg: () => {
71
+ },
72
+ sendAck: () => {
73
+ },
74
+ handleIncomingData: () => {
75
+ },
76
+ _checkIfAlreadyProcessed: () => {
77
+ },
78
+ delMsgFromQueue: () => {
79
+ },
80
+ addMsgToQueue: () => {
81
+ },
82
+ resendMsg: () => {
83
+ },
84
+ waitForAck: () => {
85
+ }
86
+ },
87
+ about: {
88
+ queryAbout: () => {
89
+ }
90
+ }
91
+ }
92
+
93
+ this.encryption = {
94
+ encryptMsg: () => {
95
+ }
96
+ }
97
+
98
+ this.orbit = {
99
+ createRcvDb: () => {
100
+ return { id: 'fake-orbit-id' }
101
+ },
102
+ connectToPeerDb: () => {
103
+ }
104
+ }
105
+
106
+ this.log = {
107
+ statusLog: () => {
108
+ }
109
+ }
110
+
111
+ this.gist = {
112
+ getCRList: async () => {
113
+ }
114
+ }
115
+ }
116
+ }
117
+
118
+ // module.exports = AdaptersMock
119
+ export default AdaptersMock
@@ -0,0 +1,67 @@
1
+ /** Circuit Relays mock */
2
+ const circuitRelays = [
3
+ {
4
+ name: 'ipfs.fullstack.cash',
5
+ multiaddr:
6
+ '/ip4/116.203.193.74/tcp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL',
7
+ connected: true
8
+ }
9
+ ]
10
+
11
+ const duplicateRelays = [
12
+ {
13
+ multiaddr:
14
+ '/ip4/139.162.76.54/tcp/5269/ws/p2p/QmaKzQTAtoJWYMiG5ATx41uWsMajr1kSxRdtg919s8fK77',
15
+ connected: true,
16
+ updatedAt: '2021-09-20T15:59:12.961Z',
17
+ ipfsId: 'QmaKzQTAtoJWYMiG5ATx41uWsMajr1kSxRdtg919s8fK77',
18
+ isBootstrap: false,
19
+ metrics: { aboutLatency: [] },
20
+ latencyScore: 10000
21
+ },
22
+ {
23
+ multiaddr:
24
+ '/ip4/157.90.28.11/tcp/4001/p2p/QmedLCUDSSvsjfPt9rDm65drNL7Dzu1mk1JCRxu9yuxgLL',
25
+ connected: false,
26
+ updatedAt: '2021-09-20T15:58:22.480Z',
27
+ ipfsId: 'QmedLCUDSSvsjfPt9rDm65drNL7Dzu1mk1JCRxu9yuxgLL',
28
+ isBootstrap: true,
29
+ metrics: { aboutLatency: [] },
30
+ latencyScore: 10000
31
+ },
32
+ {
33
+ multiaddr:
34
+ '/ip4/157.90.28.11/tcp/4001/p2p/QmedLCUDSSvsjfPt9rDm65drNL7Dzu1mk1JCRxu9yuxgLL',
35
+ connected: false,
36
+ updatedAt: '2021-09-20T15:58:22.480Z',
37
+ ipfsId: 'QmedLCUDSSvsjfPt9rDm65drNL7Dzu1mk1JCRxu9yuxgLL',
38
+ isBootstrap: true,
39
+ metrics: { aboutLatency: [] },
40
+ latencyScore: 10000
41
+ },
42
+ {
43
+ multiaddr:
44
+ '/ip4/157.90.28.11/tcp/4001/p2p/QmedLCUDSSvsjfPt9rDm65drNL7Dzu1mk1JCRxu9yuxgLL',
45
+ connected: false,
46
+ updatedAt: '2021-09-20T15:58:22.480Z',
47
+ ipfsId: 'QmedLCUDSSvsjfPt9rDm65drNL7Dzu1mk1JCRxu9yuxgLL',
48
+ isBootstrap: true,
49
+ metrics: { aboutLatency: [] },
50
+ latencyScore: 10000
51
+ },
52
+ {
53
+ multiaddr:
54
+ '/ip4/137.184.13.92/tcp/5668/p2p/Qma4iaNqgCAzA3HqNNEkKZzqWhCMnjt19TEHLu8TKhHhRK',
55
+ connected: true,
56
+ updatedAt: '2021-09-20T15:58:14.963Z',
57
+ ipfsId: 'Qma4iaNqgCAzA3HqNNEkKZzqWhCMnjt19TEHLu8TKhHhRK',
58
+ isBootstrap: true,
59
+ metrics: { aboutLatency: [] },
60
+ latencyScore: 10000
61
+ }
62
+ ]
63
+
64
+ export default {
65
+ circuitRelays,
66
+ duplicateRelays
67
+ }
@@ -0,0 +1,46 @@
1
+ /*
2
+ A mocked instance of ipfs, for use in unit tests.
3
+
4
+ */
5
+ const ipfs = {
6
+ id: () => {
7
+ return {
8
+ id: 'myID',
9
+ addresses: ['addr1', 'addr2']
10
+ }
11
+ },
12
+ swarm: {
13
+ connect: async () => {},
14
+ peers: async () => {
15
+ return []
16
+ },
17
+ disconnect: async () => {}
18
+ },
19
+ pubsub: {
20
+ subscribe: async () => {},
21
+ publish: async () => {}
22
+ },
23
+ config: {
24
+ set: () => {},
25
+ get: () => {},
26
+ getAll: () => {}
27
+ },
28
+ libp2p: {
29
+ peerId: {
30
+ toString: () => 'fake-peerId'
31
+ },
32
+ getMultiaddrs: () => [],
33
+ dial: async () => {},
34
+ getPeers: async () => [],
35
+ services: {
36
+ pubsub: {
37
+ publish: async () => {},
38
+ subscribe: async () => {},
39
+ subscriptions: []
40
+ }
41
+ }
42
+ }
43
+ }
44
+
45
+ // module.exports = ipfs
46
+ export default ipfs
@@ -0,0 +1,75 @@
1
+ const announceObj = {
2
+ from: 'QmcReHFvNgxFLnLWtVa5SYmeGbmnzBdphKEqPMKJ6XfBh4',
3
+ channel: 'psf-ipfs-coordination-001',
4
+ data: {
5
+ apiName: 'ipfs-coord-announce',
6
+ apiVersion: '1.3.0',
7
+ apiInfo: 'ipfs-hash-to-documentation-to-go-here',
8
+ ipfsId: 'QmcReHFvNgxFLnLWtVa5SYmeGbmnzBdphKEqPMKJ6XfBh4',
9
+ type: 'browser',
10
+ ipfsMultiaddrs: [],
11
+ circuitRelays: [],
12
+ isCircuitRelay: false,
13
+ cryptoAddresses: [],
14
+ encryptPubKey: ''
15
+ }
16
+ }
17
+
18
+ const announceObj2 = {
19
+ from: 'QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
20
+ channel: 'psf-ipfs-coordination-001',
21
+ data: {
22
+ apiName: 'ipfs-coord-announce',
23
+ apiVersion: '1.3.0',
24
+ apiInfo: 'ipfs-hash-to-documentation-to-go-here',
25
+ ipfsId: 'QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
26
+ type: 'browser',
27
+ ipfsMultiaddrs: [],
28
+ circuitRelays: [],
29
+ isCircuitRelay: false,
30
+ cryptoAddresses: [],
31
+ encryptPubKey: ''
32
+ }
33
+ }
34
+ const swarmPeers = [
35
+ {
36
+ addr:
37
+ '<Multiaddr 049d5a1c0b060fa2a503221220ca9b6cedac4cf9252543e49e94cec725452b8a588641213c67a2841794545b10 - /ip4/157.90.28.11/tcp/4002/p2p/QmbyYXKbnAmMbMGo8LRBZ58jYs58anqUzY1m4jxDmhDsjd>',
38
+ peer: 'QmbyYXKbnAmMbMGo8LRBZ58jYs58anqUzY1m4jxDmhDsjd'
39
+ },
40
+ {
41
+ addr:
42
+ '<Multiaddr 04934b6409060fa1a503221220c9ab4abc592cae0b1d076c557ce9bc2a9ff5d40a726a683e36fe274afa9122a5 - /ip4/147.75.100.9/tcp/4001/p2p/QmcReHFvNgxFLnLWtVa5SYmeGbmnzBdphKEqPMKJ6XfBh4>',
43
+ peer: 'QmcReHFvNgxFLnLWtVa5SYmeGbmnzBdphKEqPMKJ6XfJh4'
44
+ },
45
+ {
46
+ addr:
47
+ ' <Multiaddr 0468838352060fa1a503221220b04a57d40eca138809f139a76b12044333c3740391c9bf1ce9d8e21a79210bfd - /ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ>',
48
+ peer: 'QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ'
49
+ }
50
+ ]
51
+ // Peers that match with circuit relay address mock id
52
+ const swarmPeers2 = [
53
+ {
54
+ addr:
55
+ ' <Multiaddr 0468838352060fa1a503221220b04a57d40eca138809f139a76b12044333c3740391c9bf1ce9d8e21a79210bfd - /ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ>',
56
+ peer: 'QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL'
57
+ }
58
+ ]
59
+
60
+ const mockRelayData = [
61
+ {
62
+ name: 'ipfs.fullstack.cash',
63
+ multiaddr:
64
+ '/ip4/116.203.193.74/tcp/4001/ipfs/QmNZktxkfScScnHCFSGKELH3YRqdxHQ3Le9rAoRLhZ6vgL',
65
+ connected: true
66
+ }
67
+ ]
68
+
69
+ export default {
70
+ announceObj,
71
+ announceObj2,
72
+ swarmPeers,
73
+ swarmPeers2,
74
+ mockRelayData
75
+ }
@@ -0,0 +1,37 @@
1
+ const mockData = `${'{"apiName":"ipfs-coord","apiVersion":"1.3.0","apiInfo":"ipfs-hash-to-documentation-to-go-here","ipfsId":"QmRrUu64cAnPntYiUc7xMunLKZgj1XZT5HmqJNtDMqQcD7","type":"node.js","ipfsMultiaddrs":["/ip4/10.0.0.3/tcp/4002/p2p/QmRrUu64cAnPntYiUc7xMunLKZgj1XZT5HmqJNtDMqQcD7","/ip4/127.0.0.1/tcp/4002/p2p/QmRrUu64cAnPntYiUc7xMunLKZgj1XZT5HmqJNtDMqQcD7","/ip4/127.0.0.1/tcp/4003/ws/p2p/QmRrUu64cAnPntYiUc7xMunLKZgj1XZT5HmqJNtDMqQcD7","/ip4/157.90.20.129/tcp/4002/p2p/QmRrUu64cAnPntYiUc7xMunLKZgj1XZT5HmqJNtDMqQcD7"],"circuitRelays":[],"cryptoAddresses":[],"encryptPubKey":""}'}`
2
+
3
+ const mockMsg = {
4
+ from: 'QmRrUu64cAnPntYiUc7xMunLKZgj1XZT5HmqJNtDMqQcD7',
5
+ data: Buffer.from(JSON.stringify(mockData)),
6
+ seqno: Buffer.from('test'),
7
+ topicIDs: ['psf-ipfs-coordination-001'],
8
+ signature: Buffer.from('test'),
9
+ key: Buffer.from('test'),
10
+ receivedFrom: 'QmRrUu64cAnPntYiUc7xMunLKZgj1XZT5HmqJNtDMqQcD7'
11
+ }
12
+
13
+ const aboutRequest = '{"jsonrpc":"2.0","id":"metrics3796","method":"about"}'
14
+
15
+ const aboutResponse = '{"jsonrpc": "2.0", "id": "metrics3796", "result": {"method": "about", "receiver": "12D3KooWE6tkdArVpCHG9QN61G1cE7eCq2Q7i4bNx6CJFTDprk9f", "value": {"ipfsId":"12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa","name":"12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa","type":"node.js","ipfsMultiaddrs":["/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa","/ip4/5.161.46.163/tcp/4001/p2p/12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa","/ip6/2a01:4ff:f0:f76::1/tcp/4001/p2p/12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa","/ip6/::1/tcp/4001/p2p/12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa"],"isCircuitRelay":true,"circuitRelayInfo":{"ip4":"5.161.46.163","tcpPort":"4001","crDomain":""},"cashAddress":"bitcoincash:qzerrnr5nfdkr3h62cxf0adn4jykjk53zudz4py26e","slpAddress":"simpleledger:qzerrnr5nfdkr3h62cxf0adn4jykjk53zupe7632y8","publicKey":"02e719acbfd3060fa75503ec7af528f5ba67da8a2b9b8e89dbf9b60676740868a0","orbitdbId":"","apiInfo":"You should put an IPFS hash or web URL here to your documentation.","announceJsonLd":{"@context":"https://schema.org/","@type":"WebAPI","name":"ipfs-bch-service-generic","version":"2.0.0","protocol":"bch-wallet","description":"IPFS service providing BCH blockchain access needed by a wallet.","documentation":"https://ipfs-bch-wallet-service.fullstack.cash/","provider":{"@type":"Organization","name":"Permissionless Software Foundation","url":"https://PSFoundation.cash"},"identifier":"12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa"}}}}'
16
+
17
+ const badId = '{"jsonrpc":"2.0","id":"bad-id","method":"about"}'
18
+
19
+ const msgObj = {
20
+ from: '12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa',
21
+ channel: '12D3KooWE6tkdArVpCHG9QN61G1cE7eCq2Q7i4bNx6CJFTDprk9f',
22
+ data: {
23
+ timestamp: '2022-03-04T18:19:18.897Z',
24
+ uuid: '311e15f5-e647-488f-8ff5-8a41b254e7c3',
25
+ sender: '12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa',
26
+ receiver: '12D3KooWE6tkdArVpCHG9QN61G1cE7eCq2Q7i4bNx6CJFTDprk9f',
27
+ payload: '{"jsonrpc": "2.0", "id": "metrics3796", "result": {"method": "about", "receiver": "12D3KooWE6tkdArVpCHG9QN61G1cE7eCq2Q7i4bNx6CJFTDprk9f", "value": {"ipfsId":"12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa","name":"12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa","type":"node.js","ipfsMultiaddrs":["/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa","/ip4/5.161.46.163/tcp/4001/p2p/12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa","/ip6/2a01:4ff:f0:f76::1/tcp/4001/p2p/12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa","/ip6/::1/tcp/4001/p2p/12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa"],"isCircuitRelay":true,"circuitRelayInfo":{"ip4":"5.161.46.163","tcpPort":"4001","crDomain":""},"cashAddress":"bitcoincash:qzerrnr5nfdkr3h62cxf0adn4jykjk53zudz4py26e","slpAddress":"simpleledger:qzerrnr5nfdkr3h62cxf0adn4jykjk53zupe7632y8","publicKey":"02e719acbfd3060fa75503ec7af528f5ba67da8a2b9b8e89dbf9b60676740868a0","orbitdbId":"","apiInfo":"You should put an IPFS hash or web URL here to your documentation.","announceJsonLd":{"@context":"https://schema.org/","@type":"WebAPI","name":"ipfs-bch-service-generic","version":"2.0.0","protocol":"bch-wallet","description":"IPFS service providing BCH blockchain access needed by a wallet.","documentation":"https://ipfs-bch-wallet-service.fullstack.cash/","provider":{"@type":"Organization","name":"Permissionless Software Foundation","url":"https://PSFoundation.cash"},"identifier":"12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa"}}}}'
28
+ }
29
+ }
30
+
31
+ export default {
32
+ mockMsg,
33
+ aboutRequest,
34
+ aboutResponse,
35
+ badId,
36
+ msgObj
37
+ }
@@ -0,0 +1,82 @@
1
+ /*
2
+ 'thisNode' is an object that is passed around to a lot of functions. The object
3
+ represents an instance of the IPFS node. This file creates a mock of thisNode
4
+ that can be used for unit tests.
5
+ */
6
+
7
+ const thisNode = {
8
+ ipfsId: '12D3KooWE6tkdArVpCHG9QN61G1cE7eCq2Q7i4bNx6CJFTDprk9f',
9
+ ipfsMultiaddrs: [
10
+ '/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWE6tkdArVpCHG9QN61G1cE7eCq2Q7i4bNx6CJFTDprk9f',
11
+ '/ip6/::1/tcp/4001/p2p/12D3KooWE6tkdArVpCHG9QN61G1cE7eCq2Q7i4bNx6CJFTDprk9f'
12
+ ],
13
+ bchAddr: 'bitcoincash:qpjecejl9n90u9vv7cg7p9qfjk4zjwqus5hff6sfpm',
14
+ slpAddr: 'simpleledger:qpjecejl9n90u9vv7cg7p9qfjk4zjwqus5mjzp9fl9',
15
+ publicKey: '0232ef60e2c545d49d18c95fa7379164693ff6d201221aefea6bee872e4c03be12',
16
+ type: 'node.js',
17
+ peerList: ['12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa'],
18
+ peerData: [
19
+ {
20
+ from: '12D3KooWHS5A6Ey4V8fLWD64jpPn2EKi4r4btGN6FfkNgMTnfqVa',
21
+ channel: 'psf-ipfs-coordination-002',
22
+ data: {
23
+ encryptPubKey: '0232ef60e2c545d49d18c95fa7379164693ff6d201221aefea6bee872e4c03be12'
24
+ }
25
+ }
26
+ ],
27
+ relayData: [
28
+ {
29
+ multiaddr: '/ip4/5.161.43.61/tcp/5268/p2p/QmWPfWgbSjPPFpvmS2QH7NPx14DqxMV8eGAUHLcYfyo1St',
30
+ connected: false,
31
+ updatedAt: '2022-03-03T22:01:05.715Z',
32
+ ipfsId: 'QmWPfWgbSjPPFpvmS2QH7NPx14DqxMV8eGAUHLcYfyo1St',
33
+ isBootstrap: false,
34
+ metrics: {},
35
+ latencyScore: 10000
36
+ },
37
+ {
38
+ multiaddr: '/ip4/88.99.188.196/tcp/5268/p2p/QmXbyd4tWzwhGyyZJ9QJctfJJLq7oAJRs39aqpRXUAbu5j',
39
+ connected: false,
40
+ updatedAt: '2022-03-03T22:01:06.110Z',
41
+ ipfsId: 'QmXbyd4tWzwhGyyZJ9QJctfJJLq7oAJRs39aqpRXUAbu5j',
42
+ isBootstrap: false,
43
+ metrics: {},
44
+ latencyScore: 10000
45
+ }
46
+ ],
47
+ serviceList: [],
48
+ serviceData: [],
49
+ blacklistPeers: [
50
+ 'QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
51
+ 'Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6',
52
+ 'QmV7gnbW5VTcJ3oyM2Xk1rdFBJ3kTkvxc87UFGsun29STS',
53
+ 'QmY7JB6MQXhxHvq7dBDh4HpbH29v4yE9JRadAVpndvzySN',
54
+ 'QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
55
+ 'QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
56
+ 'QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
57
+ 'QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
58
+ 'QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
59
+ 'QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
60
+ ],
61
+ blacklistMultiaddrs: [
62
+ '/dns4/node0.preload.ipfs.io/tcp/443/wss/p2p/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
63
+ '/dns4/node1.preload.ipfs.io/tcp/443/wss/p2p/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6',
64
+ '/dns4/node2.preload.ipfs.io/tcp/443/wss/p2p/QmV7gnbW5VTcJ3oyM2Xk1rdFBJ3kTkvxc87UFGsun29STS',
65
+ '/dns4/node3.preload.ipfs.io/tcp/443/wss/p2p/QmY7JB6MQXhxHvq7dBDh4HpbH29v4yE9JRadAVpndvzySN',
66
+ '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
67
+ '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
68
+ '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
69
+ '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
70
+ '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
71
+ '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt',
72
+ '/dns4/node0.delegate.ipfs.io/tcp/443/https',
73
+ '/dns4/node1.delegate.ipfs.io/tcp/443/https',
74
+ '/dns4/node2.delegate.ipfs.io/tcp/443/https',
75
+ '/dns4/node3.delegate.ipfs.io/tcp/443/https'
76
+ ],
77
+ schema: {},
78
+ useCases: {}
79
+ }
80
+
81
+ // module.exports = thisNode
82
+ export default thisNode
@@ -0,0 +1,24 @@
1
+ /*
2
+ Mocked version of the Use Cases library.
3
+ */
4
+
5
+ class UseCasesMock {
6
+ constructor () {
7
+ this.thisNode = {
8
+ refreshPeerConnections: () => {},
9
+ enforceBlacklist: () => {},
10
+ enforceWhitelist: () => {}
11
+ }
12
+ this.relays = {
13
+ connectToCRs: () => {},
14
+ addRelay: () => {},
15
+ measureRelays: () => {},
16
+ sortRelays: obj => obj,
17
+ removeDuplicates: () => {}
18
+ }
19
+ this.pubsub = {}
20
+ this.peer = {}
21
+ }
22
+ }
23
+
24
+ export default UseCasesMock
@@ -0,0 +1,96 @@
1
+ /*
2
+ Unit tests for the bch-lib library.
3
+ */
4
+
5
+ // npm libraries
6
+ import { assert } from 'chai'
7
+ import sinon from 'sinon'
8
+ import SlpWallet from 'minimal-slp-wallet'
9
+
10
+ // local libraries
11
+ import BchLib from '../../../lib/adapters/bch-adapter.js'
12
+
13
+ describe('#bch-adapter', () => {
14
+ let sandbox
15
+ let uut
16
+ let wallet
17
+
18
+ beforeEach(async () => {
19
+ // Restore the sandbox before each test.
20
+ sandbox = sinon.createSandbox()
21
+
22
+ wallet = new SlpWallet()
23
+ await wallet.walletInfoPromise
24
+
25
+ uut = new BchLib({ wallet })
26
+ })
27
+
28
+ afterEach(() => sandbox.restore())
29
+
30
+ describe('#constructor', () => {
31
+ it('should throw an error if minimal-slp-wallet instance is not passed in', () => {
32
+ try {
33
+ uut = new BchLib({})
34
+ } catch (err) {
35
+ assert.include(
36
+ err.message,
37
+ 'An instance of minimal-slp-wallet must be passed when instantiating the BCH adapter library.'
38
+ )
39
+ }
40
+ })
41
+ })
42
+
43
+ describe('#generateBchId', () => {
44
+ it('should generate a new BCH ID if mnemonic is not given', async () => {
45
+ const result = await uut.generateBchId()
46
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
47
+
48
+ assert.property(result, 'cashAddress')
49
+ assert.property(result, 'slpAddress')
50
+ assert.property(result, 'publicKey')
51
+ })
52
+
53
+ it('should catch and throw an error', async () => {
54
+ try {
55
+ sandbox
56
+ .stub(uut.bchjs.Mnemonic, 'toSeed')
57
+ .rejects(new Error('test error'))
58
+
59
+ await uut.generateBchId()
60
+
61
+ assert.fail('Unexpected code path. Error was expected to be thrown.')
62
+ } catch (err) {
63
+ // console.log(err)
64
+ assert.include(err.message, 'test error')
65
+ }
66
+ })
67
+ })
68
+
69
+ describe('#generatePrivateKey', () => {
70
+ it('should generate a private key', async () => {
71
+ const result = await uut.generatePrivateKey()
72
+ console.log('result: ', result)
73
+
74
+ // The private key shoul be a string.
75
+ assert.isString(result)
76
+
77
+ // It shoul be a WIF that starts with a K or L
78
+ // assert.equal(result[0], 'K' || 'L')
79
+ })
80
+
81
+ it('should catch and throw an error', async () => {
82
+ try {
83
+ sandbox
84
+ .stub(uut.bchjs.Mnemonic, 'toSeed')
85
+ .rejects(new Error('test error'))
86
+
87
+ await uut.generatePrivateKey()
88
+
89
+ assert.fail('Unexpected code path. Error was expected to be thrown.')
90
+ } catch (err) {
91
+ // console.log(err)
92
+ assert.include(err.message, 'test error')
93
+ }
94
+ })
95
+ })
96
+ })
@@ -0,0 +1,129 @@
1
+ /*
2
+ Unit tests for the encryption adapter library.
3
+ */
4
+
5
+ // npm libraries
6
+ import { assert } from 'chai'
7
+ import sinon from 'sinon'
8
+ import SlpWallet from 'minimal-slp-wallet'
9
+
10
+ // local libraries
11
+ import EncryptionAdapter from '../../../lib/adapters/encryption-adapter.js'
12
+ import BchAdapter from '../../../lib/adapters/bch-adapter.js'
13
+
14
+ describe('#Adapters - Encryption', () => {
15
+ let uut
16
+ let sandbox
17
+ let wallet
18
+
19
+ beforeEach(async () => {
20
+ // Restore the sandbox before each test.
21
+ sandbox = sinon.createSandbox()
22
+
23
+ wallet = new SlpWallet()
24
+ await wallet.walletInfoPromise
25
+
26
+ const bch = new BchAdapter({ wallet })
27
+
28
+ // Instantiate the library under test. Must instantiate dependencies first.
29
+ uut = new EncryptionAdapter({ bch })
30
+ })
31
+
32
+ afterEach(() => sandbox.restore())
33
+
34
+ describe('#constructor', () => {
35
+ it('should throw an error if bch adapter is not included', () => {
36
+ try {
37
+ uut = new EncryptionAdapter()
38
+
39
+ assert.fail('Unexpected code path')
40
+ } catch (err) {
41
+ assert.include(
42
+ err.message,
43
+ 'Must pass in an instance of bch Adapter when instantiating the encryption Adapter library.'
44
+ )
45
+ }
46
+ })
47
+ })
48
+
49
+ describe('#decryptMsg', () => {
50
+ it('should decrypt a message', async () => {
51
+ // Mock dependencies
52
+ sandbox
53
+ .stub(uut.bchEncrypt.encryption, 'decryptFile')
54
+ .resolves('decryptedMsg')
55
+
56
+ const result = await uut.decryptMsg('F6')
57
+ // console.log('result: ', result)
58
+
59
+ assert.isOk(result)
60
+ })
61
+
62
+ it('should handle BAD MAC error messages', async () => {
63
+ try {
64
+ // Force a BAD MAC error
65
+ sandbox
66
+ .stub(uut.bchEncrypt.encryption, 'decryptFile')
67
+ .rejects(new Error('Bad MAC'))
68
+
69
+ await uut.decryptMsg('F6')
70
+
71
+ assert.fail('Unexpected code path')
72
+ } catch (err) {
73
+ assert.include(err.message, 'Bad MAC. Could not decrypt message.')
74
+ }
75
+ })
76
+
77
+ it('should catch and throw an error', async () => {
78
+ try {
79
+ // Force an error
80
+ sandbox
81
+ .stub(uut.bchEncrypt.encryption, 'decryptFile')
82
+ .rejects(new Error('test error'))
83
+
84
+ await uut.decryptMsg('F6')
85
+
86
+ assert.fail('Unexpected code path')
87
+ } catch (err) {
88
+ assert.include(err.message, 'test error')
89
+ }
90
+ })
91
+ })
92
+
93
+ describe('#encryptMsg', () => {
94
+ it('should catch and throw errors', async () => {
95
+ try {
96
+ const peer = {
97
+ data: {
98
+ encryptionKey: 'abc123'
99
+ }
100
+ }
101
+
102
+ await uut.encryptMsg(peer, 'testMsg')
103
+ // console.log('result: ', result)
104
+
105
+ assert.fail('Unexpected code path')
106
+ } catch (err) {
107
+ assert.include(err.message, 'pubkey must be a hex string')
108
+ }
109
+ })
110
+
111
+ it('should encrypt a string', async () => {
112
+ // Mock dependencies
113
+ sandbox
114
+ .stub(uut.bchEncrypt.encryption, 'encryptFile')
115
+ .resolves('encryptedMsg')
116
+
117
+ const peer = {
118
+ data: {
119
+ encryptionKey: 'abc123'
120
+ }
121
+ }
122
+
123
+ const result = await uut.encryptMsg(peer, 'testMsg')
124
+ // console.log('result: ', result)
125
+
126
+ assert.equal(result, 'encryptedMsg')
127
+ })
128
+ })
129
+ })