Skip to content

Commit

Permalink
Adds logic to update all fees upon tradingFeeUpdated event. Modifies …
Browse files Browse the repository at this point in the history
…to update fees for pairs upon StrategyCreated event.
  • Loading branch information
mikewcasale committed Aug 15, 2023
1 parent 3bcb4e5 commit 78fc667
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 92 deletions.
209 changes: 172 additions & 37 deletions fastlane_bot/events/managers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from typing import List, Dict, Any, Type, Optional, Tuple

import brownie
from eth_typing import ChecksumAddress
from web3 import Web3
from web3.contract import Contract

Expand Down Expand Up @@ -160,6 +161,93 @@ def get_tkn_info(self, address: str) -> Tuple[Optional[str], Optional[int]]:
def multicall(self, address):
return brownie.multicall(address)

def get_carbon_controller_contract(self):
"""
Gets the Carbon Controller contract, already initialized.
"""
return self.pool_contracts["carbon_v1"][self.cfg.CARBON_CONTROLLER_ADDRESS]

def get_pool(self, cid) -> Dict[str, Any]:
"""
Get a pool from the state
Parameters
----------
cid: str
"""
return [p for p in self.pool_data if p["cid"] == cid][0]

def get_custom_trading_fee(
self,
fee_pairs: Dict[Tuple[ChecksumAddress, ChecksumAddress], Any],
tkn0_address: ChecksumAddress,
tkn1_address: ChecksumAddress,
) -> float:
"""
Get the custom trading fee.
Parameters
----------
fee_pairs : Dict[Tuple[ChecksumAddress,ChecksumAddress], Any]
The custom fees per pair, where pair is a (token0_address, token1_address) tuple.
tkn0_address : ChecksumAddress
The token0 address.
tkn1_address : ChecksumAddress
The token1 address.
Returns
-------
float
The custom trading fee.
"""
fee = None
if fee_pairs is not None:
fee = fee_pairs[(tkn0_address, tkn1_address)]
return fee

def update_carbon_fees_for_pairs(self, carbon_controller, pairs):
"""
Update all carbon fees.
"""
all_pairs = pairs

fee_pairs = self.get_fee_pairs(all_pairs, carbon_controller)

strategies_by_pair = self.get_strats_by_pair(all_pairs, carbon_controller)

strategies_by_pair = [
s for strat in strategies_by_pair if strat for s in strat if s
]

for strategy in strategies_by_pair:
if len(strategy) > 0:

cid = strategy[0]
pool_info = self.get_pool(cid)
tkn0_address, tkn1_address = (
pool_info["tkn0_address"],
pool_info["tkn1_address"],
)
fee = self.get_custom_trading_fee(
fee_pairs=fee_pairs,
tkn0_address=tkn0_address,
tkn1_address=tkn1_address,
)

# Update pool_info fee and fee_float
pool_info["fee"] = f"{fee}"
pool_info["fee_float"] = float(fee) / 1e6

# Update pool_data
self.pool_data = [p for p in self.pool_data if p["cid"] != cid]
self.pool_data.append(pool_info)

self.cfg.logger.info(
f"Updating pool {cid} with fee {fee} and fee_float {float(fee) / 1e6}"
)

