Skip to content

Ithaca Python SDK Reference

Version: 0.2.30
Description: A Python library to interact with the Ithaca Protocol (for both on-chain and off-chain operations).


Table of Contents

  1. Authentication & Session Handling
  2. Market & Orders
  3. Client: Positions & History
  4. Fundlock: Deposits & Withdrawals
  5. Calculation & Fees
  6. Analytics
  7. Protocol & Misc
  8. Common HTTP Status Codes
  9. Socket and Real-Time Updates

Authentication & Session Handling

Auth.login()

Description
Performs an Ethereum signature-based login, generating an authToken that is stored in the internal session. This allows subsequent API calls without needing extra credentials.

Endpoints Invoked
- POST /v1/auth/requestAuth (requests nonce)
- POST /v1/auth/validateAuth (validates signature)

No direct user parameters—uses your private_key from IthacaSDK(...).

Example

sdk = IthacaSDK(private_key="0xabc123...", env_name="CANARY")
login_ok = sdk.auth.login()
print("Logged in:", login_ok)

Example Response (typical success):

{
  "result": "OK",
  "details": "",
  "payload": {
    "authToken": "ec798c76-8032-45fd-af44-4eb7cc1f2b01",
    "clientId": 12345,
    "ethAddress": "0x123abc...",
    "riskScoreValidationStatus": "PENDING",
    "accountInfos": {}
  }
}

Potential Errors
- 401 if signature fails or session is invalid.
- 500 on unexpected server error.


Auth.logout()

Description
Invalidates the current authToken and ends the server-side session.

Endpoint
- POST /v1/auth/logout

Example

sdk.auth.logout()

Example Response:

{"result": "OK"}

If the user was never logged in, a 401 may occur.


Description
Links a secondary (managed) wallet to the currently authenticated user’s main wallet.

Endpoints
- POST /v1/linked_wallets/request_link - POST /v1/linked_wallets/confirm_link

Parameters
- address (str): The address to link

Example

resp = sdk.auth.link_address("0xManagerAccount123")

Typical Response:

{
  "result": "OK",
  "details": "",
  "payload": "some success message or object"
}

Errors
- 401 if not logged in.
- 412 if already linked or address invalid.


Market & Orders

Orders.new_order(legs, price, client_order_id=None, time_in_force="GOOD_TILL_CANCEL", ...)

Description
Places a new “conditional” order with one or more legs. Requires an authenticated session.

Endpoint
- POST /v1/clientapi/newOrder

Key Parameters
- legs (list of tuples): Each (contractId, side, quantity)
- side is "BUY" or "SELL".
- price (float): The limit/conditional price.
- time_in_force (str): e.g. "GOOD_TILL_CANCEL".

Example

legs = [(5559, "SELL", 1.0), (5563, "BUY", 1.0)]
response = sdk.orders.new_order(legs, price=99.5)

Example Request Body

{
  "clientOrderId": 1742473240341423,
  "totalNetPrice": "99.5000",
  "legs": [
    {"contractId": 5559, "side": "SELL", "quantity": "1.0000"},
    {"contractId": 5563, "side": "BUY",  "quantity": "1.0000"}
  ],
  "signature": "<EIP712-signature>",
  "orderGenesis": "CLIENT_PREDEFINED",
  "orderDescr": "",
  "requestSinglePrice": true
}

Example Response

{
  "result": "OK",
  "details": "",
  "payload": {},
  "clientOrderId": 1742473240341423
}

Errors
- 401 if not authenticated.
- 412 for insufficient collateral or invalid input.
- 500 if internal server error.


Orders.open_orders()

Description
Returns current open orders.

Endpoint
- POST /v1/clientapi/clientOpenOrders

Example

resp = sdk.orders.open_orders()

Truncated Example Response:

