diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts new file mode 100644 index 0000000000..5bb58dd16f --- /dev/null +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -0,0 +1,482 @@ +import { MasterNodeRegTestContainer } from '@defichain/testcontainers' +import { ContainerAdapterClient } from '../container_adapter_client' +import waitForExpect from 'wait-for-expect' +import BigNumber from 'bignumber.js' + +describe('masternode', () => { + const container = new MasterNodeRegTestContainer() + const client = new ContainerAdapterClient(container) + + beforeAll(async () => { + await container.start() + await container.waitForReady() + await container.waitForWalletCoinbaseMaturity() + await container.waitForWalletBalanceGTE(300) + + await setup() + }) + + afterAll(async () => { + await container.stop() + }) + + async function setup (): Promise { + await container.generate(100) + + const from = await container.call('getnewaddress') + await createToken(from, 'DBTC', 200) + + const to = await accountToAccount('DBTC', 5, from) + await accountToAccount('DBTC', 18, from, to) + + await createToken(from, 'DETH', 200) + await accountToAccount('DETH', 46, from) + } + + async function createToken (address: string, symbol: string, amount: number): Promise { + const metadata = { + symbol, + name: symbol, + isDAT: true, + mintable: true, + tradeable: true, + collateralAddress: address + } + await container.call('createtoken', [metadata]) + await container.generate(25) + + await container.call('minttokens', [`${amount.toString()}@${symbol}`]) + await container.generate(25) + } + + async function accountToAccount (symbol: string, amount: number, from: string, _to = ''): Promise { + const to = _to !== '' ? _to : await container.call('getnewaddress') + + await container.call('accounttoaccount', [from, { [to]: `${amount.toString()}@${symbol}` }]) + await container.generate(25) + + return to + } + + async function waitForListingAccounts (): Promise { + let accounts: any[] = [] + + await waitForExpect(async () => { + accounts = await client.account.listAccounts() + expect(accounts.length).toBeGreaterThan(0) + }) + + return accounts + } + + describe('listAccounts', () => { + it('should listAccounts', async () => { + await waitForListingAccounts() + + const accounts = await client.account.listAccounts() + + for (let i = 0; i < accounts.length; i += 1) { + const account = accounts[i] + expect(typeof account.key).toBe('string') + expect(typeof account.owner === 'object').toBe(true) + expect(typeof account.owner.asm).toBe('string') + expect(account.owner.reqSigs instanceof BigNumber).toBe(true) + expect(typeof account.owner.type).toBe('string') + expect(account.owner.addresses.length).toBeGreaterThan(0) + expect(typeof account.amount).toBe('string') // 10.00000000@DFI + } + }) + + it('should listAccounts with pagination start and including_start', async () => { + const accounts = await waitForListingAccounts() + + const pagination = { + start: accounts[accounts.length - 1].key, + including_start: true + } + + const lastAccounts = await client.account.listAccounts(pagination) + expect(lastAccounts.length).toBe(1) + }) + + it('should listAccounts with pagination.limit', async () => { + await waitForExpect(async () => { + const pagination = { + limit: 2 + } + const accounts = await client.account.listAccounts(pagination) + expect(accounts.length).toBe(2) + }) + }) + + it('should listAccounts with verbose false and indexed_amounts false', async () => { + await waitForListingAccounts() + + const accounts = await client.account.listAccounts({}, false, { indexedAmounts: false, isMineOnly: false }) + + for (let i = 0; i < accounts.length; i += 1) { + const account = accounts[i] + expect(typeof account.key).toBe('string') + expect(typeof account.owner).toBe('string') + expect(typeof account.amount).toBe('string') // 10.00000000@DFI + } + }) + + it('should listAccounts with verbose false and indexed_amounts true', async () => { + await waitForListingAccounts() + + const accounts = await client.account.listAccounts({}, false, { indexedAmounts: true, isMineOnly: false }) + + for (let i = 0; i < accounts.length; i += 1) { + const account = accounts[i] + expect(typeof account.key).toBe('string') + expect(typeof account.owner).toBe('string') + + expect(typeof account.amount === 'object').toBe(true) + for (const k in account.amount) { + expect(account.amount[k] instanceof BigNumber).toBe(true) // [{'0': 100}] + } + } + }) + + it('should listAccounts with verbose true and indexed_amounts true', async () => { + await waitForListingAccounts() + + const accounts = await client.account.listAccounts({}, true, { indexedAmounts: true, isMineOnly: false }) + + for (let i = 0; i < accounts.length; i += 1) { + const account = accounts[i] + expect(typeof account.key).toBe('string') + expect(typeof account.owner === 'object').toBe(true) + expect(typeof account.owner.asm).toBe('string') + expect(account.owner.reqSigs instanceof BigNumber).toBe(true) + expect(typeof account.owner.type).toBe('string') + expect(account.owner.addresses.length).toBeGreaterThan(0) + + expect(typeof account.amount === 'object').toBe(true) + for (const k in account.amount) { + expect(account.amount[k] instanceof BigNumber).toBe(true) // [{'0': 100}] + } + } + }) + + it('should listAccounts with verbose true and indexed_amounts false', async () => { + await waitForListingAccounts() + + const accounts = await client.account.listAccounts({}, true, { indexedAmounts: false, isMineOnly: false }) + + for (let i = 0; i < accounts.length; i += 1) { + const account = accounts[i] + expect(typeof account.key).toBe('string') + expect(typeof account.owner === 'object').toBe(true) + expect(typeof account.owner.asm).toBe('string') + expect(account.owner.reqSigs instanceof BigNumber).toBe(true) + expect(typeof account.owner.type).toBe('string') + expect(account.owner.addresses.length).toBeGreaterThan(0) + expect(typeof account.amount).toBe('string') // 10.00000000@DFI + } + }) + + it('should listAccounts with isMineOnly true', async () => { + await waitForListingAccounts() + + const accounts = await client.account.listAccounts({}, true, { indexedAmounts: false, isMineOnly: true }) + + for (let i = 0; i < accounts.length; i += 1) { + const account = accounts[i] + expect(typeof account.key).toBe('string') + expect(typeof account.owner === 'object').toBe(true) + expect(typeof account.owner.asm).toBe('string') + expect(account.owner.reqSigs instanceof BigNumber).toBe(true) + expect(typeof account.owner.type).toBe('string') + expect(account.owner.addresses.length).toBeGreaterThan(0) + expect(typeof account.amount).toBe('string') // 10.00000000@DFI + } + }) + }) + + describe('getAccount', () => { + it('should getAccount', async () => { + const accounts = await waitForListingAccounts() + + // [ '187.00000000@DBTC', '154.00000000@DETH' ] + const account = await client.account.getAccount(accounts[0].owner.addresses[0]) + expect(account.length).toBeGreaterThan(0) + for (let i = 0; i < account.length; i += 1) { + expect(typeof account[i]).toBe('string') + } + }) + + it('should getAccount with pagination start and including_start', async () => { + let accounts: any[] = [] + let beforeAccountCount = 0 + + await waitForExpect(async () => { + accounts = await client.account.listAccounts() + expect(accounts.length).toBeGreaterThan(0) + + const account = await client.account.getAccount(accounts[0].owner.addresses[0]) + beforeAccountCount = account.length + }) + + const pagination = { + start: beforeAccountCount, + including_start: true + } + + // [ '187.00000000@DBTC', '154.00000000@DETH' ] + const account = await client.account.getAccount(accounts[0].owner.addresses[0], pagination) + expect(account.length).toBe(1) + + for (let i = 0; i < account.length; i += 1) { + expect(typeof account[i]).toBe('string') + } + }) + + it('should getAccount with pagination.limit', async () => { + const accounts = await waitForListingAccounts() + + const pagination = { + limit: 1 + } + const account = await client.account.getAccount(accounts[0].owner.addresses[0], pagination) + expect(account.length).toBe(1) + }) + + it('should getAccount with indexedAmount true', async () => { + const accounts = await waitForListingAccounts() + + const account = await client.account.getAccount(accounts[0].owner.addresses[0], {}, { indexedAmounts: true }) + expect(typeof account).toBe('object') + for (const k in account) { + expect(typeof account[k]).toBe('number') + } + }) + }) + + describe('getTokenBalances', () => { + it('should getTokenBalances', async () => { + await waitForExpect(async () => { + const tokenBalances = await client.account.getTokenBalances() + expect(tokenBalances.length).toBeGreaterThan(0) + }) + + const tokenBalances = await client.account.getTokenBalances() + for (let i = 0; i < tokenBalances.length; i += 1) { + expect(typeof tokenBalances[i]).toBe('string') // [ '300.00000000@0', '200.00000000@1' ] + } + }) + + it('should getTokenBalances with pagination start and including_start', async () => { + let id = '' + + await waitForExpect(async () => { + const tokenBalances = await client.account.getTokenBalances() // [ '300.00000000@0', '200.00000000@1' ] + expect(tokenBalances.length).toBeGreaterThan(0) + + id = tokenBalances[tokenBalances.length - 1].split('@')[1] + }) + + const pagination = { + start: Number(id), + including_start: true + } + const tokenBalances = await client.account.getTokenBalances(pagination) + expect(tokenBalances.length).toBe(1) + }) + + it('should getTokenBalances with pagination limit', async () => { + await waitForExpect(async () => { + const tokenBalances = await client.account.getTokenBalances() + expect(tokenBalances.length).toBe(2) + }) + const pagination = { + limit: 1 + } + const tokenBalances = await client.account.getTokenBalances(pagination) + expect(tokenBalances.length).toBe(1) + }) + + it('should getTokenBalances with indexedAmounts true', async () => { + await waitForExpect(async () => { + const tokenBalances = await client.account.getTokenBalances({}, true, { symbolLookup: false }) + expect(typeof tokenBalances === 'object').toBe(true) + for (const k in tokenBalances) { + expect(tokenBalances[k] instanceof BigNumber).toBe(true) + } + }) + }) + + it('should getTokenBalances with symbolLookup', async () => { + await waitForExpect(async () => { + const tokenBalances = await client.account.getTokenBalances({}, false, { symbolLookup: true }) + expect(tokenBalances.length).toBeGreaterThan(0) + }) + + const tokenBalances = await client.account.getTokenBalances({}, false, { symbolLookup: true }) + for (let i = 0; i < tokenBalances.length; i += 1) { + expect(typeof tokenBalances[i]).toBe('string') // [ '300.00000000@DFI', '200.00000000@DBTC' ] + } + }) + }) + + describe('listAccountHistory', () => { + it('should listAccountHistory', async () => { + await waitForExpect(async () => { + const accountHistories = await client.account.listAccountHistory() + expect(accountHistories.length).toBeGreaterThan(0) + }) + + const accountHistories = await client.account.listAccountHistory() + + for (let i = 0; i < accountHistories.length; i += 1) { + const accountHistory = accountHistories[i] + expect(typeof accountHistory.owner).toBe('string') + expect(typeof accountHistory.blockHeight).toBe('number') + expect(typeof accountHistory.blockHash).toBe('string') + expect(typeof accountHistory.blockTime).toBe('number') + expect(typeof accountHistory.type).toBe('string') + expect(typeof accountHistory.txn).toBe('number') + expect(typeof accountHistory.txid).toBe('string') + expect(accountHistory.amounts.length).toBeGreaterThan(0) + expect(typeof accountHistory.amounts[0]).toBe('string') // [ '10.00000000@DFI' ] + } + }) + + it('should listAccountHistory with owner "all"', async () => { + await waitForExpect(async () => { + const accountHistories = await client.account.listAccountHistory('all') + expect(accountHistories.length).toBeGreaterThan(0) + }) + + const accountHistories = await client.account.listAccountHistory('all') + + for (let i = 0; i < accountHistories.length; i += 1) { + const accountHistory = accountHistories[i] + expect(typeof accountHistory.owner).toBe('string') + expect(typeof accountHistory.blockHeight).toBe('number') + expect(typeof accountHistory.blockHash).toBe('string') + expect(typeof accountHistory.blockTime).toBe('number') + expect(typeof accountHistory.type).toBe('string') + expect(typeof accountHistory.txn).toBe('number') + expect(typeof accountHistory.txid).toBe('string') + expect(accountHistory.amounts.length).toBeGreaterThan(0) + expect(typeof accountHistory.amounts[0]).toBe('string') + } + }) + + it('should listAccountHistory with owner CScript', async () => { + const accounts = await waitForListingAccounts() + + const { owner } = accounts[0] + const { hex, addresses } = owner + + const accountHistories = await client.account.listAccountHistory(hex) + + for (let i = 0; i < accountHistories.length; i += 1) { + const accountHistory = accountHistories[i] + expect(addresses.includes(accountHistory.owner)).toBe(true) + } + }) + + it('should listAccountHistory with owner address', async () => { + let address = '' + + await waitForExpect(async () => { + const accountHistories = await client.account.listAccountHistory() + expect(accountHistories.length).toBeGreaterThan(0) + address = accountHistories[0].owner + }) + + const accountHistories = await client.account.listAccountHistory(address) + for (let i = 0; i < accountHistories.length; i += 1) { + const accountHistory = accountHistories[i] + expect(accountHistory.owner).toBe(address) + } + }) + + it('should listAccountHistory with options maxBlockHeight', async () => { + const options = { + maxBlockHeight: 80 + } + await waitForExpect(async () => { + const accountHistories = await client.account.listAccountHistory('mine', options) + expect(accountHistories.length).toBeGreaterThan(0) + }) + + const accountHistories = await client.account.listAccountHistory('mine', options) + for (let i = 0; i < accountHistories.length; i += 1) { + const accountHistory = accountHistories[i] + expect(accountHistory.blockHeight).toBeLessThanOrEqual(80) + } + }) + + it('should listAccountHistory with options depth', async () => { + await waitForExpect(async () => { + const depth = 10 + const accountHistories = await client.account.listAccountHistory('mine', { depth }) + expect(accountHistories.length).toBe(depth + 1) // plus 1 to include zero index + }) + }) + + it('should listAccountHistory with options no_rewards', async () => { + const options = { + no_rewards: true + } + await waitForExpect(async () => { + const accountHistories = await client.account.listAccountHistory('mine', options) + expect(accountHistories.length).toBeGreaterThan(0) + }) + + const accountHistories = await client.account.listAccountHistory('mine', options) + for (let i = 0; i < accountHistories.length; i += 1) { + const accountHistory = accountHistories[i] + expect(accountHistory.txn).not.toBe('blockReward') + } + }) + + it('should listAccountHistory with options token', async () => { + const options = { + token: 'DBTC' + } + await waitForExpect(async () => { + const accountHistories = await client.account.listAccountHistory('mine', options) + expect(accountHistories.length).toBeGreaterThan(0) + }) + + const accountHistories = await client.account.listAccountHistory('mine', options) + for (let i = 0; i < accountHistories.length; i += 1) { + const accountHistory = accountHistories[i] + expect(accountHistory.amounts.length).toBeGreaterThan(0) + for (let j = 0; j < accountHistory.amounts.length; j += 1) { + const amount = accountHistory.amounts[j] + const symbol = amount.split('@')[1] + expect(symbol).toBe('DBTC') + } + } + }) + + it('should listAccountHistory with options txtype', async () => { + await waitForExpect(async () => { + const accountHistories = await client.account.listAccountHistory('mine', { txtype: 'M' }) + expect(accountHistories.length).toBeGreaterThan(0) + }) + + const accountHistories = await client.account.listAccountHistory('mine', { txtype: 'M' }) + for (let i = 0; i < accountHistories.length; i += 1) { + const accountHistory = accountHistories[i] + expect(accountHistory.type).toBe('MintToken') + } + }) + + it('should listAccountHistory with options limit', async () => { + await waitForExpect(async () => { + const options = { + limit: 1 + } + const accountHistories = await client.account.listAccountHistory('mine', options) + expect(accountHistories.length).toBe(1) + }) + }) + }) +}) diff --git a/packages/jellyfish-api-core/src/category/account.ts b/packages/jellyfish-api-core/src/category/account.ts new file mode 100644 index 0000000000..3ea3d49567 --- /dev/null +++ b/packages/jellyfish-api-core/src/category/account.ts @@ -0,0 +1,279 @@ +import BigNumber from 'bignumber.js' +import { ApiClient } from '../.' + +/** + * Single account ID (CScript or address) or reserved words, + * 'mine' to list history for all owned accounts or + * 'all' to list the whole DB + */ +type OwnerType = 'mine' | 'all' | string + +/** + * Account RPCs for DeFi Blockchain + */ +export class Account { + private readonly client: ApiClient + + constructor (client: ApiClient) { + this.client = client + } + + /** + * Get information about all accounts on chain + * Return account with object owner info, addresses and amount with tokenId + * + * @param {AccountPagination} [pagination] + * @param {string} [pagination.start] + * @param {boolean} [pagination.including_start] + * @param {number} [pagination.limit=100] + * @param {boolean} [verbose=true] default = true, otherwise limited objects are listed + * @param {ListAccountOptions} [options] default = true, otherwise limited objects are listed + * @param {boolean} [options.indexedAmounts=false] format of amount output, default = false (true: {tokenid:amount}, false: amount@tokenid) + * @param {boolean} [options.isMineOnly=false] get balances about all accounts belonging to the wallet + * @return {Promise>>} + */ + listAccounts (pagination?: AccountPagination, verbose?: boolean, options?: ListAccountOptions): Promise>> + + /** + * Get information about all accounts on chain + * Return account with hex-encoded owner info, addresses and amount with tokenId + * + * @param {AccountPagination} [pagination] + * @param {string} [pagination.start] + * @param {boolean} [pagination.including_start] + * @param {number} [pagination.limit=100] + * @param {boolean} [verbose=true] default = true, otherwise limited objects are listed + * @param {ListAccountOptions} [options] default = true, otherwise limited objects are listed + * @param {boolean} [options.indexedAmounts=false] format of amount output, default = false (true: {tokenid:amount}, false: amount@tokenid) + * @param {boolean} [options.isMineOnly=false] get balances about all accounts belonging to the wallet + * @return {Promise>>} + */ + listAccounts (pagination: AccountPagination, verbose: false, options: {indexedAmounts: false, isMineOnly: boolean}): Promise>> + + /** + * Get information about all accounts on chain + * Return account with object owner info, addresses and object with indexed amount + * + * @param {AccountPagination} [pagination] + * @param {string} [pagination.start] + * @param {boolean} [pagination.including_start] + * @param {number} [pagination.limit=100] + * @param {boolean} [verbose=true] default = true, otherwise limited objects are listed + * @param {ListAccountOptions} [options] default = true, otherwise limited objects are listed + * @param {boolean} [options.indexedAmounts=false] format of amount output, default = false (true: {tokenid:amount}, false: amount@tokenid) + * @param {boolean} [options.isMineOnly=false] get balances about all accounts belonging to the wallet + * @return {Promise>>} + */ + listAccounts (pagination: AccountPagination, verbose: true, options: {indexedAmounts: true, isMineOnly: boolean}): Promise>> + + /** + * Get information about all accounts on chain + * Return account with hex-encoded owner info, addresses and object with indexed amount + * + * @param {AccountPagination} [pagination] + * @param {string} [pagination.start] + * @param {boolean} [pagination.including_start] + * @param {number} [pagination.limit=100] + * @param {boolean} [verbose=true] default = true, otherwise limited objects are listed + * @param {ListAccountOptions} [options] default = true, otherwise limited objects are listed + * @param {boolean} [options.indexedAmounts=false] format of amount output, default = false (true: {tokenid:amount}, false: amount@tokenid) + * @param {boolean} [options.isMineOnly=false] get balances about all accounts belonging to the wallet + * @return {Promise>>} + */ + listAccounts (pagination: AccountPagination, verbose: false, options: {indexedAmounts: true, isMineOnly: boolean}): Promise>> + + async listAccounts ( + pagination: AccountPagination = { limit: 100 }, + verbose = true, + options: ListAccountOptions = { indexedAmounts: false, isMineOnly: false } + ): Promise>> { + const { indexedAmounts, isMineOnly } = options + return await this.client.call('listaccounts', [pagination, verbose, indexedAmounts, isMineOnly], 'bignumber') + } + + /** + * Get information about account + * Return an object account with indexed amount + * + * @param {string} owner address in base58/bech32/hex encoding + * @param {AccountPagination} [pagination] + * @param {string | number} [pagination.start] + * @param {boolean} [pagination.including_start] + * @param {number} [pagination.limit=100] + * @param {GetAccountOptions} [options] + * @param {boolean} [options.indexedAmounts=false] format of amount output, default = false (true: {tokenid:amount}, false: amount@tokenid) + * @return {Promise + + /** + * Get information about account + * Return an array of amount with tokenId + * + * @param {string} owner address in base58/bech32/hex encoding + * @param {AccountPagination} [pagination] + * @param {string | number} [pagination.start] + * @param {boolean} [pagination.including_start] + * @param {number} [pagination.limit=100] + * @param {GetAccountOptions} [options] + * @param {boolean} [options.indexedAmounts=false] format of amount output, default = false (true: {tokenid:amount}, false: amount@tokenid) + * @return {Promise | AccountAmount} resolves as ['60.00000000@DFI'] + */ + getAccount (owner: string, pagination?: AccountPagination, options?: GetAccountOptions): Promise + + async getAccount ( + owner: string, + pagination: AccountPagination = { limit: 100 }, + options: GetAccountOptions = { indexedAmounts: false } + ): Promise { + const { indexedAmounts = false } = options + return await this.client.call('getaccount', [owner, pagination, indexedAmounts], 'number') + } + + /** + * Get the balances of all accounts that belong to the wallet + * Return an array of amount with index + * + * @param {AccountPagination} [pagination] + * @param {string} [pagination.start] + * @param {boolean} [pagination.including_start] + * @param {number} [pagination.limit=100] + * @param {boolean} [indexedAmounts=false] format of amount output, default = false (true: {tokenid:amount}, false: amount@tokenid) + * @param {GetTokenBalancesOptions} [options] + * @param {boolean} [options.symbolLookup=false] use token symbols in output, default = false + * @return {Promise} resolves as [ '300.00000000@0', '200.00000000@1' ] + */ + getTokenBalances (pagination?: AccountPagination, indexedAmounts?: boolean, options?: GetTokenBalancesOptions): Promise + + /** + * Get the balances of all accounts that belong to the wallet + * Return object amount with index + * + * @param {AccountPagination} [pagination] + * @param {string} [pagination.start] + * @param {boolean} [pagination.including_start] + * @param {number} [pagination.limit=100] + * @param {boolean} [indexedAmounts=false] format of amount output, default = false (true: {tokenid:amount}, false: amount@tokenid) + * @param {GetTokenBalancesOptions} [options] + * @param {boolean} [options.symbolLookup=false] use token symbols in output, default = false + * @return {Promise} resolves as { '0': 300, '1': 200 } + */ + getTokenBalances (pagination: AccountPagination, indexedAmounts: true, options: { symbolLookup: false }): Promise + + /** + * Get the balances of all accounts that belong to the wallet + * Return array of amount with tokenId + * + * @param {AccountPagination} [pagination] + * @param {string} [pagination.start] + * @param {boolean} [pagination.including_start] + * @param {number} [pagination.limit=100] + * @param {boolean} [indexedAmounts=false] format of amount output, default = false (true: {tokenid:amount}, false: amount@tokenid) + * @param {GetTokenBalancesOptions} [options] + * @param {boolean} [options.symbolLookup=false] use token symbols in output, default = false + * @return {Promise} resolves as [ '300.00000000@DFI', '200.00000000@DBTC' ] + */ + getTokenBalances (pagination: AccountPagination, indexedAmounts: false, options: { symbolLookup: true }): Promise + + /** + * Get the balances of all accounts that belong to the wallet + * Return object amount with tokenId + * + * @param {AccountPagination} [pagination] + * @param {string} [pagination.start] + * @param {boolean} [pagination.including_start] + * @param {number} [pagination.limit=100] + * @param {boolean} [indexedAmounts=false] format of amount output, default = false (true: {tokenid:amount}, false: amount@tokenid) + * @param {GetTokenBalancesOptions} [options] + * @param {boolean} [options.symbolLookup=false] use token symbols in output, default = false + * @return {Promise} resolves as { DFI: 300, DBTC: 200 } + */ + getTokenBalances (pagination: AccountPagination, indexedAmounts: true, options: { symbolLookup: true }): Promise + + async getTokenBalances ( + pagination: AccountPagination = { limit: 100 }, + indexedAmounts = false, + options: GetTokenBalancesOptions = { symbolLookup: false } + ): Promise { + const { symbolLookup } = options + return await this.client.call('gettokenbalances', [pagination, indexedAmounts, symbolLookup], 'bignumber') + } + + /** + * Returns information about account history + * + * @param {OwnerType} [owner='mine'] single account ID (CScript or address) or reserved words 'mine' to list history for all owned accounts or 'all' to list whole DB + * @param {AccountHistoryOptions} [options] + * @param {number} [options.maxBlockHeight] Optional height to iterate from (downto genesis block), (default = chaintip). + * @param {number} [options.depth] Maximum depth, from the genesis block is the default + * @param {boolean} [options.no_rewards] Filter out rewards + * @param {string} [options.token] Filter by token + * @param {string} [options.txtype] Filter by transaction type, supported letter from 'CRTMNnpuslrUbBG + * @param {number} [options.limit=100] Maximum number of records to return, 100 by default + * @return {Promise} + */ + async listAccountHistory ( + owner: OwnerType = 'mine', + options: AccountHistoryOptions = { + limit: 100 + } + ): Promise { + return await this.client.call('listaccounthistory', [owner, options], 'number') + } +} + +export interface AccountPagination { + start?: string | number + including_start?: boolean + limit?: number +} + +export interface AccountResult { + key: string + owner: T // string | AccountOwner + amount: U // string | AccountAmount +} + +export interface AccountOwner { + asm: string + reqSigs: BigNumber + type: string + addresses: string[] +} + +export interface AccountAmount { + [id: string]: BigNumber +} + +export interface ListAccountOptions { + indexedAmounts?: boolean + isMineOnly?: boolean +} + +export interface GetAccountOptions { + indexedAmounts?: boolean +} + +export interface GetTokenBalancesOptions { + symbolLookup?: boolean +} + +export interface AccountHistory { + owner: string + blockHeight: number + blockHash: string + blockTime: number + type: string + txn: number + txid: string + amounts: string[] +} + +export interface AccountHistoryOptions { + maxBlockHeight?: number + depth?: number + no_rewards?: boolean + token?: string + txtype?: string + limit?: number +} diff --git a/packages/jellyfish-api-core/src/index.ts b/packages/jellyfish-api-core/src/index.ts index 8086b0e7ed..55e78f068f 100644 --- a/packages/jellyfish-api-core/src/index.ts +++ b/packages/jellyfish-api-core/src/index.ts @@ -3,6 +3,7 @@ import { Blockchain } from './category/blockchain' import { Mining } from './category/mining' import { RawTx } from './category/rawtx' import { Wallet } from './category/wallet' +import { Account } from './category/account' import { PoolPair } from './category/poolpair' import { Token } from './category/token' @@ -14,6 +15,7 @@ export * as rawtx from './category/rawtx' export * as wallet from './category/wallet' export * as poolpair from './category/poolpair' export * as token from './category/token' +export * as account from './category/account' /** * A protocol agnostic DeFiChain node client, RPC calls are separated into their category. @@ -23,6 +25,7 @@ export abstract class ApiClient { public readonly mining = new Mining(this) public readonly rawtx = new RawTx(this) public readonly wallet = new Wallet(this) + public readonly account = new Account(this) public readonly poolpair = new PoolPair(this) public readonly token = new Token(this) diff --git a/website/docs/jellyfish/api/account.md b/website/docs/jellyfish/api/account.md new file mode 100644 index 0000000000..98854cddaf --- /dev/null +++ b/website/docs/jellyfish/api/account.md @@ -0,0 +1,144 @@ +--- +id: account +title: Account API +sidebar_label: Account API +slug: /jellyfish/api/account +--- + +```js +import {Client} from '@defichain/jellyfish' +const client = new Client() +// Using client.account. +const something = await client.account.method() +``` + +## listAccounts + +Returns information about all accounts on chain + +```ts title="client.account.listAccounts()" +interface account { + listAccounts (pagination?: AccountPagination, verbose?: boolean, options?: ListAccountOptions): Promise>> + listAccounts (pagination: AccountPagination, verbose: false, options: {indexedAmounts: false, isMineOnly: boolean}): Promise>> + listAccounts (pagination: AccountPagination, verbose: true, options: {indexedAmounts: true, isMineOnly: boolean}): Promise>> + listAccounts (pagination: AccountPagination, verbose: false, options: {indexedAmounts: true, isMineOnly: boolean}): Promise>> + listAccounts ( + pagination: AccountPagination = { limit: 100 }, + verbose = true, + options: ListAccountOptions = { indexedAmounts: false, isMineOnly: false } + ): Promise>> +} + +interface AccountPagination { + start?: string | number + including_start?: boolean + limit?: number +} + +interface AccountResult { + key: string + owner: T // string | AccountOwner (if verbose true) + amount: U // string | AccountAmount (if options.indexedAmounts true) +} + +interface AccountOwner { + asm: string + reqSigs: BigNumber + type: string + addresses: string[] +} + +interface AccountAmount { + [id: string]: BigNumber +} + +interface ListAccountOptions { + indexedAmounts?: boolean + isMineOnly?: boolean +} +``` + +## getAccount + +Returns information about account + +```ts title="client.account.getAccount()" +interface account { + getAccount (owner: string, pagination: AccountPagination, options: { indexedAmounts: true }): Promise + getAccount (owner: string, pagination?: AccountPagination, options?: GetAccountOptions): Promise + getAccount ( + owner: string, + pagination: AccountPagination = { limit: 100 }, + options: GetAccountOptions = { indexedAmounts: false } + ): Promise +} +``` + +## getTokenBalances + +Returns the balances of all accounts that belong to the wallet + +```ts title="client.account.getTokenBalances()" +interface account { + getTokenBalances (pagination?: AccountPagination, indexedAmounts?: boolean, options?: GetTokenBalancesOptions): Promise + getTokenBalances (pagination: AccountPagination, indexedAmounts: true, options: { symbolLookup: false }): Promise + getTokenBalances (pagination: AccountPagination, indexedAmounts: false, options: { symbolLookup: true }): Promise + getTokenBalances (pagination: AccountPagination, indexedAmounts: true, options: { symbolLookup: true }): Promise + getTokenBalances ( + pagination: AccountPagination = { limit: 100 }, + indexedAmounts = false, + options: GetTokenBalancesOptions = { symbolLookup: false} + ): Promise +} + +interface AccountAmount { + [id: string]: BigNumber +} + +interface AccountPagination { + start?: string | number + including_start?: boolean + limit?: number +} + +interface GetTokenBalancesOptions { + symbolLookup?: boolean +} +``` + +## listAccountHistory + +Returns information about account history + +```ts title="client.account.listAccountHistory()" +interface account { + async listAccountHistory ( + owner: OwnerType = 'mine', + options: AccountHistoryOptions = { + limit: 100 + } + ): Promise +} + +type OwnerType = 'mine' | 'all' | string + +interface AccountHistory { + owner: string + blockHeight: number + blockHash: string + blockTime: number + type: string + txn: number + txid: string + amounts: string[] +} + +interface AccountHistoryOptions { + maxBlockHeight?: number + depth?: number + no_rewards?: boolean + token?: string + txtype?: string + limit?: number +} +``` \ No newline at end of file diff --git a/website/sidebars.js b/website/sidebars.js index 2748b9b58e..40b8a0a040 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -13,7 +13,8 @@ module.exports = { 'jellyfish/api/rawtx', 'jellyfish/api/wallet', 'jellyfish/api/poolpair', - 'jellyfish/api/token' + 'jellyfish/api/token', + 'jellyfish/api/account' ] } ],