Skip to content

Commit

Permalink
Bignumbers in providers (#169)
Browse files Browse the repository at this point in the history
* Changes of getBalance for Ethereum and ERC20 provider and singleChain tests

* Bitcoin balance is now returned as a bignumber

* Added chai bignumber extension

* Fixed typo in EthereumProvider unit tests

* Updated package lock for Travis
  • Loading branch information
grandsmarquis authored Apr 9, 2019
1 parent 1b03044 commit c6fd3a5
Show file tree
Hide file tree
Showing 10 changed files with 2,423 additions and 2,378 deletions.
4,734 changes: 2,383 additions & 2,351 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"babel-plugin-istanbul": "^5.1.1",
"babel-plugin-lodash": "^3.3.4",
"chai-as-promised": "^7.1.1",
"chai-bignumber": "^3.0.0",
"copy": "^0.3.2",
"coveralls": "^3.0.2",
"cross-env": "^5.2.0",
Expand Down
3 changes: 2 additions & 1 deletion src/Client.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { find, findLast, findLastIndex, isArray, isBoolean, isFunction, isNumber, isString } from 'lodash'
import Ajv from 'ajv'
import { BigNumber } from 'bignumber.js'

import { Block, Transaction } from './schema'
import { sha256 } from './crypto'
Expand Down Expand Up @@ -274,7 +275,7 @@ export default class Client {

const balance = await this.getMethod('getBalance')(addresses)

if (!isNumber(balance)) {
if (!BigNumber.isBigNumber(balance)) {
throw new InvalidProviderResponseError('Provider returned an invalid response')
}

Expand Down
2 changes: 1 addition & 1 deletion src/providers/bitcoin/BitcoinRPCProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export default class BitcoinRPCProvider extends JsonRpcProvider {

const _utxos = await this.getUnspentTransactionsForAddresses(addresses)
const utxos = _.flatten(_utxos)
return utxos.reduce((acc, utxo) => acc + utxo.satoshis, 0)
return utxos.map(balance => new BigNumber(balance.satoshis)).reduce((acc, utxo) => acc.plus(utxo), new BigNumber(0))
}

async getListUnspent (addresses) {
Expand Down
7 changes: 5 additions & 2 deletions src/providers/ethereum/EthereumERC20Provider.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Provider from '../../Provider'
import { padHexStart } from '../../crypto'
import { ensureAddressStandardFormat, ensureHexEthFormat } from './EthereumUtil'
import { BigNumber } from 'bignumber.js'

export default class EthereumERC20Provider extends Provider {
constructor (contractAddress) {
Expand All @@ -9,6 +10,7 @@ export default class EthereumERC20Provider extends Provider {
}

generateErc20Transfer (to, value) {
// function transfer(address to, uint tokens) public returns (bool success)
const functionSignature = 'a9059cbb'
const encodedAddress = padHexStart(ensureAddressStandardFormat(to), 64)
const encodedValue = padHexStart(value.toString(16), 64)
Expand All @@ -25,12 +27,13 @@ export default class EthereumERC20Provider extends Provider {
}

async getBalance (addresses) {
// function balanceOf(address tokenOwner)
const functionSignature = '0x70a08231'
addresses = addresses
.map(address => String(address))
const addrs = addresses.map(ensureHexEthFormat)
const promiseBalances = await Promise.all(addrs.map(address => this.getMethod('jsonrpc')('eth_call', { data: functionSignature + padHexStart(ensureAddressStandardFormat(address), 64), to: ensureHexEthFormat(this._contractAddress) }, 'latest')))
return promiseBalances.map(balance => parseInt(balance, 16))
.reduce((acc, balance) => acc + balance, 0)
return promiseBalances.map(balance => new BigNumber(balance, 16))
.reduce((acc, balance) => acc.plus(balance), new BigNumber(0))
}
}
3 changes: 2 additions & 1 deletion src/providers/ethereum/EthereumERC20SwapProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Provider from '../../Provider'
import { padHexStart } from '../../crypto'
import { sleep } from '../../GlobalUtils'
import { ensureAddressStandardFormat } from './EthereumUtil'
import { BigNumber } from 'bignumber.js'

export default class EthereumERC20SwapProvider extends Provider {
createSwapScript (recipientAddress, refundAddress, secretHash, expiration) {
Expand Down Expand Up @@ -66,7 +67,7 @@ export default class EthereumERC20SwapProvider extends Provider {

async doesBalanceMatchValue (contractAddress, value) {
const balance = await this.getMethod('getBalance')([contractAddress])
return balance === value
return balance.isEqualTo(new BigNumber(value))
}

async verifyInitiateSwapTransaction (initiationTxHash, value, recipientAddress, refundAddress, secretHash, expiration) {
Expand Down
4 changes: 2 additions & 2 deletions src/providers/ethereum/EthereumRPCProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ export default class EthereumRPCProvider extends JsonRpcProvider {

const addrs = addresses.map(ensureHexEthFormat)
const promiseBalances = await Promise.all(addrs.map(address => this.jsonrpc('eth_getBalance', address, 'latest')))
return promiseBalances.map(balance => parseInt(balance, 16))
.reduce((acc, balance) => acc + balance, 0)
return promiseBalances.map(balance => new BigNumber(balance, 16))
.reduce((acc, balance) => acc.plus(balance), new BigNumber(0))
}

async isAddressUsed (address) {
Expand Down
27 changes: 14 additions & 13 deletions test/integration/swap/singleChain.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import config from './config'
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0

chai.use(chaiAsPromised)
chai.use(require('chai-bignumber')())

const { calculateFee } = providers.bitcoin.BitcoinUtil
const mockSecret = _.repeat('ff', 32)
Expand All @@ -31,7 +32,7 @@ function testSingle (chain) {
let claimTx
await expectBalance(chain, swapParams.recipientAddress,
async () => { claimTx = await claimAndVerify(chain, initiationTxId, secret, swapParams) },
(before, after) => expect(after).to.be.greaterThan(before))
(before, after) => expect(after).to.be.bignumber.greaterThan(before))
const revealedSecret = claimTx.secret
expect(revealedSecret).to.equal(secret)
})
Expand Down Expand Up @@ -75,7 +76,7 @@ function testSingle (chain) {
await sleep(20000)
await refund(chain, initiationTxId, secretHash, swapParams)
},
(before, after) => expect(after).to.be.greaterThan(before))
(before, after) => expect(after).to.be.bignumber.greaterThan(before))
})

it('Refund fails after claim', async () => {
Expand All @@ -85,18 +86,18 @@ function testSingle (chain) {
const initiationTxId = await initiateAndVerify(chain, secretHash, swapParams)
await expectBalance(chain, swapParams.recipientAddress,
async () => claimAndVerify(chain, initiationTxId, mockSecret, swapParams),
(before, after) => expect(after).to.be.greaterThan(before))
(before, after) => expect(after).to.be.bignumber.greaterThan(before))
await expectBalance(chain, swapParams.refundAddress,
async () => {
try { await refund(chain, initiationTxId, secretHash, swapParams) } catch (e) {} // Refund failing is ok
},
(before, after) => expect(after).to.be.equal(before))
(before, after) => expect(after).to.be.bignumber.equal(before))
await sleep(20000)
await expectBalance(chain, swapParams.refundAddress,
async () => {
try { await refund(chain, initiationTxId, secretHash, swapParams) } catch (e) {} // Refund failing is ok
},
(before, after) => expect(after).to.be.equal(before))
(before, after) => expect(after).to.be.bignumber.equal(before))
})

it('Refund available after expiration', async () => {
Expand All @@ -118,8 +119,8 @@ function testEthereumBalance (chain) {
await expectBalance(chain, swapParams.recipientAddress,
async () => { await claimAndVerify(chain, initiationTxId, mockSecret, swapParams) },
(before, after) => {
const expectedBalance = BigNumber(before).plus(BigNumber(swapParams.value)).toNumber()
expect(after).to.be.equal(expectedBalance)
const expectedBalance = BigNumber(before).plus(BigNumber(swapParams.value))
expect(after.toString()).to.be.bignumber.equal(expectedBalance)
})
})

Expand All @@ -132,8 +133,8 @@ function testEthereumBalance (chain) {
await expectBalance(chain, swapParams.refundAddress,
async () => refund(chain, initiationTxId, secretHash, swapParams),
(before, after) => {
const expectedBalance = BigNumber(before).plus(BigNumber(swapParams.value)).toNumber()
expect(after).to.be.equal(expectedBalance)
const expectedBalance = BigNumber(before).plus(BigNumber(swapParams.value))
expect(after).to.be.bignumber.equal(expectedBalance)
})
})
}
Expand All @@ -147,8 +148,8 @@ function testBitcoinBalance (chain) {
await expectBalance(chain, swapParams.recipientAddress,
async () => { await claimAndVerify(chain, initiationTxId, mockSecret, swapParams) },
(before, after) => {
const expectedBalance = BigNumber(before).plus(BigNumber(swapParams.value)).minus(BigNumber(fee)).toNumber()
expect(after).to.be.equal(expectedBalance)
const expectedBalance = BigNumber(before).plus(BigNumber(swapParams.value)).minus(BigNumber(fee))
expect(after).to.be.bignumber.equal(expectedBalance)
})
})

Expand All @@ -162,8 +163,8 @@ function testBitcoinBalance (chain) {
await expectBalance(chain, swapParams.refundAddress,
async () => refund(chain, initiationTxId, secretHash, swapParams),
(before, after) => {
const expectedBalance = BigNumber(before).plus(BigNumber(swapParams.value)).minus(BigNumber(fee)).toNumber()
expect(after).to.be.equal(expectedBalance)
const expectedBalance = BigNumber(before).plus(BigNumber(swapParams.value)).minus(BigNumber(fee))
expect(after).to.be.bignumber.equal(expectedBalance)
})
})
}
Expand Down
8 changes: 5 additions & 3 deletions test/unit/providers/bitcoin/BitcoinRPCProvider.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/* eslint-env mocha */
require('chai').config.truncateThreshold = 0
const { expect } = require('chai')
import BigNumber from 'bignumber.js'
import chai, { expect } from 'chai'

