diff --git a/packages/core/src/credential-provider.ts b/packages/core/src/credential-provider.ts index 7d60772b..9db77ff8 100644 --- a/packages/core/src/credential-provider.ts +++ b/packages/core/src/credential-provider.ts @@ -113,6 +113,8 @@ export async function addCredential({wallet, credential}) { }); } + syncCredentialStatus({ wallet, credentialIds: [credential.id] }); + return response; } @@ -203,10 +205,11 @@ async function syncCredentialStatus({ wallet, credentialIds, forceFetch }: SyncC continue; } - statusDoc.status = CredentialStatus.Pending; - statusDoc.updatedAt = new Date().toISOString(); - - await wallet.updateDocument(statusDoc); + if (!statusDoc.status) { + statusDoc.status = CredentialStatus.Pending; + statusDoc.updatedAt = new Date().toISOString(); + await wallet.updateDocument(statusDoc); + } if (!isApiConnected) { await dockService.ensureDockReady(); diff --git a/packages/core/src/wallet.ts b/packages/core/src/wallet.ts index 4a95f517..a2300b70 100644 --- a/packages/core/src/wallet.ts +++ b/packages/core/src/wallet.ts @@ -123,12 +123,14 @@ export async function createWallet( return result; }); }, - removeDocument: (id: string) => { + removeDocument: async (id: string) => { + const document = await wallet.getDocumentById(id); + return removeDocument({ dataStore, id, }).then(result => { - eventEmitter.emit(WalletEvents.documentRemoved, result); + eventEmitter.emit(WalletEvents.documentRemoved, document); return result; }); }, diff --git a/packages/react-native/lib/credentials/credentialHooks.js b/packages/react-native/lib/credentials/credentialHooks.js index 5e8d9717..f3972710 100644 --- a/packages/react-native/lib/credentials/credentialHooks.js +++ b/packages/react-native/lib/credentials/credentialHooks.js @@ -1,8 +1,7 @@ import {useMemo, useCallback, useState, useEffect} from 'react'; -import {useDocument, useWallet} from '../index'; +import {useDocument, useDocuments} from '../index'; import assert from 'assert'; -import axios from 'axios'; -import { getCredentialProvider } from '../wallet'; +import { getCredentialProvider, getWallet } from '../wallet'; export const sortByIssuanceDate = (a, b) => getCredentialTimestamp(b) - getCredentialTimestamp(a); @@ -34,20 +33,14 @@ export function waitFor(condition, timeout) { } export function useCredentialUtils() { - const { documents, wallet } = useWallet(); + const {documents, loading} = useDocuments({ + type: 'VerifiableCredential', + }); const credentials = useMemo(() => { - if (Array.isArray(documents)) { - return documents - .filter(doc => { - return ( - doc.type === 'VerifiableCredential' || - doc.type?.includes('VerifiableCredential') - ); - }) - .sort(sortByIssuanceDate); - } - return []; + return documents + .filter(doc => !!doc.id) + .sort(sortByIssuanceDate); }, [documents]); const doesCredentialExist = useCallback((allCredentials, credentialToAdd) => { @@ -60,9 +53,9 @@ export function useCredentialUtils() { typeof credentialId === 'string' && credentialId.length > 0, 'Credential ID is not set', ); - return await wallet.remove(credentialId); + return await getWallet().remove(credentialId); }, - [wallet], + [], ); return useMemo(() => { @@ -70,8 +63,9 @@ export function useCredentialUtils() { credentials, doesCredentialExist, deleteCredential, + loading, }; - }, [credentials, doesCredentialExist, deleteCredential]); + }, [credentials, doesCredentialExist, deleteCredential, loading]); } export function useCredentialStatus({ credential }: any) { diff --git a/packages/react-native/lib/index.tsx b/packages/react-native/lib/index.tsx index 4e84e403..e2b87083 100644 --- a/packages/react-native/lib/index.tsx +++ b/packages/react-native/lib/index.tsx @@ -16,7 +16,10 @@ import WebView from 'react-native-webview'; import {WebviewEventHandler} from './message-handler'; import AsyncStorage from '@react-native-async-storage/async-storage'; import {AccountDetails} from '@docknetwork/wallet-sdk-wasm/src/modules/account'; -import {DocumentType, WalletDocument} from '@docknetwork/wallet-sdk-wasm/src/types'; +import { + DocumentType, + WalletDocument, +} from '@docknetwork/wallet-sdk-wasm/src/types'; import './rn-rpc-server'; import {useDIDManagement} from './didHooks'; import {useAccounts} from './accountsHooks'; @@ -24,7 +27,7 @@ import { useCredentialUtils, useCredentialStatus, } from './credentials/credentialHooks'; -import {getOrCreateWallet} from './wallet'; +import {getOrCreateWallet, getWallet} from './wallet'; import debounce from 'lodash.debounce'; import {setV1LocalStorage} from '@docknetwork/wallet-sdk-data-store/src/migration/migration1/v1-data-store'; import {IWallet} from '@docknetwork/wallet-sdk-core/src/types'; @@ -51,10 +54,7 @@ export const WalletSDKContext = React.createContext({ setStorage(AsyncStorage); export {useAccounts}; export {useDIDManagement}; -export { - useCredentialUtils, - useCredentialStatus, -}; +export {useCredentialUtils, useCredentialStatus}; export function getStorage() { return AsyncStorage; } @@ -103,34 +103,73 @@ export function useAccount(address) { }; } +const useEventListener = (eventManager, eventNames, listener) => { + useEffect(() => { + eventNames.forEach(eventName => eventManager.on(eventName, listener)); + return () => + eventNames.forEach(eventName => + eventManager.removeListener(eventName, listener), + ); + }, [eventManager, eventNames, listener]); +}; + +const events = [ + WalletEvents.documentAdded, + WalletEvents.documentRemoved, + WalletEvents.documentUpdated, +]; + export function useDocument(id) { - const {wallet} = useWallet(); const [document, setDocument] = useState(null); - useEffect(() => { - console.log('useDocument', id, wallet); - async function refetchDocument(updatedDoc) { + const refetchDocument = useCallback( + async updatedDoc => { if (updatedDoc.id !== id) return; - const _doc = await wallet.getDocumentById(id); - setDocument(_doc); - } + const doc = await getWallet().getDocumentById(id); + setDocument(doc); + }, + [id], + ); - setDocument(wallet.getDocumentById(id)) + useEffect(() => { + getWallet().getDocumentById(id).then(setDocument); + }, [id]); - wallet.eventManager.on(WalletEvents.documentAdded, refetchDocument); - wallet.eventManager.on(WalletEvents.documentRemoved, refetchDocument); - wallet.eventManager.on(WalletEvents.documentUpdated, refetchDocument); + useEventListener(getWallet().eventManager, events, refetchDocument); - return () => { - wallet.eventManager.removeListener(WalletEvents.documentAdded, refetchDocument); - wallet.eventManager.removeListener(WalletEvents.documentRemoved, refetchDocument); - wallet.eventManager.removeListener(WalletEvents.documentUpdated, refetchDocument); - } - }, [id, wallet]); - return document; } +export function useDocuments({type}) { + const [documents, setDocuments] = useState([]); + const [loading, setLoading] = useState(true); + + const fetchDocuments = useCallback( + async (updatedDoc, forceFetch = false) => { + if ( + forceFetch || + updatedDoc?.type === type || + updatedDoc?.type?.includes(type) + ) { + const docs = await getWallet().getDocumentsByType(type); + setDocuments(docs); + setLoading(false); + } + }, + [type], + ); + + useEffect(() => { + fetchDocuments(null, true); + }, [fetchDocuments, setLoading]); + + useEventListener(getWallet().eventManager, events, fetchDocuments); + + return { + documents, + loading, + }; +} export function useWallet() { return useContext(WalletSDKContext);