author_submitAndWatchExtrinsic - JSON-RPC Method
Description
Submits an extrinsic and returns a subscription ID to receive real-time status updates about the transaction's lifecycle. This JSON-RPC method is only available via WebSocket connections and provides notifications when the transaction enters the pool, gets included in a block, and becomes finalized.
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
extrinsic | string | Yes | Hex-encoded signed extrinsic to submit and watch |
Returns
Field | Type | Description |
---|---|---|
result | string | Subscription ID for receiving status updates |
Subscription Updates
The subscription will emit the following status updates:
Status | Description |
---|---|
ready | Transaction is in the ready queue |
broadcast | Transaction has been broadcast to peers |
inBlock | Transaction included in a block (with block hash) |
retracted | Transaction was retracted (with block hash) |
finalityTimeout | Maximum finality timeout reached |
finalized | Transaction is finalized (with block hash) |
usurped | Transaction was usurped by another |
dropped | Transaction dropped from the pool |
invalid | Transaction is invalid |
Request Example
{
"jsonrpc": "2.0",
"method": "author_submitAndWatchExtrinsic",
"params": [
"0x450284008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48..."
],
"id": 1
}
Response Example
{
"jsonrpc": "2.0",
"result": "CWz4K7hQdp8xFhS",
"id": 1
}
Subscription Update Examples
// Ready status
{
"jsonrpc": "2.0",
"method": "author_extrinsicUpdate",
"params": {
"subscription": "CWz4K7hQdp8xFhS",
"result": "ready"
}
}
// In block status
{
"jsonrpc": "2.0",
"method": "author_extrinsicUpdate",
"params": {
"subscription": "CWz4K7hQdp8xFhS",
"result": {
"inBlock": "0x5d83e66b61701da7b6e3e8c9d8e2e57e1391e3e58e677b30e1f391d568c9ca24"
}
}
}
// Finalized status
{
"jsonrpc": "2.0",
"method": "author_extrinsicUpdate",
"params": {
"subscription": "CWz4K7hQdp8xFhS",
"result": {
"finalized": "0x5d83e66b61701da7b6e3e8c9d8e2e57e1391e3e58e677b30e1f391d568c9ca24"
}
}
}
Code Examples
JavaScript (WebSocket)
const WebSocket = require('ws');
const submitAndWatch = async (extrinsic) => {
const ws = new WebSocket('wss://api-polkadot.n.dwellir.com', {
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
});
return new Promise((resolve, reject) => {
let subscriptionId;
ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'author_submitAndWatchExtrinsic',
params: [extrinsic],
id: 1
}));
});
ws.on('message', (data) => {
const response = JSON.parse(data);
// Initial subscription response
if (response.id === 1) {
subscriptionId = response.result;
console.log('Watching transaction:', subscriptionId);
}
// Status updates
if (response.method === 'author_extrinsicUpdate') {
const status = response.params.result;
console.log('Status update:', status);
if (status.finalized) {
console.log('Transaction finalized in block:', status.finalized);
ws.close();
resolve(status.finalized);
}
if (status === 'dropped' || status === 'invalid') {
ws.close();
reject(new Error(`Transaction ${status}`));
}
}
});
ws.on('error', reject);
});
};
Python (websocket-client)
import json
import websocket
def submit_and_watch_extrinsic(extrinsic, api_key):
"""Submit extrinsic and watch its status"""
ws_url = "wss://api-polkadot.n.dwellir.com"
headers = {"Authorization": f"Bearer {api_key}"}
subscription_id = None
finalized_block = None
def on_message(ws, message):
nonlocal subscription_id, finalized_block
data = json.loads(message)
# Initial subscription
if data.get("id") == 1:
subscription_id = data["result"]
print(f"Watching: {subscription_id}")
# Status updates
if data.get("method") == "author_extrinsicUpdate":
status = data["params"]["result"]
print(f"Status: {status}")
if isinstance(status, dict):
if "finalized" in status:
finalized_block = status["finalized"]
print(f"Finalized in: {finalized_block}")
ws.close()
elif "inBlock" in status:
print(f"In block: {status['inBlock']}")
elif status in ["dropped", "invalid"]:
print(f"Transaction {status}")
ws.close()
def on_open(ws):
subscribe_msg = {
"jsonrpc": "2.0",
"method": "author_submitAndWatchExtrinsic",
"params": [extrinsic],
"id": 1
}
ws.send(json.dumps(subscribe_msg))
ws = websocket.WebSocketApp(
ws_url,
header=headers,
on_message=on_message,
on_open=on_open
)
ws.run_forever()
return finalized_block
TypeScript (@polkadot/api)
import { ApiPromise, WsProvider } from '@polkadot/api';
async function submitAndWatchExtrinsic() {
const provider = new WsProvider('wss://api-polkadot.n.dwellir.com');
const api = await ApiPromise.create({ provider });
// Create and sign transaction
const transfer = api.tx.balances.transfer(
'RECIPIENT_ADDRESS',
1000000000000
);
// Submit and watch
const unsub = await transfer.signAndSend(
sender,
({ status, events }) => {
if (status.isReady) {
console.log('Transaction is ready');
} else if (status.isBroadcast) {
console.log('Transaction has been broadcast');
} else if (status.isInBlock) {
console.log(`Transaction included in block: ${status.asInBlock}`);
} else if (status.isFinalized) {
console.log(`Transaction finalized: ${status.asFinalized}`);
unsub();
} else if (status.isDropped || status.isInvalid) {
console.error('Transaction failed');
unsub();
}
}
);
}
Use Cases
- Transaction Confirmation: Wait for finality before proceeding
- User Notifications: Update UI with real-time transaction status
- Automated Workflows: Trigger actions after transaction finalization
- Error Recovery: Handle failed transactions automatically
- Cross-chain Operations: Coordinate actions after confirmations
Notes
- WebSocket connection required (not available via HTTPS)
- Subscription automatically ends after finalization or failure
- Use
author_unwatchExtrinsic
to manually unsubscribe - Consider network delays and finalization time (typically 12-60 seconds)
- Handle connection drops and implement reconnection logic
Related Methods
author_submitExtrinsic
- Submit without watchingauthor_pendingExtrinsics
- View pending transactionschain_getFinalizedHead
- Get finalized block