diff --git a/.github/workflows/install-macos.yml b/.github/workflows/install-macos.yml deleted file mode 100644 index b815c17c..00000000 --- a/.github/workflows/install-macos.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Install mxpy (MacOS) - -on: - pull_request: - branches: [main, feat/*] - workflow_dispatch: - -env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} - -jobs: - install: - runs-on: macos-latest - - strategy: - matrix: - python-version: [3.11] - - steps: - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install - run: | - wget -O mxpy-up.py https://raw.githubusercontent.com/multiversx/mx-sdk-py-cli/$BRANCH_NAME/mxpy-up.py - python3 mxpy-up.py --from-branch $BRANCH_NAME --not-interactive - - name: Smoke test - run: | - export PATH="~/multiversx-sdk:${PATH}" - mxpy --version diff --git a/.github/workflows/install-ubuntu.yml b/.github/workflows/install-ubuntu.yml deleted file mode 100644 index 734e3593..00000000 --- a/.github/workflows/install-ubuntu.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Install mxpy (Ubuntu) - -on: - pull_request: - branches: [main, feat/*] - workflow_dispatch: - -env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} - -jobs: - install: - runs-on: ubuntu-latest - - strategy: - matrix: - python-version: [3.11] - - steps: - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install - run: | - wget -O mxpy-up.py https://raw.githubusercontent.com/multiversx/mx-sdk-py-cli/$BRANCH_NAME/mxpy-up.py - python3 mxpy-up.py --from-branch $BRANCH_NAME --not-interactive - - name: Smoke test - run: | - export PATH="~/multiversx-sdk:${PATH}" - mxpy --version diff --git a/.github/workflows/install-windows.yml b/.github/workflows/install-windows.yml deleted file mode 100644 index 0e7d6dca..00000000 --- a/.github/workflows/install-windows.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Install mxpy (Windows) - -on: - pull_request: - branches: [main, feat/*] - workflow_dispatch: - -env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} - -jobs: - install: - runs-on: windows-2019 - - strategy: - matrix: - python-version: [3.11] - - steps: - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install - shell: bash - run: | - curl.exe --output mxpy-up.py --url https://raw.githubusercontent.com/multiversx/mx-sdk-py-cli/$BRANCH_NAME/mxpy-up.py - python3 mxpy-up.py --from-branch $BRANCH_NAME --not-interactive - - name: Smoke test - shell: bash - run: | - export PATH="~/multiversx-sdk:${PATH}" - mxpy --version diff --git a/.github/workflows/test-localnet.yml b/.github/workflows/test-localnet.yml index fc52ee2c..dcbc9a4f 100644 --- a/.github/workflows/test-localnet.yml +++ b/.github/workflows/test-localnet.yml @@ -48,6 +48,13 @@ jobs: python3 -m multiversx_sdk_cli.cli localnet config --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml python3 -m multiversx_sdk_cli.cli localnet start --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml --stop-after-seconds=120 + if grep -r --include=\*.log "started committing block" ./localnet; then + echo "The localnet processed blocks successfully." + else + echo "The localnet failed to process blocks." + exit 1 + fi + - name: Smoke test (with resolution == local) run: | mkdir -p ~/multiversx-sdk/sandbox @@ -65,3 +72,10 @@ jobs: python3 -m multiversx_sdk_cli.cli localnet clean --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_local.toml python3 -m multiversx_sdk_cli.cli localnet config --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_local.toml python3 -m multiversx_sdk_cli.cli localnet start --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_local.toml --stop-after-seconds=120 + + if grep -r --include=\*.log "started committing block" ./localnet; then + echo "The localnet processed blocks successfully." + else + echo "The localnet failed to process blocks." + exit 1 + fi diff --git a/CLI.md b/CLI.md index 6f18244f..e3721cbb 100644 --- a/CLI.md +++ b/CLI.md @@ -949,6 +949,631 @@ options: --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger +``` +## Group **StakingProvider** + + +``` +$ mxpy staking-provider --help +usage: mxpy staking-provider COMMAND [-h] ... + +Staking provider omnitool + +COMMANDS: + {create-new-delegation-contract,get-contract-address,add-nodes,remove-nodes,stake-nodes,unbond-nodes,unstake-nodes,unjail-nodes,change-service-fee,modify-delegation-cap,automatic-activation,redelegate-cap,set-metadata} + +OPTIONS: + -h, --help show this help message and exit + +``` +### StakingProvider.CreateNewDelegationContract + + +``` +$ mxpy staking-provider create-new-delegation-contract --help +usage: mxpy staking-provider create-new-delegation-contract [-h] ... + +Create a new delegation system smart contract, transferred value must begreater than baseIssuingCost + min deposit value + +options: + -h, --help show this help message and exit + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + --total-delegation-cap TOTAL_DELEGATION_CAP the total delegation contract capacity + --service-fee SERVICE_FEE the delegation contract service fee + +``` +### StakingProvider.GetContractAddress + + +``` +$ mxpy staking-provider get-contract-address --help +usage: mxpy staking-provider get-contract-address [-h] ... + +Get create contract address by transaction hash + +options: + -h, --help show this help message and exit + --create-tx-hash CREATE_TX_HASH the hash + --sender SENDER the sender address + --proxy PROXY 🔗 the URL of the proxy + +``` +### StakingProvider.AddNodes + + +``` +$ mxpy staking-provider add-nodes --help +usage: mxpy staking-provider add-nodes [-h] ... + +Add new nodes must be called by the contract owner + +options: + -h, --help show this help message and exit + --validators-file VALIDATORS_FILE a JSON file describing the Nodes + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --using-delegation-manager whether delegation contract was created using the Delegation Manager + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + +``` +### StakingProvider.RemoveNodes + + +``` +$ mxpy staking-provider remove-nodes --help +usage: mxpy staking-provider remove-nodes [-h] ... + +Remove nodes must be called by the contract owner + +options: + -h, --help show this help message and exit + --bls-keys BLS_KEYS a list with the bls keys of the nodes + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + +``` +### StakingProvider.StakeNodes + + +``` +$ mxpy staking-provider stake-nodes --help +usage: mxpy staking-provider stake-nodes [-h] ... + +Stake nodes must be called by the contract owner + +options: + -h, --help show this help message and exit + --bls-keys BLS_KEYS a list with the bls keys of the nodes + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + +``` +### StakingProvider.UnbondNodes + + +``` +$ mxpy staking-provider unbond-nodes --help +usage: mxpy staking-provider unbond-nodes [-h] ... + +Unbond nodes must be called by the contract owner + +options: + -h, --help show this help message and exit + --bls-keys BLS_KEYS a list with the bls keys of the nodes + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + +``` +### StakingProvider.UnstakeNodes + + +``` +$ mxpy staking-provider unstake-nodes --help +usage: mxpy staking-provider unstake-nodes [-h] ... + +Unstake nodes must be called by the contract owner + +options: + -h, --help show this help message and exit + --bls-keys BLS_KEYS a list with the bls keys of the nodes + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + +``` +### StakingProvider.UnjailNodes + + +``` +$ mxpy staking-provider unjail-nodes --help +usage: mxpy staking-provider unjail-nodes [-h] ... + +Unjail nodes must be called by the contract owner + +options: + -h, --help show this help message and exit + --bls-keys BLS_KEYS a list with the bls keys of the nodes + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + +``` +### StakingProvider.ChangeServiceFee + + +``` +$ mxpy staking-provider change-service-fee --help +usage: mxpy staking-provider change-service-fee [-h] ... + +Change service fee must be called by the contract owner + +options: + -h, --help show this help message and exit + --service-fee SERVICE_FEE new service fee value + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + +``` +### StakingProvider.ModifyDelegationCap + + +``` +$ mxpy staking-provider modify-delegation-cap --help +usage: mxpy staking-provider modify-delegation-cap [-h] ... + +Modify delegation cap must be called by the contract owner + +options: + -h, --help show this help message and exit + --delegation-cap DELEGATION_CAP new delegation contract capacity + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + +``` +### StakingProvider.AutomaticActivation + + +``` +$ mxpy staking-provider automatic-activation --help +usage: mxpy staking-provider automatic-activation [-h] ... + +Automatic activation must be called by the contract owner + +options: + -h, --help show this help message and exit + --set set automatic activation True + --unset set automatic activation False + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + +``` +### StakingProvider.RedelegateCap + + +``` +$ mxpy staking-provider redelegate-cap --help +usage: mxpy staking-provider redelegate-cap [-h] ... + +Redelegate cap must be called by the contract owner + +options: + -h, --help show this help message and exit + --set set redelegate cap True + --unset set redelegate cap False + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + +``` +### StakingProvider.SetMetadata + + +``` +$ mxpy staking-provider set-metadata --help +usage: mxpy staking-provider set-metadata [-h] ... + +Set metadata must be called by the contract owner + +options: + -h, --help show this help message and exit + --name NAME name field in staking provider metadata + --website WEBSITE website field in staking provider metadata + --identifier IDENTIFIER identifier field in staking provider metadata + --delegation-contract DELEGATION_CONTRACT address of the delegation contract + --proxy PROXY 🔗 the URL of the proxy + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --guardian GUARDIAN the address of the guradian + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-pem-index GUARDIAN_PEM_INDEX 🔑 the index in the PEM file (default: 0) + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-ledger-account-index GUARDIAN_LEDGER_ACCOUNT_INDEX + 🔐 the index of the account when using Ledger + --guardian-ledger-address-index GUARDIAN_LEDGER_ADDRESS_INDEX + 🔐 the index of the address when using Ledger + ``` ## Group **Account** diff --git a/CLI.md.sh b/CLI.md.sh index c1b3ac8d..49790861 100755 --- a/CLI.md.sh +++ b/CLI.md.sh @@ -63,6 +63,21 @@ generate() { command "Validator.ChangeRewardAddress" "validator change-reward-address" command "Validator.Claim" "validator claim" + group "StakingProvider" "staking-provider" + command "StakingProvider.CreateNewDelegationContract" "staking-provider create-new-delegation-contract" + command "StakingProvider.GetContractAddress" "staking-provider get-contract-address" + command "StakingProvider.AddNodes" "staking-provider add-nodes" + command "StakingProvider.RemoveNodes" "staking-provider remove-nodes" + command "StakingProvider.StakeNodes" "staking-provider stake-nodes" + command "StakingProvider.UnbondNodes" "staking-provider unbond-nodes" + command "StakingProvider.UnstakeNodes" "staking-provider unstake-nodes" + command "StakingProvider.UnjailNodes" "staking-provider unjail-nodes" + command "StakingProvider.ChangeServiceFee" "staking-provider change-service-fee" + command "StakingProvider.ModifyDelegationCap" "staking-provider modify-delegation-cap" + command "StakingProvider.AutomaticActivation" "staking-provider automatic-activation" + command "StakingProvider.RedelegateCap" "staking-provider redelegate-cap" + command "StakingProvider.SetMetadata" "staking-provider set-metadata" + group "Account" "account" command "Account.Get" "account get" diff --git a/multiversx_sdk_cli/accounts.py b/multiversx_sdk_cli/accounts.py index bb563ae5..515093b1 100644 --- a/multiversx_sdk_cli/accounts.py +++ b/multiversx_sdk_cli/accounts.py @@ -72,6 +72,9 @@ def sign_transaction(self, transaction: ITransaction) -> str: assert self.signer is not None transaction_computer = TransactionComputer() + if transaction.options & TX_HASH_SIGN_OPTIONS == TX_HASH_SIGN_OPTIONS: + return self.signer.sign(transaction_computer.compute_hash_for_signing(transaction)).hex() + return self.signer.sign(transaction_computer.compute_bytes_for_signing(transaction)).hex() def sign_message(self, data: bytes) -> str: @@ -96,7 +99,7 @@ def sign_transaction(self, transaction: ITransaction) -> str: should_use_hash_signing = compare_versions(ledger_version, SIGN_USING_HASH_VERSION) >= 0 if should_use_hash_signing: transaction.version = TX_HASH_SIGN_VERSION - transaction.options = TX_HASH_SIGN_OPTIONS + transaction.options = transaction.options | TX_HASH_SIGN_OPTIONS transaction_computer = TransactionComputer() diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index 53cdf3db..c6eda82a 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -429,7 +429,7 @@ def query(args: Any): proxy = ProxyNetworkProvider(args.proxy) function = args.function - arguments = args.arguments or [] + arguments: List[Any] = args.arguments or [] result = query_contract(contract_address, proxy, function, arguments) utils.dump_out_json(result) diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index 3d76b348..7d936c18 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -41,7 +41,8 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: # remove nodes sub = cli_shared.add_command_subparser(subparsers, "staking-provider", "remove-nodes", "Remove nodes must be called by the contract owner") - sub.add_argument("--bls-keys", required=True, help="a list with the bls keys of the nodes") + sub.add_argument("--bls-keys", help="a list with the bls keys of the nodes") + sub.add_argument("--validators-file", help="a JSON file describing the Nodes") sub.add_argument("--delegation-contract", required=True, help="address of the delegation contract") _add_common_arguments(args, sub) sub.set_defaults(func=remove_nodes) @@ -49,7 +50,8 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: # stake nodes sub = cli_shared.add_command_subparser(subparsers, "staking-provider", "stake-nodes", "Stake nodes must be called by the contract owner") - sub.add_argument("--bls-keys", required=True, help="a list with the bls keys of the nodes") + sub.add_argument("--bls-keys", help="a list with the bls keys of the nodes") + sub.add_argument("--validators-file", help="a JSON file describing the Nodes") sub.add_argument("--delegation-contract", required=True, help="address of the delegation contract") _add_common_arguments(args, sub) sub.set_defaults(func=stake_nodes) @@ -57,7 +59,8 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: # unbond nodes sub = cli_shared.add_command_subparser(subparsers, "staking-provider", "unbond-nodes", "Unbond nodes must be called by the contract owner") - sub.add_argument("--bls-keys", required=True, help="a list with the bls keys of the nodes") + sub.add_argument("--bls-keys", help="a list with the bls keys of the nodes") + sub.add_argument("--validators-file", help="a JSON file describing the Nodes") sub.add_argument("--delegation-contract", required=True, help="address of the delegation contract") _add_common_arguments(args, sub) sub.set_defaults(func=unbond_nodes) @@ -65,7 +68,8 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: # unstake nodes sub = cli_shared.add_command_subparser(subparsers, "staking-provider", "unstake-nodes", "Unstake nodes must be called by the contract owner") - sub.add_argument("--bls-keys", required=True, help="a list with the bls keys of the nodes") + sub.add_argument("--bls-keys", help="a list with the bls keys of the nodes") + sub.add_argument("--validators-file", help="a JSON file describing the Nodes") sub.add_argument("--delegation-contract", required=True, help="address of the delegation contract") _add_common_arguments(args, sub) sub.set_defaults(func=unstake_nodes) @@ -73,7 +77,8 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: # unjail nodes sub = cli_shared.add_command_subparser(subparsers, "staking-provider", "unjail-nodes", "Unjail nodes must be called by the contract owner") - sub.add_argument("--bls-keys", required=True, help="a list with the bls keys of the nodes") + sub.add_argument("--bls-keys", help="a list with the bls keys of the nodes") + sub.add_argument("--validators-file", help="a JSON file describing the Nodes") sub.add_argument("--delegation-contract", required=True, help="address of the delegation contract") _add_common_arguments(args, sub) sub.set_defaults(func=unjail_nodes) @@ -182,6 +187,7 @@ def add_new_nodes(args: Any): def remove_nodes(args: Any): + _check_if_either_bls_keys_or_validators_file_are_provided(args) cli_shared.check_guardian_and_options_args(args) cli_shared.check_broadcast_args(args) cli_shared.prepare_chain_id_in_args(args) @@ -196,6 +202,7 @@ def remove_nodes(args: Any): def stake_nodes(args: Any): + _check_if_either_bls_keys_or_validators_file_are_provided(args) cli_shared.check_guardian_and_options_args(args) cli_shared.check_broadcast_args(args) cli_shared.prepare_chain_id_in_args(args) @@ -209,7 +216,16 @@ def stake_nodes(args: Any): cli_shared.send_or_simulate(tx, args) +def _check_if_either_bls_keys_or_validators_file_are_provided(args: Any): + bls_keys = args.bls_keys + validators_file = args.validators_file + + if not bls_keys and not validators_file: + raise errors.BadUsage("No bls keys or validators file provided. Use either `--bls-keys` or `--validators-file`") + + def unbond_nodes(args: Any): + _check_if_either_bls_keys_or_validators_file_are_provided(args) cli_shared.check_guardian_and_options_args(args) cli_shared.check_broadcast_args(args) cli_shared.prepare_chain_id_in_args(args) @@ -224,6 +240,7 @@ def unbond_nodes(args: Any): def unstake_nodes(args: Any): + _check_if_either_bls_keys_or_validators_file_are_provided(args) cli_shared.check_guardian_and_options_args(args) cli_shared.check_broadcast_args(args) cli_shared.prepare_chain_id_in_args(args) @@ -238,6 +255,7 @@ def unstake_nodes(args: Any): def unjail_nodes(args: Any): + _check_if_either_bls_keys_or_validators_file_are_provided(args) cli_shared.check_guardian_and_options_args(args) cli_shared.check_broadcast_args(args) cli_shared.prepare_chain_id_in_args(args) diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 02005c06..48d04f2f 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -16,6 +16,7 @@ load_password) from multiversx_sdk_cli.constants import (DEFAULT_TX_VERSION, TRANSACTION_OPTIONS_TX_GUARDED) +from multiversx_sdk_cli.custom_network_provider import CustomNetworkProvider from multiversx_sdk_cli.errors import ArgumentsNotProvidedError from multiversx_sdk_cli.interfaces import ITransaction from multiversx_sdk_cli.ledger.ledger_functions import do_get_ledger_address @@ -245,11 +246,11 @@ def should_sign_with_guardian_key(args: Any) -> bool: def check_options_for_guarded_tx(options: int): if not options & TRANSACTION_OPTIONS_TX_GUARDED == TRANSACTION_OPTIONS_TX_GUARDED: - raise errors.BadUsage("Invalid guarded transaction's options. The second least significant bit must be set.") + raise errors.BadUsage("Invalid guarded transaction's options. The second least significant bit must be set") def send_or_simulate(tx: ITransaction, args: Any, dump_output: bool = True) -> CLIOutputBuilder: - proxy = ProxyNetworkProvider(args.proxy) + proxy = CustomNetworkProvider(args.proxy) is_set_wait_result = hasattr(args, "wait_result") and args.wait_result is_set_send = hasattr(args, "send") and args.send diff --git a/multiversx_sdk_cli/cli_transactions.py b/multiversx_sdk_cli/cli_transactions.py index 6850ac8e..5e02cac1 100644 --- a/multiversx_sdk_cli/cli_transactions.py +++ b/multiversx_sdk_cli/cli_transactions.py @@ -1,12 +1,10 @@ from pathlib import Path from typing import Any, List -from multiversx_sdk_network_providers.proxy_network_provider import \ - ProxyNetworkProvider - from multiversx_sdk_cli import cli_shared, utils from multiversx_sdk_cli.cli_output import CLIOutputBuilder from multiversx_sdk_cli.cosign_transaction import cosign_transaction +from multiversx_sdk_cli.custom_network_provider import CustomNetworkProvider from multiversx_sdk_cli.errors import NoWalletProvided from multiversx_sdk_cli.transactions import (compute_relayed_v1_data, do_prepare_transaction, @@ -88,9 +86,9 @@ def send_transaction(args: Any): tx = load_transaction_from_file(args.infile) output = CLIOutputBuilder() + proxy = CustomNetworkProvider(args.proxy) try: - proxy = ProxyNetworkProvider(args.proxy) tx_hash = proxy.send_transaction(tx) output.set_emitted_transaction_hash(tx_hash) finally: @@ -101,7 +99,7 @@ def send_transaction(args: Any): def get_transaction(args: Any): args = utils.as_object(args) omit_fields = cli_shared.parse_omit_fields_arg(args) - proxy = ProxyNetworkProvider(args.proxy) + proxy = CustomNetworkProvider(args.proxy) transaction = proxy.get_transaction(args.hash, True) output = CLIOutputBuilder().set_transaction_on_network(transaction, omit_fields).build() diff --git a/multiversx_sdk_cli/cli_wallet.py b/multiversx_sdk_cli/cli_wallet.py index 337bd0aa..de7dd7ce 100644 --- a/multiversx_sdk_cli/cli_wallet.py +++ b/multiversx_sdk_cli/cli_wallet.py @@ -112,6 +112,7 @@ def wallet_new(args: Any): mnemonic = Mnemonic.generate() print(f"Mnemonic: {mnemonic.get_text()}") + print(f"Wallet address: {mnemonic.derive_key().generate_public_key().to_address(address_hrp).to_bech32()}") if format is None: return diff --git a/multiversx_sdk_cli/contracts.py b/multiversx_sdk_cli/contracts.py index 251ffbae..a0a18855 100644 --- a/multiversx_sdk_cli/contracts.py +++ b/multiversx_sdk_cli/contracts.py @@ -280,6 +280,8 @@ def prepare_args_for_factory(arguments: List[str]) -> List[Any]: args.append(True) elif arg.startswith(STR_PREFIX): args.append(arg[len(STR_PREFIX):]) + else: + raise errors.BadUserInput(f"Unknown argument type for argument: `{arg}`. Use `mxpy contract --help` to check all supported arguments") return args diff --git a/multiversx_sdk_cli/custom_network_provider.py b/multiversx_sdk_cli/custom_network_provider.py new file mode 100644 index 00000000..3354a495 --- /dev/null +++ b/multiversx_sdk_cli/custom_network_provider.py @@ -0,0 +1,36 @@ +from typing import Any, Dict, Optional, Protocol + +from multiversx_sdk_network_providers import GenericError, ProxyNetworkProvider + +from multiversx_sdk_cli.errors import ProxyError +from multiversx_sdk_cli.interfaces import ISimulateResponse, ITransaction + + +class ITransactionOnNetwork(Protocol): + hash: str + is_completed: Optional[bool] + + def to_dictionary(self) -> Dict[str, Any]: + ... + + +class CustomNetworkProvider: + def __init__(self, url: str) -> None: + self._provider = ProxyNetworkProvider(url) + + def send_transaction(self, transaction: ITransaction) -> str: + try: + hash = self._provider.send_transaction(transaction) + return hash + except GenericError as ge: + url = ge.url + message = ge.data.get("error", "") + data = ge.data.get("data", "") + code = ge.data.get("code", "") + raise ProxyError(message, url, data, code) + + def get_transaction(self, tx_hash: str, with_process_status: Optional[bool] = False) -> ITransactionOnNetwork: + return self._provider.get_transaction(tx_hash, with_process_status) + + def simulate_transaction(self, transaction: ITransaction) -> ISimulateResponse: + return self._provider.simulate_transaction(transaction) diff --git a/multiversx_sdk_cli/delegation/staking_provider.py b/multiversx_sdk_cli/delegation/staking_provider.py index cbcb6160..06c3a331 100644 --- a/multiversx_sdk_cli/delegation/staking_provider.py +++ b/multiversx_sdk_cli/delegation/staking_provider.py @@ -52,11 +52,12 @@ def prepare_transaction_for_new_delegation_contract(self, owner: IAccount, args: tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_adding_nodes(self, owner: IAccount, args: Any) -> ITransaction: @@ -73,16 +74,18 @@ def prepare_transaction_for_adding_nodes(self, owner: IAccount, args: Any) -> IT tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_removing_nodes(self, owner: IAccount, args: Any) -> ITransaction: delegation_contract = Address.new_from_bech32(args.delegation_contract) - public_keys = self._parse_public_bls_keys(args.bls_keys) + + public_keys = self._load_validators_public_keys(args) tx = self._factory.create_transaction_for_removing_nodes( sender=owner.address, @@ -93,16 +96,18 @@ def prepare_transaction_for_removing_nodes(self, owner: IAccount, args: Any) -> tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_staking_nodes(self, owner: IAccount, args: Any) -> ITransaction: delegation_contract = Address.new_from_bech32(args.delegation_contract) - public_keys = self._parse_public_bls_keys(args.bls_keys) + + public_keys = self._load_validators_public_keys(args) tx = self._factory.create_transaction_for_staking_nodes( sender=owner.address, @@ -113,16 +118,18 @@ def prepare_transaction_for_staking_nodes(self, owner: IAccount, args: Any) -> I tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_unbonding_nodes(self, owner: IAccount, args: Any) -> ITransaction: delegation_contract = Address.new_from_bech32(args.delegation_contract) - public_keys = self._parse_public_bls_keys(args.bls_keys) + + public_keys = self._load_validators_public_keys(args) tx = self._factory.create_transaction_for_unbonding_nodes( sender=owner.address, @@ -133,16 +140,18 @@ def prepare_transaction_for_unbonding_nodes(self, owner: IAccount, args: Any) -> tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_unstaking_nodes(self, owner: IAccount, args: Any) -> ITransaction: delegation_contract = Address.new_from_bech32(args.delegation_contract) - public_keys = self._parse_public_bls_keys(args.bls_keys) + + public_keys = self._load_validators_public_keys(args) tx = self._factory.create_transaction_for_unstaking_nodes( sender=owner.address, @@ -153,16 +162,18 @@ def prepare_transaction_for_unstaking_nodes(self, owner: IAccount, args: Any) -> tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_unjailing_nodes(self, owner: IAccount, args: Any) -> ITransaction: delegation_contract = Address.new_from_bech32(args.delegation_contract) - public_keys = self._parse_public_bls_keys(args.bls_keys) + + public_keys = self._load_validators_public_keys(args) tx = self._factory.create_transaction_for_unjailing_nodes( sender=owner.address, @@ -173,11 +184,12 @@ def prepare_transaction_for_unjailing_nodes(self, owner: IAccount, args: Any) -> tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_changing_service_fee(self, owner: IAccount, args: Any) -> ITransaction: @@ -192,11 +204,12 @@ def prepare_transaction_for_changing_service_fee(self, owner: IAccount, args: An tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_modifying_delegation_cap(self, owner: IAccount, args: Any) -> ITransaction: @@ -211,11 +224,12 @@ def prepare_transaction_for_modifying_delegation_cap(self, owner: IAccount, args tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_automatic_activation(self, owner: IAccount, args: Any) -> ITransaction: @@ -238,11 +252,12 @@ def prepare_transaction_for_automatic_activation(self, owner: IAccount, args: An tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_redelegate_cap(self, owner: IAccount, args: Any) -> ITransaction: @@ -265,11 +280,12 @@ def prepare_transaction_for_redelegate_cap(self, owner: IAccount, args: Any) -> tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx def prepare_transaction_for_setting_metadata(self, owner: IAccount, args: Any) -> ITransaction: @@ -286,13 +302,22 @@ def prepare_transaction_for_setting_metadata(self, owner: IAccount, args: Any) - tx.version = int(args.version) tx.options = int(args.options) tx.guardian = args.guardian - tx.signature = bytes.fromhex(owner.sign_transaction(tx)) if args.gas_limit: tx.gas_limit = int(args.gas_limit) + tx.signature = bytes.fromhex(owner.sign_transaction(tx)) + return tx + def _load_validators_public_keys(self, args: Any) -> List[ValidatorPublicKey]: + if args.bls_keys: + return self._parse_public_bls_keys(args.bls_keys) + + validators_file_path = Path(args.validators_file).expanduser() + validators_file = ValidatorsFile(validators_file_path) + return validators_file.load_public_keys() + def _parse_public_bls_keys(self, public_bls_keys: str) -> List[ValidatorPublicKey]: keys = public_bls_keys.split(",") validator_public_keys: List[ValidatorPublicKey] = [] diff --git a/multiversx_sdk_cli/errors.py b/multiversx_sdk_cli/errors.py index 139b3c26..13b06e87 100644 --- a/multiversx_sdk_cli/errors.py +++ b/multiversx_sdk_cli/errors.py @@ -198,3 +198,13 @@ def __init__(self, message: str): class ArgumentsNotProvidedError(KnownError): def __init__(self, message: str): super().__init__(message) + + +class ProxyError(KnownError): + def __init__(self, message: str, url: str, data: str, code: str): + inner = { + "url": url, + "data": data, + "code": code + } + super().__init__(message, inner) diff --git a/multiversx_sdk_cli/interfaces.py b/multiversx_sdk_cli/interfaces.py index 9e736b17..e59c3c8f 100644 --- a/multiversx_sdk_cli/interfaces.py +++ b/multiversx_sdk_cli/interfaces.py @@ -15,7 +15,7 @@ class ITransaction(Protocol): gas_limit: int chain_id: str nonce: int - amount: int + value: int sender_username: str receiver_username: str gas_price: int diff --git a/multiversx_sdk_cli/localnet/step_build_software.py b/multiversx_sdk_cli/localnet/step_build_software.py index 34c46e79..533b0066 100644 --- a/multiversx_sdk_cli/localnet/step_build_software.py +++ b/multiversx_sdk_cli/localnet/step_build_software.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import Dict, List -from multiversx_sdk_cli import dependencies, utils +from multiversx_sdk_cli import dependencies, utils, workstation from multiversx_sdk_cli.errors import KnownError from multiversx_sdk_cli.localnet import libraries from multiversx_sdk_cli.localnet.config_root import ConfigRoot @@ -22,18 +22,16 @@ def build(configfile: Path, software_components: List[str]): cmd_node = config.software.mx_chain_go.get_cmd_node_folder() _do_build(cmd_node, golang_env) - - wasmer_path = golang.get_gopath() / "pkg" / "mod" / _get_wasm_vm_package(config) / "wasmer" - libraries.copy_libraries(wasmer_path, cmd_node) + _copy_wasmer_libs(config, cmd_node) + _set_rpath(cmd_node / "node") if "seednode" in software_components: logger.info("Building seednode...") cmd_seednode = config.software.mx_chain_go.get_cmd_seednode_folder() _do_build(cmd_seednode, golang_env) - - wasmer_path = golang.get_gopath() / "pkg" / "mod" / _get_wasm_vm_package(config) / "wasmer" - libraries.copy_libraries(wasmer_path, cmd_seednode) + _copy_wasmer_libs(config, cmd_seednode) + _set_rpath(cmd_seednode / "seednode") if "proxy" in software_components: logger.info("Building proxy...") @@ -48,9 +46,45 @@ def _do_build(cwd: Path, env: Dict[str, str]): raise KnownError(f"error code = {return_code}, see output") -def _get_wasm_vm_package(config: ConfigRoot) -> str: +def _copy_wasmer_libs(config: ConfigRoot, destination: Path): + golang = dependencies.get_golang() + vm_go_folder_name = _get_chain_vm_go_folder_name(config) + vm_go_path = golang.get_gopath() / "pkg" / "mod" / vm_go_folder_name + wasmer_path = vm_go_path / "wasmer" + wasmer2_path = vm_go_path / "wasmer2" + + libraries.copy_libraries(wasmer_path, destination) + libraries.copy_libraries(wasmer2_path, destination) + + +def _get_chain_vm_go_folder_name(config: ConfigRoot) -> str: go_mod = config.software.mx_chain_go.get_path_within_source(Path("go.mod")) lines = utils.read_lines(go_mod) - line = [line for line in lines if "github.com/multiversx/mx-chain-vm-v" in line][-1] + line = [line for line in lines if "github.com/multiversx/mx-chain-vm-go" in line][0] parts = line.split() return f"{parts[0]}@{parts[1]}" + + +def _set_rpath(cmd_path: Path): + """ + Set the rpath of the executable to the current directory, on a best-effort basis. + + For other occurrences of this approach, see: + - https://github.com/multiversx/mx-chain-scenario-cli-go/blob/master/.github/workflows/on_release_attach_artifacts.yml + """ + + if not workstation.is_osx(): + # We're only patching the executable on macOS. + # For Linux, we're leveraging LD_LIBRARY_PATH to resolve the libraries. + return + + try: + subprocess.check_call([ + "install_name_tool", + "-add_rpath", + "@loader_path", + cmd_path + ]) + except Exception as e: + # In most cases, this isn't critical (libraries might be found among the downloaded Go packages). + logger.warning(f"Failed to set rpath of {cmd_path}: {e}") diff --git a/multiversx_sdk_cli/localnet/step_start.py b/multiversx_sdk_cli/localnet/step_start.py index 14491576..11dd41eb 100644 --- a/multiversx_sdk_cli/localnet/step_start.py +++ b/multiversx_sdk_cli/localnet/step_start.py @@ -135,7 +135,7 @@ async def run(args: List[str], cwd: Path, delay: int = 0): if workstation.is_linux(): env["LD_LIBRARY_PATH"] = str(cwd) else: - # For MacOS, libwasmer is directly found near the binary (no workaround needed) + # For MacOS, dylibs are directly found near the binary (no workaround needed) pass process = await asyncio.create_subprocess_exec(*args, stdout=asyncio.subprocess.PIPE, diff --git a/multiversx_sdk_cli/projects/report/features/twiggy_paths_check.py b/multiversx_sdk_cli/projects/report/features/twiggy_paths_check.py index 8d8cbab3..31fa51ff 100644 --- a/multiversx_sdk_cli/projects/report/features/twiggy_paths_check.py +++ b/multiversx_sdk_cli/projects/report/features/twiggy_paths_check.py @@ -31,7 +31,6 @@ def run_twiggy_paths(wasm_path: Path) -> Path: rust = dependencies.get_module_by_key("rust") debug_wasm_path = _get_debug_wasm_path(wasm_path) - dependencies.install_module("twiggy") twiggy_paths_args = ["twiggy", "paths", str(debug_wasm_path)] output = myprocess.run_process(twiggy_paths_args, env=rust.get_env(), cwd=debug_wasm_path.parent, dump_to_stdout=False) diff --git a/multiversx_sdk_cli/tests/test_cli_contracts.py b/multiversx_sdk_cli/tests/test_cli_contracts.py index ef5780bc..b69b9867 100644 --- a/multiversx_sdk_cli/tests/test_cli_contracts.py +++ b/multiversx_sdk_cli/tests/test_cli_contracts.py @@ -290,6 +290,33 @@ def test_contract_deploy_without_required_arguments(): assert return_code +def test_contract_commands_argument_parameter(): + alice = f"{parent}/testdata/alice.pem" + adder = f"{parent}/testdata/adder.wasm" + + return_code = main([ + "contract", "deploy", + "--bytecode", adder, + "--pem", alice, + "--nonce", "7", + "--chain", "D", + "--gas-limit", "5000000", + "--arguments", "foobar", + ]) + assert return_code + + return_code = main([ + "contract", "deploy", + "--bytecode", adder, + "--pem", alice, + "--nonce", "7", + "--chain", "D", + "--gas-limit", "5000000", + "--arguments", "str:foobar", + ]) + assert not return_code + + def _read_stdout(capsys: Any) -> str: return capsys.readouterr().out.strip() diff --git a/multiversx_sdk_cli/tests/test_cli_staking_provider.py b/multiversx_sdk_cli/tests/test_cli_staking_provider.py index 3b3f8a10..7c141820 100644 --- a/multiversx_sdk_cli/tests/test_cli_staking_provider.py +++ b/multiversx_sdk_cli/tests/test_cli_staking_provider.py @@ -9,6 +9,7 @@ first_bls_key = "f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d" second_bls_key = "1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d" +validators_file = parent / "testdata" / "validators_file.json" def test_create_new_delegation_contract(capsys: Any): @@ -31,6 +32,31 @@ def test_create_new_delegation_contract(capsys: Any): assert transaction["chainID"] == "T" assert transaction["gasLimit"] == 60126500 assert transaction["value"] == "1250000000000000000000" + assert transaction["signature"] == "0a6d7249c671b1db00f1b8807770bb64eac51e2e2779e426f35439c6cb7b00dadd023392a061ba1b6ee35d235ac2c0ad87283413b1d5558d8526bc5712588702" + + +def test_create_new_delegation_contract_with_provided_gas_limit(capsys: Any): + main([ + "staking-provider", "create-new-delegation-contract", + "--pem", str(alice), + "--nonce", "7", "--estimate-gas", + "--value", "1250000000000000000000", + "--total-delegation-cap", "10000000000000000000000", + "--service-fee", "100", + "--chain", "T", + "--gas-limit", "60126501" + ]) + tx = get_transaction(capsys) + data = tx["emittedTransactionData"] + transaction = tx["emittedTransaction"] + + assert data == "createNewDelegationContract@021e19e0c9bab2400000@64" + assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6" + assert transaction["chainID"] == "T" + assert transaction["gasLimit"] == 60126501 + assert transaction["value"] == "1250000000000000000000" + assert transaction["signature"] == "8e28aa5a11454d975a4841086397000de053784b04e68402da9abcf26adc8726d3ce32f415119e3aa38746f2e5524063a6176a0c8cd88c9e8e89f9626d045202" def test_add_nodes(capsys: Any): @@ -51,9 +77,34 @@ def test_add_nodes(capsys: Any): assert data == "addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@604882237a9845f508ad03877b5aab90569683eeb51fafcbbeb87440ba359992b3c0b837a8757c25be18132549404f88@78689fd4b1e2e434d567fe01e61598a42717d83124308266bd09ccc15d2339dd318c019914b86ac29adbae5dd8a02d0307425e9bd85a296e94943708c72f8c670f0b7c50a890a5719088dbd9f1d062cad9acffa06df834106eebe1a4257ef00d@ec54a009695af56c3585ef623387b67b6df1974b0b3c9138eb64bde6eb33978ae9851112b20c99bf63588e8e949e4388@7188b234a8bf834f2e6258012aa09a2ab93178ffab9c789480275f61fe02cd1b9a58ddc63b79a73abea9e2b7ac5cac0b0d4324eff50aca2f0ec946b9ae6797511fa3ce461b57e77129cba8ab3b51147695d4ce889cbe67905f6586b4e4f22491@c6c637de17db5f89a2fa1d1d935cb60c0e5e8958d3bfc47f903f774dd97398c8fe22093e113865ee98c3afdd1de62694" assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh" + assert transaction["gasLimit"] == 20367000 + assert transaction["signature"] == "b383909206bf9631d5bef583c6e28250815494b459977fe8f037c2a97d2692a77d1b5c5dda6095d64ad180d213b5fd5eb7038a54af3765a3cb3fd86b86a1f305" + + +def test_add_nodes_with_gas_limit(capsys: Any): + validators_file = parent / "testdata" / "validators.json" + + main([ + "staking-provider", "add-nodes", + "--validators-file", str(validators_file), + "--delegation-contract", "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh", + "--pem", str(alice), + "--chain", "T", + "--nonce", "7", + "--gas-limit", "20367001" + ]) + tx = get_transaction(capsys) + data = tx["emittedTransactionData"] + transaction = tx["emittedTransaction"] + + assert data == "addNodes@e7beaa95b3877f47348df4dd1cb578a4f7cabf7a20bfeefe5cdd263878ff132b765e04fef6f40c93512b666c47ed7719b8902f6c922c04247989b7137e837cc81a62e54712471c97a2ddab75aa9c2f58f813ed4c0fa722bde0ab718bff382208@604882237a9845f508ad03877b5aab90569683eeb51fafcbbeb87440ba359992b3c0b837a8757c25be18132549404f88@78689fd4b1e2e434d567fe01e61598a42717d83124308266bd09ccc15d2339dd318c019914b86ac29adbae5dd8a02d0307425e9bd85a296e94943708c72f8c670f0b7c50a890a5719088dbd9f1d062cad9acffa06df834106eebe1a4257ef00d@ec54a009695af56c3585ef623387b67b6df1974b0b3c9138eb64bde6eb33978ae9851112b20c99bf63588e8e949e4388@7188b234a8bf834f2e6258012aa09a2ab93178ffab9c789480275f61fe02cd1b9a58ddc63b79a73abea9e2b7ac5cac0b0d4324eff50aca2f0ec946b9ae6797511fa3ce461b57e77129cba8ab3b51147695d4ce889cbe67905f6586b4e4f22491@c6c637de17db5f89a2fa1d1d935cb60c0e5e8958d3bfc47f903f774dd97398c8fe22093e113865ee98c3afdd1de62694" + assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh" + assert transaction["gasLimit"] == 20367001 + assert transaction["signature"] == "a889b50844eb5b33d410cbc8c8d2d88eebd64839d22fc1d246b82315123bd3acc6ad4445f9d2430965ce516ff89256faea42a97ebba2e1b386147ff8328b2e01" -def test_remove_nodes(capsys: Any): +def test_remove_nodes_with_bls_keys(capsys: Any): main([ "staking-provider", "remove-nodes", "--bls-keys", f"{first_bls_key},{second_bls_key}", @@ -72,7 +123,45 @@ def test_remove_nodes(capsys: Any): assert transaction["gasLimit"] == 13645500 -def test_stake_nodes(capsys: Any): +def test_remove_nodes_with_validators_file(capsys: Any): + main([ + "staking-provider", "remove-nodes", + "--validators-file", str(validators_file), + "--delegation-contract", "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh", + "--pem", str(alice), + "--chain", "T", + "--nonce", "7", "--estimate-gas" + ]) + tx = get_transaction(capsys) + data = tx["emittedTransactionData"] + transaction = tx["emittedTransaction"] + + assert data == "removeNodes@f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d@1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d" + assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh" + assert transaction["gasLimit"] == 13645500 + + +def test_stake_nodes_with_bls_keys(capsys: Any): + main([ + "staking-provider", "stake-nodes", + "--validators-file", str(validators_file), + "--delegation-contract", "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh", + "--pem", str(alice), + "--chain", "T", + "--nonce", "7", "--estimate-gas" + ]) + tx = get_transaction(capsys) + data = tx["emittedTransactionData"] + transaction = tx["emittedTransaction"] + + assert data == "stakeNodes@f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d@1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d" + assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh" + assert transaction["gasLimit"] == 18644000 + + +def test_stake_nodes_with_validators_file(capsys: Any): main([ "staking-provider", "stake-nodes", "--bls-keys", f"{first_bls_key},{second_bls_key}", diff --git a/multiversx_sdk_cli/tests/test_cli_transactions.py b/multiversx_sdk_cli/tests/test_cli_transactions.py index fda91c98..35897304 100644 --- a/multiversx_sdk_cli/tests/test_cli_transactions.py +++ b/multiversx_sdk_cli/tests/test_cli_transactions.py @@ -1,3 +1,4 @@ +import json from pathlib import Path from typing import Any @@ -28,5 +29,24 @@ def test_relayed_v1_transaction(capsys: Any): assert relayed_tx == "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414141415141414141414141414141414141414141414141414141414141432f2f383d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a2239682b6e6742584f5536776674315464437368534d4b3454446a5a32794f74686336564c576e3478724d5a706248427738677a6c6659596d362b766b505258303764634a562b4745635462616a7049692b5a5a5942773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a317d" +def test_create_tx_and_sign_by_hash(capsys: Any): + return_code = main([ + "tx", "new", + "--pem", str(testdata_path / "alice.pem"), + "--receiver", "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + "--nonce", "89", + "--gas-limit", "50000", + "--version", "2", + "--options", "1", + "--chain", "integration tests chain ID", + ]) + assert False if return_code else True + + tx = _read_stdout(capsys) + tx_json = json.loads(tx) + signature = tx_json["emittedTransaction"]["signature"] + assert signature == "f0c81f2393b1ec5972c813f817bae8daa00ade91c6f75ea604ab6a4d2797aca4378d783023ff98f1a02717fe4f24240cdfba0b674ee9abb18042203d713bc70a" + + def _read_stdout(capsys: Any) -> str: return capsys.readouterr().out.strip() diff --git a/multiversx_sdk_cli/tests/test_cli_validators.sh b/multiversx_sdk_cli/tests/test_cli_validators.sh index 7a355223..d489c9c0 100755 --- a/multiversx_sdk_cli/tests/test_cli_validators.sh +++ b/multiversx_sdk_cli/tests/test_cli_validators.sh @@ -7,38 +7,38 @@ testAll() { REWARD_ADDRESS="erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8" echo "Stake with recall nonce" - ${CLI} --verbose validator stake --pem="${USERS}/alice.pem" --value="2500${DENOMINATION}" --validators-file=./testdata/validators.json --reward-address=${REWARD_ADDRESS} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator stake --pem="${USERS}/alice.pem" --value="2500${DENOMINATION}" --validators-file=./testdata/validators.json --reward-address=${REWARD_ADDRESS} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "Stake with provided nonce" ${CLI} --verbose validator stake --pem="${USERS}/bob.pem" --value="2500${DENOMINATION}" --validators-file=./testdata/validators.json --reward-address=${REWARD_ADDRESS} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --nonce=300 || return 1 echo "Stake with topUP" - ${CLI} --verbose validator stake --top-up --pem="${USERS}/carol.pem" --value="2711${DENOMINATION}" --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator stake --top-up --pem="${USERS}/carol.pem" --value="2711${DENOMINATION}" --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "Unstake" - ${CLI} --verbose validator unstake --pem="${USERS}/dan.pem" --nodes-public-keys="${BLS_KEY}" --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator unstake --pem="${USERS}/dan.pem" --nodes-public-keys="${BLS_KEY}" --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "Unbond" - ${CLI} --verbose validator unbond --pem="${USERS}/eve.pem" --nodes-public-keys=${BLS_KEY} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator unbond --pem="${USERS}/eve.pem" --nodes-public-keys=${BLS_KEY} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "Unjail" - ${CLI} --verbose validator unjail --pem="${USERS}/frank.pem" --value="2500${DENOMINATION}" --nodes-public-keys=${BLS_KEY} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator unjail --pem="${USERS}/frank.pem" --value="2500${DENOMINATION}" --nodes-public-keys=${BLS_KEY} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "Change reward address" - ${CLI} --verbose validator change-reward-address --pem="${USERS}/grace.pem" --reward-address=${REWARD_ADDRESS} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator change-reward-address --pem="${USERS}/grace.pem" --reward-address=${REWARD_ADDRESS} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "UnstakeNodes" - ${CLI} --verbose validator unstake-nodes --pem="${USERS}/heidi.pem" --nodes-public-keys=${BLS_KEY} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator unstake-nodes --pem="${USERS}/heidi.pem" --nodes-public-keys=${BLS_KEY} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "UnstakeTokens" - ${CLI} --verbose validator unstake-tokens --pem="${USERS}/ivan.pem" --unstake-value="11${DENOMINATION}" --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator unstake-tokens --pem="${USERS}/ivan.pem" --unstake-value="11${DENOMINATION}" --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "UnbondNodes" - ${CLI} --verbose validator unbond-nodes --pem="${USERS}/judy.pem" --nodes-public-keys=${BLS_KEY} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator unbond-nodes --pem="${USERS}/judy.pem" --nodes-public-keys=${BLS_KEY} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "UnbondTokens" - ${CLI} --verbose validator unbond-tokens --pem="${USERS}/mallory.pem" --unbond-value="20${DENOMINATION}" --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator unbond-tokens --pem="${USERS}/mallory.pem" --unbond-value="20${DENOMINATION}" --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "CleanRegistrationData" - ${CLI} --verbose validator clean-registered-data --pem="${USERS}/mike.pem" --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator clean-registered-data --pem="${USERS}/mike.pem" --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 echo "ReStakeUnstakedNodes" - ${CLI} --verbose validator restake-unstaked-nodes --pem="${USERS}/alice.pem" --nodes-public-keys=${BLS_KEY} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce --send || return 1 + ${CLI} --verbose validator restake-unstaked-nodes --pem="${USERS}/alice.pem" --nodes-public-keys=${BLS_KEY} --chain=${CHAIN_ID} --proxy=${PROXY} --estimate-gas --recall-nonce || return 1 } diff --git a/multiversx_sdk_cli/tests/test_cli_wallet.py b/multiversx_sdk_cli/tests/test_cli_wallet.py index 2e495382..5255b4d3 100644 --- a/multiversx_sdk_cli/tests/test_cli_wallet.py +++ b/multiversx_sdk_cli/tests/test_cli_wallet.py @@ -367,7 +367,8 @@ def test_sign_and_verify_message_with_multi_address_pem(capsys: Any): def _read_stdout_mnemonic(capsys: Any) -> str: - return _read_stdout(capsys).replace("Mnemonic:", "").strip() + lines = _read_stdout(capsys).split("\n") + return lines[0].replace("Mnemonic:", "").strip() def _read_stdout(capsys: Any) -> str: diff --git a/multiversx_sdk_cli/tests/test_proxy.py b/multiversx_sdk_cli/tests/test_proxy.py index e49cb06c..969aecd2 100644 --- a/multiversx_sdk_cli/tests/test_proxy.py +++ b/multiversx_sdk_cli/tests/test_proxy.py @@ -32,11 +32,11 @@ def test_query_contract(): [ "contract", "query", - "erd1qqqqqqqqqqqqqpgq8z2zzyu30f4607hth0tfj5m3vpjvwrvvrawqw09jem", + "erd1qqqqqqqqqqqqqpgq6qr0w0zzyysklfneh32eqp2cf383zc89d8sstnkl60", "--function", "getSum", "--proxy", - "https://testnet-api.multiversx.com", + "https://devnet-api.multiversx.com", ] ) assert False if result else True @@ -48,9 +48,9 @@ def test_get_transaction(): "tx", "get", "--proxy", - "https://testnet-api.multiversx.com", + "https://devnet-api.multiversx.com", "--hash", - "bf63fdd7d74cbc78f1ec0fbad05f156984a5c995b782e1947352210dd80c5164", + "06f381ee88ed27ba08a35f995f17dceb737e1a99c5c4da0c247bbe7aa1d18551", ] ) assert False if result else True diff --git a/multiversx_sdk_cli/tests/testdata/validator_01.pem b/multiversx_sdk_cli/tests/testdata/validator_01.pem new file mode 100644 index 00000000..32f62751 --- /dev/null +++ b/multiversx_sdk_cli/tests/testdata/validator_01.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY for f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d----- +N2MxOWJmM2EwYzU3Y2RkMWZiMDhlNDYwN2NlYmFhMzY0N2Q2YjkyNjFiNDY5M2Y2 +MWU5NmU1NGIyMThkNDQyYQ== +-----END PRIVATE KEY for f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d----- diff --git a/multiversx_sdk_cli/tests/testdata/validator_02.pem b/multiversx_sdk_cli/tests/testdata/validator_02.pem new file mode 100644 index 00000000..6f700ebb --- /dev/null +++ b/multiversx_sdk_cli/tests/testdata/validator_02.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY for 1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d----- +MzAzNGIxZDU4NjI4YTg0Mjk4NGRhMGM3MGRhMGI1YTI1MWViYjJhZWJmNTFhZmM1 +YjU4NmUyODM5YjVlNTI2Mw== +-----END PRIVATE KEY for 1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d----- diff --git a/multiversx_sdk_cli/tests/testdata/validators_file.json b/multiversx_sdk_cli/tests/testdata/validators_file.json new file mode 100644 index 00000000..f9fedd19 --- /dev/null +++ b/multiversx_sdk_cli/tests/testdata/validators_file.json @@ -0,0 +1,10 @@ +{ + "validators": [ + { + "pemFile": "validator_01.pem" + }, + { + "pemFile": "validator_02.pem" + } + ] +} diff --git a/multiversx_sdk_cli/transactions.py b/multiversx_sdk_cli/transactions.py index 418a469d..6f32c511 100644 --- a/multiversx_sdk_cli/transactions.py +++ b/multiversx_sdk_cli/transactions.py @@ -2,7 +2,7 @@ import json import logging import time -from typing import Any, Dict, Optional, Protocol, Sequence, TextIO, Tuple +from typing import Any, Dict, Optional, Protocol, TextIO from multiversx_sdk_core import Address, Transaction, TransactionPayload @@ -30,9 +30,6 @@ class INetworkProvider(Protocol): def send_transaction(self, transaction: ITransaction) -> str: ... - def send_transactions(self, transactions: Sequence[ITransaction]) -> Tuple[int, str]: - ... - def get_transaction(self, tx_hash: str, with_process_status: Optional[bool] = False) -> ITransactionOnNetwork: ... @@ -77,7 +74,7 @@ def do_prepare_transaction(args: Any) -> Transaction: gas_price=int(args.gas_price), data=str(args.data).encode(), nonce=int(args.nonce), - amount=int(args.value), + value=int(args.value), version=int(args.version), options=int(args.options) ) @@ -153,7 +150,7 @@ def tx_to_dictionary_as_inner_for_relayed_V1(tx: Transaction) -> Dict[str, Any]: dictionary["nonce"] = tx.nonce dictionary["sender"] = base64.b64encode(Address.new_from_bech32(tx.sender).get_public_key()).decode() dictionary["receiver"] = base64.b64encode(Address.new_from_bech32(tx.receiver).get_public_key()).decode() - dictionary["value"] = tx.amount + dictionary["value"] = tx.value dictionary["gasPrice"] = tx.gas_price dictionary["gasLimit"] = tx.gas_limit dictionary["data"] = base64.b64encode(tx.data).decode() @@ -207,7 +204,7 @@ def load_transaction_from_file(f: TextIO) -> Transaction: receiver_username=decode_field_value(instance.receiverUsername), gas_limit=instance.gasLimit, gas_price=instance.gasPrice, - amount=int(instance.value), + value=int(instance.value), data=TransactionPayload.from_encoded_str(instance.data).data, version=instance.version, options=instance.options, diff --git a/multiversx_sdk_cli/validators/validators_file.py b/multiversx_sdk_cli/validators/validators_file.py index 8da16bd5..4a664aac 100644 --- a/multiversx_sdk_cli/validators/validators_file.py +++ b/multiversx_sdk_cli/validators/validators_file.py @@ -1,8 +1,9 @@ import json from pathlib import Path -from typing import List +from typing import Dict, List from multiversx_sdk_wallet import ValidatorSigner +from multiversx_sdk_wallet.validator_keys import ValidatorPublicKey from multiversx_sdk_wallet.validator_pem import ValidatorPEM from multiversx_sdk_cli import guards @@ -23,17 +24,28 @@ def get_validators_list(self): def load_signers(self) -> List[ValidatorSigner]: signers: List[ValidatorSigner] = [] for validator in self.get_validators_list(): - # Get path of "pemFile", make it absolute - validator_pem = Path(validator.get("pemFile")).expanduser() - validator_pem = validator_pem if validator_pem.is_absolute() else self.validators_file_path.parent / validator_pem - - pem_file = ValidatorPEM.from_file(validator_pem) - + pem_file = self._load_validator_pem(validator) validator_signer = ValidatorSigner(pem_file.secret_key) signers.append(validator_signer) return signers + def load_public_keys(self) -> List[ValidatorPublicKey]: + public_keys: List[ValidatorPublicKey] = [] + + for validator in self.get_validators_list(): + pem_file = self._load_validator_pem(validator) + public_keys.append(pem_file.secret_key.generate_public_key()) + + return public_keys + + def _load_validator_pem(self, validator: Dict[str, str]) -> ValidatorPEM: + # Get path of "pemFile", make it absolute + validator_pem = Path(validator.get("pemFile", "")).expanduser() + validator_pem = validator_pem if validator_pem.is_absolute() else self.validators_file_path.parent / validator_pem + + return ValidatorPEM.from_file(validator_pem) + def _read_json_file_validators(self): val_file = self.validators_file_path.expanduser() guards.is_file(val_file) diff --git a/multiversx_sdk_cli/workstation.py b/multiversx_sdk_cli/workstation.py index 01996d9d..af1b5142 100644 --- a/multiversx_sdk_cli/workstation.py +++ b/multiversx_sdk_cli/workstation.py @@ -18,6 +18,10 @@ def is_windows(): return get_platform() == "windows" +def is_osx(): + return get_platform() == "osx" + + def get_platform(): platforms = { "linux": "linux", diff --git a/pyproject.toml b/pyproject.toml index acefc85d..b1220a9b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "multiversx-sdk-cli" -version = "9.4.0" +version = "9.5.4" authors = [ { name="MultiversX" }, ] diff --git a/requirements.txt b/requirements.txt index 0e46f190..1d7aa8f9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,6 @@ requests-cache rich==13.3.4 argcomplete==3.2.2 -multiversx-sdk-core>=0.7.0,<0.8.0 -multiversx-sdk-network-providers>=0.12.0,<0.13.0 -multiversx-sdk-wallet>=0.8.0,<0.9.0 +multiversx-sdk-core>=0.8.0,<0.9.0 +multiversx-sdk-network-providers>=0.13.0,<0.14.0 +multiversx-sdk-wallet>=0.9.0,<0.10.0