SDK Version

This Documentation is based upon avail-rust version v0.1.9

Account

Account Balance

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;

	let alice_account = account::account_id_from_str("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY")?;

	let info = account::account_info(&sdk.client, alice_account).await?;
	println!("Flags: {:?}", info.data.flags);
	println!("Free: {}", info.data.free);
	println!("Frozen: {}", info.data.frozen);
	println!("Reserved: {}", info.data.reserved);

	Ok(())
}

Account Creation

use std::str::FromStr;

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	// Use SecretUri and Keypair to create your own account...
	let secret_uri = SecretUri::from_str("//Alice")?;
	let acc = Keypair::from_uri(&secret_uri)?;
	println!("Alice Address: {}", acc.public_key().to_account_id());

	// ... or from_secret_uri function
	let acc = account::from_secret_uri("//Alice")?;
	println!("Alice Address: {}", acc.public_key().to_account_id());

	// There are predefined testing accounts available to be used on local dev networks.
	let acc = account::alice();
	println!("Alice Address: {}", acc.public_key().to_account_id());
	let acc = account::bob();
	println!("Bob Address: {}", acc.public_key().to_account_id());
	let acc = account::charlie();
	println!("Charlie Address: {}", acc.public_key().to_account_id());
	let acc = account::dave();
	println!("Dave Address: {}", acc.public_key().to_account_id());
	let acc = account::eve();
	println!("Eve Address: {}", acc.public_key().to_account_id());
	let acc = account::ferdie();
	println!("Ferdie Address: {}", acc.public_key().to_account_id());

	// AccountId can be created form Keypair...
	let account_id = acc.public_key().to_account_id();
	println!("Ferdie Address: {}", account_id);

	// ...or from SS58 address
	let account_id = account::account_id_from_str("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY")?;
	println!("Alice Address: {}", account_id);

	// SS58 address can be created from Account ID
	println!("Alice Address: {}", account_id);

	// MultiAddress can be created from Public Key...
	let _address = acc.public_key().to_address::<u32>();

	// ...or from account id
	let _address = MultiAddress::from(account_id);

	Ok(())
}

Account Nonce

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;

	let alice_address = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";

	// Fetch nonce via RPC
	let nonce = account::nonce(&sdk.client, alice_address).await?;
	println!("RPC Nonce: {}", nonce);

	// Fetch none via Storage
	let alice_account = account::account_id_from_str(alice_address)?;
	let info = account::account_info(&sdk.client, alice_account).await?;
	println!("Nonce: {}", info.nonce);

	Ok(())
}

Data Submission

use avail_rust::prelude::*;
use std::time::SystemTime;

type DataSubmissionCall = avail::data_availability::calls::types::SubmitData;
type ApplicationKeyCreatedEvent = avail::data_availability::events::ApplicationKeyCreated;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let account = account::alice();

	// Application Key Creation
	let time = std::format!("{:?}", SystemTime::now());
	let key = time.into_bytes();
	let tx = sdk.tx.data_availability.create_application_key(key);
	let res = tx.execute_and_watch_inclusion(&account, Options::default()).await?;
	assert_eq!(res.is_successful(), Some(true), "Transactions must be successful");

	let events = res.events.as_ref().unwrap();
	let event = events.find_first::<ApplicationKeyCreatedEvent>().unwrap();
	let Some(event) = event else {
		return Err("Failed to get Application Key Created Event".into());
	};
	let app_id = event.id.0;

	// Data Submission
	let data = String::from("My Data").into_bytes();
	let options = Options::new().app_id(app_id);
	let tx = sdk.tx.data_availability.submit_data(data);
	let res = tx.execute_and_watch_inclusion(&account, options).await?;
	assert_eq!(res.is_successful(), Some(true), "Transactions must be successful");

	println!(
		"Block Hash: {:?}, Block Number: {}, Tx Hash: {:?}, Tx Index: {}",
		res.block_hash, res.block_number, res.tx_hash, res.tx_index
	);

	// Events
	let events = res.events.as_ref().unwrap();
	for event in events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Decoding
	let decoded = res.decode_as::<DataSubmissionCall>().await?;
	let Some(decoded) = decoded else {
		return Err("Failed to get Data Submission Call data".into());
	};

	let data = to_ascii(decoded.data.0).unwrap();
	println!("Call data: {:?}", data);

	println!("Data Submission finished correctly");

	Ok(())
}

Batch

use std::ops::Mul;

use avail_rust::prelude::*;

use avail::{
	runtime_types::{da_runtime::RuntimeCall, pallet_balances::pallet::Call::transfer_keep_alive as TransferKeepAlive},
	utility::events as UtilityEvents,
};

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let account = account::alice();

	let value_1 = SDK::one_avail();
	let value_2 = SDK::one_avail();
	let dest_bob = account::account_id_from_str("5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty")?;
	let dest_charlie = account::account_id_from_str("5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y")?;

	let call_1 = TransferKeepAlive {
		dest: dest_bob.clone().into(),
		value: value_1,
	};
	let call_2 = TransferKeepAlive {
		dest: dest_charlie.clone().into(),
		value: value_2,
	};
	let mut calls = Vec::new();
	calls.push(RuntimeCall::Balances(call_1).into());
	calls.push(RuntimeCall::Balances(call_2).into());

	//
	// Happy Path
	//

	// Batch Call
	//
	// This will return `Ok` in all circumstances. To determine the success of the batch, an
	// event is deposited. If a call failed and the batch was interrupted, then the
	// `BatchInterrupted` event is deposited, along with the number of successful calls made
	// and the error of the failed call. If all were successful, then the `BatchCompleted`
	// event is deposited.
	let payload = avail::tx().utility().batch(calls.clone());
	let tx = Transaction::new(sdk.client.clone(), payload);
	let res = tx.execute_and_watch_inclusion(&account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true), "Transactions must be successful");

	let events = res.events.unwrap();
	assert_eq!(events.has::<UtilityEvents::BatchCompleted>(), Some(true), "");
	assert_eq!(events.count::<UtilityEvents::ItemCompleted>(), 2, "");

	println!("-- Batch Call Done --");

	// Batch All Call
	//
	// Send a batch of dispatch calls and atomically execute them.
	// The whole transaction will rollback and fail if any of the calls failed.
	let payload = avail::tx().utility().batch_all(calls.clone());
	let tx = Transaction::new(sdk.client.clone(), payload);
	let res = tx.execute_and_watch_inclusion(&account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true), "Transactions must be successful");

	let events = res.events.unwrap();
	assert_eq!(events.has::<UtilityEvents::BatchCompleted>(), Some(true), "");
	assert_eq!(events.count::<UtilityEvents::ItemCompleted>(), 2, "");

	println!("-- Batch All Call Done --");

	// Force Batch Call
	//
	// Send a batch of dispatch calls.
	// Unlike `batch`, it allows errors and won't interrupt.

	let payload = avail::tx().utility().force_batch(calls.clone());
	let tx = Transaction::new(sdk.client.clone(), payload);
	let res = tx.execute_and_watch_inclusion(&account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true), "Transactions must be successful");

	let events = res.events.unwrap();
	assert_eq!(events.has::<UtilityEvents::BatchCompleted>(), Some(true), "");
	assert_eq!(events.count::<UtilityEvents::ItemCompleted>(), 2, "");

	println!("-- Force Batch Call Done --");

	//
	//	Things differ when we introduce a call that will fail
	//

	let call_3 = TransferKeepAlive {
		dest: dest_charlie.into(),
		value: SDK::one_avail().mul(1_000_000_000u128),
	};

	let call_4 = TransferKeepAlive {
		dest: dest_bob.into(),
		value: SDK::one_avail().mul(1u128),
	};

	// The 3. is poisoned with a too high transfer amount
	calls.push(RuntimeCall::Balances(call_3).into());
	// The 4. call is a normal one
	calls.push(RuntimeCall::Balances(call_4).into());

	// Batch Call
	let payload = avail::tx().utility().batch(calls.clone());
	let tx = Transaction::new(sdk.client.clone(), payload);
	let res = tx.execute_and_watch_inclusion(&account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true), "Transactions must be successful");

	let events = res.events.unwrap();
	assert_eq!(events.has::<UtilityEvents::BatchInterrupted>(), Some(true), "");
	assert_eq!(events.has::<UtilityEvents::BatchCompleted>(), Some(false), "");
	assert_eq!(events.count::<UtilityEvents::ItemCompleted>(), 2, "");

	println!("-- Batch Call Done --");

	// Batch All Call
	let payload = avail::tx().utility().batch_all(calls.clone());
	let tx = Transaction::new(sdk.client.clone(), payload);
	let res = tx.execute_and_watch_inclusion(&account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(false), "Transactions needs fail.");

	println!("-- Batch All Call Done --");

	// Force Batch Call
	let payload = avail::tx().utility().force_batch(calls.clone());
	let tx = Transaction::new(sdk.client.clone(), payload);
	let res = tx.execute_and_watch_inclusion(&account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true), "Transactions must be successful");

	let events = res.events.unwrap();
	assert_eq!(events.has::<UtilityEvents::BatchCompletedWithErrors>(), Some(true), "");
	assert_eq!(events.count::<UtilityEvents::ItemFailed>(), 1, "");
	assert_eq!(events.count::<UtilityEvents::ItemCompleted>(), 3, "");

	println!("-- Force Batch Call Done --");

	println!("Batch finished correctly");

	Ok(())
}

Block

All Transactions

use avail_rust::prelude::*;

