Pendle¶
Connector for Pendle yield trading protocol.
almanak.framework.connectors.pendle
¶
Pendle Protocol Connector
This module provides integration with Pendle Finance, a permissionless yield-trading protocol that enables: - Tokenizing yield-bearing assets into PT (Principal) and YT (Yield) tokens - Trading PT and YT on Pendle's AMM - Providing liquidity to PT/SY pools - Redeeming PT at maturity
Components: - PendleSDK: Low-level protocol interactions - PendleAdapter: ActionType to SDK mapping - PendleReceiptParser: Transaction receipt parsing
Supported Chains: - Arbitrum (primary) - Ethereum
Example
from almanak.framework.connectors.pendle import ( PendleSDK, PendleAdapter, PendleReceiptParser, )
Create SDK¶
sdk = PendleSDK(rpc_url="https://arb1.arbitrum.io/rpc", chain="arbitrum")
Build swap transaction¶
tx = sdk.build_swap_exact_token_for_pt( receiver="0x...", market="0x...", token_in="0x...", amount_in=1018, min_pt_out=1018, )
PendleAdapter
¶
Adapter for Pendle Protocol operations.
This adapter translates between the framework's ActionType enum and Pendle's specific operations. It handles: - Token swaps to/from PT (Principal Token) - Token swaps to/from YT (Yield Token) - Liquidity provision (adding/removing) - PT/YT redemption at maturity
Example
adapter = PendleAdapter(rpc_url="https://arb1.arbitrum.io/rpc", chain="arbitrum")
Build a swap transaction¶
tx = adapter.build_swap( params=PendleSwapParams( market="0x...", token_in="0x...", token_out="0x...", amount_in=1018, min_amount_out=1018, receiver="0x...", swap_type="token_to_pt", ) )
Initialize the Pendle adapter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rpc_url
|
str
|
RPC endpoint URL |
required |
chain
|
str
|
Target chain (arbitrum, ethereum) |
'arbitrum'
|
wallet_address
|
str | None
|
Optional default wallet address for transactions |
None
|
supports_action
¶
Check if this adapter supports the given action type.
get_supported_actions
¶
Get list of supported action types.
build_swap
¶
Build a swap transaction based on the swap type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
PendleSwapParams
|
Swap parameters including market, tokens, and amounts |
required |
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data ready for execution |
build_swap_token_to_pt
¶
build_swap_token_to_pt(
market: str,
token_in: str,
amount_in: int,
min_pt_out: int,
receiver: str,
slippage_bps: int = 50,
) -> PendleTransactionData
Build a token -> PT swap transaction.
This is a convenience method for the most common swap type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
market
|
str
|
Pendle market address |
required |
token_in
|
str
|
Input token address |
required |
amount_in
|
int
|
Amount of input token |
required |
min_pt_out
|
int
|
Minimum PT to receive |
required |
receiver
|
str
|
Address to receive PT |
required |
slippage_bps
|
int
|
Slippage tolerance in basis points |
50
|
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data |
build_swap_pt_to_token
¶
build_swap_pt_to_token(
market: str,
pt_amount: int,
token_out: str,
min_token_out: int,
receiver: str,
slippage_bps: int = 50,
) -> PendleTransactionData
Build a PT -> token swap transaction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
market
|
str
|
Pendle market address |
required |
pt_amount
|
int
|
Amount of PT to swap |
required |
token_out
|
str
|
Output token address |
required |
min_token_out
|
int
|
Minimum token to receive |
required |
receiver
|
str
|
Address to receive token |
required |
slippage_bps
|
int
|
Slippage tolerance |
50
|
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data |
build_add_liquidity
¶
Build an add liquidity transaction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
PendleLPParams
|
Liquidity parameters |
required |
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data |
build_remove_liquidity
¶
Build a remove liquidity transaction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
PendleLPParams
|
Liquidity parameters |
required |
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data |
build_redeem
¶
Build a PT+YT redemption transaction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
PendleRedeemParams
|
Redemption parameters |
required |
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data |
build_approve
¶
Build an approval transaction for the Pendle Router.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token_address
|
str
|
Token to approve |
required |
amount
|
int | None
|
Amount to approve (defaults to max) |
None
|
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data |
get_gas_estimate
¶
Get gas estimate for an action.
estimate_output
¶
Estimate output amount for a swap.
Note: This is a simplified estimation. In production, use the Pendle API or RouterStatic contract for accurate quotes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
market
|
str
|
Market address |
required |
token_in
|
str
|
Input token |
required |
amount_in
|
int
|
Input amount |
required |
swap_type
|
str
|
Type of swap |
required |
Returns:
| Type | Description |
|---|---|
int
|
Estimated output amount |
PendleLPParams
dataclass
¶
PendleLPParams(
market: str,
token: str,
amount: int,
min_amount: int,
receiver: str,
operation: str,
slippage_bps: int = 50,
)
Parameters for Pendle liquidity operations.
PendleRedeemParams
dataclass
¶
PendleRedeemParams(
yt_address: str,
py_amount: int,
token_out: str,
min_token_out: int,
receiver: str,
slippage_bps: int = 50,
)
Parameters for Pendle redemption operations.
PendleSwapParams
dataclass
¶
PendleSwapParams(
market: str,
token_in: str,
token_out: str,
amount_in: int,
min_amount_out: int,
receiver: str,
swap_type: str,
slippage_bps: int = 50,
token_mint_sy: str | None = None,
)
Parameters for Pendle swap operations.
BurnEventData
dataclass
¶
BurnEventData(
receiver: str,
net_lp_burned: int,
net_sy_out: int,
net_pt_out: int,
market_address: str,
)
Parsed data from Pendle Burn (LP removal) event.
MintEventData
dataclass
¶
MintEventData(
receiver: str,
net_lp_minted: int,
net_sy_used: int,
net_pt_used: int,
market_address: str,
)
Parsed data from Pendle Mint (LP) event.
ParsedSwapResult
dataclass
¶
ParsedSwapResult(
token_in: str,
token_out: str,
amount_in: int,
amount_out: int,
amount_in_decimal: Decimal,
amount_out_decimal: Decimal,
effective_price: Decimal,
slippage_bps: int,
market_address: str,
swap_type: str,
)
High-level swap result from Pendle.
ParseResult
dataclass
¶
ParseResult(
success: bool,
events: list[PendleEvent] = list(),
swap_events: list[SwapEventData] = list(),
mint_events: list[MintEventData] = list(),
burn_events: list[BurnEventData] = list(),
redeem_events: list[RedeemPYEventData] = list(),
transfer_events: list[TransferEventData] = list(),
swap_result: ParsedSwapResult | None = None,
error: str | None = None,
transaction_hash: str = "",
block_number: int = 0,
transaction_success: bool = True,
)
Result of parsing a Pendle receipt.
PendleEvent
dataclass
¶
PendleEvent(
event_type: PendleEventType,
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 Pendle event.
PendleEventType
¶
Bases: Enum
Pendle event types.
PendleReceiptParser
¶
PendleReceiptParser(
chain: str = "arbitrum",
token_in_decimals: int = 18,
token_out_decimals: int = 18,
quoted_price: Decimal | None = None,
**kwargs: Any,
)
Parser for Pendle Protocol transaction receipts.
Uses the base infrastructure (EventRegistry, HexDecoder) for standardized event parsing while handling Pendle-specific event structures.
Example
parser = PendleReceiptParser(chain="arbitrum") result = parser.parse_receipt(receipt)
if result.success and result.swap_events: swap = result.swap_events[0] print(f"Swapped {swap.sy_amount} SY for {swap.pt_amount} PT")
Initialize the Pendle receipt parser.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain
|
str
|
Chain name for address resolution |
'arbitrum'
|
token_in_decimals
|
int
|
Decimals for input token |
18
|
token_out_decimals
|
int
|
Decimals for output token |
18
|
quoted_price
|
Decimal | None
|
Expected price for slippage calculation |
None
|
parse_receipt
¶
Parse a Pendle transaction receipt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dictionary |
required |
quoted_amount_out
|
int | None
|
Expected output for slippage calculation |
None
|
Returns:
| Type | Description |
|---|---|
ParseResult
|
ParseResult with extracted events and swap data |
extract_swap_amounts
¶
Extract swap amounts from receipt for Result Enrichment.
Called by the framework after SWAP execution to populate ExecutionResult.swap_amounts.
Returns:
| Type | Description |
|---|---|
dict[str, Any] | None
|
Dictionary with amount_in, amount_out, effective_price, slippage_bps |
extract_lp_minted
¶
Extract LP tokens minted from receipt.
Called by the framework after LP_OPEN execution.
extract_lp_burned
¶
Extract LP tokens burned from receipt.
Called by the framework after LP_CLOSE execution.
extract_redemption_amounts
¶
Extract redemption amounts from receipt.
Called by the framework after WITHDRAW/REDEEM execution.
RedeemPYEventData
dataclass
¶
RedeemPYEventData(
caller: str,
receiver: str,
net_py_redeemed: int,
net_sy_redeemed: int,
yt_address: str,
)
Parsed data from Pendle RedeemPY event.
SwapEventData
dataclass
¶
SwapEventData(
caller: str,
receiver: str,
pt_to_account: int,
sy_to_account: int,
market_address: str,
)
Parsed data from Pendle Swap event.
TransferEventData
dataclass
¶
Parsed data from ERC20 Transfer event.
LiquidityParams
dataclass
¶
LiquidityParams(
receiver: str,
market: str,
token_in: str,
amount_in: int,
min_lp_out: int,
slippage_bps: int = 50,
)
Parameters for liquidity operations.
MarketInfo
dataclass
¶
MarketInfo(
market_address: str,
sy_address: str,
pt_address: str,
yt_address: str,
expiry: int,
underlying_token: str,
underlying_symbol: str,
)
Information about a Pendle market.
PendleActionType
¶
Bases: Enum
Pendle action types.
PendleQuote
dataclass
¶
PendleQuote(
token_in: str,
token_out: str,
amount_in: int,
amount_out: int,
price_impact_bps: int,
gas_estimate: int,
effective_price: Decimal,
)
Quote for a Pendle operation.
PendleSDK
¶
SDK for interacting with Pendle Protocol.
Pendle enables yield tokenization and trading through its AMM. This SDK builds transactions for: - Swapping tokens to/from PT (Principal Token) - Swapping tokens to/from YT (Yield Token) - Adding/removing liquidity - Minting/redeeming SY and PY tokens
Example
sdk = PendleSDK(rpc_url="https://arb1.arbitrum.io/rpc", chain="arbitrum")
Build swap transaction (WETH -> PT-wstETH)¶
tx = sdk.build_swap_exact_token_for_pt( receiver="0x...", market="0x...", token_in="0x...", # WETH amount_in=1018, # 1 WETH min_pt_out=1018, # Minimum PT to receive )
Initialize Pendle SDK.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rpc_url
|
str
|
RPC endpoint URL |
required |
chain
|
str
|
Target chain (arbitrum, ethereum) |
'arbitrum'
|
token_resolver
|
TokenResolver | None
|
Optional TokenResolver instance. If None, uses singleton. |
None
|
build_swap_exact_token_for_pt
¶
build_swap_exact_token_for_pt(
receiver: str,
market: str,
token_in: str,
amount_in: int,
min_pt_out: int,
slippage_bps: int = 50,
token_mint_sy: str | None = None,
) -> PendleTransactionData
Build a swap transaction from token to PT using swapExactTokenForPtSimple.
This uses the simplified Pendle V4 function that doesn't require ApproxParams or LimitOrderData, making encoding more reliable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receiver
|
str
|
Address to receive the PT |
required |
market
|
str
|
Market address |
required |
token_in
|
str
|
Input token address |
required |
amount_in
|
int
|
Amount of input token (in wei) |
required |
min_pt_out
|
int
|
Minimum PT to receive |
required |
slippage_bps
|
int
|
Slippage tolerance in basis points |
50
|
token_mint_sy
|
str | None
|
Token that mints SY (defaults to token_in if not specified). For yield-bearing token markets (like fUSDT0), this should be the yield-bearing token address, not the underlying. |
None
|
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data for execution |
build_swap_exact_pt_for_token
¶
build_swap_exact_pt_for_token(
receiver: str,
market: str,
pt_amount: int,
token_out: str,
min_token_out: int,
slippage_bps: int = 50,
) -> PendleTransactionData
Build a swap transaction from PT to token using swapExactPtForTokenSimple.
This uses the simplified Pendle V4 function that doesn't require LimitOrderData, making encoding more reliable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receiver
|
str
|
Address to receive the token |
required |
market
|
str
|
Market address |
required |
pt_amount
|
int
|
Amount of PT to swap |
required |
token_out
|
str
|
Output token address |
required |
min_token_out
|
int
|
Minimum output token to receive |
required |
slippage_bps
|
int
|
Slippage tolerance in basis points |
50
|
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data for execution |
build_add_liquidity_single_token
¶
build_add_liquidity_single_token(
receiver: str,
market: str,
token_in: str,
amount_in: int,
min_lp_out: int,
slippage_bps: int = 50,
) -> PendleTransactionData
Build a transaction to add liquidity with a single token.
This adds liquidity to a Pendle market using a single input token. The router handles conversion to the proper ratio of SY and PT.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receiver
|
str
|
Address to receive LP tokens |
required |
market
|
str
|
Market address |
required |
token_in
|
str
|
Input token address |
required |
amount_in
|
int
|
Amount of input token |
required |
min_lp_out
|
int
|
Minimum LP tokens to receive |
required |
slippage_bps
|
int
|
Slippage tolerance in basis points |
50
|
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data for execution |
build_remove_liquidity_single_token
¶
build_remove_liquidity_single_token(
receiver: str,
market: str,
lp_amount: int,
token_out: str,
min_token_out: int,
slippage_bps: int = 50,
) -> PendleTransactionData
Build a transaction to remove liquidity to a single token.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receiver
|
str
|
Address to receive output token |
required |
market
|
str
|
Market address |
required |
lp_amount
|
int
|
Amount of LP tokens to burn |
required |
token_out
|
str
|
Output token address |
required |
min_token_out
|
int
|
Minimum output token to receive |
required |
slippage_bps
|
int
|
Slippage tolerance in basis points |
50
|
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data for execution |
build_redeem_py_to_token
¶
build_redeem_py_to_token(
receiver: str,
yt_address: str,
py_amount: int,
token_out: str,
min_token_out: int,
slippage_bps: int = 50,
) -> PendleTransactionData
Build a transaction to redeem PT+YT to token.
After maturity, PT can be redeemed 1:1 for the underlying. Before maturity, you need equal amounts of PT and YT to redeem.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receiver
|
str
|
Address to receive output token |
required |
yt_address
|
str
|
YT contract address |
required |
py_amount
|
int
|
Amount of PT+YT to redeem |
required |
token_out
|
str
|
Output token address |
required |
min_token_out
|
int
|
Minimum output token |
required |
slippage_bps
|
int
|
Slippage tolerance |
50
|
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data for execution |
build_approve_tx
¶
build_approve_tx(
token_address: str,
spender: str | None = None,
amount: int = MAX_UINT256,
) -> PendleTransactionData
Build an ERC-20 approval transaction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token_address
|
str
|
Token to approve |
required |
spender
|
str | None
|
Spender address (defaults to router) |
None
|
amount
|
int
|
Amount to approve (defaults to max) |
MAX_UINT256
|
Returns:
| Type | Description |
|---|---|
PendleTransactionData
|
Transaction data for execution |
PendleTransactionData
dataclass
¶
PendleTransactionData(
to: str,
value: int,
data: str,
gas_estimate: int,
description: str,
action_type: PendleActionType,
)
Transaction data for Pendle operations.
SwapParams
dataclass
¶
SwapParams(
receiver: str,
market: str,
min_out: int,
token_in: str,
amount_in: int,
slippage_bps: int = 50,
)
Parameters for a swap operation.
get_pendle_adapter
¶
get_pendle_adapter(
rpc_url: str,
chain: str = "arbitrum",
wallet_address: str | None = None,
) -> PendleAdapter
Factory function to create a PendleAdapter instance.
get_pendle_sdk
¶
Factory function to create a PendleSDK instance.