Files
bch-dex/src/adapters/ipfs/ipfs.js
T

180 lines
5.6 KiB
JavaScript
Raw Normal View History

/*
Clean Architecture Adapter for IPFS.
This library deals with IPFS so that the apps business logic doesn't need
to have any specific knowledge of the js-ipfs library.
2021-09-05 09:23:38 -07:00
TODO: Add the external IP address to the list of multiaddrs advertised by
this node. See this GitHub Issue for details:
https://github.com/Permissionless-Software-Foundation/ipfs-service-provider/issues/38
*/
// Global npm libraries
2023-10-22 07:51:45 -07:00
import { createHelia } from 'helia'
2022-09-08 08:58:39 -07:00
import fs from 'fs'
2023-10-22 07:51:45 -07:00
import { FsBlockstore } from 'blockstore-fs'
import { FsDatastore } from 'datastore-fs'
import { createLibp2p } from 'libp2p'
import { tcp } from '@libp2p/tcp'
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { bootstrap } from '@libp2p/bootstrap'
import { identifyService } from 'libp2p/identify'
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
// Local libraries
2022-09-08 08:58:39 -07:00
import config from '../../../config/index.js'
2023-10-22 17:35:10 -07:00
// Hack to get __dirname back.
// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/
import * as url from 'url'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
console.log('__dirname: ', __dirname)
const IPFS_DIR = `${__dirname}../../../.ipfsdata/ipfs`
class IpfsAdapter {
constructor (localConfig) {
// Encapsulate dependencies
this.config = config
2022-09-08 08:58:39 -07:00
this.fs = fs
2023-10-22 07:51:45 -07:00
// this.create = create
// Choose the IPFS constructor based on the config settings.
2022-09-08 08:58:39 -07:00
// this.IPFS = IPFSembedded // default
// if (this.config.isProduction) {
// this.IPFS = IPFSexternal
// }
// Properties of this class instance.
this.isReady = false
2023-10-22 17:35:10 -07:00
// Bind 'this' object to all subfunctions
this.start = this.start.bind(this)
this.createNode = this.createNode.bind(this)
this.stop = this.stop.bind(this)
}
// Start an IPFS node.
async start () {
try {
2023-10-22 07:51:45 -07:00
// Create an IPFS node
const ipfs = await this.createNode()
// console.log('ipfs: ', ipfs)
2023-10-22 07:51:45 -07:00
// Get the multiaddrs for the node.
const multiaddrs = ipfs.libp2p.getMultiaddrs()
console.log('Multiaddrs: ', multiaddrs)
2023-10-22 07:51:45 -07:00
this.multiaddrs = multiaddrs
this.id = ipfs.libp2p.peerId.toString()
console.log('IPFS ID: ', this.id)
// Signal that this adapter is ready.
this.isReady = true
2023-10-22 07:51:45 -07:00
this.ipfs = ipfs
return this.ipfs
} catch (err) {
console.error('Error in ipfs.js/start()')
// If IPFS crashes because the /blocks directory is full, wipe the directory.
// if (err.message.includes('No space left on device')) {
// this.rmBlocksDir()
// }
throw err
}
}
2021-08-08 08:09:48 -07:00
2023-10-22 07:51:45 -07:00
// This function creates an IPFS node using Helia.
// It returns the node as an object.
async createNode () {
try {
// Create block and data stores.
const blockstore = new FsBlockstore(`${IPFS_DIR}/blockstore`)
const datastore = new FsDatastore(`${IPFS_DIR}/datastore`)
// libp2p is the networking layer that underpins Helia
const libp2p = await createLibp2p({
datastore,
addresses: {
listen: [
'/ip4/127.0.0.1/tcp/0',
`/ip4/0.0.0.0/tcp/${this.config.ipfsTcpPort}`
]
},
transports: [
tcp()
],
connectionEncryption: [
noise()
],
streamMuxers: [
yamux()
],
peerDiscovery: [
bootstrap({
list: [
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
'/ip4/5.161.108.190/tcp/4102/p2p/12D3KooWKNuBjaMgEDN2tGqzmdfM2bmd22VEuboC4X7x8ua4DvUg',
'/ip4/5.161.108.190/tcp/4001/p2p/12D3KooWMW3u8ygGHqNHjxXsw7TA39vgrSQEx7vEGoUh7EiCwGGv',
'/ip4/137.184.13.92/tcp/4001/p2p/12D3KooWMbpo92kSGwWiN6QH7fvstMWiLZKcxmReq3Hhbpya2bq4',
'/ip4/78.46.129.7/tcp/4001/p2p/12D3KooWJyc54njjeZGbLew4D8u1ghrmZTTPyh3QpBF7dxtd3zGY',
'/ip4/5.161.72.148/tcp/4001/p2p/12D3KooWAVG5kn46P9mjKCLUSPesmmLeKf2a79qRt6u22hJaEARJ',
'/ip4/161.35.99.207/tcp/4001/p2p/12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu',
'/ip4/192.168.2.173/tcp/4001/p2p/12D3KooWAz2hbriyU9o1wHNU2nxqG8mMgAdWnXCSfWiv5kxSfW49'
]
})
],
services: {
identify: identifyService(),
pubsub: gossipsub({ allowPublishToZeroPeers: true })
}
})
// create a Helia node
const helia = await createHelia({
blockstore,
datastore,
libp2p
})
return helia
} catch (err) {
console.error('Error creating Helia node: ', err)
}
}
2021-08-08 08:09:48 -07:00
async stop () {
await this.ipfs.stop()
return true
2021-08-08 08:09:48 -07:00
}
// Remove the '/blocks' directory that is used to store IPFS data.
// Dev Note: It's assumed this node is not pinning any data and that
// everything in this directory is transient. This folder will regularly
// fill up and prevent IPFS from starting.
// rmBlocksDir () {
// try {
// const dir = `${IPFS_DIR}/blocks`
// console.log(`Deleting ${dir} directory...`)
//
// this.fs.rmdirSync(dir, { recursive: true })
//
// console.log(`${dir} directory is deleted!`)
//
// return true // Signal successful execution.
// } catch (err) {
// console.log('Error in rmBlocksDir()')
// throw err
// }
// }
}
2022-09-08 08:58:39 -07:00
export default IpfsAdapter