type SubmitDataCall = avail::data_availability::calls::types::SubmitData;
type DataSubmittedEvent = avail::data_availability::events::DataSubmitted;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Transactions
	let block_transactions = block.transactions(Filter::default());
	assert_eq!(block_transactions.len(), 9, "Transaction count must be 9");

	// Printout Block Transactions
	for tx in block_transactions.iter() {
		println!(
			"Pallet Name: {:?}, Pallet Index: {}, Call Name: {:?}, Call Index: {:?}, Tx Hash: {:?}, Tx Index: {}",
			tx.pallet_name(),
			tx.pallet_index(),
			tx.call_name(),
			tx.call_index(),
			tx.tx_hash(),
			tx.tx_index()
		);

		println!(
			"Tx Signer: {:?}, App Id: {:?}, Tip: {:?}, Mortality: {:?}, Nonce: {:?}",
			tx.ss58address(),
			tx.app_id(),
			tx.tip(),
			tx.mortality(),
			tx.nonce(),
		);
	}

	// Convert from Block Transaction to Specific Transaction
	let da_tx = block_transactions.index(2).decode::<SubmitDataCall>();
	assert!(da_tx.is_some(), "SubmitDataCall should exist");
	let da_tx = da_tx.unwrap();
	let data = to_ascii(da_tx.data.0).unwrap();
	println!("Data: {}", data);

	// Printout all Transaction Events
	let tx_events = block_transactions.index(2).events().await;
	assert!(tx_events.is_some(), "Events should exist");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 7, "Event count must be 7");

	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Generic Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<DataSubmittedEvent>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "DataSubmittedEvent");
	let event = event.unwrap().unwrap();
	println!("Who: {}, Data Hash: {:?}", event.who, event.data_hash);

	Ok(())
}

All Transactions Static

use avail_rust::prelude::*;

type SubmitDataCall = avail::data_availability::calls::types::SubmitData;
type DataSubmittedEvent = avail::data_availability::events::DataSubmitted;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Transactions
	let block_transactions = block.transactions_static::<SubmitDataCall>(Filter::default());
	assert_eq!(block_transactions.len(), 4, "Transaction count must be 4");

	// Printout Block Transactions
	for tx in block_transactions.iter() {
		let data = to_ascii(tx.value.data.0.clone()).unwrap();

		println!(
			"Pallet Name: {:?}, Pallet Index: {}, Call Name: {:?}, Call Index: {:?}, Tx Hash: {:?}, Tx Index: {}",
			tx.pallet_name(),
			tx.pallet_index(),
			tx.call_name(),
			tx.call_index(),
			tx.tx_hash(),
			tx.tx_index()
		);

		println!(
			"Tx Signer: {:?}, App Id: {:?}, Tip: {:?}, Mortality: {:?}, Nonce: {:?}, Data: {}",
			tx.ss58address(),
			tx.app_id(),
			tx.tip(),
			tx.mortality(),
			tx.nonce(),
			data
		);
	}

	// Printout all Transaction Events
	let tx_events = block_transactions[0].events().await;
	assert!(tx_events.is_some(), "Events should exist");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 7, "Event count must be 7");

	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Generic Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<DataSubmittedEvent>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "DataSubmittedEvent");
	let event = event.unwrap().unwrap();
	println!("Who: {}, Data Hash: {:?}", event.who, event.data_hash);

	Ok(())
}

Transaction Filtered By App Id

use avail_rust::prelude::*;

type SubmitDataCall = avail::data_availability::calls::types::SubmitData;
type DataSubmittedEvent = avail::data_availability::events::DataSubmitted;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Transaction filtered by Signer
	let app_id = 2;
	let block_transactions = block.transactions(Filter::new().app_id(app_id));
	assert_eq!(block_transactions.len(), 2, "Transaction count must be 2");

	// Printout Block Transactions made by Signer
	for tx in block_transactions.iter() {
		assert_eq!(tx.app_id(), Some(app_id), "App Id must be the same");

		println!(
			"Pallet Name: {:?}, Pallet Index: {}, Call Name: {:?}, Call Index: {:?}, Tx Hash: {:?}, Tx Index: {}",
			tx.pallet_name(),
			tx.pallet_index(),
			tx.call_name(),
			tx.call_index(),
			tx.tx_hash(),
			tx.tx_index()
		);

		println!(
			"Tx Signer: {:?}, App Id: {:?}, Tip: {:?}, Mortality: {:?}, Nonce: {:?}",
			tx.ss58address(),
			tx.app_id(),
			tx.tip(),
			tx.mortality(),
			tx.nonce(),
		);
	}

	// Convert from Block Transaction to Specific Transaction
	let da_tx = block_transactions.index(0).decode::<SubmitDataCall>();
	assert!(da_tx.is_some(), "SubmitDataCall should exist");
	let da_tx = da_tx.unwrap();
	let data = to_ascii(da_tx.data.0).unwrap();
	println!("Data: {}", data);

	// Printout all Transaction Events
	let tx_events = block_transactions.index(0).events().await;
	assert!(tx_events.is_some(), "Events should exist");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 7, "Event count must be 7");

	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Generic Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<DataSubmittedEvent>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "DataSubmittedEvent");
	let event = event.unwrap().unwrap();
	println!("Who: {}, Data Hash: {:?}", event.who, event.data_hash);

	Ok(())
}

Transaction Filtered By App Id Static

use avail_rust::prelude::*;

type SubmitDataCall = avail::data_availability::calls::types::SubmitData;
type DataSubmittedEvent = avail::data_availability::events::DataSubmitted;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Transaction filtered by Signer
	let app_id = 2;
	let block_transactions = block.transactions_static::<SubmitDataCall>(Filter::new().app_id(app_id));
	assert_eq!(block_transactions.len(), 2, "Transaction count must be 2");

	// Printout Block Transactions made by Signer
	for tx in block_transactions.iter() {
		assert_eq!(tx.app_id(), Some(app_id), "App Id must be the same");
		let data = to_ascii(tx.value.data.0.clone()).unwrap();

		println!(
			"Pallet Name: {:?}, Pallet Index: {}, Call Name: {:?}, Call Index: {:?}, Tx Hash: {:?}, Tx Index: {}",
			tx.pallet_name(),
			tx.pallet_index(),
			tx.call_name(),
			tx.call_index(),
			tx.tx_hash(),
			tx.tx_index()
		);

		println!(
			"Tx Signer: {:?}, App Id: {:?}, Tip: {:?}, Mortality: {:?}, Nonce: {:?}, Data: {}",
			tx.ss58address(),
			tx.app_id(),
			tx.tip(),
			tx.mortality(),
			tx.nonce(),
			data
		);
	}

	// Printout all Transaction Events
	let tx_events = block_transactions[0].events().await;
	assert!(tx_events.is_some(), "Events should exist");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 7, "Event count must be 7");

	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Generic Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<DataSubmittedEvent>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "DataSubmittedEvent");
	let event = event.unwrap().unwrap();
	println!("Who: {}, Data Hash: {:?}", event.who, event.data_hash);

	Ok(())
}

Transaction Filtered By Transaction Hash

use avail_rust::prelude::*;

type TransferKeepAliveCall = avail::balances::calls::types::TransferKeepAlive;
type TransferEvent = avail::balances::events::Transfer;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// Transaction filtered by Transaction Hash
	let tx_hash = new_h256_from_hex("0x19c486e107c926ff4af3fa9b1d95aaba130cb0bc89515d0f5b523ef6bac06338")?;
	let txs = block.transactions(Filter::new().tx_hash(tx_hash));
	assert_eq!(txs.len(), 1, "");
	let tx = txs.index(0);

	// Printout
	assert_eq!(tx.tx_hash(), tx_hash, "Tx Hash must be the same");
	println!(
		"Pallet Name: {:?}, Pallet Index: {}, Call Name: {:?}, Call Index: {:?}, Tx Hash: {:?}, Tx Index: {}",
		tx.pallet_name(),
		tx.pallet_index(),
		tx.call_name(),
		tx.call_index(),
		tx.tx_hash(),
		tx.tx_index()
	);

	println!(
		"Tx Signer: {:?}, App Id: {:?}, Tip: {:?}, Mortality: {:?}, Nonce: {:?}",
		tx.ss58address(),
		tx.app_id(),
		tx.tip(),
		tx.mortality(),
		tx.nonce(),
	);

	// Convert from Block Transaction to Specific Transaction
	let ba_tx = tx.decode::<TransferKeepAliveCall>();
	assert!(ba_tx.is_some(), "TransferKeepAliveCall should exist");
	let ba_tx = ba_tx.unwrap();

	let account_id = match ba_tx.dest {
		subxt::utils::MultiAddress::Id(x) => x,
		_ => panic!("Not decodable."),
	};
	println!("Destination: {}, Value: {}", account_id, ba_tx.value);

	// Printout all Transaction Events
	let tx_events = tx.events().await;
	assert!(tx_events.is_some(), "Events should exist");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 7, "Event count must be 7");

	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Generic Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<TransferEvent>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "TransferEvent");
	let event = event.unwrap().unwrap();
	println!("From: {}, To: {}, Amount: {}", event.from, event.to, event.amount);

	Ok(())
}

Transaction Filtered By Transaction Hash Static

use avail_rust::prelude::*;

