Smart Contracts Reference
ULedger smart contracts are written in WebAssembly Text Format (.wat) and executed by the ULVM — ULedger's own WebAssembly virtual machine. Every deploy, upgrade, and invocation is a signed transaction on the blockchain.
Deploy Contract
Deploys a .wat smart contract to a blockchain. The request is multipart — the contract file is uploaded alongside the transaction parameters. The wallet must already be registered on the target blockchain.
Request
POST /api/v1/smartcontracts/deploy
Headers
X-AccessKey— Your entity access keyContent-Type: multipart/form-data
Form fields
walletAddress(required) — The wallet deploying the contractblockchainId(required) — Target blockchain IDfrom(required) — Sender address (usually same aswalletAddress)file(required) — The.watcontract filepayload— Optional deployment label or notepassphrase— Only if the wallet was created with one
Response
Returns the transaction result on success. The contract address is derived from the transaction ID — retrieve the block at the current height to find it.
- cURL
- TypeScript
curl -X POST \
'https://your-tms-url/api/v1/smartcontracts/deploy' \
-H 'X-AccessKey: your-entity-access-key' \
-F 'walletAddress=54677be320b0bd704a99ee1f3d60c7309dfdee4810b1846d7b66ddbe0e84f585' \
-F 'blockchainId=08c28f29a62819120958984b761ddf8ccb45951612731409873994958fd150a2' \
-F 'from=54677be320b0bd704a99ee1f3d60c7309dfdee4810b1846d7b66ddbe0e84f585' \
-F 'payload=my first contract' \
-F 'file=@./contract.wat'
import fs from 'fs';
import FormData from 'form-data';
const form = new FormData();
form.append('walletAddress', '54677be320b0bd704a99ee1f3d60c7309dfdee4810b1846d7b66ddbe0e84f585');
form.append('blockchainId', '08c28f29a62819120958984b761ddf8ccb45951612731409873994958fd150a2');
form.append('from', '54677be320b0bd704a99ee1f3d60c7309dfdee4810b1846d7b66ddbe0e84f585');
form.append('payload', 'my first contract');
form.append('file', fs.createReadStream('./contract.wat'));
const res = await fetch('https://your-tms-url/api/v1/smartcontracts/deploy', {
method: 'POST',
headers: {
'X-AccessKey': 'your-entity-access-key',
...form.getHeaders(),
},
body: form,
});
const data = await res.json();
console.log(data);
Upgrade Contract
Upgrades an existing deployed contract with a new .wat file. The contract address stays the same — only the code changes. Previous versions are preserved on-chain.
Request
POST /api/v1/smartcontracts/upgrade
Headers
X-AccessKey— Your entity access keyContent-Type: multipart/form-data
Form fields
walletAddress(required) — The wallet performing the upgradeblockchainId(required) — Target blockchain IDcontractAddress(required) — Address of the contract to upgradefile(required) — The new.watcontract fileupgradeReason— A note describing what changedpassphrase— Only if the wallet was created with one
Response
Returns the upgrade transaction result on success.
- cURL
- TypeScript
curl -X POST \
'https://your-tms-url/api/v1/smartcontracts/upgrade' \
-H 'X-AccessKey: your-entity-access-key' \
-F 'walletAddress=54677be320b0bd704a99ee1f3d60c7309dfdee4810b1846d7b66ddbe0e84f585' \
-F 'blockchainId=08c28f29a62819120958984b761ddf8ccb45951612731409873994958fd150a2' \
-F 'contractAddress=your-contract-address' \
-F 'upgradeReason=fixed a bug in the main function' \
-F 'file=@./contract-v2.wat'
import fs from 'fs';
import FormData from 'form-data';
const form = new FormData();
form.append('walletAddress', '54677be320b0bd704a99ee1f3d60c7309dfdee4810b1846d7b66ddbe0e84f585');
form.append('blockchainId', '08c28f29a62819120958984b761ddf8ccb45951612731409873994958fd150a2');
form.append('contractAddress', 'your-contract-address');
form.append('upgradeReason', 'fixed a bug in the main function');
form.append('file', fs.createReadStream('./contract-v2.wat'));
const res = await fetch('https://your-tms-url/api/v1/smartcontracts/upgrade', {
method: 'POST',
headers: {
'X-AccessKey': 'your-entity-access-key',
...form.getHeaders(),
},
body: form,
});
const data = await res.json();
console.log(data);
Invoke Contract
Calls a function on a deployed smart contract. Arguments are typed — the ULVM needs to know the type of each argument to encode it correctly before execution.
Request
POST /api/v1/smartcontracts/invoke/payload
Headers
X-AccessKey— Your entity access keyContent-Type: application/json
Body
walletAddress— The wallet signing the invocationblockchainId— Target blockchain IDcontractAddress(required) — The deployed contract addressfunctionName(required) — The exported function to callarguments— Array of typed arguments. Each entry has atypeandvalue. Supported types:int32,int64,float32,float64,bool,string,bytesgasLimit— Max gas for execution. Use0for no limit.passphrase— Only if the wallet was created with one
Response
Returns the invocation transaction result including any output from the contract function.
Example response
{
"transactionId": "a1b2c3...",
"status": "confirmed",
"output": "42",
"gasUsed": 100
}
- cURL
- TypeScript
curl -X POST \
'https://your-tms-url/api/v1/smartcontracts/invoke/payload' \
-H 'X-AccessKey: your-entity-access-key' \
-H 'Content-Type: application/json' \
-d '{
"walletAddress": "54677be320b0bd704a99ee1f3d60c7309dfdee4810b1846d7b66ddbe0e84f585",
"blockchainId": "08c28f29a62819120958984b761ddf8ccb45951612731409873994958fd150a2",
"contractAddress": "your-contract-address",
"functionName": "main",
"arguments": [
{ "type": "string", "value": "hello" },
{ "type": "int32", "value": "42" }
],
"gasLimit": 0
}'
const res = await fetch('https://your-tms-url/api/v1/smartcontracts/invoke/payload', {
method: 'POST',
headers: {
'X-AccessKey': 'your-entity-access-key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
walletAddress: '54677be320b0bd704a99ee1f3d60c7309dfdee4810b1846d7b66ddbe0e84f585',
blockchainId: '08c28f29a62819120958984b761ddf8ccb45951612731409873994958fd150a2',
contractAddress: 'your-contract-address',
functionName: 'main',
arguments: [
{ type: 'string', value: 'hello' },
{ type: 'int32', value: '42' },
],
gasLimit: 0,
}),
});
const data = await res.json();
console.log('Output:', data.output);