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.
		
		
		
		
		
			
		
			
				
					
					
						
							156 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							156 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>
							 | 
						|
								        Derive from Existing Identity
							 | 
						|
								      </h1>
							 | 
						|
								    </div>
							 | 
						|
								    <!-- Import Account Form -->
							 | 
						|
								
							 | 
						|
								    <div>
							 | 
						|
								      <p class="text-center text-xl mb-4 font-light">
							 | 
						|
								        Will increment the maximum known derivation path from the existing seed.
							 | 
						|
								      </p>
							 | 
						|
								
							 | 
						|
								      <p v-if="didArrays.length > 1">
							 | 
						|
								        Choose existing DIDs from same seed phrase to compute derivation.
							 | 
						|
								      </p>
							 | 
						|
								      <ul class="mb-4">
							 | 
						|
								        <li
							 | 
						|
								          class="block bg-slate-100 rounded-md flex items-center px-4 py-3 mb-2"
							 | 
						|
								          v-for="dids in didArrays"
							 | 
						|
								          :key="dids[0]"
							 | 
						|
								          @click="switchAccount(dids[0])"
							 | 
						|
								        >
							 | 
						|
								          <fa
							 | 
						|
								            v-if="dids[0] == selectedArrayFirstDid"
							 | 
						|
								            icon="circle"
							 | 
						|
								            class="fa-fw text-blue-400 text-xl mr-3"
							 | 
						|
								          ></fa>
							 | 
						|
								          <fa
							 | 
						|
								            v-else
							 | 
						|
								            icon="circle"
							 | 
						|
								            class="fa-fw text-slate-400 text-xl mr-3"
							 | 
						|
								          ></fa>
							 | 
						|
								          <span class="overflow-hidden">
							 | 
						|
								            <div class="text-sm text-slate-500 truncate">
							 | 
						|
								              <code>{{ dids.join(",") }}</code>
							 | 
						|
								            </div>
							 | 
						|
								          </span>
							 | 
						|
								        </li>
							 | 
						|
								      </ul>
							 | 
						|
								    </div>
							 | 
						|
								    <div class="mt-8">
							 | 
						|
								      <div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
							 | 
						|
								        <button
							 | 
						|
								          @click="incrementDerivation()"
							 | 
						|
								          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"
							 | 
						|
								        >
							 | 
						|
								          Increment and 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 {
							 | 
						|
								  DEFAULT_ROOT_DERIVATION_PATH,
							 | 
						|
								  deriveAddress,
							 | 
						|
								  newIdentifier,
							 | 
						|
								  nextDerivationPath,
							 | 
						|
								} from "@/libs/crypto";
							 | 
						|
								import { accountsDB, db } from "@/db/index";
							 | 
						|
								import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
							 | 
						|
								
							 | 
						|
								@Component({
							 | 
						|
								  components: {},
							 | 
						|
								})
							 | 
						|
								export default class ImportAccountView extends Vue {
							 | 
						|
								  derivationPath = DEFAULT_ROOT_DERIVATION_PATH;
							 | 
						|
								  didArrays: Array<Array<string>> = [];
							 | 
						|
								  selectedArrayFirstDid = "";
							 | 
						|
								
							 | 
						|
								  async mounted() {
							 | 
						|
								    await accountsDB.open();
							 | 
						|
								    const accounts = await accountsDB.accounts.toArray();
							 | 
						|
								    const seedDids: Record<string, Array<string>> = {};
							 | 
						|
								    accounts.forEach((account) => {
							 | 
						|
								      const prevDids: Array<string> = seedDids[account.mnemonic] || [];
							 | 
						|
								      seedDids[account.mnemonic] = prevDids.concat([account.did]);
							 | 
						|
								    });
							 | 
						|
								    this.didArrays = Object.values(seedDids);
							 | 
						|
								    this.selectedArrayFirstDid = this.didArrays[0][0];
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public onCancelClick() {
							 | 
						|
								    this.$router.back();
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public switchAccount(did: string) {
							 | 
						|
								    this.selectedArrayFirstDid = did;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public async incrementDerivation() {
							 | 
						|
								    await accountsDB.open();
							 | 
						|
								    // find the maximum derivation path for the selected DIDs
							 | 
						|
								    const selectedArray: Array<string> =
							 | 
						|
								      this.didArrays.find((dids) => dids[0] === this.selectedArrayFirstDid) ||
							 | 
						|
								      [];
							 | 
						|
								    const allMatchingAccounts = await accountsDB.accounts
							 | 
						|
								      .where("did")
							 | 
						|
								      .anyOf(...selectedArray)
							 | 
						|
								      .toArray();
							 | 
						|
								    const accountWithMaxDeriv = allMatchingAccounts[0];
							 | 
						|
								    allMatchingAccounts.slice(1).forEach((account) => {
							 | 
						|
								      if (account.derivationPath > accountWithMaxDeriv.derivationPath) {
							 | 
						|
								        accountWithMaxDeriv.derivationPath = account.derivationPath;
							 | 
						|
								      }
							 | 
						|
								    });
							 | 
						|
								    // increment the last number in that max derivation path
							 | 
						|
								    const newDerivPath = nextDerivationPath(accountWithMaxDeriv.derivationPath);
							 | 
						|
								
							 | 
						|
								    const mne: string = accountWithMaxDeriv.mnemonic;
							 | 
						|
								
							 | 
						|
								    const [address, privateHex, publicHex] = deriveAddress(mne, newDerivPath);
							 | 
						|
								
							 | 
						|
								    const newId = newIdentifier(address, publicHex, privateHex, newDerivPath);
							 | 
						|
								
							 | 
						|
								    try {
							 | 
						|
								      await accountsDB.accounts.add({
							 | 
						|
								        dateCreated: new Date().toISOString(),
							 | 
						|
								        derivationPath: newDerivPath,
							 | 
						|
								        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" });
							 | 
						|
								    } catch (err) {
							 | 
						|
								      console.error("Error saving mnemonic & updating settings:", err);
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								</script>
							 | 
						|
								
							 |