type TransferKeepAliveCall = avail::balances::calls::types::TransferKeepAlive;
type TransferEvent = avail::balances::events::Transfer;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// Transaction filtered by Transaction Hash
	let tx_hash = new_h256_from_hex("0x19c486e107c926ff4af3fa9b1d95aaba130cb0bc89515d0f5b523ef6bac06338")?;
	let txs = block.transactions_static::<TransferKeepAliveCall>(Filter::new().tx_hash(tx_hash));
	assert_eq!(txs.len(), 1, "");
	let tx = &txs[0];

	// Printout
	assert_eq!(tx.tx_hash(), tx_hash, "Tx Hash must be the same");
	println!(
		"Pallet Name: {:?}, Pallet Index: {}, Call Name: {:?}, Call Index: {:?}, Tx Hash: {:?}, Tx Index: {}",
		tx.pallet_name(),
		tx.pallet_index(),
		tx.call_name(),
		tx.call_index(),
		tx.tx_hash(),
		tx.tx_index()
	);

	println!(
		"Tx Signer: {:?}, App Id: {:?}, Tip: {:?}, Mortality: {:?}, Nonce: {:?}",
		tx.ss58address(),
		tx.app_id(),
		tx.tip(),
		tx.mortality(),
		tx.nonce(),
	);

	let account_id = match &tx.value.dest {
		subxt::utils::MultiAddress::Id(x) => x.clone(),
		_ => panic!("Not decodable."),
	};
	println!("Destination: {}, Value: {}", account_id, tx.value.value);

	// Printout all Transaction Events
	let tx_events = tx.events().await;
	assert!(tx_events.is_some(), "Events should exist");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 7, "Event count must be 7");

	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Generic Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<TransferEvent>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "TransferEvent");
	let event = event.unwrap().unwrap();
	println!("From: {}, To: {}, Amount: {}", event.from, event.to, event.amount);

	Ok(())
}

Transaction Filtered By Index

use avail_rust::prelude::*;

type TransferKeepAliveCall = avail::balances::calls::types::TransferKeepAlive;
type NetAccountEvent = avail::system::events::NewAccount;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// Transaction filtered by Transaction index
	let tx_index = 1;
	let txs = block.transactions(Filter::new().tx_index(tx_index));
	assert_eq!(txs.len(), 1, "");
	let tx = txs.index(0);

	// Printout
	assert_eq!(tx.tx_index(), tx_index, "Tx Index must be the same");
	println!(
		"Pallet Name: {:?}, Pallet Index: {}, Call Name: {:?}, Call Index: {:?}, Tx Hash: {:?}, Tx Index: {}",
		tx.pallet_name(),
		tx.pallet_index(),
		tx.call_name(),
		tx.call_index(),
		tx.tx_hash(),
		tx.tx_index()
	);

	println!(
		"Tx Signer: {:?}, App Id: {:?}, Tip: {:?}, Mortality: {:?}, Nonce: {:?}",
		tx.ss58address(),
		tx.app_id(),
		tx.tip(),
		tx.mortality(),
		tx.nonce(),
	);

	// Convert from Block Transaction to Specific Transaction
	let ba_tx = tx.decode::<TransferKeepAliveCall>();
	assert!(ba_tx.is_some(), "TransferKeepAliveCall should exist");
	let ba_tx = ba_tx.unwrap();

	let account_id = match ba_tx.dest {
		subxt::utils::MultiAddress::Id(x) => x,
		_ => panic!("Not decodable."),
	};
	println!("Destination: {}, Value: {}", account_id, ba_tx.value);

	// Printout all Transaction Events
	let tx_events = tx.events().await;
	assert!(tx_events.is_some(), "Events should exist");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 9, "Event count must be 9");

	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Generic Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<NetAccountEvent>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "NetAccountEvent");
	let event = event.unwrap().unwrap();
	println!("Account: {}", event.account);

	Ok(())
}

Transaction Filtered By Index Static

use avail_rust::prelude::*;

type TransferKeepAliveCall = avail::balances::calls::types::TransferKeepAlive;
type NetAccountEvent = avail::system::events::NewAccount;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// Transaction filtered by Transaction index
	let tx_index = 1;
	let txs = block.transactions_static::<TransferKeepAliveCall>(Filter::new().tx_index(tx_index));
	assert_eq!(txs.len(), 1, "");
	let tx = &txs[0];

	// Printout
	assert_eq!(tx.tx_index(), tx_index, "Tx Index must be the same");
	println!(
		"Pallet Name: {:?}, Pallet Index: {}, Call Name: {:?}, Call Index: {:?}, Tx Hash: {:?}, Tx Index: {}",
		tx.pallet_name(),
		tx.pallet_index(),
		tx.call_name(),
		tx.call_index(),
		tx.tx_hash(),
		tx.tx_index()
	);

	println!(
		"Tx Signer: {:?}, App Id: {:?}, Tip: {:?}, Mortality: {:?}, Nonce: {:?}",
		tx.ss58address(),
		tx.app_id(),
		tx.tip(),
		tx.mortality(),
		tx.nonce(),
	);

	let account_id = match &tx.value.dest {
		subxt::utils::MultiAddress::Id(x) => x.clone(),
		_ => panic!("Not decodable."),
	};
	println!("Destination: {}, Value: {}", account_id, tx.value.value);

	// Printout all Transaction Events
	let tx_events = tx.events().await;
	assert!(tx_events.is_some(), "Events should exist");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 9, "Event count must be 9");

	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Generic Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<NetAccountEvent>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "NetAccountEvent");
	let event = event.unwrap().unwrap();
	println!("Account: {}", event.account);

	Ok(())
}

Transaction Filtered By Signer

use avail_rust::prelude::*;

type CreateAppKeyCall = avail::data_availability::calls::types::CreateApplicationKey;
type AppKeyCreated = avail::data_availability::events::ApplicationKeyCreated;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Transaction filtered by Signer
	let account_id = account_id_from_str("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY")?;
	let block_transactions = block.transactions(Filter::new().tx_signer(account_id.clone()));
	assert_eq!(block_transactions.len(), 5, "Transaction count must be 5");

	// Printout Block Transactions made by Signer
	for tx in block_transactions.iter() {
		assert_eq!(tx.account_id(), Some(account_id.clone()), "Signer must be the same");

		println!(
			"Pallet Name: {:?}, Pallet Index: {}, Call Name: {:?}, Call Index: {:?}, Tx Hash: {:?}, Tx Index: {}",
			tx.pallet_name(),
			tx.pallet_index(),
			tx.call_name(),
			tx.call_index(),
			tx.tx_hash(),
			tx.tx_index()
		);

		println!(
			"Tx Signer: {:?}, App Id: {:?}, Tip: {:?}, Mortality: {:?}, Nonce: {:?}",
			tx.ss58address(),
			tx.app_id(),
			tx.tip(),
			tx.mortality(),
			tx.nonce(),
		);
	}

	// Convert from Block Transaction to Specific Transaction
	let da_tx = block_transactions.index(0).decode::<CreateAppKeyCall>();
	assert!(da_tx.is_some(), "CreateAppKeyCall should exist");
	let da_tx = da_tx.unwrap();
	let key = to_ascii(da_tx.key.0).unwrap();
	println!("Key: {}", key);

	// Printout all Transaction Events
	let tx_events = block_transactions.index(0).events().await;
	assert!(tx_events.is_some(), "Events should exist");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 7, "Event count must be 7");

	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Generic Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<AppKeyCreated>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "AppKeyCreated");
	let event = event.unwrap().unwrap();

	let key = to_ascii(event.key.0).unwrap();
	println!("App Id: {}, Owner: {}, Key: {}", event.id.0, event.owner, key);

	Ok(())
}

Transaction Filtered By Signer Static

use avail_rust::prelude::*;

type CreateAppKeyCall = avail::data_availability::calls::types::CreateApplicationKey;
type AppKeyCreated = avail::data_availability::events::ApplicationKeyCreated;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Transaction filtered by Signer
	let account_id = account_id_from_str("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY")?;
	let block_transactions = block.transactions_static::<CreateAppKeyCall>(Filter::new().tx_signer(account_id.clone()));
	assert_eq!(block_transactions.len(), 1, "Transaction count must be 1");

	// Printout Block Transactions made by Signer
	for tx in block_transactions.iter() {
		assert_eq!(tx.account_id(), Some(account_id.clone()), "Signer must be the same");

		let key = to_ascii(tx.value.key.0.clone()).unwrap();
		println!("Key: {}", key);

		println!(
			"Pallet Name: {:?}, Pallet Index: {}, Call Name: {:?}, Call Index: {:?}, Tx Hash: {:?}, Tx Index: {}",
			tx.pallet_name(),
			tx.pallet_index(),
			tx.call_name(),
			tx.call_index(),
			tx.tx_hash(),
			tx.tx_index()
		);

		println!(
			"Tx Signer: {:?}, App Id: {:?}, Tip: {:?}, Mortality: {:?}, Nonce: {:?}",
			tx.ss58address(),
			tx.app_id(),
			tx.tip(),
			tx.mortality(),
			tx.nonce(),
		);
	}

	// Printout all Transaction Events
	let tx_events = block_transactions[0].events().await;
	assert!(tx_events.is_some(), "Events should exist");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 7, "Event count must be 7");

	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Generic Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<AppKeyCreated>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "AppKeyCreated");
	let event = event.unwrap().unwrap();

	let key = to_ascii(event.key.0).unwrap();
	println!("App Id: {}, Owner: {}, Key: {}", event.id.0, event.owner, key);

	Ok(())
}

All Data Submissions

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Block Blobs
	let blobs = block.data_submissions(Filter::default());
	assert_eq!(blobs.len(), 4, "Blobs must present 4 times");

	// Printout All Block Blobs
	for blob in blobs {
		let blob_data = blob.to_ascii().unwrap();

		println!(
			"Tx Hash: {:?}, Tx Index: {}, Data: {:?}, App Id: {}, Tx Singer: {:?}",
			blob.tx_hash,
			blob.tx_index,
			blob_data,
			blob.app_id,
			blob.ss58address(),
		);
	}

	Ok(())
}

Data Submissions Filtered by App Id

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Block Blobs by App Id
	let app_id = 2u32;
	let blobs = block.data_submissions(Filter::new().app_id(app_id));
	assert_eq!(blobs.len(), 2, "Blobs must present 2 times");

	// Printout All Block Blobs by App Id
	for blob in blobs {
		let blob_data = blob.to_ascii().unwrap();
		assert_eq!(blob.app_id, app_id, "App Id must be 2");

		println!(
			"Tx Hash: {:?}, Tx Index: {}, Data: {:?}, App Id: {}, Tx Singer: {:?}",
			blob.tx_hash,
			blob.tx_index,
			blob_data,
			blob.app_id,
			blob.ss58address(),
		);
	}

	Ok(())
}

