Saltar a contenido

BenQi

Connector for BenQi lending protocol (Compound V2 fork on Avalanche).

almanak.framework.connectors.benqi

BENQI Lending Connector (Compound V2 fork on Avalanche).

This module provides adapters and utilities for interacting with BENQI, a leading lending/borrowing protocol on Avalanche using the qiToken architecture.

BENQI Features: - Compound V2-style qiToken model - Supply to earn yield (mint qiTokens) - Borrow against collateral (enterMarkets + borrow) - Multiple asset markets: AVAX, USDC, USDT, WETH.e, BTC.b, sAVAX

Supported Chains: - Avalanche

Example

from almanak.framework.connectors.benqi import ( BenqiAdapter, BenqiConfig, BenqiReceiptParser, )

config = BenqiConfig( chain="avalanche", wallet_address="0x...", ) adapter = BenqiAdapter(config)

Supply USDC

result = adapter.supply(asset="USDC", amount=Decimal("1000"))

Parse receipts

parser = BenqiReceiptParser(underlying_decimals=6) events = parser.parse_receipt(receipt)

BenqiAdapter

BenqiAdapter(
    config: BenqiConfig,
    token_resolver: TokenResolver | None = None,
)

Adapter for BENQI lending protocol on Avalanche.

Provides methods to build transactions for supply, withdraw, borrow, and repay operations using the qiToken (Compound V2) architecture.

get_market_info

get_market_info(asset: str) -> BenqiMarketInfo | None

Get market info for an asset.

get_qi_token_address

get_qi_token_address(asset: str) -> str | None

Get the qiToken address for an asset.

get_supported_assets

get_supported_assets() -> list[str]

Get list of supported asset symbols.

supply

supply(asset: str, amount: Decimal) -> TransactionResult

Build a supply (lend) transaction.

For ERC20 tokens: calls mint(uint256) on the qiToken. For AVAX: calls mint() payable on qiAVAX.

Parameters:

Name Type Description Default
asset str

Asset symbol (e.g., "USDC", "AVAX")

required
amount Decimal

Amount in underlying token units (e.g., 1000 USDC)

required

Returns:

Type Description
TransactionResult

TransactionResult with TX data for execution

withdraw

withdraw(
    asset: str,
    amount: Decimal,
    *,
    withdraw_all: bool = False,
    redeem_amount: int | None = None,
) -> TransactionResult

Build a withdraw transaction.

Calls redeemUnderlying(uint256) on the qiToken to withdraw exact underlying amount. For withdraw_all with redeem_amount, uses redeem(uint256) with exact qiToken count. For withdraw_all with amount > 0, uses redeemUnderlying(amount_wei) with the tracked amount.

Parameters:

Name Type Description Default
asset str

Asset symbol

required
amount Decimal

Amount of underlying to withdraw

required
withdraw_all bool

If True, withdraw entire balance

False
redeem_amount int | None

Exact qiToken amount for redeem() when withdraw_all=True. Not yet wired from the compiler — reserved for future use when the compiler can query on-chain qiToken balances.

None

Returns:

Type Description
TransactionResult

TransactionResult with TX data

borrow

borrow(asset: str, amount: Decimal) -> TransactionResult

Build a borrow transaction.

Calls borrow(uint256) on the qiToken. Requires collateral to be supplied and enterMarkets() called first.

Parameters:

Name Type Description Default
asset str

Asset symbol to borrow

required
amount Decimal

Amount to borrow in underlying units

required

Returns:

Type Description
TransactionResult

TransactionResult with TX data

repay

repay(
    asset: str, amount: Decimal, *, repay_all: bool = False
) -> TransactionResult

Build a repay transaction.

For ERC20: calls repayBorrow(uint256) on the qiToken. For AVAX: calls repayBorrow() payable on qiAVAX. For repay_all: uses MAX_UINT256 to repay full debt.

Parameters:

Name Type Description Default
asset str

Asset symbol

required
amount Decimal

Amount to repay

required
repay_all bool

If True, repay entire outstanding debt

False

Returns:

Type Description
TransactionResult

TransactionResult with TX data

enter_markets

enter_markets(assets: list[str]) -> TransactionResult

Build an enterMarkets transaction to enable assets as collateral.

Parameters:

Name Type Description Default
assets list[str]

List of asset symbols to enable as collateral

required

Returns:

Type Description
TransactionResult

TransactionResult with TX data

exit_market

exit_market(asset: str) -> TransactionResult

Build an exitMarket transaction to remove an asset from collateral.

