Skip to content

Commit

Permalink
Save temporary VCmetadata to display pending VC + handle credentialEn…
Browse files Browse the repository at this point in the history
…try not existing
  • Loading branch information
Hjort committed Aug 23, 2023
1 parent be7e52c commit 8061655
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 12 deletions.
6 changes: 6 additions & 0 deletions packages/browser-wallet/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Fixed

- Show verifiable credentials in overview before they are put on chain.

## 1.1.1

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useLocation } from 'react-router-dom';
import ExternalRequestLayout from '@popup/page-layouts/ExternalRequestLayout';
import Button from '@popup/shared/Button';
import {
sessionTemporaryVerifiableCredentialMetadataAtom,
sessionTemporaryVerifiableCredentialsAtom,
storedVerifiableCredentialMetadataAtom,
storedVerifiableCredentialsAtom,
Expand Down Expand Up @@ -51,6 +52,7 @@ export default function AddWeb3IdCredential({ onAllow, onReject }: Props) {
const { onClose, withClose } = useContext(fullscreenPromptContext);
const [acceptButtonDisabled, setAcceptButtonDisabled] = useState<boolean>(false);
const [web3IdCredentials, setWeb3IdCredentials] = useAtom(sessionTemporaryVerifiableCredentialsAtom);
const [tempMetdata, setTempMetadata] = useAtom(sessionTemporaryVerifiableCredentialMetadataAtom);
const storedWeb3IdCredentials = useAtomValue(storedVerifiableCredentialsAtom);
const [verifiableCredentialMetadata, setVerifiableCredentialMetadata] = useAtom(
storedVerifiableCredentialMetadataAtom
Expand Down Expand Up @@ -144,18 +146,20 @@ export default function AddWeb3IdCredential({ onAllow, onReject }: Props) {
const credentialHolderId = wallet.getVerifiableCredentialPublicKey(issuer, index).toString('hex');
const credentialSubjectId = createPublicKeyIdentifier(credentialHolderId, network);
const credentialSubject = { ...credential.credentialSubject, id: credentialSubjectId };
const credentialId = createCredentialId(credentialHolderId, issuer, network);

const fullCredential = {
...credential,
credentialSubject,
id: createCredentialId(credentialHolderId, issuer, network),
id: credentialId,
index,
};
await setWeb3IdCredentials([...web3IdCredentials.value, fullCredential]);
if (metadata) {
const newMetadata = { ...verifiableCredentialMetadata.value };
newMetadata[metadataUrl.url] = metadata;
await setVerifiableCredentialMetadata(newMetadata);
await setTempMetadata({ ...tempMetdata.value, [credentialId]: metadata });
}
return credentialSubjectId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ import { useEffect, useState } from 'react';
import {
storedVerifiableCredentialMetadataAtom,
storedVerifiableCredentialSchemasAtom,
sessionTemporaryVerifiableCredentialMetadataAtom,
} from '@popup/store/verifiable-credential';
import { AsyncWrapper } from '@popup/store/utils';
import { ConcordiumGRPCClient } from '@concordium/web-sdk';
import { useTranslation } from 'react-i18next';
import { noOp } from 'wallet-common-helpers';

/**
* Retrieve the on-chain credential status for a verifiable credential in a CIS-4 credential registry contract.
Expand Down Expand Up @@ -77,9 +79,11 @@ export function useCredentialEntry(credential?: VerifiableCredential) {
if (credential) {
const credentialHolderId = getCredentialHolderId(credential.id);
const registryContractAddress = getCredentialRegistryContractAddress(credential.id);
getVerifiableCredentialEntry(client, registryContractAddress, credentialHolderId).then((entry) => {
setCredentialEntry(entry);
});
getVerifiableCredentialEntry(client, registryContractAddress, credentialHolderId)
.then((entry) => {
setCredentialEntry(entry);
})
.catch(noOp); // TODO add logging on catch?
}
}, [credential?.id, client]);

Expand All @@ -97,6 +101,7 @@ export function useCredentialMetadata(credential?: VerifiableCredential) {
const [metadata, setMetadata] = useState<VerifiableCredentialMetadata>();
const credentialEntry = useCredentialEntry(credential);
const storedMetadata = useAtomValue(storedVerifiableCredentialMetadataAtom);
const tempMetadata = useAtomValue(sessionTemporaryVerifiableCredentialMetadataAtom);

useEffect(() => {
if (!storedMetadata.loading && credentialEntry) {
Expand All @@ -107,8 +112,14 @@ export function useCredentialMetadata(credential?: VerifiableCredential) {
);
}
setMetadata(storedCredentialMetadata);
} else if (!storedMetadata.loading && !credentialEntry && !tempMetadata.loading && credential) {
// Use temporary metadata
const tMetadata = tempMetadata.value[credential.id];
if (tMetadata) {
setMetadata(tMetadata);
}
}
}, [storedMetadata, credentialEntry]);
}, [storedMetadata.loading, tempMetadata.loading, credentialEntry, credential?.id]);

return metadata;
}
Expand Down
5 changes: 5 additions & 0 deletions packages/browser-wallet/src/popup/store/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
storedAllowlist,
storedVerifiableCredentialMetadata,
sessionVerifiableCredentials,
sessionVerifiableCredentialMetadata,
} from '@shared/storage/access';
import { ChromeStorageKey } from '@shared/storage/types';
import { atom, PrimitiveAtom, WritableAtom } from 'jotai';
Expand Down Expand Up @@ -66,6 +67,10 @@ const accessorMap: Record<ChromeStorageKey, StorageAccessor<any>> = {
[ChromeStorageKey.VerifiableCredentialMetadata]: storedVerifiableCredentialMetadata,
[ChromeStorageKey.Allowlist]: storedAllowlist,
[ChromeStorageKey.TemporaryVerifiableCredentials]: useIndexedStorage(sessionVerifiableCredentials, getGenesisHash),
[ChromeStorageKey.TemporaryVerifiableCredentialMetadata]: useIndexedStorage(
sessionVerifiableCredentialMetadata,
getGenesisHash
),
};

export function resetOnUnmountAtom<V>(initial: V): PrimitiveAtom<V> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ export const storedVerifiableCredentialMetadataAtom = atomWithChromeStorage<
export const sessionTemporaryVerifiableCredentialsAtom = atomWithChromeStorage<
Omit<VerifiableCredential, 'signature' | 'randomness'>[]
>(ChromeStorageKey.TemporaryVerifiableCredentials, [], true);

export const sessionTemporaryVerifiableCredentialMetadataAtom = atomWithChromeStorage<
Record<string, VerifiableCredentialMetadata>
>(ChromeStorageKey.TemporaryVerifiableCredentialMetadata, {}, true);
4 changes: 4 additions & 0 deletions packages/browser-wallet/src/shared/storage/access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,7 @@ export const sessionPendingTransactions = makeIndexedStorageAccessor<string[]>(
export const sessionVerifiableCredentials = makeSerializedAndIndexedStorageAccessor<
Omit<VerifiableCredential, 'signature' | 'randomness'>[]
>('session', ChromeStorageKey.TemporaryVerifiableCredentials);

export const sessionVerifiableCredentialMetadata = makeIndexedStorageAccessor<
Record<string, VerifiableCredentialMetadata>
>('session', ChromeStorageKey.TemporaryVerifiableCredentialMetadata);
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 @@ -30,6 +30,7 @@ export enum ChromeStorageKey {
VerifiableCredentialSchemas = 'verifiableCredentialSchemas',
VerifiableCredentialMetadata = 'verifiableCredentialMetadata',
TemporaryVerifiableCredentials = 'tempVerifiableCredentials',
TemporaryVerifiableCredentialMetadata = 'tempVerifiableCredentialMetadata',
Allowlist = 'allowlist',
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -809,13 +809,17 @@ export async function getCredentialMetadata(
) {
const metadataUrls: MetadataUrl[] = [];
for (const vc of credentials) {
const entry = await getVerifiableCredentialEntry(
client,
getCredentialRegistryContractAddress(vc.id),
getCredentialHolderId(vc.id)
);
if (entry) {
metadataUrls.push(entry.credentialInfo.metadataUrl);
try {
const entry = await getVerifiableCredentialEntry(
client,
getCredentialRegistryContractAddress(vc.id),
getCredentialHolderId(vc.id)
);
if (entry) {
metadataUrls.push(entry.credentialInfo.metadataUrl);
}
} catch (e) {
// If we fail, the credential most likely doesn't exist and we skip it
}
}

Expand Down

0 comments on commit 8061655

Please sign in to comment.