Data Submissions Filtered by Hash

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Block Blobs by Hash
	let tx_hash = new_h256_from_hex("0xe7efa71363d11bce370fe71a33e5ff296775f37507075c49316132131420f793")?;
	let blobs = block.data_submissions(Filter::new().tx_hash(tx_hash));
	assert_eq!(blobs.len(), 1, "");

	let blob = &blobs[0];

	// Printout All Block Blobs by Hash
	let blob_data = blob.to_ascii().unwrap();
	assert_eq!(blob.tx_hash, tx_hash, "Tx Hash must be the same");

	println!(
		"Tx Hash: {:?}, Tx Index: {}, Data: {:?}, App Id: {}, Tx Singer: {:?}",
		blob.tx_hash,
		blob.tx_index,
		blob_data,
		blob.app_id,
		blob.ss58address(),
	);

	Ok(())
}

Data Submissions Filtered by Index

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Block Blobs by Index
	let tx_index = 6;
	let blobs = block.data_submissions(Filter::new().tx_index(tx_index));
	assert_eq!(blobs.len(), 1, "");

	let blob = &blobs[0];

	// Printout All Block Blobs by Index
	let blob_data = blob.to_ascii().unwrap();
	assert_eq!(blob.tx_index, tx_index, "Tx Index must be the same");

	println!(
		"Tx Hash: {:?}, Tx Index: {}, Data: {:?}, App Id: {}, Tx Singer: {:?}",
		blob.tx_hash,
		blob.tx_index,
		blob_data,
		blob.app_id,
		blob.ss58address(),
	);

	Ok(())
}

Data Submissions Filtered by Signer

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Block Blobs by Signer
	let account_id = account_id_from_str("5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty").unwrap();
	let blobs = block.data_submissions(Filter::new().tx_signer(account_id.clone()));
	assert_eq!(blobs.len(), 1, "Blobs must present 1 time");

	// Printout All Block Blobs by Signer
	for blob in blobs {
		let blob_data = blob.to_ascii().unwrap();
		assert_eq!(blob.account_id(), Some(account_id.clone()), "Signer must be the same.");

		println!(
			"Tx Hash: {:?}, Tx Index: {}, Data: {:?}, App Id: {}, Tx Singer: {:?}",
			blob.tx_hash,
			blob.tx_index,
			blob_data,
			blob.app_id,
			blob.ss58address(),
		);
	}

	Ok(())
}

Block Events

use avail_rust::prelude::*;

type TransferEvent = avail::balances::events::Transfer;
type AppKeyCreatedEvent = avail::data_availability::events::ApplicationKeyCreated;
type DataSubmittedEvent = avail::data_availability::events::DataSubmitted;
type SuccessEvent = avail::system::events::ExtrinsicSuccess;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Block Events
	let block_events = block.events().await;
	assert!(block_events.is_some(), "Events must been present");
	let block_events = block_events.unwrap();
	assert_eq!(block_events.len(), 53, "Block event count must be 53");

	// Printout All Block Events
	for event in block_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Block Transaction Event to Specific Transaction Event
	let events = block_events.find::<TransferEvent>();
	assert_eq!(events.len(), 2, "Transfer event count must be 2");

	for event in events {
		println!("From: {}, To: {}, Amount: {}", event.from, event.to, event.amount)
	}

	// Convert from Block Transaction Event to Specific ApplicationKeyCreated Event
	let event = block_events.find_first::<AppKeyCreatedEvent>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "AppKeyCreatedEvent");

	let event = event.unwrap().unwrap();
	let key: String = to_ascii(event.key.0).unwrap();
	println!("Owner: {}, App Id: {}, Key: {}", event.owner, event.id.0, key);

	// Check
	assert_eq!(
		block_events.find::<DataSubmittedEvent>().len(),
		4,
		"DataSubmitted event count must be 4"
	);
	assert_eq!(
		block_events.find::<AppKeyCreatedEvent>().len(),
		1,
		"AppKeyCreated event count must be 1"
	);

	// Events for Specific Transaction
	let tx_index = 0u32;
	let tx_events = block.tx_events(tx_index).await;
	assert!(tx_events.is_some(), "Transaction Events must be present");
	let tx_events = tx_events.unwrap();
	assert_eq!(tx_events.len(), 1, "Transaction event count must be 1");

	// Printout All Tx Events
	for event in tx_events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Convert from Block Transaction Event to Specific Transaction Event
	let event = tx_events.find_first::<SuccessEvent>();
	assert!(event.as_ref().is_some_and(|x| x.is_some()), "SuccessEvent");

	let event = event.unwrap().unwrap();
	println!("Weight {:?}", event.dispatch_info.weight);

	Ok(())
}

Transaction

Execute

use avail::data_availability::{calls::types::SubmitData, events::DataSubmitted};
use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	// Transaction will be signed, and sent.
	//
	// There is no guarantee that the transaction was executed at all. It might have been
	// dropped or discarded for various reasons. The caller is responsible for querying future
	// blocks in order to determine the execution status of that transaction.
	let tx = sdk.tx.data_availability.submit_data(vec![0, 1, 2]);
	let tx_hash = tx.execute(&account::alice(), Options::new().app_id(1)).await?;
	println!("Tx Hash: {:?}", tx_hash);

	// Checking if the transaction was included
	//
	// It's not necessary to use the builtin watcher. A custom watcher
	// might yield better results in some cases.
	let mut watcher = Watcher::new(sdk.client.clone(), tx_hash);
	watcher.set_options(|opt: &mut WatcherOptions| opt.wait_for = WaitFor::BlockInclusion);

	let res = watcher.run().await?;
	let res = res.unwrap();
	assert_eq!(res.is_successful(), Some(true));

	// Printout Transaction Details
	println!(
		"Block Hash: {:?}, Block Number: {}, Tx Hash: {:?}, Tx Index: {}",
		res.block_hash, res.block_number, res.tx_hash, res.tx_index
	);

	// Printout Transaction Events
	let events = res.events.as_ref().unwrap();
	for event in events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Converts generic event to a specific one
	let event = events.find_first::<DataSubmitted>();
	let event = event.unwrap().unwrap();
	print!("Data Hash: {:?}, Who: {}", event.data_hash, event.who);

	// Converts generic transaction to a specific one
	let decoded = res.decode_as::<SubmitData>().await?.unwrap();
	let data = to_ascii(decoded.data.0).unwrap();
	println!("Data: {}", data);

	println!("Transaction Execute finished correctly");

	Ok(())
}

Execute and Watch For Inclusion

use avail::data_availability::{calls::types::SubmitData, events::DataSubmitted};
use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	// Transaction will be signed, sent, and watched
	// If the transaction was dropped or never executed, the system will retry it
	// for 2 more times using the same nonce and app id.
	//
	// Waits for transaction inclusion. Most of the time you would want to call `ExecuteAndWatchFinalization` as
	// inclusion doesn't mean that the transaction will be in the canonical chain.
	let tx = sdk.tx.data_availability.submit_data(vec![0, 1, 2]);
	let res = tx
		.execute_and_watch_inclusion(&account::alice(), Options::new().app_id(1))
		.await?;
	assert_eq!(res.is_successful(), Some(true));

	// Printout Transaction Details
	println!(
		"Block Hash: {:?}, Block Number: {}, Tx Hash: {:?}, Tx Index: {}",
		res.block_hash, res.block_number, res.tx_hash, res.tx_index
	);

	// Printout Transaction Events
	let events = res.events.as_ref().unwrap();
	for event in events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Converts generic event to a specific one
	let event = events.find_first::<DataSubmitted>();
	let event = event.unwrap().unwrap();
	print!("Data Hash: {:?}, Who: {}", event.data_hash, event.who);

	// Converts generic transaction to a specific one
	let decoded = res.decode_as::<SubmitData>().await?.unwrap();
	let data = to_ascii(decoded.data.0).unwrap();
	println!("Data: {}", data);

	println!("Transaction Execute Inclusion finished correctly");

	Ok(())
}

Execute and Watch For Finalization

use avail::data_availability::{calls::types::SubmitData, events::DataSubmitted};
use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	// Transaction will be signed, sent, and watched
	// If the transaction was dropped or never executed, the system will retry it
	// for 2 more times using the same nonce and app id.
	//
	// Waits for finalization to finalize the transaction.
	let tx = sdk.tx.data_availability.submit_data(vec![0, 1, 2]);
	let res = tx
		.execute_and_watch_finalization(&account::alice(), Options::new().app_id(1))
		.await?;
	assert_eq!(res.is_successful(), Some(true));

	// Printout Transaction Details
	println!(
		"Block Hash: {:?}, Block Number: {}, Tx Hash: {:?}, Tx Index: {}",
		res.block_hash, res.block_number, res.tx_hash, res.tx_index
	);

	// Printout Transaction Events
	let events = res.events.as_ref().unwrap();
	for event in events.iter() {
		let tx_index = match event.phase() {
			subxt::events::Phase::ApplyExtrinsic(x) => Some(x),
			_ => None,
		};

		println!(
			"Pallet Name: {}, Pallet Index: {}, Event Name: {}, Event Index: {}, Event Position: {}, Tx Index: {:?}",
			event.pallet_name(),
			event.pallet_index(),
			event.variant_name(),
			event.variant_index(),
			event.index(),
			tx_index,
		);
	}

	// Converts generic event to a specific one
	let event = events.find_first::<DataSubmitted>();
	let event = event.unwrap().unwrap();
	print!("Data Hash: {:?}, Who: {}", event.data_hash, event.who);

	// Converts generic transaction to a specific one
	let decoded = res.decode_as::<SubmitData>().await?.unwrap();
	let data = to_ascii(decoded.data.0).unwrap();
	println!("Data: {}", data);

	println!("Transaction Execute Finalization finished correctly");

	Ok(())
}

