Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Excluding former holders in holders endpoint #349

Merged
merged 3 commits into from
Jul 6, 2022
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
10 changes: 9 additions & 1 deletion app/routers/position.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
Query
)
from fastapi.exceptions import HTTPException
from sqlalchemy import or_
from sqlalchemy.orm import Session

from app.database import db_session
Expand Down Expand Up @@ -77,6 +78,12 @@ def list_all_position(
join(Token, IDXPosition.token_address == Token.token_address). \
filter(IDXPosition.account_address == account_address). \
filter(Token.token_status != 2). \
filter(or_(
IDXPosition.balance != 0,
IDXPosition.exchange_balance != 0,
IDXPosition.pending_transfer != 0,
IDXPosition.exchange_commitment != 0
)). \
order_by(IDXPosition.token_address, IDXPosition.account_address)
if issuer_address is not None:
query = query.filter(Token.issuer_address == issuer_address)
Expand Down Expand Up @@ -163,7 +170,8 @@ def retrieve_position(
filter(IDXPosition.account_address == account_address). \
first()
if _position is None:
raise HTTPException(status_code=404, detail="position not found")
# If there is no position, set default value(0) to each balance.
_position = IDXPosition(balance=0, exchange_balance=0, exchange_commitment=0, pending_transfer=0)
Comment on lines +173 to +174
Copy link
Member Author

@purplesmoke05 purplesmoke05 Jul 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no records found, this will return 200.


# Get Token Name
token_name = None
Expand Down
116 changes: 114 additions & 2 deletions tests/test_app_routers_positions_{account_address}_GET.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ def test_normal_2(self, mock_IbetStraightBondContract_get, client, db):
]
}

# <Normal_3>
# <Normal_3_1>
# multi record
@mock.patch("app.model.blockchain.token.IbetShareContract.get")
@mock.patch("app.model.blockchain.token.IbetStraightBondContract.get")
def test_normal_3(self, mock_IbetStraightBondContract_get, mock_IbetShareContract_get, client, db):
def test_normal_3_1(self, mock_IbetStraightBondContract_get, mock_IbetShareContract_get, client, db):
account_address = "0x1234567890123456789012345678900000000000"

# prepare data: Token
Expand Down Expand Up @@ -258,6 +258,118 @@ def test_normal_3(self, mock_IbetStraightBondContract_get, mock_IbetShareContrac
]
}

# <Normal_3_2>
# multi record (Including former holder)
@mock.patch("app.model.blockchain.token.IbetShareContract.get")
@mock.patch("app.model.blockchain.token.IbetStraightBondContract.get")
def test_normal_3_2(self, mock_IbetStraightBondContract_get, mock_IbetShareContract_get, client, db):
account_address = "0x1234567890123456789012345678900000000000"

# prepare data: Token
_token = Token()
_token.token_address = "0x1234567890123456789012345678900000000010"
_token.issuer_address = "0x1234567890123456789012345678900000000100"
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
db.add(_token)

# prepare data: Position
_position = IDXPosition()
_position.token_address = "0x1234567890123456789012345678900000000010"
_position.account_address = account_address
_position.balance = 10
_position.exchange_balance = 11
_position.exchange_commitment = 12
_position.pending_transfer = 13
db.add(_position)

# prepare data: Token
_token = Token()
_token.token_address = "0x1234567890123456789012345678900000000011"
_token.issuer_address = "0x1234567890123456789012345678900000000101"
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
db.add(_token)

# prepare data: Position
_position = IDXPosition()
_position.token_address = "0x1234567890123456789012345678900000000011"
_position.account_address = account_address
_position.balance = 0
_position.exchange_balance = 0
_position.exchange_commitment = 22
_position.pending_transfer = 23
db.add(_position)

# prepare data: Token
_token = Token()
_token.token_address = "0x1234567890123456789012345678900000000012"
_token.issuer_address = "0x1234567890123456789012345678900000000100"
_token.type = TokenType.IBET_SHARE.value
_token.tx_hash = ""
_token.abi = ""
db.add(_token)

# prepare data: Position
_position = IDXPosition()
_position.token_address = "0x1234567890123456789012345678900000000012"
_position.account_address = account_address
_position.balance = 0
_position.exchange_balance = 0
_position.exchange_commitment = 0
_position.pending_transfer = 0
db.add(_position)

# mock
bond_1 = IbetStraightBondContract()
bond_1.name = "test_bond_1"
bond_2 = IbetStraightBondContract()
bond_2.name = "test_bond_2"
mock_IbetStraightBondContract_get.side_effect = [bond_1, bond_2]
share_1 = IbetShareContract()
share_1.name = "test_share_1"
mock_IbetShareContract_get.side_effect = [share_1]

# request target api
resp = client.get(
self.base_url.format(account_address=account_address),
)

# assertion
assert resp.status_code == 200
assert resp.json() == {
"result_set": {
"count": 2,
"offset": None,
"limit": None,
"total": 2,
},
"positions": [
{
"issuer_address": "0x1234567890123456789012345678900000000100",
"token_address": "0x1234567890123456789012345678900000000010",
"token_type": TokenType.IBET_STRAIGHT_BOND.value,
"token_name": "test_bond_1",
"balance": 10,
"exchange_balance": 11,
"exchange_commitment": 12,
"pending_transfer": 13,
},
{
"issuer_address": "0x1234567890123456789012345678900000000101",
"token_address": "0x1234567890123456789012345678900000000011",
"token_type": TokenType.IBET_STRAIGHT_BOND.value,
"token_name": "test_bond_2",
"balance": 0,
"exchange_balance": 0,
"exchange_commitment": 22,
"pending_transfer": 23,
}
]
}