def get_rows_to_update(self, update_from_contract_block: int) -> List[int]:
"""
Get the rows to update.
Expand Down Expand Up @@ -192,40 +280,14 @@ def get_rows_to_update(self, update_from_contract_block: int) -> List[int]:
self.cfg.CARBON_CONTROLLER_ADDRESS
] = carbon_controller

# Create a list of pairs from the CarbonController contract object
pairs = [(second, first) for first, second in carbon_controller.pairs()]

# Combine both pair lists and add extra parameters
all_pairs = [(pair[0], pair[1], 0, 5000) for pair in pairs]

all_pairs = self.get_pairs_from_carbon_controller(carbon_controller)
strategies_by_pair = self.get_strats_by_pair(all_pairs, carbon_controller)

# expand strategies_by_pair
strategies_by_pair = [
s for strat in strategies_by_pair if strat for s in strat if s
]

# Get the fees for each pair and store in a dictionary
fees_by_pair = self.get_fees_by_pair(all_pairs, carbon_controller)
fee_pairs = {
(
self.web3.toChecksumAddress(pair[0]),
self.web3.toChecksumAddress(pair[1]),
): fee
for pair, fee in zip(all_pairs, fees_by_pair)
}

# Add the reverse pair to the fee_pairs dictionary
fee_pairs.update(
{
(
self.web3.toChecksumAddress(pair[1]),
self.web3.toChecksumAddress(pair[0]),
): fee
for pair, fee in zip(all_pairs, fees_by_pair)
}
)

# Log the time taken for the above operations
self.cfg.logger.info(
f"Fetched {len(strategies_by_pair)} carbon strategies in {time.time() - start_time} seconds"
Expand All @@ -240,7 +302,6 @@ def get_rows_to_update(self, update_from_contract_block: int) -> List[int]:
self.add_pool_info_from_event(
strategy=strategy,
block_number=current_block,
fee_pairs=fee_pairs,
)

# Log the time taken for the above operations
Expand All @@ -255,8 +316,69 @@ def get_rows_to_update(self, update_from_contract_block: int) -> List[int]:
< update_from_contract_block - self.alchemy_max_block_fetch
]

@staticmethod
def get_pairs_from_carbon_controller(carbon_controller: Contract) -> List[Tuple]:
"""
Get all pairs from the CarbonController contract.
Parameters
----------
carbon_controller : Contract
The CarbonController contract object.
Returns
-------
List[Tuple]
A list of pairs.
"""
# Create a list of pairs from the CarbonController contract object
pairs = [(second, first) for first, second in carbon_controller.pairs()]
# Combine both pair lists and add extra parameters
all_pairs = [(pair[0], pair[1], 0, 5000) for pair in pairs]
return all_pairs

def get_fee_pairs(
self, all_pairs: List[Tuple], carbon_controller: Contract
) -> Dict:
"""
Get the fees for each pair and store in a dictionary.
Parameters
----------
all_pairs : List[Tuple]
A list of pairs.
carbon_controller : Contract
The CarbonController contract object.
Returns
-------
Dict
A dictionary of fees for each pair.
"""
# Get the fees for each pair and store in a dictionary
fees_by_pair = self.get_fees_by_pair(all_pairs, carbon_controller)
fee_pairs = {
(
self.web3.toChecksumAddress(pair[0]),
self.web3.toChecksumAddress(pair[1]),
): fee
for pair, fee in zip(all_pairs, fees_by_pair)
}
# Add the reverse pair to the fee_pairs dictionary
fee_pairs.update(
{
(
self.web3.toChecksumAddress(pair[1]),
self.web3.toChecksumAddress(pair[0]),
): fee
for pair, fee in zip(all_pairs, fees_by_pair)
}
)
return fee_pairs

def get_strats_by_pair(
self, all_pairs: List[Tuple[str, str]], carbon_controller: Contract
self, all_pairs: List[Tuple[Any, Any, int, int]], carbon_controller: Contract
):
"""
Get the strategies by pair.
Expand All @@ -275,10 +397,16 @@ def get_strats_by_pair(
"""
with self.multicall(address=self.cfg.MULTICALL_CONTRACT_ADDRESS):
# Fetch strategies for each pair from the CarbonController contract object
strategies_by_pair = [
carbon_controller.strategiesByPair(*pair) for pair in all_pairs
]
try:
# Fetch strategies for each pair from the CarbonController contract object
strategies_by_pair = [
carbon_controller.strategiesByPair(*pair) for pair in all_pairs
]
except AttributeError:
strategies_by_pair = [
carbon_controller.caller.strategiesByPair(*pair)
for pair in all_pairs
]
return strategies_by_pair

def get_fees_by_pair(
Expand All @@ -302,10 +430,17 @@ def get_fees_by_pair(
"""
with self.multicall(address=self.cfg.MULTICALL_CONTRACT_ADDRESS):
# Fetch strategies for each pair from the CarbonController contract object
fees_by_pair = [
carbon_controller.pairTradingFeePPM(pair[0], pair[1])
for pair in all_pairs
]
try:
fees_by_pair = [
carbon_controller.pairTradingFeePPM(pair[0], pair[1])
for pair in all_pairs
]
except AttributeError:
fees_by_pair = [
carbon_controller.caller.pairTradingFeePPM(pair[0], pair[1])
for pair in all_pairs
]

return fees_by_pair

def get_tkn_symbol_and_decimals(
Expand Down
35 changes: 2 additions & 33 deletions fastlane_bot/events/managers/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

class EventManager(BaseManager):
@property
def events(self) -> List[Type[Contract]]:
def events(self) -> List[Contract]:
"""
Get the events from the exchanges.
Expand Down Expand Up @@ -62,15 +62,9 @@ def add_pool_info_from_event(
strategy[2][0]
), self.web3.toChecksumAddress(strategy[2][1])

fee = self.get_custom_trading_fee(
fee_pairs=fee_pairs, tkn0_address=tkn0_address, tkn1_address=tkn1_address
)

return self.add_pool_info(
address=self.cfg.CARBON_CONTROLLER_ADDRESS,
exchange_name="carbon_v1",
fee=f"{fee}",
fee_float=fee,
tkn0_address=tkn0_address,
tkn1_address=tkn1_address,
cid=cid,
Expand All @@ -87,30 +81,5 @@ def add_pool_info_from_event(
block_number=block_number,
)

def get_custom_trading_fee(
self,
fee_pairs: Dict[Tuple[ChecksumAddress, ChecksumAddress], Any],
tkn0_address: ChecksumAddress,
tkn1_address: ChecksumAddress,
) -> float:
"""
Get the custom trading fee.
Parameters
----------
fee_pairs : Dict[Tuple[ChecksumAddress,ChecksumAddress], Any]
The custom fees per pair, where pair is a (token0_address, token1_address) tuple.
tkn0_address : ChecksumAddress
The token0 address.
tkn1_address : ChecksumAddress
The token1 address.

Returns
-------
float
The custom trading fee.
"""
fee = self.cfg.CARBON_FEE
if fee_pairs is not None:
fee = fee_pairs[(tkn0_address, tkn1_address)]
return fee / 1e6
#%%
4 changes: 2 additions & 2 deletions fastlane_bot/events/managers/pools.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,10 @@ def add_pool_info(
self,
address: str,
exchange_name: str,
fee: Any,
fee_float: float,
tkn0_address: str,
tkn1_address: str,
fee: Any = None,
fee_float: float = None,
cid: Optional[str] = None,
other_args: Optional[Dict[str, Any]] = None,
contract: Optional[Contract] = None,
Expand Down
14 changes: 0 additions & 14 deletions fastlane_bot/events/pools/carbon_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,20 +132,6 @@ def update_from_contract(self, contract: Contract) -> Dict[str, Any]:
}
}
params = self.parse_event(self.state, fake_event, "None")

try:
fee = contract.pairTradingFeePPM(
self.state["tkn0_address"], self.state["tkn1_address"]
)
except AttributeError:
fee = contract.caller.pairTradingFeePPM(
self.state["tkn0_address"], self.state["tkn1_address"]
)

fee = fee / 1e6
params["fee"] = f"{fee}"
params["fee_float"] = fee

params["exchange_name"] = "carbon_v1"
for key, value in params.items():
self.state[key] = value
Expand Down
Loading

0 comments on commit 78fc667

Please sign in to comment.