{'result': 'OK',
 'details': '',
 'payload': [{'revDate': 1738360260010,
   'orderId': 1780080905569458,
   'clientId': 1759288230128641,
   'orderStatus': 'NEW',
   'netPrice': -0.0111,
   'orderGenesis': 'CLIENT_PREDEFINED',
   'orderDescr': 'Quoter - Call 3',
   'collateral': {'currencyPair': 'WETH/USDC',
    'underlierAmount': 0.0007,
    'numeraireAmount': 0.0},
   'timeInForce': 'GOOD_TILL_CANCEL',
   'orderClass': 'ConditionalOrder',
   'requestSinglePrice': True,
   'iocAuctionTime': 0,
   'details': [{'contractId': 36875,
     'contractDto': {'contractId': 36875,
      'payoff': 'Call',
      'economics': {'currencyPair': 'WETH/USDC',
       'expiry': 250205080,
       'strike': 3600.0,
       'priceCurrency': 'USDC',
       'qtyCurrency': 'WETH'},
      'tradeable': True},
     'side': 'SELL',
     'originalQty': 0.0007,
     'remainingQty': 0.0007,
     'cancelledQty': 0.0,
     'avgPrice': 0.0,
     'totalCost': 0.0,
     'currencyPair': 'WETH/USDC',
     'expiry': 250205080}],
   'insertionDate': 1738360264223,
   'spotPriceAtCreation': 3315.14},
  {'revDate': 1738360260010,
   'orderId': 1780080904649219,
   'clientId': 1759288230128641,
   'orderStatus': 'NEW',
   'netPrice': 0.0184,
   'orderGenesis': 'CLIENT_PREDEFINED',
   'orderDescr': 'Quoter - Call 3',
   'collateral': {'currencyPair': 'WETH/USDC',
    'underlierAmount': 0.0,
    'numeraireAmount': 0.0},
   'timeInForce': 'GOOD_TILL_CANCEL',
   'orderClass': 'ConditionalOrder',
   'requestSinglePrice': True,
   'iocAuctionTime': 0,
   'details': [{'contractId': 30927,
     'contractDto': {'contractId': 30927,
      'payoff': 'Call',
      'economics': {'currencyPair': 'WETH/USDC',
       'expiry': 250207080,
       'strike': 3600.0,
       'priceCurrency': 'USDC',
       'qtyCurrency': 'WETH'},
      'tradeable': True},
     'side': 'BUY',
     'originalQty': 0.0008,
     'remainingQty': 0.0008,
     'cancelledQty': 0.0,
     'avgPrice': 0.0,
     'totalCost': 0.0,
     'currencyPair': 'WETH/USDC',
     'expiry': 250207080}],
   'insertionDate': 1738360264223,
   'spotPriceAtCreation': 3315.14},
  {'revDate': 1738360260010,
   'orderId': 1780080904991230,
   'clientId': 1759288230128641,
   'orderStatus': 'NEW',
   'netPrice': 0.0016,
   'orderGenesis': 'CLIENT_PREDEFINED',
   'orderDescr': 'Quoter - Call 2',
   'collateral': {'currencyPair': 'WETH/USDC',
    'underlierAmount': 0.0,
    'numeraireAmount': 0.0},
   'timeInForce': 'GOOD_TILL_CANCEL',
   'orderClass': 'ConditionalOrder',
   'requestSinglePrice': True,
   'iocAuctionTime': 0,
   'details': [{'contractId': 36273,
     'contractDto': {'contractId': 36273,
      'payoff': 'Call',
      'economics': {'currencyPair': 'WETH/USDC',
       'expiry': 250203080,
       'strike': 3500.0,
       'priceCurrency': 'USDC',
       'qtyCurrency': 'WETH'},
      'tradeable': True},
     'side': 'BUY',
     'originalQty': 0.0005,
     'remainingQty': 0.0005,
     'cancelledQty': 0.0,
     'avgPrice': 0.0,
     'totalCost': 0.0,
     'currencyPair': 'WETH/USDC',
     'expiry': 250203080}],
   'insertionDate': 1738360264223,
   'spotPriceAtCreation': 3315.14},
  {'revDate': 1738360260010,
   'orderId': 1780080904616646,
   'clientId': 1759288230128641,
   'orderStatus': 'NEW',
   'netPrice': -0.0567,
   'orderGenesis': 'CLIENT_PREDEFINED',
   'orderDescr': 'Quoter - Call 2',
   'collateral': {'currencyPair': 'WETH/USDC',
    'underlierAmount': 0.0012,
    'numeraireAmount': 0.0},
   'timeInForce': 'GOOD_TILL_CANCEL',
   'orderClass': 'ConditionalOrder',
   'requestSinglePrice': True,
   'iocAuctionTime': 0,
   'details': [{'contractId': 30919,
     'contractDto': {'contractId': 30919,
      'payoff': 'Call',
      'economics': {'currencyPair': 'WETH/USDC',
       'expiry': 250207080,
       'strike': 3500.0,
       'priceCurrency': 'USDC',
       'qtyCurrency': 'WETH'},
      'tradeable': True},
     'side': 'SELL',
     'originalQty': 0.0012,
     'remainingQty': 0.0012,
     'cancelledQty': 0.0,
     'avgPrice': 0.0,
     'totalCost': 0.0,
     'currencyPair': 'WETH/USDC',
     'expiry': 250207080}],
   'insertionDate': 1738360264223,
   'spotPriceAtCreation': 3315.14},
  {'revDate': 1738360260010,
   'orderId': 1780080904843514,
   'clientId': 1759288230128641,
   'orderStatus': 'NEW',
   'netPrice': -0.0153,
   'orderGenesis': 'CLIENT_PREDEFINED',
   'orderDescr': 'Quoter - Put 3',
   'collateral': {'currencyPair': 'WETH/USDC',
    'underlierAmount': 0.0,
    'numeraireAmount': 2.4},
   'timeInForce': 'GOOD_TILL_CANCEL',
   'orderClass': 'ConditionalOrder',
   'requestSinglePrice': True,
   'iocAuctionTime': 0,
   'details': [{'contractId': 30925,
     'contractDto': {'contractId': 30925,
      'payoff': 'Put',
      'economics': {'currencyPair': 'WETH/USDC',
       'expiry': 250207080,
       'strike': 3000.0,
       'priceCurrency': 'USDC',
       'qtyCurrency': 'WETH'},
      'tradeable': True},
     'side': 'SELL',
     'originalQty': 0.0008,
     'remainingQty': 0.0008,
     'cancelledQty': 0.0,
     'avgPrice': 0.0,
     'totalCost': 0.0,
     'currencyPair': 'WETH/USDC',
     'expiry': 250207080}],
   'insertionDate': 1738360264223,
   'spotPriceAtCreation': 3315.14},
    ...
  ]
}

