eth_sendRawTransaction - Bittensor RPC Method
Submit signed transactions to Bittensor. Essential for broadcasting transactions for decentralized AI inference, subnet-specific AI models, TAO staking, and cross-subnet AI collaboration.
Submits a pre-signed transaction for broadcast to Bittensor.
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
The eth_sendRawTransaction method serves these key scenarios for AI/ML developers, subnet operators, and teams building decentralized machine learning applications:
- Submit pre-signed transactions - Broadcast transactions that were signed offline or in a secure enclave, keeping private keys away from the RPC endpoint
- Broadcast from offline signers - Air-gapped devices and hardware wallets first sign, then use this method to push the signed payload to Bittensor
- Resubmit stuck transactions - Replace pending transactions with the same nonce and a higher gas price when the original is not being included in blocks
- Deploy contracts programmatically - Submit contract creation transactions containing compiled bytecode and constructor arguments
Common Use Cases
1. Sign and Send an ETH Transfer
Build, sign, and broadcast a native ETH transfer with proper nonce management. The nonce must be retrieved from the node immediately before signing to avoid conflicts with pending transactions.
import { JsonRpcProvider, Wallet, parseEther, Transaction } from 'ethers';
const provider = new JsonRpcProvider('https://api-bittensor-mainnet.n.dwellir.com/YOUR_API_KEY');
const wallet = new Wallet('PRIVATE_KEY', provider);
async function sendNativeTransfer(to, amountInEth) {
const tx = await wallet.sendTransaction({
to: to,
value: parseEther(amountInEth)
});
console.log('Transaction submitted:', tx.hash);
const receipt = await tx.wait();
console.log(`Confirmed in block ${receipt.blockNumber}, gas used: ${receipt.gasUsed}`);
return receipt;
}
const receipt = await sendNativeTransfer('0x156e431cc96e0e3b70c97214d869c9bc4b5bbd21', '0.01');2. Resubmit a Stuck Transaction
If a pending transaction is not being confirmed due to low gas, submit a replacement with the same nonce and a higher gas price. The replacement must use an increased fee to be accepted by the Bittensor mempool.
import { JsonRpcProvider, Wallet, parseEther } from 'ethers';
const provider = new JsonRpcProvider('https://api-bittensor-mainnet.n.dwellir.com/YOUR_API_KEY');
const wallet = new Wallet('PRIVATE_KEY', provider);
async function speedUpTransaction(originalTxHash, gasMultiplier = 1.5) {
const pendingTx = await provider.getTransaction(originalTxHash);
if (!pendingTx) throw new Error('Transaction not found');
const feeData = await provider.getFeeData();
const replacementTx = {
to: pendingTx.to,
value: pendingTx.value,
data: pendingTx.data,
nonce: pendingTx.nonce,
maxFeePerGas: feeData.maxFeePerGas * BigInt(Math.floor(gasMultiplier * 100)) / 100n,
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas * BigInt(Math.floor(gasMultiplier * 100)) / 100n,
gasLimit: pendingTx.gasLimit
};
const tx = await wallet.sendTransaction(replacementTx);
console.log('Replacement transaction:', tx.hash);
return tx;
}
const newTx = await speedUpTransaction('0x...');3. Deploy a Compiled Contract
Submit a contract deployment transaction containing the compiled bytecode. The to field is omitted for contract creation transactions; the contract address is deterministically derived from the sender address and nonce.
import { JsonRpcProvider, Wallet, ContractFactory } from 'ethers';
const provider = new JsonRpcProvider('https://api-bittensor-mainnet.n.dwellir.com/YOUR_API_KEY');
const wallet = new Wallet('PRIVATE_KEY', provider);
const contractAbi = ['constructor(string memory name, uint256 supply)'];
const contractBytecode = '0x608060...';
async function deployContract(constructorArgs) {
const factory = new ContractFactory(contractAbi, contractBytecode, wallet);
const contract = await factory.deploy(...constructorArgs);
console.log('Deployment tx:', contract.deploymentTransaction().hash);
await contract.waitForDeployment();
console.log('Contract deployed at:', await contract.getAddress());
return contract;
}
const contract = await deployContract(['MyToken', 1000000]);Best Practices
- Always sign transactions client-side: never send private keys to any RPC endpoint, including https://api-bittensor-mainnet.n.dwellir.com/YOUR_API_KEY
- Track nonces carefully to avoid gaps or conflicts: retrieve the pending nonce from
eth_getTransactionCountwith"pending"tag before each signing - The return value is a transaction hash: use
eth_getTransactionReceiptto poll for confirmation status - Handle replacement transactions correctly: the replacement must use the same nonce with a higher gas price
- Use
eth_estimateGasto set an appropriate gas limit before signing and sending
Code Examples
Error Handling
| Error Code | Message | Description |
|---|---|---|
| -32000 | Nonce too low | Transaction nonce already used |
| -32000 | Insufficient funds | Account has insufficient balance |
| -32000 | Gas too low | Gas limit insufficient |
| -32000 | Replacement underpriced | Gas price too low for replacement |
Related Methods
eth_estimateGas- Estimate gas requiredeth_gasPrice- Get current gas priceeth_getTransactionReceipt- Get transaction result
eth_accounts
Returns a list of addresses owned by the client on Bittensor. Typically returns an empty array on public RPC endpoints.
eth_getTransactionByHash
Retrieve transaction details by hash on Bittensor. Essential for AI/ML developers, subnet operators, and teams building decentralized machine learning applications tracking transactions on the decentralized machine intelligence network built around subnets, TAO staking, and validator-miner coordination.