Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add comments and cleanup codes #655

Merged
merged 1 commit into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CommonError } from '@common/errors/common';
import { StorageMigrator, StorageModelLatest } from '@migrates/storage-migrator';
import { Storage } from '.';

// Define the valid types of storage keys
type StorageKeyTypes =
| 'NETWORKS'
| 'CURRENT_CHAIN_ID'
Expand All @@ -19,6 +20,7 @@ type StorageKeyTypes =
| 'ACCOUNT_GRC721_COLLECTIONS'
| 'ACCOUNT_GRC721_PINNED_PACKAGES';

// List of all available storage keys
const StorageKeys: StorageKeyTypes[] = [
'NETWORKS',
'CURRENT_CHAIN_ID',
Expand All @@ -37,11 +39,14 @@ const StorageKeys: StorageKeyTypes[] = [
'ACCOUNT_GRC721_PINNED_PACKAGES',
];

// Function to validate if a given key is a valid storage key
function isStorageKey(key: string): key is StorageKeyTypes {
return StorageKeys.some((storageKey) => storageKey === key);
}

// Class to handle Chrome's local storage with migration support
export class ChromeLocalStorage implements Storage {
// Define the main storage key for the application
private static StorageKey = 'ADENA_DATA';

private storage: chrome.storage.LocalStorageArea;
Expand Down Expand Up @@ -71,10 +76,12 @@ export class ChromeLocalStorage implements Storage {
};

public remove = async (key: string): Promise<void> => {
return this.set(key, '');
await this.set(key, '');
await this.storage.remove(key);
};

public clear = async (): Promise<void> => {
await this.storage.set({ [ChromeLocalStorage.StorageKey]: '{}' });
await this.storage.clear();
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class ChromeSessionStorage implements Storage {
};

public remove = async (key: string): Promise<void> => {
await this.set(key, '');
await this.storage.remove(key);
};

Expand Down
3 changes: 2 additions & 1 deletion packages/adena-extension/src/common/utils/amount-utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { GNOT_TOKEN } from '@common/constants/token.constant';
import { Amount } from '@types';
import BigNumber from 'bignumber.js';
import { convertTextToAmount } from './string-utils';
Expand All @@ -19,7 +20,7 @@ export function makeGnotAmountByRaw(amountRaw: string): Amount | null {
return gnotAmount;
}

export function parseTokenAmount(tokenAmount: string, denomination = 'ugnot'): number {
export function parseTokenAmount(tokenAmount: string, denomination = GNOT_TOKEN.denom): number {
const pattern = new RegExp(`^(\\d+)${denomination}$`);
const match = tokenAmount.match(pattern);

Expand Down
5 changes: 4 additions & 1 deletion packages/adena-extension/src/common/utils/crypto-utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { v4 as uuidv4 } from 'uuid';
import CryptoJS from 'crypto-js';
import { v4 as uuidv4 } from 'uuid';

// Static cipher key used for encrypting the cryptographic key
const ENCRYPT_CIPHER_KEY = 'r3v4';

export const encryptSha256Password = (password: string): string => {
return CryptoJS.SHA256(password).toString();
};

// Encrypts a password with a dynamically generated key and returns the encrypted key and password
export const encryptPassword = (
password: string,
): { encryptedKey: string; encryptedPassword: string } => {
Expand All @@ -20,6 +22,7 @@ export const encryptPassword = (
};
};

// Decrypts a password using the encrypted key and password
export const decryptPassword = (encryptedKey: string, encryptedPassword: string): string => {
const adenaKey = ENCRYPT_CIPHER_KEY;
const key = CryptoJS.AES.decrypt(encryptedKey, adenaKey).toString(CryptoJS.enc.Utf8);
Expand Down
3 changes: 2 additions & 1 deletion packages/adena-extension/src/hooks/use-faucet.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { GNOT_TOKEN } from '@common/constants/token.constant';
import { waitForRun } from '@common/utils/timeout-utils';
import { FaucetResponse } from '@repositories/common/response';
import { useMutation, useQuery } from '@tanstack/react-query';
Expand All @@ -11,7 +12,7 @@ export type UseFaucetReturn = {
faucet: () => Promise<{ success: boolean; message: string }>;
};

const FAUCET_AMOUNT = 10_000_000 + 'ugnot';
const FAUCET_AMOUNT = 10_000_000 + GNOT_TOKEN.denom;

const FAUCET_UNEXPECTED_ERROR_MESSAGES = 'Unexpected Errors.';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe('StorageMigrator', () => {
const migrated = await migrator.migrate(current);

expect(migrated).not.toBeNull();
expect(migrated?.version).toBe(7);
expect(migrated?.version).toBe(8);
expect(migrated?.data).not.toBeNull();
expect(migrated?.data.NETWORKS).toHaveLength(3);
expect(migrated?.data.CURRENT_CHAIN_ID).toBe('');
Expand All @@ -89,7 +89,7 @@ describe('StorageMigrator', () => {
const migrated = await migrator.migrate(current);

expect(migrated).not.toBeNull();
expect(migrated?.version).toBe(7);
expect(migrated?.version).toBe(8);
expect(migrated?.data).not.toBeNull();
expect(migrated?.data.SERIALIZED).not.toBe('');
expect(migrated?.data.ADDRESS_BOOK).toBe('');
Expand Down
32 changes: 27 additions & 5 deletions packages/adena-extension/src/migrates/storage-migrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { StorageMigration006 } from './migrations/v006/storage-migration-v006';
import { StorageModelV006 } from './migrations/v006/storage-model-v006';
import { StorageMigration007 } from './migrations/v007/storage-migration-v007';
import { StorageModelV007 } from './migrations/v007/storage-model-v007';
import { StorageMigration008 } from './migrations/v008/storage-migration-v008';
import { StorageModelV008 } from './migrations/v008/storage-model-v008';
import { Migration, Migrator } from './migrator';

const LegacyStorageKeys = [
Expand All @@ -27,8 +29,10 @@ const LegacyStorageKeys = [
'ACCOUNT_TOKEN_METAINFOS',
];

export type StorageModelLatest = StorageModelV007;
// The latest storage model type
export type StorageModelLatest = StorageModelV008;

// Default data structure for version 1 storage model
const defaultData: StorageModelDataV001 = {
ACCOUNT_NAMES: {},
ADDRESS_BOOK: {},
Expand All @@ -42,24 +46,28 @@ const defaultData: StorageModelDataV001 = {
ACCOUNT_TOKEN_METAINFOS: {},
};

// Storage interface with set and get methods
interface Storage {
set(items: { [key: string]: any }): Promise<void>;
get(keys?: string | string[] | { [key: string]: any } | null): Promise<{ [key: string]: any }>;
}

// Handles storage migrations and serialization/deserialization of storage data
export class StorageMigrator implements Migrator {
private static StorageKey = 'ADENA_DATA';

constructor(
private migrations: Migration[],
private storage: Storage,
private password?: string,
private migrations: Migration[], // Array of migration strategies
private storage: Storage, // Storage interface for data persistence
private password?: string, // Password for encryption (optional)
) {}

// Sets the encryption password
setPassword(password: string): void {
this.password = password;
}

// Validates if the data can be saved
async saveable(): Promise<boolean | '' | undefined> {
const current = await this.getCurrent();
const latestVersion = Math.max(...this.migrations.map((m) => m.version));
Expand All @@ -72,13 +80,16 @@ export class StorageMigrator implements Migrator {
return this.password && this.password.length > 0;
}

// Serializes the storage model to a string
async serialize(data: StorageModel<unknown>): Promise<string> {
return JSON.stringify(data);
}

// Deserializes a string into the corresponding storage model
async deserialize(
data: string | undefined,
): Promise<
| StorageModelV008
| StorageModelV007
| StorageModelV006
| StorageModelV005
Expand All @@ -98,7 +109,9 @@ export class StorageMigrator implements Migrator {
return this.mappedJson(jsonData);
}

// Retrieves the current storage data, performing deserialization
async getCurrent(): Promise<
| StorageModelV008
| StorageModelV007
| StorageModelV006
| StorageModelV005
Expand All @@ -118,7 +131,8 @@ export class StorageMigrator implements Migrator {
};
}

async migrate(current: StorageModel): Promise<StorageModelV007 | null> {
// Migrates storage data to the latest version
async migrate(current: StorageModel): Promise<StorageModelV008 | null> {
let latest = current;
try {
const currentVersion = current.version || 1;
Expand All @@ -137,6 +151,7 @@ export class StorageMigrator implements Migrator {
return latest as StorageModelLatest;
}

// Saves the latest version of the storage data
async save(latest: StorageModel): Promise<void> {
if (!(await this.saveable())) {
throw new Error('Unable to save');
Expand All @@ -147,16 +162,19 @@ export class StorageMigrator implements Migrator {
});
}

// Creates a backup of the current storage data
private async backup(current: StorageModel): Promise<void> {
const backupStorageKey = `${StorageMigrator.StorageKey}_${Date.now()}`;
const savedData = await this.serialize(current);
await this.storage.set({ [backupStorageKey]: savedData });
}

// Maps JSON data to the corresponding storage model version
private async mappedJson(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
json: any,
): Promise<
| StorageModelV008
| StorageModelV007
| StorageModelV006
| StorageModelV005
Expand All @@ -165,6 +183,9 @@ export class StorageMigrator implements Migrator {
| StorageModelV002
| StorageModelV001
> {
if (json?.version === 8) {
return json as StorageModelV008;
}
if (json?.version === 7) {
return json as StorageModelV007;
}
Expand Down Expand Up @@ -218,6 +239,7 @@ export class StorageMigrator implements Migrator {
new StorageMigration005(),
new StorageMigration006(),
new StorageMigration007(),
new StorageMigration008(),
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
WalletResponseRejectType,
WalletResponseSuccessType,
} from '@adena-wallet/sdk';
import { GNOT_TOKEN } from '@common/constants/token.constant';
import {
createFaviconByHostname,
decodeParameter,
Expand Down Expand Up @@ -153,7 +154,7 @@ const ApproveTransactionContainer: React.FC = () => {
if (!currentAddress || !gnoProvider) {
return;
}
gnoProvider.getBalance(currentAddress, 'ugnot').then(setCurrentBalance);
gnoProvider.getBalance(currentAddress, GNOT_TOKEN.denom).then(setCurrentBalance);
});
}, [getCurrentAddress, gnoProvider]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React, { useCallback, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';

import { GNOT_TOKEN } from '@common/constants/token.constant';
import { DEFAULT_GAS_WANTED } from '@common/constants/tx.constant';
import NFTTransferSummary from '@components/pages/nft-transfer-summary/nft-transfer-summary/nft-transfer-summary';
import { useGetGRC721TokenUri } from '@hooks/nft/use-get-grc721-token-uri';
Expand Down Expand Up @@ -86,7 +87,7 @@ const NFTTransferSummaryContainer: React.FC = () => {
return false;
}

const currentBalance = await gnoProvider.getBalance(currentAddress, 'ugnot');
const currentBalance = await gnoProvider.getBalance(currentAddress, GNOT_TOKEN.denom);
const networkFee = summaryInfo.networkFee.value;
return BigNumber(currentBalance).shiftedBy(-6).isGreaterThanOrEqualTo(networkFee);
}, [gnoProvider, currentAddress, summaryInfo]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';

import UnknownTokenIcon from '@assets/common-unknown-token.svg';
import { GNOT_TOKEN } from '@common/constants/token.constant';
import { DEFAULT_GAS_WANTED } from '@common/constants/tx.constant';
import { isGRC20TokenModel, isNativeTokenModel } from '@common/validation/validation-token';
import TransferSummary from '@components/pages/transfer-summary/transfer-summary/transfer-summary';
Expand Down Expand Up @@ -115,7 +116,7 @@ const TransferSummaryContainer: React.FC = () => {
return false;
}

const currentBalance = await gnoProvider.getBalance(currentAddress, 'ugnot');
const currentBalance = await gnoProvider.getBalance(currentAddress, GNOT_TOKEN.denom);
const networkFee = summaryInfo.networkFee.value;
return BigNumber(currentBalance).shiftedBy(-6).isGreaterThanOrEqualTo(networkFee);
}, [gnoProvider, currentAddress, summaryInfo]);
Expand Down
Loading
Loading