test_: added transaction from route test
This commit is contained in:
parent
28506bcd17
commit
107e2cb8da
|
@ -18,7 +18,16 @@
|
|||
"Networks": [
|
||||
{
|
||||
"ChainID": 31337,
|
||||
"RPCURL": "http://anvil:8545"
|
||||
"ChainName": "Anvil",
|
||||
"DefaultRPCURL": "http://anvil:8545",
|
||||
"RPCURL": "http://anvil:8545",
|
||||
"ShortName": "eth",
|
||||
"NativeCurrencyName": "Ether",
|
||||
"NativeCurrencySymbol": "ETH",
|
||||
"NativeCurrencyDecimals": 18,
|
||||
"IsTest": false,
|
||||
"Layer": 1,
|
||||
"Enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -21,6 +21,12 @@ def pytest_addoption(parser):
|
|||
help="",
|
||||
default="ws://0.0.0.0:8354",
|
||||
)
|
||||
parser.addoption(
|
||||
"--anvil_url",
|
||||
action="store",
|
||||
help="",
|
||||
default="http://0.0.0.0:8545",
|
||||
)
|
||||
parser.addoption(
|
||||
"--password",
|
||||
action="store",
|
||||
|
@ -35,11 +41,11 @@ class Account():
|
|||
private_key: str
|
||||
|
||||
user_1 = Account(
|
||||
address="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
||||
address="0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
|
||||
)
|
||||
user_2 = Account(
|
||||
address="0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
|
||||
address="0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
|
||||
private_key="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d",
|
||||
)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ services:
|
|||
image: ghcr.io/foundry-rs/foundry:latest
|
||||
platform: linux/amd64
|
||||
command:
|
||||
- anvil --host 0.0.0.0
|
||||
- anvil --host 0.0.0.0 --block-time 2
|
||||
|
||||
deploy-sntv2:
|
||||
platform: linux/amd64
|
||||
|
|
|
@ -16,6 +16,9 @@ services:
|
|||
"--password", "Strong12345",
|
||||
"--dir", "/tmp/status-go-data", # Keep in sync with `config.json/DataDir` value. Later this arg will not be needed.
|
||||
]
|
||||
ports:
|
||||
- 3333:3333
|
||||
# - 8354:8354 # use for local debbuging only
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -X POST --data '{\"jsonrpc\":\"2.0\",\"method\":\"net_version\",\"params\":[],\"id\":1}' -H 'Content-Type: application/json' http://0.0.0.0:3333 || exit 1"]
|
||||
interval: 5s
|
||||
|
@ -72,6 +75,8 @@ services:
|
|||
"-m", "wallet",
|
||||
"--rpc_url=http://status-go:3333",
|
||||
"--rpc_url_2=http://status-go-no-funds:3333",
|
||||
"--anvil_url=http://anvil:8545",
|
||||
"--ws_url=ws://status-go:8354",
|
||||
"--junitxml=/tests-rpc/reports/report.xml",
|
||||
]
|
||||
volumes:
|
||||
|
|
|
@ -3,6 +3,7 @@ import websocket
|
|||
import threading
|
||||
import logging
|
||||
import jsonschema
|
||||
import time
|
||||
import requests
|
||||
from conftest import option, user_1, user_2
|
||||
|
||||
|
@ -16,9 +17,11 @@ class RpcTestCase:
|
|||
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.")
|
||||
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
|
||||
|
@ -40,7 +43,6 @@ class RpcTestCase:
|
|||
assert response.content
|
||||
self._try_except_JSONDecodeError_KeyError(response, "error")
|
||||
|
||||
|
||||
def rpc_request(self, method, params=[], _id=None, client=None, url=None):
|
||||
client = client if client else requests.Session()
|
||||
url = url if url else option.rpc_url
|
||||
|
@ -60,10 +62,8 @@ class RpcTestCase:
|
|||
schema=json.load(schema))
|
||||
|
||||
|
||||
|
||||
class TransactionTestCase(RpcTestCase):
|
||||
|
||||
|
||||
def wallet_create_multi_transaction(self, **kwargs):
|
||||
method = "wallet_createMultiTransaction"
|
||||
transferTx_data = {
|
||||
|
@ -81,7 +81,8 @@ class TransactionTestCase(RpcTestCase):
|
|||
if key in transferTx_data:
|
||||
transferTx_data[key] = new_value
|
||||
else:
|
||||
print(f"Warning: The key '{key}' does not exist in the transferTx parameters and will be ignored.")
|
||||
print(
|
||||
f"Warning: The key '{key}' does not exist in the transferTx parameters and will be ignored.")
|
||||
params = [
|
||||
{
|
||||
"fromAddress": user_1.address,
|
||||
|
@ -116,10 +117,23 @@ class TransactionTestCase(RpcTestCase):
|
|||
|
||||
class SignalTestCase(RpcTestCase):
|
||||
|
||||
received_signals = []
|
||||
await_signals = []
|
||||
received_signals = {}
|
||||
|
||||
def _on_message(self, ws, signal):
|
||||
self.received_signals.append(signal)
|
||||
def on_message(self, ws, signal):
|
||||
signal = json.loads(signal)
|
||||
if signal.get("type") in self.await_signals:
|
||||
self.received_signals[signal["type"]] = signal
|
||||
|
||||
def wait_for_signal(self, signal_type, timeout=10):
|
||||
start_time = time.time()
|
||||
while signal_type not in self.received_signals:
|
||||
time_passed = time.time() - start_time
|
||||
if time_passed >= timeout:
|
||||
raise TimeoutError(
|
||||
f"Signal {signal_type} is not received in {timeout} seconds")
|
||||
time.sleep(0.5)
|
||||
return self.received_signals[signal_type]
|
||||
|
||||
def _on_error(self, ws, error):
|
||||
logging.info(f"Error: {error}")
|
||||
|
@ -134,7 +148,7 @@ class SignalTestCase(RpcTestCase):
|
|||
self.url = f"{option.ws_url}/signals"
|
||||
|
||||
ws = websocket.WebSocketApp(self.url,
|
||||
on_message=self._on_message,
|
||||
on_message=self.on_message,
|
||||
on_error=self._on_error,
|
||||
on_close=self._on_close)
|
||||
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
import pytest
|
||||
import time
|
||||
import uuid
|
||||
from conftest import user_1, user_2, option
|
||||
from test_cases import SignalTestCase
|
||||
|
||||
|
||||
@pytest.mark.rpc
|
||||
@pytest.mark.transaction
|
||||
@pytest.mark.wallet
|
||||
class TestTransactionFromRoute(SignalTestCase):
|
||||
|
||||
await_signals = [
|
||||
"wallet.suggested.routes",
|
||||
"wallet.router.sign-transactions",
|
||||
"wallet.router.sending-transactions-started",
|
||||
"wallet.transaction.status-changed",
|
||||
"wallet.router.transactions-sent"
|
||||
]
|
||||
|
||||
def test_tx_from_route(self):
|
||||
|
||||
_uuid = str(uuid.uuid4())
|
||||
amount_in = "0xde0b6b3a7640000"
|
||||
|
||||
method = "wallet_getSuggestedRoutesAsync"
|
||||
params = [
|
||||
{
|
||||
"uuid": _uuid,
|
||||
"sendType": 0,
|
||||
"addrFrom": user_1.address,
|
||||
"addrTo": user_2.address,
|
||||
"amountIn": amount_in,
|
||||
"amountOut": "0x0",
|
||||
"tokenID": "ETH",
|
||||
"tokenIDIsOwnerToken": False,
|
||||
"toTokenID": "",
|
||||
"disabledFromChainIDs": [10, 42161],
|
||||
"disabledToChainIDs": [10, 42161],
|
||||
"gasFeeMode": 1,
|
||||
"fromLockedAmount": {}
|
||||
}
|
||||
]
|
||||
response = self.rpc_request(method, params)
|
||||
self.verify_is_valid_json_rpc_response(response)
|
||||
|
||||
routes = self.wait_for_signal("wallet.suggested.routes")
|
||||
assert routes['event']['Uuid'] == _uuid
|
||||
|
||||
method = "wallet_buildTransactionsFromRoute"
|
||||
params = [
|
||||
{
|
||||
"uuid": _uuid,
|
||||
"slippagePercentage": 0
|
||||
}
|
||||
]
|
||||
response = self.rpc_request(method, params)
|
||||
self.verify_is_valid_json_rpc_response(response)
|
||||
|
||||
self.wait_for_signal("wallet.router.sign-transactions")
|
||||
|
||||
assert self.received_signals[
|
||||
'wallet.router.sign-transactions']['event']['signingDetails']['signOnKeycard'] == False
|
||||
transaction_hashes = self.received_signals[
|
||||
'wallet.router.sign-transactions']['event']['signingDetails']['hashes']
|
||||
|
||||
assert transaction_hashes, "Transaction hashes are empty!"
|
||||
|
||||
tx_signatures = {}
|
||||
|
||||
for hash in transaction_hashes:
|
||||
|
||||
method = "wallet_signMessage"
|
||||
params = [
|
||||
hash,
|
||||
user_1.address,
|
||||
option.password
|
||||
]
|
||||
|
||||
response = self.rpc_request(method, params)
|
||||
self.verify_is_valid_json_rpc_response(response)
|
||||
|
||||
if response.json()["result"].startswith("0x"):
|
||||
tx_signature = response.json()["result"][2:]
|
||||
|
||||
signature = {
|
||||
"r": tx_signature[:64],
|
||||
"s": tx_signature[64:128],
|
||||
"v": tx_signature[128:]
|
||||
}
|
||||
|
||||
tx_signatures[hash] = signature
|
||||
|
||||
method = "wallet_sendRouterTransactionsWithSignatures"
|
||||
params = [
|
||||
{
|
||||
"uuid": _uuid,
|
||||
"Signatures": tx_signatures
|
||||
}
|
||||
]
|
||||
response = self.rpc_request(method, params)
|
||||
self.verify_is_valid_json_rpc_response(response)
|
||||
|
||||
tx_status = self.wait_for_signal("wallet.transaction.status-changed")
|
||||
|
||||
|
||||
assert tx_status["event"]["chainId"] == 31337
|
||||
assert tx_status["event"]["status"] == "Success"
|
||||
tx_hash = tx_status["event"]["hash"]
|
||||
|
||||
method = "eth_getTransactionByHash"
|
||||
params = [tx_hash]
|
||||
|
||||
response = self.rpc_request(method, params, url=option.anvil_url)
|
||||
self.verify_is_valid_json_rpc_response(response)
|
||||
tx_details = response.json()["result"]
|
||||
|
||||
assert tx_details["value"] == amount_in
|
||||
assert tx_details["to"] == user_2.address
|
||||
assert tx_details["from"] == user_1.address
|
|
@ -84,8 +84,7 @@ class TestRpc(RpcTestCase):
|
|||
("wallet_getEthereumChains", []),
|
||||
("wallet_getTokenList", []),
|
||||
("wallet_getCryptoOnRamps", []),
|
||||
("wallet_getCachedCurrencyFormats", []),
|
||||
("wallet_fetchAllCurrencyFormats", [])
|
||||
("wallet_getCachedCurrencyFormats", [])
|
||||
],
|
||||
)
|
||||
def test_(self, method, params):
|
||||
|
|
|
@ -30,6 +30,7 @@ const (
|
|||
ArbitrumSepolia uint64 = 421614
|
||||
BinanceChainID uint64 = 56 // obsolete?
|
||||
BinanceTestChainID uint64 = 97 // obsolete?
|
||||
AnvilMainnet uint64 = 31337
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -14,8 +14,10 @@ var (
|
|||
newBlockCheckIntervalMainnet = 3 * time.Second
|
||||
newBlockCheckIntervalOptimism = 1 * time.Second
|
||||
newBlockCheckIntervalArbitrum = 200 * time.Millisecond
|
||||
newBlockCheckIntervalAnvilMainnet = 2 * time.Second
|
||||
|
||||
feeRecalculationTimeout = 5 * time.Minute
|
||||
feeRecalculationAnvilTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
type fetchingLastBlock struct {
|
||||
|
@ -42,7 +44,11 @@ func (r *Router) subscribeForUdates(chainID uint64) error {
|
|||
}
|
||||
r.clientsForUpdatesPerChains.Store(chainID, flb)
|
||||
|
||||
r.startTimeoutForUpdates(flb.closeCh)
|
||||
timeout := feeRecalculationTimeout
|
||||
if chainID == walletCommon.AnvilMainnet {
|
||||
timeout = feeRecalculationAnvilTimeout
|
||||
}
|
||||
r.startTimeoutForUpdates(flb.closeCh, timeout)
|
||||
|
||||
var ticker *time.Ticker
|
||||
switch chainID {
|
||||
|
@ -55,6 +61,8 @@ func (r *Router) subscribeForUdates(chainID uint64) error {
|
|||
case walletCommon.ArbitrumMainnet,
|
||||
walletCommon.ArbitrumSepolia:
|
||||
ticker = time.NewTicker(newBlockCheckIntervalArbitrum)
|
||||
case walletCommon.AnvilMainnet:
|
||||
ticker = time.NewTicker(newBlockCheckIntervalAnvilMainnet)
|
||||
}
|
||||
|
||||
ctx, cancelCtx := context.WithCancel(context.Background())
|
||||
|
@ -123,8 +131,8 @@ func (r *Router) subscribeForUdates(chainID uint64) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *Router) startTimeoutForUpdates(closeCh chan struct{}) {
|
||||
dedlineTicker := time.NewTicker(feeRecalculationTimeout)
|
||||
func (r *Router) startTimeoutForUpdates(closeCh chan struct{}, timeout time.Duration) {
|
||||
dedlineTicker := time.NewTicker(timeout)
|
||||
go func() {
|
||||
defer gocommon.LogOnPanic()
|
||||
for {
|
||||
|
|
Loading…
Reference in New Issue