diff --git a/packages/webapp/src/containers/Banking/Plaid/PlaidLanchLink.tsx b/packages/webapp/src/containers/Banking/Plaid/PlaidLanchLink.tsx
index a925181da..fb0cef281 100644
--- a/packages/webapp/src/containers/Banking/Plaid/PlaidLanchLink.tsx
+++ b/packages/webapp/src/containers/Banking/Plaid/PlaidLanchLink.tsx
@@ -1,5 +1,4 @@
// @ts-nocheck
-import { usePlaidExchangeToken } from '@/hooks/query';
import React, { useEffect } from 'react';
import {
usePlaidLink,
@@ -10,28 +9,28 @@ import {
PlaidLinkOnEventMetadata,
PlaidLinkStableEvent,
} from 'react-plaid-link';
-import { useHistory } from 'react-router-dom';
-// import { exchangeToken, setItemState } from '../services/api';
-// import { useItems, useLink, useErrors } from '../services';
+import { logEvent } from './_utils';
+import { usePlaidExchangeToken } from '@/hooks/query';
+import { useResetBankingPlaidToken } from '@/hooks/state/banking';
-interface LaunchLinkProps {
- isOauth?: boolean;
+interface PlaidLaunchLinkProps {
token: string;
- userId: number;
itemId?: number | null;
children?: React.ReactNode;
}
-// Uses the usePlaidLink hook to manage the Plaid Link creation. See https://github.com/plaid/react-plaid-link for full usage instructions.
-// The link token passed to usePlaidLink cannot be null. It must be generated outside of this component. In this sample app, the link token
-// is generated in the link context in client/src/services/link.js.
-
-export function LaunchLink(props: LaunchLinkProps) {
- const history = useHistory();
- // const { getItemsByUser, getItemById } = useItems();
- // const { generateLinkToken, deleteLinkToken } = useLink();
- // const { setError, resetError } = useErrors();
-
+/**
+ * Uses the usePlaidLink hook to manage the Plaid Link creation.
+ * See https://github.com/plaid/react-plaid-link for full usage instructions.
+ * The link token passed to usePlaidLink cannot be null.
+ * It must be generated outside of this component. In this sample app, the link token
+ * is generated in the link context in client/src/services/link.js.
+ *
+ * @param {PlaidLaunchLinkProps} props
+ * @returns {React.ReactNode}
+ */
+export function LaunchLink(props: PlaidLaunchLinkProps) {
+ const resetPlaidToken = useResetBankingPlaidToken();
const { mutateAsync: exchangeAccessToken } = usePlaidExchangeToken();
// define onSuccess, onExit and onEvent functions as configs for Plaid Link creation
@@ -40,7 +39,7 @@ export function LaunchLink(props: LaunchLinkProps) {
metadata: PlaidLinkOnSuccessMetadata,
) => {
// log and save metatdata
- // logSuccess(metadata, props.userId);
+ logSuccess(metadata);
if (props.itemId != null) {
// update mode: no need to exchange public token
// await setItemState(props.itemId, 'good');
@@ -48,39 +47,26 @@ export function LaunchLink(props: LaunchLinkProps) {
// getItemById(props.itemId, true);
// regular link mode: exchange public token for access token
} else {
- // call to Plaid api endpoint: /item/public_token/exchange in order to obtain access_token which is then stored with the created item
- debugger;
-
await exchangeAccessToken({
public_token: publicToken,
institution_id: metadata.institution.institution_id,
});
- // await exchangeToken(
- // publicToken,
- // metadata.institution,
- // metadata.accounts,
- // props.userId,
- // );
- // getItemsByUser(props.userId, true);
}
// resetError();
- // deleteLinkToken(props.userId, null);
- history.push(`/user/${props.userId}`);
+ resetPlaidToken();
};
+ // Handle other error codes, see https://plaid.com/docs/errors/
const onExit = async (
error: PlaidLinkError | null,
metadata: PlaidLinkOnExitMetadata,
) => {
// log and save error and metatdata
- // logExit(error, metadata, props.userId);
- if (error != null && error.error_code === 'INVALID_LINK_TOKEN') {
- // await generateLinkToken(props.userId, props.itemId);
- }
+ logExit(error, metadata, props.userId);
if (error != null) {
// setError(error.error_code, error.display_message || error.error_message);
}
- // to handle other error codes, see https://plaid.com/docs/errors/
+ resetPlaidToken();
};
const onEvent = async (
@@ -91,7 +77,7 @@ export function LaunchLink(props: LaunchLinkProps) {
if (eventName === 'ERROR' && metadata.error_code != null) {
// setError(metadata.error_code, ' ');
}
- // logEvent(eventName, metadata);
+ logEvent(eventName, metadata);
};
const config: PlaidLinkOptionsWithLinkToken = {
@@ -101,31 +87,14 @@ export function LaunchLink(props: LaunchLinkProps) {
token: props.token,
};
- if (props.isOauth) {
- // add additional receivedRedirectUri config when handling an OAuth reidrect
- config.receivedRedirectUri = window.location.href;
- }
const { open, ready } = usePlaidLink(config);
useEffect(() => {
// initiallizes Link automatically
- if (props.isOauth && ready) {
- open();
- } else if (ready) {
- // regular, non-OAuth case:
- // set link token, userId and itemId in local storage for use if needed later by OAuth
-
- localStorage.setItem(
- 'oauthConfig',
- JSON.stringify({
- userId: props.userId,
- itemId: props.itemId,
- token: props.token,
- }),
- );
+ if (ready) {
open();
}
- }, [ready, open, props.isOauth, props.userId, props.itemId, props.token]);
+ }, [ready, open, props.itemId, props.token]);
return <>>;
}
diff --git a/packages/webapp/src/containers/Banking/Plaid/_utils.ts b/packages/webapp/src/containers/Banking/Plaid/_utils.ts
new file mode 100644
index 000000000..cef95bba2
--- /dev/null
+++ b/packages/webapp/src/containers/Banking/Plaid/_utils.ts
@@ -0,0 +1,30 @@
+import {
+ PlaidLinkError,
+ PlaidLinkOnEventMetadata,
+ PlaidLinkOnExitMetadata,
+ PlaidLinkOnSuccessMetadata,
+ PlaidLinkStableEvent,
+} from 'react-plaid-link';
+
+export const logEvent = (
+ eventName: PlaidLinkStableEvent | string,
+ metadata:
+ | PlaidLinkOnEventMetadata
+ | PlaidLinkOnSuccessMetadata
+ | PlaidLinkOnExitMetadata,
+ error?: PlaidLinkError | null,
+) => {
+ console.log(`Link Event: ${eventName}`, metadata, error);
+};
+
+export const logSuccess = async ({
+ institution,
+ accounts,
+ link_session_id,
+}: PlaidLinkOnSuccessMetadata) => {
+ logEvent('onSuccess', {
+ institution,
+ accounts,
+ link_session_id,
+ });
+};
diff --git a/packages/webapp/src/containers/CashFlow/CashFlowAccounts/CashflowAccountsPlaidLink.tsx b/packages/webapp/src/containers/CashFlow/CashFlowAccounts/CashflowAccountsPlaidLink.tsx
index b3a927f9b..5eeb72ddd 100644
--- a/packages/webapp/src/containers/CashFlow/CashFlowAccounts/CashflowAccountsPlaidLink.tsx
+++ b/packages/webapp/src/containers/CashFlow/CashFlowAccounts/CashflowAccountsPlaidLink.tsx
@@ -4,5 +4,5 @@ import { useGetBankingPlaidToken } from '@/hooks/state/banking';
export function CashflowAccountsPlaidLink() {
const plaidToken = useGetBankingPlaidToken();
- return ;
+ return ;
}
diff --git a/packages/webapp/src/hooks/state/banking.ts b/packages/webapp/src/hooks/state/banking.ts
index d7499dfd7..9b6b356ca 100644
--- a/packages/webapp/src/hooks/state/banking.ts
+++ b/packages/webapp/src/hooks/state/banking.ts
@@ -1,4 +1,8 @@
-import { getPlaidToken, setPlaidId } from '@/store/banking/banking.reducer';
+import {
+ getPlaidToken,
+ setPlaidId,
+ resetPlaidId,
+} from '@/store/banking/banking.reducer';
import { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
@@ -18,3 +22,11 @@ export const useGetBankingPlaidToken = () => {
return plaidToken;
};
+
+export const useResetBankingPlaidToken = () => {
+ const dispatch = useDispatch();
+
+ return useCallback(() => {
+ dispatch(resetPlaidId());
+ }, [dispatch]);
+};
diff --git a/packages/webapp/src/store/banking/banking.reducer.ts b/packages/webapp/src/store/banking/banking.reducer.ts
index 93023cdc0..d6a842d32 100644
--- a/packages/webapp/src/store/banking/banking.reducer.ts
+++ b/packages/webapp/src/store/banking/banking.reducer.ts
@@ -13,8 +13,11 @@ export const PlaidSlice = createSlice({
setPlaidId: (state: StorePlaidState, action: PayloadAction) => {
state.plaidToken = action.payload;
},
+ resetPlaidId: (state: StorePlaidState) => {
+ state.plaidToken = '';
+ }
},
});
-export const { setPlaidId } = PlaidSlice.actions;
-export const getPlaidToken = (state: any) => state.plaid.plaidToken;
+export const { setPlaidId, resetPlaidId } = PlaidSlice.actions;
+export const getPlaidToken = (state: any) => state.plaid.plaidToken;
\ No newline at end of file