Skip to content

Commit

Permalink
feat: vks birthdays (#1415)
Browse files Browse the repository at this point in the history
* feat: wip vks birthdays

* feat: pass dated viewing keys

* feat: integrate with backend

* feat: vault migrations

* fix: cr commnets, store timestamp 0 for imported accounts

* fix: remove source from returned transparent account
  • Loading branch information
mateuszjasiuk authored Dec 27, 2024
1 parent 9af3ad3 commit 294031d
Show file tree
Hide file tree
Showing 31 changed files with 549 additions and 200 deletions.
2 changes: 2 additions & 0 deletions apps/extension/src/Setup/Setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ export const Setup: React.FC = () => {
...accountCreationDetails,
path,
accountSecret,
flow: "create",
});
navigate(routes.accountCreationComplete());
}
Expand Down Expand Up @@ -329,6 +330,7 @@ export const Setup: React.FC = () => {
...accountCreationDetails,
path,
accountSecret,
flow: "import",
});
navigate(routes.accountImportComplete());
}
Expand Down
9 changes: 5 additions & 4 deletions apps/extension/src/Setup/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ export class AccountManager {
async saveAccountSecret(
details: DeriveAccountDetails
): Promise<AccountStore> {
const { accountSecret, alias, path } = details;
const { accountSecret, alias, path, flow } = details;
const derivationPath =
accountSecret?.t === "PrivateKey" ? DEFAULT_BIP44_PATH : path;

const parentAccountStore =
await this.requester.sendMessage<SaveAccountSecretMsg>(
Ports.Background,
new SaveAccountSecretMsg(accountSecret, alias, derivationPath)
new SaveAccountSecretMsg(accountSecret, alias, flow, derivationPath)
);

return parentAccountStore as AccountStore;
Expand All @@ -65,15 +65,16 @@ export class AccountManager {
const derivationPath =
accountSecret?.t === "PrivateKey" ? DEFAULT_BIP44_PATH : path;

const { alias, id } = parentAccount;
const { alias, id, source } = parentAccount;
return await this.requester.sendMessage<DeriveAccountMsg>(
Ports.Background,
new DeriveAccountMsg(
derivationPath,
AccountType.ShieldedKeys,
alias,
// Sets the parent ID of this shielded account
id
id,
source
)
);
}
Expand Down
1 change: 1 addition & 0 deletions apps/extension/src/Setup/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type AccountDetails = {
};

export type DeriveAccountDetails = AccountDetails & {
flow: "create" | "import";
accountSecret: AccountSecret;
path: Bip44Path;
passwordRequired?: boolean;
Expand Down
14 changes: 10 additions & 4 deletions apps/extension/src/background/keyring/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ const handleSaveAccountSecretMsg: (
service: KeyRingService
) => InternalHandler<SaveAccountSecretMsg> = (service) => {
return async (_, msg) => {
const { accountSecret, alias, path } = msg;
const { accountSecret, alias, flow, path } = msg;
if (accountSecret) {
return await service.saveAccountSecret(accountSecret, alias, path);
return await service.saveAccountSecret(accountSecret, alias, flow, path);
}
return false;
};
Expand All @@ -159,8 +159,14 @@ const handleDeriveAccountMsg: (
service: KeyRingService
) => InternalHandler<DeriveAccountMsg> = (service) => {
return async (_, msg) => {
const { path, accountType, alias, parentId } = msg;
return await service.deriveAccount(path, accountType, alias, parentId);
const { path, accountType, alias, parentId, source } = msg;
return await service.deriveAccount(
path,
accountType,
alias,
parentId,
source
);
};
};

Expand Down
21 changes: 18 additions & 3 deletions apps/extension/src/background/keyring/keyring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ export class KeyRing {
owner: address,
path: bip44Path,
type: AccountType.Ledger,
source: "imported",
timestamp: 0,
};

const sensitive = await this.vaultService.encryptSensitiveData({
Expand Down Expand Up @@ -154,11 +156,14 @@ export class KeyRing {
public async storeAccountSecret(
accountSecret: AccountSecret,
alias: string,
flow: "create" | "import",
path: Bip44Path = { account: 0, change: 0, index: 0 }
): Promise<AccountStore> {
await this.vaultService.assertIsUnlocked();

const keys = this.sdkService.getSdk().getKeys();
const source = flow === "create" ? "generated" : "imported";
const timestamp = source === "generated" ? new Date().getTime() : 0;

const { sk, text, passphrase, accountType } = ((): {
sk: string;
Expand Down Expand Up @@ -227,6 +232,8 @@ export class KeyRing {
path,
publicKey,
type: accountType,
source,
timestamp,
};
const sensitiveData: SensitiveAccountStoreData = { text, passphrase };
const sensitive =
Expand Down Expand Up @@ -363,7 +370,9 @@ export class KeyRing {
parentId: string,
type: AccountType,
alias: string,
derivedAccountInfo: DerivedAccountInfo
derivedAccountInfo: DerivedAccountInfo,
source: "imported" | "generated",
timestamp: number
): Promise<DerivedAccount> {
const { address, id, text, owner, pseudoExtendedKey } = derivedAccountInfo;
const account: AccountStore = {
Expand All @@ -375,6 +384,8 @@ export class KeyRing {
type,
owner,
pseudoExtendedKey,
source,
timestamp,
};
const sensitive = await this.vaultService.encryptSensitiveData({
text,
Expand All @@ -394,7 +405,8 @@ export class KeyRing {
bip44Path: Bip44Path,
type: AccountType,
alias: string,
parentId: string
parentId: string,
source: "imported" | "generated"
): Promise<DerivedAccount> {
await this.vaultService.assertIsUnlocked();

Expand Down Expand Up @@ -437,12 +449,15 @@ export class KeyRing {
);
}

const timestamp = source === "generated" ? new Date().getTime() : 0;
const derivedAccount = await this.persistAccount(
type === AccountType.ShieldedKeys ? zip32Path : derivationPath,
parentId,
type,
alias,
info
info,
source,
timestamp
);
return derivedAccount;
}
Expand Down
10 changes: 8 additions & 2 deletions apps/extension/src/background/keyring/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,17 @@ export class SaveAccountSecretMsg extends Message<AccountStore | false> {
constructor(
public readonly accountSecret: AccountSecret,
public readonly alias: string,
public readonly flow: "create" | "import",
public readonly path?: Bip44Path
) {
super();
}

validate(): void {
if (!this.flow) {
throw new Error("Flow is required!");
}

if (!this.accountSecret) {
throw new Error("A wordlist or private key is required!");
}
Expand Down Expand Up @@ -222,13 +227,14 @@ export class DeriveAccountMsg extends Message<DerivedAccount> {
public readonly path: Bip44Path,
public readonly accountType: AccountType,
public readonly alias: string,
public readonly parentId: string
public readonly parentId: string,
public readonly source: "imported" | "generated"
) {
super();
}

validate(): void {
validateProps(this, ["path", "accountType", "alias", "parentId"]);
validateProps(this, ["path", "accountType", "alias", "parentId", "source"]);

const { account, change } = this.path;

Expand Down
8 changes: 6 additions & 2 deletions apps/extension/src/background/keyring/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@ export class KeyRingService {
async saveAccountSecret(
accountSecret: AccountSecret,
alias: string,
flow: "create" | "import",
path?: Bip44Path
): Promise<AccountStore> {
const results = await this._keyRing.storeAccountSecret(
accountSecret,
alias,
flow,
path
);
await this.broadcaster.updateAccounts();
Expand Down Expand Up @@ -103,13 +105,15 @@ export class KeyRingService {
path: Bip44Path,
type: AccountType,
alias: string,
parentId: string
parentId: string,
source: "imported" | "generated"
): Promise<DerivedAccount> {
const account = await this._keyRing.deriveAccount(
path,
type,
alias,
parentId
parentId,
source
);
await this.broadcaster.updateAccounts();
return account;
Expand Down
2 changes: 2 additions & 0 deletions apps/extension/src/background/keyring/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export interface AccountStore extends StoredRecord {
parentId?: string;
pseudoExtendedKey?: string;
type: AccountType;
source: "imported" | "generated";
timestamp: number;
}

export type AccountState = DerivedAccount & {
Expand Down
6 changes: 4 additions & 2 deletions apps/extension/src/background/vault/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ export class VaultService {
) {}

public async initialize(): Promise<void> {
const storage = await this.vaultStorage.get();
if (!storage) {
const exists = await this.vaultStorage.exists();
if (!exists) {
await this.vaultStorage.reset();
} else {
await this.vaultStorage.migrate();
}
}

Expand Down
2 changes: 2 additions & 0 deletions apps/extension/src/background/vault/tests/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const getKeyStore = (id: string, alias: string): KeyStoreType => ({
index: 0,
},
type: AccountType.Mnemonic,
source: "generated",
timestamp: 0,
});

describe("Testing untouched Vault Service", () => {
Expand Down
8 changes: 6 additions & 2 deletions apps/extension/src/provider/data.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { KdfType } from "@namada/sdk/web";
import { AccountType, BridgeType, Chain, Extensions } from "@namada/types";
import { ActiveAccountStore } from "background/keyring";
import { Vault } from "background/vault";
import { VaultTypes } from "storage";
import { KeyStoreType } from "storage";

export const ACTIVE_ACCOUNT: ActiveAccountStore = {
id: "324bfe0e-cb19-5f1a-9630-9daaaecadabe",
Expand All @@ -30,7 +30,7 @@ export const chain: Chain = {
},
};

export const keyStore: Vault<VaultTypes>[] = [
export const keyStore: Vault<KeyStoreType>[] = [
{
public: {
alias: "Parent Account",
Expand All @@ -47,6 +47,8 @@ export const keyStore: Vault<VaultTypes>[] = [
},
publicKey: undefined,
type: ACTIVE_ACCOUNT.type,
timestamp: 0,
source: "generated",
},
sensitive: {
cipher: {
Expand Down Expand Up @@ -90,6 +92,8 @@ export const keyStore: Vault<VaultTypes>[] = [
},
publicKey: undefined,
type: AccountType.PrivateKey,
timestamp: 0,
source: "generated",
},
sensitive: {
cipher: {
Expand Down
7 changes: 5 additions & 2 deletions apps/extension/src/storage/VaultStorage.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { AccountType } from "@namada/types";
import { KVStoreMock } from "test/init";
import { KeyStore, VaultStorage } from "./VaultStorage";
import { VaultStorage } from "./VaultStorage";
import { KeyStore } from "./schemas";

jest.mock("webextension-polyfill", () => ({}));

Expand Down Expand Up @@ -40,7 +41,7 @@ const addNonSensitiveData = async (
): Promise<void> => {
await vaultStorage.set({
data: {
test: [
"key-store": [
{
public: {
id: `${id}`,
Expand All @@ -49,6 +50,8 @@ const addNonSensitiveData = async (
owner: `test-${id}`,
path: { account: 0, change: 0, index: 0 },
type: AccountType.Mnemonic,
source: "generated",
timestamp: 0,
},
sensitive: {} as any,
},
Expand Down
Loading

1 comment on commit 294031d

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.