diff --git a/package.json b/package.json
index 9da95a4a31f16b19bbf7a8b763463f978de48b91..e2cbe845634233b6c389514b009691f14ee6b286 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
     "@capacitor/haptics": "4.0.1",
     "@capacitor/keyboard": "4.0.1",
     "@capacitor/status-bar": "4.0.1",
+    "@capacitor-community/sqlite": "^4.0.1",
     "@ionic/angular": "^6.2.4",
     "@ionic/storage-angular": "^3.0.6",
     "@ngx-translate/core": "^14.0.0",
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 90f9f03cde8dbfecea3c4d76962f0c56fb0cb9dc..033bc58bcb495812ab8482081e13454349bb3a3c 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,4 +1,4 @@
-import { Component } from '@angular/core';
+import {Component} from '@angular/core';
 import {PlatformService} from "./shared/services/platform.service";
 import {environment} from "@environments/environment";
 
@@ -28,8 +28,11 @@ export class AppComponent {
   }
 
   async start() {
+    var now = Date.now();
     console.info('[app] Starting...');
+
     await this.platform.start();
-    console.info('[app] Starting [OK]');
+
+    console.info(`[app] Starting [OK] in ${Date.now()-now}ms`);
   }
 }
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 15e6be2447bb533b7d9e73902b8ba1fb4a041d79..ac23ccd9c258906a872b2d1e22d02022dc99bf7a 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -2,7 +2,7 @@ import {NgModule} from '@angular/core';
 import {BrowserModule} from '@angular/platform-browser';
 import {RouteReuseStrategy} from '@angular/router';
 
-import {IonicModule, IonicRouteStrategy, Platform} from '@ionic/angular';
+import {IonicModule, IonicRouteStrategy} from '@ionic/angular';
 
 import {AppComponent} from './app.component';
 import {AppRoutingModule} from './app-routing.module';
@@ -11,14 +11,15 @@ import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
 import {HttpClient, HttpClientModule} from "@angular/common/http";
 import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
 import {TranslateHttpLoader} from '@ngx-translate/http-loader';
-import {IonicStorageModule, Storage} from '@ionic/storage-angular';
+import {IonicStorageModule} from '@ionic/storage-angular';
 import {environment} from "@environments/environment";
 import {AppSharedModule} from "@app/shared/shared.module";
 import {APP_BASE_HREF} from "@angular/common";
 import {JDENTICON_CONFIG} from "ngx-jdenticon";
 import {APP_LOCALES} from "@app/settings/settings.model";
-import {APP_STORAGE} from "@app/shared/services/storage/storage.interface";
+import {APP_STORAGE} from "@app/shared/services/storage/storage.utils";
 import {StorageService} from "@app/shared/services/storage/storage.service";
