Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ investment = client.investment.create_investment(
| `create_wallet(account_id=None, currency_code=None)` | `POST /wallets` |
| `transfer(wallet_id=None, product_code=None, amount=None)` | `POST /wallets/:wallet_id/transfer` |
| `get_wallet(wallet_id)` | `GET /wallets/:wallet_id` |
| `list_flexible_savings(**kwargs)` | `GET /flexible-savings` |
| `create_fixed_note(**kwargs)` | `POST /fixed-notes` |
| `list_withdrawals(**kwargs)` | `GET /withdrawals` |

Check the [API reference](https://developers.cowrywise.com/reference) document for all resources and their respective endpoints.

Expand Down
36 changes: 36 additions & 0 deletions embed/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@
from embed.errors import CredentialsError
from embed.resources.account import Account
from embed.resources.asset import Asset
from embed.resources.deposit import Deposit
from embed.resources.index import Index
from embed.resources.integrations import Integration
from embed.resources.investment import Investment
from embed.resources.price import Price
from embed.resources.saving import Saving
from embed.resources.flexible_savings import FlexibleSaving
from embed.resources.fixed_notes import FixedNote
from embed.resources.settlement import Settlement
from embed.resources.stock import Stock
from embed.resources.stock_portfolio import StockPortfolio
from embed.resources.trade import Trade
from embed.resources.transaction import Transaction
from embed.resources.withdrawal import Withdrawal
from embed.resources.withdrawal_intents import WithdrawalIntent
from embed.resources.misc import Misc
from embed.resources.wallet import Wallet
from embed.common import APISession
Expand Down Expand Up @@ -61,14 +67,20 @@ def __init__(

self._accounts = Account(self._session)
self._assets = Asset(self._session)
self._deposits = Deposit(self._session)
self._investments = Investment(self._session)
self._indexes = Index(self._session)
self._integrations = Integration(self._session)
self._savings = Saving(self._session)
self._flexible_savings = FlexibleSaving(self._session)
self._fixed_notes = FixedNote(self._session)
self._settlements = Settlement(self._session)
self._stocks = Stock(self._session)
self._stock_portfolios = StockPortfolio(self._session)
self._trades = Trade(self._session)
self._transactions = Transaction(self._session)
self._withdrawals = Withdrawal(self._session)
self._withdrawal_intents = WithdrawalIntent(self._session)
self._prices = Price(self._session)
self._wallets = Wallet(self._session)
self._misc = Misc(self._session)
Expand All @@ -85,6 +97,10 @@ def accounts(self):
def assets(self):
return self._assets

@property
def deposits(self):
return self._deposits

@property
def investments(self):
return self._investments
Expand All @@ -93,10 +109,22 @@ def investments(self):
def indexes(self):
return self._indexes

@property
def integrations(self):
return self._integrations

@property
def savings(self):
return self._savings

@property
def flexible_savings(self):
return self._flexible_savings

@property
def fixed_notes(self):
return self._fixed_notes

@property
def settlements(self):
return self._settlements
Expand All @@ -117,6 +145,14 @@ def trades(self):
def transactions(self):
return self._transactions

@property
def withdrawals(self):
return self._withdrawals

@property
def withdrawal_intents(self):
return self._withdrawal_intents

@property
def prices(self):
return self._prices
Expand Down
49 changes: 49 additions & 0 deletions embed/resources/deposit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import json

from embed.common import APIResponse


class Deposit(APIResponse):
"""
Handles all queries for Deposits including listing and retrieving.
"""

def __init__(self, api_session):
super(Deposit, self).__init__()
self.base_url = f"{api_session.base_url}/api/{api_session.api_version}/"
self.token = api_session.token
self._headers.update({"Authorization": f"Bearer {self.token}"})

def list_deposits(self, **kwargs):
"""
Retrieve a list of all deposits.

Args:
**kwargs: Arbitrary keyword arguments for filtering and pagination.
page_size (int): Optional.
page (int): Optional.
all (bool): Optional. If True, return all without pagination.

Returns:
dict: The API response containing a list of deposits.
"""
query_path = self._format_query(kwargs)
method = "GET"
url = self.base_url + "deposits"
if query_path:
url = f"{url}?{query_path}"
return self.get_essential_details(method, url)

def get_deposit(self, deposit_id):
"""
Retrieve details of a specific deposit.

Args:
deposit_id (str): The unique identifier for the deposit.

Returns:
dict: The API response containing deposit details.
"""
method = "GET"
url = self.base_url + f"deposits/{deposit_id}"
return self.get_essential_details(method, url)
202 changes: 202 additions & 0 deletions embed/resources/fixed_notes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import json

from embed.common import APIResponse


class FixedNote(APIResponse):
"""
Handles all queries for Fixed Notes management including creation, withdrawal, rollover, and performance tracking.
"""

def __init__(self, api_session):
super(FixedNote, self).__init__()
self.base_url = f"{api_session.base_url}/api/{api_session.api_version}/"
self.token = api_session.token
self._headers.update({"Authorization": f"Bearer {self.token}"})

def list_fixed_notes(self, **kwargs):
"""
Retrieve a list of all fixed notes.

Args:
**kwargs: Arbitrary keyword arguments for pagination.
page_size (int): Optional.
page (int): Optional.

Returns:
dict: The API response containing a list of fixed notes.
"""
query_path = self._format_query(kwargs)
method = "GET"
url = self.base_url + "fixed-notes"
if query_path:
url = f"{url}?{query_path}"
return self.get_essential_details(method, url)

def get_fixed_note(self, fixed_note_id):
"""
Retrieve details of a specific fixed note.

Args:
fixed_note_id (str): The unique identifier for the fixed note.

Returns:
dict: The API response containing fixed note details.
"""
method = "GET"
url = self.base_url + f"fixed-notes/{fixed_note_id}"
return self.get_essential_details(method, url)

def create_fixed_note(self, **kwargs):
"""
Create a new fixed note investment.

Args:
**kwargs: Arbitrary keyword arguments.
account_id (str): Required. The unique identifier for the account.
asset_code (str): Required. The asset code for the fixed note.
tenor_in_months (int): Required. Duration in months.
amount_range (str): Required. Amount range (e.g., '10M-100M').
auto_reinvest (bool): Optional. Whether to automatically reinvest.
idempotency_key (str): Optional. Unique key to prevent duplicate requests.

Returns:
dict: The API response containing new fixed note details.
"""
required = ["account_id", "asset_code", "tenor_in_months", "amount_range"]
self._validate_kwargs(required, kwargs)

if "idempotency_key" in kwargs.keys():
self._headers.update(
{"Embed-Idempotency-Key": str(kwargs.pop("idempotency_key"))}
)

method = "POST"
url = self.base_url + "fixed-notes"
payload = json.dumps(kwargs)
return self.get_essential_details(method, url, payload)

def get_fixed_note_rates(self, **kwargs):
"""
Retrieve fixed note rates.

Args:
**kwargs: Arbitrary keyword arguments.
tenor_in_months (int): Required. Duration in months.
amount_range (str): Required. Amount range (e.g., '10M-100M').
currency (str): Required. Currency code (e.g., 'NGN', 'USD').

Returns:
dict: The API response containing rate information.
"""
required = ["tenor_in_months", "amount_range", "currency"]
self._validate_kwargs(required, kwargs)

query_path = "&".join(f"{k}={v}" for k, v in kwargs.items())
method = "GET"
url = self.base_url + f"fixed-notes/rates?{query_path}"
return self.get_essential_details(method, url)

def get_fixed_note_performance(
self, fixed_note_id: str, start_date: str = None, end_date: str = None, **kwargs
):
"""
Retrieve performance timeseries for a fixed note.

Args:
fixed_note_id (str): The unique identifier for the fixed note.
start_date (str): Optional. YYYY-MM-DD.
end_date (str): Optional. YYYY-MM-DD.
**kwargs: Additional filtering parameters.

Returns:
dict: The API response containing performance data.
"""
if start_date:
kwargs["start_date"] = self._validate_date_string(start_date)
if end_date:
kwargs["end_date"] = self._validate_date_string(end_date)

method = "GET"
url = self.base_url + f"fixed-notes/{fixed_note_id}/performance"
query_path = "&".join("{}={}".format(k, v) for k, v in kwargs.items())
if query_path:
url = f"{url}?{query_path}"
return self.get_essential_details(method, url)

def get_fixed_note_returns(
self, fixed_note_id: str, start_date: str = None, end_date: str = None, **kwargs
):
"""
Retrieve returns history for a fixed note.

Args:
fixed_note_id (str): The unique identifier for the fixed note.
start_date (str): Optional. YYYY-MM-DD.
end_date (str): Optional. YYYY-MM-DD.
**kwargs: Additional filtering parameters.

Returns:
dict: The API response containing returns data.
"""
if start_date:
kwargs["start_date"] = self._validate_date_string(start_date)
if end_date:
kwargs["end_date"] = self._validate_date_string(end_date)

method = "GET"
url = self.base_url + f"fixed-notes/{fixed_note_id}/returns"
query_path = "&".join("{}={}".format(k, v) for k, v in kwargs.items())
if query_path:
url = f"{url}?{query_path}"
return self.get_essential_details(method, url)

def withdraw(self, fixed_note_id, **kwargs):
"""
Withdraw from a fixed note.

Args:
fixed_note_id (str): The unique identifier for the fixed note.
amount (float): Optional. Specific amount to withdraw.
liquidate_all (bool): Optional. Whether to liquidate all units.
same_day_if_mature (bool): Optional. Whether to process same day if mature.

Returns:
dict: The API response containing withdrawal details.
"""
method = "POST"
url = self.base_url + f"fixed-notes/{fixed_note_id}/withdraw"
payload = json.dumps(kwargs)
return self.get_essential_details(method, url, payload)

def rollover(self, fixed_note_id, tenor_in_months):
"""
Rollover a fixed note for an additional period.

Args:
fixed_note_id (str): The unique identifier for the fixed note.
tenor_in_months (int): Additional duration in months.

Returns:
dict: The API response containing rollover details.
"""
method = "POST"
url = self.base_url + f"fixed-notes/{fixed_note_id}/rollover"
payload = json.dumps({"tenor_in_months": tenor_in_months})
return self.get_essential_details(method, url, payload)

def partial_update(self, fixed_note_id, **kwargs):
"""
Partially update a fixed note.

Args:
fixed_note_id (str): The unique identifier for the fixed note.
**kwargs: Fields to update (e.g., auto_reinvest).

Returns:
dict: The API response.
"""
method = "PATCH"
url = self.base_url + f"fixed-notes/{fixed_note_id}"
payload = json.dumps(kwargs)
return self.get_essential_details(method, url, payload)
Loading
Loading