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
457 changes: 457 additions & 0 deletions docs/source/builder-integration.rst

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ You might want to use a virtual environment to isolate your packages.
user-guides
margin-manager
order-appendix
builder-integration
api-reference
1 change: 1 addition & 0 deletions nado_protocol/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ def create_nado_client(
perp_engine_addr=deployment.perp_engine_addr,
spot_engine_addr=deployment.spot_engine_addr,
clearinghouse_addr=deployment.clearinghouse_addr,
offchain_exchange_addr=deployment.offchain_exchange_addr,
airdrop_addr=deployment.airdrop_addr,
staking_addr=deployment.staking_addr,
foundation_rewards_airdrop_addr=deployment.foundation_rewards_airdrop_addr,
Expand Down
74 changes: 73 additions & 1 deletion nado_protocol/contracts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@
from web3.contract.contract import ContractFunction
from eth_account.signers.local import LocalAccount
from nado_protocol.contracts.loader import load_abi
from nado_protocol.contracts.types import DepositCollateralParams, NadoAbiName
from nado_protocol.contracts.types import (
BuilderInfo,
ClaimBuilderFeeParams,
DepositCollateralParams,
NadoAbiName,
)
from nado_protocol.utils.bytes32 import (
hex_to_bytes32,
str_to_hex,
subaccount_name_to_bytes12,
subaccount_to_bytes32,
zero_address,
)
from nado_protocol.utils.exceptions import InvalidProductId
from nado_protocol.utils.slow_mode import encode_claim_builder_fee_tx
from nado_protocol.contracts.types import *


Expand All @@ -33,6 +40,8 @@ class NadoContractsContext(BaseModel):

clearinghouse_addr (Optional[str]): The clearinghouse address. This may be None.

offchain_exchange_addr (Optional[str]): The offchain exchange address. This may be None.

airdrop_addr (Optional[str]): The airdrop address. This may be None.

staking_addr (Optional[str]): The staking address. This may be None.
Expand All @@ -46,6 +55,7 @@ class NadoContractsContext(BaseModel):
spot_engine_addr: Optional[str]
perp_engine_addr: Optional[str]
clearinghouse_addr: Optional[str]
offchain_exchange_addr: Optional[str]
airdrop_addr: Optional[str]
staking_addr: Optional[str]
foundation_rewards_airdrop_addr: Optional[str]
Expand All @@ -62,6 +72,7 @@ class NadoContracts:
querier: Contract
endpoint: Contract
clearinghouse: Optional[Contract]
offchain_exchange: Optional[Contract]
spot_engine: Optional[Contract]
perp_engine: Optional[Contract]
airdrop: Optional[Contract]
Expand Down Expand Up @@ -92,6 +103,7 @@ def __init__(self, node_url: str, contracts_context: NadoContractsContext):
abi=load_abi(NadoAbiName.ENDPOINT), # type: ignore
)
self.clearinghouse = None
self.offchain_exchange = None
self.spot_engine = None
self.perp_engine = None

Expand All @@ -113,6 +125,12 @@ def __init__(self, node_url: str, contracts_context: NadoContractsContext):
abi=load_abi(NadoAbiName.IPERP_ENGINE), # type: ignore
)

if self.contracts_context.offchain_exchange_addr:
self.offchain_exchange: Contract = self.w3.eth.contract(
address=self.contracts_context.offchain_exchange_addr,
abi=load_abi(NadoAbiName.IOFFCHAIN_EXCHANGE), # type: ignore
)