Options

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	run_app_id().await?;
	run_nonce().await?;
	run_tip().await?;
	run_mortality().await?;

	println!("Transaction Options finished correctly");

	Ok(())
}

async fn run_app_id() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	// Executing Transaction
	let app_id = 5u32;
	let tx = sdk.tx.data_availability.submit_data(vec![0, 1, 2]);
	let options = Options::new().app_id(app_id);
	let res = tx.execute_and_watch_inclusion(&account::alice(), options).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Check if the correct app id has been used
	let block = Block::new(&sdk.client, res.block_hash).await?;
	let block_txs = block.transactions(Filter::new().tx_hash(res.tx_hash));
	assert_eq!(block_txs.len(), 1);
	assert_eq!(block_txs.index(0).app_id(), Some(app_id));

	println!("Transaction Options App Id finished correctly");

	Ok(())
}

async fn run_nonce() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;
	let account = account::alice();

	// Executing Transaction
	let nonce = account::nonce(&sdk.client, &std::format!("{}", account.public_key().to_account_id())).await?;
	let tx = sdk.tx.data_availability.submit_data(vec![0, 1, 2]);
	let options = Options::new().nonce(nonce);
	let res = tx.execute_and_watch_inclusion(&account, options).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Check if the correct app id has been used
	let block = Block::new(&sdk.client, res.block_hash).await?;
	let block_txs = block.transactions(Filter::new().tx_hash(res.tx_hash));
	assert_eq!(block_txs.len(), 1);
	assert_eq!(block_txs.index(0).nonce(), Some(nonce));

	println!("Transaction Options Nonce finished correctly");

	Ok(())
}

async fn run_tip() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	// Executing Transaction
	let tip = SDK::one_avail();
	let tx = sdk.tx.data_availability.submit_data(vec![0, 1, 2]);
	let options = Options::new().tip(tip);
	let res = tx.execute_and_watch_inclusion(&account::alice(), options).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Check if the correct app id has been used
	let block = Block::new(&sdk.client, res.block_hash).await?;
	let block_txs = block.transactions(Filter::new().tx_hash(res.tx_hash));
	assert_eq!(block_txs.len(), 1);
	assert_eq!(block_txs.index(0).tip(), Some(tip));

	println!("Transaction Options Tip finished correctly");

	Ok(())
}

async fn run_mortality() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	// Executing Transaction
	let mortality = 8u64;
	let tx = sdk.tx.data_availability.submit_data(vec![0, 1, 2]);
	let options = Options::new().mortality(mortality);
	let res = tx.execute_and_watch_inclusion(&account::alice(), options).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Check if the correct app id has been used
	let block = Block::new(&sdk.client, res.block_hash).await?;
	let block_txs = block.transactions(Filter::new().tx_hash(res.tx_hash));
	assert_eq!(block_txs.len(), 1);

	let actual_mortality = block_txs.index(0).mortality().unwrap();
	let actual_mortality = match actual_mortality {
		subxt::utils::Era::Mortal { period, phase: _ } => period,
		_ => panic!("Should not be here"),
	};

	assert_eq!(actual_mortality, mortality);

	println!("Transaction Options Mortality finished correctly");

	Ok(())
}

Payment

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let account = account::alice();

	let key = String::from("My Key").into_bytes();
	let tx = sdk.tx.data_availability.create_application_key(key);
	let options = Options::new();

	let fee_details = tx.payment_query_fee_details(&account, Some(options)).await?;
	let inclusion_fee = fee_details.inclusion_fee.unwrap();
	println!(
		"Adjusted Weight Fee: {}, Len Fee: {}, Base Fee: {}",
		inclusion_fee.adjusted_weight_fee, inclusion_fee.len_fee, inclusion_fee.base_fee
	);

	let fee_details = tx.payment_query_call_fee_details().await?;
	let inclusion_fee = fee_details.inclusion_fee.unwrap();
	println!(
		"Adjusted Weight Fee: {}, Len Fee: {}, Base Fee: {}",
		inclusion_fee.adjusted_weight_fee, inclusion_fee.len_fee, inclusion_fee.base_fee
	);

	let info = tx.payment_query_info(&account, Some(options)).await?;
	println!(
		"ProofSize: {}, RefTime: {}, Class: {:?}, Partial Fee: {}",
		info.weight.proof_size, info.weight.ref_time, info.class, info.partial_fee
	);

	let info = tx.payment_query_call_info().await?;
	println!(
		"ProofSize: {}, RefTime: {}, Class: {:?}, Partial Fee: {}",
		info.weight.proof_size, info.weight.ref_time, info.class, info.partial_fee
	);

	println!("Transaction Options finished correctly");

	Ok(())
}

Proxy

use avail::{
	proxy::events::{ProxyAdded, ProxyExecuted, ProxyRemoved, PureCreated},
	runtime_types::{
		da_control::pallet::Call::create_application_key, pallet_balances::pallet::Call::transfer_keep_alive,
	},
};
use avail_rust::{
	avail::runtime_types::da_runtime::{impls::ProxyType, RuntimeCall},
	prelude::*,
};
use std::time::SystemTime;

pub async fn run() -> Result<(), ClientError> {
	run_normal_proxy().await?;
	run_pure_proxy().await?;
	run_proxy_failure().await?;

	println!("Proxy finished correctly");

	Ok(())
}

