Call contract functions
Every interaction with the blockchain involves the same basic steps:
- Connecting to an appropriate network endpoint for the development, test, or main network that you want to interact with.
- Providing a payload with your request that's properly formatted and contains all of the information required to complete any particular task.
- Signing the transaction with a valid key that has whatever permissions a specific task might require.
There's little difference between interacting with the blockchain directly through the API or through an abstraction layer such as the Kadena CLI or Kadena.js libraries. The difference is primarily a matter of preference about how you want to deliver the request. However, when you are calling functions, you might want to consider whether you want to make a local request or send the request to the blockchain.
In many cases, sending the request to the /local endpoint has advantages over sending the request to the network using the /send endpoint.
This guide provides examples for calling functions using both endpoints and using curl, the Kadena CLI, and the Kadena.js client libraries.
Using a YAML request and curl
If you want to call a function that modifies informatipon stored in the blockchain, you should make the transaction request using the /send endpoint.
If you want to call a function that reads information from the blockchain, you should make the transaction request using the /local endpoint.
For example, the free.vote-topics contract has three functions: init, vote, and getVotes.
The init and vote functions modify the votes table, so they should be called using the /send endpoint.
The getVotes function reads information from the table, so it can be called using the /local endpoint.
To call the init function using a curl command and /send endpoint:
-
Generate a random public and secret key pair and save them to a file.
pact --genkey > pistolas.yaml -
Construct the transaction using the YAML transaction request format for an unsigned transaction.
code: |-
(free.simple-vote.init)
data:
ks: {
keys: ["3bdb1d3c48a1bb5f072b067e265ce5d9a5eabf5e290128be4d2623dd559ca698"],
pred: "keys-all"
}
publicMeta:
chainId: "3"
sender: "pact-generated-key"
gasLimit: 63000
gasPrice: 0.00000001
ttl: 900
signers:
- public: 3bdb1d3c48a1bb5f072b067e265ce5d9a5eabf5e290128be4d2623dd559ca698
caps: []
networkId: "development"
type: exec -
Prepare the YAML transaction request to be signed.
pact --unsigned call-init-signers.yaml > tx-init.yaml -
Add a signature from your randomly-generated key pair and convert the request to a valid JSON object.
cat tx-init.yaml | pact add-sig pistolas.yaml > tx-signed-init.json -
Use
curlto connect to the/sendendpoint on thedevelopment,testnet04ormainnet01network.curl -X POST -H "Content-Type: application/json" -d "@tx-signed-init.json" http://localhost:8080/chainweb/0.0/development/chain/3/pact/api/v1/send
To call the getVotes function using a curl command and /local endpoint:
-
Construct the transaction using the YAML transaction request format for an unsigned transaction.
code: |-
(free.simple-vote.getVotes "A")
data:
publicMeta:
chainId: "3"
sender: "pact-generated-key"
gasLimit: 63000
gasPrice: 0.00000001
ttl: 900
networkId: "development"
type: exec -
Format the request and use
curlto connect to the/localendpoint on thedevelopment,testnet04ormainnet01network.pact --apireq simple-call.yaml --local | curl -X POST -H "Content-Type: application/json" \
--json @- http://localhost:8080/chainweb/0.0/development/chain/3/pact/api/v1/localThe command returns the result from the
/localendpoint. In this example, five votes have been recorded for topic "A".{"gas":18,"result":{"status":"success","data":5},"reqKey":"tg201pWYbHUdh3umkbKEeKyvRjWycBQlZSDcrCwasts",...}
Using kadena-cli commands
With the kadena-cli, you can construct a transaction template to call functions in smart contracts.
You can then customize the transactions to call the same function on different chains or different networks.
Depending on how you create your template, you can also use it to call different types of functions with interactive prompting for values or by setting command-line options.
To call a smart contract function using kadena-cli:
-
Create a
call-function.ktpltemplate file with the template variables for calling a function.call-function.yaml - YAML configuration for executing a smart contract function
code: |-
{{namespace.module.function args}}
data:
publicMeta:
chainId: "{{chain-id}}"
sender: "{{{account-name}}}"
gasLimit: 80300
gasPrice: 0.000001
ttl: 600
networkId: "{{network-id}}"
signers:
- public: "{{public-key}}"
caps: []
type: execFor convenience, you can move the
deploy-contract.ktpltemplate to the.kadena/transaction-templatesdirectory, so that the template is listed when you add transactions with interactive prompting. -
Create a new unsigned transaction using the
kadena tx addcommand and thecall-function.ktpltemplate and follow the prompts displayed to set the appropriate information.For example, the prompts and output for calling the
votefunction look similar to the following:? Which template do you want to use: call-function.ktpl
? File path of data to use for template .json or .yaml (optional):
? Template value namespace.module.function args: (free.vote-topics.vote "B")
? Template value chain-id: 3
? Template value account-name: k:58705e8699678bd15bbda2cf40fa236694895db614aafc82cf1c06c014ca963c
? Template value network-id: development
? Template value public-key: 58705e8699678bd15bbda2cf40fa236694895db614aafc82cf1c06c014ca963c
? Where do you want to save the output: test-vote-2 -
Sign the unsigned transaction using the
kadena tx signcommand and the transaction file name generated by thekadena tx addcommand. -
Send the signed transaction using the
kadena tx sendcommand and the signed transaction file name generated by thekadena tx signcommand.
You can use the same template to call the getVotes function and use kadena tx test to test the function call results.
kadena tx add
kadena tx sign
kadena tx test
Using the Kadena client library
If you're familiar with JavaScript or TypeScript, you can use the @kadena/client library to write scripts for common tasks.
The @kadena/client library implements a TypeScript-based API for interacting with smart contracts and Chainweb nodes.
The library provides functions that simplify building transactions with Pact commands and connecting to blockchain nodes.
You should note that creating the client connection is separate from using the Pact.builder function to construct transactions.
This example calls the greet function defined in the simplemodule that's been deployed in the free namespace on the testnet04 network.
import { Pact, createClient } from '@kadena/client';
const client = createClient();
const command = async (functionName: string) => {
const unsignedTransaction = Pact.builder
.execution(functionName)
.setMeta({
chainId: '1',
gasLimit: 2500,
})
.setNetworkId('testnet04')
.createTransaction();
try {
const res = await client.dirtyRead(unsignedTransaction);
if (res.result.status === 'success') {
console.log(res.result.data);
return res.result.data;
} else {
console.log('No data returned:', res);
}
} catch (error) {
console.error('Error with dirtyRead or data processing:', error);
}
try {
const res = await client.dirtyRead(unsignedTransaction);
if (res.result.status === 'success') {
console.log(res.result.data);
return res.result.data;
} else {
console.log('No data returned:', res);
}
} catch (error) {
console.error('Error with dirtyRead or data processing:', error);
}
};
command('(free.simplemodule.greet)').catch(console.error);