Skip to content

Commit

Permalink
feat(Contract): Add test for calling contract using cointract descrip…
Browse files Browse the repository at this point in the history
…tor file or source code and address

Adjust `call` command with additional options like `backend`, `fee, ttl, nonce`, `waitMined`
  • Loading branch information
nduchak committed Apr 14, 2020
1 parent ed48a83 commit 3f77138
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 45 deletions.
9 changes: 7 additions & 2 deletions bin/aecli-contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,22 @@ program
// You can preset gas, nonce and ttl for that call. If not set use default.
// Example: `aecli contract call ./myWalletFile --password tstpass sumFunc int 1 2 --descrPath ./contractDescriptorFile.json --gas 2222222 --nonce 4 --ttl 1243`
program
.command('call <wallet_path> <fn> <return_type> [args...]')
.command('call <wallet_path> <fn> [args...]')
.option('-W, --no-waitMined', 'Force waiting until transaction will be mined')
.option('--networkId [networkId]', 'Network id (default: ae_mainnet)')
.option('-P, --password [password]', 'Wallet Password')
.option('-G --gas [gas]', 'Amount of gas to call the contract', utils.constant.GAS)
.option('-d --descrPath [descrPath]', 'Path to contract descriptor file')
.option('--backend [backend]', 'Compiler backend("fate" | "aevm")', utils.constant.COMPILER_BACKEND)
.option('-s --callStatic', 'Call static', false)
.option('-t --topHash', 'Hash of block to make call')
.option('--contractAddress [contractAddress]', 'Contract address to call')
.option('--contractSource [contractSource]', 'Contract source code')
.option('-F, --fee [fee]', 'Spend transaction fee.')
.option('-T, --ttl [ttl]', 'Validity of the spend transaction in number of blocks (default forever)', utils.constant.TX_TTL)
.option('-N, --nonce [nonce]', 'Override the nonce that the transaction is going to be sent with')
.description('Execute a function of the contract')
.action(async (walletPath, fn, returnType, args, ...arguments) => await Contract.call(walletPath, fn, returnType, args, utils.cli.getCmdFromArguments(arguments)))
.action(async (walletPath, fn, args, ...arguments) => await Contract.call(walletPath, fn, args, utils.cli.getCmdFromArguments(arguments)))

//
// ## Initialize `deploy` command
Expand Down
35 changes: 16 additions & 19 deletions bin/commands/contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,12 @@ async function deploy (walletPath, contractPath, init = [], options) {
// block as well, together with the contract's bytecode.
const deployDescriptor = await contract.deploy([...init], { fee, ttl, nonce, gas, gasPrince, backend })
// Write contractDescriptor to file
const descPath = `${R.last(contractPath.split('/'))}.deploy.${deployDescriptor.deployInfo.owner.slice(3)}.json`
const descPath = `${R.last(contractPath.split('/'))}.deploy.${deployDescriptor.owner.slice(3)}.json`
const contractDescriptor = R.merge({
descPath,
source: contractFile,
bytecode: contract.compiled,
}, deployDescriptor.deployInfo)
}, contract.deployInfo)

