diff --git a/app/model/db/__init__.py b/app/model/db/__init__.py index 1cad05374..fdc11c4ea 100644 --- a/app/model/db/__init__.py +++ b/app/model/db/__init__.py @@ -22,7 +22,7 @@ from .idx_agreement import AgreementStatus, IDXAgreement from .idx_block_data import IDXBlockData, IDXBlockDataBlockNumber from .idx_consume_coupon import IDXConsumeCoupon -from .idx_lock_unlock import IDXLock, IDXUnlock +from .idx_lock_unlock import IDXLock, IDXUnlock, LockDataMessage, UnlockDataMessage from .idx_order import IDXOrder from .idx_position import ( IDXLockedPosition, @@ -42,10 +42,10 @@ ) from .idx_token_list_register import IDXTokenListBlockNumber, IDXTokenListRegister from .idx_transfer import ( - DataMessage, IDXTransfer, IDXTransferBlockNumber, IDXTransferSourceEventType, + TransferDataMessage, ) from .idx_transfer_approval import IDXTransferApproval, IDXTransferApprovalBlockNumber from .idx_tx_data import IDXTxData diff --git a/app/model/db/idx_lock_unlock.py b/app/model/db/idx_lock_unlock.py index 3f303c140..62c1e15b9 100644 --- a/app/model/db/idx_lock_unlock.py +++ b/app/model/db/idx_lock_unlock.py @@ -18,8 +18,10 @@ """ from datetime import datetime, timedelta, timezone +from enum import StrEnum from zoneinfo import ZoneInfo +from pydantic import BaseModel from sqlalchemy import JSON, BigInteger, Boolean, DateTime, String from sqlalchemy.orm import Mapped, mapped_column @@ -30,6 +32,26 @@ local_tz = ZoneInfo(TZ) +class LockMessage(StrEnum): + garnishment = "garnishment" + force_lock = "force_lock" + ibet_wst_bridge = "ibet_wst_bridge" + + +class LockDataMessage(BaseModel): + message: LockMessage + + +class UnlockMessage(StrEnum): + garnishment = "garnishment" + force_unlock = "force_unlock" + ibet_wst_bridge = "ibet_wst_bridge" + + +class UnlockDataMessage(BaseModel): + message: UnlockMessage + + class IDXLock(Base): """Token Lock Event (INDEX)""" @@ -55,7 +77,7 @@ class IDXLock(Base): account_address: Mapped[str] = mapped_column(String(42), index=True, nullable=False) # Locked Amount value: Mapped[int] = mapped_column(BigInteger, index=True, nullable=False) - # Data + # Data(LockDataMessage) data: Mapped[dict] = mapped_column(JSON, nullable=False) # Lock Datetime block_timestamp: Mapped[datetime] = mapped_column( @@ -135,7 +157,7 @@ class IDXUnlock(Base): ) # Locked Amount value: Mapped[int] = mapped_column(BigInteger, index=True, nullable=False) - # Data + # Data(UnlockDataMessage) data: Mapped[dict] = mapped_column(JSON, nullable=False) # Lock Datetime block_timestamp: Mapped[datetime] = mapped_column( diff --git a/app/model/db/idx_transfer.py b/app/model/db/idx_transfer.py index a4898eac5..921b8f00b 100644 --- a/app/model/db/idx_transfer.py +++ b/app/model/db/idx_transfer.py @@ -43,10 +43,9 @@ class IDXTransferSourceEventType(StrEnum): REALLOCATION = "Reallocation" -class DataMessage(BaseModel): +class TransferDataMessage(BaseModel): message: Literal[ "garnishment", - "inheritance", "force_unlock", "ibet_wst_bridge", ] diff --git a/batch/indexer_Position_Bond.py b/batch/indexer_Position_Bond.py index 80592bff0..46f9828c0 100644 --- a/batch/indexer_Position_Bond.py +++ b/batch/indexer_Position_Bond.py @@ -43,6 +43,8 @@ IDXPositionBondBlockNumber, IDXUnlock, Listing, + LockDataMessage, + UnlockDataMessage, ) from app.model.schema.base import TokenType from app.utils.asyncio_utils import SemaphoreTaskGroup @@ -1751,6 +1753,7 @@ def __insert_lock_idx( """ try: data = json.loads(data_str) + LockDataMessage.model_validate(data) except Exception: data = {} lock = IDXLock() @@ -1797,6 +1800,7 @@ def __insert_unlock_idx( """ try: data = json.loads(data_str) + UnlockDataMessage.model_validate(data) except: data = {} unlock = IDXUnlock() diff --git a/batch/indexer_Position_Share.py b/batch/indexer_Position_Share.py index 09a5de3c8..a011c6160 100644 --- a/batch/indexer_Position_Share.py +++ b/batch/indexer_Position_Share.py @@ -43,6 +43,8 @@ IDXPositionShareBlockNumber, IDXUnlock, Listing, + LockDataMessage, + UnlockDataMessage, ) from app.model.schema.base import TokenType from app.utils.asyncio_utils import SemaphoreTaskGroup @@ -1751,6 +1753,7 @@ def __insert_lock_idx( """ try: data = json.loads(data_str) + LockDataMessage.model_validate(data) except Exception: data = {} lock = IDXLock() @@ -1797,6 +1800,7 @@ def __insert_unlock_idx( """ try: data = json.loads(data_str) + UnlockDataMessage.model_validate(data) except: data = {} unlock = IDXUnlock() diff --git a/batch/indexer_Transfer.py b/batch/indexer_Transfer.py index 70e711f1b..445d0e49f 100644 --- a/batch/indexer_Transfer.py +++ b/batch/indexer_Transfer.py @@ -37,11 +37,11 @@ from app.database import BatchAsyncSessionLocal from app.errors import ServiceUnavailable from app.model.db import ( - DataMessage, IDXTransfer, IDXTransferBlockNumber, IDXTransferSourceEventType, Listing, + TransferDataMessage, ) from app.model.schema.base import TokenType from app.utils.web3_utils import AsyncWeb3Wrapper @@ -183,7 +183,7 @@ def __insert_idx( if data_str is not None: try: data = json.loads(data_str) - validated_data = DataMessage(**data) + validated_data = TransferDataMessage(**data) message = validated_data.message except ValidationError: data = {} diff --git a/migrations/versions/819325835c3d_v25_9_0_feature_1657.py b/migrations/versions/819325835c3d_v25_9_0_feature_1657.py new file mode 100644 index 000000000..463cbccf7 --- /dev/null +++ b/migrations/versions/819325835c3d_v25_9_0_feature_1657.py @@ -0,0 +1,47 @@ +"""v25_9_0_feature_1657 + +Revision ID: 819325835c3d +Revises: 9a28ed8d4afd +Create Date: 2025-07-23 18:08:21.277260 + +""" + +from alembic import op +import sqlalchemy as sa +from sqlalchemy import update, cast, String + + +from app.database import get_db_schema +from app.model.db import IDXTransfer, IDXLock, IDXUnlock + +# revision identifiers, used by Alembic. +revision = "819325835c3d" +down_revision = "9a28ed8d4afd" +branch_labels = None +depends_on = None + + +def upgrade(): + connection = op.get_bind() + + op.get_bind().execute( + update(IDXTransfer) + .values(message=None, data={}) + .where(IDXTransfer.message == "inheritance") + ) + op.get_bind().execute( + update(IDXLock) + .values(data={}) + .where(cast(IDXLock.data, String).like(f"%inheritance%")) + ) + op.get_bind().execute( + update(IDXUnlock) + .values(data={}) + .where(cast(IDXUnlock.data, String).like(f"%inheritance%")) + ) + + +def downgrade(): + connection = op.get_bind() + + pass diff --git a/tests/batch/indexer_Position_Bond_test.py b/tests/batch/indexer_Position_Bond_test.py index afd8e891b..b7ba56312 100644 --- a/tests/batch/indexer_Position_Bond_test.py +++ b/tests/batch/indexer_Position_Bond_test.py @@ -515,10 +515,13 @@ async def test_normal_4_1(self, processor, shared_contract, session): # Lock token_contract.functions.lock( - self.trader["account_address"], 1500, '{"message": "locked1"}' + self.trader["account_address"], 1500, '{"message": "garnishment"}' ).transact({"from": self.issuer["account_address"]}) token_contract.functions.lock( - self.trader["account_address"], 1500, '{"message": "locked2"}' + self.trader["account_address"], 1500, '{"message": "ibet_wst_bridge"}' + ).transact({"from": self.issuer["account_address"]}) + token_contract.functions.lock( + self.trader["account_address"], 1500, '{"message": "inheritance"}' ).transact({"from": self.issuer["account_address"]}) # Run target process @@ -541,7 +544,7 @@ async def test_normal_4_1(self, processor, shared_contract, session): _position = _position_list[0] assert _position.token_address == token["address"] assert _position.account_address == self.issuer["account_address"] - assert _position.balance == 1000000 - 3000 + assert _position.balance == 1000000 - 4500 assert _position.pending_transfer == 0 assert _position.exchange_balance == 0 assert _position.exchange_commitment == 0 @@ -554,12 +557,12 @@ async def test_normal_4_1(self, processor, shared_contract, session): assert _locked1.token_address == token["address"] assert _locked1.lock_address == self.trader["account_address"] assert _locked1.account_address == self.issuer["account_address"] - assert _locked1.value == 3000 + assert _locked1.value == 4500 _lock_list: Sequence[IDXLock] = session.scalars( select(IDXLock).order_by(IDXLock.id) ).all() - assert len(_lock_list) == 2 + assert len(_lock_list) == 3 _lock1 = _lock_list[0] assert _lock1.id == 1 assert _lock1.token_address == token["address"] @@ -567,7 +570,7 @@ async def test_normal_4_1(self, processor, shared_contract, session): assert _lock1.lock_address == self.trader["account_address"] assert _lock1.account_address == self.issuer["account_address"] assert _lock1.value == 1500 - assert _lock1.data == {"message": "locked1"} + assert _lock1.data == {"message": "garnishment"} assert _lock1.is_forced is False _lock2 = _lock_list[1] assert _lock2.id == 2 @@ -576,8 +579,17 @@ async def test_normal_4_1(self, processor, shared_contract, session): assert _lock2.lock_address == self.trader["account_address"] assert _lock2.account_address == self.issuer["account_address"] assert _lock2.value == 1500 - assert _lock2.data == {"message": "locked2"} + assert _lock2.data == {"message": "ibet_wst_bridge"} assert _lock2.is_forced is False + _lock3 = _lock_list[2] + assert _lock3.id == 3 + assert _lock3.token_address == token["address"] + assert _lock3.msg_sender == self.issuer["account_address"] + assert _lock3.lock_address == self.trader["account_address"] + assert _lock3.account_address == self.issuer["account_address"] + assert _lock3.value == 1500 + assert _lock3.data == {} + assert _lock3.is_forced is False # # Single Token @@ -611,13 +623,13 @@ async def test_normal_4_2(self, processor, shared_contract, session): self.issuer["account_address"], self.trader["account_address"], 1500, - '{"message": "force_locked1"}', + '{"message": "force_lock"}', ).transact({"from": self.issuer["account_address"]}) token_contract.functions.forceLock( self.issuer["account_address"], self.trader["account_address"], 1500, - '{"message": "force_locked2"}', + '{"message": "force_lock"}', ).transact({"from": self.issuer["account_address"]}) # Run target process @@ -666,7 +678,7 @@ async def test_normal_4_2(self, processor, shared_contract, session): assert _lock1.lock_address == self.issuer["account_address"] assert _lock1.account_address == self.trader["account_address"] assert _lock1.value == 1500 - assert _lock1.data == {"message": "force_locked1"} + assert _lock1.data == {"message": "force_lock"} assert _lock1.is_forced is True _lock2 = _lock_list[1] assert _lock2.id == 2 @@ -675,7 +687,7 @@ async def test_normal_4_2(self, processor, shared_contract, session): assert _lock2.lock_address == self.issuer["account_address"] assert _lock2.account_address == self.trader["account_address"] assert _lock2.value == 1500 - assert _lock2.data == {"message": "force_locked2"} + assert _lock2.data == {"message": "force_lock"} assert _lock2.is_forced is True # @@ -698,7 +710,7 @@ async def test_normal_5_1(self, processor, shared_contract, session): # Lock token_contract.functions.lock( - self.trader["account_address"], 3000, '{"message": "locked1"}' + self.trader["account_address"], 3000, '{"message": "garnishment"}' ).transact({"from": self.issuer["account_address"]}) # Unlock @@ -706,7 +718,7 @@ async def test_normal_5_1(self, processor, shared_contract, session): self.issuer["account_address"], self.trader2["account_address"], 100, - '{"message": "unlocked1"}', + '{"message": "garnishment"}', ).transact({"from": self.trader["account_address"]}) # Run target process @@ -781,7 +793,7 @@ async def test_normal_5_1(self, processor, shared_contract, session): assert _lock1.lock_address == self.trader["account_address"] assert _lock1.account_address == self.issuer["account_address"] assert _lock1.value == 3000 - assert _lock1.data == {"message": "locked1"} + assert _lock1.data == {"message": "garnishment"} _unlock_list: Sequence[IDXUnlock] = session.scalars( select(IDXUnlock).order_by(IDXUnlock.id) @@ -795,7 +807,7 @@ async def test_normal_5_1(self, processor, shared_contract, session): assert _unlock1.account_address == self.issuer["account_address"] assert _unlock1.recipient_address == self.trader2["account_address"] assert _unlock1.value == 100 - assert _unlock1.data == {"message": "unlocked1"} + assert _unlock1.data == {"message": "garnishment"} assert _unlock1.is_forced is False # @@ -818,7 +830,7 @@ async def test_normal_5_2(self, processor, shared_contract, session): # Lock token_contract.functions.lock( - self.trader["account_address"], 3000, '{"message": "locked1"}' + self.trader["account_address"], 3000, '{"message": "garnishment"}' ).transact({"from": self.issuer["account_address"]}) # ForceUnlock @@ -827,7 +839,7 @@ async def test_normal_5_2(self, processor, shared_contract, session): self.issuer["account_address"], self.trader2["account_address"], 100, - '{"message": "unlocked1"}', + '{"message": "garnishment"}', ).transact({"from": self.issuer["account_address"]}) # Run target process @@ -902,7 +914,7 @@ async def test_normal_5_2(self, processor, shared_contract, session): assert _lock1.lock_address == self.trader["account_address"] assert _lock1.account_address == self.issuer["account_address"] assert _lock1.value == 3000 - assert _lock1.data == {"message": "locked1"} + assert _lock1.data == {"message": "garnishment"} _unlock_list: Sequence[IDXUnlock] = session.scalars( select(IDXUnlock).order_by(IDXUnlock.id) @@ -916,7 +928,7 @@ async def test_normal_5_2(self, processor, shared_contract, session): assert _unlock1.account_address == self.issuer["account_address"] assert _unlock1.recipient_address == self.trader2["account_address"] assert _unlock1.value == 100 - assert _unlock1.data == {"message": "unlocked1"} + assert _unlock1.data == {"message": "garnishment"} assert _unlock1.is_forced is True # @@ -954,7 +966,7 @@ async def test_normal_5_3(self, processor, shared_contract, session): token_contract.functions.lock( self.issuer["account_address"], # lock address 3000, - '{"message": "locked1"}', + '{"message": "garnishment"}', ).transact({"from": self.trader["account_address"]}) # ForceChangeLockedAccount @@ -963,7 +975,7 @@ async def test_normal_5_3(self, processor, shared_contract, session): self.trader["account_address"], # before account address self.trader2["account_address"], # after account address 100, - '{"message": "force_changed"}', + '{"message": "ibet_wst_bridge"}', ).transact({"from": self.issuer["account_address"]}) # Run target process @@ -1026,7 +1038,7 @@ async def test_normal_5_3(self, processor, shared_contract, session): assert _lock1.lock_address == self.issuer["account_address"] assert _lock1.account_address == self.trader["account_address"] assert _lock1.value == 3000 - assert _lock1.data == {"message": "locked1"} + assert _lock1.data == {"message": "garnishment"} _lock2 = _lock_list[1] assert _lock2.id == 2 assert _lock2.token_address == token["address"] @@ -1034,7 +1046,7 @@ async def test_normal_5_3(self, processor, shared_contract, session): assert _lock2.lock_address == self.issuer["account_address"] assert _lock2.account_address == self.trader2["account_address"] assert _lock2.value == 100 - assert _lock2.data == {"message": "force_changed"} + assert _lock2.data == {"message": "ibet_wst_bridge"} _unlock_list: Sequence[IDXUnlock] = session.scalars( select(IDXUnlock).order_by(IDXUnlock.id) @@ -1048,7 +1060,7 @@ async def test_normal_5_3(self, processor, shared_contract, session): assert _unlock1.account_address == self.trader["account_address"] assert _unlock1.recipient_address == self.trader2["account_address"] assert _unlock1.value == 100 - assert _unlock1.data == {"message": "force_changed"} + assert _unlock1.data == {"message": "ibet_wst_bridge"} assert _unlock1.is_forced is True # diff --git a/tests/batch/indexer_Position_Share_test.py b/tests/batch/indexer_Position_Share_test.py index 0f3d62fd0..f18d0df4e 100644 --- a/tests/batch/indexer_Position_Share_test.py +++ b/tests/batch/indexer_Position_Share_test.py @@ -497,10 +497,13 @@ async def test_normal_4_1(self, processor, shared_contract, session): # Lock token_contract.functions.lock( - self.trader["account_address"], 1500, '{"message": "locked1"}' + self.trader["account_address"], 1500, '{"message": "garnishment"}' ).transact({"from": self.issuer["account_address"]}) token_contract.functions.lock( - self.trader["account_address"], 1500, '{"message": "locked2"}' + self.trader["account_address"], 1500, '{"message": "ibet_wst_bridge"}' + ).transact({"from": self.issuer["account_address"]}) + token_contract.functions.lock( + self.trader["account_address"], 1500, '{"message": "inheritance"}' ).transact({"from": self.issuer["account_address"]}) # Run target process @@ -523,7 +526,7 @@ async def test_normal_4_1(self, processor, shared_contract, session): _position = _position_list[0] assert _position.token_address == token["address"] assert _position.account_address == self.issuer["account_address"] - assert _position.balance == 1000000 - 3000 + assert _position.balance == 1000000 - 4500 assert _position.pending_transfer == 0 assert _position.exchange_balance == 0 assert _position.exchange_commitment == 0 @@ -537,10 +540,10 @@ async def test_normal_4_1(self, processor, shared_contract, session): assert _locked1.token_address == token["address"] assert _locked1.lock_address == self.trader["account_address"] assert _locked1.account_address == self.issuer["account_address"] - assert _locked1.value == 3000 + assert _locked1.value == 4500 _lock_list = session.scalars(select(IDXLock).order_by(IDXLock.id)).all() - assert len(_lock_list) == 2 + assert len(_lock_list) == 3 _lock1 = _lock_list[0] assert _lock1.id == 1 @@ -548,7 +551,7 @@ async def test_normal_4_1(self, processor, shared_contract, session): assert _lock1.lock_address == self.trader["account_address"] assert _lock1.account_address == self.issuer["account_address"] assert _lock1.value == 1500 - assert _lock1.data == {"message": "locked1"} + assert _lock1.data == {"message": "garnishment"} assert _lock1.is_forced is False _lock2 = _lock_list[1] assert _lock2.id == 2 @@ -556,8 +559,16 @@ async def test_normal_4_1(self, processor, shared_contract, session): assert _lock2.lock_address == self.trader["account_address"] assert _lock2.account_address == self.issuer["account_address"] assert _lock2.value == 1500 - assert _lock2.data == {"message": "locked2"} + assert _lock2.data == {"message": "ibet_wst_bridge"} assert _lock2.is_forced is False + _lock3 = _lock_list[2] + assert _lock3.id == 3 + assert _lock3.token_address == token["address"] + assert _lock3.lock_address == self.trader["account_address"] + assert _lock3.account_address == self.issuer["account_address"] + assert _lock3.value == 1500 + assert _lock3.data == {} + assert _lock3.is_forced is False # # Single Token @@ -591,13 +602,13 @@ async def test_normal_4_2(self, processor, shared_contract, session): self.issuer["account_address"], self.trader["account_address"], 1500, - '{"message": "force_locked1"}', + '{"message": "force_lock"}', ).transact({"from": self.issuer["account_address"]}) token_contract.functions.forceLock( self.issuer["account_address"], self.trader["account_address"], 1500, - '{"message": "force_locked2"}', + '{"message": "force_lock"}', ).transact({"from": self.issuer["account_address"]}) # Run target process @@ -646,7 +657,7 @@ async def test_normal_4_2(self, processor, shared_contract, session): assert _lock1.lock_address == self.issuer["account_address"] assert _lock1.account_address == self.trader["account_address"] assert _lock1.value == 1500 - assert _lock1.data == {"message": "force_locked1"} + assert _lock1.data == {"message": "force_lock"} assert _lock1.is_forced is True _lock2 = _lock_list[1] assert _lock2.id == 2 @@ -655,7 +666,7 @@ async def test_normal_4_2(self, processor, shared_contract, session): assert _lock2.lock_address == self.issuer["account_address"] assert _lock2.account_address == self.trader["account_address"] assert _lock2.value == 1500 - assert _lock2.data == {"message": "force_locked2"} + assert _lock2.data == {"message": "force_lock"} assert _lock2.is_forced is True # @@ -678,7 +689,7 @@ async def test_normal_5_1(self, processor, shared_contract, session): # Lock token_contract.functions.lock( - self.trader["account_address"], 3000, '{"message": "locked1"}' + self.trader["account_address"], 3000, '{"message": "garnishment"}' ).transact({"from": self.issuer["account_address"]}) # Unlock @@ -686,7 +697,7 @@ async def test_normal_5_1(self, processor, shared_contract, session): self.issuer["account_address"], self.trader2["account_address"], 100, - '{"message": "unlocked1"}', + '{"message": "garnishment"}', ).transact({"from": self.trader["account_address"]}) # Run target process @@ -759,7 +770,7 @@ async def test_normal_5_1(self, processor, shared_contract, session): assert _lock1.lock_address == self.trader["account_address"] assert _lock1.account_address == self.issuer["account_address"] assert _lock1.value == 3000 - assert _lock1.data == {"message": "locked1"} + assert _lock1.data == {"message": "garnishment"} _unlock_list = session.scalars(select(IDXUnlock).order_by(IDXUnlock.id)).all() assert len(_unlock_list) == 1 @@ -771,7 +782,7 @@ async def test_normal_5_1(self, processor, shared_contract, session): assert _unlock1.account_address == self.issuer["account_address"] assert _unlock1.recipient_address == self.trader2["account_address"] assert _unlock1.value == 100 - assert _unlock1.data == {"message": "unlocked1"} + assert _unlock1.data == {"message": "garnishment"} assert _unlock1.is_forced is False # @@ -794,7 +805,7 @@ async def test_normal_5_2(self, processor, shared_contract, session): # Lock token_contract.functions.lock( - self.trader["account_address"], 3000, '{"message": "locked1"}' + self.trader["account_address"], 3000, '{"message": "garnishment"}' ).transact({"from": self.issuer["account_address"]}) # Unlock @@ -803,7 +814,7 @@ async def test_normal_5_2(self, processor, shared_contract, session): self.issuer["account_address"], self.trader2["account_address"], 100, - '{"message": "unlocked1"}', + '{"message": "garnishment"}', ).transact({"from": self.issuer["account_address"]}) # Run target process @@ -876,7 +887,7 @@ async def test_normal_5_2(self, processor, shared_contract, session): assert _lock1.lock_address == self.trader["account_address"] assert _lock1.account_address == self.issuer["account_address"] assert _lock1.value == 3000 - assert _lock1.data == {"message": "locked1"} + assert _lock1.data == {"message": "garnishment"} _unlock_list = session.scalars(select(IDXUnlock).order_by(IDXUnlock.id)).all() assert len(_unlock_list) == 1 @@ -888,7 +899,7 @@ async def test_normal_5_2(self, processor, shared_contract, session): assert _unlock1.account_address == self.issuer["account_address"] assert _unlock1.recipient_address == self.trader2["account_address"] assert _unlock1.value == 100 - assert _unlock1.data == {"message": "unlocked1"} + assert _unlock1.data == {"message": "garnishment"} assert _unlock1.is_forced is True # @@ -925,7 +936,7 @@ async def test_normal_5_3(self, processor, shared_contract, session): token_contract.functions.lock( self.issuer["account_address"], # lock address 3000, - '{"message": "locked1"}', + '{"message": "garnishment"}', ).transact({"from": self.trader["account_address"]}) # ForceChangeLockedAccount @@ -934,7 +945,7 @@ async def test_normal_5_3(self, processor, shared_contract, session): self.trader["account_address"], # before account address self.trader2["account_address"], # after account address 100, - '{"message": "force_changed"}', + '{"message": "ibet_wst_bridge"}', ).transact({"from": self.issuer["account_address"]}) # Run target process @@ -995,7 +1006,7 @@ async def test_normal_5_3(self, processor, shared_contract, session): assert _lock1.lock_address == self.issuer["account_address"] assert _lock1.account_address == self.trader["account_address"] assert _lock1.value == 3000 - assert _lock1.data == {"message": "locked1"} + assert _lock1.data == {"message": "garnishment"} _lock2 = _lock_list[1] assert _lock2.id == 2 assert _lock2.token_address == token["address"] @@ -1003,7 +1014,7 @@ async def test_normal_5_3(self, processor, shared_contract, session): assert _lock2.lock_address == self.issuer["account_address"] assert _lock2.account_address == self.trader2["account_address"] assert _lock2.value == 100 - assert _lock2.data == {"message": "force_changed"} + assert _lock2.data == {"message": "ibet_wst_bridge"} _unlock_list = session.scalars(select(IDXUnlock).order_by(IDXUnlock.id)).all() assert len(_unlock_list) == 1 @@ -1015,7 +1026,7 @@ async def test_normal_5_3(self, processor, shared_contract, session): assert _unlock1.account_address == self.trader["account_address"] assert _unlock1.recipient_address == self.trader2["account_address"] assert _unlock1.value == 100 - assert _unlock1.data == {"message": "force_changed"} + assert _unlock1.data == {"message": "ibet_wst_bridge"} assert _unlock1.is_forced is True # diff --git a/tests/batch/indexer_Transfer_test.py b/tests/batch/indexer_Transfer_test.py index c6209ab49..ec286e0d1 100644 --- a/tests/batch/indexer_Transfer_test.py +++ b/tests/batch/indexer_Transfer_test.py @@ -668,8 +668,8 @@ async def test_normal_2(self, processor, shared_contract, async_session): assert idx_transfer.to_address == self.trader2["account_address"] assert idx_transfer.value == 30000 assert idx_transfer.source_event == IDXTransferSourceEventType.UNLOCK - assert idx_transfer.data == {"message": "inheritance"} - assert idx_transfer.message == "inheritance" + assert idx_transfer.data == {} + assert idx_transfer.message is None assert idx_transfer.created is not None assert idx_transfer.modified is not None @@ -682,8 +682,8 @@ async def test_normal_2(self, processor, shared_contract, async_session): assert idx_transfer.to_address == self.trader2["account_address"] assert idx_transfer.value == 30000 assert idx_transfer.source_event == IDXTransferSourceEventType.UNLOCK - assert idx_transfer.data == {"message": "inheritance"} - assert idx_transfer.message == "inheritance" + assert idx_transfer.data == {} + assert idx_transfer.message is None assert idx_transfer.created is not None assert idx_transfer.modified is not None diff --git a/tests/migrations/upgrade_test.py b/tests/migrations/upgrade_test.py index 2e42c9308..7ad05475d 100644 --- a/tests/migrations/upgrade_test.py +++ b/tests/migrations/upgrade_test.py @@ -18,6 +18,7 @@ """ import importlib +import json import logging from datetime import datetime from typing import Final @@ -39,6 +40,7 @@ REVISION_23_12: Final = "f6f13d28bb48" REVISION_24_3: Final = "3d3b90fda898" REVISION_24_6: Final = "418af51b07b5" +REVISION_25_6: Final = "9a28ed8d4afd" REVISION_UP_TO_1_8 = [REVISION_22_3] REVISION_UP_TO_22_6 = REVISION_UP_TO_1_8 + [REVISION_22_6] @@ -925,3 +927,98 @@ def test_upgrade_v24_6( else: assert share_tokens[0].require_personal_info_registered is True assert share_tokens[1].require_personal_info_registered is True + + def test_upgrade_v25_6( + self, alembic_runner: MigrationContext, caplog: LogCaptureFixture + ): + # 1. Migrate to v25.6 initial + alembic_runner.migrate_up_to(REVISION_25_6) + meta = MetaData() + meta.reflect(bind=engine) + + # 2. Insert test record + idx_transfer = meta.tables.get("transfer") + stmt1 = insert(idx_transfer).values( + id=1, + transaction_hash="test1", + token_address="test1", + from_address="test1", + to_address="test1", + value=1, + source_event="Unlock", + data={"message": "inheritance"}, + message="inheritance", + ) + + idx_lock = meta.tables.get("lock") + stmt2 = insert(idx_lock).values( + id=1, + transaction_hash="test1", + msg_sender="test1", + block_number=1, + token_address="test1", + lock_address="test1", + account_address="test1", + value=1, + data={"message": "inheritance"}, + block_timestamp=datetime(2025, 7, 23, 0, 0, 0), + is_forced=False, + ) + + idx_unlock = meta.tables.get("unlock") + stmt3 = insert(idx_unlock).values( + id=1, + transaction_hash="test1", + msg_sender="test1", + block_number=1, + token_address="test1", + lock_address="test1", + account_address="test1", + recipient_address="test1", + value=1, + data={"message": "inheritance"}, + block_timestamp=datetime(2025, 7, 23, 0, 0, 0), + is_forced=False, + ) + + with engine.connect() as conn: + conn.execute(stmt1) + conn.execute(stmt2) + conn.execute(stmt3) + conn.commit() + + # 3. Run to head + alembic_runner.migrate_up_to("head") + + with engine.connect() as conn: + transfers = conn.execute( + text("SELECT * FROM transfer ORDER BY created ASC") + ) + transfers = list(transfers) + if engine.name == "mysql": + assert json.loads(transfers[0].data) == {} + else: + assert transfers[0].data == {} + assert transfers[0].message is None + + if engine.name == "mysql": + locks = conn.execute(text("SELECT * FROM `lock` ORDER BY created ASC")) + locks = list(locks) + assert json.loads(locks[0].data) == {} + else: + locks = conn.execute(text("SELECT * FROM lock ORDER BY created ASC")) + locks = list(locks) + assert locks[0].data == {} + + if engine.name == "mysql": + unlocks = conn.execute( + text("SELECT * FROM `unlock` ORDER BY created ASC") + ) + unlocks = list(unlocks) + assert json.loads(unlocks[0].data) == {} + else: + unlocks = conn.execute( + text("SELECT * FROM unlock ORDER BY created ASC") + ) + unlocks = list(unlocks) + assert unlocks[0].data == {}