Skip to content

Commit

Permalink
Feature/add any account 2 account dftx (#181)
Browse files Browse the repository at this point in the history
* add account2utxo / utxo2account / account2account dftx

* fixed account-to-utxos types, add mapping for 2 more dftx

* added unit test

* remove invalid comment

* add test for TokenBalance and ScriptBalances as they are reused now

* split dftx_balance into balance and account

* remove log

* remove move log

* added new dftx composers and test

* delete duplicated test (refactored to different folder before merged)
  • Loading branch information
ivan-zynesis authored May 4, 2021
1 parent db95cd0 commit 3fb5abc
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { SmartBuffer } from 'smart-buffer'
import { AnyAccountToAccount, CAnyAccountToAccount } from '../../../../src/script/defi/dftx_account'
import { OP_CODES, toBuffer, toOPCodes } from '../../../../src/script'
import BigNumber from 'bignumber.js'
import { OP_DEFI_TX } from '../../../../src/script/defi'

it('should bi-directional buffer-object-buffer', () => {
const fixtures = [
'6a4c9d44665478610317a91457188c8b982570fe69ed6b99ce0489a9ea482023870100000000f28302000000000017a914d6e3de1c51f22e580944bb6a1647f1d22f0159c787010000000038a9d855020000001976a914016d3983837e91768af05e7fbbd956995c0ea37088ac010000000046030b00000000000117a914d6e3de1c51f22e580944bb6a1647f1d22f0159c78701000000007030e65502000000',
'6a4c5144665478610117a914fad0d4ab78412ec38e7a0b118e51e147e947e02d870100000000f6ba3e75020000000117a914fad0d4ab78412ec38e7a0b118e51e147e947e02d870100000000f6ba3e7502000000',
'6a4c5144665478610117a914f9038d01ce94d1b063d38fb580b1c85f927094a8870100000000b6d3ce1d000000000117a914fb61bf557ad5548558c054255026c858c8fefc83870100000000b6d3ce1d00000000',
'6a4c5144665478610117a9147983732a70b6bdc52f3a3cc1bd1a35017f69ecb887010300000000ca9a3b000000000117a914fb3cc0b39e5634578c914f132a1eba0ac9992feb87010300000000ca9a3b00000000'
]

fixtures.forEach(hex => {
const stack = toOPCodes(
SmartBuffer.fromBuffer(Buffer.from(hex, 'hex'))
)
const buffer = toBuffer(stack)
expect(buffer.toString('hex')).toBe(hex)
expect((stack[1] as OP_DEFI_TX).tx.type).toBe(0x61)
})
})

/**
* using accountToUtxos sample from DFI mainnet
* https://explorer.defichain.io/#/DFI/mainnet/tx/76409014d03f23b7b2522143003d98ee09341cf86300099e8e620d5dab4587e4
*/
const header = '6a4c9d4466547861' // OP_RETURN 44665478 61
const data = '0317a91457188c8b982570fe69ed6b99ce0489a9ea482023870100000000f28302000000000017a914d6e3de1c51f22e580944bb6a1647f1d22f0159c787010000000038a9d855020000001976a914016d3983837e91768af05e7fbbd956995c0ea37088ac010000000046030b00000000000117a914d6e3de1c51f22e580944bb6a1647f1d22f0159c78701000000007030e65502000000'
const anyAccountToAccount: AnyAccountToAccount = {
from: [
{
balances: [
{
amount: new BigNumber('0.0016485'), token: 0
}
],
script: {
stack: [
OP_CODES.OP_HASH160,
OP_CODES.OP_PUSHDATA_HEX_LE('57188c8b982570fe69ed6b99ce0489a9ea482023'),
OP_CODES.OP_EQUAL
]
}
},
{
balances: [
{
amount: new BigNumber('100.30197048'), token: 0
}
],
script: {
stack: [
OP_CODES.OP_HASH160,
OP_CODES.OP_PUSHDATA_HEX_LE('d6e3de1c51f22e580944bb6a1647f1d22f0159c7'),
OP_CODES.OP_EQUAL
]
}
},
{
balances: [
{
amount: new BigNumber('0.00721734'), token: 0
}
],
script: {
stack: [
OP_CODES.OP_DUP,
OP_CODES.OP_HASH160,
OP_CODES.OP_PUSHDATA_HEX_LE('016d3983837e91768af05e7fbbd956995c0ea370'),
OP_CODES.OP_EQUALVERIFY,
OP_CODES.OP_CHECKSIG
]
}
}
],
to: [{
balances: [
{
amount: new BigNumber('100.31083632'), token: 0
}
],
script: {
stack: [
OP_CODES.OP_HASH160,
OP_CODES.OP_PUSHDATA_HEX_LE('d6e3de1c51f22e580944bb6a1647f1d22f0159c7'),
OP_CODES.OP_EQUAL
]
}
}]
}

it('should craft dftx with OP_CODES._()', () => {
const stack = [
OP_CODES.OP_RETURN,
OP_CODES.DEFI_OP_ANY_ACCOUNT_TO_ACCOUNT(anyAccountToAccount)
]

const buffer = toBuffer(stack)
expect(buffer.toString('hex')).toBe(header + data)
})

describe('Composable', () => {
it('should compose from buffer to composable', () => {
const buffer = SmartBuffer.fromBuffer(Buffer.from(data, 'hex'))
const composable = new CAnyAccountToAccount(buffer)
expect(composable.toObject()).toEqual(anyAccountToAccount)
})

it('should compose from composable to buffer', () => {
const composable = new CAnyAccountToAccount(anyAccountToAccount)
const buffer = new SmartBuffer()
composable.toBuffer(buffer)

expect(buffer.toBuffer().toString('hex')).toEqual(data)
})
})
4 changes: 4 additions & 0 deletions packages/jellyfish-transaction/src/script/defi/dftx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { BufferComposer, ComposableBuffer } from '../../buffer/buffer_composer'
import {
AccountToAccount,
AccountToUtxos,
AnyAccountToAccount,
CAccountToAccount,
CAccountToUtxos,
CAnyAccountToAccount,
CUtxosToAccount,
UtxosToAccount
} from './dftx_account'
Expand Down Expand Up @@ -104,6 +106,8 @@ export class CDfTx extends ComposableBuffer<DfTx<any>> {
return compose<AccountToUtxos>(CAccountToUtxos.OP_NAME, d => new CAccountToUtxos(d))
case CAccountToAccount.OP_CODE:
return compose<AccountToAccount>(CAccountToAccount.OP_NAME, d => new CAccountToAccount(d))
case CAnyAccountToAccount.OP_CODE:
return compose<AnyAccountToAccount>(CAnyAccountToAccount.OP_NAME, d => new CAnyAccountToAccount(d))
default:
return compose<DeFiOpUnmapped>(CDeFiOpUnmapped.OP_NAME, d => new CDeFiOpUnmapped(d))
}
Expand Down
24 changes: 24 additions & 0 deletions packages/jellyfish-transaction/src/script/defi/dftx_account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,27 @@ export class CAccountToAccount extends ComposableBuffer<AccountToAccount> {
]
}
}

