Skip to content

Commit

Permalink
Issue 138 funding (#139)
Browse files Browse the repository at this point in the history
* Using templates

* removed response headers

* Fixed fundings

* Commit from GitHub Actions
  • Loading branch information
stabacco authored Feb 2, 2022
1 parent 709130e commit 89af298
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 185 deletions.
4 changes: 2 additions & 2 deletions coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion stake/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Url(str, Enum):
create_session: str = "sessions/v2/createSession"
equity_positions: str = "users/accounts/v2/equityPositions"
fund_details: str = "fund/details"
fundings: str = "utils/activityLog/fundingOnly"
fundings: str = "users/accounts/transactionHistory"
market_status: str = "utils/marketStatus"
orders: str = "users/accounts/v2/orders"
quotes: str = "quotes/marketData/${symbols}"
Expand Down
58 changes: 16 additions & 42 deletions stake/funding.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,17 @@
"""Your current fundings."""
from datetime import date, datetime, timedelta
import json
from datetime import datetime
from typing import List, Optional

from pydantic import BaseModel, Field
from pydantic.types import UUID4

from stake.common import BaseClient, camelcase
from stake.constant import Url

__all__ = ["FundingRequest"]


class FundingRequest(BaseModel):
"""Request to be issued to the fundings endpoint."""

end_date: date = Field(default_factory=date.today)
start_date: date = Field(
default_factory=lambda *_: date.today() - timedelta(days=365)
)


class Funding(BaseModel):
id: UUID4
timestamp: datetime
order_type: str
event_type: str
status: str
title: str
amount: str
description: str
currency_from: str
currency_to: str
spot_rate: float
total_fee: float
amount_from: float
amount_to: float
rate: float
reference_number: str

class Config:
alias_generator = camelcase
from stake.transaction import (
TransactionHistoryElement,
TransactionHistoryType,
TransactionRecordRequest,
)


class CashSettlement(BaseModel):
Expand Down Expand Up @@ -80,14 +52,16 @@ class Config:


class FundingsClient(BaseClient):
async def list(self, request: FundingRequest) -> List[Funding]:
payload = {
"endDate": request.end_date.strftime("%d/%m/%Y"),
"startDate": request.start_date.strftime("%d/%m/%Y"),
}
async def list(
self, request: TransactionRecordRequest
) -> List[TransactionHistoryElement]:
payload = json.loads(request.json(by_alias=True))
data = await self._client.post(Url.fundings, payload=payload)

return [Funding(**d) for d in data]
return [
TransactionHistoryElement(**d)
for d in data
if d["referenceType"] == TransactionHistoryType.FUNDING.value
]

async def in_flight(self) -> List[FundsInFlight]:
"""Returns the funds currently in flight."""
Expand Down
43 changes: 38 additions & 5 deletions stake/transaction.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import enum
import json
from datetime import datetime, timedelta
from enum import Enum
from typing import Dict, List, Optional
Expand All @@ -19,7 +21,7 @@ class TransactionRecordEnumDirection(str, Enum):
class TransactionRecordRequest(BaseModel):
to: datetime = Field(default_factory=datetime.utcnow)
from_: datetime = Field(
default_factory=lambda *_: datetime.utcnow() - timedelta(days=365)
default_factory=lambda *_: datetime.utcnow() - timedelta(days=365), alias="from"
)
limit: int = 1000
offset: Optional[int]
Expand Down Expand Up @@ -68,6 +70,40 @@ class Config:
alias_generator = camelcase


class TransactionHistoryType(str, enum.Enum):
BUY = "Buy"
CORPORATE_ACTION = "Corporate Action"
DIVIDEND = "Dividend"
DIVIDEND_TAX = "Dividend Tax"
FUNDING = "Funding"
SELL = "Sell"


class TransactionHistorySide(str, enum.Enum):
CREDIT = "CREDIT"
DEBIT = "DEBIT"


class TransactionHistoryElement(BaseModel):
transaction_type: TransactionHistoryType
fin_tran_type_id: Optional[str] = None
timestamp: datetime
tran_amount: Optional[float] = None
fee_amount: Optional[float] = None
side: TransactionHistorySide
text: str
comment: str
amount_per_share: float
tax_rate: float
order_id: Optional[str] = None
symbol: Optional[str] = None
reference: Optional[str] = None
reference_type: Optional[TransactionHistoryType] = None

class Config:
alias_generator = camelcase


class TransactionsClient(BaseClient):
async def list(self, request: TransactionRecordRequest) -> List[Transaction]:
"""Returns the transactions executed by the user.
Expand All @@ -79,10 +115,7 @@ async def list(self, request: TransactionRecordRequest) -> List[Transaction]:
Returns:
List[Transaction]: the transactions executed in the time frame.
"""
payload = request.dict()
payload.update(
{"to": payload["to"].isoformat(), "from": payload.pop("from_").isoformat()}
)
payload = json.loads(request.json(by_alias=True))

data = await self._client.post(Url.account_transactions, payload=payload)
transactions = []
Expand Down
86 changes: 3 additions & 83 deletions tests/cassettes/test_funding/test_funds_in_flight.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,41 +27,7 @@ interactions:
"fxSpeed": "Regular", "facilitaStatus": null, "dateOfBirth": null, "upToDateDetails2021":
"NO_REQUIREMENTS", "stakeKycStatus": "KYC_APPROVED", "awxMigrationDocsRequired":
null, "documentsStatus": "NO_ACTION", "mfaenabled": false}'
headers:
Access-Control-Allow-Headers:
- Content-type, Accept, Stake-Session-Token, stake_tid
Access-Control-Allow-Methods:
- GET, POST, DELETE, PUT
Access-Control-Allow-Origin:
- '*'
Connection:
- keep-alive
Content-Length:
- '1187'
Content-Type:
- application/json
Date:
- Wed, 19 Jan 2022 23:47:25 GMT
Via:
- 1.1 e3d6764a647541ed814ff5842b8b1476.cloudfront.net (CloudFront)
X-Amz-Cf-Id:
- k3bkL5K_B72p2N5kVZDNcc1Y40RN6yIA731WDQscLeiZ9Cb8aBQ9aA==
X-Amz-Cf-Pop:
- SYD62-P2
X-Cache:
- Miss from cloudfront
stake_tid:
- 656bf946-1cca-49b2-8c30-8ed012bf8467
x-amz-apigw-id:
- MN5qBERFywMF-sQ=
x-amzn-Remapped-Content-Length:
- '1187'
x-amzn-Remapped-Date:
- Wed, 19 Jan 2022 23:47:24 GMT
x-amzn-Remapped-Server:
- Jetty(9.4.44.v20210927)
x-amzn-RequestId:
- fc247b8a-2fcc-42d0-9ff2-4e1f17397d60
headers: {}
status:
code: 200
message: OK
Expand All @@ -77,54 +43,8 @@ interactions:
uri: https://global-prd-api.hellostake.com/api/fund/details
response:
body:
string: |
'{"fundsInFlight": [
{
"type": "Funding",
"insertDateTime": "17 Sep 2020 05:21AM",
"estimatedArrivalTime": "19 Sep 2020 05:00AM",
"estimatedArrivalTimeUS": "Fri 1:00pm NY time",
"transactionType": "Poli",
"toAmount": 1512.0,
"fromAmount": 2100.0
}
]}
'
headers:
Access-Control-Allow-Headers:
- Content-type, Accept, Stake-Session-Token, stake_tid
Access-Control-Allow-Methods:
- GET, POST, DELETE, PUT
Access-Control-Allow-Origin:
- '*'
Connection:
- keep-alive
Content-Length:
- '20'
Content-Type:
- application/json
Date:
- Wed, 19 Jan 2022 23:47:25 GMT
Via:
- 1.1 b96ad58427ffff8b9d3959350f8c9f16.cloudfront.net (CloudFront)
X-Amz-Cf-Id:
- ya0CFD1VuJq5VOB_JdqS4gLyUgtFQBrdZI8OMv7PFkzxYQ-gqLtnuw==
X-Amz-Cf-Pop:
- SYD62-P2
X-Cache:
- Miss from cloudfront
stake_tid:
- 179618fa-5fb5-4281-8e0e-1a28093ed963
x-amz-apigw-id:
- MN5qHEYpSwMF74w=
x-amzn-Remapped-Content-Length:
- '20'
x-amzn-Remapped-Date:
- Wed, 19 Jan 2022 23:47:25 GMT
x-amzn-Remapped-Server:
- Jetty(9.4.44.v20210927)
x-amzn-RequestId:
- 513d1f21-81a5-4a7d-b960-f6cdc9f96dde
string: '{"fundsInFlight": [{"type": "Funding","insertDateTime": "17 Sep 2020 05:21AM","estimatedArrivalTime": "19 Sep 2020 05:00AM","estimatedArrivalTimeUS": "Fri 1:00pm NY time","transactionType": "Poli", "toAmount": 1512.0,"fromAmount": 2100.0}]}'
headers: {}
status:
code: 200
message: OK
Expand Down
49 changes: 16 additions & 33 deletions tests/cassettes/test_funding/test_list_fundings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,43 +27,26 @@ interactions:
"fxSpeed": "Regular", "facilitaStatus": null, "dateOfBirth": null, "upToDateDetails2021":
"NO_REQUIREMENTS", "stakeKycStatus": "KYC_APPROVED", "awxMigrationDocsRequired":
null, "documentsStatus": "NO_ACTION", "mfaenabled": false}'
headers: {}
status:
code: 200
message: OK
url: https://global-prd-api.hellostake.com/api/user
- request:
body: null
headers:
Access-Control-Allow-Headers:
- Content-type, Accept, Stake-Session-Token, stake_tid
Access-Control-Allow-Methods:
- GET, POST, DELETE, PUT
Access-Control-Allow-Origin:
- '*'
Connection:
- keep-alive
Content-Length:
- '1187'
Accept:
- application/json
Content-Type:
- application/json
Date:
- Wed, 19 Jan 2022 23:47:22 GMT
Via:
- 1.1 f1add8f4c4c2d3927809bab0bfad9b82.cloudfront.net (CloudFront)
X-Amz-Cf-Id:
- x4D2vnxhunv51D7owRTp1faZ6Au0cDkdVnFiZiL_ns05SW8nhzwnYA==
X-Amz-Cf-Pop:
- SYD62-P2
X-Cache:
- Miss from cloudfront
stake_tid:
- 1d0beda3-3154-4fd2-bc31-139b5d5a2b5d
x-amz-apigw-id:
- MN5poG8mywMFY2Q=
x-amzn-Remapped-Content-Length:
- '1187'
x-amzn-Remapped-Date:
- Wed, 19 Jan 2022 23:47:22 GMT
x-amzn-Remapped-Server:
- Jetty(9.4.44.v20210927)
x-amzn-RequestId:
- 329118f9-1a4d-4acd-980b-940d0970b644
method: POST
uri: https://global-prd-api.hellostake.com/api/users/accounts/transactionHistory
response:
body:
string: '[{"transactionType": "Funding","finTranTypeID": "JNLC","timestamp": "2021-09-30T15:45:50.425Z","tranAmount": 1000,"feeAmount": 0.0,"orderID": "HHI.1cf93550-8eb4-4c32-a229-826cf8c1be59","symbol": null,"side": "CREDIT","text": "Deposit","comment": "S7-1945193t","amountPerShare": 0.0,"taxRate": 0.0,"reference": "P0-3814688Z","referenceType": "Funding"},{"transactionType": "Funding","finTranTypeID": "JNLC","timestamp": "2021-09-30T15:45:50.425Z","tranAmount": 1000,"feeAmount": 0.0,"orderID": "HHI.1cf93550-8eb4-4c32-a229-826cf8c1be59","symbol": null,"side": "CREDIT","text": "Deposit","comment": "S7-1945193t","amountPerShare": 0.0,"taxRate": 0.0,"reference": "P0-3814688Z","referenceType": "Funding"}]'
headers: {}
status:
code: 200
message: OK
url: https://global-prd-api.hellostake.com/api/user
url: https://global-prd-api.hellostake.com/api/users/accounts/transactionHistory
version: 1
3 changes: 3 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ def redact_sensitive_data(response):
"cashAvailableForWithdrawal": 1000,
"cashAvailableForTrade": 800,
"dwCashAvailableForWithdrawal": 1000,
"reference": fake.pystr_format(),
"comment": fake.pystr_format(),
"tranAmount": 1000,
}

