diff --git a/README.md b/README.md
index 7bfc1dc662c7d506d573a80f3f66f621852baf85..38eb3a801b0c9dcd4f4974323548c194ff36c793 100644
--- a/README.md
+++ b/README.md
@@ -70,5 +70,7 @@ Secret key format can be changed using `--secret-format` with the following valu
 ## TODO
 
 - [x] implement config formatter
-- [ ] add link/unlink account commands
-- [ ] migrate all xt to submit_call_and_look_event
\ No newline at end of file
+- [x] add link/unlink account commands
+- [ ] migrate all xt to submit_call_and_look_event
+- [ ] add transfer with unit (ÄžD, UD...)
+- [ ] 
\ No newline at end of file
diff --git a/src/commands/account.rs b/src/commands/account.rs
index dc86d706acaceeaa13d5121f537e6e4c2485ca5b..3d8844d96a2421dd31ef5038d3c3b26840bcb951 100644
--- a/src/commands/account.rs
+++ b/src/commands/account.rs
@@ -27,6 +27,8 @@ pub enum Subcommand {
 		/// List of target addresses
 		dests: Vec<AccountId>,
 	},
+	/// Unlink the account from the linked identity
+	Unlink,
 }
 
 /// handle account commands
@@ -48,6 +50,9 @@ pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<(
 		Subcommand::TransferMultiple { amount, dests } => {
 			commands::transfer::transfer_multiple(&data, amount, dests).await?;
 		}
+		Subcommand::Unlink => {
+			unlink_account(&data).await?;
+		}
 	};
 
 	Ok(())
@@ -78,3 +83,12 @@ pub async fn get_account_info(
 		.fetch(&runtime::storage().system().account(account_id), None)
 		.await
 }
+
+/// unlink account
+pub async fn unlink_account(data: &Data) -> Result<(), subxt::Error> {
+	submit_call_and_look_event::<
+		runtime::account::events::AccountUnlinked,
+		StaticTxPayload<runtime::account::calls::UnlinkIdentity>,
+	>(data, &runtime::tx().account().unlink_identity())
+	.await
+}
diff --git a/src/commands/identity.rs b/src/commands/identity.rs
index 02f75fbbd0e34379a218f89a6e2e266b8b30e89e..b361755c51e571302d7315d91686724a5bb09ba0 100644
--- a/src/commands/identity.rs
+++ b/src/commands/identity.rs
@@ -3,7 +3,9 @@ use crate::*;
 use crate::{
 	commands::revocation::generate_revoc_doc,
 	runtime::runtime_types::{
-		common_runtime::entities::IdtyData, pallet_identity::types::*, sp_core::sr25519::Signature,
+		common_runtime::entities::{IdtyData, NewOwnerKeySignature},
+		pallet_identity::types::*,
+		sp_core::sr25519::Signature,
 		sp_runtime::MultiSignature,
 	},
 };
@@ -40,6 +42,11 @@ pub enum Subcommand {
 	GenRevocDoc,
 	/// Display member count
 	MemberCount,
+	/// Link an account to the identity
+	LinkAccount {
+		/// address of the account that has to be linked
+		address: AccountId,
+	},
 }
 
 /// handle identity commands
@@ -88,6 +95,10 @@ pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<(
 					.unwrap()
 			)
 		}
+		Subcommand::LinkAccount { address } => {
+			data = data.fetch_idty_index().await?; // idty index required for payload
+			link_account(&data, address).await?;
+		}
 	};
 
 	Ok(())
@@ -258,3 +269,34 @@ pub async fn revoke_identity(data: Data) -> Result<(), subxt::Error> {
 	}
 	Ok(())
 }
+
+type LinkAccountPayload = Vec<u8>;
+/// generate link account document
+pub fn generate_link_account(
+	data: &Data,
+	address: AccountId,
+) -> (LinkAccountPayload, sp_core::sr25519::Signature) {
+	let payload = (b"link", data.genesis_hash, data.idty_index(), address).encode();
+	let signature = data.keypair().sign(&payload);
+	(payload, signature)
+}
+
+/// link an account to the identity
+pub async fn link_account(data: &Data, address: AccountId) -> Result<(), subxt::Error> {
+	let (_payload, signature) = generate_link_account(&data, address.clone());
+
+	// this is a hack, see
+	// https://substrate.stackexchange.com/questions/10309/how-to-use-core-crypto-types-instead-of-runtime-types
+	let signature = Signature(signature.0);
+
+	submit_call_and_look_event::<
+		runtime::account::events::AccountLinked,
+		StaticTxPayload<runtime::identity::calls::LinkAccount>,
+	>(
+		data,
+		&runtime::tx()
+			.identity()
+			.link_account(address, NewOwnerKeySignature(signature)),
+	)
+	.await
+}
diff --git a/src/main.rs b/src/main.rs
index e4c0b008508f7c00651d44bf841772ccc9bd8b9b..1c90aacc3cbf9037f90b0a032c2d2d89ffe1f39f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -92,7 +92,7 @@ pub enum Subcommand {
 	Config(conf::Subcommand),
 }
 
-/// maint function
+/// main function
 #[tokio::main(flavor = "current_thread")]
 async fn main() -> Result<(), GcliError> {
 	// init logger
diff --git a/src/runtime_config.rs b/src/runtime_config.rs
index d62c5e1172f96d69ab3eed69296462a8a4d0ff31..f0eff326e055c05bfad520b2ab9ffe7a5209b436 100644
--- a/src/runtime_config.rs
+++ b/src/runtime_config.rs
@@ -5,8 +5,8 @@
 )]
 pub mod runtime {
 	// IF NEEDED
-	// #[subxt(substitute_type = "spcore::sr25519::Signature")]
-	// use crate::gdev::runtime_types::sp_core::sr25519::Signature;
+	// #[subxt(substitute_type = "sp_core::sr25519::Signature")]
+	// use crate::runtime::runtime_types::sp_core::sr25519::Signature;
 }
 
 // declare custom types