Skip to content

Commit fee470a

Browse files
committed
Add Plaid integration for transaction viewing and UI implementation
1 parent 73d7341 commit fee470a

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed

api/gradio/app.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import os
2+
import gradio as gr
3+
import pandas as pd
4+
from datetime import datetime, timedelta
5+
from plaid.api import plaid_api
6+
from plaid.model.transactions_get_request import TransactionsGetRequest
7+
from plaid.model.transactions_get_request_options import TransactionsGetRequestOptions
8+
from plaid.model.products import Products
9+
from plaid.model.item_public_token_exchange_request import ItemPublicTokenExchangeRequest
10+
from plaid.model.link_token_create_request import LinkTokenCreateRequest
11+
from plaid.configuration import Configuration
12+
from plaid.api_client import ApiClient
13+
from dotenv import load_dotenv
14+
from plaid.model.country_code import CountryCode
15+
16+
# Load environment variables
17+
load_dotenv()
18+
19+
class PlaidViewer:
20+
def __init__(self):
21+
configuration = Configuration(
22+
host="https://sandbox.plaid.com",
23+
api_key={
24+
'clientId': os.getenv('PLAID_CLIENT_ID'),
25+
'secret': os.getenv('PLAID_SECRET')
26+
}
27+
)
28+
api_client = ApiClient(configuration)
29+
self.client = plaid_api.PlaidApi(api_client)
30+
self.access_token = None
31+
32+
def create_link_token(self):
33+
try:
34+
request = LinkTokenCreateRequest(
35+
products=[Products('transactions')],
36+
client_name='Plaid Gradio App',
37+
country_codes=[CountryCode('US')],
38+
user={'client_user_id': f'user-{datetime.now().timestamp()}'},
39+
language='en'
40+
)
41+
response = self.client.link_token_create(request)
42+
return response['link_token']
43+
except Exception as e:
44+
return f"Error: {str(e)}"
45+
46+
def exchange_token(self, public_token):
47+
try:
48+
request = ItemPublicTokenExchangeRequest(public_token=public_token)
49+
response = self.client.item_public_token_exchange(request)
50+
self.access_token = response['access_token']
51+
return "Successfully connected account!"
52+
except Exception as e:
53+
return f"Error: {str(e)}"
54+
55+
def get_transactions(self):
56+
if not self.access_token:
57+
return pd.DataFrame(), "Please connect an account first"
58+
59+
try:
60+
end_date = datetime.strptime('2024-04-10', '%Y-%m-%d').date()
61+
start_date = end_date - timedelta(days=40)
62+
63+
request = TransactionsGetRequest(
64+
access_token=self.access_token,
65+
start_date=start_date,
66+
end_date=end_date
67+
)
68+
response = self.client.transactions_get(request)
69+
transactions = response['transactions']
70+
df = pd.DataFrame(transactions)
71+
72+
# the transactions in the response are paginated, so make multiple calls while increasing the offset to
73+
# retrieve all transactions
74+
while len(transactions) < response['total_transactions']:
75+
options = TransactionsGetRequestOptions()
76+
options.offset = len(transactions)
77+
78+
request = TransactionsGetRequest(
79+
access_token=self.access_token,
80+
start_date=start_date,
81+
end_date=end_date,
82+
options=options
83+
)
84+
response = self.client.transactions_get(request)
85+
df.append(pd.DataFrame(response['transactions']))
86+
87+
return df[['date', 'name', 'amount', 'category']], "Transactions retrieved successfully"
88+
#return df, "Transactions retrieved successfully"
89+
except Exception as e:
90+
return pd.DataFrame(), f"Error: {str(e)}"
91+
92+
def create_ui():
93+
plaid = PlaidViewer()
94+
95+
def get_link():
96+
return plaid.create_link_token()
97+
98+
def connect(token):
99+
return plaid.exchange_token(token)
100+
101+
def fetch_transactions():
102+
df, msg = plaid.get_transactions()
103+
return df, msg
104+
105+
with gr.Blocks(title="Plaid Transaction Viewer") as app:
106+
gr.Markdown("# Plaid Transaction Viewer")
107+
108+
with gr.Row():
109+
link_btn = gr.Button("Get Link Token")
110+
link_output = gr.Textbox(label="Link Token")
111+
112+
with gr.Row():
113+
token_input = gr.Textbox(label="Enter Public Token")
114+
connect_btn = gr.Button("Connect Account")
115+
connect_output = gr.Textbox(label="Connection Status")
116+
117+
status = gr.Textbox(label="Status")
118+
transactions = gr.DataFrame(label="Transactions")
119+
120+
link_btn.click(fn=get_link, outputs=link_output)
121+
connect_btn.click(fn=connect, inputs=token_input, outputs=connect_output)
122+
refresh_btn = gr.Button("Refresh Transactions")
123+
refresh_btn.click(fn=fetch_transactions, outputs=[transactions, status])
124+
125+
return app
126+
127+
if __name__ == "__main__":
128+
demo = create_ui()
129+
demo.launch()

api/gradio/requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
plaid-python
2+
gradio
3+
python-dotenv
4+
pandas

0 commit comments

Comments
 (0)