Merged with ipfs-service-provider. Mitigated several conflict errors

This commit is contained in:
Chris Troutner
2024-11-22 10:54:21 -08:00
43 changed files with 18289 additions and 16260 deletions
+89 -88
View File
@@ -13,7 +13,6 @@ import axios from 'axios'
// Local support libraries
import config from '../../../config/index.js'
import Server from '../../../bin/server.js'
import testUtils from '../../utils/test-utils.js'
import AdminLib from '../../../src/adapters/admin.js'
@@ -24,105 +23,107 @@ const context = {}
const LOCALHOST = `http://localhost:${config.port}`
describe('Auth', () => {
before(async () => {
const app = new Server()
if (!config.noMongo) {
describe('Auth', () => {
before(async () => {
const app = new Server()
// This should be the first instruction. It starts the REST API server.
await app.startServer()
// This should be the first instruction. It starts the REST API server.
await app.startServer()
// Stop the IPFS node for the rest of the e2e tests.
// await app.controllers.adapters.ipfs.stop()
// Stop the IPFS node for the rest of the e2e tests.
// await app.controllers.adapters.ipfs.stop()
// Delete all previous users in the database.
await testUtils.deleteAllUsers()
// Delete all previous users in the database.
await testUtils.deleteAllUsers()
// Create a new admin user.
await adminLib.createSystemUser()
// Create a new admin user.
await adminLib.createSystemUser()
const userObj = {
email: 'test@test.com',
password: 'pass',
name: 'test'
}
const testUser = await testUtils.createUser(userObj)
// console.log('TestUser: ', testUser)
context.user = testUser.user
context.token = testUser.token
})
describe('POST /auth', () => {
it('should throw 401 if credentials are incorrect', async () => {
try {
const options = {
method: 'post',
url: `${LOCALHOST}/auth`,
data: {
email: 'test@test.com',
password: 'wrongpassword'
}
}
const result = await axios(options)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
console.log(
`result stringified: ${JSON.stringify(result.data, null, 2)}`
)
assert(false, 'Unexpected result')
} catch (err) {
assert(err.response.status === 401, 'Error code 401 expected.')
const userObj = {
email: 'test@test.com',
password: 'pass',
name: 'test'
}
const testUser = await testUtils.createUser(userObj)
// console.log('TestUser: ', testUser)
context.user = testUser.user
context.token = testUser.token
})
it('should throw 401 if email is wrong format', async () => {
try {
const options = {
method: 'post',
url: `${LOCALHOST}/auth`,
data: {
email: 'wrongEmail',
password: 'wrongpassword'
describe('POST /auth', () => {
it('should throw 401 if credentials are incorrect', async () => {
try {
const options = {
method: 'post',
url: `${LOCALHOST}/auth`,
data: {
email: 'test@test.com',
password: 'wrongpassword'
}
}
const result = await axios(options)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
console.log(
`result stringified: ${JSON.stringify(result.data, null, 2)}`
)
assert(false, 'Unexpected result')
} catch (err) {
assert(err.response.status === 401, 'Error code 401 expected.')
}
})
await axios(options)
assert(false, 'Unexpected result')
} catch (err) {
assert(err.response.status === 401, 'Error code 401 expected.')
}
})
it('should auth user', async () => {
try {
const options = {
method: 'post',
url: `${LOCALHOST}/auth`,
data: {
email: 'test@test.com',
password: 'pass'
it('should throw 401 if email is wrong format', async () => {
try {
const options = {
method: 'post',
url: `${LOCALHOST}/auth`,
data: {
email: 'wrongEmail',
password: 'wrongpassword'
}
}
}
const result = await axios(options)
// console.log(`result: ${JSON.stringify(result.data, null, 2)}`)
assert(result.status === 200, 'Status Code 200 expected.')
assert(
result.data.user.email === 'test@test.com',
'Email of test expected'
)
assert(
result.data.user.password === undefined,
'Password expected to be omited'
)
} catch (err) {
console.log(
'Error authenticating test user: ' + JSON.stringify(err, null, 2)
)
throw err
}
await axios(options)
assert(false, 'Unexpected result')
} catch (err) {
assert(err.response.status === 401, 'Error code 401 expected.')
}
})
it('should auth user', async () => {
try {
const options = {
method: 'post',
url: `${LOCALHOST}/auth`,
data: {
email: 'test@test.com',
password: 'pass'
}
}
const result = await axios(options)
// console.log(`result: ${JSON.stringify(result.data, null, 2)}`)
assert(result.status === 200, 'Status Code 200 expected.')
assert(
result.data.user.email === 'test@test.com',
'Email of test expected'
)
assert(
result.data.user.password === undefined,
'Password expected to be omited'
)
} catch (err) {
console.log(
'Error authenticating test user: ' + JSON.stringify(err, null, 2)
)
throw err
}
})
})
})
})
}
File diff suppressed because it is too large Load Diff
+93 -89
View File
@@ -2,6 +2,8 @@ import { assert } from 'chai'
import Admin from '../../../src/adapters/admin.js'
import sinon from 'sinon'
import util from 'util'
import config from '../../../config/index.js'
util.inspect.defaultOptions = { depth: 1 }
let sandbox
@@ -15,101 +17,103 @@ describe('Admin', () => {
afterEach(() => sandbox.restore())
describe('loginAdmin()', () => {
it('should logind admin', async () => {
try {
const error = new Error('test error')
error.response = {
status: 422
if (!config.noMongo) {
describe('loginAdmin()', () => {
it('should logind admin', async () => {
try {
const error = new Error('test error')
error.response = {
status: 422
}
// sandbox.stub(uut.axios, 'request').onFirstCall().throws(error)
const result = await uut.loginAdmin()
const user = result.data.user
assert.property(user, '_id')
assert.property(user, 'email')
assert.property(user, 'type')
assert.isString(user._id)
assert.isString(user.email)
assert.isString(user.type)
assert.equal(user.type, 'admin')
} catch (err) {
assert(false, 'Unexpected result')
}
// sandbox.stub(uut.axios, 'request').onFirstCall().throws(error)
})
const result = await uut.loginAdmin()
const user = result.data.user
it('should handle axios error', async () => {
try {
// Returns an erroneous password to force
// an auth error
sandbox.stub(uut.jsonFiles, 'readJSON').resolves({ password: 'wrong' })
assert.property(user, '_id')
assert.property(user, 'email')
assert.property(user, 'type')
assert.isString(user._id)
assert.isString(user.email)
assert.isString(user.type)
assert.equal(user.type, 'admin')
} catch (err) {
assert(false, 'Unexpected result')
}
})
it('should handle axios error', async () => {
try {
// Returns an erroneous password to force
// an auth error
sandbox.stub(uut.jsonFiles, 'readJSON').resolves({ password: 'wrong' })
await uut.loginAdmin()
assert(false, 'Unexpected result')
} catch (err) {
assert.equal(err.response.status, 401)
assert.include(err.response.data, 'Unauthorized')
}
})
})
describe('createSystemUser()', () => {
it('should create admin', async () => {
try {
const result = await uut.createSystemUser()
assert.property(result, 'email')
assert.property(result, 'password')
assert.property(result, 'id')
assert.property(result, 'token')
} catch (err) {
assert(false, 'Unexpected result')
}
})
it('should handle axios error', async () => {
try {
const error1 = new Error('test error')
error1.response = {
status: 422
await uut.loginAdmin()
assert(false, 'Unexpected result')
} catch (err) {
assert.equal(err.response.status, 401)
assert.include(err.response.data, 'Unauthorized')
}
const error2 = new Error('test error')
error1.response = {
status: 500
}
// The loginAdmin() function in some use cases is recursive
// after handling the 422 error, it gets called again
sandbox
.stub(uut.axios, 'request')
.onFirstCall()
.throws(error1)
.onSecondCall()
.throws(error2)
await uut.createSystemUser()
assert(false, 'Unexpected result')
} catch (err) {
assert.include(err.message, 'test error')
}
})
})
it('should handle errors when remove user', async () => {
try {
const error1 = new Error('test error')
error1.response = {
status: 422
}
sandbox.stub(uut.axios, 'request').throws(error1)
sandbox.stub(uut.User, 'deleteOne').throws(new Error('test error'))
describe('createSystemUser()', () => {
it('should create admin', async () => {
try {
const result = await uut.createSystemUser()
await uut.createSystemUser()
assert(false, 'Unexpected result')
} catch (err) {
assert.include(err.message, 'test error')
}
assert.property(result, 'email')
assert.property(result, 'password')
assert.property(result, 'id')
assert.property(result, 'token')
} catch (err) {
assert(false, 'Unexpected result')
}
})
it('should handle axios error', async () => {
try {
const error1 = new Error('test error')
error1.response = {
status: 422
}
const error2 = new Error('test error')
error1.response = {
status: 500
}
// The loginAdmin() function in some use cases is recursive
// after handling the 422 error, it gets called again
sandbox
.stub(uut.axios, 'request')
.onFirstCall()
.throws(error1)
.onSecondCall()
.throws(error2)
await uut.createSystemUser()
assert(false, 'Unexpected result')
} catch (err) {
assert.include(err.message, 'test error')
}
})
it('should handle errors when remove user', async () => {
try {
const error1 = new Error('test error')
error1.response = {
status: 422
}
sandbox.stub(uut.axios, 'request').throws(error1)
sandbox.stub(uut.User, 'deleteOne').throws(new Error('test error'))
await uut.createSystemUser()
assert(false, 'Unexpected result')
} catch (err) {
assert.include(err.message, 'test error')
}
})
})
})
}
})
@@ -27,6 +27,8 @@ describe('#adapters', () => {
it('should start the async adapters', async () => {
// Mock dependencies
uut.config.getJwtAtStartup = true
uut.config.useIpfs = true
uut.config.env = 'not-a-test'
sandbox.stub(uut.fullStackJwt, 'getJWT').resolves()
sandbox.stub(uut.fullStackJwt, 'instanceBchjs').resolves()
sandbox.stub(uut.ipfs, 'start').resolves()
@@ -52,7 +52,7 @@ describe('#IPFS', () => {
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').resolves('123')
sandbox.stub(uut, 'publicIp').resolves('123')
// Force Circuit Relay
uut.config.isCircuitRelay = true
@@ -66,7 +66,7 @@ describe('#IPFS', () => {
it('should exit quietly if this node is a Circuit Relay and there is an issue getting the IP address', async () => {
// Mock dependencies.
uut.IpfsCoord = IPFSCoordMock
sandbox.stub(uut.publicIp, 'v4').rejects(new Error('test error'))
sandbox.stub(uut, 'publicIp').rejects(new Error('test error'))
// Force Circuit Relay
uut.config.isCircuitRelay = true
@@ -66,4 +66,155 @@ describe('#IPFS-adapter-index', () => {
}
})
})
describe('#getStatus', () => {
it('should return an object with node metrics', () => {
// Force uut to have the needed properties
uut.ipfsCoordAdapter = {
ipfsCoord: {
thisNode: {
ipfsId: 'fake-id',
ipfsMultiaddrs: [],
bchAddr: 'fake-bch-addr',
slpAddr: 'fake-slp-addr',
pubKey: 'fake-pubkey',
peerList: [],
relayData: []
}
}
}
const result = uut.getStatus()
// console.log('result: ', result)
assert.property(result, 'ipfsId')
assert.property(result, 'multiAddrs')
assert.property(result, 'bchAddr')
assert.property(result, 'slpAddr')
assert.property(result, 'pubKey')
assert.property(result, 'peers')
assert.property(result, 'relays')
})
it('should catch, report, and throw errors', () => {
try {
uut.getStatus()
assert.fail('Unexpected code path')
} catch (err) {
// console.log('err.message: ', err.message)
assert.include(err.message, 'Cannot read properties')
}
})
})
describe('#_removeDuplicatePeers', () => {
it('should return the same array when there are no duplicates', () => {
const inArray = [
'12D3KooWPpBXhhAeoCZCGuQ3KR4xwHzzvtP57f6zLmo8P7ZFBJFE',
'12D3KooWRBhwfeP2Y9CDkFRBAZ1pmxUadH36TKuk3KtKm5XXP8mA',
'12D3KooWGsgHWyDLKuV4ZSfRJfsxQJj77rxx3i8Px3qXKHsLN7a2',
'12D3KooWJyc54njjeZGbLew4D8u1ghrmZTTPyh3QpBF7dxtd3zGY',
'12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu'
]
const result = uut._removeDuplicatePeers(inArray)
// console.log('result: ', result)
assert.equal(result.length, inArray.length)
})
it('should remove duplicates from an array', () => {
const inArray = [
'12D3KooWPpBXhhAeoCZCGuQ3KR4xwHzzvtP57f6zLmo8P7ZFBJFE',
'12D3KooWRBhwfeP2Y9CDkFRBAZ1pmxUadH36TKuk3KtKm5XXP8mA',
'12D3KooWGsgHWyDLKuV4ZSfRJfsxQJj77rxx3i8Px3qXKHsLN7a2',
'12D3KooWJyc54njjeZGbLew4D8u1ghrmZTTPyh3QpBF7dxtd3zGY',
'12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu',
'12D3KooWPpBXhhAeoCZCGuQ3KR4xwHzzvtP57f6zLmo8P7ZFBJFE',
'12D3KooWRBhwfeP2Y9CDkFRBAZ1pmxUadH36TKuk3KtKm5XXP8mA'
]
const result = uut._removeDuplicatePeers(inArray)
// console.log('result: ', result)
assert.equal(result.length, inArray.length - 2)
})
})
describe('#getPeers', () => {
it('should return an array of current JSON data about each peer when showAll is true', async () => {
// Mock dependencies
uut.ipfsCoordAdapter.ipfsCoord = {
thisNode: {
peerData: [{ from: 'a', data: { jsonLd: { name: 'a', protocol: 'test', version: '1' } } }, { from: 'b' }]
},
adapters: {
ipfs: {
getPeers: async () => ['a', 'b']
}
}
}
const result = await uut.getPeers(true)
assert.isArray(result)
})
it('should catch, report, and throw errors', async () => {
try {
// Force an error
uut.ipfsCoordAdapter.ipfsCoord = {
thisNode: {},
adapters: {
ipfs: {
getPeers: async () => { throw new Error('test error') }
}
}
}
await uut.getPeers()
assert.fail('Unexpected code path')
} catch (err) {
// console.log('err.message: ', err.message)
assert.include(err.message, 'test error')
}
})
})
describe('#getRelays', () => {
it('should return known relays', () => {
uut.ipfsCoordAdapter.ipfsCoord = {
thisNode: {
peerData: [{ from: 'a', data: { jsonLd: { name: 'a', description: 'test' } } }, { from: 'b' }],
relayData: [{ ipfsId: 'c' }, { ipfsId: 'a' }]
}
}
const result = uut.getRelays()
// console.log('result: ', result)
assert.isArray(result.v2Relays)
assert.equal(result.v2Relays.length, 2)
assert.property(result.v2Relays[0], 'name')
assert.property(result.v2Relays[0], 'description')
assert.property(result.v2Relays[1], 'name')
assert.property(result.v2Relays[1], 'description')
})
it('should catch, report, and throw errors', () => {
try {
// Force an error
uut.ipfsCoordAdapter.ipfsCoord = { thisNode: {} }
uut.getRelays()
assert.fail('Unexpected code path')
} catch (err) {
// console.log('err.message: ', err.message)
assert.include(err.message, 'Cannot read')
}
})
})
})
+161 -38
View File
@@ -2,21 +2,29 @@
Unit tests for the IPFS Adapter.
*/
// Global npm libraries
import { assert } from 'chai'
import sinon from 'sinon'
import cloneDeep from 'lodash.clonedeep'
import { peerIdFromString } from '@libp2p/peer-id'
// Local libraries
import IPFSLib from '../../../src/adapters/ipfs/ipfs.js'
import create from '../mocks/ipfs-mock.js'
// import create from '../mocks/ipfs-mock.js'
import config from '../../../config/index.js'
import createHeliaLib from '../mocks/helia-mock.js'
// config.isProduction = true;
describe('#IPFS-adapter', () => {
let uut
let sandbox
let ipfs
beforeEach(() => {
uut = new IPFSLib()
ipfs = cloneDeep(createHeliaLib)
sandbox = sinon.createSandbox()
})
@@ -45,35 +53,28 @@ describe('#IPFS-adapter', () => {
describe('#start', () => {
it('should return a promise that resolves into an instance of IPFS.', async () => {
// Mock dependencies.
uut.create = create
sandbox.stub(uut, 'createNode').resolves(ipfs)
sandbox.stub(uut, 'publicIp').resolves('192.168.2.4')
sandbox.stub(uut, 'multiaddr').returns('/ip4/fake-multiaddr')
const result = await uut.start()
// console.log('result: ', result)
// Assert properties of the instance are set.
assert.equal(uut.isReady, true)
assert.property(uut, 'multiaddrs')
assert.property(uut, 'id')
assert.property(result, 'config')
})
it('should return a promise that resolves into an instance of IPFS in production mode.', async () => {
// Mock dependencies.
uut.create = create
uut.config.isProduction = true
const result = await uut.start()
// console.log('result: ', result)
assert.equal(uut.isReady, true)
assert.property(result, 'config')
// Output should be an instance of IPFS
assert.property(result, 'libp2p')
})
it('should catch and throw an error', async () => {
try {
// Force an error
sandbox.stub(uut, 'create').rejects(new Error('test error'))
sandbox.stub(uut, 'createNode').rejects(new Error('test error'))
await uut.start()
assert.fail('Unexpected code path.')
} catch (err) {
// console.log(err)
@@ -96,24 +97,146 @@ describe('#IPFS-adapter', () => {
})
})
// describe('#rmBlocksDir', () => {
// it('should delete the /blocks directory', () => {
// const result = uut.rmBlocksDir()
//
// assert.equal(result, true)
// })
//
// it('should catch and throw an error', () => {
// try {
// // Force an error
// sandbox.stub(uut.fs, 'rmdirSync').throws(new Error('test error'))
//
// uut.rmBlocksDir()
//
// assert.fail('Unexpected code path')
// } catch (err) {
// assert.equal(err.message, 'test error')
// }
// })
// })
describe('#ensureBlocksDir', () => {
it('should create directory if it does not exist', () => {
// Force desired code path
sandbox.stub(uut.fs, 'existsSync').returns(false)
sandbox.stub(uut.fs, 'mkdirSync').returns(true)
const result = uut.ensureBlocksDir()
assert.equal(result, true)
})
it('should report and throw errors', () => {
// Force an error
sandbox.stub(uut.fs, 'existsSync').throws(new Error('test error'))
try {
uut.ensureBlocksDir()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(err.message, 'test error')
}
})
})
describe('#createNode', () => {
it('should report and throw errors', async () => {
// Force an error
sandbox.stub(uut, 'createLibp2p').rejects(new Error('test error'))
try {
await uut.createNode()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(err.message, 'test error')
}
})
it('should create an IPFS node from Helia', async () => {
uut.config.isCircuitRelay = false
const result = await uut.createNode()
// console.log('result: ', result)
// Assert the returned IPFS node has expected properties
assert.property(result, 'libp2p')
assert.property(result, 'blockstore')
// Stop the IPFS node
await result.stop()
})
it('should create a Circuit Relay if configured', async () => {
uut.config.isCircuitRelay = true
const result = await uut.createNode()
// Assert the returned IPFS node has expected properties
assert.property(result, 'libp2p')
assert.property(result, 'blockstore')
// Stop the IPFS node
await result.stop()
})
it('should create a new private key on first run', async () => {
uut.config.isCircuitRelay = false
// Mock dependencies and force desired code path.
let beenCalled = false
sandbox.stub(uut, 'getKeychain').resolves({
exportPeerId: async () => {
if (!beenCalled) {
beenCalled = true
throw new Error('test error')
}
return peerIdFromString('12D3KooWSXF1PnEfiA8bCG8SJduCvzdwHtvhVPK4WC6zzDoto2XP')
},
createKey: async () => {}
})
sandbox.stub(uut, 'createLibp2p').resolves()
sandbox.stub(uut, 'createHelia').resolves({})
const result = await uut.createNode()
// console.log('result: ', result)
assert.property(result, 'fs')
})
it('should not use circuit relay when CONNECT_PREF is set to direct', async () => {
process.env.CONNECT_PREF = 'direct'
uut.config.isCircuitRelay = false
const result = await uut.createNode()
// console.log('result: ', result)
delete process.env.CONNECT_PREF
// Assert the returned IPFS node has expected properties
assert.property(result, 'libp2p')
assert.property(result, 'blockstore')
// Stop the IPFS node
await result.stop()
})
})
describe('#getSeed', () => {
it('should read the seed from the JSON file', async () => {
// Mock dependencies and force desired code path
sandbox.stub(uut.jsonFiles, 'readJSON').resolves('12345678')
const result = await uut.getSeed()
// console.log('result: ', result)
assert.isString(result)
})
it('should generate a new seed if the JSON file is not found', async () => {
// Mock dependencies and force desired code path
sandbox.stub(uut.jsonFiles, 'readJSON').rejects(new Error('test error'))
sandbox.stub(uut.jsonFiles, 'writeJSON').resolves()
const result = await uut.getSeed()
// console.log('result: ', result)
assert.isString(result)
})
it('should catch, report, and throw errors', async () => {
try {
// Force an error
sandbox.stub(uut.jsonFiles, 'readJSON').rejects(new Error('test error'))
sandbox.stub(uut.jsonFiles, 'writeJSON').rejects(new Error('test error'))
await uut.getSeed()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(err.message, 'test error')
}
})
})
})
+180 -160
View File
@@ -2,16 +2,14 @@
Unit tests for the Wallet Adapter library.
*/
// Public npm libraries.
// Global npm libraries
import { assert } from 'chai'
import sinon from 'sinon'
import BchWallet from 'minimal-slp-wallet'
import fs from 'fs'
// const BCHJS = require('@psf/bch-js')
// Local libraries.
import WalletAdapter from '../../../src/adapters/wallet.js'
// Local libraries
import WalletAdapter from '../../../src/adapters/wallet.adapter.js'
import { MockBchWallet } from '../mocks/adapters/wallet.js'
// Hack to get __dirname back.
@@ -20,7 +18,7 @@ import * as url from 'url'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
// Global constants
const testWalletFile = `${__dirname.toString()}/test-wallet.json`
const testWalletFile = `${__dirname.toString()}test-wallet.json`
describe('#wallet', () => {
let uut
@@ -30,7 +28,7 @@ describe('#wallet', () => {
// Delete the test file if it exists.
try {
deleteFile(testWalletFile)
} catch (err) {}
} catch (err) { }
})
beforeEach(() => {
@@ -44,20 +42,26 @@ describe('#wallet', () => {
// Delete the test file if it exists.
try {
deleteFile(testWalletFile)
} catch (err) {}
} catch (err) { }
})
describe('#_instanceWallet', () => {
it('should create a wallet given a mnemonic', async () => {
const mnemonic = 'wagon tray learn flat erase laugh lonely rug check captain jacket morning'
const result = await uut._instanceWallet(mnemonic)
// console.log('result: ', result)
assert.equal(result.walletInfo.mnemonic, mnemonic)
})
})
describe('#openWallet', () => {
it('should create a new wallet what wallet file does not exist', async () => {
it('should create a new wallet when wallet file does not exist', async () => {
// Mock dependencies
uut.BchWallet = MockBchWallet
// Ensure we open the test file, not the production wallet file.
uut.WALLET_FILE = testWalletFile
uut.config.walletFile = testWalletFile
const result = await uut.openWallet()
// console.log('result: ', result)
assert.property(result, 'mnemonic')
assert.property(result, 'privateKey')
assert.property(result, 'publicKey')
@@ -70,13 +74,10 @@ describe('#wallet', () => {
it('should open existing wallet file', async () => {
// This test case uses the file created in the previous test case.
// Ensure we open the test file, not the production wallet file.
uut.WALLET_FILE = testWalletFile
uut.config.walletFile = testWalletFile
const result = await uut.openWallet()
// console.log('result: ', result)
assert.property(result, 'mnemonic')
assert.property(result, 'privateKey')
assert.property(result, 'publicKey')
@@ -90,13 +91,11 @@ describe('#wallet', () => {
it('should catch and throw an error', async () => {
try {
// Force an error
uut.WALLET_FILE = ''
uut.config.walletFile = ''
uut.BchWallet = () => {
}
await uut.openWallet()
// console.log('result: ', result)
assert.fail('Unexpected code path')
} catch (err) {
// console.log('err: ', err)
@@ -105,113 +104,158 @@ describe('#wallet', () => {
})
})
describe('#instanceWallet', () => {
// it('should create an instance of BchWallet', async () => {
// // Mock dependencies
// uut.BchWallet = MockBchWallet
//
// // Ensure we open the test file, not the production wallet file.
// uut.WALLET_FILE = testWalletFile
//
// const walletData = await uut.openWallet()
//
// const result = await uut.instanceWallet(walletData.mnemonic)
// console.log('result: ', result)
//
// assert.property(result, 'walletInfoPromise')
// })
describe('#instanceWalletWithoutInitialization', () => {
it('should create an instance of BchWallet', async () => {
// Create a mock wallet.
const mockWallet = new BchWallet()
await mockWallet.walletInfoPromise
sandbox.stub(mockWallet, 'initialize').resolves()
// Mock dependencies
sandbox.stub(uut, '_instanceWallet').resolves(mockWallet)
uut.config.authPass = 'fake-auth-pass'
// Ensure we open the test file, not the production wallet file.
uut.config.walletFile = testWalletFile
const walletData = await uut.openWallet()
// console.log('walletData: ', walletData)
const result = await uut.instanceWalletWithoutInitialization(walletData)
// console.log('result: ', result)
assert.property(result, 'walletInfoPromise')
assert.property(result, 'walletInfo')
})
it('should catch and throw an error', async () => {
try {
await uut.instanceWallet()
// Force an error
sandbox.stub(uut, '_instanceWallet').rejects(new Error('test error'))
await uut.instanceWalletWithoutInitialization()
assert.fail('Unexpected code path')
} catch (err) {
// console.log('err: ', err)
assert.include(err.message, 'Cannot read')
}
})
})
describe('#generateSignature', () => {
it('should return a signature', async () => {
// mock instance of minimal-slp-wallet
uut.bchWallet = new MockBchWallet()
const result = await uut.generateSignature('test')
// console.log('result: ', result)
assert.isString(result)
})
it('should catch and throw errors', async () => {
try {
// mock instance of minimal-slp-wallet
uut.bchWallet = new MockBchWallet()
// force an error
sandbox
.stub(uut.bchWallet.bchjs.BitcoinCash, 'signMessageWithPrivKey')
.throws(new Error('test error'))
await uut.generateSignature('test')
assert.fail('Unexpected code path')
} catch (err) {
assert.include(err.message, 'test error')
}
})
it('should create an instance of BchWallet using web2 infra', async () => {
// Create a mock wallet.
const mockWallet = new BchWallet()
await mockWallet.walletInfoPromise
sandbox.stub(mockWallet, 'initialize').resolves()
// Mock dependencies
sandbox.stub(uut, '_instanceWallet').resolves(mockWallet)
// Ensure we open the test file, not the production wallet file.
uut.config.walletFile = testWalletFile
const walletData = await uut.openWallet()
// console.log('walletData: ', walletData)
// Force desired code path
uut.config.walletInterface = 'web2'
const result = await uut.instanceWalletWithoutInitialization(walletData)
// console.log('result: ', result)
assert.property(result, 'walletInfoPromise')
assert.property(result, 'walletInfo')
})
it('should generate wallet from mnemonic in config', async () => {
// Create a mock wallet.
const mockWallet = new BchWallet()
await mockWallet.walletInfoPromise
sandbox.stub(mockWallet, 'initialize').resolves()
// Mock dependencies
sandbox.stub(uut, '_instanceWallet').resolves(mockWallet)
// Ensure we open the test file, not the production wallet file.
uut.config.walletFile = testWalletFile
const walletData = await uut.openWallet()
// console.log('walletData: ', walletData)
const originalConfig = uut.config.mnemonic
uut.config.mnemonic = walletData.mnemonic
const result = await uut.instanceWalletWithoutInitialization({})
// console.log('result: ', result)
uut.config.mnemonic = originalConfig
assert.property(result, 'walletInfoPromise')
assert.property(result, 'walletInfo')
})
})
// describe('#burnPsf', () => {
// it('should burn PSF tokens and return the txid', async () => {
// // mock instance of minimal-slp-wallet
// uut.bchWallet = new MockBchWallet()
//
// const result = await uut.burnPsf()
// // console.log('result: ', result)
//
// assert.equal(result.success, true)
// assert.equal(result.txid, 'txid')
// })
//
// it('should throw error if no PSF tokens are found', async () => {
// try {
// // mock instance of minimal-slp-wallet
// uut.bchWallet = new MockBchWallet()
//
// // Remove the PSF token from the mock data.
// uut.bchWallet.utxos.utxoStore.slpUtxos.type1.tokens.pop()
//
// await uut.burnPsf()
//
// assert.fail('Unexpected code path')
// } catch (err) {
// assert.include(err.message, 'Token UTXO of with ID of')
// }
// })
//
// it('should catch and throw an error', async () => {
// try {
// await uut.burnPsf()
//
// assert.fail('Unexpected code path')
// } catch (err) {
// assert.include(err.message, 'Cannot read')
// }
// })
// })
describe('#instanceWallet', () => {
it('should create an instance of BchWallet', async () => {
// Create a mock wallet.
const mockWallet = new BchWallet()
await mockWallet.walletInfoPromise
sandbox.stub(mockWallet, 'initialize').resolves()
// Mock dependencies
sandbox.stub(uut, '_instanceWallet').resolves(mockWallet)
// Ensure we open the test file, not the production wallet file.
uut.WALLET_FILE = testWalletFile
const walletData = await uut.openWallet()
// console.log('walletData: ', walletData)
const result = await uut.instanceWallet(walletData)
// console.log('result: ', result)
assert.property(result, 'walletInfoPromise')
assert.property(result, 'walletInfo')
})
it('should catch and throw an error', async () => {
try {
// Force an error
sandbox.stub(uut, 'instanceWalletWithoutInitialization').rejects(new Error('test error'))
await uut.instanceWallet()
assert.fail('Unexpected code path')
} catch (err) {
// console.log('err: ', err)
assert.include(err.message, 'test error')
}
})
it('should create an instance of BchWallet using web2 infra', async () => {
// Create a mock wallet.
const mockWallet = new BchWallet()
await mockWallet.walletInfoPromise
sandbox.stub(mockWallet, 'initialize').resolves()
// Mock dependencies
sandbox.stub(uut, '_instanceWallet').resolves(mockWallet)
// Ensure we open the test file, not the production wallet file.
uut.WALLET_FILE = testWalletFile
const walletData = await uut.openWallet()
// console.log('walletData: ', walletData)
// Force desired code path
uut.config.useFullStackCash = true
const result = await uut.instanceWallet(walletData)
// console.log('result: ', result)
assert.property(result, 'walletInfoPromise')
assert.property(result, 'walletInfo')
})
})
describe('#incrementNextAddress', () => {
it('should increment the nextAddress property', async () => {
// Ensure we open the test file, not the production wallet file.
uut.WALLET_FILE = testWalletFile
// mock instance of minimal-slp-wallet
uut.bchWallet = new MockBchWallet()
const result = await uut.incrementNextAddress()
assert.equal(result, 2)
})
@@ -219,9 +263,7 @@ describe('#wallet', () => {
try {
// Force an error
sandbox.stub(uut, 'openWallet').rejects(new Error('test error'))
await uut.incrementNextAddress()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(err.message, 'test error')
@@ -232,10 +274,8 @@ describe('#wallet', () => {
describe('#getKeyPair', () => {
it('should return an object with a key pair', async () => {
// Ensure we open the test file, not the production wallet file.
uut.WALLET_FILE = testWalletFile
// mock instance of minimal-slp-wallet
uut.bchWallet = new MockBchWallet()
// uut.WALLET_FILE = testWalletFile
uut.config.walletFile = testWalletFile
const result = await uut.getKeyPair()
// console.log('result: ', result)
@@ -251,9 +291,7 @@ describe('#wallet', () => {
sandbox
.stub(uut, 'incrementNextAddress')
.rejects(new Error('test error'))
await uut.getKeyPair()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(err.message, 'test error')
@@ -261,55 +299,37 @@ describe('#wallet', () => {
})
})
describe('#moveTokens', () => {
it('should move tokens to a new address in the HD wallet', async () => {
// Mock dependencies
sandbox.stub(uut, 'getKeyPair').resolves({
cashAddress: 'bitcoincash:qqsj63493jk4p05zzdgqzc29k5unqtet9vv8l4x0yt',
wif: 'L4qKTMCwjH9jHnYtNh9Vsrxj7Hg6zmoN8E2v7N47UKvNVEjw7FU8',
hdIndex: 6
})
describe('#optimize', () => {
it('should call the wallet optimize function', async () => {
// mock instance of minimal-slp-wallet
uut.bchWallet = new MockBchWallet()
// uut.bchWallet = {
// sendTokens: async () => 'fake-txid',
// getUtxos: async () => {}
// }
const inObj = {
tokenId: 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2',
qty: 1
}
const result = await uut.moveTokens(inObj)
// console.log('result: ', result)
assert.property(result, 'txid')
assert.property(result, 'vout')
assert.property(result, 'hdIndex')
sandbox.stub(uut.bchWallet, 'optimize').resolves({ bchUtxoCnt: 10 })
const result = await uut.optimize()
assert.equal(result, true)
})
})
describe('#moveBch', () => {
it('should move BCH to a new address in the HD wallet', async () => {
// Mock dependencies
sandbox.stub(uut, 'getKeyPair').resolves({
cashAddress: 'bitcoincash:qqsj63493jk4p05zzdgqzc29k5unqtet9vv8l4x0yt',
wif: 'L4qKTMCwjH9jHnYtNh9Vsrxj7Hg6zmoN8E2v7N47UKvNVEjw7FU8',
hdIndex: 6
})
uut.bchWallet = {
send: async () => 'fake-txid',
getUtxos: async () => {}
}
const amountSat = 1000
const result = await uut.moveBch(amountSat)
describe('#getBalance', () => {
it('should get the balance for the wallet', async () => {
// mock instance of minimal-slp-wallet
uut.bchWallet = new MockBchWallet()
// Mock dependencies and force desired code path
sandbox.stub(uut.bchWallet, 'getBalance').resolves(41012)
sandbox.stub(uut.bchWallet, 'listTokens').resolves([{
tokenId: '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0',
ticker: 'PSF',
name: 'Permissionless Software Foundation',
decimals: 8,
tokenType: 1,
url: 'psfoundation.cash',
qty: 2
}])
const result = await uut.getBalance()
// console.log('result: ', result)
assert.property(result, 'txid')
assert.property(result, 'vout')
assert.property(result, 'hdIndex')
// Assert the expected properties exist and have the expected values.
assert.equal(result.satBalance, 41012)
assert.equal(result.psfBalance, 2)
assert.equal(result.success, true)
})
})
})
@@ -28,6 +28,9 @@ describe('#Controllers', () => {
attachRPCRouter: () => {}
}
// Mock the timer controllers
sandbox.stub(uut.timerControllers, 'startTimers').returns()
const app = {
use: () => {}
}
@@ -0,0 +1,251 @@
/*
Unit tests for the REST API handler for the /ipfs endpoints.
*/
// Public npm libraries
import { assert } from 'chai'
import sinon from 'sinon'
// Local libraries
import IpfsApiController from '../../../../../src/controllers/rest-api/ipfs/controller.js'
import adapters from '../../../mocks/adapters/index.js'
import UseCasesMock from '../../../mocks/use-cases/index.js'
import { context as mockContext } from '../../../mocks/ctx-mock.js'
let uut
let sandbox
let ctx
describe('#IPFS REST API', () => {
before(async () => {
})
beforeEach(() => {
const useCases = new UseCasesMock()
uut = new IpfsApiController({ adapters, useCases })
sandbox = sinon.createSandbox()
// Mock the context object.
ctx = mockContext()
})
afterEach(() => sandbox.restore())
describe('#constructor', () => {
it('should throw an error if adapters are not passed in', () => {
try {
uut = new IpfsApiController()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(
err.message,
'Instance of Adapters library required when instantiating /ipfs REST Controller.'
)
}
})
it('should throw an error if useCases are not passed in', () => {
try {
uut = new IpfsApiController({ adapters })
assert.fail('Unexpected code path')
} catch (err) {
assert.include(
err.message,
'Instance of Use Cases library required when instantiating /ipfs REST Controller.'
)
}
})
})
describe('#GET /status', () => {
it('should return 422 status on biz logic error', async () => {
try {
// Force an error
sandbox.stub(uut.adapters.ipfs, 'getStatus').rejects(new Error('test error'))
await uut.getStatus(ctx)
assert.fail('Unexpected result')
} catch (err) {
assert.equal(err.status, 422)
assert.include(err.message, 'test error')
}
})
it('should return 200 status on success', async () => {
// Mock dependencies
sandbox.stub(uut.adapters.ipfs, 'getStatus').resolves({ a: 'b' })
await uut.getStatus(ctx)
// console.log('ctx.body: ', ctx.body)
assert.property(ctx.body, 'status')
assert.equal(ctx.body.status.a, 'b')
})
})
describe('#POST /peers', () => {
it('should return 422 status on biz logic error', async () => {
try {
// Force an error
sandbox.stub(uut.adapters.ipfs, 'getPeers').rejects(new Error('test error'))
ctx.request.body = {
showAll: true
}
await uut.getPeers(ctx)
assert.fail('Unexpected result')
} catch (err) {
assert.equal(err.status, 422)
assert.include(err.message, 'test error')
}
})
it('should return 200 status on success', async () => {
// Mock dependencies
sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves({ a: 'b' })
ctx.request.body = {
showAll: true
}
await uut.getPeers(ctx)
// console.log('ctx.body: ', ctx.body)
assert.property(ctx.body, 'peers')
assert.equal(ctx.body.peers.a, 'b')
})
})
describe('#POST /relays', () => {
it('should return 422 status on biz logic error', async () => {
try {
// Force an error
sandbox.stub(uut.adapters.ipfs, 'getRelays').rejects(new Error('test error'))
await uut.getRelays(ctx)
assert.fail('Unexpected result')
} catch (err) {
assert.equal(err.status, 422)
assert.include(err.message, 'test error')
}
})
it('should return 200 status on success', async () => {
// Mock dependencies
sandbox.stub(uut.adapters.ipfs, 'getRelays').resolves({ a: 'b' })
await uut.getRelays(ctx)
// console.log('ctx.body: ', ctx.body)
assert.property(ctx.body, 'relays')
assert.equal(ctx.body.relays.a, 'b')
})
})
describe('#POST /connect', () => {
it('should return 422 status on biz logic error', async () => {
try {
// Force an error
sandbox.stub(uut.adapters.ipfs.ipfsCoordAdapter.ipfsCoord.adapters.ipfs, 'connectToPeer').rejects(new Error('test error'))
ctx.request.body = {
multiaddr: '/ip4/161.35.99.207/tcp/4001/p2p/12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu'
}
await uut.connect(ctx)
assert.fail('Unexpected result')
} catch (err) {
assert.equal(err.status, 422)
assert.include(err.message, 'test error')
}
})
it('should return 200 status on success', async () => {
// Mock dependencies
sandbox.stub(uut.adapters.ipfs.ipfsCoordAdapter.ipfsCoord.adapters.ipfs, 'connectToPeer').resolves({ success: true })
ctx.request.body = {
multiaddr: '/ip4/161.35.99.207/tcp/4001/p2p/12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu'
}
await uut.connect(ctx)
// console.log('ctx.body: ', ctx.body)
assert.property(ctx.body, 'success')
assert.equal(ctx.body.success, true)
})
})
describe('#handleError', () => {
it('should still throw error if there is no message', () => {
try {
const err = {
status: 404
}
uut.handleError(ctx, err)
} catch (err) {
assert.include(err.message, 'Not Found')
}
})
it('should throw error with message', () => {
try {
const err = {
status: 422,
message: 'test error'
}
uut.handleError(ctx, err)
} catch (err) {
assert.include(err.message, 'test error')
}
})
})
describe('#getThisNode', () => {
it('should return 422 status on biz logic error', async () => {
try {
// Force an error
// sandbox.stub(uut.adapters.ipfs.ipfsCoordAdapter.ipfsCoord, 'thisNode').rejects(new Error('test error'))
uut.adapters.ipfs.ipfsCoordAdapter = {}
ctx.request.body = {}
await uut.getThisNode(ctx)
assert.fail('Unexpected result')
} catch (err) {
// console.log('err: ', err)
assert.equal(err.status, 422)
assert.include(err.message, 'Cannot read')
}
})
it('should return 200 status on success', async () => {
// Mock dependencies
// sandbox.stub(uut.adapters.ipfs.ipfsCoordAdapter.ipfsCoord.adapters.ipfs, 'connectToPeer').resolves({ success: true })
uut.adapters.ipfs.ipfsCoordAdapter = {
ipfsCoord: {
thisNode: {}
}
}
ctx.request.body = {}
await uut.getThisNode(ctx)
assert.property(ctx.body, 'thisNode')
})
})
})
@@ -0,0 +1,78 @@
/*
Unit tests for the REST API handler for the /ipfs endpoints.
*/
// Public npm libraries
import { assert } from 'chai'
import sinon from 'sinon'
// Local support libraries
import adapters from '../../../mocks/adapters/index.js'
import UseCasesMock from '../../../mocks/use-cases/index.js'
import IpfsRouter from '../../../../../src/controllers/rest-api/ipfs/index.js'
// const app = require('../../../mocks/app-mock')
let uut
let sandbox
// let ctx
// const mockContext = require('../../../../unit/mocks/ctx-mock').context
describe('#IPFS-REST-Router', () => {
// const testUser = {}
beforeEach(() => {
const useCases = new UseCasesMock()
uut = new IpfsRouter({ adapters, useCases })
sandbox = sinon.createSandbox()
// Mock the context object.
// ctx = mockContext()
})
afterEach(() => sandbox.restore())
describe('#constructor', () => {
it('should throw an error if adapters are not passed in', () => {
try {
uut = new IpfsRouter()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(
err.message,
'Instance of Adapters library required when instantiating IPFS REST Controller.'
)
}
})
it('should throw an error if useCases are not passed in', () => {
try {
uut = new IpfsRouter({ adapters })
assert.fail('Unexpected code path')
} catch (err) {
assert.include(
err.message,
'Instance of Use Cases library required when instantiating IPFS REST Controller.'
)
}
})
})
describe('#attach', () => {
it('should throw an error if app is not passed in.', () => {
try {
uut.attach()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(
err.message,
'Must pass app object when attaching REST API controllers.'
)
}
})
})
})
@@ -0,0 +1,82 @@
/*
Unit tests for the timer-controller.js Controller library
*/
// Public npm libraries
import { assert } from 'chai'
import sinon from 'sinon'
// Local libraries
import TimerControllers from '../../../src/controllers/timer-controllers.js'
import adapters from '../mocks/adapters/index.js'
import UseCasesMock from '../mocks/use-cases/index.js'
describe('#Timer-Controllers', () => {
let uut
let sandbox
beforeEach(() => {
sandbox = sinon.createSandbox()
const useCases = new UseCasesMock()
uut = new TimerControllers({ adapters, useCases })
})
afterEach(() => {
sandbox.restore()
uut.stopTimers()
})
describe('#constructor', () => {
it('should throw an error if adapters are not passed in', () => {
try {
uut = new TimerControllers()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(
err.message,
'Instance of Adapters library required when instantiating Timer Controller libraries.'
)
}
})
it('should throw an error if useCases are not passed in', () => {
try {
uut = new TimerControllers({ adapters })
assert.fail('Unexpected code path')
} catch (err) {
assert.include(
err.message,
'Instance of Use Cases library required when instantiating Timer Controller libraries.'
)
}
})
})
// describe('#startTimers', () => {
// it('should start the timers', () => {
// const result = uut.startTimers()
//
// // uut.stopTimers()
//
// assert.equal(result, true)
// })
// })
// describe('#exampleTimerFunc', () => {
// it('should kick off the Use Case', async () => {
// const result = await uut.exampleTimerFunc()
//
// assert.equal(result, true)
// })
//
// it('should return false on error', async () => {
// const result = await uut.exampleTimerFunc(true)
//
// assert.equal(result, false)
// })
// })
})
+5 -1
View File
@@ -40,9 +40,13 @@ describe('#config', () => {
assert.equal(config.env, 'test')
})
it('Should return test environment config', async () => {
it('Should return prod environment config', async () => {
process.env.BCH_DEX = 'prod'
process.env.WALLET_INTERFACE = 'web2'
process.env.APISERVER = 'https://api.fullstack.cash/v5/'
await import('../../../config/env/common.js?foo=bar2')
const importedConfig3 = await import('../../../config/index.js?foo=bar2')
const config = importedConfig3.default
// console.log('config: ', config)
+11 -2
View File
@@ -18,19 +18,28 @@ class IpfsAdapter {
class IpfsCoordAdapter {
constructor () {
this.ipfsCoord = {
adapters: {
ipfs: {
connectToPeer: async () => {}
}
},
useCases: {
peer: {
sendPrivateMessage: () => {
}
}
}
},
thisNode: {}
}
}
}
const ipfs = {
ipfsAdapter: new IpfsAdapter(),
ipfsCoordAdapter: new IpfsCoordAdapter()
ipfsCoordAdapter: new IpfsCoordAdapter(),
getStatus: async () => {},
getPeers: async () => {},
getRelays: async () => {}
}
ipfs.ipfs = ipfs.ipfsAdapter.ipfs
+141 -139
View File
@@ -1,147 +1,149 @@
/*
Mock data for the wallet.adapter.unit.js test file.
*/
import BCHJS from '@psf/bch-js';
import BCHJS from "@psf/bch-js";
const mockWallet = {
mnemonic: 'course abstract aerobic deer try switch turtle diet fence affair butter top',
privateKey: 'L5D2UAam8tvo3uii5kpgaGyjvVMimdrXu8nWGQSQjuuAix6ji1YQ',
publicKey: '0379433ffc401483ade310469953c1cba77c71af904f07c15bde330d7198b4d6dc',
cashAddress: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
address: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
slpAddress: 'simpleledger:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acq9zm7d33',
legacyAddress: '1JQj1KcQL7GPKzc1D2PvdUSgw3MbDtrHzi',
hdPath: "m/44'/245'/0'/0/0",
nextAddress: 1
}
mnemonic: 'course abstract aerobic deer try switch turtle diet fence affair butter top',
privateKey: 'L5D2UAam8tvo3uii5kpgaGyjvVMimdrXu8nWGQSQjuuAix6ji1YQ',
publicKey: '0379433ffc401483ade310469953c1cba77c71af904f07c15bde330d7198b4d6dc',
cashAddress: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
address: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
slpAddress: 'simpleledger:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acq9zm7d33',
legacyAddress: '1JQj1KcQL7GPKzc1D2PvdUSgw3MbDtrHzi',
hdPath: "m/44'/245'/0'/0/0",
nextAddress: 1
};
class MockBchWallet {
constructor () {
this.walletInfoPromise = true
this.walletInfo = mockWallet
this.bchjs = new BCHJS()
this.burnTokens = async () => {
return { success: true, txid: 'txid' }
}
this.sendTokens = async () => {
return 'fakeTxid'
}
this.getUtxos = async () => {
}
this.getTxData = async () => {
return [{
tokenTicker: 'TROUT'
}]
}
this.getTokenData = async () => {}
this.initialize = async () => {}
this.utxoIsValid = async () => {}
this.optimize = async () => {}
// Environment variable is used by wallet-balance.unit.js to force an error.
if (process.env.NO_UTXO) {
this.utxos = {}
} else {
this.utxos = {
utxoStore: {
address: 'bitcoincash:qqetvdnlt0p8g27dr44cx7h057kpzly9xse9huc97z',
bchUtxos: [
{
height: 700685,
tx_hash: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654',
tx_pos: 0,
value: 1000,
txid: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654',
vout: 0,
isValid: false
},
{
height: 700685,
tx_hash: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654',
tx_pos: 2,
value: 19406,
txid: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654',
vout: 2,
isValid: false
}
],
nullUtxos: [],
slpUtxos: {
type1: {
mintBatons: [],
tokens: [
{
'height': 717331,
'tx_hash': '74889580bb1a5f8c026aa2f55118ac9917df3332f7abae72a70343daa1c29621',
'tx_pos': 1,
'value': 546,
'txid': '74889580bb1a5f8c026aa2f55118ac9917df3332f7abae72a70343daa1c29621',
'vout': 1,
'isSlp': true,
'type': 'token',
'qty': '10',
'tokenId': '600ee24d0f208aebc2bdd2c4ee1b9acb6d57343561442e8676b5bbea311d5a0f',
'address': 'bitcoincash:qqraj35x6l2qyqhjm5l7qlt7z2245ez8l5z3dwkeq5',
'ticker': 'FLIPS',
'name': 'FLIPS',
'documentUri': '',
'documentHash': '',
'decimals': 1,
'qtyStr': '1'
},
{
'height': 730597,
'tx_hash': '52520faddfafc46b8f8c9548b097f3a3b82a5bf363b5095047b9c5f83247fe36',
'tx_pos': 1,
'value': 546,
'txid': '52520faddfafc46b8f8c9548b097f3a3b82a5bf363b5095047b9c5f83247fe36',
'vout': 1,
'isSlp': true,
'type': 'token',
'qty': '34999991',
'tokenId': '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0',
'address': 'bitcoincash:qqraj35x6l2qyqhjm5l7qlt7z2245ez8l5z3dwkeq5',
'ticker': 'PSF',
'name': 'Permissionless Software Foundation',
'documentUri': 'psfoundation.cash',
'documentHash': '',
'decimals': 8,
'qtyStr': '0.34999991'
},
{
'height': 730597,
'tx_hash': '5dc7e7c91382aed1666a51212dfb74050261e12c3c4f62b6b1e57f42d6c51ee1',
'tx_pos': 2,
'value': 546,
'txid': '5dc7e7c91382aed1666a51212dfb74050261e12c3c4f62b6b1e57f42d6c51ee1',
'vout': 2,
'isSlp': true,
'type': 'token',
'qty': '18898',
'tokenId': 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2',
'address': 'bitcoincash:qqraj35x6l2qyqhjm5l7qlt7z2245ez8l5z3dwkeq5',
'ticker': 'TROUT',
'name': "Trout's test token",
'documentUri': 'troutsblog.com',
'documentHash': '',
'decimals': 2,
'qtyStr': '188.98'
}
]
},
nft: {
tokens: []
},
group: {
tokens: [],
mintBatons: []
}
}
constructor() {
this.walletInfoPromise = true;
this.walletInfo = mockWallet;
this.initialize = async () => {}
this.bchjs = new BCHJS();
this.burnTokens = async () => {
return { success: true, txid: 'txid' };
};
this.sendTokens = async () => {
return 'fakeTxid';
};
this.getUtxos = async () => { };
this.getBalance = async () => { };
this.listTokens = async () => { };
this.getTxData = async () => {
return [{
tokenTicker: 'TROUT'
}];
};
this.optimize = async () => { };
// Environment variable is used by wallet-balance.unit.js to force an error.
if (process.env.NO_UTXO) {
this.utxos = {};
}
else {
this.utxos = {
utxoStore: {
address: 'bitcoincash:qqetvdnlt0p8g27dr44cx7h057kpzly9xse9huc97z',
bchUtxos: [
{
height: 700685,
tx_hash: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654',
tx_pos: 0,
value: 1000,
txid: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654',
vout: 0,
isValid: false
},
{
height: 700685,
tx_hash: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654',
tx_pos: 2,
value: 19406,
txid: '1fc577caaff5626a8477162581e57bae1b19dc6aa6c10638013c2b1ba14dc654',
vout: 2,
isValid: false
}
],
nullUtxos: [],
slpUtxos: {
type1: {
mintBatons: [],
tokens: [
{
'height': 717331,
'tx_hash': '74889580bb1a5f8c026aa2f55118ac9917df3332f7abae72a70343daa1c29621',
'tx_pos': 1,
'value': 546,
'txid': '74889580bb1a5f8c026aa2f55118ac9917df3332f7abae72a70343daa1c29621',
'vout': 1,
'isSlp': true,
'type': 'token',
'qty': '10',
'tokenId': '600ee24d0f208aebc2bdd2c4ee1b9acb6d57343561442e8676b5bbea311d5a0f',
'address': 'bitcoincash:qqraj35x6l2qyqhjm5l7qlt7z2245ez8l5z3dwkeq5',
'ticker': 'FLIPS',
'name': 'FLIPS',
'documentUri': '',
'documentHash': '',
'decimals': 1,
'qtyStr': '1'
},
{
'height': 730597,
'tx_hash': '52520faddfafc46b8f8c9548b097f3a3b82a5bf363b5095047b9c5f83247fe36',
'tx_pos': 1,
'value': 546,
'txid': '52520faddfafc46b8f8c9548b097f3a3b82a5bf363b5095047b9c5f83247fe36',
'vout': 1,
'isSlp': true,
'type': 'token',
'qty': '34999991',
'tokenId': '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0',
'address': 'bitcoincash:qqraj35x6l2qyqhjm5l7qlt7z2245ez8l5z3dwkeq5',
'ticker': 'PSF',
'name': 'Permissionless Software Foundation',
'documentUri': 'psfoundation.cash',
'documentHash': '',
'decimals': 8,
'qtyStr': '0.34999991'
},
{
'height': 730597,
'tx_hash': '5dc7e7c91382aed1666a51212dfb74050261e12c3c4f62b6b1e57f42d6c51ee1',
'tx_pos': 2,
'value': 546,
'txid': '5dc7e7c91382aed1666a51212dfb74050261e12c3c4f62b6b1e57f42d6c51ee1',
'vout': 2,
'isSlp': true,
'type': 'token',
'qty': '18898',
'tokenId': 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2',
'address': 'bitcoincash:qqraj35x6l2qyqhjm5l7qlt7z2245ez8l5z3dwkeq5',
'ticker': 'TROUT',
'name': "Trout's test token",
'documentUri': 'troutsblog.com',
'documentHash': '',
'decimals': 2,
'qtyStr': '188.98'
}
]
},
nft: {
tokens: []
},
group: {
tokens: [],
mintBatons: []
}
}
}
};
}
}
}
}
}
export { MockBchWallet, mockWallet};
export { MockBchWallet };
export { mockWallet };
export default {
MockBchWallet,
mockWallet
};
+13
View File
@@ -0,0 +1,13 @@
/*
Mocking library for helia.
This is used to replace the helia library when running unit tests.
*/
const ipfs = {
libp2p: {
getMultiaddrs: () => [],
peerId: 'fake-id'
}
}
export default ipfs
+69 -69
View File
@@ -51,76 +51,76 @@ describe('#offer-use-case', () => {
})
describe('#createOffer', () => {
it('should ignore an offer if utxo has been spent', async () => {
const offerObj = {
appId: 'swapTest555',
data: {
messageType: 1,
messageClass: 1,
tokenId:
'38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0',
buyOrSell: 'sell',
rateInSats: 1000,
minSatsToExchange: 10,
numTokens: 0.02,
utxoTxid:
'241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87',
utxoVout: 0
},
timestamp: '2021-09-20T17:54:26.395Z',
localTimeStamp: '9/20/2021, 10:54:26 AM',
txid: '46f50f2a0cf44e3ed70dfb0618ef3ebfee57aabcf229b5d2d17c07322b54a8d7',
hash: 'zdpuB2X25AZCKo3wpr4sSbw44vqPWJRqcxWQRHZccK5BdtoGD'
}
// it('should ignore an offer if utxo has been spent', async () => {
// const offerObj = {
// appId: 'swapTest555',
// data: {
// messageType: 1,
// messageClass: 1,
// tokenId:
// '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0',
// buyOrSell: 'sell',
// rateInSats: 1000,
// minSatsToExchange: 10,
// numTokens: 0.02,
// utxoTxid:
// '241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87',
// utxoVout: 0
// },
// timestamp: '2021-09-20T17:54:26.395Z',
// localTimeStamp: '9/20/2021, 10:54:26 AM',
// txid: '46f50f2a0cf44e3ed70dfb0618ef3ebfee57aabcf229b5d2d17c07322b54a8d7',
// hash: 'zdpuB2X25AZCKo3wpr4sSbw44vqPWJRqcxWQRHZccK5BdtoGD'
// }
//
// // Mock dependencies
// // sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').resolves(false)
// sandbox.stub(uut.adapters.wallet.bchWallet, 'getTokenData').resolves({})
// sandbox.stub(uut, 'categorizeToken').resolves('nft')
// sandbox.stub(uut, 'detectNsfw').resolves(false)
//
// const result = await uut.createOffer(offerObj)
// // console.log('result: ', result)
//
// assert.equal(result, false)
// })
// Mock dependencies
sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').resolves(false)
sandbox.stub(uut.adapters.wallet.bchWallet, 'getTokenData').resolves({})
sandbox.stub(uut, 'categorizeToken').resolves('nft')
sandbox.stub(uut, 'detectNsfw').resolves(false)
const result = await uut.createOffer(offerObj)
// console.log('result: ', result)
assert.equal(result, false)
})
it('should create an offer and return the hash', async () => {
const offerObj = {
appId: 'swapTest555',
data: {
messageType: 1,
messageClass: 1,
tokenId:
'38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0',
buyOrSell: 'sell',
rateInBaseUnit: 1000,
minUnitsToExchange: 10,
numTokens: 0.02,
utxoTxid:
'241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87',
utxoVout: 0,
makerAddr: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
ticker: 'TROUT',
tokenType: 1
},
timestamp: '2021-09-20T17:54:26.395Z',
localTimeStamp: '9/20/2021, 10:54:26 AM',
txid: '46f50f2a0cf44e3ed70dfb0618ef3ebfee57aabcf229b5d2d17c07322b54a8d7',
hash: 'zdpuB2X25AZCKo3wpr4sSbw44vqPWJRqcxWQRHZccK5BdtoGD'
}
// Mock dependencies
sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').resolves(true)
sandbox.stub(uut, 'categorizeToken').resolves('fungible')
sandbox.stub(uut.adapters.wallet.bchWallet, 'getTokenData').resolves({})
sandbox.stub(uut, 'detectNsfw').resolves(false)
const result = await uut.createOffer(offerObj)
// console.log('result: ', result)
assert.equal(result, true)
})
// it('should create an offer and return the hash', async () => {
// const offerObj = {
// appId: 'swapTest555',
// data: {
// messageType: 1,
// messageClass: 1,
// tokenId:
// '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0',
// buyOrSell: 'sell',
// rateInBaseUnit: 1000,
// minUnitsToExchange: 10,
// numTokens: 0.02,
// utxoTxid:
// '241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87',
// utxoVout: 0,
// makerAddr: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
// ticker: 'TROUT',
// tokenType: 1
// },
// timestamp: '2021-09-20T17:54:26.395Z',
// localTimeStamp: '9/20/2021, 10:54:26 AM',
// txid: '46f50f2a0cf44e3ed70dfb0618ef3ebfee57aabcf229b5d2d17c07322b54a8d7',
// hash: 'zdpuB2X25AZCKo3wpr4sSbw44vqPWJRqcxWQRHZccK5BdtoGD'
// }
//
// // Mock dependencies
// // sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').resolves(true)
// sandbox.stub(uut, 'categorizeToken').resolves('fungible')
// sandbox.stub(uut.adapters.wallet.bchWallet, 'getTokenData').resolves({})
// sandbox.stub(uut, 'detectNsfw').resolves(false)
//
// const result = await uut.createOffer(offerObj)
// // console.log('result: ', result)
//
// assert.equal(result, true)
// })
})
describe('#categorizeToken', () => {