Errors
- 401 if session is invalid.
- 500 server error.


Orders.open_orders_with_lock_info()

Description
Returns open orders including collateral lock info.

Endpoint
- POST /v1/clientapi/clientOpenOrdersWithLockInfo

Example

resp = sdk.orders.open_orders_with_lock_info()

Truncated Example Response:

{
  "result": "OK",
  "details": "",
  "payload": {
    "openOrders": [
      {
        "orderId": 1779794543802527,
        "netPrice": 1.4431,
        "details": [
          { "contractId": 30919, "side": "SELL", ... },
          ...
        ],
        "insertionDate": 1738080609604,
        "spotPriceAtCreation": 3171.06
      }
    ],
    "softLock": {
      "currencyPair": "WETH/USDC",
      "numeraireAmount": 7.5906
    },
    "postExecutionLock": {
      "currencyPair": "WETH/USDC",
      "numeraireAmount": 7.4431
    }
  }
}

Orders.order_cancel(client_order_id)

Description
Cancel a single open order by its client_order_id.

Endpoint
- POST /v1/clientapi/orderCancel

Parameters
- client_order_id (int)

Example

sdk.orders.order_cancel(1742473240341423)

Example Response

{"result": "OK","details": ""}

Orders.order_cancel_all(contains=None)

Description
Cancels all orders, optionally filtered by a substring.