if self.contracts_context.staking_addr:
self.staking: Contract = self.w3.eth.contract(
address=self.contracts_context.staking_addr,
Expand Down Expand Up @@ -294,6 +312,58 @@ def claim_foundation_rewards(
self.foundation_rewards_airdrop.functions.claim(proofs), signer
)

def claim_builder_fee(
self,
params: ClaimBuilderFeeParams,
signer: LocalAccount,
) -> str:
"""
Claims accumulated builder fees via slow mode transaction.

This submits a ClaimBuilderFee slow mode transaction to the Endpoint contract.
The fees will be credited to the specified subaccount.

Args:
params (ClaimBuilderFeeParams): The parameters for claiming builder fees.
signer (LocalAccount): The account that will sign the transaction.

Returns:
str: The transaction hash of the claim operation.
"""
params = ClaimBuilderFeeParams.parse_obj(params)
sender_bytes = subaccount_to_bytes32(
params.subaccount_owner, params.subaccount_name
)
tx_bytes = encode_claim_builder_fee_tx(sender_bytes, params.builder_id)
return self.execute(
self.endpoint.functions.submitSlowModeTransaction(tx_bytes),
signer,
)

def get_builder_info(self, builder_id: int) -> BuilderInfo:
"""
Gets builder information from the OffchainExchange contract.

Args:
builder_id (int): The builder ID to query.

Returns:
BuilderInfo: The builder information including owner, fee tier, and fee rates.

Raises:
Exception: If the OffchainExchange contract is not initialized.
"""
if self.offchain_exchange is None:
raise Exception("OffchainExchange contract not initialized")

result = self.offchain_exchange.functions.getBuilder(builder_id).call()
return BuilderInfo(
owner=result[0],
default_fee_tier=result[1],
lowest_fee_rate=result[2],
highest_fee_rate=result[3],
)

def _mint_mock_erc20(
self, erc20: Contract, amount: int, signer: LocalAccount
) -> str:
Expand Down Expand Up @@ -377,6 +447,8 @@ def _build_tx_params(self, signer: LocalAccount) -> TxParams:
__all__ = [
"NadoContractsContext",
"NadoContracts",
"BuilderInfo",
"ClaimBuilderFeeParams",
"DepositCollateralParams",
"NadoExecuteType",
"NadoNetwork",
Expand Down
43 changes: 43 additions & 0 deletions nado_protocol/contracts/abis/IOffchainExchange.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[
{
"inputs": [
{
"internalType": "uint32",
"name": "builderId",
"type": "uint32"
}
],
"name": "getBuilder",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "uint32",
"name": "defaultFeeTier",
"type": "uint32"
},
{
"internalType": "int128",
"name": "lowestFeeRate",
"type": "int128"
},
{
"internalType": "int128",
"name": "highestFeeRate",
"type": "int128"
}
],
"internalType": "struct IOffchainExchange.Builder",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"endpoint": "0x05ec92D78ED421f3D3Ada77FFdE167106565974E",
"spotEngine": "0xFcD94770B95fd9Cc67143132BB172EB17A0907fE",
"perpEngine": "0xF8599D58d1137fC56EcDd9C16ee139C8BDf96da1",
"offchainExchange": "0x8373C3Aa04153aBc0cfD28901c3c971a946994ab",
"airdrop": "0x0000000000000000000000000000000000000000",
"staking": "0x0000000000000000000000000000000000000000",
"foundationRewardsAirdrop": "0x0000000000000000000000000000000000000000"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"endpoint": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318",
"spotEngine": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
"perpEngine": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"offchainExchange": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
"airdrop": "0x0000000000000000000000000000000000000000",
"staking": "0x0000000000000000000000000000000000000000",
"foundationRewardsAirdrop": "0x0000000000000000000000000000000000000000"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"endpoint": "0x698D87105274292B5673367DEC81874Ce3633Ac2",
"spotEngine": "0x3352b2fF0fAc4ce38A6eA1C188cF4F924df54E5D",
"perpEngine": "0x4E859C47fea3666B5053B16C81AF64e77567702e",
"offchainExchange": "0x1e38180CFa9100b653c1Ea73B1B8175Aca1a45d0",
"airdrop": "0x0000000000000000000000000000000000000000",
"staking": "0x0000000000000000000000000000000000000000",
"foundationRewardsAirdrop": "0x0000000000000000000000000000000000000000"
Expand Down
34 changes: 34 additions & 0 deletions nado_protocol/contracts/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class NadoAbiName(StrEnum):
FQUERIER = "FQuerier"
ICLEARINGHOUSE = "IClearinghouse"
IENDPOINT = "IEndpoint"
IOFFCHAIN_EXCHANGE = "IOffchainExchange"
IPERP_ENGINE = "IPerpEngine"
ISPOT_ENGINE = "ISpotEngine"
MOCK_ERC20 = "MockERC20"
Expand Down Expand Up @@ -74,6 +75,7 @@ class NadoDeployment(NadoBaseModel):
airdrop_addr: str = Field(alias="airdrop")
staking_addr: str = Field(alias="staking")
foundation_rewards_airdrop_addr: str = Field(alias="foundationRewardsAirdrop")
offchain_exchange_addr: str = Field(alias="offchainExchange")


class DepositCollateralParams(NadoBaseModel):
Expand Down Expand Up @@ -119,6 +121,38 @@ class ClaimFoundationRewardsContractParams(NadoBaseModel):
claim_proofs: list[ClaimFoundationRewardsProofStruct]


class ClaimBuilderFeeParams(NadoBaseModel):
"""
Parameters for claiming builder fees via slow mode transaction.

Attributes:
subaccount_owner (str): The address of the subaccount owner.
subaccount_name (str): The name of the subaccount (default: "default").
builder_id (int): The builder ID to claim fees for.
"""

subaccount_owner: str
subaccount_name: str = "default"
builder_id: int


class BuilderInfo(NadoBaseModel):
"""
Builder information from the OffchainExchange contract.

Attributes:
owner (str): The address that can claim builder fees.
default_fee_tier (int): The default fee tier for the builder.
lowest_fee_rate (int): The lowest fee rate (x18).
highest_fee_rate (int): The highest fee rate (x18).
"""

owner: str
default_fee_tier: int
lowest_fee_rate: int
highest_fee_rate: int


class NadoExecuteType(StrEnum):
"""
Enumeration of possible actions to execute in Nado.
Expand Down
4 changes: 4 additions & 0 deletions nado_protocol/indexer_client/types/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class IndexerEventType(StrEnum):
TRANSFER_QUOTE = "transfer_quote"
CREATE_ISOLATED_SUBACCOUNT = "create_isolated_subaccount"
CLOSE_ISOLATED_SUBACCOUNT = "close_isolated_subaccount"
CLAIM_BUILDER_FEE = "claim_builder_fee"


class IndexerCandlesticksGranularity(IntEnum):
Expand Down Expand Up @@ -57,6 +58,7 @@ class IndexerOrderFill(IndexerBaseModel):
base_filled: str
quote_filled: str
fee: str
builder_fee: str


class IndexerHistoricalOrder(IndexerOrderFill):
Expand All @@ -66,6 +68,7 @@ class IndexerHistoricalOrder(IndexerOrderFill):
price_x18: str
expiration: str
nonce: str
appendix: str
isolated: bool


Expand All @@ -76,6 +79,7 @@ class IndexerSignedOrder(NadoBaseModel):

class IndexerMatch(IndexerOrderFill):
order: IndexerBaseOrder
sequencer_fee: str
cumulative_fee: str
cumulative_base_filled: str
cumulative_quote_filled: str
Expand Down
8 changes: 8 additions & 0 deletions nado_protocol/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from nado_protocol.utils.nonce import *
from nado_protocol.utils.exceptions import *
from nado_protocol.utils.order import *
from nado_protocol.utils.slow_mode import *

__all__ = [
"NadoBackendURL",
Expand Down Expand Up @@ -53,4 +54,11 @@
"order_trigger_type",
"order_twap_data",
"order_execution_type",
# Builder utilities
"order_builder_id",
"order_builder_fee_rate",
"order_builder_info",
# Slow mode utilities
"SlowModeTxType",
"encode_claim_builder_fee_tx",
]
Loading