fin-infra 0.5.0__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fin_infra-0.5.0 → fin_infra-0.6.0}/PKG-INFO +1 -1
- {fin_infra-0.5.0 → fin_infra-0.6.0}/pyproject.toml +1 -1
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/banking/__init__.py +49 -2
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/banking/plaid_client.py +29 -9
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/banking/teller_client.py +13 -5
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/base.py +38 -2
- {fin_infra-0.5.0 → fin_infra-0.6.0}/LICENSE +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/README.md +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/__main__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/cash_flow.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/ease.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/portfolio.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/projections.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/rebalancing.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/savings.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/scenarios.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/analytics/spending.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/banking/history.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/banking/utils.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/brokerage/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/alerts.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/ease.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/scaffold_templates/README.md +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/scaffold_templates/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/scaffold_templates/models.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/scaffold_templates/repository.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/scaffold_templates/schemas.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/templates.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/tracker.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/cashflows/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/cashflows/core.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/categorization/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/categorization/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/categorization/ease.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/categorization/engine.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/categorization/llm_layer.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/categorization/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/categorization/rules.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/categorization/taxonomy.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/chat/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/chat/ease.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/chat/planning.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/cli/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/cli/cmds/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/cli/cmds/scaffold_cmds.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/clients/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/clients/base.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/clients/plaid.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/compliance/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/credit/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/credit/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/credit/experian/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/credit/experian/auth.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/credit/experian/client.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/credit/experian/parser.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/credit/experian/provider.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/credit/mock.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/crypto/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/crypto/insights.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/documents/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/documents/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/documents/analysis.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/documents/ease.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/documents/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/documents/ocr.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/documents/storage.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/exceptions.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/funding.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/management.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/milestones.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/scaffold_templates/README.md +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/scaffold_templates/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/scaffold_templates/models.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/scaffold_templates/repository.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/scaffold_templates/schemas.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/insights/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/insights/aggregator.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/insights/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/ease.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/providers/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/providers/base.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/providers/plaid.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/providers/snaptrade.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/scaffold_templates/README.md +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/scaffold_templates/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/scaffold_templates/models.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/scaffold_templates/repository.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/scaffold_templates/schemas.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/markets/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/models/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/models/accounts.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/models/brokerage.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/models/candle.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/models/credit.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/models/money.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/models/quotes.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/models/tax.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/models/transactions.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/aggregator.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/calculator.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/ease.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/goals.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/insights.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/scaffold_templates/README.md +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/scaffold_templates/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/scaffold_templates/models.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/scaffold_templates/repository.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/scaffold_templates/schemas.py.tmpl +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/normalization/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/normalization/currency_converter.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/normalization/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/normalization/providers/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/normalization/providers/exchangerate.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/normalization/providers/static_mappings.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/normalization/symbol_resolver.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/obs/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/obs/classifier.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/banking/base.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/brokerage/alpaca.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/brokerage/base.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/credit/experian.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/identity/stripe_identity.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/market/alphavantage.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/market/base.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/market/ccxt_crypto.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/market/coingecko.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/market/yahoo.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/registry.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/tax/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/tax/irs.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/tax/mock.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/providers/tax/taxbit.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/py.typed +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/recurring/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/recurring/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/recurring/detector.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/recurring/detectors_llm.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/recurring/ease.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/recurring/insights.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/recurring/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/recurring/normalizer.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/recurring/normalizers.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/recurring/summary.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/scaffold/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/scaffold/budgets.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/scaffold/goals.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/security/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/security/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/security/audit.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/security/encryption.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/security/models.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/security/pii_filter.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/security/pii_patterns.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/security/token_store.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/settings.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/tax/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/tax/add.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/tax/tlh.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/utils/__init__.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/utils/deprecation.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/utils/http.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/utils/retry.py +0 -0
- {fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: fin-infra
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Financial infrastructure toolkit: banking connections, market data, credit, cashflows, and brokerage integrations
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: finance,banking,plaid,brokerage,markets,credit,tax,cashflow,fintech,infra
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "fin-infra"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.6.0"
|
|
4
4
|
description = "Financial infrastructure toolkit: banking connections, market data, credit, cashflows, and brokerage integrations"
|
|
5
5
|
authors = ["Ali Khatami <aliikhatami94@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -89,6 +89,15 @@ class CreateLinkTokenResponse(BaseModel):
|
|
|
89
89
|
link_token: str
|
|
90
90
|
|
|
91
91
|
|
|
92
|
+
class CreateUpdateLinkTokenRequest(BaseModel):
|
|
93
|
+
"""Request model for creating a link token in update mode (re-authentication)."""
|
|
94
|
+
|
|
95
|
+
user_id: str
|
|
96
|
+
access_token: str = Field(
|
|
97
|
+
..., description="Existing access token for the item requiring re-auth"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
92
101
|
class ExchangeTokenRequest(BaseModel):
|
|
93
102
|
"""Request model for exchanging public token."""
|
|
94
103
|
|
|
@@ -334,6 +343,23 @@ def add_banking(
|
|
|
334
343
|
link_token = banking.create_link_token(user_id=request.user_id)
|
|
335
344
|
return CreateLinkTokenResponse(link_token=link_token)
|
|
336
345
|
|
|
346
|
+
@router.post("/link/update", response_model=CreateLinkTokenResponse)
|
|
347
|
+
async def create_update_link_token(request: CreateUpdateLinkTokenRequest):
|
|
348
|
+
"""Create link token in update mode for re-authentication.
|
|
349
|
+
|
|
350
|
+
Use this endpoint when a user's bank connection has expired
|
|
351
|
+
(ITEM_LOGIN_REQUIRED error). The returned link token will open
|
|
352
|
+
Plaid Link in update mode, allowing the user to re-authenticate
|
|
353
|
+
without creating a new connection.
|
|
354
|
+
|
|
355
|
+
After successful re-authentication, the existing access_token
|
|
356
|
+
remains valid and no token exchange is needed.
|
|
357
|
+
"""
|
|
358
|
+
link_token = banking.create_link_token(
|
|
359
|
+
user_id=request.user_id, access_token=request.access_token
|
|
360
|
+
)
|
|
361
|
+
return CreateLinkTokenResponse(link_token=link_token)
|
|
362
|
+
|
|
337
363
|
@router.post("/exchange", response_model=ExchangeTokenResponse)
|
|
338
364
|
async def exchange_token(request: ExchangeTokenRequest):
|
|
339
365
|
"""Exchange public token for access token (Plaid flow)."""
|
|
@@ -343,8 +369,29 @@ def add_banking(
|
|
|
343
369
|
@router.get("/accounts")
|
|
344
370
|
async def get_accounts(access_token: str = Depends(get_access_token)):
|
|
345
371
|
"""List accounts for access token."""
|
|
346
|
-
|
|
347
|
-
|
|
372
|
+
try:
|
|
373
|
+
accounts = banking.accounts(access_token=access_token)
|
|
374
|
+
return {"accounts": accounts}
|
|
375
|
+
except Exception as e:
|
|
376
|
+
error_str = str(e)
|
|
377
|
+
# Check for Plaid-specific errors that require user action
|
|
378
|
+
if "ITEM_LOGIN_REQUIRED" in error_str:
|
|
379
|
+
raise HTTPException(
|
|
380
|
+
status_code=401,
|
|
381
|
+
detail="ITEM_LOGIN_REQUIRED: Your bank connection has expired. Please re-authenticate your bank account.",
|
|
382
|
+
)
|
|
383
|
+
elif "INVALID_ACCESS_TOKEN" in error_str:
|
|
384
|
+
raise HTTPException(
|
|
385
|
+
status_code=401,
|
|
386
|
+
detail="INVALID_ACCESS_TOKEN: The access token is invalid or expired. Please reconnect your bank account.",
|
|
387
|
+
)
|
|
388
|
+
elif "ITEM_NOT_FOUND" in error_str:
|
|
389
|
+
raise HTTPException(
|
|
390
|
+
status_code=404,
|
|
391
|
+
detail="ITEM_NOT_FOUND: This bank connection no longer exists. Please reconnect your bank account.",
|
|
392
|
+
)
|
|
393
|
+
# Re-raise other errors
|
|
394
|
+
raise
|
|
348
395
|
|
|
349
396
|
@router.get("/transactions")
|
|
350
397
|
async def get_transactions(
|
|
@@ -81,21 +81,41 @@ class PlaidClient(BankingProvider):
|
|
|
81
81
|
api_client = plaid.ApiClient(configuration)
|
|
82
82
|
self.client = plaid_api.PlaidApi(api_client)
|
|
83
83
|
|
|
84
|
-
def create_link_token(self, user_id: str) -> str:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
def create_link_token(self, user_id: str, access_token: str | None = None) -> str:
|
|
85
|
+
"""Create a Plaid Link token for new connections or re-authentication.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
user_id: Client-defined user ID for the Link session
|
|
89
|
+
access_token: If provided, creates Link in update mode for re-authentication
|
|
90
|
+
(used when ITEM_LOGIN_REQUIRED error occurs)
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Link token string for Plaid Link initialization
|
|
94
|
+
"""
|
|
95
|
+
# Build base request parameters
|
|
96
|
+
request_params = {
|
|
97
|
+
"user": LinkTokenCreateRequestUser(client_user_id=user_id),
|
|
98
|
+
"client_name": "fin-infra",
|
|
99
|
+
"country_codes": [CountryCode("US")],
|
|
100
|
+
"language": "en",
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if access_token:
|
|
104
|
+
# Update mode: re-authenticate existing connection
|
|
105
|
+
# Don't include products - Plaid uses existing item's products
|
|
106
|
+
request_params["access_token"] = access_token
|
|
107
|
+
else:
|
|
108
|
+
# New connection: specify products to enable
|
|
109
|
+
request_params["products"] = [
|
|
89
110
|
Products("auth"), # Account/routing numbers for ACH
|
|
90
111
|
Products("transactions"), # Transaction history
|
|
91
112
|
Products("liabilities"), # Credit cards, loans, student loans
|
|
92
113
|
Products("investments"), # Brokerage, retirement accounts
|
|
93
114
|
Products("assets"), # Asset reports for lending/verification
|
|
94
115
|
Products("identity"), # Account holder info (name, email, phone)
|
|
95
|
-
]
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
)
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
request = LinkTokenCreateRequest(**request_params)
|
|
99
119
|
response = self.client.link_token_create(request)
|
|
100
120
|
return cast("str", response["link_token"])
|
|
101
121
|
|
|
@@ -121,7 +121,7 @@ class TellerClient(BankingProvider):
|
|
|
121
121
|
response.raise_for_status()
|
|
122
122
|
return response.json()
|
|
123
123
|
|
|
124
|
-
def create_link_token(self, user_id: str) -> str:
|
|
124
|
+
def create_link_token(self, user_id: str, access_token: str | None = None) -> str:
|
|
125
125
|
"""Create link token for user authentication.
|
|
126
126
|
|
|
127
127
|
Note: Teller uses a simpler auth flow than Plaid. In production,
|
|
@@ -130,6 +130,9 @@ class TellerClient(BankingProvider):
|
|
|
130
130
|
|
|
131
131
|
Args:
|
|
132
132
|
user_id: Your application's user identifier
|
|
133
|
+
access_token: If provided, creates Link in update mode for re-authentication
|
|
134
|
+
(used when connection needs to be repaired). Teller handles
|
|
135
|
+
this differently than Plaid - see Teller Connect docs.
|
|
133
136
|
|
|
134
137
|
Returns:
|
|
135
138
|
Link token or enrollment ID for user to authenticate
|
|
@@ -138,13 +141,18 @@ class TellerClient(BankingProvider):
|
|
|
138
141
|
httpx.HTTPStatusError: On HTTP errors
|
|
139
142
|
"""
|
|
140
143
|
# Teller's enrollment endpoint for creating application links
|
|
144
|
+
payload: dict[str, Any] = {
|
|
145
|
+
"user_id": user_id,
|
|
146
|
+
"products": ["accounts", "transactions", "balances", "identity"],
|
|
147
|
+
}
|
|
148
|
+
# If access_token provided, add it for update mode (re-authentication)
|
|
149
|
+
if access_token:
|
|
150
|
+
payload["access_token"] = access_token
|
|
151
|
+
|
|
141
152
|
response = self._request(
|
|
142
153
|
"POST",
|
|
143
154
|
"/enrollments",
|
|
144
|
-
json=
|
|
145
|
-
"user_id": user_id,
|
|
146
|
-
"products": ["accounts", "transactions", "balances", "identity"],
|
|
147
|
-
},
|
|
155
|
+
json=payload,
|
|
148
156
|
)
|
|
149
157
|
return cast("str", response.get("enrollment_id", ""))
|
|
150
158
|
|
|
@@ -32,6 +32,13 @@ from ..models import Candle, Quote
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class MarketDataProvider(ABC):
|
|
35
|
+
"""Abstract base class for stock and equity market data providers.
|
|
36
|
+
|
|
37
|
+
Implement this class to integrate with market data sources like
|
|
38
|
+
Yahoo Finance, Alpha Vantage, or Polygon.io for real-time quotes
|
|
39
|
+
and historical price data.
|
|
40
|
+
"""
|
|
41
|
+
|
|
35
42
|
@abstractmethod
|
|
36
43
|
def quote(self, symbol: str) -> Quote:
|
|
37
44
|
pass
|
|
@@ -44,6 +51,12 @@ class MarketDataProvider(ABC):
|
|
|
44
51
|
|
|
45
52
|
|
|
46
53
|
class CryptoDataProvider(ABC):
|
|
54
|
+
"""Abstract base class for cryptocurrency market data providers.
|
|
55
|
+
|
|
56
|
+
Implement this class to integrate with crypto exchanges like
|
|
57
|
+
Binance, Coinbase, or Kraken for ticker data and OHLCV candles.
|
|
58
|
+
"""
|
|
59
|
+
|
|
47
60
|
@abstractmethod
|
|
48
61
|
def ticker(self, symbol_pair: str) -> Any:
|
|
49
62
|
pass
|
|
@@ -57,8 +70,17 @@ class BankingProvider(ABC):
|
|
|
57
70
|
"""Abstract provider for bank account aggregation (Teller, Plaid, MX)."""
|
|
58
71
|
|
|
59
72
|
@abstractmethod
|
|
60
|
-
def create_link_token(self, user_id: str) -> str:
|
|
61
|
-
"""Create a link/connect token for user to authenticate with their bank.
|
|
73
|
+
def create_link_token(self, user_id: str, access_token: str | None = None) -> str:
|
|
74
|
+
"""Create a link/connect token for user to authenticate with their bank.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
user_id: Client-defined user ID for the Link session
|
|
78
|
+
access_token: If provided, creates Link in update mode for re-authentication
|
|
79
|
+
(used when ITEM_LOGIN_REQUIRED error occurs)
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
Link token string for initializing the bank connection UI
|
|
83
|
+
"""
|
|
62
84
|
pass
|
|
63
85
|
|
|
64
86
|
@abstractmethod
|
|
@@ -90,6 +112,13 @@ class BankingProvider(ABC):
|
|
|
90
112
|
|
|
91
113
|
|
|
92
114
|
class BrokerageProvider(ABC):
|
|
115
|
+
"""Abstract base class for brokerage trading integrations.
|
|
116
|
+
|
|
117
|
+
Implement this class to integrate with trading platforms like
|
|
118
|
+
Alpaca, Interactive Brokers, or TD Ameritrade for order execution,
|
|
119
|
+
position management, and portfolio tracking.
|
|
120
|
+
"""
|
|
121
|
+
|
|
93
122
|
@abstractmethod
|
|
94
123
|
def submit_order(
|
|
95
124
|
self,
|
|
@@ -185,6 +214,13 @@ class IdentityProvider(ABC):
|
|
|
185
214
|
|
|
186
215
|
|
|
187
216
|
class CreditProvider(ABC):
|
|
217
|
+
"""Abstract base class for credit data providers.
|
|
218
|
+
|
|
219
|
+
Implement this class to integrate with credit bureaus like
|
|
220
|
+
Experian, Equifax, or TransUnion for credit score retrieval
|
|
221
|
+
and full credit report access.
|
|
222
|
+
"""
|
|
223
|
+
|
|
188
224
|
@abstractmethod
|
|
189
225
|
def get_credit_score(self, user_id: str, **kwargs: Any) -> Any:
|
|
190
226
|
pass
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/scaffold_templates/repository.py.tmpl
RENAMED
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/budgets/scaffold_templates/schemas.py.tmpl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/goals/scaffold_templates/repository.py.tmpl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/scaffold_templates/__init__.py
RENAMED
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/scaffold_templates/models.py.tmpl
RENAMED
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/scaffold_templates/repository.py.tmpl
RENAMED
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/investments/scaffold_templates/schemas.py.tmpl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/scaffold_templates/models.py.tmpl
RENAMED
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/scaffold_templates/repository.py.tmpl
RENAMED
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/net_worth/scaffold_templates/schemas.py.tmpl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fin_infra-0.5.0 → fin_infra-0.6.0}/src/fin_infra/normalization/providers/static_mappings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|