Skip to content
This repository was archived by the owner on Feb 18, 2026. It is now read-only.

Commit 7968d02

Browse files
committed
Add ETH bridge conversion test cases and add aiohttp
1 parent cdbc9fd commit 7968d02

5 files changed

Lines changed: 388 additions & 254 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ NUM_THREADS ?= 1
1212
# Migration test settings
1313
OLD_SERVER_PORT ?= 9001
1414
NEW_SERVER_PORT ?= 9000 # Note: adev uses OLD_SERVER_PORT+1 for aux/livereload server
15-
MIGRATION_BASE_REF ?= master
15+
MIGRATION_BASE_REF ?= develop
1616
WORKTREE_DIR ?= ../.graphsense-rest-old
1717

1818
test: install-dev

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dependencies = [
2020
"python-dateutil>=2.9.0",
2121
"redis>=7.1.0",
2222
"uvicorn[standard]>=0.32.0",
23+
"aiohttp>=3.8.0"
2324
]
2425

2526
[project.urls]
@@ -94,6 +95,10 @@ exclude = [
9495
extend-select = ["T201"]
9596

9697

98+
[tool.uv.sources]
99+
graphsense-lib = { path="../graphsense-lib"}
100+
101+
97102
[dependency-groups]
98103
dev = [
99104
"gunicorn>=23.0.0",

tests/test_fastapi_migration.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@
3737

3838
HEADERS = {"Content-Type": "application/json", "Accept": "application/json"}
3939

40+
# Headers that simulate authenticated access with private tags permission
41+
# The X-Consumer-Groups header is typically set by an API gateway
42+
AUTHENTICATED_HEADERS = {
43+
"Content-Type": "application/json",
44+
"Accept": "application/json",
45+
"X-Consumer-Groups": "tags-private", # Grants access to private tags
46+
}
47+
4048
# Test data constants
4149
BTC_ADDRESS = "1Archive1n2C579dMsAu3iC6tWzuQJz8dN"
4250
BTC_ADDRESS_PRIVATE_TAGS = "3D4gm7eGSXiEkWS5V3hN9kDVo2eDGBK4eA" # Address with potentially private tags
@@ -74,10 +82,18 @@ def normalize_endpoint_to_pattern(uri: str) -> str:
7482
return pattern
7583

7684

77-
def get_response(base_url: str, endpoint: str, auth: str = "test") -> tuple[dict, int, float]:
78-
"""Get response from an endpoint, returning (data, status_code, elapsed_time)."""
85+
def get_response(base_url: str, endpoint: str, auth: str = "test", authenticated: bool = True) -> tuple[dict, int, float]:
86+
"""Get response from an endpoint, returning (data, status_code, elapsed_time).
87+
88+
Args:
89+
base_url: The server base URL
90+
endpoint: The API endpoint to call
91+
auth: Authorization header value
92+
authenticated: If True, include X-Consumer-Groups for private tags access
93+
"""
7994
url = urljoin(base_url + "/", endpoint.lstrip("/"))
80-
headers = {**HEADERS, "Authorization": auth}
95+
base_headers = AUTHENTICATED_HEADERS if authenticated else HEADERS
96+
headers = {**base_headers, "Authorization": auth}
8197

8298
start = time.time()
8399
response = requests.get(url, headers=headers, timeout=30)
@@ -91,10 +107,19 @@ def get_response(base_url: str, endpoint: str, auth: str = "test") -> tuple[dict
91107
return data, response.status_code, elapsed
92108

93109

94-
def post_response(base_url: str, endpoint: str, body: dict, auth: str = "test") -> tuple[dict, int, float]:
95-
"""POST request to an endpoint, returning (data, status_code, elapsed_time)."""
110+
def post_response(base_url: str, endpoint: str, body: dict, auth: str = "test", authenticated: bool = True) -> tuple[dict, int, float]:
111+
"""POST request to an endpoint, returning (data, status_code, elapsed_time).
112+
113+
Args:
114+
base_url: The server base URL
115+
endpoint: The API endpoint to call
116+
body: The JSON body to send
117+
auth: Authorization header value
118+
authenticated: If True, include X-Consumer-Groups for private tags access
119+
"""
96120
url = urljoin(base_url + "/", endpoint.lstrip("/"))
97-
headers = {**HEADERS, "Authorization": auth}
121+
base_headers = AUTHENTICATED_HEADERS if authenticated else HEADERS
122+
headers = {**base_headers, "Authorization": auth}
98123

99124
start = time.time()
100125
response = requests.post(url, headers=headers, json=body, timeout=60)

tests/test_regression.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
"Accept": "application/json"
2121
}
2222

23+
# Headers to simulate authenticated access (what API gateway provides)
24+
authenticated_headers = {
25+
"Content-Type": "application/json",
26+
"Accept": "application/json",
27+
"X-Consumer-Groups": "tags-private" # Simulate gateway adding this on auth
28+
}
29+
2330

2431
def get_data_from_current_endpoint(endpoint: str, key: str) -> tuple[Dict[str, Any], float]:
2532
"""Get data from the current endpoint with API key authentication."""
@@ -39,12 +46,20 @@ def get_data_from_current_endpoint(endpoint: str, key: str) -> tuple[Dict[str, A
3946
raise
4047

4148

42-
def get_data_from_new_endpoint(endpoint: str) -> tuple[Dict[str, Any], float]:
43-
"""Get data from the new endpoint without authentication."""
49+
def get_data_from_new_endpoint(endpoint: str, authenticated: bool = True) -> tuple[Dict[str, Any], float]:
50+
"""Get data from the new endpoint.
51+
52+
Args:
53+
endpoint: The API endpoint to call
54+
authenticated: If True, include headers that simulate API gateway auth.
55+
If False, call without auth headers (for anonymous user tests).
56+
"""
4457
now = time.time()
4558
url = urljoin(new_endpoint, endpoint)
4659
try:
47-
response = requests.get(url, headers=headers)
60+
# Use authenticated_headers to simulate what the API gateway provides
61+
request_headers = authenticated_headers if authenticated else headers
62+
response = requests.get(url, headers=request_headers)
4863
response.raise_for_status()
4964
elapsed = time.time() - now
5065
return response.json(), elapsed
@@ -150,11 +165,14 @@ def test_conversions():
150165
# thor BTC OP RETURN
151166
call_7_2 = "eth/txs/9ADD0876DC5478BC9658C10033AC59B8C504A5122266DBBBDE289BEEF2DF3D97/conversions" # bridge eth -> btc with log, now supported via OP RETURN
152167
call_7 = "eth/txs/0xC0915244DC52B5EFC4F602A7C68874D689AB6F8B71D151D39244617030DB89E0/conversions" # bridge eth -> btc without log, direct memo, now supported
168+
call_8 = "eth/txs/e2948634dce13d0998dbd65a0f56ffa8d4f070088cce57cc09cc366981073f9f_I321/conversions" # bridge BTC -> ETH , ETH receiving to_asset_transfer subtx
169+
call_8_1 = "eth/txs/e2948634dce13d0998dbd65a0f56ffa8d4f070088cce57cc09cc366981073f9f/conversions" # bridge BTC -> ETH , ETH receiving tx (general, not subtx)
153170
#call_7_3 = "btc/txs/0B7B76EF969D20D3015CA92726F4BA0E2070D6920DDCAC2E61ABB07C72FD1878/conversions"
154171

155172
calls = [
156173
call_1, call_2, call_3_send, call_3_receive, call_3_refund, call_4_eth_to_token,
157174
call_4_eth_to_btc_thorchain, call_5, call_6, call_7_2, call_7, #, call_7_2
175+
call_8, call_8_1,
158176
]
159177
for call in calls:
160178
logger.info(f"Testing call: {call}")
@@ -218,7 +236,7 @@ def test_obfuscation():
218236
call = "btc/addresses/3D4gm7eGSXiEkWS5V3hN9kDVo2eDGBK4eA/tag_summary"
219237

220238
# Get data without auth header (anonymous user)
221-
data, _ = get_data_from_new_endpoint(call)
239+
data, _ = get_data_from_new_endpoint(call, authenticated=False)
222240

223241
# Anonymous users should still get tags (not zero)
224242
assert data.get("tag_count", 0) > 0, \

0 commit comments

Comments
 (0)