diff --git a/lib/data/models/contact_wot_info.dart b/lib/data/models/contact_wot_info.dart
index 00fc0082c799a36d40f7c102944410e3f868e3a7..b847256722b2ff77328fd61f5ea8bbe85090d2e7 100644
--- a/lib/data/models/contact_wot_info.dart
+++ b/lib/data/models/contact_wot_info.dart
@@ -1,5 +1,5 @@
+import '../../ui/ui_helpers.dart';
 import 'contact.dart';
-import 'identity_status.dart';
 
 class ContactWotInfo {
   ContactWotInfo({
@@ -11,16 +11,10 @@ class ContactWotInfo {
   final Contact you;
   bool? canCert;
   bool? canCreateIdty;
+  bool? waitingForCerts;
 
-  bool get isMe {
-    return me.pubKey == you.pubKey;
-  }
-
-  bool get isMember {
-    return you.status == IdentityStatus.MEMBER;
-  }
-
-  bool get iAmMember {
-    return me.status == IdentityStatus.MEMBER;
+  @override
+  String toString() {
+    return 'ContactWotInfo{me: ${humanizeContact('', me)}, you: ${humanizeContact('', you)}, canCert: $canCert, canCreateIdty: $canCreateIdty}, waitingForCert: $waitingForCerts}';
   }
 }
diff --git a/lib/g1/g1_v2_helper_others.dart b/lib/g1/g1_v2_helper_others.dart
index c49fa13b62888d83a636c61b7635b89cb8a0c030..5cc666eb75b7d79bc07815a3ed5ac0244f953d4d 100644
--- a/lib/g1/g1_v2_helper_others.dart
+++ b/lib/g1/g1_v2_helper_others.dart
@@ -514,3 +514,126 @@ Uri parseNodeUrl(String url) {
   final Uri parsedUri = Uri.parse(url);
   return parsedUri;
 }
+
+Future<String> requestDistanceEvaluation(int idtyIndex,
+    {Duration timeout = defPolkadotTimeout}) async {
+  final CesiumWallet walletV1 = await SharedPreferencesHelper().getWallet();
+  final KeyPair wallet = KeyPair.ed25519.fromSeed(walletV1.seed);
+  final Completer<String> result = Completer<String>();
+
+  return executeOnNodes<String>(
+      (Node node, Provider provider, Gdev gdev) async {
+    // distance rule has been evaluated positively locally on web of trust at block storage.distance.evaluationBlock()
+    // TODO(vjrj): Implement this
+    // gdev.query.distance.evaluationBlock();
+    final RuntimeCall call =
+        gdev.tx.distance.requestDistanceEvaluationFor(target: idtyIndex);
+    return signAndSend(gdev, wallet, call, provider, result, timeout);
+  });
+}
+
+Future<String> signAndSend(Gdev polkadot, KeyPair wallet, RuntimeCall call,
+    Provider provider, Completer<String> result, Duration timeout) async {
+  final RuntimeVersion runtimeVersion =
+      await polkadot.rpc.state.getRuntimeVersion();
+  final int currentBlockNumber = (await polkadot.query.system.number()) - 1;
+  final H256 currentBlockHash =
+      await polkadot.query.system.blockHash(currentBlockNumber);
+  final int nonce = await polkadot.rpc.system.accountNextIndex(wallet.address);
+
+  final H256 genesisHash = await polkadot.query.system.blockHash(0);
+
+  final Uint8List encodedCall = call.encode();
+
+  final Uint8List payload = SigningPayload(
+          method: encodedCall,
+          specVersion: runtimeVersion.specVersion,
+          transactionVersion: runtimeVersion.transactionVersion,
+          genesisHash: encodeHex(genesisHash),
+          blockHash: encodeHex(currentBlockHash),
+          blockNumber: currentBlockNumber,
+          eraPeriod: 64,
+          nonce: nonce,
+          tip: 0)
+      .encode(polkadot.registry);
+
+  final Uint8List signature = wallet.sign(payload);
+  final Uint8List extrinsic = ExtrinsicPayload(
+          signer: wallet.bytes(),
+          method: encodedCall,
+          signature: signature,
+          eraPeriod: 64,
+          blockNumber: currentBlockNumber,
+          nonce: nonce,
+          tip: 0)
+      .encode(polkadot.registry, SignatureType.ed25519);
+
+  final AuthorApi<Provider> author = AuthorApi<Provider>(provider);
+
+  await author.submitAndWatchExtrinsic(extrinsic, (ExtrinsicStatus status) {
+    switch (status.type) {
+      case 'finalized':
+        result.complete('');
+        break;
+      case 'dropped':
+        result.complete(tr('op_dropped'));
+        break;
+      case 'invalid':
+        result.complete(tr('op_invalid'));
+        break;
+      case 'usurped':
+        result.complete(tr('op_usurped'));
+        break;
+      case 'future':
+        break;
+      case 'ready':
+        break;
+      case 'inBlock':
+        break;
+      case 'broadcast':
+        break;
+      default:
+        result.complete('Unexpected transaction status: ${status.type}.');
+        loggerDev('Unexpected transaction status: ${status.type}.');
+        break;
+    }
+  }).timeout(timeout);
+  return result.future;
+}
+
+Future<String> createIdentity(
+    {required Contact you, Duration timeout = defPolkadotTimeout}) async {
+  final List<Node> nodes = NodeManager().getBestNodes(NodeType.endpoint);
+  nodes.shuffle();
+  final CesiumWallet walletV1 = await SharedPreferencesHelper().getWallet();
+  final KeyPair wallet = KeyPair.ed25519.fromSeed(walletV1.seed);
+  final Completer<String> result = Completer<String>();
+  return executeOnNodes((Node node, Provider provider, Gdev polkadot) async {
+    final RuntimeCall call = polkadot.tx.identity.createIdentity(
+      ownerKey: Address.decode(you.address).pubkey,
+    );
+
+    return signAndSend(polkadot, wallet, call, provider, result, timeout);
+  });
+}
+
+Future<String> confirmIdentity(String identityName,
+    {Duration timeout = defPolkadotTimeout}) async {
+  final List<Node> nodes = NodeManager().getBestNodes(NodeType.endpoint);
+  nodes.shuffle();
+  final CesiumWallet walletV1 = await SharedPreferencesHelper().getWallet();
+  final KeyPair wallet = KeyPair.ed25519.fromSeed(walletV1.seed);
+  final Completer<String> result = Completer<String>();
+  return executeOnNodes((Node node, Provider provider, Gdev polkadot) async {
+    final RuntimeCall call =
+        polkadot.tx.identity.confirmIdentity(idtyName: identityName.codeUnits);
+    return signAndSend(polkadot, wallet, call, provider, result, timeout);
+  });
+}
+
+Constants gdevConstants() {
+  final Provider provider =
+      Provider.fromUri(parseNodeUrl(NodeManager().endpointNodes.first.url));
+  final Gdev gdev = Gdev(provider);
+  return gdev.constant;
+}
diff --git a/lib/g1/wot_actions.dart b/lib/g1/wot_actions.dart
index 86563da2f8ad2144286576d34f6731112f1c2733..17a956ea2b2ad508eaf46327f855f02dfe2965ed 100644
--- a/lib/g1/wot_actions.dart
+++ b/lib/g1/wot_actions.dart
@@ -1,161 +1,36 @@
 import 'dart:async';
-import 'dart:typed_data';
 
-import 'package:durt/durt.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
-import 'package:polkadart/apis/apis.dart';
-import 'package:polkadart/extrinsic/extrinsic_payload.dart';
-import 'package:polkadart/extrinsic/signature_type.dart';
-import 'package:polkadart/extrinsic/signing_payload.dart';
-import 'package:polkadart/primitives/primitives.dart';
-import 'package:polkadart/provider.dart';
-import 'package:polkadart/scale_codec.dart';
-import 'package:polkadart_keyring/polkadart_keyring.dart';
-import 'package:ss58/ss58.dart';
 
-import '../data/models/contact.dart';
 import '../data/models/contact_wot_info.dart';
 import '../data/models/identity_status.dart';
 import '../data/models/menu_action.dart';
-import '../data/models/node.dart';
-import '../data/models/node_manager.dart';
-import '../data/models/node_type.dart';
-import '../generated/gdev/gdev.dart';
-import '../generated/gdev/types/gdev_runtime/runtime_call.dart';
-import '../generated/gdev/types/primitive_types/h256.dart';
-import '../shared_prefs_helper.dart';
 import '../ui/logger.dart';
-import 'g1_helper.dart';
+import '../ui/ui_helpers.dart';
 import 'g1_v2_helper_others.dart';
 
-Future<String> requestDistanceEvaluation(int idtyIndex,
-    {Duration timeout = defPolkadotTimeout}) async {
-  final CesiumWallet walletV1 = await SharedPreferencesHelper().getWallet();
-  final KeyPair wallet = KeyPair.ed25519.fromSeed(walletV1.seed);
-  final Completer<String> result = Completer<String>();
-
-  return executeOnNodes<String>(
-      (Node node, Provider provider, Gdev gdev) async {
-    // distance rule has been evaluated positively locally on web of trust at block storage.distance.evaluationBlock()
-    // TODO(vjrj): Implement this
-    // gdev.query.distance.evaluationBlock();
-    final RuntimeCall call =
-        gdev.tx.distance.requestDistanceEvaluationFor(target: idtyIndex);
-    return signAndSend(gdev, wallet, call, provider, result, timeout);
-  });
-}
-
-Future<String> signAndSend(Gdev polkadot, KeyPair wallet, RuntimeCall call,
-    Provider provider, Completer<String> result, Duration timeout) async {
-  final RuntimeVersion runtimeVersion =
-      await polkadot.rpc.state.getRuntimeVersion();
-  final int currentBlockNumber = (await polkadot.query.system.number()) - 1;
-  final H256 currentBlockHash =
-      await polkadot.query.system.blockHash(currentBlockNumber);
-  final int nonce = await polkadot.rpc.system.accountNextIndex(wallet.address);
-
-  final H256 genesisHash = await polkadot.query.system.blockHash(0);
-
-  final Uint8List encodedCall = call.encode();
-
-  final Uint8List payload = SigningPayload(
-          method: encodedCall,
-          specVersion: runtimeVersion.specVersion,
-          transactionVersion: runtimeVersion.transactionVersion,
-          genesisHash: encodeHex(genesisHash),
-          blockHash: encodeHex(currentBlockHash),
-          blockNumber: currentBlockNumber,
-          eraPeriod: 64,
-          nonce: nonce,
-          tip: 0)
-      .encode(polkadot.registry);
-
-  final Uint8List signature = wallet.sign(payload);
-  final Uint8List extrinsic = ExtrinsicPayload(
-          signer: wallet.bytes(),
-          method: encodedCall,
-          signature: signature,
-          eraPeriod: 64,
-          blockNumber: currentBlockNumber,
-          nonce: nonce,
-          tip: 0)
-      .encode(polkadot.registry, SignatureType.ed25519);
-
-  final AuthorApi<Provider> author = AuthorApi<Provider>(provider);
-
-  await author.submitAndWatchExtrinsic(extrinsic, (ExtrinsicStatus status) {
-    switch (status.type) {
-      case 'finalized':
-        result.complete('');
-        break;
-      case 'dropped':
-        result.complete(tr('op_dropped'));
-        break;
-      case 'invalid':
-        result.complete(tr('op_invalid'));
-        break;
-      case 'usurped':
-        result.complete(tr('op_usurped'));
-        break;
-      case 'future':
-        break;
-      case 'ready':
-        break;
-      case 'inBlock':
-        break;
-      case 'broadcast':
-        break;
-      default:
-        result.complete('Unexpected transaction status: ${status.type}.');
-        loggerDev('Unexpected transaction status: ${status.type}.');
-        break;
-    }
-  }).timeout(timeout);
-  return result.future;
-}
-
-Future<String> createIdentity(
-    {required Contact you, Duration timeout = defPolkadotTimeout}) async {
-  final List<Node> nodes = NodeManager().getBestNodes(NodeType.endpoint);
-  nodes.shuffle();
-  final CesiumWallet walletV1 = await SharedPreferencesHelper().getWallet();
-  final KeyPair wallet = KeyPair.ed25519.fromSeed(walletV1.seed);
-  final Completer<String> result = Completer<String>();
-  return executeOnNodes((Node node, Provider provider, Gdev polkadot) async {
-    final RuntimeCall call = polkadot.tx.identity.createIdentity(
-      ownerKey: Address.decode(you.address).pubkey,
-    );
-
-    return signAndSend(polkadot, wallet, call, provider, result, timeout);
-  });
-}
-
-Future<String> confirmIdentity(String identityName,
-    {Duration timeout = defPolkadotTimeout}) async {
-  final List<Node> nodes = NodeManager().getBestNodes(NodeType.endpoint);
-  nodes.shuffle();
-  final CesiumWallet walletV1 = await SharedPreferencesHelper().getWallet();
-  final KeyPair wallet = KeyPair.ed25519.fromSeed(walletV1.seed);
-  final Completer<String> result = Completer<String>();
-  return executeOnNodes((Node node, Provider provider, Gdev polkadot) async {
-    final RuntimeCall call =
-        polkadot.tx.identity.confirmIdentity(idtyName: identityName.codeUnits);
-    return signAndSend(polkadot, wallet, call, provider, result, timeout);
-  });
-}
-
 List<MenuAction> getWotMenuActions(
     BuildContext context, bool isMe, ContactWotInfo wotInfo) {
   final List<MenuAction> actions = <MenuAction>[];
   final IdentityStatus? status = wotInfo.you.status;
-
+  if (inDevelopment) {
+    actions.add(
+      MenuAction(
+        name: 'isMe: $isMe $wotInfo',
+        icon: Icons.info,
+        action: () {
+          return Future<String>.value('');
+        },
+      ),
+    );
+  }
   switch (status) {
     case IdentityStatus.MEMBER:
       if (isMe) {
         actions.addAll(<MenuAction>[
           MenuAction(
-            name: 'Renew Membership',
+            name: tr('renew_membership'),
             icon: Icons.refresh,
             action: () {
               loggerDev('Renewing Membership');
@@ -163,7 +38,7 @@ List<MenuAction> getWotMenuActions(
             },
           ),
           MenuAction(
-            name: 'Revoke Membership',
+            name: tr('revoke_membership'),
             icon: Icons.cancel,
             action: () {
               loggerDev('Revoking Membership');
@@ -195,20 +70,20 @@ List<MenuAction> getWotMenuActions(
       if (isMe) {
         actions.add(
           MenuAction(
-            name: 'Confirm Identity',
+            name: tr('confirm_identity'),
             icon: Icons.verified,
             action: () {
               final TextEditingController controller = TextEditingController();
               final RegExp validateIdtyName = RegExp(r'^[a-zA-Z0-9_-]{1,42}$');
-
               showDialog(
                 context: context,
                 builder: (BuildContext context) {
                   return AlertDialog(
-                    title: Text('Confirm Identity'),
+                    title: Text(tr('confirm_identity')),
                     content: TextField(
                       controller: controller,
-                      decoration: InputDecoration(hintText: 'Identity Name'),
+                      decoration:
+                          InputDecoration(hintText: tr('identity_name_hint')),
                     ),
                     actions: <Widget>[
                       TextButton(
@@ -234,7 +109,7 @@ List<MenuAction> getWotMenuActions(
                           } else {
                             ScaffoldMessenger.of(context).showSnackBar(
                               SnackBar(
-                                  content: Text(tr('Invalid identity name'))),
+                                  content: Text(tr('invalid_identity_name'))),
                             );
                           }
                         },
@@ -272,7 +147,7 @@ List<MenuAction> getWotMenuActions(
 void _requestDistanceAction(int? idtyIndex, List<MenuAction> actions) {
   if (idtyIndex != null) {
     actions.add(MenuAction(
-        name: 'Request Distance Evaluation',
+        name: tr('request_distance_evaluation'),
         icon: Icons.social_distance,
         action: () {
           return requestDistanceEvaluation(idtyIndex);
@@ -284,7 +159,7 @@ void _certAction(ContactWotInfo wotInfo, List<MenuAction> actions) {
   if (wotInfo.canCert ?? false) {
     actions.add(
       MenuAction(
-        name: 'Certify Member',
+        name: tr('certify'),
         icon: Icons.verified,
         action: () {
           loggerDev('Certifying Member');
diff --git a/lib/ui/widgets/contact_page.dart b/lib/ui/widgets/contact_page.dart
index 1905901f13612082cea4dabd7ee43802cc8bdfe7..358e1dcbdd2b098b7ff913634e1432c97db9b83f 100644
--- a/lib/ui/widgets/contact_page.dart
+++ b/lib/ui/widgets/contact_page.dart
@@ -446,6 +446,14 @@ class _ContactPageState extends State<ContactPage> {
             idtyCertMeta.issuedCount < Constants().maxByIssuer;
         wotInfo.canCert = canCert;
       }
+
+      // Waiting for Certifications
+      if (you.certsReceived != null &&
+          you.certsReceived!.isNotEmpty &&
+          you.certsReceived!.length <
+              gdevConstants().wot.minCertForMembership) {
+        wotInfo.waitingForCerts = true;
+      }
     }
     return wotInfo;
   }