Skip to content

Commit

Permalink
refactor(NodeApi)!: return BigInt instead of string | number
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Node API returns BigInts for coin fields instead of string or number
  • Loading branch information
davidyuk committed May 27, 2022
1 parent d403b77 commit 7f37e74
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 43 deletions.
10 changes: 5 additions & 5 deletions src/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export async function waitForTxConfirm (
export async function getAccount (
address: EncodedData<'ak'>,
{ height, hash, onNode }:
{ height?: number, hash?: EncodedData<'kh'> | EncodedData<'mh'>, onNode: Node }
{ height?: number, hash?: EncodedData<'kh' | 'mh'>, onNode: Node }
): Promise<TransformNodeType<AccountNode>> {
if (height != null) return await onNode.api.getAccountByPubkeyAndHeight(address, height)
if (hash != null) return await onNode.api.getAccountByPubkeyAndHash(address, hash)
Expand All @@ -189,10 +189,10 @@ export async function getBalance (
address: EncodedData<'ak'>,
{ format = AE_AMOUNT_FORMATS.AETTOS, ...options }:
{ format: AeAmountFormats } & Parameters<typeof getAccount>[1]
): Promise<string | number> {
const { balance } = await getAccount(address, options).catch(() => ({ balance: 0 }))
): Promise<string> {
const { balance } = await getAccount(address, options).catch(() => ({ balance: 0n }))

return formatAmount(balance, { targetDenomination: format }).toString()
return formatAmount(balance, { targetDenomination: format })
}

/**
Expand Down Expand Up @@ -440,7 +440,7 @@ export async function resolveName (
key: string,
{ verify = true, resolveByNode, onNode }:
{ verify: boolean, resolveByNode: boolean, onNode: Node }
): Promise<EncodedData<'ak'> | EncodedData<'nm'>> {
): Promise<EncodedData<'ak' | 'nm'>> {
try {
decode(nameOrId)
return nameOrId as EncodedData<'ak'>
Expand Down
13 changes: 5 additions & 8 deletions src/nodeApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import { mapObject } from './utils/other'
import { EncodedData } from './utils/encoder'

const bigIntPropertyNames = [
'balance', 'queryFee', 'fee', 'amount', 'nameSalt', 'nameFee', 'channelAmount',
'balance', 'queryFee', 'fee', 'amount', 'nameFee', 'channelAmount',
'initiatorAmount', 'responderAmount', 'channelReserve', 'initiatorAmountFinal',
'responderAmountFinal', 'gasPrice', 'gas', 'gasUsed', 'deposit'
'responderAmountFinal', 'gasPrice', 'deposit'
] as const

const numberPropertyNames = [
'time',
'time', 'gas', 'gasUsed', 'nameSalt',
'nonce', 'nextNonce', 'height', 'blockHeight', 'top', 'topBlockHeight', 'ttl',
'inbound', 'outbound', 'peerCount', 'pendingTransactionsCount', 'effectiveAtHeight',
'version', 'solutions'
Expand All @@ -35,7 +35,7 @@ export type TransformNodeType<Type> =
? {
[Property in keyof Type]:
Property extends BigIntPropertyNames
? PreserveOptional<string | number, Type[Property]>
? PreserveOptional<bigint, Type[Property]>
: Property extends NumberPropertyNames
? PreserveOptional<number, Type[Property]>
: Property extends 'txHash'
Expand Down Expand Up @@ -103,10 +103,7 @@ export default class extends (Node as unknown as TransformedNode) {

#decodeRes (data: any): any {
return this.#mapData(data, {
bigInt: value => {
const bn = new BigNumber(value)
return bn.isLessThanOrEqualTo(Number.MAX_SAFE_INTEGER) ? +bn : bn.toFixed()
},
bigInt: value => BigInt(value),
number: value => +value
})
}
Expand Down
4 changes: 2 additions & 2 deletions src/tx/builder/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ function validateField (value, type, prefix) {
switch (type) {
case FIELD_TYPES.amount:
case FIELD_TYPES.int: {
if (isNaN(value) && !BigNumber.isBigNumber(value)) {
return `${value} is not of type Number or BigNumber`
if (typeof value !== 'bigint' && isNaN(value) && !BigNumber.isBigNumber(value)) {
return `${value} is not of type BigInt, Number or BigNumber`
}
if (new BigNumber(value).lt(0)) return `${value} must be >= 0`
return
Expand Down
4 changes: 2 additions & 2 deletions src/utils/amount-formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ export const toAettos = (
* @return {String}
*/
export const formatAmount = (
value: string | number | BigNumber,
value: string | number | bigint | BigNumber,
{ denomination = AE_AMOUNT_FORMATS.AETTOS, targetDenomination = AE_AMOUNT_FORMATS.AETTOS }:
{ denomination?: AeAmountFormats, targetDenomination?: AeAmountFormats }
): string => {
if (!isBigNumber(value)) throw new ArgumentError('value', 'a number', value)

return new BigNumber(value)
return new BigNumber(typeof value === 'bigint' ? value.toString() : value)
.shiftedBy(DENOMINATION_MAGNITUDE[denomination] - DENOMINATION_MAGNITUDE[targetDenomination])
.toFixed()
}
Expand Down
13 changes: 7 additions & 6 deletions src/utils/bignumber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import BigNumber from 'bignumber.js'

/**
* Check if value is BigNumber, Number or number string representation
* @param {String|Number|BigNumber} number number to convert
* @return {Boolean}
* Check if value is BigNumber, Number, BigInt or number string representation
* @param number number to check
*/
export const isBigNumber = (number: string | number | BigNumber): boolean =>
['number', 'object', 'string', 'bigint'].includes(typeof number) &&
(!isNaN(number as number) || Number.isInteger(number) || BigNumber.isBigNumber(number))
export const isBigNumber = (number: string | number | bigint | BigNumber): boolean => {
if (typeof number === 'bigint') return true
return ['number', 'object', 'string'].includes(typeof number) &&
(!isNaN(number as number) || Number.isInteger(number) || BigNumber.isBigNumber(number))
}

/**
* BigNumber ceil operation
Expand Down
16 changes: 5 additions & 11 deletions test/integration/accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,31 +108,25 @@ describe('Accounts', function () {
it('spends coins', async () => {
const ret = await aeSdk.spend(1, receiver)
ret.should.have.property('tx')
ret.tx.should.include({
amount: 1, recipientId: receiver
})
ret.tx.should.include({ amount: 1n, recipientId: receiver })
})

it('spends coins in AE format', async () => {
const ret = await aeSdk.spend(1, receiver, { denomination: AE_AMOUNT_FORMATS.AE })
ret.should.have.property('tx')
ret.tx.should.include({
amount: `${1e18}`, recipientId: receiver
})
ret.tx.should.include({ amount: 10n ** 18n, recipientId: receiver })
})

it('spends big amount of coins', async () => {
const bigAmount = '10000000000000100000000000000000'
const bigAmount = 10n ** 31n + 10n ** 17n
const genesis = await BaseAe({ networkId })
const receiverWallet = generateKeyPair()
const ret = await genesis.spend(bigAmount, receiverWallet.publicKey)

const balanceAfter = await aeSdk.getBalance(receiverWallet.publicKey)
balanceAfter.should.be.equal(bigAmount)
balanceAfter.should.be.equal(bigAmount.toString())
ret.should.have.property('tx')
ret.tx.should.include({
amount: bigAmount, recipientId: receiverWallet.publicKey
})
ret.tx.should.include({ amount: bigAmount, recipientId: receiverWallet.publicKey })
})

it('Get Account by block height/hash', async () => {
Expand Down
6 changes: 3 additions & 3 deletions test/integration/contract-aci.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,10 @@ describe('Contract instance', function () {
})
expect(deployInfo.address).to.satisfy(b => b.startsWith('ct_'))
expect(deployInfo.txData.tx.gas).to.be.equal(16000)
expect(deployInfo.txData.tx.amount).to.be.equal(42)
expect(deployInfo.txData.tx.amount).to.be.equal(42n)
expect(deployInfo.txData.gasUsed).to.be.equal(209)
expect(deployInfo.txData.gasPrice).to.be.equal(1000000000)
expect(deployInfo.txData.tx.deposit).to.be.equal(0)
expect(deployInfo.txData.gasPrice).to.be.equal(1000000000n)
expect(deployInfo.txData.tx.deposit).to.be.equal(0n)
expect(testContract.bytecode).to.satisfy(b => b.startsWith('cb_'))
testContractAddress = deployInfo.address
})
Expand Down
8 changes: 4 additions & 4 deletions test/integration/oracle.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe('Oracle', function () {

describe('Oracle query fee settings', async () => {
let oracleWithFee
const queryFee = 24000
const queryFee = 24000n
const account = generateKeyPair()

before(async function () {
Expand All @@ -98,7 +98,7 @@ describe('Oracle', function () {

it('Post Oracle Query with default query fee', async () => {
query = await oracle.postQuery("{'city': 'Berlin'}")
query.tx.queryFee.should.be.equal(QUERY_FEE)
query.tx.queryFee.should.be.equal(BigInt(QUERY_FEE))
})

it('Post Oracle Query with registered query fee', async () => {
Expand All @@ -107,8 +107,8 @@ describe('Oracle', function () {
})

it('Post Oracle Query with custom query fee', async () => {
query = await oracleWithFee.postQuery("{'city': 'Berlin'}", { queryFee: queryFee + 2000 })
query.tx.queryFee.should.be.equal(queryFee + 2000)
query = await oracleWithFee.postQuery("{'city': 'Berlin'}", { queryFee: queryFee + 2000n })
query.tx.queryFee.should.be.equal(queryFee + 2000n)
})
})
})
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"outDir": "./es",
"noImplicitAny": true,
"module": "es6",
"target": "es6",
"lib": ["es2019", "dom"],
"target": "es2020",
"lib": ["es2020", "dom"],
"moduleResolution": "node",
"preserveConstEnums": true,
"declaration": true,
Expand Down

0 comments on commit 7f37e74

Please sign in to comment.