GMX V2¶
| Field | Value |
|---|---|
| Module | almanak.connectors.gmx_v2 |
| Protocol kind | Perp |
| Aliases | N/A |
Supported Chains And Intents¶
| Chain | Family | Supported Intents |
|---|---|---|
| Arbitrum | EVM | PERP_CANCEL_ORDER, PERP_CLOSE, PERP_OPEN |
| Avalanche | EVM | PERP_CANCEL_ORDER, PERP_CLOSE, PERP_OPEN |
API Reference¶
almanak.connectors.gmx_v2
¶
GMX v2 Connector.
This module provides an adapter for interacting with GMX v2 perpetuals protocol, supporting position management, order execution, and event parsing.
GMX v2 is a decentralized perpetual exchange supporting: - Long and short positions with leverage - Multiple collateral types - Limit and market orders - Position sizing and management
Supported chains: - Arbitrum - Avalanche
Example
from almanak.connectors.gmx_v2 import GMXv2Adapter, GMXv2Config
config = GMXv2Config( chain="arbitrum", wallet_address="0x...", ) adapter = GMXv2Adapter(config)
Open a position¶
result = adapter.open_position( market="ETH/USD", collateral_token="USDC", collateral_amount=Decimal("1000"), size_delta_usd=Decimal("5000"), is_long=True, )
GMXv2Adapter
¶
Adapter for GMX v2 perpetuals protocol.
This adapter provides methods for: - Opening and closing positions - Increasing and decreasing position size - Managing limit orders and stop losses - Querying position and market data - Parsing transaction receipts
Example
config = GMXv2Config( chain="arbitrum", wallet_address="0x...", ) adapter = GMXv2Adapter(config)
Open a long position¶
result = adapter.open_position( market="ETH/USD", collateral_token="USDC", collateral_amount=Decimal("1000"), size_delta_usd=Decimal("5000"), is_long=True, )
Check position¶
position = adapter.get_position( market="ETH/USD", collateral_token="USDC", is_long=True, )
Close position¶
result = adapter.close_position( market="ETH/USD", collateral_token="USDC", is_long=True, size_delta_usd=position.size_in_usd, )
Initialize the adapter.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
config
|
GMXv2Config
|
GMX v2 adapter configuration |
必需 |
token_resolver
|
TokenResolver | None
|
Optional TokenResolver instance. If None, uses singleton. |
None
|
open_position
¶
open_position(
market: str,
collateral_token: str,
collateral_amount: Decimal,
size_delta_usd: Decimal,
is_long: bool,
acceptable_price: Decimal | None = None,
trigger_price: Decimal | None = None,
) -> OrderResult
Open a new position or increase existing position.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
market
|
str
|
Market identifier (e.g., "ETH/USD") or market address |
必需 |
collateral_token
|
str
|
Token symbol or address for collateral |
必需 |
collateral_amount
|
Decimal
|
Amount of collateral in token decimals |
必需 |
size_delta_usd
|
Decimal
|
Position size in USD (will be scaled to 30 decimals) |
必需 |
is_long
|
bool
|
True for long, False for short |
必需 |
acceptable_price
|
Decimal | None
|
Maximum (long) or minimum (short) execution price |
None
|
trigger_price
|
Decimal | None
|
Trigger price for limit orders |
None
|
返回:
| 类型 | 描述 |
|---|---|
OrderResult
|
OrderResult with order details |
close_position
¶
close_position(
market: str,
collateral_token: str,
is_long: bool,
size_delta_usd: Decimal | None = None,
receive_token: str | None = None,
acceptable_price: Decimal | None = None,
trigger_price: Decimal | None = None,
) -> OrderResult
Close a position or decrease position size.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
market
|
str
|
Market identifier or address |
必需 |
collateral_token
|
str
|
Token symbol or address for collateral |
必需 |
is_long
|
bool
|
Position direction |
必需 |
size_delta_usd
|
Decimal | None
|
Amount to close in USD (None = close entire position) |
None
|
receive_token
|
str | None
|
Token to receive (defaults to collateral_token) |
None
|
acceptable_price
|
Decimal | None
|
Minimum (long) or maximum (short) execution price |
None
|
trigger_price
|
Decimal | None
|
Trigger price for limit orders |
None
|
返回:
| 类型 | 描述 |
|---|---|
OrderResult
|
OrderResult with order details |
increase_position
¶
increase_position(
market: str,
collateral_token: str,
is_long: bool,
collateral_delta: Decimal,
size_delta_usd: Decimal,
acceptable_price: Decimal | None = None,
trigger_price: Decimal | None = None,
) -> OrderResult
Increase an existing position.
This is an alias for open_position with an existing position.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
market
|
str
|
Market identifier or address |
必需 |
collateral_token
|
str
|
Token symbol or address |
必需 |
is_long
|
bool
|
Position direction |
必需 |
collateral_delta
|
Decimal
|
Additional collateral to add |
必需 |
size_delta_usd
|
Decimal
|
Additional size in USD |
必需 |
acceptable_price
|
Decimal | None
|
Maximum (long) or minimum (short) execution price |
None
|
trigger_price
|
Decimal | None
|
Trigger price for limit orders |
None
|
返回:
| 类型 | 描述 |
|---|---|
OrderResult
|
OrderResult with order details |
decrease_position
¶
decrease_position(
market: str,
collateral_token: str,
is_long: bool,
size_delta_usd: Decimal,
collateral_delta: Decimal = Decimal("0"),
receive_token: str | None = None,
acceptable_price: Decimal | None = None,
trigger_price: Decimal | None = None,
) -> OrderResult
Decrease an existing position.
This is similar to close_position but for partial closes.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
market
|
str
|
Market identifier or address |
必需 |
collateral_token
|
str
|
Token symbol or address |
必需 |
is_long
|
bool
|
Position direction |
必需 |
size_delta_usd
|
Decimal
|
Size to reduce in USD |
必需 |
collateral_delta
|
Decimal
|
Collateral to withdraw |
Decimal('0')
|
receive_token
|
str | None
|
Token to receive |
None
|
acceptable_price
|
Decimal | None
|
Minimum (long) or maximum (short) execution price |
None
|
trigger_price
|
Decimal | None
|
Trigger price for limit orders |
None
|
返回:
| 类型 | 描述 |
|---|---|
OrderResult
|
OrderResult with order details |
get_position
¶
Get position details.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
market
|
str
|
Market identifier or address |
必需 |
collateral_token
|
str
|
Token symbol or address |
必需 |
is_long
|
bool
|
Position direction |
必需 |
返回:
| 类型 | 描述 |
|---|---|
GMXv2Position | None
|
Position details or None if not found |
get_all_positions
¶
Get all open positions from in-memory state.
返回:
| 类型 | 描述 |
|---|---|
list[GMXv2Position]
|
List of all open positions (in-memory only, not on-chain) |
get_positions_onchain
¶
get_positions_onchain(
rpc_url: str | None = None,
gateway_client: GatewayClient | None = None,
) -> list[GMXv2Position]
Read all open positions for this wallet directly from on-chain state.
Uses the GMX V2 SyntheticsReader contract to query the DataStore for all positions belonging to the configured wallet address. Includes fallback mechanisms for when Reader methods revert (e.g. after GMX contract upgrades).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
rpc_url
|
str | None
|
RPC endpoint URL for on-chain queries |
None
|
返回:
| 类型 | 描述 |
|---|---|
list[GMXv2Position]
|
List of GMXv2Position objects read from chain |
引发:
| 类型 | 描述 |
|---|---|
ValueError
|
If the chain is not supported for on-chain reads |
get_positions_as_teardown_summary
¶
get_positions_as_teardown_summary(
rpc_url: str | None = None,
deployment_id: str = "",
gateway_client: GatewayClient | None = None,
) -> TeardownPositionSummary
Read on-chain positions and return as TeardownPositionSummary.
This is the primary method for integrating with the teardown system. It reads positions directly from chain and converts them to the PositionInfo format used by get_open_positions().
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
rpc_url
|
str | None
|
DEPRECATED — RPC endpoint URL. Prefer gateway_client. |
None
|
deployment_id
|
str
|
Deployment identifier for the summary |
''
|
gateway_client
|
GatewayClient | None
|
Gateway client for routing eth_call through the gateway. Preferred over rpc_url. |
None
|
返回:
| 类型 | 描述 |
|---|---|
TeardownPositionSummary
|
TeardownPositionSummary with on-chain position data |
cancel_order
¶
Cancel a pending order.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
order_key
|
str
|
Order key to cancel |
必需 |
返回:
| 类型 | 描述 |
|---|---|
OrderResult
|
OrderResult indicating success/failure |
get_order
¶
Get order details.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
order_key
|
str
|
Order key to look up |
必需 |
返回:
| 类型 | 描述 |
|---|---|
GMXv2Order | None
|
Order details or None if not found |
get_all_orders
¶
build_cancel_order_tx
¶
Build ExchangeRouter.cancelOrder(bytes32) transaction data for an order key.
Pure and stateless: keyed only by the on-chain order_key (bytes32), with
no dependency on the adapter's in-memory _orders tracking. This is what the
teardown recovery lane (VIB-5568) uses to cancel a discovered stranded order
(fresh process, nothing tracked) — unlike :meth:cancel_order, which requires
the order to be locally tracked and is blind to teardown-discovered residuals.
value=0 — a cancel carries no keeper execution fee; the OrderVault refund
(committed collateral + unspent exec fee) lands in the wallet
(cancellationReceiver defaults to the caller).
set_position
¶
GMXv2Config
dataclass
¶
GMXv2Config(
chain: str,
wallet_address: str,
execution_fee: int | None = None,
referral_code: bytes = b"\x00" * 32,
)
Configuration for GMXv2Adapter.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
chain |
str
|
Target blockchain (arbitrum or avalanche) |
wallet_address |
str
|
Address executing transactions |
execution_fee |
int | None
|
Execution fee in native token wei (auto-set per chain) |
referral_code |
bytes
|
Optional referral code for fee discounts |
GMXv2Order
dataclass
¶
GMXv2Order(
order_key: str,
market: str,
initial_collateral_token: str,
order_type: GMXv2OrderType,
is_long: bool,
size_delta_usd: Decimal,
initial_collateral_delta_amount: Decimal,
trigger_price: Decimal | None = None,
acceptable_price: Decimal | None = None,
execution_fee: int = 0,
callback_gas_limit: int = 0,
is_frozen: bool = False,
created_at: datetime = (lambda: datetime.now(UTC))(),
updated_at: datetime = (lambda: datetime.now(UTC))(),
)
Represents a GMX v2 order.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
order_key |
str
|
Unique identifier for the order |
market |
str
|
Market address |
initial_collateral_token |
str
|
Collateral token for the order |
order_type |
GMXv2OrderType
|
Type of order |
is_long |
bool
|
Position direction |
size_delta_usd |
Decimal
|
Size change in USD (30 decimals) |
initial_collateral_delta_amount |
Decimal
|
Collateral amount change |
trigger_price |
Decimal | None
|
Trigger price for limit/stop orders |
acceptable_price |
Decimal | None
|
Maximum/minimum acceptable execution price |
execution_fee |
int
|
Fee paid to keeper |
callback_gas_limit |
int
|
Gas limit for callback execution |
is_frozen |
bool
|
Whether order is frozen |
created_at |
datetime
|
Order creation timestamp |
updated_at |
datetime
|
Last update timestamp |
GMXv2OrderType
¶
GMXv2Position
dataclass
¶
GMXv2Position(
position_key: str,
market: str,
collateral_token: str,
size_in_usd: Decimal,
size_in_tokens: Decimal,
collateral_amount: Decimal,
entry_price: Decimal,
is_long: bool,
realized_pnl: Decimal = Decimal("0"),
unrealized_pnl: Decimal = Decimal("0"),
leverage: Decimal = Decimal("1"),
liquidation_price: Decimal | None = None,
funding_fee_amount: Decimal = Decimal("0"),
borrowing_fee_amount: Decimal = Decimal("0"),
last_updated: datetime = (lambda: datetime.now(UTC))(),
)
Represents an open GMX v2 position.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
position_key |
str
|
Unique identifier for the position |
market |
str
|
Market address |
collateral_token |
str
|
Token used as collateral |
size_in_usd |
Decimal
|
Position size in USD (30 decimals) |
size_in_tokens |
Decimal
|
Position size in index tokens (token decimals) |
collateral_amount |
Decimal
|
Collateral amount in token decimals |
entry_price |
Decimal
|
Average entry price (30 decimals) |
is_long |
bool
|
True for long, False for short |
realized_pnl |
Decimal
|
Realized PnL (30 decimals) |
unrealized_pnl |
Decimal
|
Unrealized PnL (30 decimals) |
leverage |
Decimal
|
Current leverage (size / collateral) |
liquidation_price |
Decimal | None
|
Price at which position gets liquidated |
funding_fee_amount |
Decimal
|
Accumulated funding fees |
borrowing_fee_amount |
Decimal
|
Accumulated borrowing fees |
last_updated |
datetime
|
Timestamp of last update |
GMXv2PositionSide
¶
Bases: Enum
Position side (long/short).
GMXv2Event
dataclass
¶
GMXv2Event(
event_type: GMXv2EventType,
event_name: str,
log_index: int,
transaction_hash: str,
block_number: int,
contract_address: str,
data: dict[str, Any],
raw_topics: list[str] = list(),
raw_data: str = "",
timestamp: datetime = (lambda: datetime.now(UTC))(),
)
Parsed GMX v2 event.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
event_type |
GMXv2EventType
|
Type of event |
event_name |
str
|
Name of event (e.g., "PositionIncrease") |
log_index |
int
|
Index of log in transaction |
transaction_hash |
str
|
Transaction hash |
block_number |
int
|
Block number |
contract_address |
str
|
Contract that emitted event |
data |
dict[str, Any]
|
Parsed event data |
raw_topics |
list[str]
|
Raw event topics |
raw_data |
str
|
Raw event data |
timestamp |
datetime
|
Event timestamp |
GMXv2EventType
¶
Bases: Enum
GMX v2 event types.
GMXv2ReceiptParser
¶
Parser for GMX v2 transaction receipts.
This parser extracts and decodes GMX v2 events from transaction receipts, providing structured data for position updates, order fills, and other protocol events.
SUPPORTED_EXTRACTIONS declares the extraction fields this parser can provide. Used by ResultEnricher to warn when expected fields are unsupported.
Example
parser = GMXv2ReceiptParser()
Parse a receipt dict (from web3.py)¶
result = parser.parse_receipt(receipt)
if result.success: for event in result.events: print(f"Event: {event.event_name}")
for increase in result.position_increases:
print(f"Position increased: size=${increase.size_in_usd}")
Initialize the parser.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
chain
|
EVM chain slug (e.g. |
必需 | |
**kwargs
|
Any
|
Additional arguments (ignored for compatibility). |
{}
|
build_extract_kwargs
staticmethod
¶
Thread compiler-verified index decimals into perp fill scaling.
parse_receipt
¶
Parse a transaction receipt.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict containing 'logs', 'transactionHash', 'blockNumber', etc. |
必需 |
返回:
| 类型 | 描述 |
|---|---|
ParseResult
|
ParseResult with extracted events and data |
parse_logs
¶
Parse a list of logs.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
logs
|
list[dict[str, Any]]
|
List of log dicts |
必需 |
返回:
| 类型 | 描述 |
|---|---|
list[GMXv2Event]
|
List of parsed events |
is_gmx_event
¶
Check if a topic is a known GMX v2 event.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
topic
|
str | bytes
|
Event topic (supports bytes, hex string with/without 0x, any case) |
必需 |
返回:
| 类型 | 描述 |
|---|---|
bool
|
True if topic is a known GMX v2 event |
get_event_type
¶
Get the event type for a topic.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
topic
|
str | bytes
|
Event topic (supports bytes, hex string with/without 0x, any case) |
必需 |
返回:
| 类型 | 描述 |
|---|---|
GMXv2EventType
|
Event type or UNKNOWN |
extract_swap_amounts_result
¶
Fail-closed variant of :meth:extract_swap_amounts — see VIB-3159.
extract_async_orders_result
¶
extract_async_orders_result(
receipt: dict[str, Any],
*,
intent_type: str | None = None,
) -> ExtractResult[list[AsyncOrderData]]
Extract authoritative GMX OrderCreated identifiers.
extract_async_orders
¶
extract_async_orders(
receipt: dict[str, Any],
*,
intent_type: str | None = None,
) -> list[AsyncOrderData] | None
Legacy-compatible raw accessor for authoritative created orders.
extract_position_id_result
¶
Fail-closed variant of :meth:extract_position_id — see VIB-3159.
extract_size_delta_result
¶
Fail-closed variant of :meth:extract_size_delta — see VIB-3159.
extract_collateral_result
¶
Fail-closed variant of :meth:extract_collateral — see VIB-3159.
extract_entry_price_result
¶
Fail-closed variant of :meth:extract_entry_price — see VIB-3159.
extract_leverage_result
¶
Fail-closed variant of :meth:extract_leverage — see VIB-3159.
extract_realized_pnl_result
¶
Fail-closed variant of :meth:extract_realized_pnl — see VIB-3159.
extract_exit_price_result
¶
Fail-closed variant of :meth:extract_exit_price — see VIB-3159.
extract_fees_paid_result
¶
Fail-closed variant of :meth:extract_fees_paid — see VIB-3159.
extract_collateral_returned_result
¶
Fail-closed variant of :meth:extract_collateral_returned — see VIB-3159.
extract_swap_amounts
¶
Extract swap amounts from transaction receipt.
GMX V2 "swaps" are executed through perpetual orders, not spot swaps. For GMX orders: - amount_in = initial_collateral_delta_amount (collateral deposited) - amount_out = size_delta_usd (position size in USD, scaled by 1e30) - effective_price represents the leverage ratio
The VIB-3203 expected_out kwarg is accepted for interface parity
with spot-swap parsers, but NOT used to compute slippage_bps —
comparing "realized collateral" to a "quoted collateral" is not the
same semantic as realized vs quoted swap output, and would produce
misleading slippage values. Slippage reporting for GMX V2 perps
(acceptable price vs execution price) is a separate semantic and is
out of scope for VIB-3203.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
必需 |
expected_out
|
Decimal | None
|
Accepted but ignored — see docstring. |
None
|
返回:
| 类型 | 描述 |
|---|---|
Any
|
SwapAmounts dataclass if swap order found, None otherwise |
extract_position_id
¶
Extract position ID (key) from transaction receipt.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
必需 |
返回:
| 类型 | 描述 |
|---|---|
str | None
|
Position key if found, None otherwise |
extract_size_delta
¶
Extract size delta (in USD) from transaction receipt.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Decimal | None
|
Size delta in USD if found, None otherwise |
extract_collateral
¶
Extract collateral amount from transaction receipt.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Decimal | None
|
Collateral amount if found, None otherwise |
extract_entry_price
¶
Extract entry price from transaction receipt.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Decimal | None
|
Entry price in USD if found, None otherwise |
extract_leverage
¶
Extract leverage from transaction receipt.
Leverage is calculated as size_in_usd / (collateral_amount * collateral_token_price).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Decimal | None
|
Leverage multiplier (e.g., Decimal("10") for 10x) if found, None otherwise. |
extract_realized_pnl
¶
Extract realized PnL from transaction receipt.
Only available for position decreases (closing/reducing positions).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Decimal | None
|
Realized PnL in USD if found, None otherwise |
extract_exit_price
¶
Extract exit price from transaction receipt.
Only available for position decreases (closing/reducing positions).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Decimal | None
|
Exit price in USD if found, None otherwise |
extract_collateral_returned
¶
Extract collateral returned at close from a PERP_CLOSE receipt.
Sums raw collateralDeltaAmount values (the collateral withdrawn from the
position) across every PositionDecrease event in the receipt. For a
full close GMX sets the delta to the position's entire remaining
collateral, so this is the raw collateral-token leg of the close payout.
Raw smallest-unit semantics match the other perpetual receipt parsers
and allow exact wallet-delta reconciliation without a guessed decimal
scale.
Semantics — what this is NOT: the net wallet credit (GMX's
outputAmount = collateral delta ± realized PnL − fees, optionally
swapped to another token) lives in the EventUtils.EventLogData
payload and is distinct from this collateral delta. PnL and fees are
extracted separately (realized_pnl, fees_paid).
Empty != Zero: only values the decoder actually produced are summed.
Events whose decode fell back to raw_data carry no
collateral_delta_amount key and are skipped; if no event carries a
decoded value this returns None (unmeasured), never a fabricated
zero. A decoded 0 (size-only decrease) is a measured zero and is
returned as Decimal("0").
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Decimal | None
|
Total collateral withdrawn across PositionDecrease events, or None |
Decimal | None
|
when no event carries a decoded collateral_delta_amount. |
extract_fees_paid
¶
Extract fees paid from transaction receipt.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
必需 |
返回:
| 类型 | 描述 |
|---|---|
int | None
|
Execution fee in wei if found, None otherwise. |
extract_funding_fee_usd_result
¶
Fail-closed variant of :meth:extract_funding_fee_usd — see VIB-3159.
extract_funding_fee_usd
¶
Extract accumulated funding fee in USD from a CLOSE receipt (VIB-3497).
GMX V2 emits a PositionFeesCollected event alongside every
PositionDecrease. The fundingFeeAmount field (collateral-token
units) lives inside that event's keyed EventUtils.EventLogData
payload. This decodes it BY NAME (VIB-3873) and converts it to USD with
the SAME event's collateralTokenPrice bounds — a decimals-free
conversion (amount * price / 1e30) that needs no live oracle read, so
the parser stays a pure function of the receipt.
Empty != Zero: returns None when the receipt carries no
PositionFeesCollected event (or the funding amount / price could not
be decoded) — "funding cost unknown" — never a fabricated 0. A
measured zero funding fee (short hold) returns Decimal("0").
返回:
| 类型 | 描述 |
|---|---|
Decimal | None
|
Funding fee in USD, or |
extract_keeper_execution_fee
¶
extract_keeper_execution_fee(
receipt: dict[str, Any], *, account: str | None = None
) -> tuple[int | None, int | None]
Native-wei (keeper_fee, refund) from a keeper receipt (VIB-6061).
Returns (None, None) when the receipt carries no unambiguous, authentic,
account-owned pair — see :meth:_select_execution_fee_events. Never raises:
a malformed receipt is unmeasured, not an error, because this rides alongside
the fill economics and must never take a settlement write down with it.
extract_perp_fill_result
¶
extract_perp_fill_result(
receipt: dict[str, Any],
order_key: str | None = None,
account: str | None = None,
index_token_decimals_override: int | None = None,
) -> ExtractResult[PerpFillData]
Fail-closed variant of :meth:extract_perp_fill — see VIB-3159.
account is threaded through (VIB-6061) so this wrapper measures the same
fields as the method it wraps. Dropping it here would leave the keeper
execution fee unmeasured BY CONSTRUCTION for every caller of the fail-closed
variant — a silent divergence between two functions whose whole contract is
that they differ only in error handling.
extract_perp_fill
¶
extract_perp_fill(
receipt: dict[str, Any],
order_key: str | None = None,
account: str | None = None,
index_token_decimals_override: int | None = None,
) -> PerpFillData | None
Build typed fill economics from a GMX keeper receipt (VIB-3872 WI-1).
Merges the receipt's PositionIncrease or PositionDecrease
event (position identity, execution price, size / collateral deltas,
price impact, realized PnL) with its PositionFeesCollected event
(funding / position / borrowing fees in USD). Every field is decoded BY
NAME from the keyed EventUtils payload and follows Empty != Zero.
order_key is the settlement being measured (VIB-6110). A GMX keeper
transaction may execute SEVERAL orders — on different markets, in
different directions — so the position and fee events must be
correlated to the watched order rather than taken first-wins.
Uncorrelated, closing order B inside a batch that also opened order A
returns A's fill: is_open=True with A's market and A's entry price,
and B's real exit price is lost. Because the impostor price is itself
plausible, nothing downstream can detect the substitution.
Returns None when the receipt carries no PositionIncrease /
PositionDecrease event attributable to order_key (nothing to
settle) — callers map that to UNMEASURED rather than to a fill. A
keeper receipt that only yields the position event (no matching fees
event) still returns a PerpFillData with the fee fields left None
(unmeasured). Passing order_key=None keeps the legacy first-wins
behaviour for callers that have no watched order.
Source authentication. When order_key is supplied, only logs
emitted by the chain's canonical GMX EventEmitter are considered.
Correlating on an orderKey decoded from an unauthenticated log
would not be correlation at all: _parse_log recognises GMX events by
topic hash alone and never checks log["address"], and a GMX order
carries an owner-chosen callbackContract that runs inside the very
keeper transaction this method parses. A co-batched adversary can read
the order nonce from DataStore, compute our key, and emit a forged
PositionDecrease carrying it with an arbitrary market and price —
moving the attack from "be first in the log list" to "write the right
32 bytes". Restricting to the EventEmitter is what makes the decoded
orderKey trustworthy. If the emitter cannot be resolved (unknown or
absent chain) a correlated call fails closed to None: an
unmeasured settlement is recoverable, a forged one is not.
The emitter check runs against each PARSED event's contract_address
(see :meth:_select_fill_events), never by pre-filtering the receipt's
logs — a filtered receipt keeps its transactionHash, which is the
key ResultEnricher's parse cache uses, so pre-filtering is
defeatable by a warmed cache.
account (VIB-6061) is the strategy wallet. Supplying it additionally
measures the keeper execution fee — the native-token cost of the fill that
is NOT transaction gas and that the Cost Stack previously showed nowhere.
Omitting it leaves keeper_execution_fee_wei unmeasured; it never
affects the fill economics above.
extract_protocol_fees
¶
Placeholder for GMX V2 perp-fee extraction (VIB-3204).
GMX V2 encodes open / close fees in PositionFeesInfo events
emitted by the position handler. Decoding those events (including
borrowing, funding, and execution-fee components) is non-trivial
and is deferred to a follow-up; extract_fees_paid already
surfaces the execution fee in wei for operator-level accounting.
Follow-up ticket: "Perps fee extraction for GMX V2 / Drift — follow-up to VIB-3204".
PerpFillData
dataclass
¶
PerpFillData(
is_open: bool | None = None,
is_long: bool | None = None,
market: str | None = None,
collateral_token: str | None = None,
position_key: str | None = None,
order_key: str | None = None,
entry_price: Decimal | None = None,
exit_price: Decimal | None = None,
size_delta_usd: Decimal | None = None,
size_delta_in_tokens: Decimal | None = None,
collateral_delta_amount: Decimal | None = None,
price_impact_usd: Decimal | None = None,
realized_pnl_usd: Decimal | None = None,
position_fee_usd: Decimal | None = None,
funding_fee_usd: Decimal | None = None,
borrowing_fee_usd: Decimal | None = None,
keeper_tx_hash: str | None = None,
block_number: int | None = None,
keeper_execution_fee_wei: int | None = None,
execution_fee_refund_wei: int | None = None,
)
Receipt-measured GMX V2 fill economics (VIB-3873 / VIB-3872 WI-1).
Built from a keeper transaction's PositionIncrease or
PositionDecrease event, merged with its PositionFeesCollected event,
each decoded BY KEY from the dynamic EventUtils.EventLogData payload (not
fixed byte offsets — that is the VIB-3873 misread class). This is the typed
verdict payload the WI-2 settlement capability carries into accounting; it is
intentionally self-contained (no framework imports) so WI-2 can consume it
without new plumbing.
Empty != Zero — every field is Optional. None means the keeper receipt
did not carry that field (unmeasured); Decimal("0") means a measured
zero (e.g. zero funding over a short hold). Never substitute one for the
other.
Scaling:
size_delta_usd/price_impact_usd/realized_pnl_usdare plain USD Decimals (GMX's 30-decimal USD convention divided out).position_fee_usd/funding_fee_usd/borrowing_fee_usdare plain USD, converted from the fee's collateral-token amount using the SAMEPositionFeesCollectedevent'scollateralTokenPrice(decimals-free:amount * price / 1e30).entry_price/exit_priceare USD-per-token: GMXexecutionPricescaled by10**(index_token_decimals) / 1e30(VIB-6110). The index-token decimals are resolved from the parser'schain+ the fill'smarketvia the venue-verified catalog. Empty≠Zero:Nonewhen the price is absent OR the decimals cannot be resolved (parser constructed without achain, or an unlisted market) — NEVER the wrongly-scaled raw GMX-native ratio (the1.9e-15bug this field previously shipped).collateral_delta_amountis the raw collateral-token smallest-unit integer (matchesextract_collateral_returnedsemantics — no guessed decimal scale).keeper_execution_fee_wei/execution_fee_refund_weiare NATIVE-token wei integers, not USD (VIB-6061). They are the two halves of the escrow we posted asmsg.valueat createOrder: the keeper's cut and our refund. Kept in wei rather than converted here because the parser is a pure function of the receipt and holds no price oracle — the USD conversion happens at the settlement-commit seam against the SUBMISSION row's ownprice_inputs_json, so the booked USD is priced at the same moment as that row'sgas_usd.
to_dict
¶
Convert to a stable machine-readable dictionary (Empty != Zero preserved).
GMXV2SDK
¶
GMXV2SDK(
rpc_url: str | None = None,
chain: str = "arbitrum",
gateway_client: GatewayClient | None = None,
)
SDK for interacting with GMX V2 perpetuals on Arbitrum.
This SDK builds transactions for creating orders using the ExchangeRouter's multicall function which atomically: 1. Sends collateral to OrderVault (via sendWnt or sendTokens) 2. Creates the order
Initialize GMX V2 SDK.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
rpc_url
|
str | None
|
DEPRECATED — direct RPC URL. Prefer gateway_client for any code path running in a strategy container. |
None
|
chain
|
str
|
Target chain — any key in GMX_V2_SDK_ADDRESSES (currently arbitrum and avalanche; see almanak/core/contracts.py:GMX_V2). |
'arbitrum'
|
gateway_client
|
GatewayClient | None
|
Gateway client for routing eth_call through the gateway. Preferred over rpc_url. |
None
|
get_account_position_count
¶
Get the number of open positions for an account.
Tries SyntheticsReader.getAccountPositionCount first. If it reverts (e.g. after a GMX contract upgrade removed the function), falls back to a DataStore getBytes32Count query using the account position list key.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
account
|
str
|
Wallet address to query |
必需 |
返回:
| 类型 | 描述 |
|---|---|
int
|
Number of open positions (0 if both methods fail) |
get_account_positions
¶
Read all open positions for an account.
Tries on-chain Reader contract first, then falls back to GMX REST API when Reader calls revert (common after GMX contract upgrades).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
account
|
str
|
Wallet address to query |
必需 |
返回:
| 类型 | 描述 |
|---|---|
list[dict]
|
List of position dicts with keys: account, market, collateral_token, |
list[dict]
|
size_in_usd, size_in_tokens, collateral_amount, borrowing_factor, |
list[dict]
|
funding_fee_amount_per_size, is_long, increased_at_time, decreased_at_time |
get_market_address
¶
Get GMX V2 market address for an index token.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
index_token_symbol
|
str
|
"ETH" or "BTC" |
必需 |
返回:
| 类型 | 描述 |
|---|---|
str
|
Market address |
get_execution_fee
¶
Calculate execution fee for GMX order dynamically.
GMX V2 validates: executionFee >= adjustedGasLimit * tx.gasprice where adjustedGasLimit = baseGasLimit + orderGasLimit * multiplierFactor (callbackGasLimit = 0 for our orders).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
order_type
|
str
|
"increase" or "decrease" to select appropriate gas limit |
'increase'
|
multiplier
|
float
|
Safety multiplier on top of the adjusted gas limit (default 1.5x for testing, use 2.0x for production) |
1.5
|
返回:
| 类型 | 描述 |
|---|---|
int
|
Execution fee in wei |
build_increase_order_multicall
¶
Build a multicall transaction to create an increase order.
This combines: 1. sendWnt or sendTokens (collateral to OrderVault) 2. createOrder
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
params
|
GMXV2OrderParams
|
Order parameters |
必需 |
返回:
| 类型 | 描述 |
|---|---|
GMXV2TransactionData
|
Transaction data ready for execution |
build_decrease_order_multicall
¶
Build a multicall transaction to create a decrease order.
For decrease orders, no collateral needs to be sent to OrderVault. Only the execution fee is needed, sent via sendWnt.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
params
|
GMXV2OrderParams
|
Order parameters |
必需 |
返回:
| 类型 | 描述 |
|---|---|
GMXV2TransactionData
|
Transaction data ready for execution |
DecreasePositionSwapType
¶
Bases: IntEnum
GMX V2 Decrease Position Swap Types
GMXV2OrderParams
dataclass
¶
GMXV2OrderParams(
from_address: str,
market: str,
initial_collateral_token: str,
initial_collateral_delta_amount: int,
size_delta_usd: int,
is_long: bool,
acceptable_price: int,
execution_fee: int,
trigger_price: int = 0,
referral_code: bytes = b"\x00" * 32,
)
Parameters for creating a GMX V2 order.
GMXV2TransactionData
dataclass
¶
Transaction data returned by the SDK.
OrderType
¶
Bases: IntEnum
GMX V2 Order Types
get_allowed_collaterals
¶
Return the tuple of allowed collateral token symbols for a market.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
chain
|
str
|
Chain name ( |
必需 |
market
|
str
|
Canonical venue market label (e.g. |
必需 |
返回:
| 类型 | 描述 |
|---|---|
str
|
Tuple of allowed collateral symbols. The tuple is non-empty for any |
...
|
registered |
引发:
| 类型 | 描述 |
|---|---|
KeyError
|
If the market is not registered for the chain. Callers that
want the "unknown market" path should call :func: |
is_market_registered
¶
Return True if collateral rules are known for (chain, market).
Used by the compiler to distinguish between "market is unknown, cannot validate locally" (permissive path) and "market is known and the collateral is wrong" (strict reject path).
Chain and market inputs are case-insensitive.
registered_markets
¶
Return the iterable of market identifiers registered for a chain.
Useful for diagnostics / operator card messages. Chain input is case-insensitive.
validate_collateral
¶
Validate that collateral_token is a legal collateral for market.
Compile-path validation. This is the main entry point used by the
_compile_perp_open path in the intent compiler. It must be called
BEFORE any transaction actions are emitted.
Behaviour
- If
marketis registered forchainandcollateral_tokenis not one of the allowed symbols, raise :class:InvalidCollateralForMarketError. - If
marketis registered andcollateral_tokenis recognised but passed as a raw 0x-address, the validation is skipped with a debug log and the compiler falls through to address-based resolution. - If
marketis NOT registered (unknown / new market), log a warning and return (permissive). The strict on-chain check still fires at order-time via the GMX keeper, but this module cannot do better without an RPC round trip.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
chain
|
str
|
Chain name ( |
必需 |
market
|
str
|
Market identifier (e.g. |
必需 |
collateral_token
|
str
|
Collateral token symbol (e.g. |
必需 |
引发:
| 类型 | 描述 |
|---|---|
InvalidCollateralForMarketError
|
When both the market is registered AND the collateral is a symbol that is not in the allowed set. |
get_gmx_v2_sdk
¶
get_gmx_v2_sdk(
rpc_url: str | None = None,
chain: str = "arbitrum",
gateway_client: GatewayClient | None = None,
) -> GMXV2SDK
Factory function to create a GMX V2 SDK instance.