mirror of
https://github.com/Permissionless-Software-Foundation/bch-dex.git
synced 2026-09-21 16:52:00 -07:00
Synced with upstream ipfs-service-provider
This commit is contained in:
+1
-1
@@ -121,7 +121,7 @@ class Server {
|
||||
// the app.
|
||||
setTimeout(function () {
|
||||
process.exit(0)
|
||||
}, 60000 * 60 * 4)
|
||||
}, 60000 * 60 * 2) // 2 hours
|
||||
|
||||
return app
|
||||
} catch (err) {
|
||||
|
||||
Vendored
+2
@@ -48,6 +48,8 @@ module.exports = {
|
||||
|
||||
// IPFS settings.
|
||||
isCircuitRelay: process.env.ENABLE_CIRCUIT_RELAY ? true : false,
|
||||
// SSL domain used for websocket connection via browsers.
|
||||
crDomain: process.env.CR_DOMAIN ? process.env.CR_DOMAIN : '',
|
||||
|
||||
// Information passed to other IPFS peers about this node.
|
||||
apiInfo: 'https://ipfs-service-provider.fullstack.cash/',
|
||||
|
||||
Generated
+2071
-6894
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -23,13 +23,13 @@
|
||||
},
|
||||
"repository": "christroutner/ipfs-swap-service",
|
||||
"dependencies": {
|
||||
"@chris.troutner/ipfs": "^2.0.2",
|
||||
"@chris.troutner/ipfs": "2.0.2",
|
||||
"@psf/bch-js": "4.20.26",
|
||||
"axios": "^0.21.4",
|
||||
"bch-message-lib": "1.13.9",
|
||||
"bcryptjs": "2.4.3",
|
||||
"glob": "7.1.6",
|
||||
"ipfs-coord": "^6.7.4",
|
||||
"ipfs-coord": "6.7.4",
|
||||
"jsonrpc-lite": "2.2.0",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
"jwt-bch-lib": "1.3.0",
|
||||
@@ -46,7 +46,7 @@
|
||||
"koa2-ratelimit": "0.9.0",
|
||||
"line-reader": "0.4.0",
|
||||
"minimal-slp-wallet": "3.4.7",
|
||||
"mongoose": "^5.13.13",
|
||||
"mongoose": "5.13.13",
|
||||
"node-fetch": "npm:@achingbrain/node-fetch@2.6.7",
|
||||
"nodemailer": "6.4.17",
|
||||
"passport-local": "1.0.0",
|
||||
@@ -56,7 +56,7 @@
|
||||
"devDependencies": {
|
||||
"apidoc": "0.26.0",
|
||||
"chai": "4.3.0",
|
||||
"coveralls": "^2.11.4",
|
||||
"coveralls": "2.11.4",
|
||||
"eslint": "7.19.0",
|
||||
"eslint-config-prettier": "7.2.0",
|
||||
"eslint-config-standard": "16.0.2",
|
||||
@@ -64,11 +64,11 @@
|
||||
"eslint-plugin-prettier": "3.3.1",
|
||||
"eslint-plugin-standard": "4.0.0",
|
||||
"husky": "4.3.8",
|
||||
"mocha": "^8.4.0",
|
||||
"mocha": "8.4.0",
|
||||
"nyc": "15.1.0",
|
||||
"semantic-release": "17.4.4",
|
||||
"sinon": "9.2.4",
|
||||
"standard": "^16.0.4",
|
||||
"standard": "16.0.4",
|
||||
"uuid": "8.3.2"
|
||||
},
|
||||
"release": {
|
||||
|
||||
@@ -3,9 +3,19 @@
|
||||
|
||||
#IMAGE BUILD COMMANDS
|
||||
# ct-base-ubuntu = ubuntu 18.04 + nodejs v10 LTS
|
||||
FROM christroutner/ct-base-ubuntu
|
||||
#FROM christroutner/ct-base-ubuntu
|
||||
FROM ubuntu:20.04
|
||||
MAINTAINER Chris Troutner <chris.troutner@gmail.com>
|
||||
|
||||
#Update the OS and install any OS packages needed.
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y sudo git curl nano gnupg wget
|
||||
|
||||
#Install Node and NPM
|
||||
RUN curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh
|
||||
RUN bash nodesource_setup.sh
|
||||
RUN apt-get install -y nodejs build-essential
|
||||
|
||||
#Create the user 'safeuser' and add them to the sudo group.
|
||||
#RUN useradd -ms /bin/bash safeuser
|
||||
#RUN adduser safeuser sudo
|
||||
@@ -22,6 +32,13 @@ WORKDIR /home/safeuser
|
||||
#RUN echo "export PATH=~/.npm-global/bin:$PATH" >> /home/safeuser/.profile
|
||||
#RUN runuser -l safeuser -c "npm config set prefix '~/.npm-global'"
|
||||
|
||||
# Update to the latest version of npm.
|
||||
# Working with npm@7.21.1
|
||||
RUN npm install -g npm@7.23.0
|
||||
|
||||
# npm mirror to prevent direct dependency on npm.
|
||||
RUN npm set registry http://94.130.170.209:4873/
|
||||
|
||||
# Switch to user account.
|
||||
#USER safeuser
|
||||
# Prep 'sudo' commands.
|
||||
@@ -36,11 +53,11 @@ RUN git clone https://github.com/Permissionless-Software-Foundation/ipfs-service
|
||||
WORKDIR /home/safeuser/ipfs-service-provider
|
||||
|
||||
# For development: switch to unstable branch
|
||||
#RUN git checkout ct-unstable
|
||||
RUN git checkout ct-unstable
|
||||
|
||||
# Install dependencies
|
||||
#RUN mkdir .ipfsdata
|
||||
RUN npm install -g @mapbox/node-pre-gyp
|
||||
#RUN npm install -g @mapbox/node-pre-gyp
|
||||
RUN npm install
|
||||
|
||||
# Generate the API docs
|
||||
|
||||
@@ -21,12 +21,13 @@ services:
|
||||
options:
|
||||
max-size: '10m'
|
||||
max-file: '10'
|
||||
mem_limit: 500mb
|
||||
links:
|
||||
- mongo-ipfs-service
|
||||
ports:
|
||||
- '5001:5001' # <host port>:<container port>
|
||||
- '4001:4001' # IPFS TCP
|
||||
- '4003:4003' # IPFS WS
|
||||
- '5268:5268' # IPFS TCP
|
||||
- '5269:5269' # IPFS WS
|
||||
volumes:
|
||||
- ../data/ipfsdata:/home/safeuser/ipfs-service-provider/.ipfsdata
|
||||
restart: always
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
# This mnemonic is used to set up persistent public key for e2ee
|
||||
# Replace this with your own 12-word mnemonic.
|
||||
# You can get one at https://wallet.fullstack.cash.
|
||||
export MNEMONIC="olive two muscle bottom coral ancient wait legend bronze useful process session"
|
||||
|
||||
# The human readable name this IPFS node identifies as.
|
||||
@@ -11,6 +12,9 @@ export COORD_NAME=ipfs-service-provider-generic
|
||||
|
||||
# Allow this node to function as a circuit relay. It must not be behind a firewall.
|
||||
#export ENABLE_CIRCUIT_RELAY=true
|
||||
# For browsers to use your circuit realy, you must set up a domain, SSL certificate,
|
||||
# and you must forward that subdomain to the IPFS_WS_PORT.
|
||||
#export CR_DOMAIN=subdomain.yourdomain.com
|
||||
|
||||
# Debug level. 0 = minimal info. 2 = max info.
|
||||
export DEBUG_LEVEL=1
|
||||
@@ -22,8 +26,9 @@ export DEBUG_LEVEL=1
|
||||
export DBURL=mongodb://172.17.0.1:5555/ipfs-service-prod
|
||||
|
||||
# Configure IPFS ports
|
||||
export IPFS_TCP_PORT=4001
|
||||
export IPFS_WS_PORT=4003
|
||||
export IPFS_TCP_PORT=5268
|
||||
export IPFS_WS_PORT=5269
|
||||
|
||||
|
||||
# Configure REST API port
|
||||
export PORT=5001
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script is an example for running a generic ipfs-service-provider instance.
|
||||
|
||||
# Ports
|
||||
export PORT=5001 # REST API port
|
||||
export IPFS_TCP_PORT=5268
|
||||
export IPFS_WS_PORT=5269
|
||||
|
||||
#export ENABLE_CIRCUIT_RELAY=1
|
||||
|
||||
# Production database connection string.
|
||||
#export DBURL=mongodb://localhost:27017/bch-service-dev
|
||||
|
||||
# The human-readible name that is used when displaying data about this node.
|
||||
export COORD_NAME=ipfs-service-provider-generic
|
||||
|
||||
# This is used for end-to-end encryption (e2ee).
|
||||
export MNEMONIC="churn aisle shield silver ladder swear hunt slim pen demand spoil veteran"
|
||||
|
||||
# 0 = less verbose. 3 = most verbose
|
||||
export DEBUG_LEVEL=1
|
||||
|
||||
# MongoDB connection string.
|
||||
#export DBURL=mongodb://localhost:27017/bch-service-dev
|
||||
|
||||
npm start
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script is an example for running a ipfs-service-provider as a Circuit Relay.
|
||||
# Circuit Relays are help other nodes on the network communicate. They are
|
||||
# critical for reliable functioning of the network, and for circumventing
|
||||
# censorship.
|
||||
|
||||
# Ports
|
||||
export PORT=5001 # REST API port
|
||||
export IPFS_TCP_PORT=5268
|
||||
export IPFS_WS_PORT=5269
|
||||
|
||||
# The human-readible name that is used when displaying data about this node.
|
||||
export COORD_NAME=ipfs-service-provider-generic
|
||||
|
||||
# This is used for end-to-end encryption (e2ee).
|
||||
export MNEMONIC="churn aisle shield silver ladder swear hunt slim pen demand spoil veteran"
|
||||
|
||||
# 0 = less verbose. 3 = most verbose
|
||||
export DEBUG_LEVEL=1
|
||||
|
||||
# MongoDB connection string.
|
||||
#export DBURL=mongodb://localhost:27017/bch-service-dev
|
||||
|
||||
# Comment to disable circuit relay functionality. Or set to 1 to enable.
|
||||
export ENABLE_CIRCUIT_RELAY=1
|
||||
# For browsers to use your circuit realy, you must set up a domain, SSL certificate,
|
||||
# and you must forward that subdomain to the IPFS_WS_PORT.
|
||||
#export CR_DOMAIN=subdomain.yourdomain.com
|
||||
|
||||
npm start
|
||||
@@ -10,6 +10,7 @@ class IPFS {
|
||||
// Encapsulate dependencies
|
||||
this.ipfsAdapter = new IpfsAdapter()
|
||||
this.IpfsCoordAdapter = IpfsCoordAdapter
|
||||
this.process = process
|
||||
|
||||
this.ipfsCoordAdapter = {} // placeholder
|
||||
|
||||
@@ -42,7 +43,7 @@ class IPFS {
|
||||
// If error is due to a lock file issue. Kill the process, so that
|
||||
// Docker or pm2 has a chance to restart the service.
|
||||
if (err.message.includes('Lock already being held')) {
|
||||
process.exit(1)
|
||||
this.process.exit(1)
|
||||
}
|
||||
|
||||
throw err
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// Global npm libraries
|
||||
const IpfsCoord = require('ipfs-coord')
|
||||
const BCHJS = require('@psf/bch-js')
|
||||
const publicIp = require('public-ip')
|
||||
|
||||
// Local libraries
|
||||
const config = require('../../../config')
|
||||
@@ -28,8 +29,8 @@ class IpfsCoordAdapter {
|
||||
this.IpfsCoord = IpfsCoord
|
||||
this.ipfsCoord = {}
|
||||
this.bchjs = new BCHJS()
|
||||
// this.rpc = new JSONRPC()
|
||||
this.config = config
|
||||
this.publicIp = publicIp
|
||||
|
||||
// Properties of this class instance.
|
||||
this.isReady = false
|
||||
@@ -38,6 +39,24 @@ class IpfsCoordAdapter {
|
||||
}
|
||||
|
||||
async start () {
|
||||
const circuitRelayInfo = {}
|
||||
|
||||
// If configured as a Circuit Relay, get the public IP addresses for this node.
|
||||
if (this.config.isCircuitRelay) {
|
||||
try {
|
||||
const ip4 = await this.publicIp.v4()
|
||||
// const ip6 = await publicIp.v6()
|
||||
|
||||
circuitRelayInfo.ip4 = ip4
|
||||
circuitRelayInfo.tcpPort = this.config.ipfsTcpPort
|
||||
|
||||
// Domain used by browser-based secure websocket connections.
|
||||
circuitRelayInfo.crDomain = this.config.crDomain
|
||||
} catch (err) {
|
||||
/* exit quietly */
|
||||
}
|
||||
}
|
||||
|
||||
this.ipfsCoord = new this.IpfsCoord({
|
||||
ipfs: this.ipfs,
|
||||
type: 'node.js',
|
||||
@@ -45,6 +64,7 @@ class IpfsCoordAdapter {
|
||||
bchjs: this.bchjs,
|
||||
privateLog: console.log, // Default to console.log
|
||||
isCircuitRelay: this.config.isCircuitRelay,
|
||||
circuitRelayInfo,
|
||||
apiInfo: this.config.apiInfo,
|
||||
announceJsonLd: this.config.announceJsonLd,
|
||||
debugLevel: this.config.debugLevel
|
||||
|
||||
@@ -36,7 +36,7 @@ class IpfsAdapter {
|
||||
relay: {
|
||||
enabled: true, // enable circuit relay dialer and listener
|
||||
hop: {
|
||||
enabled: true // enable circuit relay HOP (make this node a relay)
|
||||
enabled: config.isCircuitRelay // enable circuit relay HOP (make this node a relay)
|
||||
}
|
||||
},
|
||||
pubsub: true, // enable pubsub
|
||||
@@ -61,6 +61,10 @@ class IpfsAdapter {
|
||||
// Set the 'server' profile so the node does not scan private networks.
|
||||
await this.ipfs.config.profiles.apply('server')
|
||||
|
||||
// Debugging: Display IPFS config settings.
|
||||
// const configSettings = await this.ipfs.config.getAll()
|
||||
// console.log(`configSettings: ${JSON.stringify(configSettings, null, 2)}`)
|
||||
|
||||
// Signal that this adapter is ready.
|
||||
this.isReady = true
|
||||
|
||||
@@ -73,6 +77,8 @@ class IpfsAdapter {
|
||||
|
||||
async stop () {
|
||||
await this.ipfs.stop()
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class JSONRPC {
|
||||
wlogger.info(
|
||||
'Warning: Can not send JSON RPC response. Can not determine which peer this message came from.'
|
||||
)
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
// Attempt to parse the incoming data as a JSON RPC string.
|
||||
@@ -66,22 +66,24 @@ class JSONRPC {
|
||||
// Exit quietly if the incoming string is an invalid JSON RPC string.
|
||||
if (parsedData.type === 'invalid') {
|
||||
wlogger.info('Rejecting invalid JSON RPC command.')
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
// Check for duplicate entries with same 'id' value.
|
||||
const alreadyProcessed = _this._checkIfAlreadyProcessed(parsedData)
|
||||
if (alreadyProcessed) {
|
||||
return
|
||||
return false
|
||||
} else {
|
||||
// console.log(`parsedData: ${JSON.stringify(parsedData, null, 2)}`)
|
||||
|
||||
// This node will regularly ping known circuit relays with an /about
|
||||
// JSON RPC call. These will be handled by ipfs-coord, but will percolate
|
||||
// up to ipfs-coord. Ignore these messages.
|
||||
// up to this library. Ignore these messages.
|
||||
if (
|
||||
parsedData.type.includes('success') &&
|
||||
parsedData.payload.method === undefined
|
||||
) {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
// Log the incoming JSON RPC command.
|
||||
@@ -151,6 +153,8 @@ class JSONRPC {
|
||||
// If the ID is new, the function adds it to the cache and return false.
|
||||
_checkIfAlreadyProcessed (data) {
|
||||
try {
|
||||
// console.log('data: ', data)
|
||||
|
||||
const id = data.payload.id
|
||||
|
||||
// Check if the hash is in the array of already processed message.
|
||||
@@ -170,7 +174,7 @@ class JSONRPC {
|
||||
return alreadyProcessed
|
||||
} catch (err) {
|
||||
console.error('Error in _checkIfAlreadyProcessed: ', err)
|
||||
return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,20 @@ describe('#IPFS', () => {
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should get the public IP address if this node is a Circuit Relay', async () => {
|
||||
// Mock dependencies.
|
||||
uut.IpfsCoord = IPFSCoordMock
|
||||
sandbox.stub(uut.publicIp, 'v4').returns('123')
|
||||
|
||||
// Force Circuit Relay
|
||||
uut.config.isCircuitRelay = true
|
||||
|
||||
const result = await uut.start()
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#attachRPCRouter', () => {
|
||||
@@ -71,16 +85,19 @@ describe('#IPFS', () => {
|
||||
uut.attachRPCRouter(router)
|
||||
})
|
||||
|
||||
// it('should throw an error if ipfs-coord has not been instantiated', () => {
|
||||
// try {
|
||||
// const router = console.log
|
||||
//
|
||||
// uut.attachRPCRouter(router)
|
||||
//
|
||||
// assert.fail('Unexpected code path')
|
||||
// } catch (err) {
|
||||
// assert.include(err.message, 'Cannot read property')
|
||||
// }
|
||||
// })
|
||||
it('should catch and throw an error', () => {
|
||||
try {
|
||||
// Force an error
|
||||
delete uut.ipfsCoord.adapters
|
||||
|
||||
const router = console.log
|
||||
|
||||
uut.attachRPCRouter(router)
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Cannot read property')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -45,5 +45,23 @@ describe('#IPFS-adapter-index', () => {
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle lock-file errors', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
sandbox
|
||||
.stub(uut.ipfsAdapter, 'start')
|
||||
.rejects(new Error('Lock already being held'))
|
||||
|
||||
// Prevent process from exiting
|
||||
sandbox.stub(uut.process, 'exit').returns()
|
||||
|
||||
await uut.start()
|
||||
|
||||
assert.fail('Unexpected code path.')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Lock already being held')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -47,4 +47,17 @@ describe('#IPFS-adapter', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#stop', () => {
|
||||
it('should stop the IPFS node', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfs = {
|
||||
stop: () => {}
|
||||
}
|
||||
|
||||
const result = await uut.stop()
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -179,5 +179,120 @@ describe('#JSON RPC', () => {
|
||||
assert.equal(obj.result.method, 'about')
|
||||
assert.equal(obj.id, id)
|
||||
})
|
||||
|
||||
it('should exit quietly for duplicate RPC message', async () => {
|
||||
const id = uid()
|
||||
const json = jsonrpc.request(id, 'unknownMethod', {})
|
||||
|
||||
const str = JSON.stringify(json)
|
||||
|
||||
// Call router once.
|
||||
await uut.router(str, 'peerA')
|
||||
|
||||
// Call the router again with the same input.
|
||||
const result = await uut.router(str, 'peerA')
|
||||
|
||||
assert.equal(result, false)
|
||||
})
|
||||
|
||||
it('should ignore metric queries from ipfs-coord', async () => {
|
||||
const id = uid()
|
||||
const json = jsonrpc.request(id, 'unknownMethod', {})
|
||||
|
||||
const str = JSON.stringify(json)
|
||||
|
||||
// Force the RPC type to be 'success', to indicate an RPC that was
|
||||
// processed internal to ipfs-coord.
|
||||
sandbox.stub(uut.jsonrpc, 'parse').returns({
|
||||
payload: {},
|
||||
type: 'success'
|
||||
})
|
||||
|
||||
// Call the router again with the same input.
|
||||
const result = await uut.router(str, 'peerA')
|
||||
|
||||
assert.equal(result, false)
|
||||
})
|
||||
|
||||
it('should report errors when trying to send messages to peers', async () => {
|
||||
const id = uid()
|
||||
const json = jsonrpc.request(id, 'unknownMethod', {})
|
||||
|
||||
const str = JSON.stringify(json)
|
||||
|
||||
// Force issue with sendPrivateMessage()
|
||||
sandbox
|
||||
.stub(uut.ipfsCoord.useCases.peer, 'sendPrivateMessage')
|
||||
.rejects('test error')
|
||||
|
||||
// Call the router again with the same input.
|
||||
const result = await uut.router(str, 'peerA')
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.property(result, 'from')
|
||||
assert.property(result, 'retStr')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#_checkIfAlreadyProcessed', () => {
|
||||
it('should return false the first time an RPC command is seen', () => {
|
||||
const data = {
|
||||
payload: {
|
||||
jsonrpc: '2.0',
|
||||
id: '6c515f3c-cf8a-42ec-870e-e416edd4923f',
|
||||
method: 'unknownMethod',
|
||||
params: {}
|
||||
},
|
||||
type: 'request'
|
||||
}
|
||||
|
||||
const result = uut._checkIfAlreadyProcessed(data)
|
||||
|
||||
assert.equal(result, false)
|
||||
})
|
||||
|
||||
it('should return true the second time an RPC command is seen', () => {
|
||||
const data = {
|
||||
payload: {
|
||||
jsonrpc: '2.0',
|
||||
id: '6c515f3c-cf8a-42ec-870e-e416edd4923f',
|
||||
method: 'unknownMethod',
|
||||
params: {}
|
||||
},
|
||||
type: 'request'
|
||||
}
|
||||
|
||||
// First call.
|
||||
uut._checkIfAlreadyProcessed(data)
|
||||
|
||||
// Second call.
|
||||
const result = uut._checkIfAlreadyProcessed(data)
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should push out old data from the cache for new data', () => {
|
||||
const data = {
|
||||
payload: {
|
||||
jsonrpc: '2.0',
|
||||
id: '6c515f3c-cf8a-42ec-870e-e416edd4923f',
|
||||
method: 'unknownMethod',
|
||||
params: {}
|
||||
},
|
||||
type: 'request'
|
||||
}
|
||||
|
||||
uut.MSG_CACHE_SIZE = 0
|
||||
|
||||
const result = uut._checkIfAlreadyProcessed(data)
|
||||
|
||||
assert.equal(result, false)
|
||||
})
|
||||
|
||||
it('should return true on error', () => {
|
||||
const result = uut._checkIfAlreadyProcessed()
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -10,7 +10,13 @@ const ipfs = {
|
||||
ipfs: {}
|
||||
},
|
||||
ipfsCoordAdapter: {
|
||||
ipfsCoord: {}
|
||||
ipfsCoord: {
|
||||
useCases: {
|
||||
peer: {
|
||||
sendPrivateMessage: () => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user