author_submitAndWatchExtrinsic - Bittensor RPC Method
Submit an extrinsic and subscribe to lifecycle status updates on Bittensor. Track transactions from pool admission through finalization with real-time WebSocket events for decentralized AI inference, subnet-specific AI models, TAO staking, and cross-subnet AI collaboration.
Submits a signed extrinsic to Bittensor and returns a subscription that emits status updates as the transaction progresses through the lifecycle -- from entering the transaction pool, through block inclusion, to finalization. This is a WebSocket-only subscription method.
Why Bittensor? Build on the decentralized machine intelligence network built around subnets, TAO staking, and validator-miner coordination with Yuma Consensus, subnet-based specialization, dual Substrate and EVM surfaces, and onchain incentive coordination.
When to Use This Method
author_submitAndWatchExtrinsic is essential for AI/ML developers, subnet operators, and teams building decentralized machine learning applications:
- Transaction Lifecycle Tracking -- Receive real-time status events as your extrinsic moves from the pool into a block and reaches finality on Bittensor
- Confirmation Waiting -- Block until a transaction reaches a specific finality level (e.g.,
inBlockorfinalized) before proceeding with dependent logic - Error Detection -- Detect dropped, invalid, or usurped transactions immediately instead of polling, critical for decentralized AI inference, subnet-specific AI models, TAO staking, and cross-subnet AI collaboration
- User-Facing Feedback -- Power progress indicators and toast notifications in dApp interfaces with granular status updates
Code Examples
# author_submitAndWatchExtrinsic requires WebSocket.
# Use websocat to send the subscription request:
echo '{
"jsonrpc": "2.0",
"method": "author_submitAndWatchExtrinsic",
"params": ["0x2d028400d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01..."],
"id": 1
}' | websocat wss://api-bittensor-mainnet.n.dwellir.com/YOUR_API_KEY
# The connection stays open and prints status update messages as they arrive.
# For a fire-and-forget HTTP approach, use author_submitExtrinsic instead:
curl -X POST https://api-bittensor-mainnet.n.dwellir.com/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "author_submitExtrinsic",
"params": ["0x2d028400..."],
"id": 1
}'Common Use Cases
1. Transaction Confirmation with Timeout
Wait for finalization with a configurable timeout to avoid hanging indefinitely:
import { ApiPromise, WsProvider, Keyring } from '@polkadot/api';
async function sendAndConfirm(api, sender, tx, timeoutMs = 120000) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error('Transaction confirmation timed out'));
}, timeoutMs);
tx.signAndSend(sender, ({ status, dispatchError, events }) => {
if (dispatchError) {
clearTimeout(timer);
if (dispatchError.isModule) {
const { docs, name, section } = api.registry.findMetaError(dispatchError.asModule);
reject(new Error(`${section}.${name}: ${docs.join(' ')}`));
} else {
reject(new Error(dispatchError.toString()));
}
}
if (status.isFinalized) {
clearTimeout(timer);
resolve({
blockHash: status.asFinalized.toHex(),
events: events.map((e) => `${e.event.section}.${e.event.method}`)
});
}
}).catch((err) => {
clearTimeout(timer);
reject(err);
});
});
}2. Batch Transaction Pipeline
Submit multiple extrinsics sequentially and track each one through finalization:
async function submitBatch(api, sender, calls) {
const results = [];
let nonce = (await api.rpc.system.accountNextIndex(sender.address)).toNumber();
for (const call of calls) {
const result = await new Promise((resolve, reject) => {
call.signAndSend(sender, { nonce: nonce++ }, ({ status, dispatchError }) => {
if (dispatchError) {
const decoded = dispatchError.isModule
? api.registry.findMetaError(dispatchError.asModule)
: { name: dispatchError.toString() };
reject(new Error(`Dispatch error: ${decoded.name}`));
}
if (status.isFinalized) {
resolve({ blockHash: status.asFinalized.toHex(), nonce: nonce - 1 });
}
});
});
results.push(result);
console.log(`Tx nonce=${result.nonce} finalized in ${result.blockHash}`);
}
return results;
}3. Reorg-Aware Event Handling
Handle block retractions gracefully, re-evaluating transaction inclusion after reorganizations:
async function sendWithReorgHandling(api, sender, tx) {
let includedBlock = null;
return new Promise((resolve, reject) => {
tx.signAndSend(sender, ({ status, events }) => {
if (status.isReady) {
console.log('Transaction in ready queue');
}
if (status.isInBlock) {
includedBlock = status.asInBlock.toHex();
console.log(`Included in block: ${includedBlock}`);
}
if (status.isRetracted) {
console.warn(`Block retracted: ${status.asRetracted.toHex()} -- waiting for re-inclusion`);
includedBlock = null;
}
if (status.isFinalized) {
console.log(`Finalized in block: ${status.asFinalized.toHex()}`);
resolve({ finalized: status.asFinalized.toHex(), events });
}
if (status.isDropped || status.isInvalid) {
reject(new Error(`Transaction ${status.type}`));
}
if (status.isUsurped) {
reject(new Error(`Transaction usurped by ${status.asUsurped.toHex()}`));
}
});
});
}Status Flow
┌─────────────────────────────────────┐
│ future (nonce gap) │
└──────────────┬──────────────────────┘
│ nonce becomes current
▼
submit ──► ready ──► broadcast ──► inBlock ──► finalized ✓
│ │
├──► dropped ✗ ├──► retracted (reorg) ──► inBlock (re-included)
├──► invalid ✗ └──► finalityTimeout ✗
└──► usurped ✗Error Handling
Common errors and solutions:
| Error Code | Description | Solution |
|---|---|---|
| 1002 | Verification error | The extrinsic has an invalid signature, wrong format, or failed validation -- re-sign and resubmit |
| 1010 | Invalid transaction | Bad nonce, insufficient balance, or the call is not permitted -- check account state with system_accountNextIndex |
| 1014 | Priority too low | Transaction pool rejected the extrinsic because a higher-priority transaction exists for the same nonce -- increase tip or wait |
| -32603 | Internal error | Node encountered an unexpected error -- retry after delay |
| Connection closed | WebSocket dropped | The subscription is lost -- reconnect and check author_pendingExtrinsics or re-query chain state to determine transaction outcome |
Related Methods
author_submitExtrinsic-- Submit an extrinsic without subscribing to status updates (fire-and-forget)system_accountNextIndex-- Get the next valid nonce for an account, including pending pool transactionsauthor_pendingExtrinsics-- List all extrinsics currently in the transaction poolpayment_queryInfo-- Estimate the fee for an extrinsic before submissionchain_getFinalizedHead-- Get the hash of the latest finalized block
author_pendingExtrinsics
Get pending extrinsics in the transaction pool on Bittensor. Monitor mempool activity, verify transaction submission, and analyze network congestion.
author_rotateKeys
Generate new session keys for validator operations on Bittensor. Essential for validator setup, key rotation, and security best practices on the decentralized machine intelligence network built around subnets, TAO staking, and validator-miner coordination.