Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getRawTransaction rpc #385

Merged
merged 3 commits into from
Jun 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .idea/dictionaries/fuxing.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { RawTransaction } from '@defichain/jellyfish-api-core/category/rawtx'
import { MasterNodeRegTestContainer } from '@defichain/testcontainers'
import { ContainerAdapterClient } from '../../container_adapter_client'
import { RpcApiError } from '../../../src'

describe('RawTransaction', () => {
const container = new MasterNodeRegTestContainer()
const client = new ContainerAdapterClient(container)

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

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

async function createToken (symbol: string): Promise<string> {
const address = await container.call('getnewaddress')
const metadata = {
symbol,
name: symbol,
isDAT: true,
mintable: true,
tradeable: true,
collateralAddress: address
}
const txid = await container.call('createtoken', [metadata])
await container.generate(1)
return txid
}

it('should getRawTransaction with verbose true to get informative json object', async () => {
const txid = await createToken('ANT')

const data: RawTransaction = await client.rawtx.getRawTransaction(txid, true)
expect(typeof data.txid).toStrictEqual('string')
expect(typeof data.hash).toStrictEqual('string')
expect(typeof data.version).toStrictEqual('number')
expect(typeof data.size).toStrictEqual('number')
expect(typeof data.vsize).toStrictEqual('number')
expect(typeof data.weight).toStrictEqual('number')
expect(typeof data.locktime).toStrictEqual('number')
expect(typeof data.vin[0].txid).toStrictEqual('string')
expect(typeof data.vin[0].vout).toStrictEqual('number')
expect(typeof data.vin[0].scriptSig.asm).toStrictEqual('string')
expect(typeof data.vin[0].scriptSig.hex).toStrictEqual('string')
expect(typeof data.vin[0].sequence).toStrictEqual('number')
expect(typeof data.vout[0].value).toStrictEqual('number')
expect(typeof data.vout[0].n).toStrictEqual('number')
expect(typeof data.vout[0].scriptPubKey.asm).toStrictEqual('string')
expect(typeof data.vout[0].scriptPubKey.hex).toStrictEqual('string')
expect(typeof data.vout[0].scriptPubKey.type).toStrictEqual('string')
expect(typeof data.vout[0].tokenId).toStrictEqual('number')
expect(typeof data.hex).toStrictEqual('string')
expect(typeof data.blockhash).toStrictEqual('string')
expect(typeof data.confirmations).toStrictEqual('number')
expect(typeof data.time).toStrictEqual('number')
expect(typeof data.blocktime).toStrictEqual('number')
})

it('should getRawTransaction with verbose false in hex-encoded format', async () => {
const txid = await createToken('BAT')

const hex = await client.rawtx.getRawTransaction(txid, false)
expect(typeof hex).toStrictEqual('string')
})

it('should getRawTransaction with verbose true and specified blockHash', async () => {
const txid = await createToken('CAT')

const count = await container.call('getblockcount')
const hash = await container.call('getblockhash', [count])
const data: RawTransaction = await client.rawtx.getRawTransaction(txid, true, hash)
expect(typeof data.in_active_chain).toStrictEqual('boolean')
expect(typeof data.txid).toStrictEqual('string')
expect(typeof data.hash).toStrictEqual('string')
expect(typeof data.version).toStrictEqual('number')
expect(typeof data.size).toStrictEqual('number')
expect(typeof data.vsize).toStrictEqual('number')
expect(typeof data.weight).toStrictEqual('number')
expect(typeof data.locktime).toStrictEqual('number')
expect(typeof data.vin[0].txid).toStrictEqual('string')
expect(typeof data.vin[0].vout).toStrictEqual('number')
expect(typeof data.vin[0].scriptSig.asm).toStrictEqual('string')
expect(typeof data.vin[0].scriptSig.hex).toStrictEqual('string')
expect(typeof data.vin[0].sequence).toStrictEqual('number')
expect(typeof data.vout[0].value).toStrictEqual('number')
expect(typeof data.vout[0].n).toStrictEqual('number')
expect(typeof data.vout[0].scriptPubKey.asm).toStrictEqual('string')
expect(typeof data.vout[0].scriptPubKey.hex).toStrictEqual('string')
expect(typeof data.vout[0].scriptPubKey.type).toStrictEqual('string')
expect(typeof data.vout[0].tokenId).toStrictEqual('number')
expect(typeof data.hex).toStrictEqual('string')
expect(typeof data.blockhash).toStrictEqual('string')
expect(typeof data.confirmations).toStrictEqual('number')
expect(typeof data.time).toStrictEqual('number')
expect(typeof data.blocktime).toStrictEqual('number')
})

it('should be failed as specified hash which does not come with txid', async () => {
const txid = await createToken('DOG')

const count = await container.call('getblockcount')
const wrongHash = await container.call('getblockhash', [count - 1])
const promise = client.rawtx.getRawTransaction(txid, true, wrongHash)
await expect(promise).rejects.toThrow(RpcApiError)
await expect(promise).rejects.toThrow('No such transaction found in the provided block. Use gettransaction for wallet transactions.')
})

it('should getRawTransaction with verbose true and specified blockHash in hex-encoded format', async () => {
const txid = await createToken('ELF')

const count = await container.call('getblockcount')
const hash = await container.call('getblockhash', [count])
const hex: string = await client.rawtx.getRawTransaction(txid, false, hash)
expect(typeof hex).toStrictEqual('string')
})
})
4 changes: 2 additions & 2 deletions packages/jellyfish-api-core/src/category/blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,14 +273,14 @@ export interface Transaction {
}