Endpoint
- POST /v1/clientapi/allOrdersCancel?contains=...

Example

resp = sdk.orders.order_cancel_all()

Truncated Example Response:

{
  "result": "OK",
  "details": "",
  "payload": [
    {
      "clientId": 1755725897769985,
      "clientOrderId": 1779794543802527
    }
  ]
}

Orders.order_status(client_order_id)

Description
Get status for a specific order.

Endpoint
- POST /v1/clientapi/orderStatus

Example

sdk.orders.order_status(1780080905569458)

Example Response (if invalid):

{'result': 'OK',
 'details': '',
 'payload': {'revDate': 1738360275010,
  'orderId': 1780080905569458,
  'clientId': 1759288230128641,
  'orderStatus': 'CANCELED',
  'ordRejReason': 'CANCELLED_BY_USER',
  'netPrice': -0.0111,
  'orderGenesis': 'CLIENT_PREDEFINED',
  'orderDescr': 'Quoter - Call 3',
  'timeInForce': 'GOOD_TILL_CANCEL',
  'orderClass': 'ConditionalOrder',
  'requestSinglePrice': True,
  'iocAuctionTime': 0,
  'details': [{'contractId': 36875,
    'contractDto': {'contractId': 36875,
     'payoff': 'Call',
     'economics': {'currencyPair': 'WETH/USDC',
      'expiry': 250205080,
      'strike': 3600.0,
      'priceCurrency': 'USDC',
      'qtyCurrency': 'WETH'},
     'tradeable': True},
    'side': 'SELL',
    'originalQty': 0.0007,
    'remainingQty': 0.0,
    'cancelledQty': 0.0007,
    'avgPrice': 0.0,
    'totalCost': 0.0,
    'currencyPair': 'WETH/USDC',
    'expiry': 250205080}],
  'insertionDate': 1738360281627,
  'spotPriceAtCreation': 3315.14}}

Client: Positions & History

Client.current_positions(_filter=None, details=False)

Description
Fetch the user’s current open positions.

Endpoint
- POST /v1/clientapi/clientCurrentPositions

Parameters
- _filter (str): "COMBINE_STRATEGIES", "SHOW_ORDERS", etc.
- details (bool): If True, returns a pandas DataFrame with contract info (when used in Python).

Example

positions = sdk.client.current_positions(_filter="SHOW_ORDERS", details=True)

Truncated Response:

{
  "result":"OK",
  "payload":[
    {
      "contractId":30913,
      "positionsAvgPrice":133.0,
      "positionsQty":-0.0002
    },
    ...
  ]
}

Client.fundlock_state()

Description
Retrieve the client’s fundlock state (locked deposit info).

Endpoint
- POST /v1/clientapi/clientFundLockState

Example

sdk.client.fundlock_state()

Example Response:

{
  "result": "OK",
  "details": "",
  "payload": [
    {
      "currency": "WETH",
      "orderValue": 0.0,
      "fundLockValue": 10.0,
      "settleValue": -4.39e-05
    },
    {
      "currency": "USDC",
      "orderValue": 0.0,
      "fundLockValue": 10.0,
      "settleValue": 0.3953
    }
  ]
}

Client.historical_positions(expiry, _filter="NO_DETAILS")

Description
Return historical (closed) positions at a specific expiry.

Endpoint
- POST /v1/clientapi/clientHistoricalPositions

Parameters
- expiry (int): e.g. 250207080
- _filter (str): "NO_DETAILS", "SHOW_ORDERS", etc.

Example

resp = sdk.client.historical_positions(250207080, _filter="NO_DETAILS")

Example Response (If error):

