Skip to content

Commit

Permalink
Merge branch 'feature/web3-id' of github.com:Concordium/concordium-br…
Browse files Browse the repository at this point in the history
…owser-wallet into fix-import-popup
  • Loading branch information
orhoj committed Aug 25, 2023
2 parents 4c04567 + 3b33356 commit a8ffba1
Show file tree
Hide file tree
Showing 12 changed files with 195 additions and 25 deletions.
1 change: 1 addition & 0 deletions packages/browser-wallet/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Fixed

- An issue where the import window would fail to open.
- Updated the JSON schema for the verifiable credential schema validation, so that invalid schemas are rejected.

## 1.1.2

Expand Down
2 changes: 1 addition & 1 deletion packages/browser-wallet/src/popup/pages/Account/i18n/da.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ const t: typeof en = {
},
'3': {
title: 'Opdateringer med længere cool-downs',
body: 'Hvis du vælger at formindske din delegation saldo, så vil ændringen træde i kraft efter en cool-down periode.\n\nI løbet af denne cool-down periode, vil delegation saldoen være låst og kan ikke ændres, og du vil ikke kunne stoppe delegation.\n\nDu vil stadig få fortjenester i cool-down perioden, og du vil stadig kunne ændre andre delegationindstillinger.n\n.Hvis du laver andre ændringer samtidigt med at du formindsker delegation saldoen, vil disse ændringer træde i kraft ved den næste pay day, som beskrevet på sidste side.',
body: 'Hvis du vælger at formindske din delegation saldo, så vil ændringen træde i kraft efter en cool-down periode.\n\nI løbet af denne cool-down periode, vil delegation saldoen være låst og kan ikke ændres, og du vil ikke kunne stoppe delegation.\n\nDu vil stadig få fortjenester i cool-down perioden, og du vil stadig kunne ændre andre delegationindstillinger.\n\nHvis du laver andre ændringer samtidigt med at du formindsker delegation saldoen, vil disse ændringer træde i kraft ved den næste pay day, som beskrevet på sidste side.',
},
},
removeIntro: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { APIVerifiableCredential } from '@concordium/browser-wallet-api-helpers'
import { networkConfigurationAtom } from '@popup/store/settings';
import { MetadataUrl } from '@concordium/browser-wallet-api-helpers/lib/wallet-api-types';
import { parse } from '@shared/utils/payload-helpers';
import { logError } from '@shared/utils/log-helpers';
import { VerifiableCredentialCard } from '../VerifiableCredential/VerifiableCredentialCard';

type Props = {
Expand Down Expand Up @@ -81,7 +82,10 @@ export default function AddWeb3IdCredential({ onAllow, onReject }: Props) {
}
return fetchCredentialMetadata(metadataUrl, controller);
},
() => setError(t('error.metadata')),
(e) => {
setError(t('error.metadata'));
logError(e);
},
[verifiableCredentialMetadata.loading]
);

Expand All @@ -97,7 +101,10 @@ export default function AddWeb3IdCredential({ onAllow, onReject }: Props) {
}
return fetchCredentialSchema({ url: schemaUrl }, controller);
},
() => setError(t('error.schema')),
(e) => {
setError(t('error.schema'));
logError(e);
},
[schemas.loading]
);

