mirror of
https://github.com/Permissionless-Software-Foundation/bch-dex.git
synced 2026-09-21 16:52:00 -07:00
fix(p2wdb): Refactored p2wdb adapter and unit tests
This commit is contained in:
Vendored
+4
-2
@@ -37,6 +37,9 @@ module.exports = {
|
||||
? process.env.CONSUMER_URL
|
||||
: 'https://free-bch.fullstack.cash',
|
||||
|
||||
// P2WDB URL that will accept API calls from the p2wdb npm library.
|
||||
p2wdbUrl: process.env.P2WDB_URL ? process.env.P2WDB_URL : 'https://p2wdb.fullstack.cash',
|
||||
|
||||
// FullStack.cash account information, used for automatic JWT handling.
|
||||
getJwtAtStartup: process.env.GET_JWT_AT_STARTUP ? true : false,
|
||||
authServer: process.env.AUTHSERVER
|
||||
@@ -67,8 +70,7 @@ module.exports = {
|
||||
name: ipfsCoordName,
|
||||
version,
|
||||
protocol: 'generic-service',
|
||||
description:
|
||||
'This is a generic IPFS Serivice Provider that uses JSON RPC over IPFS to communicate with it. This instance has not been customized. Source code: https://github.com/Permissionless-Software-Foundation/ipfs-service-provider',
|
||||
description: 'This is a generic IPFS Serivice Provider that uses JSON RPC over IPFS to communicate with it. This instance has not been customized. Source code: https://github.com/Permissionless-Software-Foundation/ipfs-service-provider',
|
||||
documentation: 'https://ipfs-service-provider.fullstack.cash/',
|
||||
provider: {
|
||||
'@type': 'Organization',
|
||||
|
||||
Vendored
+1
-1
@@ -7,6 +7,6 @@
|
||||
module.exports = {
|
||||
session: 'secret-boilerplate-token',
|
||||
token: 'secret-jwt-token',
|
||||
database: 'mongodb://localhost:27017/swap-service-dev',
|
||||
database: 'mongodb://localhost:27017/bch-swap-service-dev',
|
||||
env: 'dev'
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -13,6 +13,6 @@ module.exports = {
|
||||
// database: 'mongodb://172.17.0.1:5555/ipfs-service-prod',
|
||||
database: process.env.DBURL
|
||||
? process.env.DBURL
|
||||
: 'mongodb://172.17.0.1:5555/swap-service-prod',
|
||||
: 'mongodb://172.17.0.1:5555/bch-swap-service-prod',
|
||||
env: 'prod'
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -7,6 +7,6 @@
|
||||
module.exports = {
|
||||
session: 'secret-boilerplate-token',
|
||||
token: 'secret-jwt-token',
|
||||
database: 'mongodb://localhost:27017/swap-service-test',
|
||||
database: 'mongodb://localhost:27017/bch-swap-service-test',
|
||||
env: 'test'
|
||||
}
|
||||
|
||||
Generated
+196
-1403
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -27,7 +27,7 @@
|
||||
},
|
||||
"repository": "Permissionless-Software-Foundation/bch-dex",
|
||||
"dependencies": {
|
||||
"@psf/bch-js": "5.3.2",
|
||||
"@psf/bch-js": "../bch-js",
|
||||
"axios": "0.21.1",
|
||||
"bch-message-lib": "2.1.4",
|
||||
"bcryptjs": "2.4.3",
|
||||
@@ -55,6 +55,7 @@
|
||||
"mongoose": "5.13.13",
|
||||
"node-fetch": "npm:@achingbrain/node-fetch@2.6.7",
|
||||
"nodemailer": "6.4.17",
|
||||
"p2wdb": "../p2wdb",
|
||||
"passport-local": "1.0.0",
|
||||
"public-ip": "^4.0.4",
|
||||
"winston": "3.3.3",
|
||||
|
||||
@@ -18,7 +18,7 @@ const JSONFiles = require('./json-files')
|
||||
const FullStackJWT = require('./fullstack-jwt')
|
||||
const BCHAdapter = require('./bch')
|
||||
const WalletAdapter = require('./wallet')
|
||||
const P2wdbAdapter = require('./p2wdb')
|
||||
const P2wdbAdapter = require('./p2wdb-adapter')
|
||||
|
||||
//
|
||||
// // Instantiate adapter libraries.
|
||||
@@ -52,10 +52,11 @@ class Adapters {
|
||||
this.nodemailer = new Nodemailer()
|
||||
this.jsonFiles = new JSONFiles()
|
||||
this.bchjs = new BCHJS()
|
||||
localConfig.bchjs = this.bchjs
|
||||
this.bch = new BCHAdapter()
|
||||
this.config = config
|
||||
this.wallet = new WalletAdapter()
|
||||
this.p2wdb = new P2wdbAdapter()
|
||||
this.p2wdb = new P2wdbAdapter(localConfig)
|
||||
|
||||
// Get a valid JWT API key and instance bch-js.
|
||||
this.fullStackJwt = new FullStackJWT(config)
|
||||
|
||||
@@ -14,6 +14,7 @@ const Offer = new mongoose.Schema({
|
||||
utxoTxid: { type: String },
|
||||
utxoVout: { type: Number },
|
||||
numTokens: { type: Number },
|
||||
hdIndex: { type: Number }, // HD index address holding the UTXO for this offer.
|
||||
|
||||
//
|
||||
offerIpfsId: { type: String },
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
Adapter library for interacting with the P2WDB
|
||||
*/
|
||||
|
||||
// Public npm libraries.
|
||||
const axios = require('axios')
|
||||
const { Write, Read } = require('p2wdb/index')
|
||||
|
||||
// Local libraries
|
||||
const config = require('../../config')
|
||||
|
||||
class P2wdbAdapter {
|
||||
constructor (localConfig = {}) {
|
||||
// Dependency injection
|
||||
this.bchjs = localConfig.bchjs
|
||||
if (!this.bchjs) {
|
||||
throw new Error('Must pass an instance of bch-js when instantiating p2wdb.js adapter.')
|
||||
}
|
||||
|
||||
// Encapsulate dependencies
|
||||
this.axios = axios
|
||||
this.config = config
|
||||
this.Write = Write
|
||||
this.Read = Read
|
||||
|
||||
// Allow the localConfig to overwrite the config file values.
|
||||
this.p2wdbURL = localConfig.p2wdbURL || config.p2wdbUrl
|
||||
}
|
||||
|
||||
// Write some data to the P2WDB
|
||||
async write (inputObj = {}) {
|
||||
try {
|
||||
const { appId = 'test', data = {}, wif } = inputObj
|
||||
|
||||
if (typeof wif !== 'string' || !wif) {
|
||||
throw new Error('wif input must be a private key starting with the letter L or K')
|
||||
}
|
||||
|
||||
const p2write = this.instantiateWriteLib(wif)
|
||||
|
||||
const result = await p2write.postEntry(data, appId)
|
||||
|
||||
return result.hash
|
||||
} catch (err) {
|
||||
console.error('Error in p2wdb.js/write()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate the Write library with a WIF, handling the various config
|
||||
// settings.
|
||||
instantiateWriteLib (wif) {
|
||||
try {
|
||||
// Object used to configure the Write library.
|
||||
let configObj = {}
|
||||
|
||||
if (this.config.useFullStackCash) {
|
||||
// Use web 2 infrastructure.
|
||||
// bch-js and FullStack.cash
|
||||
|
||||
configObj = {
|
||||
wif,
|
||||
serverURL: this.p2wdbURL,
|
||||
restURL: this.bchjs.restURL,
|
||||
apiToken: this.bchjs.apiToken
|
||||
}
|
||||
} else {
|
||||
// Use web 3 infrastructure.
|
||||
// ipfs-bch-wallet-consumer and bch-consumer library
|
||||
|
||||
configObj = {
|
||||
wif,
|
||||
serverURL: this.p2wdbURL,
|
||||
interface: 'consumer-api',
|
||||
restURL: this.config.consumerUrl
|
||||
}
|
||||
}
|
||||
|
||||
const write = new this.Write(configObj)
|
||||
|
||||
return write
|
||||
} catch (err) {
|
||||
console.error('Error in p2wdb-adapter.js/instantitateWriteLib()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a promise that resolves to true or false, to indicate if the
|
||||
// WIF controls the required funds to write to the P2WDB.
|
||||
async checkForSufficientFunds (wif) {
|
||||
try {
|
||||
if (typeof wif !== 'string' || !wif) {
|
||||
throw new Error('invalid wif to check for funds')
|
||||
}
|
||||
|
||||
// Instatiate the Write library
|
||||
const p2write = this.instantiateWriteLib(wif)
|
||||
|
||||
return await p2write.checkForSufficientFunds()
|
||||
} catch (err) {
|
||||
console.error('Error in p2wdb.js/checkForSufficientFunds()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = P2wdbAdapter
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
Adapter library for interacting with the P2WDB
|
||||
*/
|
||||
|
||||
// Public npm libraries.
|
||||
const axios = require('axios')
|
||||
|
||||
// Local libraries
|
||||
const config = require('../../config')
|
||||
|
||||
// Global constants
|
||||
let P2WDB_SERVER = 'http://localhost:5001/entry/write'
|
||||
// const P2WDB_SERVER = 'https://p2wdb.fullstack.cash/entry/write'
|
||||
|
||||
class P2wdbAdapter {
|
||||
constructor (localConfig = {}) {
|
||||
// Encapsulate dependencies
|
||||
this.axios = axios
|
||||
this.config = config
|
||||
|
||||
P2WDB_SERVER = `http://localhost:${config.p2wdbPort}/entry/write`
|
||||
}
|
||||
|
||||
async write (inputObj) {
|
||||
try {
|
||||
const { txid, signature, message, appId, data } = inputObj
|
||||
|
||||
// TODO: Input validation
|
||||
|
||||
const now = new Date()
|
||||
|
||||
const dataObj = {
|
||||
appId,
|
||||
data,
|
||||
timestamp: now.toISOString(),
|
||||
localTimeStamp: now.toLocaleString()
|
||||
}
|
||||
|
||||
const bodyData = {
|
||||
txid,
|
||||
message,
|
||||
signature,
|
||||
data: JSON.stringify(dataObj)
|
||||
}
|
||||
|
||||
const result = await this.axios.post(P2WDB_SERVER, bodyData)
|
||||
// console.log(`Response from API: ${JSON.stringify(result.data, null, 2)}`)
|
||||
|
||||
return result.data.hash
|
||||
} catch (err) {
|
||||
console.error('Error in p2wdb.js/write()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = P2wdbAdapter
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Integration tests for hte p2wdb-adapter.js library
|
||||
|
||||
These integration tests may not necessarily pass. They require a WIF set
|
||||
as an environment variable, and loaded with enough BCH and PSF to make
|
||||
a write to the P2WDB.
|
||||
|
||||
If these tests fail, it does not necessarily mean there is a problem with the
|
||||
code. Check that the WIF envrionment variable meets the requirements.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
const BCHJS = require('@psf/bch-js')
|
||||
|
||||
// Local libraries
|
||||
const P2wdbAdapter = require('../../../src/adapters/p2wdb-adapter')
|
||||
|
||||
const wif = process.env.WIF
|
||||
if (!wif) {
|
||||
throw new Error('You must provide a BCH WIF private key as an environment variable to run this test.')
|
||||
}
|
||||
|
||||
describe('#p2wdb-adapter.js', () => {
|
||||
let uut
|
||||
|
||||
beforeEach(() => {
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
uut = new P2wdbAdapter({ bchjs })
|
||||
})
|
||||
|
||||
describe('#checkForSufficientFunds', () => {
|
||||
it('should check for sufficient funds', async () => {
|
||||
const result = await uut.checkForSufficientFunds(wif)
|
||||
|
||||
console.log('Provided WIF has funds for making a write: ', result)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#write', () => {
|
||||
it('should write data to the P2WDB', async () => {
|
||||
const inObj = {
|
||||
appId: 'test234',
|
||||
data: {
|
||||
key: 'value'
|
||||
},
|
||||
wif
|
||||
}
|
||||
|
||||
const result = await uut.write(inObj)
|
||||
console.log('result: ', result)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -5,48 +5,141 @@
|
||||
// Public npm libraries.
|
||||
const assert = require('chai').assert
|
||||
const sinon = require('sinon')
|
||||
const BCHJS = require('@psf/bch-js')
|
||||
|
||||
// Local libraries.
|
||||
const P2wdbAdapter = require('../../../src/adapters/p2wdb')
|
||||
const P2wdbAdapter = require('../../../src/adapters/p2wdb-adapter')
|
||||
|
||||
describe('#P2wdbAdapter', () => {
|
||||
let uut, sandbox
|
||||
|
||||
beforeEach(() => {
|
||||
uut = new P2wdbAdapter()
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
uut = new P2wdbAdapter({ bchjs })
|
||||
sandbox = sinon.createSandbox()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe('#write', () => {
|
||||
it('should write an offer to the P2WDB', async () => {
|
||||
const inputObj = {
|
||||
txid: 'testTxid',
|
||||
signature: 'testSignature',
|
||||
message: 'testMessage',
|
||||
appId: 'testAppId',
|
||||
data: { key: 'value' }
|
||||
describe('#constructor', () => {
|
||||
it('should throw error if bch-js is not passed in', () => {
|
||||
try {
|
||||
uut = new P2wdbAdapter()
|
||||
|
||||
assert.fail('Unexpected coded path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Must pass an instance of bch-js when instantiating p2wdb.js adapter.')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Mock axios to prevent live network call
|
||||
sandbox.stub(uut.axios, 'post').resolves({ data: { hash: 'testhash' } })
|
||||
describe('#instantiateWriteLib', () => {
|
||||
it('should instantiate Write library using web 3 interface', async () => {
|
||||
// Force code path
|
||||
uut.config.useFullStackCash = false
|
||||
|
||||
const result = await uut.write(inputObj)
|
||||
// Mock dependencies
|
||||
uut.Write =
|
||||
class Write {
|
||||
constructor () {
|
||||
this.interface = 'web3'
|
||||
}
|
||||
}
|
||||
|
||||
const wif = 'L1tcvcqa5PztqqDH4ZEcUmHA9aSHhTau5E2Zwp1xEK5CrKBrjP3m'
|
||||
|
||||
const result = uut.instantiateWriteLib(wif)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.equal(result, 'testhash')
|
||||
assert.equal(result.interface, 'web3')
|
||||
})
|
||||
|
||||
it('should instantiate Write library using web 2 interface', async () => {
|
||||
// Force code path
|
||||
uut.config.useFullStackCash = true
|
||||
|
||||
// Mock dependencies
|
||||
uut.Write =
|
||||
class Write {
|
||||
constructor () {
|
||||
this.interface = 'fullstack'
|
||||
}
|
||||
}
|
||||
|
||||
const wif = 'L1tcvcqa5PztqqDH4ZEcUmHA9aSHhTau5E2Zwp1xEK5CrKBrjP3m'
|
||||
|
||||
const result = uut.instantiateWriteLib(wif)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.equal(result.interface, 'fullstack')
|
||||
})
|
||||
|
||||
it('should catch and throw errors', async () => {
|
||||
try {
|
||||
await uut.instantiateWriteLib()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.include(err.message, 'WIF private key required')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#checkForSufficientFunds', () => {
|
||||
it('should throw error if WIF is not provided', async () => {
|
||||
try {
|
||||
await uut.checkForSufficientFunds()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.include(err.message, 'invalid wif to check for funds')
|
||||
}
|
||||
})
|
||||
|
||||
it('should return status of funds', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut, 'instantiateWriteLib').returns({
|
||||
checkForSufficientFunds: () => true
|
||||
})
|
||||
|
||||
const wif = 'L1tcvcqa5PztqqDH4ZEcUmHA9aSHhTau5E2Zwp1xEK5CrKBrjP3m'
|
||||
|
||||
const result = await uut.checkForSufficientFunds(wif)
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#write', async () => {
|
||||
it('should throw error if WIF is not provided', async () => {
|
||||
try {
|
||||
await uut.write()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.include(err.message, 'Cannot destructure property')
|
||||
assert.include(err.message, 'wif input must be a private key starting with the letter L or K')
|
||||
}
|
||||
})
|
||||
|
||||
it('should write data to the P2WDB', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(uut, 'instantiateWriteLib').returns({
|
||||
postEntry: async () => {
|
||||
return { hash: 'fake-hash' }
|
||||
}
|
||||
})
|
||||
|
||||
const wif = 'L1tcvcqa5PztqqDH4ZEcUmHA9aSHhTau5E2Zwp1xEK5CrKBrjP3m'
|
||||
const inObj = { wif }
|
||||
|
||||
const result = await uut.write(inObj)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.equal(result, 'fake-hash')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user