{'result': 'OK',
 'details': '',
 'payload': {'240915080': {'totalCollateral': {'WETH/USDC': {'currencyPair': 'WETH/USDC',
     'underlierAmount': 0.0008,
     'numeraireAmount': 0.1583}},
   'expiryPrices': {'WETH/USDC': 2423.1799},
   'payoff': {'WETH/USDC': {'currencyPair': 'WETH/USDC',
     'underlierAmount': 0.0007243,
     'numeraireAmount': 0.0794}},
   'positions': [{'contractId': 6663,
     'positionsAvgPrice': 2182.0667,
     'positionsQty': -0.0015},
    {'contractId': 6571, 'positionsAvgPrice': 58.5, 'positionsQty': 0.0004},
    {'contractId': 6573,
     'positionsAvgPrice': 198.969,
     'positionsQty': -0.0012997},
    {'contractId': 6578, 'positionsAvgPrice': 1.0, 'positionsQty': 0.03},

(Might indicate the given expiry doesn’t exist or a server issue.)


Client.historical_positions_by_date(_from, to)

Description
Return historical positions for a date range in milliseconds since 1970.

Endpoint
- POST /v1/clientapi/clientHistoricalPositionsByDatePeriod

Parameters
- _from (int): e.g. 1690000000
- to (int): e.g. 1695000000

Example

resp = sdk.client.historical_positions_by_date(1690000000, 1695000000)

Shortened Example Response:

{
  "result":"OK",
  "payload":{
    "240915080":{
      "totalCollateral":{"WETH/USDC":{"currencyPair":"WETH/USDC","underlierAmount":0.0008,"numeraireAmount":0.1583}},
      "expiryPrices":{"WETH/USDC":2423.1799},
      "payoff":{"WETH/USDC":{"underlierAmount":0.0007243,"numeraireAmount":0.0794}},
      "positions":[
        {"contractId":6663,"positionsAvgPrice":2182.0667,"positionsQty":-0.0015},
        ...
      ]
    },
    ...
  }
}

Client.positions_lock_state()

Description
Retrieve client’s locked positions collateral by expiry.

Endpoint
- POST /v1/clientapi/getLockedCollateral

Example

sdk.client.positions_lock_state()

Truncated Example Response:

{
  "result":"OK",
  "payload":{
    "1738569600000":[
      {
        "clientId":1759288230128641,
        "expiry":250203080,
        "locked":{
          "currencyPair":"WETH/USDC",
          "underlierAmount":5e-07,
          "numeraireAmount":1.057
        },
        "feesPaid":3.0576
      }
    ],
    ...
  }
}

Client.trade_history(date_from=None, date_to=None, offset=None, limit=None, status=None)

Description
Fetch user’s trade history.

Endpoint
- POST /v1/clientapi/tradeHistory

Example

resp = sdk.client.trade_history(date_from=1690000000, date_to=1695000000, limit=10)

Truncated Example Response:

{
  "result": "OK",
  "details": "",
  "payload": []
}

Fundlock: Deposits & Withdrawals

Fundlock.deposit(symbol, amount)

Description
Approves (if needed) and deposits tokens from your wallet to the Ithaca FundLock contract on-chain.

Endpoint
(On-chain transaction; no direct Ithaca REST endpoint is used. The SDK calls Web3.)

Parameters
- symbol (str): e.g. "USDC", "WETH".
- amount (int or float): The amount (scaled by token decimals).

Example

sdk.fundlock.deposit("USDC", 100000000) # If USDC has 6 decimals => 100 USDC

On success, returns a web3 tx receipt:

{
  "transactionHash": "0xf4de...",
  "status": 1,
  ...
}

Errors
- “Invalid token” if symbol is unrecognized.
- On-chain revert if insufficient balance.


Fundlock.withdraw(symbol, amount)

Description
Requests a withdrawal from the Ithaca FundLock contract. The user can then “release” after a lock period.

Endpoint
(On-chain transaction via Web3.)

Parameters
- symbol (str)
- amount (int or float)

Example

sdk.fundlock.withdraw("USDC", 50000000) # withdraw 50 USDC if 6 decimals

Returns a web3 receipt or None on error.


Fundlock.release(symbol, withdrawal_slot)

Description
Releases funds previously withdrawn after the lock period.

Endpoint
(On-chain transaction)

Parameters
- symbol (str) - withdrawal_slot (int)

Example

sdk.fundlock.release("USDC", withdrawal_slot=1)

Returns a web3 tx receipt or None.


Fundlock.history()

Description
Fetch all deposit/withdrawal history from the subgraph.

Endpoint
(GraphQL request to self.parent.subgraph_url)

Example

sdk.fundlock.history()

Truncated Example Response:

{
  "errors": "...",
  "data": {
    "account": {
      "deposits": [...],
      "withdrawalRequests": [...],
      "releases": [...]
    }
  }
}

If your subgraph URL is None, you might get an error.


Calculation & Fees

Calculation.calc_portfolio_collateral()

Description
Calculate portfolio collateral usage given your current positions (session-based).

Endpoint
- POST /v1/clientapi/calcPortfolioCollateral

Example

sdk.calculation.calc_portfolio_collateral()

Example Response:

{
  "result": "OK",
  "details": "",
  "payload": {
    "actual": {
      "currencyPair":"WETH/USDC",
      "underlierAmount":0.0,
      "numeraireAmount":0.0
    },
    "potential": {
      "currencyPair":"WETH/USDC",
      "underlierAmount":0.0,
      "numeraireAmount":0.0
    }
  }
}

Calculation.estimate_order_lock(...)

Description
Estimates how much collateral would be locked by a hypothetical order.

Endpoint
- POST /v1/clientapi/estimateOrderLock

Example

sdk.calculation.estimate_order_lock(legs=..., price=..., order_type="LIMIT")

Typical Errors
- Will fail if legs is empty or if user is not logged in.


Calculation.estimate_order_fees(...)

Description
Estimate the fees for a proposed order.

Endpoint
- POST /v1/clientapi/estimateOrderFees or - POST /v1/clientapi/estimateOrderFeesExtended

Example

sdk.calculation.estimate_order_fees(legs=..., price=..., order_type="LIMIT")

Errors
- Same as above, e.g. NoneType if invalid parameters.


Analytics

Below, we demonstrate typical calls for the "WETH/USDC" pair. Each method is configured similarly for other pairs.

Analytics.total_trading_volume()

Description
Returns total trading volume for the specified underlier/numeraire.

Endpoint
- GET /v1/analytics/{underlier}/{numeraire}/totalTradingVolume

Example

resp = sdk.analytics.total_trading_volume()

Shortened Response:

{
  "response": {
    "num": 847.50825,
    "totalInNum": 279198.91263458,
    "totalInUnd": 95.6624274,
    "und": 95.3386274
  }
}

Analytics.total_open_interest()

Description
Fetch total open interest (OI).

Endpoint
- GET /v1/analytics/{underlier}/{numeraire}/totalOpenInterest

Example

resp = sdk.analytics.total_open_interest()

If no OI => server returns 204 NO_CONTENT.
If error => possibly "<Response [500]>".


Analytics.total_value_locked()

Description
Get total value locked (TVL).

Endpoint
- GET /v1/analytics/{underlier}/{numeraire}/totalValueLocked

Example

resp = sdk.analytics.total_value_locked()

Example:

{
  "response": 715298652.1484877
}

(Large numeric means 715M in USDC, for instance.)


Analytics.trades(date_range=...)

Description
Returns aggregated trades data over a date range.

Endpoint
- POST /v1/analytics/{underlier}/{numeraire}/trades

Example

resp = sdk.analytics.trades(since=someDate, to=someDate)

Truncated Example:

{
  "response": {
    "2025-01-01T00:00": 169040,
    "2025-01-02T00:00": 157875,
    ...
  }
}

If no data: 204.


Analytics.open_interest_by_product(date_range=...)

Description
Open interest grouped by product type (Call, Put, BinaryCall, etc.).

Endpoint
- POST /v1/analytics/{underlier}/{numeraire}/openInterestByProduct

Truncated Example:

{
  "response": {
    "Binary Call": {
      "num": 25.4212,
      "totalInNum": 25.4212,
      ...
    },
    "Call": {...},
    "Forward": {...},
    "Put": {...}
  }
}

Analytics.open_interest_by_strike(date_range=..., strike_range=...)

Description
Open interest grouped by strike prices.

Endpoint
- POST /v1/analytics/{underlier}/{numeraire}/openInterestByStrike

Truncated Example:

{
  "response": {
    "2700.0": {
      "Put": {...}
    },
    "3000.0": {
      "Call": {...},
      "Put": {...}
    },
    "3500.0": {
      "Binary Call": {...},
      "Call": {...}
    }
  }
}

Analytics.daily_volume(date_range=...)

Description
Aggregated daily volume.

Endpoint
- POST /v1/analytics/{underlier}/{numeraire}/dailyVolume

Truncated Example:

{
  "response": {
    "2025-01-01T00:00": {
      "num": 0,
      "totalInNum": 670.95531,
      "totalInUnd": 0.2001,
      "und": 0.2001
    },
    ...
  }
}

Analytics.best_prices()

Description
Returns best bid/ask for each contract (estimated or from real orders).

Endpoints
- POST /clientapi/bestBidAsk - POST /clientapi/bestBidAskPrecise

Truncated Example:

{
  "result": "OK",
  "details": "",
  "payload": {
    "30903": {
      "bestAsk": 120.5833,
      "bestBid": 115.0,
      "askVolume": 0.0024,
      "bidVolume": 0.0016
    },
    ...
  }
}

If none found, can return empty object.


Protocol & Misc

Protocol.system_info()

Description
Retrieves system parameters: fundlock address, token addresses, etc.

Endpoint
- POST /v1/clientapi/systemInfo

Example

info = sdk.protocol.system_info()

Truncated Example:

{
  "result": "OK",
  "payload": {
    "fundlockAddress": "0xabc123...",
    "tokenAddress": {
      "USDC": "0xTokenUsdcAddr",
      "WETH": "0xTokenWethAddr"
    },
    ...
  }
}

Common HTTP Status Codes

  • 200 OK
    Request succeeded; typically returns JSON of the form {"result": "OK", "payload": ...}.
  • 204 NO_CONTENT
    Request succeeded but no data is available (empty response).
  • 400 BAD_REQUEST
    The request’s JSON or input is malformed.
  • 401 UNAUTHORIZED
    No valid session; you must login.
  • 404 NOT_FOUND
    The resource or item ID was not found.
  • 412 PRECONDITION_FAILED
    Validation or logical failure. E.g. insufficient collateral, invalid address, etc.
  • 500 INTERNAL_SERVER_ERROR
    Unexpected server-side error.

Socket and Real-Time Updates

The SDK provides a WebSocket-based interface for streaming real-time events such as:

  • Execution reports (updates about order fills or cancellations)
  • Auction notifications (e.g. AUCTION_STARTED, AUCTION_FINISHED)
  • Orderbook updates (ORDERBOOK, MM_ORDERBOOK_UPDATED, etc.)
  • Trade reports (TRADE_REPORT)
  • Fundlock updates (FUNDLOCK_UPDATED)
  • Other server-pushed notifications

Once you connect and authenticate, the server begins pushing messages to your provided callback function.


Overview

  1. Connect: Call sdk.socket.connect(on_message=..., on_open=...).
  2. Authenticate: Upon connection, the SDK automatically logs in (via Ethereum private key or RSA) and sends a VALIDATE_AUTH_TOKEN action so the server knows who you are.
  3. Receive Messages: The server sends JSON objects containing a responseType and payload, among other fields.
  4. Process: In your on_message callback, parse the JSON and handle the responseType (e.g. EXEC_REPORT, ORDERBOOK, AUCTION_STARTED, etc.).
  5. Close: If needed, call sdk.socket.close() to stop streaming and reconnect attempts.

Important: The SDK will auto-reconnect if the connection drops or if the server instructs you to reconnect.


Socket.connect(on_message=None, on_open=None)

Description
Starts a background thread to connect to the WebSocket endpoint specified in your IthacaSDK constructor (ws_endpoint). The method also ensures you are authenticated using your existing credentials (private_key or RSA). If authentication fails, the SDK retries with exponential backoff.

  • Parameters
  • on_message (function): Your callback to handle server messages.
    • Signature should be on_message(ws, message).
    • ws is the raw WebSocket object from websocket-client.
    • message is a string containing JSON from the server.
  • on_open (function, optional): Callback invoked once the socket is fully open (post-auth).
    • Signature: on_open(ws).
    • Useful if you want to immediately send subscription messages to the server.

Example

import json

def my_on_message(ws, message):
    data = json.loads(message)
    response_type = data.get("responseType")

    if response_type == "VALIDATE_AUTH_TOKEN_RESPONSE":
        print("Socket authenticated successfully!", data)
    elif response_type == "AUCTION_STARTED":
        print("Auction started:", data["payload"])
    elif response_type == "EXEC_REPORT":
        print("Execution report:", data["payload"])
    else:
        print("Other socket response:", data)

# Connect
sdk.socket.connect(on_message=my_on_message)

Typical responseType Values

  • VALIDATE_AUTH_TOKEN_RESPONSE
    Confirmation you’re authenticated

  • EXEC_REPORT
    Real-time updates about orders (canceled, partially/fully filled)

  • AUCTION_STARTED / AUCTION_FINISHED
    Auction cycle events

  • ORDERBOOK, ORDERBOOK_DELTA, MM_ORDERBOOK_UPDATED
    Orderbook updates

  • TRADE_REPORT
    Trade notifications

  • FUNDLOCK_UPDATED
    Fundlock/collateral changes

  • HEARTBEAT_RESPONSE
    Response to keep-alive requests

  • UNKNOWN
    Unexpected action or error

Note
If your on_message or on_open callback raises exceptions, the SDK logs them but continues running.


Handling Disconnections & Inactivity

The SDK automatically handles:

  1. Network Disconnects
    If the WebSocket closes unexpectedly, the SDK waits a few seconds and retries the connection, with an exponential backoff up to a maximum delay.

  2. Inactivity
    By default, if no messages arrive within inactivity_threshold seconds, the SDK closes and re-establishes the connection. This keeps the stream alive if the server times out idle connections.


Socket.close()

Description
Closes the current WebSocket connection and stops the automatic reconnect loop. After close() is called, the socket thread shuts down, and no more real-time messages will be received.

sdk.socket.close()

Complete Example

Below is a short snippet demonstrating how to:

  1. Initialize IthacaSDK
  2. Connect to the WebSocket
  3. Handle real-time messages (auctions, execution reports, etc.)
  4. Optionally send your own subscription commands in on_open
import json
from ithaca import IthacaSDK

sdk = IthacaSDK(
    private_key="0xabc123...",
    api_endpoint="https://app.canary.ithacanoemon.tech/api/v1",
    ws_endpoint="wss://app.canary.ithacanoemon.tech/wss"
)

def on_socket_open(ws):
    # Subscribe to an linked accounts, to receive notifications of managed accounts.
    subscribe_linked_accounts = {
        "action": "subscribe_linked_accounts"
    }
    ws.send(json.dumps(subscribe_linked_accounts))

def on_socket_message(ws, message):
    data = json.loads(message)
    rtype = data.get("responseType")
    if rtype == "VALIDATE_AUTH_TOKEN_RESPONSE":
        print("WebSocket Authenticated:", data)
    elif rtype == "EXEC_REPORT":
        print("Exec report:", data["payload"])
    elif rtype == "AUCTION_STARTED":
        print("Auction started:", data["payload"])
    else:
        print("Received message:", rtype, data)

# Connect with your callbacks:
sdk.socket.connect(on_message=on_socket_message, on_open=on_socket_open)

This allows you to maintain real-time awareness of events happening in the Ithaca Protocol without constantly polling HTTP endpoints.