pub async fn run_normal_proxy() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let proxy_account = account::bob();
	let prox_account_multi = MultiAddress::from(proxy_account.public_key().to_account_id());
	let main_account = account::ferdie();
	let main_account_multi = MultiAddress::from(main_account.public_key().to_account_id());

	// Creating Proxy
	let proxy_type = ProxyType::Any;
	let tx = sdk
		.tx
		.proxy
		.add_proxy(prox_account_multi.clone(), proxy_type.clone(), 0);
	let res = tx.execute_and_watch_inclusion(&main_account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Finding Proxy Added Event
	let tx_events = res.events.as_ref().unwrap();
	let event = tx_events.find_first::<ProxyAdded>();
	let event = event.unwrap().unwrap();
	println!(
		"Delegatee: {}, Delegator: {}, ProxyTpe: {:?}, Delay: {}",
		event.delegatee, event.delegator, event.proxy_type, event.delay
	);

	// Executing the Proxy.Proxy() call
	let call = transfer_keep_alive {
		dest: prox_account_multi.clone(),
		value: SDK::one_avail(),
	};
	let call = RuntimeCall::Balances(call);

	let tx = sdk.tx.proxy.proxy(main_account_multi, None, call);
	let res = tx.execute_and_watch_inclusion(&proxy_account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Finding ProxyExecuted event
	let tx_events = res.events.as_ref().unwrap();
	let event = tx_events.find_first::<ProxyExecuted>();
	let event = event.unwrap().unwrap();
	assert!(event.result.is_ok());

	// Removing Proxy
	let tx = sdk.tx.proxy.remove_proxy(prox_account_multi, proxy_type, 0);
	let res = tx.execute_and_watch_inclusion(&main_account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Finding for EventProxyRemoved event.
	let tx_events = res.events.as_ref().unwrap();
	let event = tx_events.find_first::<ProxyRemoved>();
	let event = event.unwrap().unwrap();
	println!(
		"Delegatee: {}, Delegator: {}, ProxyTpe: {:?}, Delay: {}",
		event.delegatee, event.delegator, event.proxy_type, event.delay
	);

	Ok(())
}

pub async fn run_pure_proxy() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let main_account = account::ferdie();

	// Creating Proxy
	let proxy_type = ProxyType::Any;
	let tx = sdk.tx.proxy.create_pure(proxy_type.clone(), 0, 0);
	let res = tx.execute_and_watch_inclusion(&main_account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Finding PureCreated Event
	let tx_events = res.events.as_ref().unwrap();
	let event = tx_events.find_first::<PureCreated>();
	let event = event.unwrap().unwrap();
	println!(
		"Pure: {}, Who: {}, ProxyTpe: {:?}, Disambiguation Index: {}",
		event.pure, event.who, event.proxy_type, event.disambiguation_index
	);
	let pure_proxy = event.pure;
	let pure_proxy_multi = MultiAddress::from(pure_proxy);

	// Executing the Proxy.Proxy() call
	let time = std::format!("{:?}", SystemTime::now());
	let key = time.into_bytes();
	let call = create_application_key { key: BoundedVec(key) };
	let call = RuntimeCall::DataAvailability(call);

	let tx = sdk.tx.proxy.proxy(pure_proxy_multi, None, call);
	let res = tx.execute_and_watch_inclusion(&main_account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Finding ProxyExecuted event
	let tx_events = res.events.as_ref().unwrap();
	let event = tx_events.find_first::<ProxyExecuted>();
	let event = event.unwrap().unwrap();
	assert!(event.result.is_ok());

	Ok(())
}

pub async fn run_proxy_failure() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let proxy_account = account::bob();
	let prox_account_multi = MultiAddress::from(proxy_account.public_key().to_account_id());
	let main_account = account::ferdie();
	let main_account_multi = MultiAddress::from(main_account.public_key().to_account_id());

	// Creating Proxy
	let proxy_type = ProxyType::NonTransfer;
	let tx = sdk
		.tx
		.proxy
		.add_proxy(prox_account_multi.clone(), proxy_type.clone(), 0);
	let res = tx.execute_and_watch_inclusion(&main_account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Executing the Proxy.Proxy() call
	let call = transfer_keep_alive {
		dest: prox_account_multi.clone(),
		value: SDK::one_avail(),
	};
	let call = RuntimeCall::Balances(call);

	let tx = sdk.tx.proxy.proxy(main_account_multi, None, call);
	let res = tx.execute_and_watch_inclusion(&proxy_account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Finding ProxyExecuted event
	let tx_events = res.events.as_ref().unwrap();
	let event = tx_events.find_first::<ProxyExecuted>();
	let event = event.unwrap().unwrap();
	assert!(event.result.is_err());
	println!("Proxy error: {:?}", event.result.unwrap_err());

	// Removing Proxy
	let tx = sdk.tx.proxy.remove_proxy(prox_account_multi, proxy_type, 0);
	let res = tx.execute_and_watch_inclusion(&main_account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));
	Ok(())
}

Custom Client

use avail_rust::prelude::*;
use std::time::Duration;
use subxt::backend::rpc::{
	reconnecting_rpc_client::{ExponentialBackoff, RpcClient as ReconnectingRpcClient},
	RpcClient,
};

pub async fn run() -> Result<(), ClientError> {
	let rpc_client = ReconnectingRpcClient::builder()
		.retry_policy(
			ExponentialBackoff::from_millis(1000)
				.max_delay(Duration::from_secs(3))
				.take(3),
		)
		.build(SDK::local_endpoint())
		.await
		.map_err(|e| e.to_string())?;
	let rpc_client = RpcClient::new(rpc_client);
	let online_client = AOnlineClient::from_rpc_client(rpc_client.clone()).await?;
	let client = Client::new(online_client, rpc_client);

	let _sdk = SDK::new_custom(client).await?;

	Ok(())
}

HTTP Client

use avail_rust::prelude::*;
use std::time::SystemTime;

type ApplicationKeyCreatedEvent = avail::data_availability::events::ApplicationKeyCreated;

pub async fn run() -> Result<(), ClientError> {
	run_transaction().await?;
	run_block().await?;

	println!("HTTP Client finished correctly");
	Ok(())
}

pub async fn run_transaction() -> Result<(), ClientError> {
	let sdk = SDK::new_http(SDK::local_http_endpoint()).await?;

	let account = account::alice();

	// Application Key Creation
	let time = std::format!("{:?}", SystemTime::now());
	let key = time.into_bytes();
	let tx = sdk.tx.data_availability.create_application_key(key);
	let res = tx.execute_and_watch_inclusion(&account, Options::default()).await?;
	assert_eq!(res.is_successful(), Some(true));

	let events = res.events.unwrap();
	let event = events.find_first::<ApplicationKeyCreatedEvent>().unwrap();
	let Some(event) = event else {
		return Err("Failed to get Application Key Created Event".into());
	};
	let app_id = event.id.0;

	// Data Submission
	let data = String::from("My Data").into_bytes();
	let options = Options::new().app_id(app_id);
	let tx = sdk.tx.data_availability.submit_data(data);
	let res = tx.execute_and_watch_inclusion(&account, options).await?;
	assert_eq!(res.is_successful(), Some(true));

	Ok(())
}

pub async fn run_block() -> Result<(), ClientError> {
	let sdk = SDK::new_http(SDK::turing_http_endpoint()).await?;
	let block_hash = new_h256_from_hex("0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")?;

	let block = Block::new(&sdk.client, block_hash).await?;

	// All Transactions
	let block_transactions = block.transactions(Filter::default());
	assert_eq!(block_transactions.len(), 9, "Transaction count must be 9");

	// Printout Block Transactions
	for tx in block_transactions.iter().take(2) {
		println!("Tx Index: {}", tx.tx_index());
	}

	let blobs = block.data_submissions(Filter::default());
	assert_eq!(blobs.len(), 4, "Blobs must present 4 times");

	// Printout All Block Blobs
	for blob in blobs.iter().take(2) {
		println!("Tx Index: {}", blob.tx_index,);
	}

	Ok(())
}

RPC

use avail_rust::{prelude::*, primitives::kate};

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	// author_rotate_keys
	let value = rpc::author::rotate_keys(&sdk.client).await?;
	dbg!(value);
	/*	Output
	SessionKeys {
		babe: Public(...),
		grandpa: Public(...),
		im_online: Public(...),
		authority_discovery: Public(...),
	}
	*/

	// author_submit_extrinsic
	let account = account::alice();
	let account_id = account.public_key().to_account_id();
	let call = avail::tx().data_availability().submit_data(BoundedVec(vec![0, 1, 2]));
	let params = Options::new().build(&sdk.client, &account_id).await?.build().await?;
	let signed_call = sdk
		.client
		.online_client
		.tx()
		.create_signed(&call, &account, params)
		.await?;
	let extrinsic = signed_call.encoded();
	let value = rpc::author::submit_extrinsic(&sdk.client, extrinsic).await?;
	dbg!(value);
	/*	Output
		"0x56edc7516bb403f0d812f0f91dea5e36b46bbb31f7b69e78469652f74882377d"
	*/

	// chain_get_block
	let value = rpc::chain::get_block(&sdk.client, None).await?;
	dbg!(value);
	/*	Output
	BlockDetails {
		block: Block {
			header: AvailHeader {
				parent_hash: 0x4753c70a0652f50ee24f19ea402c1377ce5ab08fc5e0f801123e8116e5e1fcf8,
				number: 495,
				state_root: 0x22470c3402bee3cd95c10b9303e61019aaec0603cbfc197eca646c94ba9332f1,
				extrinsics_root: 0x609ed0e14f3252c9f59ab59004ea458d7927a5bd81f241651634266b7098f415,
				digest: Digest {...},
				extension: V3(
					HeaderExtension {
						app_lookup: CompactDataLookup {
							size: 0,
							index: [],
						},
						commitment: KateCommitment {
							rows: 0,
							cols: 0,
							commitment: [],
							data_root: 0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5,
						},
					},
				),
			},
			extrinsics: [...],
		},
		justifications: None,
	}
	*/

	// chain_get_block_hash
	let value = rpc::chain::get_block_hash(&sdk.client, None).await?;
	dbg!(value);
	/*	Output
		0xc4e0a9a2ef80ddc1d70c9946d8a6f86ca4b15053b39ba56709222f01ddc64561
	*/

	// chain_get_finalized_head
	let value = rpc::chain::get_finalized_head(&sdk.client).await?;
	dbg!(value);
	/*	Output
		0x2c896c9faae4e111f1fbeb955be5e999a328846969b59a7a7c64eadc4701122a
	*/

	// chain_get_header
	let value = rpc::chain::get_header(&sdk.client, None).await?;
	dbg!(value);
	/*	Output
	AvailHeader {
		parent_hash: 0x4753c70a0652f50ee24f19ea402c1377ce5ab08fc5e0f801123e8116e5e1fcf8,
		number: 495,
		state_root: 0x22470c3402bee3cd95c10b9303e61019aaec0603cbfc197eca646c94ba9332f1,
		extrinsics_root: 0x609ed0e14f3252c9f59ab59004ea458d7927a5bd81f241651634266b7098f415,
		digest: Digest {...},
		extension: V3(
			HeaderExtension {
				app_lookup: CompactDataLookup {
					size: 0,
					index: [],
				},
				commitment: KateCommitment {
					rows: 0,
					cols: 0,
					commitment: [],
					data_root: 0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5,
				},
			},
		),
	}
	*/

	// system_account_next_index
	let account = String::from("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY");
	let value = rpc::system::account_next_index(&sdk.client, account).await?;
	dbg!(value);
	/*	Output
		2
	*/

	// system_chain
	let value = rpc::system::chain(&sdk.client).await?;
	dbg!(value);
	/*	Output
		"Avail Development Network"
	*/

	// system_chain_type
	let value = rpc::system::chain_type(&sdk.client).await?;
	dbg!(value);
	/*	Output
		"Development"
	*/

	// system_health
	let value = rpc::system::health(&sdk.client).await?;
	dbg!(value);
	/*	Output
	SystemHealth {
		peers: 0,
		is_syncing: false,
		should_have_peers: false,
	}
	*/

	// system_local_listen_addresses
	let value = rpc::system::local_listen_addresses(&sdk.client).await?;
	dbg!(value);
	/*	Output
	value = [
		"/ip6/fe81::a234:6e32:1034:3c3b/tcp/30333/p2p/12D3KooWRajsCfp1NR15iN7PcwcFAG3LB7iGDKUBosHkevNRQLYs",
		"/ip4/192.168.1.103/tcp/30333/p2p/12D3KooWRajsCfp1NR15iN7PcwcFAG3LB7iGDKUBosHkevNRQLYs",
		"/ip6/::1/tcp/30333/p2p/12D3KooWRajsCfp1NR15iN7PcwcFAG3LB7iGDKUBosHkevNRQLYs",
		"/ip4/127.0.0.1/tcp/30333/p2p/12D3KooWRajsCfp1NR15iN7PcwcFAG3LB7iGDKUBosHkevNRQLYs",
	]
	*/

	// system_local_peer_id
	let value = rpc::system::local_peer_id(&sdk.client).await?;
	dbg!(value);
	/*	Output
		"12D3KooWRajsCfp1NR15iN7PcwcFAG3LB7iGDKUBosHkevNRQLYs"
	*/

	// system_name
	let value = rpc::system::name(&sdk.client).await?;
	dbg!(value);
	/*	Output
		"Avail Node"
	*/

	// system_node_roles
	let value = rpc::system::node_roles(&sdk.client).await?;
	dbg!(value);
	/*	Output
	[
		Authority,
	]
	*/

	// system_peers
	let value = rpc::system::peers(&sdk.client).await?;
	dbg!(value);
	/*	Output
		[]
	*/

	// system_properties
	let value = rpc::system::properties(&sdk.client).await?;
	dbg!(value);
	/*	Output
	{
		"ss58Format": Number(42),
		"tokenDecimals": Number(18),
		"tokenSymbol": String("AVAIL"),
	}
	*/

	// system_system_sync_state
	let value = rpc::system::sync_state(&sdk.client).await?;
	dbg!(value);
	/*	Output
	SyncState {
		starting_block: 0,
		current_block: 495,
		highest_block: 495,
	}
	*/

	// system_version
	let value = rpc::system::version(&sdk.client).await?;
	dbg!(value);
	/*	Output
		"2.2.1-55da578d34b"
	*/
	// state_get_runtime_version
	let value = rpc::state::get_runtime_version(&sdk.client, None).await?;
	dbg!(value);
	/*	Output
	RuntimeVersion {
		spec_version: 39,
		transaction_version: 1,
		other: {
			"stateVersion": Number(1),
			"authoringVersion": Number(12),
			"specName": String("avail"),
			"implVersion": Number(0),
			"apis": Array [...],
			"implName": String("avail"),
		},
	}
	*/

	// kate_block_length
	let value = rpc::kate::block_length(&sdk.client, None).await?;
	dbg!(value);
	/*	Output
	BlockLength {
		max: PerDispatchClass {
			normal: 2097152,
			operational: 2097152,
			mandatory: 2097152,
		},
		cols: BlockLengthColumns(
			256,
		),
		rows: BlockLengthRows(
			256,
		),
		chunk_size: 32,
	}
	*/

	// kate_query_data_proof
	let data = String::from("My Data").into_bytes();
	let tx = sdk.tx.data_availability.submit_data(data);
	let result = tx
		.execute_and_watch_finalization(&account::alice(), Options::new().app_id(1))
		.await?;
	let (tx_index, block_hash) = (result.tx_index, Some(result.block_hash));
	let value = rpc::kate::query_data_proof(&sdk.client, tx_index, block_hash).await?;
	dbg!(value);
	/*	Output
	ProofResponse {
		data_proof: DataProof {
			roots: TxDataRoots {
				data_root: 0xd6e516bbf0b0d964a6a6a41a18c58a2eac4757001c2338a8601c4cc961332fda,
				blob_root: 0x29c73490baca9fe2b11095a69294de4b4a86bcb3a2eb3cd04b51dfdd0b4030f9,
				bridge_root: 0x0000000000000000000000000000000000000000000000000000000000000000,
			},
			proof: [],
			number_of_leaves: 1,
			leaf_index: 0,
			leaf: 0x47a59a7805e0bfe350ee0395d426c15770edc03fee72aa6532b5bbcffaf28030,
		},
		message: None,
	}
	*/

	// kate_query_proof
	let cells = vec![kate::Cell::from((0u32, 0u32))];
	let value = rpc::kate::query_proof(&sdk.client, cells, block_hash).await?;
	dbg!(value);
	/*	Output
	[
		(
			2178534751726990040338027377623275511556638494274780568875624948149315822336,
			GProof(
				[...],
			),
		),
	]
	*/

	// kate_query_rows
	let rows = vec![0u32];
	let value = rpc::kate::query_rows(&sdk.client, rows, block_hash).await?;
	dbg!(value);
	/*	Output
	[
		[
			2178534751726990040338027377623275511556638494274780568875624948149315822336,
			69809044805081050561201039752112594468796256047454289799440609083602104564736,
			26941852917393734161602180963833199552029986735939578666038548832600818441216,
			14351520191331507525755130937317610561547699892218140156652644610507664261120,
		],
	]
	*/

	Ok(())
}

Storage

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	println!("da_app_keys");
	da_app_keys().await?;
	println!("da_app_keys_iter");
	da_app_keys_iter().await?;
	println!("da_next_app_id");
	da_next_app_id().await?;
	println!("staking_active_era");
	staking_active_era().await?;
	println!("staking_bonded");
	staking_bonded().await?;
	println!("staking_bonded_iter");
	staking_bonded_iter().await?;
	println!("system_account");
	system_account().await?;
	println!("system_account_iter");
	system_account_iter().await?;

	println!("Storage finished correctly");

	Ok(())
}

pub async fn da_app_keys() -> Result<(), ClientError> {
	use avail::data_availability::storage::types::app_keys::Param0;

	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let key = String::from("Reserved-1").as_bytes().to_vec();
	let key = Param0 { 0: key };

	let block_hash = sdk.client.best_block_hash().await?;
	let storage = sdk.client.storage().at(block_hash);
	let address = avail::storage().data_availability().app_keys(key);
	let result = storage.fetch(&address).await?;

	dbg!(result);
	/* Output
	AppKeyInfo {
		owner: AccountId32(...),
		id: AppId(
			1,
		),
	}
	*/

	Ok(())
}

pub async fn da_app_keys_iter() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let block_hash = sdk.client.best_block_hash().await?;
	let storage = sdk.client.storage().at(block_hash);
	let address = avail::storage().data_availability().app_keys_iter();
	let mut results = storage.iter(address).await?;

	while let Some(Ok(kv)) = results.next().await {
		let key = (&kv.key_bytes[49..]).to_vec();
		let key = String::from_utf8(key).unwrap();

		println!("Key: {:?}", key);
		println!("Value: {:?}", kv.value);
	}
	/* Output
		Key: "Reserved-2"
		Value: AppKeyInfo { owner: AccountId32(...), id: AppId(2) }
		Key: "Reserved-8"
		Value: AppKeyInfo { owner: AccountId32(...), id: AppId(8) }
		Key: "Reserved-1"
		Value: AppKeyInfo { owner: AccountId32(...) id: AppId(1) }
		Key: "Reserved-9"
		Value: AppKeyInfo { owner: AccountId32(...), id: AppId(9) }
		Key: "Reserved-4"
		Value: AppKeyInfo { owner: AccountId32(...), id: AppId(4) }
		Key: "Reserved-5"
		Value: AppKeyInfo { owner: AccountId32(...), id: AppId(5) }
		Key: "Reserved-7"
		Value: AppKeyInfo { owner: AccountId32(...), id: AppId(7) }
		Key: "Avail"
		Value: AppKeyInfo { owner: AccountId32(...), id: AppId(0) }
		Key: "Reserved-3"
		Value: AppKeyInfo { owner: AccountId32(...), id: AppId(3) }
		Key: "Reserved-6"
		Value: AppKeyInfo { owner: AccountId32(...), id: AppId(6) }
	*/

	Ok(())
}

