Skip to content
Draft
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
4 changes: 2 additions & 2 deletions .env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
NODE_URLS=http://localhost:8669,http://localhost:8679,http://localhost:8689
NODE_URLS=http://localhost:8669
PRIVATE_KEYS=
MNEMONIC="denial kitchen pet squirrel other broom bar gas better priority spoil cross"
NETWORK_TYPE=default-private
NETWORK_TYPE=solo

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I suppose we dont need to push this one, as it is just local config

7 changes: 7 additions & 0 deletions src/thor-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ class ThorClient {
)
}

// POST /transactions/call
async callTransaction(request, options) {
return this.performRequest(() =>
this.axios.post(`/transactions/call`, request, options),
)
}

// GET /blocks
async getBlock(revision, expanded, raw, options) {
let url = `/blocks/${revision}`
Expand Down
24 changes: 24 additions & 0 deletions src/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,30 @@ class ThorWallet {
}
}

buildCallTransaction = async (clauses, options) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

do we need to have specific method for that or we can enhance buildTransaction one ?

const bestBlockRef = await getBlockRef('best')
const genesisBlock = await Client.raw.getBlock('0')

if (!genesisBlock.success || !genesisBlock.body?.id) {
throw new Error('Could not get best block')
}

return {
id: "0x0000000000000000000000000000000000000000000000000000000000000000",
chainTag: parseInt(genesisBlock.body.id.slice(-2), 16),
blockRef: options?.blockRef ?? "0x0000000000000000",
expiration: 10,
clauses: clauses,
gasPriceCoef: 0,
gas: 1_000_000,
origin: options?.origin ?? null,
delegator: null,
nonce: options?.nonce ?? "0x0",
dependsOn: options?.dependsOn ?? null,
meta: null
}
}

signTransaction = async (transaction, delegationSignature) => {
const signingHash = transaction.getTransactionHash()
const signature = Secp256k1.sign(signingHash.bytes, this.privateKey)
Expand Down
120 changes: 120 additions & 0 deletions test/thorest-api/transactions/post-call-transaction.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { ThorWallet, generateAddress } from '../../../src/wallet'
import { TransactionDataDrivenFlow } from './setup/transaction-data-driven-flow'
import { successfulCallTxNoRevert, successfulCallTxRevert } from './setup/asserts'
import { SimpleCounter__factory as SimpleCounter } from '../../../typechain-types'

/**
* @group api
* @group transactions
*/
describe('Call transaction with clauses', function () {
const wallet = ThorWallet.withFunds()

let counter

beforeAll(async () => {
await wallet.waitForFunding()
counter = await wallet.deployContract(
SimpleCounter.bytecode,
SimpleCounter.abi,
)
})

it.e2eTest('should simulate vet transfer', 'all', async function () {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe we can add: mixed clauses (like contract call + vet transfer), tx delegation and not enough gas cases. As this should follow the same validation rules

const txBody = await wallet.buildCallTransaction([
{
to: await generateAddress(),
value: `0x${BigInt(5).toString(16)}`,
data: '0x',
},
{
to: await generateAddress(),
value: `0x${BigInt(6).toString(16)}`,
data: '0x',
},
], {
origin: wallet.address
})

const testPlan = {
postTxStep: {
tx: txBody,
expectedResult: successfulCallTxNoRevert,
},
}

const ddt = new TransactionDataDrivenFlow(testPlan)
await ddt.callTransaction()
})

it.e2eTest('should simulate function call', 'all', async function () {
const incrementCounter = '0x5b34b966'

const txBody = await wallet.buildCallTransaction([
{
value: "0x0",
data: incrementCounter,
to: counter.address,
},
], {
origin: wallet.address
})

const testPlan = {
postTxStep: {
tx: txBody,
expectedResult: successfulCallTxNoRevert,
},
}

const ddt = new TransactionDataDrivenFlow(testPlan)
await ddt.callTransaction()
})

it.e2eTest('should simulate reverted function call', 'all', async function () {
const incrementCounter = '0x5b34b966'

const txBody = await wallet.buildCallTransaction([
{
value: "0x0",
data: incrementCounter,
to: counter.address,
},
], {
origin: "0x000000000000000000000000000000000000dEaD"
})

const testPlan = {
postTxStep: {
tx: txBody,
expectedResult: successfulCallTxRevert,
},
}

const ddt = new TransactionDataDrivenFlow(testPlan)
await ddt.callTransaction()
})

it.e2eTest('should simulate contract deployment', 'all', async function () {

const txBody = await wallet.buildCallTransaction([
{
value: "0x0",
data: SimpleCounter.bytecode,
to: null,
},
], {
origin: wallet.address
})

const testPlan = {
postTxStep: {
tx: txBody,
expectedResult: successfulCallTxNoRevert,
},
}

const ddt = new TransactionDataDrivenFlow(testPlan)
await ddt.callTransaction()
})
})
16 changes: 16 additions & 0 deletions test/thorest-api/transactions/setup/asserts.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ const successfulPostTx = ({ success, body, httpCode }) => {
expect(body?.id).toBeDefined()
}

const successfulCallTxNoRevert = ({ success, body, httpCode }) => {
expect(success).toBeTrue()
expect(httpCode).toBe(200)
expect(body?.txID).toBeDefined()
expect(body?.vmError).toBe("")
}

const successfulCallTxRevert = ({ success, body, httpCode }) => {
expect(success).toBeTrue()
expect(httpCode).toBe(200)
expect(body?.txID).toBeDefined()
expect(body?.vmError).not.toBe("")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

wonder if we can add specific error we look for ? as this just checks it is not empty

}

const revertedPostTx = (
{ success, body, httpCode, httpMessage },
expectedErrorMsg,
Expand Down Expand Up @@ -121,6 +135,8 @@ const checkTransactionLogSuccess = (input, block, tx, transferClauses) => {

export {
successfulPostTx,
successfulCallTxNoRevert,
successfulCallTxRevert,
revertedPostTx,
compareSentTxWithCreatedTx,
checkDelegatedTransaction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ class TransactionDataDrivenFlow {
return sendTxResponse.body?.id
}

async callTransaction() {
const { tx, expectedResult } = this.plan.postTxStep
const callTxResponse = await Client.raw.callTransaction(tx)

expectedResult(callTxResponse)
return callTxResponse.body?.id
}

async getTransaction(txId) {
if (!this.plan.getTxStep) {
return
Expand Down
Loading