Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/decibel/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"round_to_valid_order_size",
"amount_to_chain_units",
"chain_units_to_amount",
"bps_to_chain_units",
"extract_vault_address_from_create_tx",
"generate_random_replay_protection_nonce",
]
Expand Down Expand Up @@ -385,6 +386,21 @@ def amount_to_chain_units(amount: float, decimals: int = 6) -> int:
return round(amount * (10**decimals))


def bps_to_chain_units(bps: int | float) -> int:
"""Convert basis points (bps) to chain units for builder fees.

The contract uses FEE_PRECISION = 10000 to represent 1%.
Since a basis point is 1/100th of a percent, multiply by 100.

Args:
bps: Basis point value (e.g. 10 for 0.1%)

Returns:
Chain units as integer (e.g. 10 bps -> 1000)
"""
return round(bps * 100)
Comment thread
WGB5445 marked this conversation as resolved.


def chain_units_to_amount(chain_units: int, decimals: int = 6) -> float:
"""Convert chain units to a decimal amount (e.g., 5670000 -> 5.67)."""
return chain_units / (10**decimals)
Expand Down
23 changes: 15 additions & 8 deletions src/decibel/write/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from decibel._subaccount_types import RenameSubaccount, RenameSubaccountArgs
from decibel._transaction_builder import InputEntryFunctionData
from decibel._utils import (
bps_to_chain_units,
get_market_addr,
get_primary_subaccount_addr,
post_request,
Expand Down Expand Up @@ -270,6 +271,7 @@ async def place_order(
if sl_limit_price is not None and tick_size
else sl_limit_price
)
final_builder_fee = bps_to_chain_units(builder_fee) if builder_fee is not None else None

pkg = self._config.deployment.package

Expand All @@ -293,7 +295,7 @@ async def _send(addr: str) -> dict[str, Any]:
final_sl_trigger,
final_sl_limit,
builder_addr,
builder_fee,
final_builder_fee,
],
),
account_override,
Expand Down Expand Up @@ -359,6 +361,7 @@ async def place_twap_order(
) -> PlaceOrderResult:
market_addr = get_market_addr(market_name, self._config.deployment.perp_engine_global)
pkg = self._config.deployment.package
final_builder_fees = bps_to_chain_units(builder_fees) if builder_fees is not None else None

async def _send(addr: str) -> dict[str, Any]:
return await self._send_tx(
Expand All @@ -375,7 +378,7 @@ async def _send(addr: str) -> dict[str, Any]:
twap_frequency_seconds,
twap_duration_seconds,
builder_address,
builder_fees,
final_builder_fees,
],
),
account_override,
Expand Down Expand Up @@ -1049,17 +1052,18 @@ async def approve_max_builder_fee(
self,
*,
builder_addr: str,
max_fee: int,
max_fee: int | float,
subaccount_addr: str | None = None,
) -> dict[str, Any]:
pkg = self._config.deployment.package
final_max_fee = bps_to_chain_units(max_fee)

async def _send(addr: str) -> dict[str, Any]:
return await self._send_tx(
InputEntryFunctionData(
function=f"{pkg}::dex_accounts_entry::approve_max_builder_fee_for_subaccount",
type_arguments=[],
function_arguments=[addr, builder_addr, max_fee],
function_arguments=[addr, builder_addr, final_max_fee],
)
)

Expand Down Expand Up @@ -1302,6 +1306,7 @@ def place_order(
if sl_limit_price is not None and tick_size
else sl_limit_price
)
final_builder_fee = bps_to_chain_units(builder_fee) if builder_fee is not None else None

pkg = self._config.deployment.package

Expand All @@ -1325,7 +1330,7 @@ def _send(addr: str) -> dict[str, Any]:
final_sl_trigger,
final_sl_limit,
builder_addr,
builder_fee,
final_builder_fee,
],
),
account_override,
Expand Down Expand Up @@ -1391,6 +1396,7 @@ def place_twap_order(
) -> PlaceOrderResult:
market_addr = get_market_addr(market_name, self._config.deployment.perp_engine_global)
pkg = self._config.deployment.package
final_builder_fees = bps_to_chain_units(builder_fees) if builder_fees is not None else None

def _send(addr: str) -> dict[str, Any]:
return self._send_tx(
Expand All @@ -1407,7 +1413,7 @@ def _send(addr: str) -> dict[str, Any]:
twap_frequency_seconds,
twap_duration_seconds,
builder_address,
builder_fees,
final_builder_fees,
],
),
account_override,
Expand Down Expand Up @@ -2077,17 +2083,18 @@ def approve_max_builder_fee(
self,
*,
builder_addr: str,
max_fee: int,
max_fee: int | float,
subaccount_addr: str | None = None,
) -> dict[str, Any]:
pkg = self._config.deployment.package
final_max_fee = bps_to_chain_units(max_fee)

def _send(addr: str) -> dict[str, Any]:
return self._send_tx(
InputEntryFunctionData(
function=f"{pkg}::dex_accounts_entry::approve_max_builder_fee_for_subaccount",
type_arguments=[],
function_arguments=[addr, builder_addr, max_fee],
function_arguments=[addr, builder_addr, final_max_fee],
)
)

Expand Down
2 changes: 1 addition & 1 deletion src/decibel/write/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class CancelTpSlOrderArgs(TypedDict):

class ApproveBuilderFeeArgs(TypedDict):
builder_addr: str
max_fee: int
max_fee: int | float
subaccount_addr: NotRequired[str | None]


Expand Down