Skip to content

Commit

Permalink
Avoid Transaction save without WorldBossReward model
Browse files Browse the repository at this point in the history
  • Loading branch information
ipdae committed Sep 24, 2024
1 parent 224ae37 commit 5517ed7
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 22 deletions.
56 changes: 56 additions & 0 deletions tests/raid_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from world_boss.app.kms import signer
from world_boss.app.models import Transaction, WorldBossReward, WorldBossRewardAmount
from world_boss.app.raid import (
bulk_insert_transactions,
create_unsigned_tx,
get_assets,
get_latest_raid_id,
Expand Down Expand Up @@ -387,3 +388,58 @@ def test_get_next_month_last_day():
with patch("datetime.date") as m:
m.today.return_value = date(2024, 9, 19)
assert get_next_month_last_day() == datetime(2024, 10, 31, tzinfo=timezone.utc)


def test_bulk_insert_transactions(fx_session):
content = """3,25,0x01069aaf336e6aEE605a8A54D0734b43B62f8Fe4,5b65f5D0e23383FA18d74A62FbEa383c7D11F29d,150000,CRYSTAL,18,175
3,25,0x01069aaf336e6aEE605a8A54D0734b43B62f8Fe4,5b65f5D0e23383FA18d74A62FbEa383c7D11F29d,560,RUNESTONE_FENRIR1,0,175
3,25,0x01069aaf336e6aEE605a8A54D0734b43B62f8Fe4,5b65f5D0e23383FA18d74A62FbEa383c7D11F29d,150,RUNESTONE_FENRIR2,0,175
3,25,0x01069aaf336e6aEE605a8A54D0734b43B62f8Fe4,5b65f5D0e23383FA18d74A62FbEa383c7D11F29d,40,RUNESTONE_FENRIR3,0,175
3,26,5b65f5D0e23383FA18d74A62FbEa383c7D11F29d,0x01069aaf336e6aEE605a8A54D0734b43B62f8Fe4,560,RUNESTONE_FENRIR1,0,175"""
rows = [r.split(",") for r in content.split("\n")]
nonce_rows_map = {175: rows}
bulk_insert_transactions(
rows,
nonce_rows_map,
datetime(2024, 9, 24, tzinfo=timezone.utc),
fx_session,
signer,
"memo",
)

assert len(fx_session.query(Transaction).first().amounts) == 5

world_boss_rewards = fx_session.query(WorldBossReward)
for i, world_boss_reward in enumerate(world_boss_rewards):
agent_address = "0x01069aaf336e6aEE605a8A54D0734b43B62f8Fe4"
avatar_address = "5b65f5D0e23383FA18d74A62FbEa383c7D11F29d"
ranking = 25
amounts = [
("CRYSTAL", 150000, 18),
("RUNESTONE_FENRIR1", 560, 0),
("RUNESTONE_FENRIR2", 150, 0),
("RUNESTONE_FENRIR3", 40, 0),
]
if i == 1:
agent_address = "5b65f5D0e23383FA18d74A62FbEa383c7D11F29d"
avatar_address = "0x01069aaf336e6aEE605a8A54D0734b43B62f8Fe4"
ranking = 26
amounts = [
("RUNESTONE_FENRIR1", 560, 0),
]

assert world_boss_reward.raid_id == 3
assert world_boss_reward.ranking == ranking
assert world_boss_reward.agent_address == agent_address
assert world_boss_reward.avatar_address == avatar_address

assert len(world_boss_reward.amounts) == len(amounts)

for ticker, amount, decimal_places in amounts:
world_boss_reward_amount = (
fx_session.query(WorldBossRewardAmount)
.filter_by(reward_id=world_boss_reward.id, ticker=ticker)
.one()
)
assert world_boss_reward_amount.decimal_places == decimal_places
assert world_boss_reward_amount.amount == amount
13 changes: 0 additions & 13 deletions tests/tasks_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
RankingRewardWithAgentDictionary,
)
from world_boss.app.tasks import (
check_season,
check_signer_balance,
count_users,
get_ranking_rewards,
Expand Down Expand Up @@ -371,18 +370,6 @@ def test_stage_transactions_with_countdown(
)


def test_check_season(redisdb, celery_session_worker, fx_session, httpx_mock):
raid_id = 1
network_type = NetworkType.MAIN
offset = 0
check_season.delay().get(timeout=10)
httpx_mock.add_response(
method="POST",
url=config.data_provider_url,
json={"data": {"worldBossTotalUsers": 20000}},
)


@pytest.mark.parametrize("exist", [True, False])
def test_save_ranking_rewards(
redisdb,
Expand Down
14 changes: 14 additions & 0 deletions world_boss/app/kms.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,20 @@ def _save_transaction(
db.commit()
return transaction

def sign(self, unsigned_transaction: bytes, nonce: int) -> bytes:
account = ethereum_kms_signer.kms.BasicKmsAccount(self._key_id, self.address)
msg_hash = hashlib.sha256(unsigned_transaction).digest()
_, r, s = account.sign_msg_hash(msg_hash).vrs

n = int.from_bytes(
base64.b64decode("/////////////////////rqu3OavSKA7v9JejNA2QUE="), "big"
)

seq = SequenceOf(componentType=Integer())
seq.extend([r, min(s, n - s)])
signature = der_encode(seq)
return self._sign_transaction(unsigned_transaction, signature)

def transfer_assets(
self,
time_stamp: datetime.datetime,
Expand Down
88 changes: 87 additions & 1 deletion world_boss/app/raid.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import calendar
import csv
import datetime
import hashlib
import json
import typing
from typing import List, Tuple, cast
Expand All @@ -10,7 +11,7 @@
import jwt
from fastapi import HTTPException
from fastapi.encoders import jsonable_encoder
from sqlalchemy import func
from sqlalchemy import func, insert
from sqlalchemy.orm import Session
from starlette.responses import Response

Expand Down Expand Up @@ -389,3 +390,88 @@ def get_next_month_last_day() -> datetime.datetime:
next_month_year, next_month, last_day, tzinfo=datetime.timezone.utc
)
return last_date


def bulk_insert_transactions(
rows: List[RecipientRow],
nonce_rows_map: dict[int, List[RecipientRow]],
time_stamp: datetime.datetime,
db: Session,
signer,
memo: typing.Optional[str] = None,
):
# ranking : world_boss_reward
world_boss_rewards: dict[int, dict] = {}
signer_address = signer.address
tx_values: List[dict] = []
tx_ids: dict[int, str] = {}
for n in nonce_rows_map.keys():
recipient_rows = nonce_rows_map[n]
recipients = [row_to_recipient(r) for r in recipient_rows]
pv = get_transfer_assets_plain_value(signer_address, recipients, memo)
unsigned_transaction = create_unsigned_tx(
config.planet_id, signer.public_key, signer_address, n, pv, time_stamp
)
signed_transaction = signer.sign(unsigned_transaction, n)
tx_id = hashlib.sha256(signed_transaction).hexdigest()
tx_values.append(
{
"tx_id": tx_id,
"nonce": n,
"signer": signer_address,
"payload": signed_transaction.hex(),
"tx_result": "CREATED",
}
)
tx_ids[n] = tx_id
db.execute(insert(Transaction), tx_values)
raid_id = int(rows[0][0])
exist_rankings = [
r for r, in db.query(WorldBossReward.ranking).filter_by(raid_id=raid_id)
]
world_boss_reward_amounts: dict[int, list[dict]] = {}
# raid_id,ranking,agent_address,avatar_address,amount,ticker,decimal_places,target_nonce
for row in rows:
# parse row
ranking = int(row[1])
agent_address = row[2]
avatar_address = row[3]
amount = int(row[4])
ticker = row[5]
decimal_places = int(row[6])
nonce = int(row[7])

# get or create world_boss_reward
if ranking not in exist_rankings and not world_boss_rewards.get(ranking):
world_boss_reward = {
"raid_id": raid_id,
"ranking": ranking,
"agent_address": agent_address,
"avatar_address": avatar_address,
}
world_boss_rewards[ranking] = world_boss_reward

# create world_boss_reward_amount
world_boss_reward_amount = {
"amount": amount,
"decimal_places": decimal_places,
"ticker": ticker,
"tx_id": tx_ids[nonce],
}
if not world_boss_reward_amounts.get(ranking):
world_boss_reward_amounts[ranking] = []
world_boss_reward_amounts[ranking].append(world_boss_reward_amount)
if world_boss_rewards:
db.execute(insert(WorldBossReward), world_boss_rewards.values())
result = db.query(WorldBossReward).filter_by(raid_id=raid_id)
values = []
for reward in result:
exist_tickers = [i.ticker for i in reward.amounts]
if world_boss_rewards.get(reward.ranking):
for amounts in world_boss_reward_amounts[reward.ranking]:
if amounts["ticker"] not in exist_tickers:
amounts["reward_id"] = reward.id
values.append(amounts)
if values:
db.execute(insert(WorldBossRewardAmount), values)
db.commit()
10 changes: 2 additions & 8 deletions world_boss/app/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
from world_boss.app.kms import signer
from world_boss.app.models import Transaction, WorldBossReward, WorldBossRewardAmount
from world_boss.app.raid import (
bulk_insert_transactions,
get_assets,
get_latest_raid_id,
get_next_month_last_day,
get_next_tx_nonce,
get_reward_count,
get_tx_delay_factor,
row_to_recipient,
update_agent_address,
write_ranking_rewards_csv,
write_tx_result_csv,
Expand Down Expand Up @@ -262,7 +262,6 @@ def save_ranking_rewards(raid_id: int, size: int, offset: int, signer_address: s
results: List[RankingRewardWithAgentDictionary] = []
payload_size = size
time_stamp = get_next_month_last_day()
signed_transactions: List[Transaction] = []
memo = "world boss ranking rewards by world boss signer"
with TaskSessionLocal() as db:
start_nonce = get_next_tx_nonce(db)
Expand Down Expand Up @@ -300,12 +299,7 @@ def save_ranking_rewards(raid_id: int, size: int, offset: int, signer_address: s
rows.append(row)
nonce_rows_map[nonce].append(row)
i += 1
for n in nonce_rows_map.keys():
recipient_rows = nonce_rows_map[n]
recipients = [row_to_recipient(r) for r in recipient_rows]
tx = signer.transfer_assets(time_stamp, n, recipients, memo, db)
signed_transactions.append(tx)
insert_world_boss_rewards(rows, signer_address)
bulk_insert_transactions(rows, nonce_rows_map, time_stamp, db, memo)


@celery.task()
Expand Down

0 comments on commit 5517ed7

Please sign in to comment.