For the contract platform where contract-related operations are called frequently, BaaS has optimized the JS SDK to make contract operations easier and more efficient. Before you use contract-related operations, you need to understand the ABI and bytecodes. For more information, see Cloud IDE smart contract development environment.
In the following description, the sample codeCreditManager
is from Solidity smart contract development.The JS SDK can be used with solc-js
, a Solidity compiler. For more information about solc-js, see Compile contracts using Solidity.
Create a smart contract instance
You can run the contract
code to create a smart contract instance. You can deploy and call this smart contract.
Request parameters
Parameter | Required | Type | Description |
name | true | string | The name of the target smart contract. The identity of this contract is the hash value of the contract name. |
abi | true | string | ABI-based string in the JSON format. |
vmType | false | string | The smart contract platform supports both Solidity and C++ contract languages. To initialize a contract instance written in C++, you can configure this parameter as |
Example 1
java script
const solc = require('@alipay/solc')
const contract = fs.readFileSync('. /CreditManager.sol', {encoding: 'ascii'})
// Set the second parameter to 1 to start compiling
const output = solc.compile(contract, 1)
const abi = JSON.parse(output.contracts[':CreditManager'].interface)
const bytecode = output.contracts[':CreditManager'].bytecode
// Add a timestamp to make sure that the identity of the contract name is unique
const contractName = 'contract'+Date.now()
// Initialize a smart contract instance
let myContract = chain.ctr.contract(contractName, abi)
Example 2
Use the Wasm bytecode to initialize a contract written in C++.
java script
const wasm_code = fs.readFileSync('./contract/base.wasm')
const abi = fs.readFileSync('./contract/base.abi')
const bytecode = '0x'+wasm_code.toString('hex')
// Add a timestamp to make sure that the identity of the contract name is unique
const contractName = 'contract'+Date.now()
// Initialize a smart contract instance
let myContract = chain.ctr.contract(contractName, abi, chain.WASM)
Deploy smart contracts
You can call the new
operation to deploy a smart contract.
Request parameters
Parameter | Required | Type | Description |
bytecode | true | string | The bytecode of the target smart contract. The bytecode is in the hexadecimal format without the “0x” prefix. |
data | true | object | Contains fields such as ‘from’ and ‘parameters’. |
Content of the data field
Field | Required | Type | Description |
from | true | string | The current account name to be configured. |
parameters | true | Array | If the smart contract contains an init() function and this function requires a list of parameters, this list can be passed in through the parameters field. |
Examples
java script
const solc = require('@alipay/solc')
const contract = fs.readFileSync('. /CreditManager.sol', {encoding: 'ascii'})
// Set the second parameter to 1 to start compiling
const output = solc.compile(contract, 1)
const abi = JSON.parse(output.contracts[':CreditManager'].interface)
const bytecode = output.contracts[':CreditManager'].bytecode
// Add a timestamp to make sure that the identity of the contract name is unique
const contractName = 'contract'+Date.now()
// Initialize a smart contract instance
let myContract = chain.ctr.contract(contractName, abi)
// Deploy a smart contract. Parameters required by the init() function can be passed in.
myContract.new(bytecode, {
from: 'Tester001',
// parameters: [param1, param2]
}, (err, contract, data) => {
console.log(data)
})
Call smart contracts
Use the name of the target contract method to call the contract method.
Request parameters
Parameter | Required | Type | Description |
parameters | false | Not specified | See the parameter list of a specific contract method. The number of parameters varies with the contract method. |
data | true | object | Contains the from field. |
Content of the data field
Field | Required | Type | Description |
from | true | string | The current account name to be configured. |
Example 1
Call a contract method when deploying the callback function of the contract:
java script
myContract.new(bytecode, {
from: 'Tester001',
// parameters: [param1, param2]
}, (err, contract, data) => {
console.log(data)
// Two parameters are required when calling the Issue contract method: the account identity and a numerical value.
myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
console.log('output is:', output)
})
})
Example 2
Call a contract method after the contract has been deployed. In case of multiple contracts, these contracts are called concurrently. If a call dependency exists, use the callback function.
java script
myContract.new(bytecode, {
from: 'Tester001',
// parameters: [param1, param2]
}, (err, contract, data) => {
console.log(data)
})
// Call the ‘Issue’ contract method
myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
console.log('output is:', output)
})
Update smart contracts
You can call the update
operation to update a contract that exists on a blockchain. Update smart contracts with caution. The update of contracts needs to be compatible with the data storage of the new contracts and the old contract. Under normal circumstances, we recommend that you do not use this update feature.
Request parameters
Parameter | Required | Type | Description |
bytecode | true | string | The bytecode of the target smart contract. The bytecode is in the hexadecimal format without the 0x prefix. |
data | true | object | An empty object. |
Examples
Call a contract method when deploying the callback function of the contract:
java script
myContract.update(bytecode, {}
, (err, contract, data) => {
console.log('contract update result:', data)
})
To update the contract, the compiled runtime
bytecode is required. This bytecode can be obtained directly by using the --bin-runtime
parameter of solc compiler, the Solidity compiler. It is the subset of the bytecode of the compiled --bin
parameter. The runtime
bytecode can also be obtained by deploying local contracts.
Examples
Obtain the runtime
bytecode by deploying a contract or using solc-js to update a contract:In JavaScript syntax, solc-js uses the --bin
parameter to compile a contract into bytecode by default. This bytecode cannot be used directly to update a contract. However, the runtime
bytecode obtained after deploying a contract can be used to update the contract.
It is only applicable to Solidity-0.4.24 version. For versions 0.6.4 and above, please use the Solidity compiler (solc) to obtain the runtime
bytecode.
Use solc-js to update smart contracts as follows:
Use solc-js to compile contract A
Deploy smart contract A
Call smart contract A
Modify the smart contract code to obtain smart contract A’
Use solc-js to compile smart contract A’
Deploy the smart contract A’ locally and obtain the
runtime
bytecode.Use the A’
runtime
bytecode to update smart contract A.Call smart contract A to verify the update status.
const solc = require('@alipay/solc')
const contract = fs.readFileSync('. /CreditManager.sol', {encoding: 'ascii'})
// Set the second parameter to 1 to start compiling
const output = solc.compile(contract, 1)
const abi = JSON.parse(output.contracts[':CreditManager'].interface)
const bytecode = output.contracts[':CreditManager'].bytecode
console.log('bytecode:', bytecode)
// Add a timestamp to make sure that the identity of the contract name is unique
let contractName = 'contract'+Date.now()
let myContract = chain.ctr.contract(contractName, abi)
// Use the bytecode compiled by solc-js to upgrade contracts
myContract.new(bytecode, {
from: 'Tester001',
}, (err, contract, data) => {
console.log('contract new:', data)
myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
console.log('output1 is:', output)
//Change the calculation logic of the contract named CreditManager.sol to obtain a contract named CreditManagerPro.sol. Note that the contract storage definition cannot be changed.
//In the Issue method: change `credit[account] += value;` to `credit[account] += value * 2;`
const contract_pro = fs.readFileSync('. /CreditManagerPro.sol', {encoding: 'ascii'})
// Set the second parameter to 1 to start compiling
const output_pro = solc.compile(contract_pro, 1)
const abi_pro = JSON.parse(output_pro.contracts[':CreditManager'].interface)
const bytecode_pro = output_pro.contracts[':CreditManager'].bytecode
myContract = chain.ctr.contract(contractName, abi_pro)
myContract.new(bytecode_pro, {
from: 'Tester001',
local: true, //Deploy a contract locally to obtain the `runtime` bytecode
block_number: 0 //Use a genesis block to deploy the contract locally to avoid conflict contract IDs.
}, (err, contract, data) => {
console.log('local contract new result:', data)
// Use the obtained `runtime` bytecode to upgrade the contract
myContract.update(data.receipt.output.replace('0x' + chain.EVM, ''), {
}, (err, contract, data) => {
console.log('contract update result:', data)
// Call the updated contract to issue credits
myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
console.log('output2 is:', output.toString())
// View the credits that have been issued to the target account. If the contract is updated successfully, the result is 300.
myContract.Query('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', { from: 'Tester001' }, (err, output, data) => {
console.log('output3 is:', output.toString())
})
})
})
})
})
})
Results:
...
contract update result: { msg_type: 63,
sequence: 7,
return_code: 0,
group_id: '0x0000000000000000000000000000000000000000',
receipt:
{ result: 0,
gas_used: 28610,
log_entry: [ [Object] ],
output: '' },
block_number: 86114,
transaction_index: 0,
api: 'QueryTransactionReceipt',
txhash:
'0x40a72b99ec64fca0e1cc5025920de086a2523b4761ea5020c0f43a5240dc754a' }
output2 is: true
output3 is: 300