You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							177 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							177 lines
						
					
					
						
							4.9 KiB
						
					
					
				
								<template>
							 | 
						|
								  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
							 | 
						|
								    <!-- Breadcrumb -->
							 | 
						|
								    <div id="ViewBreadcrumb" class="mb-8">
							 | 
						|
								      <h1 class="text-lg text-center font-light relative px-7">
							 | 
						|
								        <!-- Cancel -->
							 | 
						|
								        <button
							 | 
						|
								          @click="$router.go(-1)"
							 | 
						|
								          class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
							 | 
						|
								        >
							 | 
						|
								          <fa icon="chevron-left"></fa>
							 | 
						|
								        </button>
							 | 
						|
								        Import Existing Identifier
							 | 
						|
								      </h1>
							 | 
						|
								    </div>
							 | 
						|
								    <!-- Import Account Form -->
							 | 
						|
								    <p class="text-center text-xl mb-4 font-light">
							 | 
						|
								      Enter your seed phrase below to import your identifier on this device.
							 | 
						|
								    </p>
							 | 
						|
								    <!-- id used by puppeteer test script -->
							 | 
						|
								    <textarea
							 | 
						|
								      id="seed-input"
							 | 
						|
								      type="text"
							 | 
						|
								      placeholder="Seed Phrase"
							 | 
						|
								      class="block w-full rounded border border-slate-400 mb-4 px-3 py-2"
							 | 
						|
								      v-model="mnemonic"
							 | 
						|
								    />
							 | 
						|
								
							 | 
						|
								    <h3
							 | 
						|
								      class="text-sm uppercase font-semibold mb-3"
							 | 
						|
								      @click="showAdvanced = !showAdvanced"
							 | 
						|
								    >
							 | 
						|
								      Advanced
							 | 
						|
								    </h3>
							 | 
						|
								    <div v-if="showAdvanced">
							 | 
						|
								      Enter a custom derivation path
							 | 
						|
								      <input
							 | 
						|
								        type="text"
							 | 
						|
								        class="block w-full rounded border border-slate-400 mb-2 px-3 py-2"
							 | 
						|
								        v-model="derivationPath"
							 | 
						|
								      />
							 | 
						|
								      <span class="ml-4">
							 | 
						|
								        For previous uPort or Endorser users,
							 | 
						|
								        <a
							 | 
						|
								          @click="derivationPath = UPORT_DERIVATION_PATH"
							 | 
						|
								          class="text-blue-500"
							 | 
						|
								        >
							 | 
						|
								          click here to use that value.
							 | 
						|
								        </a>
							 | 
						|
								      </span>
							 | 
						|
								
							 | 
						|
								      <div class="mt-4" v-if="numAccounts == 1">
							 | 
						|
								        <input type="checkbox" class="mr-2" v-model="shouldErase" />
							 | 
						|
								        <label>Erase the previous identifier.</label>
							 | 
						|
								      </div>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <div class="mt-8">
							 | 
						|
								      <div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
							 | 
						|
								        <button
							 | 
						|
								          @click="fromMnemonic()"
							 | 
						|
								          class="block w-full text-center text-lg font-bold uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md"
							 | 
						|
								        >
							 | 
						|
								          Import
							 | 
						|
								        </button>
							 | 
						|
								        <button
							 | 
						|
								          @click="onCancelClick()"
							 | 
						|
								          type="button"
							 | 
						|
								          class="block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md"
							 | 
						|
								        >
							 | 
						|
								          Cancel
							 | 
						|
								        </button>
							 | 
						|
								      </div>
							 | 
						|
								    </div>
							 | 
						|
								  </section>
							 | 
						|
								</template>
							 | 
						|
								
							 | 
						|
								<script lang="ts">
							 | 
						|
								import { Component, Vue } from "vue-facing-decorator";
							 | 
						|
								
							 | 
						|
								import { NotificationIface } from "@/constants/app";
							 | 
						|
								import { accountsDB, db } from "@/db/index";
							 | 
						|
								import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
							 | 
						|
								import {
							 | 
						|
								  DEFAULT_ROOT_DERIVATION_PATH,
							 | 
						|
								  deriveAddress,
							 | 
						|
								  newIdentifier,
							 | 
						|
								} from "@/libs/crypto";
							 | 
						|
								
							 | 
						|
								@Component({
							 | 
						|
								  components: {},
							 | 
						|
								})
							 | 
						|
								export default class ImportAccountView extends Vue {
							 | 
						|
								  UPORT_DERIVATION_PATH = "m/7696500'/0'/0'/0'"; // for legacy imports, likely never used
							 | 
						|
								
							 | 
						|
								  $notify!: (notification: NotificationIface, timeout?: number) => void;
							 | 
						|
								
							 | 
						|
								  mnemonic = "";
							 | 
						|
								  address = "";
							 | 
						|
								  numAccounts = 0;
							 | 
						|
								  privateHex = "";
							 | 
						|
								  publicHex = "";
							 | 
						|
								  derivationPath = DEFAULT_ROOT_DERIVATION_PATH;
							 | 
						|
								  showAdvanced = false;
							 | 
						|
								  shouldErase = false;
							 | 
						|
								
							 | 
						|
								  async created() {
							 | 
						|
								    await accountsDB.open();
							 | 
						|
								    this.numAccounts = await accountsDB.accounts.count();
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public onCancelClick() {
							 | 
						|
								    this.$router.back();
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public async fromMnemonic() {
							 | 
						|
								    const mne: string = this.mnemonic.trim().toLowerCase();
							 | 
						|
								    try {
							 | 
						|
								      [this.address, this.privateHex, this.publicHex] = deriveAddress(
							 | 
						|
								        mne,
							 | 
						|
								        this.derivationPath,
							 | 
						|
								      );
							 | 
						|
								
							 | 
						|
								      const newId = newIdentifier(
							 | 
						|
								        this.address,
							 | 
						|
								        this.publicHex,
							 | 
						|
								        this.privateHex,
							 | 
						|
								        this.derivationPath,
							 | 
						|
								      );
							 | 
						|
								
							 | 
						|
								      await accountsDB.open();
							 | 
						|
								      if (this.shouldErase) {
							 | 
						|
								        await accountsDB.accounts.clear();
							 | 
						|
								      }
							 | 
						|
								      await accountsDB.accounts.add({
							 | 
						|
								        dateCreated: new Date().toISOString(),
							 | 
						|
								        derivationPath: this.derivationPath,
							 | 
						|
								        did: newId.did,
							 | 
						|
								        identity: JSON.stringify(newId),
							 | 
						|
								        mnemonic: mne,
							 | 
						|
								        publicKeyHex: newId.keys[0].publicKeyHex,
							 | 
						|
								      });
							 | 
						|
								
							 | 
						|
								      // record that as the active DID
							 | 
						|
								      await db.open();
							 | 
						|
								      db.settings.update(MASTER_SETTINGS_KEY, {
							 | 
						|
								        activeDid: newId.did,
							 | 
						|
								      });
							 | 
						|
								      this.$router.push({ name: "account" });
							 | 
						|
								      // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								    } catch (err: any) {
							 | 
						|
								      console.error("Error saving mnemonic & updating settings:", err);
							 | 
						|
								      if (err == "Error: invalid mnemonic") {
							 | 
						|
								        this.$notify(
							 | 
						|
								          {
							 | 
						|
								            group: "alert",
							 | 
						|
								            type: "danger",
							 | 
						|
								            title: "Invalid Mnemonic",
							 | 
						|
								            text: "Please check your mnemonic and try again.",
							 | 
						|
								          },
							 | 
						|
								          -1,
							 | 
						|
								        );
							 | 
						|
								      } else {
							 | 
						|
								        this.$notify(
							 | 
						|
								          {
							 | 
						|
								            group: "alert",
							 | 
						|
								            type: "danger",
							 | 
						|
								            title: "Error",
							 | 
						|
								            text: "Got an error creating that identifier.",
							 | 
						|
								          },
							 | 
						|
								          -1,
							 | 
						|
								        );
							 | 
						|
								      }
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								</script>
							 | 
						|
								
							 |