UNPKG

react-native-unit-components

Version:

Unit React Native components

108 lines (95 loc) 4.19 kB
import { useEffect, useState, useRef } from 'react'; import { UNWalletCode, UNWalletName } from '../../../types/shared/wallet.types'; import type { UNWallet } from '../../../types/shared/wallet.types'; import { UnitSDK } from '../../../unitSdkManager/UnitSdkManager'; import { getMobileWalletPayload } from '../../../networking/requests/UNWalletPayloadRequest'; import { useSelector, useDispatch } from 'react-redux'; import { selectWallet, setSignedNonce } from '../../../slices/pushProvisioningSlice'; import { useLaunchInitialize } from './useLaunchInitialize'; import { UNVPErrorType } from '../types'; import { promiseRejectToUNVPErrorType } from '../helpers'; import { UNErrorCodes, UNErrorData } from '../../../types/shared/error.types'; import { isUNError } from '../../../types/internal/errorHelpers'; export type CardToEncryptedPayload = { [cardId: string]: string; }; export const useCardWallet = (cardId: string) => { const [currentUNWallet, setCurrentUNWallet] = useState<UNWallet>(); const { signedNonce } = useSelector(selectWallet); const { initializePushProvisioning } = useLaunchInitialize(); const dispatch = useDispatch(); const isRecoveringSignedNonceRef = useRef<boolean>(false); const shouldRecoverVPSDKForError = (errorType: UNVPErrorType) => { const recoveringTypes = [UNVPErrorType.PayloadDecryptionFailed, UNVPErrorType.SessionExpired, UNVPErrorType.InvalidNonce]; return recoveringTypes.includes(errorType); }; useEffect(() => { const getEncryptedPayload = async () => { const env = UnitSDK.getEnv(); const customerToken = UnitSDK.getCustomerToken(); if (!env || !customerToken) return; // In case we use flow if (!signedNonce) { await initializePushProvisioning(); return; } const encryptedPayload = await getMobileWalletPayload(customerToken, cardId, env, signedNonce); return encryptedPayload; }; const getCardWalletData = async () => { const currentProvisioningModule = UnitSDK.getPushProvisionModule(); if (!currentProvisioningModule) return; try { const encryptedPayload = await getEncryptedPayload(); if (!encryptedPayload) return; const walletsResponse = await currentProvisioningModule.launchGetWallets(JSON.stringify({ encPayload: encryptedPayload })); const unWallet: UNWallet | null = parseWalletsResponse(walletsResponse); if (!unWallet) return; setCurrentUNWallet(unWallet); return; } catch (error) { console.error('Coudln\'t get card wallet data:', error); if (isRecoveringSignedNonceRef.current) return; isRecoveringSignedNonceRef.current = true; // handle unit network api errors if (isUNError(error)) { const errors: UNErrorData[] = error.errors; // errors will return in an array but hold only a single error element if (errors[0]?.code === UNErrorCodes.INVALID_NONCE) { dispatch(setSignedNonce(null)); } return; } // handle VDE SDK errors const errorType = promiseRejectToUNVPErrorType(error); if (!errorType) return; if (shouldRecoverVPSDKForError(errorType)) { dispatch(setSignedNonce(null)); return; } } }; getCardWalletData(); }, [signedNonce, cardId]); return { currentUNWallet, }; }; const parseWalletsResponse = (walletsResponse: string): UNWallet | null => { try { const parsedWalletsResponse = JSON.parse(walletsResponse); const wallets = parsedWalletsResponse.wallets; if (!wallets) return null; if (wallets[0].code === UNWalletCode.Apple) { return ({ name: UNWalletName.Apple, code: UNWalletCode.Apple, status: wallets[0].status }); } else { const googleWallet = wallets.filter((wallet: { name: UNWalletName }) => { return wallet.name === UNWalletName.Google; }); if (!googleWallet) return null; return ({ name: UNWalletName.Google, code: UNWalletCode.Google, status: googleWallet[0].status }); } } catch (error) { throw new Error('Error parsing wallet response'); } };