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
//! Polkadot AssetHub pallet and call indices
18
//!
19
//! These indices have been verified against the actual Polkadot AssetHub runtime metadata.
20
//!
21
//! ## Verification
22
//!
23
//! Verified using:
24
//! ```bash
25
//! subxt metadata --url wss://polkadot-asset-hub-rpc.polkadot.io:443 --format json
26
//! ```
27
//!
28
//! ## Sources
29
//! - Runtime: Polkadot AssetHub (asset-hub-polkadot)
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
/// Polkadot AssetHub pallet and extrinsic indices
40
///
41
/// All indices have been verified against live Polkadot AssetHub metadata.
42
pub const POLKADOT_ASSETHUB_INDICES: AssetHubIndices = AssetHubIndices {
43
	// Pallet indices (from AssetHub Polkadot runtime metadata)
44
	utility: 40,
45
	proxy: 42,
46
	staking: 89,
47
	nomination_pools: 80,
48
	delegated_staking: 83,
49
	assets: 50,
50
	nfts: 52,
51

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

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

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

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

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

            
110
pub struct PolkadotAssetHubEncoder;
111

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

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

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

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

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

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

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

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

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

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

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