Skip to content

Commit 385185d

Browse files
feat(polkadot): Add Staking.BondExtraAndNominate transaction type (#4428)
1 parent 0e19dd0 commit 385185d

File tree

4 files changed

+102
-4
lines changed

4 files changed

+102
-4
lines changed

rust/chains/tw_polkadot/src/call_encoder/mod.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use tw_proto::Polkadot::Proto::{
55
mod_CallIndices::OneOfvariant as CallIndicesVariant,
66
mod_SigningInput::OneOfmessage_oneof as SigningVariant,
77
mod_Staking::{
8-
Bond, BondAndNominate, Chill, ChillAndUnbond, Nominate,
8+
Bond, BondAndNominate, BondExtra, BondExtraAndNominate, Chill, ChillAndUnbond, Nominate,
99
OneOfmessage_oneof as StakingVariant, Unbond,
1010
},
1111
Balance, CallIndices, Staking,
@@ -131,6 +131,30 @@ impl CallEncoder {
131131
self.encode_batch(vec![first, second], &ban.call_indices)
132132
}
133133

134+
fn encode_staking_bond_extra_and_nominate(
135+
&self,
136+
bean: &BondExtraAndNominate,
137+
) -> EncodeResult<RawOwned> {
138+
// Encode a bond call
139+
let first = self.encode_call(&SigningVariant::staking_call(Proto::Staking {
140+
message_oneof: StakingVariant::bond_extra(BondExtra {
141+
value: bean.value.clone(),
142+
call_indices: bean.bond_extra_call_indices.clone(),
143+
}),
144+
}))?;
145+
146+
// Encode a nominate call
147+
let second = self.encode_call(&SigningVariant::staking_call(Proto::Staking {
148+
message_oneof: StakingVariant::nominate(Nominate {
149+
nominators: bean.nominators.clone(),
150+
call_indices: bean.nominate_call_indices.clone(),
151+
}),
152+
}))?;
153+
154+
// Encode both calls as batched
155+
self.encode_batch(vec![first, second], &bean.call_indices)
156+
}
157+
134158
fn encode_staking_chill_and_unbond(&self, cau: &ChillAndUnbond) -> EncodeResult<RawOwned> {
135159
let first = self.encode_call(&SigningVariant::staking_call(Proto::Staking {
136160
message_oneof: StakingVariant::chill(Chill {
@@ -155,6 +179,10 @@ impl CallEncoder {
155179
let batch = self.encode_staking_bond_and_nominate(ban)?;
156180
Ok(Some(batch))
157181
},
182+
StakingVariant::bond_extra_and_nominate(bean) => {
183+
let batch = self.encode_staking_bond_extra_and_nominate(bean)?;
184+
Ok(Some(batch))
185+
},
158186
StakingVariant::chill_and_unbond(cau) => {
159187
let batch = self.encode_staking_chill_and_unbond(cau)?;
160188
Ok(Some(batch))

rust/tw_tests/tests/chains/polkadot/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,12 @@ pub fn helper_encode_and_compile(
6868
let mut pre_imager = PreImageHelper::<CompilerProto::PreSigningOutput>::default();
6969
let preimage_output = pre_imager.pre_image_hashes(coin, &input);
7070

71-
assert_eq!(preimage_output.error, SigningError::OK);
71+
assert_eq!(
72+
preimage_output.error,
73+
SigningError::OK,
74+
"{}",
75+
preimage_output.error_message
76+
);
7277
let preimage = preimage_output.data.to_hex();
7378

7479
// Step 2: Compile transaction info
@@ -87,7 +92,7 @@ pub fn helper_encode_and_compile(
8792
// Compile transaction info
8893
let mut compiler = CompilerHelper::<Proto::SigningOutput>::default();
8994
let output = compiler.compile(coin, &input, vec![signature_bytes], vec![public_key]);
90-
assert_eq!(output.error, SigningError::OK);
95+
assert_eq!(output.error, SigningError::OK, "{}", output.error_message);
9196
let signed = output.encoded.to_hex();
9297

9398
(preimage, signed)

rust/tw_tests/tests/chains/polkadot/polkadot_compile.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
//
33
// Copyright © 2017 Trust Wallet.
44

5-
use crate::chains::polkadot::{balance_call, helper_encode_and_compile, GENESIS_HASH};
5+
use crate::chains::polkadot::{
6+
balance_call, helper_encode_and_compile, staking_call, GENESIS_HASH,
7+
};
8+
use std::borrow::Cow;
69
use tw_coin_registry::coin_type::CoinType;
710
use tw_encoding::hex::DecodeHex;
11+
use tw_number::U256;
812
use tw_proto::Polkadot::Proto::{self, mod_Balance::Transfer};
913

1014
#[test]
@@ -51,3 +55,45 @@ fn test_polkadot_compile_transfer() {
5155
"390284d84accbb64934815506288fafbfc7d275e64aa4e3cd9c5392db6e83b13256bf300fb43727477caaa12542b9060856816d42eedef6ebf2e98e4f8dff4355fe384751925833c4a26b2fed1707aebe655cb3317504a61ee59697c086f7baa6ca06a099dfe00000500be4c21aa92dcba057e9b719ce1de970f774f064c09b13a3ea3009affb8cb5ec707000cdc0f21"
5256
);
5357
}
58+
59+
// Successfully broadcasted transaction on Polkadot mainnet:
60+
// https://polkadot.subscan.io/extrinsic/26528041-2
61+
#[test]
62+
fn test_polkadot_compile_bond_extra_and_nominate() {
63+
// Step 1: Prepare input.
64+
let genesis_hash = GENESIS_HASH.decode_hex().unwrap();
65+
let input = Proto::SigningInput {
66+
network: 0,
67+
nonce: 18,
68+
block_hash: genesis_hash.clone().into(),
69+
genesis_hash: genesis_hash.into(),
70+
spec_version: 1005001,
71+
transaction_version: 26,
72+
message_oneof: staking_call(
73+
Proto::mod_Staking::OneOfmessage_oneof::bond_extra_and_nominate(
74+
Proto::mod_Staking::BondExtraAndNominate {
75+
value: Cow::Owned(U256::from(50_000_000_000_u64).to_big_endian().to_vec()),
76+
nominators: vec!["14Y4s6V1PWrwBLvxW47gcYgZCGTYekmmzvFsK1kiqNH2d84t".into()],
77+
..Default::default()
78+
},
79+
),
80+
),
81+
..Default::default()
82+
};
83+
84+
// Simulate signature, normally obtained from signature server
85+
let signature = "0xb959bd1506e2863cd3f92bd703d31b3f38847e6425f8abd94fa1aed863b5e27c45008abb8d260d8d306b0f129ebe5e2eb845dc3e6585a08d4be231e4b886cd0e";
86+
let public_key = "0x4883c6369ec0764c0cada1dcc55a4873d1c1c6a13400bf57c206e660302081ca";
87+
88+
let (preimage, signed) =
89+
helper_encode_and_compile(CoinType::Polkadot, input, signature, public_key, true);
90+
91+
assert_eq!(
92+
preimage,
93+
"1a020807010700743ba40b070504009c665073980c9bdbd5620ef9a860b9f1efbeda8f10e13ef7431f6970d765a25700480000c9550f001a00000091b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c391b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c300"
94+
);
95+
assert_eq!(
96+
signed,
97+
"590284004883c6369ec0764c0cada1dcc55a4873d1c1c6a13400bf57c206e660302081ca00b959bd1506e2863cd3f92bd703d31b3f38847e6425f8abd94fa1aed863b5e27c45008abb8d260d8d306b0f129ebe5e2eb845dc3e6585a08d4be231e4b886cd0e004800001a020807010700743ba40b070504009c665073980c9bdbd5620ef9a860b9f1efbeda8f10e13ef7431f6970d765a257"
98+
);
99+
}

src/proto/Polkadot.proto

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,24 @@ message Staking {
139139
CallIndices nominate_call_indices = 7;
140140
}
141141

142+
// Bond extra, with nominators
143+
message BondExtraAndNominate {
144+
// amount (uint256, serialized big endian)
145+
bytes value = 1;
146+
147+
// list of nominators
148+
repeated string nominators = 2;
149+
150+
// Batch call indices
151+
CallIndices call_indices = 3;
152+
153+
// Staking.BondExtra call indices
154+
CallIndices bond_extra_call_indices = 4;
155+
156+
// Staking.Nominate call indices
157+
CallIndices nominate_call_indices = 5;
158+
}
159+
142160
// Bond extra amount
143161
message BondExtra {
144162
// amount (uint256, serialized big endian)
@@ -215,6 +233,7 @@ message Staking {
215233
Chill chill = 7;
216234
ChillAndUnbond chill_and_unbond = 8;
217235
Rebond rebond = 9;
236+
BondExtraAndNominate bond_extra_and_nominate = 10;
218237
}
219238
}
220239

0 commit comments

Comments
 (0)