Skip to content

Commit be43462

Browse files
authored
Unit denomination and conversion (#301)
* feat: balance utils with conversion and formatting * feat: balance utils with conversion and formatting * test: updated formatBalance call and tests * test: remove deprecated GAS value * chore: add to index
1 parent 3eb8fc1 commit be43462

File tree

7 files changed

+174
-14
lines changed

7 files changed

+174
-14
lines changed

src/__integrationtests__/utils.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ import CType from '../ctype/CType'
99
import { getOwner } from '../ctype/CType.chain'
1010
import Identity from '../identity/Identity'
1111

12-
// FIXME: check with weights
13-
// export const GAS = new BN(1_000_000)
14-
export const GAS = new BN(125_000_000)
1512
export const MIN_TRANSACTION = new BN(100_000_000)
1613
export const ENDOWMENT = MIN_TRANSACTION.mul(new BN(100))
1714

src/balance/Balance.chain.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import BN from 'bn.js'
1515
import { getCached } from '../blockchainApiConnection'
1616
import Identity from '../identity/Identity'
1717
import IPublicIdentity from '../types/PublicIdentity'
18+
import BalanceUtils from './Balance.utils'
1819

1920
/**
2021
* Fetches the current balance of the account with [accountAddress].
@@ -89,11 +90,12 @@ export async function listenToBalanceChanges(
8990

9091
/**
9192
* Transfer Kilt [amount] tokens to [toAccountAddress] using the given [[Identity]].
92-
* <B>Note that balance amount is in Femto-Kilt (1e-15) and must be translated to Kilt-Coin</B>.
93+
* <B>Note that the value of the transferred currency and the balance amount reported by the chain is in Femto-Kilt (1e-15), and must be translated to Kilt-Coin</B>.
9394
*
9495
* @param identity Identity to use for token transfer.
9596
* @param accountAddressTo Address of the receiver account.
96-
* @param amount Amount of Femto-Kilt (1e-15) to transfer.
97+
* @param amount Amount of Units to transfer.
98+
* @param exponent Magnitude of the amount. Default magnitude of Femto-Kilt.
9799
* @returns Promise containing the transaction status.
98100
*
99101
* @example
@@ -117,9 +119,17 @@ export async function listenToBalanceChanges(
117119
export async function makeTransfer(
118120
identity: Identity,
119121
accountAddressTo: IPublicIdentity['address'],
120-
amount: BN
122+
amount: BN,
123+
exponent = -15
121124
): Promise<SubmittableResult> {
122125
const blockchain = await getCached()
123-
const transfer = blockchain.api.tx.balances.transfer(accountAddressTo, amount)
126+
const cleanExponent =
127+
(exponent >= 0 ? 1 : -1) * Math.floor(Math.abs(exponent))
128+
const transfer = blockchain.api.tx.balances.transfer(
129+
accountAddressTo,
130+
cleanExponent === -15
131+
? amount
132+
: BalanceUtils.convertToTxUnit(amount, cleanExponent)
133+
)
124134
return blockchain.submitTx(identity, transfer)
125135
}

src/balance/Balance.spec.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ import {
99
makeTransfer,
1010
} from './Balance.chain'
1111
import TYPE_REGISTRY from '../blockchainApiConnection/__mocks__/BlockchainQuery'
12+
import BalanceUtils from './Balance.utils'
1213

1314
jest.mock('../blockchainApiConnection/BlockchainApiConnection')
1415

1516
const BALANCE = 42
1617
const FEE = 30
1718

1819
describe('Balance', () => {
20+
let alice: Identity
21+
let bob: Identity
1922
const blockchainApi = require('../blockchainApiConnection/BlockchainApiConnection')
2023
.__mocked_api
2124

@@ -41,9 +44,11 @@ describe('Balance', () => {
4144
return accountInfo(BALANCE - FEE)
4245
}
4346
)
44-
47+
beforeAll(async () => {
48+
alice = await Identity.buildFromURI('//Alice')
49+
bob = await Identity.buildFromURI('//Bob')
50+
})
4551
it('should listen to balance changes', async (done) => {
46-
const bob = await Identity.buildFromURI('//Bob')
4752
const listener = (account: string, balance: BN, change: BN): void => {
4853
expect(account).toBe(bob.address)
4954
expect(balance.toNumber()).toBe(BALANCE)
@@ -58,11 +63,23 @@ describe('Balance', () => {
5863
})
5964

6065
it('should make transfer', async () => {
61-
const alice = await Identity.buildFromURI('//Alice')
62-
const bob = await Identity.buildFromURI('//Bob')
63-
6466
const status = await makeTransfer(alice, bob.address, new BN(100))
6567
expect(status).toBeInstanceOf(SubmittableResult)
6668
expect(status.isFinalized).toBeTruthy()
6769
})
70+
it('should make transfer of amount with arbitrary exponent', async () => {
71+
const amount = new BN(10)
72+
const exponent = -6
73+
const expectedAmount = BalanceUtils.convertToTxUnit(
74+
amount,
75+
(exponent >= 0 ? 1 : -1) * Math.floor(Math.abs(exponent))
76+
)
77+
const status = await makeTransfer(alice, bob.address, amount, exponent)
78+
expect(blockchainApi.tx.balances.transfer).toHaveBeenCalledWith(
79+
bob.address,
80+
expectedAmount
81+
)
82+
expect(status).toBeInstanceOf(SubmittableResult)
83+
expect(status.isFinalized).toBeTruthy()
84+
})
6885
})

src/balance/Balance.utils.spec.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import BN from 'bn.js'
2+
import {
3+
formatKiltBalance,
4+
convertToTxUnit,
5+
asFemtoKilt,
6+
TRANSACTION_FEE,
7+
} from './Balance.utils'
8+
9+
describe('formatKiltBalance', () => {
10+
const TESTVALUE = new BN('123456789000')
11+
const baseValue = new BN('1')
12+
it('formats the given balance', async () => {
13+
expect(formatKiltBalance(TESTVALUE)).toEqual('123.456 micro KILT')
14+
expect(formatKiltBalance(baseValue.mul(new BN(10).pow(new BN(3))))).toEqual(
15+
'1.000 pico KILT'
16+
)
17+
expect(formatKiltBalance(baseValue.mul(new BN(10).pow(new BN(6))))).toEqual(
18+
'1.000 nano KILT'
19+
)
20+
expect(formatKiltBalance(baseValue.mul(new BN(10).pow(new BN(9))))).toEqual(
21+
'1.000 micro KILT'
22+
)
23+
expect(
24+
formatKiltBalance(baseValue.mul(new BN(10).pow(new BN(12))))
25+
).toEqual('1.000 milli KILT')
26+
expect(
27+
formatKiltBalance(baseValue.mul(new BN(10).pow(new BN(15))))
28+
).toEqual('1.000 KILT')
29+
expect(
30+
formatKiltBalance(baseValue.mul(new BN(10).pow(new BN(18))))
31+
).toEqual('1.000 Kilo KILT')
32+
expect(
33+
formatKiltBalance(baseValue.mul(new BN(10).pow(new BN(21))))
34+
).toEqual('1.000 Mega KILT')
35+
expect(
36+
formatKiltBalance(baseValue.mul(new BN(10).pow(new BN(24))))
37+
).toEqual('1.000 Giga KILT')
38+
expect(
39+
formatKiltBalance(baseValue.mul(new BN(10).pow(new BN(27))))
40+
).toEqual('1.000 Tera KILT')
41+
})
42+
})
43+
describe('convertToTxUnit', () => {
44+
it('converts given value with given power to femto KILT', () => {
45+
expect(new BN(convertToTxUnit(new BN(1), -15).toString())).toEqual(
46+
new BN(1)
47+
)
48+
expect(new BN(convertToTxUnit(new BN(1), -12).toString())).toEqual(
49+
new BN('1000')
50+
)
51+
expect(new BN(convertToTxUnit(new BN(1), -9).toString())).toEqual(
52+
new BN('1000000')
53+
)
54+
expect(new BN(convertToTxUnit(new BN(1), -6).toString())).toEqual(
55+
new BN('1000000000')
56+
)
57+
expect(new BN(convertToTxUnit(new BN(1), -3).toString())).toEqual(
58+
new BN('1000000000000')
59+
)
60+
expect(new BN(convertToTxUnit(new BN(1), 0).toString())).toEqual(
61+
new BN('1000000000000000')
62+
)
63+
expect(new BN(convertToTxUnit(new BN(1), 3).toString())).toEqual(
64+
new BN('1000000000000000000')
65+
)
66+
expect(new BN(convertToTxUnit(new BN(1), 6).toString())).toEqual(
67+
new BN('1000000000000000000000')
68+
)
69+
expect(new BN(convertToTxUnit(new BN(1), 9).toString())).toEqual(
70+
new BN('1000000000000000000000000')
71+
)
72+
expect(new BN(convertToTxUnit(new BN(1), 12).toString())).toEqual(
73+
new BN('1000000000000000000000000000')
74+
)
75+
expect(new BN(convertToTxUnit(new BN(1), 15).toString())).toEqual(
76+
new BN('1000000000000000000000000000000')
77+
)
78+
expect(new BN(convertToTxUnit(new BN(1), 18).toString())).toEqual(
79+
new BN('1000000000000000000000000000000000')
80+
)
81+
})
82+
})
83+
describe('asFemtoKilt', () => {
84+
it('converts whole KILT to femtoKilt using convertToTxUnit', () => {
85+
expect(new BN(asFemtoKilt(new BN(1000)).toString())).toEqual(
86+
new BN('1000000000000000000')
87+
)
88+
})
89+
})
90+
91+
describe('TRANSACTION_FEE', () => {
92+
it('equals 125 nano KILT', () => {
93+
expect(formatKiltBalance(TRANSACTION_FEE)).toEqual('125.000 nano KILT')
94+
})
95+
})

src/balance/Balance.utils.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @packageDocumentation
3+
* @module BalanceUtils
4+
* @preferred
5+
*/
6+
7+
import BN from 'bn.js'
8+
import { formatBalance } from '@polkadot/util'
9+
10+
export const KILT_COIN = new BN(1)
11+
12+
export function formatKiltBalance(amount: BN): string {
13+
return formatBalance(amount, {
14+
decimals: 15,
15+
withSiFull: true,
16+
withUnit: 'KILT',
17+
})
18+
}
19+
20+
export function convertToTxUnit(balance: BN, power: number): BN {
21+
return new BN(balance).mul(new BN(10).pow(new BN(15 + power)))
22+
}
23+
24+
export function asFemtoKilt(balance: BN): BN {
25+
return convertToTxUnit(balance, 0)
26+
}
27+
28+
export const TRANSACTION_FEE = convertToTxUnit(new BN(125), -9)
29+
30+
export default {
31+
KILT_COIN,
32+
TRANSACTION_FEE,
33+
formatKiltBalance,
34+
asFemtoKilt,
35+
convertToTxUnit,
36+
}

src/balance/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@
33
* @ignore
44
*/
55

6-
export * from './Balance.chain'
6+
import BalanceUtils from './Balance.utils'
7+
import * as Balance from './Balance.chain'
8+
9+
export { Balance, BalanceUtils }
10+
export default Balance

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Accumulator, CombinedPresentation } from '@kiltprotocol/portablegabi'
66
import { Attester, Claimer, Verifier } from './actor'
77
import Attestation, { AttestationUtils } from './attestation'
88
import AttestedClaim, { AttestedClaimUtils } from './attestedclaim'
9-
import * as Balance from './balance'
9+
import { Balance, BalanceUtils } from './balance'
1010
import Blockchain, { IBlockchainApi } from './blockchain'
1111
import * as BlockchainApiConnection from './blockchainApiConnection'
1212
import Claim, { ClaimUtils } from './claim'
@@ -66,6 +66,7 @@ export {
6666
IBlockchainApi,
6767
BlockchainApiConnection,
6868
Balance,
69+
BalanceUtils,
6970
Crypto,
7071
Identity,
7172
AttesterIdentity,

0 commit comments

Comments
 (0)