const { Client, providers: { bitcoin: { BitcoinRPCProvider } } } = require('../../../../src')
const mockJsonRpc = require('../../../mock/mockJsonRpc')
const bitcoinRpc = require('../../../mock/bitcoin/rpc')

chai.config.truncateThreshold = 0

describe('Bitcoin RPC provider', () => {
let client
let provider
Expand Down Expand Up @@ -123,7 +125,7 @@ describe('Bitcoin RPC provider', () => {
describe('getBalance', () => {
it('should return correct balance in sats', async () => {
const balance = await provider.getBalance(['mpJJQJzJhjceFabMVXAMB8i4VJcwwWQmcc'])
expect(balance).to.equal(20000000)
expect(balance).to.be.bignumber.equal(new BigNumber(20000000))
})
})

Expand Down
12 changes: 8 additions & 4 deletions test/unit/providers/ethereum/EthereumRPCProvider.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
/* eslint-env mocha */

require('chai').config.truncateThreshold = 0
const { expect } = require('chai')
import BigNumber from 'bignumber.js'
import chai, { expect } from 'chai'

chai.config.truncateThreshold = 0

const { Client, providers: { ethereum: { EthereumRPCProvider } } } = require('../../../../src')
const mockJsonRpc = require('../../../mock/mockJsonRpc')
const ethereumRpc = require('../../../mock/ethereum/rpc')

chai.use(require('chai-bignumber')())

describe('Ethereum RPC provider', () => {
let client
let provider
Expand Down Expand Up @@ -127,8 +131,8 @@ describe('Ethereum RPC provider', () => {
it('should return correct balance', async () => {
const balance = await client.getBalance([ '322d4959c911520645c0638204b42ce0689236e9' ])
expect(balance)
.to
.equal(99995379999999890000)
.to.be.bignumber
.equal(new BigNumber(99995379999999890000))
})
})

Expand Down

0 comments on commit c6fd3a5

Please sign in to comment.