pub async fn da_next_app_id() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let block_hash = sdk.client.best_block_hash().await?;
	let storage = sdk.client.storage().at(block_hash);
	let address = avail::storage().data_availability().next_app_id();
	let result = storage.fetch_or_default(&address).await?;

	dbg!(result);
	/* Output
		AppId(10)
	*/

	Ok(())
}

pub async fn staking_active_era() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let block_hash = sdk.client.best_block_hash().await?;
	let storage = sdk.client.storage().at(block_hash);
	let address = avail::storage().staking().active_era();
	let result = storage.fetch(&address).await?;

	dbg!(result);
	/* Output
	ActiveEraInfo {
		index: 13,
		start: Some(
			1732612788000,
		),
	}
	*/

	Ok(())
}

pub async fn staking_bonded() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let account_id = account::account_id_from_str("5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY")?; // Alice_Stash

	let block_hash = sdk.client.best_block_hash().await?;
	let storage = sdk.client.storage().at(block_hash);
	let address = avail::storage().staking().bonded(account_id);
	let result = storage.fetch(&address).await?;

	dbg!(result);
	/* Output
		AccountId32(...)
	*/

	Ok(())
}

pub async fn staking_bonded_iter() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let block_hash = sdk.client.best_block_hash().await?;
	let storage = sdk.client.storage().at(block_hash);
	let storage_query = avail::storage().staking().bonded_iter();
	let mut results = storage.iter(storage_query).await?;

	while let Some(Ok(kv)) = results.next().await {
		let key = kv.key_bytes.last_chunk::<32>().unwrap();
		let key = AccountId::from(*key);

		println!("Key: {:?}", key.to_string());
		println!("Value: {:?}", kv.value);
	}
	/* Output
		Key: "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY"
		Value: AccountId32(...)
	*/

	Ok(())
}

pub async fn system_account() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let account = account::alice();
	let account_id = account.public_key().to_account_id();

	let block_hash = sdk.client.best_block_hash().await?;
	let storage = sdk.client.storage().at(block_hash);
	let address = avail::storage().system().account(account_id);
	let result = storage.fetch(&address).await?;

	if let Some(account) = result {
		println!("Consumers: {}", account.consumers);
		println!("Data: {:?}", account.data);
		println!("Nonce: {}", account.nonce);
		println!("Providers: {}", account.providers);
		println!("Sufficients: {}", account.sufficients);
	}
	/* Output
		Consumers: 0
		Data: AccountData { free: 10000000000000000000000000, reserved: 0, frozen: 0, flags: ExtraFlags(170141183460469231731687303715884105728) }
		Nonce: 0
		Providers: 1
		Sufficients: 0
	*/

	Ok(())
}

