test_: add python linters (#6212)
* test_: add python linters * test_: add python linters * test_: add python linters * test_: add python linters * test_: enabled pyright typeCheckingMode * test_: enabled pyright typeCheckingMode
This commit is contained in:
parent
66850321ef
commit
08eee8a647
|
@ -0,0 +1,33 @@
|
|||
name: Pytest Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
push:
|
||||
branches:
|
||||
- "test-linting"
|
||||
|
||||
jobs:
|
||||
pytest-lint:
|
||||
timeout-minutes: 10
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
cache: 'pip'
|
||||
|
||||
- name: Set up virtual environment in /tests-functional/
|
||||
run: |
|
||||
python -m venv tests-functional/.venv
|
||||
echo "tests-functional/.venv/bin" >> $GITHUB_PATH # Add virtualenv to PATH for subsequent steps
|
||||
|
||||
- name: Install dependencies based on requirements.txt
|
||||
run: pip install -r tests-functional/requirements.txt
|
||||
|
||||
- name: Run pytest-lint
|
||||
run: pre-commit run --all-files --verbose --config tests-functional/.pre-commit-config.yaml
|
|
@ -109,7 +109,6 @@ tests-functional/coverage
|
|||
tests-functional/reports
|
||||
tests-functional/signals
|
||||
tests-functional/*.log
|
||||
pyrightconfig.json
|
||||
.venv
|
||||
|
||||
|
||||
|
|
5
Makefile
5
Makefile
|
@ -428,3 +428,8 @@ run-anvil:
|
|||
codecov-validate: SHELL := /bin/sh
|
||||
codecov-validate:
|
||||
curl -X POST --data-binary @.codecov.yml https://codecov.io/validate
|
||||
|
||||
.PHONY: pytest-lint
|
||||
pytest-lint:
|
||||
@echo "Running python linting on all files..."
|
||||
pre-commit run --all-files --verbose --config tests-functional/.pre-commit-config.yaml
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"include": ["tests-functional"],
|
||||
"venvPath": "./tests-functional", // Ensure the virtual environment (.venv) is located in ./tests-functional
|
||||
"venv": ".venv"
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 24.10.0 # Latest version of Black
|
||||
hooks:
|
||||
- id: black
|
||||
args: [--line-length=150]
|
||||
files: ^tests-functional/.*\.py$
|
||||
# Black: Automatically formats Python code to adhere to its strict style guidelines.
|
||||
# - Ensures consistent code formatting across the project.
|
||||
# - Helps maintain readability and avoids debates about style in code reviews.
|
||||
|
||||
- repo: https://github.com/RobertCraigie/pyright-python
|
||||
rev: v1.1.388 # Version of Pyright used
|
||||
hooks:
|
||||
- id: pyright
|
||||
files: ^tests-functional/.*\.py$
|
||||
# Pyright: A static type checker for Python.
|
||||
# - Validates type hints and ensures type correctness in code.
|
||||
# - Identifies type mismatches, missing imports, and potential runtime errors.
|
||||
# - Ensures better type safety and helps catch bugs early.
|
||||
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 7.1.1 # Latest version of Flake8
|
||||
hooks:
|
||||
- id: flake8
|
||||
args: ["--max-line-length=150"]
|
||||
files: ^tests-functional/.*\.py$
|
||||
# Flake8: A lightweight Python linter for style and syntax checking.
|
||||
# - Detects unused imports, undefined variables, and redefined functions (e.g., F811).
|
||||
# - Checks for adherence to Python coding standards (PEP 8).
|
||||
# - Helps maintain clean, bug-free code.
|
|
@ -12,10 +12,18 @@ Functional tests for status-go
|
|||
|
||||
## How to Install
|
||||
|
||||
* Install [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/)
|
||||
* Install [Python 3.10.14](https://www.python.org/downloads/)
|
||||
* In `./tests-functional`, run `pip install -r requirements.txt`
|
||||
* **Optional (for test development)**: Use Python virtual environment for better dependency management. You can follow the guide [here](https://akrabat.com/creating-virtual-environments-with-pyenv/):
|
||||
1. Install [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/)
|
||||
2. Install [Python 3](https://www.python.org/downloads/) (tested with 3.10 and 3.12 and it works with both)
|
||||
3. **Set up a virtual environment (required for linting):**
|
||||
- In `./tests-functional`, run:
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
pre-commit install
|
||||
```
|
||||
- **Important**: The virtual environment must be created in the `./tests-functional` directory for pre-commit linting and type-checking tools like Pyright to work correctly.
|
||||
- **Optional (for test development)**: Use Python virtual environment for better dependency management. You can follow the guide [here](https://akrabat.com/creating-virtual-environments-with-pyenv/)
|
||||
|
||||
## How to Run
|
||||
|
||||
|
@ -39,4 +47,4 @@ Functional tests for status-go
|
|||
- Every test has two types of verifications:
|
||||
- `verify_is_valid_json_rpc_response()` checks for status code 200, non-empty response, JSON-RPC structure, presence of the `result` field, and expected ID.
|
||||
- `jsonschema.validate()` is used to check that the response contains expected data, including required fields and types. Schemas are stored in `/schemas/wallet_MethodName`
|
||||
- New schemas can be generated using `./tests-functional/schema_builder.py` by passing a response to the `CustomSchemaBuilder(schema_name).create_schema(response.json())` method, should be used only on test creation phase, please search `how to create schema:` to see an example in a test
|
||||
- New schemas can be generated using `./tests-functional/utils/schema_builder.py` by passing a response to the `CustomSchemaBuilder(schema_name).create_schema(response.json())` method, should be used only on test creation phase, please search `how to create schema:` to see an example in a test
|
|
@ -17,11 +17,9 @@ class RpcClient:
|
|||
try:
|
||||
return response.json()[key]
|
||||
except json.JSONDecodeError:
|
||||
raise AssertionError(
|
||||
f"Invalid JSON in response: {response.content}")
|
||||
raise AssertionError(f"Invalid JSON in response: {response.content}")
|
||||
except KeyError:
|
||||
raise AssertionError(
|
||||
f"Key '{key}' not found in the JSON response: {response.content}")
|
||||
raise AssertionError(f"Key '{key}' not found in the JSON response: {response.content}")
|
||||
|
||||
def verify_is_valid_json_rpc_response(self, response, _id=None):
|
||||
assert response.status_code == 200, f"Got response {response.content}, status code {response.status_code}"
|
||||
|
@ -31,9 +29,7 @@ class RpcClient:
|
|||
if _id:
|
||||
try:
|
||||
if _id != response.json()["id"]:
|
||||
raise AssertionError(
|
||||
f"got id: {response.json()['id']} instead of expected id: {_id}"
|
||||
)
|
||||
raise AssertionError(f"got id: {response.json()['id']} instead of expected id: {_id}")
|
||||
except KeyError:
|
||||
raise AssertionError(f"no id in response {response.json()}")
|
||||
return response
|
||||
|
@ -44,7 +40,9 @@ class RpcClient:
|
|||
self._check_decode_and_key_errors_in_response(response, "error")
|
||||
|
||||
@retry(stop=stop_after_delay(10), wait=wait_fixed(0.5), reraise=True)
|
||||
def rpc_request(self, method, params=None, request_id=13, url=None):
|
||||
def rpc_request(self, method, params=None, request_id=None, url=None):
|
||||
if not request_id:
|
||||
request_id = 13
|
||||
if params is None:
|
||||
params = []
|
||||
url = url if url else self.rpc_url
|
||||
|
@ -69,5 +67,4 @@ class RpcClient:
|
|||
|
||||
def verify_json_schema(self, response, method):
|
||||
with open(f"{option.base_dir}/schemas/{method}", "r") as schema:
|
||||
jsonschema.validate(instance=response,
|
||||
schema=json.load(schema))
|
||||
jsonschema.validate(instance=response, schema=json.load(schema))
|
||||
|
|
|
@ -3,7 +3,7 @@ from clients.rpc import RpcClient
|
|||
|
||||
class Service:
|
||||
def __init__(self, client: RpcClient, name: str):
|
||||
assert name is not ""
|
||||
assert name != ""
|
||||
self.rpc_client = client
|
||||
self.name = name
|
||||
|
||||
|
|
|
@ -5,10 +5,11 @@ import time
|
|||
import websocket
|
||||
import os
|
||||
from pathlib import Path
|
||||
from constants import SIGNALS_DIR, LOG_SIGNALS_TO_FILE
|
||||
from resources.constants import SIGNALS_DIR, LOG_SIGNALS_TO_FILE
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class SignalType(Enum):
|
||||
MESSAGES_NEW = "messages.new"
|
||||
MESSAGE_DELIVERED = "message.delivered"
|
||||
|
@ -22,6 +23,7 @@ class SignalType(Enum):
|
|||
WALLET_TRANSACTION_STATUS_CHANGED = "wallet.transaction.status-changed"
|
||||
WALLET_ROUTER_TRANSACTIONS_SENT = "wallet.router.transactions-sent"
|
||||
|
||||
|
||||
class SignalClient:
|
||||
def __init__(self, ws_url, await_signals):
|
||||
self.url = f"{ws_url}/signals"
|
||||
|
@ -37,11 +39,15 @@ class SignalClient:
|
|||
"received": [],
|
||||
"delta_count": 1,
|
||||
"expected_count": 1,
|
||||
"accept_fn": None
|
||||
} for signal in self.await_signals
|
||||
"accept_fn": None,
|
||||
}
|
||||
for signal in self.await_signals
|
||||
}
|
||||
if LOG_SIGNALS_TO_FILE:
|
||||
self.signal_file_path = os.path.join(SIGNALS_DIR, f"signal_{ws_url.split(':')[-1]}_{datetime.now().strftime('%H%M%S')}.log")
|
||||
self.signal_file_path = os.path.join(
|
||||
SIGNALS_DIR,
|
||||
f"signal_{ws_url.split(':')[-1]}_{datetime.now().strftime('%H%M%S')}.log",
|
||||
)
|
||||
Path(SIGNALS_DIR).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def on_message(self, ws, signal):
|
||||
|
@ -77,8 +83,7 @@ class SignalClient:
|
|||
received_signals = self.received_signals.get(signal_type)
|
||||
while (not received_signals) or len(received_signals["received"]) < received_signals["expected_count"]:
|
||||
if time.time() - start_time >= timeout:
|
||||
raise TimeoutError(
|
||||
f"Signal {signal_type} is not received in {timeout} seconds")
|
||||
raise TimeoutError(f"Signal {signal_type} is not received in {timeout} seconds")
|
||||
time.sleep(0.2)
|
||||
logging.debug(f"Signal {signal_type} is received in {round(time.time() - start_time)} seconds")
|
||||
delta_count = received_signals["delta_count"]
|
||||
|
@ -97,17 +102,13 @@ class SignalClient:
|
|||
start_time = time.time()
|
||||
while True:
|
||||
if time.time() - start_time >= timeout:
|
||||
raise TimeoutError(
|
||||
f"Signal {signal_type} containing {event_pattern} is not received in {timeout} seconds"
|
||||
)
|
||||
raise TimeoutError(f"Signal {signal_type} containing {event_pattern} is not received in {timeout} seconds")
|
||||
if not self.received_signals.get(signal_type):
|
||||
time.sleep(0.2)
|
||||
continue
|
||||
for event in self.received_signals[signal_type]["received"]:
|
||||
if event_pattern in str(event):
|
||||
logging.info(
|
||||
f"Signal {signal_type} containing {event_pattern} is received in {round(time.time() - start_time)} seconds"
|
||||
)
|
||||
logging.info(f"Signal {signal_type} containing {event_pattern} is received in {round(time.time() - start_time)} seconds")
|
||||
return event
|
||||
time.sleep(0.2)
|
||||
|
||||
|
@ -121,10 +122,12 @@ class SignalClient:
|
|||
logging.info("Connection opened")
|
||||
|
||||
def _connect(self):
|
||||
ws = websocket.WebSocketApp(self.url,
|
||||
on_message=self.on_message,
|
||||
on_error=self._on_error,
|
||||
on_close=self._on_close)
|
||||
ws = websocket.WebSocketApp(
|
||||
self.url,
|
||||
on_message=self.on_message,
|
||||
on_error=self._on_error,
|
||||
on_close=self._on_close,
|
||||
)
|
||||
ws.on_open = self._on_open
|
||||
ws.run_forever()
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ from clients.signals import SignalClient
|
|||
from clients.rpc import RpcClient
|
||||
from datetime import datetime
|
||||
from conftest import option
|
||||
from constants import user_1, DEFAULT_DISPLAY_NAME, USER_DIR
|
||||
from resources.constants import user_1, DEFAULT_DISPLAY_NAME, USER_DIR
|
||||
|
||||
|
||||
class StatusBackend(RpcClient, SignalClient):
|
||||
|
@ -29,7 +29,6 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
url = f"http://127.0.0.1:{host_port}"
|
||||
option.status_backend_port_range.remove(host_port)
|
||||
|
||||
|
||||
self.api_url = f"{url}/statusgo"
|
||||
self.ws_url = f"{url}".replace("http", "ws")
|
||||
self.rpc_url = f"{url}/statusgo/CallRPC"
|
||||
|
@ -59,7 +58,8 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
"labels": {"com.docker.compose.project": docker_project_name},
|
||||
"entrypoint": [
|
||||
"status-backend",
|
||||
"--address", "0.0.0.0:3333",
|
||||
"--address",
|
||||
"0.0.0.0:3333",
|
||||
],
|
||||
"ports": {"3333/tcp": host_port},
|
||||
"environment": {
|
||||
|
@ -78,8 +78,7 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
|
||||
container = self.docker_client.containers.run(**container_args)
|
||||
|
||||
network = self.docker_client.networks.get(
|
||||
f"{docker_project_name}_default")
|
||||
network = self.docker_client.networks.get(f"{docker_project_name}_default")
|
||||
network.connect(container)
|
||||
|
||||
option.status_backend_containers.append(container.id)
|
||||
|
@ -99,8 +98,7 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
def api_request(self, method, data, url=None):
|
||||
url = url if url else self.api_url
|
||||
url = f"{url}/{method}"
|
||||
logging.info(
|
||||
f"Sending POST request to url {url} with data: {json.dumps(data, sort_keys=True, indent=4)}")
|
||||
logging.info(f"Sending POST request to url {url} with data: {json.dumps(data, sort_keys=True, indent=4)}")
|
||||
response = requests.post(url, json=data)
|
||||
logging.info(f"Got response: {response.content}")
|
||||
return response
|
||||
|
@ -113,8 +111,7 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
error = response.json()["error"]
|
||||
assert not error, f"Error: {error}"
|
||||
except json.JSONDecodeError:
|
||||
raise AssertionError(
|
||||
f"Invalid JSON in response: {response.content}")
|
||||
raise AssertionError(f"Invalid JSON in response: {response.content}")
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
@ -133,7 +130,12 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
}
|
||||
return self.api_valid_request(method, data)
|
||||
|
||||
def create_account_and_login(self, data_dir=USER_DIR, display_name=DEFAULT_DISPLAY_NAME, password=user_1.password):
|
||||
def create_account_and_login(
|
||||
self,
|
||||
data_dir=USER_DIR,
|
||||
display_name=DEFAULT_DISPLAY_NAME,
|
||||
password=user_1.password,
|
||||
):
|
||||
method = "CreateAccountAndLogin"
|
||||
data = {
|
||||
"rootDataDir": data_dir,
|
||||
|
@ -146,8 +148,13 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
}
|
||||
return self.api_valid_request(method, data)
|
||||
|
||||
def restore_account_and_login(self, data_dir=USER_DIR, display_name=DEFAULT_DISPLAY_NAME, user=user_1,
|
||||
network_id=31337):
|
||||
def restore_account_and_login(
|
||||
self,
|
||||
data_dir=USER_DIR,
|
||||
display_name=DEFAULT_DISPLAY_NAME,
|
||||
user=user_1,
|
||||
network_id=31337,
|
||||
):
|
||||
method = "RestoreAccountAndLogin"
|
||||
data = {
|
||||
"rootDataDir": data_dir,
|
||||
|
@ -172,9 +179,9 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
"NativeCurrencyDecimals": 18,
|
||||
"IsTest": False,
|
||||
"Layer": 1,
|
||||
"Enabled": True
|
||||
"Enabled": True,
|
||||
}
|
||||
]
|
||||
],
|
||||
}
|
||||
return self.api_valid_request(method, data)
|
||||
|
||||
|
@ -197,12 +204,11 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
# ToDo: change this part for waiting for `node.login` signal when websockets are migrated to StatusBackend
|
||||
while time.time() - start_time <= timeout:
|
||||
try:
|
||||
self.rpc_valid_request(method='accounts_getKeypairs')
|
||||
self.rpc_valid_request(method="accounts_getKeypairs")
|
||||
return
|
||||
except AssertionError:
|
||||
time.sleep(3)
|
||||
raise TimeoutError(
|
||||
f"RPC client was not started after {timeout} seconds")
|
||||
raise TimeoutError(f"RPC client was not started after {timeout} seconds")
|
||||
|
||||
@retry(stop=stop_after_delay(10), wait=wait_fixed(0.5), reraise=True)
|
||||
def start_messenger(self, params=[]):
|
||||
|
@ -210,9 +216,9 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
response = self.rpc_request(method, params)
|
||||
json_response = response.json()
|
||||
|
||||
if 'error' in json_response:
|
||||
assert json_response['error']['code'] == -32000
|
||||
assert json_response['error']['message'] == "messenger already started"
|
||||
if "error" in json_response:
|
||||
assert json_response["error"]["code"] == -32000
|
||||
assert json_response["error"]["message"] == "messenger already started"
|
||||
return
|
||||
|
||||
self.verify_is_valid_json_rpc_response(response)
|
||||
|
@ -239,8 +245,7 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
for account in accounts:
|
||||
if account.get("name") == display_name:
|
||||
return account.get("public-key")
|
||||
raise ValueError(
|
||||
f"Public key not found for display name: {display_name}")
|
||||
raise ValueError(f"Public key not found for display name: {display_name}")
|
||||
|
||||
def send_contact_request(self, contact_id: str, message: str):
|
||||
method = "wakuext_sendContactRequest"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import os
|
||||
import docker
|
||||
import pytest as pytest
|
||||
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
|
@ -43,9 +43,12 @@ def pytest_addoption(parser):
|
|||
default=None,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Option:
|
||||
pass
|
||||
status_backend_port_range: List[int] = field(default_factory=list)
|
||||
status_backend_containers: List[str] = field(default_factory=list)
|
||||
base_dir: str = ""
|
||||
|
||||
|
||||
option = Option()
|
||||
|
@ -55,7 +58,7 @@ def pytest_configure(config):
|
|||
global option
|
||||
option = config.option
|
||||
|
||||
executor_number = int(os.getenv('EXECUTOR_NUMBER', 5))
|
||||
executor_number = int(os.getenv("EXECUTOR_NUMBER", 5))
|
||||
base_port = 7000
|
||||
range_size = 100
|
||||
|
||||
|
@ -66,6 +69,7 @@ def pytest_configure(config):
|
|||
|
||||
option.base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def pytest_unconfigure():
|
||||
docker_client = docker.from_env()
|
||||
for container_id in option.status_backend_containers:
|
||||
|
|
|
@ -7,3 +7,6 @@ websocket-client~=1.4.2
|
|||
tenacity~=9.0.0
|
||||
pytest-dependency~=0.6.0
|
||||
docker==7.1.0
|
||||
pyright==1.1.388
|
||||
black==24.10.0
|
||||
pre-commit==3.6.2
|
|
@ -15,17 +15,17 @@ user_1 = Account(
|
|||
address="0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
|
||||
password="Strong12345",
|
||||
passphrase="test test test test test test test test test test test junk"
|
||||
passphrase="test test test test test test test test test test test junk",
|
||||
)
|
||||
user_2 = Account(
|
||||
address="0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
|
||||
private_key="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d",
|
||||
password="Strong12345",
|
||||
passphrase="test test test test test test test test test test nest junk"
|
||||
passphrase="test test test test test test test test test test nest junk",
|
||||
)
|
||||
DEFAULT_DISPLAY_NAME = "Mr_Meeseeks"
|
||||
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../"))
|
||||
TESTS_DIR = os.path.join(PROJECT_ROOT, "tests-functional")
|
||||
SIGNALS_DIR = os.path.join(TESTS_DIR, "signals")
|
||||
LOG_SIGNALS_TO_FILE = False # used for debugging purposes
|
||||
LOG_SIGNALS_TO_FILE = False # used for debugging purposes
|
||||
USER_DIR = option.user_dir if option.user_dir else "/usr/status-user"
|
|
@ -1,5 +1,6 @@
|
|||
from enum import Enum
|
||||
|
||||
|
||||
class MessageContentType(Enum):
|
||||
UNKNOWN_CONTENT_TYPE = 0
|
||||
TEXT_PLAIN = 1
|
||||
|
@ -18,5 +19,5 @@ class MessageContentType(Enum):
|
|||
SYSTEM_MESSAGE_PINNED_MESSAGE = 14
|
||||
SYSTEM_MESSAGE_MUTUAL_EVENT_SENT = 15
|
||||
SYSTEM_MESSAGE_MUTUAL_EVENT_ACCEPTED = 16
|
||||
SYSTEM_MESSAGE_MUTUAL_EVENT_REMOVED = 17
|
||||
SYSTEM_MESSAGE_MUTUAL_EVENT_REMOVED = 17
|
||||
BRIDGE_MESSAGE = 18
|
||||
|
|
|
@ -2,7 +2,7 @@ import random
|
|||
|
||||
import pytest
|
||||
|
||||
from constants import user_1
|
||||
from resources.constants import user_1
|
||||
from test_cases import StatusBackendTestCase
|
||||
|
||||
|
||||
|
@ -18,7 +18,6 @@ class TestAccounts(StatusBackendTestCase):
|
|||
# ("accounts_hasPairedDevices", []), # randomly crashes app, to be reworked/fixed
|
||||
# ("accounts_remainingAccountCapacity", []), # randomly crashes app, to be reworked/fixed
|
||||
("multiaccounts_getIdentityImages", [user_1.private_key]),
|
||||
|
||||
],
|
||||
)
|
||||
def test_(self, method, params):
|
||||
|
|
|
@ -13,7 +13,6 @@ class TestAppGeneral(StatusBackendTestCase):
|
|||
"method, params",
|
||||
[
|
||||
("appgeneral_getCurrencies", []),
|
||||
|
||||
],
|
||||
)
|
||||
def test_(self, method, params):
|
||||
|
|
|
@ -11,23 +11,19 @@ from clients.services.wallet import WalletService
|
|||
from clients.signals import SignalClient, SignalType
|
||||
from clients.status_backend import RpcClient, StatusBackend
|
||||
from conftest import option
|
||||
from constants import user_1, user_2, DEFAULT_DISPLAY_NAME
|
||||
from resources.constants import user_1, user_2, DEFAULT_DISPLAY_NAME
|
||||
|
||||
|
||||
class StatusDTestCase:
|
||||
network_id = 31337
|
||||
|
||||
def setup_method(self):
|
||||
self.rpc_client = RpcClient(
|
||||
option.rpc_url_statusd
|
||||
)
|
||||
self.rpc_client = RpcClient(option.rpc_url_statusd)
|
||||
|
||||
|
||||
class StatusBackendTestCase:
|
||||
|
||||
await_signals = [
|
||||
SignalType.NODE_LOGIN.value
|
||||
]
|
||||
await_signals = [SignalType.NODE_LOGIN.value]
|
||||
|
||||
network_id = 31337
|
||||
|
||||
|
@ -59,8 +55,7 @@ class WalletTestCase(StatusBackendTestCase):
|
|||
if key in transfer_tx_data:
|
||||
transfer_tx_data[key] = new_value
|
||||
else:
|
||||
logging.info(
|
||||
f"Warning: The key '{key}' does not exist in the transferTx parameters and will be ignored.")
|
||||
logging.info(f"Warning: The key '{key}' does not exist in the transferTx parameters and will be ignored.")
|
||||
params = [
|
||||
{
|
||||
"fromAddress": user_1.address,
|
||||
|
@ -74,7 +69,7 @@ class WalletTestCase(StatusBackendTestCase):
|
|||
{
|
||||
"bridgeName": "Transfer",
|
||||
"chainID": 31337,
|
||||
"transferTx": transfer_tx_data
|
||||
"transferTx": transfer_tx_data,
|
||||
}
|
||||
],
|
||||
f"{option.password}",
|
||||
|
@ -87,8 +82,7 @@ class WalletTestCase(StatusBackendTestCase):
|
|||
tx_hash = None
|
||||
self.rpc_client.verify_is_valid_json_rpc_response(response)
|
||||
try:
|
||||
tx_hash = response.json(
|
||||
)["result"]["hashes"][str(self.network_id)][0]
|
||||
tx_hash = response.json()["result"]["hashes"][str(self.network_id)][0]
|
||||
except (KeyError, json.JSONDecodeError):
|
||||
raise Exception(response.content)
|
||||
return tx_hash
|
||||
|
@ -102,7 +96,7 @@ class TransactionTestCase(WalletTestCase):
|
|||
|
||||
class EthRpcTestCase(WalletTestCase):
|
||||
|
||||
@pytest.fixture(autouse=True, scope='class')
|
||||
@pytest.fixture(autouse=True, scope="class")
|
||||
def tx_data(self):
|
||||
tx_hash = self.send_valid_multi_transaction()
|
||||
self.wait_until_tx_not_pending(tx_hash)
|
||||
|
@ -133,11 +127,10 @@ class EthRpcTestCase(WalletTestCase):
|
|||
response = self.rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
start_time = time.time()
|
||||
while response.json()["result"]["isPending"] == True:
|
||||
while response.json()["result"]["isPending"] is True:
|
||||
time_passed = time.time() - start_time
|
||||
if time_passed >= timeout:
|
||||
raise TimeoutError(
|
||||
f"Tx {tx_hash} is still pending after {timeout} seconds")
|
||||
raise TimeoutError(f"Tx {tx_hash} is still pending after {timeout} seconds")
|
||||
time.sleep(0.5)
|
||||
response = self.rpc_client.rpc_valid_request(method, params)
|
||||
return response.json()["result"]["tx"]
|
||||
|
@ -159,23 +152,36 @@ class NetworkConditionTestCase:
|
|||
|
||||
@contextmanager
|
||||
def add_latency(self):
|
||||
pass
|
||||
#TODO: To be implemented when we have docker exec capability
|
||||
try:
|
||||
# TODO: To be implemented when we have docker exec capability
|
||||
yield
|
||||
finally:
|
||||
pass
|
||||
|
||||
@contextmanager
|
||||
def add_packet_loss(self):
|
||||
pass
|
||||
#TODO: To be implemented when we have docker exec capability
|
||||
try:
|
||||
# TODO: To be implemented when we have docker exec capability
|
||||
yield
|
||||
finally:
|
||||
pass
|
||||
|
||||
@contextmanager
|
||||
def add_low_bandwith(self):
|
||||
pass
|
||||
#TODO: To be implemented when we have docker exec capability
|
||||
try:
|
||||
# TODO: To be implemented when we have docker exec capability
|
||||
yield
|
||||
finally:
|
||||
pass
|
||||
|
||||
@contextmanager
|
||||
def node_pause(self, node):
|
||||
pass
|
||||
#TODO: To be implemented when we have docker exec capability
|
||||
try:
|
||||
# TODO: To be implemented when we have docker exec capability
|
||||
yield
|
||||
finally:
|
||||
pass
|
||||
|
||||
|
||||
class OneToOneMessageTestCase(NetworkConditionTestCase):
|
||||
|
||||
|
@ -186,13 +192,15 @@ class OneToOneMessageTestCase(NetworkConditionTestCase):
|
|||
backend.start_messenger()
|
||||
return backend
|
||||
|
||||
|
||||
def validate_signal_event_against_response(self, signal_event, fields_to_validate, expected_message):
|
||||
expected_message_id = expected_message.get("id")
|
||||
signal_event_messages = signal_event.get("event", {}).get("messages")
|
||||
assert len(signal_event_messages) > 0, "No messages found in the signal event"
|
||||
|
||||
message = next((message for message in signal_event_messages if message.get("id") == expected_message_id), None)
|
||||
message = next(
|
||||
(message for message in signal_event_messages if message.get("id") == expected_message_id),
|
||||
None,
|
||||
)
|
||||
assert message, f"Message with ID {expected_message_id} not found in the signal event"
|
||||
|
||||
message_mismatch = []
|
||||
|
@ -200,17 +208,14 @@ class OneToOneMessageTestCase(NetworkConditionTestCase):
|
|||
response_value = expected_message[response_field]
|
||||
event_value = message[event_field]
|
||||
if response_value != event_value:
|
||||
message_mismatch.append(
|
||||
f"Field '{response_field}': Expected '{response_value}', Found '{event_value}'"
|
||||
)
|
||||
message_mismatch.append(f"Field '{response_field}': Expected '{response_value}', Found '{event_value}'")
|
||||
|
||||
if not message_mismatch:
|
||||
return
|
||||
|
||||
raise AssertionError(
|
||||
"Some Sender RPC responses are not matching the signals received by the receiver.\n"
|
||||
"Details of mismatches:\n" +
|
||||
"\n".join(message_mismatch)
|
||||
"Details of mismatches:\n" + "\n".join(message_mismatch)
|
||||
)
|
||||
|
||||
def get_message_by_content_type(self, response, content_type):
|
||||
|
|
|
@ -2,14 +2,14 @@ from time import sleep
|
|||
from uuid import uuid4
|
||||
import pytest
|
||||
from test_cases import OneToOneMessageTestCase
|
||||
from constants import DEFAULT_DISPLAY_NAME
|
||||
from resources.constants import DEFAULT_DISPLAY_NAME
|
||||
from clients.signals import SignalType
|
||||
from resources.enums import MessageContentType
|
||||
|
||||
|
||||
@pytest.mark.rpc
|
||||
class TestContactRequests(OneToOneMessageTestCase):
|
||||
|
||||
|
||||
@pytest.mark.dependency(name="test_contact_request_baseline")
|
||||
def test_contact_request_baseline(self, execution_number=1):
|
||||
|
||||
|
@ -21,7 +21,7 @@ class TestContactRequests(OneToOneMessageTestCase):
|
|||
message_text = f"test_contact_request_{execution_number}_{uuid4()}"
|
||||
|
||||
sender = self.initialize_backend(await_signals=await_signals)
|
||||
receiver = self.initialize_backend(await_signals=await_signals)
|
||||
receiver = self.initialize_backend(await_signals=await_signals)
|
||||
|
||||
pk_sender = sender.get_pubkey(DEFAULT_DISPLAY_NAME)
|
||||
pk_receiver = receiver.get_pubkey(DEFAULT_DISPLAY_NAME)
|
||||
|
@ -34,25 +34,31 @@ class TestContactRequests(OneToOneMessageTestCase):
|
|||
response = sender.send_contact_request(pk_receiver, message_text)
|
||||
expected_message = self.get_message_by_content_type(response, content_type=MessageContentType.CONTACT_REQUEST.value)
|
||||
|
||||
messages_new_event = receiver.find_signal_containing_pattern(SignalType.MESSAGES_NEW.value, event_pattern=expected_message.get("id"), timeout=60)
|
||||
messages_new_event = receiver.find_signal_containing_pattern(
|
||||
SignalType.MESSAGES_NEW.value,
|
||||
event_pattern=expected_message.get("id"),
|
||||
timeout=60,
|
||||
)
|
||||
|
||||
signal_messages_texts = []
|
||||
if "messages" in messages_new_event.get("event", {}):
|
||||
signal_messages_texts.extend(
|
||||
message["text"]
|
||||
for message in messages_new_event["event"]["messages"]
|
||||
if "text" in message
|
||||
)
|
||||
signal_messages_texts.extend(message["text"] for message in messages_new_event["event"]["messages"] if "text" in message)
|
||||
|
||||
assert f"@{pk_sender} sent you a contact request" in signal_messages_texts, "Couldn't find the signal corresponding to the contact request"
|
||||
|
||||
self.validate_signal_event_against_response(
|
||||
signal_event=messages_new_event,
|
||||
fields_to_validate={"text": "text"},
|
||||
expected_message=expected_message
|
||||
expected_message=expected_message,
|
||||
)
|
||||
|
||||
@pytest.mark.skip(reason="Skipping because of error 'Not enough status-backend containers, please add more'. Unkipping when we merge https://github.com/status-im/status-go/pull/6159")
|
||||
@pytest.mark.skip(
|
||||
reason=(
|
||||
"Skipping because of error 'Not enough status-backend containers, "
|
||||
"please add more'. Unkipping when we merge "
|
||||
"https://github.com/status-im/status-go/pull/6159"
|
||||
)
|
||||
)
|
||||
@pytest.mark.parametrize("execution_number", range(10))
|
||||
@pytest.mark.dependency(depends=["test_contact_request_baseline"])
|
||||
def test_multiple_contact_requests(self, execution_number):
|
||||
|
@ -84,7 +90,7 @@ class TestContactRequests(OneToOneMessageTestCase):
|
|||
SignalType.MESSAGE_DELIVERED.value,
|
||||
]
|
||||
sender = self.initialize_backend(await_signals=await_signals)
|
||||
receiver = self.initialize_backend(await_signals=await_signals)
|
||||
receiver = self.initialize_backend(await_signals=await_signals)
|
||||
pk_receiver = receiver.get_pubkey(DEFAULT_DISPLAY_NAME)
|
||||
|
||||
with self.node_pause(receiver):
|
||||
|
|
|
@ -35,13 +35,17 @@ class TestEth(EthRpcTestCase):
|
|||
self.rpc_client.rpc_valid_request("ethclient_suggestGasPrice", [self.network_id])
|
||||
|
||||
def test_header_by_number(self, tx_data):
|
||||
response = self.rpc_client.rpc_valid_request("ethclient_headerByNumber",
|
||||
[self.network_id, tx_data.block_number])
|
||||
response = self.rpc_client.rpc_valid_request("ethclient_headerByNumber", [self.network_id, tx_data.block_number])
|
||||
validate_header(response.json()["result"], tx_data.block_number, tx_data.block_hash)
|
||||
|
||||
def test_block_by_number(self, tx_data):
|
||||
response = self.rpc_client.rpc_valid_request("ethclient_blockByNumber", [self.network_id, tx_data.block_number])
|
||||
validate_block(response.json()["result"], tx_data.block_number, tx_data.block_hash, tx_data.tx_hash)
|
||||
validate_block(
|
||||
response.json()["result"],
|
||||
tx_data.block_number,
|
||||
tx_data.block_hash,
|
||||
tx_data.tx_hash,
|
||||
)
|
||||
|
||||
def test_header_by_hash(self, tx_data):
|
||||
response = self.rpc_client.rpc_valid_request("ethclient_headerByHash", [self.network_id, tx_data.block_hash])
|
||||
|
@ -49,7 +53,12 @@ class TestEth(EthRpcTestCase):
|
|||
|
||||
def test_block_by_hash(self, tx_data):
|
||||
response = self.rpc_client.rpc_valid_request("ethclient_blockByHash", [self.network_id, tx_data.block_hash])
|
||||
validate_block(response.json()["result"], tx_data.block_number, tx_data.block_hash, tx_data.tx_hash)
|
||||
validate_block(
|
||||
response.json()["result"],
|
||||
tx_data.block_number,
|
||||
tx_data.block_hash,
|
||||
tx_data.tx_hash,
|
||||
)
|
||||
|
||||
def test_transaction_by_hash(self, tx_data):
|
||||
response = self.rpc_client.rpc_valid_request("ethclient_transactionByHash", [self.network_id, tx_data.tx_hash])
|
||||
|
@ -57,4 +66,9 @@ class TestEth(EthRpcTestCase):
|
|||
|
||||
def test_transaction_receipt(self, tx_data):
|
||||
response = self.rpc_client.rpc_valid_request("ethclient_transactionReceipt", [self.network_id, tx_data.tx_hash])
|
||||
validate_receipt(response.json()["result"], tx_data.tx_hash, tx_data.block_number, tx_data.block_hash)
|
||||
validate_receipt(
|
||||
response.json()["result"],
|
||||
tx_data.tx_hash,
|
||||
tx_data.block_number,
|
||||
tx_data.block_hash,
|
||||
)
|
||||
|
|
|
@ -3,6 +3,7 @@ import pytest
|
|||
from clients.signals import SignalType
|
||||
import os
|
||||
|
||||
|
||||
@pytest.mark.create_account
|
||||
@pytest.mark.rpc
|
||||
class TestInitialiseApp:
|
||||
|
@ -11,7 +12,6 @@ class TestInitialiseApp:
|
|||
def test_init_app(self):
|
||||
|
||||
await_signals = [
|
||||
|
||||
SignalType.MEDIASERVER_STARTED.value,
|
||||
SignalType.NODE_STARTED.value,
|
||||
SignalType.NODE_READY.value,
|
||||
|
@ -24,13 +24,18 @@ class TestInitialiseApp:
|
|||
|
||||
assert backend_client is not None
|
||||
backend_client.verify_json_schema(
|
||||
backend_client.wait_for_signal(SignalType.MEDIASERVER_STARTED.value), "signal_mediaserver_started")
|
||||
backend_client.wait_for_signal(SignalType.MEDIASERVER_STARTED.value),
|
||||
"signal_mediaserver_started",
|
||||
)
|
||||
backend_client.verify_json_schema(
|
||||
backend_client.wait_for_signal(SignalType.NODE_STARTED.value), "signal_node_started")
|
||||
backend_client.wait_for_signal(SignalType.NODE_STARTED.value),
|
||||
"signal_node_started",
|
||||
)
|
||||
backend_client.verify_json_schema(
|
||||
backend_client.wait_for_signal(SignalType.NODE_READY.value), "signal_node_ready")
|
||||
backend_client.verify_json_schema(
|
||||
backend_client.wait_for_login(), "signal_node_login")
|
||||
backend_client.wait_for_signal(SignalType.NODE_READY.value),
|
||||
"signal_node_ready",
|
||||
)
|
||||
backend_client.verify_json_schema(backend_client.wait_for_login(), "signal_node_login")
|
||||
|
||||
|
||||
@pytest.mark.rpc
|
||||
|
@ -45,7 +50,6 @@ class TestInitializeLogging:
|
|||
def test_no_logging(self, tmp_path):
|
||||
self.check_logs(tmp_path, log_enabled=False, api_logging_enabled=False)
|
||||
|
||||
|
||||
def assert_file_first_line(self, path, pattern: str, expected: bool):
|
||||
assert os.path.exists(path) == expected
|
||||
if not expected:
|
||||
|
@ -63,20 +67,20 @@ class TestInitializeLogging:
|
|||
logs_dir.mkdir()
|
||||
|
||||
backend = StatusBackend()
|
||||
backend.api_valid_request("InitializeApplication", {
|
||||
"dataDir": str(data_dir),
|
||||
"logDir": str(logs_dir),
|
||||
"logEnabled": log_enabled,
|
||||
"apiLoggingEnabled": api_logging_enabled,
|
||||
})
|
||||
backend.api_valid_request(
|
||||
"InitializeApplication",
|
||||
{
|
||||
"dataDir": str(data_dir),
|
||||
"logDir": str(logs_dir),
|
||||
"logEnabled": log_enabled,
|
||||
"apiLoggingEnabled": api_logging_enabled,
|
||||
},
|
||||
)
|
||||
|
||||
self.assert_file_first_line(
|
||||
logs_dir / "geth.log",
|
||||
pattern="logging initialised",
|
||||
expected=log_enabled)
|
||||
self.assert_file_first_line(logs_dir / "geth.log", pattern="logging initialised", expected=log_enabled)
|
||||
|
||||
self.assert_file_first_line(
|
||||
logs_dir / "api.log",
|
||||
pattern='"method": "InitializeApplication"',
|
||||
expected=api_logging_enabled)
|
||||
|
||||
expected=api_logging_enabled,
|
||||
)
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import re
|
||||
import time
|
||||
from test_cases import StatusBackend
|
||||
import pytest
|
||||
import os
|
||||
|
||||
|
||||
@pytest.mark.rpc
|
||||
@pytest.mark.skip("waiting for status-backend to be executed on the same host/container")
|
||||
|
@ -27,7 +26,10 @@ class TestLogging:
|
|||
|
||||
# Configure logging
|
||||
backend_client.rpc_valid_request("wakuext_setLogLevel", [{"logLevel": "ERROR"}])
|
||||
backend_client.rpc_valid_request("wakuext_setLogNamespaces", [{"logNamespaces": "test1.test2:debug,test1.test2.test3:info"}])
|
||||
backend_client.rpc_valid_request(
|
||||
"wakuext_setLogNamespaces",
|
||||
[{"logNamespaces": "test1.test2:debug,test1.test2.test3:info"}],
|
||||
)
|
||||
|
||||
# Re-login (logging settings take effect after re-login)
|
||||
backend_client.logout()
|
||||
|
@ -36,19 +38,23 @@ class TestLogging:
|
|||
|
||||
# Test logging
|
||||
backend_client.rpc_valid_request("wakuext_logTest")
|
||||
self.expect_logs(tmp_path / "geth.log", "test message", [
|
||||
r"DEBUG\s+test1\.test2",
|
||||
r"INFO\s+test1\.test2",
|
||||
r"INFO\s+test1\.test2\.test3",
|
||||
r"WARN\s+test1\.test2",
|
||||
r"WARN\s+test1\.test2\.test3",
|
||||
r"ERROR\s+test1",
|
||||
r"ERROR\s+test1\.test2",
|
||||
r"ERROR\s+test1\.test2\.test3",
|
||||
])
|
||||
self.expect_logs(
|
||||
tmp_path / "geth.log",
|
||||
"test message",
|
||||
[
|
||||
r"DEBUG\s+test1\.test2",
|
||||
r"INFO\s+test1\.test2",
|
||||
r"INFO\s+test1\.test2\.test3",
|
||||
r"WARN\s+test1\.test2",
|
||||
r"WARN\s+test1\.test2\.test3",
|
||||
r"ERROR\s+test1",
|
||||
r"ERROR\s+test1\.test2",
|
||||
r"ERROR\s+test1\.test2\.test3",
|
||||
],
|
||||
)
|
||||
|
||||
def expect_logs(self, log_file, filter_keyword, expected_logs):
|
||||
with open(log_file, 'r') as f:
|
||||
with open(log_file, "r") as f:
|
||||
log_content = f.read()
|
||||
|
||||
filtered_logs = [line for line in log_content.splitlines() if filter_keyword in line]
|
||||
|
|
|
@ -2,10 +2,11 @@ from time import sleep
|
|||
from uuid import uuid4
|
||||
import pytest
|
||||
from test_cases import OneToOneMessageTestCase
|
||||
from constants import DEFAULT_DISPLAY_NAME
|
||||
from resources.constants import DEFAULT_DISPLAY_NAME
|
||||
from clients.signals import SignalType
|
||||
from resources.enums import MessageContentType
|
||||
|
||||
|
||||
@pytest.mark.rpc
|
||||
class TestOneToOneMessages(OneToOneMessageTestCase):
|
||||
|
||||
|
@ -33,11 +34,15 @@ class TestOneToOneMessages(OneToOneMessageTestCase):
|
|||
sleep(0.01)
|
||||
|
||||
for i, expected_message in enumerate(sent_messages):
|
||||
messages_new_event = self.receiver.find_signal_containing_pattern(SignalType.MESSAGES_NEW.value, event_pattern=expected_message.get("id"), timeout=60)
|
||||
messages_new_event = self.receiver.find_signal_containing_pattern(
|
||||
SignalType.MESSAGES_NEW.value,
|
||||
event_pattern=expected_message.get("id"),
|
||||
timeout=60,
|
||||
)
|
||||
self.validate_signal_event_against_response(
|
||||
signal_event=messages_new_event,
|
||||
fields_to_validate={"text": "text"},
|
||||
expected_message=expected_message
|
||||
expected_message=expected_message,
|
||||
)
|
||||
|
||||
@pytest.mark.dependency(depends=["test_one_to_one_message_baseline"])
|
||||
|
@ -73,5 +78,3 @@ class TestOneToOneMessages(OneToOneMessageTestCase):
|
|||
sleep(30)
|
||||
self.receiver.find_signal_containing_pattern(SignalType.MESSAGES_NEW.value, event_pattern=message_text)
|
||||
self.sender.wait_for_signal("messages.delivered")
|
||||
|
||||
|
||||
|
|
|
@ -3,10 +3,11 @@ import uuid
|
|||
import pytest
|
||||
|
||||
from conftest import option
|
||||
from constants import user_1, user_2
|
||||
from resources.constants import user_1, user_2
|
||||
from test_cases import StatusBackendTestCase
|
||||
from clients.signals import SignalType
|
||||
|
||||
|
||||
@pytest.mark.rpc
|
||||
@pytest.mark.transaction
|
||||
@pytest.mark.wallet
|
||||
|
@ -19,6 +20,7 @@ class TestTransactionFromRoute(StatusBackendTestCase):
|
|||
SignalType.WALLET_TRANSACTION_STATUS_CHANGED.value,
|
||||
SignalType.WALLET_ROUTER_TRANSACTIONS_SENT.value,
|
||||
]
|
||||
|
||||
def test_tx_from_route(self):
|
||||
|
||||
_uuid = str(uuid.uuid4())
|
||||
|
@ -39,28 +41,22 @@ class TestTransactionFromRoute(StatusBackendTestCase):
|
|||
"disabledFromChainIDs": [10, 42161],
|
||||
"disabledToChainIDs": [10, 42161],
|
||||
"gasFeeMode": 1,
|
||||
"fromLockedAmount": {}
|
||||
"fromLockedAmount": {},
|
||||
}
|
||||
]
|
||||
response = self.rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
routes = self.rpc_client.wait_for_signal(SignalType.WALLET_SUGGESTED_ROUTES.value)
|
||||
assert routes['event']['Uuid'] == _uuid
|
||||
assert routes["event"]["Uuid"] == _uuid
|
||||
|
||||
method = "wallet_buildTransactionsFromRoute"
|
||||
params = [
|
||||
{
|
||||
"uuid": _uuid,
|
||||
"slippagePercentage": 0
|
||||
}
|
||||
]
|
||||
params = [{"uuid": _uuid, "slippagePercentage": 0}]
|
||||
response = self.rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
wallet_router_sign_transactions = self.rpc_client.wait_for_signal(
|
||||
SignalType.WALLET_ROUTER_SIGN_TRANSACTIONS.value)
|
||||
wallet_router_sign_transactions = self.rpc_client.wait_for_signal(SignalType.WALLET_ROUTER_SIGN_TRANSACTIONS.value)
|
||||
|
||||
assert wallet_router_sign_transactions['event']['signingDetails']['signOnKeycard'] == False
|
||||
transaction_hashes = wallet_router_sign_transactions['event']['signingDetails']['hashes']
|
||||
assert wallet_router_sign_transactions["event"]["signingDetails"]["signOnKeycard"] is False
|
||||
transaction_hashes = wallet_router_sign_transactions["event"]["signingDetails"]["hashes"]
|
||||
|
||||
assert transaction_hashes, "Transaction hashes are empty!"
|
||||
|
||||
|
@ -69,36 +65,28 @@ class TestTransactionFromRoute(StatusBackendTestCase):
|
|||
for hash in transaction_hashes:
|
||||
|
||||
method = "wallet_signMessage"
|
||||
params = [
|
||||
hash,
|
||||
user_1.address,
|
||||
option.password
|
||||
]
|
||||
params = [hash, user_1.address, option.password]
|
||||
|
||||
response = self.rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
if response.json()["result"].startswith("0x"):
|
||||
tx_signature = response.json()["result"][2:]
|
||||
result = response.json().get("result")
|
||||
assert result and result.startswith("0x"), f"Invalid transaction signature for hash {hash}: {result}"
|
||||
|
||||
tx_signature = result[2:]
|
||||
|
||||
signature = {
|
||||
"r": tx_signature[:64],
|
||||
"s": tx_signature[64:128],
|
||||
"v": tx_signature[128:]
|
||||
"v": tx_signature[128:],
|
||||
}
|
||||
|
||||
tx_signatures[hash] = signature
|
||||
|
||||
method = "wallet_sendRouterTransactionsWithSignatures"
|
||||
params = [
|
||||
{
|
||||
"uuid": _uuid,
|
||||
"Signatures": tx_signatures
|
||||
}
|
||||
]
|
||||
params = [{"uuid": _uuid, "Signatures": tx_signatures}]
|
||||
response = self.rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
tx_status = self.rpc_client.wait_for_signal(
|
||||
SignalType.WALLET_TRANSACTION_STATUS_CHANGED.value)
|
||||
tx_status = self.rpc_client.wait_for_signal(SignalType.WALLET_TRANSACTION_STATUS_CHANGED.value)
|
||||
|
||||
assert tx_status["event"]["chainId"] == 31337
|
||||
assert tx_status["event"]["status"] == "Success"
|
||||
|
|
|
@ -15,7 +15,10 @@ class TestRpc(StatusBackendTestCase):
|
|||
"method, params",
|
||||
[
|
||||
("wakuext_peers", []),
|
||||
("wakuext_activityCenterNotifications", [{"cursor": "", "limit": 20, "activityTypes": [5], "readType": 2}])
|
||||
(
|
||||
"wakuext_activityCenterNotifications",
|
||||
[{"cursor": "", "limit": 20, "activityTypes": [5], "readType": 2}],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_(self, method, params):
|
||||
|
@ -41,17 +44,11 @@ class TestRpcMessaging(StatusBackendTestCase):
|
|||
|
||||
# get chat public key
|
||||
for user in self.user_1, self.user_2:
|
||||
response = self.rpc_client.rpc_request(
|
||||
"accounts_getAccounts", [], _id, url=user.rpc_url
|
||||
)
|
||||
response = self.rpc_client.rpc_request("accounts_getAccounts", [], _id, url=user.rpc_url)
|
||||
self.rpc_client.verify_is_valid_json_rpc_response(response)
|
||||
|
||||
user.chat_public_key = next(
|
||||
(
|
||||
item["public-key"]
|
||||
for item in response.json()["result"]
|
||||
if item["chat"]
|
||||
),
|
||||
(item["public-key"] for item in response.json()["result"] if item["chat"]),
|
||||
None,
|
||||
)
|
||||
|
||||
|
|
|
@ -12,15 +12,22 @@ class TestProfile(StatusBackendTestCase):
|
|||
[
|
||||
("wakuext_setDisplayName", ["new valid username"]),
|
||||
("wakuext_setBio", ["some valid bio"]),
|
||||
("wakuext_setCustomizationColor", [{'customizationColor': 'magenta',
|
||||
'keyUid': '0xea42dd9a4e668b0b76c7a5210ca81576d51cd19cdd0f6a0c22196219dc423f29'}]),
|
||||
(
|
||||
"wakuext_setCustomizationColor",
|
||||
[
|
||||
{
|
||||
"customizationColor": "magenta",
|
||||
"keyUid": "0xea42dd9a4e668b0b76c7a5210ca81576d51cd19cdd0f6a0c22196219dc423f29",
|
||||
}
|
||||
],
|
||||
),
|
||||
("wakuext_setUserStatus", [3, ""]),
|
||||
("wakuext_setSyncingOnMobileNetwork", [{"enabled": False}]),
|
||||
("wakuext_togglePeerSyncing", [{"enabled": True}]),
|
||||
("wakuext_backupData", []),
|
||||
],
|
||||
)
|
||||
def test_(self, method, params):
|
||||
def test_wakuext_(self, method, params):
|
||||
_id = str(random.randint(1, 8888))
|
||||
self.rpc_client.rpc_valid_request(method, params, _id)
|
||||
|
||||
|
@ -32,11 +39,21 @@ class TestProfile(StatusBackendTestCase):
|
|||
("settings_saveSetting", "preview-privacy?", False, True),
|
||||
("settings_saveSetting", "default-sync-period", 777600, 259200),
|
||||
("settings_saveSetting", "appearance", 0, 1),
|
||||
("settings_saveSetting", "profile-pictures-show-to", 2, 1), # obsolete from v1
|
||||
("settings_saveSetting", "profile-pictures-visibility", 2, 1), # obsolete from v1
|
||||
(
|
||||
"settings_saveSetting",
|
||||
"profile-pictures-show-to",
|
||||
2,
|
||||
1,
|
||||
), # obsolete from v1
|
||||
(
|
||||
"settings_saveSetting",
|
||||
"profile-pictures-visibility",
|
||||
2,
|
||||
1,
|
||||
), # obsolete from v1
|
||||
],
|
||||
)
|
||||
def test_(self, method, setting_name, default_value, changed_value):
|
||||
def test_settings_(self, method, setting_name, default_value, changed_value):
|
||||
_id = str(random.randint(1, 8888))
|
||||
|
||||
logging.info("Step: check that %s is %s by default " % (setting_name, default_value))
|
||||
|
@ -59,14 +76,14 @@ class TestProfile(StatusBackendTestCase):
|
|||
("settings_saveSetting", "remember-syncing-choice?", True),
|
||||
("settings_saveSetting", "remote-push-notifications-enabled?", True),
|
||||
("settings_saveSetting", "syncing-on-mobile-network?", True),
|
||||
## advanced token settings
|
||||
# advanced token settings
|
||||
("settings_saveSetting", "wallet-set-up-passed?", True),
|
||||
("settings_saveSetting", "opensea-enabled?", True),
|
||||
("settings_saveSetting", "waku-bloom-filter-mode", True),
|
||||
("settings_saveSetting", "webview-allow-permission-requests?", True),
|
||||
("settings_saveSetting", "token-group-by-community?", True),
|
||||
("settings_saveSetting", "display-assets-below-balance?", True),
|
||||
## token management settings for collectibles
|
||||
# token management settings for collectibles
|
||||
("settings_saveSetting", "collectible-group-by-collection?", True),
|
||||
("settings_saveSetting", "collectible-group-by-community?", True),
|
||||
],
|
||||
|
@ -89,7 +106,11 @@ class TestProfile(StatusBackendTestCase):
|
|||
[
|
||||
("settings_saveSetting", "send-status-updates?", False),
|
||||
("settings_saveSetting", "link-preview-request-enabled", False),
|
||||
("settings_saveSetting", "show-community-asset-when-sending-tokens?", False),
|
||||
(
|
||||
"settings_saveSetting",
|
||||
"show-community-asset-when-sending-tokens?",
|
||||
False,
|
||||
),
|
||||
("settings_saveSetting", "url-unfurling-mode", 0),
|
||||
],
|
||||
)
|
||||
|
@ -104,4 +125,3 @@ class TestProfile(StatusBackendTestCase):
|
|||
self.rpc_client.rpc_valid_request(method, [setting_name, set_value], _id)
|
||||
response = self.rpc_client.rpc_valid_request("settings_getSettings", [])
|
||||
assert setting_name not in response.json()["result"]
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import json
|
||||
import random
|
||||
import wallet_utils
|
||||
from utils import wallet_utils
|
||||
import pytest
|
||||
|
||||
from constants import user_1
|
||||
from resources.constants import user_1
|
||||
from test_cases import StatusBackendTestCase
|
||||
from clients.signals import SignalType
|
||||
|
||||
|
@ -11,10 +11,12 @@ EventActivityFilteringDone = "wallet-activity-filtering-done"
|
|||
EventActivityFilteringUpdate = "wallet-activity-filtering-entries-updated"
|
||||
EventActivitySessionUpdated = "wallet-activity-session-updated"
|
||||
|
||||
|
||||
def validate_entry(entry, tx_data):
|
||||
assert entry["transactions"][0]["chainId"] == tx_data["tx_status"]["chainId"]
|
||||
assert entry["transactions"][0]["hash"] == tx_data["tx_status"]["hash"]
|
||||
|
||||
|
||||
@pytest.mark.wallet
|
||||
@pytest.mark.rpc
|
||||
class TestWalletActivitySession(StatusBackendTestCase):
|
||||
|
@ -25,64 +27,88 @@ class TestWalletActivitySession(StatusBackendTestCase):
|
|||
"wallet.router.sign-transactions",
|
||||
"wallet.router.sending-transactions-started",
|
||||
"wallet.transaction.status-changed",
|
||||
"wallet.router.transactions-sent"]
|
||||
"wallet.router.transactions-sent",
|
||||
]
|
||||
|
||||
def setup_method(self):
|
||||
self.request_id = str(random.randint(1, 8888))
|
||||
|
||||
def test_wallet_start_activity_filter_session(self):
|
||||
tx_data = [] # (routes, build_tx, tx_signatures, tx_status)
|
||||
tx_data = [] # (routes, build_tx, tx_signatures, tx_status)
|
||||
# Set up a transactions for account before starting session
|
||||
tx_data.append(wallet_utils.send_router_transaction(self.rpc_client))
|
||||
|
||||
# Start activity session
|
||||
method = "wallet_startActivityFilterSessionV2"
|
||||
params = [[user_1.address], [self.network_id],
|
||||
{"period": {"startTimestamp": 0, "endTimestamp": 0}, "types": [], "statuses": [],
|
||||
"counterpartyAddresses": [], "assets": [], "collectibles": [], "filterOutAssets": False,
|
||||
"filterOutCollectibles": False}, 10]
|
||||
self.rpc_client.prepare_wait_for_signal("wallet", 1, lambda signal : signal["event"]["type"] == EventActivityFilteringDone)
|
||||
params = [
|
||||
[user_1.address],
|
||||
[self.network_id],
|
||||
{
|
||||
"period": {"startTimestamp": 0, "endTimestamp": 0},
|
||||
"types": [],
|
||||
"statuses": [],
|
||||
"counterpartyAddresses": [],
|
||||
"assets": [],
|
||||
"collectibles": [],
|
||||
"filterOutAssets": False,
|
||||
"filterOutCollectibles": False,
|
||||
},
|
||||
10,
|
||||
]
|
||||
self.rpc_client.prepare_wait_for_signal(
|
||||
"wallet",
|
||||
1,
|
||||
lambda signal: signal["event"]["type"] == EventActivityFilteringDone,
|
||||
)
|
||||
response = self.rpc_client.rpc_valid_request(method, params, self.request_id)
|
||||
event_response = self.rpc_client.wait_for_signal("wallet", timeout=10)['event']
|
||||
event_response = self.rpc_client.wait_for_signal("wallet", timeout=10)["event"]
|
||||
|
||||
# Check response
|
||||
# Check response
|
||||
sessionID = int(response.json()["result"])
|
||||
assert sessionID > 0
|
||||
|
||||
# Check response event
|
||||
assert int(event_response['requestId']) == sessionID
|
||||
message = json.loads(event_response['message'].replace("'", "\""))
|
||||
assert int(message['errorCode']) == 1
|
||||
assert len(message['activities']) > 0 # Should have at least 1 entry
|
||||
assert int(event_response["requestId"]) == sessionID
|
||||
message = json.loads(event_response["message"].replace("'", '"'))
|
||||
assert int(message["errorCode"]) == 1
|
||||
assert len(message["activities"]) > 0 # Should have at least 1 entry
|
||||
# First activity entry should match last sent transaction
|
||||
validate_entry(message['activities'][0], tx_data[-1])
|
||||
validate_entry(message["activities"][0], tx_data[-1])
|
||||
|
||||
# Trigger new transaction
|
||||
self.rpc_client.prepare_wait_for_signal("wallet", 1, lambda signal : signal["event"]["type"] == EventActivitySessionUpdated and signal['event']['requestId'] == sessionID)
|
||||
self.rpc_client.prepare_wait_for_signal(
|
||||
"wallet",
|
||||
1,
|
||||
lambda signal: signal["event"]["type"] == EventActivitySessionUpdated and signal["event"]["requestId"] == sessionID,
|
||||
)
|
||||
tx_data.append(wallet_utils.send_router_transaction(self.rpc_client))
|
||||
print(tx_data[-1])
|
||||
event_response = self.rpc_client.wait_for_signal("wallet", timeout=10)['event']
|
||||
event_response = self.rpc_client.wait_for_signal("wallet", timeout=10)["event"]
|
||||
|
||||
# Check response event
|
||||
assert int(event_response['requestId']) == sessionID
|
||||
message = json.loads(event_response['message'].replace("'", "\""))
|
||||
assert message['hasNewOnTop'] # New entries reported
|
||||
assert int(event_response["requestId"]) == sessionID
|
||||
message = json.loads(event_response["message"].replace("'", '"'))
|
||||
assert message["hasNewOnTop"] # New entries reported
|
||||
|
||||
# Reset activity session
|
||||
method = "wallet_resetActivityFilterSession"
|
||||
params = [sessionID, 10]
|
||||
self.rpc_client.prepare_wait_for_signal("wallet", 1, lambda signal : signal["event"]["type"] == EventActivityFilteringDone and signal['event']['requestId'] == sessionID)
|
||||
self.rpc_client.prepare_wait_for_signal(
|
||||
"wallet",
|
||||
1,
|
||||
lambda signal: signal["event"]["type"] == EventActivityFilteringDone and signal["event"]["requestId"] == sessionID,
|
||||
)
|
||||
response = self.rpc_client.rpc_valid_request(method, params, self.request_id)
|
||||
event_response = self.rpc_client.wait_for_signal("wallet", timeout=10)['event']
|
||||
event_response = self.rpc_client.wait_for_signal("wallet", timeout=10)["event"]
|
||||
|
||||
# Check response event
|
||||
assert int(event_response['requestId']) == sessionID
|
||||
message = json.loads(event_response['message'].replace("'", "\""))
|
||||
assert int(message['errorCode']) == 1
|
||||
assert len(message['activities']) > 1 # Should have at least 2 entries
|
||||
assert int(event_response["requestId"]) == sessionID
|
||||
message = json.loads(event_response["message"].replace("'", '"'))
|
||||
assert int(message["errorCode"]) == 1
|
||||
assert len(message["activities"]) > 1 # Should have at least 2 entries
|
||||
|
||||
# First activity entry should match last sent transaction
|
||||
validate_entry(message['activities'][0], tx_data[-1])
|
||||
validate_entry(message["activities"][0], tx_data[-1])
|
||||
|
||||
# Second activity entry should match second to last sent transaction
|
||||
validate_entry(message['activities'][1], tx_data[-2])
|
||||
validate_entry(message["activities"][1], tx_data[-2])
|
||||
|
|
|
@ -5,8 +5,8 @@ import jsonschema
|
|||
import pytest
|
||||
|
||||
from conftest import option
|
||||
from constants import user_1
|
||||
from test_cases import StatusBackendTestCase, TransactionTestCase, StatusDTestCase
|
||||
from resources.constants import user_1
|
||||
from test_cases import StatusBackendTestCase, TransactionTestCase
|
||||
|
||||
|
||||
@pytest.mark.wallet
|
||||
|
@ -18,12 +18,12 @@ class TestTransactionRpc(TransactionTestCase):
|
|||
"method, params",
|
||||
[
|
||||
(
|
||||
"wallet_checkRecentHistoryForChainIDs",
|
||||
[[31337], ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"]],
|
||||
"wallet_checkRecentHistoryForChainIDs",
|
||||
[[31337], ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"]],
|
||||
),
|
||||
(
|
||||
"wallet_getPendingTransactionsForIdentities",
|
||||
[[{"chainId": None, "hash": None}]],
|
||||
"wallet_getPendingTransactionsForIdentities",
|
||||
[[{"chainId": None, "hash": None}]],
|
||||
),
|
||||
],
|
||||
)
|
||||
|
@ -42,35 +42,41 @@ class TestTransactionRpc(TransactionTestCase):
|
|||
self.rpc_client.verify_is_valid_json_rpc_response(response)
|
||||
|
||||
# how to create schema:
|
||||
# from schema_builder import CustomSchemaBuilder
|
||||
# from utils.schema_builder import CustomSchemaBuilder
|
||||
# CustomSchemaBuilder(method).create_schema(response.json())
|
||||
|
||||
with open(f"{option.base_dir}/schemas/wallet_createMultiTransaction/transferTx_positive", "r") as schema:
|
||||
with open(
|
||||
f"{option.base_dir}/schemas/wallet_createMultiTransaction/transferTx_positive",
|
||||
"r",
|
||||
) as schema:
|
||||
jsonschema.validate(instance=response.json(), schema=json.load(schema))
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"method, changed_values, expected_error_code, expected_error_text",
|
||||
[
|
||||
(
|
||||
"transferTx_value_not_enough_balance",
|
||||
{'value': '0x21e438ea8139cd35004'}, -32000, "Insufficient funds for gas",
|
||||
"transferTx_value_not_enough_balance",
|
||||
{"value": "0x21e438ea8139cd35004"},
|
||||
-32000,
|
||||
"Insufficient funds for gas",
|
||||
),
|
||||
(
|
||||
"transferTx_from_from_invalid_string",
|
||||
{'from': 'some_invalid_address'}, -32602, "cannot unmarshal hex string without 0x prefix",
|
||||
"transferTx_from_from_invalid_string",
|
||||
{"from": "some_invalid_address"},
|
||||
-32602,
|
||||
"cannot unmarshal hex string without 0x prefix",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_create_multi_transaction_validation(self, method,
|
||||
changed_values,
|
||||
expected_error_code, expected_error_text):
|
||||
def test_create_multi_transaction_validation(self, method, changed_values, expected_error_code, expected_error_text):
|
||||
response = self.wallet_create_multi_transaction(**changed_values)
|
||||
self.rpc_client.verify_is_json_rpc_error(response)
|
||||
actual_error_code, actual_error_text = response.json()['error']['code'], response.json()['error']['message']
|
||||
assert expected_error_code == actual_error_code, \
|
||||
f"got code: {actual_error_code} instead of expected: {expected_error_code}"
|
||||
assert expected_error_text in actual_error_text, \
|
||||
f"got error: {actual_error_text} that does not include: {expected_error_text}"
|
||||
actual_error_code, actual_error_text = (
|
||||
response.json()["error"]["code"],
|
||||
response.json()["error"]["message"],
|
||||
)
|
||||
assert expected_error_code == actual_error_code, f"got code: {actual_error_code} instead of expected: {expected_error_code}"
|
||||
assert expected_error_text in actual_error_text, f"got error: {actual_error_text} that does not include: {expected_error_text}"
|
||||
|
||||
self.rpc_client.verify_json_schema(response.json(), "wallet_createMultiTransaction/transferTx_error")
|
||||
|
||||
|
@ -87,19 +93,69 @@ class TestRpc(StatusBackendTestCase):
|
|||
("wallet_getTokenList", []),
|
||||
("wallet_getCryptoOnRamps", []),
|
||||
("wallet_getCachedCurrencyFormats", []),
|
||||
("wallet_fetchPrices",
|
||||
[["WETH9", "USDC", "ZEENUS", "EUROC", "WEENUS", "XEENUS", "WETH", "ETH", "STT", "UNI", "YEENUS", "DAI"],
|
||||
["usd"]]),
|
||||
|
||||
("wallet_fetchMarketValues",
|
||||
[["WETH9", "USDC", "ZEENUS", "EUROC", "WEENUS", "XEENUS", "WETH", "ETH", "STT", "UNI", "YEENUS", "DAI"],
|
||||
"usd"]),
|
||||
("wallet_fetchTokenDetails",
|
||||
[["WETH9", "USDC", "ZEENUS", "EUROC", "WEENUS", "XEENUS", "WETH", "ETH", "STT", "UNI", "YEENUS", "DAI"]]),
|
||||
(
|
||||
"wallet_fetchPrices",
|
||||
[
|
||||
[
|
||||
"WETH9",
|
||||
"USDC",
|
||||
"ZEENUS",
|
||||
"EUROC",
|
||||
"WEENUS",
|
||||
"XEENUS",
|
||||
"WETH",
|
||||
"ETH",
|
||||
"STT",
|
||||
"UNI",
|
||||
"YEENUS",
|
||||
"DAI",
|
||||
],
|
||||
["usd"],
|
||||
],
|
||||
),
|
||||
(
|
||||
"wallet_fetchMarketValues",
|
||||
[
|
||||
[
|
||||
"WETH9",
|
||||
"USDC",
|
||||
"ZEENUS",
|
||||
"EUROC",
|
||||
"WEENUS",
|
||||
"XEENUS",
|
||||
"WETH",
|
||||
"ETH",
|
||||
"STT",
|
||||
"UNI",
|
||||
"YEENUS",
|
||||
"DAI",
|
||||
],
|
||||
"usd",
|
||||
],
|
||||
),
|
||||
(
|
||||
"wallet_fetchTokenDetails",
|
||||
[
|
||||
[
|
||||
"WETH9",
|
||||
"USDC",
|
||||
"ZEENUS",
|
||||
"EUROC",
|
||||
"WEENUS",
|
||||
"XEENUS",
|
||||
"WETH",
|
||||
"ETH",
|
||||
"STT",
|
||||
"UNI",
|
||||
"YEENUS",
|
||||
"DAI",
|
||||
]
|
||||
],
|
||||
),
|
||||
("wallet_checkRecentHistoryForChainIDs", [[31337], [user_1.address]]),
|
||||
("wallet_getWalletConnectActiveSessions", [1728995277]),
|
||||
("wallet_stopSuggestedRoutesAsyncCalculation", []),
|
||||
]
|
||||
],
|
||||
)
|
||||
def test_(self, method, params):
|
||||
_id = str(random.randint(1, 8888))
|
||||
|
|
|
@ -3,7 +3,7 @@ import random
|
|||
|
||||
import pytest
|
||||
|
||||
from constants import user_1
|
||||
from resources.constants import user_1
|
||||
from test_cases import StatusBackendTestCase
|
||||
|
||||
|
||||
|
@ -13,8 +13,7 @@ class TestWalletSignals(StatusBackendTestCase):
|
|||
|
||||
def setup_class(self):
|
||||
self.await_signals.append("wallet")
|
||||
super().setup_class(self)
|
||||
|
||||
super().setup_class()
|
||||
|
||||
def setup_method(self):
|
||||
self.request_id = str(random.randint(1, 8888))
|
||||
|
@ -22,26 +21,49 @@ class TestWalletSignals(StatusBackendTestCase):
|
|||
@pytest.mark.skip
|
||||
def test_wallet_get_owned_collectibles_async(self):
|
||||
method = "wallet_getOwnedCollectiblesAsync"
|
||||
params = [0, [self.network_id, ], [user_1.address], None, 0, 25, 1,
|
||||
{"fetch-type": 2, "max-cache-age-seconds": 3600}]
|
||||
params = [
|
||||
0,
|
||||
[
|
||||
self.network_id,
|
||||
],
|
||||
[user_1.address],
|
||||
None,
|
||||
0,
|
||||
25,
|
||||
1,
|
||||
{"fetch-type": 2, "max-cache-age-seconds": 3600},
|
||||
]
|
||||
self.rpc_client.rpc_valid_request(method, params, self.request_id)
|
||||
signal_response = self.rpc_client.wait_for_signal("wallet", timeout=60)
|
||||
self.rpc_client.verify_json_schema(signal_response, method)
|
||||
assert signal_response['event']['type'] == "wallet-owned-collectibles-filtering-done"
|
||||
message = json.loads(signal_response['event']['message'].replace("'", "\""))
|
||||
assert user_1.address in message['ownershipStatus'].keys()
|
||||
assert signal_response["event"]["type"] == "wallet-owned-collectibles-filtering-done"
|
||||
message = json.loads(signal_response["event"]["message"].replace("'", '"'))
|
||||
assert user_1.address in message["ownershipStatus"].keys()
|
||||
|
||||
@pytest.mark.skip
|
||||
def test_wallet_filter_activity_async(self):
|
||||
method = "wallet_filterActivityAsync"
|
||||
params = [1, [user_1.address], [self.network_id],
|
||||
{"period": {"startTimestamp": 0, "endTimestamp": 0}, "types": [], "statuses": [],
|
||||
"counterpartyAddresses": [], "assets": [], "collectibles": [], "filterOutAssets": False,
|
||||
"filterOutCollectibles": False}, 0, 50]
|
||||
params = [
|
||||
1,
|
||||
[user_1.address],
|
||||
[self.network_id],
|
||||
{
|
||||
"period": {"startTimestamp": 0, "endTimestamp": 0},
|
||||
"types": [],
|
||||
"statuses": [],
|
||||
"counterpartyAddresses": [],
|
||||
"assets": [],
|
||||
"collectibles": [],
|
||||
"filterOutAssets": False,
|
||||
"filterOutCollectibles": False,
|
||||
},
|
||||
0,
|
||||
50,
|
||||
]
|
||||
self.rpc_client.rpc_valid_request(method, params, self.request_id)
|
||||
signal_response = self.rpc_client.wait_for_signal("wallet", timeout=60)
|
||||
self.rpc_client.verify_json_schema(signal_response, method)
|
||||
assert signal_response['event']['type'] == "wallet-activity-filtering-done"
|
||||
message = json.loads(signal_response['event']['message'].replace("'", "\""))
|
||||
for item in message['activities']:
|
||||
assert user_1.address in item['sender'], item['recipient']
|
||||
assert signal_response["event"]["type"] == "wallet-activity-filtering-done"
|
||||
message = json.loads(signal_response["event"]["message"].replace("'", '"'))
|
||||
for item in message["activities"]:
|
||||
assert user_1.address in item["sender"], item["recipient"]
|
||||
|
|
|
@ -2,19 +2,17 @@ import json
|
|||
import logging
|
||||
import jsonschema
|
||||
import uuid
|
||||
import threading
|
||||
import time
|
||||
|
||||
|
||||
from conftest import option
|
||||
from constants import user_1, user_2
|
||||
from resources.constants import user_1, user_2
|
||||
|
||||
from clients.signals import SignalClient
|
||||
|
||||
def verify_json_schema(response, method):
|
||||
with open(f"{option.base_dir}/schemas/{method}", "r") as schema:
|
||||
jsonschema.validate(instance=response,
|
||||
schema=json.load(schema))
|
||||
|
||||
jsonschema.validate(instance=response, schema=json.load(schema))
|
||||
|
||||
|
||||
def get_suggested_routes(rpc_client, **kwargs):
|
||||
_uuid = str(uuid.uuid4())
|
||||
amount_in = "0xde0b6b3a7640000"
|
||||
|
@ -33,47 +31,44 @@ def get_suggested_routes(rpc_client, **kwargs):
|
|||
"disabledFromChainIDs": [10, 42161],
|
||||
"disabledToChainIDs": [10, 42161],
|
||||
"gasFeeMode": 1,
|
||||
"fromLockedAmount": {}
|
||||
"fromLockedAmount": {},
|
||||
}
|
||||
for key, new_value in kwargs.items():
|
||||
if key in input_params:
|
||||
input_params[key] = new_value
|
||||
else:
|
||||
logging.info(
|
||||
f"Warning: The key '{key}' does not exist in the input_params parameters and will be ignored.")
|
||||
logging.info(f"Warning: The key '{key}' does not exist in the input_params parameters and will be ignored.")
|
||||
params = [input_params]
|
||||
|
||||
rpc_client.prepare_wait_for_signal("wallet.suggested.routes", 1)
|
||||
_ = rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
routes = rpc_client.wait_for_signal("wallet.suggested.routes")
|
||||
assert routes['event']['Uuid'] == _uuid
|
||||
assert routes["event"]["Uuid"] == _uuid
|
||||
|
||||
return routes["event"]
|
||||
|
||||
return routes['event']
|
||||
|
||||
def build_transactions_from_route(rpc_client, uuid, **kwargs):
|
||||
method = "wallet_buildTransactionsFromRoute"
|
||||
build_tx_params = {
|
||||
"uuid": uuid,
|
||||
"slippagePercentage": 0
|
||||
}
|
||||
build_tx_params = {"uuid": uuid, "slippagePercentage": 0}
|
||||
for key, new_value in kwargs.items():
|
||||
if key in build_tx_params:
|
||||
build_tx_params[key] = new_value
|
||||
else:
|
||||
logging.info(
|
||||
f"Warning: The key '{key}' does not exist in the build_tx_params parameters and will be ignored.")
|
||||
logging.info(f"Warning: The key '{key}' does not exist in the build_tx_params parameters and will be ignored.")
|
||||
params = [build_tx_params]
|
||||
_ = rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
wallet_router_sign_transactions = rpc_client.wait_for_signal("wallet.router.sign-transactions")
|
||||
|
||||
assert wallet_router_sign_transactions['event']['signingDetails']['signOnKeycard'] == False
|
||||
transaction_hashes = wallet_router_sign_transactions['event']['signingDetails']['hashes']
|
||||
assert wallet_router_sign_transactions["event"]["signingDetails"]["signOnKeycard"] is False
|
||||
transaction_hashes = wallet_router_sign_transactions["event"]["signingDetails"]["hashes"]
|
||||
|
||||
assert transaction_hashes, "Transaction hashes are empty!"
|
||||
|
||||
return wallet_router_sign_transactions['event']
|
||||
return wallet_router_sign_transactions["event"]
|
||||
|
||||
|
||||
def sign_messages(rpc_client, hashes):
|
||||
tx_signatures = {}
|
||||
|
@ -81,51 +76,45 @@ def sign_messages(rpc_client, hashes):
|
|||
for hash in hashes:
|
||||
|
||||
method = "wallet_signMessage"
|
||||
params = [
|
||||
hash,
|
||||
user_1.address,
|
||||
option.password
|
||||
]
|
||||
params = [hash, user_1.address, option.password]
|
||||
|
||||
response = rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
if response.json()["result"].startswith("0x"):
|
||||
tx_signature = response.json()["result"][2:]
|
||||
result = response.json().get("result")
|
||||
assert result and result.startswith("0x"), f"Invalid transaction signature for hash {hash}: {result}"
|
||||
|
||||
tx_signature = result[2:]
|
||||
|
||||
signature = {
|
||||
"r": tx_signature[:64],
|
||||
"s": tx_signature[64:128],
|
||||
"v": tx_signature[128:]
|
||||
"v": tx_signature[128:],
|
||||
}
|
||||
|
||||
tx_signatures[hash] = signature
|
||||
return tx_signatures
|
||||
|
||||
|
||||
def send_router_transactions_with_signatures(rpc_client, uuid, tx_signatures):
|
||||
method = "wallet_sendRouterTransactionsWithSignatures"
|
||||
params = [
|
||||
{
|
||||
"uuid": uuid,
|
||||
"Signatures": tx_signatures
|
||||
}
|
||||
]
|
||||
params = [{"uuid": uuid, "Signatures": tx_signatures}]
|
||||
_ = rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
tx_status = rpc_client.wait_for_signal(
|
||||
"wallet.transaction.status-changed")
|
||||
tx_status = rpc_client.wait_for_signal("wallet.transaction.status-changed")
|
||||
|
||||
assert tx_status["event"]["status"] == "Success"
|
||||
|
||||
return tx_status["event"]
|
||||
|
||||
|
||||
def send_router_transaction(rpc_client, **kwargs):
|
||||
routes = get_suggested_routes(rpc_client, **kwargs)
|
||||
build_tx = build_transactions_from_route(rpc_client, routes['Uuid'])
|
||||
tx_signatures = sign_messages(rpc_client, build_tx['signingDetails']['hashes'])
|
||||
tx_status = send_router_transactions_with_signatures(rpc_client, routes['Uuid'], tx_signatures)
|
||||
build_tx = build_transactions_from_route(rpc_client, routes["Uuid"])
|
||||
tx_signatures = sign_messages(rpc_client, build_tx["signingDetails"]["hashes"])
|
||||
tx_status = send_router_transactions_with_signatures(rpc_client, routes["Uuid"], tx_signatures)
|
||||
return {
|
||||
"routes": routes,
|
||||
"build_tx": build_tx,
|
||||
"tx_signatures": tx_signatures,
|
||||
"tx_status": tx_status
|
||||
"tx_status": tx_status,
|
||||
}
|
Loading…
Reference in New Issue