Skip to content

Instantly share code, notes, and snippets.

@miohtama
Last active May 7, 2025 11:53
Show Gist options
  • Save miohtama/2e695f4c66a48da2466439575011e438 to your computer and use it in GitHub Desktop.
Save miohtama/2e695f4c66a48da2466439575011e438 to your computer and use it in GitHub Desktop.
Compare GRVT CCXT-compatibility API with a known similiar decentralised perp exchange
"""Compare GRVT CCXT-compatibility API with a known similiar decentralised perp exchange.
- Run the same CCXT API functions against know decentralised perp exchange and GRVT
and compare the results
"""
import logging
import os
from pprint import pprint
import ccxt
from pysdk.grvt_ccxt import GrvtCcxt
from pysdk.grvt_ccxt_env import GrvtEnv
logger = logging.getLogger(__name__)
def create_grvt_exchange() -> GrvtCcxt:
"""Create GRVT adapter.
- Details how to create https://github.com/gravity-technologies/grvt-pysdk/blob/f41e5b97d89c320515809433e9542bbbd2a653bd/tests/pysdk/test_grvt_ccxt.py#L241
- How to get API key https://api-docs.grvt.io/api_setup/
"""
parameters = {
"api_key": os.getenv("GRVT_API_KEY"),
"trading_account_id": os.getenv("GRVT_TRADING_ACCOUNT_ID"),
"private_key": os.getenv("GRVT_PRIVATE_KEY"),
}
api = GrvtCcxt(
GrvtEnv.PROD,
logger,
parameters=parameters,
)
return api
def create_orderly_exchange() -> ccxt.Exchange:
"""Create Orderly CCXT instance.
- Orderly is available in CCXT as 'woo' for Woofi Pro
- Orderly has multiple "brokers" - you do not have a direct access as a trader
- You need to register a broker and get the API key and secret
- Here https://github-dev.orderly.network/broker-registration/
- Orderly has multiple key formats. Keys are format: ``ed25519:KBf....``
- Then deposit through the broker website
- Mode L2 here: https://trade.mode.network/perp/PERP_ETH_USDC
"""
broker_id = "mode"
# Initialize the Orderly exchange as WooFi Pro,
# who probably sponsored the CCXT implementation?
exchange = ccxt.woofipro({
'apiKey': os.environ[f"{broker_id.upper()}_PUBLIC_KEY"],
'secret': os.environ[f"{broker_id.upper()}_PRIVATE_KEY"],
'accountId': os.environ[f"{broker_id.upper()}_ACCOUNT_ID"],
})
exchange.options["brokerId"] = broker_id
exchange.urls["api"] = {
'public': 'https://api.orderly.org',
'private': 'https://api.orderly.org',
}
return exchange
def validate_exchange_api(exchange: GrvtCcxt | ccxt.Exchange) -> None:
"""See if GRVT SDK and CCXT API behave the same"""
assert isinstance(exchange, (GrvtCcxt, ccxt.Exchange)), "Exchange is not a supported instance"
# Load the markets to get trading pairs info.
# Gets zero markets.
exchange.load_markets()
if len(exchange.markets) == 0:
print("No markets found.")
else:
for idx, market in enumerate(exchange.markets):
print(f"Market #{idx + 1}: {market}")
try:
balance = exchange.fetch_balance()
# Print the total balance (includes both available and used balances)
print("Total Balance:")
pprint(balance['total'])
# Print available balance (what you can trade with)
print("\nAvailable Balance:")
pprint(balance['free'])
# If you want details about a specific currency
specific_currency = 'BTC' # change to your desired currency
if specific_currency in balance:
print(f"\n{specific_currency} Balance Details:")
pprint(balance.get(specific_currency, "No details available"))
except Exception as e:
logger.warning(f"Failed to fetch balance: {e}", exc_info=e)
# Check the feature map of CCXT connector,
# supported timeframes and such
exchange_desc = exchange.describe()
print(f"Exchange Description: {list(exchange_desc)[0:5]}...")
required_features = ["margin", "fetchBalance", "fetchLeverageTiers"]
for feat in required_features:
if not exchange.has[feat]:
logger.warning(f"Exchange {exchange.__class__.__name__} does not support: {feat}")
def main():
grvt = create_grvt_exchange()
orderly = create_orderly_exchange()
# Orderly goes first as it is CCXT-documented instance and should work
for target in (orderly, grvt,):
print(f"Testing exchange: {target.__class__.__name__}")
try:
validate_exchange_api(target)
except Exception as e:
print(f"Error validating exchange API {target.__class__.__name__}: {e}")
raise
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment