From 115b167d063541c23553657af497b7bda5cea0ec Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Thu, 20 May 2021 13:54:55 +0800 Subject: [PATCH 01/19] Add accounttoaccount rpc --- .../__tests__/category/account.test.ts | 40 +++++++++++++++++++ .../src/category/account.ts | 4 ++ 2 files changed, 44 insertions(+) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 6014deefc3..fc2a853093 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -516,4 +516,44 @@ describe('masternode', () => { expect(data.length).toBe(64) }) }) + + describe('accountToAccount', () => { + it('should accountToAccount', async () => { + const from = await container.getNewAddress() + await createToken(from, 'DABC', 5) + await createToken(from, 'DDEF', 5) + + const payload: UtxosToAccountPayload = {} + payload[await container.getNewAddress()] = '5@DABC' + payload[await container.getNewAddress()] = '5@DDEF' + + const data = await client.account.accountToAccount(from, payload) + + expect(typeof data).toBe('string') + expect(data.length).toBe(64) + }) + + it('should utxosToAccount with utxos', async () => { + const from = await container.getNewAddress() + await createToken(from, 'DABC', 5) + await createToken(from, 'DDEF', 5) + + const utxos = await container.call('listunspent') + const inputs = utxos.map((utxo: { txid: string, vout: number }) => { + return { + txid: utxo.txid, + vout: utxo.vout + } + }) + + const payload: UtxosToAccountPayload = {} + payload[await container.getNewAddress()] = '5@DABC' + payload[await container.getNewAddress()] = '5@DDEF' + + const data = await client.account.accountToAccount(from, payload, inputs) + + expect(typeof data).toBe('string') + expect(data.length).toBe(64) + }) + }) }) diff --git a/packages/jellyfish-api-core/src/category/account.ts b/packages/jellyfish-api-core/src/category/account.ts index 6bd5fd11b8..9d48eb4a2a 100644 --- a/packages/jellyfish-api-core/src/category/account.ts +++ b/packages/jellyfish-api-core/src/category/account.ts @@ -235,6 +235,10 @@ export class Account { async utxosToAccount (payload: UtxosToAccountPayload, utxos: UtxosToAccountUTXO[] = []): Promise { return await this.client.call('utxostoaccount', [payload, utxos], 'number') } + + async accountToAccount (from: string, payload: UtxosToAccountPayload, utxos: UtxosToAccountUTXO[] = []): Promise { + return await this.client.call('accounttoaccount', [from, payload, utxos], 'number') + } } export interface AccountPagination { From 6314953c962fedb59fd56411c0017cd42a193638 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Mon, 24 May 2021 11:37:42 +0800 Subject: [PATCH 02/19] Improve accountToAccount rpc unit test --- .../__tests__/category/account.test.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index fc2a853093..2119cf999f 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -535,21 +535,30 @@ describe('masternode', () => { it('should utxosToAccount with utxos', async () => { const from = await container.getNewAddress() + const to1 = await container.getNewAddress() + const to2 = await container.getNewAddress() + await createToken(from, 'DABC', 5) await createToken(from, 'DDEF', 5) + const payload: UtxosToAccountPayload = {} + payload[to1] = '5@DABC' + payload[to2] = '5@DDEF' + + const txid = await container.call('sendmany', ['', { + [to1]: 10, + [to2]: 20 + }]) + const utxos = await container.call('listunspent') - const inputs = utxos.map((utxo: { txid: string, vout: number }) => { + + const inputs = utxos.filter((utxo: any) => utxo.txid === txid).map((utxo: any) => { return { txid: utxo.txid, vout: utxo.vout } }) - const payload: UtxosToAccountPayload = {} - payload[await container.getNewAddress()] = '5@DABC' - payload[await container.getNewAddress()] = '5@DDEF' - const data = await client.account.accountToAccount(from, payload, inputs) expect(typeof data).toBe('string') From a9aa8128a47e59fd6543fda412f70608d8b27779 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Mon, 24 May 2021 19:00:13 +0800 Subject: [PATCH 03/19] Improve code --- .../__tests__/category/account.test.ts | 70 +++++++++++++++---- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 2119cf999f..5a0b0d5a46 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -3,6 +3,7 @@ import { ContainerAdapterClient } from '../container_adapter_client' import waitForExpect from 'wait-for-expect' import BigNumber from 'bignumber.js' import { UtxosToAccountPayload } from '../../src/category/account' +import { RpcApiError } from '../../src' describe('masternode', () => { const container = new MasterNodeRegTestContainer() @@ -12,7 +13,7 @@ describe('masternode', () => { await container.start() await container.waitForReady() await container.waitForWalletCoinbaseMaturity() - + await container.waitForWalletBalanceGTE(15) await setup() }) @@ -40,10 +41,13 @@ describe('masternode', () => { tradeable: true, collateralAddress: address } - await container.waitForWalletBalanceGTE(101) await container.call('createtoken', [metadata]) await container.generate(1) + const payload: { [key: string]: string } = {} + payload[address] = '5@0' + await container.call('utxostoaccount', [payload]) + await container.call('minttokens', [`${amount.toString()}@${symbol}`]) await container.generate(1) } @@ -515,6 +519,25 @@ describe('masternode', () => { expect(typeof data).toBe('string') expect(data.length).toBe(64) }) + + it('should not utxosToAccount with utxos for DFI coin if does not own the recipient address', async () => { + const payload: UtxosToAccountPayload = {} + // NOTE(jingyi2811): Only support sending utxos to DFI account. + payload['2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz'] = '5@DFI' + + const utxos = await container.call('listunspent') + const inputs = utxos.map((utxo: { txid: string, vout: number }) => { + return { + txid: utxo.txid, + vout: utxo.vout + } + }) + + const promise = client.account.utxosToAccount(payload, inputs) + + await expect(promise).rejects.toThrow(RpcApiError) + await expect(promise).rejects.toThrow('The address (2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz) is not your own address') + }) }) describe('accountToAccount', () => { @@ -524,6 +547,7 @@ describe('masternode', () => { await createToken(from, 'DDEF', 5) const payload: UtxosToAccountPayload = {} + payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DABC' payload[await container.getNewAddress()] = '5@DDEF' @@ -533,22 +557,17 @@ describe('masternode', () => { expect(data.length).toBe(64) }) - it('should utxosToAccount with utxos', async () => { + it('should accountToAccount with utxos', async () => { const from = await container.getNewAddress() - const to1 = await container.getNewAddress() - const to2 = await container.getNewAddress() + await createToken(from, 'DGHI', 5) + await createToken(from, 'DJKL', 5) - await createToken(from, 'DABC', 5) - await createToken(from, 'DDEF', 5) + const { txid } = await container.fundAddress(from, 10) const payload: UtxosToAccountPayload = {} - payload[to1] = '5@DABC' - payload[to2] = '5@DDEF' - - const txid = await container.call('sendmany', ['', { - [to1]: 10, - [to2]: 20 - }]) + payload[await container.getNewAddress()] = '5@DFI' + payload[await container.getNewAddress()] = '5@DGHI' + payload[await container.getNewAddress()] = '5@DJKL' const utxos = await container.call('listunspent') @@ -564,5 +583,28 @@ describe('masternode', () => { expect(typeof data).toBe('string') expect(data.length).toBe(64) }) + + it('should not accountToAccount with utxos for DFI coin if does not own the recipient address', async () => { + const from = await container.getNewAddress() + + const payload: UtxosToAccountPayload = {} + payload['2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz'] = '5@DFI' + + const { txid } = await container.fundAddress(from, 10) + + const utxos = await container.call('listunspent') + + const inputs = utxos.filter((utxo: any) => utxo.txid === txid).map((utxo: any) => { + return { + txid: utxo.txid, + vout: utxo.vout + } + }) + + const promise = client.account.accountToAccount(from, payload, inputs) + + await expect(promise).rejects.toThrow(RpcApiError) + await expect(promise).rejects.toThrow('The address (2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz) is not your own address') + }) }) }) From 66a77da7f08ee54073af011228ef747e724356b2 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Mon, 24 May 2021 20:16:23 +0800 Subject: [PATCH 04/19] Add JS Doc --- .../__tests__/category/account.test.ts | 4 ++-- .../src/category/account.ts | 23 ++++++++++++++++++- website/docs/jellyfish/api/account.md | 20 ++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 5a0b0d5a46..6dda1b9909 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -13,7 +13,6 @@ describe('masternode', () => { await container.start() await container.waitForReady() await container.waitForWalletCoinbaseMaturity() - await container.waitForWalletBalanceGTE(15) await setup() }) @@ -41,11 +40,12 @@ describe('masternode', () => { tradeable: true, collateralAddress: address } + await container.waitForWalletBalanceGTE(101) await container.call('createtoken', [metadata]) await container.generate(1) const payload: { [key: string]: string } = {} - payload[address] = '5@0' + payload[address] = '100@0' await container.call('utxostoaccount', [payload]) await container.call('minttokens', [`${amount.toString()}@${symbol}`]) diff --git a/packages/jellyfish-api-core/src/category/account.ts b/packages/jellyfish-api-core/src/category/account.ts index 9d48eb4a2a..33bbb3ca94 100644 --- a/packages/jellyfish-api-core/src/category/account.ts +++ b/packages/jellyfish-api-core/src/category/account.ts @@ -236,7 +236,19 @@ export class Account { return await this.client.call('utxostoaccount', [payload, utxos], 'number') } - async accountToAccount (from: string, payload: UtxosToAccountPayload, utxos: UtxosToAccountUTXO[] = []): Promise { + /** + * Creates and submits to a local node and transfer transaction from the specified account to the specfied accounts. + * Optionally, specific UTXOs to spend to create that transaction. + * + * @param {string} from + * @param {AccountToAccountPayload} payload + * @param {string} payload[address] + * @param {AccountToAccountUTXO[]} [utxos=[]] + * @param {string} [utxos.txid] + * @param {number} [utxos.vout] + * @return {Promise} + */ + async accountToAccount (from: string, payload: AccountToAccountPayload, utxos: AccountToAccountUTXO[] = []): Promise { return await this.client.call('accounttoaccount', [from, payload, utxos], 'number') } } @@ -305,3 +317,12 @@ export interface UtxosToAccountUTXO { txid: string vout: number } + +export interface AccountToAccountPayload { + [key: string]: string +} + +export interface AccountToAccountUTXO { + txid: string + vout: number +} diff --git a/website/docs/jellyfish/api/account.md b/website/docs/jellyfish/api/account.md index 72b74558ae..f9984c7d96 100644 --- a/website/docs/jellyfish/api/account.md +++ b/website/docs/jellyfish/api/account.md @@ -162,3 +162,23 @@ interface UtxosToAccountUTXO { vout: number } ``` + +## accountToAccount + +Creates and submits to a local node and transfer transaction from the specified account to the specfied accounts. +Optionally, specific UTXOs to spend to create that transaction. + +```ts title="client.account.accountToAccount()" +interface account { + accountToAccount (from: string, payload: AccountToAccountPayload, utxos: AccountToAccountUTXO[] = []): Promise { +} + +interface AccountToAccountPayload { + [key: string]: string; +} + +interface AccountToAccountUTXO { + txid: string + vout: number +} +``` From 13a8fb238d8b5938fbd9f49286e5ef0610458629 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Mon, 24 May 2021 20:18:14 +0800 Subject: [PATCH 05/19] Minor changes --- packages/jellyfish-api-core/__tests__/category/account.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 6dda1b9909..9765d0d572 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -13,6 +13,7 @@ describe('masternode', () => { await container.start() await container.waitForReady() await container.waitForWalletCoinbaseMaturity() + await setup() }) From f00eed755c1fd8fd9ba086112a9e64c4ca9ece2e Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Mon, 24 May 2021 20:32:02 +0800 Subject: [PATCH 06/19] Refactor code --- .../jellyfish-api-core/__tests__/category/account.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 9765d0d572..8edb908820 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -2,7 +2,7 @@ import { MasterNodeRegTestContainer } from '@defichain/testcontainers' import { ContainerAdapterClient } from '../container_adapter_client' import waitForExpect from 'wait-for-expect' import BigNumber from 'bignumber.js' -import { UtxosToAccountPayload } from '../../src/category/account' +import { AccountToAccountPayload, UtxosToAccountPayload } from '../../src/category/account' import { RpcApiError } from '../../src' describe('masternode', () => { @@ -547,7 +547,7 @@ describe('masternode', () => { await createToken(from, 'DABC', 5) await createToken(from, 'DDEF', 5) - const payload: UtxosToAccountPayload = {} + const payload: AccountToAccountPayload = {} payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DABC' payload[await container.getNewAddress()] = '5@DDEF' @@ -565,7 +565,7 @@ describe('masternode', () => { const { txid } = await container.fundAddress(from, 10) - const payload: UtxosToAccountPayload = {} + const payload: AccountToAccountPayload = {} payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DGHI' payload[await container.getNewAddress()] = '5@DJKL' @@ -588,7 +588,7 @@ describe('masternode', () => { it('should not accountToAccount with utxos for DFI coin if does not own the recipient address', async () => { const from = await container.getNewAddress() - const payload: UtxosToAccountPayload = {} + const payload: AccountToAccountPayload = {} payload['2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz'] = '5@DFI' const { txid } = await container.fundAddress(from, 10) From e1ce81dc0558967804716c1d3d599b10d5338bbd Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Mon, 24 May 2021 20:51:08 +0800 Subject: [PATCH 07/19] Refactor code --- .../__tests__/category/account.test.ts | 10 ++++------ website/docs/jellyfish/api/account.md | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 8edb908820..a827014f18 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -571,8 +571,7 @@ describe('masternode', () => { payload[await container.getNewAddress()] = '5@DJKL' const utxos = await container.call('listunspent') - - const inputs = utxos.filter((utxo: any) => utxo.txid === txid).map((utxo: any) => { + const inputs = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: any) => { return { txid: utxo.txid, vout: utxo.vout @@ -588,14 +587,13 @@ describe('masternode', () => { it('should not accountToAccount with utxos for DFI coin if does not own the recipient address', async () => { const from = await container.getNewAddress() + const { txid } = await container.fundAddress(from, 10) + const payload: AccountToAccountPayload = {} payload['2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz'] = '5@DFI' - const { txid } = await container.fundAddress(from, 10) - const utxos = await container.call('listunspent') - - const inputs = utxos.filter((utxo: any) => utxo.txid === txid).map((utxo: any) => { + const inputs = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: any) => { return { txid: utxo.txid, vout: utxo.vout diff --git a/website/docs/jellyfish/api/account.md b/website/docs/jellyfish/api/account.md index f9984c7d96..03dbd0873f 100644 --- a/website/docs/jellyfish/api/account.md +++ b/website/docs/jellyfish/api/account.md @@ -170,7 +170,7 @@ Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.accountToAccount()" interface account { - accountToAccount (from: string, payload: AccountToAccountPayload, utxos: AccountToAccountUTXO[] = []): Promise { + accountToAccount (from: string, payload: AccountToAccountPayload, utxos: AccountToAccountUTXO[] = []): Promise } interface AccountToAccountPayload { From 355610042f446abd018a60df5b4087cc56fbc401 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Mon, 24 May 2021 21:05:15 +0800 Subject: [PATCH 08/19] Fix unit test and typo --- packages/jellyfish-api-core/__tests__/category/account.test.ts | 2 +- website/docs/jellyfish/api/account.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index a827014f18..72ab66224e 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -292,7 +292,7 @@ describe('masternode', () => { it('should getTokenBalances with pagination limit', async () => { await waitForExpect(async () => { const tokenBalances = await client.account.getTokenBalances() - expect(tokenBalances.length).toBe(2) + expect(tokenBalances.length).toBe(3) }) const pagination = { limit: 1 diff --git a/website/docs/jellyfish/api/account.md b/website/docs/jellyfish/api/account.md index 03dbd0873f..370db52a4b 100644 --- a/website/docs/jellyfish/api/account.md +++ b/website/docs/jellyfish/api/account.md @@ -145,7 +145,7 @@ interface AccountHistoryOptions { ## utxosToAccount -Creates and submits to a connect node; a transfer transaction from the wallet UTXOs to a specified account. +Creates and submits to a connect node; a transfer transaction from the wallet UTXOs to a specified account. Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.utxosToAccount()" From 775e829cf05f825abaaf40b0a4616d16c127bc7d Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Mon, 24 May 2021 21:13:40 +0800 Subject: [PATCH 09/19] Rearrange import --- packages/jellyfish-api-core/__tests__/category/account.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 72ab66224e..4cb6a3c90f 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -2,7 +2,7 @@ import { MasterNodeRegTestContainer } from '@defichain/testcontainers' import { ContainerAdapterClient } from '../container_adapter_client' import waitForExpect from 'wait-for-expect' import BigNumber from 'bignumber.js' -import { AccountToAccountPayload, UtxosToAccountPayload } from '../../src/category/account' +import { UtxosToAccountPayload, AccountToAccountPayload } from '../../src/category/account' import { RpcApiError } from '../../src' describe('masternode', () => { From e985f21a288306039e3a2fe642b1b4335105bcd9 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Tue, 25 May 2021 11:05:22 +0800 Subject: [PATCH 10/19] Add fixes based on review --- .../__tests__/category/account.test.ts | 91 ++++++------------- .../src/category/account.ts | 32 +++---- website/docs/jellyfish/api/account.md | 16 ++-- 3 files changed, 52 insertions(+), 87 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 25e1fdbafe..b907262cc7 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -2,7 +2,6 @@ import { MasterNodeRegTestContainer } from '@defichain/testcontainers' import { ContainerAdapterClient } from '../container_adapter_client' import waitForExpect from 'wait-for-expect' import BigNumber from 'bignumber.js' -import { UtxosToAccountPayload, AccountToAccountPayload } from '../../src/category/account' import { RpcApiError } from '../../src' describe('masternode', () => { @@ -21,8 +20,10 @@ describe('masternode', () => { await container.stop() }) + let from: any + async function setup (): Promise { - const from = await container.call('getnewaddress') + from = await container.call('getnewaddress') await createToken(from, 'DBTC', 200) const to = await accountToAccount('DBTC', 5, from) @@ -45,9 +46,7 @@ describe('masternode', () => { await container.call('createtoken', [metadata]) await container.generate(1) - const payload: { [key: string]: string } = {} - payload[address] = '100@0' - await container.call('utxostoaccount', [payload]) + await container.call('utxostoaccount', [{ [address]: '100@0' }]) await container.call('minttokens', [`${amount.toString()}@${symbol}`]) await container.generate(1) @@ -490,7 +489,7 @@ describe('masternode', () => { describe('utxosToAccount', () => { it('should utxosToAccount', async () => { - const payload: UtxosToAccountPayload = {} + const payload: { [key: string]: string } = {} // NOTE(jingyi2811): Only support sending utxos to DFI account. payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DFI' @@ -501,8 +500,16 @@ describe('masternode', () => { expect(data.length).toStrictEqual(64) }) + it('should not utxosToAccount for DFI coin if does not own the recipient address', async () => { + // NOTE(jingyi2811): Only support sending utxos to DFI account. + const promise = client.account.utxosToAccount({ '2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz': '5@DFI' }) + + await expect(promise).rejects.toThrow(RpcApiError) + await expect(promise).rejects.toThrow('The address (2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz) is not your own address') + }) + it('should utxosToAccount with utxos', async () => { - const payload: UtxosToAccountPayload = {} + const payload: { [key: string]: string } = {} // NOTE(jingyi2811): Only support sending utxos to DFI account. payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DFI' @@ -520,37 +527,14 @@ describe('masternode', () => { expect(typeof data).toStrictEqual('string') expect(data.length).toStrictEqual(64) }) - - it('should not utxosToAccount with utxos for DFI coin if does not own the recipient address', async () => { - const payload: UtxosToAccountPayload = {} - // NOTE(jingyi2811): Only support sending utxos to DFI account. - payload['2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz'] = '5@DFI' - - const utxos = await container.call('listunspent') - const inputs = utxos.map((utxo: { txid: string, vout: number }) => { - return { - txid: utxo.txid, - vout: utxo.vout - } - }) - - const promise = client.account.utxosToAccount(payload, inputs) - - await expect(promise).rejects.toThrow(RpcApiError) - await expect(promise).rejects.toThrow('The address (2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz) is not your own address') - }) }) describe('accountToAccount', () => { it('should accountToAccount', async () => { - const from = await container.getNewAddress() - await createToken(from, 'DABC', 5) - await createToken(from, 'DDEF', 5) - - const payload: AccountToAccountPayload = {} + const payload: { [key: string]: string } = {} payload[await container.getNewAddress()] = '5@DFI' - payload[await container.getNewAddress()] = '5@DABC' - payload[await container.getNewAddress()] = '5@DDEF' + payload[await container.getNewAddress()] = '5@DBTC' + payload[await container.getNewAddress()] = '5@DETH' const data = await client.account.accountToAccount(from, payload) @@ -558,17 +542,20 @@ describe('masternode', () => { expect(data.length).toStrictEqual(64) }) - it('should accountToAccount with utxos', async () => { - const from = await container.getNewAddress() - await createToken(from, 'DGHI', 5) - await createToken(from, 'DJKL', 5) + it('should not accountToAccount for DFI coin if does not own the recipient address', async () => { + const promise = client.account.accountToAccount(from, { '2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz': '5@DFI' }) + + await expect(promise).rejects.toThrow(RpcApiError) + await expect(promise).rejects.toThrow('The address (2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz) is not your own address') + }) + it('should accountToAccount with utxos', async () => { const { txid } = await container.fundAddress(from, 10) - const payload: AccountToAccountPayload = {} + const payload: { [key: string]: string } = {} payload[await container.getNewAddress()] = '5@DFI' - payload[await container.getNewAddress()] = '5@DGHI' - payload[await container.getNewAddress()] = '5@DJKL' + payload[await container.getNewAddress()] = '5@DBTC' + payload[await container.getNewAddress()] = '5@DETH' const utxos = await container.call('listunspent') const inputs = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: any) => { @@ -578,32 +565,10 @@ describe('masternode', () => { } }) - const data = await client.account.accountToAccount(from, payload, inputs) + const data = await client.account.accountToAccount(from, payload, { utxos: inputs }) expect(typeof data).toStrictEqual('string') expect(data.length).toStrictEqual(64) }) - - it('should not accountToAccount with utxos for DFI coin if does not own the recipient address', async () => { - const from = await container.getNewAddress() - - const { txid } = await container.fundAddress(from, 10) - - const payload: AccountToAccountPayload = {} - payload['2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz'] = '5@DFI' - - const utxos = await container.call('listunspent') - const inputs = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: any) => { - return { - txid: utxo.txid, - vout: utxo.vout - } - }) - - const promise = client.account.accountToAccount(from, payload, inputs) - - await expect(promise).rejects.toThrow(RpcApiError) - await expect(promise).rejects.toThrow('The address (2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz) is not your own address') - }) }) }) diff --git a/packages/jellyfish-api-core/src/category/account.ts b/packages/jellyfish-api-core/src/category/account.ts index 33bbb3ca94..c219bfd5fc 100644 --- a/packages/jellyfish-api-core/src/category/account.ts +++ b/packages/jellyfish-api-core/src/category/account.ts @@ -225,14 +225,14 @@ export class Account { * Creates and submits to a connect node; a transfer transaction from the wallet UTXOs to a specified account. * Optionally, specific UTXOs to spend to create that transaction. * - * @param {UtxosToAccountPayload} payload + * @param {Payload} payload * @param {string} payload[address] - * @param {UtxosToAccountUTXO[]} [utxos=[]] + * @param {UTXO[]} [utxos=[]] * @param {string} [utxos.txid] * @param {number} [utxos.vout] * @return {Promise} */ - async utxosToAccount (payload: UtxosToAccountPayload, utxos: UtxosToAccountUTXO[] = []): Promise { + async utxosToAccount (payload: Payload, utxos: UTXO[] = []): Promise { return await this.client.call('utxostoaccount', [payload, utxos], 'number') } @@ -241,15 +241,16 @@ export class Account { * Optionally, specific UTXOs to spend to create that transaction. * * @param {string} from - * @param {AccountToAccountPayload} payload + * @param {Payload} payload * @param {string} payload[address] - * @param {AccountToAccountUTXO[]} [utxos=[]] - * @param {string} [utxos.txid] - * @param {number} [utxos.vout] + * @param {AccountToAccountOptions} [options] + * @param {UTXO[]} [options.utxos = []] + * @param {string} [options.utxos.txid] + * @param {number} [options.utxos.vout] * @return {Promise} */ - async accountToAccount (from: string, payload: AccountToAccountPayload, utxos: AccountToAccountUTXO[] = []): Promise { - return await this.client.call('accounttoaccount', [from, payload, utxos], 'number') + async accountToAccount (from: string, payload: Payload, options: AccountToAccountOptions = { utxos: [] }): Promise { + return await this.client.call('accounttoaccount', [from, payload, options.utxos], 'number') } } @@ -309,20 +310,15 @@ export interface AccountHistoryOptions { limit?: number } -export interface UtxosToAccountPayload { +export interface Payload { [key: string]: string } -export interface UtxosToAccountUTXO { - txid: string - vout: number -} - -export interface AccountToAccountPayload { - [key: string]: string +export interface AccountToAccountOptions { + utxos?: UTXO[] } -export interface AccountToAccountUTXO { +export interface UTXO { txid: string vout: number } diff --git a/website/docs/jellyfish/api/account.md b/website/docs/jellyfish/api/account.md index 370db52a4b..181ad4d1fc 100644 --- a/website/docs/jellyfish/api/account.md +++ b/website/docs/jellyfish/api/account.md @@ -150,14 +150,14 @@ Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.utxosToAccount()" interface account { - utxosToAccount (payload: UtxosToAccountPayload, utxos: UtxosToAccountUTXO[] = []): Promise + utxosToAccount (payload: Payload, utxos: UTXO[] = []): Promise } -interface UtxosToAccountPayload { +interface Payload { [key: string]: string; } -interface UtxosToAccountUTXO { +interface UTXO { txid: string vout: number } @@ -170,14 +170,18 @@ Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.accountToAccount()" interface account { - accountToAccount (from: string, payload: AccountToAccountPayload, utxos: AccountToAccountUTXO[] = []): Promise + accountToAccount (from: string, payload: Payload, options: AccountToAccountOptions = {}): Promise } -interface AccountToAccountPayload { +interface Payload { [key: string]: string; } -interface AccountToAccountUTXO { +interface AccountToAccountOptions { + utxos?: UTXO[] +} + +interface UTXO { txid: string vout: number } From a46feaff9460bd6c79e089055a2ad98bb7f3ad03 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Tue, 25 May 2021 11:25:12 +0800 Subject: [PATCH 11/19] Refactor code --- .../__tests__/category/account.test.ts | 9 +++++---- packages/jellyfish-api-core/src/category/account.ts | 4 ++-- website/docs/jellyfish/api/account.md | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index b907262cc7..051a974d3d 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -3,6 +3,7 @@ import { ContainerAdapterClient } from '../container_adapter_client' import waitForExpect from 'wait-for-expect' import BigNumber from 'bignumber.js' import { RpcApiError } from '../../src' +import { Payload } from '../../src/category/account' describe('masternode', () => { const container = new MasterNodeRegTestContainer() @@ -489,7 +490,7 @@ describe('masternode', () => { describe('utxosToAccount', () => { it('should utxosToAccount', async () => { - const payload: { [key: string]: string } = {} + const payload: Payload = {} // NOTE(jingyi2811): Only support sending utxos to DFI account. payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DFI' @@ -509,7 +510,7 @@ describe('masternode', () => { }) it('should utxosToAccount with utxos', async () => { - const payload: { [key: string]: string } = {} + const payload: Payload = {} // NOTE(jingyi2811): Only support sending utxos to DFI account. payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DFI' @@ -531,7 +532,7 @@ describe('masternode', () => { describe('accountToAccount', () => { it('should accountToAccount', async () => { - const payload: { [key: string]: string } = {} + const payload: Payload = {} payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DBTC' payload[await container.getNewAddress()] = '5@DETH' @@ -552,7 +553,7 @@ describe('masternode', () => { it('should accountToAccount with utxos', async () => { const { txid } = await container.fundAddress(from, 10) - const payload: { [key: string]: string } = {} + const payload: Payload = {} payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DBTC' payload[await container.getNewAddress()] = '5@DETH' diff --git a/packages/jellyfish-api-core/src/category/account.ts b/packages/jellyfish-api-core/src/category/account.ts index c219bfd5fc..8b7cf6def3 100644 --- a/packages/jellyfish-api-core/src/category/account.ts +++ b/packages/jellyfish-api-core/src/category/account.ts @@ -222,12 +222,12 @@ export class Account { } /** - * Creates and submits to a connect node; a transfer transaction from the wallet UTXOs to a specified account. + * Creates and submits to a connect node and transfer transaction from the wallet UTXOs to a specified account. * Optionally, specific UTXOs to spend to create that transaction. * * @param {Payload} payload * @param {string} payload[address] - * @param {UTXO[]} [utxos=[]] + * @param {UTXO[]} [utxos = []] * @param {string} [utxos.txid] * @param {number} [utxos.vout] * @return {Promise} diff --git a/website/docs/jellyfish/api/account.md b/website/docs/jellyfish/api/account.md index 181ad4d1fc..7c790eacaa 100644 --- a/website/docs/jellyfish/api/account.md +++ b/website/docs/jellyfish/api/account.md @@ -145,7 +145,7 @@ interface AccountHistoryOptions { ## utxosToAccount -Creates and submits to a connect node; a transfer transaction from the wallet UTXOs to a specified account. +Creates and submits to a connect node and transfer transaction from the wallet UTXOs to a specified account. Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.utxosToAccount()" @@ -154,7 +154,7 @@ interface account { } interface Payload { - [key: string]: string; + [key: string]: string } interface UTXO { @@ -174,7 +174,7 @@ interface account { } interface Payload { - [key: string]: string; + [key: string]: string } interface AccountToAccountOptions { From 4329dd14ab3f158c9cbb1ccdbf6148d3c2eebb8e Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Tue, 25 May 2021 17:02:42 +0800 Subject: [PATCH 12/19] Apply suggestions from code review --- .../__tests__/category/account.test.ts | 10 +++++----- .../jellyfish-api-core/src/category/account.ts | 17 +++++++++++------ website/docs/jellyfish/api/account.md | 16 ++++++++++------ 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 051a974d3d..3a52425cf4 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -3,7 +3,7 @@ import { ContainerAdapterClient } from '../container_adapter_client' import waitForExpect from 'wait-for-expect' import BigNumber from 'bignumber.js' import { RpcApiError } from '../../src' -import { Payload } from '../../src/category/account' +import { UtxosToAccountPayload, AccountToAccountPayload } from '../../src/category/account' describe('masternode', () => { const container = new MasterNodeRegTestContainer() @@ -490,7 +490,7 @@ describe('masternode', () => { describe('utxosToAccount', () => { it('should utxosToAccount', async () => { - const payload: Payload = {} + const payload: UtxosToAccountPayload = {} // NOTE(jingyi2811): Only support sending utxos to DFI account. payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DFI' @@ -510,7 +510,7 @@ describe('masternode', () => { }) it('should utxosToAccount with utxos', async () => { - const payload: Payload = {} + const payload: UtxosToAccountPayload = {} // NOTE(jingyi2811): Only support sending utxos to DFI account. payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DFI' @@ -532,7 +532,7 @@ describe('masternode', () => { describe('accountToAccount', () => { it('should accountToAccount', async () => { - const payload: Payload = {} + const payload: AccountToAccountPayload = {} payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DBTC' payload[await container.getNewAddress()] = '5@DETH' @@ -553,7 +553,7 @@ describe('masternode', () => { it('should accountToAccount with utxos', async () => { const { txid } = await container.fundAddress(from, 10) - const payload: Payload = {} + const payload: AccountToAccountPayload = {} payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DBTC' payload[await container.getNewAddress()] = '5@DETH' diff --git a/packages/jellyfish-api-core/src/category/account.ts b/packages/jellyfish-api-core/src/category/account.ts index 8b7cf6def3..26e8ffc1f5 100644 --- a/packages/jellyfish-api-core/src/category/account.ts +++ b/packages/jellyfish-api-core/src/category/account.ts @@ -7,6 +7,7 @@ import { ApiClient } from '../.' * - 'all' to list the whole DB */ type OwnerType = 'mine' | 'all' | string +type TokenType = `${string}@${string}` /** * Account RPCs for DeFi Blockchain @@ -225,14 +226,14 @@ export class Account { * Creates and submits to a connect node and transfer transaction from the wallet UTXOs to a specified account. * Optionally, specific UTXOs to spend to create that transaction. * - * @param {Payload} payload + * @param {UtxosToAccountPayload} payload * @param {string} payload[address] * @param {UTXO[]} [utxos = []] * @param {string} [utxos.txid] * @param {number} [utxos.vout] * @return {Promise} */ - async utxosToAccount (payload: Payload, utxos: UTXO[] = []): Promise { + async utxosToAccount (payload: UtxosToAccountPayload, utxos: UTXO[] = []): Promise { return await this.client.call('utxostoaccount', [payload, utxos], 'number') } @@ -241,7 +242,7 @@ export class Account { * Optionally, specific UTXOs to spend to create that transaction. * * @param {string} from - * @param {Payload} payload + * @param {AccountToAccountPayload} payload * @param {string} payload[address] * @param {AccountToAccountOptions} [options] * @param {UTXO[]} [options.utxos = []] @@ -249,7 +250,7 @@ export class Account { * @param {number} [options.utxos.vout] * @return {Promise} */ - async accountToAccount (from: string, payload: Payload, options: AccountToAccountOptions = { utxos: [] }): Promise { + async accountToAccount (from: string, payload: AccountToAccountPayload, options: AccountToAccountOptions = { utxos: [] }): Promise { return await this.client.call('accounttoaccount', [from, payload, options.utxos], 'number') } } @@ -310,8 +311,12 @@ export interface AccountHistoryOptions { limit?: number } -export interface Payload { - [key: string]: string +export interface UtxosToAccountPayload { + [key: string]: TokenType +} + +export interface AccountToAccountPayload { + [key: string]: TokenType } export interface AccountToAccountOptions { diff --git a/website/docs/jellyfish/api/account.md b/website/docs/jellyfish/api/account.md index 7c790eacaa..f1b95f9bba 100644 --- a/website/docs/jellyfish/api/account.md +++ b/website/docs/jellyfish/api/account.md @@ -150,11 +150,13 @@ Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.utxosToAccount()" interface account { - utxosToAccount (payload: Payload, utxos: UTXO[] = []): Promise + utxosToAccount (payload: UtxosToAccountPayload, utxos: UTXO[] = []): Promise } -interface Payload { - [key: string]: string +type TokenType = `${string}@${string}` + +interface UtxosToAccountPayload { + [key: string]: TokenType } interface UTXO { @@ -170,11 +172,13 @@ Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.accountToAccount()" interface account { - accountToAccount (from: string, payload: Payload, options: AccountToAccountOptions = {}): Promise + accountToAccount (from: string, payload: AccountToAccountPayload, options: AccountToAccountOptions = { utxos: [] }): Promise } -interface Payload { - [key: string]: string +type TokenType = `${string}@${string}` + +interface AccountToAccountPayload { + [key: string]: TokenType } interface AccountToAccountOptions { From c356371e2637209040e1b59b8ccffb2da83dddc9 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Tue, 25 May 2021 17:26:49 +0800 Subject: [PATCH 13/19] Change any to string --- packages/jellyfish-api-core/__tests__/category/account.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 3a52425cf4..c5c5b77d0b 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -21,7 +21,7 @@ describe('masternode', () => { await container.stop() }) - let from: any + let from: string async function setup (): Promise { from = await container.call('getnewaddress') From 08ba42011a7b861225f6f55609c468709b53be4b Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Tue, 25 May 2021 17:34:40 +0800 Subject: [PATCH 14/19] Add type --- .../jellyfish-api-core/__tests__/category/account.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index c5c5b77d0b..bb686a5c5d 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -3,7 +3,7 @@ import { ContainerAdapterClient } from '../container_adapter_client' import waitForExpect from 'wait-for-expect' import BigNumber from 'bignumber.js' import { RpcApiError } from '../../src' -import { UtxosToAccountPayload, AccountToAccountPayload } from '../../src/category/account' +import { UtxosToAccountPayload, AccountToAccountPayload, UTXO } from '../../src/category/account' describe('masternode', () => { const container = new MasterNodeRegTestContainer() @@ -516,7 +516,7 @@ describe('masternode', () => { payload[await container.getNewAddress()] = '5@DFI' const utxos = await container.call('listunspent') - const inputs = utxos.map((utxo: { txid: string, vout: number }) => { + const inputs: UTXO[] = utxos.map((utxo: { txid: string, vout: number }) => { return { txid: utxo.txid, vout: utxo.vout @@ -559,7 +559,7 @@ describe('masternode', () => { payload[await container.getNewAddress()] = '5@DETH' const utxos = await container.call('listunspent') - const inputs = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: any) => { + const inputs: UTXO[] = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: any) => { return { txid: utxo.txid, vout: utxo.vout From 80db4d5dd7c48be17017add819b421027b6ef0fa Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Tue, 25 May 2021 19:38:44 +0800 Subject: [PATCH 15/19] Apply suggestions from code review --- .../__tests__/category/account.test.ts | 10 +++++----- .../jellyfish-api-core/src/category/account.ts | 18 +++++++----------- website/docs/jellyfish/api/account.md | 16 ++++++++-------- 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index bb686a5c5d..21e8860413 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -3,7 +3,7 @@ import { ContainerAdapterClient } from '../container_adapter_client' import waitForExpect from 'wait-for-expect' import BigNumber from 'bignumber.js' import { RpcApiError } from '../../src' -import { UtxosToAccountPayload, AccountToAccountPayload, UTXO } from '../../src/category/account' +import { BalanceTransferPayload, UTXO } from '../../src/category/account' describe('masternode', () => { const container = new MasterNodeRegTestContainer() @@ -490,7 +490,7 @@ describe('masternode', () => { describe('utxosToAccount', () => { it('should utxosToAccount', async () => { - const payload: UtxosToAccountPayload = {} + const payload: BalanceTransferPayload = {} // NOTE(jingyi2811): Only support sending utxos to DFI account. payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DFI' @@ -510,7 +510,7 @@ describe('masternode', () => { }) it('should utxosToAccount with utxos', async () => { - const payload: UtxosToAccountPayload = {} + const payload: BalanceTransferPayload = {} // NOTE(jingyi2811): Only support sending utxos to DFI account. payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DFI' @@ -532,7 +532,7 @@ describe('masternode', () => { describe('accountToAccount', () => { it('should accountToAccount', async () => { - const payload: AccountToAccountPayload = {} + const payload: BalanceTransferPayload = {} payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DBTC' payload[await container.getNewAddress()] = '5@DETH' @@ -553,7 +553,7 @@ describe('masternode', () => { it('should accountToAccount with utxos', async () => { const { txid } = await container.fundAddress(from, 10) - const payload: AccountToAccountPayload = {} + const payload: BalanceTransferPayload = {} payload[await container.getNewAddress()] = '5@DFI' payload[await container.getNewAddress()] = '5@DBTC' payload[await container.getNewAddress()] = '5@DETH' diff --git a/packages/jellyfish-api-core/src/category/account.ts b/packages/jellyfish-api-core/src/category/account.ts index 26e8ffc1f5..dc9f25ba78 100644 --- a/packages/jellyfish-api-core/src/category/account.ts +++ b/packages/jellyfish-api-core/src/category/account.ts @@ -7,7 +7,7 @@ import { ApiClient } from '../.' * - 'all' to list the whole DB */ type OwnerType = 'mine' | 'all' | string -type TokenType = `${string}@${string}` +type AccountRegexType = `${string}@${string}` /** * Account RPCs for DeFi Blockchain @@ -226,14 +226,14 @@ export class Account { * Creates and submits to a connect node and transfer transaction from the wallet UTXOs to a specified account. * Optionally, specific UTXOs to spend to create that transaction. * - * @param {UtxosToAccountPayload} payload + * @param {BalanceTransferPayload} payload * @param {string} payload[address] * @param {UTXO[]} [utxos = []] * @param {string} [utxos.txid] * @param {number} [utxos.vout] * @return {Promise} */ - async utxosToAccount (payload: UtxosToAccountPayload, utxos: UTXO[] = []): Promise { + async utxosToAccount (payload: BalanceTransferPayload, utxos: UTXO[] = []): Promise { return await this.client.call('utxostoaccount', [payload, utxos], 'number') } @@ -242,7 +242,7 @@ export class Account { * Optionally, specific UTXOs to spend to create that transaction. * * @param {string} from - * @param {AccountToAccountPayload} payload + * @param {BalanceTransferPayload} payload * @param {string} payload[address] * @param {AccountToAccountOptions} [options] * @param {UTXO[]} [options.utxos = []] @@ -250,7 +250,7 @@ export class Account { * @param {number} [options.utxos.vout] * @return {Promise} */ - async accountToAccount (from: string, payload: AccountToAccountPayload, options: AccountToAccountOptions = { utxos: [] }): Promise { + async accountToAccount (from: string, payload: BalanceTransferPayload, options: AccountToAccountOptions = { utxos: [] }): Promise { return await this.client.call('accounttoaccount', [from, payload, options.utxos], 'number') } } @@ -311,12 +311,8 @@ export interface AccountHistoryOptions { limit?: number } -export interface UtxosToAccountPayload { - [key: string]: TokenType -} - -export interface AccountToAccountPayload { - [key: string]: TokenType +export interface BalanceTransferPayload { + [key: string]: AccountRegexType } export interface AccountToAccountOptions { diff --git a/website/docs/jellyfish/api/account.md b/website/docs/jellyfish/api/account.md index f1b95f9bba..710619fc8f 100644 --- a/website/docs/jellyfish/api/account.md +++ b/website/docs/jellyfish/api/account.md @@ -150,13 +150,13 @@ Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.utxosToAccount()" interface account { - utxosToAccount (payload: UtxosToAccountPayload, utxos: UTXO[] = []): Promise + utxosToAccount (payload: BalanceTransferPayload, utxos: UTXO[] = []): Promise } -type TokenType = `${string}@${string}` +type AccountRegexType = `${string}@${string}` -interface UtxosToAccountPayload { - [key: string]: TokenType +interface BalanceTransferPayload { + [key: string]: AccountRegexType } interface UTXO { @@ -172,13 +172,13 @@ Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.accountToAccount()" interface account { - accountToAccount (from: string, payload: AccountToAccountPayload, options: AccountToAccountOptions = { utxos: [] }): Promise + accountToAccount (from: string, payload: BalanceTransferPayload, options: AccountToAccountOptions = { utxos: [] }): Promise } -type TokenType = `${string}@${string}` +type AccountRegexType = `${string}@${string}` -interface AccountToAccountPayload { - [key: string]: TokenType +interface BalanceTransferPayload { + [key: string]: AccountRegexType } interface AccountToAccountOptions { From 2d1932719a9b98171ae6c4d90ebe8c45c80901e6 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Thu, 27 May 2021 11:10:31 +0800 Subject: [PATCH 16/19] Apply suggestions from code review --- packages/jellyfish-api-core/src/category/account.ts | 4 ++-- website/docs/jellyfish/api/account.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/jellyfish-api-core/src/category/account.ts b/packages/jellyfish-api-core/src/category/account.ts index dc9f25ba78..573f92f4b8 100644 --- a/packages/jellyfish-api-core/src/category/account.ts +++ b/packages/jellyfish-api-core/src/category/account.ts @@ -223,7 +223,7 @@ export class Account { } /** - * Creates and submits to a connect node and transfer transaction from the wallet UTXOs to a specified account. + * Create an UTXOs to Account transaction submitted to a connected node. * Optionally, specific UTXOs to spend to create that transaction. * * @param {BalanceTransferPayload} payload @@ -238,7 +238,7 @@ export class Account { } /** - * Creates and submits to a local node and transfer transaction from the specified account to the specfied accounts. + * Create an Account to Account transaction submitted to a connected node. * Optionally, specific UTXOs to spend to create that transaction. * * @param {string} from diff --git a/website/docs/jellyfish/api/account.md b/website/docs/jellyfish/api/account.md index 710619fc8f..f07e80e2b6 100644 --- a/website/docs/jellyfish/api/account.md +++ b/website/docs/jellyfish/api/account.md @@ -145,7 +145,7 @@ interface AccountHistoryOptions { ## utxosToAccount -Creates and submits to a connect node and transfer transaction from the wallet UTXOs to a specified account. +Create an UTXOs to Account transaction submitted to a connected node. Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.utxosToAccount()" @@ -167,7 +167,7 @@ interface UTXO { ## accountToAccount -Creates and submits to a local node and transfer transaction from the specified account to the specfied accounts. +Create an Account to Account transaction submitted to a connected node. Optionally, specific UTXOs to spend to create that transaction. ```ts title="client.account.accountToAccount()" From 382531b5da8579303e9cde8b9bf10080b97996d8 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Thu, 27 May 2021 12:37:28 +0800 Subject: [PATCH 17/19] Refactor code --- .../__tests__/category/account.test.ts | 51 +-------- .../category/account/accountToAccount.test.ts | 105 ++++++++++++++++++ 2 files changed, 107 insertions(+), 49 deletions(-) create mode 100644 packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index ba1801be22..8ef004868b 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -21,10 +21,8 @@ describe('masternode', () => { await container.stop() }) - let from: string - async function setup (): Promise { - from = await container.call('getnewaddress') + const from = await container.call('getnewaddress') await createToken(from, 'DBTC', 200) const to = await accountToAccount('DBTC', 5, from) @@ -47,8 +45,6 @@ describe('masternode', () => { await container.call('createtoken', [metadata]) await container.generate(1) - await container.call('utxostoaccount', [{ [address]: '100@0' }]) - await container.call('minttokens', [`${amount.toString()}@${symbol}`]) await container.generate(1) } @@ -292,7 +288,7 @@ describe('masternode', () => { it('should getTokenBalances with pagination limit', async () => { await waitForExpect(async () => { const tokenBalances = await client.account.getTokenBalances() - expect(tokenBalances.length).toStrictEqual(3) + expect(tokenBalances.length).toStrictEqual(2) }) const pagination = { limit: 1 @@ -530,49 +526,6 @@ describe('masternode', () => { }) }) - describe('accountToAccount', () => { - it('should accountToAccount', async () => { - const payload: BalanceTransferPayload = {} - payload[await container.getNewAddress()] = '5@DFI' - payload[await container.getNewAddress()] = '5@DBTC' - payload[await container.getNewAddress()] = '5@DETH' - - const data = await client.account.accountToAccount(from, payload) - - expect(typeof data).toStrictEqual('string') - expect(data.length).toStrictEqual(64) - }) - - it('should not accountToAccount for DFI coin if does not own the recipient address', async () => { - const promise = client.account.accountToAccount(from, { '2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz': '5@DFI' }) - - await expect(promise).rejects.toThrow(RpcApiError) - await expect(promise).rejects.toThrow('The address (2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz) is not your own address') - }) - - it('should accountToAccount with utxos', async () => { - const { txid } = await container.fundAddress(from, 10) - - const payload: BalanceTransferPayload = {} - payload[await container.getNewAddress()] = '5@DFI' - payload[await container.getNewAddress()] = '5@DBTC' - payload[await container.getNewAddress()] = '5@DETH' - - const utxos = await container.call('listunspent') - const inputs: UTXO[] = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: any) => { - return { - txid: utxo.txid, - vout: utxo.vout - } - }) - - const data = await client.account.accountToAccount(from, payload, { utxos: inputs }) - - expect(typeof data).toStrictEqual('string') - expect(data.length).toStrictEqual(64) - }) - }) - describe('accountHistoryCount', () => { it('should get accountHistoryCount', async () => { await waitForExpect(async () => { diff --git a/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts b/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts new file mode 100644 index 0000000000..ed6aeadcbc --- /dev/null +++ b/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts @@ -0,0 +1,105 @@ +import { MasterNodeRegTestContainer } from '@defichain/testcontainers' +import { ContainerAdapterClient } from '../../container_adapter_client' +import { RpcApiError } from '../../../src' +import { BalanceTransferPayload, UTXO } from '../../../src/category/account' + +describe('masternode', () => { + const container = new MasterNodeRegTestContainer() + const client = new ContainerAdapterClient(container) + + beforeAll(async () => { + await container.start() + await container.waitForReady() + await container.waitForWalletCoinbaseMaturity() + await setup() + }) + + afterAll(async () => { + await container.stop() + }) + + let from: string + + async function setup (): Promise { + from = await container.call('getnewaddress') + await createToken(from, 'DBTC', 200) + + const to = await accountToAccount('DBTC', 5, from) + await accountToAccount('DBTC', 18, from, to) + + await createToken(from, 'DETH', 200) + await accountToAccount('DETH', 46, from) + } + + async function createToken (address: string, symbol: string, amount: number): Promise { + const metadata = { + symbol, + name: symbol, + isDAT: true, + mintable: true, + tradeable: true, + collateralAddress: address + } + await container.waitForWalletBalanceGTE(101) + await container.call('createtoken', [metadata]) + await container.generate(1) + + await container.call('utxostoaccount', [{ [address]: '100@0' }]) + await container.generate(1) + + await container.call('minttokens', [`${amount.toString()}@${symbol}`]) + await container.generate(1) + } + + async function accountToAccount (symbol: string, amount: number, from: string, _to = ''): Promise { + const to = _to !== '' ? _to : await container.call('getnewaddress') + + await container.call('accounttoaccount', [from, { [to]: `${amount.toString()}@${symbol}` }]) + await container.generate(1) + + return to + } + + describe('accountToAccount', () => { + it('should accountToAccount', async () => { + const payload: BalanceTransferPayload = {} + payload[await container.getNewAddress()] = '5@DFI' + payload[await container.getNewAddress()] = '5@DBTC' + payload[await container.getNewAddress()] = '5@DETH' + + const data = await client.account.accountToAccount(from, payload) + + expect(typeof data).toStrictEqual('string') + expect(data.length).toStrictEqual(64) + }) + + it('should not accountToAccount for DFI coin if does not own the recipient address', async () => { + const promise = client.account.accountToAccount(from, { '2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz': '5@DFI' }) + + await expect(promise).rejects.toThrow(RpcApiError) + await expect(promise).rejects.toThrow('The address (2Mywjs9zEU4NtLknXQJZgozaxMvPn2Bb3qz) is not your own address') + }) + + it('should accountToAccount with utxos', async () => { + const { txid } = await container.fundAddress(from, 10) + + const payload: BalanceTransferPayload = {} + payload[await container.getNewAddress()] = '5@DFI' + payload[await container.getNewAddress()] = '5@DBTC' + payload[await container.getNewAddress()] = '5@DETH' + + const utxos = await container.call('listunspent') + const inputs: UTXO[] = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: any) => { + return { + txid: utxo.txid, + vout: utxo.vout + } + }) + + const data = await client.account.accountToAccount(from, payload, { utxos: inputs }) + + expect(typeof data).toStrictEqual('string') + expect(data.length).toStrictEqual(64) + }) + }) +}) From 47709836561b61f8a74719106bb0a4be53c82390 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Thu, 27 May 2021 13:29:44 +0800 Subject: [PATCH 18/19] Apply suggestions from code review --- .../__tests__/category/account/accountToAccount.test.ts | 2 +- packages/jellyfish-api-core/src/category/account.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts b/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts index ed6aeadcbc..29a1989b6d 100644 --- a/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts @@ -89,7 +89,7 @@ describe('masternode', () => { payload[await container.getNewAddress()] = '5@DETH' const utxos = await container.call('listunspent') - const inputs: UTXO[] = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: any) => { + const inputs: UTXO[] = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: { txid: string, vout: number }) => { return { txid: utxo.txid, vout: utxo.vout diff --git a/packages/jellyfish-api-core/src/category/account.ts b/packages/jellyfish-api-core/src/category/account.ts index 6840d2fa6c..2899177242 100644 --- a/packages/jellyfish-api-core/src/category/account.ts +++ b/packages/jellyfish-api-core/src/category/account.ts @@ -6,7 +6,6 @@ import { ApiClient } from '../.' * - 'mine' to list history for all owned accounts or * - 'all' to list the whole DB */ - export enum OwnerType { MINE = 'mine', ALL = 'all' From cd9982ede668be2447e5ccac74aec025fbf53597 Mon Sep 17 00:00:00 2001 From: jingyi2811 Date: Thu, 27 May 2021 13:35:06 +0800 Subject: [PATCH 19/19] Apply suggestions from code review --- packages/jellyfish-api-core/__tests__/category/account.test.ts | 2 +- .../__tests__/category/account/accountToAccount.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/account.test.ts b/packages/jellyfish-api-core/__tests__/category/account.test.ts index 8ef004868b..19ba85576a 100644 --- a/packages/jellyfish-api-core/__tests__/category/account.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account.test.ts @@ -512,7 +512,7 @@ describe('masternode', () => { payload[await container.getNewAddress()] = '5@DFI' const utxos = await container.call('listunspent') - const inputs: UTXO[] = utxos.map((utxo: { txid: string, vout: number }) => { + const inputs: UTXO[] = utxos.map((utxo: UTXO) => { return { txid: utxo.txid, vout: utxo.vout diff --git a/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts b/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts index 29a1989b6d..8667e78dd4 100644 --- a/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/account/accountToAccount.test.ts @@ -89,7 +89,7 @@ describe('masternode', () => { payload[await container.getNewAddress()] = '5@DETH' const utxos = await container.call('listunspent') - const inputs: UTXO[] = utxos.filter((utxo: { txid: string, vout: number }) => utxo.txid === txid).map((utxo: { txid: string, vout: number }) => { + const inputs: UTXO[] = utxos.filter((utxo: UTXO) => utxo.txid === txid).map((utxo: UTXO) => { return { txid: utxo.txid, vout: utxo.vout