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

feat(rawtx): add decodeRawTransaction function #1963

Merged
merged 8 commits into from
Jan 13, 2023
35 changes: 35 additions & 0 deletions docs/node/CATEGORIES/04-rawtx.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,41 @@ interface CreateRawTxOut {
}
```

## decodeRawTransaction

Return a JSON object representing the serialized, hex-encoded transaction.
If iswitness is not present, heuristic tests will be used in decoding.
If true, only witness deserialization will be tried.
If false, only non-witness deserialization will be tried.
This boolean should reflect whether the transaction has inputs
(e.g. fully valid, or on-chain transactions), if known by the caller.

```ts title="client.rawtx.decodeRawTransaction()"
interface rawtx {
decodeRawTransaction (
hexstring: string,
iswitness: boolean
): Promise<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
}
```

## signRawTransactionWithKey

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { MasterNodeRegTestContainer } from '@defichain/testcontainers/dist/index'
import { ContainerAdapterClient } from '../../container_adapter_client'
import { RpcApiError } from '../../../src'

describe('poolpair update', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong description

const container = new MasterNodeRegTestContainer()
DocteurPing marked this conversation as resolved.
Show resolved Hide resolved
const client = new ContainerAdapterClient(container)

beforeAll(async () => {
await container.start()
await container.waitForWalletCoinbaseMaturity()
DocteurPing marked this conversation as resolved.
Show resolved Hide resolved
})

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

it('should decode a witness transaction', async () => {
const encrawtx = '010000000001010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f50500000000000102616100000000'
const decrawtx = await client.rawtx.decodeRawTransaction(encrawtx, true)

expect(decrawtx).toStrictEqual({
txid: 'd006b4ece5d4adbd6f46b3a6f65f4a230caf6c44d8510e4340d0f26b7ceeb44a',
hash: '23f0c1f68f0a43bb434494933a5a0f6f9636261f33b036b7700d96e264aceeda',
version: 1,
size: 66,
vsize: 62,
weight: 246,
locktime: 0,
vin: [
expect.objectContaining({
txid: '000000000019d6689c085ae165831e934ff763ae46a2a6c17200000000000000',
vout: 0,
scriptSig:
expect.objectContaining({
asm: '',
hex: ''
}),
txinwitness: ['6161'],
sequence: 4294967295
})
],
vout: [
expect.objectContaining({
value: 1,
n: 0,
scriptPubKey:
expect.objectContaining({
asm: '',
hex: '',
type: 'nonstandard'
})
})
]
})
})

it('should throw an error when for decode as non-witness a witness transaction', async () => {
const encrawtx = '010000000001010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f50500000000000102616100000000'
await expect(client.rawtx.decodeRawTransaction(encrawtx, false)).rejects.toThrow(RpcApiError)
})

it('should decode a non-witness transaction', async () => {
const encrawtx = '01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000'
const decrawtx = await client.rawtx.decodeRawTransaction(encrawtx, true)

expect(decrawtx).toStrictEqual({
txid: 'd006b4ece5d4adbd6f46b3a6f65f4a230caf6c44d8510e4340d0f26b7ceeb44a',
hash: 'd006b4ece5d4adbd6f46b3a6f65f4a230caf6c44d8510e4340d0f26b7ceeb44a',
version: 1,
size: 60,
vsize: 60,
weight: 240,
locktime: 0,
vin: [
expect.objectContaining({
txid: '000000000019d6689c085ae165831e934ff763ae46a2a6c17200000000000000',
vout: 0,
scriptSig:
expect.objectContaining({
asm: '',
hex: ''
}),
sequence: 4294967295
})
],
vout: [
expect.objectContaining({
value: 1,
n: 0,
scriptPubKey:
expect.objectContaining({
asm: '',
hex: '',
type: 'nonstandard'
})
})
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be explicitly defined instead of expect.objectContaining()? What was the reason for using expect.objectContaining()?

})
})
})
18 changes: 18 additions & 0 deletions packages/jellyfish-api-core/src/category/rawtx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,24 @@ export class RawTx {
], 'number')
}

/**
* Return a JSON object representing the serialized, hex-encoded transaction.
* If iswitness is not present, heuristic tests will be used in decoding.
* If true, only witness deserialization will be tried.
* If false, only non-witness deserialization will be tried.
* This boolean should reflect whether the transaction has inputs
* (e.g. fully valid, or on-chain transactions), if known by the caller.
*
* @param {string} hexstring The transaction hex string
* @param {boolean} iswitness Whether the transaction hex is a serialized witness transaction.
*/
async decodeRawTransaction (
hexstring: string,
iswitness: boolean
): Promise<RawTransaction> {
return await this.client.call('decoderawtransaction', [hexstring, iswitness], 'number')
}

/**
* Sign inputs for raw transaction (serialized, hex-encoded), providing an array of base58-encoded private keys that
* will be the keys used to sign the transaction. An optional array of previous transaction outputs that this
Expand Down