writeFile(
descPath,
Expand All @@ -168,8 +168,8 @@ async function deploy (walletPath, contractPath, init = [], options) {

// Log contract descriptor
json
? print({ descPath, ...deployDescriptor.deployInfo })
: logContractDescriptor(contractDescriptor, 'Contract was successfully deployed', json)
? print(contractDescriptor)
: logContractDescriptor(contractDescriptor, 'Contract was successfully deployed')
}
)
} catch (e) {
Expand All @@ -179,9 +179,9 @@ async function deploy (walletPath, contractPath, init = [], options) {
}

// ## Function which `call` contract
async function call (walletPath, fn, returnType, args, options) {
async function call (walletPath, fn, args, options) {
const { callStatic, json, top } = options
if (!fn || !returnType) {
if (!fn) {
program.outputHelp()
process.exit(1)
}
Expand All @@ -195,19 +195,16 @@ async function call (walletPath, fn, returnType, args, options) {
// Call static or call
const contract = await client.getContractInstance(params.source, { contractAddress: params.address })
const callResult = await contract.call(fn, args, { ...params.options, callStatic, top })
// The execution result, if successful, will be an AEVM-encoded result
// value. Once type decoding will be implemented in the SDK, this value will
// not be a hexadecimal string, anymore.
if (callResult && callResult.hash) printTransaction(await client.tx(callResult.hash), json)
print('----------------------Transaction info-----------------------')
printUnderscored('Contract address', params.address)
printUnderscored('Gas price', R.path(['result', 'gasPrice'])(callResult))
printUnderscored('Gas used', R.path(['result', 'gasUsed'])(callResult))
printUnderscored('Return value (encoded)', R.path(['result', 'returnValue'])(callResult))
// Decode result
console.log(callResult)
const decoded = await callResult.decode()
printUnderscored('Return value (decoded)', decoded)
if (json) {
print(callResult)
} else {
print('----------------------Transaction info-----------------------')
printUnderscored('Contract address', params.address)
printUnderscored('Gas price', R.path(['result', 'gasPrice'])(callResult))
printUnderscored('Gas used', R.path(['result', 'gasUsed'])(callResult))
printUnderscored('Return value (encoded)', R.path(['result', 'returnValue'])(callResult))
printUnderscored('Return value (decoded)', callResult.decodedRes)
}
}
)
} catch (e) {
Expand Down
46 changes: 22 additions & 24 deletions test/cli/contract.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@
import fs from 'fs'
import { before, describe, it } from 'mocha'

import { configure, plan, ready, WALLET_NAME, execute as exec, parseBlock } from './index'
import KEY_PAIR from '@aeternity/aepp-sdk/es/account/memory';
import { configure, plan, ready, WALLET_NAME, execute as exec, parseBlock, KEY_PAIR } from './index'

// CONTRACT SOURCE
const testContract = `contract Identity =
entrypoint main(x : int) = x
entrypoint main(x : int, y: int) = x + y
`

const encodedNumber3 = 'cb_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPJ9AW0'
Expand Down Expand Up @@ -86,43 +85,42 @@ describe('CLI Contract Module', function () {
fs.writeFileSync(contractFile, testContract)

// Deploy contract
const res = await exec(['contract', 'deploy', WALLET_NAME, '--password', 'test', contractFile])
const { contract_address, transaction_hash, deploy_descriptor } = (parseBlock(res))
deployDescriptor = deploy_descriptor
const [name, pref, address] = deployDescriptor.split('.')
cAddress = contract_address
contract_address.should.be.ok
transaction_hash.should.be.ok
const res = JSON.parse(await exec(['contract', 'deploy', WALLET_NAME, '--password', 'test', contractFile, '--json']))
const { result: { contractId }, transaction, descPath } = res
deployDescriptor = descPath
const [name, pref, add] = deployDescriptor.split('.')
cAddress = contractId
contractId.should.be.ok
transaction.should.be.ok
name.should.equal(contractFile)
pref.should.equal('deploy')
address.should.equal(KEY_PAIR.publicKey.split('_')[1])
add.should.equal(KEY_PAIR.publicKey.split('_')[1])
})

it('Call Contract by descriptor', async () => {
// Call contract
const callResponse = (parseBlock(await exec(['contract', 'call', WALLET_NAME, '--password', 'test', '--descrPath', deployDescriptor, 'main', 'int', '1', '2'])))
const isValid = callResponse['return_value_(encoded)'].indexOf('cb_') !== -1
const callResponse = JSON.parse(await exec(['contract', 'call', WALLET_NAME, '--password', 'test', '--json', '--descrPath', deployDescriptor, 'main', '1', '2']))
const isValid = callResponse.result.returnValue.indexOf('cb_') !== -1
isValid.should.be.equal(true)
callResponse['return_value_(decoded)'].should.equal('3')
callResponse.decodedResult.should.equal(3)
})
it('Call Contract static by descriptor', async () => {
// Call contract
const callResponse = (parseBlock(await exec(['contract', 'call', WALLET_NAME, '--password', 'test', '--descrPath', deployDescriptor, 'main', 'int', '1', '2', '--callStatic'])))
const isValid = callResponse['return_value_(encoded)'].indexOf('cb_') !== -1
const callResponse = (JSON.parse(await exec(['contract', 'call', WALLET_NAME, '--password', 'test', '--json', '--descrPath', deployDescriptor, 'main', '1', '2', '--callStatic'])))
const isValid = callResponse.result.returnValue.indexOf('cb_') !== -1
isValid.should.be.equal(true)
callResponse['return_value_(decoded)'].should.equal('3')
callResponse.decodedResult.should.equal(3)
})
it('Call Contract by contract address', async () => {
const callResponse = (parseBlock(await exec(['contract', 'call', WALLET_NAME, '--password', 'test', '--contractAddress', cAddress, '--contractSource', contractFile, 'main', 'int', '1', '2'])))
const isValid = callResponse['return_value_(encoded)'].indexOf('cb_') !== -1
const callResponse = (JSON.parse(await exec(['contract', 'call', WALLET_NAME, '--password', 'test', '--json', '--contractAddress', cAddress, '--contractSource', contractFile, 'main', '1', '2'])))
const isValid = callResponse.result.returnValue.indexOf('cb_') !== -1
isValid.should.be.equal(true)
callResponse['return_value_(decoded)'].should.equal('3')
callResponse.decodedResult.should.equal(3)
})
it('Call Contract static by contract address', async () => {
const callResponse = (parseBlock(await exec(['contract', 'call', WALLET_NAME, '--password', 'test', '--contractAddress', cAddress, '--contractSource', contractFile, 'main', 'int', '1', '2', '--callStatic'])))
const isValid = callResponse['return_value_(encoded)'].indexOf('cb_') !== -1

const callResponse = (JSON.parse(await exec(['contract', 'call', WALLET_NAME, '--password', 'test', '--json', '--contractAddress', cAddress, '--contractSource', contractFile, 'main', '1', '2', '--callStatic'])))
const isValid = callResponse.result.returnValue.indexOf('cb_') !== -1
isValid.should.be.equal(true)
callResponse['return_value_(decoded)'].should.equal('3')
callResponse.decodedResult.should.equal(3)
})
})

0 comments on commit 3f77138

Please sign in to comment.