Note: exitMarket is per-asset (not array), unlike enterMarkets. Will revert if the user has outstanding borrows against this collateral.

Parameters:

Name Type Description Default
asset str

Asset symbol to remove from collateral

required

Returns:

Type Description
TransactionResult

TransactionResult with TX data

BenqiConfig dataclass

BenqiConfig(
    chain: str = "avalanche",
    wallet_address: str = "",
    default_slippage_bps: int = 50,
)

Configuration for BENQI adapter.

BenqiMarketInfo dataclass

BenqiMarketInfo(
    asset: str,
    qi_token_address: str,
    underlying_address: str | None,
    decimals: int,
    is_native: bool,
)

Information about a BENQI market (qiToken).

BenqiPosition dataclass

BenqiPosition(
    supplied: dict[str, Decimal] = dict(),
    borrowed: dict[str, Decimal] = dict(),
)

User position in BENQI.

TransactionResult dataclass

TransactionResult(
    success: bool,
    tx_data: dict[str, Any] | None = None,
    gas_estimate: int = 0,
    description: str = "",
    error: str | None = None,
)

Result of building a transaction.

BenqiEvent dataclass

BenqiEvent(
    event_type: BenqiEventType,
    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 BENQI event.

to_dict

to_dict() -> dict[str, Any]

Convert to dictionary.

from_dict classmethod

from_dict(data: dict[str, Any]) -> BenqiEvent

Create from dictionary.

BenqiEventType

Bases: Enum

BENQI event types.

BenqiReceiptParser

BenqiReceiptParser(
    underlying_decimals: int = 18, **kwargs: Any
)

Parse BENQI transaction receipts.

Extracts supply, withdraw, borrow, and repay amounts from Compound V2-style events (Mint, Redeem, Borrow, RepayBorrow).

parse_receipt

parse_receipt(
    receipt: dict[str, Any],
    qi_token_address: str | None = None,
) -> ParseResult

Parse a transaction receipt for BENQI events.

Parameters:

Name Type Description Default
receipt dict[str, Any]

Transaction receipt dict with 'logs' field

required
qi_token_address str | None

Optional filter for specific qiToken

None

Returns:

Type Description
ParseResult

ParseResult with extracted events and amounts

parse_logs

parse_logs(
    logs: list[dict[str, Any]],
    tx_hash: str = "",
    block_number: int = 0,
) -> list[BenqiEvent]

Parse a list of log entries into BENQI events.

extract_supply_data

extract_supply_data(result: dict[str, Any]) -> dict | None

Extract supply data from a parsed transaction receipt.

Called by ResultEnricher for SUPPLY intents.

Parameters:

Name Type Description Default
result dict[str, Any]

Transaction receipt dict with 'logs' field

required

Returns:

Type Description
dict | None

Dict with supply_amount and qi_tokens_minted, or None if not found

extract_borrow_data

extract_borrow_data(result: dict[str, Any]) -> dict | None

Extract borrow data from a parsed transaction receipt.

Called by ResultEnricher for BORROW intents.

Parameters:

Name Type Description Default
result dict[str, Any]

Transaction receipt dict with 'logs' field

required

Returns:

Type Description
dict | None

Dict with borrow_amount, or None if not found

extract_withdraw_data

extract_withdraw_data(
    result: dict[str, Any],
) -> dict | None

Extract withdraw data from a parsed transaction receipt.

Called by ResultEnricher for WITHDRAW intents.

Parameters:

Name Type Description Default
result dict[str, Any]

Transaction receipt dict with 'logs' field

required

Returns:

Type Description
dict | None

Dict with withdraw_amount, or None if not found

extract_repay_data

extract_repay_data(result: dict[str, Any]) -> dict | None

Extract repay data from a parsed transaction receipt.

Called by ResultEnricher for REPAY intents.

Parameters:

Name Type Description Default
result dict[str, Any]

Transaction receipt dict with 'logs' field

required

Returns:

Type Description
dict | None

Dict with repay_amount, or None if not found

ParseResult dataclass

ParseResult(
    success: bool,
    events: list[BenqiEvent] = list(),
    supply_amount: Decimal = Decimal("0"),
    withdraw_amount: Decimal = Decimal("0"),
    borrow_amount: Decimal = Decimal("0"),
    repay_amount: Decimal = Decimal("0"),
    qi_tokens_minted: Decimal = Decimal("0"),
    qi_tokens_redeemed: Decimal = Decimal("0"),
    error: str | None = None,
)

Result of parsing a transaction receipt.

to_dict

to_dict() -> dict[str, Any]

Convert to dictionary.