1
0

Kucoin deposits and withdrawals
Some checks failed
Python Ruff Code Quality / ruff (push) Failing after 22s
Run Python tests (through Pytest) / Test (push) Successful in 31s
Verify Python project can be installed, loaded and have version checked / Test (push) Successful in 24s

This commit is contained in:
Jon Michael Aanes 2024-11-27 21:56:13 +01:00
parent fee812a24e
commit 678390e881
Signed by: Jmaa
SSH Key Fingerprint: SHA256:Ab0GfHGCblESJx7JRE4fj4bFy/KRpeLhi41y4pF3sNA
4 changed files with 197 additions and 92 deletions

View File

@ -134,3 +134,30 @@ class TradeOrderDetails:
order_id: object order_id: object
raw_order_details: object raw_order_details: object
@enforce_typing.enforce_types
@dataclasses.dataclass(frozen=True)
class WithdrawalDetails:
withdrawn_asset: Asset
withdrawn_amount: Decimal
fee_asset: Asset
fee_amount: Decimal
executed_time: datetime.datetime
raw_details: object
@enforce_typing.enforce_types
@dataclasses.dataclass(frozen=True)
class DepositDetails:
deposit_asset: Asset
deposit_amount: Decimal
fee_asset: Asset
fee_amount: Decimal
executed_time: datetime.datetime
raw_details: object

View File

