MarketlabMarketlabDocs
Scripting V2 - PythonPlain Python Files

Elysium Scripts

React to pool and bonding trades and execute contract actions from Python.

Write Python scripts that react to trades in Market Lab pools and bonding markets on Elysium testnet. No wallet is needed to read trades. External markets and backtesting are not supported yet.

Read Trades

Create watch-market.py. Use the pool or bonding contract address, not the token address, before @trades@elysium:

script = {"name": "watch-market", "version": "2", "lookback": 100}
SOURCE = "0x59675174f1700677e608f86016f1cea764e1abfa@trades@elysium"


def on_data(ctx, history):
    trade = history.source(SOURCE, 0)
    market = trade["onchain"]
    print(market["current_price"], market["volume"]["quote"])

on_data runs when a trade arrives. lookback keeps up to 100 trades for your script.

mlab script run watch-market.py

The market is validated on-chain when the script starts. No market refresh is needed.

Latest Trade or List

Inside on_data, choose which records to read:

latest = history.source(SOURCE, 0)    # Latest trade
previous = history.source(SOURCE, 1)  # One trade before the latest
earlier = history.source(SOURCE, 2)   # Two trades before the latest
trades = history.source(SOURCE)      # List, oldest to newest

An index returns one trade, or None if it is not available yet. No index returns the retained list, or [] when empty, not the market's entire trading history.

What a Trade Returns

Example bonding trade (sample values; block metadata and state omitted):

{
  "price": 0.0001,
  "size": 10,
  "onchain": {
    "kind": "bonding",
    "market": "0x59675174f1700677e608f86016f1cea764e1abfa",
    "side": "buy",
    "base": {
      "symbol": "gurt",
      "address": "0x1171daed16376968bdd3d865318a9a4f3687f328",
      "decimals": 18
    },
    "quote": {
      "symbol": "HYPE",
      "address": null,
      "decimals": 18
    },
    "base_amount": "10",
    "quote_amount": "0.001",
    "current_price": 0.000100004,
    "fee": {
      "amount": "0.000003",
      "asset": {
        "symbol": "HYPE",
        "address": null,
        "decimals": 18
      }
    },
    "volume": {
      "base": "10",
      "quote": "0.001",
      "trades": 1,
      "from_block": 3000000,
      "through_log_index": 0
    }
  }
}

Read these fields from trade:

FieldMeaning
price, sizeTrade execution price and base-token quantity
onchain.sidebuy or sell of the base token
onchain.base, onchain.quoteEach asset's symbol, address, and decimals; native HYPE has no token address
onchain.base_amount, onchain.quote_amountExact traded amounts as decimal strings
onchain.current_pricePrice per base token at the end of the confirmed block, or None if undefined
onchain.feeFee amount and asset
onchain.volumeObserved base and quote totals and number of trades, not 24-hour volume
onchain.statePool reserves or bonding market state
onchain.kind, onchain.marketMarket type and contract address
onchain.transaction_hash, onchain.timestamp_msTransaction and trade time in milliseconds

For example, trade["onchain"]["fee"]["amount"] reads the fee paid. Trades arrive after 12 block confirmations; the current market price can differ from the trade's execution price.

Trade From Your Script

mlab auth set elysium

This creates a trading wallet and prints its address. Fund it with HYPE for gas and the assets you want to trade.

Use ctx.swap inside on_data to buy or sell, after reading that market with history.source. This example buys with 0.01 HYPE:

ctx.swap({
    "exchange": "elysium",
    "market": "0x59675174f1700677e608f86016f1cea764e1abfa",
    "token_in": "native",
    "amount": "0.01",
    "key": "first-buy",
})

For bonding, "native" buys with HYPE; the token's contract address sells it. For pools, use the address of the token you are paying with, such as WHYPE.

Add or Remove Liquidity

For pools only, set POOL to your pool's contract address and read its trades with history.source before calling these helpers:

ctx.deposit({
    "exchange": "elysium", "market": POOL,
    "amount0": "1", "amount1": "2", "key": "deposit-1",
})

ctx.withdraw({
    "exchange": "elysium", "market": POOL,
    "shares": "0.1", "key": "withdraw-1",
})

amount0 and amount1 follow the pool's token order. shares is the number of LP tokens to redeem, not a percentage. Pass amounts as decimal strings, such as "0.01", not base-unit integers.

All three helpers accept slippage_bps (default 50, or 0.5%) and max_gas (default "0.0001" HYPE per transaction).

Follow Execution

def on_execution(ctx):
    event = ctx.execution
    if event["type"] == "contract.confirmed":
        print(event["key"], event["data"]["result"]["receipts"])
    elif event["type"] == "contract.failed":
        print(event["data"]["result"]["error"])

An action is complete when contract.confirmed arrives, not when the helper returns. Use a new key for each intended action; the same key and request will not trade again within that job.

On this page