Web3 SDK Reference¶
Last updated: 2026-06-28
Use Web3 integration when you need direct contract reads or writes. Most application traffic uses the hosted gateway or a router API; Web3 is for protocol-level tooling, dashboards, operators, wallets, and integrations that manage sessions or inspect task state directly.
Contract Flow¶
flowchart TB
App["Web3 app / operator tool"] --> Session["SessionV2"]
Session --> Data["SessionData"]
Session --> Queue["SessionQueueV2"]
Queue --> QueueData["SessionQueueData"]
Queue --> Validation["SessionQueueValidation"]
Session --> NodePool["NodePool / NodePoolData"]
Session --> Payment["SessionPayment / staking payment"]
Queue --> Results["Task results"]
Install¶
npm install ethers
Configure¶
Keep RPC URLs, private keys, ABIs, and deployment addresses outside frontend code.
export CORTENSOR_RPC_URL=""
export CORTENSOR_PRIVATE_KEY=""
export CORTENSOR_SESSION_V2_ADDRESS=""
export CORTENSOR_SESSION_QUEUE_V2_ADDRESS=""
Set these variables from the active network matrix and never ship private keys in frontend bundles.
import { ethers } from "ethers";
import sessionV2Abi from "./abi/SessionV2.json" assert { type: "json" };
import sessionQueueV2Abi from "./abi/SessionQueueV2.json" assert { type: "json" };
const provider = new ethers.JsonRpcProvider(process.env.CORTENSOR_RPC_URL);
const signer = new ethers.Wallet(process.env.CORTENSOR_PRIVATE_KEY, provider);
const session = new ethers.Contract(
process.env.CORTENSOR_SESSION_V2_ADDRESS,
sessionV2Abi,
signer
);
const sessionQueue = new ethers.Contract(
process.env.CORTENSOR_SESSION_QUEUE_V2_ADDRESS,
sessionQueueV2Abi,
signer
);
const network = await provider.getNetwork();
console.log({ chainId: Number(network.chainId) });
Address Table¶
Use the address table for the active network. At minimum, session integrations normally need:
| Module | Purpose |
|---|---|
ACL / IAM |
Access control and identity/role permissions. |
RuntimeV1 / NetworkData |
Runtime and network configuration reads. |
SessionV2 |
Creates, updates, deactivates, and submits work to sessions. |
SessionData |
Stores session records used by SessionV2. |
SessionQueueV2 |
Queues tasks and exposes task/result reads. |
SessionQueueData |
Stores task and task-result state. |
NodePool / NodePoolData / NodeSpec |
Selects nodes and exposes node capacity/model metadata. |
SessionPayment / SessionPaymentData / staking payment modules |
Handles per-session payment flows when enabled. |
PrivacySettingData |
Stores session/task privacy and allowlist settings where enabled. |
ValidatorStats / QuantitiveStats / QualitativeStats / QualityStatsData |
Validator and quality-stat state. |
Create A Session¶
The SessionV2.create ABI includes stakeToUse as the final argument.
function create(
string memory name,
string memory metadata,
address variableAddress,
uint256 minNumOfNodes,
uint256 maxNumOfNodes,
uint256 redundant,
uint256 numOfValidatorNodes,
uint256 mode,
bool reserveEphemeralNodes,
uint256 sla,
uint256 modelIdentifier,
uint256 reservePeriod,
uint256 maxTaskExecutionCount,
bool stakeToUse
) external;
Session mode values:
| Mode | Meaning |
|---|---|
0 |
Ephemeral node selection. |
1 |
Hybrid session. |
2 |
Dedicated session. |
Example:
const owner = await signer.getAddress();
const tx = await session.create(
"API completion session",
JSON.stringify({ purpose: "completion", environment: "testnet" }),
owner,
1, // minNumOfNodes
3, // maxNumOfNodes
1, // redundant
0, // numOfValidatorNodes
0, // mode: ephemeral
false, // reserveEphemeralNodes
0, // sla
0, // modelIdentifier
300, // reservePeriod
5, // maxTaskExecutionCount
false // stakeToUse
);
const receipt = await tx.wait();
console.log(receipt.hash);
Read session events from the receipt or listen for SessionCreated(uint256 sessionId, bytes32 sid, address owner, address[] miners).
Read Sessions¶
const sessionId = 0n;
const sessionRecord = await session.getSession(sessionId);
console.log(sessionRecord);
For owner-level session lists, use the active ABI for the deployed SessionV2 contract. Some deployments expose paginated reads such as getSessionsByAddressByPage(address,uint256,uint256) rather than an unpaginated helper.
Submit A Task¶
The SessionV2.submit ABI includes requestParams before clientReference.
function submit(
uint256 sessionId,
uint256 nodeType,
string calldata taskData,
uint256 promptType,
string calldata promptTemplate,
uint256[] calldata llmParams,
uint256[] calldata requestParams,
string calldata clientReference
) public;
nodeType must match the session mode. For a simple prompt, set promptType to the mode expected by the deployment and keep promptTemplate empty unless the session requires a template.
const taskData = JSON.stringify({
prompt: "Explain Cortensor in one paragraph.",
stream: false
});
const llmParams = [
160, // maxTokens
7, // temperature scale used by deployment adapter, if applicable
10, // topP scale used by deployment adapter, if applicable
0, // topK
0, // presencePenalty
0 // frequencyPenalty
];
const requestParams = [
120, // param0: execution/precommit timeout
180, // param1: overall timeout or deployment-specific request setting
0,
0,
0,
0
];
const tx = await session.submit(
0, // sessionId
0, // nodeType
taskData,
1, // promptType
"",
llmParams,
requestParams,
"web3-demo-001"
);
await tx.wait();
The contract emits TaskSubmitted(uint256 sessionId, uint256 taskId, string taskData, string clientReference).
Read Tasks And Results¶
const tasks = await sessionQueue.getTasksBySessionId(0);
console.log(tasks);
const [miners, results] = await sessionQueue.getTaskResults(0, 0);
console.log({ miners, results });
const [resultMiners, resultValues, resultHashes] =
await sessionQueue.getTaskResultsAndHashes(0, 0);
console.log({ resultMiners, resultValues, resultHashes });
Task results may be direct strings or off-chain URNs, depending on the route/session configuration.
Useful Events¶
| Contract | Event |
|---|---|
SessionV2 |
SessionCreated(uint256 sessionId, bytes32 sid, address owner, address[] miners) |
SessionV2 |
TaskSubmitted(uint256 sessionId, uint256 taskId, string taskData, string clientReference) |
SessionV2 |
SessionUpdated(uint256 indexed sessionId, address indexed updater, uint256 minNumOfNodes, uint256 maxNumOfNodes, uint256 redundant) |
SessionV2 |
SessionDeactivated(uint256 indexed sessionId, address indexed deactivator) |
SessionQueueV2 |
TaskQueued(uint256 sessionId, uint256 taskId, uint256 globalId, string taskData) |
SessionQueueV2 |
TaskAssigned(uint256 sessionId, uint256 taskId, address[] miners) |
SessionQueueV2 |
TaskAcked, TaskPrecommitted, TaskCommitted, TaskEnded lifecycle events |
sessionQueue.on("TaskEnded", (sessionId, taskId, miners, event) => {
console.log({
sessionId: sessionId.toString(),
taskId: taskId.toString(),
miners,
tx: event.log.transactionHash
});
});
Read Before Write¶
Before sending transactions:
- Confirm the RPC URL and chain ID.
- Confirm the contract address table belongs to that network.
- Confirm the ABI matches the deployed contract.
- Read the relevant state first.
- Estimate gas.
- Send the transaction.
- Wait for confirmation and record the transaction hash.
const gas = await session.submit.estimateGas(
0,
0,
taskData,
1,
"",
llmParams,
requestParams,
"web3-demo-001"
);
console.log({ gas: gas.toString() });
Security Notes¶
- Never embed private keys in frontend code.
- Use read-only providers for public dashboards.
- Keep write operations server-side, in wallets, or in controlled operator tooling.
- Validate chain ID before signing.
- Store the ABI and address table with the deployment version they belong to.
- Treat off-chain URNs as references; fetch and verify content according to the active privacy and storage policy.