@ -8,7 +8,8 @@ from decimal import Decimal
import fin_defs import fin_defs
import kucoin.client import kucoin.client
from .data import DepoFetcher, DepoGroup, DepoSingle, TradeOrderDetails from .data import (DepoFetcher, DepoGroup, DepoSingle, TradeOrderDetails,
WithdrawalDetails, DepositDetails)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -146,6 +147,50 @@ class KucoinDepoFetcher(DepoFetcher):
# Determine order details # Determine order details
return self._get_order_details(response['orderId'], input_asset, output_asset) return self._get_order_details(response['orderId'], input_asset, output_asset)
def _get_withdrawals(self) -> list[WithdrawalDetails]:
raw_details = self.kucoin_client.get_withdrawals()
withdrawals = []
for item in raw_details['items']:
withdrawn_asset = parse_asset_from_ticker(item['currency'])
withdrawn_amount = Decimal(item['amount'])
fee_asset = withdrawn_asset # Assumed
fee_amount = Decimal(item['fee'])
executed_time=datetime.datetime.fromtimestamp(
item['createdAt'] / 1000,
tz=datetime.UTC,
)
withdrawals.append(WithdrawalDetails(withdrawn_asset,
withdrawn_amount, fee_asset,
fee_amount, executed_time,
item))
del item
return withdrawals
def _get_deposits(self) -> list[WithdrawalDetails]:
raw_details = self.kucoin_client.get_deposits()
deposits = []
for item in raw_details['items']:
deposit_asset = parse_asset_from_ticker(item['currency'])
deposit_amount = Decimal(item['amount'])
fee_asset = deposit_asset # Assumed
fee_amount = Decimal(item['fee'])
executed_time=datetime.datetime.fromtimestamp(
item['createdAt'] / 1000,
tz=datetime.UTC,
)
deposits.append(DepositDetails(deposit_asset,
deposit_amount, fee_asset,
fee_amount, executed_time,
item))
del item
return deposits
def _get_order_details( def _get_order_details(
self, self,
order_id: str, order_id: str,

View File

@ -19,106 +19,30 @@ fin_depo.defi_kucoin.logger.setLevel('INFO')
NOW = datetime.datetime.now(tz=datetime.UTC) NOW = datetime.datetime.now(tz=datetime.UTC)
def get_fetcher() -> fin_depo.defi_kucoin.KucoinDepoFetcher:
@needs_secrets return fin_depo.defi_kucoin.KucoinDepoFetcher(
def test_get_depo():
"""Can inspect kucoin depository."""
fetcher = fin_depo.defi_kucoin.KucoinDepoFetcher(
secrets.KUCOIN_KEY, secrets.KUCOIN_KEY,
secrets.KUCOIN_SECRET, secrets.KUCOIN_SECRET,
secrets.KUCOIN_PASS, secrets.KUCOIN_PASS,
) )
depo = fetcher.get_depo() @needs_secrets
def test_get_depo():
"""Can inspect kucoin depository."""
depo = get_fetcher().get_depo()
assert isinstance(depo, fin_depo.data.DepoGroup) assert isinstance(depo, fin_depo.data.DepoGroup)
for nested_depo in depo.nested: for nested_depo in depo.nested:
assert isinstance(nested_depo, fin_depo.data.DepoSingle) assert isinstance(nested_depo, fin_depo.data.DepoSingle)
@needs_secrets
def test_get_withdrawals():
withdrawals = get_fetcher()._get_withdrawals()
print(withdrawals)
assert len(withdrawals) > 0
@needs_secrets @needs_secrets
def test_place_market_order_requires_allow_trades(): def test_get_deposits():
"""Client fails if allow_trades is not enabled when doing market orders.""" deposits = get_fetcher()._get_deposits()
fetcher = fin_depo.defi_kucoin.KucoinDepoFetcher( print(deposits)
secrets.KUCOIN_KEY, assert len(deposits) > 0
secrets.KUCOIN_SECRET,
secrets.KUCOIN_PASS,
allow_trades=False,
)
with pytest.raises(PermissionError) as m:
fetcher.place_market_order(fin_defs.MPC, Decimal(1), fin_defs.USDT)
assert 'KucoinDepoFetcher.allow_trades is not enabled: Cannot make trades' in str(m)
@needs_secrets
def test_place_buy_side_order():
"""Client can place buy side market orders."""
fetcher = fin_depo.defi_kucoin.KucoinDepoFetcher(
secrets.KUCOIN_KEY,
secrets.KUCOIN_SECRET,
secrets.KUCOIN_PASS,
allow_trades=TEST_MARKET_ORDERS,
)
input_amount = Decimal('0.1')
order_details = fetcher.place_market_order(
fin_defs.USDT,
input_amount,
fin_defs.MPC,
)
assert order_details is not None
assert order_details.order_id is not None
assert order_details.raw_order_details is not None
assert order_details.input_asset == fin_defs.USDT
assert order_details.output_asset == fin_defs.MPC
assert order_details.input_amount <= input_amount
assert order_details.output_amount >= 0
assert order_details.input_amount != order_details.output_amount
assert order_details.fee_asset == fin_defs.USDT
assert order_details.fee_amount <= Decimal('0.0002')
assert NOW <= order_details.executed_time <= NOW + datetime.timedelta(minutes=10)
@needs_secrets
def test_place_sell_side_order():
"""Client can place sell side market orders."""
fetcher = fin_depo.defi_kucoin.KucoinDepoFetcher(
secrets.KUCOIN_KEY,
secrets.KUCOIN_SECRET,
secrets.KUCOIN_PASS,
allow_trades=TEST_MARKET_ORDERS,
)
input_amount = Decimal('1')
order_details = fetcher.place_market_order(
fin_defs.MPC,
input_amount,
fin_defs.USDT,
)
assert order_details is not None
assert order_details.order_id is not None
assert order_details.raw_order_details is not None
assert order_details.input_asset == fin_defs.MPC
assert order_details.output_asset == fin_defs.USDT
assert order_details.input_amount <= input_amount
assert order_details.output_amount >= 0
assert order_details.input_amount != order_details.output_amount
assert order_details.fee_asset == fin_defs.USDT
assert order_details.fee_amount is not None
assert NOW <= order_details.executed_time <= NOW + datetime.timedelta(minutes=10)

109
test/test_kucoin_trading.py Normal file
View File

@ -0,0 +1,109 @@
import datetime
from decimal import Decimal
import fin_defs
import pytest
import fin_depo
from . import secrets
TEST_MARKET_ORDERS = True
needs_secrets = pytest.mark.skipif(
not secrets.KUCOIN_KEY,
reason='Secret kucoin_USERNAME required',
)
fin_depo.defi_kucoin.logger.setLevel('INFO')
NOW = datetime.datetime.now(tz=datetime.UTC)
@needs_secrets
def test_place_market_order_requires_allow_trades():
"""Client fails if allow_trades is not enabled when doing market orders."""
fetcher = fin_depo.defi_kucoin.KucoinDepoFetcher(
secrets.KUCOIN_KEY,
secrets.KUCOIN_SECRET,
secrets.KUCOIN_PASS,
allow_trades=False,
)
with pytest.raises(PermissionError) as m:
fetcher.place_market_order(fin_defs.MPC, Decimal(1), fin_defs.USDT)
assert 'KucoinDepoFetcher.allow_trades is not enabled: Cannot make trades' in str(m)
@needs_secrets
def test_place_buy_side_order():
"""Client can place buy side market orders."""
fetcher = fin_depo.defi_kucoin.KucoinDepoFetcher(
secrets.KUCOIN_KEY,
secrets.KUCOIN_SECRET,
secrets.KUCOIN_PASS,
allow_trades=TEST_MARKET_ORDERS,
)
input_amount = Decimal('0.1')
order_details = fetcher.place_market_order(
fin_defs.USDT,
input_amount,
fin_defs.MPC,
)
assert order_details is not None
assert order_details.order_id is not None
assert order_details.raw_order_details is not None
assert order_details.input_asset == fin_defs.USDT
assert order_details.output_asset == fin_defs.MPC
assert order_details.input_amount <= input_amount
assert order_details.output_amount >= 0
assert order_details.input_amount != order_details.output_amount
assert order_details.fee_asset == fin_defs.USDT
assert order_details.fee_amount <= Decimal('0.0002')
assert NOW <= order_details.executed_time <= NOW + datetime.timedelta(minutes=10)
@needs_secrets
def test_place_sell_side_order():
"""Client can place sell side market orders."""
fetcher = fin_depo.defi_kucoin.KucoinDepoFetcher(
secrets.KUCOIN_KEY,
secrets.KUCOIN_SECRET,
secrets.KUCOIN_PASS,
allow_trades=TEST_MARKET_ORDERS,
)
input_amount = Decimal('1')
order_details = fetcher.place_market_order(
fin_defs.MPC,
input_amount,
fin_defs.USDT,
)
assert order_details is not None
assert order_details.order_id is not None
assert order_details.raw_order_details is not None
assert order_details.input_asset == fin_defs.MPC
assert order_details.output_asset == fin_defs.USDT
assert order_details.input_amount <= input_amount
assert order_details.output_amount >= 0
assert order_details.input_amount != order_details.output_amount
assert order_details.fee_asset == fin_defs.USDT
assert order_details.fee_amount is not None
assert NOW <= order_details.executed_time <= NOW + datetime.timedelta(minutes=10)