diff --git a/lib/globals.dart b/lib/globals.dart
index ba6d8d4ccb55dcdbd2d7ca7d3724496af6ceb5f4..991afe78092e7d197b038bcbc77a3697fb27e78f 100644
--- a/lib/globals.dart
+++ b/lib/globals.dart
@@ -46,7 +46,6 @@ Color floattingYellow = const Color(0xffEFEFBF);
 Color backgroundColor = const Color(0xFFF5F5F5);
 
 // Substrate settings
-const int ss58 = 42;
 String currencyName = 'ÄžD';
 
 // Debug
diff --git a/lib/providers/generate_wallets.dart b/lib/providers/generate_wallets.dart
index 6039e535d156257ba98fe076ae0661b5790e8d19..871c177e9846657dabeed3543c4f454e833f46e4 100644
--- a/lib/providers/generate_wallets.dart
+++ b/lib/providers/generate_wallets.dart
@@ -385,19 +385,20 @@ class GenerateWalletsProvider with ChangeNotifier {
     }
 
     for (var derivationNbr in [for (var i = 0; i < numberScan; i += 1) i]) {
-      final addressData = await sub.sdk.api.keyring.addressFromMnemonic(ss58,
+      final addressData = await sub.sdk.api.keyring.addressFromMnemonic(
+          sub.ss58,
           cryptoType: CryptoType.sr25519,
           mnemonic: generatedMnemonic!,
           derivePath: '//$derivationNbr');
 
       final balance = await sub.getBalance(addressData.address!).timeout(
             const Duration(seconds: 1),
-            onTimeout: () => 0,
+            onTimeout: () => {},
           );
       // const balance = 0;
 
       log.d(balance);
-      if (balance != 0) {
+      if (balance != {}) {
         isAlive = true;
         String walletName = scanedWalletNumber == 0
             ? 'currentWallet'.tr()
@@ -426,16 +427,16 @@ class GenerateWalletsProvider with ChangeNotifier {
   }
 
   Future<bool> scanRootBalance(SubstrateSdk sub, int currentChestNumber) async {
-    final addressData = await sub.sdk.api.keyring.addressFromMnemonic(ss58,
+    final addressData = await sub.sdk.api.keyring.addressFromMnemonic(sub.ss58,
         cryptoType: CryptoType.sr25519, mnemonic: generatedMnemonic!);
 
     final balance = await sub.getBalance(addressData.address!).timeout(
           const Duration(seconds: 1),
-          onTimeout: () => 0,
+          onTimeout: () => {},
         );
 
     log.d(balance);
-    if (balance != 0) {
+    if (balance != {}) {
       String walletName = 'myRootWallet'.tr();
       await sub.importAccount(
           mnemonic: '', fromMnemonic: true, password: pin.text);
diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart
index 575d26eaa9de6cb5bfd7d78d7e7a1a4e8816bacd..bf516d47fd4ebd7adec6b7a5b75d3065feb34e28 100644
--- a/lib/providers/substrate_sdk.dart
+++ b/lib/providers/substrate_sdk.dart
@@ -28,10 +28,287 @@ class SubstrateSdk with ChangeNotifier {
   bool isLoadingEndpoint = false;
   String debugConnection = '';
   String transactionStatus = '';
+  int ss58 = 42;
 
   TextEditingController jsonKeystore = TextEditingController();
   TextEditingController keystorePassword = TextEditingController();
 
+  /////////////////////////////////////
+  ////////// 1: API METHODS ///////////
+  /////////////////////////////////////
+
+  Future<String> executeCall(TxInfoData txInfo, txOptions, String password,
+      [String? rawParams]) async {
+    try {
+      final hash = await sdk.api.tx
+          .signAndSend(txInfo, txOptions, password, rawParam: rawParams)
+          .timeout(
+            const Duration(seconds: 12),
+            onTimeout: () => {},
+          );
+      log.d(hash);
+      if (hash.isEmpty) {
+        transactionStatus = 'timeout';
+        notifyListeners();
+
+        return 'timeout';
+      } else {
+        transactionStatus = hash.toString();
+        notifyListeners();
+        return hash.toString();
+      }
+    } catch (e) {
+      transactionStatus = e.toString();
+      notifyListeners();
+      return e.toString();
+    }
+  }
+
+  Future getStorage(String call) async {
+    return await sdk.webView!.evalJavascript('api.query.$call');
+  }
+
+  TxSenderData _setSender() {
+    return TxSenderData(
+      keyring.current.address,
+      keyring.current.pubKey,
+    );
+  }
+
+  ////////////////////////////////////////////
+  ////////// 2: GET ONCHAIN STORAGE //////////
+  ////////////////////////////////////////////
+
+  Future<List<AddressInfo>> getKeyStoreAddress() async {
+    List<AddressInfo> result = [];
+
+    for (var element in keyring.allAccounts) {
+      final account = AddressInfo(address: element.address);
+      final globalBalance = await getBalance(element.address!);
+      account.balance = globalBalance['transferableBalance']!;
+
+      result.add(account);
+    }
+
+    return result;
+  }
+
+  Future<int> getIdentityIndexOf(String address) async {
+    return await getStorage('identity.identityIndexOf("$address")') ?? 0;
+  }
+
+  Future<List<int>> getCerts(String address) async {
+    final idtyIndex = await getIdentityIndexOf(address);
+    final certsReceiver =
+        await getStorage('cert.storageIdtyCertMeta($idtyIndex)') ?? [];
+
+    return [certsReceiver['receivedCount'], certsReceiver['issuedCount']];
+  }
+
+  Future<int> getCertValidityPeriod(String from, String to) async {
+    final idtyIndexFrom = await getIdentityIndexOf(from);
+    final idtyIndexTo = await getIdentityIndexOf(to);
+
+    if (idtyIndexFrom == 0 || idtyIndexTo == 0) return 0;
+
+    final List certData =
+        await getStorage('cert.certsByReceiver($idtyIndexTo)') ?? [];
+
+    if (certData.isEmpty) return 0;
+    for (List certInfo in certData) {
+      if (certInfo[0] == idtyIndexFrom) {
+        return certInfo[1];
+      }
+    }
+
+    return 0;
+  }
+
+  Future<Map<String, dynamic>> getParameters() async {
+    final currencyParameters =
+        await getStorage('parameters.parametersStorage()') ?? {};
+    return currencyParameters;
+  }
+
+  Future<bool> hasAccountConsumers(String address) async {
+    final accountInfo = await getStorage('system.account("$address")');
+    final consumers = accountInfo['consumers'];
+    return consumers == 0 ? false : true;
+  }
+
+  // Future<double> getBalance(String address) async {
+  //   double balance = 0.0;
+
+  //   if (nodeConnected) {
+  //     final brutBalance = await sdk.api.account.queryBalance(address);
+  //     // log.d(brutBalance?.toJson());
+  //     balance = int.parse(brutBalance!.freeBalance) / 100;
+  //   } else {
+  //     balance = -1;
+  //   }
+
+  //   await getUnclaimedUd(address);
+  //   return balance;
+  // }
+
+  Future<Map<String, double>> getBalance(String address) async {
+    if (!nodeConnected) {
+      return {
+        'transferableBalance': 0,
+        'free': 0,
+        'unclaimedUds': 0,
+        'reserved': 0,
+      };
+    }
+
+    // Get onchain storage values
+    final Map balanceGlobal = await getStorage('system.account("$address")');
+    final int? idtyIndex =
+        await getStorage('identity.identityIndexOf("$address")');
+    final Map? idtyData = idtyIndex == null
+        ? null
+        : await getStorage('identity.identities($idtyIndex)');
+    final int currentUdIndex =
+        int.parse(await getStorage('universalDividend.currentUdIndex()'));
+    final List pastReevals =
+        await getStorage('universalDividend.pastReevals()');
+
+    // Compute amount of claimable UDs
+    final int unclaimedUds = _computeUnclaimUds(currentUdIndex,
+        idtyData?['data']?['firstEligibleUd'] ?? 0, pastReevals);
+
+    // Calculate transferable and potential balance
+    final int transferableBalance =
+        (balanceGlobal['data']['free'] + unclaimedUds);
+
+    Map<String, double> finalBalances = {
+      'transferableBalance': transferableBalance / 100,
+      'free': balanceGlobal['data']['free'] / 100,
+      'unclaimedUds': unclaimedUds / 100,
+      'reserved': balanceGlobal['data']['reserved'] / 100,
+    };
+
+    // log.i(finalBalances);
+
+    return finalBalances;
+  }
+
+  int _computeUnclaimUds(
+      int currentUdIndex, int firstEligibleUd, List pastReevals) {
+    int totalAmount = 0;
+
+    if (firstEligibleUd == 0) return 0;
+
+    for (final List reval in pastReevals.reversed) {
+      final int revalNbr = reval[0];
+      final int revalValue = reval[1];
+
+      // Loop each UDs revaluations and sum unclaimed balance
+      if (revalNbr <= firstEligibleUd) {
+        final count = currentUdIndex - firstEligibleUd;
+        totalAmount += count * revalValue;
+        break;
+      } else {
+        final count = currentUdIndex - revalNbr;
+        totalAmount += count * revalValue;
+        currentUdIndex = revalNbr;
+      }
+    }
+
+    return totalAmount;
+  }
+
+  Future<int> getSs58Prefix() async {
+    final List res = await sdk.webView!.evalJavascript(
+            'api.consts.system.ss58Prefix.words',
+            wrapPromise: false) ??
+        [42];
+
+    ss58 = res[0];
+    log.d(ss58);
+    return ss58;
+  }
+
+  Future<bool> isMemberGet(String address) async {
+    return await idtyStatus(address) == 'Validated';
+  }
+
+  Future<String> getMemberAddress() async {
+    // TODOO: Continue digging memberAddress detection
+    String memberAddress = '';
+    walletBox.toMap().forEach((key, value) async {
+      final bool isMember = await isMemberGet(value.address!);
+      log.d(isMember);
+      if (isMember) {
+        final currentChestNumber = configBox.get('currentChest');
+        ChestData newChestData = chestBox.get(currentChestNumber)!;
+        newChestData.memberWallet = value.number;
+        await chestBox.put(currentChestNumber, newChestData);
+        memberAddress = value.address!;
+        return;
+      }
+    });
+    log.d(memberAddress);
+    return memberAddress;
+  }
+
+  Future<Map<String, int>> certState(String from, String to) async {
+    Map<String, int> result = {};
+    if (from != to && await isMemberGet(from)) {
+      final removableOn = await getCertValidityPeriod(from, to);
+      final certMeta = await getCertMeta(from);
+      final int nextIssuableOn = certMeta['nextIssuableOn'] ?? 0;
+      final certRemovableDuration = (removableOn - blocNumber) * 6;
+      const int renewDelay = 2 * 30 * 24 * 3600; // 2 months
+
+      if (certRemovableDuration >= renewDelay) {
+        final certRenewDuration = certRemovableDuration - renewDelay;
+        result.putIfAbsent('certRenewable', () => certRenewDuration);
+      } else if (nextIssuableOn > blocNumber) {
+        final certDelayDuration = (nextIssuableOn - blocNumber) * 6;
+        result.putIfAbsent('certDelay', () => certDelayDuration);
+      } else {
+        result.putIfAbsent('canCert', () => 0);
+      }
+      log.d('tatatatata: ${nextIssuableOn - blocNumber}');
+    }
+
+    return result;
+  }
+
+  Future<Map> getCertMeta(String address) async {
+    var idtyIndex = await getIdentityIndexOf(address);
+
+    final certMeta =
+        await getStorage('cert.storageIdtyCertMeta($idtyIndex)') ?? '';
+
+    return certMeta;
+  }
+
+  Future<String> idtyStatus(String address, [bool smooth = true]) async {
+    var idtyIndex = await getIdentityIndexOf(address);
+
+    if (idtyIndex == 0) {
+      return 'noid';
+    }
+
+    final idtyStatus = await getStorage('identity.identities($idtyIndex)');
+
+    if (idtyStatus != null) {
+      final String status = idtyStatus['status'];
+
+      return (status);
+    } else {
+      return 'expired';
+    }
+  }
+
+  Future getCurencyName() async {}
+
+  /////////////////////////////////////
+  ////// 3: SUBSTRATE CONNECTION //////
+  /////////////////////////////////////
+
   Future<void> initApi() async {
     sdkLoading = true;
     await keyring.init([ss58]);
@@ -43,15 +320,13 @@ class SubstrateSdk with ChangeNotifier {
     notifyListeners();
   }
 
+  String? getConnectedEndpoint() {
+    return sdk.api.connectedNode?.endpoint;
+  }
+
   Future<void> connectNode(BuildContext ctx) async {
     HomeProvider homeProvider = Provider.of<HomeProvider>(ctx, listen: false);
 
-    // var connectivityResult = await (Connectivity().checkConnectivity());
-    // if (connectivityResult == ConnectivityResult.mobile ||
-    //     connectivityResult == ConnectivityResult.wifi) {
-    //   _homeProvider.changeMessage("Vous n'êtes pas connecté à internet", 0);
-    //   return;
-    // }
     homeProvider.changeMessage("connectionPending".tr(), 0);
 
     // configBox.delete('customEndpoint');
@@ -60,31 +335,8 @@ class SubstrateSdk with ChangeNotifier {
             ? [getDuniterCustomEndpoint()]
             : getDuniterBootstrap();
 
-    // final nodes = getDuniterBootstrap();
-
     int timeout = 10000;
 
-    // if (n.endpoint!.startsWith('ws://')) {
-    //   timeout = 5000;
-    // }
-
-    //// Check websocket conenction - only for wss
-    // final channel = IOWebSocketChannel.connect(
-    //   Uri.parse('wss://192.168.1.72:9944'),
-    // );
-
-    // channel.stream.listen(
-    //   (dynamic message) {
-    //     log.d('message $message');
-    //   },
-    //   onDone: () {
-    //     log.d('ws channel closed');
-    //   },
-    //   onError: (error) {
-    //     log.d('ws error $error');
-    //   },
-    // );
-
     if (sdk.api.connectedNode?.endpoint != null) {
       await sdk.api.setting.unsubscribeBestNumber();
     }
@@ -99,6 +351,7 @@ class SubstrateSdk with ChangeNotifier {
     notifyListeners();
     if (res != null) {
       nodeConnected = true;
+      // await getSs58Prefix();
 
       // Subscribe bloc number
       sdk.api.setting.subscribeBestNumber((res) {
@@ -197,7 +450,7 @@ class SubstrateSdk with ChangeNotifier {
       notifyListeners();
     });
     if (json == null) return '';
-    log.d(json);
+    // log.d(json);
     try {
       await sdk.api.keyring.addAccount(
         keyring,
@@ -205,7 +458,6 @@ class SubstrateSdk with ChangeNotifier {
         acc: json,
         password: password,
       );
-      // Clipboard.setData(ClipboardData(text: jsonEncode(acc.toJson())));
     } catch (e) {
       log.e(e);
       importIsLoading = false;
@@ -218,91 +470,9 @@ class SubstrateSdk with ChangeNotifier {
     return keyring.allAccounts.last.address!;
   }
 
-  void reload() {
-    notifyListeners();
-  }
-
-  Future<List<AddressInfo>> getKeyStoreAddress() async {
-    List<AddressInfo> result = [];
-
-    // sdk.api.account.unsubscribeBalance();
-    for (var element in keyring.allAccounts) {
-      // Clipboard.setData(ClipboardData(text: jsonEncode(element)));
-      final account = AddressInfo(address: element.address);
-      // await sdk.api.account.subscribeBalance(element.address, (p0) {
-      //   account.balance = int.parse(p0.freeBalance) / 100;
-      // });
-      // sdk.api.setting.unsubscribeBestNumber();
-      account.balance = await getBalance(element.address!);
-      result.add(account);
-    }
-
-    return result;
-  }
-
-  Future<List<int>> getCerts(String address) async {
-    final idtyIndex = await sdk.webView!
-        .evalJavascript('api.query.identity.identityIndexOf("$address")');
-    // log.d('u32: ' + idtyIndex.toString());
-
-    final certsReceiver = await sdk.webView!
-            .evalJavascript('api.query.cert.storageIdtyCertMeta($idtyIndex)') ??
-        [];
-
-    return [certsReceiver['receivedCount'], certsReceiver['issuedCount']];
-  }
-
-  Future<Map> getCertData(String from, String to) async {
-    final idtyIndexFrom = await sdk.webView!
-        .evalJavascript('api.query.identity.identityIndexOf("$from")');
-
-    final idtyIndexTo = await sdk.webView!
-        .evalJavascript('api.query.identity.identityIndexOf("$to")');
-
-    if (idtyIndexFrom == null || idtyIndexTo == null) return {};
-
-    final certData = await sdk.webView!.evalJavascript(
-            'api.query.cert.storageCertsByIssuer($idtyIndexFrom, $idtyIndexTo)') ??
-        '';
-
-    if (certData == '') return {};
-
-    // log.d(_certData);
-    return certData;
-  }
-
-  Future<bool> hasAccountConsumers(String address) async {
-    final accountInfo = await sdk.webView!
-        .evalJavascript('api.query.system.account("$address")');
-    final consumers = accountInfo['consumers'];
-    // log.d('Consumers: $_consumers');
-    return consumers == 0 ? false : true;
-  }
-
-  Future<double> getBalance(String address, {bool isUd = false}) async {
-    double balance = 0.0;
-
-    // log.d('nodeConnected: ' + nodeConnected.toString());
-    if (nodeConnected) {
-      final brutBalance = await sdk.api.account.queryBalance(address);
-      balance = int.parse(brutBalance!.freeBalance) / 100;
-    } else {
-      balance = -1;
-    }
-    return balance;
-  }
-
-  Future<double> subscribeBalance(String address, {bool isUd = false}) async {
-    double balance = 0.0;
-    if (nodeConnected) {
-      await sdk.api.account.subscribeBalance(address, (balanceData) {
-        balance = int.parse(balanceData.freeBalance) / 100;
-        notifyListeners();
-      });
-    }
-
-    return balance;
-  }
+  //////////////////////////////////
+  /////// 4: CRYPTOGRAPHY //////////
+  //////////////////////////////////
 
   KeyPairData getKeypair(String address) {
     return keyring.keyPairs.firstWhere((kp) => kp.address == address,
@@ -311,7 +481,6 @@ class SubstrateSdk with ChangeNotifier {
 
   Future<bool> checkPassword(String address, String pass) async {
     final account = getKeypair(address);
-    // log.d(account.address);
 
     return await sdk.api.keyring.checkPassword(account, pass);
   }
@@ -367,8 +536,6 @@ class SubstrateSdk with ChangeNotifier {
     final gen = await sdk.api.keyring.generateMnemonic(ss58);
     generatedMnemonic = gen.mnemonic!;
 
-    // final res = await importAccount(fromMnemonic: true);
-    // await Clipboard.setData(ClipboardData(text: generatedMnemonic));
     return gen.mnemonic!;
   }
 
@@ -396,75 +563,99 @@ class SubstrateSdk with ChangeNotifier {
     }
   }
 
+  Future<String> derive(
+      BuildContext context, String address, int number, String password) async {
+    final keypair = getKeypair(address);
+
+    final seedMap =
+        await keyring.store.getDecryptedSeed(keypair.pubKey, password);
+
+    if (seedMap?['type'] != 'mnemonic') return '';
+    final List seedList = seedMap!['seed'].split('//');
+    generatedMnemonic = seedList[0];
+
+    return await importAccount(
+        mnemonic: generatedMnemonic,
+        fromMnemonic: true,
+        derivePath: '//$number',
+        password: password);
+  }
+
+  Future<String> generateRootKeypair(String address, String password) async {
+    final keypair = getKeypair(address);
+
+    final seedMap =
+        await keyring.store.getDecryptedSeed(keypair.pubKey, password);
+
+    if (seedMap?['type'] != 'mnemonic') return '';
+    final List seedList = seedMap!['seed'].split('//');
+    generatedMnemonic = seedList[0];
+
+    return await importAccount(fromMnemonic: true, password: password);
+  }
+
+  Future<bool> isMnemonicValid(String mnemonic) async {
+    // Needed for bad encoding of UTF-8
+    mnemonic = mnemonic.replaceAll('é', 'é');
+    mnemonic = mnemonic.replaceAll('è', 'è');
+
+    return await sdk.api.keyring.checkMnemonicValid(mnemonic);
+  }
+
+  //////////////////////////////////////
+  ///////// 5: CALLS EXECUTION /////////
+  //////////////////////////////////////
+
   Future<String> pay(
       {required String fromAddress,
       required String destAddress,
       required double amount,
       required String password}) async {
     transactionStatus = '';
-
-    // setCurrentWallet(fromAddress);
-
-    log.d(keyring.current.address);
-    log.d(fromAddress);
-    log.d(password);
-    // log.d(await checkPassword(fromAddress, password));
-
     final fromPubkey = await sdk.api.account.decodeAddress([fromAddress]);
-    log.d(fromPubkey!.keys.first);
+    final int amountUnit = (amount * 100).toInt();
+
     final sender = TxSenderData(
       fromAddress,
-      fromPubkey.keys.first,
+      fromPubkey!.keys.first,
     );
-    final txInfo = TxInfoData(
-        'balances', amount == -1 ? 'transferAll' : 'transferKeepAlive', sender);
 
-    final int amountUnit = (amount * 100).toInt();
-    try {
-      final hash = await sdk.api.tx.signAndSend(
-        txInfo,
-        [destAddress, amount == -1 ? false : amountUnit],
-        password,
-        onStatusChange: (status) {
-          log.d('Transaction status: $status');
-          transactionStatus = status;
-          notifyListeners();
-        },
-      ).timeout(
-        const Duration(seconds: 12),
-        onTimeout: () => {},
+    final globalBalance = await getBalance(fromAddress);
+    TxInfoData txInfo;
+    List txOptions = [];
+    String? rawParams;
+
+    if (globalBalance['unclaimedUds'] == 0) {
+      txInfo = TxInfoData('balances',
+          amount == -1 ? 'transferAll' : 'transferKeepAlive', sender);
+      txOptions = [destAddress, amount == -1 ? false : amountUnit];
+    } else {
+      txInfo = TxInfoData(
+        'utility',
+        'batchAll',
+        sender,
       );
-      log.d(hash.toString());
-      if (hash.isEmpty) {
-        transactionStatus = 'timeout';
-        notifyListeners();
+      const tx1 = 'api.tx.universalDividend.claimUds()';
+      final tx2 = amount == -1
+          ? 'api.tx.balances.transferAll(false)'
+          : 'api.tx.balances.transferKeepAlive("$destAddress", $amountUnit)';
 
-        return 'timeout';
-      } else {
-        transactionStatus = hash.toString();
-        notifyListeners();
-        return hash.toString();
-      }
-    } catch (e) {
-      transactionStatus = e.toString();
-      notifyListeners();
-      return e.toString();
+      rawParams = '[[$tx1, $tx2]]';
     }
+
+    // log.d('pay args:  ${txInfo.module}, ${txInfo.call}, $txOptions, $rawParams');
+    return await executeCall(txInfo, txOptions, password, rawParams);
   }
 
   Future<String> certify(
       String fromAddress, String password, String toAddress) async {
     transactionStatus = '';
 
-    // setCurrentWallet(fromAddress);
-    log.d('me: $fromAddress');
-    log.d('to: $toAddress');
-
     final myIdtyStatus = await idtyStatus(fromAddress);
     final toIdtyStatus = await idtyStatus(toAddress);
 
-    log.d(myIdtyStatus);
-    log.d(toIdtyStatus);
+    final fromIndex = await getIdentityIndexOf(fromAddress);
+    final toIndex = await getIdentityIndexOf(toAddress);
 
     if (myIdtyStatus != 'Validated') {
       transactionStatus = 'notMember';
@@ -472,11 +663,13 @@ class SubstrateSdk with ChangeNotifier {
       return 'notMember';
     }
 
-    final sender = TxSenderData(
-      keyring.current.address,
-      keyring.current.pubKey,
-    );
+    final sender = _setSender();
     TxInfoData txInfo;
+    List txOptions = [];
+    String? rawParams;
+
+    final toCerts = await getCerts(toAddress);
+    final currencyParameters = await getParameters();
 
     if (toIdtyStatus == 'noid') {
       txInfo = TxInfoData(
@@ -484,13 +677,29 @@ class SubstrateSdk with ChangeNotifier {
         'createIdentity',
         sender,
       );
+      txOptions = [toAddress];
     } else if (toIdtyStatus == 'Validated' ||
         toIdtyStatus == 'ConfirmedByOwner') {
-      txInfo = TxInfoData(
-        'cert',
-        'addCert',
-        sender,
-      );
+      if (toCerts[0] >= currencyParameters['wotMinCertForMembership'] &&
+          toIdtyStatus != 'Validated') {
+        log.i('Batch cert and membership validation');
+        txInfo = TxInfoData(
+          'utility',
+          'batchAll',
+          sender,
+        );
+        final tx1 = 'cert.addCert($fromIndex, $toIndex)';
+        final tx2 = 'identity.validateIdentity($toIndex)';
+
+        rawParams = '[[$tx1, $tx2]]';
+      } else {
+        txInfo = TxInfoData(
+          'cert',
+          'addCert',
+          sender,
+        );
+        txOptions = [fromIndex, toIndex];
+      }
     } else {
       transactionStatus = 'cantBeCert';
       notifyListeners();
@@ -498,63 +707,26 @@ class SubstrateSdk with ChangeNotifier {
     }
 
     log.d('Cert action: ${txInfo.call!}');
-
-    try {
-      final hash = await sdk.api.tx
-          .signAndSend(
-            txInfo,
-            [toAddress],
-            password,
-          )
-          .timeout(
-            const Duration(seconds: 12),
-            onTimeout: () => {},
-          );
-      log.d(hash);
-      if (hash.isEmpty) {
-        transactionStatus = 'timeout';
-        notifyListeners();
-
-        return 'timeout';
-      } else {
-        transactionStatus = hash.toString();
-        notifyListeners();
-        return hash.toString();
-      }
-    } catch (e) {
-      transactionStatus = e.toString();
-      notifyListeners();
-      return e.toString();
-    }
+    return await executeCall(txInfo, txOptions, password, rawParams);
   }
 
-  Future<String> idtyStatus(String address, [bool smooth = true]) async {
-    //   var tata = await sdk.webView!
-    //       .evalJavascript('api.query.system.account("$address")');
-
-    var idtyIndex = await sdk.webView!
-        .evalJavascript('api.query.identity.identityIndexOf("$address")');
-
-    if (idtyIndex == null) {
-      return 'noid';
-    }
+  // Future claimUDs(String password) async {
+  //   final sender = TxSenderData(
+  //     keyring.current.address,
+  //     keyring.current.pubKey,
+  //   );
 
-    final idtyStatus = await sdk.webView!
-        .evalJavascript('api.query.identity.identities($idtyIndex)');
+  //   final txInfo = TxInfoData(
+  //     'universalDividend',
+  //     'claimUds',
+  //     sender,
+  //   );
 
-    if (idtyStatus != null) {
-      final String status = idtyStatus['status'];
-      // log.d('Status $address: $_status');
-      return (status);
-    } else {
-      return 'expired';
-    }
-  }
+  //   return await executeCall(txInfo, [], password);
+  // }
 
   Future<String> confirmIdentity(
       String fromAddress, String name, String password) async {
-    // Confirm identity
-    // setCurrentWallet(fromAddress);
     log.d('me: ${keyring.current.address!}');
 
     final sender = TxSenderData(
@@ -567,102 +739,13 @@ class SubstrateSdk with ChangeNotifier {
       'confirmIdentity',
       sender,
     );
+    final txOptions = [name];
 
-    try {
-      final hash = await sdk.api.tx.signAndSend(
-        txInfo,
-        [name],
-        password,
-        onStatusChange: (status) {
-          log.d('Transaction status: $status');
-          transactionStatus = status;
-          notifyListeners();
-        },
-      ).timeout(
-        const Duration(seconds: 12),
-        onTimeout: () => {},
-      );
-      log.d(hash);
-      if (hash.isEmpty) {
-        transactionStatus = 'timeout';
-        notifyListeners();
-
-        return 'timeout';
-      } else {
-        transactionStatus = hash.toString();
-        notifyListeners();
-        return hash.toString();
-      }
-    } on Exception catch (e) {
-      log.e(e);
-      transactionStatus = e.toString();
-      notifyListeners();
-      return e.toString();
-    }
-  }
-
-  Future<bool> isMemberGet(String address) async {
-    return await idtyStatus(address) == 'Validated';
-  }
-
-  Future<String> getMemberAddress() async {
-    // TODOO: Continue digging memberAddress detection
-    String memberAddress = '';
-    walletBox.toMap().forEach((key, value) async {
-      final bool isMember = await isMemberGet(value.address!);
-      log.d(isMember);
-      if (isMember) {
-        final currentChestNumber = configBox.get('currentChest');
-        ChestData newChestData = chestBox.get(currentChestNumber)!;
-        newChestData.memberWallet = value.number;
-        await chestBox.put(currentChestNumber, newChestData);
-        memberAddress = value.address!;
-        return;
-      }
-    });
-    log.d(memberAddress);
-    return memberAddress;
-  }
-
-  Future<Map<String, int>> certState(String from, String to) async {
-    Map<String, int> result = {};
-    if (from != to && await isMemberGet(from)) {
-      final certData = await getCertData(from, to);
-      final certMeta = await getCertMeta(from);
-      final int removableOn = certData['removableOn'] ?? 0;
-      final int nextIssuableOn = certMeta['nextIssuableOn'] ?? 0;
-      final certRemovableDuration = (removableOn - blocNumber) * 6;
-      const int renewDelay = 2 * 30 * 24 * 3600; // 2 months
-
-      if (certRemovableDuration >= renewDelay) {
-        final certRenewDuration = certRemovableDuration - renewDelay;
-        result.putIfAbsent('certRenewable', () => certRenewDuration);
-      } else if (nextIssuableOn > blocNumber) {
-        final certDelayDuration = (nextIssuableOn - blocNumber) * 6;
-        result.putIfAbsent('certDelay', () => certDelayDuration);
-      } else {
-        result.putIfAbsent('canCert', () => 0);
-      }
-    }
-    return result;
-  }
-
-  Future<Map> getCertMeta(String address) async {
-    var idtyIndex = await sdk.webView!
-        .evalJavascript('api.query.identity.identityIndexOf("$address")');
-
-    final certMeta = await sdk.webView!
-            .evalJavascript('api.query.cert.storageIdtyCertMeta($idtyIndex)') ??
-        '';
-    // if (_certMeta['nextIssuableOn'] != 0) return {};
-
-    // log.d(_certMeta);
-    return certMeta;
+    return await executeCall(txInfo, txOptions, password);
   }
 
   Future revokeIdentity(String address, String password) async {
-    final idtyIndex = await sdk.webView!
-        .evalJavascript('api.query.identity.identityIndexOf("$address")');
+    final idtyIndex = await getIdentityIndexOf(address);
 
     final sender = TxSenderData(
       keyring.current.address,
@@ -678,81 +761,20 @@ class SubstrateSdk with ChangeNotifier {
       sender,
     );
 
-    try {
-      final hash = await sdk.api.tx
-          .signAndSend(
-            txInfo,
-            [idtyIndex],
-            password,
-          )
-          .timeout(
-            const Duration(seconds: 12),
-            onTimeout: () => {},
-          );
-      log.d(hash);
-      if (hash.isEmpty) {
-        transactionStatus = 'timeout';
-        notifyListeners();
+    final txOptions = [idtyIndex];
 
-        return 'timeout';
-      } else {
-        transactionStatus = hash.toString();
-        notifyListeners();
-        return hash.toString();
-      }
-    } catch (e) {
-      transactionStatus = e.toString();
-      notifyListeners();
-      return e.toString();
-    }
+    return await executeCall(txInfo, txOptions, password);
   }
 
-  Future getCurencyName() async {}
-
-  Future<String> derive(
-      BuildContext context, String address, int number, String password) async {
-    final keypair = getKeypair(address);
-
-    final seedMap =
-        await keyring.store.getDecryptedSeed(keypair.pubKey, password);
-
-    if (seedMap?['type'] != 'mnemonic') return '';
-    final List seedList = seedMap!['seed'].split('//');
-    generatedMnemonic = seedList[0];
-
-    return await importAccount(
-        mnemonic: generatedMnemonic,
-        fromMnemonic: true,
-        derivePath: '//$number',
-        password: password);
-  }
-
-  Future<String> generateRootKeypair(String address, String password) async {
-    final keypair = getKeypair(address);
-
-    final seedMap =
-        await keyring.store.getDecryptedSeed(keypair.pubKey, password);
-
-    if (seedMap?['type'] != 'mnemonic') return '';
-    final List seedList = seedMap!['seed'].split('//');
-    generatedMnemonic = seedList[0];
-
-    return await importAccount(fromMnemonic: true, password: password);
-  }
-
-  Future<bool> isMnemonicValid(String mnemonic) async {
-    // Needed for bad encoding of UTF-8
-    mnemonic = mnemonic.replaceAll('é', 'é');
-    mnemonic = mnemonic.replaceAll('è', 'è');
-
-    return await sdk.api.keyring.checkMnemonicValid(mnemonic);
-  }
-
-  String? getConnectedEndpoint() {
-    return sdk.api.connectedNode?.endpoint;
+  void reload() {
+    notifyListeners();
   }
 }
 
+////////////////////////////////////////////
+/////// 6: UI ELEMENTS (off class) /////////
+////////////////////////////////////////////
+
 void snack(BuildContext context, String message, {int duration = 2}) {
   final snackBar =
       SnackBar(content: Text(message), duration: Duration(seconds: duration));
diff --git a/lib/providers/wallet_options.dart b/lib/providers/wallet_options.dart
index 3aa3bb99ecfdc1247746d1c3d334d30e95c680f5..fa0c42141ed9bc72d9e8c8e248e07bdcaeba2552 100644
--- a/lib/providers/wallet_options.dart
+++ b/lib/providers/wallet_options.dart
@@ -56,7 +56,7 @@ class WalletOptionsProvider with ChangeNotifier {
     if (answer ?? false) {
       //Check if balance is null
       final balance = await sub.getBalance(wallet.address!);
-      if (balance != 0) {
+      if (balance != {}) {
         MyWalletsProvider myWalletProvider =
             Provider.of<MyWalletsProvider>(context, listen: false);
         final defaultWallet = myWalletProvider.getDefaultWallet();
@@ -531,9 +531,10 @@ Widget balance(BuildContext context, String address, double size,
     Consumer<SubstrateSdk>(builder: (context, sdk, _) {
       return FutureBuilder(
           future: sdk.getBalance(address),
-          builder: (BuildContext context, AsyncSnapshot<double> balance) {
-            if (balance.connectionState != ConnectionState.done ||
-                balance.hasError) {
+          builder: (BuildContext context,
+              AsyncSnapshot<Map<String, double>> globalBalance) {
+            if (globalBalance.connectionState != ConnectionState.done ||
+                globalBalance.hasError) {
               if (balanceCache[address] != null &&
                   balanceCache[address] != -1) {
                 return Text(
@@ -551,7 +552,7 @@ Widget balance(BuildContext context, String address, double size,
                 );
               }
             }
-            balanceCache[address] = balance.data!;
+            balanceCache[address] = globalBalance.data!['transferableBalance']!;
             if (balanceCache[address] != -1) {
               return Text(
                 "${balanceCache[address]!.toString()} $currencyName",
diff --git a/lib/screens/myWallets/wallet_options.dart b/lib/screens/myWallets/wallet_options.dart
index c038376171921e9ff72383704ea49860dd58d874..8c6b7848f23e2504f10bed58ba9dcc12a8cb450b 100644
--- a/lib/screens/myWallets/wallet_options.dart
+++ b/lib/screens/myWallets/wallet_options.dart
@@ -457,12 +457,15 @@ class WalletOptions extends StatelessWidget {
     SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
     MyWalletsProvider myWalletProvider =
         Provider.of<MyWalletsProvider>(context, listen: false);
+    WalletOptionsProvider walletOptions =
+        Provider.of<WalletOptionsProvider>(context, listen: false);
 
     // WalletData defaultWallet = _myWalletProvider.getDefaultWallet()!;
     // defaultWallet = wallet;
     await sub.setCurrentWallet(wallet);
     myWalletProvider.readAllWallets(currentChest);
     myWalletProvider.rebuildWidget();
+    walletOptions.reloadBuild();
   }
 
   Widget deleteWallet(BuildContext context,
diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart
index c5611f269063908bcb15f91188d8cdfd5d31b988..b3e871526927bcaa8512e59a7cfe3d90cdd159dc 100644
--- a/lib/screens/settings.dart
+++ b/lib/screens/settings.dart
@@ -77,16 +77,14 @@ class SettingsScreen extends StatelessWidget {
         sub.getConnectedEndpoint() ?? duniterBootstrapNodes.first.endpoint;
 
     final customEndpoint = NetworkParams();
-    customEndpoint.name = currencyName;
     customEndpoint.endpoint = 'Personnalisé';
-    customEndpoint.ss58 = ss58;
-
+    final localEndpoint = NetworkParams();
+    localEndpoint.endpoint = 'ws://127.0.0.1:9944';
     final automaticEndpoint = NetworkParams();
-    automaticEndpoint.name = currencyName;
     automaticEndpoint.endpoint = 'Auto';
-    automaticEndpoint.ss58 = ss58;
     // duniterBootstrapNodes.add(_sub.getDuniterCustomEndpoint());
     duniterBootstrapNodes.insert(0, automaticEndpoint);
+    duniterBootstrapNodes.add(localEndpoint);
     duniterBootstrapNodes.add(customEndpoint);
 
     if (configBox.get('autoEndpoint') == true) {
diff --git a/lib/screens/wallet_view.dart b/lib/screens/wallet_view.dart
index 84a0d748e7cc7036905b17ca417667d84cc87c03..7d2c5cb2200423cb309cd08c5160f5db9353ac01 100644
--- a/lib/screens/wallet_view.dart
+++ b/lib/screens/wallet_view.dart
@@ -129,6 +129,9 @@ class WalletViewScreen extends StatelessWidget {
                   builder: (context, AsyncSnapshot<Map<String, int>> snapshot) {
                     if (snapshot.data == null) return const SizedBox();
                     String duration = '';
+                    log.d('certDelay ${snapshot.data!['certDelay']}');
+                    log.d('certRenewable ${snapshot.data!['certRenewable']}');
+
                     if (snapshot.data!['certDelay'] != null ||
                         snapshot.data!['certRenewable'] != null) {
                       final Duration durationSeconds = Duration(
@@ -515,10 +518,11 @@ class WalletViewScreen extends StatelessWidget {
                                     future:
                                         sub.getBalance(defaultWallet.address!),
                                     builder: (BuildContext context,
-                                        AsyncSnapshot<double> balance) {
-                                      if (balance.connectionState !=
+                                        AsyncSnapshot<Map<String, double>>
+                                            globalBalance) {
+                                      if (globalBalance.connectionState !=
                                               ConnectionState.done ||
-                                          balance.hasError) {
+                                          globalBalance.hasError) {
                                         if (balanceCache[
                                                 defaultWallet.address!] !=
                                             null) {
@@ -539,7 +543,8 @@ class WalletViewScreen extends StatelessWidget {
                                         }
                                       }
                                       balanceCache[defaultWallet.address!] =
-                                          balance.data!;
+                                          globalBalance
+                                              .data!['transferableBalance']!;
                                       return Text(
                                         "${balanceCache[defaultWallet.address!]} $currencyName",
                                         style: const TextStyle(
diff --git a/pubspec.yaml b/pubspec.yaml
index 1475c8951d963c7802df40b3bcd0080b84af522c..e238544098a948c29c60255f1a081564e174464f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -5,7 +5,7 @@ description: Pay with G1.
 # pub.dev using `pub publish`. This is preferred for private packages.
 publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 
-version: 0.0.9+16
+version: 0.0.9+18
 
 environment:
   sdk: '>=2.12.0 <3.0.0'
@@ -60,7 +60,7 @@ dependencies:
   desktop_window: ^0.4.0
   durt: ^0.1.6
   package_info_plus: ^1.4.2
-  polkawallet_sdk: #^0.4.8
+  polkawallet_sdk: #^0.4.9
     git:
       url: https://github.com/poka-IT/sdk.git
       ref: gecko-old