export interface Vin {
coinbase: string
coinbase?: string
txid: string
vout: number
scriptSig: {
asm: string
hex: string
}
txinwitness: string[]
txinwitness?: string[]
sequence: string
}

Expand Down
118 changes: 117 additions & 1 deletion packages/jellyfish-api-core/src/category/rawtx.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Vin, Vout } from './blockchain'
import { BigNumber, ApiClient } from '../.'

export enum SigHashType {
Expand Down Expand Up @@ -49,7 +50,7 @@ export class RawTx {
*
* @param {string} rawTx unsigned raw transaction
* @param {string[]} privKeys array of base58-encoded private keys for signing (WIF)
* @param {SignRawTxWithKeyOption} [options]
* @param {SignRawTxWithKeyOptions} [options]
* @param {SigHashType} [options.sigHashType] the signature hash type to use
* @param {SignRawTxWithKeyPrevTx[]} [options.prevTxs] array of previous dependent transaction outputs
* @return {Promise<SignRawTxWithKeyResult>}
Expand Down Expand Up @@ -108,6 +109,58 @@ export class RawTx {
signedTx, maxFeeRate
], 'number')
}

/**
* Get raw transaction in hex-encoded format
*
* @param {string} txid the transaction id
* @param {boolean} verbose false
* @return {Promise<string>}
*/
getRawTransaction (txid: string, verbose: false): Promise<string>

/**
* Get raw transaction with block hash in hex-encoded format
*
* @param {string} txid the transaction id
* @param {boolean} verbose false
* @param {string} blockHash the block hash
* @return {Promise<string>}
*/
getRawTransaction (txid: string, verbose: false, blockHash: string): Promise<string>

/**
* Get raw transaction as json object
*
* @param {string} txid the transaction id
* @param {boolean} verbose false
* @return {Promise<RawTransaction>}
*/
getRawTransaction (txid: string, verbose: true): Promise<RawTransaction>

/**
* Get raw transaction from block at first by providing block hash, return as json object
*
* @param {string} txid the transaction id
* @param {string} verbose false
* @param {string} blockHash the block hash
* @return {Promise<RawTransaction>}
*/
getRawTransaction (txid: string, verbose: true, blockHash: string): Promise<RawTransaction>

/**
* Get raw transaction
*
* @param {string} txid transaction id
* @param {boolean} [verbose=false] true will return object information, false/omitted will return hex-encoded data
* @param {string} [blockHash] mempool transaction is returned by default. If blockHash is specified then will get transaction in block.
* @return {Promise<string | RawTransaction>}
*/
async getRawTransaction (
txid: string, verbose?: boolean, blockHash?: string
): Promise<string | RawTransaction> {
return await this.client.call('getrawtransaction', [txid, verbose, blockHash], 'number')
}
}

export interface CreateRawTxOptions {
Expand Down Expand Up @@ -209,3 +262,66 @@ export interface TestMempoolAcceptResult {
*/
'reject-reason'?: string
}

export interface RawTransaction {
/**
* Specified the block whether is in active chain
*/
in_active_chain?: boolean
/**
* The transaction id
*/
txid: string
/**
* The transaction hash
*/
hash: string
/**
* The version
*/
version: number
/**
* The serialized transaction size
*/
size: number
/**
* The virtual transaction size
*/
vsize: number
/**
* The transaction's weight (between vsize*4-3 and vsize*3)
*/
weight: number
/**
* The lock time
*/
locktime: number
/**
* Vector input
*/
vin: Vin[]
/**
* Vector output
*/
vout: Vout[]
/**
* The serialized, hex-encoded for 'txid'
*/
hex: string
/**
* the block hash
*/
blockhash: string
/**
* Number of block confirmations
*/
confirmations: number
/**
* Same as 'blocktime'
*/
time: number
/**
* The block time in seconds since epoch (Jan 1 1970 GMT)
*/
blocktime: number
}
4 changes: 2 additions & 2 deletions website/docs/jellyfish/api/blockchain.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@ interface Transaction {
}

interface Vin {
coinbase: string
coinbase?: string
txid: string
vout: number
scriptSig: {
asm: string
hex: string
}
txinwitness: string[]
txinwitness?: string[]
sequence: string
}

Expand Down
59 changes: 59 additions & 0 deletions website/docs/jellyfish/api/rawtx.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,62 @@ interface rawtx {
): Promise<string>
}
```

## getRawTransaction

Get raw transaction data

```ts title="client.rawtx.getRawTransaction()"
interface rawtx {
getRawTransaction (txid: string, verbose: false): Promise<string>
getRawTransaction (txid: string, verbose: false, blockHash: string): Promise<string>
getRawTransaction (txid: string, verbose: true): Promise<RawTransaction>
getRawTransaction (txid: string, verbose: true, blockHash: string): Promise<RawTransaction>
getRawTransaction (txid: string, verbose?: boolean, blockHash?: string): Promise<string | RawTransaction>
}

interface RawTransaction {
in_active_chain?: boolean
txid: string
hash: string
version: number
size: number
vsize: number
weight: number
locktime: number
vin: Vin[]
vout: Vout[]
hex: string
blockhash: string
confirmations: number
time: number
blocktime: number
}

interface Vin {
coinbase?: string
txid: string
vout: number
scriptSig: {
asm: string
hex: string
}
txinwitness?: string[]
sequence: string
}

interface Vout {
value: BigNumber
n: number
scriptPubKey: ScriptPubKey
tokenId: number
}

interface ScriptPubKey {
asm: string
hex: string
type: string
reqSigs: number
addresses: string[]
}
```