Skip to content

Commit

Permalink
Added listBurnHistory RPC (#444)
Browse files Browse the repository at this point in the history
* Added listBurnHistory RPC

* Added listBurnHistory tests

* Added transaction type NONE

* Added listBurnHistory API documentation

* import createToken and accountToAccount from @defichain/testing

* remove global variables

* Refactor test. Creates history beforeAll and then checks each element of the history. Uses indexes in order to test correct order of transactions

* Update packages/jellyfish-api-core/src/category/account.ts

Co-authored-by: Suraj Auwal <[email protected]>

* with maxBlockHeight, depth and limit tests

* remove duplicated tests

* requested change on maxBlockHeight test

* with clearer depth test

* revert changes to maxblockheight and depth tests and make them clearer by comparing to history without filter option

* remove redundant block generation

* change depth and maxBlockHeight to correctly work after removal of two block generation

* Assert history length while filtering by token DFI'

* remove duplicate filter on txtype tests

* don't use lambda for top level function

* fix missing space between function name and parenthesis

* replace toBeTruthy() by toStrictEqual(true) and toBeFalsy() by toStrictEqual(false)

* improve code consistency

Co-authored-by: Suraj Auwal <[email protected]>
  • Loading branch information
Jouzo and siradji authored Jul 25, 2021
1 parent 4ffe19e commit 102aa0b
Show file tree
Hide file tree
Showing 3 changed files with 293 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import { MasterNodeRegTestContainer } from '@defichain/testcontainers'
import { ContainerAdapterClient } from '../../container_adapter_client'
import { BalanceTransferPayload, DfTxType } from '../../../src/category/account'
import { createToken, accountToAccount } from '@defichain/testing'

describe('Account', () => {
const container = new MasterNodeRegTestContainer()
const client = new ContainerAdapterClient(container)
const burnAddress = 'mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG'
const burnAddressPrivateKey = '93ViFmLeJVgKSPxWGQHmSdT5RbeGDtGW4bsiwQM2qnQyucChMqQ'
let fundedAddress: string

beforeAll(async () => {
await container.start()
await container.waitForReady()
await container.waitForWalletCoinbaseMaturity()

await client.wallet.importPrivKey(burnAddressPrivateKey)

await createHistory()
})

async function createHistory (): Promise<void> {
// test masternode creation fee burn
const newAddress = await container.getNewAddress('', 'legacy')
await client.masternode.createMasternode(newAddress)
await container.generate(1)

// creates funded account address
fundedAddress = await container.getNewAddress()
await client.wallet.sendToAddress(fundedAddress, 1)
await container.call('utxostoaccount', [{ [fundedAddress]: '3@0' }])
await container.generate(1)

// burn token
await createToken(container, 'GOLD', { collateralAddress: fundedAddress })

// mint token and send token to burn address
await container.call('minttokens', ['100@GOLD'])
await container.generate(1)

await accountToAccount(container, 'GOLD', 100, {
from: fundedAddress, to: burnAddress
})

// utxostoaccount burn
await container.call('utxostoaccount', [{ [burnAddress]: '1@0' }])
await container.generate(1)

// send to burn address with accountToAccount
await accountToAccount(container, '0', 1, {
from: fundedAddress, to: burnAddress
})

// send to burn address with accounttoutxos
const payload: BalanceTransferPayload = {}
payload[burnAddress] = '2@0'
await client.account.accountToUtxos(fundedAddress, payload)
await container.generate(1)

// send utxo to burn address
await client.wallet.sendToAddress(burnAddress, 10)
await container.generate(1)
}

afterAll(async () => {
await container.stop()
})

it('should listBurnHistory', async () => {
const history = await client.account.listBurnHistory()
expect(history.length).toStrictEqual(7)
for (let i = 0; i < history.length; i += 1) {
const burnHistory = history[i]
expect(typeof burnHistory.owner).toStrictEqual('string')
expect(typeof burnHistory.blockHeight).toStrictEqual('number')
expect(typeof burnHistory.blockHash).toStrictEqual('string')
expect(typeof burnHistory.blockTime).toStrictEqual('number')
expect(typeof burnHistory.type).toStrictEqual('string')
expect(typeof burnHistory.txn).toStrictEqual('number')
expect(typeof burnHistory.txid).toStrictEqual('string')
expect(burnHistory.amounts.length).toBeGreaterThan(0)
expect(typeof burnHistory.amounts[0]).toStrictEqual('string')
}
})

it('first transaction should be masternode creation fee burn', async () => {
const history = await client.account.listBurnHistory()
expect(history[6].owner.slice(0, 16)).toStrictEqual('6a1a446654784301')
expect(history[6].type).toStrictEqual('CreateMasternode')
expect(history[6].txn).toStrictEqual(2)
expect(history[6].amounts.length).toStrictEqual(1)
expect(history[6].amounts[0]).toStrictEqual('1.00000000@DFI')
})

it('second transaction should be after burn token', async () => {
const history = await client.account.listBurnHistory()
expect(history[5].owner).toStrictEqual('6a19446654785404474f4c4404474f4c4408000000000000000007')
expect(history[5].type).toStrictEqual('CreateToken')
expect(history[5].txn).toStrictEqual(1)
expect(history[5].amounts.length).toStrictEqual(1)
expect(history[5].amounts[0]).toStrictEqual('1.00000000@DFI')
})

it('third transaction should be send token to burn address', async () => {
const history = await client.account.listBurnHistory()
expect(history[4].owner).toStrictEqual(burnAddress)
expect(history[4].type).toStrictEqual('AccountToAccount')
expect(history[4].txn).toStrictEqual(1)
expect(history[4].amounts.length).toStrictEqual(1)
expect(history[4].amounts[0]).toStrictEqual('100.00000000@GOLD')
})

it('fourth transaction should be utxostoaccount burn', async () => {
const history = await client.account.listBurnHistory()
expect(history[3].owner).toStrictEqual(burnAddress)
expect(history[3].type).toStrictEqual('UtxosToAccount')
expect(history[3].txn).toStrictEqual(1)
expect(history[3].amounts.length).toStrictEqual(1)
expect(history[3].amounts[0]).toStrictEqual('1.00000000@DFI')
})

it('fifth transaction should be send to burn address with accountToAccount', async () => {
const history = await client.account.listBurnHistory()
expect(history[2].owner).toStrictEqual(burnAddress)
expect(history[2].type).toStrictEqual('AccountToAccount')
expect(history[2].txn).toStrictEqual(1)
expect(history[2].amounts.length).toStrictEqual(1)
expect(history[2].amounts[0]).toStrictEqual('1.00000000@DFI')
})

it('sixth transaction should be send to burn address with accounttoutxos', async () => {
const history = await client.account.listBurnHistory()
expect(history[1].owner).toStrictEqual(burnAddress)
expect(history[1].type).toStrictEqual('None')
expect(history[1].txn).toStrictEqual(1)
expect(history[1].amounts.length).toStrictEqual(1)
expect(history[1].amounts[0]).toStrictEqual('2.00000000@DFI')
})

it('last transaction should be send utxo to burn address', async () => {
const history = await client.account.listBurnHistory()
expect(history[0].owner).toStrictEqual(burnAddress)
expect(history[0].type).toStrictEqual('None')
expect(history[0].txn).toStrictEqual(1)
expect(history[0].amounts.length).toStrictEqual(1)
expect(history[0].amounts[0]).toStrictEqual('10.00000000@DFI')
})

it('should listBurnHistory with filter on txtype AccountToAccount', async () => {
const history = await client.account.listBurnHistory({
txtype: DfTxType.ACCOUNT_TO_ACCOUNT
})
expect(history.length).toStrictEqual(2)
expect(history.every(({ type }) => type === 'AccountToAccount')).toStrictEqual(true)
})

it('should listBurnHistory with filter on token DFI', async () => {
const history = await client.account.listBurnHistory({
token: 'DFI'
})
expect(history.length).toStrictEqual(6)
expect(history.every(({ amounts }) => amounts[0].includes('DFI'))).toStrictEqual(true)
})

it('should listBurnHistory with maxBlockHeight 105', async () => {
const maxBlockHeight = 105
const history = await client.account.listBurnHistory()
const maxBlockHeightHistory = await client.account.listBurnHistory({
maxBlockHeight
})

expect(maxBlockHeightHistory.every(({ blockHeight }) => blockHeight <= maxBlockHeight)).toStrictEqual(true)
expect(history.every(({ blockHeight }) => blockHeight <= maxBlockHeight)).toStrictEqual(false)
})

it('should listBurnHistory with depth 5', async () => {
const depth = 5
const history = await client.account.listBurnHistory()
const depthHistory = await client.account.listBurnHistory({
depth
})
const maxBlockHeight = Math.max(...history.map(el => el.blockHeight)) // Get maxBlockHeight from history

expect(depthHistory.every(({ blockHeight }) => blockHeight >= maxBlockHeight - depth)).toStrictEqual(true)
expect(history.every(({ blockHeight }) => blockHeight >= maxBlockHeight - depth)).toStrictEqual(false)
})

it('should listBurnHistory with limit 5', async () => {
const history = await client.account.listBurnHistory()
const historyWithLimit = await client.account.listBurnHistory({
limit: 5
})
expect(historyWithLimit.length).toStrictEqual(5)
expect(historyWithLimit.slice(0, 5)).toStrictEqual(history.slice(0, 5))
})
})
41 changes: 40 additions & 1 deletion packages/jellyfish-api-core/src/category/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export enum DfTxType {
CREATE_POOL_PAIR = 'p',
UPDATE_POOL_PAIR = 'u',
SET_GOV_VARIABLE = 'G',
AUTO_AUTH_PREP = 'A'
AUTO_AUTH_PREP = 'A',
NONE = '0'
}

export enum SelectionModeType {
Expand Down Expand Up @@ -343,6 +344,25 @@ export class Account {
async listCommunityBalances (): Promise<CommunityBalanceData> {
return await this.client.call('listcommunitybalances', [], 'bignumber')
}

/**
* Returns information about burn history
*
* @param {BurnHistoryOptions} [options]
* @param {number} [options.maxBlockHeight] The block height to iterate from.
* @param {number} [options.depth] Maximum depth, from the genesis block is the default
* @param {string} [options.token] Filter by token
* @param {DfTxType} [options.txtype] Filter by transaction type. See DfTxType.
* @param {number} [options.limit=100] Maximum number of records to return, 100 by default
* @return {Promise<BurnHistory[]>}
*/
async listBurnHistory (
options: BurnHistoryOptions = {
limit: 100
}
): Promise<BurnHistory[]> {
return await this.client.call('listburnhistory', [options], 'number')
}
}

export interface AccountPagination {
Expand Down Expand Up @@ -438,3 +458,22 @@ export interface CommunityBalanceData {
Unallocated?: BigNumber
Unknown?: BigNumber
}

export interface BurnHistoryOptions {
maxBlockHeight?: number
depth?: number
token?: string
txtype?: DfTxType
limit?: number
}

export interface BurnHistory {
owner: string
blockHeight: number
blockHash: string
blockTime: number
type: string
txn: number
txid: string
amounts: string[]
}
58 changes: 56 additions & 2 deletions website/docs/jellyfish/api/account.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ enum DfTxType {
CREATE_POOL_PAIR = 'p',
UPDATE_POOL_PAIR = 'u',
SET_GOV_VARIABLE = 'G',
AUTO_AUTH_PREP = 'A'
AUTO_AUTH_PREP = 'A',
NONE = '0'
}

interface AccountHistory {
Expand Down Expand Up @@ -274,7 +275,8 @@ enum DfTxType {
CREATE_POOL_PAIR = 'p',
UPDATE_POOL_PAIR = 'u',
SET_GOV_VARIABLE = 'G',
AUTO_AUTH_PREP = 'A'
AUTO_AUTH_PREP = 'A',
NONE = '0'
}

interface AccountHistoryCountOptions {
Expand Down Expand Up @@ -334,3 +336,55 @@ interface CommunityBalanceData {
Unknown?: BigNumber
}
```

## listBurnHistory

Returns information about burn history

```ts title="client.account.listBurnHistory()"
interface account {
listBurnHistory (
options: BurnHistoryOptions = { limit: 100 }
): Promise<BurnHistory[]>
}

enum DfTxType {
MINT_TOKEN = 'M',
POOL_SWAP = 's',
ADD_POOL_LIQUIDITY = 'l',
REMOVE_POOL_LIQUIDITY = 'r',
UTXOS_TO_ACCOUNT = 'U',
ACCOUNT_TO_UTXOS = 'b',
ACCOUNT_TO_ACCOUNT = 'B',
ANY_ACCOUNTS_TO_ACCOUNTS = 'a',
CREATE_MASTERNODE = 'C',
RESIGN_MASTERNODE = 'R',
CREATE_TOKEN = 'T',
UPDATE_TOKEN = 'N',
UPDATE_TOKEN_ANY = 'n',
CREATE_POOL_PAIR = 'p',
UPDATE_POOL_PAIR = 'u',
SET_GOV_VARIABLE = 'G',
AUTO_AUTH_PREP = 'A',
NONE = '0'
}

interface BurnHistoryOptions {
maxBlockHeight?: number
depth?: number
token?: string
txtype?: DfTxType
limit?: number
}

interface BurnHistory {
owner: string
blockHeight: number
blockHash: string
blockTime: number
type: string
txn: number
txid: string
amounts: string[]
}
```

0 comments on commit 102aa0b

Please sign in to comment.