Expand Down Expand Up @@ -138,7 +145,10 @@ export default function AddWeb3IdCredential({ onAllow, onReject }: Props) {

return fetchLocalization(currentLanguageLocalization, controller);
},
() => setError('Failed to get localization'),
(e) => {
setError(t('error.localization'));
logError(e);
},
[metadata, i18n]
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const t: typeof en = {
metadata: en.error.metadata,
schema: en.error.schema,
attribute: en.error.attribute,
localization: en.error.localization,
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const t = {
metadata: 'We are unable to load the metadata for the credential.',
schema: 'We are unable to load the schema specification for the credential.',
attribute: 'The received credential is missing one or more required attributes ({{ attributeKeys }})',
localization: 'Failed to get localization',
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
import { AsyncWrapper } from '@popup/store/utils';
import { ConcordiumGRPCClient } from '@concordium/web-sdk';
import { useTranslation } from 'react-i18next';
import { noOp } from 'wallet-common-helpers';
import { logError } from '@shared/utils/log-helpers';

/**
* Retrieve the on-chain credential status for a verifiable credential in a CIS-4 credential registry contract.
Expand All @@ -36,7 +36,10 @@ export function useCredentialStatus(credential: VerifiableCredential) {
useEffect(() => {
getVerifiableCredentialStatus(client, credential.id)
.then(setStatus)
.catch(() => setStatus(VerifiableCredentialStatus.Pending));
.catch((e) => {
setStatus(VerifiableCredentialStatus.Pending);
logError(e);
});
}, [credential.id, client]);

return status;
Expand Down Expand Up @@ -83,7 +86,7 @@ export function useCredentialEntry(credential?: VerifiableCredential) {
.then((entry) => {
setCredentialEntry(entry);
})
.catch(noOp); // TODO add logging on catch?
.catch(logError);
}
}, [credential?.id, client]);

Expand Down Expand Up @@ -176,7 +179,10 @@ export function useCredentialLocalization(credential?: VerifiableCredential): Lo
// TODO Validate that localization is present for all keys.
setLocalization({ loading: false, result: res });
})
.catch(() => setLocalization({ loading: false }));
.catch((e) => {
setLocalization({ loading: false });
logError(e);
});

return () => {
abortController.abort();
Expand All @@ -199,10 +205,12 @@ export function useIssuerMetadata(issuer: string): IssuerMetadata | undefined {

useEffect(() => {
const registryContractAddress = getCredentialRegistryContractAddress(issuer);
getCredentialRegistryMetadata(client, registryContractAddress).then((res) => {
const abortController = new AbortController();
fetchIssuerMetadata(res.issuerMetadata, abortController).then(setIssuerMetadata);
});
getCredentialRegistryMetadata(client, registryContractAddress)
.then((res) => {
const abortController = new AbortController();
fetchIssuerMetadata(res.issuerMetadata, abortController).then(setIssuerMetadata).catch(logError);
})
.catch(logError);
}, [client, issuer]);

return issuerMetadata;
Expand Down Expand Up @@ -234,11 +242,13 @@ export function useFetchingEffect<T>(
const abortControllers: AbortController[] = [];

if (!credentials.loading && credentials.value.length !== 0 && !storedData.loading) {
dataFetcher(credentials.value, client, abortControllers, storedData.value).then((result) => {
if (!isCancelled && result.updateReceived) {
setStoredData(result.data);
}
});
dataFetcher(credentials.value, client, abortControllers, storedData.value)
.then((result) => {
if (!isCancelled && result.updateReceived) {
setStoredData(result.data);
}
})
.catch(logError);
}

return () => {
Expand Down
2 changes: 2 additions & 0 deletions packages/browser-wallet/src/popup/store/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
storedVerifiableCredentialMetadata,
sessionVerifiableCredentials,
sessionVerifiableCredentialMetadataUrls,
storedLog,
} from '@shared/storage/access';
import { ChromeStorageKey } from '@shared/storage/types';
import { atom, PrimitiveAtom, WritableAtom } from 'jotai';
Expand Down Expand Up @@ -71,6 +72,7 @@ const accessorMap: Record<ChromeStorageKey, StorageAccessor<any>> = {
sessionVerifiableCredentialMetadataUrls,
getGenesisHash
),
[ChromeStorageKey.Log]: storedLog,
};

export function resetOnUnmountAtom<V>(initial: V): PrimitiveAtom<V> {
Expand Down
2 changes: 2 additions & 0 deletions packages/browser-wallet/src/shared/storage/access.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { stringify } from '@concordium/browser-wallet-api/src/util';
import { parse } from '@shared/utils/payload-helpers';
import { VerifiableCredentialMetadata } from '@shared/utils/verifiable-credential-helpers';
import { Log } from '@shared/utils/log-helpers';
import {
ChromeStorageKey,
EncryptedData,
Expand Down Expand Up @@ -205,6 +206,7 @@ const indexedStoredAllowlist = makeIndexedStorageAccessor<Record<string, string[
ChromeStorageKey.Allowlist
);
export const storedAllowlist = useIndexedStorage(indexedStoredAllowlist, getGenesisHash);
export const storedLog = makeStorageAccessor<Log[]>('local', ChromeStorageKey.Log);

export const sessionOpenPrompt = makeStorageAccessor<boolean>('session', ChromeStorageKey.OpenPrompt);
export const sessionPasscode = makeStorageAccessor<string>('session', ChromeStorageKey.Passcode);
Expand Down
1 change: 1 addition & 0 deletions packages/browser-wallet/src/shared/storage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export enum ChromeStorageKey {
TemporaryVerifiableCredentials = 'tempVerifiableCredentials',
TemporaryVerifiableCredentialMetadataUrls = 'tempVerifiableCredentialMetadataUrls',
Allowlist = 'allowlist',
Log = 'log',
}

export enum Theme {
Expand Down
22 changes: 22 additions & 0 deletions packages/browser-wallet/src/shared/storage/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,28 @@ export async function removeFromList<Type>(
});
}

/*
* Generic method to add an element to list in storage while ensuring that
* the list never grows beyond the provided size. If the list is still small
* enough, then the addition is prepended to the list. If the the list would have
* grown greater than the max size, then the addition is prepended to the list and
* the last element of the list is removed.
*/
export async function addToListMaxSize<Type>(
lock: string,
addition: Type,
storage: StorageAccessor<Type[]>,
size: number
): Promise<void> {
return navigator.locks.request(lock, async () => {
const list = (await storage.get()) || [];
if (list.length < size) {
return storage.set([addition].concat(list));
}
return storage.set([addition].concat(list.slice(0, list.length - 1)));
});
}

/**
* Generic method to edit/update elements in a list in storage
* Note that this replaces the element found by the findPredicate with the edit.
Expand Down
71 changes: 71 additions & 0 deletions packages/browser-wallet/src/shared/utils/log-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { storedLog } from '@shared/storage/access';
import { addToListMaxSize } from '@shared/storage/update';
import { isDevelopmentBuild } from './environment-helpers';

const loggingLock = 'concordium_log_lock';

// Determines the maximum number of log entries that is stored
// at a time.
const LOG_MAX_ENTRIES = 100;

export enum LoggingLevel {
INFO = 'INFO',
WARN = 'WARN',
ERROR = 'ERROR',
}

export interface Log {
timestamp: number;
level: LoggingLevel;
message: string;
}

function isError(error: unknown): error is { message: string } {
return typeof error === 'object' && error !== null && 'message' in error;
}

function logForDevelopmentBuild(logEntry: Log) {
const logMessage = `[${new Date(logEntry.timestamp).toISOString()}] ${logEntry.level} ${logEntry.message}`;
switch (logEntry.level) {
case LoggingLevel.WARN:
// eslint-disable-next-line no-console
console.warn(logMessage);
break;
case LoggingLevel.ERROR:
// eslint-disable-next-line no-console
console.error(logMessage);
break;
case LoggingLevel.INFO:
default:
// eslint-disable-next-line no-console
console.log(logMessage);
break;
}
}

async function log(message: string, level: LoggingLevel) {
const timestamp = Date.now();
const logEntry: Log = {
level,
message,
timestamp,
};

if (isDevelopmentBuild()) {
logForDevelopmentBuild(logEntry);
}

await addToListMaxSize(loggingLock, logEntry, storedLog, LOG_MAX_ENTRIES);
}

export async function logErrorMessage(message: string) {
log(message, LoggingLevel.ERROR);
}

export async function logError(error: unknown) {
if (isError(error)) {
logErrorMessage(error.message);
} else {
logErrorMessage(String(error));
}
}
Loading

0 comments on commit a8ffba1

Please sign in to comment.