diff --git a/.github/workflows/lint_type_check.yml b/.github/workflows/lint_type_check.yml index a37f4697..b780972e 100644 --- a/.github/workflows/lint_type_check.yml +++ b/.github/workflows/lint_type_check.yml @@ -6,30 +6,36 @@ on: pull_request: workflow_dispatch: +env: + POETRY_VERSION: 1.4.2 + PYTHON_VERSION: "3.8" + jobs: lint-and-type-check: name: Lint and type-check - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Load cached .local + id: cache-poetry uses: actions/cache@v3 with: path: /home/runner/.local - key: dotlocal-3.11-${{ hashFiles('.github/workflows') }} + key: dotlocal-${{ env.POETRY_VERSION }} - name: Install poetry + if: steps.cache-poetry.outputs.cache-hit != 'true' run: | - curl -sSL https://install.python-poetry.org/ | python - + curl -sSL https://install.python-poetry.org/ | python - --version ${{ env.POETRY_VERSION }} echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install Python + Retrieve Poetry dependencies from cache uses: actions/setup-python@v4 with: - python-version: "3.11" + python-version: ${{ env.PYTHON_VERSION }} cache: "poetry" - name: Display Python version diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7ec70c5e..bee01cac 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,20 +5,21 @@ on: branches: [main] pull_request: paths-ignore: - - "docs/**" + - "scripts/**" - "**.md" - ".vscode/**" workflow_dispatch: +env: + POETRY_VERSION: 1.4.2 + jobs: test: name: Test - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest timeout-minutes: 10 strategy: matrix: - # we have to use 3.7.1 to get around openssl issues - # TODO: add 3.7 once xrpl-py has been updated python-version: ["3.8", "3.9", "3.10", "3.11"] fail-fast: false @@ -27,20 +28,22 @@ jobs: uses: actions/checkout@v3 - name: Load cached .local + id: cache-poetry uses: actions/cache@v3 with: path: /home/runner/.local - key: dotlocal-${{ matrix.python-version }}-${{ hashFiles('.github/workflows') }} + key: dotlocal-${{ matrix.python-version }}-${{ env.POETRY_VERSION }} - name: Install poetry + if: steps.cache-poetry.outputs.cache-hit != 'true' run: | - curl -sSL https://install.python-poetry.org/ | python - + curl -sSL https://install.python-poetry.org/ | python - --version ${{ env.POETRY_VERSION }} echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install Python + Retrieve Poetry dependencies from cache uses: actions/setup-python@v4 with: - python-version: "${{ matrix.python-version }}" + python-version: ${{ matrix.python-version }} cache: "poetry" - name: Display Python version @@ -52,8 +55,8 @@ jobs: - name: Pull images from docker run: | - docker pull legleux/rippled-xbridge-test - docker pull legleux/xbridge_witnessd-test + docker pull rippleci/rippled:2.0.0-b4 + docker pull rippleci/xbwd - name: Run tests id: runTests diff --git a/.vscode/settings.json b/.vscode/settings.json index 0ef4d5cd..0aeedd55 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { + "python.defaultInterpreterPath": ".venv/bin/python", "python.formatting.provider": "black", "python.linting.pylintEnabled": false, "python.linting.flake8Enabled": true, diff --git a/CHANGELOG.md b/CHANGELOG.md index 0325fa22..288d94e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [[Unreleased]] +### Fixed + +- Throw an error if a transaction fails instead of continuing + +### Changed + +- Switched to Docker containers with the latest versions of rippled and the witness server + ## [0.3.3] - 2023-10-10 ### Fixed diff --git a/scripts/docker-start.sh b/scripts/docker-start.sh index 07735957..28af20d4 100755 --- a/scripts/docker-start.sh +++ b/scripts/docker-start.sh @@ -4,6 +4,6 @@ xbridge-cli server start-all --docker xbridge-cli server list xbridge-cli explorer xbridge-cli bridge build --name=bridge --fund-locking -xbridge-cli fund locking_chain raFcdz1g8LWJDJWJE2ZKLRGdmUmsTyxaym -xbridge-cli bridge create-account --from-locking --bridge bridge --from snqs2zzXuMA71w9isKHPTrvFn1HaJ --to rJdTJRJZ6GXCCRaamHJgEqVzB7Zy4557Pi --amount 10 -xbridge-cli bridge transfer --bridge bridge --from-locking --amount 10 --from snqs2zzXuMA71w9isKHPTrvFn1HaJ --to snyEJjY2Xi5Dxdh81Jy9Mj3AiYRQM +xbridge-cli fund locking_chain rHLrQ3SjzxmkoYgrZ5d4kgHRPF6MdMWpAV +xbridge-cli bridge create-account --from-locking --bridge bridge --from sEdTSHsMvrzomUN9uYgVEd64CEQqwo2 --to rHLrQ3SjzxmkoYgrZ5d4kgHRPF6MdMWpAV --amount 100 +xbridge-cli bridge transfer --bridge bridge --from-locking --amount 10 --from sEdTSHsMvrzomUN9uYgVEd64CEQqwo2 --to sEdTSHsMvrzomUN9uYgVEd64CEQqwo2 diff --git a/scripts/start.sh b/scripts/start.sh index 7f28d451..b2556b44 100755 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -5,5 +5,5 @@ xbridge-cli server list xbridge-cli explorer xbridge-cli bridge build --name=bridge --fund-locking xbridge-cli fund locking_chain rHLrQ3SjzxmkoYgrZ5d4kgHRPF6MdMWpAV -xbridge-cli bridge create-account --from-locking --bridge bridge --from sEdTSHsMvrzomUN9uYgVEd64CEQqwo2 --to rHLrQ3SjzxmkoYgrZ5d4kgHRPF6MdMWpAV --amount 10 +xbridge-cli bridge create-account --from-locking --bridge bridge --from sEdTSHsMvrzomUN9uYgVEd64CEQqwo2 --to rHLrQ3SjzxmkoYgrZ5d4kgHRPF6MdMWpAV --amount 100 xbridge-cli bridge transfer --bridge bridge --from-locking --amount 10 --from sEdTSHsMvrzomUN9uYgVEd64CEQqwo2 --to sEdTSHsMvrzomUN9uYgVEd64CEQqwo2 diff --git a/scripts/tutorial.sh b/scripts/tutorial.sh index 750a4bbf..d5611dd6 100755 --- a/scripts/tutorial.sh +++ b/scripts/tutorial.sh @@ -5,6 +5,6 @@ xbridge-cli server list read -p "Pausing... (hit enter to continue)" xbridge-cli explorer xbridge-cli bridge build --name=bridge --fund-locking -xbridge-cli fund locking_chain raFcdz1g8LWJDJWJE2ZKLRGdmUmsTyxaym -xbridge-cli bridge create-account --from-locking --bridge bridge --from snqs2zzXuMA71w9isKHPTrvFn1HaJ --to rJdTJRJZ6GXCCRaamHJgEqVzB7Zy4557Pi --amount 10 -xbridge-cli bridge transfer --bridge bridge --from-locking --amount 10 --from snqs2zzXuMA71w9isKHPTrvFn1HaJ --to snyEJjY2Xi5Dxdh81Jy9Mj3AiYRQM --tutorial +xbridge-cli fund locking_chain rHLrQ3SjzxmkoYgrZ5d4kgHRPF6MdMWpAV +xbridge-cli bridge create-account --from-locking --bridge bridge --from sEdTSHsMvrzomUN9uYgVEd64CEQqwo2 --to rHLrQ3SjzxmkoYgrZ5d4kgHRPF6MdMWpAV --amount 100 +xbridge-cli bridge transfer --bridge bridge --from-locking --amount 10 --from sEdTSHsMvrzomUN9uYgVEd64CEQqwo2 --to sEdTSHsMvrzomUN9uYgVEd64CEQqwo2 --tutorial diff --git a/tests/bridge/test_build.py b/tests/bridge/test_build.py index 4c1bdbee..b8514217 100644 --- a/tests/bridge/test_build.py +++ b/tests/bridge/test_build.py @@ -53,7 +53,7 @@ def test_bridge_build(self): ], "xchain_currencies": [{"currency": "XRP"}, {"currency": "XRP"}], "signature_reward": "100", - "create_account_amounts": ["5000000", "5000000"], + "create_account_amounts": ["10000000", "10000000"], } assert config_result["bridges"][0] == expected_result @@ -149,7 +149,7 @@ def test_bridge_prod_build_xrp(self): ], "xchain_currencies": [{"currency": "XRP"}, {"currency": "XRP"}], "signature_reward": "100", - "create_account_amounts": ["5000000", "5000000"], + "create_account_amounts": ["10000000", "10000000"], } assert config_result["bridges"][0] == expected_result diff --git a/tests/bridge/test_transfer.py b/tests/bridge/test_transfer.py index ffe4736e..7a83bf39 100644 --- a/tests/bridge/test_transfer.py +++ b/tests/bridge/test_transfer.py @@ -43,7 +43,7 @@ def test_bridge_transfer(self): "--to", receive_wallet.classic_address, "--amount", - "10", + "100", "--verbose", ], ) @@ -114,7 +114,7 @@ def test_bridge_transfer_prod(self): "--to", receive_wallet.classic_address, "--amount", - "10", + "100", "--verbose", ], ) diff --git a/tests/conftest.py b/tests/conftest.py index f5f60662..8cd72bd3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -121,6 +121,12 @@ def _base_fixture(): assert stop_result.exit_code == 0, stop_result.output +@pytest.fixture(scope="class") +def basic(): + _reset_cli_config() + _create_config_files() + + @pytest.fixture(scope="class") def runner(): with _base_fixture() as cli_runner: diff --git a/tests/server/test_basic.py b/tests/server/test_basic.py index d80ff02c..d7fba4a5 100644 --- a/tests/server/test_basic.py +++ b/tests/server/test_basic.py @@ -1,8 +1,10 @@ +import pytest from click.testing import CliRunner from xbridge_cli.main import main +@pytest.mark.usefixtures("basic") class TestBasicCreation: def test_start_stop(self): runner = CliRunner() diff --git a/xbridge_cli/bridge/transfer.py b/xbridge_cli/bridge/transfer.py index a1c0b1e0..db0c5112 100644 --- a/xbridge_cli/bridge/transfer.py +++ b/xbridge_cli/bridge/transfer.py @@ -1,6 +1,6 @@ """CLI command for setting up a bridge.""" -from typing import Any, Dict, cast +from typing import Any, Dict, Union, cast import click from xrpl.clients import JsonRpcClient @@ -109,7 +109,7 @@ def _submit_tx( def send_transfer( bridge: str, from_locking: bool, - amount: int | float, + amount: Union[int, float], from_account: str, to_account: str, close_ledgers: bool = True, diff --git a/xbridge_cli/misc/fund.py b/xbridge_cli/misc/fund.py index d29ceb23..badc3fc9 100644 --- a/xbridge_cli/misc/fund.py +++ b/xbridge_cli/misc/fund.py @@ -31,7 +31,7 @@ help="Whether or not to print more verbose information.", ) def fund_account( - chain: str, accounts: List[str], amount: int = 1000, verbose: bool = False + chain: str, accounts: List[str], amount: int = 10000, verbose: bool = False ) -> None: """ Of the form `xbridge-cli fund CHAIN ACCOUNT1 [ACCOUNT2 ...]. diff --git a/xbridge_cli/server/docker-compose.yml b/xbridge_cli/server/docker-compose.yml index 03d6b2c5..cd7cbd7c 100644 --- a/xbridge_cli/server/docker-compose.yml +++ b/xbridge_cli/server/docker-compose.yml @@ -3,8 +3,9 @@ services: locking_chain: container_name: locking_chain - image: legleux/rippled-xbridge-test - command: "--conf /etc/opt/ripple/rippled.cfg -a" + image: rippleci/rippled:2.0.0-b4 + platform: linux/amd64 + command: "/opt/ripple/bin/rippled --conf /etc/opt/ripple/rippled.cfg -a" volumes: - ${XCHAIN_CONFIG_DIR}/locking_chain:/etc/opt/ripple/ ports: @@ -17,8 +18,9 @@ services: issuing_chain: container_name: issuing_chain - image: legleux/rippled-xbridge-test - command: "--conf /etc/opt/ripple/rippled.cfg -a" + image: rippleci/rippled:2.0.0-b4 + platform: linux/amd64 + command: "/opt/ripple/bin/rippled --conf /etc/opt/ripple/rippled.cfg -a" volumes: - ${XCHAIN_CONFIG_DIR}/issuing_chain:/etc/opt/ripple/ ports: @@ -31,8 +33,9 @@ services: witness0: container_name: witness0 - image: legleux/xbridge_witnessd-test - command: "/opt/witness/witness.json" + image: rippleci/xbwd + platform: linux/amd64 + command: "/opt/xbwd/bin/xbridge_witnessd --conf /opt/witness/witness.json" volumes: - ${XCHAIN_CONFIG_DIR}/witness0:/opt/witness/ ports: @@ -43,8 +46,9 @@ services: witness1: container_name: witness1 - image: legleux/xbridge_witnessd-test - command: "/opt/witness/witness.json" + image: rippleci/xbwd + platform: linux/amd64 + command: "/opt/xbwd/bin/xbridge_witnessd --conf /opt/witness/witness.json" volumes: - ${XCHAIN_CONFIG_DIR}/witness1:/opt/witness/ ports: @@ -55,8 +59,9 @@ services: witness2: container_name: witness2 - image: legleux/xbridge_witnessd-test - command: "/opt/witness/witness.json" + image: rippleci/xbwd + platform: linux/amd64 + command: "/opt/xbwd/bin/xbridge_witnessd --conf /opt/witness/witness.json" volumes: - ${XCHAIN_CONFIG_DIR}/witness2:/opt/witness/ ports: @@ -67,8 +72,9 @@ services: witness3: container_name: witness3 - image: legleux/xbridge_witnessd-test - command: "/opt/witness/witness.json" + image: rippleci/xbwd + platform: linux/amd64 + command: "/opt/xbwd/bin/xbridge_witnessd --conf /opt/witness/witness.json" volumes: - ${XCHAIN_CONFIG_DIR}/witness3:/opt/witness/ ports: @@ -79,8 +85,9 @@ services: witness4: container_name: witness4 - image: legleux/xbridge_witnessd-test - command: "/opt/witness/witness.json" + image: rippleci/xbwd + platform: linux/amd64 + command: "/opt/xbwd/bin/xbridge_witnessd --conf /opt/witness/witness.json" volumes: - ${XCHAIN_CONFIG_DIR}/witness4:/opt/witness/ ports: diff --git a/xbridge_cli/server/request.py b/xbridge_cli/server/request.py index baf56a36..9df015e2 100644 --- a/xbridge_cli/server/request.py +++ b/xbridge_cli/server/request.py @@ -42,7 +42,7 @@ def request_server( if isinstance(server, ChainConfig): # is a rippled node if server.is_docker(): - to_run = ["docker", "exec", name, "/opt/rippled/bin/rippled"] + to_run = ["docker", "exec", name, "/opt/ripple/bin/rippled"] else: to_run = [server.rippled, "--conf", server.config] to_run.extend([command, *args]) diff --git a/xbridge_cli/server/start.py b/xbridge_cli/server/start.py index 7aefadd8..81c0b787 100644 --- a/xbridge_cli/server/start.py +++ b/xbridge_cli/server/start.py @@ -148,7 +148,9 @@ def start_server( config_json = json.load(f) is_rippled = False if check_server_exists(name, config): - raise XBridgeCLIException("Server already running with that name or config.") + raise XBridgeCLIException( + f"Server already running with the name {name} or config {config}." + ) server_type = "rippled" if is_rippled else "witness" if verbose: diff --git a/xbridge_cli/utils/transaction.py b/xbridge_cli/utils/transaction.py index da9543fb..d1495db9 100644 --- a/xbridge_cli/utils/transaction.py +++ b/xbridge_cli/utils/transaction.py @@ -1,7 +1,7 @@ """Utils related to transactions.""" from pprint import pformat -from typing import List, Union +from typing import List, Union, cast import click from xrpl.clients.sync_client import SyncClient @@ -9,6 +9,8 @@ from xrpl.transaction import autofill_and_sign, submit, submit_and_wait from xrpl.wallet import Wallet +from xbridge_cli.exceptions import XBridgeCLIException + def submit_tx( txs: Union[Transaction, List[Transaction]], @@ -30,6 +32,9 @@ def submit_tx( Returns: The response from rippled. + + Raises: + XBridgeCLIException: If a transaction fails. """ if isinstance(txs, Transaction): txs = [txs] @@ -42,32 +47,40 @@ def submit_tx( for tx in txs: click.echo(pformat(tx.to_xrpl())) + results = [] + tx_results: List[str] = [] if close_ledgers: - results = [] for tx in txs: signed_tx = autofill_and_sign(tx, client, wallet) results.append(submit(signed_tx, client)) client.request(GenericRequest(method="ledger_accept")) tx_results = [ - result.result.get("error") or result.result.get("engine_result") + cast( + str, + result.result.get("error") + or result.result.get("engine_result", "ERROR"), + ) for result in results ] else: # TODO: improve runtime when there is a batch submit_and_wait - results = [] - tx_results = [] for tx in txs: signed_tx = autofill_and_sign(tx, client, wallet) result = submit_and_wait(signed_tx, client) results.append(result) tx_results.append(result.result["meta"]["TransactionResult"]) + failed = False for i in range(len(results)): result = results[i] tx_result = tx_results[i] if verbose > 0: text_color = "bright_green" if tx_result == "tesSUCCESS" else "bright_red" click.secho(f"Result: {tx_result}", fg=text_color) + if tx_result != "tesSUCCESS": + failed = True if verbose > 1: click.echo(pformat(result.result)) + if failed: + raise XBridgeCLIException(", ".join(tx_results)) return results