diff --git a/src/commands/expire.rs b/src/commands/expire.rs
index 207bfbf9dce274572e7ce7bf9e6dccdfad7346f0..d051ea80f2719ad208d4476f38ee8a3df72fa37c 100644
--- a/src/commands/expire.rs
+++ b/src/commands/expire.rs
@@ -29,8 +29,8 @@ pub async fn monitor_expirations(
 			.storage()
 			.fetch(&addr_current_session, Some(parent_hash),)
 	);
-	let current_block = current_block?.unwrap();
-	let current_session = current_session?.unwrap();
+	let current_block = current_block?.unwrap_or_default();
+	let current_session = current_session?.unwrap_or_default();
 
 	let end_block = current_block + blocks;
 	let end_session = current_session + sessions;
@@ -152,6 +152,9 @@ pub async fn monitor_expirations(
 	while let Some((k, v)) = basic_membership_iter.next().await? {
 		let block_number = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
 		if block_number < end_block {
+			if block_number < current_block {
+				dbg!((block_number, current_block));
+			}
 			basic_memberships.insert(block_number - current_block, v);
 		}
 	}
diff --git a/src/commands/identity.rs b/src/commands/identity.rs
index 0fa2755599be8df1b017be0cfeb8dad2f84f018d..6cde145611f6cca3fa09fea638539055f4b6fbc0 100644
--- a/src/commands/identity.rs
+++ b/src/commands/identity.rs
@@ -1,8 +1,9 @@
 use crate::{gdev, indexer::*, Args, Client};
 
 use anyhow::{anyhow, Result};
-use sp_core::crypto::AccountId32;
+use sp_core::{crypto::AccountId32, sr25519::Pair};
 use std::str::FromStr;
+use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
 pub async fn get_identity(
 	client: Client,
@@ -87,3 +88,29 @@ pub async fn get_identity(
 
 	Ok(())
 }
+
+pub async fn create_identity(pair: Pair, client: Client, target: AccountId32) -> Result<()> {
+	client
+		.tx()
+		.sign_and_submit_then_watch(
+			&gdev::tx().identity().create_identity(target),
+			&PairSigner::new(pair),
+			BaseExtrinsicParamsBuilder::new(),
+		)
+		.await?;
+
+	Ok(())
+}
+
+pub async fn confirm_identity(pair: Pair, client: Client, name: String) -> Result<()> {
+	client
+		.tx()
+		.sign_and_submit_then_watch(
+			&gdev::tx().identity().confirm_identity(name),
+			&PairSigner::new(pair),
+			BaseExtrinsicParamsBuilder::new(),
+		)
+		.await?;
+
+	Ok(())
+}
diff --git a/src/main.rs b/src/main.rs
index 5ce099e1d26782c9be22430cb3b703c993479d80..7b451af894722ccb7c8bfd79520d708e335b1374 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -82,6 +82,18 @@ pub struct Args {
 
 #[derive(Debug, clap::Subcommand)]
 pub enum Subcommand {
+	/// Confirm an identity
+	///
+	/// To be called by the certified not-yet-member account, to become member.
+	ConfirmIdentity {
+		name: String,
+	},
+	/// Create and certify an identity
+	///
+	/// Caller must be member, and the target account must exist.
+	CreateIdentity {
+		target: sp_core::crypto::AccountId32,
+	},
 	CreateOneshot {
 		balance: u64,
 		dest: sp_core::crypto::AccountId32,
@@ -196,6 +208,36 @@ async fn main() -> Result<()> {
 	}*/
 
 	match args.subcommand {
+		Subcommand::ConfirmIdentity { name } => {
+			commands::identity::confirm_identity(
+				get_keys(
+					args.secret_format,
+					&args.address,
+					&args.secret,
+					NeededKeys::Secret,
+				)?
+				.1
+				.unwrap(),
+				Client::from_url(&args.url).await.unwrap(),
+				name,
+			)
+			.await?
+		}
+		Subcommand::CreateIdentity { target } => {
+			commands::identity::create_identity(
+				get_keys(
+					args.secret_format,
+					&args.address,
+					&args.secret,
+					NeededKeys::Secret,
+				)?
+				.1
+				.unwrap(),
+				Client::from_url(&args.url).await.unwrap(),
+				target,
+			)
+			.await?
+		}
 		Subcommand::CreateOneshot { balance, dest } => {
 			commands::oneshot::create_oneshot_account(
 				get_keys(