# <Normal_4>
# specify header
@mock.patch("app.model.blockchain.token.IbetShareContract.get")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ def test_normal_2(self, mock_IbetStraightBondContract_get, client, db):
_position = IDXPosition()
_position.token_address = token_address
_position.account_address = account_address
_position.balance = 10
_position.exchange_balance = 11
_position.balance = 0
_position.exchange_balance = 0
_position.exchange_commitment = 12
_position.pending_transfer = 13
db.add(_position)
Expand All @@ -185,12 +185,114 @@ def test_normal_2(self, mock_IbetStraightBondContract_get, client, db):
"token_address": token_address,
"token_type": TokenType.IBET_STRAIGHT_BOND.value,
"token_name": "test_bond_1",
"balance": 10,
"exchange_balance": 11,
"balance": 0,
"exchange_balance": 0,
"exchange_commitment": 12,
"pending_transfer": 13,
}

# <Normal_3_1>
# No Position (no record)
@mock.patch("app.model.blockchain.token.IbetStraightBondContract.get")
def test_normal_3_1(self, mock_IbetStraightBondContract_get, client, db):
account_address = "0x1234567890123456789012345678900000000000"
token_address = "0x1234567890123456789012345678900000000010"
issuer_address = "0x1234567890123456789012345678900000000100"

# prepare data: Token
_token = Token()
_token.token_address = token_address
_token.issuer_address = issuer_address
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
db.add(_token)

# prepare data: Position
_position = IDXPosition()
_position.token_address = token_address
_position.account_address = "0x1234567890123456789012345678900000000001" # not target
_position.balance = 10
_position.exchange_balance = 11
_position.exchange_commitment = 12
_position.pending_transfer = 13
db.add(_position)

# mock
bond_1 = IbetStraightBondContract()
bond_1.name = "test_bond_1"
mock_IbetStraightBondContract_get.side_effect = [bond_1]

# request target api
resp = client.get(
self.base_url.format(account_address=account_address, token_address=token_address),
headers={"issuer-address": issuer_address}
)

# assertion
assert resp.status_code == 200
assert resp.json() == {
"issuer_address": issuer_address,
"token_address": token_address,
"token_type": TokenType.IBET_STRAIGHT_BOND.value,
"token_name": "test_bond_1",
"balance": 0,
"exchange_balance": 0,
"exchange_commitment": 0,
"pending_transfer": 0,
}

# <Normal_3_2>
# No Position (record exists but have no balance)
@mock.patch("app.model.blockchain.token.IbetStraightBondContract.get")
def test_normal_3_2(self, mock_IbetStraightBondContract_get, client, db):
account_address = "0x1234567890123456789012345678900000000000"
token_address = "0x1234567890123456789012345678900000000010"
issuer_address = "0x1234567890123456789012345678900000000100"

# prepare data: Token
_token = Token()
_token.token_address = token_address
_token.issuer_address = issuer_address
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
db.add(_token)

# prepare data: Position
_position = IDXPosition()
_position.token_address = token_address
_position.account_address = account_address
_position.balance = 0
_position.exchange_balance = 0
_position.exchange_commitment = 0
_position.pending_transfer = 0
db.add(_position)

# mock
bond_1 = IbetStraightBondContract()
bond_1.name = "test_bond_1"
mock_IbetStraightBondContract_get.side_effect = [bond_1]

# request target api
resp = client.get(
self.base_url.format(account_address=account_address, token_address=token_address),
headers={"issuer-address": issuer_address}
)

# assertion
assert resp.status_code == 200
assert resp.json() == {
"issuer_address": issuer_address,
"token_address": token_address,
"token_type": TokenType.IBET_STRAIGHT_BOND.value,
"token_name": "test_bond_1",
"balance": 0,
"exchange_balance": 0,
"exchange_commitment": 0,
"pending_transfer": 0,
}

###########################################################################
# Error Case
###########################################################################
Expand Down Expand Up @@ -331,45 +433,3 @@ def test_error_3(self, client, db):
},
"detail": "wait for a while as the token is being processed"
}

# <Error_4>
# NotFound: Position
def test_error_4(self, client, db):
account_address = "0x1234567890123456789012345678900000000000"
token_address = "0x1234567890123456789012345678900000000010"
issuer_address = "0x1234567890123456789012345678900000000100"

# prepare data: Token
_token = Token()
_token.token_address = token_address
_token.issuer_address = issuer_address
_token.type = TokenType.IBET_STRAIGHT_BOND.value
_token.tx_hash = ""
_token.abi = ""
db.add(_token)

# prepare data: Position
_position = IDXPosition()
_position.token_address = token_address
_position.account_address = "0x1234567890123456789012345678900000000001" # not target
_position.balance = 10
_position.exchange_balance = 11
_position.exchange_commitment = 12
_position.pending_transfer = 13
db.add(_position)

# request target api
resp = client.get(
self.base_url.format(account_address=account_address, token_address=token_address),
headers={"issuer-address": issuer_address}
)

# assertion
assert resp.status_code == 404
assert resp.json() == {
"meta": {
"code": 1,
"title": "NotFound"
},
"detail": "position not found"
}