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

txn-builder: remove-oracle #307

Merged
merged 19 commits into from
May 28, 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
10 changes: 8 additions & 2 deletions packages/jellyfish-transaction-builder/__tests__/test.utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Bech32, Elliptic, EllipticPair } from '@defichain/jellyfish-crypto'
import { Bech32, Elliptic, EllipticPair, dSHA256 } from '@defichain/jellyfish-crypto'
import { MasterNodeRegTestContainer } from '@defichain/testcontainers'
import { CTransactionSegWit, TransactionSegWit } from '@defichain/jellyfish-transaction'
import { CTransaction, CTransactionSegWit, Transaction, TransactionSegWit } from '@defichain/jellyfish-transaction'
import { SmartBuffer } from 'smart-buffer'
import { BigNumber } from 'bignumber.js'

Expand Down Expand Up @@ -59,6 +59,12 @@ export async function sendTransaction (container: MasterNodeRegTestContainer, tr
return tx.vout as TxOut[]
}

export function calculateTxid (transaction: Transaction): string {
const buffer = new SmartBuffer()
new CTransaction(transaction).toBuffer(buffer)
return dSHA256(buffer.toBuffer()).reverse().toString('hex')
}

export interface TxOut {
value: number
n: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,21 @@ describe('appoint oracle', () => {
expect(prevouts[0].value.toNumber()).toBeLessThan(10)
expect(prevouts[0].value.toNumber()).toBeGreaterThan(9.999)
})
})

it('should reject invalid appoint oracle arg - weightage over 100', async () => {
// Appoint Oracle
const script = await providers.elliptic.script()
await expect(builder.oracles.appointOracle({
script: script,
weightage: 200,
priceFeeds: [
{
token: 'TEST',
currency: 'USD'
}
]
}, script)).rejects.toThrow('Conversion input `appointOracle.weightage` must be above `0` and below `101`')
it('should reject invalid appoint oracle arg - weightage over 100', async () => {
// Appoint Oracle
const script = await providers.elliptic.script()
await expect(builder.oracles.appointOracle({
script: script,
weightage: 200,
priceFeeds: [
{
token: 'TEST',
currency: 'USD'
}
]
}, script)).rejects.toThrow('Conversion input `appointOracle.weightage` must be above `0` and below `101`')
})
})

// TODO(monstrobishi): test account state once RPC calls are in place
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { MasterNodeRegTestContainer, GenesisKeys } from '@defichain/testcontainers'
import { getProviders, MockProviders } from '../provider.mock'
import { P2WPKHTransactionBuilder } from '../../src'
import { calculateTxid, fundEllipticPair, sendTransaction } from '../test.utils'
import { WIF } from '@defichain/jellyfish-crypto'

const container = new MasterNodeRegTestContainer()
let providers: MockProviders
let builder: P2WPKHTransactionBuilder

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

providers = await getProviders(container)
providers.setEllipticPair(WIF.asEllipticPair(GenesisKeys[GenesisKeys.length - 1].owner.privKey))
builder = new P2WPKHTransactionBuilder(providers.fee, providers.prevout, providers.elliptic)

// Prep 1000 DFI Token for testing
await container.waitForWalletBalanceGTE(1001)
})

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

describe('remove oracle', () => {
beforeEach(async () => {
await container.waitForWalletBalanceGTE(1)
})

it('should appoint and then remove oracle', async () => {
// Fund 10 DFI UTXO
await fundEllipticPair(container, providers.ellipticPair, 10)
await providers.setupMocks() // required to move utxos

// Appoint Oracle
const script = await providers.elliptic.script()
const appointTxn = await builder.oracles.appointOracle({
script: script,
weightage: 1,
priceFeeds: [
{
token: 'TEST',
currency: 'USD'
}
]
}, script)

const txid = calculateTxid(appointTxn)
await sendTransaction(container, appointTxn)

// Remove Oracle
const removeTxn = await builder.oracles.removeOracle({
oracleId: txid
}, script)

// Ensure the created txn is correct.
const outs = await sendTransaction(container, removeTxn)
expect(outs[0].value).toStrictEqual(0)
expect(outs[1].value).toBeLessThan(10)
expect(outs[1].value).toBeGreaterThan(9.999)
expect(outs[1].scriptPubKey.addresses[0]).toStrictEqual(await providers.getAddress())

// Ensure you don't send all your balance away during appoint oracle
const prevouts = await providers.prevout.all()
expect(prevouts.length).toStrictEqual(1)
expect(prevouts[0].value.toNumber()).toBeLessThan(10)
expect(prevouts[0].value.toNumber()).toBeGreaterThan(9.999)
})
})

// TODO(monstrobishi): test account state once RPC calls are in place
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AppointOracle } from '@defichain/jellyfish-transaction/dist/script/defi/dftx_oracles'
import { AppointOracle, RemoveOracle } from '@defichain/jellyfish-transaction/dist/script/defi/dftx_oracles'
import { OP_CODES, Script, TransactionSegWit } from '@defichain/jellyfish-transaction'
import { P2WPKHTxnBuilder } from './txn_builder'
import { TxnBuilderError, TxnBuilderErrorType } from './txn_builder_error'
Expand All @@ -24,4 +24,18 @@ export class TxnBuilderOracles extends P2WPKHTxnBuilder {
changeScript
)
}

/**
* Removes an oracle. Currently requires Foundation Authorization.
*
* @param {RemoveOracle} removeOracle txn to create
* @param {Script} changeScript to send unspent to after deducting the (converted + fees)
* @returns {Promise<TransactionSegWit>}
*/
async removeOracle (removeOracle: RemoveOracle, changeScript: Script): Promise<TransactionSegWit> {
return await super.createDeFiTx(
OP_CODES.OP_DEFI_TX_REMOVE_ORACLE(removeOracle),
changeScript
)
}
}