/**
* AccountToAccount DeFi Transaction
*/
export interface AnyAccountToAccount {
from: ScriptBalances[] // ------------| n = VarUInt{1-9 bytes}, + n bytes
to: ScriptBalances[] // --------------| n = VarUInt{1-9 bytes}, + n bytes
}

/**
* Composable UtxosToAccount, C stands for Composable.
* Immutable by design, bi-directional fromBuffer, toBuffer deep composer.
*/
export class CAnyAccountToAccount extends ComposableBuffer<AnyAccountToAccount> {
static OP_CODE = 0x61 // 'a'
static OP_NAME = 'DEFI_OP_ANY_ACCOUNT_TO_ACCOUNT'

composers (aa2a: AnyAccountToAccount): BufferComposer[] {
return [
ComposableBuffer.varUIntArray(() => aa2a.from, v => aa2a.from = v, v => new CScriptBalances(v)),
ComposableBuffer.varUIntArray(() => aa2a.to, v => aa2a.to = v, v => new CScriptBalances(v))
]
}
}
10 changes: 10 additions & 0 deletions packages/jellyfish-transaction/src/script/mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { CTokenMint, TokenMint } from './defi/dftx_token'
import {
AccountToAccount,
AccountToUtxos,
AnyAccountToAccount,
CAnyAccountToAccount,
CAccountToAccount,
CAccountToUtxos,
CUtxosToAccount,
Expand Down Expand Up @@ -114,6 +116,14 @@ export const OP_CODES = {
data: accountToAccount
})
},
DEFI_OP_ANY_ACCOUNT_TO_ACCOUNT: (anyAccountToAccount: AnyAccountToAccount): OP_DEFI_TX => {
return new OP_DEFI_TX({
signature: CDfTx.SIGNATURE,
type: CAnyAccountToAccount.OP_CODE,
name: CAnyAccountToAccount.OP_NAME,
data: anyAccountToAccount
})
},
OP_0: new OP_0(),
OP_FALSE: new OP_FALSE(),
/**
Expand Down

0 comments on commit 3fb5abc

Please sign in to comment.