1
// Copyright 2025 Moonbeam foundation
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonbeam is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! Kusama AssetHub pallet and call indices
18
//!
19
//! These indices have been verified against the actual Kusama AssetHub runtime metadata.
20
//!
21
//! ## Verification
22
//!
23
//! Verified using:
24
//! ```bash
25
//! subxt metadata --url wss://kusama-asset-hub-rpc.polkadot.io:443 --format json
26
//! ```
27
//!
28
//! ## Sources
29
//! - Runtime: Kusama AssetHub (asset-hub-kusama)
30
//! - Metadata version: V16
31
//! - Last verified: 2025-11-14
32

            
33
use pallet_xcm_transactor::chain_indices::AssetHubIndices;
34
use parity_scale_codec::{Decode, Encode};
35
use sp_runtime::traits::{AccountIdLookup, StaticLookup};
36
use sp_runtime::AccountId32;
37
use sp_std::vec::Vec;
38

            
39
/// Kusama AssetHub pallet and extrinsic indices
40
///
41
/// All indices have been verified against live Kusama AssetHub metadata.
42
/// Kusama AssetHub has the same pallet and call indices as Polkadot AssetHub.
43
pub const KUSAMA_ASSETHUB_INDICES: AssetHubIndices = AssetHubIndices {
44
	// Pallet indices (from AssetHub Kusama runtime metadata)
45
	utility: 40,
46
	proxy: 42,
47
	staking: 89,
48
	nomination_pools: 80,
49
	delegated_staking: 83,
50
	assets: 50,
51
	nfts: 52,
52

            
53
	// Utility call indices
54
	as_derivative: 1,
55
	batch: 0,
56
	batch_all: 2,
57

            
58
	// Proxy call indices
59
	proxy_call: 0,
60
	add_proxy: 1,
61
	remove_proxy: 2,
62

            
63
	// Staking call indices
64
	bond: 0,
65
	bond_extra: 1,
66
	unbond: 2,
67
	withdraw_unbonded: 3,
68
	validate: 4,
69
	nominate: 5,
70
	chill: 6,
71
	set_payee: 7,
72
	set_controller: 8, // Deprecated but present
73
	rebond: 19,
74
};
75

            
76
/// Root-level call enum for Kusama AssetHub
77
#[derive(Encode, Decode)]
78
pub enum AssetHubCall {
79
	#[codec(index = 89u8)]
80
	Staking(StakeCall),
81
}
82

            
83
/// Staking pallet call enum for Kusama AssetHub
84
#[derive(Encode, Decode)]
85
pub enum StakeCall {
86
	#[codec(index = 0u16)]
87
	Bond(
88
		#[codec(compact)] u128,
89
		pallet_staking::RewardDestination<AccountId32>,
90
	),
91
	#[codec(index = 1u16)]
92
	BondExtra(#[codec(compact)] u128),
93
	#[codec(index = 2u16)]
94
	Unbond(#[codec(compact)] u128),
95
	#[codec(index = 3u16)]
96
	WithdrawUnbonded(u32),
97
	#[codec(index = 4u16)]
98
	Validate(pallet_staking::ValidatorPrefs),
99
	#[codec(index = 5u16)]
100
	Nominate(Vec<<AccountIdLookup<AccountId32, ()> as StaticLookup>::Source>),
101
	#[codec(index = 6u16)]
102
	Chill,
103
	#[codec(index = 7u16)]
104
	SetPayee(pallet_staking::RewardDestination<AccountId32>),
105
	#[codec(index = 8u16)]
106
	SetController,
107
	#[codec(index = 19u16)]
108
	Rebond(#[codec(compact)] u128),
109
}
110

            
111
pub struct KusamaAssetHubEncoder;
112

            
113
impl xcm_primitives::StakeEncodeCall<()> for KusamaAssetHubEncoder {
114
	fn encode_call(_transactor: (), call: xcm_primitives::AvailableStakeCalls) -> Vec<u8> {
115
		match call {
116
			xcm_primitives::AvailableStakeCalls::Bond(b, c) => {
117
				AssetHubCall::Staking(StakeCall::Bond(b, c)).encode()
118
			}
119

            
120
			xcm_primitives::AvailableStakeCalls::BondExtra(a) => {
121
				AssetHubCall::Staking(StakeCall::BondExtra(a)).encode()
122
			}
123

            
124
			xcm_primitives::AvailableStakeCalls::Unbond(a) => {
125
				AssetHubCall::Staking(StakeCall::Unbond(a)).encode()
126
			}
127

            
128
			xcm_primitives::AvailableStakeCalls::WithdrawUnbonded(a) => {
129
				AssetHubCall::Staking(StakeCall::WithdrawUnbonded(a)).encode()
130
			}
131

            
132
			xcm_primitives::AvailableStakeCalls::Validate(a) => {
133
				AssetHubCall::Staking(StakeCall::Validate(a)).encode()
134
			}
135

            
136
			xcm_primitives::AvailableStakeCalls::Chill => {
137
				AssetHubCall::Staking(StakeCall::Chill).encode()
138
			}
139

            
140
			xcm_primitives::AvailableStakeCalls::SetPayee(a) => {
141
				AssetHubCall::Staking(StakeCall::SetPayee(a.into())).encode()
142
			}
143

            
144
			xcm_primitives::AvailableStakeCalls::SetController => {
145
				AssetHubCall::Staking(StakeCall::SetController).encode()
146
			}
147

            
148
			xcm_primitives::AvailableStakeCalls::Rebond(a) => {
149
				AssetHubCall::Staking(StakeCall::Rebond(a.into())).encode()
150
			}
151

            
152
			xcm_primitives::AvailableStakeCalls::Nominate(a) => {
153
				let nominated: Vec<<AccountIdLookup<AccountId32, ()> as StaticLookup>::Source> =
154
					a.iter().map(|add| (*add).clone().into()).collect();
155

            
156
				AssetHubCall::Staking(StakeCall::Nominate(nominated)).encode()
157
			}
158
		}
159
	}
160
}