mirror of
https://github.com/Permissionless-Software-Foundation/bch-dex.git
synced 2026-09-22 09:11:59 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a5036e3aa | ||
|
|
cca10452c0 | ||
|
|
309ea0774d | ||
|
|
c2b68a0787 | ||
|
|
2bb4cd7cae | ||
|
|
9ca581e998 | ||
|
|
02adbd5634 | ||
|
|
da637df44a | ||
|
|
9315e6f166 | ||
|
|
7e965e8415 | ||
|
|
a5916c95f9 | ||
|
|
708f97d107 | ||
|
|
637738bfb9 | ||
|
|
d8e82c5ad2 | ||
|
|
b23acd3cdc | ||
|
|
c71fda38ff | ||
|
|
f99f49d840 | ||
|
|
2edd924c57 | ||
|
|
689c8fd8d9 | ||
|
|
ffd6c452c9 | ||
|
|
fc8e160874 | ||
|
|
d2f83307e6 | ||
|
|
1a09fcd26f | ||
|
|
db54a067f4 | ||
|
|
9fcee20498 | ||
|
|
0a04ee61ef | ||
|
|
7cae06dd65 | ||
|
|
96064ac9a7 | ||
|
|
3690b749fe | ||
|
|
e2c5821dbe | ||
|
|
9967d5145b | ||
|
|
9d16291855 | ||
|
|
1518d1a12b | ||
|
|
6dbf284876 | ||
|
|
d1e96505c8 | ||
|
|
1e80a3159e | ||
|
|
d3df9546a7 | ||
|
|
3422f3146e | ||
|
|
5c4dc21d3e | ||
|
|
b74f460a9a | ||
|
|
6585ceacc7 | ||
|
|
942dbedd44 | ||
|
|
825ede0760 | ||
|
|
5e4540bd84 | ||
|
|
a3b21d7547 | ||
|
|
87ece9d6bb | ||
|
|
125330f5b0 | ||
|
|
6b3fc78fc9 | ||
|
|
3d7d4a57d2 | ||
|
|
abf07005eb | ||
|
|
b68a143071 | ||
|
|
5c25ebeeca | ||
|
|
3b17ba8e8b | ||
|
|
434a4d7bd6 | ||
|
|
dd36ebc7a0 | ||
|
|
f117fe15df | ||
|
|
0333f77f5a | ||
|
|
3c908d1a4d | ||
|
|
eb46a4c130 | ||
|
|
d0efdcfa07 | ||
|
|
62a7fcb16d | ||
|
|
d8addd5b27 | ||
|
|
bf6f1cf62d | ||
|
|
b7df7c47a5 | ||
|
|
ae260db4af | ||
|
|
778098ca12 | ||
|
|
0c4bb9c4a1 | ||
|
|
9cb975656d | ||
|
|
4f6564423e | ||
|
|
54e7e74ae5 | ||
|
|
324c372119 | ||
|
|
da62f1bbe3 | ||
|
|
129047fe88 | ||
|
|
3f2a12f6ec | ||
|
|
c1b687efd1 | ||
|
|
fb182ced58 | ||
|
|
bec7c11e46 | ||
|
|
fb10e10226 | ||
|
|
5b37e47747 | ||
|
|
a3cea782ba | ||
|
|
14ffdae194 | ||
|
|
faf5a83eb6 | ||
|
|
92a35b220f | ||
|
|
58e934eeab | ||
|
|
d5de76729d | ||
|
|
805cac97d9 | ||
|
|
91fa460158 | ||
|
|
2d6055b537 | ||
|
|
72e6a37ed1 | ||
|
|
9d18a24c7e | ||
|
|
feacf6e571 | ||
|
|
c51f7cdf3a | ||
|
|
07fbe8c654 | ||
|
|
a65ec7494f | ||
|
|
59fca7903f | ||
|
|
f8948f12fa | ||
|
|
b79163cdf7 | ||
|
|
2d537994ef | ||
|
|
2ae963ee62 | ||
|
|
f5cd59eb12 | ||
|
|
d4f9e128b3 | ||
|
|
3c322ecbd0 | ||
|
|
56944176fa | ||
|
|
5f9cdc3f2e | ||
|
|
c20938f9f7 | ||
|
|
5be3c92a29 | ||
|
|
1476500c61 | ||
|
|
519980eb99 | ||
|
|
1e4b71aacd | ||
|
|
2c1c009b64 | ||
|
|
09cbfd00e8 | ||
|
|
2c21d79740 | ||
|
|
15eb871b1f | ||
|
|
7e3ce1564d |
+61
-37
@@ -24,39 +24,48 @@ const config = require('../config') // this first.
|
||||
const AdminLib = require('../src/adapters/admin')
|
||||
// const adminLib = new AdminLib()
|
||||
|
||||
const WebHookLib = require('../src/adapters/webhook')
|
||||
const webhookLib = new WebHookLib()
|
||||
// const WebHookLib = require('../src/adapters/webhook')
|
||||
// const webhookLib = new WebHookLib()
|
||||
|
||||
// const JSONRPC = require('../src/rpc')
|
||||
// const rpc = new JSONRPC()
|
||||
|
||||
const errorMiddleware = require('../src/controllers/rest-api/middleware/error')
|
||||
// const { wlogger } = require('../src/adapters/wlogger')
|
||||
const Controllers = require('../src/controllers')
|
||||
|
||||
class Server {
|
||||
constructor () {
|
||||
// Encapsulate dependencies
|
||||
this.adminLib = new AdminLib()
|
||||
this.controllers = new Controllers()
|
||||
this.mongoose = mongoose
|
||||
this.config = config
|
||||
this.process = process
|
||||
}
|
||||
|
||||
async startServer () {
|
||||
try {
|
||||
// Create a Koa instance.
|
||||
const app = new Koa()
|
||||
app.keys = [config.session]
|
||||
app.keys = [this.config.session]
|
||||
|
||||
// Connect to the Mongo Database.
|
||||
mongoose.Promise = global.Promise
|
||||
mongoose.set('useCreateIndex', true) // Stop deprecation warning.
|
||||
this.mongoose.Promise = global.Promise
|
||||
this.mongoose.set('useCreateIndex', true) // Stop deprecation warning.
|
||||
console.log(
|
||||
`Connecting to MongoDB with this connection string: ${config.database}`
|
||||
`Connecting to MongoDB with this connection string: ${this.config.database}`
|
||||
)
|
||||
await mongoose.connect(config.database, {
|
||||
await this.mongoose.connect(this.config.database, {
|
||||
useUnifiedTopology: true,
|
||||
useNewUrlParser: true
|
||||
})
|
||||
|
||||
console.log(`Starting environment: ${config.env}`)
|
||||
console.log(`Debug level: ${config.debugLevel}`)
|
||||
console.log(`Starting environment: ${this.config.env}`)
|
||||
console.log(`Debug level: ${this.config.debugLevel}\n`)
|
||||
console.log(`Using this web3 CashStack service: ${this.config.consumerUrl}`)
|
||||
console.log('Alternative web services listed here: https://gist.github.com/christroutner/63c5513782181f8b8ea3eb89f7cadeb6')
|
||||
console.log('This app is built on top of the CashStack. Find out more: https://CashStack.info\n')
|
||||
|
||||
// MIDDLEWARE START
|
||||
|
||||
@@ -81,33 +90,42 @@ class Server {
|
||||
// Dev Note: This line must come BEFORE controllers.attachRESTControllers()
|
||||
app.use(cors({ origin: '*' }))
|
||||
|
||||
// Attach REST API and JSON RPC controllers to the app.
|
||||
const Controllers = require('../src/controllers')
|
||||
const controllers = new Controllers()
|
||||
await controllers.attachRESTControllers(app)
|
||||
// Wait for any adapters to initialize.
|
||||
await this.controllers.initAdapters()
|
||||
|
||||
app.controllers = controllers
|
||||
// Wait for any use-libraries to initialize.
|
||||
await this.controllers.initUseCases()
|
||||
|
||||
// Attach REST API and JSON RPC controllers to the app.
|
||||
await this.controllers.attachRESTControllers(app)
|
||||
|
||||
app.controllers = this.controllers
|
||||
|
||||
// MIDDLEWARE END
|
||||
|
||||
// 7/7/22 CT: This code paragraph can be deleted
|
||||
// Delay startup to give the P2WDB time to start first, so that it accepts the webook call
|
||||
// if (this.config.env !== 'test') {
|
||||
// await this.sleep(20000)
|
||||
// }
|
||||
// Create webhook
|
||||
try {
|
||||
try {
|
||||
// Delete an old webhook if it exists.
|
||||
await webhookLib.deleteWebhook(config.webhookTarget)
|
||||
} catch (err) {
|
||||
/* exit quietly */
|
||||
// console.log('err deleting webhook: ', err)
|
||||
}
|
||||
|
||||
await webhookLib.createWebhook(config.webhookTarget)
|
||||
console.log('Webhook created')
|
||||
} catch (error) {
|
||||
console.log('Webhook cant be created')
|
||||
}
|
||||
// try {
|
||||
// try {
|
||||
// // Delete an old webhook if it exists.
|
||||
// await webhookLib.deleteWebhook(config.webhookTarget)
|
||||
// } catch (err) {
|
||||
// /* exit quietly */
|
||||
// // console.log('err deleting webhook: ', err)
|
||||
// }
|
||||
//
|
||||
// await webhookLib.createWebhook(config.webhookTarget)
|
||||
// console.log('Webhook created')
|
||||
// } catch (error) {
|
||||
// console.log('Webhook cant be created')
|
||||
// }
|
||||
|
||||
// startServer()
|
||||
await app.listen(config.port)
|
||||
this.server = await app.listen(config.port)
|
||||
console.log(`Server started on ${config.port}`)
|
||||
|
||||
// Create the system admin user.
|
||||
@@ -116,10 +134,16 @@ class Server {
|
||||
|
||||
// Attach the other IPFS controllers.
|
||||
// Skip if this is a test environment.
|
||||
if (config.env !== 'test') {
|
||||
await controllers.attachControllers(app)
|
||||
if (this.config.env !== 'test') {
|
||||
await this.controllers.attachControllers(app)
|
||||
}
|
||||
|
||||
// Display configuration settings
|
||||
console.log('\nConfiguration:')
|
||||
console.log(`Circuit Relay: ${this.config.isCircuitRelay}`)
|
||||
console.log(`IPFS TCP port: ${this.config.ipfsTcpPort}`)
|
||||
console.log(`IPFS WS port: ${this.config.ipfsWsPort}\n`)
|
||||
|
||||
return app
|
||||
} catch (err) {
|
||||
console.error('Could not start server. Error: ', err)
|
||||
@@ -127,14 +151,14 @@ class Server {
|
||||
console.log(
|
||||
'Exiting after 5 seconds. Depending on process manager to restart.'
|
||||
)
|
||||
await sleep(5000)
|
||||
process.exit(1)
|
||||
await this.sleep(5000)
|
||||
this.process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
sleep (ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
}
|
||||
}
|
||||
|
||||
function sleep (ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
module.exports = Server
|
||||
|
||||
Vendored
+5
-3
@@ -85,7 +85,7 @@ module.exports = {
|
||||
webhookService: process.env.WEBHOOKSERVICE
|
||||
? process.env.WEBHOOKSERVICE
|
||||
: 'http://localhost:5010/webhook', // P2WDB.
|
||||
p2wdbAppId: process.env.APP_ID ? process.env.APP_ID : 'bch-dex-test557',
|
||||
p2wdbAppId: process.env.APP_ID ? process.env.APP_ID : 'bch-dex-001',
|
||||
webhookTarget: process.env.WEBHOOKTARGET
|
||||
? process.env.WEBHOOKTARGET
|
||||
: 'http://localhost:5700/p2wdb',
|
||||
@@ -97,12 +97,14 @@ module.exports = {
|
||||
// BCH Mnemonic for generating encryption keys and payment address
|
||||
mnemonic: process.env.MNEMONIC ? process.env.MNEMONIC : '',
|
||||
|
||||
debugLevel: process.env.DEBUG_LEVEL ? parseInt(process.env.DEBUG_LEVEL) : 2,
|
||||
debugLevel: process.env.DEBUG_LEVEL ? parseInt(process.env.DEBUG_LEVEL) : 1,
|
||||
|
||||
// Settings for production, using external go-ipfs node.
|
||||
isProduction: process.env.SVC_ENV === 'production' ? true : false,
|
||||
ipfsHost: process.env.IPFS_HOST ? process.env.IPFS_HOST : 'localhost',
|
||||
ipfsApiPort: process.env.IPFS_API_PORT
|
||||
? parseInt(process.env.IPFS_API_PORT)
|
||||
: 5001
|
||||
: 5001,
|
||||
|
||||
chatPubSubChan: 'psf-ipfs-chat-001'
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
const common = require('./env/common')
|
||||
|
||||
const env = process.env.BCH_ENV || 'development'
|
||||
const env = process.env.BCH_DEX || 'development'
|
||||
const config = require(`./env/${env}`)
|
||||
|
||||
module.exports = Object.assign({}, common, config)
|
||||
|
||||
Generated
+5766
-12254
File diff suppressed because it is too large
Load Diff
+11
-11
@@ -27,14 +27,14 @@
|
||||
},
|
||||
"repository": "Permissionless-Software-Foundation/bch-dex",
|
||||
"dependencies": {
|
||||
"@psf/bch-js": "6.2.5",
|
||||
"axios": "0.21.1",
|
||||
"@psf/bch-js": "6.4.5",
|
||||
"axios": "0.27.2",
|
||||
"bch-message-lib": "2.2.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"bitcoincashjs-lib": "3.3.3",
|
||||
"glob": "7.1.6",
|
||||
"ipfs": "0.60.0",
|
||||
"ipfs-coord": "7.1.6",
|
||||
"ipfs": "0.62.3",
|
||||
"ipfs-coord": "8.0.5",
|
||||
"ipfs-http-client": "55.0.0",
|
||||
"jsonrpc-lite": "2.2.0",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
@@ -52,19 +52,19 @@
|
||||
"koa2-ratelimit": "0.9.1",
|
||||
"libp2p": "^0.36.2",
|
||||
"line-reader": "0.4.0",
|
||||
"minimal-slp-wallet": "4.4.7",
|
||||
"minimal-slp-wallet": "4.6.5",
|
||||
"mongoose": "5.13.13",
|
||||
"node-fetch": "npm:@achingbrain/node-fetch@2.6.7",
|
||||
"nodemailer": "6.4.17",
|
||||
"p2wdb": "1.3.1",
|
||||
"nodemailer": "6.7.5",
|
||||
"p2wdb": "1.4.0",
|
||||
"passport-local": "1.0.0",
|
||||
"public-ip": "^4.0.4",
|
||||
"winston": "3.3.3",
|
||||
"winston-daily-rotate-file": "4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"apidoc": "0.26.0",
|
||||
"bch-token-sweep": "1.5.16",
|
||||
"apidoc": "0.51.1",
|
||||
"bch-token-sweep": "2.1.2",
|
||||
"chai": "4.3.0",
|
||||
"coveralls": "2.11.4",
|
||||
"eslint": "7.19.0",
|
||||
@@ -75,9 +75,9 @@
|
||||
"eslint-plugin-promise": "^4.3.1",
|
||||
"eslint-plugin-standard": "4.0.0",
|
||||
"husky": "4.3.8",
|
||||
"mocha": "8.4.0",
|
||||
"mocha": "10.0.0",
|
||||
"nyc": "15.1.0",
|
||||
"semantic-release": "17.4.4",
|
||||
"semantic-release": "19.0.3",
|
||||
"sinon": "9.2.4",
|
||||
"standard": "16.0.4",
|
||||
"uuid": "8.3.2"
|
||||
|
||||
@@ -37,7 +37,7 @@ WORKDIR /home/safeuser
|
||||
RUN npm install -g npm
|
||||
|
||||
# npm mirror to prevent direct dependency on npm.
|
||||
RUN npm set registry http://94.130.170.209:4873/
|
||||
#RUN npm set registry http://94.130.170.209:4873/
|
||||
|
||||
# Switch to user account.
|
||||
#USER safeuser
|
||||
@@ -46,11 +46,11 @@ RUN npm set registry http://94.130.170.209:4873/
|
||||
|
||||
# Clone the rest.bitcoin.com repository
|
||||
WORKDIR /home/safeuser
|
||||
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui2
|
||||
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui-v2
|
||||
|
||||
# Switch to the desired branch. `master` is usually stable,
|
||||
# and `stage` has the most up-to-date changes.
|
||||
WORKDIR /home/safeuser/bch-dex-ui2
|
||||
WORKDIR /home/safeuser/bch-dex-ui-v2
|
||||
|
||||
# For development: switch to unstable branch
|
||||
RUN git checkout ct-unstable
|
||||
@@ -58,7 +58,7 @@ RUN git checkout ct-unstable
|
||||
# Install dependencies
|
||||
#RUN mkdir .ipfsdata
|
||||
#RUN npm install -g @mapbox/node-pre-gyp
|
||||
RUN npm install --force
|
||||
RUN npm install
|
||||
|
||||
# Build the site
|
||||
RUN CI=true npm run build
|
||||
@@ -68,6 +68,6 @@ FROM nginx
|
||||
EXPOSE 80
|
||||
|
||||
# Copy the files built in the first container to the new NGINX container.
|
||||
COPY --from=builder /home/safeuser/bch-dex-ui2/public /usr/share/nginx/html
|
||||
COPY --from=builder /home/safeuser/bch-dex-ui-v2/build /usr/share/nginx/html
|
||||
|
||||
#USER safeuser
|
||||
|
||||
@@ -72,7 +72,7 @@ RUN npm run docs
|
||||
#EXPOSE 5010
|
||||
|
||||
# Start the application.
|
||||
COPY start-production.sh start-production.sh
|
||||
#COPY start-production.sh start-production.sh
|
||||
CMD ["./start-production.sh"]
|
||||
|
||||
#CMD ["npm", "start"]
|
||||
|
||||
@@ -24,9 +24,9 @@ export DBURL=mongodb://172.17.0.1:5666/bch-swap-service-prod
|
||||
export PORT=5700
|
||||
|
||||
# bch-dex specific env vars
|
||||
export BCH_ENV=production
|
||||
export BCH_DEX=production
|
||||
export WEBHOOKSERVICE=http://172.17.0.1:5667/webhook
|
||||
export WEBHOOKTARGET=http://172.17.0.1:5700/p2wdb
|
||||
export APP_ID=bch-dex-test557
|
||||
export APP_ID=bch-dex-001
|
||||
|
||||
npm start
|
||||
|
||||
@@ -4,7 +4,7 @@ version: '3.9'
|
||||
|
||||
services:
|
||||
mongo-p2wdb-service:
|
||||
image: mongo:4.4
|
||||
image: mongo:4.2.0
|
||||
container_name: mongo-p2wdb-service
|
||||
ports:
|
||||
- '5666:27017' # <host port>:<container port>
|
||||
@@ -14,10 +14,16 @@ services:
|
||||
restart: always
|
||||
|
||||
ipfs:
|
||||
image: ipfs/go-ipfs:v0.12.0
|
||||
# https://github.com/christroutner/trickle-ipfs
|
||||
image: christroutner/trickle-ipfs:v1.0.1
|
||||
#build:
|
||||
# context: ./
|
||||
# dockerfile: Dockerfile
|
||||
container_name: ipfs
|
||||
environment:
|
||||
MY_ENV_VAR: 'placeholder'
|
||||
IPFS_DAEMON_ARGUMENTS: '--enable-pubsub-experiment --migrate=true --agent-version-suffix=docker --routing=dhtclient'
|
||||
UPLOAD_KBPS: '1000'
|
||||
DOWNLOAD_KBPS: '1000'
|
||||
logging:
|
||||
driver: 'json-file'
|
||||
options:
|
||||
@@ -26,30 +32,25 @@ services:
|
||||
mem_limit: 2000mb
|
||||
ports:
|
||||
- 4001:4001
|
||||
- 4003:4003
|
||||
- 172.17.0.1:5001:5001
|
||||
- 172.17.0.1:8080:8080
|
||||
command: [
|
||||
'./start-ipfs.sh'
|
||||
]
|
||||
volumes:
|
||||
- ../data/go-ipfs/data:/data/ipfs
|
||||
- ../../swarm.key:/data/ipfs/swarm.key
|
||||
# https://docs.docker.com/compose/compose-file/compose-file-v3/#command
|
||||
# https://github.com/ipfs/go-ipfs/blob/91c52657166bcf86f2476926e4fe56694dc26562/Dockerfile#L115
|
||||
command:
|
||||
[
|
||||
'daemon',
|
||||
'--migrate=true',
|
||||
'--agent-version-suffix=docker',
|
||||
'--enable-pubsub-experiment'
|
||||
]
|
||||
- ../data/go-ipfs/data:/root/.ipfs
|
||||
restart: always
|
||||
|
||||
p2wdb:
|
||||
#build:
|
||||
# context: ./p2wdb/
|
||||
# dockerfile: Dockerfile
|
||||
image: christroutner/p2wdb-bch-dex:v1.6.2
|
||||
image: christroutner/p2wdb:v3.0.9
|
||||
container_name: p2wdb
|
||||
environment:
|
||||
CONSUMER_URL: 'https://free-bch.fullstack.cash'
|
||||
DEBUG_LEVEL: 1
|
||||
logging:
|
||||
driver: 'json-file'
|
||||
options:
|
||||
@@ -65,13 +66,14 @@ services:
|
||||
#- 5669:5669 # IPFS WS Port
|
||||
volumes:
|
||||
- ../data/ipfsdata/p2wdb:/home/safeuser/ipfs-p2wdb-service/.ipfsdata/p2wdb
|
||||
- ./p2wdb/start-production.sh:/home/safeuser/ipfs-p2wdb-service/start-production.sh
|
||||
restart: always
|
||||
|
||||
bch-dex:
|
||||
#build:
|
||||
# context: ./bch-dex/
|
||||
# dockerfile: Dockerfile
|
||||
image: christroutner/bch-dex:v1.6.2
|
||||
image: christroutner/bch-dex:v1.9.2
|
||||
container_name: bch-dex
|
||||
environment:
|
||||
CONSUMER_URL: 'https://free-bch.fullstack.cash'
|
||||
@@ -88,13 +90,14 @@ services:
|
||||
- '5700:5700' # <host port>:<container port>
|
||||
volumes:
|
||||
- ../scripts/wallet.json:/home/safeuser/bch-dex/wallet.json
|
||||
- ./bch-dex/start-production.sh:/home/safeuser/bch-dex/start-production.sh
|
||||
restart: always
|
||||
|
||||
dex-ui:
|
||||
#build:
|
||||
# context: ./bch-dex-ui/
|
||||
# dockerfile: Dockerfile
|
||||
image: christroutner/bch-dex-ui:v1.6.2
|
||||
image: christroutner/bch-dex-ui:v1.6.6
|
||||
container_name: dex-ui
|
||||
environment:
|
||||
SERVER: 'http://192.168.2.3'
|
||||
|
||||
@@ -61,7 +61,7 @@ RUN npm run docs
|
||||
#EXPOSE 5010
|
||||
|
||||
# Start the application.
|
||||
COPY start-production.sh start-production.sh
|
||||
#COPY start-production.sh start-production.sh
|
||||
CMD ["./start-production.sh"]
|
||||
|
||||
#CMD ["npm", "start"]
|
||||
|
||||
@@ -16,7 +16,8 @@ export COORD_NAME=generic-p2wdb-production
|
||||
#export CR_DOMAIN=subdomain.yourdomain.com
|
||||
|
||||
# Debug level. 0 = minimal info. 2 = max info.
|
||||
export DEBUG_LEVEL=2
|
||||
# This value set by docker-compose.yml
|
||||
#export DEBUG_LEVEL=1
|
||||
|
||||
# Log-in information for retrieving a JWT token from FullStack.cash.
|
||||
export FULLSTACKLOGIN=demo@demo.com
|
||||
@@ -29,8 +30,8 @@ export FULLSTACKPASS=demo
|
||||
export DBURL=mongodb://172.17.0.1:5666/p2wdb-service-dev
|
||||
|
||||
# Configure IPFS ports
|
||||
export IPFS_TCP_PORT=5668
|
||||
export IPFS_WS_PORT=5669
|
||||
#export IPFS_TCP_PORT=5668
|
||||
#export IPFS_WS_PORT=5669
|
||||
|
||||
# Configure REST API port
|
||||
export PORT=5667
|
||||
@@ -41,6 +42,6 @@ export IPFS_API_PORT=5001
|
||||
export IPFS_TCP_PORT=4001
|
||||
|
||||
# P2WDB specific env vars
|
||||
export ORBITDB_NAME=/orbitdb/zdpuAm4fPafpjs5mgbBUJV8Az7kd8Xj1ttD6M1JaAxF8RMRrw/psf-bch-p2wdb-keyvalue-v1.0.0-0004
|
||||
#export ORBITDB_NAME=/orbitdb/zdpuAm4fPafpjs5mgbBUJV8Az7kd8Xj1ttD6M1JaAxF8RMRrw/psf-bch-p2wdb-keyvalue-v1.0.0-0004
|
||||
|
||||
npm start
|
||||
|
||||
@@ -46,11 +46,11 @@ RUN npm set registry http://94.130.170.209:4873/
|
||||
|
||||
# Clone the rest.bitcoin.com repository
|
||||
WORKDIR /home/safeuser
|
||||
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui2
|
||||
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui-v2
|
||||
|
||||
# Switch to the desired branch. `master` is usually stable,
|
||||
# and `stage` has the most up-to-date changes.
|
||||
WORKDIR /home/safeuser/bch-dex-ui2
|
||||
WORKDIR /home/safeuser/bch-dex-ui-v2
|
||||
|
||||
# For development: switch to unstable branch
|
||||
RUN git checkout ct-unstable
|
||||
@@ -58,7 +58,7 @@ RUN git checkout ct-unstable
|
||||
# Install dependencies
|
||||
#RUN mkdir .ipfsdata
|
||||
#RUN npm install -g @mapbox/node-pre-gyp
|
||||
RUN npm install --force
|
||||
RUN npm install
|
||||
|
||||
# Build the site
|
||||
RUN CI=true npm run build
|
||||
@@ -68,6 +68,6 @@ FROM nginx
|
||||
EXPOSE 80
|
||||
|
||||
# Copy the files built in the first container to the new NGINX container.
|
||||
COPY --from=builder /home/safeuser/bch-dex-ui2/public /usr/share/nginx/html
|
||||
COPY --from=builder /home/safeuser/bch-dex-ui-v2/build /usr/share/nginx/html
|
||||
|
||||
#USER safeuser
|
||||
|
||||
@@ -72,7 +72,7 @@ RUN npm run docs
|
||||
#EXPOSE 5010
|
||||
|
||||
# Start the application.
|
||||
COPY start-production.sh start-production.sh
|
||||
#COPY start-production.sh start-production.sh
|
||||
CMD ["./start-production.sh"]
|
||||
|
||||
#CMD ["npm", "start"]
|
||||
|
||||
@@ -24,9 +24,9 @@ export DBURL=mongodb://172.17.0.1:5666/bch-swap-service-prod
|
||||
export PORT=5700
|
||||
|
||||
# bch-dex specific env vars
|
||||
export BCH_ENV=production
|
||||
export BCH_DEX=production
|
||||
export WEBHOOKSERVICE=http://172.17.0.1:5667/webhook
|
||||
export WEBHOOKTARGET=http://172.17.0.1:5700/p2wdb
|
||||
export APP_ID=bch-dex-test557
|
||||
export APP_ID=bch-dex-001
|
||||
|
||||
npm start
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
version: '3.9'
|
||||
|
||||
services:
|
||||
mongo-p2wdb-service:
|
||||
image: mongo:4.4
|
||||
container_name: mongo-p2wdb-service
|
||||
mongo-bch-dex:
|
||||
image: mongo:4.2.0
|
||||
container_name: mongo-bch-dex
|
||||
ports:
|
||||
- '5666:27017' # <host port>:<container port>
|
||||
volumes:
|
||||
@@ -14,43 +14,40 @@ services:
|
||||
restart: always
|
||||
|
||||
ipfs:
|
||||
#image: ipfs/go-ipfs:v0.12.0
|
||||
image: odanado/go-ipfs:v0.11.0
|
||||
image: christroutner/trickle-ipfs-rpi:v1.0.1
|
||||
#image: odanado/go-ipfs:v0.11.0
|
||||
container_name: ipfs
|
||||
environment:
|
||||
MY_ENV_VAR: 'placeholder'
|
||||
IPFS_DAEMON_ARGUMENTS: '--enable-pubsub-experiment --migrate=true --agent-version-suffix=docker --routing=dhtclient'
|
||||
UPLOAD_KBPS: '25'
|
||||
DOWNLOAD_KBPS: '25'
|
||||
logging:
|
||||
driver: 'json-file'
|
||||
options:
|
||||
max-size: '10m'
|
||||
max-file: '10'
|
||||
mem_limit: 2000mb
|
||||
mem_limit: 1000mb
|
||||
ports:
|
||||
- 4001:4001
|
||||
- 4003:4003
|
||||
- 172.17.0.1:5001:5001
|
||||
- 172.17.0.1:8080:8080
|
||||
volumes:
|
||||
- ../data/go-ipfs/data:/data/ipfs
|
||||
- ../../swarm.key:/data/ipfs/swarm.key
|
||||
# https://docs.docker.com/compose/compose-file/compose-file-v3/#command
|
||||
# https://github.com/ipfs/go-ipfs/blob/91c52657166bcf86f2476926e4fe56694dc26562/Dockerfile#L115
|
||||
command:
|
||||
[
|
||||
'daemon',
|
||||
'--migrate=true',
|
||||
'--agent-version-suffix=docker',
|
||||
'--enable-pubsub-experiment'
|
||||
]
|
||||
- ./data/go-ipfs:/root/.ipfs
|
||||
command: [
|
||||
'./start-ipfs.sh'
|
||||
]
|
||||
restart: always
|
||||
|
||||
p2wdb:
|
||||
#build:
|
||||
# context: ./p2wdb/
|
||||
# dockerfile: Dockerfile
|
||||
image: christroutner/pwd-bch-dex-rpi:v1.6.2
|
||||
image: christroutner/p2wdb-rpi:v3.0.10
|
||||
container_name: p2wdb
|
||||
environment:
|
||||
CONSUMER_URL: 'https://free-bch.fullstack.cash'
|
||||
DEBUG_LEVEL: 1
|
||||
logging:
|
||||
driver: 'json-file'
|
||||
options:
|
||||
@@ -58,7 +55,7 @@ services:
|
||||
max-file: '10'
|
||||
mem_limit: 1gb
|
||||
links:
|
||||
- mongo-p2wdb-service
|
||||
- mongo-bch-dex
|
||||
ports:
|
||||
# <host port>:<container port>
|
||||
- 5667:5667 # REST API
|
||||
@@ -66,13 +63,14 @@ services:
|
||||
#- 5669:5669 # IPFS WS Port
|
||||
volumes:
|
||||
- ../data/ipfsdata/p2wdb:/home/safeuser/ipfs-p2wdb-service/.ipfsdata/p2wdb
|
||||
- ./p2wdb/start-production.sh:/home/safeuser/ipfs-p2wdb-service/start-production.sh
|
||||
restart: always
|
||||
|
||||
bch-dex:
|
||||
#build:
|
||||
# context: ./bch-dex/
|
||||
# context: ./bch-dex/
|
||||
# dockerfile: Dockerfile
|
||||
image: christroutner/bch-dex-rpi:v1.6.2
|
||||
image: christroutner/bch-dex-rpi:v1.8.3
|
||||
container_name: bch-dex
|
||||
environment:
|
||||
CONSUMER_URL: 'https://free-bch.fullstack.cash'
|
||||
@@ -83,19 +81,20 @@ services:
|
||||
max-file: '10'
|
||||
mem_limit: 1000mb
|
||||
links:
|
||||
- mongo-p2wdb-service
|
||||
- mongo-bch-dex
|
||||
- p2wdb
|
||||
ports:
|
||||
- '5700:5700' # <host port>:<container port>
|
||||
volumes:
|
||||
- ../scripts/wallet.json:/home/safeuser/bch-dex/wallet.json
|
||||
- ./bch-dex/start-production.sh:/home/safeuser/bch-dex/start-production.sh
|
||||
restart: always
|
||||
|
||||
dex-ui:
|
||||
#build:
|
||||
# context: ./bch-dex-ui/
|
||||
# dockerfile: Dockerfile
|
||||
image: christroutner/bch-dex-ui-rpi:v1.6.2
|
||||
image: christroutner/bch-dex-ui-rpi:v1.7.5
|
||||
container_name: dex-ui
|
||||
logging:
|
||||
driver: 'json-file'
|
||||
|
||||
@@ -61,7 +61,7 @@ RUN npm run docs
|
||||
#EXPOSE 5010
|
||||
|
||||
# Start the application.
|
||||
COPY start-production.sh start-production.sh
|
||||
#COPY start-production.sh start-production.sh
|
||||
CMD ["./start-production.sh"]
|
||||
|
||||
#CMD ["npm", "start"]
|
||||
|
||||
@@ -16,7 +16,8 @@ export COORD_NAME=generic-p2wdb-production
|
||||
#export CR_DOMAIN=subdomain.yourdomain.com
|
||||
|
||||
# Debug level. 0 = minimal info. 2 = max info.
|
||||
export DEBUG_LEVEL=2
|
||||
# This value set by docker-compose.yml
|
||||
#export DEBUG_LEVEL=1
|
||||
|
||||
# Log-in information for retrieving a JWT token from FullStack.cash.
|
||||
export FULLSTACKLOGIN=demo@demo.com
|
||||
@@ -39,8 +40,9 @@ export P2W_ENV=production
|
||||
export IPFS_HOST=172.17.0.1
|
||||
export IPFS_API_PORT=5001
|
||||
export IPFS_TCP_PORT=4001
|
||||
export IPFS_WS_PORT=4003
|
||||
|
||||
# P2WDB specific env vars
|
||||
export ORBITDB_NAME=/orbitdb/zdpuAm4fPafpjs5mgbBUJV8Az7kd8Xj1ttD6M1JaAxF8RMRrw/psf-bch-p2wdb-keyvalue-v1.0.0-0004
|
||||
export ORBITDB_NAME=/orbitdb/zdpuAqNiwLiJBfbRK7uihV2hAbNSXj78ufzv5VyQb8GuvRwDh/psf-bch-p2wdb-keyvalue-v3.0.0-0001
|
||||
|
||||
npm start
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
This script will sweep the HD wallet, looking for NFTs. When found, it will
|
||||
send the NFT to the root (index 0) address. It will pay transaction fees from
|
||||
the root address.
|
||||
*/
|
||||
|
||||
// Global npm libraries
|
||||
const BchWallet = require('minimal-slp-wallet/index')
|
||||
|
||||
// Local libraries
|
||||
const WalletAdapter = require('../../src/adapters/wallet')
|
||||
|
||||
// Constants
|
||||
const EMTPY_ADDR_CUTOFF = 10
|
||||
const WEB3_SERVER = 'https://free-bch.fullstack.cash'
|
||||
|
||||
async function sweepNfts () {
|
||||
try {
|
||||
// Open the wallet files.
|
||||
const walletLib = new WalletAdapter()
|
||||
// const walletInfo = await walletLib.openWallet()
|
||||
const walletInfo = await openWallet(walletLib)
|
||||
// const walletRoot = await walletLib.instanceWallet(walletInfo)
|
||||
const walletRoot = new BchWallet(walletInfo.mnemonic, {
|
||||
interface: 'consumer-api',
|
||||
restURL: WEB3_SERVER
|
||||
})
|
||||
await walletRoot.walletInfoPromise
|
||||
console.log('walletInfo: ', walletInfo)
|
||||
|
||||
const rootAddr = walletInfo.cashAddress
|
||||
// const rootWif = walletInfo.privateKey
|
||||
console.log(`Sweeping all funds into root address ${rootAddr}...`)
|
||||
|
||||
// Generate an HD tree
|
||||
const bchjs = walletRoot.bchjs
|
||||
const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic)
|
||||
const masterHDNode = bchjs.HDNode.fromSeed(rootSeed)
|
||||
|
||||
let emptyAddrCnt = 0
|
||||
let hdIndex = 1
|
||||
|
||||
do {
|
||||
// Generate a keypair from the HD wallet.
|
||||
const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`)
|
||||
const cashAddress = bchjs.HDNode.toCashAddress(childNode)
|
||||
const wifToSweep = bchjs.HDNode.toWIF(childNode)
|
||||
|
||||
console.log(`\n${hdIndex}: Sweeping ${cashAddress} with private key ${wifToSweep}`)
|
||||
|
||||
const walletChild = new BchWallet(wifToSweep, { interface: 'consumer-api', restURL: WEB3_SERVER })
|
||||
await walletChild.walletInfoPromise
|
||||
|
||||
try {
|
||||
const tokens = await walletChild.tokens.listTokensFromAddress(cashAddress)
|
||||
// console.log(`tokens: ${JSON.stringify(tokens, null, 2)}`)
|
||||
|
||||
await walletChild.utxos.initUtxoStore(cashAddress)
|
||||
// console.log(`utxoStore: ${JSON.stringify(utxoStore, null, 2)}`)
|
||||
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
const thisToken = tokens[i]
|
||||
|
||||
if (thisToken.tokenType === 65) {
|
||||
console.log(`NFT ${thisToken.ticker} (${thisToken.name}) found. Sweeping to ${rootAddr}`)
|
||||
|
||||
// Send BCH to the child address, to pay for transaction fees.
|
||||
const receiver1 = [{
|
||||
address: cashAddress,
|
||||
amountSat: 10000
|
||||
}]
|
||||
const txid1 = await walletRoot.send(receiver1)
|
||||
console.log(`10,000 sats sent to child address. TXID: ${txid1}`)
|
||||
|
||||
// Wait for indexers to update.
|
||||
console.log('Waiting for indexers to update...')
|
||||
await bchjs.Util.sleep(120000)
|
||||
|
||||
// Send NFT to root address.
|
||||
const receiver2 = [{
|
||||
address: rootAddr,
|
||||
tokenId: thisToken.tokenId,
|
||||
qty: thisToken.qty
|
||||
}]
|
||||
const txid2 = await walletChild.sendTokens(receiver2)
|
||||
console.log(`NFT sent from child address to root address. TXID: ${txid2}`)
|
||||
|
||||
// Wait for indexers to update.
|
||||
console.log('Waiting for indexers to update...')
|
||||
await bchjs.Util.sleep(3000)
|
||||
|
||||
// Refresh the UTXO store.
|
||||
await walletChild.utxos.initUtxoStore(cashAddress)
|
||||
|
||||
// Send the rest of the BCH back to the root address.
|
||||
const txid3 = await walletChild.sendAll(rootAddr)
|
||||
console.log(`Leftover BCH in child address sent to root address. TXID: ${txid3}`)
|
||||
|
||||
emptyAddrCnt = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Wait between loop iterations.
|
||||
await bchjs.Util.sleep(3000)
|
||||
|
||||
// emptyAddrCnt++
|
||||
} catch (err) {
|
||||
console.log(`error message with index ${hdIndex}: ${err.message}`)
|
||||
console.log(err)
|
||||
// emptyAddrCnt++
|
||||
}
|
||||
|
||||
emptyAddrCnt++
|
||||
hdIndex++
|
||||
} while (emptyAddrCnt < EMTPY_ADDR_CUTOFF)
|
||||
|
||||
console.log(`${EMTPY_ADDR_CUTOFF} empty addresses detected. Exiting.`)
|
||||
|
||||
console.log('\n\nDo not forget to reset the nextAddress property in the wallet.json file!\n\n')
|
||||
} catch (err) {
|
||||
console.log('Error while sweeping NFTs: ', err)
|
||||
}
|
||||
}
|
||||
sweepNfts()
|
||||
|
||||
// Open the wallet file, or create one if the file doesn't exist.
|
||||
// Does not instance the wallet. The output of this function is expected to
|
||||
// be passed to instanceWallet().
|
||||
async function openWallet (walletLib) {
|
||||
try {
|
||||
// console.log('this.WALLET_FILE: ', this.WALLET_FILE)
|
||||
const walletData = await walletLib.jsonFiles.readJSON('./wallet.json')
|
||||
|
||||
return walletData
|
||||
} catch (err) {
|
||||
console.error('Error in openWallet()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,12 @@
|
||||
This script will travers the HD wallet and sweep funds and tokens back
|
||||
into the root address (index 0). That root address needs to have funds
|
||||
to pay for the transactions.
|
||||
|
||||
This script will sweep BCH and fungible (Type 1) tokens, but not NFTs.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
const BCHJS = require('@psf/bch-js')
|
||||
// const BCHJS = require('@psf/bch-js')
|
||||
const BchTokenSweep = require('bch-token-sweep/index')
|
||||
|
||||
// Local libraries
|
||||
@@ -17,8 +19,10 @@ const EMTPY_ADDR_CUTOFF = 10
|
||||
async function sweepFunds () {
|
||||
try {
|
||||
// Open the wallet files.
|
||||
const wallet = new WalletAdapter()
|
||||
const walletInfo = await wallet.openWallet()
|
||||
const walletLib = new WalletAdapter()
|
||||
// const walletInfo = await walletLib.openWallet()
|
||||
const walletInfo = await openWallet(walletLib)
|
||||
const wallet = await walletLib.instanceWallet(walletInfo)
|
||||
console.log('walletInfo: ', walletInfo)
|
||||
|
||||
const rootAddr = walletInfo.cashAddress
|
||||
@@ -26,7 +30,7 @@ async function sweepFunds () {
|
||||
console.log(`Sweeping all funds into root address ${rootAddr}...`)
|
||||
|
||||
// Generate an HD tree
|
||||
const bchjs = new BCHJS()
|
||||
const bchjs = wallet.bchjs
|
||||
const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic)
|
||||
const masterHDNode = bchjs.HDNode.fromSeed(rootSeed)
|
||||
|
||||
@@ -39,14 +43,14 @@ async function sweepFunds () {
|
||||
const cashAddress = bchjs.HDNode.toCashAddress(childNode)
|
||||
const wifToSweep = bchjs.HDNode.toWIF(childNode)
|
||||
|
||||
console.log(`\nSweeping ${cashAddress}`)
|
||||
console.log(`\nSweeping ${cashAddress} with private key ${wifToSweep}`)
|
||||
|
||||
try {
|
||||
// Sweep tokens from address
|
||||
const sweeper = new BchTokenSweep(
|
||||
wifToSweep,
|
||||
rootWif,
|
||||
bchjs,
|
||||
wallet,
|
||||
550,
|
||||
rootAddr
|
||||
)
|
||||
@@ -66,6 +70,7 @@ async function sweepFunds () {
|
||||
await bchjs.Util.sleep(3000)
|
||||
} catch (err) {
|
||||
console.log(`error message with index ${hdIndex}: ${err.message}`)
|
||||
// console.log(err)
|
||||
emptyAddrCnt++
|
||||
}
|
||||
|
||||
@@ -80,3 +85,18 @@ async function sweepFunds () {
|
||||
}
|
||||
}
|
||||
sweepFunds()
|
||||
|
||||
// Open the wallet file, or create one if the file doesn't exist.
|
||||
// Does not instance the wallet. The output of this function is expected to
|
||||
// be passed to instanceWallet().
|
||||
async function openWallet (walletLib) {
|
||||
try {
|
||||
// console.log('this.WALLET_FILE: ', this.WALLET_FILE)
|
||||
const walletData = await walletLib.jsonFiles.readJSON('./wallet.json')
|
||||
|
||||
return walletData
|
||||
} catch (err) {
|
||||
console.error('Error in openWallet()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
+17
-23
@@ -19,26 +19,7 @@ const FullStackJWT = require('./fullstack-jwt')
|
||||
const BCHAdapter = require('./bch')
|
||||
const WalletAdapter = require('./wallet')
|
||||
const P2wdbAdapter = require('./p2wdb-adapter')
|
||||
|
||||
//
|
||||
// // Instantiate adapter libraries.
|
||||
// const ipfs = new IPFSAdapter()
|
||||
// const localdb = new LocalDB()
|
||||
// const logapi = new LogsAPI()
|
||||
// const passport = new Passport()
|
||||
// const nodemailer = new Nodemailer()
|
||||
// const jsonFiles = new JSONFiles()
|
||||
// const bchjs = new BCHJSAdapter()
|
||||
//
|
||||
// module.exports = {
|
||||
// ipfs,
|
||||
// localdb,
|
||||
// logapi,
|
||||
// passport,
|
||||
// nodemailer,
|
||||
// wlogger,
|
||||
// jsonFiles,
|
||||
// bchjs
|
||||
const Webhook = require('./webhook')
|
||||
|
||||
const config = require('../../config')
|
||||
|
||||
@@ -57,6 +38,7 @@ class Adapters {
|
||||
this.config = config
|
||||
this.wallet = new WalletAdapter()
|
||||
this.p2wdb = new P2wdbAdapter(localConfig)
|
||||
this.webhook = new Webhook()
|
||||
|
||||
// Get a valid JWT API key and instance bch-js.
|
||||
this.fullStackJwt = new FullStackJWT(config)
|
||||
@@ -73,14 +55,26 @@ class Adapters {
|
||||
}
|
||||
|
||||
// Start the IPFS node.
|
||||
// await this.ipfs.start()
|
||||
// Do not start these adapters if this is an e2e test.
|
||||
// if (this.config.env !== 'test') {
|
||||
// await this.ipfs.start()
|
||||
// }
|
||||
|
||||
// Open the wallet file
|
||||
const walletData = await this.wallet.openWallet()
|
||||
// console.log('walletData: ', walletData)
|
||||
|
||||
// Instance the wallet.
|
||||
await this.wallet.instanceWallet(walletData, this.bchjs)
|
||||
if (this.config.env !== 'test') {
|
||||
// Instance the wallet.
|
||||
await this.wallet.instanceWallet(walletData, this.bchjs)
|
||||
|
||||
// Wait until a webhook is established with the P2WDB
|
||||
await this.webhook.waitUntilSuccess(this.config.webhookTarget)
|
||||
}
|
||||
|
||||
console.log('Async Adapters have been started.')
|
||||
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error('Error in adapters/index.js/start()')
|
||||
throw err
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
top-level IPFS library that combines the individual IPFS-based libraries.
|
||||
*/
|
||||
|
||||
// Local libraries
|
||||
const IpfsAdapter = require('./ipfs')
|
||||
const IpfsCoordAdapter = require('./ipfs-coord')
|
||||
const config = require('../../../config')
|
||||
|
||||
class IPFS {
|
||||
constructor (localConfig = {}) {
|
||||
@@ -11,6 +13,7 @@ class IPFS {
|
||||
this.ipfsAdapter = new IpfsAdapter()
|
||||
this.IpfsCoordAdapter = IpfsCoordAdapter
|
||||
this.process = process
|
||||
this.config = config
|
||||
|
||||
this.ipfsCoordAdapter = {} // placeholder
|
||||
|
||||
@@ -31,11 +34,16 @@ class IPFS {
|
||||
|
||||
// Start ipfs-coord
|
||||
this.ipfsCoordAdapter = new this.IpfsCoordAdapter({
|
||||
ipfs: this.ipfs
|
||||
ipfs: this.ipfs,
|
||||
tcpPort: this.config.ipfsTcpPort,
|
||||
wsPort: this.config.ipfsWsPort
|
||||
})
|
||||
await this.ipfsCoordAdapter.start()
|
||||
console.log('ipfs-coord is ready.')
|
||||
|
||||
// Subscribe to the chat pubsub channel
|
||||
await this.ipfsCoordAdapter.subscribeToChat()
|
||||
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error('Error in adapters/ipfs/index.js/start()')
|
||||
|
||||
@@ -97,6 +97,15 @@ class IpfsCoordAdapter {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Subscribe to the chat pubsub channel
|
||||
async subscribeToChat () {
|
||||
await this.ipfsCoord.adapters.pubsub.subscribeToPubsubChannel(
|
||||
this.config.chatPubSubChan,
|
||||
console.log,
|
||||
this.ipfsCoord.thisNode
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = IpfsCoordAdapter
|
||||
|
||||
@@ -7,6 +7,7 @@ const Offer = new mongoose.Schema({
|
||||
utxoTxid: { type: String },
|
||||
utxoVout: { type: Number },
|
||||
ticker: { type: String },
|
||||
tokenType: { type: Number },
|
||||
|
||||
// Trade data
|
||||
buyOrSell: { type: String },
|
||||
|
||||
@@ -14,6 +14,7 @@ const Order = new mongoose.Schema({
|
||||
utxoTxid: { type: String },
|
||||
utxoVout: { type: Number },
|
||||
ticker: { type: String },
|
||||
tokenType: { type: Number },
|
||||
|
||||
// Trade data
|
||||
buyOrSell: { type: String },
|
||||
|
||||
@@ -135,8 +135,10 @@ class LogsApi {
|
||||
if (!filename || typeof filename !== 'string') {
|
||||
throw new Error('filename must be a string')
|
||||
}
|
||||
// Throw an error if the file does not exist.
|
||||
|
||||
console.log('readLines() filename: ', filename)
|
||||
|
||||
// Throw an error if the file does not exist.
|
||||
if (!_this.fs.existsSync(filename)) {
|
||||
throw new Error('file does not exist')
|
||||
}
|
||||
|
||||
+32
-7
@@ -208,7 +208,7 @@ class WalletAdapter {
|
||||
|
||||
// Get token info on the offered UTXO
|
||||
const txData = await this.bchWallet.getTxData([offerInfo.utxoTxid])
|
||||
// console.log(`txData: ${JSON.stringify(txData, null, 2)}`)
|
||||
console.log(`txData: ${JSON.stringify(txData, null, 2)}`)
|
||||
|
||||
// Construct the UTXO being offered for sale.
|
||||
const offeredUtxo = {
|
||||
@@ -222,12 +222,27 @@ class WalletAdapter {
|
||||
|
||||
// Build First part of the collaborative Tx a.k.a. Alice
|
||||
// Generate the OP_RETURN code.
|
||||
const slpSendObj = bchjs.SLP.TokenType1.generateSendOpReturn(
|
||||
[offeredUtxo],
|
||||
offerInfo.numTokens.toString()
|
||||
)
|
||||
let slpSendObj
|
||||
if (offerInfo.tokenType === 65) {
|
||||
// Type 65 NFT
|
||||
|
||||
slpSendObj = bchjs.SLP.NFT1.generateNFTChildSendOpReturn(
|
||||
[offeredUtxo],
|
||||
offerInfo.numTokens.toString()
|
||||
)
|
||||
console.log(`slpOutputs: ${slpSendObj.outputs}`)
|
||||
} else if (offerInfo.tokenType === 1) {
|
||||
// Type 1 fungible token
|
||||
|
||||
slpSendObj = bchjs.SLP.TokenType1.generateSendOpReturn(
|
||||
[offeredUtxo],
|
||||
offerInfo.numTokens.toString()
|
||||
)
|
||||
console.log(`slpOutputs: ${slpSendObj.outputs}`)
|
||||
} else {
|
||||
throw new Error(`Unknown token type of ${offerInfo.tokenType}. Can not create Counter Offer.`)
|
||||
}
|
||||
const slpData = slpSendObj.script
|
||||
console.log(`slpOutputs: ${slpSendObj.outputs}`)
|
||||
|
||||
// Currently this app only supports a single SLP token UTXO for exact
|
||||
// token quantities (no token change). e.g. 1 UTXO representing the
|
||||
@@ -334,12 +349,22 @@ class WalletAdapter {
|
||||
// Update the UTXO store of the wallet.
|
||||
await this.bchWallet.getUtxos()
|
||||
|
||||
// Get the token type of the token being moved.
|
||||
// Combine Fungible and NFT token UTXOs.
|
||||
let tokenUtxos = this.bchWallet.utxos.utxoStore.slpUtxos.type1.tokens.concat(
|
||||
this.bchWallet.utxos.utxoStore.slpUtxos.nft.tokens)
|
||||
// Get token UTXOs that match the token in the order.
|
||||
tokenUtxos = tokenUtxos.filter(
|
||||
x => x.tokenId === tokenId
|
||||
)
|
||||
|
||||
const txid = await this.bchWallet.sendTokens(receiver, 3)
|
||||
|
||||
const utxoInfo = {
|
||||
txid,
|
||||
vout: 1,
|
||||
hdIndex: keyPair.hdIndex
|
||||
hdIndex: keyPair.hdIndex,
|
||||
tokenType: tokenUtxos[0].tokenType
|
||||
}
|
||||
|
||||
return utxoInfo
|
||||
|
||||
@@ -59,6 +59,46 @@ class WebHook {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a promise that will not resolve until a webhook has been successfully
|
||||
// created with the P2WDB.
|
||||
// Dev Note: This was created because establishing a webhook between bch-dex
|
||||
// and the P2WDB at startup is critical. If it's not established, then bch-dex
|
||||
// can not 'see' new Offers and Counter Offers.
|
||||
async waitUntilSuccess (url) {
|
||||
try {
|
||||
let success = false
|
||||
|
||||
do {
|
||||
try {
|
||||
// Delete an old webhook if it exists.
|
||||
await this.deleteWebhook(this.config.webhookTarget)
|
||||
} catch (err) {
|
||||
/* exit quietly */
|
||||
// console.log('err deleting webhook: ', err)
|
||||
}
|
||||
|
||||
try {
|
||||
await this.createWebhook(this.config.webhookTarget)
|
||||
console.log('Webhook created')
|
||||
success = true
|
||||
} catch (err) {
|
||||
const now = new Date()
|
||||
console.log(`${now.toLocaleString()}: Error trying to create webhook with P2WDB. Trying again...`)
|
||||
await sleep(2000)
|
||||
}
|
||||
} while (!success)
|
||||
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error('Error in webhook.js/waitUntilSuccess()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sleep (ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
module.exports = WebHook
|
||||
|
||||
@@ -17,17 +17,18 @@ class Controllers {
|
||||
constructor (localConfig = {}) {
|
||||
this.adapters = new Adapters()
|
||||
this.useCases = new UseCases({ adapters: this.adapters })
|
||||
|
||||
this.timerControllers = new TimerControllers({ adapters: this.adapters, useCases: this.useCases })
|
||||
}
|
||||
|
||||
async attachControllers (app) {
|
||||
// Wait for any startup processes to complete for the Adapters libraries.
|
||||
// Spin up any adapter libraries that have async startup needs.
|
||||
async initAdapters () {
|
||||
await this.adapters.start()
|
||||
}
|
||||
|
||||
// Attach the REST controllers to the Koa app.
|
||||
// this.attachRESTControllers(app)
|
||||
|
||||
// this.attachRPCControllers()
|
||||
this.timerControllers = new TimerControllers({ adapters: this.adapters, useCases: this.useCases })
|
||||
// Run any Use Cases to startup the app.
|
||||
async initUseCases () {
|
||||
await this.useCases.start()
|
||||
}
|
||||
|
||||
// Top-level function for this library.
|
||||
@@ -42,6 +43,12 @@ class Controllers {
|
||||
restControllers.attachRESTControllers(app)
|
||||
}
|
||||
|
||||
// Attach any other controllers other than REST API controllers.
|
||||
async attachControllers (app) {
|
||||
|
||||
// this.attachRPCControllers()
|
||||
}
|
||||
|
||||
// Add the JSON RPC router to the ipfs-coord adapter.
|
||||
attachRPCControllers () {
|
||||
const jsonRpcController = new JSONRPC({
|
||||
|
||||
@@ -29,7 +29,8 @@ class OfferEntity {
|
||||
utxoVout,
|
||||
offerStatus,
|
||||
makerAddr,
|
||||
ticker
|
||||
ticker,
|
||||
tokenType
|
||||
} = offerData.data
|
||||
|
||||
// Input Validation
|
||||
@@ -69,6 +70,9 @@ class OfferEntity {
|
||||
if (!ticker || typeof ticker !== 'string') {
|
||||
throw new Error("Property 'ticker' must be a string.")
|
||||
}
|
||||
if (!tokenType || typeof tokenType !== 'number') {
|
||||
throw new Error("Property 'tokenType' must be a number.")
|
||||
}
|
||||
|
||||
// Convert the timestamp to a number.
|
||||
let timestamp = new Date(offerData.timestamp)
|
||||
@@ -91,7 +95,8 @@ class OfferEntity {
|
||||
p2wdbHash: offerData.hash,
|
||||
offerStatus: offerStatus || this.offerStatus[0],
|
||||
makerAddr,
|
||||
ticker
|
||||
ticker,
|
||||
tokenType
|
||||
}
|
||||
|
||||
return validatedOfferData
|
||||
|
||||
@@ -25,6 +25,19 @@ class UseCases {
|
||||
localConfig.order = this.order
|
||||
this.offer = new OfferUseCases(localConfig)
|
||||
}
|
||||
|
||||
// Run any startup Use Cases at the start of the app.
|
||||
async start () {
|
||||
// try {
|
||||
console.log('Async Use Cases have been started.')
|
||||
|
||||
return true
|
||||
// } catch (err) {
|
||||
// console.error('Error in use-cases/index.js/start()')
|
||||
// // console.log(err)
|
||||
// throw err
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UseCases
|
||||
|
||||
@@ -359,10 +359,13 @@ class OfferUseCases {
|
||||
// console.log('utxoStatus: ', utxoStatus)
|
||||
} catch (err) {
|
||||
// Handle corner case of bad-data in the Offer model.
|
||||
if (err.message.includes('txid needs to be a proper transaction ID')) {
|
||||
if (err.message && err.message.includes('txid needs to be a proper transaction ID')) {
|
||||
console.log(`Deleting Offer with bad data: ${JSON.stringify(thisOffer, null, 2)}`)
|
||||
await thisOffer.remove()
|
||||
continue
|
||||
} else if (err.isAxiosError) {
|
||||
console.log('Error trying to contact api.fullstack.cash')
|
||||
continue
|
||||
} else {
|
||||
throw err
|
||||
}
|
||||
@@ -376,15 +379,15 @@ class OfferUseCases {
|
||||
|
||||
// If the Offer is older than 7 days, delete it.
|
||||
const nowMs = now.getTime()
|
||||
const sevenDays = 1000 * 60 * 60 * 24 * 7
|
||||
const sevenDaysAgo = nowMs - sevenDays
|
||||
if (thisOffer.timestamp < sevenDaysAgo) {
|
||||
console.log('Offer older than 7 days. Deleting.')
|
||||
const eightWeeks = 1000 * 60 * 60 * 24 * 7 * 8
|
||||
const eightWeeksAgo = nowMs - eightWeeks
|
||||
if (thisOffer.timestamp < eightWeeksAgo) {
|
||||
console.log('Offer older than 8 weeks. Deleting.')
|
||||
await thisOffer.remove()
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error in removeStaleOffers()')
|
||||
console.error('Error in removeStaleOffers(): ', err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
+15
-5
@@ -28,7 +28,9 @@ class OrderLib {
|
||||
async createOrder (entryObj) {
|
||||
try {
|
||||
console.log('createOrder(entryObj): ', entryObj)
|
||||
// if (!entryObj) return
|
||||
if (!entryObj) return false
|
||||
|
||||
if (!entryObj.tokenId) throw new Error('entry does not contain required properties')
|
||||
|
||||
// Specify the address to send payment.
|
||||
entryObj.makerAddr = this.adapters.wallet.bchWallet.walletInfo.cashAddress
|
||||
@@ -65,6 +67,7 @@ class OrderLib {
|
||||
// Update the order with the new UTXO information.
|
||||
orderEntity.utxoTxid = utxoInfo.txid
|
||||
orderEntity.utxoVout = utxoInfo.vout
|
||||
orderEntity.tokenType = utxoInfo.tokenType
|
||||
|
||||
// Add P2WDB specific flag for signaling that this is a new offer.
|
||||
orderEntity.dataType = 'offer'
|
||||
@@ -81,6 +84,7 @@ class OrderLib {
|
||||
// Create a MongoDB model to hold the Order
|
||||
orderEntity.hdIndex = utxoInfo.hdIndex
|
||||
orderEntity.p2wdbHash = hash
|
||||
|
||||
console.log(`creating new order model: ${JSON.stringify(orderEntity, null, 2)}`)
|
||||
const order = new this.OrderModel(orderEntity)
|
||||
await order.save()
|
||||
@@ -88,7 +92,7 @@ class OrderLib {
|
||||
return hash
|
||||
} catch (err) {
|
||||
// console.log("Error in use-cases/entry.js/createEntry()", err.message)
|
||||
wlogger.error('Error in use-cases/createOrder())')
|
||||
wlogger.error('Error in use-cases/order.js/createOrder())')
|
||||
console.log('error entryObj: ', entryObj)
|
||||
throw err
|
||||
}
|
||||
@@ -116,11 +120,14 @@ class OrderLib {
|
||||
if (orderEntity.buyOrSell.includes('sell')) {
|
||||
// Sell Order
|
||||
|
||||
// Combine Fungible and NFT token UTXOs.
|
||||
let tokenUtxos = utxos.slpUtxos.type1.tokens.concat(utxos.slpUtxos.nft.tokens)
|
||||
|
||||
// Get token UTXOs that match the token in the order.
|
||||
const tokenUtxos = utxos.slpUtxos.type1.tokens.filter(
|
||||
tokenUtxos = tokenUtxos.filter(
|
||||
x => x.tokenId === orderEntity.tokenId
|
||||
)
|
||||
// console.log('tokenUtxos: ', tokenUtxos)
|
||||
console.log('tokenUtxos: ', tokenUtxos)
|
||||
|
||||
// Get the total amount of tokens in the wallet that match the token
|
||||
// in the order.
|
||||
@@ -198,10 +205,13 @@ class OrderLib {
|
||||
// console.log('utxoStatus: ', utxoStatus)
|
||||
} catch (err) {
|
||||
// Handle corner case of bad-data in the Order model.
|
||||
if (err.message.includes('txid needs to be a proper transaction ID')) {
|
||||
if (err.message && err.message.includes('txid needs to be a proper transaction ID')) {
|
||||
console.log(`Deleting Order with bad data: ${JSON.stringify(thisOrder, null, 2)}`)
|
||||
await thisOrder.remove()
|
||||
continue
|
||||
} else if (err.isAxiosError) {
|
||||
console.log('Error trying to contact api.fullstack.cash')
|
||||
continue
|
||||
} else {
|
||||
throw err
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// Public npm libraries
|
||||
const assert = require('chai').assert
|
||||
const axios = require('axios').default
|
||||
// const sinon = require('sinon')
|
||||
|
||||
// Local support libraries
|
||||
const config = require('../../../config')
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Unit tests for the adapters index.js library
|
||||
*/
|
||||
|
||||
// Global npm libraries
|
||||
const assert = require('chai').assert
|
||||
const sinon = require('sinon')
|
||||
|
||||
// Local libraries
|
||||
const Adapters = require('../../../src/adapters')
|
||||
|
||||
describe('#adapters', () => {
|
||||
let uut, sandbox
|
||||
|
||||
beforeEach(() => {
|
||||
uut = new Adapters()
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore()
|
||||
})
|
||||
|
||||
describe('#start', () => {
|
||||
it('should start the async adapters', async () => {
|
||||
// Mock dependencies
|
||||
uut.config.getJwtAtStartup = true
|
||||
sandbox.stub(uut.fullStackJwt, 'getJWT').resolves()
|
||||
sandbox.stub(uut.fullStackJwt, 'instanceBchjs').resolves()
|
||||
sandbox.stub(uut.ipfs, 'start').resolves()
|
||||
|
||||
const result = await uut.start()
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should catch and throw an error', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
uut.config.getJwtAtStartup = false
|
||||
// uut.config.env = 'dev'
|
||||
sandbox.stub(uut.wallet, 'openWallet').rejects(new Error('test error'))
|
||||
|
||||
await uut.start()
|
||||
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
// console.log('err: ', err)
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -8,6 +8,7 @@ const sinon = require('sinon')
|
||||
const IPFSCoordAdapter = require('../../../src/adapters/ipfs/ipfs-coord')
|
||||
const IPFSMock = require('../mocks/ipfs-mock')
|
||||
const IPFSCoordMock = require('../mocks/ipfs-coord-mock')
|
||||
const config = require('../../../config')
|
||||
|
||||
describe('#IPFS', () => {
|
||||
let uut
|
||||
@@ -61,6 +62,16 @@ describe('#IPFS', () => {
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
it('should return a promise that resolves into an instance of IPFS in production mode', async () => {
|
||||
uut.config.isProduction = true
|
||||
// Mock dependencies.
|
||||
uut.IpfsCoord = IPFSCoordMock
|
||||
|
||||
const result = await uut.start()
|
||||
// console.log('result: ', result)
|
||||
assert.equal(result, true)
|
||||
config.isProduction = false
|
||||
})
|
||||
})
|
||||
|
||||
describe('#attachRPCRouter', () => {
|
||||
@@ -101,4 +112,20 @@ describe('#IPFS', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#subscribeToChat', () => {
|
||||
it('should subscribe to the chat channel', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
adapters: {
|
||||
pubsub: {
|
||||
subscribeToPubsubChannel: async () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await uut.subscribeToChat()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -32,19 +32,18 @@ describe('#LogsApiLib', () => {
|
||||
})
|
||||
|
||||
it('should return log', async () => {
|
||||
try {
|
||||
const pass = 'test'
|
||||
const result = await uut.getLogs(pass)
|
||||
// console.log('result', result)
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut, 'generateFileName').returns(`${__dirname.toString()}/../mocks/adapters/fake-log`)
|
||||
|
||||
assert.isTrue(result.success)
|
||||
assert.isArray(result.data)
|
||||
assert.property(result.data[0], 'message')
|
||||
assert.property(result.data[0], 'level')
|
||||
assert.property(result.data[0], 'timestamp')
|
||||
} catch (err) {
|
||||
assert(false, 'Unexpected result')
|
||||
}
|
||||
const pass = 'test'
|
||||
const result = await uut.getLogs(pass)
|
||||
// console.log('result', result)
|
||||
|
||||
assert.isTrue(result.success)
|
||||
assert.isArray(result.data)
|
||||
assert.property(result.data[0], 'message')
|
||||
assert.property(result.data[0], 'level')
|
||||
assert.property(result.data[0], 'timestamp')
|
||||
})
|
||||
|
||||
it('should return false if files are not found!', async () => {
|
||||
@@ -201,31 +200,25 @@ describe('#LogsApiLib', () => {
|
||||
})
|
||||
|
||||
it('should ignore fileReader callback errors', async () => {
|
||||
try {
|
||||
// https://sinonjs.org/releases/latest/stubs/
|
||||
// About yields
|
||||
sandbox.stub(uut.lineReader, 'eachLine').yieldsRight({}, true)
|
||||
// https://sinonjs.org/releases/latest/stubs/
|
||||
// About yields
|
||||
sandbox.stub(uut.lineReader, 'eachLine').yieldsRight({}, true)
|
||||
|
||||
const fileName = context.fileName
|
||||
const result = await uut.readLines(fileName)
|
||||
assert.isArray(result)
|
||||
} catch (err) {
|
||||
assert.fail('Unexpected result')
|
||||
}
|
||||
const fileName = `${__dirname.toString()}/../mocks/adapters/fake-log`
|
||||
|
||||
const result = await uut.readLines(fileName)
|
||||
assert.isArray(result)
|
||||
})
|
||||
|
||||
it('should return data', async () => {
|
||||
try {
|
||||
const fileName = context.fileName
|
||||
const result = await uut.readLines(fileName)
|
||||
const fileName = `${__dirname.toString()}/../mocks/adapters/fake-log`
|
||||
|
||||
assert.isArray(result)
|
||||
assert.property(result[1], 'message')
|
||||
assert.property(result[1], 'level')
|
||||
assert.property(result[1], 'timestamp')
|
||||
} catch (err) {
|
||||
assert.fail('Unexpected result')
|
||||
}
|
||||
const result = await uut.readLines(fileName)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.property(result[1], 'message')
|
||||
assert.property(result[1], 'level')
|
||||
assert.property(result[1], 'timestamp')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -262,10 +262,11 @@ describe('#wallet', () => {
|
||||
wif: 'L4qKTMCwjH9jHnYtNh9Vsrxj7Hg6zmoN8E2v7N47UKvNVEjw7FU8',
|
||||
hdIndex: 6
|
||||
})
|
||||
uut.bchWallet = {
|
||||
sendTokens: async () => 'fake-txid',
|
||||
getUtxos: async () => {}
|
||||
}
|
||||
uut.bchWallet = new MockBchWallet()
|
||||
// uut.bchWallet = {
|
||||
// sendTokens: async () => 'fake-txid',
|
||||
// getUtxos: async () => {}
|
||||
// }
|
||||
|
||||
const inObj = {
|
||||
tokenId: 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2',
|
||||
|
||||
@@ -254,7 +254,8 @@ describe('#Offer-Entity', () => {
|
||||
utxoVout: 0,
|
||||
offerStatus: 'posted',
|
||||
makerAddr: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
|
||||
ticker: 'TROUT'
|
||||
ticker: 'TROUT',
|
||||
tokenType: 1
|
||||
},
|
||||
timestamp: '2021-09-20T17:54:26.395Z',
|
||||
localTimeStamp: '9/20/2021, 10:54:26 AM',
|
||||
@@ -279,6 +280,7 @@ describe('#Offer-Entity', () => {
|
||||
assert.property(result, 'localTimestamp')
|
||||
assert.property(result, 'txid')
|
||||
assert.property(result, 'p2wdbHash')
|
||||
assert.property(result, 'tokenType')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Unit tests for the bin/server.js file
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
const assert = require('chai').assert
|
||||
const sinon = require('sinon')
|
||||
|
||||
// Local libraries
|
||||
const Server = require('../../../bin/server')
|
||||
|
||||
describe('#server', () => {
|
||||
let uut, sandbox
|
||||
|
||||
beforeEach(() => {
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
uut = new Server()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe('#startServer', () => {
|
||||
it('should start the server', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut.mongoose, 'connect').resolves()
|
||||
sandbox.stub(uut.controllers, 'initAdapters').resolves()
|
||||
sandbox.stub(uut.controllers, 'initUseCases').resolves()
|
||||
sandbox.stub(uut.controllers, 'attachRESTControllers').resolves()
|
||||
sandbox.stub(uut.adminLib, 'createSystemUser').resolves(true)
|
||||
sandbox.stub(uut.controllers, 'attachControllers').resolves()
|
||||
sandbox.stub(uut, 'sleep').resolves()
|
||||
uut.config.env = 'dev'
|
||||
|
||||
const result = await uut.startServer()
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.property(result, 'env')
|
||||
|
||||
// Turn off the server.
|
||||
uut.server.close()
|
||||
|
||||
// Restor config env
|
||||
uut.config.env = 'test'
|
||||
})
|
||||
|
||||
it('should exit on failure', async () => {
|
||||
// Force an error
|
||||
sandbox.stub(uut.mongoose, 'connect').rejects(new Error('test error'))
|
||||
|
||||
// Prevent default behavior of exiting the program.
|
||||
sandbox.stub(uut, 'sleep').resolves()
|
||||
sandbox.stub(uut.process, 'exit').returns()
|
||||
|
||||
await uut.startServer()
|
||||
|
||||
// Not throwing an error is a success
|
||||
})
|
||||
})
|
||||
|
||||
describe('#sleep', () => {
|
||||
it('should execute', async () => {
|
||||
await uut.sleep(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,70 @@
|
||||
{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:36:43.907Z"}
|
||||
{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:36:43.909Z"}
|
||||
{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:36:43.910Z"}
|
||||
{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:36:43.912Z"}
|
||||
{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:36:43.915Z"}
|
||||
{"level":"error","message":"Error in lib/nodemailer.js/sendEmail()","timestamp":"2022-06-27T17:36:58.979Z"}
|
||||
{"level":"error","message":"Error in lib/nodemailer.js/sendEmail()","timestamp":"2022-06-27T17:36:58.980Z"}
|
||||
{"level":"error","message":"Error in lib/nodemailer.js/sendEmail()","timestamp":"2022-06-27T17:36:58.981Z"}
|
||||
{"level":"error","message":"Error in lib/nodemailer.js/sendEmail()","timestamp":"2022-06-27T17:36:58.982Z"}
|
||||
{"level":"error","message":"Error in lib/nodemailer.js/sendEmail()","timestamp":"2022-06-27T17:36:58.983Z"}
|
||||
{"level":"error","message":"Error in lib/nodemailer.js/validateEmailArray()","timestamp":"2022-06-27T17:36:59.002Z"}
|
||||
{"level":"error","message":"Error in lib/nodemailer.js/validateEmailArray()","timestamp":"2022-06-27T17:36:59.003Z"}
|
||||
{"level":"error","message":"Error in lib/nodemailer.js/getHtmlFromObject()","timestamp":"2022-06-27T17:36:59.005Z"}
|
||||
{"level":"error","message":"Error in lib/nodemailer.js/getHtmlFromObject()","timestamp":"2022-06-27T17:36:59.006Z"}
|
||||
{"level":"error","message":"Error in lib/nodemailer.js/getHtmlFromObject()","timestamp":"2022-06-27T17:36:59.008Z"}
|
||||
{"level":"info","message":"Warning: Can not send JSON RPC response. Can not determine which peer this message came from.","timestamp":"2022-06-27T17:36:59.353Z"}
|
||||
{"level":"info","message":"Rejecting invalid JSON RPC command.","timestamp":"2022-06-27T17:36:59.354Z"}
|
||||
{"level":"info","message":"JSON RPC received from peerA, ID: ea442e78-2297-466a-823b-9cbb12c8ddd9, type: request, method: unknownMethod","timestamp":"2022-06-27T17:36:59.355Z"}
|
||||
{"level":"error","message":"Error in rpc router(): test error","stack":"Error: test error\n at Context.<anonymous> (/home/trout/work/psf/code/ipfs-service-provider/test/unit/controllers/json-rpc/a10-rpc.unit.js:110:49)\n at callFn (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:366:21)\n at Test.Runnable.run (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:354:5)\n at Runner.runTest (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:666:10)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:789:12\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:581:14)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:591:7\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:474:14)\n at Immediate._onImmediate (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:559:5)\n at processImmediate (node:internal/timers:466:21)","timestamp":"2022-06-27T17:36:59.357Z"}
|
||||
{"level":"info","message":"JSON RPC received from peerA, ID: 9ef6ad90-7fc3-4cb3-8769-4498e5512b3d, type: request, method: users","timestamp":"2022-06-27T17:36:59.358Z"}
|
||||
{"level":"info","message":"JSON RPC received from peerA, ID: bd57a1cf-7f2f-4ff2-93d4-6727eec4d778, type: request, method: auth","timestamp":"2022-06-27T17:36:59.359Z"}
|
||||
{"level":"info","message":"JSON RPC received from peerA, ID: 8fd9edc8-6a45-4042-ac06-9ace60567cbf, type: request, method: about","timestamp":"2022-06-27T17:36:59.361Z"}
|
||||
{"level":"info","message":"JSON RPC received from peerA, ID: 1b27624a-e698-4bbe-9183-b860a1a0d78d, type: request, method: unknownMethod","timestamp":"2022-06-27T17:36:59.363Z"}
|
||||
{"level":"info","message":"JSON RPC received from peerA, ID: 40fabddf-59c6-4910-a22c-63da7387f99a, type: request, method: unknownMethod","timestamp":"2022-06-27T17:36:59.365Z"}
|
||||
{"level":"error","message":"Error in authUser(): Login credential do not match","stack":"Error: Login credential do not match\n at Context.<anonymous> (/home/trout/work/psf/code/ipfs-service-provider/test/unit/controllers/json-rpc/auth.json-rpc.controller.unit.js:144:18)\n at callFn (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:366:21)\n at Test.Runnable.run (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:354:5)\n at Runner.runTest (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:666:10)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:789:12\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:581:14)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:591:7\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:474:14)\n at Immediate.<anonymous> (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:559:5)\n at processImmediate (node:internal/timers:466:21)","timestamp":"2022-06-27T17:37:04.421Z"}
|
||||
{"level":"error","message":"Error in authUser(): login must be specified","stack":"Error: login must be specified\n at AuthRPC.authUser (/home/trout/work/psf/code/ipfs-service-provider/src/controllers/json-rpc/auth/index.js:78:93)\n at Context.<anonymous> (/home/trout/work/psf/code/ipfs-service-provider/test/unit/controllers/json-rpc/auth.json-rpc.controller.unit.js:165:34)\n at callFn (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:366:21)\n at Test.Runnable.run (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:354:5)\n at Runner.runTest (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:666:10)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:789:12\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:581:14)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:591:7\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:474:14)\n at Immediate._onImmediate (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:559:5)\n at processImmediate (node:internal/timers:466:21)","timestamp":"2022-06-27T17:37:04.423Z"}
|
||||
{"level":"error","message":"Error in authUser(): password must be specified","stack":"Error: password must be specified\n at AuthRPC.authUser (/home/trout/work/psf/code/ipfs-service-provider/src/controllers/json-rpc/auth/index.js:78:284)\n at Context.<anonymous> (/home/trout/work/psf/code/ipfs-service-provider/test/unit/controllers/json-rpc/auth.json-rpc.controller.unit.js:185:34)\n at callFn (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:366:21)\n at Test.Runnable.run (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runnable.js:354:5)\n at Runner.runTest (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:666:10)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:789:12\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:581:14)\n at /home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:591:7\n at next (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:474:14)\n at Immediate._onImmediate (/home/trout/work/psf/code/ipfs-service-provider/node_modules/mocha/lib/runner.js:559:5)\n at processImmediate (node:internal/timers:466:21)","timestamp":"2022-06-27T17:37:04.425Z"}
|
||||
{"level":"error","timestamp":"2022-06-27T17:37:04.466Z"}
|
||||
{"level":"info","message":"Running server in environment: dev","timestamp":"2022-06-27T17:37:04.487Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.495Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.495Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.496Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.497Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.497Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/getAllUsers()","timestamp":"2022-06-27T17:37:04.499Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.502Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.503Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.503Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.504Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.505Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:04.506Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/deleteUser()","timestamp":"2022-06-27T17:37:04.508Z"}
|
||||
{"level":"info","message":"Running server in environment: test","timestamp":"2022-06-27T17:37:04.514Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:04.638Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:05.273Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:05.277Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:05.280Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:05.286Z"}
|
||||
{"level":"error","timestamp":"2022-06-27T17:37:05.412Z"}
|
||||
{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac1b4f08950b955d27f, Target user: 1","timestamp":"2022-06-27T17:37:05.441Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:05.448Z"}
|
||||
{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac1b4f08950b955d27f, Target user: 62b9eac1b4f08950b955d27d","timestamp":"2022-06-27T17:37:05.452Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:05.457Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:05.463Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:05.467Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/updateUser()","timestamp":"2022-06-27T17:37:05.473Z"}
|
||||
{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac0b4f08950b955d274, Target user: 62b9eac1b4f08950b955d27d","timestamp":"2022-06-27T17:37:05.478Z"}
|
||||
{"level":"verbose","message":"It's ok. The user is an admin.","timestamp":"2022-06-27T17:37:05.478Z"}
|
||||
{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac1b4f08950b955d27f, Target user: 1","timestamp":"2022-06-27T17:37:05.600Z"}
|
||||
{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac1b4f08950b955d27f, Target user: 62b9eac1b4f08950b955d27d","timestamp":"2022-06-27T17:37:05.603Z"}
|
||||
{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac0b4f08950b955d274, Target user: 62b9eac1b4f08950b955d27d","timestamp":"2022-06-27T17:37:05.615Z"}
|
||||
{"level":"verbose","message":"It's ok. The user is an admin.","timestamp":"2022-06-27T17:37:05.615Z"}
|
||||
{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:37:05.619Z"}
|
||||
{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:37:05.622Z"}
|
||||
{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:37:05.624Z"}
|
||||
{"level":"error","message":"Error in lib/contact.js/sendEmail()","timestamp":"2022-06-27T17:37:05.627Z"}
|
||||
{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac1b4f08950b955d2a6, Target user: Target Id","timestamp":"2022-06-27T17:37:05.754Z"}
|
||||
{"level":"verbose","message":"Calling user and target user do not match! Calling user: 62b9eac0b4f08950b955d274, Target user: 62b9eac1b4f08950b955d2a6","timestamp":"2022-06-27T17:37:05.756Z"}
|
||||
{"level":"verbose","message":"It's ok. The user is an admin.","timestamp":"2022-06-27T17:37:05.756Z"}
|
||||
{"level":"error","message":"Error in lib/users.js/createUser()","timestamp":"2022-06-27T17:37:06.060Z"}
|
||||
@@ -1,16 +1,22 @@
|
||||
/*
|
||||
Mocks for the Adapter library.
|
||||
*/
|
||||
|
||||
const BCHJS = require('@psf/bch-js')
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
const ipfs = {
|
||||
ipfsAdapter: {
|
||||
ipfs: {}
|
||||
},
|
||||
ipfsCoordAdapter: {
|
||||
ipfsCoord: {
|
||||
class IpfsAdapter {
|
||||
constructor () {
|
||||
this.ipfs = {
|
||||
files: {
|
||||
stat: () => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IpfsCoordAdapter {
|
||||
constructor () {
|
||||
this.ipfsCoord = {
|
||||
useCases: {
|
||||
peer: {
|
||||
sendPrivateMessage: () => {
|
||||
@@ -21,6 +27,12 @@ const ipfs = {
|
||||
}
|
||||
}
|
||||
|
||||
const ipfs = {
|
||||
ipfsAdapter: new IpfsAdapter(),
|
||||
ipfsCoordAdapter: new IpfsCoordAdapter()
|
||||
}
|
||||
ipfs.ipfs = ipfs.ipfsAdapter.ipfs
|
||||
|
||||
const localdb = {
|
||||
Users: class Users {
|
||||
static findById () {}
|
||||
|
||||
@@ -127,9 +127,11 @@ class MockBchWallet {
|
||||
]
|
||||
},
|
||||
nft: {
|
||||
groupMintBatons: [],
|
||||
groupTokens: [],
|
||||
tokens: []
|
||||
},
|
||||
group: {
|
||||
tokens: [],
|
||||
mintBatons: []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ class IPFSCoord {
|
||||
}
|
||||
|
||||
async start () {}
|
||||
|
||||
async subscribeToChat() {}
|
||||
}
|
||||
|
||||
module.exports = IPFSCoord
|
||||
|
||||
@@ -47,4 +47,17 @@ describe('#use-cases', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#start', () => {
|
||||
it('should initialize async use cases', async () => {
|
||||
const result = await uut.start()
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
// it('should catch and throw errors', async () => {
|
||||
// // Force an error
|
||||
// sandbox.stub()
|
||||
// })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -96,7 +96,8 @@ describe('#offer-use-case', () => {
|
||||
'241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87',
|
||||
utxoVout: 0,
|
||||
makerAddr: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
|
||||
ticker: 'TROUT'
|
||||
ticker: 'TROUT',
|
||||
tokenType: 1
|
||||
},
|
||||
timestamp: '2021-09-20T17:54:26.395Z',
|
||||
localTimeStamp: '9/20/2021, 10:54:26 AM',
|
||||
|
||||
@@ -125,12 +125,18 @@ describe('#order-use-case', () => {
|
||||
|
||||
it('should catch and throw an error', async () => {
|
||||
try {
|
||||
await uut.createOrder()
|
||||
await uut.createOrder({ a: 'b' })
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Cannot set')
|
||||
assert.include(err.message, 'entry does not contain required properties')
|
||||
}
|
||||
})
|
||||
|
||||
it('should exit quietly if the entry is empty', async () => {
|
||||
const result = await uut.createOrder()
|
||||
|
||||
assert.equal(result, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user