Skip to content

Commit

Permalink
fix(contract call)!: accept arguments as JSON-encoded array
Browse files Browse the repository at this point in the history
  • Loading branch information
davidyuk committed Jan 28, 2022
1 parent b0a5cdc commit 201a7e0
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 62 deletions.
36 changes: 10 additions & 26 deletions src/actions/contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,11 @@ import { print, printTransaction, printUnderscored } from '../utils/print';
const readFile = (filename) => fs.readFileSync(path.resolve(process.cwd(), filename), 'utf-8');

// ## Function which compile your `source` code
export async function compile(file, options) {
const { json } = options;
const code = readFile(file);
if (!code) throw new Error('Contract file not found');

export async function compile(filename, options) {
const sdk = await initClient(options);

// Call `node` API which return `compiled code`
const contract = await sdk.compileContractAPI(code);
if (json) {
print({ bytecode: contract });
} else {
print(`Contract bytecode: ${contract}`);
}
const bytecode = await sdk.compileContractAPI(readFile(filename));
if (options.json) print({ bytecode });
else print(`Contract bytecode: ${bytecode}`);
}

function getContractParams({
Expand Down Expand Up @@ -143,8 +134,6 @@ export async function call(walletPath, fn, args, options) {
callStatic, json, top, ttl, gas, nonce,
} = options;
const sdk = await initClientByWalletFile(walletPath, options);

// Call static or call
const contract = await sdk.getContractInstance(getContractParams(options));
const callResult = await contract.call(fn, args, {
ttl: parseInt(ttl),
Expand All @@ -153,19 +142,14 @@ export async function call(walletPath, fn, args, options) {
callStatic,
top,
});
// The execution result, if successful, will be an FATE-encoded result
// value. Once type decoding will be implemented in the SDK, this value will
// not be a hexadecimal string, anymore.
if (json) print(callResult);
else {
if (callResult && callResult.hash) printTransaction(await sdk.tx(callResult.hash), json);
print('----------------------Transaction info-----------------------');
if (callResult.hash) printTransaction(await sdk.tx(callResult.hash), json);
print('----------------------Call info-----------------------');
printUnderscored('Contract address', contract.deployInfo.address);
printUnderscored('Gas price', callResult?.result?.gasPrice);
printUnderscored('Gas used', callResult?.result?.gasUsed);
printUnderscored('Return value (encoded)', callResult?.result?.returnValue);
// Decode result
const decoded = await callResult.decode();
printUnderscored('Return value (decoded)', decoded);
printUnderscored('Gas price', callResult.result?.gasPrice);
printUnderscored('Gas used', callResult.result?.gasUsed);
printUnderscored('Return value (encoded)', callResult.result?.returnValue);
printUnderscored('Return value (decoded)', callResult.decodedResult);
}
}
22 changes: 12 additions & 10 deletions src/commands/contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,26 +89,28 @@ export default () => {
// You can use this command to execute a function's of contract
//
// Example:
// `aecli contract call ./myWalletFile --password testpass sumFunc int 1 2 --descrPath ./contractDescriptorFile.json ` --> Using descriptor file
// `aecli contract call ./myWalletFile --password testpass sumFunc int 1 2 --contractAddress ct_1dsf35423fdsg345g4wsdf35ty54234235 ` --> Using contract address
// `aecli contract call ./myWalletFile --password testpass sumFunc '[1, 2]' --descrPath ./contractDescriptorFile.json ` --> Using descriptor file
// `aecli contract call ./myWalletFile --password testpass sumFunc '[1, 2]' --contractAddress ct_1dsf35423fdsg345g4wsdf35ty54234235 ` --> Using contract address
//
// Also you have ability to make `static` call using `--callStatic` flag
// Example:
// `aecli contract call ./myWalletFile --password testpass sumFunc int 1 2 --descrPath ./contractDescriptorFile.json --callStatic` --> Static call using descriptor
// `aecli contract call ./myWalletFile --password testpass sumFunc int 1 2 --contractAddress ct_1dsf35423fdsg345g4wsdf35ty54234235 --callStatic` --> Static call using contract address
// `aecli contract call ./myWalletFile --password testpass sumFunc '[1, 2]' --descrPath ./contractDescriptorFile.json --callStatic` --> Static call using descriptor
// `aecli contract call ./myWalletFile --password testpass sumFunc '[1, 2]' --contractAddress ct_1dsf35423fdsg345g4wsdf35ty54234235 --callStatic` --> Static call using contract address
// 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`
// Example: `aecli contract call ./myWalletFile --password testpass sumFunc '[1, 2]' --descrPath ./contractDescriptorFile.json --gas 2222222 --nonce 4 --ttl 1243`
program
.command('call <wallet_path> <fn> [args...]')
.command('call <wallet_path> <fn>')
.addArgument(callArgs)
.addOption(descriptorPathOption)
.option('--contractAddress [contractAddress]', 'Contract address to call')
.addOption(contractSourceFilenameOption)
.addOption(contractAciFilenameOption)
.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', GAS)
.option('-d --descrPath [descrPath]', 'Path to contract descriptor file')
.option('-s --callStatic', 'Call static', false)
.option('-s --callStatic', 'Call static')
.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)', SCHEMA.TX_TTL)
.option('-N, --nonce [nonce]', 'Override the nonce that the transaction is going to be sent with')
Expand Down
77 changes: 51 additions & 26 deletions test/contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('CLI Contract Module', () => {
const contractAciFile = 'testContractAci';
let deployDescriptorFile;
let sdk;
let cAddress;
let contractAddress;

before(async () => {
fs.writeFileSync(contractSourceFile, testContractSource);
Expand All @@ -52,11 +52,9 @@ describe('CLI Contract Module', () => {
if (fs.existsSync(contractAciFile)) fs.unlinkSync(contractAciFile);
});

it('Compile Contract', async () => {
const compiled = await sdk.contractCompile(testContractSource);
const compiledCLI = await executeContract(['compile', contractSourceFile]);
const bytecodeCLI = compiledCLI.split(':')[1].trim();
bytecodeCLI.should.be.equal(compiled.bytecode);
it('compiles contract', async () => {
const { bytecode } = await executeContract(['compile', contractSourceFile, '--json']);
expect(bytecode).to.satisfy((b) => b.startsWith('cb_'));
});

it('Deploy Contract', async () => {
Expand All @@ -65,36 +63,63 @@ describe('CLI Contract Module', () => {
const { result: { contractId }, transaction, descPath } = res;
deployDescriptorFile = descPath;
const [name, pref, add] = deployDescriptorFile.split('.');
cAddress = contractId;
contractAddress = contractId;
contractId.should.be.a('string');
transaction.should.be.a('string');
name.should.be.equal(contractSourceFile);
pref.should.be.equal('deploy');
add.should.be.equal((await sdk.address()).split('_')[1]);
});

it('Call Contract by descriptor', async () => {
const callResponse = await executeContract(['call', WALLET_NAME, '--password', 'test', '--json', '--descrPath', deployDescriptorFile, 'test', '1', '2']);
callResponse.result.returnValue.should.contain('cb_');
callResponse.decodedResult.should.be.equal('3');
});
describe('Call', () => {
it('calls contract', async () => {
const callResponse = await executeContract([
'call',
WALLET_NAME, '--password', 'test',
'--json',
'--descrPath', deployDescriptorFile,
'test', '[1, 2]',
]);
callResponse.result.returnValue.should.contain('cb_');
callResponse.decodedResult.should.be.equal('3');
});

it('Call Contract static by descriptor', async () => {
const callResponse = await executeContract(['call', WALLET_NAME, '--password', 'test', '--json', '--descrPath', deployDescriptorFile, 'test', '1', '2', '--callStatic']);
callResponse.result.returnValue.should.contain('cb_');
callResponse.decodedResult.should.equal('3');
});
it('calls contract static', async () => {
const callResponse = await executeContract([
'call',
WALLET_NAME, '--password', 'test',
'--json',
'--descrPath', deployDescriptorFile,
'test', '[1, 2]',
'--callStatic',
]);
callResponse.result.returnValue.should.contain('cb_');
callResponse.decodedResult.should.equal('3');
});

it('Call Contract by contract address', async () => {
const callResponse = await executeContract(['call', WALLET_NAME, '--password', 'test', '--json', '--contractAddress', cAddress, '--contractSource', contractSourceFile, 'test', '1', '2']);
callResponse.result.returnValue.should.contain('cb_');
callResponse.decodedResult.should.equal('3');
});
it('calls contract by contract source and address', async () => {
const callResponse = await executeContract([
'call',
WALLET_NAME, '--password', 'test',
'--json',
'--contractAddress', contractAddress,
'--contractSource', contractSourceFile,
'test', '[1, 2]',
]);
callResponse.decodedResult.should.equal('3');
});

it('Call Contract static by contract address', async () => {
const callResponse = await executeContract(['call', WALLET_NAME, '--password', 'test', '--json', '--contractAddress', cAddress, '--contractSource', contractSourceFile, 'test', '1', '2', '--callStatic']);
callResponse.result.returnValue.should.contain('cb_');
callResponse.decodedResult.should.equal('3');
it('calls contract by contract ACI and address', async () => {
const callResponse = await executeContract([
'call',
WALLET_NAME, '--password', 'test',
'--json',
'--contractAddress', contractAddress,
'--contractAci', contractAciFile,
'test', '[1, 2]',
]);
callResponse.decodedResult.should.equal('3');
});
});

describe('Calldata', () => {
Expand Down

0 comments on commit 201a7e0

Please sign in to comment.