pub async fn system_account_iter() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let block_hash = sdk.client.best_block_hash().await?;
	let storage = sdk.client.storage().at(block_hash);
	let address = avail::storage().system().account_iter();
	let mut results = storage.iter(address).await?;

	while let Some(Ok(kv)) = results.next().await {
		let key = kv.key_bytes.last_chunk::<32>().unwrap();
		let key = AccountId::from(*key);

		println!("Key: {:?}", key.to_string());
		println!("Value: {:?}", kv.value);
	}
	/* Output
		Key: "5FCfAonRZgTFrTd9HREEyeJjDpT397KMzizE6T3DvebLFE7n"
		Value: AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 0, data: AccountData { free: 10000000000000000000000000, reserved: 0, frozen: 0, flags: ExtraFlags(170141183460469231731687303715884105728) } }

		Key: "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL"
		Value: AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 0, data: AccountData { free: 10000000000000000000000000, reserved: 0, frozen: 0, flags: ExtraFlags(170141183460469231731687303715884105728) } }

		Key: "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY"
		Value: AccountInfo { nonce: 0, consumers: 3, providers: 1, sufficients: 0, data: AccountData { free: 10000001075151923366255874, reserved: 0, frozen: 100000000000000000000000, flags: ExtraFlags(170141183460469231731687303715884105728) } }

		Key: "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
		Value: AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 0, data: AccountData { free: 10000000000000000000000000, reserved: 0, frozen: 0, flags: ExtraFlags(170141183460469231731687303715884105728) } }
		...
	*/

	Ok(())
}

Validator

use avail_rust::{
	prelude::*,
	transactions::staking::{Commission, RewardDestination},
};

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	let account = account::charlie();

	// Bond min_validator_bond or 1 AVAIL token
	let storage = sdk.client.storage().at_latest().await?;
	let min_validator_bond = storage
		.fetch(&avail::storage().staking().min_validator_bond())
		.await?
		.unwrap_or_else(|| SDK::one_avail());

	let payee = RewardDestination::Staked;

	// Bond
	let tx = sdk.tx.staking.bond(min_validator_bond, payee);
	let res = tx.execute_and_watch_inclusion(&account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Generate Session Keys
	let keys = rpc::author::rotate_keys(&sdk.client).await?;

	// Set Keys
	let tx = sdk.tx.session.set_keys(keys);
	let res = tx.execute_and_watch_inclusion(&account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));

	// Validate
	let commission = Commission::new(10)?;
	let tx = sdk.tx.staking.validate(commission, false);
	let res = tx.execute_and_watch_inclusion(&account, Options::new()).await?;
	assert_eq!(res.is_successful(), Some(true));

	Ok(())
}

Transaction State

use avail_rust::prelude::*;

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::local_endpoint()).await?;

	// Transaction will be signed, and sent.
	//
	// There is no guarantee that the transaction was executed at all. It might have been
	// dropped or discarded for various reasons. The caller is responsible for querying future
	// blocks in order to determine the execution status of that transaction.
	let tx = sdk.tx.data_availability.submit_data(vec![0, 1, 2]);
	let tx_hash = tx.execute(&account::alice(), Options::new().app_id(1)).await?;
	println!("Tx Hash: {:?}", tx_hash);

	let result = loop {
		let res = sdk.client.transaction_state(&tx_hash, false).await?;
		if !res.is_empty() {
			break res;
		}
		std::thread::sleep(std::time::Duration::from_secs(1));
	};
	assert_eq!(result.len(), 1);

	println!(
		"Block Hash: {:?}, Block Height: {}, Tx Hash: {:?}, Tx Index {}",
		result[0].block_hash, result[0].block_height, result[0].tx_hash, result[0].tx_index
	);
	println!(
		"Pallet Index: {:?}, Call Index: {}, Tx Success: {:?}, Is Finalized {}",
		result[0].pallet_index, result[0].call_index, result[0].tx_success, result[0].is_finalized
	);

	println!("Transaction State finished correctly");

	Ok(())
}

Indexer

use std::{
	future::Future,
	sync::{atomic::AtomicBool, Arc, Mutex},
	time::Duration,
};

use avail_rust::prelude::*;
use tokio::task::JoinHandle;

type SharedLock<T> = Arc<Mutex<T>>;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Kind {
	Manual,
	Stream,
}

pub async fn run() -> Result<(), ClientError> {
	let sdk = SDK::new(SDK::turing_endpoint()).await?;
	let mut indexer = Indexer::new(sdk.clone());
	indexer.run(Kind::Stream);

	// Fetching blocks in procedural way
	let mut sub = indexer.subscribe().await;
	for _ in 0..3 {
		let block = sub.fetch().await;
		println!("Current: Block Height: {}, Block Hash: {:?}", block.height, block.hash)
	}

	// Fetching historical blocks
	sub.block_height -= 100;
	for _ in 0..3 {
		let block = sub.fetch().await;
		println!(
			"Historical: Block Height: {}, Block Hash: {:?}",
			block.height, block.hash
		)
	}

	// Callback
	let mut sub = indexer.callback(callback).await;
	tokio::time::sleep(Duration::from_secs(25)).await;

	sub.shutdown();
	indexer.shutdown();

	tokio::time::sleep(Duration::from_secs(3)).await;

	Ok(())
}

async fn callback(block: IndexedBlock) {
	println!("Callback: Block Height: {}, Block Hash: {:?}", block.height, block.hash)
}

#[derive(Clone)]
struct Indexer {
	block: SharedLock<Option<IndexedBlock>>,
	sdk: Arc<SDK>,
	thread: SharedLock<Option<JoinHandle<()>>>,
}

impl Indexer {
	pub fn new(sdk: SDK) -> Self {
		Self {
			block: Arc::new(Mutex::new(None)),
			sdk: Arc::new(sdk),
			thread: Arc::new(Mutex::new(None)),
		}
	}
	pub fn run(&mut self, kind: Kind) {
		if self.thread.lock().unwrap().is_some() {
			return;
		}

		let block = self.block.clone();
		let sdk = self.sdk.clone();
		let t = tokio::spawn(async move {
			println!("Kind: {:?}", kind);
			match kind {
				Kind::Manual => Self::task_man(block, sdk).await,
				Kind::Stream => Self::task_sub(block, sdk).await,
			};
		});

		self.thread = Arc::new(Mutex::new(Some(t)))
	}

	pub fn shutdown(&mut self) {
		let lock = self.thread.lock().unwrap();
		let Some(t) = lock.as_ref() else {
			return;
		};
		t.abort();
	}

	pub async fn get_block(&self, block_height: u32) -> IndexedBlock {
		loop {
			let block = self.block.lock().unwrap().clone();

			let Some(block) = block else {
				tokio::time::sleep(Duration::from_secs(5)).await;
				continue;
			};

			if block_height > block.height {
				tokio::time::sleep(Duration::from_secs(5)).await;
				continue;
			}

			if block_height == block.height {
				return block;
			}

			let block_hash = self.sdk.client.block_hash(block_height).await.unwrap();
			let block = Block::new(&self.sdk.client, block_hash.clone()).await.unwrap();

			return IndexedBlock {
				height: block_height,
				hash: block_hash,
				block,
			};
		}
	}

	pub async fn subscribe(&self) -> Subscription {
		let block_height = loop {
			let height = {
				let block = self.block.lock().unwrap();
				block.as_ref().map(|x| x.height)
			};

			if height.is_none() {
				tokio::time::sleep(Duration::from_secs(5)).await;
				continue;
			}

			break height.unwrap();
		};

		Subscription::new(block_height, self.clone())
	}

	pub async fn callback<F>(&self, cb: fn(IndexedBlock) -> F) -> Subscription
	where
		F: Future + std::marker::Send + 'static,
	{
		let sub = self.subscribe().await;
		let mut sub2 = sub.clone();
		tokio::spawn(async move {
			loop {
				let block = sub2.fetch().await;
				cb(block).await;
			}
		});

		sub
	}

	async fn task_man(shared_block: SharedLock<Option<IndexedBlock>>, sdk: Arc<SDK>) {
		loop {
			let new_hash = sdk.client.finalized_block_hash().await.unwrap();
			let cur_hash = {
				let block = shared_block.lock().unwrap();
				block.as_ref().map(|x| x.hash)
			};

			if cur_hash.is_some_and(|x| x == new_hash) {
				tokio::time::sleep(Duration::from_secs(15)).await;
				continue;
			}

			let new_block = Block::new(&sdk.client, new_hash).await.unwrap();
			let new_height = sdk.client.block_number(new_hash.clone()).await.unwrap();

			let mut cur_block = shared_block.lock().unwrap();
			*cur_block = Some(IndexedBlock {
				height: new_height,
				hash: new_hash,
				block: new_block,
			})
		}
	}

	async fn task_sub(shared_block: SharedLock<Option<IndexedBlock>>, sdk: Arc<SDK>) {
		let mut stream = sdk.client.blocks().subscribe_finalized().await.unwrap();
		loop {
			let block = stream.next().await.unwrap();
			let block = match block {
				Ok(b) => b,
				Err(e) => {
					if e.is_disconnected_will_reconnect() {
						println!("The RPC connection was lost and we may have missed a few blocks");
						continue;
					}

					panic!("Something is wrong");
				},
			};

			let height = block.number();
			let hash = block.hash();
			let block = Block::from_block(block).await.unwrap();

			let mut cur_block = shared_block.lock().unwrap();
			*cur_block = Some(IndexedBlock { height, hash, block })
		}
	}
}

#[derive(Clone)]
struct Subscription {
	pub indexer: Indexer,
	pub block_height: u32,
	pub shutdown: Arc<AtomicBool>,
}

impl Subscription {
	pub fn new(block_height: u32, indexer: Indexer) -> Self {
		Self {
			indexer,
			block_height,
			shutdown: Arc::new(AtomicBool::new(false)),
		}
	}

	pub async fn fetch(&mut self) -> IndexedBlock {
		let block = self.indexer.get_block(self.block_height).await;
		self.block_height += 1;

		block
	}

	pub fn shutdown(&mut self) {
		self.shutdown.store(false, std::sync::atomic::Ordering::Relaxed);
	}
}

#[derive(Clone)]
struct IndexedBlock {
	height: u32,
	hash: H256,
	block: Block,
}