1310 lines
51 KiB
Python
1310 lines
51 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
|
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
|
|
|
from ccxt.base.exchange import Exchange
|
|
from ccxt.abstract.aftermath import ImplicitAPI
|
|
from ccxt.base.types import Account, Any, Balances, Currencies, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Trade, TradingFeeInterface, Transaction, TransferEntry
|
|
from typing import List
|
|
from ccxt.base.errors import ExchangeError
|
|
from ccxt.base.errors import ArgumentsRequired
|
|
from ccxt.base.errors import NotSupported
|
|
from ccxt.base.decimal_to_precision import TICK_SIZE
|
|
|
|
|
|
class aftermath(Exchange, ImplicitAPI):
|
|
|
|
def describe(self) -> Any:
|
|
return self.deep_extend(super(aftermath, self).describe(), {
|
|
'id': 'aftermath',
|
|
'name': 'AftermathFinance',
|
|
'countries': [],
|
|
'version': 'v1',
|
|
'rateLimit': 50, # 1200 requests per minute, 20 request per second
|
|
'certified': False,
|
|
'pro': True,
|
|
'dex': True,
|
|
'has': {
|
|
'CORS': None,
|
|
'spot': False,
|
|
'margin': False,
|
|
'swap': True,
|
|
'future': False,
|
|
'option': False,
|
|
'addMargin': True,
|
|
'cancelOrder': True,
|
|
'cancelOrders': True,
|
|
'createOrder': True,
|
|
'createOrders': True,
|
|
'editOrder': False,
|
|
'fetchAccounts': True,
|
|
'fetchBalance': True,
|
|
'fetchCurrencies': True,
|
|
'fetchDepositAddress': False,
|
|
'fetchDeposits': False,
|
|
'fetchLedger': False,
|
|
'fetchMarkets': True,
|
|
'fetchMyTrades': False,
|
|
'fetchOHLCV': True,
|
|
'fetchOpenOrders': True,
|
|
'fetchOrder': False,
|
|
'fetchOrderBook': True,
|
|
'fetchOrders': False,
|
|
'fetchPosition': True,
|
|
'fetchPositions': True,
|
|
'fetchTicker': True,
|
|
'fetchTickers': True,
|
|
'fetchTrades': True,
|
|
'fetchTradingFee': True,
|
|
'fetchTradingFees': False,
|
|
'fetchTradingLimits': False,
|
|
'fetchTransactions': False,
|
|
'fetchWithdrawals': False,
|
|
'reduceMargin': True,
|
|
'setLeverage': True,
|
|
'transfer': True,
|
|
'withdraw': True,
|
|
},
|
|
'timeframes': {
|
|
'1m': '1m',
|
|
'3m': '3m',
|
|
'5m': '5m',
|
|
'15m': '15m',
|
|
'30m': '30m',
|
|
'1h': '1h',
|
|
'2h': '2h',
|
|
'4h': '4h',
|
|
'8h': '8h',
|
|
'12h': '12h',
|
|
'1d': '1d',
|
|
'3d': '3d',
|
|
'1w': '1w',
|
|
'1M': '1M',
|
|
},
|
|
'urls': {
|
|
'logo': 'https://github.com/user-attachments/assets/70e5ae86-2f3a-4755-976b-aedb9d3c2807',
|
|
'api': {
|
|
'rest': 'https://aftermath.finance/api/ccxt',
|
|
},
|
|
'test': {
|
|
'rest': 'https://testnet.aftermath.finance/api/ccxt',
|
|
},
|
|
'docs': 'https://docs.aftermath.finance',
|
|
},
|
|
'api': {
|
|
'public': {
|
|
'get': {
|
|
'markets': 1,
|
|
'currencies': 1,
|
|
},
|
|
'post': {
|
|
'ticker': 1,
|
|
'orderbook': 1,
|
|
'trades': 1,
|
|
'OHLCV': 1,
|
|
},
|
|
},
|
|
'private': {
|
|
'post': {
|
|
'accounts': 1,
|
|
'balance': 1,
|
|
'myPendingOrders': 1,
|
|
'positions': 1,
|
|
'build/allocate': 1,
|
|
'build/cancelOrders': 1,
|
|
'build/createAccount': 1,
|
|
'build/createOrders': 1,
|
|
'build/deallocate': 1,
|
|
'build/deposit': 1,
|
|
'build/setLeverage': 1,
|
|
'build/withdraw': 1,
|
|
'submit/allocate': 1,
|
|
'submit/cancelOrders': 1,
|
|
'submit/createAccount': 1,
|
|
'submit/createOrders': 1,
|
|
'submit/deallocate': 1,
|
|
'submit/deposit': 1,
|
|
'submit/setLeverage': 1,
|
|
'submit/withdraw': 1,
|
|
},
|
|
},
|
|
},
|
|
'requiredCredentials': {
|
|
'apiKey': False,
|
|
'secret': False,
|
|
'walletAddress': True,
|
|
'privateKey': True,
|
|
},
|
|
'precisionMode': TICK_SIZE,
|
|
'options': {
|
|
'defaultType': 'swap',
|
|
'sandboxMode': False,
|
|
},
|
|
'exceptions': {
|
|
'exact': {},
|
|
'broad': {},
|
|
},
|
|
'features': {
|
|
'default': {
|
|
'sandbox': True,
|
|
'createOrder': {
|
|
'timeInForce': {
|
|
'IOC': True,
|
|
'FOK': True,
|
|
'PO': True,
|
|
'GTD': False,
|
|
},
|
|
'leverage': False,
|
|
'marketBuyRequiresPrice': False,
|
|
'marketBuyByCost': False,
|
|
'selfTradePrevention': False,
|
|
'trailing': False,
|
|
'iceberg': False,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
def fetch_currencies(self, params={}) -> Currencies:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/currencies
|
|
|
|
fetches all available currencies on an exchange
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: an associative dictionary of currencies
|
|
"""
|
|
response = self.publicGetCurrencies(params)
|
|
currencies = self.parse_currencies(response)
|
|
#
|
|
# {
|
|
# "BTC": {
|
|
# "id": "BTC",
|
|
# "code": "BTC",
|
|
# "precision": 1e-9,
|
|
# "name": "BTC",
|
|
# "active": True,
|
|
# "deposit": False,
|
|
# "withdraw": False,
|
|
# "limits": {
|
|
# "amount": {},
|
|
# "withdraw": {}
|
|
# },
|
|
# "networks": {}
|
|
# }
|
|
# }
|
|
#
|
|
return currencies
|
|
|
|
def parse_currency(self, rawCurrency: dict) -> Currency:
|
|
return self.safe_currency_structure({
|
|
'id': self.safe_string(rawCurrency, 'id'),
|
|
'code': self.safe_string(rawCurrency, 'code'),
|
|
'name': self.safe_string(rawCurrency, 'name'),
|
|
'active': self.safe_bool(rawCurrency, 'active'),
|
|
'deposit': self.safe_bool(rawCurrency, 'deposit'),
|
|
'withdraw': self.safe_bool(rawCurrency, 'withdraw'),
|
|
'precision': self.safe_number(rawCurrency, 'precision'),
|
|
'type': 'crypto',
|
|
'info': rawCurrency,
|
|
})
|
|
|
|
def fetch_markets(self, params={}) -> List[Market]:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/markets
|
|
|
|
retrieves data on all markets for woo
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict[]: an array of objects representing market data
|
|
"""
|
|
response = self.publicGetMarkets(params)
|
|
#
|
|
# [
|
|
# {
|
|
# "id": "0x49bd40cc7880bd358465116157f0271c25d23361b94eace9a25dc2019b449bfc",
|
|
# "symbol": "BTC/USD:USDC",
|
|
# "base": "BTC",
|
|
# "quote": "USD",
|
|
# "baseId": "BTC",
|
|
# "quoteId": "USD",
|
|
# "active": True,
|
|
# "type": "swap",
|
|
# "spot": False,
|
|
# "margin": False,
|
|
# "swap": True,
|
|
# "future": False,
|
|
# "option": False,
|
|
# "contract": True,
|
|
# "settle": "USDC",
|
|
# "settleId": "0x457049371f5b5dc2bda857bb804ca6e93c5a3cae1636d0cd17bb6b6070d19458::usdc::USDC",
|
|
# "contractSize": 0.00001,
|
|
# "linear": True,
|
|
# "inverse": False,
|
|
# "taker": 0.001,
|
|
# "maker": 0.0,
|
|
# "percentage": True,
|
|
# "tierBased": False,
|
|
# "precision": {
|
|
# "amount": 0.00001,
|
|
# "price": 0.0001
|
|
# },
|
|
# "limits": {
|
|
# "cost": {
|
|
# "min": 1.0
|
|
# },
|
|
# "leverage": {
|
|
# "max": 50.0
|
|
# }
|
|
# },
|
|
# "marginModes": {
|
|
# "isolated": True,
|
|
# "cross": False
|
|
# },
|
|
# "subType": "linear"
|
|
# }
|
|
# ]
|
|
#
|
|
return self.parse_markets(response)
|
|
|
|
def parse_market(self, market: dict) -> Market:
|
|
#
|
|
# {
|
|
# "id": "0x49bd40cc7880bd358465116157f0271c25d23361b94eace9a25dc2019b449bfc",
|
|
# "symbol": "BTC/USD:USDC",
|
|
# "base": "BTC",
|
|
# "quote": "USD",
|
|
# "baseId": "BTC",
|
|
# "quoteId": "USD",
|
|
# "active": True,
|
|
# "type": "swap",
|
|
# "spot": False,
|
|
# "margin": False,
|
|
# "swap": True,
|
|
# "future": False,
|
|
# "option": False,
|
|
# "contract": True,
|
|
# "settle": "USDC",
|
|
# "settleId": "0x457049371f5b5dc2bda857bb804ca6e93c5a3cae1636d0cd17bb6b6070d19458::usdc::USDC",
|
|
# "contractSize": 0.00001,
|
|
# "linear": True,
|
|
# "inverse": False,
|
|
# "taker": 0.001,
|
|
# "maker": 0.0,
|
|
# "percentage": True,
|
|
# "tierBased": False,
|
|
# "precision": {
|
|
# "amount": 0.00001,
|
|
# "price": 0.0001
|
|
# },
|
|
# "limits": {
|
|
# "cost": {
|
|
# "min": 1.0
|
|
# },
|
|
# "leverage": {
|
|
# "max": 50.0
|
|
# }
|
|
# },
|
|
# "marginModes": {
|
|
# "isolated": True,
|
|
# "cross": False
|
|
# },
|
|
# "subType": "linear"
|
|
# }
|
|
#
|
|
precision = self.safe_dict(market, 'precision')
|
|
limits = self.safe_dict(market, 'limits')
|
|
return self.safe_market_structure({
|
|
'id': self.safe_string(market, 'id'),
|
|
'symbol': self.safe_string(market, 'symbol'),
|
|
'base': self.safe_string(market, 'base'),
|
|
'quote': self.safe_string(market, 'quote'),
|
|
'settle': self.safe_string(market, 'settle'),
|
|
'baseId': self.safe_string(market, 'baseId'),
|
|
'quoteId': self.safe_string(market, 'quoteId'),
|
|
'settleId': self.safe_string(market, 'settleId'),
|
|
'type': self.safe_string(market, 'type'),
|
|
'subType': self.safe_string(market, 'subType'),
|
|
'spot': self.safe_bool(market, 'spot'),
|
|
'margin': self.safe_bool(market, 'margin'),
|
|
'swap': self.safe_bool(market, 'swap'),
|
|
'future': self.safe_bool(market, 'future'),
|
|
'option': self.safe_bool(market, 'option'),
|
|
'active': self.safe_bool(market, 'active'),
|
|
'contract': self.safe_bool(market, 'contract'),
|
|
'linear': self.safe_bool(market, 'linear'),
|
|
'inverse': self.safe_bool(market, 'inverse'),
|
|
'tierBased': self.safe_bool(market, 'tierBased'),
|
|
'percentage': self.safe_bool(market, 'percentage'),
|
|
'contractSize': self.safe_number(market, 'contractSize'),
|
|
'expiry': None,
|
|
'expiryDatetime': None,
|
|
'strike': None,
|
|
'optionType': None,
|
|
'taker': self.safe_number(market, 'taker'),
|
|
'maker': self.safe_number(market, 'maker'),
|
|
'precision': {
|
|
'amount': self.safe_number(precision, 'amount'),
|
|
'price': self.safe_number(precision, 'price'),
|
|
},
|
|
'limits': {
|
|
'leverage': {
|
|
'min': None,
|
|
'max': self.safe_number(limits['leverage'], 'max'),
|
|
},
|
|
'amount': {
|
|
'min': None,
|
|
'max': None,
|
|
},
|
|
'price': {
|
|
'min': None,
|
|
'max': None,
|
|
},
|
|
'cost': {
|
|
'min': self.safe_number(limits['cost'], 'min'),
|
|
'max': None,
|
|
},
|
|
},
|
|
'marginModes': self.safe_dict(market, 'marginModes'),
|
|
'created': None,
|
|
'info': market,
|
|
})
|
|
|
|
def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/markets
|
|
|
|
fetch the trading fees for a market
|
|
:param str symbol: unified market symbol
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: a `fee structure <https://docs.ccxt.com/?id=fee-structure>`
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
return self.parse_trading_fee(market)
|
|
|
|
def parse_trading_fee(self, market: Market = None) -> TradingFeeInterface:
|
|
symbol = self.safe_string(market, 'symbol')
|
|
return {
|
|
'info': market,
|
|
'symbol': symbol,
|
|
'maker': self.safe_number(market, 'maker'),
|
|
'taker': self.safe_number(market, 'taker'),
|
|
'percentage': True,
|
|
'tierBased': None,
|
|
}
|
|
|
|
def fetch_ticker(self, symbol: str, params={}) -> Ticker:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/ticker
|
|
|
|
fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: a `ticker structure <https://docs.ccxt.com/?id=ticker-structure>`
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
request = {
|
|
'chId': market['id'],
|
|
}
|
|
response = self.publicPostTicker(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "ask": 0.1,
|
|
# "askVolume": 0.1,
|
|
# "average": 0.1,
|
|
# "baseVolume": 0.1,
|
|
# "bid": 0.1,
|
|
# "bidVolume": 0.1,
|
|
# "change": 0.1,
|
|
# "close": 0.1,
|
|
# "high": 0.1,
|
|
# "indexPrice": 0.1,
|
|
# "last": 0.1,
|
|
# "low": 0.1,
|
|
# "markPrice": 0.1,
|
|
# "open": 0.1,
|
|
# "percentage": 0.1,
|
|
# "previousClose": 0.1,
|
|
# "quoteVolume": 0.1,
|
|
# "symbol": "string",
|
|
# "timestamp": null,
|
|
# "vwap": 0.1
|
|
# }
|
|
#
|
|
return self.parse_ticker(response, market)
|
|
|
|
def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
|
|
timestamp = self.safe_integer(ticker, 'timestamp')
|
|
return self.safe_ticker({
|
|
'symbol': self.safe_string(ticker, 'symbol'),
|
|
'timestamp': timestamp,
|
|
'datetime': self.iso8601(timestamp),
|
|
'high': self.safe_string(ticker, 'high'),
|
|
'low': self.safe_string(ticker, 'low'),
|
|
'bid': self.safe_string(ticker, 'bid'),
|
|
'bidVolume': self.safe_string(ticker, 'bidVolume'),
|
|
'ask': self.safe_string(ticker, 'ask'),
|
|
'askVolume': self.safe_string(ticker, 'askVolume'),
|
|
'vwap': self.safe_string(ticker, 'vwap'),
|
|
'open': self.safe_string(ticker, 'open'),
|
|
'close': None,
|
|
'last': None,
|
|
'previousClose': None,
|
|
'change': self.safe_string(ticker, 'change'),
|
|
'percentage': None,
|
|
'average': None,
|
|
'baseVolume': self.safe_string(ticker, 'baseVolume'),
|
|
'quoteVolume': self.safe_string(ticker, 'quoteVolume'),
|
|
'markPrice': None,
|
|
'indexPrice': self.safe_string(ticker, 'indexPrice'),
|
|
'info': ticker,
|
|
}, market)
|
|
|
|
def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/orderbook
|
|
|
|
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
:param str symbol: unified symbol of the market to fetch the order book for
|
|
:param int [limit]: the maximum amount of order book entries to return
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/?id=order-book-structure>` indexed by market symbols
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
chId = self.safe_string(market, 'id')
|
|
request = {
|
|
'chId': chId,
|
|
}
|
|
response = self.publicPostOrderbook(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "asks":[
|
|
# [76228.1534,11.58777]
|
|
# ],
|
|
# "bids":[
|
|
# [76213.4842,11.96145],
|
|
# ],
|
|
# "datetime":"2025-04-07 09:29:28.213 UTC",
|
|
# "timestamp":1744018168213,
|
|
# "symbol":"BTC/USD:USDC"
|
|
# }
|
|
#
|
|
timestamp = self.safe_integer(response, 'timestamp')
|
|
orderbook = self.parse_order_book(response, symbol, timestamp)
|
|
orderbook['nonce'] = self.safe_integer(response, 'nonce')
|
|
return orderbook
|
|
|
|
def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/trades
|
|
|
|
get the list of most recent trades for a particular symbol
|
|
:param str symbol: unified symbol of the market to fetch trades for
|
|
:param int [since]: timestamp in ms of the earliest trade to fetch
|
|
:param int [limit]: the maximum amount of trades to fetch
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param int [params.until]: the latest time in ms to fetch trades for
|
|
:returns Trade[]: a list of `trade structures <https://docs.ccxt.com/?id=public-trades>`
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
chId = self.safe_string(market, 'id')
|
|
request = {
|
|
'chId': chId,
|
|
}
|
|
if limit is not None:
|
|
request['limit'] = min(limit, 50)
|
|
response = self.publicPostTrades(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "trades": [
|
|
# {
|
|
# "amount": 0.03378,
|
|
# "datetime": "2025-12-29 22:43:54.639 UTC",
|
|
# "price": 87239.09499000001,
|
|
# "timestamp": 1767048234639,
|
|
# "side": "buy",
|
|
# "symbol": "BTC/USD:USDC"
|
|
# }
|
|
# ],
|
|
# "nextCursor": 573
|
|
# }
|
|
#
|
|
data = self.safe_list(response, 'trades', [])
|
|
return self.parse_trades(data, market, since, limit)
|
|
|
|
def parse_trade(self, rawTrade: dict, market: Market = None) -> Trade:
|
|
trade = self.safe_trade(self.extend({'info': rawTrade}, rawTrade))
|
|
trade['id'] = ''
|
|
trade['order'] = None
|
|
trade['takerOrMaker'] = None
|
|
trade['timestamp'] = self.safe_integer(rawTrade, 'timestamp')
|
|
return trade
|
|
|
|
def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/ohlcv
|
|
|
|
fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
|
:param str timeframe: the length of time each candle represents
|
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
|
:param int [limit]: max=1000, max=100 when since is defined and is less than(now - (999 * (timeframe in ms)))
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
chId = self.safe_string(market, 'id')
|
|
request = {
|
|
'chId': chId,
|
|
'timeframe': timeframe,
|
|
}
|
|
if since is not None:
|
|
request['since'] = since
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = self.publicPostOHLCV(self.extend(request, params))
|
|
#
|
|
# [
|
|
# [
|
|
# 1743932340000,
|
|
# 83093.5445,
|
|
# 83093.5445,
|
|
# 83093.5445,
|
|
# 83093.5445,
|
|
# 0.0
|
|
# ]
|
|
# ]
|
|
#
|
|
return self.parse_ohlcvs(response, market, timeframe, since, limit)
|
|
|
|
def fetch_balance(self, params={}) -> Balances:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/balance
|
|
|
|
query for balance and get the amount of funds available for trading or funds locked in positions
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param str [params.account]: account object ID, required
|
|
:returns dict: a `balance structure <https://docs.ccxt.com/?id=balance-structure>`
|
|
"""
|
|
account = None
|
|
account, params = self.handle_option_and_params(params, 'fetchBalance', 'account')
|
|
request = {
|
|
'account': account,
|
|
}
|
|
if account is None:
|
|
raise ArgumentsRequired(self.id + ' fetchBalance() requires account')
|
|
response = self.privatePostBalance(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "timestamp": 1744045700352,
|
|
# "balances": {
|
|
# "USDC": {
|
|
# "free": 7.726913939320065,
|
|
# "used": 22.273086060679937,
|
|
# "total": 30.0
|
|
# }
|
|
# }
|
|
# }
|
|
#
|
|
return self.parse_balance(response)
|
|
|
|
def parse_balance(self, response) -> Balances:
|
|
result: dict = {
|
|
'info': response,
|
|
}
|
|
balances = self.safe_dict(response, 'balances', [])
|
|
currencies = list(balances.keys())
|
|
for i in range(0, len(currencies)):
|
|
code = currencies[i]
|
|
balance = balances[code]
|
|
account = self.account()
|
|
account['free'] = self.safe_string(balance, 'free')
|
|
account['used'] = self.safe_string(balance, 'used')
|
|
account['total'] = self.safe_string(balance, 'total')
|
|
result[code] = account
|
|
timestamp = self.safe_integer(response, 'timestamp')
|
|
result['timestamp'] = timestamp
|
|
result['datetime'] = self.iso8601(timestamp)
|
|
return self.safe_balance(result)
|
|
|
|
def fetch_accounts(self, params={}) -> List[Account]:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/accounts
|
|
|
|
query for accounts owned by the walletAddress. An Account is needed for all trading methods.
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns Array: a list of `account structures <https://github.com/ccxt/ccxt/wiki/Manual#accounts>`
|
|
"""
|
|
self.load_markets()
|
|
request = {
|
|
'address': self.walletAddress,
|
|
}
|
|
response = self.privatePostAccounts(self.extend(request, params))
|
|
#
|
|
# [
|
|
# {
|
|
# "id": "0x22c5e3d2f5bcfd4351a62cd70874878b7923b56d79d04225ed96370a7ac844c4",
|
|
# "type": "primary",
|
|
# "code": "USDC",
|
|
# "accountNumber": 14822
|
|
# }
|
|
# ]
|
|
#
|
|
return self.parse_accounts(response)
|
|
|
|
def parse_account(self, account: dict) -> Account:
|
|
return {
|
|
'id': self.safe_string(account, 'id'),
|
|
'type': self.safe_string(account, 'type'),
|
|
'code': self.safe_string(account, 'code'),
|
|
'info': account,
|
|
}
|
|
|
|
def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/my_pending_orders
|
|
|
|
fetch all unfilled currently open orders
|
|
:param str symbol: unified market symbol
|
|
:param int [since]: the earliest time in ms to fetch open orders for
|
|
:param int [limit]: the maximum number of open orders structures to retrieve
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param int [params.accountNumber]: account number to query orders for, required
|
|
:returns Order[]: a list of `order structures <https://docs.ccxt.com/?id=order-structure>`
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
accountNumber = None
|
|
accountNumber, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'accountNumber')
|
|
if accountNumber is None:
|
|
raise ArgumentsRequired(self.id + ' fetchOpenOrders() requires an accountNumber parameter in params')
|
|
request = {
|
|
'chId': self.safe_string(market, 'id'),
|
|
'accountNumber': accountNumber,
|
|
}
|
|
response = self.privatePostMyPendingOrders(self.extend(request, params))
|
|
#
|
|
# [
|
|
# {
|
|
# "id": "340282366919093789037556908196463492660",
|
|
# "datetime": "2025-04-07 14:10:49.472 UTC",
|
|
# "timestamp": 1744035049472,
|
|
# "status": "open",
|
|
# "symbol": "BTC/USD:USDC",
|
|
# "type": "limit",
|
|
# "side": "buy",
|
|
# "price": 10000.0,
|
|
# "amount": 0.0001,
|
|
# "filled": 0.0,
|
|
# "remaining": 0.0001,
|
|
# "cost": 0.0,
|
|
# "trades": [],
|
|
# "fee": {}
|
|
# }
|
|
# ]
|
|
#
|
|
return self.parse_orders(response)
|
|
|
|
def fetch_position(self, symbol: str, params={}):
|
|
"""
|
|
fetch data on an open position
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/positions
|
|
|
|
:param str symbol: unified market symbol of the market the position is held in
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param int [params.accountNumber]: account number to query positions for, required
|
|
:returns dict: a `position structure <https://docs.ccxt.com/?id=position-structure>`
|
|
"""
|
|
positions = self.fetch_positions([symbol], params)
|
|
return self.safe_dict(positions, 0, {})
|
|
|
|
def fetch_positions(self, symbols: Strings = None, params={}):
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/positions
|
|
|
|
fetch all open positions
|
|
:param str[] symbols: list of unified market symbols
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param int [params.accountNumber]: account number to query positions for, required
|
|
:returns dict[]: a list of `position structure <https://docs.ccxt.com/?id=position-structure>`
|
|
"""
|
|
self.load_markets()
|
|
accountNumber = None
|
|
accountNumber, params = self.handle_option_and_params(params, 'fetchPositions', 'accountNumber')
|
|
if accountNumber is None:
|
|
raise ArgumentsRequired(self.id + ' fetchPositions() requires an accountNumber parameter in params')
|
|
request = {
|
|
'accountNumber': accountNumber,
|
|
}
|
|
response = self.privatePostPositions(self.extend(request, params))
|
|
#
|
|
# [
|
|
# {
|
|
# "id": "0xb60c5078b060e4aede8e670089c9b1bc6eb231b4bcc0bfb3e97534770ace4d0c:101",
|
|
# "symbol": "BTC/USD",
|
|
# "timestamp": 1744360128358,
|
|
# "datetime": "2025-04-11 08:28:48.358 UTC",
|
|
# "side": "long",
|
|
# "contracts": 0.001,
|
|
# "contractSize": 81299.8225,
|
|
# "entryPrice": 0.000012292609480106,
|
|
# "notional": 81.30326975863777,
|
|
# "leverage": 2.091737393826,
|
|
# "collateral": 38.918646841955464,
|
|
# "initialMargin": 2.0325817439659444,
|
|
# "maintenanceMargin": 1.0162908719829722,
|
|
# "initialMarginPercentage": 0.025,
|
|
# "maintenanceMarginPercentage": 0.0125,
|
|
# "unrealizedPnl": -0.0498699,
|
|
# "liquidationPrice": 42969.81843916013,
|
|
# "marginMode": "isolated",
|
|
# "marginRatio": 0.4780714839977587
|
|
# }
|
|
# ]
|
|
#
|
|
return self.parse_positions(response, symbols)
|
|
|
|
def parse_position(self, position: dict, market: Market = None) -> Position:
|
|
return self.safe_position(position)
|
|
|
|
def parse_create_edit_order_args(self, id: Str, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
|
market = self.market(symbol)
|
|
symbol = market['symbol']
|
|
order = {
|
|
'symbol': symbol,
|
|
'type': type,
|
|
'side': side,
|
|
'amount': amount,
|
|
'price': price,
|
|
'params': params,
|
|
}
|
|
if id is not None:
|
|
order['id'] = id
|
|
return order
|
|
|
|
def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
|
"""
|
|
create a trade order
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/build_create_orders
|
|
https://testnet.aftermath.finance/docs/#/CCXT/submit_create_orders
|
|
|
|
:param str symbol: unified symbol of the market to create an order in
|
|
:param str type: 'market' or 'limit'
|
|
:param str side: 'buy' or 'sell'
|
|
:param float amount: how much of currency you want to trade in units of base currency
|
|
:param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param bool [params.reduceOnly]: True or False whether the order is reduce-only
|
|
:param Account [params.account]: account id to use, required
|
|
:returns dict: an `order structure <https://docs.ccxt.com/?id=order-structure>`
|
|
"""
|
|
self.load_markets()
|
|
account = None
|
|
account, params = self.handle_option_and_params(params, 'createOrder', 'account')
|
|
order = self.parse_create_edit_order_args(None, symbol, type, side, amount, price, params)
|
|
accountObj = {'account': account}
|
|
orders = self.create_orders([order], accountObj)
|
|
return orders[0]
|
|
|
|
def create_orders(self, orders: List[OrderRequest], params={}) -> List[Order]:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/build_create_orders
|
|
https://testnet.aftermath.finance/docs/#/CCXT/submit_create_orders
|
|
|
|
create a list of trade orders
|
|
:param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param Account [params.account]: account id to use, required
|
|
:returns dict: an `order structure <https://docs.ccxt.com/?id=order-structure>`
|
|
"""
|
|
self.load_markets()
|
|
ordersRequest = []
|
|
for i in range(0, len(orders)):
|
|
order = self.clone(orders[i])
|
|
symbol = self.safe_string(order, 'symbol')
|
|
market = self.market(symbol)
|
|
price = self.safe_string(order, 'price')
|
|
amount = self.safe_string(order, 'amount')
|
|
orderParams = self.safe_dict(order, 'params', {})
|
|
reduceOnly = self.safe_bool(orderParams, 'reduceOnly')
|
|
if reduceOnly is not None:
|
|
order['reduceOnly'] = reduceOnly
|
|
del order['symbol']
|
|
del order['params']
|
|
order['chId'] = market['id']
|
|
if price is not None:
|
|
order['price'] = self.parse_to_numeric(self.price_to_precision(symbol, price))
|
|
order['amount'] = self.parse_to_numeric(self.amount_to_precision(symbol, amount))
|
|
ordersRequest.append(order)
|
|
account = None
|
|
account, params = self.handle_option_and_params(params, 'createOrders', 'account')
|
|
txRequest = {
|
|
'accountId': account,
|
|
'metadata': {
|
|
'sender': self.walletAddress,
|
|
},
|
|
'orders': ordersRequest,
|
|
'deallocateFreeCollateral': False,
|
|
}
|
|
tx = self.privatePostBuildCreateOrders(self.extend(txRequest, params))
|
|
request = self.sign_tx_ed25519(tx)
|
|
response = self.privatePostSubmitCreateOrders(request)
|
|
#
|
|
# [
|
|
# {
|
|
# "id": "340282366919093604570116171100942992979",
|
|
# "datetime": "2025-04-10 10:38:39.323 UTC",
|
|
# "timestamp": 1744281519323,
|
|
# "status": "open",
|
|
# "symbol": "BTC/USD:USDC",
|
|
# "type": "limit",
|
|
# "side": "buy",
|
|
# "price": 10001.0,
|
|
# "average": 0.0,
|
|
# "amount": 0.01,
|
|
# "filled": 0.0,
|
|
# "remaining": 0.01,
|
|
# "cost": 0.0,
|
|
# "trades": [],
|
|
# "fee": {}
|
|
# }
|
|
# ]
|
|
#
|
|
return self.parse_orders(response)
|
|
|
|
def cancel_order(self, id: str, symbol: Str = None, params={}):
|
|
"""
|
|
cancels an open order
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/build_cancel_orders
|
|
https://testnet.aftermath.finance/docs/#/CCXT/submit_cancel_orders
|
|
|
|
:param str id: order id
|
|
:param str symbol: unified symbol of the market the order was made in
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: An `order structure <https://docs.ccxt.com/?id=order-structure>`
|
|
"""
|
|
orders = self.cancel_orders([id], symbol, params)
|
|
return self.safe_dict(orders, 0)
|
|
|
|
def cancel_orders(self, ids: List[str], symbol: Str = None, params={}) -> List[Order]:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/build_cancel_orders
|
|
https://testnet.aftermath.finance/docs/#/CCXT/submit_cancel_orders
|
|
|
|
cancel multiple orders
|
|
:param str[] ids: order ids
|
|
:param str [symbol]: unified market symbol
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param Account [params.account]: account to cancel orders for, required
|
|
:returns Order[]: an list of `order structures <https://docs.ccxt.com/?id=order-structure>`
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
account = None
|
|
account, params = self.handle_option_and_params(params, 'cancelOrders', 'account')
|
|
txRequest = {
|
|
'accountId': account,
|
|
'metadata': {
|
|
'sender': self.walletAddress,
|
|
},
|
|
'chId': market['id'],
|
|
'orderIds': ids,
|
|
}
|
|
tx = self.privatePostBuildCancelOrders(txRequest)
|
|
request = self.sign_tx_ed25519(tx)
|
|
response = self.privatePostSubmitCancelOrders(request)
|
|
#
|
|
# [
|
|
# {
|
|
# "id": "340282366919093604570116171100942992979",
|
|
# "datetime": "2025-04-10 10:45:16.765 UTC",
|
|
# "timestamp": 1744281916765,
|
|
# "status": "closed",
|
|
# "symbol": "BTC/USD:USDC",
|
|
# "type": "limit",
|
|
# "side": "buy",
|
|
# "price": 10001.0,
|
|
# "amount": 0.01,
|
|
# "filled": 0.0,
|
|
# "remaining": 0.0,
|
|
# "cost": 0.0,
|
|
# "trades": [],
|
|
# "fee": {}
|
|
# }
|
|
# ]
|
|
#
|
|
return self.parse_orders(response)
|
|
|
|
def create_account(self, symbol: str, params={}) -> List[Order]:
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
settleId = market['settleId']
|
|
txRequest = {
|
|
'metadata': {
|
|
'sender': self.walletAddress,
|
|
},
|
|
'settleId': settleId,
|
|
}
|
|
tx = self.privatePostBuildCreateAccount(txRequest)
|
|
request = self.sign_tx_ed25519(tx)
|
|
response = self.privatePostSubmitCreateAccount(request)
|
|
#
|
|
# [
|
|
# {
|
|
# "id": "0x2238b380cdf548cf9922a76ad8cf41cd886a04c1a68e7d0f99100b84b0b1ee48",
|
|
# "type": "primary",
|
|
# "code": "USDC",
|
|
# "accountNumber": 357
|
|
# },
|
|
# {
|
|
# "id": "0x6048be1c533a25226e2b505f5c7b8c4d731c87e9fb775dc577052c66febf1c93",
|
|
# "type": "subaccount",
|
|
# "code": "USDC",
|
|
# "accountNumber": 357
|
|
# }
|
|
# ]
|
|
#
|
|
return response
|
|
|
|
def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/build_allocate
|
|
https://testnet.aftermath.finance/docs/#/CCXT/submit_allocate
|
|
|
|
add margin
|
|
:param str symbol: unified market symbol
|
|
:param float amount: amount of margin to add
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param Account [params.account]: account id to use, required
|
|
:returns dict: a `margin structure <https://docs.ccxt.com/?id=add-margin-structure>`
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
account = None
|
|
account, params = self.handle_option_and_params_2(params, 'addMargin', 'account', 'accountId')
|
|
txRequest = {
|
|
'accountId': account,
|
|
'chId': market['id'],
|
|
'amount': self.parse_to_numeric(self.amount_to_precision(symbol, amount)),
|
|
'metadata': {
|
|
'sender': self.walletAddress,
|
|
},
|
|
}
|
|
tx = self.privatePostBuildAllocate(txRequest)
|
|
request = self.sign_tx_ed25519(tx)
|
|
response = self.privatePostSubmitAllocate(request)
|
|
#
|
|
# {
|
|
# "id": "0xb60c5078b060e4aede8e670089c9b1bc6eb231b4bcc0bfb3e97534770ace4d0c:101",
|
|
# "symbol": "BTC/USD",
|
|
# "contracts": 0.0,
|
|
# "contractSize": 81656.98359916,
|
|
# "notional": 0.0,
|
|
# "leverage": 0.0,
|
|
# "collateral": 40.0,
|
|
# "initialMargin": 0.0,
|
|
# "maintenanceMargin": 0.0,
|
|
# "initialMarginPercentage": 0.025,
|
|
# "maintenanceMarginPercentage": 0.0125,
|
|
# "unrealizedPnl": 0.0,
|
|
# "marginMode": "isolated"
|
|
# }
|
|
#
|
|
return response
|
|
|
|
def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/build_deallocate
|
|
https://testnet.aftermath.finance/docs/#/CCXT/submit_deallocate
|
|
|
|
remove margin from a position
|
|
:param str symbol: unified market symbol
|
|
:param float amount: amount of margin to remove
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param Account [params.account]: account id to use, required
|
|
:returns dict: a `margin structure <https://docs.ccxt.com/?id=reduce-margin-structure>`
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
account = None
|
|
account, params = self.handle_option_and_params_2(params, 'reduceMargin', 'account', 'accountId')
|
|
txRequest = {
|
|
'accountId': account,
|
|
'chId': market['id'],
|
|
'amount': self.parse_to_numeric(self.amount_to_precision(symbol, amount)),
|
|
'metadata': {
|
|
'sender': self.walletAddress,
|
|
},
|
|
}
|
|
tx = self.privatePostBuildDeallocate(txRequest)
|
|
request = self.sign_tx_ed25519(tx)
|
|
response = self.privatePostSubmitDeallocate(request)
|
|
#
|
|
# {
|
|
# "id": "0xb60c5078b060e4aede8e670089c9b1bc6eb231b4bcc0bfb3e97534770ace4d0c:101",
|
|
# "symbol": "BTC/USD",
|
|
# "contracts": 0.0,
|
|
# "contractSize": 81678.2625,
|
|
# "notional": 0.0,
|
|
# "leverage": 0.0,
|
|
# "collateral": 39.0,
|
|
# "initialMargin": 0.0,
|
|
# "maintenanceMargin": 0.0,
|
|
# "initialMarginPercentage": 0.025,
|
|
# "maintenanceMarginPercentage": 0.0125,
|
|
# "unrealizedPnl": 0.0,
|
|
# "marginMode": "isolated"
|
|
# }
|
|
#
|
|
return response
|
|
|
|
def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/build_deposit
|
|
https://testnet.aftermath.finance/docs/#/CCXT/submit_deposit
|
|
|
|
transfer currency internally between wallets on the same account
|
|
:param str code: unified currency code
|
|
:param float amount: amount to transfer
|
|
:param str fromAccount: account to transfer from
|
|
:param str toAccount: account to transfer to
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: a `transfer structure <https://docs.ccxt.com/?id=transfer-structure>`
|
|
"""
|
|
self.load_markets()
|
|
currency = self.currency(code)
|
|
txRequest = {
|
|
'metadata': {
|
|
'sender': self.walletAddress,
|
|
},
|
|
'accountId': toAccount,
|
|
'amount': amount,
|
|
}
|
|
tx = self.privatePostBuildDeposit(txRequest)
|
|
request = self.sign_tx_ed25519(tx)
|
|
response = self.privatePostSubmitDeposit(request)
|
|
#
|
|
# {
|
|
# "id": "0xf93f9bb8bf97eb570410caada92cfa3e66c7ed3a203a164f51d22d41eabe09c0",
|
|
# "type": "subaccount",
|
|
# "code": "USDC",
|
|
# "accountNumber": 101,
|
|
# "collateral": 1.0
|
|
# }
|
|
#
|
|
return self.extend(self.parse_transfer(response, currency), {
|
|
'fromAccount': self.walletAddress,
|
|
'toAccount': toAccount,
|
|
'amount': amount,
|
|
})
|
|
|
|
def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
|
|
currencyId = self.safe_string(transfer, 'code')
|
|
return {
|
|
'info': transfer,
|
|
'id': self.safe_string(transfer, 'id'),
|
|
'timestamp': None,
|
|
'datetime': None,
|
|
'currency': self.safe_currency_code(currencyId, currency),
|
|
'amount': None,
|
|
'fromAccount': None,
|
|
'toAccount': None,
|
|
'status': None,
|
|
}
|
|
|
|
def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}) -> Transaction:
|
|
"""
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/build_withdraw
|
|
https://testnet.aftermath.finance/docs/#/CCXT/submit_withdraw
|
|
|
|
make a withdrawal
|
|
:param str code: unified currency code
|
|
:param float amount: the amount to withdraw
|
|
:param str address: the address to withdraw to
|
|
:param str tag:
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param Account [params.account]: account id to use, required
|
|
:returns dict: a `transaction structure <https://docs.ccxt.com/?id=transaction-structure>`
|
|
"""
|
|
self.load_markets()
|
|
currency = self.currency(code)
|
|
account = None
|
|
account, params = self.handle_option_and_params(params, 'withdraw', 'account')
|
|
if account is None:
|
|
raise ArgumentsRequired(self.id + ' withdraw() requires a account parameter in params')
|
|
txRequest = {
|
|
'accountId': account,
|
|
'metadata': {
|
|
'sender': self.walletAddress,
|
|
},
|
|
'amount': amount,
|
|
}
|
|
tx = self.privatePostBuildWithdraw(txRequest)
|
|
request = self.sign_tx_ed25519(tx)
|
|
response = self.privatePostSubmitWithdraw(request)
|
|
#
|
|
# {
|
|
# "id": "0xf93f9bb8bf97eb570410caada92cfa3e66c7ed3a203a164f51d22d41eabe09c0",
|
|
# "type": "subaccount",
|
|
# "code": "USDC",
|
|
# "accountNumber": 101,
|
|
# "collateral": 39.0
|
|
# }
|
|
#
|
|
parsedTx = self.parse_transaction(response, currency)
|
|
parsedTx['addressFrom '] = account
|
|
parsedTx['amount'] = amount
|
|
return parsedTx
|
|
# return self.extend(, {
|
|
# 'addressFrom': account,
|
|
# 'amount': amount,
|
|
# })
|
|
|
|
def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
|
|
return {
|
|
'info': transaction,
|
|
'id': self.safe_string(transaction, 'id'),
|
|
'txid': self.safe_string(transaction, 'tx_id'),
|
|
'timestamp': None,
|
|
'datetime': None,
|
|
'address': None,
|
|
'addressFrom': None,
|
|
'addressTo': None,
|
|
'tag': None,
|
|
'tagFrom': None,
|
|
'tagTo': None,
|
|
'type': None,
|
|
'amount': None,
|
|
'currency': self.safe_string(transaction, 'code'),
|
|
'status': None,
|
|
'updated': None,
|
|
'comment': None,
|
|
'internal': None,
|
|
'fee': None,
|
|
'network': None,
|
|
}
|
|
|
|
def set_leverage(self, leverage: int, symbol: Str = None, params={}):
|
|
"""
|
|
set the level of leverage for a market
|
|
|
|
https://testnet.aftermath.finance/docs/#/CCXT/build_set_leverage
|
|
https://testnet.aftermath.finance/docs/#/CCXT/submit_set_leverage
|
|
|
|
:param float leverage: the rate of leverage
|
|
:param str symbol: unified market symbol
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param Account [params.account]: account id to use, required
|
|
:returns dict: response from the exchange
|
|
"""
|
|
if symbol is None:
|
|
raise ArgumentsRequired(self.id + ' setLeverage() requires a symbol argument')
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
account = None
|
|
account, params = self.handle_option_and_params_2(params, 'setLeverage', 'account', 'accountId')
|
|
txRequest = {
|
|
'accountId': account,
|
|
'chId': market['id'],
|
|
'leverage': leverage,
|
|
'metadata': {
|
|
'sender': self.walletAddress,
|
|
},
|
|
}
|
|
tx = self.privatePostBuildSetLeverage(txRequest)
|
|
request = self.sign_tx_ed25519(tx)
|
|
response = self.privatePostSubmitSetLeverage(request)
|
|
#
|
|
# {
|
|
# "id": "0xyydsxxxxxxxxyydsxxxxxxx:141",
|
|
# "symbol": "BTC/USD:USDC",
|
|
# "marginMode": "isolated",
|
|
# "side": "long",
|
|
# "contracts": 0.001,
|
|
# "contractSize": 88506.195911625,
|
|
# "entryPrice": 90999.0,
|
|
# "notional": 88.50907726931732,
|
|
# "marginRatio": 1.0000000000041465,
|
|
# "leverage": 0.9999999999958537,
|
|
# "collateral": 91.00196251238035,
|
|
# "initialMargin": 2.212726931732933,
|
|
# "maintenanceMargin": 1.1063634658664665,
|
|
# "initialMarginPercentage": 0.025,
|
|
# "maintenanceMarginPercentage": 0.0125,
|
|
# "unrealizedPnl": -2.492804088375008,
|
|
# "liquidationPrice": -3.71625538227e-7
|
|
# }
|
|
#
|
|
return response
|
|
|
|
def sign_tx_ed25519(self, tx: dict) -> dict:
|
|
"""
|
|
Helper to sign some transaction bytes and return a generic transaction execution request.
|
|
:param dict [tx]: transaction bytes and the signing digest for them
|
|
:returns dict: the input transaction bytes and the signed digest
|
|
"""
|
|
if self.privateKey.find('suiprivkey') >= 0:
|
|
raise NotSupported(self.id + ' only support hex encoding private key, please transform bech32 encoding private key')
|
|
signingDigest = self.safe_string(tx, 'signingDigest')
|
|
digest = self.base64_to_binary(signingDigest)
|
|
privateKey = self.base16_to_binary(self.privateKey)
|
|
signature = self.eddsa(digest, privateKey, 'ed25519')
|
|
hexPublicKey = self.safe_string(self.options, 'publicKey')
|
|
if hexPublicKey is None:
|
|
raise ArgumentsRequired(self.id + ' requires hex encoding public key in options')
|
|
publicKey = self.base16_to_binary(hexPublicKey)
|
|
suiSignature = self.binary_concat(self.base16_to_binary('00'), self.binary_concat(self.base64_to_binary(signature), publicKey))
|
|
base64Sig = self.binary_to_base64(suiSignature)
|
|
transactionBytes = self.safe_string(tx, 'transactionBytes')
|
|
signatures = [base64Sig]
|
|
return {'transactionBytes': transactionBytes, 'signatures': signatures}
|
|
|
|
def parse_order(self, order: dict, market: Market = None) -> Order:
|
|
return self.safe_order(order, market)
|
|
|
|
def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
|
if not response:
|
|
return None # fallback to default error handler
|
|
#
|
|
# Error with ID: #68498f1e536664f31a7b1aa7
|
|
#
|
|
if body.find('Error') >= 0:
|
|
self.throw_broadly_matched_exception(self.exceptions['broad'], body, '')
|
|
raise ExchangeError(body)
|
|
return None
|
|
|
|
def sign(self, path, api='public', method='POST', params={}, headers=None, body=None):
|
|
url = self.urls['api']['rest'] + '/' + path
|
|
if api == 'private':
|
|
self.check_required_credentials()
|
|
if method == 'POST':
|
|
headers = {
|
|
'Content-Type': 'application/json',
|
|
}
|
|
body = self.json(params)
|
|
return {'url': url, 'method': method, 'body': body, 'headers': headers}
|