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.
- package/.on-save.json +8 -0
- package/PEDIGREE.md +3 -0
- package/README.md +3 -0
- package/config/bootstrap-circuit-relays.js +48 -0
- package/examples/start-external.js +56 -0
- package/index.js +129 -0
- package/lib/adapters/bch-adapter.js +94 -0
- package/lib/adapters/encryption-adapter.js +123 -0
- package/lib/adapters/gist.js +42 -0
- package/lib/adapters/index.js +66 -0
- package/lib/adapters/ipfs-adapter.js +263 -0
- package/lib/adapters/logs-adapter.js +44 -0
- package/lib/adapters/pubsub-adapter/README.md +86 -0
- package/lib/adapters/pubsub-adapter/about-adapter.js +117 -0
- package/lib/adapters/pubsub-adapter/index.js +275 -0
- package/lib/adapters/pubsub-adapter/messaging.js +389 -0
- package/lib/adapters/pubsub-adapter/msg-router.js +58 -0
- package/lib/adapters/pubsub-adapter/resend-msg.js +58 -0
- package/lib/controllers/index.js +24 -0
- package/lib/controllers/timer-controller.js +417 -0
- package/lib/entities/this-node-entity.js +102 -0
- package/lib/use-cases/index.js +36 -0
- package/lib/use-cases/peer-use-cases.js +146 -0
- package/lib/use-cases/pubsub-use-cases.js +56 -0
- package/lib/use-cases/relay-use-cases.js +479 -0
- package/lib/use-cases/schema.js +158 -0
- package/lib/use-cases/this-node-use-cases.js +443 -0
- package/lib/util/utils.js +12 -0
- package/package.json +52 -0
- package/test/mocks/adapter-mock.js +119 -0
- package/test/mocks/circuit-relay-mocks.js +67 -0
- package/test/mocks/ipfs-mock.js +46 -0
- package/test/mocks/peers-mock.js +75 -0
- package/test/mocks/pubsub-mocks.js +37 -0
- package/test/mocks/thisnode-mocks.js +82 -0
- package/test/mocks/use-case-mocks.js +24 -0
- package/test/unit/adapters/bch-adapter-unit.js +96 -0
- package/test/unit/adapters/encryption-adapter-unit.js +129 -0
- package/test/unit/adapters/gist.unit.adapters.js +58 -0
- package/test/unit/adapters/index-adapters-unit.js +79 -0
- package/test/unit/adapters/ipfs-adapter-unit.js +215 -0
- package/test/unit/adapters/logs-adapter-unit.js +55 -0
- package/test/unit/adapters/pubsub/about-adapter-unit.js +129 -0
- package/test/unit/adapters/pubsub/messaging-adapter-unit.js +576 -0
- package/test/unit/adapters/pubsub/pubsub-adapter-unit.js +367 -0
- package/test/unit/adapters/pubsub/resend-msg-adapter-unit.js +58 -0
- package/test/unit/controllers/controllers-index-unit.js +30 -0
- package/test/unit/controllers/timer-controller-unit.js +261 -0
- package/test/unit/entities/this-node.unit.entity.js +157 -0
- package/test/unit/index-unit.js +160 -0
- package/test/unit/use-cases/peer.unit.use-cases.js +186 -0
- package/test/unit/use-cases/pubsub.unit.use-cases.js +114 -0
- package/test/unit/use-cases/relay-use-cases-unit.js +658 -0
- package/test/unit/use-cases/schema-use-case-unit.js +101 -0
- package/test/unit/use-cases/this-node-use-cases-unit.js +427 -0
- package/test/unit/use-cases/use-cases-index-unit.js +47 -0
- package/test/unit/util/utils-unit.js +31 -0
package/.on-save.json
ADDED
package/PEDIGREE.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This library contains known circuit relays that new IPFS nodes can use to
|
|
3
|
+
bootstrap themselves into the network and join the pubsub network.
|
|
4
|
+
*/
|
|
5
|
+
/* eslint camelcase: 0 */
|
|
6
|
+
|
|
7
|
+
const BOOTSTRAP_BROWSER_CRs = [
|
|
8
|
+
{
|
|
9
|
+
// Based in USA, east coast.
|
|
10
|
+
name: 'bchd.nl',
|
|
11
|
+
multiaddr: '/dns4/bchd.nl/tcp/443/wss/p2p/12D3KooWRBhwfeP2Y9CDkFRBAZ1pmxUadH36TKuk3KtKm5XXP8mA',
|
|
12
|
+
connected: false,
|
|
13
|
+
ipfsId: '12D3KooWRBhwfeP2Y9CDkFRBAZ1pmxUadH36TKuk3KtKm5XXP8mA',
|
|
14
|
+
isBootstrap: true
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: 'ipfs-cr.fullstackslp.nl',
|
|
18
|
+
multiaddr: '/dns4/ipfs-cr.fullstackslp.nl/tcp/443/wss/p2p/12D3KooWJyc54njjeZGbLew4D8u1ghrmZTTPyh3QpBF7dxtd3zGY',
|
|
19
|
+
connected: false,
|
|
20
|
+
ipfsId: '12D3KooWJyc54njjeZGbLew4D8u1ghrmZTTPyh3QpBF7dxtd3zGY',
|
|
21
|
+
isBootstrap: true
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
const BOOTSTRAP_NODE_CRs = [
|
|
26
|
+
{
|
|
27
|
+
name: 'bchd.nl',
|
|
28
|
+
multiaddr: '/ip4/5.161.95.233/tcp/4001/p2p/12D3KooWRBhwfeP2Y9CDkFRBAZ1pmxUadH36TKuk3KtKm5XXP8mA',
|
|
29
|
+
connected: false,
|
|
30
|
+
ipfsId: '12D3KooWRBhwfeP2Y9CDkFRBAZ1pmxUadH36TKuk3KtKm5XXP8mA',
|
|
31
|
+
isBootstrap: true
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'ipfs-cr.fullstackslp.nl',
|
|
35
|
+
multiaddr: '/ip4/78.46.129.7/tcp/4001/p2p/12D3KooWJyc54njjeZGbLew4D8u1ghrmZTTPyh3QpBF7dxtd3zGY',
|
|
36
|
+
connected: false,
|
|
37
|
+
ipfsId: '12D3KooWJyc54njjeZGbLew4D8u1ghrmZTTPyh3QpBF7dxtd3zGY',
|
|
38
|
+
isBootstrap: true
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
const bootstrapCircuitRelays = {
|
|
43
|
+
browser: BOOTSTRAP_BROWSER_CRs,
|
|
44
|
+
node: BOOTSTRAP_NODE_CRs
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// module.exports = bootstrapCircuitRelays
|
|
48
|
+
export default bootstrapCircuitRelays
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This example shows how to start an IPFS node, using ipfs-coord, with the
|
|
3
|
+
IPFS node running as an external node that can be controlled via the
|
|
4
|
+
ipfs-http-client library.
|
|
5
|
+
|
|
6
|
+
Designed to use IPFS running in this Docker container:
|
|
7
|
+
https://github.com/christroutner/docker-ipfs
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// const IPFS = require('@chris.troutner/ipfs')
|
|
11
|
+
import { create } from 'ipfs-http-client'
|
|
12
|
+
// const IPFS = require('/home/trout/work/personal/js-ipfs/packages/ipfs')
|
|
13
|
+
// const BCHJS = require('@psf/bch-js')
|
|
14
|
+
import SlpWallet from 'minimal-slp-wallet'
|
|
15
|
+
// const IpfsCoord = require('ipfs-coord')
|
|
16
|
+
import IpfsCoord from '../index.js'
|
|
17
|
+
import http from 'http'
|
|
18
|
+
|
|
19
|
+
// Configuration for external IPFS node.
|
|
20
|
+
const ipfsOptions = {
|
|
21
|
+
protocol: 'http',
|
|
22
|
+
host: 'localhost',
|
|
23
|
+
port: 5001,
|
|
24
|
+
agent: http.Agent({ keepAlive: true, maxSockets: 100 })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function start () {
|
|
28
|
+
// Create an instance of bch-js and IPFS.
|
|
29
|
+
// const bchjs = new BCHJS()
|
|
30
|
+
const wallet = new SlpWallet()
|
|
31
|
+
await wallet.walletInfoPromise
|
|
32
|
+
const ipfs = await create(ipfsOptions)
|
|
33
|
+
|
|
34
|
+
// Pass bch-js and IPFS to ipfs-coord when instantiating it.
|
|
35
|
+
const ipfsCoord = new IpfsCoord({
|
|
36
|
+
ipfs,
|
|
37
|
+
wallet,
|
|
38
|
+
type: 'node.js',
|
|
39
|
+
// type: 'browser'
|
|
40
|
+
nodeType: 'external',
|
|
41
|
+
debugLevel: 2
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
await ipfsCoord.start()
|
|
45
|
+
console.log('IPFS and the coordination library is ready.')
|
|
46
|
+
|
|
47
|
+
// Used for debugging
|
|
48
|
+
// setTimeout(async function () {
|
|
49
|
+
// const thisNode = ipfsCoord.thisNode
|
|
50
|
+
// console.log('\nthisNode: ', thisNode)
|
|
51
|
+
// // console.log(
|
|
52
|
+
// // `thisNode.peerData: ${JSON.stringify(thisNode.peerData, null, 2)}`
|
|
53
|
+
// // )
|
|
54
|
+
// }, 20000)
|
|
55
|
+
}
|
|
56
|
+
start()
|
package/index.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/*
|
|
2
|
+
A JS npm library for helping IPFS peers coordinate, find a common interest,
|
|
3
|
+
and stay connected around that interest.
|
|
4
|
+
|
|
5
|
+
See the specification document in the dev-docs directory.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Local libraries
|
|
9
|
+
import Adapters from './lib/adapters/index.js'
|
|
10
|
+
import UseCases from './lib/use-cases/index.js'
|
|
11
|
+
import Controllers from './lib/controllers/index.js'
|
|
12
|
+
|
|
13
|
+
class IpfsCoord {
|
|
14
|
+
constructor (localConfig = {}) {
|
|
15
|
+
// Dependency Injection
|
|
16
|
+
if (!localConfig.ipfs) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
'An instance of IPFS must be passed when instantiating the ipfs-coord library.'
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
if (!localConfig.wallet) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
'An instance of minimal-slp-wallet must be passed when instantiating the ipfs-coord library.'
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
this.type = localConfig.type
|
|
27
|
+
if (!this.type) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
'The type of IPFS node (browser or node.js) must be specified.'
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Retrieve and/or set the debug level.
|
|
34
|
+
// 0 = no debug information.
|
|
35
|
+
// 1 = status logs
|
|
36
|
+
// 2 = verbose errors about peer connections
|
|
37
|
+
this.debugLevel = parseInt(localConfig.debugLevel)
|
|
38
|
+
if (!this.debugLevel) this.debugLevel = 0
|
|
39
|
+
localConfig.debugLevel = this.debugLevel
|
|
40
|
+
console.log(`ipfs-coord debug level: ${localConfig.debugLevel}`)
|
|
41
|
+
|
|
42
|
+
// localConfiguration of an optional 'status' log handler for log reports. If none
|
|
43
|
+
// is specified, defaults to console.log.
|
|
44
|
+
if (localConfig.statusLog) {
|
|
45
|
+
this.statusLog = localConfig.statusLog
|
|
46
|
+
} else {
|
|
47
|
+
this.statusLog = console.log
|
|
48
|
+
}
|
|
49
|
+
// If the statusLog handler wasn't specified, then define it.
|
|
50
|
+
localConfig.statusLog = this.statusLog
|
|
51
|
+
|
|
52
|
+
// localConfiguration of an optional 'private' log handler for recieving e2e
|
|
53
|
+
// encrypted message. If none is specified, default to console.log.
|
|
54
|
+
if (localConfig.privateLog) {
|
|
55
|
+
this.privateLog = localConfig.privateLog
|
|
56
|
+
} else {
|
|
57
|
+
this.privateLog = console.log
|
|
58
|
+
}
|
|
59
|
+
// If the privateLog handler wasn't specified, then define it.
|
|
60
|
+
localConfig.privateLog = this.privateLog
|
|
61
|
+
|
|
62
|
+
// Load the adapter libraries.
|
|
63
|
+
this.adapters = new Adapters(localConfig)
|
|
64
|
+
localConfig.adapters = this.adapters
|
|
65
|
+
|
|
66
|
+
// Load the Use Cases
|
|
67
|
+
this.useCases = new UseCases(localConfig)
|
|
68
|
+
localConfig.useCases = this.useCases
|
|
69
|
+
|
|
70
|
+
// Load Controllers
|
|
71
|
+
this.controllers = new Controllers(localConfig)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Returns a Promise that resolves to true once the IPFS node has been
|
|
75
|
+
// initialized and has had a chance to connect to circuit relays and
|
|
76
|
+
// coordination pubsub channels.
|
|
77
|
+
async start () {
|
|
78
|
+
// Wait for the IPFS to finish initializing, then retrieve information
|
|
79
|
+
// about the node like it's ID and multiaddrs.
|
|
80
|
+
await this.adapters.ipfs.start()
|
|
81
|
+
|
|
82
|
+
// Create an instance of the 'self' which represents this IPFS node, BCH
|
|
83
|
+
// wallet, and other things that make up this ipfs-coord powered IPFS node.
|
|
84
|
+
this.thisNode = await this.useCases.thisNode.createSelf({ type: this.type })
|
|
85
|
+
// console.log('thisNode: ', this.thisNode)
|
|
86
|
+
|
|
87
|
+
// Subscribe to Pubsub Channels
|
|
88
|
+
await this.useCases.pubsub.initializePubsub(this.thisNode)
|
|
89
|
+
|
|
90
|
+
// Start timer-based controllers.
|
|
91
|
+
await this.controllers.timer.startTimers(this.thisNode, this.useCases)
|
|
92
|
+
|
|
93
|
+
// Kick-off initial connection to Circuit Relays and Peers.
|
|
94
|
+
// Note: Deliberatly *not* using await here, so that it doesn't block startup
|
|
95
|
+
// of ipfs-service-provider.
|
|
96
|
+
this._initializeConnections()
|
|
97
|
+
|
|
98
|
+
return true
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// This function kicks off initial connections to the circuit relays and then
|
|
102
|
+
// peers. This function is intended to be called once at startup. This handles
|
|
103
|
+
// the initial connections, but the timer-controller manages the connections
|
|
104
|
+
// after this initial function.
|
|
105
|
+
async _initializeConnections () {
|
|
106
|
+
try {
|
|
107
|
+
// Connect to Circuit Relays
|
|
108
|
+
await this.useCases.relays.initializeRelays(this.thisNode)
|
|
109
|
+
console.log('Initial connections to Circuit Relays complete.')
|
|
110
|
+
|
|
111
|
+
// Load list of Circuit Relays from GitHub Gist.
|
|
112
|
+
await this.useCases.relays.getCRGist(this.thisNode)
|
|
113
|
+
console.log('Finished connecting to Circuit Relays in GitHub Gist.')
|
|
114
|
+
|
|
115
|
+
await this.useCases.thisNode.refreshPeerConnections()
|
|
116
|
+
console.log('Initial connections to subnet Peers complete.')
|
|
117
|
+
|
|
118
|
+
return true
|
|
119
|
+
} catch (err) {
|
|
120
|
+
console.error('Error in _initializeConnections(): ', err)
|
|
121
|
+
// throw err
|
|
122
|
+
|
|
123
|
+
// Do not throw errors as it will prevent the node from starting.
|
|
124
|
+
return false
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export default IpfsCoord
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/*
|
|
2
|
+
A top level library for Bitcoin Cash (BCH) handling. This library will
|
|
3
|
+
encapsulate a lot of support libraries and contain BCH-specific methods.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class BchAdapter {
|
|
7
|
+
constructor (localConfig) {
|
|
8
|
+
// Dependency Injection
|
|
9
|
+
if (!localConfig.wallet) {
|
|
10
|
+
throw new Error(
|
|
11
|
+
'An instance of minimal-slp-wallet must be passed when instantiating the BCH adapter library.'
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
this.bchjs = localConfig.wallet.bchjs
|
|
16
|
+
this.mnemonic = localConfig.wallet.walletInfo.mnemonic
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Generate a BCH key pair and address. Returns an object with this information,
|
|
20
|
+
// which can be used for payments and e2e encryption.
|
|
21
|
+
// 12-word mnemonic string input is optional. Will generate a new wallet and
|
|
22
|
+
// keypair if not provided. Will use the first address on the SLIP44
|
|
23
|
+
// derivation path of 245 if a 12 word mnemonic is provided.
|
|
24
|
+
async generateBchId () {
|
|
25
|
+
try {
|
|
26
|
+
// Generate a 12-word mnemonic, if one isn't provided.
|
|
27
|
+
// if (!this.mnemonic) {
|
|
28
|
+
// this.mnemonic = this.bchjs.Mnemonic.generate(
|
|
29
|
+
// 128,
|
|
30
|
+
// this.bchjs.Mnemonic.wordLists().english
|
|
31
|
+
// )
|
|
32
|
+
// }
|
|
33
|
+
// console.log(`mnemonic: ${mnemonic}`)
|
|
34
|
+
|
|
35
|
+
// root seed buffer
|
|
36
|
+
const rootSeed = await this.bchjs.Mnemonic.toSeed(this.mnemonic)
|
|
37
|
+
|
|
38
|
+
const masterHDNode = this.bchjs.HDNode.fromSeed(rootSeed)
|
|
39
|
+
|
|
40
|
+
const childNode = masterHDNode.derivePath("m/44'/245'/0'/0/0")
|
|
41
|
+
|
|
42
|
+
const outObj = {}
|
|
43
|
+
|
|
44
|
+
// Generate the cash and SLP addresses.
|
|
45
|
+
outObj.cashAddress = this.bchjs.HDNode.toCashAddress(childNode)
|
|
46
|
+
outObj.slpAddress = this.bchjs.SLP.Address.toSLPAddress(
|
|
47
|
+
outObj.cashAddress
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
// No need to export the private key?
|
|
51
|
+
// outObj.WIF = this.bchjs.HDNode.toWIF(childNode)
|
|
52
|
+
|
|
53
|
+
// Export the public key as a hex string. This will be used for e2e
|
|
54
|
+
// encryption.
|
|
55
|
+
const pubKey = this.bchjs.HDNode.toPublicKey(childNode)
|
|
56
|
+
outObj.publicKey = pubKey.toString('hex')
|
|
57
|
+
|
|
58
|
+
return outObj
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error('Error in bch-lib.js/generateBchId()')
|
|
61
|
+
throw err
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async generatePrivateKey () {
|
|
66
|
+
try {
|
|
67
|
+
// Generate a 12-word mnemonic, if one isn't provided.
|
|
68
|
+
// if (!this.mnemonic) {
|
|
69
|
+
// this.mnemonic = this.bchjs.Mnemonic.generate(
|
|
70
|
+
// 128,
|
|
71
|
+
// this.bchjs.Mnemonic.wordLists().english
|
|
72
|
+
// )
|
|
73
|
+
// }
|
|
74
|
+
// console.log(`mnemonic: ${mnemonic}`)
|
|
75
|
+
|
|
76
|
+
// root seed buffer
|
|
77
|
+
const rootSeed = await this.bchjs.Mnemonic.toSeed(this.mnemonic)
|
|
78
|
+
|
|
79
|
+
const masterHDNode = this.bchjs.HDNode.fromSeed(rootSeed)
|
|
80
|
+
|
|
81
|
+
const childNode = masterHDNode.derivePath("m/44'/245'/0'/0/0")
|
|
82
|
+
|
|
83
|
+
const privKey = this.bchjs.HDNode.toWIF(childNode)
|
|
84
|
+
|
|
85
|
+
return privKey
|
|
86
|
+
} catch (err) {
|
|
87
|
+
console.error('Error in bch-lib.js/generatePrivateKey()')
|
|
88
|
+
throw err
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// module.exports = BchAdapter
|
|
94
|
+
export default BchAdapter
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/*
|
|
2
|
+
A library for end-to-end encryption (e2ee). This will largely be a wrapper
|
|
3
|
+
for existing encryption libraries.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import BchEncrypt from 'bch-encrypt-lib/index.js'
|
|
7
|
+
|
|
8
|
+
class EncryptionAdapter {
|
|
9
|
+
constructor (localConfig = {}) {
|
|
10
|
+
// Dependency injection
|
|
11
|
+
this.bch = localConfig.bch
|
|
12
|
+
if (!this.bch) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
'Must pass in an instance of bch Adapter when instantiating the encryption Adapter library.'
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
this.bchjs = this.bch.bchjs // Copy of bch-js
|
|
18
|
+
|
|
19
|
+
this.bchEncrypt = new BchEncrypt({ bchjs: this.bchjs })
|
|
20
|
+
// this.ipfs = encryptConfig.ipfs
|
|
21
|
+
// this.orbitdb = encryptConfig.orbitdb
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Decrypt incoming messages on the pubsub channel for this node.
|
|
25
|
+
async decryptMsg (msg) {
|
|
26
|
+
try {
|
|
27
|
+
// console.log('decryptMsg msgObj: ', msg)
|
|
28
|
+
|
|
29
|
+
const privKey = await this.bch.generatePrivateKey()
|
|
30
|
+
// console.log(`privKey: ${privKey}`)
|
|
31
|
+
|
|
32
|
+
const decryptedHexStr = await this.bchEncrypt.encryption.decryptFile(
|
|
33
|
+
privKey,
|
|
34
|
+
msg
|
|
35
|
+
)
|
|
36
|
+
// console.log(`decryptedHexStr ${decryptedHexStr}`)
|
|
37
|
+
|
|
38
|
+
const decryptedBuff = Buffer.from(decryptedHexStr, 'hex')
|
|
39
|
+
|
|
40
|
+
const decryptedStr = decryptedBuff.toString()
|
|
41
|
+
// console.log(`decryptedStr: ${decryptedStr}`)
|
|
42
|
+
|
|
43
|
+
return decryptedStr
|
|
44
|
+
} catch (err) {
|
|
45
|
+
// Exit quietly if the issue is a 'Bad MAC'. This seems to be a startup
|
|
46
|
+
// issue.
|
|
47
|
+
if (err.message.includes('Bad MAC')) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
'Bad MAC. Could not decrypt message. Peer may have stale encryption data for this node.'
|
|
50
|
+
)
|
|
51
|
+
// return ''
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
console.error('Error in decryptMsg()')
|
|
55
|
+
throw err
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Returns an encrypted hexidecimal string derived from an input message
|
|
60
|
+
// (string), encrypted with the public key of a peer.
|
|
61
|
+
async encryptMsg (peer, msg) {
|
|
62
|
+
try {
|
|
63
|
+
// console.log('peer: ', peer)
|
|
64
|
+
|
|
65
|
+
const pubKey = peer.data.encryptPubKey
|
|
66
|
+
// console.log('msg to encrypt: ', msg)
|
|
67
|
+
// console.log(`Encrypting with public key: ${pubKey}`)
|
|
68
|
+
|
|
69
|
+
const msgBuf = Buffer.from(msg, 'utf8').toString('hex')
|
|
70
|
+
|
|
71
|
+
const encryptedHexStr = await this.bchEncrypt.encryption.encryptFile(
|
|
72
|
+
pubKey,
|
|
73
|
+
msgBuf
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
return encryptedHexStr
|
|
77
|
+
} catch (err) {
|
|
78
|
+
console.error('Error in encryption.js/encryptMsg()')
|
|
79
|
+
throw err
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Send an e2e encrypted message to a peer.
|
|
84
|
+
// async sendEncryptedMsg (peer, msg) {
|
|
85
|
+
// try {
|
|
86
|
+
// // console.log('sendEncryptedMsg peer: ', peer)
|
|
87
|
+
// // console.log('sendEncryptedMsg msg: ', msg)
|
|
88
|
+
//
|
|
89
|
+
// // const channel = peer.ipfsId.toString()
|
|
90
|
+
// const pubKey = peer.encryptPubKey
|
|
91
|
+
// // const orbitdbId = peer.orbitdb
|
|
92
|
+
//
|
|
93
|
+
// const msgBuf = Buffer.from(msg, 'utf8').toString('hex')
|
|
94
|
+
// // console.log(`msgBuf: ${msgBuf}`)
|
|
95
|
+
//
|
|
96
|
+
// const encryptedHexStr = await this.bchEncrypt.encryption.encryptFile(
|
|
97
|
+
// pubKey,
|
|
98
|
+
// msgBuf
|
|
99
|
+
// )
|
|
100
|
+
// console.log(`encryptedHexStr: ${encryptedHexStr}`)
|
|
101
|
+
//
|
|
102
|
+
// // const msgBuf2 = Buffer.from(encryptedHexStr, 'hex')
|
|
103
|
+
//
|
|
104
|
+
// // Publish the message to the pubsub channel.
|
|
105
|
+
// // TODO: This will be deprecated in the future in favor of publishing to
|
|
106
|
+
// // the peers OrbitDB.
|
|
107
|
+
// // await this.ipfs.pubsub.publish(channel, msgBuf2)
|
|
108
|
+
//
|
|
109
|
+
// // if (orbitdbId) {
|
|
110
|
+
// // console.log(
|
|
111
|
+
// // `Ready to send encrypted message to peer ${channel} on orbitdb ID ${orbitdbId}`
|
|
112
|
+
// // )
|
|
113
|
+
// // await this.orbitdb.sendToDb(channel, encryptedHexStr, orbitdbId)
|
|
114
|
+
// // }
|
|
115
|
+
// } catch (err) {
|
|
116
|
+
// console.error('Error in sendEncryptedMsg()')
|
|
117
|
+
// throw err
|
|
118
|
+
// }
|
|
119
|
+
// }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// module.exports = EncryptionAdapter
|
|
123
|
+
export default EncryptionAdapter
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This adapter library is concerned with interfacing with the GitHub Gist API.
|
|
3
|
+
It's used to download a more easily maintained list of Circuit Relays
|
|
4
|
+
operated by members of the PSF.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import axios from 'axios'
|
|
8
|
+
|
|
9
|
+
class Gist {
|
|
10
|
+
constructor (localConfig = {}) {
|
|
11
|
+
this.axios = axios
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Retrieve a JSON file from a GitHub Gist
|
|
15
|
+
async getCRList () {
|
|
16
|
+
try {
|
|
17
|
+
// Public CRs
|
|
18
|
+
// https://gist.github.com/christroutner/048ea1a4b635a055c6bb63d48c373806
|
|
19
|
+
const gistUrl =
|
|
20
|
+
'https://api.github.com/gists/048ea1a4b635a055c6bb63d48c373806'
|
|
21
|
+
|
|
22
|
+
// Retrieve the gist from github.com.
|
|
23
|
+
const result = await this.axios.get(gistUrl)
|
|
24
|
+
// console.log('result.data: ', result.data)
|
|
25
|
+
|
|
26
|
+
// Get the current content of the gist.
|
|
27
|
+
const content = result.data.files['psf-public-circuit-relays.json'].content
|
|
28
|
+
// console.log('content: ', content)
|
|
29
|
+
|
|
30
|
+
// Parse the JSON string into an Object.
|
|
31
|
+
const object = JSON.parse(content)
|
|
32
|
+
// console.log('object: ', object)
|
|
33
|
+
|
|
34
|
+
return object
|
|
35
|
+
} catch (err) {
|
|
36
|
+
console.error('Error attempting to download GitHub Gist of alternative servers.')
|
|
37
|
+
throw err
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default Gist
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This is a top-level library for the Adapters. This file loads all other
|
|
3
|
+
adapter libraries.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Public npm libraries
|
|
7
|
+
// const EventEmitter = require('events')
|
|
8
|
+
// EventEmitter.defaultMaxListeners = 200
|
|
9
|
+
|
|
10
|
+
// Local libraries
|
|
11
|
+
import LogsAdapter from './logs-adapter.js'
|
|
12
|
+
import BchAdapter from './bch-adapter.js'
|
|
13
|
+
import IpfsAdapter from './ipfs-adapter.js'
|
|
14
|
+
import EncryptionAdapter from './encryption-adapter.js'
|
|
15
|
+
import PubsubAdapter from './pubsub-adapter/index.js'
|
|
16
|
+
import Gist from './gist.js'
|
|
17
|
+
|
|
18
|
+
// const Gist = require('./gist')
|
|
19
|
+
|
|
20
|
+
class Adapters {
|
|
21
|
+
constructor (localConfig = {}) {
|
|
22
|
+
// Dependency injection
|
|
23
|
+
if (!localConfig.ipfs) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
'An instance of IPFS must be passed when instantiating the Adapters library.'
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
if (!localConfig.wallet) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
'An instance of minimal-slp-wallet must be passed when instantiating the Adapters library.'
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Input Validation
|
|
35
|
+
if (!localConfig.type) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
'The type of IPFS node (browser or node.js) must be specified.'
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// BEGIN: Encapsulate dependencies
|
|
42
|
+
|
|
43
|
+
// Some adapter libraries depend on other adapter libraries. Pass them
|
|
44
|
+
// in the localConfig object.
|
|
45
|
+
|
|
46
|
+
this.log = new LogsAdapter(localConfig)
|
|
47
|
+
localConfig.log = this.log
|
|
48
|
+
|
|
49
|
+
this.bch = new BchAdapter(localConfig)
|
|
50
|
+
localConfig.bch = this.bch
|
|
51
|
+
|
|
52
|
+
this.ipfs = new IpfsAdapter(localConfig)
|
|
53
|
+
localConfig.ipfsAdapter = this.ipfs
|
|
54
|
+
|
|
55
|
+
this.encryption = new EncryptionAdapter(localConfig)
|
|
56
|
+
localConfig.encryption = this.encryption
|
|
57
|
+
|
|
58
|
+
this.pubsub = new PubsubAdapter(localConfig)
|
|
59
|
+
this.gist = new Gist(localConfig)
|
|
60
|
+
|
|
61
|
+
// END: Encapsulate dependencies
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// module.exports = Adapters
|
|
66
|
+
export default Adapters
|