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 ()
0 commit comments