def _redact_response_body(body):
Expand Down
41 changes: 22 additions & 19 deletions tests/test_funding.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
# import pytest
import pytest

# from stake.funding import FundingRequest
from stake.funding import TransactionRecordRequest

# @pytest.mark.vcr()
# @pytest.mark.asyncio
# async def test_list_fundings(tracing_client):
# fundings = await tracing_client.fundings.list(FundingRequest())
# assert len(fundings) == 11

# @pytest.mark.vcr()
# @pytest.mark.asyncio
# async def test_cash_available(tracing_client):
# cash_available = await tracing_client.fundings.cash_available()
# assert cash_available.cash_available_for_withdrawal == 1000.0
# assert cash_available.cash_settlement[0].utc_time.month == 1
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_list_fundings(tracing_client):
fundings = await tracing_client.fundings.list(TransactionRecordRequest())
assert len(fundings) == 2

# @pytest.mark.vcr()
# @pytest.mark.asyncio
# async def test_funds_in_flight(tracing_client):
# funds_in_flight = await tracing_client.fundings.in_flight()
# assert len(funds_in_flight) == 1
# assert funds_in_flight[0].transaction_type == "Poli"

@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_cash_available(tracing_client):
cash_available = await tracing_client.fundings.cash_available()
assert cash_available.cash_available_for_withdrawal == 1000.0
assert cash_available.cash_settlement[0].utc_time.month == 1


@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_funds_in_flight(tracing_client):
funds_in_flight = await tracing_client.fundings.in_flight()
assert len(funds_in_flight) == 1
assert funds_in_flight[0].transaction_type == "Poli"

0 comments on commit 89af298

Please sign in to comment.