diff --git a/.idea/dictionaries/fuxing.xml b/.idea/dictionaries/fuxing.xml index 40a3ca783f..2b5e0706a9 100644 --- a/.idea/dictionaries/fuxing.xml +++ b/.idea/dictionaries/fuxing.xml @@ -94,6 +94,7 @@ libevent listaccounts listaddressgroupings + listpoolpairs listunspent locktime logtimemicros @@ -187,4 +188,4 @@ wtxid - \ No newline at end of file + diff --git a/README.md b/README.md index ff1f18bd4f..ed514701a4 100644 --- a/README.md +++ b/README.md @@ -101,9 +101,9 @@ Package | Description ## Developing & Contributing Thanks for contributing, appreciate all the help we can get. Feel free to make a pull-request, we will guide you along -the way to make it mergeable. Here are some of our documented [contributing guidelines](CONTRIBUTING.md). +the way to make it merge-able. Here are some of our documented [contributing guidelines](CONTRIBUTING.md). -We use `npm 7` for this project, it's required to set +You need `node v14`, and `npm v7` for this project, it's required to set up [npm workspaces](https://docs.npmjs.com/cli/v7/using-npm/workspaces). ```shell @@ -112,14 +112,15 @@ npm install ### Testing -`jest.config.js` is set up at the root project level as well as at each sub module. You can run jest at root to test all -modules or individually at each sub module. By default, only regtest chain are used for normal testing. If you use -IntelliJ IDEA, you can right click any file to test it individually and have it reported to the IDE. +`jest.config.js` is set up at the root project level as well as at each submodule. You can run jest at root to test all +modules or individually at each submodule. By default, only regtest chain are used for normal testing. If you use +IntelliJ IDEA, you can right-click any file to test it individually and have it reported to the IDE. Docker is required to run the tests as [`@defichain/testcontainers`](./packages/testcontainers) will automatically spin up `regtest` instances for testing. The number of containers it will spin up concurrently is dependent on your jest `--maxConcurrency` count. Test are known to be flaky due to the usage of multiple Docker containers for test -concurrency. +concurrency. Although testcontainers cleans up after itself, there are cases where the tests fail exceptionally you +might need to occasionally: `docker system prune --volumes`. Coverage is collected at each pull request to main with `codecov`; more testing 🚀 less 🐛 = 😎 diff --git a/package-lock.json b/package-lock.json index 52d82ae8c3..4b8f3e6495 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13124,9 +13124,10 @@ } }, "node_modules/@types/dockerode": { - "version": "3.2.2", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.2.3.tgz", + "integrity": "sha512-nZRhpSxm3PYianRBcRExcHxDvEzYHUPfGCnRL5Fe4/fSEZbtxrRNJ7okzCans3lXxj2t298EynFHGTnTC2f1Iw==", "dev": true, - "license": "MIT", "dependencies": { "@types/node": "*" } @@ -13203,9 +13204,9 @@ "license": "MIT" }, "node_modules/@types/node-fetch": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz", - "integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==", + "version": "2.5.10", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.10.tgz", + "integrity": "sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==", "dev": true, "dependencies": { "@types/node": "*", @@ -16343,8 +16344,9 @@ } }, "node_modules/docker-modem": { - "version": "2.1.4", - "license": "Apache-2.0", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.0.tgz", + "integrity": "sha512-WwFajJ8I5geZ/dDZ5FDMDA6TBkWa76xWwGIGw8uzUjNUGCN0to83wJ8Oi1AxrJTC0JBn+7fvIxUctnawtlwXeg==", "dependencies": { "debug": "^4.1.1", "readable-stream": "^3.5.0", @@ -16356,10 +16358,11 @@ } }, "node_modules/dockerode": { - "version": "3.2.1", - "license": "Apache-2.0", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.3.0.tgz", + "integrity": "sha512-St08lfOjpYCOXEM8XA0VLu3B3hRjtddODphNW5GFoA0AS3JHgoPQKOz0Qmdzg3P+hUPxhb02g1o1Cu1G+U3lRg==", "dependencies": { - "docker-modem": "^2.1.0", + "docker-modem": "^3.0.0", "tar-fs": "~2.0.1" }, "engines": { @@ -26891,7 +26894,8 @@ }, "node_modules/split-ca": { "version": "1.0.1", - "license": "ISC" + "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", + "integrity": "sha1-bIOv82kvphJW4M0ZfgXp3hV2kaY=" }, "node_modules/split-on-first": { "version": "1.1.0", @@ -26939,6 +26943,8 @@ }, "node_modules/ssh2": { "version": "0.8.9", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.8.9.tgz", + "integrity": "sha512-GmoNPxWDMkVpMFa9LVVzQZHF6EW3WKmBwL+4/GeILf2hFmix5Isxm7Amamo8o7bHiU0tC+wXsGcUXOxp8ChPaw==", "dependencies": { "ssh2-streams": "~0.4.10" }, @@ -26948,6 +26954,8 @@ }, "node_modules/ssh2-streams": { "version": "0.4.10", + "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.4.10.tgz", + "integrity": "sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ==", "dependencies": { "asn1": "~0.2.0", "bcrypt-pbkdf": "^1.0.2", @@ -27160,6 +27168,8 @@ }, "node_modules/streamsearch": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", "engines": { "node": ">=0.8.0" } @@ -29414,12 +29424,12 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "dockerode": "^3.2.1", + "dockerode": "^3.3.0", "node-fetch": "^2.6.1" }, "devDependencies": { - "@types/dockerode": "^3.2.2", - "@types/node-fetch": "^2.5.8" + "@types/dockerode": "^3.2.3", + "@types/node-fetch": "^2.5.10" } } }, @@ -30656,9 +30666,9 @@ "@defichain/testcontainers": { "version": "file:packages/testcontainers", "requires": { - "@types/dockerode": "^3.2.2", - "@types/node-fetch": "^2.5.8", - "dockerode": "^3.2.1", + "@types/dockerode": "^3.2.3", + "@types/node-fetch": "^2.5.10", + "dockerode": "^3.3.0", "node-fetch": "^2.6.1" } }, @@ -39898,7 +39908,9 @@ } }, "@types/dockerode": { - "version": "3.2.2", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.2.3.tgz", + "integrity": "sha512-nZRhpSxm3PYianRBcRExcHxDvEzYHUPfGCnRL5Fe4/fSEZbtxrRNJ7okzCans3lXxj2t298EynFHGTnTC2f1Iw==", "dev": true, "requires": { "@types/node": "*" @@ -39968,9 +39980,9 @@ "dev": true }, "@types/node-fetch": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz", - "integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==", + "version": "2.5.10", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.10.tgz", + "integrity": "sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==", "dev": true, "requires": { "@types/node": "*", @@ -42264,7 +42276,9 @@ } }, "docker-modem": { - "version": "2.1.4", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.0.tgz", + "integrity": "sha512-WwFajJ8I5geZ/dDZ5FDMDA6TBkWa76xWwGIGw8uzUjNUGCN0to83wJ8Oi1AxrJTC0JBn+7fvIxUctnawtlwXeg==", "requires": { "debug": "^4.1.1", "readable-stream": "^3.5.0", @@ -42273,9 +42287,11 @@ } }, "dockerode": { - "version": "3.2.1", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.3.0.tgz", + "integrity": "sha512-St08lfOjpYCOXEM8XA0VLu3B3hRjtddODphNW5GFoA0AS3JHgoPQKOz0Qmdzg3P+hUPxhb02g1o1Cu1G+U3lRg==", "requires": { - "docker-modem": "^2.1.0", + "docker-modem": "^3.0.0", "tar-fs": "~2.0.1" }, "dependencies": { @@ -49821,7 +49837,9 @@ } }, "split-ca": { - "version": "1.0.1" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", + "integrity": "sha1-bIOv82kvphJW4M0ZfgXp3hV2kaY=" }, "split-on-first": { "version": "1.1.0", @@ -49853,12 +49871,16 @@ }, "ssh2": { "version": "0.8.9", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.8.9.tgz", + "integrity": "sha512-GmoNPxWDMkVpMFa9LVVzQZHF6EW3WKmBwL+4/GeILf2hFmix5Isxm7Amamo8o7bHiU0tC+wXsGcUXOxp8ChPaw==", "requires": { "ssh2-streams": "~0.4.10" } }, "ssh2-streams": { "version": "0.4.10", + "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.4.10.tgz", + "integrity": "sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ==", "requires": { "asn1": "~0.2.0", "bcrypt-pbkdf": "^1.0.2", @@ -50003,7 +50025,9 @@ } }, "streamsearch": { - "version": "0.1.2" + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" }, "strict-uri-encode": { "version": "2.0.0", diff --git a/packages/jellyfish-api-core/README.md b/packages/jellyfish-api-core/README.md index 99765cb5d2..1f3a2a7ff7 100644 --- a/packages/jellyfish-api-core/README.md +++ b/packages/jellyfish-api-core/README.md @@ -46,6 +46,8 @@ handling with rich structure. regular numeric operations, and it will throw an error when this would result in losing information. * **'bignumber'** parse all numeric values as 'BigNumber' using bignumber.js library. * **'number'** parse all numeric values as 'Number' and precision will be loss if it exceeds IEEE-754 standard. +* **'PrecisionPath'** provides path based precision mapping, specifying 'bignumber' will automatically map all Number in + that path as 'bignumber'. Otherwise, it will default to number, This applies deeply. ## Testing diff --git a/packages/jellyfish-api-core/__tests__/category/blockchain.test.ts b/packages/jellyfish-api-core/__tests__/category/blockchain.test.ts index b09fa5c7d4..ef3080e0f4 100644 --- a/packages/jellyfish-api-core/__tests__/category/blockchain.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/blockchain.test.ts @@ -1,7 +1,7 @@ import { RegTestContainer, MasterNodeRegTestContainer } from '@defichain/testcontainers' import { ContainerAdapterClient } from '../container_adapter_client' import waitForExpect from 'wait-for-expect' -import { BigNumber, Block, BlockHeader, MempoolTx, Transaction, WalletFlag } from '../../src' +import { BigNumber, blockchain, wallet } from '../../src' describe('non masternode', () => { const container = new RegTestContainer() @@ -103,7 +103,7 @@ describe('masternode', () => { it('should getBlock with verbosity 1 and return block with tx as hex', async () => { const blockHash = await waitForBlockHash(1) - const block: Block = await client.blockchain.getBlock(blockHash, 1) + const block: blockchain.Block = await client.blockchain.getBlock(blockHash, 1) expect(block.hash.length).toBe(64) @@ -139,7 +139,7 @@ describe('masternode', () => { it('should getBlock with verbosity 2 and return block with tx as RawText', async () => { const blockHash = await waitForBlockHash(1) - const block: Block = await client.blockchain.getBlock(blockHash, 2) + const block: blockchain.Block = await client.blockchain.getBlock(blockHash, 2) expect(block.tx.length).toBeGreaterThanOrEqual(1) expect(block.tx[0].vin[0].coinbase).toStrictEqual('5100') @@ -159,7 +159,7 @@ describe('masternode', () => { describe('getBlockHeader', () => { it('should getBlockHeader with verbosity true and return block with tx as hex', async () => { const blockHash = await waitForBlockHash(1) - const blockHeader: BlockHeader = await client.blockchain.getBlockHeader(blockHash, true) + const blockHeader: blockchain.BlockHeader = await client.blockchain.getBlockHeader(blockHash, true) expect(blockHeader.hash.length).toBe(64) @@ -236,7 +236,7 @@ describe('masternode', () => { let transactionId = '' beforeAll(async () => { - await client.wallet.setWalletFlag(WalletFlag.AVOID_REUSE) + await client.wallet.setWalletFlag(wallet.WalletFlag.AVOID_REUSE) transactionId = await client.wallet.sendToAddress('mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU', 0.00001) }) @@ -248,7 +248,7 @@ describe('masternode', () => { }) it('should getRawMempool and return json object', async () => { - const rawMempool: MempoolTx = await client.blockchain.getRawMempool(true) + const rawMempool: blockchain.MempoolTx = await client.blockchain.getRawMempool(true) const data = rawMempool[transactionId] expect(data.fees.base 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 63e3f0020e..e505330f7b 100644 --- a/packages/jellyfish-api-core/__tests__/category/wallet.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/wallet.test.ts @@ -1,6 +1,6 @@ import { ContainerAdapterClient } from '../container_adapter_client' import { MasterNodeRegTestContainer, RegTestContainer } from '@defichain/testcontainers' -import { BigNumber, ValidateAddressResult, AddressType, AddressInfo } from '../../src' +import { BigNumber, wallet } from '../../src' import waitForExpect from 'wait-for-expect' import { UTXO, ListUnspentOptions, WalletFlag, SendToAddressOptions, Mode } from '../../src/category/wallet' @@ -44,13 +44,13 @@ describe('non masternode', () => { it('should getNewAddress with address type specified', async () => { return await waitForExpect(async () => { - const legacyAddress = await client.wallet.getNewAddress('', AddressType.LEGACY) + const legacyAddress = await client.wallet.getNewAddress('', wallet.AddressType.LEGACY) const legacyAddressValidateResult = await client.wallet.validateAddress(legacyAddress) - const p2shSegwitAddress = await client.wallet.getNewAddress('', AddressType.P2SH_SEGWIT) + const p2shSegwitAddress = await client.wallet.getNewAddress('', wallet.AddressType.P2SH_SEGWIT) const p2shSegwitAddressValidateResult = await client.wallet.validateAddress(p2shSegwitAddress) - const bech32Address = await client.wallet.getNewAddress('bob', AddressType.BECH32) + const bech32Address = await client.wallet.getNewAddress('bob', wallet.AddressType.BECH32) const bech32AddressValidateResult = await client.wallet.validateAddress(bech32Address) expect(typeof legacyAddress).toBe('string') @@ -81,7 +81,7 @@ describe('non masternode', () => { it('should getAddressInfo', async () => { return await waitForExpect(async () => { const aliceAddress = await client.wallet.getNewAddress('alice') - const addressInfo: AddressInfo = await client.wallet.getAddressInfo(aliceAddress) + const addressInfo: wallet.AddressInfo = await client.wallet.getAddressInfo(aliceAddress) expect(addressInfo.address).toBe(aliceAddress) expect(typeof addressInfo.scriptPubKey).toBe('string') @@ -108,7 +108,7 @@ describe('non masternode', () => { it('should validateAddress', async () => { return await waitForExpect(async () => { const aliceAddress = await client.wallet.getNewAddress('alice') - const result: ValidateAddressResult = await client.wallet.validateAddress(aliceAddress) + const result: wallet.ValidateAddressResult = await client.wallet.validateAddress(aliceAddress) expect(result.isvalid).toBe(true) expect(result.address).toBe(aliceAddress) @@ -377,13 +377,13 @@ describe('masternode', () => { it('should getNewAddress with address type specified', async () => { return await waitForExpect(async () => { - const legacyAddress = await client.wallet.getNewAddress('', AddressType.LEGACY) + const legacyAddress = await client.wallet.getNewAddress('', wallet.AddressType.LEGACY) const legacyAddressValidateResult = await client.wallet.validateAddress(legacyAddress) - const p2shSegwitAddress = await client.wallet.getNewAddress('', AddressType.P2SH_SEGWIT) + const p2shSegwitAddress = await client.wallet.getNewAddress('', wallet.AddressType.P2SH_SEGWIT) const p2shSegwitAddressValidateResult = await client.wallet.validateAddress(p2shSegwitAddress) - const bech32Address = await client.wallet.getNewAddress('bob', AddressType.BECH32) + const bech32Address = await client.wallet.getNewAddress('bob', wallet.AddressType.BECH32) const bech32AddressValidateResult = await client.wallet.validateAddress(bech32Address) expect(typeof legacyAddress).toBe('string') @@ -414,7 +414,7 @@ describe('masternode', () => { it('should getAddressInfo', async () => { return await waitForExpect(async () => { const aliceAddress = await client.wallet.getNewAddress('alice') - const addressInfo: AddressInfo = await client.wallet.getAddressInfo(aliceAddress) + const addressInfo: wallet.AddressInfo = await client.wallet.getAddressInfo(aliceAddress) expect(addressInfo.address).toBe(aliceAddress) expect(typeof addressInfo.scriptPubKey).toBe('string') @@ -441,7 +441,7 @@ describe('masternode', () => { it('should validateAddress', async () => { return await waitForExpect(async () => { const aliceAddress = await client.wallet.getNewAddress('alice') - const result: ValidateAddressResult = await client.wallet.validateAddress(aliceAddress) + const result: wallet.ValidateAddressResult = await client.wallet.validateAddress(aliceAddress) expect(result.isvalid).toBe(true) expect(result.address).toBe(aliceAddress) diff --git a/packages/jellyfish-api-core/__tests__/index.test.ts b/packages/jellyfish-api-core/__tests__/index.test.ts index 9d3e7c782a..291be03f38 100644 --- a/packages/jellyfish-api-core/__tests__/index.test.ts +++ b/packages/jellyfish-api-core/__tests__/index.test.ts @@ -1,4 +1,4 @@ -import { MintingInfo, ApiClient, ClientApiError } from '../src' +import { mining, ApiClient, ClientApiError } from '../src' import { ContainerAdapterClient } from './container_adapter_client' import { RegTestContainer } from '@defichain/testcontainers' @@ -17,7 +17,7 @@ it('should export client', async () => { it('should export categories', async () => { const client = new TestClient() await expect(async () => { - const info: MintingInfo = await client.mining.getMintingInfo() + const info: mining.MintingInfo = await client.mining.getMintingInfo() console.log(info) }).rejects.toThrowError(ClientApiError) }) diff --git a/packages/jellyfish-api-core/src/category/blockchain.ts b/packages/jellyfish-api-core/src/category/blockchain.ts index 097798b6d0..4b98771820 100644 --- a/packages/jellyfish-api-core/src/category/blockchain.ts +++ b/packages/jellyfish-api-core/src/category/blockchain.ts @@ -2,7 +2,7 @@ import BigNumber from 'bignumber.js' import { ApiClient } from '../.' /** - * Blockchain related RPC calls for DeFiChain + * Blockchain RPCs for DeFi Blockchain */ export class Blockchain { private readonly client: ApiClient diff --git a/packages/jellyfish-api-core/src/category/mining.ts b/packages/jellyfish-api-core/src/category/mining.ts index 4dc0bb17ec..905ba607b0 100644 --- a/packages/jellyfish-api-core/src/category/mining.ts +++ b/packages/jellyfish-api-core/src/category/mining.ts @@ -1,7 +1,7 @@ import { ApiClient } from '../.' /** - * Minting related RPC calls for DeFiChain + * Mining RPCs for DeFi Blockchain */ export class Mining { private readonly client: ApiClient diff --git a/packages/jellyfish-api-core/src/category/poolpair.ts b/packages/jellyfish-api-core/src/category/poolpair.ts index 67dc56a19f..c777401964 100644 --- a/packages/jellyfish-api-core/src/category/poolpair.ts +++ b/packages/jellyfish-api-core/src/category/poolpair.ts @@ -2,7 +2,7 @@ import BigNumber from 'bignumber.js' import { ApiClient } from '..' /** - * PoolPair related RPC calls for DeFiChain + * PoolPair RPCs for DeFi Blockchain */ export class PoolPair { private readonly client: ApiClient @@ -38,7 +38,7 @@ export class PoolPair { * @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 + * @param {boolean} verbose default = true, otherwise only symbol, name, status, idTokenA, idTokenB * @return {Promise} */ async listPoolPairs ( @@ -135,8 +135,8 @@ export interface PoolPairInfo { reserveB: BigNumber commission: BigNumber totalLiquidity: BigNumber - ['reserveA/reserveB']: BigNumber | string - ['reserveB/reserveA']: BigNumber | string + 'reserveA/reserveB': BigNumber | string + 'reserveB/reserveA': BigNumber | string tradeEnabled: boolean ownerAddress: string blockCommissionA: BigNumber @@ -146,6 +146,7 @@ export interface PoolPairInfo { creationTx: string creationHeight: BigNumber } + export interface PoolShareResult { [id: string]: PoolShareInfo } @@ -153,7 +154,7 @@ export interface PoolShareResult { interface PoolShareInfo { poolID: string owner: string - ['%']: BigNumber + '%': BigNumber amount: BigNumber totalLiquidity: BigNumber } diff --git a/packages/jellyfish-api-core/src/category/rawtx.ts b/packages/jellyfish-api-core/src/category/rawtx.ts index 45460cb1f0..bd3a070ac8 100644 --- a/packages/jellyfish-api-core/src/category/rawtx.ts +++ b/packages/jellyfish-api-core/src/category/rawtx.ts @@ -169,28 +169,30 @@ export interface SignRawTxWithKeyResult { /** * Script verification errors (if there are any) */ - errors: Array<{ - /** - * The hash of the referenced, previous transaction - */ - txid: string - /** - * The index of the output to spent and used as input - */ - vout: number - /** - * The hex-encoded signature script - */ - scriptSig: string - /** - * Script sequence number - */ - sequence: number - /** - * Verification or signing error related to the input - */ - error: string - }> + errors: SignRawTxWithKeyError[] +} + +export interface SignRawTxWithKeyError { + /** + * The hash of the referenced, previous transaction + */ + txid: string + /** + * The index of the output to spent and used as input + */ + vout: number + /** + * The hex-encoded signature script + */ + scriptSig: string + /** + * Script sequence number + */ + sequence: number + /** + * Verification or signing error related to the input + */ + error: string } export interface TestMempoolAcceptResult { diff --git a/packages/jellyfish-api-core/src/category/token.ts b/packages/jellyfish-api-core/src/category/token.ts index e573af64d2..9bcff16eb0 100644 --- a/packages/jellyfish-api-core/src/category/token.ts +++ b/packages/jellyfish-api-core/src/category/token.ts @@ -1,7 +1,7 @@ import { ApiClient } from '../.' /** - * Token related RPC calls for DeFiChain + * Token RPCs for DeFi Blockchain */ export class Token { private readonly client: ApiClient @@ -84,24 +84,26 @@ export class Token { } export interface TokenResult { - [id: string]: { - symbol: string - symbolKey: string - name: string - decimal: number - limit: number - mintable: boolean - tradeable: boolean - isDAT: boolean - isLPS: boolean - finalized: boolean - minted: number - creationTx: string - creationHeight: number - destructionTx: string - destructionHeight: number - collateralAddress: string - } + [id: string]: TokenInfo +} + +export interface TokenInfo { + symbol: string + symbolKey: string + name: string + decimal: number + limit: number + mintable: boolean + tradeable: boolean + isDAT: boolean + isLPS: boolean + finalized: boolean + minted: number + creationTx: string + creationHeight: number + destructionTx: string + destructionHeight: number + collateralAddress: string } export interface CreateTokenMetadata { diff --git a/packages/jellyfish-api-core/src/category/wallet.ts b/packages/jellyfish-api-core/src/category/wallet.ts index 783bd81681..cb4c71ed9f 100644 --- a/packages/jellyfish-api-core/src/category/wallet.ts +++ b/packages/jellyfish-api-core/src/category/wallet.ts @@ -28,7 +28,7 @@ export enum WalletFlag { } /** - * Wallet related RPC calls for DeFiChain + * Wallet RPCs for DeFi Blockchain */ export class Wallet { private readonly client: ApiClient @@ -63,7 +63,7 @@ export class Wallet { * @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 ( minimumConfirmation = 1, maximumConfirmation = 9999999, @@ -134,7 +134,7 @@ export class Wallet { /** * Returns a new DeFi address for receiving payments. * If 'label' is specified, it's added to the address book - * so payments recevied with the address will be associated with 'label' + * so payments received with the address will be associated with 'label' * * @param {string} label for address to be linked to. It can also be set as empty string * @param {AddressType} addressType to use, eg: legacy, p2sh-segwit, bech32 @@ -295,8 +295,8 @@ export interface ValidateAddressResult { scriptPubKey: string isscript: boolean iswitness: boolean - ['witness_version']: number - ['witness_program']: string + witness_version: number + witness_program: string } export interface AddressInfo { @@ -309,8 +309,8 @@ export interface AddressInfo { isscript: boolean ischange: true iswitness: boolean - ['witness_version']: number - ['witness_program']: string + witness_version: number + witness_program: string script: ScriptType hex: string pubkeys: string[] @@ -321,8 +321,8 @@ export interface AddressInfo { scriptPubKey: string isscript: boolean iswitness: boolean - ['witness_version']: number - ['witness_program']: string + witness_version: number + witness_program: string script: ScriptType hex: string sigsrequired: number @@ -344,7 +344,7 @@ export interface Label { } export interface WalletFlagResult { - ['flag_name']: string - ['flag_state']: boolean + flag_name: string + flag_state: boolean warnings: string } diff --git a/packages/jellyfish-api-core/src/index.ts b/packages/jellyfish-api-core/src/index.ts index 3811e5bdd9..8086b0e7ed 100644 --- a/packages/jellyfish-api-core/src/index.ts +++ b/packages/jellyfish-api-core/src/index.ts @@ -7,15 +7,16 @@ import { PoolPair } from './category/poolpair' import { Token } from './category/token' export * from '@defichain/jellyfish-json' -export * from './category/blockchain' -export * from './category/mining' + +export * as blockchain from './category/blockchain' +export * as mining from './category/mining' export * as rawtx from './category/rawtx' -export * from './category/wallet' -export * from './category/poolpair' -export * from './category/token' +export * as wallet from './category/wallet' +export * as poolpair from './category/poolpair' +export * as token from './category/token' /** - * ApiClient; a protocol agnostic DeFiChain node client, RPC calls are separated into their category. + * A protocol agnostic DeFiChain node client, RPC calls are separated into their category. */ export abstract class ApiClient { public readonly blockchain = new Blockchain(this) @@ -51,7 +52,9 @@ export abstract class ApiClient { } /** - * ApiError; where defichain errors are encapsulated into. + * DeFi Blockchain errors are encapsulated into ApiError. + * @see ClientApiError + * @see RpcApiError */ export class ApiError extends Error { } diff --git a/packages/jellyfish-api-jsonrpc/src/index.ts b/packages/jellyfish-api-jsonrpc/src/index.ts index b3d727bbcf..14e9b61cae 100644 --- a/packages/jellyfish-api-jsonrpc/src/index.ts +++ b/packages/jellyfish-api-jsonrpc/src/index.ts @@ -45,8 +45,8 @@ export class JsonRpcClient extends ApiClient { /** * Construct a Jellyfish client to connect to a DeFiChain node via JSON-RPC. * - * @param url endpoint - * @param options Optional ClientOptions + * @param {string} url endpoint + * @param {ClientOptions} [options] Optional ClientOptions * timeout: default to 60000ms * headers: none */ diff --git a/packages/jellyfish-crypto/__tests__/bech32.test.ts b/packages/jellyfish-crypto/__tests__/bech32.test.ts index 0d01578352..ca4aa52620 100644 --- a/packages/jellyfish-crypto/__tests__/bech32.test.ts +++ b/packages/jellyfish-crypto/__tests__/bech32.test.ts @@ -1,41 +1,40 @@ -import { fromBech32, toBech32 } from '../src/bech32' -import { HASH160 } from '../src' +import { HASH160, Bech32 } from '../src' const hrp = 'bcrt' const bech32 = 'bcrt1qykj5fsrne09yazx4n72ue4fwtpx8u65zac9zhn' const pubKey = '03987aec2e508e124468f0f07a836d185b329026e7aaf75be48cf12be8f18cbe81' it('should convert bech32 to pubkey', () => { - const buffer: Buffer = fromBech32(bech32) + const buffer: Buffer = Bech32.toPubKey(bech32) const hash160 = HASH160(Buffer.from(pubKey, 'hex')) expect(buffer.toString('hex')).toBe(hash160.toString('hex')) }) it('should convert bech32 to pubkey with hrp and version', () => { - const buffer: Buffer = fromBech32(bech32, 'bcrt', 0x00) + const buffer: Buffer = Bech32.toPubKey(bech32, 'bcrt', 0x00) const hash160 = HASH160(Buffer.from(pubKey, 'hex')) expect(buffer.toString('hex')).toBe(hash160.toString('hex')) }) it('should fail convert bech32 to pubkey with invalid hrp', () => { expect(() => { - fromBech32(bech32, 'tf', 0x00) + Bech32.toPubKey(bech32, 'tf', 0x00) }).toThrow('Invalid HRP: human readable part') }) it('should fail convert bech32 to pubkey with invalid version', () => { expect(() => { // @ts-expect-error - fromBech32(bech32, 'bcrt', 0x01) + Bech32.toPubKey(bech32, 'bcrt', 0x01) }).toThrow('Invalid witness version') }) it('should convert pubkey to bech32', () => { - const bech32 = toBech32(Buffer.from(pubKey, 'hex'), hrp) + const bech32 = Bech32.fromPubKey(Buffer.from(pubKey, 'hex'), hrp) expect(bech32).toBe(bech32) }) it('should convert pubkey to bech32 with witness version', () => { - const bech32 = toBech32(Buffer.from(pubKey, 'hex'), hrp, 0x00) + const bech32 = Bech32.fromPubKey(Buffer.from(pubKey, 'hex'), hrp, 0x00) expect(bech32).toBe(bech32) }) diff --git a/packages/jellyfish-crypto/__tests__/elliptic.test.ts b/packages/jellyfish-crypto/__tests__/elliptic.test.ts index 7a49c55aae..323cde9ef3 100644 --- a/packages/jellyfish-crypto/__tests__/elliptic.test.ts +++ b/packages/jellyfish-crypto/__tests__/elliptic.test.ts @@ -1,11 +1,11 @@ -import { getEllipticPairFromPrivateKey } from '../src' +import { Elliptic } from '../src' // Test vector taken from https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki it('should return privateKey from getEllipticPairFromPrivateKey ', async () => { const privateKeyHex = 'bbc27228ddcb9209d7fd6f36b02f7dfa6252af40bb2f1cbc7a557da8027ff866' const privateKey = Buffer.from(privateKeyHex, 'hex') - const curvePair = getEllipticPairFromPrivateKey(privateKey) + const curvePair = Elliptic.fromPrivKey(privateKey) const getPrivKey: Buffer = await curvePair.privateKey() expect(getPrivKey.toString('hex')).toBe(privateKeyHex) @@ -17,7 +17,7 @@ describe('keypair', () => { it('should return publicKey from getEllipticPairFromPrivateKey', async () => { const privateKey = Buffer.from(privateKeyHex, 'hex') - const curvePair = getEllipticPairFromPrivateKey(privateKey) + const curvePair = Elliptic.fromPrivKey(privateKey) const getPubKey: Buffer = await curvePair.publicKey() expect(getPubKey.toString('hex')).toBe(publicKeyHex) @@ -25,7 +25,7 @@ describe('keypair', () => { it('should return privateKey from getEllipticPairFromPrivateKey ', async () => { const privateKey = Buffer.from(privateKeyHex, 'hex') - const curvePair = getEllipticPairFromPrivateKey(privateKey) + const curvePair = Elliptic.fromPrivKey(privateKey) const getPrivKey: Buffer = await curvePair.privateKey() expect(getPrivKey.toString('hex')).toBe(privateKeyHex) @@ -35,7 +35,7 @@ describe('keypair', () => { describe('DER Signature: sign and verify', () => { async function shouldReturnPubKeyFromPubKey (privateKeyHex: string, publicKeyHex: string): Promise { const privateKey = Buffer.from(privateKeyHex, 'hex') - const curvePair = getEllipticPairFromPrivateKey(privateKey) + const curvePair = Elliptic.fromPrivKey(privateKey) const getPubKey: Buffer = await curvePair.publicKey() expect(getPubKey.toString('hex')).toBe(publicKeyHex) @@ -43,7 +43,7 @@ describe('DER Signature: sign and verify', () => { async function shouldSignHashBufferGetSignature (privateKeyHex: string, hashHex: string, signatureHex: string): Promise { const privateKey = Buffer.from(privateKeyHex, 'hex') - const curvePair = getEllipticPairFromPrivateKey(privateKey) + const curvePair = Elliptic.fromPrivKey(privateKey) const hash = Buffer.from(hashHex, 'hex') const signature = await curvePair.sign(hash) @@ -52,7 +52,7 @@ describe('DER Signature: sign and verify', () => { async function shouldVerifyHashWithSignature (privateKeyHex: string, hashHex: string, signatureHex: string): Promise { const privateKey = Buffer.from(privateKeyHex, 'hex') - const curvePair = getEllipticPairFromPrivateKey(privateKey) + const curvePair = Elliptic.fromPrivKey(privateKey) const hash = Buffer.from(hashHex, 'hex') const signature = Buffer.from(signatureHex, 'hex') @@ -111,7 +111,7 @@ describe('DER Signature: sign and verify', () => { it('should sign hash Buffer and verify signature', async () => { const privateKey = Buffer.from(privateKeyHex, 'hex') - const curvePair = getEllipticPairFromPrivateKey(privateKey) + const curvePair = Elliptic.fromPrivKey(privateKey) const hash = Buffer.from(hashHex, 'hex') const signature = await curvePair.sign(hash) @@ -135,7 +135,7 @@ describe('DER Signature: sign and verify', () => { it('should sign hash Buffer and verify signature', async () => { const privateKey = Buffer.from(privateKeyHex, 'hex') - const curvePair = getEllipticPairFromPrivateKey(privateKey) + const curvePair = Elliptic.fromPrivKey(privateKey) const hash = Buffer.from(hashHex, 'hex') const signature = await curvePair.sign(hash) diff --git a/packages/jellyfish-crypto/__tests__/wif.test.ts b/packages/jellyfish-crypto/__tests__/wif.test.ts index ee9c5cbbc1..92165a09c8 100644 --- a/packages/jellyfish-crypto/__tests__/wif.test.ts +++ b/packages/jellyfish-crypto/__tests__/wif.test.ts @@ -1,11 +1,11 @@ -import { encode, decode, decodeAsEllipticPair } from '../src' +import { WIF } from '../src' const REG_TEST_WIF = 'cQSsfYvYkK5tx3u1ByK2ywTTc9xJrREc1dd67ZrJqJUEMwgktPWN' const privKey = '557c4bdff86e59015987c1c7f3328a1fb4c2177b5e834f09c8cd10fae51af93b' const pubKey = '03987aec2e508e124468f0f07a836d185b329026e7aaf75be48cf12be8f18cbe81' it('should decode without version', () => { - const decoded = decode(REG_TEST_WIF) + const decoded = WIF.decode(REG_TEST_WIF) expect(decoded.version).toBe(0xef) expect(decoded.compressed).toBe(true) @@ -14,12 +14,12 @@ it('should decode without version', () => { it('should decode with failed version', () => { expect(() => { - decode(REG_TEST_WIF, 0x80) + WIF.decode(REG_TEST_WIF, 0x80) }).toThrow('Invalid network version') }) it('should decode with correct version', () => { - const decoded = decode(REG_TEST_WIF, 0xef) + const decoded = WIF.decode(REG_TEST_WIF, 0xef) expect(decoded.version).toBe(0xef) expect(decoded.compressed).toBe(true) @@ -27,7 +27,7 @@ it('should decode with correct version', () => { }) it('should decode decodeAsEllipticPair', async () => { - const pair = decodeAsEllipticPair(REG_TEST_WIF, 0xef) + const pair = WIF.asEllipticPair(REG_TEST_WIF, 0xef) const privateKey = await pair.privateKey() const publicKey = await pair.publicKey() expect(privateKey.toString('hex')).toBe(privKey) @@ -35,6 +35,6 @@ it('should decode decodeAsEllipticPair', async () => { }) it('should encode', () => { - const wif = encode(0xef, Buffer.from(privKey, 'hex')) + const wif = WIF.encode(0xef, Buffer.from(privKey, 'hex')) expect(wif).toBe(REG_TEST_WIF) }) diff --git a/packages/jellyfish-crypto/src/bech32.ts b/packages/jellyfish-crypto/src/bech32.ts index 56673354e0..481e43ce50 100644 --- a/packages/jellyfish-crypto/src/bech32.ts +++ b/packages/jellyfish-crypto/src/bech32.ts @@ -13,11 +13,11 @@ export type HRP = 'df' | 'tf' | 'bcrt' /** * @param {Buffer} pubKey to format into bech32 * @param {'df'|'tf'|'bcrt'} hrp is the human readable part - * @param {number} version witness version, OP_0 + * @param {number} [version=0x00] witness version, OP_0 * @return {string} bech32 encoded address * @see https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki */ -export function toBech32 (pubKey: Buffer, hrp: HRP, version: 0x00 = 0x00): string { +function toBech32 (pubKey: Buffer, hrp: HRP, version: 0x00 = 0x00): string { const hash = SHA256(pubKey) const words = bech32.toWords(hash) words.unshift(version) @@ -27,11 +27,11 @@ export function toBech32 (pubKey: Buffer, hrp: HRP, version: 0x00 = 0x00): strin /** * @param {string} address to decode from bech32 * @param {'df'|'tf'|'bcrt'} hrp is the human readable part - * @param {number} version witness version, OP_0 + * @param {number} [version] witness version, OP_0 * @return {Buffer} hash160 of the pubkey * @see https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki */ -export function fromBech32 (address: string, hrp?: HRP, version?: 0x00): Buffer { +function fromBech32 (address: string, hrp?: HRP, version?: 0x00): Buffer { const { prefix, words } = bech32.decode(address) if (hrp !== undefined && prefix !== hrp) { throw new Error('Invalid HRP: human readable part') @@ -44,3 +44,24 @@ export function fromBech32 (address: string, hrp?: HRP, version?: 0x00): Buffer return Buffer.from(bech32.fromWords(words)) } + +export const Bech32 = { + /** + * @param {Buffer} pubKey to format into bech32 + * @param {'df'|'tf'|'bcrt'} hrp is the human readable part + * @param {number} [version=0x00] witness version, OP_0 + * @return {string} bech32 encoded address + */ + fromPubKey (pubKey: Buffer, hrp: HRP, version: 0x00 = 0x00): string { + return toBech32(pubKey, hrp, version) + }, + /** + * @param {string} address to decode from bech32 + * @param {'df'|'tf'|'bcrt'} hrp is the human readable part + * @param {number} [version] witness version, OP_0 + * @return {Buffer} hash160 of the pubkey + */ + toPubKey (address: string, hrp?: HRP, version?: 0x00): Buffer { + return fromBech32(address, hrp, version) + } +} diff --git a/packages/jellyfish-crypto/src/elliptic.ts b/packages/jellyfish-crypto/src/elliptic.ts index 8932baefe7..ec17648d34 100644 --- a/packages/jellyfish-crypto/src/elliptic.ts +++ b/packages/jellyfish-crypto/src/elliptic.ts @@ -11,18 +11,18 @@ import { DERSignature } from './der' */ export interface EllipticPair { /** - * @return Promise compressed public key + * @return {Promise} compressed public key */ publicKey: () => Promise /** * Allowed to fail if EllipticPair does not provide hardware key - * @return Promise privateKey + * @return {Promise} privateKey */ privateKey: () => Promise /** - * @param hash {Buffer} to sign + * @param {Buffer} hash to sign * @return {Buffer} signature in DER format, SIGHASHTYPE not included * @see https://tools.ietf.org/html/rfc6979 * @see https://github.com/bitcoin/bitcoin/pull/13666 @@ -30,9 +30,9 @@ export interface EllipticPair { sign: (hash: Buffer) => Promise /** - * @param hash {Buffer} to verify with signature - * @param derSignature {Buffer} of the hash in encoded with DER, SIGHASHTYPE must not be included - * @return boolean validity of signature of the hash + * @param {Buffer} hash to verify with signature + * @param {Buffer} derSignature of the hash in encoded with DER, SIGHASHTYPE must not be included + * @return {boolean} validity of signature of the hash */ verify: (hash: Buffer, derSignature: Buffer) => Promise } @@ -84,9 +84,19 @@ class SECP256K1 implements EllipticPair { } /** - * @param buffer in little endian - * @return SECP256K1 EllipticPair + * @param {Buffer} buffer in little endian + * @return {SECP256K1} EllipticPair */ -export function getEllipticPairFromPrivateKey (buffer: Buffer): EllipticPair { +function getEllipticPairFromPrivateKey (buffer: Buffer): EllipticPair { return new SECP256K1(buffer) } + +export const Elliptic = { + /** + * @param {Buffer} buffer in little endian + * @return {SECP256K1} EllipticPair + */ + fromPrivKey (buffer: Buffer): EllipticPair { + return getEllipticPairFromPrivateKey(buffer) + } +} diff --git a/packages/jellyfish-crypto/src/hash.ts b/packages/jellyfish-crypto/src/hash.ts index cd08f6f55c..2f0d6524d6 100644 --- a/packages/jellyfish-crypto/src/hash.ts +++ b/packages/jellyfish-crypto/src/hash.ts @@ -1,28 +1,28 @@ import createHash from 'create-hash' /** - * @param buffer to RIPEMD160(buffer) + * @param {Buffer} buffer to RIPEMD160(buffer) */ export function RIPEMD160 (buffer: Buffer): Buffer { return createHash('rmd160').update(buffer).digest() } /** - * @param buffer to SHA256(buffer) + * @param {Buffer} buffer to SHA256(buffer) */ export function SHA256 (buffer: Buffer): Buffer { return createHash('sha256').update(buffer).digest() } /** - * @param buffer to RIPEMD160(SHA256(buffer)) + * @param {Buffer} buffer to RIPEMD160(SHA256(buffer)) */ export function HASH160 (buffer: Buffer): Buffer { return RIPEMD160(SHA256(buffer)) } /** - * @param buffer to SHA256(SHA256(buffer)) + * @param {Buffer} buffer to SHA256(SHA256(buffer)) */ export function dSHA256 (buffer: Buffer): Buffer { return SHA256(SHA256(buffer)) diff --git a/packages/jellyfish-crypto/src/wif.ts b/packages/jellyfish-crypto/src/wif.ts index 658963c095..14211af4a1 100644 --- a/packages/jellyfish-crypto/src/wif.ts +++ b/packages/jellyfish-crypto/src/wif.ts @@ -1,5 +1,5 @@ import wif from 'wif' -import { EllipticPair, getEllipticPairFromPrivateKey } from './elliptic' +import { EllipticPair, Elliptic } from './elliptic' interface DecodedWIF { readonly version: number @@ -10,10 +10,10 @@ interface DecodedWIF { /** * @param {string} wifEncoded private key * @param {number} version network to optionally validate - * @return DecodedWIF + * @return {DecodedWIF} * @throws Error invalid network version if version mismatch */ -export function decode (wifEncoded: string, version?: number): DecodedWIF { +function decode (wifEncoded: string, version?: number): DecodedWIF { return wif.decode(wifEncoded, version) } @@ -22,12 +22,12 @@ export function decode (wifEncoded: string, version?: number): DecodedWIF { * * @param {string} wifEncoded private key * @param {number} version network to optionally validate - * @return EllipticPair + * @return {EllipticPair} * @throws Error invalid network version if version mismatch */ -export function decodeAsEllipticPair (wifEncoded: string, version?: number): EllipticPair { +function decodeAsEllipticPair (wifEncoded: string, version?: number): EllipticPair { const { privateKey } = decode(wifEncoded, version) - return getEllipticPairFromPrivateKey(privateKey) + return Elliptic.fromPrivKey(privateKey) } /** @@ -35,6 +35,40 @@ export function decodeAsEllipticPair (wifEncoded: string, version?: number): Ell * @param {Buffer} privKey to encode * @return {string} encoded WIF */ -export function encode (version: number, privKey: Buffer): string { +function encode (version: number, privKey: Buffer): string { return wif.encode(version, privKey, true) } + +export const WIF = { + + /** + * @param {string} wif private key + * @param {number} [version] network to optionally validate + * @return {DecodedWIF} + * @throws Error invalid network version if version mismatch + */ + decode (wif: string, version?: number): DecodedWIF { + return decode(wif, version) + }, + + /** + * @param {number} version network version to encoded WIF with + * @param {Buffer} privKey to encode + * @return {string} encoded WIF + */ + encode (version: number, privKey: Buffer): string { + return encode(version, privKey) + }, + + /** + * Get a EllipticPair from WIF encoded private key + * + * @param {string} wif private key + * @param {number} [version] network to optionally validate + * @return EllipticPair + * @throws Error invalid network version if version mismatch + */ + asEllipticPair (wif: string, version?: number): EllipticPair { + return decodeAsEllipticPair(wif, version) + } +} diff --git a/packages/jellyfish-json/README.md b/packages/jellyfish-json/README.md index 22684ec96b..0091834a43 100644 --- a/packages/jellyfish-json/README.md +++ b/packages/jellyfish-json/README.md @@ -9,3 +9,5 @@ regular numeric operations, and it will throw an error when this would result in losing information. - `'bignumber'` parse all numeric values as 'BigNumber' using bignumber.js library. - `'number'` parse all numeric values as 'Number' and precision will be loss if it exceeds IEEE-754 standard. +- `'PrecisionPath'` provides path based precision mapping, specifying 'bignumber' will automatically map all Number in + that path as 'bignumber'. Otherwise, it will default to number, This applies deeply. diff --git a/packages/jellyfish-transaction/__testcontainers__/craft_sign_send_tx.test.ts b/packages/jellyfish-transaction/__testcontainers__/craft_sign_send_tx.test.ts index 45fe70e8ea..6e6f51ba25 100644 --- a/packages/jellyfish-transaction/__testcontainers__/craft_sign_send_tx.test.ts +++ b/packages/jellyfish-transaction/__testcontainers__/craft_sign_send_tx.test.ts @@ -3,7 +3,7 @@ import { MasterNodeRegTestContainer } from '@defichain/testcontainers' import { JsonRpcClient } from '@defichain/jellyfish-api-jsonrpc' import { CTransactionSegWit, DeFiTransactionConstants, Transaction, TransactionSigner } from '../src' import { OP_CODES } from '../src/script' -import { decodeAsEllipticPair, HASH160 } from '@defichain/jellyfish-crypto' +import { WIF, HASH160 } from '@defichain/jellyfish-crypto' import { SmartBuffer } from 'smart-buffer' const container = new MasterNodeRegTestContainer() @@ -39,8 +39,8 @@ it('should craft, sign and broadcast a txn from scratch', async () => { // Decode 2 set of deterministic EllipticPair using WIF // You can use 'jellyfish-wallet' or 'jellyfish-crypto' to generate your pair - const inputPair = decodeAsEllipticPair(input.privKey) - const outputPair = decodeAsEllipticPair(output.privKey) + const inputPair = WIF.asEllipticPair(input.privKey) + const outputPair = WIF.asEllipticPair(output.privKey) // Fund an untracked address with 10.0 DFI for testing const { txid, vout } = await container.fundAddress(input.bech32, 10) diff --git a/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_1.test.ts b/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_1.test.ts index e2c991008b..9be8bba918 100644 --- a/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_1.test.ts +++ b/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_1.test.ts @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js' import { SmartBuffer } from 'smart-buffer' -import { fromBech32, decodeAsEllipticPair } from '@defichain/jellyfish-crypto' +import { Bech32, WIF } from '@defichain/jellyfish-crypto' import { CTransaction, CTransactionSegWit, SignInputOption, TransactionSigner } from '../../src' import { OP_CODES } from '../../src/script' @@ -42,13 +42,13 @@ it('sign transaction', async () => { script: { stack: [ OP_CODES.OP_0, - OP_CODES.OP_PUSHDATA(fromBech32(input.bech32, 'bcrt', 0x00), 'little') + OP_CODES.OP_PUSHDATA(Bech32.toPubKey(input.bech32, 'bcrt', 0x00), 'little') ] }, value: new BigNumber('10'), dct_id: 0 }, - ellipticPair: decodeAsEllipticPair(input.privKey) + ellipticPair: WIF.asEllipticPair(input.privKey) }] const txSigned = new CTransactionSegWit(await TransactionSigner.sign(txUnsigned, inputs)) diff --git a/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_2.test.ts b/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_2.test.ts index bf9230df62..4b2611e828 100644 --- a/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_2.test.ts +++ b/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_2.test.ts @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js' import { SmartBuffer } from 'smart-buffer' -import { fromBech32, decodeAsEllipticPair } from '@defichain/jellyfish-crypto' +import { Bech32, WIF } from '@defichain/jellyfish-crypto' import { CTransaction, CTransactionSegWit, SignInputOption, TransactionSigner } from '../../src' import { OP_CODES } from '../../src/script' @@ -42,13 +42,13 @@ it('sign transaction', async () => { script: { stack: [ OP_CODES.OP_0, - OP_CODES.OP_PUSHDATA(fromBech32(input.bech32, 'bcrt', 0x00), 'little') + OP_CODES.OP_PUSHDATA(Bech32.toPubKey(input.bech32, 'bcrt', 0x00), 'little') ] }, value: new BigNumber('10'), dct_id: 0 }, - ellipticPair: decodeAsEllipticPair(input.privKey) + ellipticPair: WIF.asEllipticPair(input.privKey) }] const txSigned = new CTransactionSegWit(await TransactionSigner.sign(txUnsigned, inputs)) diff --git a/packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts b/packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts index 808888539a..70ea6c5b9d 100644 --- a/packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts +++ b/packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts @@ -1,7 +1,7 @@ import BigNumber from 'bignumber.js' import { SIGHASH, Transaction, TransactionSigner, Vout } from '../../src' import { OP_CODES, OP_PUSHDATA } from '../../src/script' -import { getEllipticPairFromPrivateKey, SHA256, HASH160 } from '@defichain/jellyfish-crypto' +import { SHA256, HASH160, Elliptic } from '@defichain/jellyfish-crypto' describe('sign single input', () => { const transaction: Transaction = { @@ -67,7 +67,7 @@ describe('sign single input', () => { value: new BigNumber('6'), dct_id: 0x00 } - const keyPair = getEllipticPairFromPrivateKey(privateKey) + const keyPair = Elliptic.fromPrivKey(privateKey) it('should sign single input', async () => { const witness = await TransactionSigner.signInput(transaction, 1, { diff --git a/packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts b/packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts index 8e12a60afe..e745736c4f 100644 --- a/packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts +++ b/packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts @@ -1,7 +1,7 @@ import BigNumber from 'bignumber.js' import { DeFiTransactionConstants, SIGHASH, Transaction, TransactionSigner, Vout } from '../../src' import { OP_CODES, OP_PUSHDATA } from '../../src/script' -import { getEllipticPairFromPrivateKey } from '@defichain/jellyfish-crypto' +import { Elliptic } from '@defichain/jellyfish-crypto' describe('sign transaction', () => { const transaction: Transaction = { @@ -43,7 +43,7 @@ describe('sign transaction', () => { value: new BigNumber('1000'), dct_id: 0x00 } - const keyPair = getEllipticPairFromPrivateKey(privateKey) + const keyPair = Elliptic.fromPrivKey(privateKey) const inputOption = { prevout: prevout, ellipticPair: keyPair diff --git a/packages/jellyfish-wallet-whale/src/index.ts b/packages/jellyfish-wallet-whale/src/index.ts index 46ae5f3e74..12fc88dca0 100644 --- a/packages/jellyfish-wallet-whale/src/index.ts +++ b/packages/jellyfish-wallet-whale/src/index.ts @@ -1,6 +1,6 @@ import { WalletAccount, WalletAccountProvider, WalletHdNode } from '@defichain/jellyfish-wallet' import { Network } from '@defichain/jellyfish-network' -import { HRP, toBech32 } from '@defichain/jellyfish-crypto' +import { HRP, Bech32 } from '@defichain/jellyfish-crypto' /** * jellyfish-api-whale implementation of WalletAccount. @@ -20,7 +20,7 @@ export class WhaleWalletAccount implements WalletAccount { */ async getAddress (): Promise { const pubKey = await this.hdNode.publicKey() - return toBech32(pubKey, this.network.bech32.hrp as HRP) + return Bech32.fromPubKey(pubKey, this.network.bech32.hrp as HRP) } async isActive (): Promise { diff --git a/packages/jellyfish-wallet/__tests__/node.mock.ts b/packages/jellyfish-wallet/__tests__/node.mock.ts index 357b112381..ddfc74455a 100644 --- a/packages/jellyfish-wallet/__tests__/node.mock.ts +++ b/packages/jellyfish-wallet/__tests__/node.mock.ts @@ -6,7 +6,7 @@ import { TransactionSigner, Vout } from '@defichain/jellyfish-transaction' -import { EllipticPair, getEllipticPairFromPrivateKey } from '@defichain/jellyfish-crypto' +import { EllipticPair, Elliptic } from '@defichain/jellyfish-crypto' /** * This is for testing only, please don't use this for anything else. @@ -17,7 +17,7 @@ export class TestNode implements WalletHdNode { constructor (path: string) { this.path = path - this.ellipticPair = getEllipticPairFromPrivateKey( + this.ellipticPair = Elliptic.fromPrivKey( Buffer.alloc(32, path, 'ascii') ) } diff --git a/packages/testcontainers/package.json b/packages/testcontainers/package.json index 8b29afa5e9..18bcb72dfa 100644 --- a/packages/testcontainers/package.json +++ b/packages/testcontainers/package.json @@ -35,11 +35,11 @@ "build": "tsc" }, "dependencies": { - "dockerode": "^3.2.1", + "dockerode": "^3.3.0", "node-fetch": "^2.6.1" }, "devDependencies": { - "@types/dockerode": "^3.2.2", - "@types/node-fetch": "^2.5.8" + "@types/dockerode": "^3.2.3", + "@types/node-fetch": "^2.5.10" } } diff --git a/website/docs/jellyfish/api/poolpair.md b/website/docs/jellyfish/api/poolpair.md index 527a88c027..5ff489939a 100644 --- a/website/docs/jellyfish/api/poolpair.md +++ b/website/docs/jellyfish/api/poolpair.md @@ -42,8 +42,8 @@ interface PoolPairInfo { reserveB: BigNumber commission: BigNumber totalLiquidity: BigNumber - ['reserveA/reserveB']: BigNumber - ['reserveB/reserveA']: BigNumber + 'reserveA/reserveB': BigNumber + 'reserveB/reserveA': BigNumber tradeEnabled: boolean ownerAddress: string blockCommissionA: BigNumber @@ -84,8 +84,8 @@ interface PoolPairInfo { reserveB: BigNumber commission: BigNumber totalLiquidity: BigNumber - ['reserveA/reserveB']: BigNumber - ['reserveB/reserveA']: BigNumber + 'reserveA/reserveB': BigNumber + 'reserveB/reserveA': BigNumber tradeEnabled: boolean ownerAddress: string blockCommissionA: BigNumber @@ -145,7 +145,7 @@ interface PoolShareResult { interface PoolShareInfo { poolID: string owner: string - ['%']: BigNumber + '%': BigNumber amount: BigNumber totalLiquidity: BigNumber } @@ -159,4 +159,4 @@ interface PoolPairPagination { interface PoolShareOptions { isMineOnly?: boolean } -``` \ No newline at end of file +``` diff --git a/website/docs/jellyfish/api/rawtx.md b/website/docs/jellyfish/api/rawtx.md index 504bbe564d..9aa743eba2 100644 --- a/website/docs/jellyfish/api/rawtx.md +++ b/website/docs/jellyfish/api/rawtx.md @@ -81,6 +81,20 @@ enum SigHashType { NONE_ANYONECANPAY = 'NONE|ANYONECANPAY', SINGLE_ANYONECANPAY = 'SINGLE|ANYONECANPAY', } + +interface SignRawTxWithKeyResult { + hex: string + complete: boolean + errors: Array +} + +interface SignRawTxWithKeyError { + txid: string + vout: number + scriptSig: string + sequence: number + error: string +} ``` ## testMempoolAccept diff --git a/website/docs/jellyfish/api/token.md b/website/docs/jellyfish/api/token.md index 6ad9e75640..e16ce2faa2 100644 --- a/website/docs/jellyfish/api/token.md +++ b/website/docs/jellyfish/api/token.md @@ -73,24 +73,26 @@ interface token { } interface TokenResult { - [id: string]: { - symbol: string - symbolKey: string - name: string - decimal: number - limit: number - mintable: boolean - tradeable: boolean - isDAT: boolean - isLPS: boolean - finalized: boolean - minted: number - creationTx: string - creationHeight: number - destructionTx: string - destructionHeight: number - collateralAddress: string - } + [id: string]: TokenInfo +} + +interface TokenInfo { + symbol: string + symbolKey: string + name: string + decimal: number + limit: number + mintable: boolean + tradeable: boolean + isDAT: boolean + isLPS: boolean + finalized: boolean + minted: number + creationTx: string + creationHeight: number + destructionTx: string + destructionHeight: number + collateralAddress: string } interface TokenPagination { @@ -110,23 +112,25 @@ interface token { } interface TokenResult { - [id: string]: { - symbol: string - symbolKey: string - name: string - decimal: number - limit: number - mintable: boolean - tradeable: boolean - isDAT: boolean - isLPS: boolean - finalized: boolean - minted: number - creationTx: string - creationHeight: number - destructionTx: string - destructionHeight: number - collateralAddress: string - } + [id: string]: TokenInfo } -``` \ No newline at end of file + +interface TokenInfo { + symbol: string + symbolKey: string + name: string + decimal: number + limit: number + mintable: boolean + tradeable: boolean + isDAT: boolean + isLPS: boolean + finalized: boolean + minted: number + creationTx: string + creationHeight: number + destructionTx: string + destructionHeight: number + collateralAddress: string +} +``` diff --git a/website/docs/jellyfish/api/wallet.md b/website/docs/jellyfish/api/wallet.md index b51aa92018..4f98bb5f16 100644 --- a/website/docs/jellyfish/api/wallet.md +++ b/website/docs/jellyfish/api/wallet.md @@ -88,7 +88,7 @@ interface CreateWalletOptions { avoidReuse?: boolean } -export interface CreateWalletResult { +interface CreateWalletResult { name: string warning: string } @@ -145,7 +145,7 @@ interface WalletFlagResult { Returns a new DeFi address for receiving payments. If 'label' is specified, it's added to the address book. -So payments recevied with the address will be associated with 'label'. +So payments received with the address will be associated with 'label'. ```ts title="client.wallet.getNewAddress()" interface wallet { @@ -168,8 +168,8 @@ interface ValidateAddressResult { scriptPubKey: string isscript: boolean iswitness: boolean - ['witness_version']: number - ['witness_program']: string + witness_version: number + witness_program: string } ``` @@ -192,8 +192,8 @@ interface AddressInfo { isscript: boolean ischange: true iswitness: boolean - ['witness_version']: number - ['witness_program']: string + witness_version: number + witness_program: string script: ScriptType hex: string pubkeys: string[] @@ -204,8 +204,8 @@ interface AddressInfo { scriptPubKey: string isscript: boolean iswitness: boolean - ['witness_version']: number - ['witness_program']: string + witness_version: number + witness_program: string script: ScriptType hex: string sigsrequired: number @@ -249,10 +249,10 @@ interface SendToAddressOptions { ## listAddressGroupings -Lists groups of addresses which have had their common ownership made public by common use as inputs or as the resulting change in past transactions. +List groups of addresses which have had their common ownership made public by common use as inputs or as the resulting change in past transactions. ```ts title="client.wallet.listAddressGroupings()" interface wallet { listAddressGroupings (): Promise } -``` \ No newline at end of file +``` diff --git a/website/docs/jellyfish/design.md b/website/docs/jellyfish/design.md index 548041eadd..8a97c15788 100644 --- a/website/docs/jellyfish/design.md +++ b/website/docs/jellyfish/design.md @@ -56,8 +56,8 @@ it('lost precision converting DFI 😥', () => { regular numeric operations, and it will throw an error when this would result in losing information. * **'bignumber'** parse all numeric values as 'BigNumber' using bignumber.js library. * **'number'** parse all numeric values as 'Number' and precision will be loss if it exceeds IEEE-754 standard. -* **'PrecisionPath'** path based precision mapping, specifying 'bignumber' will automatically map all Number in that - path as 'bignumber'. Otherwise, it will default to number, This applies deeply. +* **'PrecisionPath'** provides path based precision mapping, specifying 'bignumber' will automatically map all Number in + that path as 'bignumber'. Otherwise, it will default to number, This applies deeply. As not all number parsed are significant in all context, (e.g. `mining.getMintingInfo()`), this allows jellyfish library