fix: remove staking-score from relay chain, fix CI quick-checks

- Remove pezpallet_staking_score from relay chain runtime (noter model
  lives on People Chain only)
- Update welati mock to current staking-score Config trait
- Fix staking-score feature propagation (zepter: std, runtime-benchmarks)
- Format vendor subxt example files (rustfmt)
- Regenerate umbrella crate
- Update CRITICAL_STATE.md with noter delegation status
This commit is contained in:
2026-02-16 19:50:13 +03:00
parent d23daa8f67
commit da3a8f23c0
25 changed files with 652 additions and 741 deletions
Generated
-1
View File
@@ -14932,7 +14932,6 @@ dependencies = [
"pezpallet-session-benchmarking",
"pezpallet-staking",
"pezpallet-staking-runtime-api",
"pezpallet-staking-score",
"pezpallet-state-trie-migration",
"pezpallet-sudo",
"pezpallet-timestamp",
@@ -27,12 +27,13 @@ serde = { version = "1.0.197", default-features = false, features = [
# PezkuwiChain primitives
pezkuwi-primitives = { workspace = true, default-features = false }
# dev / test dependencies (also used as optional for feature propagation)
pezpallet-balances = { workspace = true, default-features = false, optional = true }
pezsp-io = { workspace = true, default-features = false, optional = true }
[dev-dependencies]
pezframe-support = { workspace = true, features = ["std"] }
pezframe-system = { workspace = true, features = ["std"] }
pezpallet-balances = { workspace = true, features = ["std"] }
pezsp-io = { workspace = true, features = ["std"] }
pezsp-runtime = { workspace = true, features = ["std"] }
[features]
default = ["std"]
@@ -41,7 +42,9 @@ std = [
"pezframe-benchmarking?/std",
"pezframe-support/std",
"pezframe-system/std",
"pezpallet-balances?/std",
"pezkuwi-primitives/std",
"pezsp-io?/std",
"pezsp-runtime/std",
"pezsp-std/std",
"scale-info/std",
@@ -53,6 +56,8 @@ runtime-benchmarks = [
"pezframe-system/runtime-benchmarks",
"pezkuwi-primitives/runtime-benchmarks",
"pezsp-runtime/runtime-benchmarks",
"pezpallet-balances/runtime-benchmarks",
"pezsp-io/runtime-benchmarks",
]
try-runtime = [
"pezframe-benchmarking?/try-runtime",
@@ -60,6 +65,7 @@ try-runtime = [
"pezframe-system/try-runtime",
"pezkuwi-primitives/try-runtime",
"pezsp-runtime/try-runtime",
"pezpallet-balances?/try-runtime"
]
serde = [
"codec/serde",
@@ -282,25 +282,12 @@ impl pezpallet_identity_kyc::Config for Test {
type DefaultReferrer = DefaultReferrerKyc;
}
// Mock StakingInfo provider - SADECE BİR KEZ TANIMLA
pub struct MockStakingInfo;
impl pezpallet_staking_score::StakingInfoProvider<AccountId, Balance> for MockStakingInfo {
fn get_staking_details(
_account: &AccountId,
) -> Option<pezpallet_staking_score::StakingDetails<Balance>> {
Some(pezpallet_staking_score::StakingDetails {
staked_amount: 1000u128,
nominations_count: 0,
unlocking_chunks_count: 0,
})
}
}
// Staking Score Configuration
impl pezpallet_staking_score::Config for Test {
type WeightInfo = ();
type Balance = Balance;
type StakingInfo = MockStakingInfo;
type OnStakingUpdate = ();
type WeightInfo = ();
type NoterChecker = ();
}
// Referral Configuration
-4
View File
@@ -111,7 +111,6 @@ pezkuwi-runtime-teyrchains = { workspace = true }
pezkuwi-teyrchain-primitives = { workspace = true }
# Custom Pezkuwi Pallets
pezpallet-staking-score = { workspace = true }
pezpallet-validator-pool = { workspace = true }
xcm = { workspace = true }
@@ -184,7 +183,6 @@ std = [
"pezpallet-session-benchmarking?/std",
"pezpallet-session/std",
"pezpallet-staking-runtime-api/std",
"pezpallet-staking-score/std",
"pezpallet-staking/std",
"pezpallet-state-trie-migration/std",
"pezpallet-sudo/std",
@@ -277,7 +275,6 @@ runtime-benchmarks = [
"pezpallet-session-benchmarking/runtime-benchmarks",
"pezpallet-session/runtime-benchmarks",
"pezpallet-staking-runtime-api/runtime-benchmarks",
"pezpallet-staking-score/runtime-benchmarks",
"pezpallet-staking/runtime-benchmarks",
"pezpallet-state-trie-migration/runtime-benchmarks",
"pezpallet-sudo/runtime-benchmarks",
@@ -360,7 +357,6 @@ try-runtime = [
"pezpallet-scheduler/try-runtime",
"pezpallet-session-benchmarking?/try-runtime",
"pezpallet-session/try-runtime",
"pezpallet-staking-score/try-runtime",
"pezpallet-staking/try-runtime",
"pezpallet-state-trie-migration/try-runtime",
"pezpallet-sudo/try-runtime",
-38
View File
@@ -565,40 +565,6 @@ impl pezpallet_staking::Config for Runtime {
type BenchmarkingConfig = PezkuwiStakingBenchmarkingConfig;
}
// =====================================================
// STAKING SCORE CONFIGURATION
// =====================================================
/// Relay Chain StakingInfoProvider - reads directly from pezpallet_staking
/// This is the REAL implementation that accesses actual staking data
pub struct RelayStakingInfoProvider;
impl pezpallet_staking_score::StakingInfoProvider<AccountId, Balance> for RelayStakingInfoProvider {
fn get_staking_details(
who: &AccountId,
) -> Option<pezpallet_staking_score::StakingDetails<Balance>> {
// Get staking ledger from pezpallet_staking
let ledger = pezpallet_staking::Ledger::<Runtime>::get(who)?;
// Get nominations if any
let nominations_count = pezpallet_staking::Nominators::<Runtime>::get(who)
.map(|n| n.targets.len() as u32)
.unwrap_or(0);
Some(pezpallet_staking_score::StakingDetails {
staked_amount: ledger.active,
nominations_count,
unlocking_chunks_count: ledger.unlocking.len() as u32,
})
}
}
impl pezpallet_staking_score::Config for Runtime {
type Balance = Balance;
type StakingInfo = RelayStakingInfoProvider;
type WeightInfo = pezpallet_staking_score::weights::BizinikiwiWeight<Runtime>;
}
// =====================================================
// FAST UNSTAKE CONFIGURATION
// =====================================================
@@ -1605,9 +1571,6 @@ construct_runtime! {
// TNPoS Validator Pool - Shadow Mode (runs parallel to NPoS)
ValidatorPool: pezpallet_validator_pool = 91,
// Staking Score - Time-weighted staking reputation score
StakingScore: pezpallet_staking_score = 92,
// Root testing pezpallet.
RootTesting: pezpallet_root_testing = 249,
@@ -1859,7 +1822,6 @@ mod benches {
[pezpallet_whitelist, Whitelist]
// Pezkuwichain Custom Pallets
[pezpallet_validator_pool, ValidatorPool]
[pezpallet_staking_score, StakingScore]
// XCM
[pezpallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
[pezpallet_xcm_benchmarks::fungible, pezpallet_xcm_benchmarks::fungible::Pezpallet::<Runtime>]
-1
View File
@@ -1,6 +1,5 @@
[package]
name = "pezkuwi-sdk"
version = "0.0.0"
description = "Pezkuwi SDK umbrella crate."
license = "Apache-2.0"
+13 -40
View File
@@ -23,7 +23,7 @@ const ASSET_HUB_PARA_ID: u32 = 1000;
// NominationPools pallet index on Asset Hub
const NOM_POOLS_PALLET_INDEX: u8 = 81; // 0x51
// set_configs call index
// set_configs call index
const SET_CONFIGS_CALL_INDEX: u8 = 11; // 0x0b
/// SCALE encode ConfigOp::Noop
@@ -74,9 +74,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let relay_url =
std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let min_join_hez: u128 = std::env::var("MIN_JOIN_BOND")
.unwrap_or_else(|_| "10".to_string())
.parse()?;
let min_join_hez: u128 =
std::env::var("MIN_JOIN_BOND").unwrap_or_else(|_| "10".to_string()).parse()?;
let min_create_hez: u128 = std::env::var("MIN_CREATE_BOND")
.unwrap_or_else(|_| "10000".to_string())
.parse()?;
@@ -87,10 +86,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Relay RPC: {}", relay_url);
println!("Asset Hub Para ID: {}", ASSET_HUB_PARA_ID);
println!("MinJoinBond: {} HEZ ({} TYR)", min_join_hez, min_join_bond);
println!(
"MinCreateBond: {} HEZ ({} TYR)",
min_create_hez, min_create_bond
);
println!("MinCreateBond: {} HEZ ({} TYR)", min_create_hez, min_create_bond);
// Connect to relay chain
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&relay_url).await?;
@@ -105,11 +101,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Encode the NominationPools::set_configs call for Asset Hub
let encoded_call = encode_set_configs_call(min_join_bond, min_create_bond);
println!(
"Encoded call: {} bytes (0x{})",
encoded_call.len(),
hex::encode(&encoded_call)
);
println!("Encoded call: {} bytes (0x{})", encoded_call.len(), hex::encode(&encoded_call));
// Build XCM destination: V3 MultiLocation { parents: 0, interior: X1(Teyrchain(1000)) }
let dest = Value::unnamed_variant(
@@ -136,23 +128,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Value::named_variant(
"UnpaidExecution",
[
(
"weight_limit",
Value::unnamed_variant("Unlimited", vec![]),
),
(
"check_origin",
Value::unnamed_variant("None", vec![]),
),
("weight_limit", Value::unnamed_variant("Unlimited", vec![])),
("check_origin", Value::unnamed_variant("None", vec![])),
],
),
Value::named_variant(
"Transact",
[
(
"origin_kind",
Value::unnamed_variant("Superuser", vec![]),
),
("origin_kind", Value::unnamed_variant("Superuser", vec![])),
(
"require_weight_at_most",
Value::named_composite([
@@ -167,8 +150,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
);
// Wrap in XcmPallet.send
let xcm_send =
pezkuwi_subxt::dynamic::tx("XcmPallet", "send", vec![dest, message]);
let xcm_send = pezkuwi_subxt::dynamic::tx("XcmPallet", "send", vec![dest, message]);
// Wrap in sudo_unchecked_weight (no weight limit for sudo)
let sudo_call = pezkuwi_subxt::dynamic::tx(
@@ -188,15 +170,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Submit and watch
use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await?;
let tx_progress =
api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await?;
println!(
"TX hash: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!("TX hash: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
println!("Watching TX status...");
let mut progress = tx_progress;
@@ -212,11 +189,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" TX SUCCESS!");
for event in events.iter() {
if let Ok(ev) = event {
println!(
" Event: {}::{}",
ev.pallet_name(),
ev.variant_name()
);
println!(" Event: {}::{}", ev.pallet_name(), ev.variant_name());
}
}
},
+15 -29
View File
@@ -28,10 +28,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.unwrap_or_else(|_| "499000".to_string())
.parse()?;
let bond_planck = bond_hez * PLANCKS_PER_HEZ;
let skip: usize = std::env::var("SKIP")
.unwrap_or_else(|_| "0".to_string())
.parse()
.unwrap_or(0);
let skip: usize =
std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
println!("RPC: {}", url);
println!("Wallets file: {}", wallets_file);
@@ -90,33 +88,24 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" Account: {}", account);
// staking.bond_extra(max_additional: Balance)
let bond_extra_tx = pezkuwi_subxt::dynamic::tx(
"Staking",
"bond_extra",
vec![Value::u128(bond_planck)],
);
let bond_extra_tx =
pezkuwi_subxt::dynamic::tx("Staking", "bond_extra", vec![Value::u128(bond_planck)]);
use pezkuwi_subxt::tx::TxStatus;
let mut tx_ok = false;
for attempt in 0..3 {
let tx_progress = match api
.tx()
.sign_and_submit_then_watch_default(&bond_extra_tx, &keypair)
.await
{
Ok(p) => p,
Err(e) => {
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
tokio::time::sleep(std::time::Duration::from_secs(12)).await;
continue;
},
};
let tx_progress =
match api.tx().sign_and_submit_then_watch_default(&bond_extra_tx, &keypair).await {
Ok(p) => p,
Err(e) => {
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
tokio::time::sleep(std::time::Duration::from_secs(12)).await;
continue;
},
};
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
loop {
@@ -198,10 +187,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("\n=== RESULTS ===");
println!("Success: {}/{}", success_count, stash_wallets.len() - skip);
println!("Failed: {}/{}", fail_count, stash_wallets.len() - skip);
println!(
"Total bonded: {} HEZ",
bond_hez * success_count as u128
);
println!("Total bonded: {} HEZ", bond_hez * success_count as u128);
Ok(())
}
@@ -85,13 +85,7 @@ fn build_pool_configs(wallets: Vec<WalletInfo>) -> Vec<PoolConfig> {
.enumerate()
.map(|(i, w)| {
let stake_hez = base_stake.saturating_sub(i as u128 * 10_000);
PoolConfig {
name: w.name,
mnemonic: w.mnemonic,
ss58: w.ss58,
transfer_hez,
stake_hez,
}
PoolConfig { name: w.name, mnemonic: w.mnemonic, ss58: w.ss58, transfer_hez, stake_hez }
})
.collect()
}
@@ -104,26 +98,20 @@ async fn wait_for_success(
loop {
let status = progress.next().await;
match status {
Some(Ok(TxStatus::InBestBlock(details))) => {
match details.wait_for_success().await {
Ok(events) => {
println!(" {} SUCCESS!", label);
for event in events.iter() {
if let Ok(ev) = event {
println!(
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
}
Some(Ok(TxStatus::InBestBlock(details))) => match details.wait_for_success().await {
Ok(events) => {
println!(" {} SUCCESS!", label);
for event in events.iter() {
if let Ok(ev) = event {
println!(" {}::{}", ev.pallet_name(), ev.variant_name());
}
return Ok(true);
},
Err(e) => {
println!(" {} DISPATCH ERROR: {}", label, e);
return Ok(false);
},
}
}
return Ok(true);
},
Err(e) => {
println!(" {} DISPATCH ERROR: {}", label, e);
return Ok(false);
},
},
Some(Ok(TxStatus::Error { message })) => {
println!(" {} TX ERROR: {}", label, message);
@@ -158,13 +146,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Parse CLI args
let args: Vec<String> = std::env::args().collect();
let phase = args.get(1).map(|s| s.as_str()).unwrap_or("all");
let skip: usize = std::env::var("SKIP")
.unwrap_or_else(|_| "0".to_string())
.parse()
.unwrap_or(0);
let skip: usize =
std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
let rpc =
std::env::var("ASSET_HUB_RPC").unwrap_or_else(|_| DEFAULT_ASSET_HUB_RPC.to_string());
let rpc = std::env::var("ASSET_HUB_RPC").unwrap_or_else(|_| DEFAULT_ASSET_HUB_RPC.to_string());
println!("=== NOMINATION POOL CREATOR ===");
println!("Asset Hub RPC: {}", rpc);
@@ -182,10 +167,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let founder_mn = Mnemonic::from_str(&founder_mnemonic())?;
let founder_keypair = Keypair::from_phrase(&founder_mn, None)?;
println!(
"Founder: {}\n",
founder_keypair.public_key().to_account_id()
);
println!("Founder: {}\n", founder_keypair.public_key().to_account_id());
for (i, pool) in pool_configs.iter().enumerate().skip(skip) {
println!(
@@ -228,10 +210,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
},
};
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
tx_ok = wait_for_success(tx_progress, "TRANSFER").await?;
if tx_ok {
@@ -314,10 +293,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
},
};
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
create_ok = wait_for_success(tx_progress, "CREATE_POOL").await?;
if create_ok {
@@ -335,15 +311,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
tokio::time::sleep(std::time::Duration::from_secs(12)).await;
// Query LastPoolId to get the pool_id
let last_pool_query = pezkuwi_subxt::dynamic::storage::<(), Value>(
"NominationPools",
"LastPoolId",
);
let last_pool_query =
pezkuwi_subxt::dynamic::storage::<(), Value>("NominationPools", "LastPoolId");
let storage_client = api.storage().at_latest().await?;
let last_pool = storage_client
.entry(last_pool_query)?
.try_fetch(())
.await?;
let last_pool = storage_client.entry(last_pool_query)?.try_fetch(()).await?;
let pool_id = match last_pool {
Some(val) => {
@@ -369,10 +340,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let metadata_tx = pezkuwi_subxt::dynamic::tx(
"NominationPools",
"set_metadata",
vec![
Value::u128(pool_id as u128),
Value::from_bytes(&name_bytes),
],
vec![Value::u128(pool_id as u128), Value::from_bytes(&name_bytes)],
);
let tx_progress = match api
@@ -387,10 +355,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
},
};
println!(
" METADATA TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" METADATA TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let ok = wait_for_success(tx_progress, "SET_METADATA").await?;
if ok {
@@ -401,7 +366,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
}
println!(" Pool '{}' (ID: {}) created with {} HEZ\n", pool.name, pool_id, pool.stake_hez);
println!(
" Pool '{}' (ID: {}) created with {} HEZ\n",
pool.name, pool_id, pool.stake_hez
);
// Wait between pools
if i + 1 < pool_configs.len() {
+8 -29
View File
@@ -28,20 +28,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Sudo account: {}\n", keypair.public_key().to_account_id());
// Staking::ForceEra storage key (verified twox128)
let force_era_key = hex::decode(
"5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3",
)?;
let force_era_key =
hex::decode("5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3")?;
// NotForcing = enum variant 0 = 0x00
let not_forcing_value = vec![0x00u8];
println!(
"Storage key: 0x{}",
hex::encode(&force_era_key)
);
println!(
"New value: 0x{} (NotForcing)",
hex::encode(&not_forcing_value)
);
println!("Storage key: 0x{}", hex::encode(&force_era_key));
println!("New value: 0x{} (NotForcing)", hex::encode(&not_forcing_value));
// Build: system.setStorage(items: Vec<(Key, Value)>)
let set_storage_call = pezkuwi_subxt::dynamic::tx(
@@ -54,24 +47,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
);
// Wrap in sudo
let sudo_call = pezkuwi_subxt::dynamic::tx(
"Sudo",
"sudo",
vec![set_storage_call.into_value()],
);
let sudo_call = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![set_storage_call.into_value()]);
println!("\nSubmitting sudo(system.setStorage)...");
use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &keypair)
.await?;
let tx_progress = api.tx().sign_and_submit_then_watch_default(&sudo_call, &keypair).await?;
println!(
"TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!("TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
loop {
@@ -83,11 +66,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut sudid = false;
for event in events.iter() {
if let Ok(ev) = event {
println!(
" Event: {}::{}",
ev.pallet_name(),
ev.variant_name()
);
println!(" Event: {}::{}", ev.pallet_name(), ev.variant_name());
if ev.pallet_name() == "Sudo" && ev.variant_name() == "Sudid" {
sudid = true;
}
+11 -36
View File
@@ -20,7 +20,7 @@ const PEOPLE_CHAIN_PARA_ID: u32 = 1004;
// Tiki pallet index on People Chain
const TIKI_PALLET_INDEX: u8 = 61; // 0x3d
// force_mint_citizen_nft call index
// force_mint_citizen_nft call index
const FORCE_MINT_CALL_INDEX: u8 = 2; // 0x02
/// Encode Tiki::force_mint_citizen_nft(dest) for People Chain
@@ -61,23 +61,14 @@ fn build_xcm_sudo_transact(encoded_call: &[u8]) -> (Value, Value) {
Value::named_variant(
"UnpaidExecution",
[
(
"weight_limit",
Value::unnamed_variant("Unlimited", vec![]),
),
(
"check_origin",
Value::unnamed_variant("None", vec![]),
),
("weight_limit", Value::unnamed_variant("Unlimited", vec![])),
("check_origin", Value::unnamed_variant("None", vec![])),
],
),
Value::named_variant(
"Transact",
[
(
"origin_kind",
Value::unnamed_variant("Superuser", vec![]),
),
("origin_kind", Value::unnamed_variant("Superuser", vec![])),
(
"require_weight_at_most",
Value::named_composite([
@@ -127,10 +118,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
// Skip first N validators (already minted)
let skip: usize = std::env::var("SKIP")
.unwrap_or_else(|_| "0".to_string())
.parse()
.unwrap_or(0);
let skip: usize =
std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
println!("Relay RPC: {}", relay_url);
println!("People Chain Para ID: {}", PEOPLE_CHAIN_PARA_ID);
@@ -175,8 +164,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (dest, message) = build_xcm_sudo_transact(&encoded_call);
// Wrap in xcmPallet.send then sudo
let xcm_send =
pezkuwi_subxt::dynamic::tx("XcmPallet", "send", vec![dest, message]);
let xcm_send = pezkuwi_subxt::dynamic::tx("XcmPallet", "send", vec![dest, message]);
let sudo_call = pezkuwi_subxt::dynamic::tx(
"Sudo",
@@ -196,11 +184,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Retry up to 3 times on submit error
let mut tx_progress_opt = None;
for attempt in 0..3 {
match api
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await
{
match api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await {
Ok(p) => {
tx_progress_opt = Some(p);
break;
@@ -220,10 +204,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
},
};
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
let mut tx_ok = false;
@@ -237,9 +218,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut has_sent = false;
for event in events.iter() {
if let Ok(ev) = event {
if ev.pallet_name() == "Sudo"
&& ev.variant_name() == "Sudid"
{
if ev.pallet_name() == "Sudo" && ev.variant_name() == "Sudid" {
has_sudid = true;
}
if ev.pallet_name() == "XcmPallet"
@@ -256,11 +235,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" WARNING: Missing expected events");
for event in events.iter() {
if let Ok(ev) = event {
println!(
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
println!(" {}::{}", ev.pallet_name(), ev.variant_name());
}
}
}
+75 -62
View File
@@ -6,66 +6,79 @@ use std::str::FromStr;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let message = std::env::var("MESSAGE").expect("MESSAGE env var required");
println!("RPC: {}", url);
println!("Message: {}", message);
println!("Message bytes: {}", message.len());
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&url).await?;
println!("Connected!");
let mnemonic_str = std::env::var("SUDO_MNEMONIC").expect("SUDO_MNEMONIC required");
let mnemonic = Mnemonic::from_str(&mnemonic_str)?;
let keypair = Keypair::from_phrase(&mnemonic, None)?;
println!("Account: {}\n", keypair.public_key().to_account_id());
let remark_tx = pezkuwi_subxt::dynamic::tx(
"System",
"remark_with_event",
vec![Value::from_bytes(message.as_bytes())],
);
println!("Submitting remarkWithEvent...");
use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api.tx()
.sign_and_submit_then_watch_default(&remark_tx, &keypair)
.await?;
println!("TX hash: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
loop {
let status = progress.next().await;
match status {
Some(Ok(TxStatus::Validated)) => println!(" Validated"),
Some(Ok(TxStatus::Broadcasted)) => println!(" Broadcasted"),
Some(Ok(TxStatus::InBestBlock(details))) => {
println!(" InBestBlock {:?}", details.block_hash());
match details.wait_for_success().await {
Ok(events) => {
println!(" SUCCESS!");
for event in events.iter() {
if let Ok(ev) = event {
println!(" {}::{}", ev.pallet_name(), ev.variant_name());
}
}
},
Err(e) => println!(" Error: {}", e),
}
break;
},
Some(Ok(TxStatus::Error { message })) => { println!(" ERROR: {}", message); break; },
Some(Ok(TxStatus::Invalid { message })) => { println!(" INVALID: {}", message); break; },
Some(Ok(TxStatus::Dropped { message })) => { println!(" DROPPED: {}", message); break; },
Some(Err(e)) => { println!(" Error: {}", e); break; },
None => { println!(" Stream ended"); break; },
_ => {},
}
}
println!("\nDone.");
Ok(())
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let message = std::env::var("MESSAGE").expect("MESSAGE env var required");
println!("RPC: {}", url);
println!("Message: {}", message);
println!("Message bytes: {}", message.len());
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&url).await?;
println!("Connected!");
let mnemonic_str = std::env::var("SUDO_MNEMONIC").expect("SUDO_MNEMONIC required");
let mnemonic = Mnemonic::from_str(&mnemonic_str)?;
let keypair = Keypair::from_phrase(&mnemonic, None)?;
println!("Account: {}\n", keypair.public_key().to_account_id());
let remark_tx = pezkuwi_subxt::dynamic::tx(
"System",
"remark_with_event",
vec![Value::from_bytes(message.as_bytes())],
);
println!("Submitting remarkWithEvent...");
use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api.tx().sign_and_submit_then_watch_default(&remark_tx, &keypair).await?;
println!("TX hash: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
loop {
let status = progress.next().await;
match status {
Some(Ok(TxStatus::Validated)) => println!(" Validated"),
Some(Ok(TxStatus::Broadcasted)) => println!(" Broadcasted"),
Some(Ok(TxStatus::InBestBlock(details))) => {
println!(" InBestBlock {:?}", details.block_hash());
match details.wait_for_success().await {
Ok(events) => {
println!(" SUCCESS!");
for event in events.iter() {
if let Ok(ev) = event {
println!(" {}::{}", ev.pallet_name(), ev.variant_name());
}
}
},
Err(e) => println!(" Error: {}", e),
}
break;
},
Some(Ok(TxStatus::Error { message })) => {
println!(" ERROR: {}", message);
break;
},
Some(Ok(TxStatus::Invalid { message })) => {
println!(" INVALID: {}", message);
break;
},
Some(Ok(TxStatus::Dropped { message })) => {
println!(" DROPPED: {}", message);
break;
},
Some(Err(e)) => {
println!(" Error: {}", e);
break;
},
None => {
println!(" Stream ended");
break;
},
_ => {},
}
}
println!("\nDone.");
Ok(())
}
+112 -48
View File
@@ -33,27 +33,111 @@ struct ValidatorInfo {
fn validators() -> Vec<ValidatorInfo> {
vec![
ValidatorInfo { name: "Çiyager (Cihat Türkan)", ss58: "5GipBJs2uNWTCazyZQ2vG3DEqLz4tXNmNZtBAT1Mtm1orZ5i", staked_hez: 499_100 },
ValidatorInfo { name: "Mehmet Tunç", ss58: "5HWFZbhkZuTUySXu6ZXYKrTHBnWXHvWRKLozE22zhnwXGGxk", staked_hez: 499_100 },
ValidatorInfo { name: "Nagihan Akarsel", ss58: "5CrB5BWJfLNWEZAsAXDKXdJUGzFMXKvYnwRX4DVMcgBwxSdx", staked_hez: 499_100 },
ValidatorInfo { name: "Sait Çürükkaya (Doktor Süleyman)", ss58: "5ELgySrX5ZyK7EWXjj6bAedyTCcTNWDANbiiipsT5gnpoCEp", staked_hez: 499_100 },
ValidatorInfo { name: "Evdile Koçer", ss58: "5GCZQNjRdHofEHPvVq4ePrfDYcjRzQ1HQ2awHMX6AawpRYuM", staked_hez: 499_100 },
ValidatorInfo { name: "Mam Zeki", ss58: "5H8jTzi4Gm4rbFtXw6h5enhLhgsuhNAqR5K2itmPiz83ymWy", staked_hez: 499_100 },
ValidatorInfo { name: "Kakaî Falah", ss58: "5Fs3P5tHuL9cvwPQojsheViRRAjFkMMFa32jAkDSwW9mbTfU", staked_hez: 499_100 },
ValidatorInfo { name: "Feryad Fazil Ömer", ss58: "5DXgq7uDXog6zcubT3wgtaYosoibjudz4w5ScPW2phLuAy3V", staked_hez: 499_100 },
ValidatorInfo { name: "Mevlud Afand", ss58: "5FyFwbGLgPXun3azh6Gx83wCuUt5FTavb2WAVDYrjziVB9rN", staked_hez: 499_100 },
ValidatorInfo { name: "Şêrko Fatih Şivandî", ss58: "5HEcuuypLDeJaSj6ZgH57aXhuviyeLNdw9QrCDJ8u6gsnjnL", staked_hez: 499_100 },
ValidatorInfo { name: "Ramin Hüseyin Penahi", ss58: "5EpmpTXbMXpz6ixy3WhutdzcexzPbvybNKv4eiiN1kvTnQH5", staked_hez: 499_100 },
ValidatorInfo { name: "Zanyar Moradi", ss58: "5DFsm3BBEgHmSEZkvwGKB7c7tiH2avhfuQE1SEjfMDGuczsW", staked_hez: 499_100 },
ValidatorInfo { name: "Heidar Ghorbani", ss58: "5HePVUXjGSM2hVZ1YMz2V3KoX6EdQNEmmzUnUvpfGV95ofUR", staked_hez: 499_100 },
ValidatorInfo { name: "Farhad Salimi", ss58: "5GP4nAcwtETTg1oAHQNvevmmhG8GEstGQeCirKEhaDTwpFgx", staked_hez: 499_100 },
ValidatorInfo { name: "Vafa Azarbar", ss58: "5FYoCM3oeEGeoFY94EgXBhmABkRCabvPp72ur5bJNG3cK619", staked_hez: 499_100 },
ValidatorInfo { name: "Dr. Aziz Mihemed", ss58: "5GspwkKF6aYzFkmAyBBQg7coSCSgDCore79fbW8uxJNAH347", staked_hez: 499_100 },
ValidatorInfo { name: "Arîn Mîrkan", ss58: "5GmuX11pN2fC4Fyq1V7MuiYt3aevZcVQs3HZWKyzmap9bKfe", staked_hez: 499_100 },
ValidatorInfo { name: "Ebu Leyla", ss58: "5FQptVCtM1qsxkLbQkATkw4Kio4M9LxWvM6TwgEo3QjmTXF3", staked_hez: 499_100 },
ValidatorInfo { name: "Rêvan Kobanê", ss58: "5E7VD2qmso1yRfyq3t9u2qhauAgtmjZTybVsCARF5Zz9bXy6", staked_hez: 499_100 },
ValidatorInfo { name: "Amanj Babani", ss58: "5Ccz5W7Q21g4UPCytzHxD3VSMLJ1BbbWSkJKFwsNtYRk3HkX", staked_hez: 499_100 },
ValidatorInfo { name: "Xosrow Gulan", ss58: "5D7WPmK1SAJyYDdCtgqEzGJpWXQe3Lj9FqWL8z9waLTkUNv3", staked_hez: 499_100 },
ValidatorInfo {
name: "Çiyager (Cihat Türkan)",
ss58: "5GipBJs2uNWTCazyZQ2vG3DEqLz4tXNmNZtBAT1Mtm1orZ5i",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Mehmet Tunç",
ss58: "5HWFZbhkZuTUySXu6ZXYKrTHBnWXHvWRKLozE22zhnwXGGxk",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Nagihan Akarsel",
ss58: "5CrB5BWJfLNWEZAsAXDKXdJUGzFMXKvYnwRX4DVMcgBwxSdx",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Sait Çürükkaya (Doktor Süleyman)",
ss58: "5ELgySrX5ZyK7EWXjj6bAedyTCcTNWDANbiiipsT5gnpoCEp",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Evdile Koçer",
ss58: "5GCZQNjRdHofEHPvVq4ePrfDYcjRzQ1HQ2awHMX6AawpRYuM",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Mam Zeki",
ss58: "5H8jTzi4Gm4rbFtXw6h5enhLhgsuhNAqR5K2itmPiz83ymWy",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Kakaî Falah",
ss58: "5Fs3P5tHuL9cvwPQojsheViRRAjFkMMFa32jAkDSwW9mbTfU",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Feryad Fazil Ömer",
ss58: "5DXgq7uDXog6zcubT3wgtaYosoibjudz4w5ScPW2phLuAy3V",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Mevlud Afand",
ss58: "5FyFwbGLgPXun3azh6Gx83wCuUt5FTavb2WAVDYrjziVB9rN",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Şêrko Fatih Şivandî",
ss58: "5HEcuuypLDeJaSj6ZgH57aXhuviyeLNdw9QrCDJ8u6gsnjnL",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Ramin Hüseyin Penahi",
ss58: "5EpmpTXbMXpz6ixy3WhutdzcexzPbvybNKv4eiiN1kvTnQH5",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Zanyar Moradi",
ss58: "5DFsm3BBEgHmSEZkvwGKB7c7tiH2avhfuQE1SEjfMDGuczsW",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Heidar Ghorbani",
ss58: "5HePVUXjGSM2hVZ1YMz2V3KoX6EdQNEmmzUnUvpfGV95ofUR",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Farhad Salimi",
ss58: "5GP4nAcwtETTg1oAHQNvevmmhG8GEstGQeCirKEhaDTwpFgx",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Vafa Azarbar",
ss58: "5FYoCM3oeEGeoFY94EgXBhmABkRCabvPp72ur5bJNG3cK619",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Dr. Aziz Mihemed",
ss58: "5GspwkKF6aYzFkmAyBBQg7coSCSgDCore79fbW8uxJNAH347",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Arîn Mîrkan",
ss58: "5GmuX11pN2fC4Fyq1V7MuiYt3aevZcVQs3HZWKyzmap9bKfe",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Ebu Leyla",
ss58: "5FQptVCtM1qsxkLbQkATkw4Kio4M9LxWvM6TwgEo3QjmTXF3",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Rêvan Kobanê",
ss58: "5E7VD2qmso1yRfyq3t9u2qhauAgtmjZTybVsCARF5Zz9bXy6",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Amanj Babani",
ss58: "5Ccz5W7Q21g4UPCytzHxD3VSMLJ1BbbWSkJKFwsNtYRk3HkX",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Xosrow Gulan",
ss58: "5D7WPmK1SAJyYDdCtgqEzGJpWXQe3Lj9FqWL8z9waLTkUNv3",
staked_hez: 499_100,
},
]
}
@@ -143,10 +227,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let relay_url =
std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let skip: usize = std::env::var("SKIP")
.unwrap_or_else(|_| "0".to_string())
.parse()
.unwrap_or(0);
let skip: usize =
std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
let vals = validators();
println!("Relay RPC: {}", relay_url);
@@ -155,10 +237,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connect to relay chain
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&relay_url).await?;
println!(
"Connected! specVersion: {}\n",
api.runtime_version().spec_version
);
println!("Connected! specVersion: {}\n", api.runtime_version().spec_version);
// Load sudo keypair
let mnemonic_str =
@@ -196,11 +275,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
0,
0,
);
println!(
" Call: {} bytes (0x{}...)",
call.len(),
hex::encode(&call[..6])
);
println!(" Call: {} bytes (0x{}...)", call.len(), hex::encode(&call[..6]));
// Build XCM message
let (dest, message) = build_xcm_values(&call);
@@ -224,11 +299,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
use pezkuwi_subxt::tx::TxStatus;
let mut tx_progress_opt = None;
for attempt in 0..3 {
match api
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await
{
match api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await {
Ok(p) => {
tx_progress_opt = Some(p);
break;
@@ -249,10 +320,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
},
};
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
let mut tx_ok = false;
@@ -283,11 +351,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" WARNING: Events:");
for event in events.iter() {
if let Ok(ev) = event {
println!(
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
println!(" {}::{}", ev.pallet_name(), ev.variant_name());
}
}
}
+14 -36
View File
@@ -48,12 +48,9 @@ fn load_wallets() -> Vec<WalletInfo> {
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== SET POOL METADATA ===\n");
let start_id: u32 = std::env::var("START_ID")
.unwrap_or_else(|_| "1".to_string())
.parse()?;
let start_id: u32 = std::env::var("START_ID").unwrap_or_else(|_| "1".to_string()).parse()?;
let rpc =
std::env::var("ASSET_HUB_RPC").unwrap_or_else(|_| DEFAULT_ASSET_HUB_RPC.to_string());
let rpc = std::env::var("ASSET_HUB_RPC").unwrap_or_else(|_| DEFAULT_ASSET_HUB_RPC.to_string());
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&rpc).await?;
println!("Connected to Asset Hub!\n");
@@ -66,23 +63,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
if let Some(val) = last_pool {
let decoded = val.decode()?;
println!("LastPoolId raw value: {:?}", decoded);
println!(
"LastPoolId as_u128: {:?}",
decoded.as_u128()
);
println!("LastPoolId as_u128: {:?}", decoded.as_u128());
}
let wallets = load_wallets();
for (i, wallet) in wallets.iter().enumerate() {
let pool_id = start_id + i as u32;
println!(
"--- [{}/{}] Pool {} -> '{}' ---",
i + 1,
wallets.len(),
pool_id,
wallet.name
);
println!("--- [{}/{}] Pool {} -> '{}' ---", i + 1, wallets.len(), pool_id, wallet.name);
let mnemonic = Mnemonic::from_str(&wallet.mnemonic)?;
let keypair = Keypair::from_phrase(&mnemonic, None)?;
@@ -102,22 +90,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
tokio::time::sleep(std::time::Duration::from_secs(18)).await;
}
let tx_progress = match api
.tx()
.sign_and_submit_then_watch_default(&metadata_tx, &keypair)
.await
{
Ok(p) => p,
Err(e) => {
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
continue;
},
};
let tx_progress =
match api.tx().sign_and_submit_then_watch_default(&metadata_tx, &keypair).await {
Ok(p) => p,
Err(e) => {
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
continue;
},
};
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
use pezkuwi_subxt::tx::TxStatus;
let mut progress = tx_progress;
@@ -130,11 +112,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" SUCCESS!");
for event in events.iter() {
if let Ok(ev) = event {
println!(
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
println!(" {}::{}", ev.pallet_name(), ev.variant_name());
}
}
ok = true;
@@ -0,0 +1,130 @@
//! Test start_score_tracking on People Chain
//!
//! 1. Transfer small amount from founder to validator on People Chain
//! 2. Call start_score_tracking() from validator account
//! 3. Verify StakingStartBlock was set
//!
//! FOUNDER_MNEMONIC="..." VALIDATOR_MNEMONIC="..." cargo run --release -p pezkuwi-subxt --example test_start_tracking
#![allow(missing_docs)]
use pezkuwi_subxt::dynamic::Value;
use pezkuwi_subxt::utils::AccountId32;
use pezkuwi_subxt::{OnlineClient, PezkuwiConfig};
use pezkuwi_subxt_signer::bip39::Mnemonic;
use pezkuwi_subxt_signer::sr25519::Keypair;
use std::str::FromStr;
const PEOPLE_RPC: &str = "ws://217.77.6.126:41944";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== TEST: start_score_tracking on People Chain ===\n");
let founder_mnemonic_str =
std::env::var("FOUNDER_MNEMONIC").expect("FOUNDER_MNEMONIC env var required");
let validator_mnemonic_str =
std::env::var("VALIDATOR_MNEMONIC").expect("VALIDATOR_MNEMONIC env var required");
let founder_mnemonic = Mnemonic::from_str(&founder_mnemonic_str)?;
let founder_keypair = Keypair::from_phrase(&founder_mnemonic, None)?;
let founder_account = AccountId32(founder_keypair.public_key().0);
let validator_mnemonic = Mnemonic::from_str(&validator_mnemonic_str)?;
let validator_keypair = Keypair::from_phrase(&validator_mnemonic, None)?;
let validator_account = AccountId32(validator_keypair.public_key().0);
println!("Founder: {}", founder_account);
println!("Validator: {}", validator_account);
println!("\nConnecting to People Chain: {}", PEOPLE_RPC);
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(PEOPLE_RPC).await?;
println!("Connected (spec_version: {})\n", api.runtime_version().spec_version);
// Step 1: Transfer 10 HEZ from founder to validator for tx fees
let transfer_amount: u128 = 10_000_000_000_000; // 10 HEZ
println!("--- Step 1: Transfer 10 HEZ to validator for fees ---");
let transfer = pezkuwi_subxt::dynamic::tx(
"Balances",
"transfer_keep_alive",
vec![
Value::unnamed_variant("Id", [Value::from_bytes(&validator_account.0)]),
Value::u128(transfer_amount),
],
);
let progress = api.tx().sign_and_submit_then_watch_default(&transfer, &founder_keypair).await?;
println!("TX: 0x{}", hex::encode(progress.extrinsic_hash().as_ref()));
let events = progress.wait_for_finalized_success().await?;
println!("Transfer finalized!");
for ev in events.iter() {
if let Ok(ev) = ev {
if ev.pallet_name() == "Balances" {
println!(" {}::{}", ev.pallet_name(), ev.variant_name());
}
}
}
// Step 2: Call start_score_tracking from validator
println!("\n--- Step 2: start_score_tracking() ---");
let start_tracking =
pezkuwi_subxt::dynamic::tx("StakingScore", "start_score_tracking", Vec::<Value>::new());
let progress = api
.tx()
.sign_and_submit_then_watch_default(&start_tracking, &validator_keypair)
.await?;
println!("TX: 0x{}", hex::encode(progress.extrinsic_hash().as_ref()));
match progress.wait_for_finalized_success().await {
Ok(events) => {
println!("start_score_tracking SUCCESS!");
for ev in events.iter() {
if let Ok(ev) = ev {
let p = ev.pallet_name();
if p == "StakingScore" || p == "Trust" || p == "System" {
println!(" {}::{}", p, ev.variant_name());
}
}
}
},
Err(e) => {
println!("start_score_tracking FAILED: {:?}", e);
},
}
// Step 3: Verify StakingStartBlock was set
println!("\n--- Step 3: Verify StakingStartBlock ---");
let query = pezkuwi_subxt::dynamic::storage::<(AccountId32,), Value>(
"StakingScore",
"StakingStartBlock",
);
let storage = api.storage().at_latest().await?;
match storage.entry(query)?.try_fetch((validator_account.clone(),)).await? {
Some(val) => {
let decoded = val.decode()?;
println!("StakingStartBlock for validator: {:?}", decoded);
},
None => {
println!("StakingStartBlock: NOT SET (ERROR!)");
},
}
// Step 4: Check TrustScore
println!("\n--- Step 4: Check TrustScore ---");
let query = pezkuwi_subxt::dynamic::storage::<(AccountId32,), Value>("Trust", "TrustScores");
match storage.entry(query)?.try_fetch((validator_account.clone(),)).await? {
Some(val) => {
let decoded = val.decode()?;
println!("TrustScore for validator: {:?}", decoded);
},
None => {
println!("TrustScore: NOT SET (may need on_initialize cycle)");
},
}
println!("\n=== TEST COMPLETE ===");
Ok(())
}
+16 -31
View File
@@ -44,14 +44,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
];
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let amount_hez: u128 = std::env::var("AMOUNT_HEZ")
.unwrap_or_else(|_| "500000".to_string())
.parse()?;
let amount_hez: u128 =
std::env::var("AMOUNT_HEZ").unwrap_or_else(|_| "500000".to_string()).parse()?;
let amount_planck = amount_hez * PLANCKS_PER_HEZ;
let skip: usize = std::env::var("SKIP")
.unwrap_or_else(|_| "0".to_string())
.parse()
.unwrap_or(0);
let skip: usize =
std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
println!("RPC: {}", url);
println!("Amount per validator: {} HEZ ({} TYR)", amount_hez, amount_planck);
@@ -100,23 +97,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut tx_ok = false;
for attempt in 0..3 {
let tx_progress = match api
.tx()
.sign_and_submit_then_watch_default(&transfer_tx, &keypair)
.await
{
Ok(p) => p,
Err(e) => {
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
tokio::time::sleep(std::time::Duration::from_secs(12)).await;
continue;
},
};
let tx_progress =
match api.tx().sign_and_submit_then_watch_default(&transfer_tx, &keypair).await {
Ok(p) => p,
Err(e) => {
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
tokio::time::sleep(std::time::Duration::from_secs(12)).await;
continue;
},
};
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
loop {
@@ -130,10 +121,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
if ev.pallet_name() == "Balances"
&& ev.variant_name() == "Transfer"
{
println!(
" SUCCESS: {} HEZ transferred",
amount_hez
);
println!(" SUCCESS: {} HEZ transferred", amount_hez);
tx_ok = true;
}
}
@@ -200,10 +188,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("\n=== RESULTS ===");
println!("Success: {}/{}", success_count, validators.len() - skip);
println!("Failed: {}/{}", fail_count, validators.len() - skip);
println!(
"Total transferred: {} HEZ",
amount_hez * success_count as u128
);
println!("Total transferred: {} HEZ", amount_hez * success_count as u128);
Ok(())
}
+90 -43
View File
@@ -44,27 +44,90 @@ struct ValidatorInfo {
fn validators() -> Vec<ValidatorInfo> {
vec![
ValidatorInfo { name: "Çiyager (Cihat Türkan)", ss58: "5GipBJs2uNWTCazyZQ2vG3DEqLz4tXNmNZtBAT1Mtm1orZ5i" },
ValidatorInfo { name: "Mehmet Tunç", ss58: "5HWFZbhkZuTUySXu6ZXYKrTHBnWXHvWRKLozE22zhnwXGGxk" },
ValidatorInfo { name: "Nagihan Akarsel", ss58: "5CrB5BWJfLNWEZAsAXDKXdJUGzFMXKvYnwRX4DVMcgBwxSdx" },
ValidatorInfo { name: "Sait Çürükkaya (Doktor Süleyman)", ss58: "5ELgySrX5ZyK7EWXjj6bAedyTCcTNWDANbiiipsT5gnpoCEp" },
ValidatorInfo { name: "Evdile Koçer", ss58: "5GCZQNjRdHofEHPvVq4ePrfDYcjRzQ1HQ2awHMX6AawpRYuM" },
ValidatorInfo { name: "Mam Zeki", ss58: "5H8jTzi4Gm4rbFtXw6h5enhLhgsuhNAqR5K2itmPiz83ymWy" },
ValidatorInfo { name: "Kakaî Falah", ss58: "5Fs3P5tHuL9cvwPQojsheViRRAjFkMMFa32jAkDSwW9mbTfU" },
ValidatorInfo { name: "Feryad Fazil Ömer", ss58: "5DXgq7uDXog6zcubT3wgtaYosoibjudz4w5ScPW2phLuAy3V" },
ValidatorInfo { name: "Mevlud Afand", ss58: "5FyFwbGLgPXun3azh6Gx83wCuUt5FTavb2WAVDYrjziVB9rN" },
ValidatorInfo { name: "Şêrko Fatih Şivandî", ss58: "5HEcuuypLDeJaSj6ZgH57aXhuviyeLNdw9QrCDJ8u6gsnjnL" },
ValidatorInfo { name: "Ramin Hüseyin Penahi", ss58: "5EpmpTXbMXpz6ixy3WhutdzcexzPbvybNKv4eiiN1kvTnQH5" },
ValidatorInfo { name: "Zanyar Moradi", ss58: "5DFsm3BBEgHmSEZkvwGKB7c7tiH2avhfuQE1SEjfMDGuczsW" },
ValidatorInfo { name: "Heidar Ghorbani", ss58: "5HePVUXjGSM2hVZ1YMz2V3KoX6EdQNEmmzUnUvpfGV95ofUR" },
ValidatorInfo { name: "Farhad Salimi", ss58: "5GP4nAcwtETTg1oAHQNvevmmhG8GEstGQeCirKEhaDTwpFgx" },
ValidatorInfo { name: "Vafa Azarbar", ss58: "5FYoCM3oeEGeoFY94EgXBhmABkRCabvPp72ur5bJNG3cK619" },
ValidatorInfo { name: "Dr. Aziz Mihemed", ss58: "5GspwkKF6aYzFkmAyBBQg7coSCSgDCore79fbW8uxJNAH347" },
ValidatorInfo { name: "Arîn Mîrkan", ss58: "5GmuX11pN2fC4Fyq1V7MuiYt3aevZcVQs3HZWKyzmap9bKfe" },
ValidatorInfo { name: "Ebu Leyla", ss58: "5FQptVCtM1qsxkLbQkATkw4Kio4M9LxWvM6TwgEo3QjmTXF3" },
ValidatorInfo { name: "Rêvan Kobanê", ss58: "5E7VD2qmso1yRfyq3t9u2qhauAgtmjZTybVsCARF5Zz9bXy6" },
ValidatorInfo { name: "Amanj Babani", ss58: "5Ccz5W7Q21g4UPCytzHxD3VSMLJ1BbbWSkJKFwsNtYRk3HkX" },
ValidatorInfo { name: "Xosrow Gulan", ss58: "5D7WPmK1SAJyYDdCtgqEzGJpWXQe3Lj9FqWL8z9waLTkUNv3" },
ValidatorInfo {
name: "Çiyager (Cihat Türkan)",
ss58: "5GipBJs2uNWTCazyZQ2vG3DEqLz4tXNmNZtBAT1Mtm1orZ5i",
},
ValidatorInfo {
name: "Mehmet Tunç",
ss58: "5HWFZbhkZuTUySXu6ZXYKrTHBnWXHvWRKLozE22zhnwXGGxk",
},
ValidatorInfo {
name: "Nagihan Akarsel",
ss58: "5CrB5BWJfLNWEZAsAXDKXdJUGzFMXKvYnwRX4DVMcgBwxSdx",
},
ValidatorInfo {
name: "Sait Çürükkaya (Doktor Süleyman)",
ss58: "5ELgySrX5ZyK7EWXjj6bAedyTCcTNWDANbiiipsT5gnpoCEp",
},
ValidatorInfo {
name: "Evdile Koçer",
ss58: "5GCZQNjRdHofEHPvVq4ePrfDYcjRzQ1HQ2awHMX6AawpRYuM",
},
ValidatorInfo {
name: "Mam Zeki",
ss58: "5H8jTzi4Gm4rbFtXw6h5enhLhgsuhNAqR5K2itmPiz83ymWy",
},
ValidatorInfo {
name: "Kakaî Falah",
ss58: "5Fs3P5tHuL9cvwPQojsheViRRAjFkMMFa32jAkDSwW9mbTfU",
},
ValidatorInfo {
name: "Feryad Fazil Ömer",
ss58: "5DXgq7uDXog6zcubT3wgtaYosoibjudz4w5ScPW2phLuAy3V",
},
ValidatorInfo {
name: "Mevlud Afand",
ss58: "5FyFwbGLgPXun3azh6Gx83wCuUt5FTavb2WAVDYrjziVB9rN",
},
ValidatorInfo {
name: "Şêrko Fatih Şivandî",
ss58: "5HEcuuypLDeJaSj6ZgH57aXhuviyeLNdw9QrCDJ8u6gsnjnL",
},
ValidatorInfo {
name: "Ramin Hüseyin Penahi",
ss58: "5EpmpTXbMXpz6ixy3WhutdzcexzPbvybNKv4eiiN1kvTnQH5",
},
ValidatorInfo {
name: "Zanyar Moradi",
ss58: "5DFsm3BBEgHmSEZkvwGKB7c7tiH2avhfuQE1SEjfMDGuczsW",
},
ValidatorInfo {
name: "Heidar Ghorbani",
ss58: "5HePVUXjGSM2hVZ1YMz2V3KoX6EdQNEmmzUnUvpfGV95ofUR",
},
ValidatorInfo {
name: "Farhad Salimi",
ss58: "5GP4nAcwtETTg1oAHQNvevmmhG8GEstGQeCirKEhaDTwpFgx",
},
ValidatorInfo {
name: "Vafa Azarbar",
ss58: "5FYoCM3oeEGeoFY94EgXBhmABkRCabvPp72ur5bJNG3cK619",
},
ValidatorInfo {
name: "Dr. Aziz Mihemed",
ss58: "5GspwkKF6aYzFkmAyBBQg7coSCSgDCore79fbW8uxJNAH347",
},
ValidatorInfo {
name: "Arîn Mîrkan",
ss58: "5GmuX11pN2fC4Fyq1V7MuiYt3aevZcVQs3HZWKyzmap9bKfe",
},
ValidatorInfo {
name: "Ebu Leyla",
ss58: "5FQptVCtM1qsxkLbQkATkw4Kio4M9LxWvM6TwgEo3QjmTXF3",
},
ValidatorInfo {
name: "Rêvan Kobanê",
ss58: "5E7VD2qmso1yRfyq3t9u2qhauAgtmjZTybVsCARF5Zz9bXy6",
},
ValidatorInfo {
name: "Amanj Babani",
ss58: "5Ccz5W7Q21g4UPCytzHxD3VSMLJ1BbbWSkJKFwsNtYRk3HkX",
},
ValidatorInfo {
name: "Xosrow Gulan",
ss58: "5D7WPmK1SAJyYDdCtgqEzGJpWXQe3Lj9FqWL8z9waLTkUNv3",
},
]
}
@@ -207,10 +270,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let relay_url =
std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let skip: usize = std::env::var("SKIP")
.unwrap_or_else(|_| "0".to_string())
.parse()
.unwrap_or(0);
let skip: usize =
std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
let vals = validators();
println!("Relay RPC: {}", relay_url);
@@ -223,10 +284,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connect to relay chain
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&relay_url).await?;
println!(
"Connected! specVersion: {}\n",
api.runtime_version().spec_version
);
println!("Connected! specVersion: {}\n", api.runtime_version().spec_version);
// Load sudo keypair
let mnemonic_str =
@@ -281,11 +339,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
use pezkuwi_subxt::tx::TxStatus;
let mut tx_progress_opt = None;
for attempt in 0..3 {
match api
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await
{
match api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await {
Ok(p) => {
tx_progress_opt = Some(p);
break;
@@ -306,10 +360,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
},
};
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
let mut tx_ok = false;
@@ -340,11 +391,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" WARNING: Events:");
for event in events.iter() {
if let Ok(ev) = event {
println!(
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
println!(" {}::{}", ev.pallet_name(), ev.variant_name());
}
}
}
+6 -22
View File
@@ -74,11 +74,7 @@ async fn submit_and_watch(
tokio::time::sleep(std::time::Duration::from_secs(18)).await;
}
let tx_progress = match api
.tx()
.sign_and_submit_then_watch_default(&tx, signer)
.await
{
let tx_progress = match api.tx().sign_and_submit_then_watch_default(&tx, signer).await {
Ok(p) => p,
Err(e) => {
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
@@ -86,10 +82,7 @@ async fn submit_and_watch(
},
};
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
loop {
@@ -101,11 +94,7 @@ async fn submit_and_watch(
println!(" {} SUCCESS!", label);
for event in events.iter() {
if let Ok(ev) = event {
println!(
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
println!(" {}::{}", ev.pallet_name(), ev.variant_name());
}
}
return Ok(true);
@@ -148,10 +137,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let ws = load_wallets();
let args: Vec<String> = std::env::args().collect();
let phase = args.get(1).map(|s| s.as_str()).unwrap_or("all");
let skip: usize = std::env::var("SKIP")
.unwrap_or_else(|_| "0".to_string())
.parse()
.unwrap_or(0);
let skip: usize =
std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
let rpc = std::env::var("PEOPLE_RPC").unwrap_or_else(|_| DEFAULT_PEOPLE_RPC.to_string());
println!("=== WELATI CITIZENSHIP WORKFLOW ===");
@@ -222,10 +209,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let tx = pezkuwi_subxt::dynamic::tx(
"IdentityKyc",
"apply_for_citizenship",
vec![
Value::from_bytes(&identity_hash),
Value::unnamed_variant("None", vec![]),
],
vec![Value::from_bytes(&identity_hash), Value::unnamed_variant("None", vec![])],
);
let ok = submit_and_watch(&api, tx, &keypair, "APPLY").await?;
+16 -59
View File
@@ -45,9 +45,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== ZAGROS: VALIDATOR DEREGISTRATION ===\n");
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string());
let keep: usize = std::env::var("KEEP")
.unwrap_or_else(|_| "2".to_string())
.parse()?;
let keep: usize = std::env::var("KEEP").unwrap_or_else(|_| "2".to_string()).parse()?;
let execute = std::env::var("EXECUTE").unwrap_or_default() == "1";
println!("RPC: {}", url);
@@ -61,15 +59,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// QueuedKeys = Vec<(ValidatorId, Keys)>
// Storage key: twox128("Session") + twox128("QueuedKeys")
let queued_keys_key =
hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903")
.unwrap();
hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903").unwrap();
let raw_data = api
.storage()
.at_latest()
.await?
.fetch_raw(queued_keys_key)
.await?;
let raw_data = api.storage().at_latest().await?.fetch_raw(queued_keys_key).await?;
if raw_data.is_empty() {
println!("ERROR: QueuedKeys storage is empty!");
@@ -95,33 +87,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// But we need to verify this. Let's compute expected total size:
let expected_entry_size = 32 + (32 * 6 + 33); // 257
let expected_total = 1 + (count * expected_entry_size); // 1 byte compact + entries
println!(
"Expected data size: {} bytes, actual: {} bytes",
expected_total,
raw_data.len()
);
println!("Expected data size: {} bytes, actual: {} bytes", expected_total, raw_data.len());
if raw_data.len() < offset + count * expected_entry_size {
// Try without beefy (older runtime might not have it)
let entry_no_beefy = 32 + (32 * 6); // 224
let expected_no_beefy = 1 + (count * entry_no_beefy);
println!(
"Without beefy: expected {} bytes",
expected_no_beefy
);
println!("Without beefy: expected {} bytes", expected_no_beefy);
if raw_data.len() >= offset + count * entry_no_beefy {
println!("Using SessionKeys without Beefy (6 keys x 32 bytes)");
extract_and_process(
&raw_data,
offset,
count,
entry_no_beefy,
keep,
execute,
&api,
)
.await?;
extract_and_process(&raw_data, offset, count, entry_no_beefy, keep, execute, &api)
.await?;
} else {
// Auto-detect entry size
let remaining = raw_data.len() - offset;
@@ -130,21 +107,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
"Auto-detected entry size: {} bytes (remaining={}, count={})",
entry_size, remaining, count
);
extract_and_process(&raw_data, offset, count, entry_size, keep, execute, &api)
.await?;
extract_and_process(&raw_data, offset, count, entry_size, keep, execute, &api).await?;
}
} else {
println!("Using SessionKeys with Beefy (6 keys x 32 + 33 beefy)");
extract_and_process(
&raw_data,
offset,
count,
expected_entry_size,
keep,
execute,
&api,
)
.await?;
extract_and_process(&raw_data, offset, count, expected_entry_size, keep, execute, &api)
.await?;
}
Ok(())
@@ -202,22 +170,16 @@ async fn extract_and_process(
vec![Value::unnamed_composite(validators_value)],
);
let sudo_call =
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![deregister_call.into_value()]);
let sudo_call = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![deregister_call.into_value()]);
println!("Submitting sudo(validatorManager.deregister_validators)...\n");
use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await?;
let tx_progress =
api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await?;
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
let mut success = false;
@@ -237,9 +199,7 @@ async fn extract_and_process(
if ev.pallet_name() == "ValidatorManager"
&& ev.variant_name() == "ValidatorsDeregistered"
{
println!(
" >>> ValidatorsDeregistered event confirmed!"
);
println!(" >>> ValidatorsDeregistered event confirmed!");
}
}
}
@@ -273,10 +233,7 @@ async fn extract_and_process(
}
if success {
println!(
"\nSUCCESS! {} validators queued for deregistration.",
to_remove.len()
);
println!("\nSUCCESS! {} validators queued for deregistration.", to_remove.len());
println!("The change will take effect at current_session + 2.");
println!("Monitor GRANDPA authorities to confirm.");
} else {
+17 -40
View File
@@ -26,11 +26,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Storage keys
let queued_keys_key =
hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903")
.unwrap();
hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903").unwrap();
let validators_to_retire_key =
hex::decode("084e7f70a295a190e2e33fd3f8cdfcc2b664fa73499821e43a617aa0e82b17b1")
.unwrap();
hex::decode("084e7f70a295a190e2e33fd3f8cdfcc2b664fa73499821e43a617aa0e82b17b1").unwrap();
// Step 1: Check ValidatorsToRetire BEFORE
println!("=== STEP 1: Check ValidatorsToRetire BEFORE deregister ===");
@@ -43,20 +41,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
if retire_before.is_empty() {
println!(" ValidatorsToRetire: EMPTY (as expected)\n");
} else {
println!(
" ValidatorsToRetire: {} bytes (already has data!)\n",
retire_before.len()
);
println!(" ValidatorsToRetire: {} bytes (already has data!)\n", retire_before.len());
}
// Step 2: Get validator #5 from QueuedKeys
println!("=== STEP 2: Get test validator from QueuedKeys ===");
let raw_data = api
.storage()
.at_latest()
.await?
.fetch_raw(queued_keys_key)
.await?;
let raw_data = api.storage().at_latest().await?.fetch_raw(queued_keys_key).await?;
let count = (raw_data[0] >> 2) as usize;
let remaining = raw_data.len() - 1;
let entry_size = remaining / count;
@@ -70,10 +60,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Get validator #5 (index 4, the first one to remove)
let test_offset = 1 + 4 * entry_size;
let test_validator = raw_data[test_offset..test_offset + 32].to_vec();
println!(
" Test validator (index 5): 0x{}\n",
hex::encode(&test_validator)
);
println!(" Test validator (index 5): 0x{}\n", hex::encode(&test_validator));
// Step 3: Load sudo key and submit deregister for ONE validator
println!("=== STEP 3: Submit deregister for ONE validator ===");
@@ -81,10 +68,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::env::var("SUDO_MNEMONIC").expect("SUDO_MNEMONIC environment variable required");
let mnemonic = Mnemonic::from_str(&mnemonic_str)?;
let sudo_keypair = Keypair::from_phrase(&mnemonic, None)?;
println!(
" Sudo account: {}",
sudo_keypair.public_key().to_account_id()
);
println!(" Sudo account: {}", sudo_keypair.public_key().to_account_id());
// Try TWO different encoding approaches
@@ -110,22 +94,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Print the encoded call data to debug
println!("\n Deregister call value: {:?}", deregister_call.call_data());
let sudo_call =
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![deregister_call.into_value()]);
let sudo_call = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![deregister_call.into_value()]);
println!("\n Submitting sudo(validatorManager.deregister_validators([1 validator]))...");
use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await?;
let tx_progress =
api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await?;
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
let mut success = false;
@@ -146,11 +124,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
&& ev.variant_name() == "ValidatorsDeregistered"
{
// Try to decode the event data
println!(
" >>> ValidatorsDeregistered event!"
);
println!(" >>> ValidatorsDeregistered event!");
let bytes = ev.field_bytes();
println!(" >>> Event field bytes ({} bytes): 0x{}", bytes.len(), hex::encode(&bytes[..std::cmp::min(bytes.len(), 128)]));
println!(
" >>> Event field bytes ({} bytes): 0x{}",
bytes.len(),
hex::encode(&bytes[..std::cmp::min(bytes.len(), 128)])
);
}
}
}
@@ -204,10 +184,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" ValidatorsToRetire: EMPTY !!! (deregister didn't populate storage!)");
println!(" THIS IS THE BUG!");
} else {
println!(
" ValidatorsToRetire: {} bytes",
retire_after.len()
);
println!(" ValidatorsToRetire: {} bytes", retire_after.len());
println!(" Raw hex: 0x{}", hex::encode(&retire_after));
// Decode it
@@ -32,8 +32,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let force_era_call =
pezkuwi_subxt::dynamic::tx("Staking", "force_new_era", Vec::<Value>::new());
let sudo_tx =
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![force_era_call.into_value()]);
let sudo_tx = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![force_era_call.into_value()]);
let tx_hash = api.tx().sign_and_submit_default(&sudo_tx, &sudo_keypair).await?;
println!("Submitted! TX hash: 0x{}", hex::encode(tx_hash.as_ref()));
@@ -21,9 +21,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== ZAGROS VALIDATOR COUNT REDUCTION ===\n");
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string());
let new_count: u32 = std::env::var("VALIDATOR_COUNT")
.unwrap_or_else(|_| "4".to_string())
.parse()?;
let new_count: u32 =
std::env::var("VALIDATOR_COUNT").unwrap_or_else(|_| "4".to_string()).parse()?;
println!("RPC: {}", url);
println!("Target validator count: {}", new_count);
@@ -43,12 +42,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Step 1: sudo(staking.setValidatorCount(new_count))
println!("[1/2] Setting validator count to {}...", new_count);
let set_count_call = pezkuwi_subxt::dynamic::tx("Staking", "set_validator_count", vec![
Value::u128(new_count as u128),
]);
let set_count_call = pezkuwi_subxt::dynamic::tx(
"Staking",
"set_validator_count",
vec![Value::u128(new_count as u128)],
);
let sudo_tx_1 =
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![set_count_call.into_value()]);
let sudo_tx_1 = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![set_count_call.into_value()]);
// Use sign_and_submit_default (does NOT wait for finalization)
let tx_hash_1 = api.tx().sign_and_submit_default(&sudo_tx_1, &sudo_keypair).await?;
@@ -64,8 +64,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let force_era_call =
pezkuwi_subxt::dynamic::tx("Staking", "force_new_era", Vec::<Value>::new());
let sudo_tx_2 =
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![force_era_call.into_value()]);
let sudo_tx_2 = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![force_era_call.into_value()]);
let tx_hash_2 = api.tx().sign_and_submit_default(&sudo_tx_2, &sudo_keypair).await?;
println!(" Submitted! TX hash: 0x{}", hex::encode(tx_hash_2.as_ref()));
+14 -51
View File
@@ -30,24 +30,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== ZAGROS: SET ValidatorsToRetire via setStorage ===\n");
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string());
let keep: usize = std::env::var("KEEP")
.unwrap_or_else(|_| "4".to_string())
.parse()?;
let keep: usize = std::env::var("KEEP").unwrap_or_else(|_| "4".to_string()).parse()?;
println!("RPC: {}", url);
println!("Keep: {} validators\n", keep);
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&url).await?;
println!(
"Connected! specVersion: {}\n",
api.runtime_version().spec_version
);
println!("Connected! specVersion: {}\n", api.runtime_version().spec_version);
// Verify genesis hash (Zagros = 0xbb4a61ab...)
let genesis = format!(
"0x{}",
hex::encode(api.genesis_hash().as_ref())
);
let genesis = format!("0x{}", hex::encode(api.genesis_hash().as_ref()));
println!("Genesis: {}", genesis);
if !genesis.starts_with("0xbb4a61ab") {
println!("ERROR: This is NOT Zagros! Aborting.");
@@ -57,15 +49,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read QueuedKeys to get all validator AccountIds
let queued_keys_key =
hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903")
.unwrap();
hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903").unwrap();
let raw_data = api
.storage()
.at_latest()
.await?
.fetch_raw(queued_keys_key)
.await?;
let raw_data = api.storage().at_latest().await?.fetch_raw(queued_keys_key).await?;
let count = (raw_data[0] >> 2) as usize;
let remaining = raw_data.len() - 1;
@@ -101,10 +87,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
for v in to_remove {
encoded_retire.extend_from_slice(v);
}
println!(
"\nSCALE-encoded ValidatorsToRetire: {} bytes",
encoded_retire.len()
);
println!("\nSCALE-encoded ValidatorsToRetire: {} bytes", encoded_retire.len());
println!(
" compact_length: 0x{} (count={})",
hex::encode(&encode_compact(to_remove.len())),
@@ -113,13 +96,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Storage key for ValidatorsToRetire
let validators_to_retire_key =
hex::decode("084e7f70a295a190e2e33fd3f8cdfcc2b664fa73499821e43a617aa0e82b17b1")
.unwrap();
hex::decode("084e7f70a295a190e2e33fd3f8cdfcc2b664fa73499821e43a617aa0e82b17b1").unwrap();
println!(
"\nStorage key: 0x{}",
hex::encode(&validators_to_retire_key)
);
println!("\nStorage key: 0x{}", hex::encode(&validators_to_retire_key));
println!(
"Storage value: 0x{}...({} bytes)",
hex::encode(&encoded_retire[..std::cmp::min(encoded_retire.len(), 40)]),
@@ -131,10 +110,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::env::var("SUDO_MNEMONIC").expect("SUDO_MNEMONIC environment variable required");
let mnemonic = Mnemonic::from_str(&mnemonic_str)?;
let sudo_keypair = Keypair::from_phrase(&mnemonic, None)?;
println!(
"\nSudo account: {}",
sudo_keypair.public_key().to_account_id()
);
println!("\nSudo account: {}", sudo_keypair.public_key().to_account_id());
// Build sudo(system.setStorage(items))
let set_storage_tx = pezkuwi_subxt::dynamic::tx(
@@ -152,15 +128,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await?;
let tx_progress =
api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await?;
println!(
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
let mut success = false;
@@ -230,19 +201,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
{
Ok(data) => {
let stored_count = (data[0] >> 2) as usize;
println!(
"ValidatorsToRetire: {} entries ({} bytes)",
stored_count,
data.len()
);
println!("ValidatorsToRetire: {} entries ({} bytes)", stored_count, data.len());
if stored_count == to_remove.len() {
println!("COUNT MATCHES! Storage write successful.");
} else {
println!(
"COUNT MISMATCH! Expected {}, got {}",
to_remove.len(),
stored_count
);
println!("COUNT MISMATCH! Expected {}, got {}", to_remove.len(), stored_count);
}
// Show first few
let mut off = 1;
+32 -37
View File
@@ -30,13 +30,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let inner_call = match call_name.as_str() {
"setValidatorCount" => {
let count: u32 = std::env::var("COUNT")
.unwrap_or_else(|_| "4".to_string())
.parse()?;
let count: u32 = std::env::var("COUNT").unwrap_or_else(|_| "4".to_string()).parse()?;
println!("Setting validator count to {}", count);
pezkuwi_subxt::dynamic::tx("Staking", "set_validator_count", vec![Value::u128(
count as u128,
)])
pezkuwi_subxt::dynamic::tx(
"Staking",
"set_validator_count",
vec![Value::u128(count as u128)],
)
},
"forceNewEra" => {
println!("Forcing new era");
@@ -48,9 +48,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
},
"setStakingConfigs" => {
// Set min_validator_count to 1 via set_staking_configs
let min_count: u32 = std::env::var("MIN_COUNT")
.unwrap_or_else(|_| "1".to_string())
.parse().unwrap();
let min_count: u32 =
std::env::var("MIN_COUNT").unwrap_or_else(|_| "1".to_string()).parse().unwrap();
println!("Setting staking configs: min_nominator_bond=Noop, min_validator_bond=Noop, max_nominator_count=Noop, max_validator_count=Noop, chill_threshold=Noop, min_commission=Noop");
// Actually we need to set min_validator_count directly
// Let's use a different approach - call set_staking_configs with all Noop except what we need
@@ -61,9 +60,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::process::exit(1);
},
"setMinValidatorCount" => {
let min_count: u32 = std::env::var("MIN_COUNT")
.unwrap_or_else(|_| "1".to_string())
.parse().unwrap();
let min_count: u32 =
std::env::var("MIN_COUNT").unwrap_or_else(|_| "1".to_string()).parse().unwrap();
println!("Setting minimum validator count to {}", min_count);
// Staking::set_staking_configs sets all params at once
// Instead we should check if there's a direct setter
@@ -72,22 +70,24 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// ConfigOp: Noop=unnamed_variant("Noop",[]), Set=unnamed_variant("Set",[Value::u128(x)])
let noop = Value::unnamed_variant("Noop", Vec::<Value>::new());
let set_val = Value::unnamed_variant("Set", vec![Value::u128(min_count as u128)]);
pezkuwi_subxt::dynamic::tx("Staking", "set_staking_configs", vec![
noop.clone(), // min_nominator_bond
noop.clone(), // min_validator_bond
noop.clone(), // max_nominator_count
noop.clone(), // max_validator_count
noop.clone(), // chill_threshold
noop.clone(), // min_commission
noop.clone(), // max_staked_rewards (if exists)
])
pezkuwi_subxt::dynamic::tx(
"Staking",
"set_staking_configs",
vec![
noop.clone(), // min_nominator_bond
noop.clone(), // min_validator_bond
noop.clone(), // max_nominator_count
noop.clone(), // max_validator_count
noop.clone(), // chill_threshold
noop.clone(), // min_commission
noop.clone(), // max_staked_rewards (if exists)
],
)
},
"setStorage" => {
// Set arbitrary storage via sudo(system.setStorage)
let key_hex =
std::env::var("STORAGE_KEY").expect("STORAGE_KEY env var required");
let value_hex =
std::env::var("STORAGE_VALUE").expect("STORAGE_VALUE env var required");
let key_hex = std::env::var("STORAGE_KEY").expect("STORAGE_KEY env var required");
let value_hex = std::env::var("STORAGE_VALUE").expect("STORAGE_VALUE env var required");
println!("Setting storage key={} value={}", key_hex, value_hex);
let key_bytes = hex::decode(key_hex.trim_start_matches("0x")).unwrap();
@@ -98,9 +98,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Value::from_bytes(&key_bytes),
Value::from_bytes(&value_bytes),
]);
pezkuwi_subxt::dynamic::tx("System", "set_storage", vec![
Value::unnamed_composite([item]),
])
pezkuwi_subxt::dynamic::tx(
"System",
"set_storage",
vec![Value::unnamed_composite([item])],
)
},
_ => {
eprintln!("Unknown call: {}", call_name);
@@ -113,10 +115,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("\nSubmitting...");
// Use sign_and_submit_then_watch to see TX lifecycle
let tx_progress = api
.tx()
.sign_and_submit_then_watch_default(&sudo_tx, &sudo_keypair)
.await?;
let tx_progress = api.tx().sign_and_submit_then_watch_default(&sudo_tx, &sudo_keypair).await?;
println!("TX hash: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
println!("Watching TX status (Ctrl+C to abort)...");
@@ -137,11 +136,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" TX SUCCESS!");
for event in events.iter() {
if let Ok(ev) = event {
println!(
" Event: {}::{}",
ev.pallet_name(),
ev.variant_name()
);
println!(" Event: {}::{}", ev.pallet_name(), ev.variant_name());
}
}
},
+32 -42
View File
@@ -22,9 +22,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string());
let wasm_path = std::env::var("WASM_FILE").expect("WASM_FILE environment variable required");
let new_validator_count: u32 = std::env::var("VALIDATOR_COUNT")
.unwrap_or_else(|_| "2".to_string())
.parse()?;
let new_validator_count: u32 =
std::env::var("VALIDATOR_COUNT").unwrap_or_else(|_| "2".to_string()).parse()?;
println!("RPC: {}", url);
println!("WASM: {}", wasm_path);
@@ -32,7 +31,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load WASM
let wasm_data = std::fs::read(&wasm_path)?;
println!("WASM size: {} bytes ({:.2} MB)", wasm_data.len(), wasm_data.len() as f64 / 1_048_576.0);
println!(
"WASM size: {} bytes ({:.2} MB)",
wasm_data.len(),
wasm_data.len() as f64 / 1_048_576.0
);
// Connect
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&url).await?;
@@ -58,13 +61,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
vec![Value::from_bytes(&wasm_data)],
);
let sudo_upgrade = pezkuwi_subxt::dynamic::tx("Sudo", "sudo_unchecked_weight", vec![
set_code.into_value(),
Value::named_composite([
("ref_time", Value::u128(1u128)),
("proof_size", Value::u128(1u128)),
]),
]);
let sudo_upgrade = pezkuwi_subxt::dynamic::tx(
"Sudo",
"sudo_unchecked_weight",
vec![
set_code.into_value(),
Value::named_composite([
("ref_time", Value::u128(1u128)),
("proof_size", Value::u128(1u128)),
]),
],
);
use pezkuwi_subxt::tx::TxStatus;
@@ -73,10 +80,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.sign_and_submit_then_watch_default(&sudo_upgrade, &sudo_keypair)
.await?;
println!(
" TX submitted: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!(" TX submitted: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress;
let mut upgrade_ok = false;
@@ -152,11 +156,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Staking::ForceEra: 0x5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3
let validator_count_key =
hex::decode("5f3e4907f716ac89b6347d15ececedca138e71612491192d68deab7e6f563fe1")
.unwrap();
hex::decode("5f3e4907f716ac89b6347d15ececedca138e71612491192d68deab7e6f563fe1").unwrap();
let force_era_key =
hex::decode("5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3")
.unwrap();
hex::decode("5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3").unwrap();
// ValidatorCount is u32 LE
let validator_count_value = new_validator_count.to_le_bytes().to_vec();
@@ -166,8 +168,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Setting ValidatorCount = {}", new_validator_count);
println!("Setting ForceEra = ForceNew (0x01)");
let set_storage_tx = pezkuwi_subxt::dynamic::tx("System", "set_storage", vec![
Value::unnamed_composite(vec![
let set_storage_tx = pezkuwi_subxt::dynamic::tx(
"System",
"set_storage",
vec![Value::unnamed_composite(vec![
Value::unnamed_composite(vec![
Value::from_bytes(&validator_count_key),
Value::from_bytes(&validator_count_value),
@@ -176,22 +180,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Value::from_bytes(&force_era_key),
Value::from_bytes(&force_era_value),
]),
]),
]);
])],
);
let sudo_storage = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![
set_storage_tx.into_value(),
]);
let sudo_storage =
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![set_storage_tx.into_value()]);
let tx_progress2 = api2
.tx()
.sign_and_submit_then_watch_default(&sudo_storage, &sudo_keypair)
.await?;
println!(
" TX submitted: 0x{}",
hex::encode(tx_progress2.extrinsic_hash().as_ref())
);
println!(" TX submitted: 0x{}", hex::encode(tx_progress2.extrinsic_hash().as_ref()));
let mut progress2 = tx_progress2;
let mut storage_ok = false;
@@ -256,23 +256,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("specVersion: {}", rv3.spec_version);
// Read back storage to verify
let vc_bytes = api3
.storage()
.at_latest()
.await?
.fetch_raw(validator_count_key)
.await?;
let vc_bytes = api3.storage().at_latest().await?.fetch_raw(validator_count_key).await?;
if vc_bytes.len() >= 4 {
let vc = u32::from_le_bytes([vc_bytes[0], vc_bytes[1], vc_bytes[2], vc_bytes[3]]);
println!("ValidatorCount: {}", vc);
}
let fe_bytes = api3
.storage()
.at_latest()
.await?
.fetch_raw(force_era_key)
.await?;
let fe_bytes = api3.storage().at_latest().await?.fetch_raw(force_era_key).await?;
if !fe_bytes.is_empty() {
let fe_name = match fe_bytes[0] {
0x00 => "NotForcing",