+import {Drivers} from "@ionic/storage";
 
 export function createTranslateLoader(http: HttpClient) {
   return new TranslateHttpLoader(http, './assets/i18n/', '.json');
@@ -48,11 +49,11 @@ export function createTranslateLoader(http: HttpClient) {
       }),
     ],
     providers: [
-      { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
-      { provide: PlatformService, useClass: PlatformService },
-      { provide: StorageService, useClass: StorageService, deps: [Platform, Storage] },
-      { provide: APP_STORAGE, useExisting: StorageService },
+      PlatformService,
+      StorageService,
 
+      {provide: RouteReuseStrategy, useClass: IonicRouteStrategy},
+      {provide: APP_STORAGE, useExisting: StorageService},
       {provide: APP_BASE_HREF, useValue: (environment.baseUrl || '/')},
 
       {
diff --git a/src/app/auth/auth.model.ts b/src/app/auth/auth.model.ts
index f035217c3351b711425e6e774503d138bd6abf11..76fea7202d3983e93219a5345ed21c09b94db6bd 100644
--- a/src/app/auth/auth.model.ts
+++ b/src/app/auth/auth.model.ts
@@ -1,9 +1,14 @@
+import {AccountMeta} from "@app/wallet/account.model";
+
 export interface AuthData {
 
+  address?: string;
   password?: string;
 
   v1?: {
     salt: string;
     password: string;
   }
+
+  meta?: AccountMeta;
 }
diff --git a/src/app/home/home.page.html b/src/app/home/home.page.html
index 20666050d9055f6871dbadcb2181b94115aba86a..002315884f26cf0ebe9bba5416e7bef71a670a50 100644
--- a/src/app/home/home.page.html
+++ b/src/app/home/home.page.html
@@ -45,18 +45,39 @@
           </ng-template>
         </ion-card-title>
       </ion-card-header>
-      <ion-card-content>
-
-        <!-- register -->
-        <ion-button id="open-register-modal"  expand="block">
-          <ion-label translate>LOGIN.CREATE_FREE_ACCOUNT</ion-label>
-        </ion-button>
-
-        <!-- login -->
-        <p class="ion-padding-top" translate>LOGIN.HAVE_ACCOUNT_QUESTION</p>
-        <ion-button id="open-auth-modal" color="light" expand="block">
-          <ion-label translate>COMMON.BTN_LOGIN</ion-label>
-        </ion-button>
+      <ion-card-content *ngIf="!loading" @fadeInAnimation>
+
+        <ng-container *ngIf="isLogin; else noAccount">
+          <!-- my account -->
+          <ion-button expand="block" [routerLink]="'/wallet'">
+            <ion-icon name="person" slot="start"></ion-icon>
+            <ion-label translate>MENU.ACCOUNT</ion-label>
+          </ion-button>
+
+          <!-- disconnect button -->
+          <p [class.cdk-visually-hidden]="mobile">
+            <ion-text [innerHTML]="'HOME.NOT_YOUR_ACCOUNT_QUESTION' | translate: {pubkey: (defaultAccount|accountName) }"></ion-text>
+            <br/>
+            <ion-text>
+              <a href="#" (click)="logout($event)">
+                <span translate>HOME.BTN_CHANGE_ACCOUNT</span>
+              </a>
+            </ion-text>
+          </p>
+        </ng-container>
+
+        <ng-template #noAccount>
+          <!-- register -->
+          <ion-button expand="block"  (click)="register($event)">
+            <ion-label translate>LOGIN.CREATE_FREE_ACCOUNT</ion-label>
+          </ion-button>
+
+          <!-- login -->
+          <p class="ion-padding-top" translate>LOGIN.HAVE_ACCOUNT_QUESTION</p>
+          <ion-button color="light" expand="block" (click)="login()">
+            <ion-label translate>COMMON.BTN_LOGIN</ion-label>
+          </ion-button>
+        </ng-template>
       </ion-card-content>
     </ion-card>
 
@@ -75,7 +96,6 @@
   </ng-template>
 </ion-modal>
 
-
 <ion-modal
   #registerModal
   trigger="open-register-modal"
diff --git a/src/app/home/home.page.ts b/src/app/home/home.page.ts
index 7ef430f021be443db33e4cc9b917aea505023ec9..6d53756b942b4e073aa3f2ddf5878baaa683e79e 100644
--- a/src/app/home/home.page.ts
+++ b/src/app/home/home.page.ts
@@ -1,30 +1,43 @@
-import {Component, Inject, Injector, OnInit} from '@angular/core';
+import {Component, Inject, Injector, OnInit, ViewChild} from '@angular/core';
 import {SettingsService} from "@app/settings/settings.service";
 import {APP_LOCALES, LocaleConfig, Settings} from "@app/settings/settings.model";
 import {BasePage} from "@app/shared/pages/base.page";
 import {NetworkService} from "@app/network/network.service";
 import {AbbreviatePipe} from "@app/shared/pipes/string.pipes";
+import {AccountService} from "@app/wallet/account.service";
+import {Account} from "@app/wallet/account.model";
+import {fadeInAnimation} from "@app/shared/animations";
+import {AuthModal} from "@app/auth/auth.modal";
+import {RegisterModal} from "@app/register/register.modal";
+import {IonModal} from "@ionic/angular";
+import {Router} from "@angular/router";
 
 @Component({
   selector: 'app-home',
   templateUrl: './home.page.html',
-  styleUrls: ['./home.page.scss']
+  styleUrls: ['./home.page.scss'],
+  animations: [fadeInAnimation]
 })
 export class HomePage extends BasePage<Settings> implements OnInit {
 
   currency: string = null;
 
+  defaultAccount: Account = null;
+  get isLogin(): boolean {
+    return this.accountService.isLogin
+  }
+
+  @ViewChild('authModal') authModal: IonModal;
+  @ViewChild('registerModal') registerModal: IonModal;
+
   constructor(
     injector: Injector,
-    @Inject(APP_LOCALES) public locales: LocaleConfig[],
-    public networkService: NetworkService
+    public networkService: NetworkService,
+    public accountService: AccountService,
+    public router: Router,
+    @Inject(APP_LOCALES) public locales: LocaleConfig[]
   ) {
     super(injector, {name: 'home'})
-
-  }
-
-  ngOnInit() {
-    super.ngOnInit();
   }
 
   protected async ngOnLoad(): Promise<Settings> {
@@ -33,6 +46,14 @@ export class HomePage extends BasePage<Settings> implements OnInit {
 
     this.currency = this.networkService.currency.name;
 
+    // Load account
+    await this.accountService.ready();
+    if (this.accountService.isLogin) {
+      this.defaultAccount = await this.accountService.getDefault();
+    }
+    else {
+      this.defaultAccount = null;
+    }
 
     return this.settings.clone();
   }
@@ -43,4 +64,25 @@ export class HomePage extends BasePage<Settings> implements OnInit {
     this.data.locale = locale;
     this.markForCheck();
   }
+
+  login(event) {
+    return this.authModal.present();
+  }
+
+  async register(event) {
+    await this.registerModal.present();
+
+    const {data} = await this.registerModal.onWillDismiss();
+
+    if (data?.address) {
+      this.defaultAccount = data;
+      setTimeout(() => this.router.navigateByUrl('/wallet/' + data.address));
+    }
+  }
+
+  logout(event) {
+    event?.preventDefault();
+    this.accountService.forgetAll();
+    this.defaultAccount = null;
+  }
 }
diff --git a/src/app/network/network.service.ts b/src/app/network/network.service.ts
index 58b343d6f71111286368bef86b12ed036345704f..05b34be7cc49a8977c670187db5c64d52a19ac00 100644
--- a/src/app/network/network.service.ts
+++ b/src/app/network/network.service.ts
@@ -58,7 +58,7 @@ export class NetworkService extends StartableService<ApiPromise> {
 
     const peer = this.selectRandomPeer(peers);
     const wsUri = Peers.getWsUri(peer);
-    console.info(`Connecting to peer {${wsUri}}...`)
+    console.info(`${this._logPrefix}Connecting to peer {${wsUri}}...`)
 
     // Extract all types from definitions - fast and dirty approach, flatted on 'types'
     // const types = Object.values(definitions).reduce((res: any, { types }): object => {
@@ -75,10 +75,10 @@ export class NetworkService extends StartableService<ApiPromise> {
 
     // get the chain information
     const chainInfo = await api.registry.getChainProperties();
-    this.debug('Connecting to chain: ', chainInfo.toHuman());
+    console.debug(`${this._logPrefix}Connecting to chain: `, chainInfo.toHuman());
 
     // Read the genesys block hash
-    console.info('Connected to Blockchain genesis: ' + api.genesisHash.toHex());
+    console.info(`${this._logPrefix}Blockchain genesis: ` + api.genesisHash.toHex());
 
     // Retrieve the chain name
     const chain = '' + (await api.rpc.system.chain());
@@ -89,7 +89,7 @@ export class NetworkService extends StartableService<ApiPromise> {
 
     // Retrieve the latest header
     const lastHeader = await api.rpc.chain.getHeader();
-    console.info(`${this.currency.name} - last block #${lastHeader.number} has hash ${lastHeader.hash}`);
+    console.info(`${this._logPrefix}${this.currency.name} - last block #${lastHeader.number} has hash ${lastHeader.hash}`);
 
     return api;
   }
diff --git a/src/app/register/register.form.html b/src/app/register/register.form.html
index f27fd9e4e06a50ef1afb20ba81eaa31b56852f05..803b832e5c2a601c4403bb9a4551b060971dd417 100644
--- a/src/app/register/register.form.html
+++ b/src/app/register/register.form.html
@@ -34,22 +34,23 @@
 
   <!-- explanation 1 -->
   <ion-slide class="ion-padding">
-    <p>TODO i18n - Cesium fabrique votre portefeuille à partir d'une phrase de restauration. </p>
+    <p [innerHTML]="'ACCOUNT.NEW.STEP_1_HELP'|translate"></p>
+<!--    <img src="assets/account-step-1.png">-->
   </ion-slide>
 
   <!-- explanation 2 -->
   <ion-slide class="ion-padding">
-    <p>TODO i18n - Conservez cette phrase précieusement, car sans elle Cesium ne pourra pas resconstruire... </p>
+    <p [innerHTML]="'ACCOUNT.NEW.STEP_2_HELP'|translate"></p>
   </ion-slide>
 
   <!-- explanation 3 -->
   <ion-slide class="ion-padding">
-    <p>TODO i18n - Dna sune blockchain, pas de procédure de récupration par mail. </p>
+    <p [innerHTML]="'ACCOUNT.NEW.STEP_3_HELP'|translate: {currency: currency?.name}"></p>
   </ion-slide>
 
   <!-- explanation 4 -->
   <ion-slide class="ion-padding">
-    <p>TODO i18n - Il est temps de vous munir d'un papier... </p>
+    <p [innerHTML]="'ACCOUNT.NEW.STEP_4_HELP'|translate"></p>
   </ion-slide>
 
   <!-- generate mnemonic -->
@@ -57,7 +58,7 @@
     <ion-grid *ngIf="form|formGetValue:'words'; let words; else wordsSkeleton" class="words">
       <ion-row>
         <ion-col size="12">
-          <p>Cesium a généré votre phrase de restauration ! Tâchez ...</p>
+          <p [innerHTML]="'ACCOUNT.NEW.STEP_MNEMONIC_HELP'|translate"></p>
         </ion-col>
       </ion-row>
 
@@ -91,15 +92,15 @@
 
   <!-- check word -->
   <ion-slide>
-    <ion-list>
+    <ion-list *ngIf="form|formGetValue:'wordNumber' as wordNumber">
       <ion-item lines="none">
         <ion-text>
-          <p>TODO i18n - Avez-vous bien noté votre phrase de restauration ?</p>
+          <p [innerHTML]="'ACCOUNT.NEW.STEP_CHECK_WORD_HELP'|translate: {number: wordNumber}"></p>
         </ion-text>
       </ion-item>
 
       <ion-item>
-        <ion-label color="medium">{{'ACCOUNT.NEW.INPUT_WORD'|translate: {number: form|formGetValue:'wordNumber'} }}</ion-label>
+        <ion-label color="medium">{{'ACCOUNT.NEW.INPUT_WORD'|translate: {number: wordNumber} }}</ion-label>
         <ion-input (ionChange)="checkWord($event.detail.value)"></ion-input>
         <ion-icon slot="end" name="checkmark" *ngIf="slideState.canNext"></ion-icon>
       </ion-item>
@@ -109,14 +110,14 @@
   <!-- Explain code #1 -->
   <ion-slide>
     <ion-text>
-      <p>TODO i18n - Cesium va maintenant générer pour vous un code secret court, qui vous permettra...</p>
+      <p [innerHTML]="'ACCOUNT.NEW.STEP_CODE_1_HELP'|translate"></p>
     </ion-text>
   </ion-slide>
 
   <!-- Explain code #2 -->
   <ion-slide>
     <ion-text>
-      <p>TODO i18n - Ce code secret protège vos portefeuilles...</p>
+      <p [innerHTML]="'ACCOUNT.NEW.STEP_CODE_2_HELP'|translate"></p>
     </ion-text>
   </ion-slide>
 
@@ -125,14 +126,13 @@
 
     <ion-grid>
       <ion-row>
-        <ion-col>
-          <ion-text>TODO i18n - Et voila votre code</ion-text>
+        <ion-col size="12">
+          <p [innerHTML]="'ACCOUNT.NEW.STEP_CODE_3_HELP'|translate"></p>
+        </ion-col>
+        <ion-col size="12">
           <ion-label color="medium" translate>ACCOUNT.NEW.YOUR_SECRET_CODE</ion-label>
         </ion-col>
-      </ion-row>
-
-      <ion-row class="ion-padding-top">
-        <ion-col>
+        <ion-col size="12" class="ion-padding-top">
           <ion-item>
             <ion-text class="ion-text-center" style="width: 100%">
               <h2>{{form|formGetValue: 'code'}}</h2>
@@ -156,15 +156,43 @@
   <!-- check code -->
   <ion-slide>
     <app-unlock-form [control]="form|formGetControl: 'codeConfirmation'"
-      (change)="checkCodeConfirmation($event)"></app-unlock-form>
+                     helpMessage="ACCOUNT.NEW.STEP_CHECK_CODE_HELP"
+      (change)="checkCodeConfirmation()">
+
+    </app-unlock-form>
   </ion-slide>
 
   <!-- congratulation ! -->
   <ion-slide>
+    <ion-row>
+      <ion-col size="12">
+        <p [innerHTML]="'ACCOUNT.NEW.STEP_CONGRATULATION_1_HELP'|translate"></p>
+      </ion-col>
+      <ion-col size="12" class="ion-padding-top">
+        <ion-item>
+          <ion-text class="ion-text-center" style="width: 100%">
+            {{form|formGetValue: 'address'}}
+          </ion-text>
+        </ion-item>
+      </ion-col>
+      <ion-col size="12" class="ion-padding-top">
+        <p [innerHTML]="'ACCOUNT.NEW.STEP_CONGRATULATION_2_HELP'|translate"></p>
+      </ion-col>
+      <ion-col size="12" class="ion-padding-top">
+        <ion-item>
+          <ion-text class="ion-text-center" style="width: 100%">
+            <h2>{{form|formGetValue: 'address'|addressFormat}}</h2>
+          </ion-text>
+        </ion-item>
 
+      </ion-col>
+    </ion-row>
+
+    <ng-content select="[last]"></ng-content>
   </ion-slide>
 </ion-slides>
 
+
 <ng-template #wordsSkeleton>
   <ion-grid>
     <ion-row>
diff --git a/src/app/register/register.form.ts b/src/app/register/register.form.ts
index 4d4fa856e0a15dd4592fb47c761f55f4aa94ee2c..c90f702cdf6fc5aeadbc5bcfcd730372bb8e8cb1 100644
--- a/src/app/register/register.form.ts
+++ b/src/app/register/register.form.ts
@@ -24,7 +24,8 @@ export const REGISTER_FORM_SLIDES = {
   MNEMONIC: 5,
   ASK_WORD: 6,
   CODE: 9,
-  CODE_CONFIRMATION: 10
+  CODE_CONFIRMATION: 10,
+  CONGRATULATION: 11
 }
 
 @Component({
@@ -34,6 +35,7 @@ export const REGISTER_FORM_SLIDES = {
 })
 export class RegisterForm extends AppForm<RegisterData> implements OnInit {
 
+  private readonly _isDevelopment: boolean;
   slideOpts = {
     initialSlide: 0,
     speed: 400,
@@ -68,19 +70,24 @@ export class RegisterForm extends AppForm<RegisterData> implements OnInit {
       wordNumber: new FormControl(null, Validators.required),
       code: new FormControl(null, Validators.required),
       codeConfirmation: new FormControl(null, Validators.compose([Validators.required, this.equalsValidator('code')])),
-      name: new FormControl(null)
+      name: new FormControl(null),
+      address: new FormControl(null)
     }));
+
+    this.debug = !environment.production;
+    this._isDevelopment = !environment.production;
   }
 
   ngOnInit() {
     // For DEV only ------------------------
-    if (!environment.production) {
+    if (this._isDevelopment) {
       this.form.setValue({
         words: 'search average amateur muffin inspire lake resist width intact viable stone barrel'.split(' '),
         wordNumber: 1,
         code: 'AAAAA',
         codeConfirmation: null,
-        name: 'Nouveau portefeuille'
+        name: 'Nouveau portefeuille',
+        address: null
       });
     }
   }
@@ -103,6 +110,7 @@ export class RegisterForm extends AppForm<RegisterData> implements OnInit {
   }
 
   async slideNext() {
+    console.log("slideNext from slide #" + this.slideState.index);
     return this.slides.slideNext()
       .then(() => this.updateState());
   }
@@ -162,10 +170,15 @@ export class RegisterForm extends AppForm<RegisterData> implements OnInit {
     this.slideState.isEnd = await this.slides.isEnd();
     this.markForCheck();
 
+    console.debug('[register-form] Slide #' + this.slideState.index);
+
     switch (this.slideState.index) {
       case REGISTER_FORM_SLIDES.MNEMONIC:
         if (!this.form.get('words').valid) {
-          this.generatePhrase();
+          await this.generatePhrase();
+        }
+        else {
+          this.slideState.canNext = false;
         }
         break;
       case REGISTER_FORM_SLIDES.ASK_WORD:
@@ -175,13 +188,18 @@ export class RegisterForm extends AppForm<RegisterData> implements OnInit {
         this.generateCode();
         break;
       case REGISTER_FORM_SLIDES.CODE_CONFIRMATION:
-        this.slideState.canNext = false;
+        this.checkCodeConfirmation();
         break;
+      case REGISTER_FORM_SLIDES.CONGRATULATION:
+        await this.generateAccount();
+        break;
+      default:
+        this.slideState.canNext = true;
     }
   }
 
   protected async generatePhrase() {
-    if (!environment.production) return;
+    if (this._isDevelopment) return; // Keep existing mnemonic
 
     // Clear previous phrase
     this.form.get('words').reset(null);
@@ -189,11 +207,11 @@ export class RegisterForm extends AppForm<RegisterData> implements OnInit {
     this.markForCheck();
 
     setTimeout(async () => {
-      const mnemonic = await this.accountService.generateNew();
+      const mnemonic = await this.accountService.generateMnemonic();
       this.form.patchValue({
         words: mnemonic.split(' ')
       });
-    });
+    }, 250 * Math.random());
   }
 
   protected toggleCanNext() {
@@ -237,9 +255,27 @@ export class RegisterForm extends AppForm<RegisterData> implements OnInit {
     this.markForCheck();
   }
 
-  checkCodeConfirmation(code: string) {
+  checkCodeConfirmation() {
+    if (this.slideState.index !== REGISTER_FORM_SLIDES.CODE_CONFIRMATION) return;
+    const code = this.form.get('codeConfirmation').value;
     const expectedCode = this.form.get('code').value;
     this.slideState.canNext = expectedCode === code;
     this.markForCheck();
   }
+
+  async generateAccount() {
+    if (this.slideState.index !== REGISTER_FORM_SLIDES.CONGRATULATION) return; // Skip
+
+    this.slideState.canNext = false;
+    this.markAsLoading();
+
+    setTimeout(async () => {
+      const data = this.value;
+      const account = await this.accountService.createAddress(data);
+      this.form.get('address').setValue(account.address);
+
+      this.slideState.canNext = true;
+      this.markAsLoaded();
+    }, 250);
+  }
 }
diff --git a/src/app/register/register.modal.html b/src/app/register/register.modal.html
index 7baedfdfb13dc55d6dde83f5c34435ff107406d0..645a8b136fc248d206f0b669aeb6f1ec1a3e0e01 100644
--- a/src/app/register/register.modal.html
+++ b/src/app/register/register.modal.html
@@ -30,7 +30,19 @@
   <app-register-form (onSubmit)="doSubmit()" (onCancel)="cancel()"
                      [class]="mobile ? '': 'has-footer'"
                      #form>
+
+
+    <ion-row *ngIf="form.debug" codeConfirmation>
+      <ion-text color="primary"  class="ion-padding">
+        <small>loading: {{loading}}<br/>
+          canNext: {{form.canNext()}}<br/>
+          isEnd: {{form.isEnd()}}<br/>
+        </small>
+      </ion-text>
+    </ion-row>
   </app-register-form>
+
+
   <!-- buttons -->
   <ion-toolbar>
 
@@ -62,12 +74,13 @@
         <ion-button *ngIf="form.isEnd()"
                     (click)="doSubmit()" fill="solid"
                     [disabled]="loading || !form.canNext()" color="tertiary">
-          <span translate>COMMON.BTN_SEND</span>
-          <ion-icon slot="end" name="send"></ion-icon>
+          <span translate>COMMON.BTN_SAVE</span>
+          <ion-icon slot="end" name="save"></ion-icon>
         </ion-button>
       </ion-col>
     </ion-row>
 
 
+
   </ion-toolbar>
 </ion-content>
diff --git a/src/app/register/register.modal.ts b/src/app/register/register.modal.ts
index 7ae561d9d6a86818d3727c99fb5b0ce269434684..963efb4db1ed3af5fea0a8b653dd67a322d21368 100644
--- a/src/app/register/register.modal.ts
+++ b/src/app/register/register.modal.ts
@@ -41,9 +41,9 @@ export class RegisterModal implements OnInit{
 
     // DEV
     if (!environment.production) {
-      setTimeout(() => {
-        this.form.slideTo(REGISTER_FORM_SLIDES.MNEMONIC);
-      });
+      // setTimeout(() => {
+      //   this.form.slideTo(REGISTER_FORM_SLIDES.MNEMONIC);
+      // });
     }
   }
 
@@ -54,6 +54,7 @@ export class RegisterModal implements OnInit{
   }
 
   async doSubmit(event?: any) {
+    console.debug('[register-modal] Submit...');
     if (this.form.disabled) return; // Skip
 
     if (!this.form.valid) {
@@ -68,18 +69,24 @@ export class RegisterModal implements OnInit{
     const data = this.form.value;
 
     this.form.disable();
+    this.form.markAsLoading();
 
     try {
-      console.debug('[register] Sending registration to server...', data);
+      console.debug('[register] Saving new account...');
 
-      await this.accountService.register(data);
+      const registered = await this.accountService.register(data);
 
-      console.debug('[register] Account registered!');
-      await this.viewCtrl.dismiss();
+      const address = registered && this.form.form.get('address').value;
+      if (address) {
+        console.debug('[register] Account registered, with address: ' + address);
+        const account = await this.accountService.getByAddress(address);
+        await this.viewCtrl.dismiss(account);
+      }
     }
     catch (err) {
       this.form.error = err && err.message || err;
       this.form.enable();
+      this.form.markAsLoaded();
     }
   }
 }
diff --git a/src/app/settings/settings.model.ts b/src/app/settings/settings.model.ts
index 38817acabf7796cfe871876540bc9de45c817b3d..75c45902603fe8cf7214eb4785c174bc07294c61 100644
--- a/src/app/settings/settings.model.ts
+++ b/src/app/settings/settings.model.ts
@@ -16,5 +16,6 @@ export declare interface Settings {
   locale?: string;
   mobile?: boolean;
   properties?: PropertiesMap;
+  unAuthDelayMs?: number;
 }
 
diff --git a/src/app/settings/settings.page.html b/src/app/settings/settings.page.html
index ec151711e0bde8de7460818ad09e32b6bf5bc8e0..7ce703b328c215f8823a1cfcd82025e00f608528 100644
--- a/src/app/settings/settings.page.html
+++ b/src/app/settings/settings.page.html
@@ -20,7 +20,10 @@
       <ion-item>
         <ion-icon slot="start" name="language"></ion-icon>
         <ion-label color="dark" translate>COMMON.LANGUAGE</ion-label>
-        <ion-select [(ngModel)]="data.locale">
+        <ion-select [(ngModel)]="data.locale"
+                    [interface]="mobile ? 'action-sheet' : 'popover'"
+                    [okText]="'COMMON.BTN_OK'|translate"
+                    [cancelText]="'COMMON.BTN_CANCEL'|translate">
           <ion-select-option *ngFor="let locale of locales" [value]="locale.key">
             {{locale.value}}
           </ion-select-option>
@@ -38,9 +41,26 @@
 
         </ion-input>
         <ion-button slot="end" (click)="selectPeer()">
-          <ion-icon slot="icon-only" name=""></ion-icon>
+          <ion-label>...</ion-label>
         </ion-button>
       </ion-item>
+
+      <ion-item-divider translate>SETTINGS.AUTHENTICATION_SETTINGS</ion-item-divider>
+
+      <ion-item>
+
+        <ion-icon slot="start" name="lock-open"></ion-icon>
+        <ion-label color="dark" translate>SETTINGS.KEEP_AUTH</ion-label>
+
+        <ion-select [(ngModel)]="data.unAuthDelayMs"
+                    [interface]="mobile ? 'action-sheet' : 'popover'"
+                    [okText]="'COMMON.BTN_OK'|translate"
+                    [cancelText]="'COMMON.BTN_CANCEL'|translate">
+          <ion-select-option *ngFor="let item of unauthOptions" [value]="item.value">
+            {{item.label|translate:{value: item.labelParam} }}
+          </ion-select-option>
+        </ion-select>
+      </ion-item>
     </ion-list>
 
     <div class="ion-text-center">
diff --git a/src/app/settings/settings.page.ts b/src/app/settings/settings.page.ts
index 2d0821ea3d5e22a167d54d8b05deb54d71cf78ef..2b6f43d0bef1b3144b7aca4307d78916481a13da 100644
--- a/src/app/settings/settings.page.ts
+++ b/src/app/settings/settings.page.ts
@@ -10,6 +10,29 @@ import {BasePage} from "@app/shared/pages/base.page";
 })
 export class SettingsPage extends BasePage<Settings> implements OnInit {
 
+  unauthOptions = [
+    {
+      label: 'SETTINGS.KEEP_AUTH_OPTION.SECONDS',
+      labelParam: 10,
+      value: 10_000
+    },
+    {
+      label: 'SETTINGS.KEEP_AUTH_OPTION.SECONDS',
+      labelParam: 30,
+      value: 30_000
+    },
+    {
+      label: 'SETTINGS.KEEP_AUTH_OPTION.MINUTE',
+      labelParam: 1,
+      value: 60_000
+    },
+    {
+      label: 'SETTINGS.KEEP_AUTH_OPTION.MINUTES',
+      labelParam: 15,
+      value: 15*60_000
+    }
+  ];
+
   constructor(
     injector: Injector,
     @Inject(APP_LOCALES) public locales: LocaleConfig[]
diff --git a/src/app/settings/settings.service.ts b/src/app/settings/settings.service.ts
index 0b31eb418f48b8d3a12a86b95e4b61501022577f..7c8e40fa2ade5022dcdc8f298cbdf3a39f6d707b 100644
--- a/src/app/settings/settings.service.ts
+++ b/src/app/settings/settings.service.ts
@@ -1,9 +1,12 @@
-import {Injectable} from "@angular/core";
+import {Inject, Injectable, Optional} from "@angular/core";
 import {Settings} from "./settings.model";
 import {environment} from "@environments/environment";
 import {StartableService} from "@app/shared/services/startable-service.class";
 import {Platform} from "@ionic/angular";
 import {Subject} from "rxjs";
+import {APP_STORAGE, IStorage} from "@app/shared/services/storage/storage.utils";
+
+const SETTINGS_STORAGE_KEY = 'settings';
 
 @Injectable({providedIn: 'root'})
 export class SettingsService extends StartableService<Settings> {
@@ -16,12 +19,18 @@ export class SettingsService extends StartableService<Settings> {
     return this._mobile;
   }
 
+  get data(): Settings {
+    return this._data;
+  }
+
   constructor(
-    protected ionicPlatform: Platform
+    protected ionicPlatform: Platform,
+    @Inject(APP_STORAGE) @Optional() protected storage?: IStorage
   ) {
     super(ionicPlatform, {
       name: 'settings-service'
-    })
+    });
+
   }
 
   protected async ngOnStart(): Promise<Settings> {
@@ -43,10 +52,14 @@ export class SettingsService extends StartableService<Settings> {
   }
 
   async restoreLocally(): Promise<Settings> {
+
+    const savedData = await this.storage.get(SETTINGS_STORAGE_KEY);
     const data = <Settings>{
       preferredPeers: !environment.production && environment.dev?.peer
         ? [environment.dev.peer]
-        : [...environment.defaultPeers]
+        : [...environment.defaultPeers],
+      unAuthDelayMs: 15 * 60_000, // 15min
+      ...savedData
     };
     return data;
   }
@@ -58,9 +71,16 @@ export class SettingsService extends StartableService<Settings> {
       ...data
     };
     this.changes.next(this._data);
+
+    // Saving changes
+    setTimeout(() => this.saveLocally(), 250);
   }
 
   async saveLocally() {
-    // TODO
+    if (!this.storage) return; // Skip, no storage
+
+    console.info('[settings] Saving settings to the storage...');
+    const data = this.clone();
+    await this.storage?.set('settings', data);
   }
 }
diff --git a/src/app/shared/pages/base.page.ts b/src/app/shared/pages/base.page.ts
index 31d334b4537e3e65e22154cfc73aa130833f38da..7587ed02d60b157a0d2438eb7ab21c684652d790 100644
--- a/src/app/shared/pages/base.page.ts
+++ b/src/app/shared/pages/base.page.ts
@@ -1,4 +1,4 @@
-import {ChangeDetectorRef, Directive, inject, Injector, OnInit} from '@angular/core';
+import {ChangeDetectorRef, Directive, inject, Injector, OnDestroy, OnInit} from '@angular/core';
 import {ActivatedRoute} from '@angular/router';
 import {SettingsService} from "@app/settings/settings.service";
 import {changeCaseToUnderscore, isNotNilOrBlank} from "@app/shared/functions";
@@ -7,18 +7,30 @@ import {waitIdle} from "@app/shared/forms";
 import {WaitForOptions} from "@app/shared/observables";
 import {ToastController, ToastOptions} from "@ionic/angular";
 import {TranslateService} from "@ngx-translate/core";
+import {Subscription} from "rxjs";
+
+export interface BasePageOptions {
+  name: string;
+  loadDueTime: number;
+}
 
 @Directive()
-export abstract class BasePage<S> implements OnInit {
+export abstract class BasePage<
+  S,
+  O extends BasePageOptions = BasePageOptions
+  >
+  implements OnInit, OnDestroy {
 
   private _cd: ChangeDetectorRef;
+  private _subscription: Subscription;
 
   protected translate: TranslateService;
   protected settings: SettingsService;
-  protected activatedRoute: ActivatedRoute;
+  protected readonly activatedRoute: ActivatedRoute;
   protected toastController: ToastController;
   protected readonly _debug = !environment.production;
   protected readonly _logPrefix: string;
+  protected readonly _options: O;
 
   mobile: boolean = null;
   error: string = null;
@@ -30,9 +42,8 @@ export abstract class BasePage<S> implements OnInit {
   }
 
   protected constructor(
-    injector: Injector, options: {
-      name?: string
-    }
+    injector: Injector,
+    options?: Partial<O>
   ) {
     this._cd = injector.get(ChangeDetectorRef);
     this.settings = injector.get(SettingsService);
@@ -40,12 +51,24 @@ export abstract class BasePage<S> implements OnInit {
     this.activatedRoute = injector.get(ActivatedRoute);
     this.toastController = injector.get(ToastController);
     this.mobile = this.settings.mobile;
-    this._logPrefix = options?.name ? `[${options.name}] ` : `[${changeCaseToUnderscore(this.constructor.name).replace(/_/g, '-')}]`;
+    this._options = <O>{
+      name: options?.name || changeCaseToUnderscore(this.constructor.name).replace(/_/g, '-'),
+      loadDueTime: 0,
+      ...options
+    };
+    this._logPrefix = `[${this._options.name}] `;
 
   }
 
   ngOnInit() {
-    this.load();
+
+    // Load data
+    setTimeout(() => this.load(), this._options.loadDueTime || 0);
+  }
+
+  ngOnDestroy() {
+    console.debug(`${this._logPrefix}Destroy`);
+    this._subscription?.unsubscribe();
   }
 
   protected async load() {
@@ -112,6 +135,11 @@ export abstract class BasePage<S> implements OnInit {
     else console.debug(this._logPrefix + msg)
   }
 
+  protected info(msg, ...params: any[]) {
+    if (params) console.info(this._logPrefix + msg, params);
+    else console.info(this._logPrefix + msg)
+  }
+
   protected log(msg, ...params: any[]) {
     if (!this._debug) return;
     if (params) console.log(this._logPrefix + msg, params);
@@ -127,4 +155,13 @@ export abstract class BasePage<S> implements OnInit {
     });
     return toast.present();
   }
+
+  protected registerSubscription(sub: Subscription) {
+    if (!this._subscription) this._subscription = new Subscription();
+    this._subscription.add(sub);
+  }
+
+  protected unregisterSubscription(sub: Subscription) {
+    this._subscription?.remove(sub);
+  }
 }
diff --git a/src/app/shared/pipes/address.pipes.ts b/src/app/shared/pipes/address.pipes.ts
index cce70c175635931a41d2191740e092bf18dcde93..56c4a8e8f3fa220a49cf4a6150e980f5e0faa020 100644
--- a/src/app/shared/pipes/address.pipes.ts
+++ b/src/app/shared/pipes/address.pipes.ts
@@ -6,6 +6,7 @@ import {Pipe, PipeTransform} from '@angular/core';
 export class AddressFormatPipe implements PipeTransform {
 
   transform(value: string, withChecksum?: boolean ): string {
+    if (!value) return '';
     if (value.length < 12) return '?';
     return value.substring(0,6) + '...' + value.substring(value.length - 6);
   }
diff --git a/src/app/shared/services/platform.service.ts b/src/app/shared/services/platform.service.ts
index f861f7b0bec88e25f7bfaab1682b5ec45e654cb3..4d38cf0bef6591d1a6142dc888f54955987be2a3 100644
--- a/src/app/shared/services/platform.service.ts
+++ b/src/app/shared/services/platform.service.ts
@@ -46,7 +46,6 @@ export class PlatformService extends StartableService {
     this._mobile = this.mobile;
     this._touchUi = this.touchUi;
 
-
     // Configure translation
     await this.configureTranslate();
 
diff --git a/src/app/shared/services/startable-service.class.ts b/src/app/shared/services/startable-service.class.ts
index 4ece06ef268cfeaef73a2ff8bce1c3af787eab80..9fcbe65583b35f366be08bd961a55a592b4d293e 100644
--- a/src/app/shared/services/startable-service.class.ts
+++ b/src/app/shared/services/startable-service.class.ts
@@ -2,6 +2,7 @@ import {Optional} from '@angular/core';
 import {Subject} from 'rxjs';
 import {waitFor} from '../observables';
 import {BaseService, IBaseServiceOptions} from "@app/shared/services/base-service.class";
+import {environment} from "@environments/environment";
 
 export interface IStartableService<T = any> {
   started: boolean;
@@ -21,6 +22,7 @@ export abstract class StartableService<T = any, O extends IStartableServiceOptio
 
   protected _startByReadyFunction = true; // should start when calling ready() ?
   protected _data: T = null;
+  protected _debug: boolean = false;
 
   private _started = false;
   private _startPromise: Promise<T> = null;
@@ -34,6 +36,7 @@ export abstract class StartableService<T = any, O extends IStartableServiceOptio
     this._startPrerequisite = prerequisiteService
       ? () => prerequisiteService.ready()
       : () => Promise.resolve();
+    this._debug = !environment.production;
   }
 
   start(): Promise<T> {
diff --git a/src/app/shared/services/keyring-storage.ts b/src/app/shared/services/storage/keyring-storage.ts
similarity index 90%
rename from src/app/shared/services/keyring-storage.ts
rename to src/app/shared/services/storage/keyring-storage.ts
index 4e8f7962f2375403bc267557c742128201712ce3..5fb913c7292b342589f7eaf2385eeb4fa1d9ec4c 100644
--- a/src/app/shared/services/keyring-storage.ts
+++ b/src/app/shared/services/storage/keyring-storage.ts
@@ -1,6 +1,6 @@
 import {KeyringJson, KeyringStore} from "@polkadot/ui-keyring/types";
 import {Directive} from '@angular/core';
-import {IStorage} from "@app/shared/services/storage/storage.interface";
+import {IStorage} from "@app/shared/services/storage/storage.utils";
 
 // @dynamic
 @Directive()
@@ -29,6 +29,7 @@ export class KeyringStorage implements KeyringStore {
 
   all(cb: (key: string, value: KeyringJson) => void) {
     this.storage.forEach((value, key, counter) => {
+      console.debug("Reading key=" + key, value);
       if (key.startsWith(this.storagePrefix)) {
         const shortKey = key.substring(this.storagePrefix.length);
         cb(shortKey, value as KeyringJson);
diff --git a/src/app/shared/services/storage/storage.service.ts b/src/app/shared/services/storage/storage.service.ts
index 4a8d98f0821e842eadd4212e621454e95dbd8f9a..9b2c07f9fc027cad61187c025efb8d3ba7690d4b 100644
--- a/src/app/shared/services/storage/storage.service.ts
+++ b/src/app/shared/services/storage/storage.service.ts
@@ -1,7 +1,7 @@
 import {Injectable} from '@angular/core';
 import {Storage} from '@ionic/storage-angular';
 import {StartableService} from "@app/shared/services/startable-service.class";
-import {IStorage} from "@app/shared/services/storage/storage.interface";
+import {IStorage} from "@app/shared/services/storage/storage.utils";
 import {Platform} from '@ionic/angular';
 
 @Injectable({
@@ -20,18 +20,22 @@ export class StorageService extends StartableService<Storage>
     this.start();
   }
 
-
   protected async ngOnStart(): Promise<Storage> {
     await this.platform.ready();
-    return this.storage.create();
+    const storage = await this.storage.create();
+    console.info(`[storage-service] Started using driver=${storage?.driver}`);
+    return storage;
   }
 
   async set(key: string, value: any) {
+    console.debug(`[storage-service] Set ${key} = `, value);
+
     if (!this.started) await this.ready();
     return this._data.set(key, value);
   }
 
   async get(key: string): Promise<any> {
+    console.debug(`[storage-service] Get ${key} ...`);
     if (!this.started) await this.ready();
     return this._data.get(key);
   }
@@ -42,8 +46,11 @@ export class StorageService extends StartableService<Storage>
   }
 
   async keys(): Promise<string[]> {
+    console.debug(`[storage-service] Get keys...`);
     if (!this.started) await this.ready();
-    return this._data.keys();
+    const keys = await this._data.keys();
+    console.debug(`[storage-service] ${keys.length} keys found: `, keys);
+    return keys;
   }
 
   async clear() {
@@ -53,6 +60,8 @@ export class StorageService extends StartableService<Storage>
 
   async forEach(iteratorCallback: (value: any, key: string, iterationNumber: Number) => any): Promise<void> {
     if (!this.started) await this.ready();
-    return this._data.forEach(iteratorCallback);
+    return this._data.forEach((value, key, iterationNumber) => {
+      iteratorCallback(value, key, iterationNumber);
+    });
   }
 }
diff --git a/src/app/shared/services/storage/storage.interface.ts b/src/app/shared/services/storage/storage.utils.ts
similarity index 61%
rename from src/app/shared/services/storage/storage.interface.ts
rename to src/app/shared/services/storage/storage.utils.ts
index 9d3e4fa44dfab11e05d6fbd00ec94c4e8731c5bc..085ab55faa48f830976ca1bcdc9187128bf9a14c 100644
--- a/src/app/shared/services/storage/storage.interface.ts
+++ b/src/app/shared/services/storage/storage.utils.ts
@@ -1,4 +1,7 @@
 import {InjectionToken} from "@angular/core";
+import {Drivers} from "@ionic/storage";
+import * as LocalForage from "localforage";
+
 
 export interface IStorage<T = any> {
   readonly driver: string;
@@ -11,4 +14,12 @@ export interface IStorage<T = any> {
   forEach(iteratorCallback: (value: any, key: string, iterationNumber: Number) => any): Promise<void>;
 }
 
+export const StorageDrivers = {
+  //SQLLite: CordovaSQLiteDriver._driver,
+  SecureStorage: Drivers.SecureStorage,
+  WebSQL: LocalForage.WEBSQL,
+  IndexedDB: Drivers.IndexedDB,
+  LocalStorage: Drivers.LocalStorage
+};
+
 export const APP_STORAGE = new InjectionToken<IStorage>('Storage');
diff --git a/src/app/transfer/transfer.page.html b/src/app/transfer/transfer.page.html
index 3eaeaed88e0b2a438e186b5d0f5714b0fa18a49c..93d5530ce5d77b9ff9e2b3d8afcacf8f9c69df0f 100644
--- a/src/app/transfer/transfer.page.html
+++ b/src/app/transfer/transfer.page.html
@@ -24,29 +24,44 @@
 
       <!-- TO -->
       <ion-item>
-        <ion-label color="medium" slot="start" translate>TRANSFER.TO</ion-label>
-        <ion-input [(ngModel)]="recipient.address" (ionFocus)="modal.present()">
+        <ion-label color="medium" translate>TRANSFER.TO</ion-label>
+        <ion-input *ngIf="data|async|isNotEmptyArray; else inputSkeleton"
+          [(ngModel)]="recipient.address" (ionFocus)="modal.present()">
         </ion-input>
-        <ion-button slot="end" fill="clear" id="open-modal-trigger" [title]="'COMMON.BTN_SEARCH'|translate">
+        <ion-button slot="end" fill="clear" id="open-modal-trigger"
+                    [disabled]="loading"
+                    [title]="'COMMON.BTN_SEARCH'|translate">
           <ion-icon slot="icon-only" name="search"></ion-icon>
         </ion-button>
       </ion-item>
 
       <!-- FROM -->
-      <ion-item >
+      <ion-item tappable>
         <ion-label color="medium" translate>TRANSFER.FROM</ion-label>
-        <ion-select *ngIf="data|async; let accounts; else inputSkeleton"
-                    [(ngModel)]="issuer.address" [interface]="mobile ? 'action-sheet' : 'popover'"
-                    [okText]="'COMMON.BTN_OK'|translate"
-                    [cancelText]="'COMMON.BTN_CANCEL'|translate">
-          <ion-select-option *ngFor="let account of accounts"
-                             [value]="account.address"
-                             [disabled]="!(account|balance)">
-            {{account|accountName}}
-            <ng-container *ngIf="account|balance; let balance">({{balance|amountFormat}})</ng-container>
-          </ion-select-option>
-        </ion-select>
-        <ion-badge *ngIf="issuer?.address" slot="end">{{issuer|balance|amountFormat}}</ion-badge>
+        <ng-container *ngIf="loading; else select">
+          <ng-container *ngTemplateOutlet="inputSkeleton"></ng-container>
+        </ng-container>
+        <ng-template #select>
+          <ng-container *ngIf="data|async; let accounts; else inputSkeleton">
+            <ion-select #ionSelect
+                        [compareWith]="compareWith"
+                        [selectedText]="issuer|accountName"
+                        [(ngModel)]="issuer"
+                        [interface]="mobile ? 'action-sheet' : 'popover'"
+                        [interfaceOptions]="mobile ? actionSheetOptions : popoverOptions"
+                        [okText]="'COMMON.BTN_OK'|translate"
+                        [cancelText]="'COMMON.BTN_CANCEL'|translate">
+              <ion-select-option *ngFor="let account of accounts"
+                                 [value]="account"
+                                 [disabled]="!(account|balance)">
+
+                {{account|accountName}}
+                <span *ngIf="account|balance; let balance">({{balance|amountFormat}})</span>
+              </ion-select-option>
+            </ion-select>
+            <ion-badge *ngIf="issuer" slot="end">{{issuer|balance|amountFormat}}</ion-badge>
+          </ng-container>
+        </ng-template>
       </ion-item>
 
       <ion-item>
@@ -113,5 +128,5 @@
 </ion-footer>
 
 <ng-template #inputSkeleton>
-  <ion-skeleton-text [animated]="true" style="width: 60%"></ion-skeleton-text>
+  <ion-skeleton-text [animated]="true" ></ion-skeleton-text>
 </ng-template>
diff --git a/src/app/transfer/transfer.page.scss b/src/app/transfer/transfer.page.scss
index c5fe043b8dd1c147ec1cf95a64625372943b0cc5..03b00c3540a0701557867bfe0c4c991fafd26561 100644
--- a/src/app/transfer/transfer.page.scss
+++ b/src/app/transfer/transfer.page.scss
@@ -8,3 +8,7 @@ ion-menu-button {
 .balance {
   color: var(--ion-color-base);
 }
+ion-select.hidden {
+  display: none;
+  visibility: hidden;
+}
diff --git a/src/app/transfer/transfer.page.ts b/src/app/transfer/transfer.page.ts
index bf11748cce09230469849d69c86efb563f5cff28..9dc265f6735582862fbf8a20b3c6f6b244ea61fc 100644
--- a/src/app/transfer/transfer.page.ts
+++ b/src/app/transfer/transfer.page.ts
@@ -9,21 +9,12 @@ import {
 } from '@angular/core';
 import {AccountService} from "../wallet/account.service";
 import {BasePage} from "@app/shared/pages/base.page";
-import {Account, AccountUtils} from "@app/wallet/account.model";
-import {IonModal} from "@ionic/angular";
-import {
-  BehaviorSubject,
-  combineAll,
-  combineLatestAll,
-  concat,
-  concatAll,
-  from,
-  Observable,
-  Subject,
-  switchMap,
-  zip
-} from "rxjs";
-import {isNotNil} from "@app/shared/functions";
+import {Account} from "@app/wallet/account.model";
+import {ActionSheetOptions, IonModal, PopoverOptions} from "@ionic/angular";
+import {BehaviorSubject, firstValueFrom, Observable} from "rxjs";
+import {isNotEmptyArray} from "@app/shared/functions";
+import {filter} from "rxjs/operators";
+import {WotLookupPage} from "@app/wot/wot-lookup.page";
 
 @Component({
   selector: 'app-transfer',
@@ -34,10 +25,18 @@ import {isNotNil} from "@app/shared/functions";
 export class TransferPage extends BasePage<Observable<Account[]>> implements OnInit, OnDestroy {
 
   showComment: boolean;
-  issuer: Partial<Account> = {};
-  recipient: Partial<Account> = {};
+  issuer: Account = null;
+  recipient: Account = {address: null, meta: null};
   amount: number;
 
+  protected actionSheetOptions: Partial<ActionSheetOptions> = {
+    cssClass: 'select-account-action-sheet'
+  };
+  protected popoverOptions: Partial<PopoverOptions> = {
+    cssClass: 'select-account-popover',
+    reference: 'event'
+  };
+
   @ViewChild('modal') modal: IonModal;
 
   get balance(): number {
@@ -51,7 +50,7 @@ export class TransferPage extends BasePage<Observable<Account[]>> implements OnI
     protected accountService: AccountService,
     protected cd: ChangeDetectorRef
   ) {
-    super(injector, {name: 'transfer'});
+    super(injector, {name: 'transfer', loadDueTime: 250});
   }
 
   ngOnInit() {
@@ -59,6 +58,7 @@ export class TransferPage extends BasePage<Observable<Account[]>> implements OnI
   }
 
   ngOnDestroy() {
+    super.ngOnDestroy();
     if (this.modal.isOpen) {
       this.modal.dismiss();
     }
@@ -67,17 +67,29 @@ export class TransferPage extends BasePage<Observable<Account[]>> implements OnI
   protected async ngOnLoad(): Promise<Observable<Account[]>> {
     await this.accountService.ready();
 
-    return this.accountService.watchAll({positiveBalanceFirst: true});
+    const subject = new BehaviorSubject<Account[]>(null);
+    this.registerSubscription(
+      this.accountService.watchAll({positiveBalanceFirst: true})
+        .pipe(filter(isNotEmptyArray))
+        .subscribe((value) => subject.next(value))
+    );
+
+    const accounts = await firstValueFrom(subject);
+
+    // Only one account: select it
+    if (accounts?.length === 1) {
+      this.issuer = accounts[0];
+    }
+
+    return subject;
   }
 
   setRecipient(recipient: string|Account) {
     if (typeof recipient === 'object') {
-      this.recipient.address = recipient.address;
-      this.recipient.meta = recipient.meta;
+      this.recipient = recipient;
     }
     else {
-      this.recipient.address = recipient;
-      this.recipient.meta = null;
+      this.recipient = {address: recipient, meta: null};
     }
     this.markForCheck();
   }
@@ -101,4 +113,8 @@ export class TransferPage extends BasePage<Observable<Account[]>> implements OnI
       this.setError(err);
     }
   }
+
+  compareWith(a1: Account, a2: Account) {
+    return a1.address === a2.address;
+  }
 }
diff --git a/src/app/unlock/unlock.form.html b/src/app/unlock/unlock.form.html
index ed5a552674fafe901f338fa5929a9f07b70f751f..9b8dbee73afbff83cc5376116cbc657c49ee3980 100644
--- a/src/app/unlock/unlock.form.html
+++ b/src/app/unlock/unlock.form.html
@@ -1,21 +1,23 @@
 <form [formGroup]="form">
   <ion-list>
     <ion-item lines="none">
-      <ion-text>
-        <p>TODO i18n - Pour vous authentifier, veuillez <b>composer votre code secret</b> :</p>
-      </ion-text>
+      <p [innerHTML]="helpMessage|translate"></p>
+
     </ion-item>
 
     <ion-item>
       <ion-label color="medium">{{'AUTH.PASSPHRASE'|translate }}</ion-label>
-      <ion-input formControlName="code" [maxlength]="maxLength" [minlength]="minLength" required
-                 (ionInput)="onChange($event)"></ion-input>
+      <ion-input [formControl]="control"
+                 [maxlength]="maxLength"
+                 [minlength]="minLength"
+                 (ionChange)="onChange($event)"
+                 required></ion-input>
       <ion-icon slot="end" name="checkmark" *ngIf="$valid|async"></ion-icon>
     </ion-item>
 
-    <ion-item *ngIf="debug" lines="none">
-      <ion-text>
-        {{form|formGetValue:'code'}}
+    <ion-item *ngIf="debug && expectedCode" lines="none">
+      <ion-text color="primary">
+        <small>expected: {{expectedCode}}</small>
       </ion-text>
     </ion-item>
   </ion-list>
diff --git a/src/app/unlock/unlock.form.ts b/src/app/unlock/unlock.form.ts
index 4dcee5fc69cedc58cd39b16a163aa358fcf133a2..0865da547180919767bcbb3bfefdcc308dead229 100644
--- a/src/app/unlock/unlock.form.ts
+++ b/src/app/unlock/unlock.form.ts
@@ -40,6 +40,7 @@ export class UnlockForm extends AppForm<string> implements OnInit {
 
   @Input('class') classList: string = null;
 
+  @Input() helpMessage = 'AUTH.PASSPHRASE_HELP';
   @Input() expectedCode: string = null;
   @Input() minLength: number = 5;
   @Input() maxLength: number = 5;
@@ -62,7 +63,7 @@ export class UnlockForm extends AppForm<string> implements OnInit {
   }
 
   ngOnInit() {
-    if (!this.control) {
+    if (!this.control && this.formGroupDir && this.controlName) {
       const formControlName = (this.formGroupDir.directives || []).find(d => this.controlName && d.name === this.controlName);
       this.control = formControlName && formControlName.control;
       if (this.formGroupDir && this.control) {
@@ -75,7 +76,7 @@ export class UnlockForm extends AppForm<string> implements OnInit {
       }
       else {
         this.setForm(this.formBuilder.group({
-          code: new FormControl(this.createValidator())
+          code: new FormControl(null, this.createValidator())
         }));
         this.control = this.form.get('code') as FormControl;
       }
@@ -94,21 +95,20 @@ export class UnlockForm extends AppForm<string> implements OnInit {
 
   }
 
-  get value(): RegisterData {
-    const json = this.form.value;
-    return json.code;
+  get value(): string {
+    return this.control.value;
   }
 
   get valid(): boolean {
-    return this.form.valid;
+    return this.control.valid;
   }
 
   cancel() {
     this.onCancel.emit();
   }
 
-  onChange(event: UIEvent, value?: string) {
-    value = this.control?.value;
+  onChange(event: CustomEvent<{ value: string; }>) {
+    let value = event.detail?.value;
     value = value && value.toUpperCase() || null;
     if (value && value.length > this.maxLength) {
       event.preventDefault();
diff --git a/src/app/unlock/unlock.modal.html b/src/app/unlock/unlock.modal.html
new file mode 100644
index 0000000000000000000000000000000000000000..2f0537e4039ac9f792ac1d01af45124ade683671
--- /dev/null
+++ b/src/app/unlock/unlock.modal.html
@@ -0,0 +1,52 @@
+<ion-header>
+  <ion-toolbar [color]="auth?'danger': 'primary'">
+    <ion-buttons slot="start">
+      <ion-button (click)="cancel()" *ngIf="mobile">
+        <ion-icon slot="icon-only" name="arrow-back"></ion-icon>
+      </ion-button>
+    </ion-buttons>
+
+    <ion-title [innerHTML]="auth?'AUTH.TITLE': 'LOGIN.TITLE'|translate">
+    </ion-title>
+
+    <ion-buttons slot="end">
+      <ion-spinner *ngIf="loading"></ion-spinner>
+
+      <ion-button
+        (click)="doSubmit()" *ngIf="!loading && mobile">
+        <ion-icon slot="icon-only" name="checkmark"></ion-icon>
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content style="height: 100%">
+  <app-unlock-form #form
+                   (onSubmit)="doSubmit($event)"
+                   (onCancel)="cancel()">
+  </app-unlock-form>
+
+  <ion-toolbar *ngIf="!mobile">
+
+    <ion-row class="ion-no-padding" nowrap>
+      <ion-col></ion-col>
+
+      <!-- buttons -->
+      <ion-col size="auto">
+        <ion-button fill="clear" color="dark" (click)="cancel()">
+          <ion-label translate>COMMON.BTN_CANCEL</ion-label>
+        </ion-button>
+
+        <ion-button [fill]="form.invalid ? 'clear' : 'solid'"
+                    [disabled]="loading || form.invalid"
+                    (click)="doSubmit()"
+                    (keyup.enter)="doSubmit()"
+                    color="tertiary">
+          <ion-label translate>COMMON.BTN_LOGIN</ion-label>
+        </ion-button>
+      </ion-col>
+    </ion-row>
+
+
+  </ion-toolbar>
+</ion-content>
diff --git a/src/app/unlock/unlock.modal.scss b/src/app/unlock/unlock.modal.scss
new file mode 100644
index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc
--- /dev/null
+++ b/src/app/unlock/unlock.modal.scss
@@ -0,0 +1 @@
+
diff --git a/src/app/unlock/unlock.modal.ts b/src/app/unlock/unlock.modal.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b9e2350b23b05c1ad518151335d903071bedf870
--- /dev/null
+++ b/src/app/unlock/unlock.modal.ts
@@ -0,0 +1,101 @@
+import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, ViewChild} from '@angular/core';
+import {ModalController} from '@ionic/angular';
+import {AccountService} from '@app/wallet/account.service';
+import {firstNotNilPromise} from '@app/shared/observables';
+import {UnlockForm} from "@app/unlock/unlock.form";
+
+export interface UnlockModalOptions {
+  title?: string;
+  expectedCode?: string;
+  minLength?: number;
+  maxLength?: number;
+}
+
+@Component({
+  selector: 'app-unlock-modal',
+  templateUrl: 'unlock.modal.html',
+  styleUrls: ['./unlock.modal.scss'],
+  changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class UnlockModal implements OnInit, UnlockModalOptions{
+
+  get loading() {
+    return this.form?.loading;
+  }
+
+  get mobile(): boolean {
+    return this.form?.mobile;
+  }
+
+  @Input() title = 'UNLOCK.TITLE';
+  @Input() expectedCode: string = null;
+  @Input() minLength: number = 5;
+  @Input() maxLength: number = 5;
+
+  @ViewChild('form', { static: true }) private form: UnlockForm;
+
+  constructor(private accountService: AccountService,
+              private viewCtrl: ModalController,
+              private cd: ChangeDetectorRef
+              ) {
+  }
+
+  ngOnInit() {
+
+    this.form.markAsReady({emitEvent: false});
+    this.form.markAsLoaded();
+    this.form.enable();
+  }
+
+  cancel() {
+    this.viewCtrl.dismiss();
+  }
+
+  async doSubmit(data?: string): Promise<any> {
+    console.debug('[auth-modal] Submit...');
+    if (this.form.disabled) return;
+    if (!this.form.valid) {
+      this.form.markAllAsTouched();
+      return;
+    }
+    this.markAsLoading();
+
+    try {
+      data = data || this.form.value;
+
+      // Disable the form
+      this.form.disable();
+
+      return this.viewCtrl.dismiss(data);
+    }
+    catch (err) {
+      this.form.error = err && err.message || err;
+      this.markAsLoaded();
+
+      // Enable the form
+      this.form.enable();
+
+      // Reset form error on next changes
+      firstNotNilPromise(this.form.form.valueChanges).then(() => {
+        this.form.error = null;
+        this.markForCheck();
+      });
+
+      return;
+    }
+  }
+
+  protected markForCheck() {
+    this.cd.markForCheck();
+  }
+
+  protected markAsLoading(opts?: {emitEvent?: boolean}) {
+    this.form.markAsLoading(opts);
+    this.markForCheck();
+  }
+
+  protected markAsLoaded(opts?: {emitEvent?: boolean}) {
+    this.form.markAsLoaded(opts);
+    this.markForCheck();
+  }
+}
diff --git a/src/app/unlock/unlock.module.ts b/src/app/unlock/unlock.module.ts
index b796195f568c1a161a8fe3e37777372522d55703..82d2d7ce83763e1f40bbd8b8beb4ded2b5a10578 100644
--- a/src/app/unlock/unlock.module.ts
+++ b/src/app/unlock/unlock.module.ts
@@ -8,18 +8,23 @@ import {RegisterModal} from "@app/register/register.modal";
 import {TranslateModule} from "@ngx-translate/core";
 import {AppSharedModule} from "@app/shared/shared.module";
 import {UnlockForm} from "@app/unlock/unlock.form";
+import {UnlockModal} from "@app/unlock/unlock.modal";
 
 @NgModule({
-    imports: [
-      CommonModule,
-      FormsModule,
-      IonicModule,
-      TranslateModule,
-      AppSharedModule
-    ],
-    exports: [
-        UnlockForm
-    ],
-    declarations: [UnlockForm]
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    TranslateModule,
+    AppSharedModule
+  ],
+  declarations: [
+    UnlockForm,
+    UnlockModal
+  ],
+  exports: [
+    UnlockForm,
+    UnlockModal
+  ],
 })
 export class AppUnlockModule {}
diff --git a/src/app/wallet/account.model.ts b/src/app/wallet/account.model.ts
index b2449dad8712a587340ec2fb5b99d999b8100888..cb89529c8b0aa39a1a199ecef5841a4564bc604d 100644
--- a/src/app/wallet/account.model.ts
+++ b/src/app/wallet/account.model.ts
@@ -18,12 +18,16 @@ export interface AccountMeta {
   avatar?: string;
   email?: string;
 }
+export interface Tx {
 
+}
 export interface AccountData {
   randomId?: string;
   free?: number;
   reserved?: number;
   feeFrozen?: number;
+
+  txs: Tx[];
 }
 
 
diff --git a/src/app/wallet/account.service.ts b/src/app/wallet/account.service.ts
index d21108d195f3471e22cc7e6faba10e59b8edbe38..1690de1dd039c5ef95dab8a6f85582f8e4ed8472 100644
--- a/src/app/wallet/account.service.ts
+++ b/src/app/wallet/account.service.ts
@@ -1,4 +1,4 @@
-import {Injectable} from "@angular/core";
+import {Inject, Injectable} from "@angular/core";
 import {NetworkService} from "../network/network.service";
 import {ApiPromise, Keyring} from "@polkadot/api";
 import {Account, AccountMeta, AccountUtils} from "./account.model";
@@ -6,34 +6,76 @@ import {StartableService} from "@app/shared/services/startable-service.class";
 import {AuthData} from "@app/auth/auth.model";
 import {keyring} from "@polkadot/ui-keyring";
 import {environment} from "@environments/environment";
-import {StorageService} from "@app/shared/services/storage/storage.service";
-import {KeyringStorage} from "@app/shared/services/keyring-storage";
+import {KeyringStorage} from "@app/shared/services/storage/keyring-storage";
 import {RegisterData} from "@app/register/register.model";
 import {cryptoWaitReady, mnemonicGenerate} from '@polkadot/util-crypto';
-import {isNilOrNaN, isNotEmptyArray} from "@app/shared/functions";
-import {Inject} from "@angular/core";
-import {IStorage, APP_STORAGE} from "@app/shared/services/storage/storage.interface";
-import {BehaviorSubject, from, map, Observable, switchMap} from "rxjs";
+import {
+  isEmptyArray,
+  isNil,
+  isNilOrBlank,
+  isNilOrNaN,
+  isNotEmptyArray, isNotNil,
+  isNotNilOrBlank,
+  sleep
+} from "@app/shared/functions";
+import {APP_STORAGE, IStorage} from "@app/shared/services/storage/storage.utils";
+import {
+  BehaviorSubject,
+  debounceTime,
+  firstValueFrom,
+  from,
+  lastValueFrom,
+  map,
+  Observable,
+  skip, Subscription,
+  switchMap, timer
+} from "rxjs";
+import {ModalController} from "@ionic/angular";
+import {UnlockModal, UnlockModalOptions} from "@app/unlock/unlock.modal";
+import {Currency} from "@app/network/currency.model";
+import {SettingsService} from "@app/settings/settings.service";
+import {KeyringAddress} from "@polkadot/ui-keyring/types";
 
 const scrypt = require('scrypt-async');
+export interface LoadAccountDataOptions {
+  reload?: boolean;
+  withTx?: boolean;
+  withBalance?: boolean;
+}
 
 @Injectable({providedIn: 'root'})
 export class AccountService extends StartableService {
 
   private _$accounts = new BehaviorSubject<Account[]>([]);
   private _store = new KeyringStorage(this.storage);
+  private readonly _isDevelopment: boolean;
+  private _password: string = null;
+  private _passwordTimer: Subscription;
 
   get api(): ApiPromise {
     return this.network.api;
   }
 
+  get accounts(): Account[] {
+    return this._$accounts.value;
+  }
+
+  get isLogin(): boolean {
+    return this.started && isNotEmptyArray(this.accounts);
+  }
+
   constructor(
     protected network: NetworkService,
+    protected settings: SettingsService,
+    protected modalController: ModalController,
     @Inject(APP_STORAGE) protected storage: IStorage
   ) {
     super(network, {
-      name: 'wallet-service'
+      name: 'account-service'
     });
+
+    // DEV mode
+    this._isDevelopment = !environment.production;
   }
 
   protected async ngOnStart(): Promise<any> {
@@ -41,24 +83,52 @@ export class AccountService extends StartableService {
     // Wait crypto to be loaded by browser
     await cryptoWaitReady();
 
-    keyring.setDevMode(!environment.production);
+    const currency = this.network.currency;
+
+    // Configure keyring
+    keyring.setDevMode(this._isDevelopment);
+    keyring.setSS58Format(currency.ss58Format || 42 /* = dev format */);
 
-    // Set the default SS58 format
-    const ss58Format = this.network.currency?.ss58Format || 42; // 42 = dev format
-    keyring.setSS58Format(ss58Format);
+    // Restoring accounts
+    await this.restoreAccounts(currency);
 
+    // Add test account --- DEV only
+    if (this._isDevelopment) {
+      const auth =  environment.dev?.auth;
+      // Set password
+      this._password = auth?.password || 'AAAAA';
+
+      // Add a V1 Dev account
+      if (auth?.v1) {
+        await this.addV1Account({...auth.v1, meta: auth.meta});
+      }
+    }
+  }
+
+  async restoreAccounts(currency?: Currency) {
     // load all available addresses and accounts
     const now = Date.now();
-    console.info('Loading accounts...');
+    console.info('[account-service] Loading all accounts...');
+
+    // Prepare an observable, to known when keyring.loadAll() will be ready
+    const accounts$ = keyring.accounts.subject
+      .pipe(
+        debounceTime(250),
+        map(_ => keyring.getAccounts())
+      )
+
     keyring.loadAll({
       store: this._store,
-      ss58Format,
-      type: 'sr25519',
-      isDevelopment: !environment.production
+      ss58Format: currency?.ss58Format,
+      genesisHash: currency?.genesys,
+      isDevelopment: this._isDevelopment
     });
 
-    const keyringAddresses = keyring.getAccounts();
-    if (isNotEmptyArray(keyringAddresses)) {
+    const keyringAddresses = await firstValueFrom(accounts$);
+    if (isEmptyArray(keyringAddresses)) {
+      console.info('[account-service] Loading all accounts [OK] No account found');
+    }
+    else {
       const accounts = keyringAddresses.map(ka => {
         return <Account>{
           address: ka.address,
@@ -73,19 +143,14 @@ export class AccountService extends StartableService {
       // Load account's data
       await Promise.all(accounts.map(a => this.loadData(a)));
 
-      // Log
+      // DEBUG
       console.info(`Loading accounts [OK] ${accounts.length} accounts loaded in ${Date.now() - now}ms`);
       accounts.forEach(a => {
-        console.info(` - ${a.address} (${a.meta?.name}) - free=${a.data.free} - reserved=${a.data.reserved}`);
+        console.info(` - ${a.address} (${a.meta?.name}) - free=${a.data?.free} - reserved=${a.data?.reserved}`);
       });
 
       this._$accounts.next(accounts);
     }
-
-    // Auto login
-    if (!environment.production && environment.dev?.auth) {
-      setTimeout(() => this.login(environment.dev.auth));
-    }
   }
 
   async login(auth: AuthData): Promise<Account> {
@@ -94,14 +159,59 @@ export class AccountService extends StartableService {
     await this.ready();
 
     if (auth.v1) {
-      return this.loginV1({...auth.v1});
+      return this.addV1Account({...auth.v1, meta: auth.meta});
     }
 
     // TODO
     //return this._accounts[0];
   }
 
-  async generateNew() {
+  async auth(): Promise<boolean> {
+    if (isNotNilOrBlank(this._password)) {
+      console.debug(`${this._logPrefix}Already authenticated. Skip`);
+      return true; // ok
+    }
+
+    console.debug(`${this._logPrefix}Not auth: opening unlock modal...`);
+
+    const modal = await this.modalController.create({
+      component: UnlockModal,
+      componentProps: <UnlockModalOptions>{
+      }
+    });
+    await modal.present();
+    const {data, role} = await modal.onWillDismiss();
+
+    // User cancelled
+    if (isNilOrBlank(data)) {
+      console.debug(`${this._logPrefix}Not auth: cancelled`);
+      return false;
+    }
+
+    this._password = data as string;
+
+    // Un auth after a delay
+    this._passwordTimer?.unsubscribe();
+    const resetDelay = Math.max(this.settings.data?.unAuthDelayMs || 0, 5000); // 5s min
+    this._passwordTimer = timer(resetDelay)
+      .subscribe(() => {
+
+        if (isNotNil(this._password)) {
+          this._password = null;
+
+          // Lock all pairs
+          (this._$accounts.value || [])
+            .map(a => keyring.getPair(a.address))
+            .filter(pair => pair.isLocked)
+            .forEach(pair => pair.lock());
+        }
+        this._passwordTimer?.unsubscribe();
+        this._passwordTimer = null;
+      });
+    return true;
+  }
+
+  async generateMnemonic() {
     if (!this.started) await this.ready();
 
     // generate a random mnemonic, 12 words in length
@@ -110,6 +220,21 @@ export class AccountService extends StartableService {
     return mnemonic;
   }
 
+  async createAddress(data: RegisterData, save?: boolean): Promise<Account> {
+    // add the account, encrypt the stored JSON with an account-specific password
+    const { pair, json } = keyring.addUri(data.mnemonic, data.password, {
+      name: data.meta?.name || 'default',
+      genesisHash: this.network.currency?.genesys
+    }, 'sr25519');
+
+    return {
+      address: json.address,
+      meta: {
+        name: data.meta?.name
+      }
+    };
+  }
+
   async register(data: RegisterData): Promise<boolean> {
 
     // add the account, encrypt the stored JSON with an account-specific password
@@ -118,8 +243,6 @@ export class AccountService extends StartableService {
       genesisHash: this.network.currency?.genesys
     }, 'sr25519');
 
-    keyring.saveAccount(pair, data.password);
-
     //this.debug('check pair', pair, json);
 
     await this.addAccount({
@@ -136,11 +259,11 @@ export class AccountService extends StartableService {
     let accounts = this._$accounts.value || [];
     const existingAccount = accounts.find(a => a.address === account.address);
     if (existingAccount) {
-      console.warn(`Account with address '${account.address}' already added. Skip`);
+      console.warn(`${this._logPrefix}Account with address '${account.address}' already added. Skip`);
       account = existingAccount;
     }
     else {
-      console.info(`Add account with address '${account.address}'`);
+      console.info(`${this._logPrefix}Add account with address '${account.address}'`);
 
       // Define as default
       if (account.default || accounts.length === 1) await this.setDefaultAccount(account, accounts);
@@ -208,7 +331,7 @@ export class AccountService extends StartableService {
     // && keyring.isAvailable(address);
   }
 
-  async getDefault(opts?: { withTx?: boolean; reload?: boolean }): Promise<Account> {
+  async getDefault(opts?: LoadAccountDataOptions): Promise<Account> {
     if (!this.started) await this.ready();
 
     const accounts = this._$accounts.value || [];
@@ -227,7 +350,7 @@ export class AccountService extends StartableService {
     return await this.loadData(account, opts);
   }
 
-  async getByName(name: string, opts?: { withTx?: boolean; reload?: boolean }): Promise<Account> {
+  async getByName(name: string, opts?: LoadAccountDataOptions): Promise<Account> {
     if (!this.started) await this.ready();
 
     const accounts = this._$accounts.value || [];
@@ -238,7 +361,7 @@ export class AccountService extends StartableService {
     return await this.loadData(account, opts);
   }
 
-  async getByAddress(address: string, opts?: { withTx?: boolean; reload?: boolean }): Promise<Account> {
+  async getByAddress(address: string, opts?: LoadAccountDataOptions): Promise<Account> {
     if (!this.started) await this.ready();
 
     const accounts = this._$accounts.value || [];
@@ -264,31 +387,51 @@ export class AccountService extends StartableService {
     // the address we use to use for signing, as injected
     //const issuer = from.address ? await this.getByAddress(from.address) : await this.getByAddress(from.meta?.name);
 
-    console.info(`[account-service] Sending ${amount} :\nfrom: ${from.address}\nto ${to.address}`)
 
     const issuerAccount = await this.getByAddress(from.address);
-    const issuerPair = keyring.getPair(issuerAccount.address);
-    const toOwner = await this.isAvailable(to.address);
+    // Not enough credit
+    if (amount > issuerAccount.data.free) {
+      throw new Error('ERROR.NOT_ENOUGH_CREDIT');
+    }
+
+    console.info(`[account-service] Sending ${amount} :\nfrom: ${from.address}\nto ${to.address}`)
 
+    const issuerPair = keyring.getPair(issuerAccount.address);
     const convertedAmount = Math.floor(amount * 100);
 
-    // TODO display unlock modal if need
-    issuerPair.unlock('test');
+    // Unlock
+    if (issuerPair.isLocked) {
+      console.debug(`[account-service] Unlocking address ${from.address} ...`);
+      const isAuth = await this.auth();
+      if (!isAuth) throw new Error('ERROR.AUTH_REQUIRED');
+      issuerPair.unlock(this._password);
+    }
 
     try {
       // Sign and send a transfer from Alice to Bob
        const txHash = await this.api.tx.balances
          .transfer(to.address, convertedAmount)
-         .signAndSend(issuerPair, async ({status}) => {
+         .signAndSend(issuerPair, async ({status, events, findRecord}) => {
             if (status.isInBlock) {
-              console.info('Completed at block hash #' + status.hash.toHuman());
+              console.info(`${this._logPrefix}Completed at block hash #${status.hash.toHuman()}`);
+
+              if (this._debug) console.debug(`${this._logPrefix}Block events:`, JSON.stringify(events));
 
-              if (toOwner) {
+              await sleep(200);
+              // Update issuer account
+              //issuerAccount.data.free -= amount;
+
+              // Update receiver account
+              if (await this.isAvailable(to.address)) {
                 const toAccount = await this.getByAddress(to.address);
-                await this.loadData(toAccount);
+                //toAccount.data.free += amount;
+
+                await this.loadData(toAccount, {reload: true});
               }
 
-              await this.loadData(issuerAccount);
+              await this.loadData(issuerAccount, {reload: true});
+
+              // Notify account changes
               this.notifyChanged();
 
             } else {
@@ -308,26 +451,41 @@ export class AccountService extends StartableService {
     }
   }
 
-  private async loadData(account: Account, opts?: {reload?: boolean}): Promise<Account> {
-    if (!!account.data && opts?.reload !== true) return account; // Already loaded: skip
-
-    const {data} = await this.api.query.system.account(account.address);
+  private async loadData(account: Account, opts?: LoadAccountDataOptions): Promise<Account> {
+    opts = {
+      reload: false,
+      withBalance: true,
+      withTx: false, // disable by default
+      ...opts
+    };
+
+    // Load balance (free + reserved)
+    if (opts.withBalance === true && (isNil(account.data?.free) || opts.reload === true)) {
+      const {data} = await this.api.query.system.account(account.address);
+      account.data = {
+        ...account.data,
+        ...JSON.parse(data.toString())
+      };
+    }
 
-    account.data = JSON.parse(data.toString());
-    this.debug(`Loaded ${account.address} data:`, account.data);
+    // Load TX
+    if (opts.withTx === true && (isNil(account.data?.txs) || opts.reload === true)) {
+      console.warn('[account-service] TODO - Implement load Tx');
+    }
 
+    console.debug(`${this._logPrefix} Loaded ${account.address} data:`, account.data);
 
     return account;
   }
 
   private notifyChanged() {
-    this._$accounts.next(this._$accounts.value);
+    this._$accounts.next(this._$accounts.value.slice() /*create a copy*/);
   }
 
-  async loginV1(data: {salt: string, password: string; meta?: AccountMeta}): Promise<Account> {
+  async addV1Account(data: {salt: string, password: string; meta?: AccountMeta}): Promise<Account> {
     if (!data?.salt || !data?.password) return;
 
-    this.log('Authenticating using salt+pwd...');
+    console.info(this._logPrefix + ' Authenticating using salt+pwd...');
 
     const rawSeedString = await new Promise((resolve) => {
       scrypt(data.password, data.salt, {
@@ -339,19 +497,17 @@ export class AccountService extends StartableService {
       }, (result) => resolve(result));
     });
 
-    console.info(rawSeedString);
+    //console.debug('Computed seed (hex) from salt+pwd:', rawSeedString);
 
     const meta = {
-      name: data.meta?.name,
+      name: data.meta?.name || 'V1',
       genesisHash: this.network.currency?.genesys
     }
 
-    const {pair, json} = await keyring.addUri(`0x${rawSeedString}`, data.password, meta, 'ed25519');
+    const isAuth = await this.auth();
+    if (!isAuth) return; // Skip
 
-    pair.unlock(data.password);
-
-    keyring.saveAccount(pair, data.password);
-    keyring.addPair(pair, data.password);
+    const {pair, json} = await keyring.addUri(`0x${rawSeedString}`, this._password, meta, 'ed25519');
 
     const account = this.addAccount({
       address: json.address,
@@ -363,4 +519,12 @@ export class AccountService extends StartableService {
     return account;
   }
 
+  forgetAll() {
+    if (!this._isDevelopment) {
+      (this._$accounts.value || []).forEach(account => {
+        keyring.forgetAccount(account.address);
+      });
+    }
+    this._$accounts.next([]);
+  }
 }
diff --git a/src/app/wallet/wallet.module.ts b/src/app/wallet/wallet.module.ts
index 1c174bdf8204096fe0589434197c95040d3420c9..da74b29a70d6607b61cceaa95365345428597c14 100644
--- a/src/app/wallet/wallet.module.ts
+++ b/src/app/wallet/wallet.module.ts
@@ -5,13 +5,15 @@ import {WalletPageRoutingModule} from "./wallet-routing.module";
 import {AppSharedModule} from "@app/shared/shared.module";
 import {TranslateModule} from "@ngx-translate/core";
 import {AppAuthModule} from "@app/auth/auth.module";
+import {AppUnlockModule} from "@app/unlock/unlock.module";
 
 @NgModule({
   imports: [
     AppSharedModule,
     TranslateModule.forChild(),
     WalletPageRoutingModule,
-    AppAuthModule
+    AppAuthModule,
+    AppUnlockModule
   ],
   declarations: [WalletPage]
 })
diff --git a/src/app/wallet/wallet.page.html b/src/app/wallet/wallet.page.html
index 3b62d16fa0b0bca6123fffa08cc70cf054226ebf..dfd6313aedd9f22ea266c76b176f41a4f970a723 100644
--- a/src/app/wallet/wallet.page.html
+++ b/src/app/wallet/wallet.page.html
@@ -19,12 +19,18 @@
       </ion-select>
     </ng-container>
   </ion-toolbar>
+  <ion-progress-bar type="indeterminate" *ngIf="loading"></ion-progress-bar>
 </ion-header>
 
 <ion-content [fullscreen]="true">
   <ion-header>
     <ion-toolbar class="ion-text-end" color="secondary">
-      <ion-title size="large">{{ balance | amountFormat }}</ion-title>
+      <ion-title size="large" *ngIf="loaded; else loadingText">
+        {{ balance | amountFormat }}
+      </ion-title>
+      <ng-template #loadingText>
+        <ion-title translate>COMMON.LOADING</ion-title>
+      </ng-template>
     </ion-toolbar>
   </ion-header>
 
@@ -39,12 +45,14 @@
       <ion-item>
         <ion-icon slot="start" name="key"></ion-icon>
         <ion-label color="medium" translate>COMMON.PUBKEY</ion-label>
-        <ion-input *ngIf="loaded; else inputSkeleton"
+        <ion-input *ngIf="loaded; else skeleton60"
                    class="ion-text-end"
                    [value]="data?.address"
                    readonly>
         </ion-input>
-        <ion-button slot="end" (click)="copyAddress()" fill="clear" [title]="'COMMON.COPY'|translate">
+        <ion-button slot="end" (click)="copyAddress()"
+                    [disabled]="loading"
+                    fill="clear" [title]="'COMMON.COPY'|translate">
           <ion-icon slot="icon-only" name="copy"></ion-icon>
         </ion-button>
       </ion-item>
@@ -72,7 +80,7 @@
   </div>
 </ion-content>
 
-<ng-template #inputSkeleton>
+<ng-template #skeleton60>
   <ion-skeleton-text [animated]="true" style="width: 60%"></ion-skeleton-text>
 </ng-template>
 
diff --git a/src/app/wallet/wallet.page.ts b/src/app/wallet/wallet.page.ts
index 97a1e74e2048cb909aec17b79646208060166d82..28a0746766eaf3f0da775f21bc05afcd8c5b1dc2 100644
--- a/src/app/wallet/wallet.page.ts
+++ b/src/app/wallet/wallet.page.ts
@@ -45,12 +45,16 @@ export class WalletPage extends BasePage<Account> implements OnInit, AfterViewCh
     protected networkService: NetworkService,
     protected accountService: AccountService
   ) {
-    super(injector, {name: 'wallet-page'})
+    super(injector, {
+      name: 'wallet-page',
+      loadDueTime: accountService.started ? 0 : 250
+    })
 
     this.address = this.activatedRoute.snapshot.paramMap.get('address');
   }
 
-  ngOnInit() {
+  async ngOnInit() {
+    console.info(this._logPrefix + 'Initializing...');
     super.ngOnInit();
   }
 
@@ -58,12 +62,14 @@ export class WalletPage extends BasePage<Account> implements OnInit, AfterViewCh
 
     // force page reload, when auth was previously cancelled
     if (!this.loading && !this.data) {
+      this.info('Reloading page...');
       setTimeout(() => this.load());
     }
   }
 
   protected async ngOnLoad(): Promise<Account> {
 
+    this.info('Loading page...');
     this.currency = this.networkService.currencySign;
 
     const accounts = await this.accountService.getAll();
@@ -108,7 +114,7 @@ export class WalletPage extends BasePage<Account> implements OnInit, AfterViewCh
     if (!this.authModal.isOpen) {
       await this.authModal.present();
     }
-    const {data, role} = await this.authModal.onDidDismiss();
+    const {data, role} = await this.authModal.onWillDismiss();
     if (!data?.address) return null;
     return data;
   }
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index 5696f0fa007c2e7fc69449bd2f5b2582fe6a8bec..a0429a1f07d770de7dfe9ae2e1d3fd129321bc09 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -129,7 +129,7 @@
     "FORK_ME": "Clonez-moi !",
     "SHOW_LICENSE": "Voir la license de l'application",
     "REPORT_ISSUE": "anomalie",
-    "NOT_YOUR_ACCOUNT_QUESTION" : "Vous n'êtes pas propriétaire du compte <b class=\"ion-key\"> {{pubkey|formatPubkey}}</b>&nbsp;?",
+    "NOT_YOUR_ACCOUNT_QUESTION" : "Vous n'êtes pas propriétaire du compte <b class=\"ion-key\"> {{pubkey}}</b>&nbsp;?",
     "BTN_CHANGE_ACCOUNT": "Déconnecter ce compte",
     "CONNECTION_ERROR": "Nœud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifiez votre connexion Internet, ou changer de nœud <a class=\"positive\" ng-click=\"doQuickFix('settings')\">dans les paramètres</a>.",
     "SHOW_ALL_FEED": "Voir tout",
@@ -473,6 +473,7 @@
     "TITLE": "<i class=\"icon ion-locked\"></i> Authentification",
     "BTN_AUTH": "S'authentifier",
     "PASSPHRASE": "Code secret",
+    "PASSPHRASE_HELP": "Veuillez vous authentifier, en tapant votre code secret :",
     "GENERAL_HELP": "Veuillez vous authentifier :",
     "EXPECTED_UID_HELP": "Veuillez vous authentifier sur le compte <i class=\"ion-person\"></i> {{uid}} :",
     "EXPECTED_PUBKEY_HELP": "Veuillez vous authentifier sur le portefeuille <br class=\"visible-xs\"/><i class=\"ion-key\"></i> {{pubkey|formatPubkey}} :",
@@ -521,22 +522,22 @@
     },
     "NEW": {
       "TITLE": "Création de compte",
-      "INTRO_WARNING_TIME": "La création d'un compte sur {{name}} est très simple. Veuillez néanmoins prendre suffisament de temps pour faire correctement cette formalité (pour ne pas oublier les identifiants, mots de passe, etc.).",
+      "INTRO_WARNING_TIME": "La création d'un compte sur {{name}} est très simple. Veuillez néanmoins prendre suffisamment de temps pour faire correctement cette formalité.",
       "INTRO_WARNING_SECURITY": "Vérifiez que le matériel que vous utilisez actuellement (ordinateur, tablette, téléphone) <b>est sécurisé et digne de confiance</b>.",
       "INTRO_WARNING_SECURITY_HELP": "Anti-virus à jour, pare-feu activé, session protégée par mot de passe ou code pin, etc.",
       "INTRO_HELP": "Cliquez sur <b>Commencer</b> pour débuter la création de compte. Vous serez guidé étape par étape.",
-      "REGISTRATION_NODE": "Votre inscription sera enregistrée via le noeud Duniter <b>{{server}}</b>, qui le diffusera ensuite au reste du réseau de la monnaie.",
-      "REGISTRATION_NODE_HELP": "Si vous ne faites pas confiance en ce noeud, veuillez en changer <a ng-click=\"doQuickFix('settings')\">dans les paramètres</a> de Cesium.",
-      "SELECT_ACCOUNT_TYPE": "Choisissez le type de compte à créer :",
-      "MEMBER_ACCOUNT": "Compte membre",
-      "MEMBER_ACCOUNT_TITLE": "Création d'un compte membre",
-      "MEMBER_ACCOUNT_HELP": "Vous connaissez suffisamment la monnaie libre et vous voulez participer à sa création ?<br/>En tant qu'individu, vous pouvez créer votre compte membre (un seul par individu). Celui-ci fonctionne comme un compte simple portefeuille, mais permet en plus de co-produire la monnaie, en <b>recevant chaque {{parameters.dt|formatPeriod}} un dividende universel</b> : à vous ensuite d'en faire bon usage !",
-      "WALLET_ACCOUNT": "Compte simple portefeuille",
-      "WALLET_ACCOUNT_TITLE": "Création d'un portefeuille",
-      "WALLET_ACCOUNT_HELP": "Vous <b>découvrez la monnaie libre</b> ? Vous avez besoin d'un compte supplémentaire ?<br/>Ce type de compte vous conviendra. Bien qu'il ne co-produise la monnaie (contrairement à un compte membre - voir ci-dessous), vous pourrez y recevoir et envoyer des paiements, dès la fin de l'inscription.<br/>Si besoin, vous pourrez le transformer en compte membre ultérieurement.",
-      "SALT_WARNING": "Choisissez votre identifiant secret.<br/>Il vous sera demandé à chaque connexion sur ce compte.<br/><br/><b>Retenez le bien</b> : en cas de perte, plus personne ne pourra accéder à votre compte !",
-      "PASSWORD_WARNING": "Choisissez un mot de passe.<br/>Il vous sera demandé à chaque connexion sur ce compte.<br/><br/><b>Retenez bien ce mot de passe</b : en cas de perte, plus personne ne pourra accéder à votre compte !",
-      "PSEUDO_WARNING": "Choisissez un pseudonyme.<br/>Il sert aux autres membres, pour vous identifier plus facilement.<div class='hidden-xs'><br/>Il <b>ne pourra pas être modifié</b>, sans refaire un compte.</div><br/><br/>Il ne doit contenir <b>ni espace, ni de caractère accentué</b>.<div class='hidden-xs'><br/>Exemple : <span class='gray'>SophieDupond, MarcelChemin, etc.</span>",
+      "STEP_1_HELP": "Cesium va générer <b>phrase de restauration</b>. Elle est un peu comme un plan, qui permet de fabriquer les clefs d'accès à votre compte.",
+      "STEP_2_HELP": "Conservez cette phrase précieusement, car sans elle Cesium ne pourra pas reconstruire les clefs d'accès à votre compte. <br/>Vous en aurez besoin dès que vous devez installer Cesium sur un nouveau téléphone ou ordinateur.",
+      "STEP_3_HELP": "Dans une blockchain, pas de procédure de récupération par mail ou SMS. Seule votre phrase de restauration peut vous permettre de récupérer vos {{currency}} à tout moment.",
+      "STEP_4_HELP": "Il est temps de vous munir d'<b>un papier et d'un crayon</b> afin de pouvoir noter votre phrase de restauration.",
+      "STEP_MNEMONIC_HELP": "Voici votre phrase de restauration !<br/>Tâcher de la garder bien secrète, car quiconque la trouve pourra vider votre compte.",
+      "STEP_CHECK_WORD_HELP": "Avez-vous bien noté votre phrase de restauration ?<br/>Pour en être sûr, veuillez taper dans le champs ci-dessous le mot n°{{number}} de la phrase :",
+      "STEP_CODE_1_HELP": "<b>Un code secret</b> va maintenant être généré.<br/>Il est nécessaire pour accéder à votre compte sur cet appareil, sans avoir à utiliser la phrase de restauration.",
+      "STEP_CODE_2_HELP": "Ce code secret a aussi pour but de <b>protèger aussi votre compte</b>. C'est pourquoi <b>vous seul devez le posséder</b>.",
+      "STEP_CODE_3_HELP": "Voici votre code secret !<br/>Mémorisez-le parfaitement, ou notez-le, car il vous sera demandé <b>à chaque fois</b> que voudrez effectuer un paiement sur cet appareil. Un peu comme le code pin pour un paiement par carte bancaire.",
+      "STEP_CHECK_CODE_HELP": "Pour vérifier que vous avez bien mémorisé ou noté votre code secret, veuillez le taper ci-dessous :",
+      "STEP_CONGRATULATION_1_HELP": "Bravo ! Tout est prêt pour créer votre compte.<br/><br/>Celui-ci aura le <b>numéro de compte</b> suivant :",
+      "STEP_CONGRATULATION_2_HELP": "Cesium pourra aussi afficher ce numéro de compte <b>sous une forme plus compacte</b> :",
       "PSEUDO": "Pseudonyme",
       "PSEUDO_HELP": "Pseudonyme",
       "SALT_CONFIRM": "Confirmation",
diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts
index cfebbcfd4e0d64baa7d2169136a9e7977af03814..3c8d152d50fdf17c649539aacae5d3fd6e90534e 100644
--- a/src/environments/environment.prod.ts
+++ b/src/environments/environment.prod.ts
@@ -1,4 +1,5 @@
 import {Environment} from "./environment.class";
+import {StorageDrivers} from "@app/shared/services/storage/storage.utils";
 
 export const environment = <Environment>{
   production: true,
@@ -8,7 +9,7 @@ export const environment = <Environment>{
 
   // Storage
   storage: {
-    driverOrder: ['sqlite', 'indexeddb', 'websql', 'localstorage']
+    driverOrder: [StorageDrivers.IndexedDB, StorageDrivers.WebSQL, StorageDrivers.LocalStorage]
   },
 
   defaultPeers: [
diff --git a/src/environments/environment.ts b/src/environments/environment.ts
index 9b1ef9850964b2795be1db67dca74885886a550e..847c8054ea297a3794b83cc119fdf53d08170bb6 100644
--- a/src/environments/environment.ts
+++ b/src/environments/environment.ts
@@ -5,9 +5,9 @@
 import {Environment} from "./environment.class";
 import {AuthData} from "@app/auth/auth.model";
 import {Drivers} from "@ionic/storage";
+import {StorageDrivers} from "@app/shared/services/storage/storage.utils";
 
 export const environment = <Environment>{
-  //production: true,
   production: false,
 
   name: 'Cesium',
@@ -17,7 +17,7 @@ export const environment = <Environment>{
   // Storage
   storage: {
     name: 'cesium',
-    driverOrder: ['localForage-cordovaSQLiteDriver', Drivers.IndexedDB, Drivers.LocalStorage]
+    driverOrder: [StorageDrivers.IndexedDB, StorageDrivers.WebSQL, StorageDrivers.LocalStorage]
   },
 
   keyring: {
diff --git a/src/global.scss b/src/global.scss
index d854de84ad51a90443ccfe6396cc2a26ee783959..8c42b86b87c5a269ef8d8c52511ab33fd6c75416 100644
--- a/src/global.scss
+++ b/src/global.scss
@@ -1,26 +1,21 @@
-/*
- * App Global CSS
- * ----------------------------------------------------------------------------
- * Put style rules here that you want to apply globally. These styles are for
- * the entire app and not just one component. Additionally, this file can be
- * used as an entry point to import other CSS/Sass files to be included in the
- * output CSS.
- * For more information on global stylesheets, visit the documentation:
- * https://ionicframework.com/docs/layout/global-stylesheets
- */
+@import "theme";
 
-/* Core CSS required for Ionic components to work properly */
-@import "~@ionic/angular/css/core.css";
+* {
+  @include font-roboto();
+}
 
-/* Basic CSS for apps built with Ionic */
-@import "~@ionic/angular/css/normalize.css";
-@import "~@ionic/angular/css/structure.css";
-@import "~@ionic/angular/css/typography.css";
-@import '~@ionic/angular/css/display.css';
+// --------------------------------------------------
+// Inject theme colors (as CSS variables)
+// --------------------------------------------------
+:root {
+  @include css-variables-to-root();
 
-/* Optional CSS utils that can be commented out */
-@import "~@ionic/angular/css/padding.css";
-@import "~@ionic/angular/css/float-elements.css";
-@import "~@ionic/angular/css/text-alignment.css";
-@import "~@ionic/angular/css/text-transformation.css";
-@import "~@ionic/angular/css/flex-utils.css";
+  // Extra small device
+  @media screen and (max-width: #{$screen-xs-max}) {
+    --mat-toolbar-height: mat.$toolbar-height-mobile;
+  }
+
+  ion-icon {
+    pointer-events: none !important;
+  }
+}
diff --git a/src/theme/_cesium.globals.scss b/src/theme/_cesium.globals.scss
index 9cfe7ec1520af1bbb04a630063622bf73be4bb9b..ddeb4ca6c79e13cd4027a75fde7341cdd1c081f2 100644
--- a/src/theme/_cesium.globals.scss
+++ b/src/theme/_cesium.globals.scss
@@ -1,5 +1,6 @@
 $app-menu-width: 255px !default;
 
 $app-toolbar-height: 60px !default; // = $mat-toolbar-height-mobile + 4 (progress bar);
-
 $app-footer-height: 56px !default;
+
+$app-popover-width: 320px !default;;
diff --git a/src/theme/_cesium.scss b/src/theme/_cesium.scss
new file mode 100644
index 0000000000000000000000000000000000000000..247c9b186284ff15d3210ed755c697ea5efcd611
--- /dev/null
+++ b/src/theme/_cesium.scss
@@ -0,0 +1,9 @@
+
+.select-popover-large .popover-content{
+  width: #{$app-popover-width} !important;
+}
+
+.cdk-visually-hidden {
+  display: none;
+  visibility: hidden;
+}
diff --git a/src/theme/_functions.scss b/src/theme/_functions.scss
new file mode 100644
index 0000000000000000000000000000000000000000..73564c8b05600a8b33f984e9bea849c5167e94a5
--- /dev/null
+++ b/src/theme/_functions.scss
@@ -0,0 +1,7 @@
+//@use './ionic/ionic.functions.string';
+//@use './ionic/ionic.functions.color';
+
+@function calculateRem($size) {
+  $remSize: $size / 16px;
+  @return $remSize * 1rem;
+}
diff --git a/src/theme/_globals.scss b/src/theme/_globals.scss
new file mode 100644
index 0000000000000000000000000000000000000000..5b12ff88f7c9ced83e4dd538c6f01a4f070a0836
--- /dev/null
+++ b/src/theme/_globals.scss
@@ -0,0 +1,4 @@
+@import "functions";
+@import "mixins";
+@import "ionic.globals";
+@import "cesium.globals";
diff --git a/src/theme/_ionic.globals.scss b/src/theme/_ionic.globals.scss
index 103001a3645703b15547c4275b5df748b6ede673..103d6828087104e76580eb63d3a7fda6e78a10d6 100644
--- a/src/theme/_ionic.globals.scss
+++ b/src/theme/_ionic.globals.scss
@@ -75,6 +75,12 @@ $ion-grid-padding: 16px !default;
 $ion-padding: 16px !default;
 $ion-margin: 16px !default;
 
+// Popover
+// --------------------------------------------------
+$popover-md-width: 320px;
+$popover-ios-width: 320px;
+$popover-wp-width: 320px;
+
 // --------------------------------------------------
 // Default General Colors
 // --------------------------------------------------
diff --git a/src/theme/_ionic.scss b/src/theme/_ionic.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e389be30941f9ec3fcc819af37190aad6a7ae992
--- /dev/null
+++ b/src/theme/_ionic.scss
@@ -0,0 +1,25 @@
+/*
+ * App Global CSS
+ * ----------------------------------------------------------------------------
+ * Put style rules here that you want to apply globally. These styles are for
+ * the entire app and not just one component. Additionally, this file can be
+ * used as an entry point to import other CSS/Sass files to be included in the
+ * output CSS.
+ * For more information on global stylesheets, visit the documentation:
+ * https://ionicframework.com/docs/layout/global-stylesheets
+ */
+/* Core CSS required for Ionic components to work properly */
+@import "~@ionic/angular/css/core.css";
+
+/* Basic CSS for apps built with Ionic */
+@import "~@ionic/angular/css/normalize.css";
+@import "~@ionic/angular/css/structure.css";
+@import "~@ionic/angular/css/typography.css";
+@import '~@ionic/angular/css/display.css';
+
+/* Optional CSS utils that can be commented out */
+@import "~@ionic/angular/css/padding.css";
+@import "~@ionic/angular/css/float-elements.css";
+@import "~@ionic/angular/css/text-alignment.css";
+@import "~@ionic/angular/css/text-transformation.css";
+@import "~@ionic/angular/css/flex-utils.css";
diff --git a/src/theme/_mixins.scss b/src/theme/_mixins.scss
new file mode 100644
index 0000000000000000000000000000000000000000..08c97222e7cabf23b4e384f6966451f62ae710c6
--- /dev/null
+++ b/src/theme/_mixins.scss
@@ -0,0 +1,105 @@
+
+@mixin font-size($size) {
+  font-size: calculateRem($size);
+}
+
+@mixin font-size-important($size) {
+  font-size: calculateRem($size) !important;
+}
+
+
+@mixin font-roboto($size: false, $colour: false, $weight: false, $lh: false) {
+  font-family: 'Roboto', Helvetica, Arial, sans-serif;
+
+  @if $size {
+    font-size: $size;
+  }
+
+  @if $colour {
+    color: $colour;
+  }
+
+  @if $weight {
+    font-weight: $weight;
+  }
+
+  @if $lh {
+    line-height: $lh;
+  }
+}
+
+@mixin color($color-name) {
+  $value: map-get($colors, $color-name);
+  $base: map-get($value, base);
+
+  color: var(--ion-color-#{""+$color-name}, $base);
+}
+
+/**
+* Define CSS theme colors
+*/
+@mixin generate-color($color-name) {
+  $value: map-get($colors, $color-name);
+  $base: map-get($value, base);
+  $contrast: map-get($value, contrast);
+  $shade: map-get($value, shade);
+  $tint: map-get($value, tint);
+  --ion-color-base: var(--ion-color-#{""+$color-name},
+    #{$base}) !important;
+  --ion-color-base-rgb: var(--ion-color-#{""+$color-name}-rgb,
+    #{color-to-rgb-list($base)}) !important;
+  --ion-color-contrast: var(--ion-color-#{""+$color-name}-contrast,
+    #{$contrast}) !important;
+  --ion-color-contrast-rgb: var(--ion-color-#{""+$color-name}-contrast-rgb,
+    #{color-to-rgb-list($contrast)}) !important;
+  --ion-color-shade: var(--ion-color-#{""+$color-name}-shade,
+    #{$shade}) !important;
+  --ion-color-tint: var(--ion-color-#{""+$color-name}-tint,
+    #{$tint}) !important;
+}
+
+@mixin generate-color-list($color-name) {
+  $value: map-get($colors, $color-name);
+  $base: map-get($value, base);
+  $contrast: map-get($value, contrast);
+  $shade: map-get($value, shade);
+  $tint: map-get($value, tint);
+  --ion-color-#{""+$color-name} : #{$base};
+  --ion-color-#{""+$color-name}-rgb: #{color-to-rgb-list($base)};
+  --ion-color-#{""+$color-name}-contrast: #{$contrast};
+  --ion-color-#{""+$color-name}-contrast-rgb: #{color-to-rgb-list($contrast)};
+  --ion-color-#{""+$color-name}-shade: #{$shade};
+  --ion-color-#{""+$color-name}-tint: #{$tint};
+}
+
+@mixin set-color-each-ion-colors($element-name) {
+
+  @each $color-name, $value in $colors {
+    #{$element-name}.ion-color-#{""+$color-name} {
+      color: var(--ion-color-base);
+    }
+  }
+}
+
+@mixin css-variables-to-root() {
+
+  @each $color-name,
+  $value in $colors {
+    .ion-color-#{""+$color-name} {
+      @include generate-color($color-name);
+    }
+  }
+
+  @each $color-name,
+  $value in $colors {
+    @include generate-color-list($color-name);
+  }
+
+  --ion-grid-column-padding: #{$ion-grid-column-padding};
+  --ion-padding: #{$ion-padding};
+  --ion-margin: #{$ion-margin};
+
+  --ion-toolbar-height: #{56px};
+
+}
+
diff --git a/src/theme/_theme.scss b/src/theme/_theme.scss
new file mode 100644
index 0000000000000000000000000000000000000000..4666bc7ed02466a21c368a05327139eb8d57dffd
--- /dev/null
+++ b/src/theme/_theme.scss
@@ -0,0 +1,12 @@
+// --------------------------------------------------
+// Import globals (variables, functions and mixins)
+// --------------------------------------------------
+@import "globals";
+// --------------------------------------------------
+// Import Ionic style
+// --------------------------------------------------
+@import "ionic";
+// --------------------------------------------------
+// Import SUMARiS style
+// --------------------------------------------------
+@import "cesium";