avail_rust_client/
transaction_api.rs

1//! Builders for transactions targeting specific Avail pallets.
2
3use crate::{Client, SubmittableTransaction};
4use avail_rust_core::{
5	AccountId, AccountIdLike, ExtrinsicCall, H256, MultiAddress,
6	avail::{
7		self,
8		multisig::types::Timepoint,
9		nomination_pools::types::{BondExtraValue, ClaimPermission, ConfigOpAccount, PoolState},
10		proxy::types::ProxyType,
11		staking::types::{RewardDestination, ValidatorPrefs},
12	},
13	types::{
14		HashString,
15		metadata::{MultiAddressLike, StringOrBytes},
16		substrate::Weight,
17	},
18};
19
20/// Entry point for constructing pallet-specific transaction builders.
21///
22/// Each accessor clones the underlying [`Client`] and returns a lightweight helper that can compose
23/// extrinsics without contacting the node. The returned builders produce [`SubmittableTransaction`]s
24/// which must be signed—and optionally submitted—separately.
25pub struct TransactionApi(pub(crate) Client);
26impl TransactionApi {
27	/// Returns helpers for composing `balances` pallet extrinsics.
28	///
29	/// # Returns
30	/// Returns a [`Balances`] builder that clones this client.
31	pub fn balances(&self) -> Balances {
32		Balances(self.0.clone())
33	}
34
35	/// Returns helpers for composing data availability submissions.
36	///
37	/// # Returns
38	/// Returns a [`DataAvailability`] builder that clones this client.
39	pub fn data_availability(&self) -> DataAvailability {
40		DataAvailability(self.0.clone())
41	}
42
43	/// Returns helpers for multisig transaction approval flows.
44	///
45	/// # Returns
46	/// Returns a [`Multisig`] builder that clones this client.
47	pub fn multisig(&self) -> Multisig {
48		Multisig(self.0.clone())
49	}
50
51	/// Returns helpers for batching extrinsics via the utility pallet.
52	///
53	/// # Returns
54	/// Returns a [`Utility`] builder that clones this client.
55	pub fn utility(&self) -> Utility {
56		Utility(self.0.clone())
57	}
58
59	/// Returns helpers for proxy management extrinsics.
60	///
61	/// # Returns
62	/// Returns a [`Proxy`] builder that clones this client.
63	pub fn proxy(&self) -> Proxy {
64		Proxy(self.0.clone())
65	}
66
67	/// Returns helpers for staking-related extrinsics.
68	///
69	/// # Returns
70	/// Returns a [`Staking`] builder that clones this client.
71	pub fn staking(&self) -> Staking {
72		Staking(self.0.clone())
73	}
74
75	/// Returns helpers for Vector message passing extrinsics.
76	///
77	/// # Returns
78	/// Returns a [`Vector`] builder that clones this client.
79	pub fn vector(&self) -> Vector {
80		Vector(self.0.clone())
81	}
82
83	/// Returns helpers for system-level extrinsics.
84	///
85	/// # Returns
86	/// Returns a [`System`] builder that clones this client.
87	pub fn system(&self) -> System {
88		System(self.0.clone())
89	}
90
91	/// Returns helpers for nomination pool extrinsics.
92	///
93	/// # Returns
94	/// Returns a [`NominationPools`] builder that clones this client.
95	pub fn nomination_pools(&self) -> NominationPools {
96		NominationPools(self.0.clone())
97	}
98
99	/// Returns helpers for validator session key management.
100	///
101	/// # Returns
102	/// Returns a [`Session`] builder that clones this client.
103	pub fn session(&self) -> Session {
104		Session(self.0.clone())
105	}
106}
107
108/// Builds extrinsics for the `session` pallet.
109///
110/// The helper clones the underlying client; composing calls does not contact the node until the
111/// resulting [`SubmittableTransaction`] is signed or submitted.
112pub struct Session(Client);
113impl Session {
114	/// Updates the node's session keys with new authorities and proof data.
115	///
116	/// # Panics
117	/// Panics when any supplied key fails to decode into an `H256` hash.
118	///
119	/// # Arguments
120	/// * `babe` - BABE authority key encoded as a hash string.
121	/// * `grandpa` - GRANDPA authority key encoded as a hash string.
122	/// * `authority_discovery` - Authority discovery key encoded as a hash string.
123	/// * `im_online` - Im-online session key encoded as a hash string.
124	/// * `proof` - Proof bytes returned by the session key generator.
125	///
126	/// # Returns
127	/// Returns a [`SubmittableTransaction`] that sets the supplied session keys.
128	///
129	/// # Errors
130	/// Does not perform network calls; transaction construction never fails.
131	pub fn set_key(
132		&self,
133		babe: impl Into<HashString>,
134		grandpa: impl Into<HashString>,
135		authority_discovery: impl Into<HashString>,
136		im_online: impl Into<HashString>,
137		proof: Vec<u8>,
138	) -> SubmittableTransaction {
139		let babe: HashString = babe.into();
140		let babe: H256 = babe.try_into().expect("Invalid string for H256");
141
142		let grandpa: HashString = grandpa.into();
143		let grandpa: H256 = grandpa.try_into().expect("Invalid string for H256");
144
145		let authority_discovery: HashString = authority_discovery.into();
146		let authority_discovery: H256 = authority_discovery.try_into().expect("Invalid string for H256");
147
148		let im_online: HashString = im_online.into();
149		let im_online: H256 = im_online.try_into().expect("Invalid string for H256");
150
151		let value = avail::session::tx::SetKeys { babe, grandpa, authority_discovery, im_online, proof };
152		SubmittableTransaction::from_encodable(self.0.clone(), value)
153	}
154
155	/// Removes the stored session keys from on-chain storage.
156	///
157	/// # Returns
158	/// Returns a [`SubmittableTransaction`] that clears session keys for the signing account.
159	///
160	/// # Errors
161	/// Does not perform network calls; transaction construction never fails.
162	pub fn purge_key(&self) -> SubmittableTransaction {
163		let value = avail::session::tx::PurgeKeys {};
164		SubmittableTransaction::from_encodable(self.0.clone(), value)
165	}
166}
167
168/// Builds extrinsics for the `nomination_pools` pallet.
169///
170/// Many helpers accept `MultiAddressLike` values and will panic if those cannot be converted into
171/// on-chain account identifiers. Constructing the [`SubmittableTransaction`] itself does not hit the
172/// network; signing or submitting it will.
173pub struct NominationPools(Client);
174impl NominationPools {
175	/// Contributes additional stake from the pool's bonded account.
176	///
177	/// # Arguments
178	/// * `value` - Amount to bond, expressed as a [`BondExtraValue`].
179	///
180	/// # Returns
181	/// Returns a [`SubmittableTransaction`] that bonds the extra amount for the pool.
182	///
183	/// # Errors
184	/// Does not perform network calls; transaction construction never fails.
185	pub fn bond_extra(&self, value: BondExtraValue) -> SubmittableTransaction {
186		let value = avail::nomination_pools::tx::BondExtra { value };
187		SubmittableTransaction::from_encodable(self.0.clone(), value)
188	}
189
190	/// Bonds additional stake on behalf of another member.
191	///
192	/// # Panics
193	/// Panics if `member` cannot be converted into a `MultiAddress`.
194	///
195	/// # Arguments
196	/// * `member` - Account that receives the increased bonded amount.
197	/// * `value` - Amount to bond, expressed as a [`BondExtraValue`].
198	///
199	/// # Returns
200	/// Returns a [`SubmittableTransaction`] that bonds extra stake for the specified member.
201	///
202	/// # Errors
203	/// Does not perform network calls; transaction construction never fails.
204	pub fn bond_extra_other(
205		&self,
206		member: impl Into<MultiAddressLike>,
207		value: BondExtraValue,
208	) -> SubmittableTransaction {
209		let member: MultiAddressLike = member.into();
210		let member: MultiAddress = member.try_into().expect("Malformed string is passed for AccountId");
211
212		let value = avail::nomination_pools::tx::BondExtraOther { member, value };
213		SubmittableTransaction::from_encodable(self.0.clone(), value)
214	}
215
216	/// Requests the pool to chill its nominations.
217	///
218	/// # Arguments
219	/// * `pool_id` - Identifier of the pool that should chill.
220	///
221	/// # Returns
222	/// Returns a [`SubmittableTransaction`] that issues the `chill` request.
223	///
224	/// # Errors
225	/// Does not perform network calls; transaction construction never fails.
226	pub fn chill(&self, pool_id: u32) -> SubmittableTransaction {
227		let value = avail::nomination_pools::tx::Chill { pool_id };
228		SubmittableTransaction::from_encodable(self.0.clone(), value)
229	}
230
231	/// Claims pending commission for the given pool.
232	///
233	/// # Arguments
234	/// * `pool_id` - Identifier of the pool that should pay out commission.
235	///
236	/// # Returns
237	/// Returns a [`SubmittableTransaction`] that claims the commission.
238	///
239	/// # Errors
240	/// Does not perform network calls; transaction construction never fails.
241	pub fn claim_commission(&self, pool_id: u32) -> SubmittableTransaction {
242		let value = avail::nomination_pools::tx::ClaimCommission { pool_id };
243		SubmittableTransaction::from_encodable(self.0.clone(), value)
244	}
245
246	/// Claims a pending payout for the caller.
247	///
248	/// # Returns
249	/// Returns a [`SubmittableTransaction`] that claims unpaid rewards for the signer.
250	///
251	/// # Errors
252	/// Does not perform network calls; transaction construction never fails.
253	pub fn claim_payout(&self) -> SubmittableTransaction {
254		let value = avail::nomination_pools::tx::ClaimPayout {};
255		SubmittableTransaction::from_encodable(self.0.clone(), value)
256	}
257
258	/// Claims a pending payout for another pool member.
259	///
260	/// # Panics
261	/// Panics if `owner` cannot be converted into an `AccountId`.
262	///
263	/// # Arguments
264	/// * `owner` - Account that receives the payout.
265	///
266	/// # Returns
267	/// Returns a [`SubmittableTransaction`] that claims unpaid rewards on behalf of `owner`.
268	///
269	/// # Errors
270	/// Does not perform network calls; transaction construction never fails.
271	pub fn claim_payout_other(&self, owner: impl Into<AccountIdLike>) -> SubmittableTransaction {
272		let owner: AccountIdLike = owner.into();
273		let owner: AccountId = owner.try_into().expect("Malformed string is passed for AccountId");
274
275		let value = avail::nomination_pools::tx::ClaimPayoutOther { owner };
276		SubmittableTransaction::from_encodable(self.0.clone(), value)
277	}
278
279	/// Creates a new nomination pool with freshly provided roles.
280	///
281	/// # Panics
282	/// Panics if any of `root`, `nominator`, or `bouncer` cannot be converted into a `MultiAddress`.
283	///
284	/// # Arguments
285	/// * `amount` - Initial bonded amount for the pool.
286	/// * `root` - Root account controlling pool administration.
287	/// * `nominator` - Account authorised to nominate validators.
288	/// * `bouncer` - Account that manages membership access.
289	///
290	/// # Returns
291	/// Returns a [`SubmittableTransaction`] that creates the pool with the supplied roles.
292	///
293	/// # Errors
294	/// Does not perform network calls; transaction construction never fails.
295	pub fn create(
296		&self,
297		amount: u128,
298		root: impl Into<MultiAddressLike>,
299		nominator: impl Into<MultiAddressLike>,
300		bouncer: impl Into<MultiAddressLike>,
301	) -> SubmittableTransaction {
302		let root: MultiAddressLike = root.into();
303		let root: MultiAddress = root.try_into().expect("Malformed string is passed for AccountId");
304		let nominator: MultiAddressLike = nominator.into();
305		let nominator: MultiAddress = nominator.try_into().expect("Malformed string is passed for AccountId");
306		let bouncer: MultiAddressLike = bouncer.into();
307		let bouncer: MultiAddress = bouncer.try_into().expect("Malformed string is passed for AccountId");
308
309		let value = avail::nomination_pools::tx::Create { amount, root, nominator, bouncer };
310		SubmittableTransaction::from_encodable(self.0.clone(), value)
311	}
312
313	/// Creates a new nomination pool using a specific pool identifier.
314	///
315	/// # Panics
316	/// Panics if any of `root`, `nominator`, or `bouncer` cannot be converted into a `MultiAddress`.
317	///
318	/// # Arguments
319	/// * `amount` - Initial bonded amount for the pool.
320	/// * `root` - Root account controlling pool administration.
321	/// * `nominator` - Account authorised to nominate validators.
322	/// * `bouncer` - Account that manages membership access.
323	/// * `pool_id` - Identifier to assign to the new pool.
324	///
325	/// # Returns
326	/// Returns a [`SubmittableTransaction`] that creates the pool with an explicit identifier.
327	///
328	/// # Errors
329	/// Does not perform network calls; transaction construction never fails.
330	pub fn create_with_pool_id(
331		&self,
332		amount: u128,
333		root: impl Into<MultiAddressLike>,
334		nominator: impl Into<MultiAddressLike>,
335		bouncer: impl Into<MultiAddressLike>,
336		pool_id: u32,
337	) -> SubmittableTransaction {
338		let root: MultiAddressLike = root.into();
339		let root: MultiAddress = root.try_into().expect("Malformed string is passed for AccountId");
340		let nominator: MultiAddressLike = nominator.into();
341		let nominator: MultiAddress = nominator.try_into().expect("Malformed string is passed for AccountId");
342		let bouncer: MultiAddressLike = bouncer.into();
343		let bouncer: MultiAddress = bouncer.try_into().expect("Malformed string is passed for AccountId");
344
345		let value = avail::nomination_pools::tx::CreateWithPoolId { amount, root, nominator, bouncer, pool_id };
346		SubmittableTransaction::from_encodable(self.0.clone(), value)
347	}
348
349	/// Joins an existing pool by contributing the requested amount.
350	///
351	/// # Arguments
352	/// * `amount` - Amount of stake contributed by the caller.
353	/// * `pool_id` - Identifier of the pool to join.
354	///
355	/// # Returns
356	/// Returns a [`SubmittableTransaction`] that adds the caller to the pool.
357	///
358	/// # Errors
359	/// Does not perform network calls; transaction construction never fails.
360	pub fn join(&self, amount: u128, pool_id: u32) -> SubmittableTransaction {
361		let value = avail::nomination_pools::tx::Join { amount, pool_id };
362		SubmittableTransaction::from_encodable(self.0.clone(), value)
363	}
364
365	/// Sets nominations for the pool to a new validator set.
366	///
367	/// # Panics
368	/// Panics if any validator identifier cannot be converted into an `AccountId`.
369	///
370	/// # Arguments
371	/// * `pool_id` - Identifier of the pool whose nominations are updated.
372	/// * `validators` - Validators that the pool should nominate.
373	///
374	/// # Returns
375	/// Returns a [`SubmittableTransaction`] that updates the pool's nominations.
376	///
377	/// # Errors
378	/// Does not perform network calls; transaction construction never fails.
379	pub fn nominate(&self, pool_id: u32, validators: Vec<impl Into<AccountIdLike>>) -> SubmittableTransaction {
380		let validators: Vec<AccountIdLike> = validators.into_iter().map(|x| x.into()).collect();
381		let validators: Result<Vec<AccountId>, _> = validators.into_iter().map(AccountId::try_from).collect();
382		let validators = validators.expect("Malformed string is passed for AccountId");
383
384		let value = avail::nomination_pools::tx::Nominate { pool_id, validators };
385		SubmittableTransaction::from_encodable(self.0.clone(), value)
386	}
387
388	/// Updates who is allowed to claim rewards for the pool.
389	///
390	/// # Arguments
391	/// * `permission` - Claim policy applied to the pool.
392	///
393	/// # Returns
394	/// Returns a [`SubmittableTransaction`] that adjusts the pool's claim permission.
395	///
396	/// # Errors
397	/// Does not perform network calls; transaction construction never fails.
398	pub fn set_claim_permission(&self, permission: ClaimPermission) -> SubmittableTransaction {
399		let value = avail::nomination_pools::tx::SetClaimPermission { permission };
400		SubmittableTransaction::from_encodable(self.0.clone(), value)
401	}
402
403	/// Updates the commission settings for the pool, optionally setting a payee.
404	///
405	/// # Panics
406	/// Panics if the payee provided in `new_commission` cannot be converted into an `AccountId`.
407	///
408	/// # Arguments
409	/// * `pool_id` - Identifier of the pool whose commission is updated.
410	/// * `new_commission` - Optional tuple of `(commission, payee)` describing the new rate and payee.
411	///
412	/// # Returns
413	/// Returns a [`SubmittableTransaction`] that updates commission settings.
414	///
415	/// # Errors
416	/// Does not perform network calls; transaction construction never fails.
417	pub fn set_commission(&self, pool_id: u32, new_commission: Option<(u32, AccountIdLike)>) -> SubmittableTransaction {
418		let new_commission =
419			new_commission.map(|x| (x.0, AccountId::try_from(x.1).expect("Malformed string is passed for AccountId")));
420		let value = avail::nomination_pools::tx::SetCommission { pool_id, new_commission };
421		SubmittableTransaction::from_encodable(self.0.clone(), value)
422	}
423
424	/// Configures how frequently pool commission may change.
425	///
426	/// # Arguments
427	/// * `pool_id` - Identifier of the pool being updated.
428	/// * `max_increase` - Maximum commission increase allowed per change.
429	/// * `min_delay` - Minimum number of eras between commission updates.
430	///
431	/// # Returns
432	/// Returns a [`SubmittableTransaction`] that applies the new change rate.
433	///
434	/// # Errors
435	/// Does not perform network calls; transaction construction never fails.
436	pub fn set_commission_change_rate(
437		&self,
438		pool_id: u32,
439		max_increase: u32,
440		min_delay: u32,
441	) -> SubmittableTransaction {
442		let value = avail::nomination_pools::tx::SetCommissionChangeRate { pool_id, max_increase, min_delay };
443		SubmittableTransaction::from_encodable(self.0.clone(), value)
444	}
445
446	/// Caps commission at the provided maximum percentage.
447	///
448	/// # Arguments
449	/// * `pool_id` - Identifier of the pool being updated.
450	/// * `max_commission` - Maximum commission percentage allowed.
451	///
452	/// # Returns
453	/// Returns a [`SubmittableTransaction`] that stores the new commission cap.
454	///
455	/// # Errors
456	/// Does not perform network calls; transaction construction never fails.
457	pub fn set_commission_max(&self, pool_id: u32, max_commission: u32) -> SubmittableTransaction {
458		let value = avail::nomination_pools::tx::SetCommissionMax { pool_id, max_commission };
459		SubmittableTransaction::from_encodable(self.0.clone(), value)
460	}
461
462	/// Updates pool metadata stored on chain.
463	///
464	/// # Arguments
465	/// * `pool_id` - Identifier of the pool being updated.
466	/// * `metadata` - Metadata payload encoded as bytes or string.
467	///
468	/// # Returns
469	/// Returns a [`SubmittableTransaction`] that writes the metadata to storage.
470	///
471	/// # Errors
472	/// Does not perform network calls; transaction construction never fails.
473	pub fn set_metadata<'a>(&self, pool_id: u32, metadata: impl Into<StringOrBytes<'a>>) -> SubmittableTransaction {
474		let metadata: StringOrBytes = metadata.into();
475		let metadata: Vec<u8> = metadata.into();
476		let value = avail::nomination_pools::tx::SetMetadata { pool_id, metadata };
477		SubmittableTransaction::from_encodable(self.0.clone(), value)
478	}
479
480	/// Transitions the pool into a new lifecycle state.
481	///
482	/// # Arguments
483	/// * `pool_id` - Identifier of the pool being updated.
484	/// * `state` - New lifecycle state to apply.
485	///
486	/// # Returns
487	/// Returns a [`SubmittableTransaction`] that updates the pool state.
488	///
489	/// # Errors
490	/// Does not perform network calls; transaction construction never fails.
491	pub fn set_state(&self, pool_id: u32, state: PoolState) -> SubmittableTransaction {
492		let value = avail::nomination_pools::tx::SetState { pool_id, state };
493		SubmittableTransaction::from_encodable(self.0.clone(), value)
494	}
495
496	/// Starts the unbonding process for the specified member account.
497	///
498	/// # Panics
499	/// Panics if `member_account` cannot be converted into a `MultiAddress`.
500	///
501	/// # Arguments
502	/// * `member_account` - Account leaving the pool.
503	/// * `unbonding_points` - Amount of stake to unbond, expressed in pool points.
504	///
505	/// # Returns
506	/// Returns a [`SubmittableTransaction`] that schedules the unbonding.
507	///
508	/// # Errors
509	/// Does not perform network calls; transaction construction never fails.
510	pub fn unbond(
511		&self,
512		member_account: impl Into<MultiAddressLike>,
513		unbonding_points: u128,
514	) -> SubmittableTransaction {
515		let member_account: MultiAddressLike = member_account.into();
516		let member_account: MultiAddress = member_account
517			.try_into()
518			.expect("Malformed string is passed for AccountId");
519
520		let value = avail::nomination_pools::tx::Unbond { member_account, unbonding_points };
521		SubmittableTransaction::from_encodable(self.0.clone(), value)
522	}
523
524	/// Updates the pool's root, nominator, and bouncer roles.
525	///
526	/// # Arguments
527	/// * `pool_id` - Identifier of the pool being updated.
528	/// * `new_root` - Operation describing how to update the root account.
529	/// * `new_nominator` - Operation describing how to update the nominator account.
530	/// * `new_bouncer` - Operation describing how to update the bouncer account.
531	///
532	/// # Returns
533	/// Returns a [`SubmittableTransaction`] that applies the new role assignments.
534	///
535	/// # Errors
536	/// Does not perform network calls; transaction construction never fails.
537	pub fn update_roles(
538		&self,
539		pool_id: u32,
540		new_root: ConfigOpAccount,
541		new_nominator: ConfigOpAccount,
542		new_bouncer: ConfigOpAccount,
543	) -> SubmittableTransaction {
544		let value = avail::nomination_pools::tx::UpdateRoles { pool_id, new_root, new_nominator, new_bouncer };
545		SubmittableTransaction::from_encodable(self.0.clone(), value)
546	}
547
548	/// Withdraws fully unbonded funds for the given member account.
549	///
550	/// # Panics
551	/// Panics if `member_account` cannot be converted into a `MultiAddress`.
552	///
553	/// # Arguments
554	/// * `member_account` - Account withdrawing previously unbonded funds.
555	/// * `num_slashing_spans` - Number of slashing spans to consider when finalising the withdrawal.
556	///
557	/// # Returns
558	/// Returns a [`SubmittableTransaction`] that withdraws the unbonded amount.
559	///
560	/// # Errors
561	/// Does not perform network calls; transaction construction never fails.
562	pub fn withdraw_unbonded(
563		&self,
564		member_account: impl Into<MultiAddressLike>,
565		num_slashing_spans: u32,
566	) -> SubmittableTransaction {
567		let member_account: MultiAddressLike = member_account.into();
568		let member_account: MultiAddress = member_account
569			.try_into()
570			.expect("Malformed string is passed for AccountId");
571
572		let value = avail::nomination_pools::tx::WithdrawUnbonded { member_account, num_slashing_spans };
573		SubmittableTransaction::from_encodable(self.0.clone(), value)
574	}
575}
576
577/// Builds extrinsics for the `staking` pallet.
578///
579/// Methods that accept `AccountIdLike` or `MultiAddressLike` parameters will panic if the provided
580/// value cannot be converted into the expected on-chain representation.
581pub struct Staking(Client);
582impl Staking {
583	/// Bonds funds from the controller with the provided reward destination.
584	///
585	/// # Arguments
586	/// * `value` - Amount of stake to bond.
587	/// * `payee` - Destination where rewards should be paid.
588	///
589	/// # Returns
590	/// Returns a [`SubmittableTransaction`] that bonds the specified amount.
591	///
592	/// # Errors
593	/// Does not perform network calls; transaction construction never fails.
594	pub fn bond(&self, value: u128, payee: RewardDestination) -> SubmittableTransaction {
595		let value = avail::staking::tx::Bond { value, payee };
596		SubmittableTransaction::from_encodable(self.0.clone(), value)
597	}
598
599	/// Adds additional stake on top of an existing bond.
600	///
601	/// # Arguments
602	/// * `value` - Additional stake to add to the bonded balance.
603	///
604	/// # Returns
605	/// Returns a [`SubmittableTransaction`] that increases the bonded amount.
606	///
607	/// # Errors
608	/// Does not perform network calls; transaction construction never fails.
609	pub fn bond_extra(&self, value: u128) -> SubmittableTransaction {
610		let value = avail::staking::tx::BondExtra { value };
611		SubmittableTransaction::from_encodable(self.0.clone(), value)
612	}
613
614	/// Starts unbonding the given amount of funds.
615	///
616	/// # Arguments
617	/// * `value` - Amount of stake to unbond.
618	///
619	/// # Returns
620	/// Returns a [`SubmittableTransaction`] that schedules the unbonding.
621	///
622	/// # Errors
623	/// Does not perform network calls; transaction construction never fails.
624	pub fn unbond(&self, value: u128) -> SubmittableTransaction {
625		let value = avail::staking::tx::Unbond { value };
626		SubmittableTransaction::from_encodable(self.0.clone(), value)
627	}
628
629	/// Re-bonds a portion of funds that are currently unbonding.
630	///
631	/// # Arguments
632	/// * `value` - Amount of stake to re-bond.
633	///
634	/// # Returns
635	/// Returns a [`SubmittableTransaction`] that re-bonds the requested amount.
636	///
637	/// # Errors
638	/// Does not perform network calls; transaction construction never fails.
639	pub fn rebond(&self, value: u128) -> SubmittableTransaction {
640		let value = avail::staking::tx::Rebond { value };
641		SubmittableTransaction::from_encodable(self.0.clone(), value)
642	}
643
644	/// Advertises validator preferences for the caller.
645	///
646	/// # Arguments
647	/// * `commission` - Desired commission percentage.
648	/// * `blocked` - Flag indicating whether new nominations are rejected.
649	///
650	/// # Returns
651	/// Returns a [`SubmittableTransaction`] that publishes the validator preferences.
652	///
653	/// # Errors
654	/// Does not perform network calls; transaction construction never fails.
655	pub fn validate(&self, commission: u32, blocked: bool) -> SubmittableTransaction {
656		let value = avail::staking::tx::Validate { prefs: ValidatorPrefs { commission, blocked } };
657		SubmittableTransaction::from_encodable(self.0.clone(), value)
658	}
659
660	/// Nominates a new set of validator targets.
661	///
662	/// # Panics
663	/// Panics if any provided target cannot be converted into a `MultiAddress`.
664	///
665	/// # Arguments
666	/// * `targets` - Validators to nominate.
667	///
668	/// # Returns
669	/// Returns a [`SubmittableTransaction`] that updates the nomination targets.
670	///
671	/// # Errors
672	/// Does not perform network calls; transaction construction never fails.
673	pub fn nominate(&self, targets: Vec<impl Into<MultiAddressLike>>) -> SubmittableTransaction {
674		let targets: Vec<MultiAddressLike> = targets.into_iter().map(|x| x.into()).collect();
675		let targets: Result<Vec<MultiAddress>, _> = targets.into_iter().map(MultiAddress::try_from).collect();
676		let targets = targets.expect("Malformed string is passed for AccountId");
677
678		let value = avail::staking::tx::Nominate { targets };
679		SubmittableTransaction::from_encodable(self.0.clone(), value)
680	}
681
682	/// Pays out staking rewards for the given validator and era.
683	///
684	/// # Panics
685	/// Panics if `validator_stash` cannot be converted into an `AccountId`.
686	///
687	/// # Arguments
688	/// * `validator_stash` - Stash account whose rewards are claimed.
689	/// * `era` - Era for which rewards are paid out.
690	///
691	/// # Returns
692	/// Returns a [`SubmittableTransaction`] that triggers the payout.
693	///
694	/// # Errors
695	/// Does not perform network calls; transaction construction never fails.
696	pub fn payout_stakers(&self, validator_stash: impl Into<AccountIdLike>, era: u32) -> SubmittableTransaction {
697		let validator_stash: AccountIdLike = validator_stash.into();
698		let validator_stash = AccountId::try_from(validator_stash).expect("Malformed string is passed for AccountId");
699
700		let value = avail::staking::tx::PayoutStakers { validator_stash, era };
701		SubmittableTransaction::from_encodable(self.0.clone(), value)
702	}
703
704	/// Switches the controller account for the stash.
705	///
706	/// # Returns
707	/// Returns a [`SubmittableTransaction`] that sets a new controller (based on the signature).
708	///
709	/// # Errors
710	/// Does not perform network calls; transaction construction never fails.
711	pub fn set_controller(&self) -> SubmittableTransaction {
712		let value = avail::staking::tx::SetController {};
713		SubmittableTransaction::from_encodable(self.0.clone(), value)
714	}
715
716	/// Updates the staking reward destination.
717	///
718	/// # Arguments
719	/// * `payee` - Destination where new rewards should be deposited.
720	///
721	/// # Returns
722	/// Returns a [`SubmittableTransaction`] that updates the reward destination.
723	///
724	/// # Errors
725	/// Does not perform network calls; transaction construction never fails.
726	pub fn set_payee(&self, payee: RewardDestination) -> SubmittableTransaction {
727		let value = avail::staking::tx::SetPayee { payee };
728		SubmittableTransaction::from_encodable(self.0.clone(), value)
729	}
730
731	/// Stops nominating for the caller.
732	///
733	/// # Returns
734	/// Returns a [`SubmittableTransaction`] that chills the caller's nominations.
735	///
736	/// # Errors
737	/// Does not perform network calls; transaction construction never fails.
738	pub fn chill(&self) -> SubmittableTransaction {
739		let value = avail::staking::tx::Chill {};
740		SubmittableTransaction::from_encodable(self.0.clone(), value)
741	}
742
743	/// Issues a chill for another stash account.
744	///
745	/// # Panics
746	/// Panics if `stash` cannot be converted into an `AccountId`.
747	///
748	/// # Arguments
749	/// * `stash` - Stash account to chill.
750	///
751	/// # Returns
752	/// Returns a [`SubmittableTransaction`] that chills the specified stash.
753	///
754	/// # Errors
755	/// Does not perform network calls; transaction construction never fails.
756	pub fn chill_other(&self, stash: impl Into<AccountIdLike>) -> SubmittableTransaction {
757		let stash: AccountIdLike = stash.into();
758		let stash = AccountId::try_from(stash).expect("Malformed string is passed for AccountId");
759
760		let value = avail::staking::tx::ChillOther { stash };
761		SubmittableTransaction::from_encodable(self.0.clone(), value)
762	}
763
764	/// Withdraws funds that have completed the unbonding period.
765	///
766	/// # Arguments
767	/// * `num_slashing_spans` - Number of slashing spans to consider when finalising the withdrawal.
768	///
769	/// # Returns
770	/// Returns a [`SubmittableTransaction`] that withdraws matured unbonded funds.
771	///
772	/// # Errors
773	/// Does not perform network calls; transaction construction never fails.
774	pub fn withdraw_unbonded(&self, num_slashing_spans: u32) -> SubmittableTransaction {
775		let value = avail::staking::tx::WithdrawUnbonded { num_slashing_spans };
776		SubmittableTransaction::from_encodable(self.0.clone(), value)
777	}
778
779	/// Removes a stash that no longer has bonded funds.
780	///
781	/// # Panics
782	/// Panics if `stash` cannot be converted into an `AccountId`.
783	///
784	/// # Arguments
785	/// * `stash` - Stash account to reap.
786	/// * `num_slashing_spans` - Number of slashing spans considered during reaping.
787	///
788	/// # Returns
789	/// Returns a [`SubmittableTransaction`] that reaps the empty stash.
790	///
791	/// # Errors
792	/// Does not perform network calls; transaction construction never fails.
793	pub fn reap_stash(&self, stash: impl Into<AccountIdLike>, num_slashing_spans: u32) -> SubmittableTransaction {
794		let stash: AccountIdLike = stash.into();
795		let stash = AccountId::try_from(stash).expect("Malformed string is passed for AccountId");
796
797		let value = avail::staking::tx::ReapStash { stash, num_slashing_spans };
798		SubmittableTransaction::from_encodable(self.0.clone(), value)
799	}
800
801	/// Removes the provided nominees from the caller's nomination list.
802	///
803	/// # Panics
804	/// Panics if any identifier in `who` cannot be converted into a `MultiAddress`.
805	///
806	/// # Arguments
807	/// * `who` - Nominees to remove.
808	///
809	/// # Returns
810	/// Returns a [`SubmittableTransaction`] that removes the specified nominees.
811	///
812	/// # Errors
813	/// Does not perform network calls; transaction construction never fails.
814	pub fn kick(&self, who: Vec<impl Into<MultiAddressLike>>) -> SubmittableTransaction {
815		let who: Vec<MultiAddressLike> = who.into_iter().map(|x| x.into()).collect();
816		let who: Result<Vec<MultiAddress>, _> = who.into_iter().map(MultiAddress::try_from).collect();
817		let who = who.expect("Malformed string is passed for AccountId");
818
819		let value = avail::staking::tx::Kick { who };
820		SubmittableTransaction::from_encodable(self.0.clone(), value)
821	}
822
823	/// Forces the commission for the given validator to the chain minimum.
824	///
825	/// # Panics
826	/// Panics if `validator_stash` cannot be converted into an `AccountId`.
827	///
828	/// # Arguments
829	/// * `validator_stash` - Stash account whose commission is being forced.
830	///
831	/// # Returns
832	/// Returns a [`SubmittableTransaction`] that enforces the minimum commission.
833	///
834	/// # Errors
835	/// Does not perform network calls; transaction construction never fails.
836	pub fn force_apply_min_commission(&self, validator_stash: impl Into<AccountIdLike>) -> SubmittableTransaction {
837		let validator_stash: AccountIdLike = validator_stash.into();
838		let validator_stash = AccountId::try_from(validator_stash).expect("Malformed string is passed for AccountId");
839
840		let value = avail::staking::tx::ForceApplyMinCommission { validator_stash };
841		SubmittableTransaction::from_encodable(self.0.clone(), value)
842	}
843
844	/// Pays out staking rewards for a subset of nominators.
845	///
846	/// # Panics
847	/// Panics if `validator_stash` cannot be converted into an `AccountId`.
848	///
849	/// # Arguments
850	/// * `validator_stash` - Stash account whose rewards are being claimed.
851	/// * `era` - Era for which rewards are paid.
852	/// * `page` - Page index selecting which nominators to payout.
853	///
854	/// # Returns
855	/// Returns a [`SubmittableTransaction`] that triggers the paged payout.
856	///
857	/// # Errors
858	/// Does not perform network calls; transaction construction never fails.
859	pub fn payout_stakers_by_page(
860		&self,
861		validator_stash: impl Into<AccountIdLike>,
862		era: u32,
863		page: u32,
864	) -> SubmittableTransaction {
865		let validator_stash: AccountIdLike = validator_stash.into();
866		let validator_stash = AccountId::try_from(validator_stash).expect("Malformed string is passed for AccountId");
867
868		let value = avail::staking::tx::PayoutStakersByPage { validator_stash, era, page };
869		SubmittableTransaction::from_encodable(self.0.clone(), value)
870	}
871}
872
873/// Builds extrinsics for the `balances` pallet.
874///
875/// All helpers expect account identifiers that can be converted into `MultiAddress` values and will
876/// panic if the conversion fails.
877pub struct Balances(Client);
878impl Balances {
879	/// Transfers funds allowing the sender's account to be removed if depleted.
880	///
881	/// # Panics
882	/// Panics if `dest` cannot be converted into a `MultiAddress`.
883	///
884	/// # Arguments
885	/// * `dest` - Destination account receiving the transfer.
886	/// * `amount` - Amount to transfer.
887	///
888	/// # Returns
889	/// Returns a [`SubmittableTransaction`] that performs the transfer.
890	///
891	/// # Errors
892	/// Does not perform network calls; transaction construction never fails.
893	pub fn transfer_allow_death(&self, dest: impl Into<MultiAddressLike>, amount: u128) -> SubmittableTransaction {
894		let dest: MultiAddressLike = dest.into();
895		let dest: MultiAddress = dest.try_into().expect("Malformed string is passed for AccountId");
896
897		let value = avail::balances::tx::TransferAllowDeath { dest, value: amount };
898		SubmittableTransaction::from_encodable(self.0.clone(), value)
899	}
900
901	/// Transfers funds while keeping the sender's account alive.
902	///
903	/// # Panics
904	/// Panics if `dest` cannot be converted into a `MultiAddress`.
905	///
906	/// # Arguments
907	/// * `dest` - Destination account receiving the transfer.
908	/// * `amount` - Amount to transfer.
909	///
910	/// # Returns
911	/// Returns a [`SubmittableTransaction`] that performs the keep-alive transfer.
912	///
913	/// # Errors
914	/// Does not perform network calls; transaction construction never fails.
915	pub fn transfer_keep_alive(&self, dest: impl Into<MultiAddressLike>, amount: u128) -> SubmittableTransaction {
916		let dest: MultiAddressLike = dest.into();
917		let dest: MultiAddress = dest.try_into().expect("Malformed string is passed for AccountId");
918
919		let value = avail::balances::tx::TransferKeepAlive { dest, value: amount };
920		SubmittableTransaction::from_encodable(self.0.clone(), value)
921	}
922
923	/// Transfers the entire free balance to the destination.
924	///
925	/// # Panics
926	/// Panics if `dest` cannot be converted into a `MultiAddress`.
927	///
928	/// # Arguments
929	/// * `dest` - Destination account receiving the transfer.
930	/// * `keep_alive` - When `true`, leaves the minimum balance to keep the account alive.
931	///
932	/// # Returns
933	/// Returns a [`SubmittableTransaction`] that transfers the full balance.
934	///
935	/// # Errors
936	/// Does not perform network calls; transaction construction never fails.
937	pub fn transfer_all(&self, dest: impl Into<MultiAddressLike>, keep_alive: bool) -> SubmittableTransaction {
938		let dest: MultiAddressLike = dest.into();
939		let dest: MultiAddress = dest.try_into().expect("Malformed string is passed for AccountId");
940
941		let value = avail::balances::tx::TransferAll { dest, keep_alive };
942		SubmittableTransaction::from_encodable(self.0.clone(), value)
943	}
944}
945
946/// Builds extrinsics for the `multisig` pallet.
947///
948/// Helper methods convert `AccountIdLike` and `HashString` inputs into on-chain representations and
949/// panic if the conversion fails; they also sort the provided signatories to match runtime
950/// expectations.
951pub struct Multisig(Client);
952impl Multisig {
953	/// Approves a multisig call by reference to its hash.
954	///
955	/// # Panics
956	/// Panics if any signatory identifier fails to convert into an `AccountId` or if `call_hash`
957	/// cannot be converted into `H256`.
958	///
959	/// # Arguments
960	/// * `threshold` - Total number of approvals required to execute the call.
961	/// * `other_signatories` - Remaining signatories excluding the caller.
962	/// * `maybe_timepoint` - Optional timepoint identifying the in-progress multisig.
963	/// * `call_hash` - Hash of the call being approved.
964	/// * `max_weight` - Execution weight budget for the call.
965	///
966	/// # Returns
967	/// Returns a [`SubmittableTransaction`] that records the approval.
968	///
969	/// # Errors
970	/// Does not perform network calls; transaction construction never fails.
971	pub fn approve_as_multi(
972		&self,
973		threshold: u16,
974		other_signatories: Vec<impl Into<AccountIdLike>>,
975		maybe_timepoint: Option<Timepoint>,
976		call_hash: impl Into<HashString>,
977		max_weight: Weight,
978	) -> SubmittableTransaction {
979		fn inner(
980			client: Client,
981			threshold: u16,
982			other_signatories: Vec<AccountIdLike>,
983			maybe_timepoint: Option<Timepoint>,
984			call_hash: HashString,
985			max_weight: Weight,
986		) -> SubmittableTransaction {
987			let other_signatories: Result<Vec<AccountId>, _> =
988				other_signatories.into_iter().map(|x| x.try_into()).collect();
989			let mut other_signatories = other_signatories.expect("Malformed string is passed for AccountId");
990			other_signatories.sort();
991
992			let call_hash: H256 = call_hash.try_into().expect("Malformed string is passed for H256");
993
994			let value = avail::multisig::tx::ApproveAsMulti {
995				threshold,
996				other_signatories,
997				maybe_timepoint,
998				call_hash,
999				max_weight,
1000			};
1001			SubmittableTransaction::from_encodable(client, value)
1002		}
1003
1004		let other_signatories: Vec<AccountIdLike> = other_signatories.into_iter().map(|x| x.into()).collect();
1005		let call_hash: HashString = call_hash.into();
1006		inner(self.0.clone(), threshold, other_signatories, maybe_timepoint, call_hash, max_weight)
1007	}
1008
1009	/// Executes a multisig call with full call data.
1010	///
1011	/// # Panics
1012	/// Panics if any signatory identifier fails to convert into an `AccountId`.
1013	///
1014	/// # Arguments
1015	/// * `threshold` - Total number of approvals required to execute the call.
1016	/// * `other_signatories` - Remaining signatories excluding the caller.
1017	/// * `maybe_timepoint` - Optional timepoint identifying the in-progress multisig.
1018	/// * `call` - Call payload to execute once approvals are satisfied.
1019	/// * `max_weight` - Execution weight budget for the call.
1020	///
1021	/// # Returns
1022	/// Returns a [`SubmittableTransaction`] that submits the multisig call.
1023	///
1024	/// # Errors
1025	/// Does not perform network calls; transaction construction never fails.
1026	pub fn as_multi(
1027		&self,
1028		threshold: u16,
1029		other_signatories: Vec<impl Into<AccountIdLike>>,
1030		maybe_timepoint: Option<Timepoint>,
1031		call: impl Into<ExtrinsicCall>,
1032		max_weight: Weight,
1033	) -> SubmittableTransaction {
1034		fn inner(
1035			client: Client,
1036			threshold: u16,
1037			other_signatories: Vec<AccountIdLike>,
1038			maybe_timepoint: Option<Timepoint>,
1039			call: ExtrinsicCall,
1040			max_weight: Weight,
1041		) -> SubmittableTransaction {
1042			let other_signatories: Result<Vec<AccountId>, _> =
1043				other_signatories.into_iter().map(|x| x.try_into()).collect();
1044			let mut other_signatories = other_signatories.expect("Malformed string is passed for AccountId");
1045			other_signatories.sort();
1046
1047			let value = avail::multisig::tx::AsMulti {
1048				threshold,
1049				other_signatories,
1050				maybe_timepoint,
1051				call,
1052				max_weight,
1053			};
1054			SubmittableTransaction::from_encodable(client, value)
1055		}
1056
1057		let other_signatories: Vec<AccountIdLike> = other_signatories.into_iter().map(|x| x.into()).collect();
1058		inner(self.0.clone(), threshold, other_signatories, maybe_timepoint, call.into(), max_weight)
1059	}
1060
1061	/// Executes a multisig call with a threshold of one.
1062	///
1063	/// # Panics
1064	/// Panics if any signatory identifier fails to convert into an `AccountId`.
1065	///
1066	/// # Arguments
1067	/// * `other_signatories` - Remaining signatories excluding the caller; used to derive the multisig account.
1068	/// * `call` - Call payload to execute.
1069	///
1070	/// # Returns
1071	/// Returns a [`SubmittableTransaction`] that executes the call with a threshold of one.
1072	///
1073	/// # Errors
1074	/// Does not perform network calls; transaction construction never fails.
1075	pub fn as_multi_threshold_1(
1076		&self,
1077		other_signatories: Vec<impl Into<AccountIdLike>>,
1078		call: impl Into<ExtrinsicCall>,
1079	) -> SubmittableTransaction {
1080		fn inner(client: Client, other_signatories: Vec<AccountIdLike>, call: ExtrinsicCall) -> SubmittableTransaction {
1081			let other_signatories: Result<Vec<AccountId>, _> =
1082				other_signatories.into_iter().map(|x| x.try_into()).collect();
1083			let mut other_signatories = other_signatories.expect("Malformed string is passed for AccountId");
1084			other_signatories.sort();
1085
1086			let value = avail::multisig::tx::AsMultiThreshold1 { other_signatories, call };
1087			SubmittableTransaction::from_encodable(client, value)
1088		}
1089
1090		let other_signatories: Vec<AccountIdLike> = other_signatories.into_iter().map(|x| x.into()).collect();
1091		inner(self.0.clone(), other_signatories, call.into())
1092	}
1093
1094	/// Cancels a previously scheduled multisig call.
1095	///
1096	/// # Panics
1097	/// Panics if any signatory identifier fails to convert into an `AccountId` or if `call_hash`
1098	/// cannot be converted into `H256`.
1099	///
1100	/// # Arguments
1101	/// * `threshold` - Total number of approvals required by the multisig.
1102	/// * `other_signatories` - Remaining signatories excluding the caller.
1103	/// * `timepoint` - Timepoint returned when the call was created.
1104	/// * `call_hash` - Hash of the call being cancelled.
1105	///
1106	/// # Returns
1107	/// Returns a [`SubmittableTransaction`] that cancels the multisig operation.
1108	///
1109	/// # Errors
1110	/// Does not perform network calls; transaction construction never fails.
1111	pub fn cancel_as_multi(
1112		&self,
1113		threshold: u16,
1114		other_signatories: Vec<impl Into<AccountIdLike>>,
1115		timepoint: Timepoint,
1116		call_hash: impl Into<HashString>,
1117	) -> SubmittableTransaction {
1118		fn inner(
1119			client: Client,
1120			threshold: u16,
1121			other_signatories: Vec<AccountIdLike>,
1122			timepoint: Timepoint,
1123			call_hash: HashString,
1124		) -> SubmittableTransaction {
1125			let other_signatories: Result<Vec<AccountId>, _> =
1126				other_signatories.into_iter().map(|x| x.try_into()).collect();
1127			let mut other_signatories = other_signatories.expect("Malformed string is passed for AccountId");
1128			other_signatories.sort();
1129
1130			let call_hash: H256 = call_hash.try_into().expect("Malformed string is passed for H256");
1131
1132			let value = avail::multisig::tx::CancelAsMulti { threshold, other_signatories, timepoint, call_hash };
1133			SubmittableTransaction::from_encodable(client, value)
1134		}
1135
1136		let other_signatories: Vec<AccountIdLike> = other_signatories.into_iter().map(|x| x.into()).collect();
1137		let call_hash: HashString = call_hash.into();
1138		inner(self.0.clone(), threshold, other_signatories, timepoint, call_hash)
1139	}
1140}
1141
1142/// Builds extrinsics for the `data_availability` pallet.
1143pub struct DataAvailability(Client);
1144impl DataAvailability {
1145	/// Registers a new application key for data availability submissions.
1146	///
1147	/// # Arguments
1148	/// * `key` - Application key bytes or string accepted by the runtime.
1149	///
1150	/// # Returns
1151	/// Returns a [`SubmittableTransaction`] that registers the application key.
1152	///
1153	/// # Errors
1154	/// Does not perform network calls; transaction construction never fails.
1155	pub fn create_application_key<'a>(&self, key: impl Into<StringOrBytes<'a>>) -> SubmittableTransaction {
1156		let key: Vec<u8> = Into::<StringOrBytes>::into(key).into();
1157		let value = avail::data_availability::tx::CreateApplicationKey { key };
1158		SubmittableTransaction::from_encodable(self.0.clone(), value)
1159	}
1160
1161	/// Submits application data for availability guarantees.
1162	///
1163	/// # Arguments
1164	/// * `data` - Data payload to submit.
1165	///
1166	/// # Returns
1167	/// Returns a [`SubmittableTransaction`] that submits the data for availability.
1168	///
1169	/// # Errors
1170	/// Does not perform network calls; transaction construction never fails.
1171	pub fn submit_data<'a>(&self, data: impl Into<StringOrBytes<'a>>) -> SubmittableTransaction {
1172		let data: Vec<u8> = Into::<StringOrBytes>::into(data).into();
1173		let value = avail::data_availability::tx::SubmitData { data };
1174		SubmittableTransaction::from_encodable(self.0.clone(), value)
1175	}
1176
1177	#[cfg(feature = "next")]
1178	/// Submits metadata describing an out-of-band blob.
1179	///
1180	/// # Arguments
1181	/// * `blob_hash` - Hash identifying the blob payload.
1182	/// * `size` - Size of the blob in bytes.
1183	/// * `commitments` - Commitment bytes used for verification.
1184	///
1185	/// # Returns
1186	/// Returns a [`SubmittableTransaction`] ready to be signed and submitted.
1187	///
1188	/// # Errors
1189	/// Does not perform network calls; transaction construction never fails.
1190	pub fn submit_blob_metadata(&self, blob_hash: H256, size: u64, commitments: Vec<u8>) -> SubmittableTransaction {
1191		let value = avail::data_availability::tx::SubmitBlobMetadata { blob_hash, size, commitments };
1192		SubmittableTransaction::from_encodable(self.0.clone(), value)
1193	}
1194}
1195
1196/// Builds extrinsics for the `utility` pallet.
1197pub struct Utility(Client);
1198impl Utility {
1199	/// Dispatches a set of calls sequentially, aborting on failure.
1200	///
1201	/// # Arguments
1202	/// * `calls` - Calls executed in sequence.
1203	///
1204	/// # Returns
1205	/// Returns a [`SubmittableTransaction`] that batches the supplied calls.
1206	///
1207	/// # Errors
1208	/// Does not perform network calls; transaction construction never fails.
1209	pub fn batch(&self, calls: Vec<impl Into<ExtrinsicCall>>) -> SubmittableTransaction {
1210		let mut batch = avail::utility::tx::Batch::new();
1211		batch.add_calls(calls.into_iter().map(|x| x.into()).collect());
1212		SubmittableTransaction::from_encodable(self.0.clone(), batch)
1213	}
1214
1215	/// Dispatches a set of calls and reverts the whole batch if any fail.
1216	///
1217	/// # Arguments
1218	/// * `calls` - Calls executed atomically; any failure rolls back the batch.
1219	///
1220	/// # Returns
1221	/// Returns a [`SubmittableTransaction`] that executes the all-or-nothing batch.
1222	///
1223	/// # Errors
1224	/// Does not perform network calls; transaction construction never fails.
1225	pub fn batch_all(&self, calls: Vec<impl Into<ExtrinsicCall>>) -> SubmittableTransaction {
1226		let mut batch = avail::utility::tx::BatchAll::new();
1227		batch.add_calls(calls.into_iter().map(|x| x.into()).collect());
1228		SubmittableTransaction::from_encodable(self.0.clone(), batch)
1229	}
1230
1231	/// Dispatches a set of calls while ignoring failures.
1232	///
1233	/// # Arguments
1234	/// * `calls` - Calls executed sequentially; individual failures are ignored.
1235	///
1236	/// # Returns
1237	/// Returns a [`SubmittableTransaction`] that executes the tolerant batch.
1238	///
1239	/// # Errors
1240	/// Does not perform network calls; transaction construction never fails.
1241	pub fn force_batch(&self, calls: Vec<impl Into<ExtrinsicCall>>) -> SubmittableTransaction {
1242		let mut batch = avail::utility::tx::ForceBatch::new();
1243		batch.add_calls(calls.into_iter().map(|x| x.into()).collect());
1244		SubmittableTransaction::from_encodable(self.0.clone(), batch)
1245	}
1246}
1247
1248/// Builds extrinsics for the `proxy` pallet.
1249///
1250/// Methods converting `MultiAddressLike` parameters will panic if the provided values cannot be
1251/// decoded into `MultiAddress` instances.
1252pub struct Proxy(Client);
1253impl Proxy {
1254	/// Dispatches a call through an existing proxy relationship.
1255	///
1256	/// # Panics
1257	/// Panics if `id` cannot be converted into a `MultiAddress`.
1258	///
1259	/// # Arguments
1260	/// * `id` - Proxy account that will dispatch the call.
1261	/// * `force_proxy_type` - Optional proxy type override.
1262	/// * `call` - Call to execute through the proxy.
1263	///
1264	/// # Returns
1265	/// Returns a [`SubmittableTransaction`] that executes the proxied call.
1266	///
1267	/// # Errors
1268	/// Does not perform network calls; transaction construction never fails.
1269	pub fn proxy(
1270		&self,
1271		id: impl Into<MultiAddressLike>,
1272		force_proxy_type: Option<ProxyType>,
1273		call: impl Into<ExtrinsicCall>,
1274	) -> SubmittableTransaction {
1275		let id: MultiAddressLike = id.into();
1276		let id: MultiAddress = id.try_into().expect("Malformed string is passed for AccountId");
1277
1278		let value = avail::proxy::tx::Proxy { id, force_proxy_type, call: call.into() };
1279		SubmittableTransaction::from_encodable(self.0.clone(), value)
1280	}
1281
1282	/// Registers a new proxy delegate for the caller.
1283	///
1284	/// # Panics
1285	/// Panics if `id` cannot be converted into a `MultiAddress`.
1286	///
1287	/// # Arguments
1288	/// * `id` - Delegate account that gains proxy rights.
1289	/// * `proxy_type` - Proxy type applied to the delegate.
1290	/// * `delay` - Number of blocks the proxy must wait before first use.
1291	///
1292	/// # Returns
1293	/// Returns a [`SubmittableTransaction`] that adds the proxy.
1294	///
1295	/// # Errors
1296	/// Does not perform network calls; transaction construction never fails.
1297	pub fn add_proxy(
1298		&self,
1299		id: impl Into<MultiAddressLike>,
1300		proxy_type: ProxyType,
1301		delay: u32,
1302	) -> SubmittableTransaction {
1303		let id: MultiAddressLike = id.into();
1304		let id: MultiAddress = id.try_into().expect("Malformed string is passed for AccountId");
1305
1306		let value = avail::proxy::tx::AddProxy { id, proxy_type, delay };
1307		SubmittableTransaction::from_encodable(self.0.clone(), value)
1308	}
1309
1310	/// Removes a specific proxy delegate.
1311	///
1312	/// # Panics
1313	/// Panics if `delegate` cannot be converted into a `MultiAddress`.
1314	///
1315	/// # Arguments
1316	/// * `delegate` - Delegate being removed.
1317	/// * `proxy_type` - Proxy type to revoke.
1318	/// * `delay` - Expected delay recorded for the delegate.
1319	///
1320	/// # Returns
1321	/// Returns a [`SubmittableTransaction`] that removes the proxy.
1322	///
1323	/// # Errors
1324	/// Does not perform network calls; transaction construction never fails.
1325	pub fn remove_proxy(
1326		&self,
1327		delegate: impl Into<MultiAddressLike>,
1328		proxy_type: ProxyType,
1329		delay: u32,
1330	) -> SubmittableTransaction {
1331		let delegate: MultiAddressLike = delegate.into();
1332		let delegate: MultiAddress = delegate.try_into().expect("Malformed string is passed for AccountId");
1333
1334		let value = avail::proxy::tx::RemoveProxy { delegate, proxy_type, delay };
1335		SubmittableTransaction::from_encodable(self.0.clone(), value)
1336	}
1337
1338	/// Removes all proxies belonging to the caller.
1339	///
1340	/// # Returns
1341	/// Returns a [`SubmittableTransaction`] that clears the caller's proxies.
1342	///
1343	/// # Errors
1344	/// Does not perform network calls; transaction construction never fails.
1345	pub fn remove_proxies(&self) -> SubmittableTransaction {
1346		let value = avail::proxy::tx::RemoveProxies {};
1347		SubmittableTransaction::from_encodable(self.0.clone(), value)
1348	}
1349
1350	/// Creates a pure proxy account with the requested parameters.
1351	///
1352	/// # Arguments
1353	/// * `proxy_type` - Proxy type to associate with the pure proxy.
1354	/// * `delay` - Number of blocks the proxy must wait before use.
1355	/// * `index` - Index differentiating multiple pure proxies.
1356	///
1357	/// # Returns
1358	/// Returns a [`SubmittableTransaction`] that spawns the pure proxy.
1359	///
1360	/// # Errors
1361	/// Does not perform network calls; transaction construction never fails.
1362	pub fn create_pure(&self, proxy_type: ProxyType, delay: u32, index: u16) -> SubmittableTransaction {
1363		let value = avail::proxy::tx::CreatePure { proxy_type, delay, index };
1364		SubmittableTransaction::from_encodable(self.0.clone(), value)
1365	}
1366
1367	/// Kills a pure proxy that was previously spawned by the provided account.
1368	///
1369	/// # Panics
1370	/// Panics if `spawner` cannot be converted into a `MultiAddress`.
1371	///
1372	/// # Arguments
1373	/// * `spawner` - Account that originally spawned the pure proxy.
1374	/// * `proxy_type` - Proxy type associated with the pure proxy.
1375	/// * `index` - Index of the pure proxy to kill.
1376	/// * `height` - Block height recorded at spawn time.
1377	/// * `ext_index` - Extrinsic index recorded at spawn time.
1378	///
1379	/// # Returns
1380	/// Returns a [`SubmittableTransaction`] that destroys the pure proxy.
1381	///
1382	/// # Errors
1383	/// Does not perform network calls; transaction construction never fails.
1384	pub fn kill_pure(
1385		&self,
1386		spawner: impl Into<MultiAddressLike>,
1387		proxy_type: ProxyType,
1388		index: u16,
1389		height: u32,
1390		ext_index: u32,
1391	) -> SubmittableTransaction {
1392		let spawner: MultiAddressLike = spawner.into();
1393		let spawner: MultiAddress = spawner.try_into().expect("Malformed string is passed for AccountId");
1394
1395		let value = avail::proxy::tx::KillPure { spawner, proxy_type, index, height, ext_index };
1396		SubmittableTransaction::from_encodable(self.0.clone(), value)
1397	}
1398}
1399
1400/// Builds extrinsics for the `vector` pallet.
1401///
1402/// Several helpers convert hash-like parameters into `H256` values and will panic if the provided
1403/// data cannot be parsed.
1404pub struct Vector(Client);
1405impl Vector {
1406	/// Submits a fulfillment proof for a pending cross-chain call.
1407	///
1408	/// # Arguments
1409	/// * `function_id` - Identifier of the function being fulfilled.
1410	/// * `input` - Encoded input payload.
1411	/// * `output` - Encoded output payload.
1412	/// * `proof` - Proof bytes attesting to the fulfillment.
1413	/// * `slot` - Slot in which the message was queued.
1414	///
1415	/// # Returns
1416	/// Returns a [`SubmittableTransaction`] that fulfills the cross-chain call.
1417	///
1418	/// # Errors
1419	/// Does not perform network calls; transaction construction never fails.
1420	pub fn batch(
1421		&self,
1422		function_id: H256,
1423		input: Vec<u8>,
1424		output: Vec<u8>,
1425		proof: Vec<u8>,
1426		slot: u64,
1427	) -> SubmittableTransaction {
1428		let value = avail::vector::tx::FulfillCall { function_id, input, output, proof, slot };
1429		SubmittableTransaction::from_encodable(self.0.clone(), value)
1430	}
1431
1432	/// Executes a vector addressed message with witness data.
1433	///
1434	/// # Arguments
1435	/// * `slot` - Slot to execute.
1436	/// * `addr_message` - Addressed message payload.
1437	/// * `account_proof` - Proof for the account tree.
1438	/// * `storage_proof` - Proof for the storage entries.
1439	///
1440	/// # Returns
1441	/// Returns a [`SubmittableTransaction`] that executes the message.
1442	///
1443	/// # Errors
1444	/// Does not perform network calls; transaction construction never fails.
1445	pub fn execute(
1446		&self,
1447		slot: u64,
1448		addr_message: avail::vector::types::AddressedMessage,
1449		account_proof: Vec<Vec<u8>>,
1450		storage_proof: Vec<Vec<u8>>,
1451	) -> SubmittableTransaction {
1452		let value = avail::vector::tx::Execute { slot, addr_message, account_proof, storage_proof };
1453		SubmittableTransaction::from_encodable(self.0.clone(), value)
1454	}
1455
1456	/// Toggles whether a source chain is frozen.
1457	///
1458	/// # Arguments
1459	/// * `source_chain_id` - Identifier of the source chain.
1460	/// * `frozen` - Boolean indicating the desired freeze state.
1461	///
1462	/// # Returns
1463	/// Returns a [`SubmittableTransaction`] that updates the frozen state.
1464	///
1465	/// # Errors
1466	/// Does not perform network calls; transaction construction never fails.
1467	pub fn source_chain_froze(&self, source_chain_id: u32, frozen: bool) -> SubmittableTransaction {
1468		let value = avail::vector::tx::SourceChainFroze { source_chain_id, frozen };
1469		SubmittableTransaction::from_encodable(self.0.clone(), value)
1470	}
1471
1472	/// Sends a vector message to the specified domain.
1473	///
1474	/// # Panics
1475	/// Panics if `to` cannot be converted into an `H256`.
1476	///
1477	/// # Arguments
1478	/// * `message` - Message payload to send.
1479	/// * `to` - Destination address encoded as a hash string.
1480	/// * `domain` - Destination domain identifier.
1481	///
1482	/// # Returns
1483	/// Returns a [`SubmittableTransaction`] that enqueues the message.
1484	///
1485	/// # Errors
1486	/// Does not perform network calls; transaction construction never fails.
1487	pub fn send_message(
1488		&self,
1489		message: avail::vector::types::Message,
1490		to: impl Into<HashString>,
1491		domain: u32,
1492	) -> SubmittableTransaction {
1493		let to: HashString = to.into();
1494		let to: H256 = to.try_into().expect("Malformed string is passed for H256");
1495
1496		let value = avail::vector::tx::SendMessage { message, to, domain };
1497		SubmittableTransaction::from_encodable(self.0.clone(), value)
1498	}
1499
1500	/// Marks previous outbound messages as failed by index.
1501	///
1502	/// # Arguments
1503	/// * `failed_txs` - Indices of failed outbound messages.
1504	///
1505	/// # Returns
1506	/// Returns a [`SubmittableTransaction`] that records the failure.
1507	///
1508	/// # Errors
1509	/// Does not perform network calls; transaction construction never fails.
1510	pub fn failed_send_message_txs(&self, failed_txs: Vec<u32>) -> SubmittableTransaction {
1511		let value = avail::vector::tx::FailedSendMessageTxs { failed_txs };
1512		SubmittableTransaction::from_encodable(self.0.clone(), value)
1513	}
1514
1515	/// Updates the Poseidon hash commitment for a sync period.
1516	///
1517	/// # Arguments
1518	/// * `period` - Period identifier.
1519	/// * `poseidon_hash` - Poseidon hash commitment bytes.
1520	///
1521	/// # Returns
1522	/// Returns a [`SubmittableTransaction`] that stores the commitment.
1523	///
1524	/// # Errors
1525	/// Does not perform network calls; transaction construction never fails.
1526	pub fn set_poseidon_hash(&self, period: u64, poseidon_hash: Vec<u8>) -> SubmittableTransaction {
1527		let value = avail::vector::tx::SetPoseidonHash { period: period.into(), poseidon_hash };
1528		SubmittableTransaction::from_encodable(self.0.clone(), value)
1529	}
1530
1531	/// Registers the broadcaster for a specific domain.
1532	///
1533	/// # Arguments
1534	/// * `broadcaster_domain` - Domain where the broadcaster operates.
1535	/// * `broadcaster` - Broadcaster identifier.
1536	///
1537	/// # Returns
1538	/// Returns a [`SubmittableTransaction`] that sets the broadcaster.
1539	///
1540	/// # Errors
1541	/// Does not perform network calls; transaction construction never fails.
1542	pub fn set_broadcaster(&self, broadcaster_domain: u32, broadcaster: H256) -> SubmittableTransaction {
1543		let value = avail::vector::tx::SetBroadcaster { broadcaster_domain: broadcaster_domain.into(), broadcaster };
1544		SubmittableTransaction::from_encodable(self.0.clone(), value)
1545	}
1546
1547	/// Overwrites the set of domains allowed to send messages.
1548	///
1549	/// # Arguments
1550	/// * `value` - Domains permitted to send messages.
1551	///
1552	/// # Returns
1553	/// Returns a [`SubmittableTransaction`] that updates the whitelist.
1554	///
1555	/// # Errors
1556	/// Does not perform network calls; transaction construction never fails.
1557	pub fn set_whitelisted_domains(&self, value: Vec<u32>) -> SubmittableTransaction {
1558		let value = avail::vector::tx::SetWhitelistedDomains { value };
1559		SubmittableTransaction::from_encodable(self.0.clone(), value)
1560	}
1561
1562	/// Updates the vector configuration parameters.
1563	///
1564	/// # Arguments
1565	/// * `value` - Configuration structure applied to the pallet.
1566	///
1567	/// # Returns
1568	/// Returns a [`SubmittableTransaction`] that stores the configuration.
1569	///
1570	/// # Errors
1571	/// Does not perform network calls; transaction construction never fails.
1572	pub fn set_configuration(&self, value: avail::vector::types::Configuration) -> SubmittableTransaction {
1573		let value = avail::vector::tx::SetConfiguration { value };
1574		SubmittableTransaction::from_encodable(self.0.clone(), value)
1575	}
1576
1577	/// Updates the function identifiers used by the pallet.
1578	///
1579	/// # Arguments
1580	/// * `value` - Optional tuple containing new function identifiers.
1581	///
1582	/// # Returns
1583	/// Returns a [`SubmittableTransaction`] that records the identifiers.
1584	///
1585	/// # Errors
1586	/// Does not perform network calls; transaction construction never fails.
1587	pub fn set_function_ids(&self, value: Option<(H256, H256)>) -> SubmittableTransaction {
1588		let value = avail::vector::tx::SetFunctionIds { value };
1589		SubmittableTransaction::from_encodable(self.0.clone(), value)
1590	}
1591
1592	/// Sets the verification key for the step circuit.
1593	///
1594	/// # Arguments
1595	/// * `value` - Optional verification key bytes.
1596	///
1597	/// # Returns
1598	/// Returns a [`SubmittableTransaction`] that updates the verification key.
1599	///
1600	/// # Errors
1601	/// Does not perform network calls; transaction construction never fails.
1602	pub fn set_step_verification_key(&self, value: Option<Vec<u8>>) -> SubmittableTransaction {
1603		let value = avail::vector::tx::SetStepVerificationKey { value };
1604		SubmittableTransaction::from_encodable(self.0.clone(), value)
1605	}
1606
1607	/// Updates the updater account hash.
1608	///
1609	/// # Arguments
1610	/// * `updater` - New updater hash.
1611	///
1612	/// # Returns
1613	/// Returns a [`SubmittableTransaction`] that stores the updater hash.
1614	///
1615	/// # Errors
1616	/// Does not perform network calls; transaction construction never fails.
1617	pub fn set_updater(&self, updater: H256) -> SubmittableTransaction {
1618		let value = avail::vector::tx::SetUpdater { updater };
1619		SubmittableTransaction::from_encodable(self.0.clone(), value)
1620	}
1621
1622	/// Submits a zero-knowledge proof fulfilling a pending message.
1623	///
1624	/// # Arguments
1625	/// * `proof` - Proof bytes attesting to message fulfillment.
1626	/// * `public_values` - Public inputs used during verification.
1627	///
1628	/// # Returns
1629	/// Returns a [`SubmittableTransaction`] that fulfills the message.
1630	///
1631	/// # Errors
1632	/// Does not perform network calls; transaction construction never fails.
1633	pub fn fulfill(&self, proof: Vec<u8>, public_values: Vec<u8>) -> SubmittableTransaction {
1634		let value = avail::vector::tx::Fulfill { proof, public_values };
1635		SubmittableTransaction::from_encodable(self.0.clone(), value)
1636	}
1637
1638	/// Sets the verification key for SP1 proofs.
1639	///
1640	/// # Arguments
1641	/// * `sp1_vk` - SP1 verification key hash.
1642	///
1643	/// # Returns
1644	/// Returns a [`SubmittableTransaction`] that stores the key.
1645	///
1646	/// # Errors
1647	/// Does not perform network calls; transaction construction never fails.
1648	pub fn set_sp1_verification_key(&self, sp1_vk: H256) -> SubmittableTransaction {
1649		let value = avail::vector::tx::SetSp1VerificationKey { sp1_vk };
1650		SubmittableTransaction::from_encodable(self.0.clone(), value)
1651	}
1652
1653	/// Updates the sync committee hash for the provided period.
1654	///
1655	/// # Arguments
1656	/// * `period` - Period identifier.
1657	/// * `hash` - New sync committee hash.
1658	///
1659	/// # Returns
1660	/// Returns a [`SubmittableTransaction`] that stores the sync committee hash.
1661	///
1662	/// # Errors
1663	/// Does not perform network calls; transaction construction never fails.
1664	pub fn set_sync_committee_hash(&self, period: u64, hash: H256) -> SubmittableTransaction {
1665		let value = avail::vector::tx::SetSyncCommitteeHash { period, hash };
1666		SubmittableTransaction::from_encodable(self.0.clone(), value)
1667	}
1668
1669	/// Enables or disables mock execution mode.
1670	///
1671	/// # Arguments
1672	/// * `value` - `true` to enable mock mode, `false` to disable.
1673	///
1674	/// # Returns
1675	/// Returns a [`SubmittableTransaction`] that toggles mock mode.
1676	///
1677	/// # Errors
1678	/// Does not perform network calls; transaction construction never fails.
1679	pub fn enable_mock(&self, value: bool) -> SubmittableTransaction {
1680		let value = avail::vector::tx::EnableMock { value };
1681		SubmittableTransaction::from_encodable(self.0.clone(), value)
1682	}
1683
1684	/// Fulfills a message when running in mock mode.
1685	///
1686	/// # Arguments
1687	/// * `public_values` - Mock public values consumed by the fulfillment.
1688	///
1689	/// # Returns
1690	/// Returns a [`SubmittableTransaction`] that fulfills the message in mock mode.
1691	///
1692	/// # Errors
1693	/// Does not perform network calls; transaction construction never fails.
1694	pub fn mock_fulfill(&self, public_values: Vec<u8>) -> SubmittableTransaction {
1695		let value = avail::vector::tx::MockFulfill { public_values };
1696		SubmittableTransaction::from_encodable(self.0.clone(), value)
1697	}
1698}
1699
1700/// Builds extrinsics for the `system` pallet.
1701pub struct System(Client);
1702impl System {
1703	/// Emits a remark event containing arbitrary bytes.
1704	///
1705	/// # Arguments
1706	/// * `remark` - Payload recorded on chain.
1707	///
1708	/// # Returns
1709	/// Returns a [`SubmittableTransaction`] that emits the remark.
1710	///
1711	/// # Errors
1712	/// Does not perform network calls; transaction construction never fails.
1713	pub fn remark(&self, remark: Vec<u8>) -> SubmittableTransaction {
1714		let value = avail::system::tx::Remark { remark };
1715		SubmittableTransaction::from_encodable(self.0.clone(), value)
1716	}
1717
1718	/// Replaces the runtime code with a new version.
1719	///
1720	/// # Arguments
1721	/// * `code` - WASM runtime bytecode.
1722	///
1723	/// # Returns
1724	/// Returns a [`SubmittableTransaction`] that schedules the code upgrade.
1725	///
1726	/// # Errors
1727	/// Does not perform network calls; transaction construction never fails.
1728	pub fn set_code(&self, code: Vec<u8>) -> SubmittableTransaction {
1729		let value = avail::system::tx::SetCode { code };
1730		SubmittableTransaction::from_encodable(self.0.clone(), value)
1731	}
1732
1733	/// Replaces the runtime code without performing standard checks.
1734	///
1735	/// # Arguments
1736	/// * `code` - WASM runtime bytecode.
1737	///
1738	/// # Returns
1739	/// Returns a [`SubmittableTransaction`] that forces the code upgrade.
1740	///
1741	/// # Errors
1742	/// Does not perform network calls; transaction construction never fails.
1743	pub fn set_code_without_checks(&self, code: Vec<u8>) -> SubmittableTransaction {
1744		let value = avail::system::tx::SetCodeWithoutChecks { code };
1745		SubmittableTransaction::from_encodable(self.0.clone(), value)
1746	}
1747
1748	/// Emits a remark while guaranteeing an event is produced.
1749	///
1750	/// # Arguments
1751	/// * `remark` - Payload recorded on chain.
1752	///
1753	/// # Returns
1754	/// Returns a [`SubmittableTransaction`] that emits the remark alongside an event.
1755	///
1756	/// # Errors
1757	/// Does not perform network calls; transaction construction never fails.
1758	pub fn remark_with_event(&self, remark: Vec<u8>) -> SubmittableTransaction {
1759		let value = avail::system::tx::RemarkWithEvent { remark };
1760		SubmittableTransaction::from_encodable(self.0.clone(), value)
1761	}
1762}