Skip to content

Commit

Permalink
Merge pull request #4 from valory-xyz/fix/claim-rewards
Browse files Browse the repository at this point in the history
  • Loading branch information
0xArdi authored Aug 30, 2024
2 parents 632cd93 + b1efaa9 commit ee72906
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 92 deletions.
8 changes: 4 additions & 4 deletions packages/packages.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
"contract/valory/uniswap_v3_non_fungible_position_manager/0.1.0": "bafybeieljamerttxyo7z2yokwripnnhzkn4zply5lz457vsixf5wfu5px4",
"contract/valory/uniswap_v3_pool/0.1.0": "bafybeidglijnyueahpgivaykbhio2r3ovfeo23a256y3yb6g7be4hngx3a",
"contract/valory/merkl_distributor/0.1.0": "bafybeifctofnyhdic2sxmkqujvf3j2wwydhtvzhi6kdeutykenymplf4e4",
"skill/valory/liquidity_trader_abci/0.1.0": "bafybeihml6udc4leqoexdbqrjchxj4nlymqky5ejh6vlnqg7mlh64jp2zi",
"skill/valory/optimus_abci/0.1.0": "bafybeia3bmcjh2xyfqqlxkapegfkuy4fdezvsjhmu5ans33gdcexlr54ha",
"agent/valory/optimus/0.1.0": "bafybeihiq4tplmbmlodqnfyojrnvyzkdoz25c667v6gocpv3r5chohnlgm",
"service/valory/optimus/0.1.0": "bafybeic6ohhyrjk7yxtllxfhepd35boyqqqolevnxnftftv6by2qhnypcu"
"skill/valory/liquidity_trader_abci/0.1.0": "bafybeia6pmuwqvpb6bdk75uywqxgr3puarikzcfkxj5xvwbyu7lxqzmkgi",
"skill/valory/optimus_abci/0.1.0": "bafybeifaid4m5y6nr6zhqhoyonl34gjq4sloajvnwfxp6odybb5tzdepnm",
"agent/valory/optimus/0.1.0": "bafybeih32imiqyeh23pu5yjtjbxcbvmblpjwl6an7vxpisqri4yeuqkwby",
"service/valory/optimus/0.1.0": "bafybeid3sapqas3ow57jc5pdnngyzrmxutih4k5y56elgbez6jjxaqzfiu"
},
"third_party": {
"protocol/open_aea/signing/1.0.0": "bafybeihv62fim3wl2bayavfcg3u5e5cxu3b7brtu4cn5xoxd6lqwachasi",
Expand Down
4 changes: 2 additions & 2 deletions packages/valory/agents/optimus/aea-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ protocols:
skills:
- valory/abstract_abci:0.1.0:bafybeihu2bcgjk2tqjiq2zhk3uogtfszqn4osvdt7ho3fubdpdj4jgdfjm
- valory/abstract_round_abci:0.1.0:bafybeibovsktd3uxur45nrcomq5shcn46cgxd5idmhxbmjhg32c5abyqim
- valory/liquidity_trader_abci:0.1.0:bafybeihml6udc4leqoexdbqrjchxj4nlymqky5ejh6vlnqg7mlh64jp2zi
- valory/optimus_abci:0.1.0:bafybeia3bmcjh2xyfqqlxkapegfkuy4fdezvsjhmu5ans33gdcexlr54ha
- valory/liquidity_trader_abci:0.1.0:bafybeia6pmuwqvpb6bdk75uywqxgr3puarikzcfkxj5xvwbyu7lxqzmkgi
- valory/optimus_abci:0.1.0:bafybeifaid4m5y6nr6zhqhoyonl34gjq4sloajvnwfxp6odybb5tzdepnm
- valory/registration_abci:0.1.0:bafybeicnth5q4httefsusywx3zrrq4al47owvge72dqf2fziruicq6hqta
- valory/reset_pause_abci:0.1.0:bafybeievjciqdvxhqxfjd4whqs27h6qbxqzrae7wwj7fpvxlvmtw3x35im
- valory/termination_abci:0.1.0:bafybeid54buqxipiuduw7b6nnliiwsxajnltseuroad53wukfonpxca2om
Expand Down
2 changes: 1 addition & 1 deletion packages/valory/services/optimus/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ aea_version: '>=1.0.0, <2.0.0'
license: Apache-2.0
fingerprint: {}
fingerprint_ignore_patterns: []
agent: valory/optimus:0.1.0:bafybeihiq4tplmbmlodqnfyojrnvyzkdoz25c667v6gocpv3r5chohnlgm
agent: valory/optimus:0.1.0:bafybeih32imiqyeh23pu5yjtjbxcbvmblpjwl6an7vxpisqri4yeuqkwby
number_of_agents: 1
deployment: {}
---
Expand Down
159 changes: 77 additions & 82 deletions packages/valory/skills/liquidity_trader_abci/behaviours.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,41 +422,6 @@ def async_act(self) -> Generator:
if invest_in_pool:
actions = yield from self.get_order_of_transactions()

current_timestamp = cast(
SharedState, self.context.state
).round_sequence.last_round_transition_timestamp.timestamp()

# Check if rewards can be claimed. Rewards can be claimed if either:
# 1. No rewards have been claimed yet (last_reward_claimed_timestamp is None), or
# 2. The current timestamp exceeds the allowed reward claiming time period since the last claim.
claim_rewards = (
True
if self.synchronized_data.last_reward_claimed_timestamp is None
else current_timestamp
>= self.synchronized_data.last_reward_claimed_timestamp
+ self.params.reward_claiming_time_period
)
if claim_rewards:
# check current reward
allowed_chains = self.params.allowed_chains
if not allowed_chains:
self.context.logger.warning("No chains found")
return None
# we can claim all our token rewards at once
# hence we build only one action per chain
for chain in allowed_chains:
chain_id = self.params.chain_to_chain_id_mapping.get(chain)
safe_address = self.params.safe_contract_addresses.get(chain)
rewards = yield from self.get_rewards(chain_id, safe_address)
if not rewards:
self.context.logger.warning(
f"No rewards to claim for user address {safe_address} on chain {chain}"
)
continue
action = yield from self.build_claim_reward_action(rewards, chain)
if action:
actions.append(action)

self.context.logger.info(f"Actions: {actions}")
serialized_actions = json.dumps(actions)
sender = self.context.agent_address
Expand Down Expand Up @@ -573,7 +538,7 @@ def _get_filtered_pools(self) -> Generator[None, None, Optional[Dict[str, Any]]]
# use this if you want to test with script
# api_url = self.params.pool_data_api_url

self.context.logger.info(f"{api_url}")
self.context.logger.info(f"Fetching campaigns from {api_url}")

response = yield from self.get_http_response(
method="GET",
Expand Down Expand Up @@ -634,24 +599,39 @@ def _filter_campaigns(self, chain, campaigns, filtered_pools):
# type 1 and 2 stand for ERC20 and Concentrated liquidity campaigns respectively
# https://docs.merkl.xyz/integrate-merkl/integrate-merkl-to-your-app#merkl-api
if campaign_type in [1, 2]:
if campaign_apr > self.current_pool.get("apr", 0.0):
campaign_pool_address = campaign.get("mainParameter")
if not campaign_pool_address:
self.context.logger.warning(
"No pool address found for campaign"
)
continue
current_pool_address = self.current_pool.get("address")
# The pool should not be the current pool
if campaign_pool_address != current_pool_address:
filtered_pools[dex_type][chain].append(campaign)
if not campaign_apr > self.current_pool.get("apr", 0.0):
self.context.logger.info(
"APR does not exceed the current pool APR"
)
continue
campaign_pool_address = campaign.get("mainParameter")
if not campaign_pool_address:
continue
current_pool_address = self.current_pool.get("address")
# The pool should not be the current pool
if campaign_pool_address != current_pool_address:
filtered_pools[dex_type][chain].append(campaign)

def get_order_of_transactions(
self,
) -> Generator[None, None, Optional[List[Dict[str, Any]]]]:
"""Get the order of transactions to perform based on the current pool status and token balances."""
actions = []

if self._can_claim_rewards():
# check current reward
allowed_chains = self.params.allowed_chains
# we can claim all our token rewards at once
# hence we build only one action per chain
for chain in allowed_chains:
chain_id = self.params.chain_to_chain_id_mapping.get(chain)
safe_address = self.params.safe_contract_addresses.get(chain)
rewards = yield from self._get_rewards(chain_id, safe_address)
if not rewards:
continue
action = self._build_claim_reward_action(rewards, chain)
actions.append(action)

if not self.current_pool:
tokens = self._get_tokens_over_min_balance()
if not tokens or len(tokens) < 2:
Expand Down Expand Up @@ -684,7 +664,6 @@ def get_order_of_transactions(
return None
actions.append(enter_pool_action)

self.context.logger.info(f"Actions: {actions}")
return actions

def _get_tokens_over_min_balance(self) -> Optional[List[Any]]:
Expand Down Expand Up @@ -969,6 +948,19 @@ def _build_enter_pool_action(self) -> Dict[str, Any]:
"apr": self.highest_apr_pool.get("apr"),
}

def _build_claim_reward_action(
self, rewards: Dict[str, Any], chain: str
) -> Dict[str, Any]:
return {
"action": Action.CLAIM_REWARDS.value,
"chain": chain,
"users": rewards.get("users"),
"tokens": rewards.get("tokens"),
"claims": rewards.get("claims"),
"proofs": rewards.get("proofs"),
"token_symbols": rewards.get("symbols"),
}

def _get_asset_symbol(self, chain: str, address: str) -> Optional[str]:
positions = self.synchronized_data.positions
for position in positions:
Expand All @@ -979,7 +971,7 @@ def _get_asset_symbol(self, chain: str, address: str) -> Optional[str]:

return None

def get_rewards(
def _get_rewards(
self, chain_id: int, user_address: str
) -> Generator[None, None, Optional[Dict[str, Any]]]:
base_url = self.params.merkl_user_rewards_url
Expand All @@ -1002,18 +994,29 @@ def get_rewards(
self.context.logger.info(f"User rewards: {data}")
tokens = [k for k, v in data.items() if v.get("proof")]
if not tokens:
self.context.logger.warning("No tokens to claim")
self.context.logger.info("No tokens to claim!")
return None
claims = [int(data[t].get("unclaimed", 0)) for t in tokens]
symbols = [data[t].get("symbol") for t in tokens]
claims = [int(data[t].get("accumulated", 0)) for t in tokens]

# Check if all claims are zero
if all(claim == 0 for claim in claims):
self.context.logger.warning("All claims are zero, nothing to claim")
self.context.logger.info("All claims are zero, nothing to claim")
return None

unclaimed = [int(data[t].get("unclaimed", 0)) for t in tokens]
# Check if everything has been already claimed are zero
if all(claim == 0 for claim in unclaimed):
self.context.logger.info(
"All accumulated claims already made. Nothing left to claim."
)
return None

proofs = [data[t].get("proof") for t in tokens]
return {
"users": [user_address] * len(tokens),
"tokens": tokens,
"symbols": symbols,
"claims": claims,
"proofs": proofs,
}
Expand All @@ -1024,35 +1027,22 @@ def get_rewards(
)
return None

def build_claim_reward_action(
self, rewards: Dict[str, Any], chain: str
) -> Generator[None, None, Optional[Dict[str, Any]]]:
action = {}
action["action"] = Action.CLAIM_REWARDS.value
action["chain"] = chain
action["users"] = rewards.get("users")
action["tokens"] = rewards.get("tokens")
action["claims"] = rewards.get("claims")
action["proofs"] = rewards.get("proofs")

token_symbols = []
# take each token and add its symbol
for token in rewards.get("tokens"):
token_symbol = yield from self.contract_interact(
performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION,
contract_address=token,
contract_public_id=ERC20.contract_id,
contract_callable="get_token_symbol",
data_key="data",
chain_id=chain,
)
if not token_symbol:
token_symbols.append("unknown")
else:
token_symbols.append(token_symbol)
def _can_claim_rewards(self) -> bool:
# Check if rewards can be claimed. Rewards can be claimed if either:
# 1. No rewards have been claimed yet (last_reward_claimed_timestamp is None), or
# 2. The current timestamp exceeds the allowed reward claiming time period since the last claim.

action["token_symbols"] = token_symbols
return action
current_timestamp = cast(
SharedState, self.context.state
).round_sequence.last_round_transition_timestamp.timestamp()

last_claimed_timestamp = self.synchronized_data.last_reward_claimed_timestamp
if last_claimed_timestamp is None:
return True
return (
current_timestamp
>= last_claimed_timestamp + self.params.reward_claiming_time_period
)


class DecisionMakingBehaviour(LiquidityTraderBaseBehaviour):
Expand Down Expand Up @@ -1187,6 +1177,7 @@ def get_next_event(self) -> Generator[None, None, Tuple[str, Dict, Optional[Dict
# If last action was Claim Rewards and it was successful we update the list of assets and the last_reward_claimed_timestamp
if (
last_executed_action_index is not None
and last_round_id != DecisionMakingRound.auto_round_id()
and Action(actions[last_executed_action_index]["action"])
== Action.CLAIM_REWARDS
):
Expand All @@ -1196,12 +1187,16 @@ def get_next_event(self) -> Generator[None, None, Tuple[str, Dict, Optional[Dict
action.get("tokens"), action.get("token_symbols")
):
self._add_token_to_assets(chain, token, token_symbol)

current_timestamp = cast(
SharedState, self.context.state
).round_sequence.last_round_transition_timestamp.timestamp()

return Event.UPDATE.value, {"last_reward_claimed_timestamp": current_timestamp}, {}
return (
Event.UPDATE.value,
{"last_reward_claimed_timestamp": current_timestamp},
{},
)

# if all actions have been executed we exit DecisionMaking
if current_action_index >= len(self.synchronized_data.actions):
Expand Down
4 changes: 2 additions & 2 deletions packages/valory/skills/liquidity_trader_abci/skill.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license: Apache-2.0
aea_version: '>=1.0.0, <2.0.0'
fingerprint:
__init__.py: bafybeia7bn2ahqqwkf63ptje6rfnftuwrsp33sswgpcbh5osbesxxr6g4m
behaviours.py: bafybeiduwq37ba5bdtus2iwomcb2bhxerdiriuhpr2at5wzjxvqut2xjwm
behaviours.py: bafybeidczsocvdmtdhqh6jm4bdjzveuvcmxstmwwyomdrdvpels7r5qipa
dialogues.py: bafybeiay23otskx2go5xhtgdwfw2kd6rxd62sxxdu3njv7hageorl5zxzm
fsm_specification.yaml: bafybeia7dh7vuifjebf63wdqlw6gtrwcss5mapmdzhbju7i6edsw3zqxki
handlers.py: bafybeidxw2lvgiifmo4siobpwuwbxscuifrdo3gnkjyn6bgexotj5f7zf4
Expand All @@ -16,7 +16,7 @@ fingerprint:
pool_behaviour.py: bafybeiaheuesscgqzwjbpyrezgwpdbdfurlmfwbc462qv6rblwwxlx5dpm
pools/balancer.py: bafybeieo53qtt557632vtp3x3huagdpqevptextbwd7euk6hpoz6ybtuci
pools/uniswap.py: bafybeif2cjbtjh5altlgranmgrif4yaevnn344fn3askbjde5h4y4rh2mq
rounds.py: bafybeiattfoicojezsnc5pidpqkrl2ncglzhbzqufkmy37t7v2b7qta53q
rounds.py: bafybeico4zvu3fpnqbw3k2et3gzvliejjjkosmqrnbh3imblqppiui4alu
strategies/simple_strategy.py: bafybeig2iygxz5gewmiyeawubs5f4pr5e3st22lmdkxthlfq7t5kbluw4a
strategy_behaviour.py: bafybeidk6sorg47kuuubamcccksi65x3txldyo7y2hm5opbye2ghmz2ljy
fingerprint_ignore_patterns: []
Expand Down
2 changes: 1 addition & 1 deletion packages/valory/skills/optimus_abci/skill.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ skills:
- valory/registration_abci:0.1.0:bafybeicnth5q4httefsusywx3zrrq4al47owvge72dqf2fziruicq6hqta
- valory/reset_pause_abci:0.1.0:bafybeievjciqdvxhqxfjd4whqs27h6qbxqzrae7wwj7fpvxlvmtw3x35im
- valory/termination_abci:0.1.0:bafybeid54buqxipiuduw7b6nnliiwsxajnltseuroad53wukfonpxca2om
- valory/liquidity_trader_abci:0.1.0:bafybeihml6udc4leqoexdbqrjchxj4nlymqky5ejh6vlnqg7mlh64jp2zi
- valory/liquidity_trader_abci:0.1.0:bafybeia6pmuwqvpb6bdk75uywqxgr3puarikzcfkxj5xvwbyu7lxqzmkgi
- valory/transaction_settlement_abci:0.1.0:bafybeihq2yenstblmaadzcjousowj5kfn5l7ns5pxweq2gcrsczfyq5wzm
behaviours:
main:
Expand Down

0 comments on commit ee72906

Please sign in to comment.