mirror of
https://github.com/Permissionless-Software-Foundation/bch-dex.git
synced 2026-09-21 16:52:00 -07:00
feat(tests): Improved adapters test coverage
This commit is contained in:
@@ -66,6 +66,9 @@ class Bch {
|
||||
// }
|
||||
// }
|
||||
|
||||
/** DEV NOTE: This function are deprecated.?
|
||||
* https://github.com/Permissionless-Software-Foundation/bch-message-lib/pull/41
|
||||
*/
|
||||
async getMerit (slpAddr) {
|
||||
try {
|
||||
if (!slpAddr || typeof slpAddr !== 'string') {
|
||||
|
||||
+28
-3
@@ -34,6 +34,7 @@ class WalletAdapter {
|
||||
this.config = config
|
||||
this.bitcoinJs = bitcoinJs
|
||||
this.BchWallet = BchWallet
|
||||
this.BchTokenSweep = BchTokenSweep
|
||||
this.bchWallet = {} // Will be replaced when initialized.
|
||||
// this.advancedConfig = localConfig.advancedConfig
|
||||
this.retryQueue = new RetryQueue({
|
||||
@@ -205,7 +206,9 @@ class WalletAdapter {
|
||||
// Generate a cryptographic signature, required to write to the P2WDB.
|
||||
async generateSignature (message) {
|
||||
try {
|
||||
// TODO: Add input validation for message.
|
||||
if (!message || typeof message !== 'string') {
|
||||
throw new Error('message is required!')
|
||||
}
|
||||
|
||||
const privKey = this.bchWallet.walletInfo.privateKey
|
||||
|
||||
@@ -370,6 +373,12 @@ class WalletAdapter {
|
||||
async moveTokens (inObj = {}) {
|
||||
try {
|
||||
const { tokenId, qty } = inObj
|
||||
if (!tokenId || typeof tokenId !== 'string') {
|
||||
throw new Error('tokenId must be a string!')
|
||||
}
|
||||
if (!qty || typeof qty !== 'number') {
|
||||
throw new Error('qty must be a number!')
|
||||
}
|
||||
|
||||
const keyPair = await this.getKeyPair()
|
||||
console.log('keyPair: ', keyPair)
|
||||
@@ -392,6 +401,10 @@ class WalletAdapter {
|
||||
x => x.tokenId === tokenId
|
||||
)
|
||||
|
||||
if (tokenUtxos.length === 0) {
|
||||
throw new Error('tokenId not found!')
|
||||
}
|
||||
|
||||
const txid = await this.bchWallet.sendTokens(receiver, 3)
|
||||
|
||||
const utxoInfo = {
|
||||
@@ -412,6 +425,10 @@ class WalletAdapter {
|
||||
// generate a segregated UTXO.
|
||||
async moveBch (amountSat) {
|
||||
try {
|
||||
if (!amountSat) {
|
||||
throw new Error('amountSat is required!')
|
||||
}
|
||||
|
||||
const keyPair = await this.getKeyPair()
|
||||
console.log('keyPair: ', keyPair)
|
||||
|
||||
@@ -444,6 +461,10 @@ class WalletAdapter {
|
||||
// representing the transaction.
|
||||
async deseralizeTx (txHex) {
|
||||
try {
|
||||
// Input validation
|
||||
if (!txHex || typeof txHex !== 'string') {
|
||||
throw new Error('hex must be a string!')
|
||||
}
|
||||
// Ensure the URL points at FullStack.cash, since the web 3 infra does not
|
||||
// yet support this call.
|
||||
const oldUrl = this.bchWallet.bchjs.RawTransactions.restURL
|
||||
@@ -555,8 +576,12 @@ class WalletAdapter {
|
||||
|
||||
// Given an Order database object, this function sends the tokens from the
|
||||
// HD index where they are stored, back to the root address of the wallet.
|
||||
async reclaimTokens (orderData) {
|
||||
async reclaimTokens (orderData = {}) {
|
||||
try {
|
||||
if (!orderData.hdIndex) {
|
||||
throw new Error('orderData.hdIndex is required!')
|
||||
}
|
||||
|
||||
// Get the key pair from the Order.
|
||||
const keyPair = await this.getKeyPair(orderData.hdIndex)
|
||||
console.log('keyPair: ', keyPair)
|
||||
@@ -576,7 +601,7 @@ class WalletAdapter {
|
||||
// const txid = await tempWallet.sendTokens(receiver)
|
||||
|
||||
// Sweep the tokens to the root address.
|
||||
const sweeper = new BchTokenSweep(
|
||||
const sweeper = new this.BchTokenSweep(
|
||||
keyPair.wif,
|
||||
this.bchWallet.walletInfo.privateKey,
|
||||
this.bchWallet,
|
||||
|
||||
+14
-12
@@ -6,13 +6,15 @@ import config from '../../config/index.js'
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
let _this
|
||||
|
||||
class WebHook {
|
||||
constructor () {
|
||||
_this = this
|
||||
_this.config = config
|
||||
_this.axios = axios
|
||||
this.config = config
|
||||
this.axios = axios
|
||||
this.sleepTime = 2000
|
||||
this.createWebhook = this.createWebhook.bind(this)
|
||||
this.deleteWebhook = this.deleteWebhook.bind(this)
|
||||
this.waitUntilSuccess = this.waitUntilSuccess.bind(this)
|
||||
this.sleep = this.sleep.bind(this)
|
||||
}
|
||||
|
||||
// REST petition to create a webhook in p2wdb-service
|
||||
@@ -22,14 +24,14 @@ class WebHook {
|
||||
throw new Error('url must be a string')
|
||||
}
|
||||
|
||||
const endpoint = _this.config.webhookService
|
||||
const endpoint = this.config.webhookService
|
||||
|
||||
const obj = {
|
||||
appId: this.config.p2wdbAppId,
|
||||
url
|
||||
}
|
||||
|
||||
const result = await axios.post(endpoint, obj)
|
||||
const result = await this.axios.post(endpoint, obj)
|
||||
|
||||
return result.data
|
||||
} catch (err) {
|
||||
@@ -45,14 +47,14 @@ class WebHook {
|
||||
throw new Error('url must be a string')
|
||||
}
|
||||
|
||||
const endpoint = _this.config.webhookService
|
||||
const endpoint = this.config.webhookService
|
||||
|
||||
const obj = {
|
||||
appId: this.config.p2wdbAppId,
|
||||
url
|
||||
}
|
||||
|
||||
const result = await axios.delete(endpoint, { data: obj })
|
||||
const result = await this.axios.delete(endpoint, { data: obj })
|
||||
|
||||
return result.data
|
||||
} catch (err) {
|
||||
@@ -86,7 +88,7 @@ class WebHook {
|
||||
} catch (err) {
|
||||
const now = new Date()
|
||||
console.log(`${now.toLocaleString()}: Error trying to create webhook with P2WDB. Trying again...`)
|
||||
await sleep(2000)
|
||||
await this.sleep(this.sleepTime)
|
||||
}
|
||||
} while (!success)
|
||||
|
||||
@@ -96,10 +98,10 @@ class WebHook {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sleep (ms) {
|
||||
async sleep (ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
||||
}
|
||||
|
||||
export default WebHook
|
||||
|
||||
@@ -24,19 +24,18 @@ describe('#adapters', () => {
|
||||
})
|
||||
|
||||
describe('#start', () => {
|
||||
// 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()
|
||||
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.wallet, 'instanceWallet').resolves()
|
||||
sandbox.stub(uut.ipfs, 'start').resolves()
|
||||
|
||||
// const result = await uut.start()
|
||||
const result = await uut.start()
|
||||
|
||||
// assert.equal(result, true)
|
||||
// })
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should not start ipfs on test enviroment', async () => {
|
||||
// Mock dependencies
|
||||
|
||||
@@ -135,18 +135,19 @@ describe('bch', () => {
|
||||
}
|
||||
})
|
||||
|
||||
// it('should return the merit ', async () => {
|
||||
// try {
|
||||
// // Mock live network calls.
|
||||
// sandbox.stub(uut.msgLib.merit, 'agMerit').resolves(100)
|
||||
//
|
||||
// const slpAddr =
|
||||
// 'simpleledger:qqgnksc6zr4nzxrye69fq625wu2myxey6uh9kzjy96'
|
||||
// const merit = await uut.getMerit(slpAddr)
|
||||
// assert.isNumber(merit)
|
||||
// } catch (err) {
|
||||
// assert.fail('Unexpected result')
|
||||
// }
|
||||
// })
|
||||
/* it('should return the merit ', async () => {
|
||||
try {
|
||||
// Mock live network calls.
|
||||
sandbox.stub(uut.msgLib.merit, 'agMerit').resolves(100)
|
||||
|
||||
const slpAddr =
|
||||
'simpleledger:qqgnksc6zr4nzxrye69fq625wu2myxey6uh9kzjy96'
|
||||
const merit = await uut.getMerit(slpAddr)
|
||||
assert.isNumber(merit)
|
||||
} catch (err) {
|
||||
console.log('err: ', err)
|
||||
assert.fail('Unexpected result')
|
||||
}
|
||||
}) */
|
||||
})
|
||||
})
|
||||
|
||||
@@ -128,4 +128,100 @@ describe('#nostr.js', () => {
|
||||
assert.equal(result.length, 1)
|
||||
})
|
||||
})
|
||||
describe('#eventId2note', () => {
|
||||
it('should handle encode error', async () => {
|
||||
try {
|
||||
await uut.eventId2note('invalid format')
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log('err: ', err)
|
||||
assert.include(err.message, 'Invalid byte sequence')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle valid eventId', async () => {
|
||||
const result = await uut.eventId2note('b1e4a3d5e40b6d0b3f1e2c234b6c9dbf4d6a80e9b3e8a2d765c7f9ed84c9a5ef')
|
||||
assert.isString(result)
|
||||
assert.include(result, 'note')
|
||||
})
|
||||
})
|
||||
describe('#pubkey2npub', () => {
|
||||
it('should handle encode error', async () => {
|
||||
try {
|
||||
await uut.pubkey2npub('invalid format')
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log('err: ', err)
|
||||
assert.include(err.message, 'Invalid byte sequence')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle valid pubkey', async () => {
|
||||
const result = await uut.pubkey2npub('f5a1b39d2cfae8e10e93b9b4d7ec8248eaf45fbe4a73409d8d4c67015e9729a3')
|
||||
assert.isString(result)
|
||||
assert.include(result, 'npub')
|
||||
})
|
||||
})
|
||||
describe('#npub2pubkey', () => {
|
||||
it('should handle decode error', async () => {
|
||||
try {
|
||||
await uut.npub2pubkey('npub17ksm88fvlt5wzr5nhx6d0myzfr40g')
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log('err: ', err)
|
||||
assert.include(err.message, 'Invalid checksum')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle valid pubkey', async () => {
|
||||
const result = await uut.npub2pubkey('npub17ksm88fvlt5wzr5nhx6d0myzfr40gha7ffe5p8vdf3nszh5h9x3sdwl7u2')
|
||||
assert.isObject(result)
|
||||
assert.property(result, 'type')
|
||||
assert.property(result, 'data')
|
||||
assert.equal(result.type, 'npub')
|
||||
assert.equal(result.data.length, 64)
|
||||
})
|
||||
})
|
||||
describe('#readGlobalFeed', () => {
|
||||
it('should throw an error if provided limit is wrong', async () => {
|
||||
try {
|
||||
await uut.readGlobalFeed({ limit: -5 })
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log('err: ', err)
|
||||
assert.include(err.message, 'Limit must be greater than 0')
|
||||
}
|
||||
})
|
||||
|
||||
it('should read message', async () => {
|
||||
const result = await uut.readGlobalFeed()
|
||||
assert.isArray(result)
|
||||
})
|
||||
|
||||
it('should read message with custom limit', async () => {
|
||||
const result = await uut.readGlobalFeed({ limit: 1 })
|
||||
assert.isArray(result)
|
||||
})
|
||||
})
|
||||
describe('#getFollowers', () => {
|
||||
it('should throw an error if no pubkey is provided', async () => {
|
||||
try {
|
||||
await uut.getFollowers()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log('err: ', err)
|
||||
assert.include(err.message, 'pubkey must be a string!')
|
||||
}
|
||||
})
|
||||
|
||||
it('should get followers', async () => {
|
||||
const result = await uut.getFollowers({ pubkey: 'f5a1b39d2cfae8e10e93b9b4d7ec8248eaf45fbe4a73409d8d4c67015e9729a3' })
|
||||
assert.isArray(result)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -9,14 +9,46 @@ import sinon from 'sinon'
|
||||
|
||||
import WalletAdapter from '../../../src/adapters/wallet.js'
|
||||
import { MockBchWallet } from '../mocks/adapters/wallet.js'
|
||||
import { BchTokenSweepMock } from '../mocks/bch-token-sweep-mock.js'
|
||||
import offerMockData from '../mocks/use-cases/offer-mock-data.js'
|
||||
import fs from 'fs'
|
||||
import * as url from 'url'
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||
|
||||
const testWalletFile = `${__dirname.toString()}/../../../test-wallet.json`
|
||||
|
||||
describe('#wallet', () => {
|
||||
let uut
|
||||
let sandbox
|
||||
let testWalletData
|
||||
|
||||
before(() => {
|
||||
// try to remove the test wallet file
|
||||
try {
|
||||
fs.unlinkSync(testWalletFile)
|
||||
} catch (error) {
|
||||
console.log('error fsUnlinkSync: ', error)
|
||||
|
||||
// silently fail
|
||||
}
|
||||
})
|
||||
after(() => {
|
||||
// try to remove the test wallet file
|
||||
try {
|
||||
fs.unlinkSync(testWalletFile)
|
||||
} catch (error) {
|
||||
console.log('error fsUnlinkSync: ', error)
|
||||
// silently fail
|
||||
}
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
uut = new WalletAdapter()
|
||||
uut.BchWallet = MockBchWallet
|
||||
uut.bchWallet = new MockBchWallet()
|
||||
uut.BchTokenSweep = BchTokenSweepMock
|
||||
uut.WALLET_FILE = testWalletFile
|
||||
uut.bitcoinJs = {
|
||||
Transaction: {
|
||||
fromHex: () => { return {} },
|
||||
@@ -34,6 +66,278 @@ describe('#wallet', () => {
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe('#openWallet', () => {
|
||||
it('should create a new wallet when wallet file does not exist', async () => {
|
||||
// Ensure we open the test file, not the production wallet file.
|
||||
const result = await uut.openWallet()
|
||||
testWalletData = result
|
||||
// console.log('result: ', result)
|
||||
assert.property(result, 'mnemonic')
|
||||
assert.property(result, 'privateKey')
|
||||
assert.property(result, 'publicKey')
|
||||
assert.property(result, 'cashAddress')
|
||||
assert.property(result, 'address')
|
||||
assert.property(result, 'slpAddress')
|
||||
assert.property(result, 'legacyAddress')
|
||||
assert.property(result, 'hdPath')
|
||||
})
|
||||
|
||||
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.
|
||||
const result = await uut.openWallet()
|
||||
// console.log('result: ', result)
|
||||
assert.property(result, 'mnemonic')
|
||||
assert.property(result, 'privateKey')
|
||||
assert.property(result, 'publicKey')
|
||||
assert.property(result, 'cashAddress')
|
||||
assert.property(result, 'address')
|
||||
assert.property(result, 'slpAddress')
|
||||
assert.property(result, 'legacyAddress')
|
||||
assert.property(result, 'hdPath')
|
||||
})
|
||||
|
||||
it('should catch and throw an error', async () => {
|
||||
try {
|
||||
uut.WALLET_FILE = ''
|
||||
// Force an error
|
||||
uut.BchWallet = () => {
|
||||
}
|
||||
await uut.openWallet()
|
||||
// console.log('result: ', result)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log('err: ', err)
|
||||
assert.include(err.message, 'this.BchWallet is not a constructor')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#instanceWallet', () => {
|
||||
it('should create an instance of BchWallet with rest-api', async () => {
|
||||
uut.config.useFullStackCash = true
|
||||
const result = await uut.instanceWallet(testWalletData)
|
||||
assert.equal(result.advancedOptions.interface, 'rest-api')
|
||||
})
|
||||
|
||||
it('should create an instance of BchWallet with consumer-api', async () => {
|
||||
uut.config.useFullStackCash = false
|
||||
const result = await uut.instanceWallet(testWalletData)
|
||||
assert.equal(result.advancedOptions.interface, 'consumer-api')
|
||||
})
|
||||
it('should catch and throw an error if no mnemonic is provided', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
await uut.instanceWallet({})
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log('err: ', err)
|
||||
assert.include(err.message, 'Wallet data is not formatted correctly. Can not read mnemonic in wallet file!')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#incrementNextAddress', () => {
|
||||
it('should increment the nextAddress property', async () => {
|
||||
const result = await uut.incrementNextAddress()
|
||||
assert.equal(result, 2)
|
||||
})
|
||||
|
||||
it('should catch and throw an error', async () => {
|
||||
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')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
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
|
||||
uut.config.walletFile = testWalletFile
|
||||
|
||||
const result = await uut.getKeyPair()
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.property(result, 'cashAddress')
|
||||
assert.property(result, 'wif')
|
||||
assert.property(result, 'hdIndex')
|
||||
})
|
||||
|
||||
it('should catch and throw an error', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
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')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#generateSignature', () => {
|
||||
it('should sign message', async () => {
|
||||
const result = await uut.generateSignature('unit test message')
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.isString(result)
|
||||
})
|
||||
|
||||
it('should catch and throw an error', async () => {
|
||||
try {
|
||||
await uut.generateSignature()
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'message is required!')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#generatePartialTx', () => {
|
||||
it('should generate tx for fungible token', async () => {
|
||||
const utxoInfo = {
|
||||
txid: '241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87',
|
||||
vout: 0,
|
||||
sats: 1000,
|
||||
wif: 'L2fzmF5hCeTZRVnr7Cyu66ucJAAKhkhkfinGVuUAKDtvAfwEx8a3'
|
||||
}
|
||||
|
||||
sandbox.stub(uut.bchWallet, 'getTxData').resolves([offerMockData.fungibleTokenData01.genesisData])
|
||||
const result = await uut.generatePartialTx(offerMockData.fungibleOffer01, utxoInfo)
|
||||
|
||||
assert.isString(result)
|
||||
})
|
||||
it('should generate tx for nft', async () => {
|
||||
const utxoInfo = {
|
||||
txid: '241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87',
|
||||
vout: 0,
|
||||
sats: 1000,
|
||||
wif: 'L2fzmF5hCeTZRVnr7Cyu66ucJAAKhkhkfinGVuUAKDtvAfwEx8a3'
|
||||
}
|
||||
|
||||
sandbox.stub(uut.bchWallet, 'getTxData').resolves([offerMockData.nftTokenData01.genesisData])
|
||||
const result = await uut.generatePartialTx(offerMockData.nftOffer01, utxoInfo)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.isString(result)
|
||||
})
|
||||
|
||||
it('should handle unknown token type', async () => {
|
||||
try {
|
||||
const utxoInfo = {
|
||||
txid: '241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87',
|
||||
vout: 0,
|
||||
sats: 1000,
|
||||
wif: 'L2fzmF5hCeTZRVnr7Cyu66ucJAAKhkhkfinGVuUAKDtvAfwEx8a3'
|
||||
}
|
||||
|
||||
const offerMock = Object.assign({}, offerMockData.nftOffer01)
|
||||
offerMock.tokenType = 100
|
||||
await uut.generatePartialTx(offerMock, utxoInfo)
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Unknown token type')
|
||||
}
|
||||
})
|
||||
it('should handle multiple outputs', async () => {
|
||||
const utxoInfo = {
|
||||
txid: '241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87',
|
||||
vout: 0,
|
||||
sats: 1000,
|
||||
wif: 'L2fzmF5hCeTZRVnr7Cyu66ucJAAKhkhkfinGVuUAKDtvAfwEx8a3'
|
||||
}
|
||||
|
||||
sandbox.stub(uut.bchWallet, 'getTxData').resolves([offerMockData.nftTokenData01.genesisData])
|
||||
sandbox.stub(uut.bchWallet.bchjs.SLP.NFT1, 'generateNFTChildSendOpReturn').returns({ outputs: 5 })
|
||||
const res = await uut.generatePartialTx(offerMockData.nftOffer01, utxoInfo)
|
||||
assert.isUndefined(res)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#moveTokens', () => {
|
||||
it('should move tokens', async () => {
|
||||
sandbox.stub(uut, 'getKeyPair').resolves({
|
||||
cashAddress: 'cashAddress',
|
||||
wif: 'wif',
|
||||
hdIndex: 11
|
||||
})
|
||||
const input = {
|
||||
tokenId: uut.bchWallet.utxos.utxoStore.slpUtxos.type1.tokens[0].tokenId,
|
||||
qty: 1
|
||||
}
|
||||
const res = await uut.moveTokens(input)
|
||||
assert.isObject(res)
|
||||
})
|
||||
|
||||
it('should throw an error if the tokenId is not found', async () => {
|
||||
try {
|
||||
sandbox.stub(uut, 'getKeyPair').resolves({
|
||||
cashAddress: 'cashAddress',
|
||||
wif: 'wif',
|
||||
hdIndex: 11
|
||||
})
|
||||
const input = {
|
||||
tokenId: '241c06bf61384b8623477e419bf4779edbcc7e3bc862f0f179a9ed2967069b87',
|
||||
qty: 1
|
||||
}
|
||||
await uut.moveTokens(input)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
assert.equal(error.message, 'tokenId not found!')
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw an error if the tokenId is not provided', async () => {
|
||||
try {
|
||||
await uut.moveTokens({
|
||||
qty: 1
|
||||
})
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
assert.equal(error.message, 'tokenId must be a string!')
|
||||
}
|
||||
})
|
||||
it('should throw an error if the qty is not provided', async () => {
|
||||
try {
|
||||
await uut.moveTokens({
|
||||
tokenId: 'tokenId'
|
||||
})
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
assert.equal(error.message, 'qty must be a number!')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#moveBch', () => {
|
||||
it('should move bch', async () => {
|
||||
sandbox.stub(uut, 'getKeyPair').resolves({
|
||||
cashAddress: 'cashAddress',
|
||||
wif: 'wif',
|
||||
hdIndex: 11
|
||||
})
|
||||
|
||||
const res = await uut.moveBch(100)
|
||||
assert.isObject(res)
|
||||
})
|
||||
|
||||
it('should throw an error if the amountSat is not provided', async () => {
|
||||
try {
|
||||
sandbox.stub(uut, 'getKeyPair').resolves({
|
||||
cashAddress: 'cashAddress',
|
||||
wif: 'wif',
|
||||
hdIndex: 11
|
||||
})
|
||||
|
||||
await uut.moveBch()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
assert.equal(error.message, 'amountSat is required!')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#moveTokensFromCustomWallet', () => {
|
||||
it('should move tokens from a custom wallet', async () => {
|
||||
sandbox.stub(uut, 'getKeyPair').resolves({
|
||||
@@ -100,28 +404,27 @@ describe('#wallet', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#deseralizeTx', () => {
|
||||
it('should throw an error if the hex is not provided', async () => {
|
||||
try {
|
||||
await uut.deseralizeTx()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
assert.equal(error.message, 'hex must be a string!')
|
||||
}
|
||||
})
|
||||
it('should decode hex', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.bchWallet.bchjs.RawTransactions, 'decodeRawTransaction').resolves({})
|
||||
const hex = '020000000286b2959cccdb80163b68bb1360abac8e0228ba7b70c779443168cc65c7c42d820100000000ffffffff879b066729eda979f1f062c83b7eccdb9e77f49b417e4723864b3861bf061c24000000006b483045022100b99c6161e18e4e34c1e438b6b03e808703695f217b30da42c3f787798a9f40cc02206d26b4f6799735779d4fac823bc60d276fbb3cea91c66dbfa136cf5b1bd0d8324121028dcd38a58c8295dbd105ef524014f77af4cddfa19b26c50926b4aaeebd95c7ceffffffff030000000000000000376a04534c500001010453454e4420a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b208000000000000006422020000000000001976a914bef6c5180648165704f22e71a1b011ba56336aee88acf81d0000000000001976a914c1f16a3876f8fbe3701a66d3cb3b9c7abb07a06c88ac00000000'
|
||||
const result = await uut.deseralizeTx(hex)
|
||||
assert.isObject(result)
|
||||
} catch (error) {
|
||||
assert.fail('Unexpected code path')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#completeTx', () => {
|
||||
// TODO: This test needs to be refactored to use the new instanceWallet() method for loading the user wallet.
|
||||
|
||||
// it('should complete a transaction', async () => {
|
||||
// sandbox.stub(uut, 'getKeyPair').resolves({
|
||||
// cashAddress: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
|
||||
// wif: 'L5D2UAam8tvo3uii5kpgaGyjvVMimdrXu8nWGQSQjuuAix6ji1YQ',
|
||||
// hdIndex: 11
|
||||
// })
|
||||
// sandbox.stub(uut, 'deseralizeTx').resolves({
|
||||
// txid: 'complete tx id result'
|
||||
// })
|
||||
// sandbox.stub(uut.retryQueue, 'addToQueue').resolves('complete tx id result')
|
||||
|
||||
// const hex = 'hex'
|
||||
// const hdIndex = 11
|
||||
// const mnemonic = 'course abstract aerobic deer try switch turtle diet fence affair butter top'
|
||||
|
||||
// const txid = await uut.completeTx(hex, hdIndex, mnemonic)
|
||||
// assert.equal(txid, 'complete tx id result')
|
||||
// })
|
||||
|
||||
it('should throw an error if the hex is not provided', async () => {
|
||||
try {
|
||||
const hdIndex = 11
|
||||
@@ -134,11 +437,60 @@ describe('#wallet', () => {
|
||||
it('should throw an error if the hdIndex is not provided', async () => {
|
||||
try {
|
||||
const hex = 'hex'
|
||||
await uut.completeTx(hex, null)
|
||||
await uut.completeTx(hex)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
assert.equal(error.message, 'hdIndex must be a non-negative number!')
|
||||
}
|
||||
})
|
||||
it('should throw an error if the mnemonic is not provided', async () => {
|
||||
try {
|
||||
const hex = 'hex'
|
||||
const hdIndex = 11
|
||||
await uut.completeTx(hex, hdIndex)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
assert.equal(error.message, 'mnemonic must be a string!')
|
||||
}
|
||||
})
|
||||
it('should complete a transaction', async () => {
|
||||
sandbox.stub(uut, 'getKeyPair').resolves({
|
||||
cashAddress: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
|
||||
wif: 'L5D2UAam8tvo3uii5kpgaGyjvVMimdrXu8nWGQSQjuuAix6ji1YQ',
|
||||
hdIndex: 11
|
||||
})
|
||||
sandbox.stub(uut, 'deseralizeTx').resolves({
|
||||
txid: 'complete tx id result'
|
||||
})
|
||||
sandbox.stub(uut.retryQueue, 'addToQueue').resolves('complete tx id result')
|
||||
|
||||
const hex = 'hex'
|
||||
const hdIndex = 11
|
||||
const mnemonic = 'course abstract aerobic deer try switch turtle diet fence affair butter top'
|
||||
|
||||
const txid = await uut.completeTx(hex, hdIndex, mnemonic)
|
||||
assert.equal(txid, 'complete tx id result')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#reClaimTokens', () => {
|
||||
it('should re-claim tokens', async () => {
|
||||
const orderData = {
|
||||
hdIndex: 11,
|
||||
tokenId: 'tokenId',
|
||||
numTokens: 1
|
||||
}
|
||||
const res = await uut.reclaimTokens(orderData)
|
||||
assert.equal(res, 'fakeTxid')
|
||||
})
|
||||
it('should handle error if order hd index is not provided', async () => {
|
||||
try {
|
||||
const orderData = {}
|
||||
await uut.reclaimTokens(orderData)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
assert.equal(error.message, 'orderData.hdIndex is required!')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -65,4 +65,51 @@ describe('#Webhook-Adapter', () => {
|
||||
assert.isString(result.id)
|
||||
})
|
||||
})
|
||||
describe('#deleteWebhook', () => {
|
||||
it('should throw error if input is not provided', async () => {
|
||||
try {
|
||||
await uut.deleteWebhook()
|
||||
assert.fail('unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'url must be a string')
|
||||
}
|
||||
})
|
||||
it('should delete webhook', async () => {
|
||||
sandbox.stub(uut.axios, 'delete').resolves({ data: { success: true } })
|
||||
const url = 'https://test.com/my-webhook'
|
||||
const result = await uut.deleteWebhook(url)
|
||||
assert.isObject(result)
|
||||
assert.property(result, 'success')
|
||||
})
|
||||
})
|
||||
describe('#waitUntilSuccess', () => {
|
||||
it('should handle error', async () => {
|
||||
try {
|
||||
sandbox.stub(uut, 'sleep').throws(new Error('test error'))
|
||||
sandbox.stub(uut, 'deleteWebhook')
|
||||
.onCall(0).throws(new Error('test error'))
|
||||
|
||||
sandbox.stub(uut, 'createWebhook')
|
||||
.onCall(0).throws(new Error('test error'))
|
||||
.onCall(1).resolves({ data: { success: true } })
|
||||
await uut.waitUntilSuccess()
|
||||
assert.fail('unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
it('should wait until success', async () => {
|
||||
uut.sleepTime = 100
|
||||
|
||||
sandbox.stub(uut, 'deleteWebhook')
|
||||
.onCall(0).throws(new Error('test error'))
|
||||
|
||||
sandbox.stub(uut, 'createWebhook')
|
||||
.onCall(0).throws(new Error('test error'))
|
||||
.onCall(1).resolves({ data: { success: true } })
|
||||
|
||||
const result = await uut.waitUntilSuccess()
|
||||
assert.isTrue(result)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -12,8 +12,18 @@ const mockWallet = {
|
||||
nextAddress: 1
|
||||
};
|
||||
|
||||
class MockBchWallet {
|
||||
|
||||
class AdapterRoute {
|
||||
constructor() {
|
||||
this.sendTx = async () => {
|
||||
return 'fakeTxid';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MockBchWallet {
|
||||
constructor(mnemonic, advancedOptions) {
|
||||
this.advancedOptions = advancedOptions
|
||||
this.walletInfoPromise = true;
|
||||
this.walletInfo = mockWallet;
|
||||
this.initialize = async () => {}
|
||||
@@ -24,6 +34,9 @@ class MockBchWallet {
|
||||
this.sendTokens = async () => {
|
||||
return 'fakeTxid';
|
||||
};
|
||||
this.send = async () => {
|
||||
return 'fakeTxid';
|
||||
};
|
||||
this.utxoIsValid =async ()=>{}
|
||||
this.getUtxos = async () => { };
|
||||
this.getBalance = async () => { };
|
||||
@@ -33,7 +46,15 @@ class MockBchWallet {
|
||||
tokenTicker: 'TROUT'
|
||||
}];
|
||||
};
|
||||
this.getKeyPair = async () => {
|
||||
return {
|
||||
cashAddress: 'bitcoincash:qzl0d3gcqeypv4cy7gh8rgdszxa9vvm2acv7fqtd00',
|
||||
wif: 'L5D2UAam8tvo3uii5kpgaGyjvVMimdrXu8nWGQSQjuuAix6ji1YQ',
|
||||
hdIndex: 11
|
||||
}
|
||||
};
|
||||
this.optimize = async () => { };
|
||||
this.ar = new AdapterRoute()
|
||||
// Environment variable is used by wallet-balance.unit.js to force an error.
|
||||
if (process.env.NO_UTXO) {
|
||||
this.utxos = {};
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
class BchTokenSweepMock {
|
||||
constructor(wif, privateKey, bchWallet, fee, cashAddress) {
|
||||
this.wif = wif
|
||||
this.privateKey = privateKey
|
||||
this.bchWallet = bchWallet
|
||||
this.fee = fee
|
||||
this.cashAddress = cashAddress
|
||||
}
|
||||
populateObjectFromNetwork() {
|
||||
return {
|
||||
success: true,
|
||||
txid: 'txid'
|
||||
}
|
||||
}
|
||||
sweepTo() {
|
||||
return {
|
||||
success: true,
|
||||
txid: 'txid'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { BchTokenSweepMock }
|
||||
|
||||
export default {
|
||||
BchTokenSweepMock
|
||||
}
|
||||
@@ -115,6 +115,7 @@ const fungibleTokenData01 = {
|
||||
"documentUri": "troutsblog.com",
|
||||
"documentHash": "",
|
||||
"decimals": 2,
|
||||
"tokenDecimals": 2,
|
||||
"mintBatonIsActive": true,
|
||||
"tokensInCirculationBN": "100097954686",
|
||||
"tokensInCirculationStr": "100097954686",
|
||||
|
||||
Reference in New Issue
Block a user