From ae7b3e5612b5a99870ee0ae6d17b36732d6c3292 Mon Sep 17 00:00:00 2001 From: Mark Tan Date: Thu, 1 Dec 2022 10:42:23 +0800 Subject: [PATCH] Extend createDeFiTx --- .../__tests__/txn/txn_builder_p2wpkh.test.ts | 46 ++++++++++++++++++- .../src/txn/txn_builder.ts | 16 +++++-- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/packages/jellyfish-transaction-builder/__tests__/txn/txn_builder_p2wpkh.test.ts b/packages/jellyfish-transaction-builder/__tests__/txn/txn_builder_p2wpkh.test.ts index 6e0740cad4..e6d8da354a 100644 --- a/packages/jellyfish-transaction-builder/__tests__/txn/txn_builder_p2wpkh.test.ts +++ b/packages/jellyfish-transaction-builder/__tests__/txn/txn_builder_p2wpkh.test.ts @@ -1,9 +1,9 @@ import BigNumber from 'bignumber.js' import { MasterNodeRegTestContainer } from '@defichain/testcontainers' import { getProviders, MockProviders } from '../provider.mock' -import { P2WPKHTxnBuilder } from '../../src' +import { P2WPKHTxnBuilder, Prevout } from '../../src' import { fundEllipticPair } from '../test.utils' -import { CDfTx, DeFiOpUnmapped, OP_CODES, OP_DEFI_TX } from '@defichain/jellyfish-transaction' +import { CDfTx, DeFiOpUnmapped, OP_CODES, OP_DEFI_TX, Vin, Vout } from '@defichain/jellyfish-transaction' import { RegTest } from '@defichain/jellyfish-network' // P2WPKHTxnBuilder is abstract and not instantiable @@ -92,4 +92,46 @@ describe('createDeFiTx()', () => { expect(result.vout[1].value.gt(new BigNumber(99.999).minus(spendAmount))).toBeTruthy() expect(result.vout[1].value.lt(new BigNumber(100).minus(spendAmount))).toBeTruthy() }) + + it('should create DfTx stack correctly with custom vin and vout', async () => { + const script = await providers.elliptic.script() + + const collateralPrevout: Prevout = { + txid: '1111111122222222333333334444444455555555666666667777777788888888', + vout: 0, + script: script, + value: new BigNumber(15), + tokenId: 0 + } + const collateralVout: Vout = { + script: script, + value: new BigNumber(15), + tokenId: 0 + } + const collateralVin: Vin = { + txid: '1111111122222222333333334444444455555555666666667777777788888888', + index: 1, + script: { stack: [] }, + sequence: 0xffffffff + } + const customVinVout = { + prevout: collateralPrevout, + vin: collateralVin, + vout: collateralVout + } + + const result = await builder.createDeFiTx(dummyDfTx, script, undefined, [customVinVout]) + + expect(result.vin.length).toStrictEqual(8) + expect(result.vout.length).toStrictEqual(3) + + expect(result.vout[0].value).toStrictEqual(new BigNumber(0)) + expect(result.vout[1]).toStrictEqual(expect.objectContaining({ + value: new BigNumber(15), + script: script + })) + expect(result.vout[2].value.gt(99.999)).toBeTruthy() + expect(result.vout[2].value.lt(100)).toBeTruthy() + expect(result.vout[2].script).toStrictEqual(script) + }) }) diff --git a/packages/jellyfish-transaction-builder/src/txn/txn_builder.ts b/packages/jellyfish-transaction-builder/src/txn/txn_builder.ts index 90300bb787..3289e2e397 100644 --- a/packages/jellyfish-transaction-builder/src/txn/txn_builder.ts +++ b/packages/jellyfish-transaction-builder/src/txn/txn_builder.ts @@ -89,6 +89,8 @@ export abstract class P2WPKHTxnBuilder { * Craft a transaction with OP_DEFI_TX from the output of OP_CODES.OP_DEFI_TX_. * This is a helper method for creating custom defi transactions. * + * Optionally, allow for custom inputs with vin and vout. + * * As DeFi custom transaction will always require small amount of DFI, * collectPrevouts() is set to search for at least 0.001 DFI amount of prevout. * This will also evidently merge small prevout during the operation. @@ -98,15 +100,21 @@ export abstract class P2WPKHTxnBuilder { * @param {OP_DEFI_TX} opDeFiTx to create * @param {Script} changeScript to send unspent to after deducting the fees * @param {BigNumber} [outValue=0] for the opDeFiTx, usually always be 0. + * @param {Array<{ vin: Vin, vout: Vout, prevout: Prevout }>} [customVinVout = []] for custom vin and vout */ async createDeFiTx ( opDeFiTx: OP_DEFI_TX, changeScript: Script, - outValue: BigNumber = new BigNumber('0') + outValue: BigNumber = new BigNumber('0'), + customVinVout: Array<{ vin: Vin, vout: Vout, prevout: Prevout }> = [] ): Promise { const minFee = outValue.plus(0.001) // see JSDoc above const { prevouts, vin, total } = await this.collectPrevouts(minFee) + const customVins = customVinVout.map(({ vin }) => vin) + const customPrevouts = customVinVout.map(({ prevout }) => prevout) + const customVouts = customVinVout.map(({ vout }) => vout) + const deFiOut: Vout = { value: outValue, script: { @@ -123,15 +131,15 @@ export abstract class P2WPKHTxnBuilder { const txn: Transaction = { version: DeFiTransactionConstants.Version, - vin: vin, - vout: [deFiOut, change], + vin: [...vin, ...customVins], + vout: [deFiOut, ...customVouts, change], lockTime: 0x00000000 } const fee = await this.calculateFee(txn) change.value = total.minus(outValue).minus(fee) - return await this.sign(txn, prevouts) + return await this.sign(txn, [...prevouts, ...customPrevouts]) } /**