From 075a7e0c2db4eaa8101354ac0b75e586a6086422 Mon Sep 17 00:00:00 2001 From: websterlcl Date: Wed, 14 Apr 2021 21:52:14 +0800 Subject: [PATCH 01/14] listpoolpairs, getpoolpair, listpoolshares, test on hold --- .../__tests__/category/pool_pair.test.ts | 91 ++++++++++++++ .../src/category/pool_pair.ts | 117 ++++++++++++++++++ packages/jellyfish-api-core/src/index.ts | 3 + website/docs/jellyfish/api/pool_pair.md | 87 +++++++++++++ 4 files changed, 298 insertions(+) create mode 100644 packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts create mode 100644 packages/jellyfish-api-core/src/category/pool_pair.ts create mode 100644 website/docs/jellyfish/api/pool_pair.md diff --git a/packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts b/packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts new file mode 100644 index 0000000000..c2e10f0643 --- /dev/null +++ b/packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts @@ -0,0 +1,91 @@ +import { RegTestContainer, MasterNodeRegTestContainer } from '@defichain/testcontainers' +import { ContainerAdapterClient } from '../container_adapter_client' +import waitForExpect from 'wait-for-expect' + +describe.skip('non masternode', () => { + const container = new RegTestContainer() + const client = new ContainerAdapterClient(container) + + beforeAll(async () => { + await container.start() + await container.waitForReady() + }) + + afterAll(async () => { + await container.stop() + }) + + // TODO(canonbrother): currently the pool pair is empty, no point to test for now + describe('listPoolPairs', () => { + it('should listPoolPairs', async () => { + await waitForExpect(async () => { + const poolPairs = await client.poolPair.listPoolPairs() + console.log('poolPairs: ', poolPairs) + }) + }) + }) + + // TODO(canonbrother): pool not found, test again once pool pair is up + describe('getPoolPair', () => { + it('should getPoolPair', async () => { + await waitForExpect(async () => { + const poolPair = await client.poolPair.getPoolPair('DFI') + console.log('poolPair: ', poolPair) + }) + }) + }) + + // TODO(canonbrother): empty pool shares, test again once pool shares is up + describe('listPoolShares', () => { + it('should listPoolShares', async () => { + await waitForExpect(async () => { + const poolShares = await client.poolPair.listPoolShares() + console.log('poolShares: ', poolShares) + }) + }) + }) +}) + +describe.skip('masternode', () => { + const container = new MasterNodeRegTestContainer() + const client = new ContainerAdapterClient(container) + + beforeAll(async () => { + await container.start() + await container.waitForReady() + }) + + afterAll(async () => { + await container.stop() + }) + + // TODO(canonbrother): currently the pool pair is empty, no point to test for now + describe('listPoolPairs', () => { + it('should listPoolPairs', async () => { + await waitForExpect(async () => { + const poolPairs = await client.poolPair.listPoolPairs() + console.log('poolPairs: ', poolPairs) + }) + }) + }) + + // TODO(canonbrother): pool not found, test again once pool pair is up + describe('getPoolPair', () => { + it('should getPoolPair', async () => { + await waitForExpect(async () => { + const poolPair = await client.poolPair.getPoolPair('DFI') + console.log('poolPair: ', poolPair) + }) + }) + }) + + // TODO(canonbrother): empty pool shares, test again once pool shares is up + describe('listPoolShares', () => { + it('should listPoolShares', async () => { + await waitForExpect(async () => { + const poolShares = await client.poolPair.listPoolShares() + console.log('poolShares: ', poolShares) + }) + }) + }) +}) diff --git a/packages/jellyfish-api-core/src/category/pool_pair.ts b/packages/jellyfish-api-core/src/category/pool_pair.ts new file mode 100644 index 0000000000..e35dd2c1fe --- /dev/null +++ b/packages/jellyfish-api-core/src/category/pool_pair.ts @@ -0,0 +1,117 @@ +import BigNumber from 'bignumber.js' +import { ApiClient } from '..' + +/** + * PoolPair related RPC calls for DeFiChain + */ +export class PoolPair { + private readonly client: ApiClient + + constructor (client: ApiClient) { + this.client = client + } + + /** + * Returns information about pools + * + * @param pagination + * @param verbose + * @return Promise + */ + async listPoolPairs ( + pagination: PoolPairPagination = { + start: 0, + including_start: true, + limit: 100 + }, + verbose = true + ): Promise { + return await this.client.call('listpoolpairs', [pagination, verbose], { + reserveA: 'bignumber', + reserveB: 'bignumber', + commission: 'bignumber', + totalLiquidity: 'bignumber', + 'reserveA/reserveB': 'bignumber', + 'reserveB/reserveA': 'bignumber', + blockCommissionA: 'bignumber', + blockCommissionB: 'bignumber', + rewardPct: 'bignumber', + customRewards: 'bignumber' + }) + } + + /** + * Returns information about pool + * + * @param symbol + * @param verbose + * @return Promise + */ + async getPoolPair (symbol: string, verbose = true): Promise { + return await this.client.call('getpoolpair', [symbol, verbose], 'number') + } + + /** + * Returns information about pool shares + * + * @param pagination + * @param verbose + * @param isMineOnly + * @return Promise + */ + async listPoolShares ( + pagination: PoolPairPagination = { + start: 0, + including_start: true, + limit: 100 + }, + verbose = true, + isMineOnly = false + ): Promise { + return await this.client.call('listpoolshares', [pagination, verbose, isMineOnly], { + '%': 'bignumber', + amount: 'bignumber', + totalLiquidity: 'bignumber' + }) + } +} + +export interface IPoolPair { + [id: string]: { + symbol: string + name: string + status: string + idTokenA: string + idTokenB: string + reserveA: BigNumber + reserveB: BigNumber + commission: BigNumber + totalLiquidity: BigNumber + ['reserveA/reserveB']: BigNumber + ['reserveB/reserveA']: BigNumber + tradeEnabled: boolean + ownerAddress: string + blockCommissionA: BigNumber + blockCommissionB: BigNumber + rewardPct: BigNumber + customRewards: BigNumber + creationTx: string + creationHeight: number + } +} + +export interface IPoolShare { + [id: string]: { + poolID: string + owner: string + ['%']: BigNumber + amount: BigNumber + totalLiquidity: BigNumber + } +} + +export interface PoolPairPagination { + start: number + including_start: boolean + limit: number +} diff --git a/packages/jellyfish-api-core/src/index.ts b/packages/jellyfish-api-core/src/index.ts index 4e3d5b29c0..206c9c90f8 100644 --- a/packages/jellyfish-api-core/src/index.ts +++ b/packages/jellyfish-api-core/src/index.ts @@ -2,11 +2,13 @@ import { Precision, PrecisionMapping } from '@defichain/jellyfish-json' import { Blockchain } from './category/blockchain' import { Mining } from './category/mining' import { Wallet } from './category/wallet' +import { PoolPair } from './category/pool_pair' export * from '@defichain/jellyfish-json' export * from './category/blockchain' export * from './category/mining' export * from './category/wallet' +export * from './category/pool_pair' /** * ApiClient; a protocol agnostic DeFiChain node client, RPC calls are separated into their category. @@ -15,6 +17,7 @@ export abstract class ApiClient { public readonly blockchain = new Blockchain(this) public readonly mining = new Mining(this) public readonly wallet = new Wallet(this) + public readonly poolPair = new PoolPair(this) /** * A promise based procedure call handling diff --git a/website/docs/jellyfish/api/pool_pair.md b/website/docs/jellyfish/api/pool_pair.md new file mode 100644 index 0000000000..50973b6836 --- /dev/null +++ b/website/docs/jellyfish/api/pool_pair.md @@ -0,0 +1,87 @@ +--- +id: poolPair +title: Pool Pair API +sidebar_label: Pool Pair API +slug: /jellyfish/api/pool-pair +--- + +```js +import {Client} from '@defichain/jellyfish' +const client = new Client() +// Using client.poolPair. +const something = await client.poolPair.method() +``` + +## listPoolPairs + +Returns information about pools + +```ts title="client.poolPair.listPoolPairs()" +interface poolPair { + listPoolPairs ( + pagination: PoolPairPagination = { + start: 0, + including_start: true, + limit: 100 + }, + verbose = true, + ): Promise +} + +export interface IPoolPair { + [id: string]: { + symbol: string + name: string + status: string + idTokenA: string + idTokenB: string + reserveA: BigNumber + reserveB: BigNumber + commission: BigNumber + totalLiquidity: BigNumber + ['reserveA/reserveB']: BigNumber + ['reserveB/reserveA']: BigNumber + tradeEnabled: boolean + ownerAddress: string + blockCommissionA: BigNumber + blockCommissionB: BigNumber + rewardPct: BigNumber + customRewards: BigNumber + creationTx: string + creationHeight: number + } +} + +interface PoolPairPagination { + start: number + including_start: boolean + limit: number +} +``` + +## getPoolPair + +Returns information about pools + +```ts title="client.poolPair.getPoolPair()" +interface poolPair { + getPoolPair (symbol: string, verbose = true): Promise { +} +``` + +## listPoolShares + +Returns information about pools + +```ts title="client.poolPair.listPoolShares()" +interface poolPair { + listPoolShares ( + pagination: PoolPairPagination = { + start: 0, + including_start: true, + limit: 100 + }, + verbose = true, + isMineOnly = false): Promise { +}: Promise +``` \ No newline at end of file From e5769bc051b810868c5b1ce6ab73e7fd4c75508e Mon Sep 17 00:00:00 2001 From: websterlcl Date: Thu, 15 Apr 2021 22:01:41 +0800 Subject: [PATCH 02/14] wip: stuck at creatPoolPair invalid amount err in commission --- .../__tests__/category/pool_pair.test.ts | 28 ++++++++++++++++--- .../src/category/pool_pair.ts | 26 +++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts b/packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts index c2e10f0643..bde48d29cc 100644 --- a/packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts @@ -46,7 +46,7 @@ describe.skip('non masternode', () => { }) }) -describe.skip('masternode', () => { +describe('masternode', () => { const container = new MasterNodeRegTestContainer() const client = new ContainerAdapterClient(container) @@ -59,8 +59,28 @@ describe.skip('masternode', () => { await container.stop() }) + describe('createPoolPair', () => { + it('should createPoolPair', async () => { + await waitForExpect(async () => { + const address = await container.call('getnewaddress') + + const metadata = { + tokenA: 'DFI', + tokenB: 'DDD', + commission: 0.003, + status: true, + ownerAddress: address, + customRewards: '', + pairSymbol: '' + } + const data = await client.poolPair.createPoolPair(metadata) + console.log('data: ', data) + }) + }) + }) + // TODO(canonbrother): currently the pool pair is empty, no point to test for now - describe('listPoolPairs', () => { + describe.skip('listPoolPairs', () => { it('should listPoolPairs', async () => { await waitForExpect(async () => { const poolPairs = await client.poolPair.listPoolPairs() @@ -70,7 +90,7 @@ describe.skip('masternode', () => { }) // TODO(canonbrother): pool not found, test again once pool pair is up - describe('getPoolPair', () => { + describe.skip('getPoolPair', () => { it('should getPoolPair', async () => { await waitForExpect(async () => { const poolPair = await client.poolPair.getPoolPair('DFI') @@ -80,7 +100,7 @@ describe.skip('masternode', () => { }) // TODO(canonbrother): empty pool shares, test again once pool shares is up - describe('listPoolShares', () => { + describe.skip('listPoolShares', () => { it('should listPoolShares', async () => { await waitForExpect(async () => { const poolShares = await client.poolPair.listPoolShares() diff --git a/packages/jellyfish-api-core/src/category/pool_pair.ts b/packages/jellyfish-api-core/src/category/pool_pair.ts index e35dd2c1fe..d5fc13299b 100644 --- a/packages/jellyfish-api-core/src/category/pool_pair.ts +++ b/packages/jellyfish-api-core/src/category/pool_pair.ts @@ -11,6 +11,17 @@ export class PoolPair { this.client = client } + /** + * Create a pool pair with given metadata + * + * @param metadata + * @param utxos is an array of specific UTXOs to spend + * @return Promise + */ + async createPoolPair (metadata: CreatePoolPairMetadata, utxos: CreatePoolPairUTXO[] = []): Promise { + return await this.client.call('createpoolpair', [metadata, utxos], 'number') + } + /** * Returns information about pools * @@ -76,6 +87,21 @@ export class PoolPair { } } +export interface CreatePoolPairMetadata { + tokenA: string + tokenB: string + commission: number + status: boolean + ownerAddress: string + customRewards?: string + pairSymbol?: string +} + +export interface CreatePoolPairUTXO { + txid: string + vout: number +} + export interface IPoolPair { [id: string]: { symbol: string From fe4aa57eedd74ac1021504499a7636692cfc07bf Mon Sep 17 00:00:00 2001 From: websterlcl Date: Sun, 18 Apr 2021 10:28:53 +0800 Subject: [PATCH 03/14] rename pool_pair to poolpair, update test, sidebar and doc --- .../__tests__/category/pool_pair.test.ts | 111 -------- .../__tests__/category/poolpair.test.ts | 246 ++++++++++++++++++ .../category/{pool_pair.ts => poolpair.ts} | 41 ++- packages/jellyfish-api-core/src/index.ts | 6 +- website/docs/jellyfish/api/pool_pair.md | 50 +++- website/sidebars.js | 3 +- 6 files changed, 327 insertions(+), 130 deletions(-) delete mode 100644 packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts create mode 100644 packages/jellyfish-api-core/__tests__/category/poolpair.test.ts rename packages/jellyfish-api-core/src/category/{pool_pair.ts => poolpair.ts} (69%) diff --git a/packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts b/packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts deleted file mode 100644 index bde48d29cc..0000000000 --- a/packages/jellyfish-api-core/__tests__/category/pool_pair.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { RegTestContainer, MasterNodeRegTestContainer } from '@defichain/testcontainers' -import { ContainerAdapterClient } from '../container_adapter_client' -import waitForExpect from 'wait-for-expect' - -describe.skip('non masternode', () => { - const container = new RegTestContainer() - const client = new ContainerAdapterClient(container) - - beforeAll(async () => { - await container.start() - await container.waitForReady() - }) - - afterAll(async () => { - await container.stop() - }) - - // TODO(canonbrother): currently the pool pair is empty, no point to test for now - describe('listPoolPairs', () => { - it('should listPoolPairs', async () => { - await waitForExpect(async () => { - const poolPairs = await client.poolPair.listPoolPairs() - console.log('poolPairs: ', poolPairs) - }) - }) - }) - - // TODO(canonbrother): pool not found, test again once pool pair is up - describe('getPoolPair', () => { - it('should getPoolPair', async () => { - await waitForExpect(async () => { - const poolPair = await client.poolPair.getPoolPair('DFI') - console.log('poolPair: ', poolPair) - }) - }) - }) - - // TODO(canonbrother): empty pool shares, test again once pool shares is up - describe('listPoolShares', () => { - it('should listPoolShares', async () => { - await waitForExpect(async () => { - const poolShares = await client.poolPair.listPoolShares() - console.log('poolShares: ', poolShares) - }) - }) - }) -}) - -describe('masternode', () => { - const container = new MasterNodeRegTestContainer() - const client = new ContainerAdapterClient(container) - - beforeAll(async () => { - await container.start() - await container.waitForReady() - }) - - afterAll(async () => { - await container.stop() - }) - - describe('createPoolPair', () => { - it('should createPoolPair', async () => { - await waitForExpect(async () => { - const address = await container.call('getnewaddress') - - const metadata = { - tokenA: 'DFI', - tokenB: 'DDD', - commission: 0.003, - status: true, - ownerAddress: address, - customRewards: '', - pairSymbol: '' - } - const data = await client.poolPair.createPoolPair(metadata) - console.log('data: ', data) - }) - }) - }) - - // TODO(canonbrother): currently the pool pair is empty, no point to test for now - describe.skip('listPoolPairs', () => { - it('should listPoolPairs', async () => { - await waitForExpect(async () => { - const poolPairs = await client.poolPair.listPoolPairs() - console.log('poolPairs: ', poolPairs) - }) - }) - }) - - // TODO(canonbrother): pool not found, test again once pool pair is up - describe.skip('getPoolPair', () => { - it('should getPoolPair', async () => { - await waitForExpect(async () => { - const poolPair = await client.poolPair.getPoolPair('DFI') - console.log('poolPair: ', poolPair) - }) - }) - }) - - // TODO(canonbrother): empty pool shares, test again once pool shares is up - describe.skip('listPoolShares', () => { - it('should listPoolShares', async () => { - await waitForExpect(async () => { - const poolShares = await client.poolPair.listPoolShares() - console.log('poolShares: ', poolShares) - }) - }) - }) -}) diff --git a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts new file mode 100644 index 0000000000..63abd44da5 --- /dev/null +++ b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts @@ -0,0 +1,246 @@ +import { MasterNodeRegTestContainer } from '@defichain/testcontainers' +import { ContainerAdapterClient } from '../container_adapter_client' + +describe('masternode', () => { + const container = new MasterNodeRegTestContainer() + const client = new ContainerAdapterClient(container) + + async function createToken (symbol: string): Promise { + const address = await container.call('getnewaddress') + const metadata = { + symbol, + name: symbol, + isDAT: true, + mintable: true, + tradeable: true, + collateralAddress: address + } + await container.call('createtoken', [metadata]) + } + + async function createPoolPair (tokenB: string, metadata?: any): Promise { + const address = await container.call('getnewaddress') + const defaultMetadata = { + tokenA: 'DFI', + tokenB, + commission: 0, + status: true, + ownerAddress: address + } + await client.poolpair.createPoolPair({ ...defaultMetadata, ...metadata }) + } + + beforeAll(async () => { + await container.start() + await container.waitForReady() + await container.waitForWalletCoinbaseMaturity() + }) + + afterAll(async () => { + await container.stop() + }) + + describe('createPoolPair', () => { + beforeAll(async () => { + await createToken('DBTC') + await container.waitForWalletCoinbaseMaturity() + }) + + it('should createPoolPair', async () => { + const poolpairsBefore = await client.poolpair.listPoolPairs() + expect(Object.keys(poolpairsBefore).length).toBe(0) + + const address = await container.call('getnewaddress') + const metadata = { + tokenA: 'DFI', + tokenB: 'DBTC', + commission: 0, + status: true, + ownerAddress: address + } + const data = await client.poolpair.createPoolPair(metadata) + expect(typeof data).toBe('string') + + await container.waitForWalletCoinbaseMaturity() + + const poolpairsAfter = await client.poolpair.listPoolPairs() + expect(Object.keys(poolpairsAfter).length).toBe(1) + for (const k in poolpairsAfter) { + const poolpair = poolpairsAfter[k] + expect(poolpair.name).toBe('Default Defi token-DBTC') + expect(poolpair.symbol).toBe(`${metadata.tokenA}-${metadata.tokenB}`) + expect(poolpair.status).toBe(metadata.status) + expect(poolpair.commission).toBe(metadata.commission) + expect(poolpair.ownerAddress).toBe(metadata.ownerAddress) + expect(poolpair.totalLiquidity).toBe(0) + expect(typeof poolpair.idTokenA).toBe('string') + expect(typeof poolpair.idTokenB).toBe('string') + expect(typeof poolpair.reserveA).toBe('number') + expect(typeof poolpair.reserveB).toBe('number') + expect(typeof poolpair['reserveA/reserveB']).toBe('string') + expect(typeof poolpair['reserveB/reserveA']).toBe('string') + expect(poolpair.tradeEnabled).toBe(false) + expect(typeof poolpair.blockCommissionA).toBe('number') + expect(typeof poolpair.blockCommissionB).toBe('number') + expect(typeof poolpair.rewardPct).toBe('number') + expect(typeof poolpair.creationTx).toBe('string') + expect(typeof poolpair.creationHeight).toBe('number') + } + }) + }) + + describe('listPoolPairs', () => { + beforeAll(async () => { + await createToken('DETH') + await createToken('DXRP') + await createToken('DUSDT') + await container.waitForWalletCoinbaseMaturity() + + await createPoolPair('DETH', { commission: 0.001 }) + await createPoolPair('DXRP', { commission: 0.003 }) + await createPoolPair('DUSDT', { status: false }) + await container.waitForWalletCoinbaseMaturity() + }) + + it('should listPoolPairs', async () => { + let points = 0 + const poolpairs = await client.poolpair.listPoolPairs() + + for (const k in poolpairs) { + const poolpair = poolpairs[k] + + if (poolpair.symbol === 'DFI-DETH') { + expect(poolpair.name).toBe('Default Defi token-DETH') + expect(poolpair.status).toBe(true) + expect(poolpair.commission).toBe(0.001) + points += 1 + } + + if (poolpair.symbol === 'DFI-DXRP') { + expect(poolpair.name).toBe('Default Defi token-DXRP') + expect(poolpair.status).toBe(true) + expect(poolpair.commission).toBe(0.003) + points += 1 + } + + if (poolpair.symbol === 'DFI-DUSD') { + expect(poolpair.name).toBe('Default Defi token-DUSDT') + expect(poolpair.status).toBe(false) + expect(poolpair.commission).toBe(0) + points += 1 + } + + expect(poolpair.totalLiquidity).toBe(0) + expect(typeof poolpair.ownerAddress).toBe('string') + expect(typeof poolpair.idTokenA).toBe('string') + expect(typeof poolpair.idTokenB).toBe('string') + expect(typeof poolpair.reserveA).toBe('number') + expect(typeof poolpair.reserveB).toBe('number') + expect(typeof poolpair['reserveA/reserveB']).toBe('string') + expect(typeof poolpair['reserveB/reserveA']).toBe('string') + expect(poolpair.tradeEnabled).toBe(false) + expect(typeof poolpair.blockCommissionA).toBe('number') + expect(typeof poolpair.blockCommissionB).toBe('number') + expect(typeof poolpair.rewardPct).toBe('number') + expect(typeof poolpair.creationTx).toBe('string') + expect(typeof poolpair.creationHeight).toBe('number') + } + + expect(points).toBe(3) + }) + }) + + it('should listPoolPairs with pagination and return an empty object as out of range', async () => { + const pagination = { + start: 300, + including_start: true, + limit: 100 + } + const poolpairs = await client.poolpair.listPoolPairs(pagination) + + expect(Object.keys(poolpairs).length).toBe(0) + }) + + it('should listPoolPairs with pagination limit', async () => { + const pagination = { + start: 0, + including_start: true, + limit: 2 + } + const poolpairs = await client.poolpair.listPoolPairs(pagination) + + expect(Object.keys(poolpairs).length).toBe(2) + }) + + it('should listPoolPairs with verbose false', async () => { + const pagination = { + start: 0, + including_start: true, + limit: 100 + } + const poolpairs = await client.poolpair.listPoolPairs(pagination, false) + + for (const k in poolpairs) { + const poolpair = poolpairs[k] + + expect(typeof poolpair.symbol).toBe('string') + expect(typeof poolpair.name).toBe('string') + expect(typeof poolpair.status).toBe('boolean') + expect(typeof poolpair.idTokenA).toBe('string') + expect(typeof poolpair.idTokenB).toBe('string') + } + }) + + describe('getPoolPair', () => { + beforeAll(async () => { + await createToken('DBCH') + await container.waitForWalletCoinbaseMaturity() + + await createPoolPair('DBCH') + await container.waitForWalletCoinbaseMaturity() + }) + + it('should getPoolPair', async () => { + const poolpair = await client.poolpair.getPoolPair('DFI-DBCH') + + for (const k in poolpair) { + const data = poolpair[k] + expect(data.symbol).toBe('DFI-DBCH') + expect(data.name).toBe('Default Defi token-DBCH') + expect(data.status).toBe(true) + expect(typeof data.idTokenA).toBe('string') + expect(typeof data.idTokenB).toBe('string') + expect(typeof data.reserveA).toBe('number') + expect(typeof data.reserveB).toBe('number') + expect(typeof data['reserveA/reserveB']).toBe('string') + expect(typeof data['reserveB/reserveA']).toBe('string') + expect(data.tradeEnabled).toBe(false) + expect(typeof data.blockCommissionA).toBe('number') + expect(typeof data.blockCommissionB).toBe('number') + expect(typeof data.rewardPct).toBe('number') + expect(typeof data.creationTx).toBe('string') + expect(typeof data.creationHeight).toBe('number') + } + }) + + it('should getPoolPair with verbose false', async () => { + const poolpair = await client.poolpair.getPoolPair('DFI-DBCH', false) + + for (const k in poolpair) { + const data = poolpair[k] + expect(data.symbol).toBe('DFI-DBCH') + expect(data.name).toBe('Default Defi token-DBCH') + expect(data.status).toBe(true) + expect(typeof data.idTokenA).toBe('string') + expect(typeof data.idTokenB).toBe('string') + } + }) + }) + + describe('listPoolShares', () => { + it('should listPoolShares', async () => { + const poolShares = await client.poolpair.listPoolShares() + console.log('poolShares: ', poolShares) + }) + }) +}) diff --git a/packages/jellyfish-api-core/src/category/pool_pair.ts b/packages/jellyfish-api-core/src/category/poolpair.ts similarity index 69% rename from packages/jellyfish-api-core/src/category/pool_pair.ts rename to packages/jellyfish-api-core/src/category/poolpair.ts index d5fc13299b..b80e0355dc 100644 --- a/packages/jellyfish-api-core/src/category/pool_pair.ts +++ b/packages/jellyfish-api-core/src/category/poolpair.ts @@ -12,21 +12,37 @@ export class PoolPair { } /** - * Create a pool pair with given metadata + * Create a poolpair with given metadata * - * @param metadata - * @param utxos is an array of specific UTXOs to spend + * @param {CreatePoolPairMetadata} metadata a data providing information for pool pair creation + * @param {string} metadata.tokenA uses to trade to obtain tokenB + * @param {string} metadata.tokenB + * @param {number} metadata.commission + * @param {boolean} metadata.status + * @param {string} metadata.ownerAddress + * @param {string} metadata.customRewards + * @param {string} metadata.pairSymbol + * @param {CreatePoolPairUTXO[]} utxos is an array of specific UTXOs to spend + * @param {string} utxo.txid + * @param {number} utxo.vout * @return Promise */ async createPoolPair (metadata: CreatePoolPairMetadata, utxos: CreatePoolPairUTXO[] = []): Promise { - return await this.client.call('createpoolpair', [metadata, utxos], 'number') + const defaultMetadata = { + customerRewards: [], + pairSymbol: '' + } + return await this.client.call('createpoolpair', [{ ...defaultMetadata, ...metadata }, utxos], 'number') } /** * Returns information about pools * - * @param pagination - * @param verbose + * @param {PoolPairPagination} pagination + * @param {number} pagination.start + * @param {boolean} pagination.including_start + * @param {number} pagination.limit + * @param {boolean} verbose * @return Promise */ async listPoolPairs ( @@ -54,8 +70,8 @@ export class PoolPair { /** * Returns information about pool * - * @param symbol - * @param verbose + * @param {string} symbol + * @param {boolean} verbose * @return Promise */ async getPoolPair (symbol: string, verbose = true): Promise { @@ -65,9 +81,12 @@ export class PoolPair { /** * Returns information about pool shares * - * @param pagination - * @param verbose - * @param isMineOnly + * @param {PoolPairPagination} pagination + * @param {number} pagination.start + * @param {boolean} pagination.including_start + * @param {number} pagination.limit + * @param {boolean} verbose + * @param {boolean} isMineOnly * @return Promise */ async listPoolShares ( diff --git a/packages/jellyfish-api-core/src/index.ts b/packages/jellyfish-api-core/src/index.ts index 93a053caaf..203897b732 100644 --- a/packages/jellyfish-api-core/src/index.ts +++ b/packages/jellyfish-api-core/src/index.ts @@ -3,14 +3,14 @@ import { Blockchain } from './category/blockchain' import { Mining } from './category/mining' import { RawTx } from './category/rawtx' import { Wallet } from './category/wallet' -import { PoolPair } from './category/pool_pair' +import { PoolPair } from './category/poolpair' export * from '@defichain/jellyfish-json' export * from './category/blockchain' export * from './category/mining' export * as rawtx from './category/rawtx' export * from './category/wallet' -export * from './category/pool_pair' +export * from './category/poolpair' /** * ApiClient; a protocol agnostic DeFiChain node client, RPC calls are separated into their category. @@ -20,7 +20,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 poolPair = new PoolPair(this) + public readonly poolpair = new PoolPair(this) /** * A promise based procedure call handling diff --git a/website/docs/jellyfish/api/pool_pair.md b/website/docs/jellyfish/api/pool_pair.md index 50973b6836..5d03010fe4 100644 --- a/website/docs/jellyfish/api/pool_pair.md +++ b/website/docs/jellyfish/api/pool_pair.md @@ -28,7 +28,7 @@ interface poolPair { ): Promise } -export interface IPoolPair { +interface IPoolPair { [id: string]: { symbol: string name: string @@ -65,7 +65,31 @@ Returns information about pools ```ts title="client.poolPair.getPoolPair()" interface poolPair { - getPoolPair (symbol: string, verbose = true): Promise { + getPoolPair (symbol: string, verbose = true): Promise +} + +interface IPoolPair { + [id: string]: { + symbol: string + name: string + status: string + idTokenA: string + idTokenB: string + reserveA: BigNumber + reserveB: BigNumber + commission: BigNumber + totalLiquidity: BigNumber + ['reserveA/reserveB']: BigNumber + ['reserveB/reserveA']: BigNumber + tradeEnabled: boolean + ownerAddress: string + blockCommissionA: BigNumber + blockCommissionB: BigNumber + rewardPct: BigNumber + customRewards: BigNumber + creationTx: string + creationHeight: number + } } ``` @@ -82,6 +106,24 @@ interface poolPair { limit: 100 }, verbose = true, - isMineOnly = false): Promise { -}: Promise + isMineOnly = false + ): Promise +} + +interface IPoolShare { + [id: string]: { + poolID: string + owner: string + ['%']: BigNumber + amount: BigNumber + totalLiquidity: BigNumber + } +} + + +interface PoolPairPagination { + start: number + including_start: boolean + limit: number +} ``` \ No newline at end of file diff --git a/website/sidebars.js b/website/sidebars.js index f7ac3e13df..5cdbaf970e 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -11,7 +11,8 @@ module.exports = { 'jellyfish/api/blockchain', 'jellyfish/api/mining', 'jellyfish/api/rawtx', - 'jellyfish/api/wallet' + 'jellyfish/api/wallet', + 'jellyfish/api/poolpair' ] } ], From 03bc71a39d04638716d2b978cceddf70ae074750 Mon Sep 17 00:00:00 2001 From: websterlcl Date: Tue, 20 Apr 2021 13:53:55 +0800 Subject: [PATCH 04/14] wip --- .../__tests__/category/poolpair.test.ts | 101 ++++++++++++------ .../src/category/poolpair.ts | 15 +++ 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts index 63abd44da5..4e9592475c 100644 --- a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts @@ -18,7 +18,7 @@ describe('masternode', () => { await container.call('createtoken', [metadata]) } - async function createPoolPair (tokenB: string, metadata?: any): Promise { + async function createPoolPair (tokenB: string, metadata?: any): Promise { const address = await container.call('getnewaddress') const defaultMetadata = { tokenA: 'DFI', @@ -28,6 +28,8 @@ describe('masternode', () => { ownerAddress: address } await client.poolpair.createPoolPair({ ...defaultMetadata, ...metadata }) + + return address } beforeAll(async () => { @@ -148,47 +150,47 @@ describe('masternode', () => { expect(points).toBe(3) }) - }) - it('should listPoolPairs with pagination and return an empty object as out of range', async () => { - const pagination = { - start: 300, - including_start: true, - limit: 100 - } - const poolpairs = await client.poolpair.listPoolPairs(pagination) + it('should listPoolPairs with pagination and return an empty object as out of range', async () => { + const pagination = { + start: 300, + including_start: true, + limit: 100 + } + const poolpairs = await client.poolpair.listPoolPairs(pagination) - expect(Object.keys(poolpairs).length).toBe(0) - }) + expect(Object.keys(poolpairs).length).toBe(0) + }) - it('should listPoolPairs with pagination limit', async () => { - const pagination = { - start: 0, - including_start: true, - limit: 2 - } - const poolpairs = await client.poolpair.listPoolPairs(pagination) + it('should listPoolPairs with pagination limit', async () => { + const pagination = { + start: 0, + including_start: true, + limit: 2 + } + const poolpairs = await client.poolpair.listPoolPairs(pagination) - expect(Object.keys(poolpairs).length).toBe(2) - }) + expect(Object.keys(poolpairs).length).toBe(2) + }) - it('should listPoolPairs with verbose false', async () => { - const pagination = { - start: 0, - including_start: true, - limit: 100 - } - const poolpairs = await client.poolpair.listPoolPairs(pagination, false) + it('should listPoolPairs with verbose false', async () => { + const pagination = { + start: 0, + including_start: true, + limit: 100 + } + const poolpairs = await client.poolpair.listPoolPairs(pagination, false) - for (const k in poolpairs) { - const poolpair = poolpairs[k] + for (const k in poolpairs) { + const poolpair = poolpairs[k] - expect(typeof poolpair.symbol).toBe('string') - expect(typeof poolpair.name).toBe('string') - expect(typeof poolpair.status).toBe('boolean') - expect(typeof poolpair.idTokenA).toBe('string') - expect(typeof poolpair.idTokenB).toBe('string') - } + expect(typeof poolpair.symbol).toBe('string') + expect(typeof poolpair.name).toBe('string') + expect(typeof poolpair.status).toBe('boolean') + expect(typeof poolpair.idTokenA).toBe('string') + expect(typeof poolpair.idTokenB).toBe('string') + } + }) }) describe('getPoolPair', () => { @@ -237,6 +239,35 @@ describe('masternode', () => { }) }) + describe.only('addPoolLiquidity', () => { + let DDAI_ADDRESS = '' + + beforeAll(async () => { + await createToken('DDAI') + await container.waitForWalletCoinbaseMaturity() + + DDAI_ADDRESS = await createPoolPair('DDAI') + await container.waitForWalletCoinbaseMaturity() + }) + + it('should addPoolLiquidity', async () => { + const aliceAddress = await container.call('getnewaddress') + const bobAddress = await container.call('getnewaddress') + console.log('addr: ', aliceAddress, bobAddress, DDAI_ADDRESS) + + const data = await client.poolpair.addPoolLiquidity({ + [aliceAddress]: '300000000@DFI', + [bobAddress]: '30000000000000000@DDAI' + }, DDAI_ADDRESS) + + // const data = await client.poolpair.addPoolLiquidity({'*': [ + // '300000000@DFI', '30000000000000000@DDAI', + // ]}, DDAI_ADDRESS) + + console.log('data: ', data) + }) + }) + describe('listPoolShares', () => { it('should listPoolShares', async () => { const poolShares = await client.poolpair.listPoolShares() diff --git a/packages/jellyfish-api-core/src/category/poolpair.ts b/packages/jellyfish-api-core/src/category/poolpair.ts index b80e0355dc..515e482513 100644 --- a/packages/jellyfish-api-core/src/category/poolpair.ts +++ b/packages/jellyfish-api-core/src/category/poolpair.ts @@ -78,6 +78,21 @@ export class PoolPair { return await this.client.call('getpoolpair', [symbol, verbose], 'number') } + /** + * Add pool liquidity transaction + * + * @param from + * @param from[address] provides at least two types of token with format 'amoun@token' + * @param shareAddress defi address for crediting tokens + * @param inputs + * @param inputs.txid + * @param inputs.vout + * @return {Promise} + */ + async addPoolLiquidity (from: any, shareAddress: string, inputs?: string[]): Promise { + return await this.client.call('addpoolliquidity', [from, shareAddress, inputs], 'number') + } + /** * Returns information about pool shares * From 9c9b80c413360aa2dfe954f56bfaf0d75db95c22 Mon Sep 17 00:00:00 2001 From: websterlcl Date: Fri, 23 Apr 2021 01:28:10 +0800 Subject: [PATCH 05/14] addpoolliquidity, listpoolshares test --- .../__tests__/category/poolpair.test.ts | 191 ++++++++++++++---- .../__tests__/category/wallet.test.ts | 2 - .../src/category/poolpair.ts | 97 +++++---- .../api/{pool_pair.md => poolpair.md} | 42 +++- 4 files changed, 245 insertions(+), 87 deletions(-) rename website/docs/jellyfish/api/{pool_pair.md => poolpair.md} (74%) diff --git a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts index 4e9592475c..4d41280a3e 100644 --- a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts @@ -1,10 +1,21 @@ import { MasterNodeRegTestContainer } from '@defichain/testcontainers' +import BigNumber from 'bignumber.js' import { ContainerAdapterClient } from '../container_adapter_client' describe('masternode', () => { const container = new MasterNodeRegTestContainer() const client = new ContainerAdapterClient(container) + beforeAll(async () => { + await container.start() + await container.waitForReady() + await container.waitForWalletCoinbaseMaturity() + }) + + afterAll(async () => { + await container.stop() + }) + async function createToken (symbol: string): Promise { const address = await container.call('getnewaddress') const metadata = { @@ -16,9 +27,10 @@ describe('masternode', () => { collateralAddress: address } await container.call('createtoken', [metadata]) + await container.generate(1) } - async function createPoolPair (tokenB: string, metadata?: any): Promise { + async function createPoolPair (tokenB: string, metadata?: any): Promise { const address = await container.call('getnewaddress') const defaultMetadata = { tokenA: 'DFI', @@ -28,24 +40,25 @@ describe('masternode', () => { ownerAddress: address } await client.poolpair.createPoolPair({ ...defaultMetadata, ...metadata }) - - return address + await container.generate(1) } - beforeAll(async () => { - await container.start() - await container.waitForReady() - await container.waitForWalletCoinbaseMaturity() - }) + async function mintTokens (symbol: string): Promise { + const address = await container.call('getnewaddress') - afterAll(async () => { - await container.stop() - }) + // NOTE(canonbrother): using `minttokens` on DFI is an error as DFI is not mintable + // await container.call('minttokens', ['1000@DFI']) + const payload: { [key: string]: string } = {} + payload[address] = '2000@0' + await container.call('utxostoaccount', [payload]) + await container.call('minttokens', [`2000@${symbol}`]) + + await container.generate(25) + } describe('createPoolPair', () => { beforeAll(async () => { await createToken('DBTC') - await container.waitForWalletCoinbaseMaturity() }) it('should createPoolPair', async () => { @@ -63,7 +76,7 @@ describe('masternode', () => { const data = await client.poolpair.createPoolPair(metadata) expect(typeof data).toBe('string') - await container.waitForWalletCoinbaseMaturity() + await container.generate(1) const poolpairsAfter = await client.poolpair.listPoolPairs() expect(Object.keys(poolpairsAfter).length).toBe(1) @@ -96,12 +109,10 @@ describe('masternode', () => { await createToken('DETH') await createToken('DXRP') await createToken('DUSDT') - await container.waitForWalletCoinbaseMaturity() await createPoolPair('DETH', { commission: 0.001 }) await createPoolPair('DXRP', { commission: 0.003 }) await createPoolPair('DUSDT', { status: false }) - await container.waitForWalletCoinbaseMaturity() }) it('should listPoolPairs', async () => { @@ -196,10 +207,7 @@ describe('masternode', () => { describe('getPoolPair', () => { beforeAll(async () => { await createToken('DBCH') - await container.waitForWalletCoinbaseMaturity() - await createPoolPair('DBCH') - await container.waitForWalletCoinbaseMaturity() }) it('should getPoolPair', async () => { @@ -237,41 +245,154 @@ describe('masternode', () => { expect(typeof data.idTokenB).toBe('string') } }) - }) - describe.only('addPoolLiquidity', () => { - let DDAI_ADDRESS = '' + // it.skip('should be failed as getting non-existent pair', async () => { + // const promise = client.poolpair.getPoolPair('DFI-NONEXIST') + // expect(promise).rejects.toThrow('RpcApiError: \'Pool not found\', code: -5') + // }) + }) + describe('addPoolLiquidity', () => { beforeAll(async () => { + await container.generate(100) + await createToken('DDAI') - await container.waitForWalletCoinbaseMaturity() - DDAI_ADDRESS = await createPoolPair('DDAI') - await container.waitForWalletCoinbaseMaturity() + await mintTokens('DDAI') + + await createPoolPair('DDAI') }) it('should addPoolLiquidity', async () => { - const aliceAddress = await container.call('getnewaddress') - const bobAddress = await container.call('getnewaddress') - console.log('addr: ', aliceAddress, bobAddress, DDAI_ADDRESS) + const shareAddress = await container.call('getnewaddress') + const data = await client.poolpair.addPoolLiquidity({ + '*': ['100@DFI', '200@DDAI'] + }, shareAddress) + expect(typeof data).toBe('string') + }) + + it.skip('should addPoolLiquidity with specific input token address', async () => { + const tokenAAddress = await container.call('getnewaddress') + const tokenBAddress = await container.call('getnewaddress') + await container.call('sendtokenstoaddress', [{}, { [tokenAAddress]: ['100@DFI'] }]) + await container.call('sendtokenstoaddress', [{}, { [tokenBAddress]: ['200@DDAI'] }]) + await container.generate(25) + + const shareAddress = await container.call('getnewaddress') const data = await client.poolpair.addPoolLiquidity({ - [aliceAddress]: '300000000@DFI', - [bobAddress]: '30000000000000000@DDAI' - }, DDAI_ADDRESS) + [tokenAAddress]: '50@DFI', + [tokenBAddress]: '100@DDAI' + }, shareAddress) + + expect(typeof data).toBe('string') + }) + + it.skip('should addPoolLiquidity with utxos', async () => { + const utxos = await container.call('listunspent') - // const data = await client.poolpair.addPoolLiquidity({'*': [ - // '300000000@DFI', '30000000000000000@DDAI', - // ]}, DDAI_ADDRESS) + const shareAddress = await container.call('getnewaddress') + const data = await client.poolpair.addPoolLiquidity({ + '*': ['100@DFI', '200@DDAI'] + }, shareAddress, { utxos: [{ txid: utxos[0].txid, vout: 0 }] }) - console.log('data: ', data) + expect(typeof data).toBe('string') }) }) describe('listPoolShares', () => { + async function addPoolLiquidity (): Promise { + const shareAddress = await container.call('getnewaddress') + const data = await client.poolpair.addPoolLiquidity({ + '*': ['100@DFI', '200@DSWAP'] + }, shareAddress) + + expect(typeof data).toBe('string') + + await container.generate(1) + } + + beforeAll(async () => { + await container.generate(100) + + await createToken('DSWAP') + + await mintTokens('DSWAP') + + await createPoolPair('DSWAP') + + await addPoolLiquidity() + await addPoolLiquidity() + await addPoolLiquidity() + }) + it('should listPoolShares', async () => { const poolShares = await client.poolpair.listPoolShares() - console.log('poolShares: ', poolShares) + + for (const k in poolShares) { + const data = poolShares[k] + expect(typeof data.poolID).toBe('string') + expect(typeof data.owner).toBe('string') + expect(data['%'] instanceof BigNumber).toBe(true) + expect(data.amount instanceof BigNumber).toBe(true) + expect(data.totalLiquidity instanceof BigNumber).toBe(true) + } + }) + + it('should listPoolShares with pagination and return an empty object as out of range', async () => { + const pagination = { + start: 300, + including_start: true, + limit: 100 + } + const poolShares = await client.poolpair.listPoolShares(pagination) + + expect(Object.keys(poolShares).length).toBe(0) + }) + + it('should listPoolShares with pagination limit', async () => { + const pagination = { + start: 0, + including_start: true, + limit: 2 + } + const poolShares = await client.poolpair.listPoolShares(pagination) + + expect(Object.keys(poolShares).length).toBe(2) + }) + + it('should listPoolPairs with verbose false', async () => { + const pagination = { + start: 0, + including_start: true, + limit: 100 + } + const poolShares = await client.poolpair.listPoolShares(pagination, false) + + for (const k in poolShares) { + const data = poolShares[k] + expect(typeof data.poolID).toBe('string') + expect(typeof data.owner).toBe('string') + expect(data['%'] instanceof BigNumber).toBe(true) + } + }) + + it('should listPoolPairs with isMineOnly true', async () => { + const pagination = { + start: 0, + including_start: true, + limit: 100 + } + const poolShares = await client.poolpair.listPoolShares(pagination, true, { isMineOnly: true }) + + for (const k in poolShares) { + const data = poolShares[k] + expect(typeof data.poolID).toBe('string') + expect(typeof data.owner).toBe('string') + expect(data['%'] instanceof BigNumber).toBe(true) + expect(data.amount instanceof BigNumber).toBe(true) + expect(data.totalLiquidity instanceof BigNumber).toBe(true) + } }) }) }) diff --git a/packages/jellyfish-api-core/__tests__/category/wallet.test.ts b/packages/jellyfish-api-core/__tests__/category/wallet.test.ts index df546c7346..efda04244b 100644 --- a/packages/jellyfish-api-core/__tests__/category/wallet.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/wallet.test.ts @@ -54,7 +54,6 @@ describe('masternode', () => { expect(utxos.length).toBeGreaterThan(0) for (let i = 0; i < utxos.length; i += 1) { const utxo = utxos[i] - console.log('utxo: ', utxo) expect(typeof utxo.txid).toBe('string') expect(typeof utxo.vout).toBe('number') expect(typeof utxo.address).toBe('string') @@ -125,7 +124,6 @@ describe('masternode', () => { const options: ListUnspentOptions = { queryOptions: { maximumAmount: 100 } } await waitForExpect(async () => { const utxos: UTXO[] = await client.wallet.listUnspent(1, 9999999, options) - console.log('utxos: ', utxos) utxos.forEach(utxo => { expect(utxo.amount.isLessThanOrEqualTo(new BigNumber('100'))).toBe(true) }) diff --git a/packages/jellyfish-api-core/src/category/poolpair.ts b/packages/jellyfish-api-core/src/category/poolpair.ts index 515e482513..8012289e3d 100644 --- a/packages/jellyfish-api-core/src/category/poolpair.ts +++ b/packages/jellyfish-api-core/src/category/poolpair.ts @@ -20,30 +20,26 @@ export class PoolPair { * @param {number} metadata.commission * @param {boolean} metadata.status * @param {string} metadata.ownerAddress - * @param {string} metadata.customRewards - * @param {string} metadata.pairSymbol + * @param {string=} metadata.customRewards + * @param {string=} metadata.pairSymbol * @param {CreatePoolPairUTXO[]} utxos is an array of specific UTXOs to spend * @param {string} utxo.txid * @param {number} utxo.vout - * @return Promise + * @return {Promise} */ async createPoolPair (metadata: CreatePoolPairMetadata, utxos: CreatePoolPairUTXO[] = []): Promise { - const defaultMetadata = { - customerRewards: [], - pairSymbol: '' - } - return await this.client.call('createpoolpair', [{ ...defaultMetadata, ...metadata }, utxos], 'number') + return await this.client.call('createpoolpair', [metadata, utxos], 'number') } /** * Returns information about pools * * @param {PoolPairPagination} pagination - * @param {number} pagination.start - * @param {boolean} pagination.including_start - * @param {number} pagination.limit - * @param {boolean} verbose - * @return Promise + * @param {number} pagination.start default is 0 + * @param {boolean} pagination.including_start default = true + * @param {number} pagination.limit to limit number of records + * @param {boolean} verbose default = true, otherwise only symbol, name, status, idTokena, idTokenB + * @return {Promise} */ async listPoolPairs ( pagination: PoolPairPagination = { @@ -52,7 +48,7 @@ export class PoolPair { limit: 100 }, verbose = true - ): Promise { + ): Promise { return await this.client.call('listpoolpairs', [pagination, verbose], { reserveA: 'bignumber', reserveB: 'bignumber', @@ -70,39 +66,42 @@ export class PoolPair { /** * Returns information about pool * - * @param {string} symbol - * @param {boolean} verbose - * @return Promise + * @param {string} symbol token's symbol + * @param {boolean} verbose default = true, otherwise only symbol, name, status, idTokena, idTokenB + * @return {Promise} */ - async getPoolPair (symbol: string, verbose = true): Promise { + async getPoolPair (symbol: string, verbose = true): Promise { return await this.client.call('getpoolpair', [symbol, verbose], 'number') } /** * Add pool liquidity transaction * - * @param from - * @param from[address] provides at least two types of token with format 'amoun@token' - * @param shareAddress defi address for crediting tokens - * @param inputs - * @param inputs.txid - * @param inputs.vout - * @return {Promise} + * @param {AddPoolLiquiditySource} from pool liquidity sources + * @param {string | string[]} from[address] provides at least two types of token with format 'amoun@token' + * @param {string} shareAddress defi address for crediting tokens + * @param {AddPoolLiquidityOptions} options + * @param {AddPoolLiquidityUTXO[]=} options.utxos utxos array of specific UTXOs to spend + * @param {string} options.utxos.txid + * @param {number} options.utxos.vout + * @return {Promise} */ - async addPoolLiquidity (from: any, shareAddress: string, inputs?: string[]): Promise { - return await this.client.call('addpoolliquidity', [from, shareAddress, inputs], 'number') + async addPoolLiquidity (from: AddPoolLiquiditySource, shareAddress: string, options: AddPoolLiquidityOptions = {}): Promise { + const { utxos } = options + return await this.client.call('addpoolliquidity', [from, shareAddress, utxos], 'bignumber') } /** * Returns information about pool shares * * @param {PoolPairPagination} pagination - * @param {number} pagination.start - * @param {boolean} pagination.including_start - * @param {number} pagination.limit - * @param {boolean} verbose - * @param {boolean} isMineOnly - * @return Promise + * @param {number} pagination.start default is 0 + * @param {boolean} pagination.including_start default = true + * @param {number} pagination.limit to limit number of records + * @param {boolean} verbose default = true, otherwise only poolID, owner and % + * @param {PoolShareOptions} options + * @param {boolean=} options.isMineOnly default = true + * @return {Promise} */ async listPoolShares ( pagination: PoolPairPagination = { @@ -111,13 +110,10 @@ export class PoolPair { limit: 100 }, verbose = true, - isMineOnly = false - ): Promise { - return await this.client.call('listpoolshares', [pagination, verbose, isMineOnly], { - '%': 'bignumber', - amount: 'bignumber', - totalLiquidity: 'bignumber' - }) + options: PoolShareOptions = {} + ): Promise { + const { isMineOnly = true } = options + return await this.client.call('listpoolshares', [pagination, verbose, isMineOnly], 'bignumber') } } @@ -136,7 +132,7 @@ export interface CreatePoolPairUTXO { vout: number } -export interface IPoolPair { +export interface PoolPairResult { [id: string]: { symbol: string name: string @@ -160,7 +156,7 @@ export interface IPoolPair { } } -export interface IPoolShare { +export interface PoolShareResult { [id: string]: { poolID: string owner: string @@ -175,3 +171,20 @@ export interface PoolPairPagination { including_start: boolean limit: number } + +export interface AddPoolLiquiditySource { + [address: string]: string | string[] +} + +export interface AddPoolLiquidityOptions { + utxos?: AddPoolLiquidityUTXO[] +} + +export interface AddPoolLiquidityUTXO { + txid: string + vout: number +} + +export interface PoolShareOptions { + isMineOnly?: boolean +} diff --git a/website/docs/jellyfish/api/pool_pair.md b/website/docs/jellyfish/api/poolpair.md similarity index 74% rename from website/docs/jellyfish/api/pool_pair.md rename to website/docs/jellyfish/api/poolpair.md index 5d03010fe4..a3c5dc3c18 100644 --- a/website/docs/jellyfish/api/pool_pair.md +++ b/website/docs/jellyfish/api/poolpair.md @@ -25,10 +25,10 @@ interface poolPair { limit: 100 }, verbose = true, - ): Promise + ): Promise } -interface IPoolPair { +interface PoolPairResult { [id: string]: { symbol: string name: string @@ -65,10 +65,10 @@ Returns information about pools ```ts title="client.poolPair.getPoolPair()" interface poolPair { - getPoolPair (symbol: string, verbose = true): Promise + getPoolPair (symbol: string, verbose = true): Promise } -interface IPoolPair { +interface PoolPairResult { [id: string]: { symbol: string name: string @@ -93,6 +93,29 @@ interface IPoolPair { } ``` +## addPoolLiquidity + +Add pool liquidity transaction + +```ts title="client.poolPair.addPoolLiquidity()" +interface poolPair { + addPoolLiquidity (from: AddPoolLiquiditySource, shareAddress: string, options: AddPoolLiquidityOptions = {}): Promise +} + +interface AddPoolLiquiditySource { + [address: string]: string | string[] +} + +interface AddPoolLiquidityOptions { + utxos?: AddPoolLiquidityUTXO[] +} + +interface AddPoolLiquidityUTXO { + txid: string + vout: number +} +``` + ## listPoolShares Returns information about pools @@ -106,11 +129,11 @@ interface poolPair { limit: 100 }, verbose = true, - isMineOnly = false - ): Promise + options: PoolShareOptions = {}, + ): Promise } -interface IPoolShare { +interface PoolShareResult { [id: string]: { poolID: string owner: string @@ -120,10 +143,13 @@ interface IPoolShare { } } - interface PoolPairPagination { start: number including_start: boolean limit: number } + +interface PoolShareOptions { + isMineOnly?: boolean +} ``` \ No newline at end of file From 61166ea201d6ae985a9eb8dc8797fdbd1d3dea82 Mon Sep 17 00:00:00 2001 From: websterlcl Date: Fri, 23 Apr 2021 11:17:26 +0800 Subject: [PATCH 06/14] fix the tothrow --- .../__tests__/category/poolpair.test.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts index 4d41280a3e..a2fc2cab03 100644 --- a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts @@ -246,10 +246,14 @@ describe('masternode', () => { } }) - // it.skip('should be failed as getting non-existent pair', async () => { - // const promise = client.poolpair.getPoolPair('DFI-NONEXIST') - // expect(promise).rejects.toThrow('RpcApiError: \'Pool not found\', code: -5') - // }) + it('should be failed as getting non-existent pair', async () => { + expect.assertions(1) + try { + await client.poolpair.getPoolPair('DFI-NONEXIST') + } catch (err) { + expect(err.message).toBe('RpcApiError: \'Pool not found\', code: -5') + } + }) }) describe('addPoolLiquidity', () => { @@ -272,7 +276,7 @@ describe('masternode', () => { expect(typeof data).toBe('string') }) - it.skip('should addPoolLiquidity with specific input token address', async () => { + it('should addPoolLiquidity with specific input token address', async () => { const tokenAAddress = await container.call('getnewaddress') const tokenBAddress = await container.call('getnewaddress') await container.call('sendtokenstoaddress', [{}, { [tokenAAddress]: ['100@DFI'] }]) From 866abecc280a4701847187731b6c578a3b174362 Mon Sep 17 00:00:00 2001 From: websterlcl Date: Fri, 23 Apr 2021 12:33:28 +0800 Subject: [PATCH 07/14] fix resp type --- .../__tests__/category/poolpair.test.ts | 55 ++++++++++--------- .../src/category/poolpair.ts | 21 ++----- 2 files changed, 33 insertions(+), 43 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts index a2fc2cab03..412edef24c 100644 --- a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts @@ -63,13 +63,13 @@ describe('masternode', () => { it('should createPoolPair', async () => { const poolpairsBefore = await client.poolpair.listPoolPairs() - expect(Object.keys(poolpairsBefore).length).toBe(0) + const poolpairsLengthBefore = Object.keys(poolpairsBefore).length const address = await container.call('getnewaddress') const metadata = { tokenA: 'DFI', tokenB: 'DBTC', - commission: 0, + commission: 1, status: true, ownerAddress: address } @@ -79,27 +79,28 @@ describe('masternode', () => { await container.generate(1) const poolpairsAfter = await client.poolpair.listPoolPairs() - expect(Object.keys(poolpairsAfter).length).toBe(1) + expect(Object.keys(poolpairsAfter).length).toBe(poolpairsLengthBefore + 1) + for (const k in poolpairsAfter) { const poolpair = poolpairsAfter[k] expect(poolpair.name).toBe('Default Defi token-DBTC') expect(poolpair.symbol).toBe(`${metadata.tokenA}-${metadata.tokenB}`) expect(poolpair.status).toBe(metadata.status) - expect(poolpair.commission).toBe(metadata.commission) + expect(poolpair.commission.toString()).toBe(new BigNumber(metadata.commission).toString()) expect(poolpair.ownerAddress).toBe(metadata.ownerAddress) - expect(poolpair.totalLiquidity).toBe(0) + expect(poolpair.totalLiquidity instanceof BigNumber).toBe(true) expect(typeof poolpair.idTokenA).toBe('string') expect(typeof poolpair.idTokenB).toBe('string') - expect(typeof poolpair.reserveA).toBe('number') - expect(typeof poolpair.reserveB).toBe('number') + expect(poolpair.reserveA instanceof BigNumber).toBe(true) + expect(poolpair.reserveB instanceof BigNumber).toBe(true) expect(typeof poolpair['reserveA/reserveB']).toBe('string') expect(typeof poolpair['reserveB/reserveA']).toBe('string') expect(poolpair.tradeEnabled).toBe(false) - expect(typeof poolpair.blockCommissionA).toBe('number') - expect(typeof poolpair.blockCommissionB).toBe('number') - expect(typeof poolpair.rewardPct).toBe('number') + expect(poolpair.blockCommissionA instanceof BigNumber).toBe(true) + expect(poolpair.blockCommissionB instanceof BigNumber).toBe(true) + expect(poolpair.rewardPct instanceof BigNumber).toBe(true) expect(typeof poolpair.creationTx).toBe('string') - expect(typeof poolpair.creationHeight).toBe('number') + expect(poolpair.creationHeight instanceof BigNumber).toBe(true) } }) }) @@ -125,38 +126,38 @@ describe('masternode', () => { if (poolpair.symbol === 'DFI-DETH') { expect(poolpair.name).toBe('Default Defi token-DETH') expect(poolpair.status).toBe(true) - expect(poolpair.commission).toBe(0.001) + expect(poolpair.commission.toString()).toBe(new BigNumber(0.001).toString()) points += 1 } if (poolpair.symbol === 'DFI-DXRP') { expect(poolpair.name).toBe('Default Defi token-DXRP') expect(poolpair.status).toBe(true) - expect(poolpair.commission).toBe(0.003) + expect(poolpair.commission.toString()).toBe(new BigNumber(0.003).toString()) points += 1 } if (poolpair.symbol === 'DFI-DUSD') { expect(poolpair.name).toBe('Default Defi token-DUSDT') expect(poolpair.status).toBe(false) - expect(poolpair.commission).toBe(0) + expect(poolpair.commission.toString()).toBe(new BigNumber(0).toString()) points += 1 } - expect(poolpair.totalLiquidity).toBe(0) + expect(poolpair.totalLiquidity instanceof BigNumber).toBe(true) expect(typeof poolpair.ownerAddress).toBe('string') expect(typeof poolpair.idTokenA).toBe('string') expect(typeof poolpair.idTokenB).toBe('string') - expect(typeof poolpair.reserveA).toBe('number') - expect(typeof poolpair.reserveB).toBe('number') + expect(poolpair.reserveA instanceof BigNumber).toBe(true) + expect(poolpair.reserveB instanceof BigNumber).toBe(true) expect(typeof poolpair['reserveA/reserveB']).toBe('string') expect(typeof poolpair['reserveB/reserveA']).toBe('string') expect(poolpair.tradeEnabled).toBe(false) - expect(typeof poolpair.blockCommissionA).toBe('number') - expect(typeof poolpair.blockCommissionB).toBe('number') - expect(typeof poolpair.rewardPct).toBe('number') + expect(poolpair.blockCommissionA instanceof BigNumber).toBe(true) + expect(poolpair.blockCommissionB instanceof BigNumber).toBe(true) + expect(poolpair.rewardPct instanceof BigNumber).toBe(true) expect(typeof poolpair.creationTx).toBe('string') - expect(typeof poolpair.creationHeight).toBe('number') + expect(poolpair.creationHeight instanceof BigNumber).toBe(true) } expect(points).toBe(3) @@ -220,16 +221,16 @@ describe('masternode', () => { expect(data.status).toBe(true) expect(typeof data.idTokenA).toBe('string') expect(typeof data.idTokenB).toBe('string') - expect(typeof data.reserveA).toBe('number') - expect(typeof data.reserveB).toBe('number') + expect(data.reserveA instanceof BigNumber).toBe(true) + expect(data.reserveB instanceof BigNumber).toBe(true) expect(typeof data['reserveA/reserveB']).toBe('string') expect(typeof data['reserveB/reserveA']).toBe('string') expect(data.tradeEnabled).toBe(false) - expect(typeof data.blockCommissionA).toBe('number') - expect(typeof data.blockCommissionB).toBe('number') - expect(typeof data.rewardPct).toBe('number') + expect(data.blockCommissionA instanceof BigNumber).toBe(true) + expect(data.blockCommissionB instanceof BigNumber).toBe(true) + expect(data.rewardPct instanceof BigNumber).toBe(true) expect(typeof data.creationTx).toBe('string') - expect(typeof data.creationHeight).toBe('number') + expect(data.creationHeight instanceof BigNumber).toBe(true) } }) diff --git a/packages/jellyfish-api-core/src/category/poolpair.ts b/packages/jellyfish-api-core/src/category/poolpair.ts index 8012289e3d..0295074aaa 100644 --- a/packages/jellyfish-api-core/src/category/poolpair.ts +++ b/packages/jellyfish-api-core/src/category/poolpair.ts @@ -49,18 +49,7 @@ export class PoolPair { }, verbose = true ): Promise { - return await this.client.call('listpoolpairs', [pagination, verbose], { - reserveA: 'bignumber', - reserveB: 'bignumber', - commission: 'bignumber', - totalLiquidity: 'bignumber', - 'reserveA/reserveB': 'bignumber', - 'reserveB/reserveA': 'bignumber', - blockCommissionA: 'bignumber', - blockCommissionB: 'bignumber', - rewardPct: 'bignumber', - customRewards: 'bignumber' - }) + return await this.client.call('listpoolpairs', [pagination, verbose], 'bignumber') } /** @@ -71,7 +60,7 @@ export class PoolPair { * @return {Promise} */ async getPoolPair (symbol: string, verbose = true): Promise { - return await this.client.call('getpoolpair', [symbol, verbose], 'number') + return await this.client.call('getpoolpair', [symbol, verbose], 'bignumber') } /** @@ -143,8 +132,8 @@ export interface PoolPairResult { reserveB: BigNumber commission: BigNumber totalLiquidity: BigNumber - ['reserveA/reserveB']: BigNumber - ['reserveB/reserveA']: BigNumber + ['reserveA/reserveB']: string + ['reserveB/reserveA']: string tradeEnabled: boolean ownerAddress: string blockCommissionA: BigNumber @@ -152,7 +141,7 @@ export interface PoolPairResult { rewardPct: BigNumber customRewards: BigNumber creationTx: string - creationHeight: number + creationHeight: BigNumber } } From 226024720c662943428b96da6b1394a0f81c625f Mon Sep 17 00:00:00 2001 From: websterlcl Date: Fri, 23 Apr 2021 13:55:37 +0800 Subject: [PATCH 08/14] improve test performance by using waitForWalletBalanceGTE, removing generate(100) --- .../__tests__/category/poolpair.test.ts | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts index 412edef24c..812c9c1a9d 100644 --- a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts @@ -10,6 +10,7 @@ describe('masternode', () => { await container.start() await container.waitForReady() await container.waitForWalletCoinbaseMaturity() + await container.waitForWalletBalanceGTE(200) }) afterAll(async () => { @@ -47,9 +48,9 @@ describe('masternode', () => { const address = await container.call('getnewaddress') // NOTE(canonbrother): using `minttokens` on DFI is an error as DFI is not mintable - // await container.call('minttokens', ['1000@DFI']) + // await container.call('minttokens', ['100@DFI']) const payload: { [key: string]: string } = {} - payload[address] = '2000@0' + payload[address] = '100@0' await container.call('utxostoaccount', [payload]) await container.call('minttokens', [`2000@${symbol}`]) @@ -62,6 +63,7 @@ describe('masternode', () => { }) it('should createPoolPair', async () => { + let assertion = 0 const poolpairsBefore = await client.poolpair.listPoolPairs() const poolpairsLengthBefore = Object.keys(poolpairsBefore).length @@ -83,25 +85,28 @@ describe('masternode', () => { for (const k in poolpairsAfter) { const poolpair = poolpairsAfter[k] - expect(poolpair.name).toBe('Default Defi token-DBTC') - expect(poolpair.symbol).toBe(`${metadata.tokenA}-${metadata.tokenB}`) - expect(poolpair.status).toBe(metadata.status) - expect(poolpair.commission.toString()).toBe(new BigNumber(metadata.commission).toString()) - expect(poolpair.ownerAddress).toBe(metadata.ownerAddress) - expect(poolpair.totalLiquidity instanceof BigNumber).toBe(true) - expect(typeof poolpair.idTokenA).toBe('string') - expect(typeof poolpair.idTokenB).toBe('string') - expect(poolpair.reserveA instanceof BigNumber).toBe(true) - expect(poolpair.reserveB instanceof BigNumber).toBe(true) - expect(typeof poolpair['reserveA/reserveB']).toBe('string') - expect(typeof poolpair['reserveB/reserveA']).toBe('string') - expect(poolpair.tradeEnabled).toBe(false) - expect(poolpair.blockCommissionA instanceof BigNumber).toBe(true) - expect(poolpair.blockCommissionB instanceof BigNumber).toBe(true) - expect(poolpair.rewardPct instanceof BigNumber).toBe(true) - expect(typeof poolpair.creationTx).toBe('string') - expect(poolpair.creationHeight instanceof BigNumber).toBe(true) + if (poolpair.name === 'Default Defi token-DBTC') { + expect(poolpair.symbol).toBe(`${metadata.tokenA}-${metadata.tokenB}`) + expect(poolpair.status).toBe(metadata.status) + expect(poolpair.commission.toString()).toBe(new BigNumber(metadata.commission).toString()) + expect(poolpair.ownerAddress).toBe(metadata.ownerAddress) + expect(poolpair.totalLiquidity instanceof BigNumber).toBe(true) + expect(typeof poolpair.idTokenA).toBe('string') + expect(typeof poolpair.idTokenB).toBe('string') + expect(poolpair.reserveA instanceof BigNumber).toBe(true) + expect(poolpair.reserveB instanceof BigNumber).toBe(true) + expect(typeof poolpair['reserveA/reserveB']).toBe('string') + expect(typeof poolpair['reserveB/reserveA']).toBe('string') + expect(poolpair.tradeEnabled).toBe(false) + expect(poolpair.blockCommissionA instanceof BigNumber).toBe(true) + expect(poolpair.blockCommissionB instanceof BigNumber).toBe(true) + expect(poolpair.rewardPct instanceof BigNumber).toBe(true) + expect(typeof poolpair.creationTx).toBe('string') + expect(poolpair.creationHeight instanceof BigNumber).toBe(true) + assertion += 1 + } } + expect(assertion).toBe(1) }) }) @@ -259,8 +264,6 @@ describe('masternode', () => { describe('addPoolLiquidity', () => { beforeAll(async () => { - await container.generate(100) - await createToken('DDAI') await mintTokens('DDAI') @@ -271,7 +274,7 @@ describe('masternode', () => { it('should addPoolLiquidity', async () => { const shareAddress = await container.call('getnewaddress') const data = await client.poolpair.addPoolLiquidity({ - '*': ['100@DFI', '200@DDAI'] + '*': ['10@DFI', '200@DDAI'] }, shareAddress) expect(typeof data).toBe('string') @@ -280,13 +283,13 @@ describe('masternode', () => { it('should addPoolLiquidity with specific input token address', async () => { const tokenAAddress = await container.call('getnewaddress') const tokenBAddress = await container.call('getnewaddress') - await container.call('sendtokenstoaddress', [{}, { [tokenAAddress]: ['100@DFI'] }]) + await container.call('sendtokenstoaddress', [{}, { [tokenAAddress]: ['10@DFI'] }]) await container.call('sendtokenstoaddress', [{}, { [tokenBAddress]: ['200@DDAI'] }]) await container.generate(25) const shareAddress = await container.call('getnewaddress') const data = await client.poolpair.addPoolLiquidity({ - [tokenAAddress]: '50@DFI', + [tokenAAddress]: '5@DFI', [tokenBAddress]: '100@DDAI' }, shareAddress) @@ -298,8 +301,8 @@ describe('masternode', () => { const shareAddress = await container.call('getnewaddress') const data = await client.poolpair.addPoolLiquidity({ - '*': ['100@DFI', '200@DDAI'] - }, shareAddress, { utxos: [{ txid: utxos[0].txid, vout: 0 }] }) + '*': ['10@DFI', '200@DDAI'] + }, shareAddress, { utxos: [{ txid: utxos[0].txid, vout: 0 }] }) // ApplyAddPoolLiquidityTx: tx must have at least one input from account owner', code: -32600 expect(typeof data).toBe('string') }) @@ -309,7 +312,7 @@ describe('masternode', () => { async function addPoolLiquidity (): Promise { const shareAddress = await container.call('getnewaddress') const data = await client.poolpair.addPoolLiquidity({ - '*': ['100@DFI', '200@DSWAP'] + '*': ['10@DFI', '200@DSWAP'] }, shareAddress) expect(typeof data).toBe('string') @@ -318,8 +321,6 @@ describe('masternode', () => { } beforeAll(async () => { - await container.generate(100) - await createToken('DSWAP') await mintTokens('DSWAP') From f2cb2650c15b55777e9a0e1b5dcd362dd9d96375 Mon Sep 17 00:00:00 2001 From: websterlcl Date: Fri, 23 Apr 2021 17:58:55 +0800 Subject: [PATCH 09/14] reorder the test, addpoolliquidity with utxos failed --- .../__tests__/category/poolpair.test.ts | 426 ++++++++++-------- .../src/category/poolpair.ts | 4 +- 2 files changed, 231 insertions(+), 199 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts index 812c9c1a9d..6e91753aa2 100644 --- a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts @@ -57,137 +57,135 @@ describe('masternode', () => { await container.generate(25) } - describe('createPoolPair', () => { + describe('addPoolLiquidity', () => { beforeAll(async () => { - await createToken('DBTC') + await createToken('DDAI') + + await mintTokens('DDAI') + + await createPoolPair('DDAI') }) - it('should createPoolPair', async () => { - let assertion = 0 - const poolpairsBefore = await client.poolpair.listPoolPairs() - const poolpairsLengthBefore = Object.keys(poolpairsBefore).length + it('should addPoolLiquidity', async () => { + const shareAddress = await container.call('getnewaddress') + const data = await client.poolpair.addPoolLiquidity({ + '*': ['10@DFI', '200@DDAI'] + }, shareAddress) - const address = await container.call('getnewaddress') - const metadata = { - tokenA: 'DFI', - tokenB: 'DBTC', - commission: 1, - status: true, - ownerAddress: address - } - const data = await client.poolpair.createPoolPair(metadata) expect(typeof data).toBe('string') + }) - await container.generate(1) + it('should addPoolLiquidity with specific input token address', async () => { + const tokenAAddress = await container.call('getnewaddress') + const tokenBAddress = await container.call('getnewaddress') + await container.call('sendtokenstoaddress', [{}, { [tokenAAddress]: ['10@DFI'] }]) + await container.call('sendtokenstoaddress', [{}, { [tokenBAddress]: ['200@DDAI'] }]) + await container.generate(25) - const poolpairsAfter = await client.poolpair.listPoolPairs() - expect(Object.keys(poolpairsAfter).length).toBe(poolpairsLengthBefore + 1) + const shareAddress = await container.call('getnewaddress') + const data = await client.poolpair.addPoolLiquidity({ + [tokenAAddress]: '5@DFI', + [tokenBAddress]: '100@DDAI' + }, shareAddress) - for (const k in poolpairsAfter) { - const poolpair = poolpairsAfter[k] - if (poolpair.name === 'Default Defi token-DBTC') { - expect(poolpair.symbol).toBe(`${metadata.tokenA}-${metadata.tokenB}`) - expect(poolpair.status).toBe(metadata.status) - expect(poolpair.commission.toString()).toBe(new BigNumber(metadata.commission).toString()) - expect(poolpair.ownerAddress).toBe(metadata.ownerAddress) - expect(poolpair.totalLiquidity instanceof BigNumber).toBe(true) - expect(typeof poolpair.idTokenA).toBe('string') - expect(typeof poolpair.idTokenB).toBe('string') - expect(poolpair.reserveA instanceof BigNumber).toBe(true) - expect(poolpair.reserveB instanceof BigNumber).toBe(true) - expect(typeof poolpair['reserveA/reserveB']).toBe('string') - expect(typeof poolpair['reserveB/reserveA']).toBe('string') - expect(poolpair.tradeEnabled).toBe(false) - expect(poolpair.blockCommissionA instanceof BigNumber).toBe(true) - expect(poolpair.blockCommissionB instanceof BigNumber).toBe(true) - expect(poolpair.rewardPct instanceof BigNumber).toBe(true) - expect(typeof poolpair.creationTx).toBe('string') - expect(poolpair.creationHeight instanceof BigNumber).toBe(true) - assertion += 1 + expect(typeof data).toBe('string') + }) + + it('should addPoolLiquidity with utxos', async () => { + const shareAddress = await container.call('getnewaddress') + const tokenAAddress = await container.call('getnewaddress') + const tokenBAddress = await container.call('getnewaddress') + await container.call('sendtokenstoaddress', [{}, { [tokenAAddress]: ['10@DFI'] }]) + await container.call('sendtokenstoaddress', [{}, { [tokenBAddress]: ['200@DDAI'] }]) + await container.generate(25) + + const { txid: txidA } = await container.fundAddress(tokenAAddress, 10) + const { txid: txidB } = await container.fundAddress(tokenBAddress, 10) + console.log('txid: ', txidA, txidB, tokenAAddress, tokenBAddress) + await container.generate(2) + + const utxos = await container.call('listunspent') + const inputs = utxos.filter((utxo: any) => utxo.txid === txidA || utxo.txid === txidB).map((utxo: any) => { + return { + txid: utxo.txid, + vout: utxo.vout } - } - expect(assertion).toBe(1) + }) + console.log('inputs: ', inputs) + + // ApplyAddPoolLiquidityTx: tx must have at least one input from account owner', code: -32600 + const data = await client.poolpair.addPoolLiquidity({ + [tokenAAddress]: '5@DFI', + [tokenBAddress]: '100@DDAI' + }, shareAddress, { utxos: inputs }) + + // NOTE(canonbrother): cannot use '*' (auto-selection) with providing utxos as mapping specific utxos in needed + // const shareAddress = await container.call('getnewaddress') + // const data = await client.poolpair.addPoolLiquidity({ + // '*': ['10@DFI', '200@DDAI'] + // }, shareAddress, { utxos: [{ txid: utxo.txid, vout: 0 }] }) + + expect(typeof data).toBe('string') }) }) - describe('listPoolPairs', () => { - beforeAll(async () => { - await createToken('DETH') - await createToken('DXRP') - await createToken('DUSDT') + describe('listPoolShares', () => { + async function addPoolLiquidity (): Promise { + const shareAddress = await container.call('getnewaddress') + const data = await client.poolpair.addPoolLiquidity({ + '*': ['10@DFI', '200@DSWAP'] + }, shareAddress) - await createPoolPair('DETH', { commission: 0.001 }) - await createPoolPair('DXRP', { commission: 0.003 }) - await createPoolPair('DUSDT', { status: false }) - }) + expect(typeof data).toBe('string') - it('should listPoolPairs', async () => { - let points = 0 - const poolpairs = await client.poolpair.listPoolPairs() + await container.generate(1) + } - for (const k in poolpairs) { - const poolpair = poolpairs[k] + beforeAll(async () => { + await createToken('DSWAP') - if (poolpair.symbol === 'DFI-DETH') { - expect(poolpair.name).toBe('Default Defi token-DETH') - expect(poolpair.status).toBe(true) - expect(poolpair.commission.toString()).toBe(new BigNumber(0.001).toString()) - points += 1 - } + await mintTokens('DSWAP') - if (poolpair.symbol === 'DFI-DXRP') { - expect(poolpair.name).toBe('Default Defi token-DXRP') - expect(poolpair.status).toBe(true) - expect(poolpair.commission.toString()).toBe(new BigNumber(0.003).toString()) - points += 1 - } + await createPoolPair('DSWAP') - if (poolpair.symbol === 'DFI-DUSD') { - expect(poolpair.name).toBe('Default Defi token-DUSDT') - expect(poolpair.status).toBe(false) - expect(poolpair.commission.toString()).toBe(new BigNumber(0).toString()) - points += 1 - } + await addPoolLiquidity() + await addPoolLiquidity() + await addPoolLiquidity() + }) - expect(poolpair.totalLiquidity instanceof BigNumber).toBe(true) - expect(typeof poolpair.ownerAddress).toBe('string') - expect(typeof poolpair.idTokenA).toBe('string') - expect(typeof poolpair.idTokenB).toBe('string') - expect(poolpair.reserveA instanceof BigNumber).toBe(true) - expect(poolpair.reserveB instanceof BigNumber).toBe(true) - expect(typeof poolpair['reserveA/reserveB']).toBe('string') - expect(typeof poolpair['reserveB/reserveA']).toBe('string') - expect(poolpair.tradeEnabled).toBe(false) - expect(poolpair.blockCommissionA instanceof BigNumber).toBe(true) - expect(poolpair.blockCommissionB instanceof BigNumber).toBe(true) - expect(poolpair.rewardPct instanceof BigNumber).toBe(true) - expect(typeof poolpair.creationTx).toBe('string') - expect(poolpair.creationHeight instanceof BigNumber).toBe(true) - } + it('should listPoolShares', async () => { + const poolShares = await client.poolpair.listPoolShares() - expect(points).toBe(3) + for (const k in poolShares) { + const data = poolShares[k] + expect(typeof data.poolID).toBe('string') + expect(typeof data.owner).toBe('string') + expect(data['%'] instanceof BigNumber).toBe(true) + expect(data.amount instanceof BigNumber).toBe(true) + expect(data.totalLiquidity instanceof BigNumber).toBe(true) + } }) - it('should listPoolPairs with pagination and return an empty object as out of range', async () => { + it('should listPoolShares with pagination and return an empty object as out of range', async () => { const pagination = { start: 300, including_start: true, limit: 100 } - const poolpairs = await client.poolpair.listPoolPairs(pagination) + const poolShares = await client.poolpair.listPoolShares(pagination) - expect(Object.keys(poolpairs).length).toBe(0) + expect(Object.keys(poolShares).length).toBe(0) }) - it('should listPoolPairs with pagination limit', async () => { + it('should listPoolShares with pagination limit', async () => { const pagination = { start: 0, including_start: true, limit: 2 } - const poolpairs = await client.poolpair.listPoolPairs(pagination) + const poolShares = await client.poolpair.listPoolShares(pagination) - expect(Object.keys(poolpairs).length).toBe(2) + expect(Object.keys(poolShares).length).toBe(2) }) it('should listPoolPairs with verbose false', async () => { @@ -196,16 +194,31 @@ describe('masternode', () => { including_start: true, limit: 100 } - const poolpairs = await client.poolpair.listPoolPairs(pagination, false) + const poolShares = await client.poolpair.listPoolShares(pagination, false) - for (const k in poolpairs) { - const poolpair = poolpairs[k] + for (const k in poolShares) { + const data = poolShares[k] + expect(typeof data.poolID).toBe('string') + expect(typeof data.owner).toBe('string') + expect(data['%'] instanceof BigNumber).toBe(true) + } + }) - expect(typeof poolpair.symbol).toBe('string') - expect(typeof poolpair.name).toBe('string') - expect(typeof poolpair.status).toBe('boolean') - expect(typeof poolpair.idTokenA).toBe('string') - expect(typeof poolpair.idTokenB).toBe('string') + it('should listPoolPairs with isMineOnly true', async () => { + const pagination = { + start: 0, + including_start: true, + limit: 100 + } + const poolShares = await client.poolpair.listPoolShares(pagination, true, { isMineOnly: true }) + + for (const k in poolShares) { + const data = poolShares[k] + expect(typeof data.poolID).toBe('string') + expect(typeof data.owner).toBe('string') + expect(data['%'] instanceof BigNumber).toBe(true) + expect(data.amount instanceof BigNumber).toBe(true) + expect(data.totalLiquidity instanceof BigNumber).toBe(true) } }) }) @@ -262,109 +275,90 @@ describe('masternode', () => { }) }) - describe('addPoolLiquidity', () => { + describe('listPoolPairs', () => { beforeAll(async () => { - await createToken('DDAI') - - await mintTokens('DDAI') - - await createPoolPair('DDAI') - }) - - it('should addPoolLiquidity', async () => { - const shareAddress = await container.call('getnewaddress') - const data = await client.poolpair.addPoolLiquidity({ - '*': ['10@DFI', '200@DDAI'] - }, shareAddress) - - expect(typeof data).toBe('string') - }) - - it('should addPoolLiquidity with specific input token address', async () => { - const tokenAAddress = await container.call('getnewaddress') - const tokenBAddress = await container.call('getnewaddress') - await container.call('sendtokenstoaddress', [{}, { [tokenAAddress]: ['10@DFI'] }]) - await container.call('sendtokenstoaddress', [{}, { [tokenBAddress]: ['200@DDAI'] }]) - await container.generate(25) - - const shareAddress = await container.call('getnewaddress') - const data = await client.poolpair.addPoolLiquidity({ - [tokenAAddress]: '5@DFI', - [tokenBAddress]: '100@DDAI' - }, shareAddress) - - expect(typeof data).toBe('string') - }) - - it.skip('should addPoolLiquidity with utxos', async () => { - const utxos = await container.call('listunspent') - - const shareAddress = await container.call('getnewaddress') - const data = await client.poolpair.addPoolLiquidity({ - '*': ['10@DFI', '200@DDAI'] - }, shareAddress, { utxos: [{ txid: utxos[0].txid, vout: 0 }] }) // ApplyAddPoolLiquidityTx: tx must have at least one input from account owner', code: -32600 + await createToken('DETH') + await createToken('DXRP') + await createToken('DUSDT') - expect(typeof data).toBe('string') + await createPoolPair('DETH', { commission: 0.001 }) + await createPoolPair('DXRP', { commission: 0.003 }) + await createPoolPair('DUSDT', { status: false }) }) - }) - - describe('listPoolShares', () => { - async function addPoolLiquidity (): Promise { - const shareAddress = await container.call('getnewaddress') - const data = await client.poolpair.addPoolLiquidity({ - '*': ['10@DFI', '200@DSWAP'] - }, shareAddress) - expect(typeof data).toBe('string') + it('should listPoolPairs', async () => { + let assertions = 0 + const poolpairs = await client.poolpair.listPoolPairs() - await container.generate(1) - } + for (const k in poolpairs) { + const poolpair = poolpairs[k] - beforeAll(async () => { - await createToken('DSWAP') + if (poolpair.symbol === 'DFI-DETH') { + expect(poolpair.name).toBe('Default Defi token-DETH') + expect(poolpair.status).toBe(true) + expect(poolpair.commission.toString()).toBe(new BigNumber(0.001).toString()) + assertions += 1 + } - await mintTokens('DSWAP') + if (poolpair.symbol === 'DFI-DXRP') { + expect(poolpair.name).toBe('Default Defi token-DXRP') + expect(poolpair.status).toBe(true) + expect(poolpair.commission.toString()).toBe(new BigNumber(0.003).toString()) + assertions += 1 + } - await createPoolPair('DSWAP') + if (poolpair.symbol === 'DFI-DUSD') { + expect(poolpair.name).toBe('Default Defi token-DUSDT') + expect(poolpair.status).toBe(false) + expect(poolpair.commission.toString()).toBe(new BigNumber(0).toString()) + assertions += 1 + } - await addPoolLiquidity() - await addPoolLiquidity() - await addPoolLiquidity() - }) + expect(poolpair.totalLiquidity instanceof BigNumber).toBe(true) + expect(typeof poolpair.ownerAddress).toBe('string') + expect(typeof poolpair.idTokenA).toBe('string') + expect(typeof poolpair.idTokenB).toBe('string') + expect(poolpair.reserveA instanceof BigNumber).toBe(true) + expect(poolpair.reserveB instanceof BigNumber).toBe(true) - it('should listPoolShares', async () => { - const poolShares = await client.poolpair.listPoolShares() + if (poolpair['reserveA/reserveB'] instanceof BigNumber && poolpair['reserveB/reserveA'] instanceof BigNumber) { + expect(poolpair.tradeEnabled).toBe(true) + } else { + expect(poolpair['reserveA/reserveB']).toBe('0') + expect(poolpair['reserveB/reserveA']).toBe('0') + expect(poolpair.tradeEnabled).toBe(false) + } - for (const k in poolShares) { - const data = poolShares[k] - expect(typeof data.poolID).toBe('string') - expect(typeof data.owner).toBe('string') - expect(data['%'] instanceof BigNumber).toBe(true) - expect(data.amount instanceof BigNumber).toBe(true) - expect(data.totalLiquidity instanceof BigNumber).toBe(true) + expect(poolpair.blockCommissionA instanceof BigNumber).toBe(true) + expect(poolpair.blockCommissionB instanceof BigNumber).toBe(true) + expect(poolpair.rewardPct instanceof BigNumber).toBe(true) + expect(typeof poolpair.creationTx).toBe('string') + expect(poolpair.creationHeight instanceof BigNumber).toBe(true) } + + expect(assertions).toBe(3) }) - it('should listPoolShares with pagination and return an empty object as out of range', async () => { + it('should listPoolPairs with pagination and return an empty object as out of range', async () => { const pagination = { start: 300, including_start: true, limit: 100 } - const poolShares = await client.poolpair.listPoolShares(pagination) + const poolpairs = await client.poolpair.listPoolPairs(pagination) - expect(Object.keys(poolShares).length).toBe(0) + expect(Object.keys(poolpairs).length).toBe(0) }) - it('should listPoolShares with pagination limit', async () => { + it('should listPoolPairs with pagination limit', async () => { const pagination = { start: 0, including_start: true, limit: 2 } - const poolShares = await client.poolpair.listPoolShares(pagination) + const poolpairs = await client.poolpair.listPoolPairs(pagination) - expect(Object.keys(poolShares).length).toBe(2) + expect(Object.keys(poolpairs).length).toBe(2) }) it('should listPoolPairs with verbose false', async () => { @@ -373,32 +367,70 @@ describe('masternode', () => { including_start: true, limit: 100 } - const poolShares = await client.poolpair.listPoolShares(pagination, false) + const poolpairs = await client.poolpair.listPoolPairs(pagination, false) - for (const k in poolShares) { - const data = poolShares[k] - expect(typeof data.poolID).toBe('string') - expect(typeof data.owner).toBe('string') - expect(data['%'] instanceof BigNumber).toBe(true) + for (const k in poolpairs) { + const poolpair = poolpairs[k] + + expect(typeof poolpair.symbol).toBe('string') + expect(typeof poolpair.name).toBe('string') + expect(typeof poolpair.status).toBe('boolean') + expect(typeof poolpair.idTokenA).toBe('string') + expect(typeof poolpair.idTokenB).toBe('string') } }) + }) - it('should listPoolPairs with isMineOnly true', async () => { - const pagination = { - start: 0, - including_start: true, - limit: 100 + describe('createPoolPair', () => { + beforeAll(async () => { + await createToken('DBTC') + }) + + it('should createPoolPair', async () => { + let assertions = 0 + const poolpairsBefore = await client.poolpair.listPoolPairs() + const poolpairsLengthBefore = Object.keys(poolpairsBefore).length + + const address = await container.call('getnewaddress') + const metadata = { + tokenA: 'DFI', + tokenB: 'DBTC', + commission: 1, + status: true, + ownerAddress: address } - const poolShares = await client.poolpair.listPoolShares(pagination, true, { isMineOnly: true }) + const data = await client.poolpair.createPoolPair(metadata) + expect(typeof data).toBe('string') - for (const k in poolShares) { - const data = poolShares[k] - expect(typeof data.poolID).toBe('string') - expect(typeof data.owner).toBe('string') - expect(data['%'] instanceof BigNumber).toBe(true) - expect(data.amount instanceof BigNumber).toBe(true) - expect(data.totalLiquidity instanceof BigNumber).toBe(true) + await container.generate(1) + + const poolpairsAfter = await client.poolpair.listPoolPairs() + expect(Object.keys(poolpairsAfter).length).toBe(poolpairsLengthBefore + 1) + + for (const k in poolpairsAfter) { + const poolpair = poolpairsAfter[k] + if (poolpair.name === 'Default Defi token-DBTC') { + expect(poolpair.symbol).toBe(`${metadata.tokenA}-${metadata.tokenB}`) + expect(poolpair.status).toBe(metadata.status) + expect(poolpair.commission.toString()).toBe(new BigNumber(metadata.commission).toString()) + expect(poolpair.ownerAddress).toBe(metadata.ownerAddress) + expect(poolpair.totalLiquidity instanceof BigNumber).toBe(true) + expect(typeof poolpair.idTokenA).toBe('string') + expect(typeof poolpair.idTokenB).toBe('string') + expect(poolpair.reserveA instanceof BigNumber).toBe(true) + expect(poolpair.reserveB instanceof BigNumber).toBe(true) + expect(typeof poolpair['reserveA/reserveB']).toBe('string') + expect(typeof poolpair['reserveB/reserveA']).toBe('string') + expect(poolpair.tradeEnabled).toBe(false) + expect(poolpair.blockCommissionA instanceof BigNumber).toBe(true) + expect(poolpair.blockCommissionB instanceof BigNumber).toBe(true) + expect(poolpair.rewardPct instanceof BigNumber).toBe(true) + expect(typeof poolpair.creationTx).toBe('string') + expect(poolpair.creationHeight instanceof BigNumber).toBe(true) + assertions += 1 + } } + expect(assertions).toBe(1) }) }) }) diff --git a/packages/jellyfish-api-core/src/category/poolpair.ts b/packages/jellyfish-api-core/src/category/poolpair.ts index 0295074aaa..647f4ac27a 100644 --- a/packages/jellyfish-api-core/src/category/poolpair.ts +++ b/packages/jellyfish-api-core/src/category/poolpair.ts @@ -132,8 +132,8 @@ export interface PoolPairResult { reserveB: BigNumber commission: BigNumber totalLiquidity: BigNumber - ['reserveA/reserveB']: string - ['reserveB/reserveA']: string + ['reserveA/reserveB']: BigNumber | string + ['reserveB/reserveA']: BigNumber | string tradeEnabled: boolean ownerAddress: string blockCommissionA: BigNumber From f20c21a897d3246f8598d3610de17ec805ea8239 Mon Sep 17 00:00:00 2001 From: websterlcl Date: Fri, 23 Apr 2021 19:41:48 +0800 Subject: [PATCH 10/14] fix addpooliquidity with utxos --- .../__tests__/category/poolpair.test.ts | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts index 6e91753aa2..9809b8d72f 100644 --- a/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/poolpair.test.ts @@ -1,5 +1,5 @@ -import { MasterNodeRegTestContainer } from '@defichain/testcontainers' import BigNumber from 'bignumber.js' +import { MasterNodeRegTestContainer } from '@defichain/testcontainers' import { ContainerAdapterClient } from '../container_adapter_client' describe('masternode', () => { @@ -99,21 +99,20 @@ describe('masternode', () => { await container.call('sendtokenstoaddress', [{}, { [tokenBAddress]: ['200@DDAI'] }]) await container.generate(25) - const { txid: txidA } = await container.fundAddress(tokenAAddress, 10) - const { txid: txidB } = await container.fundAddress(tokenBAddress, 10) - console.log('txid: ', txidA, txidB, tokenAAddress, tokenBAddress) + const txid = await container.call('sendmany', ['', { + [tokenAAddress]: 10, + [tokenBAddress]: 20 + }]) await container.generate(2) const utxos = await container.call('listunspent') - const inputs = utxos.filter((utxo: any) => utxo.txid === txidA || utxo.txid === txidB).map((utxo: any) => { + const inputs = utxos.filter((utxo: any) => utxo.txid === txid).map((utxo: any) => { return { txid: utxo.txid, vout: utxo.vout } }) - console.log('inputs: ', inputs) - // ApplyAddPoolLiquidityTx: tx must have at least one input from account owner', code: -32600 const data = await client.poolpair.addPoolLiquidity({ [tokenAAddress]: '5@DFI', [tokenBAddress]: '100@DDAI' @@ -127,6 +126,26 @@ describe('masternode', () => { expect(typeof data).toBe('string') }) + + it('should fail while addPoolLiquidity with utxos which does not include account owner', async () => { + const shareAddress = await container.call('getnewaddress') + const tokenAAddress = await container.call('getnewaddress') + const tokenBAddress = await container.call('getnewaddress') + + const utxos = await container.call('listunspent') + const inputs = utxos.map((utxo: any) => { + return { + txid: utxo.txid, + vout: utxo.vout + } + }) + + const promise = client.poolpair.addPoolLiquidity({ + [tokenAAddress]: '5@DFI', + [tokenBAddress]: '100@DDAI' + }, shareAddress, { utxos: inputs }) + await expect(promise).rejects.toThrow('tx must have at least one input from account owner') + }) }) describe('listPoolShares', () => { @@ -266,12 +285,9 @@ describe('masternode', () => { }) it('should be failed as getting non-existent pair', async () => { - expect.assertions(1) - try { - await client.poolpair.getPoolPair('DFI-NONEXIST') - } catch (err) { - expect(err.message).toBe('RpcApiError: \'Pool not found\', code: -5') - } + const promise = client.poolpair.getPoolPair('DFI-NONEXIST') + + await expect(promise).rejects.toThrow('Pool not found') }) }) From d5e7e27ad5c5fc7671cca9c41cc8a74c2ea0adcb Mon Sep 17 00:00:00 2001 From: websterlcl Date: Fri, 23 Apr 2021 20:00:09 +0800 Subject: [PATCH 11/14] rename --- website/docs/jellyfish/api/poolpair.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/website/docs/jellyfish/api/poolpair.md b/website/docs/jellyfish/api/poolpair.md index a3c5dc3c18..ec6c397168 100644 --- a/website/docs/jellyfish/api/poolpair.md +++ b/website/docs/jellyfish/api/poolpair.md @@ -2,22 +2,22 @@ id: poolPair title: Pool Pair API sidebar_label: Pool Pair API -slug: /jellyfish/api/pool-pair +slug: /jellyfish/api/poolpair --- ```js import {Client} from '@defichain/jellyfish' const client = new Client() // Using client.poolPair. -const something = await client.poolPair.method() +const something = await client.poolpair.method() ``` ## listPoolPairs Returns information about pools -```ts title="client.poolPair.listPoolPairs()" -interface poolPair { +```ts title="client.poolpair.listPoolPairs()" +interface poolpair { listPoolPairs ( pagination: PoolPairPagination = { start: 0, @@ -64,7 +64,7 @@ interface PoolPairPagination { Returns information about pools ```ts title="client.poolPair.getPoolPair()" -interface poolPair { +interface poolpair { getPoolPair (symbol: string, verbose = true): Promise } @@ -98,7 +98,7 @@ interface PoolPairResult { Add pool liquidity transaction ```ts title="client.poolPair.addPoolLiquidity()" -interface poolPair { +interface poolpair { addPoolLiquidity (from: AddPoolLiquiditySource, shareAddress: string, options: AddPoolLiquidityOptions = {}): Promise } @@ -121,7 +121,7 @@ interface AddPoolLiquidityUTXO { Returns information about pools ```ts title="client.poolPair.listPoolShares()" -interface poolPair { +interface poolpair { listPoolShares ( pagination: PoolPairPagination = { start: 0, From 4d12dee53299ef48079f5f62e6b794cf49a78c62 Mon Sep 17 00:00:00 2001 From: websterlcl Date: Mon, 26 Apr 2021 09:39:45 +0800 Subject: [PATCH 12/14] refine jsdoc syntax --- .../src/category/poolpair.ts | 20 ++++----- .../jellyfish-api-core/src/category/rawtx.ts | 12 +++--- .../jellyfish-api-core/src/category/token.ts | 14 +++---- .../jellyfish-api-core/src/category/wallet.ts | 42 +++++++++---------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/packages/jellyfish-api-core/src/category/poolpair.ts b/packages/jellyfish-api-core/src/category/poolpair.ts index 647f4ac27a..42ab27be4b 100644 --- a/packages/jellyfish-api-core/src/category/poolpair.ts +++ b/packages/jellyfish-api-core/src/category/poolpair.ts @@ -20,11 +20,11 @@ export class PoolPair { * @param {number} metadata.commission * @param {boolean} metadata.status * @param {string} metadata.ownerAddress - * @param {string=} metadata.customRewards - * @param {string=} metadata.pairSymbol + * @param {string} [metadata.customRewards] + * @param {string} [metadata.pairSymbol] * @param {CreatePoolPairUTXO[]} utxos is an array of specific UTXOs to spend - * @param {string} utxo.txid - * @param {number} utxo.vout + * @param {string} utxos.txid + * @param {number} utxos.vout * @return {Promise} */ async createPoolPair (metadata: CreatePoolPairMetadata, utxos: CreatePoolPairUTXO[] = []): Promise { @@ -69,10 +69,10 @@ export class PoolPair { * @param {AddPoolLiquiditySource} from pool liquidity sources * @param {string | string[]} from[address] provides at least two types of token with format 'amoun@token' * @param {string} shareAddress defi address for crediting tokens - * @param {AddPoolLiquidityOptions} options - * @param {AddPoolLiquidityUTXO[]=} options.utxos utxos array of specific UTXOs to spend - * @param {string} options.utxos.txid - * @param {number} options.utxos.vout + * @param {AddPoolLiquidityOptions} [options] + * @param {AddPoolLiquidityUTXO[]} [options.utxos] utxos array of specific UTXOs to spend + * @param {string} [options.utxos.txid] + * @param {number} [options.utxos.vout] * @return {Promise} */ async addPoolLiquidity (from: AddPoolLiquiditySource, shareAddress: string, options: AddPoolLiquidityOptions = {}): Promise { @@ -88,8 +88,8 @@ export class PoolPair { * @param {boolean} pagination.including_start default = true * @param {number} pagination.limit to limit number of records * @param {boolean} verbose default = true, otherwise only poolID, owner and % - * @param {PoolShareOptions} options - * @param {boolean=} options.isMineOnly default = true + * @param {PoolShareOptions} [options] + * @param {boolean} [options.isMineOnly=true] * @return {Promise} */ async listPoolShares ( diff --git a/packages/jellyfish-api-core/src/category/rawtx.ts b/packages/jellyfish-api-core/src/category/rawtx.ts index 24bc98a1e1..45460cb1f0 100644 --- a/packages/jellyfish-api-core/src/category/rawtx.ts +++ b/packages/jellyfish-api-core/src/category/rawtx.ts @@ -25,9 +25,9 @@ export class RawTx { * * @param {CreateRawTxIn[]} inputs array of inputs * @param {CreateRawTxOut[]} outputs array with outputs - * @param {CreateRawTxOptions=} options - * @param {number=} options.locktime Non-0 value also locktime-activates inputs - * @param {boolean=} options.replaceable Marks this transaction as BIP125-replaceable + * @param {CreateRawTxOptions} [options] + * @param {number} [options.locktime] Non-0 value also locktime-activates inputs + * @param {boolean} [options.replaceable] Marks this transaction as BIP125-replaceable * @return {Promise} hex string of the transaction */ async createRawTransaction ( @@ -49,9 +49,9 @@ export class RawTx { * * @param {string} rawTx unsigned raw transaction * @param {string[]} privKeys array of base58-encoded private keys for signing (WIF) - * @param {SignRawTxWithKeyOptions=} options - * @param {SigHashType=} options.sigHashType the signature hash type to use - * @param {SignRawTxWithKeyPrevTx[]=} options.prevTxs array of previous dependent transaction outputs + * @param {SignRawTxWithKeyOption} [options] + * @param {SigHashType} [options.sigHashType] the signature hash type to use + * @param {SignRawTxWithKeyPrevTx[]} [options.prevTxs] array of previous dependent transaction outputs * @return {Promise} */ async signRawTransactionWithKey ( diff --git a/packages/jellyfish-api-core/src/category/token.ts b/packages/jellyfish-api-core/src/category/token.ts index 17b4494d51..e573af64d2 100644 --- a/packages/jellyfish-api-core/src/category/token.ts +++ b/packages/jellyfish-api-core/src/category/token.ts @@ -38,13 +38,13 @@ export class Token { * Updates a token with given metadata * * @param {string} token symbolKey, id ror creation tx - * @param {UpdateTokenMetadata=} metadata - * @param {string=} metadata.symbol - * @param {string=} metadata.name - * @param {boolean=} metadata.isDAT - * @param {boolean=} metadata.mintable - * @param {boolean=} metadata.tradeable - * @param {boolean=} metadata.finalize + * @param {UpdateTokenMetadata} [metadata] + * @param {string} [metadata.symbol] + * @param {string} [metadata.name] + * @param {boolean} [metadata.isDAT] + * @param {boolean} [metadata.mintable] + * @param {boolean} [metadata.tradeable] + * @param {boolean} [metadata.finalize] * @return {Promise} */ async updateToken (token: string, metadata?: UpdateTokenMetadata): Promise { diff --git a/packages/jellyfish-api-core/src/category/wallet.ts b/packages/jellyfish-api-core/src/category/wallet.ts index 474fc64240..783bd81681 100644 --- a/packages/jellyfish-api-core/src/category/wallet.ts +++ b/packages/jellyfish-api-core/src/category/wallet.ts @@ -53,15 +53,15 @@ export class Wallet { * * @param {number} minimumConfirmation default = 1, to filter * @param {number} maximumConfirmation default = 9999999, to filter - * @param {ListUnspentOptions=} options - * @param {string[]=} options.addresses to filter - * @param {boolean=} options.includeUnsafe default = true, include outputs that are not safe to spend - * @param {ListUnspentQueryOptions=} options.queryOptions - * @param {number=} options.queryOptions.minimumAmount default = 0, minimum value of each UTXO - * @param {number=} options.queryOptions.maximumAmount default is 'unlimited', maximum value of each UTXO - * @param {number=} options.queryOptions.maximumCount default is 'unlimited', maximum number of UTXOs - * @param {number=} options.queryOptions.minimumSumAmount default is 'unlimited', minimum sum valie of all UTXOs - * @param {string=} options.queryOptions.tokenId default is 'all', filter by token + * @param {ListUnspentOptions} [options] + * @param {string[]} [options.addresses] to filter + * @param {boolean} [options.includeUnsafe=true] default = true, include outputs that are not safe to spend + * @param {ListUnspentQueryOptions} [options.queryOptions] + * @param {number} [options.queryOptions.minimumAmount] default = 0, minimum value of each UTXO + * @param {number} [options.queryOptions.maximumAmount] default is 'unlimited', maximum value of each UTXO + * @param {number} [options.queryOptions.maximumCount] default is 'unlimited', maximum number of UTXOs + * @param {number} [options.queryOptions.minimumSumAmount] default is 'unlimited', minimum sum valie of all UTXOs + * @param {string} [options.queryOptions.tokenId] default is 'all', filter by token * @return {Promise} */ async listUnspent ( @@ -86,10 +86,10 @@ export class Wallet { * * @param {string} walletName * @param {boolean} disablePrivateKeys - * @param {CreateWalletOptions=} options - * @param {boolean=} options.blank - * @param {string=} options.passphrase - * @param {boolean=} options.avoidReuse + * @param {CreateWalletOptions} [options] + * @param {boolean} [options.blank] + * @param {string} [options.passphrase] + * @param {boolean} [options.avoidReuse] * @return {Promise} */ async createWallet ( @@ -169,14 +169,14 @@ export class Wallet { * * @param {string} address * @param {number} amount - * @param {SendToAddressOptions=} options - * @param {string=} options.comment - * @param {string=} options.commentTo - * @param {boolean=} options.subtractFeeFromAmount - * @param {boolean=} options.replaceable - * @param {number=} options.confTarget - * @param {Mode=} options.estimateMode - * @param {boolean=} options.avoidReuse + * @param {SendToAddressOptions} [options] + * @param {string} [options.comment] + * @param {string} [options.commentTo] + * @param {boolean} [options.subtractFeeFromAmount] + * @param {boolean} [options.replaceable] + * @param {number} [options.confTarget] + * @param {Mode} [options.estimateMode] + * @param {boolean} [options.avoidReuse] * @return {Promise} */ async sendToAddress ( From d3d16ec9da1c99f89e04946d8e2d901d77c50e75 Mon Sep 17 00:00:00 2001 From: websterlcl Date: Mon, 26 Apr 2021 09:48:46 +0800 Subject: [PATCH 13/14] extract interface PoolShareResult and PoolPairResult --- .../src/category/poolpair.ts | 59 +++++----- website/docs/jellyfish/api/poolpair.md | 105 ++++++++++-------- 2 files changed, 87 insertions(+), 77 deletions(-) diff --git a/packages/jellyfish-api-core/src/category/poolpair.ts b/packages/jellyfish-api-core/src/category/poolpair.ts index 42ab27be4b..67dc56a19f 100644 --- a/packages/jellyfish-api-core/src/category/poolpair.ts +++ b/packages/jellyfish-api-core/src/category/poolpair.ts @@ -122,37 +122,40 @@ export interface CreatePoolPairUTXO { } export interface PoolPairResult { - [id: string]: { - symbol: string - name: string - status: string - idTokenA: string - idTokenB: string - reserveA: BigNumber - reserveB: BigNumber - commission: BigNumber - totalLiquidity: BigNumber - ['reserveA/reserveB']: BigNumber | string - ['reserveB/reserveA']: BigNumber | string - tradeEnabled: boolean - ownerAddress: string - blockCommissionA: BigNumber - blockCommissionB: BigNumber - rewardPct: BigNumber - customRewards: BigNumber - creationTx: string - creationHeight: BigNumber - } + [id: string]: PoolPairInfo } +export interface PoolPairInfo { + symbol: string + name: string + status: string + idTokenA: string + idTokenB: string + reserveA: BigNumber + reserveB: BigNumber + commission: BigNumber + totalLiquidity: BigNumber + ['reserveA/reserveB']: BigNumber | string + ['reserveB/reserveA']: BigNumber | string + tradeEnabled: boolean + ownerAddress: string + blockCommissionA: BigNumber + blockCommissionB: BigNumber + rewardPct: BigNumber + customRewards: BigNumber + creationTx: string + creationHeight: BigNumber +} export interface PoolShareResult { - [id: string]: { - poolID: string - owner: string - ['%']: BigNumber - amount: BigNumber - totalLiquidity: BigNumber - } + [id: string]: PoolShareInfo +} + +interface PoolShareInfo { + poolID: string + owner: string + ['%']: BigNumber + amount: BigNumber + totalLiquidity: BigNumber } export interface PoolPairPagination { diff --git a/website/docs/jellyfish/api/poolpair.md b/website/docs/jellyfish/api/poolpair.md index ec6c397168..1c59e9e855 100644 --- a/website/docs/jellyfish/api/poolpair.md +++ b/website/docs/jellyfish/api/poolpair.md @@ -29,27 +29,29 @@ interface poolpair { } interface PoolPairResult { - [id: string]: { - symbol: string - name: string - status: string - idTokenA: string - idTokenB: string - reserveA: BigNumber - reserveB: BigNumber - commission: BigNumber - totalLiquidity: BigNumber - ['reserveA/reserveB']: BigNumber - ['reserveB/reserveA']: BigNumber - tradeEnabled: boolean - ownerAddress: string - blockCommissionA: BigNumber - blockCommissionB: BigNumber - rewardPct: BigNumber - customRewards: BigNumber - creationTx: string - creationHeight: number - } + [id: string]: PoolPairInfo +} + +interface PoolPairInfo { + symbol: string + name: string + status: string + idTokenA: string + idTokenB: string + reserveA: BigNumber + reserveB: BigNumber + commission: BigNumber + totalLiquidity: BigNumber + ['reserveA/reserveB']: BigNumber + ['reserveB/reserveA']: BigNumber + tradeEnabled: boolean + ownerAddress: string + blockCommissionA: BigNumber + blockCommissionB: BigNumber + rewardPct: BigNumber + customRewards: BigNumber + creationTx: string + creationHeight: number } interface PoolPairPagination { @@ -69,30 +71,33 @@ interface poolpair { } interface PoolPairResult { - [id: string]: { - symbol: string - name: string - status: string - idTokenA: string - idTokenB: string - reserveA: BigNumber - reserveB: BigNumber - commission: BigNumber - totalLiquidity: BigNumber - ['reserveA/reserveB']: BigNumber - ['reserveB/reserveA']: BigNumber - tradeEnabled: boolean - ownerAddress: string - blockCommissionA: BigNumber - blockCommissionB: BigNumber - rewardPct: BigNumber - customRewards: BigNumber - creationTx: string - creationHeight: number - } + [id: string]: PoolPairInfo +} + +interface PoolPairInfo { + symbol: string + name: string + status: string + idTokenA: string + idTokenB: string + reserveA: BigNumber + reserveB: BigNumber + commission: BigNumber + totalLiquidity: BigNumber + ['reserveA/reserveB']: BigNumber + ['reserveB/reserveA']: BigNumber + tradeEnabled: boolean + ownerAddress: string + blockCommissionA: BigNumber + blockCommissionB: BigNumber + rewardPct: BigNumber + customRewards: BigNumber + creationTx: string + creationHeight: number } ``` + ## addPoolLiquidity Add pool liquidity transaction @@ -134,13 +139,15 @@ interface poolpair { } interface PoolShareResult { - [id: string]: { - poolID: string - owner: string - ['%']: BigNumber - amount: BigNumber - totalLiquidity: BigNumber - } + [id: string]: PoolShareInfo +} + +interface PoolShareInfo { + poolID: string + owner: string + ['%']: BigNumber + amount: BigNumber + totalLiquidity: BigNumber } interface PoolPairPagination { From d4e0fd2671585e487a913bf346b1e896b7c48f40 Mon Sep 17 00:00:00 2001 From: websterlcl Date: Mon, 26 Apr 2021 09:59:14 +0800 Subject: [PATCH 14/14] fix netlify id --- website/docs/jellyfish/api/poolpair.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/website/docs/jellyfish/api/poolpair.md b/website/docs/jellyfish/api/poolpair.md index 1c59e9e855..527a88c027 100644 --- a/website/docs/jellyfish/api/poolpair.md +++ b/website/docs/jellyfish/api/poolpair.md @@ -1,5 +1,5 @@ --- -id: poolPair +id: poolpair title: Pool Pair API sidebar_label: Pool Pair API slug: /jellyfish/api/poolpair @@ -8,7 +8,7 @@ slug: /jellyfish/api/poolpair ```js import {Client} from '@defichain/jellyfish' const client = new Client() -// Using client.poolPair. +// Using client.poolpair. const something = await client.poolpair.method() ``` @@ -65,7 +65,7 @@ interface PoolPairPagination { Returns information about pools -```ts title="client.poolPair.getPoolPair()" +```ts title="client.poolpair.getPoolPair()" interface poolpair { getPoolPair (symbol: string, verbose = true): Promise } @@ -102,7 +102,7 @@ interface PoolPairInfo { Add pool liquidity transaction -```ts title="client.poolPair.addPoolLiquidity()" +```ts title="client.poolpair.addPoolLiquidity()" interface poolpair { addPoolLiquidity (from: AddPoolLiquiditySource, shareAddress: string, options: AddPoolLiquidityOptions = {}): Promise } @@ -125,7 +125,7 @@ interface AddPoolLiquidityUTXO { Returns information about pools -```ts title="client.poolPair.listPoolShares()" +```ts title="client.poolpair.listPoolShares()" interface poolpair { listPoolShares ( pagination: PoolPairPagination = {