diff --git a/.github/workflows/test-localnet-tests.yml b/.github/workflows/test-localnet-tests.yml index 5ba77048..5f64fcc8 100644 --- a/.github/workflows/test-localnet-tests.yml +++ b/.github/workflows/test-localnet-tests.yml @@ -52,7 +52,7 @@ jobs: nohup python3 -m multiversx_sdk_cli.cli localnet start --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml > localnet.log 2>&1 & echo $! > localnet.pid sleep 120 - # - name: Test localnet dependent tests - # run: | - # pytest -m require_localnet . - # python3 -m multiversx_sdk_cli.cli localnet clean --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml + - name: Test localnet dependent tests + run: | + pytest -m require_localnet . + python3 -m multiversx_sdk_cli.cli localnet clean --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml diff --git a/.github/workflows/test-localnet.yml b/.github/workflows/test-localnet.yml deleted file mode 100644 index 9f3f063d..00000000 --- a/.github/workflows/test-localnet.yml +++ /dev/null @@ -1,84 +0,0 @@ -name: Test localnet - -on: - pull_request: - branches: [main, feat/*] - workflow_dispatch: - -permissions: - contents: read - -env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} - -jobs: - localnet: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - python-version: [3.11] - - steps: - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python3 -m pip install --upgrade pip - pip3 install -r requirements.txt - - - name: Smoke test (with resolution == remote) - run: | - mkdir -p ~/multiversx-sdk - export PYTHONPATH=. - python3 -m multiversx_sdk_cli.cli config set github_api_token ${{ secrets.GITHUB_TOKEN }} - python3 -m multiversx_sdk_cli.cli localnet prerequisites --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml - python3 -m multiversx_sdk_cli.cli localnet build --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml - - # "Go" and artifacts from "GOPATH/pkg/mod" are not needed anymore. - sudo rm -rf ~/multiversx-sdk/golang - - python3 -m multiversx_sdk_cli.cli localnet clean --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml - 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 - export PYTHONPATH=. - - git clone https://github.com/multiversx/mx-chain-go --branch=master --single-branch ~/multiversx-sdk/sandbox/mx-chain-go - git clone https://github.com/multiversx/mx-chain-proxy-go --branch=master --single-branch ~/multiversx-sdk/sandbox/mx-chain-proxy-go - - python3 -m multiversx_sdk_cli.cli localnet prerequisites --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_local.toml - python3 -m multiversx_sdk_cli.cli localnet build --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_local.toml - - # "Go" and artifacts from "GOPATH/pkg/mod" are not needed anymore. - sudo rm -rf ~/multiversx-sdk/golang - - 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 e27952f1..c05b48da 100644 --- a/CLI.md +++ b/CLI.md @@ -23,7 +23,7 @@ See: COMMAND GROUPS: - {config-wallet,contract,tx,validator,ledger,wallet,validator-wallet,deps,config,localnet,data,staking-provider,dns,faucet,multisig,governance,config-env,get} + {config-wallet,contract,tx,validator,ledger,wallet,validator-wallet,deps,config,localnet,data,staking-provider,dns,faucet,multisig,governance,config-env,get,token} TOP-LEVEL OPTIONS: -h, --help show this help message and exit @@ -53,6 +53,7 @@ multisig Deploy and interact with the Multisig Smart Contr governance Propose, vote and interact with the governance contract. config-env Configure MultiversX CLI to use specific environment values. get Get info from the network. +token Perform token management operations (issue tokens, create NFTs, set roles, etc.) ``` ## Group **Contract** @@ -144,6 +145,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -237,6 +240,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -340,6 +345,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -551,6 +558,8 @@ options: --receiver-username RECEIVER_USERNAME 🖄 the username of the receiver --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --data DATA the payload, or 'memo' of the transaction (default: ) --chain CHAIN the chain identifier @@ -771,6 +780,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -827,6 +838,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -881,6 +894,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -935,6 +950,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -989,6 +1006,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1043,6 +1062,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1096,6 +1117,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1150,6 +1173,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1204,6 +1229,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1258,6 +1285,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1312,6 +1341,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1365,6 +1396,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1458,6 +1491,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1530,6 +1565,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1586,6 +1623,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1642,6 +1681,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1698,6 +1739,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1754,6 +1797,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1810,6 +1855,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1864,6 +1911,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1918,6 +1967,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1972,6 +2023,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2026,6 +2079,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2080,6 +2135,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2135,6 +2192,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2190,6 +2249,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2246,6 +2307,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2302,6 +2365,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2359,6 +2424,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2416,6 +2483,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3189,6 +3258,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3264,6 +3335,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3337,6 +3410,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3409,6 +3484,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3481,6 +3558,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3553,6 +3632,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3625,6 +3706,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3698,6 +3781,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3779,6 +3864,8 @@ options: --receiver-username RECEIVER_USERNAME 🖄 the username of the receiver --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3863,6 +3950,8 @@ options: --receiver-username RECEIVER_USERNAME 🖄 the username of the receiver --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3948,6 +4037,8 @@ options: --receiver-username RECEIVER_USERNAME 🖄 the username of the receiver --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4031,6 +4122,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4114,6 +4207,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4186,6 +4281,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4258,6 +4355,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4330,6 +4429,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4402,6 +4503,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4474,6 +4577,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4546,6 +4651,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4620,6 +4727,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4693,6 +4802,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4765,6 +4876,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5163,6 +5276,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5234,6 +5349,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5304,6 +5421,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5375,6 +5494,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5444,6 +5565,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5518,6 +5641,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5657,7 +5782,7 @@ dump Dumps the active environment. delete Deletes an env value from the specified environment. switch Switch to a different environment. list List available environments -remove Deletes an environment from the env file. Use `mxpy config-env switch` to move to another env. +remove Deletes an environment from the env file. Use `mxpy config-env switch` to switch to another env. reset Deletes the environment file. Default env will be used. ``` @@ -5761,7 +5886,7 @@ options: $ mxpy config-env remove --help usage: mxpy config-env remove [-h] ... -Deletes an environment from the env file. Use `mxpy config-env switch` to move to another env. +Deletes an environment from the env file. Use `mxpy config-env switch` to switch to another env. options: -h, --help show this help message and exit @@ -6055,3 +6180,2686 @@ options: --hash HASH the transaction hash ``` +## Group **Token** + + +``` +$ mxpy token --help +usage: mxpy token COMMAND [-h] ... + +Perform token management operations (issue tokens, create NFTs, set roles, etc.) + +COMMANDS: + {issue-fungible,issue-semi-fungible,issue-non-fungible,register-meta-esdt,register-and-set-all-roles,set-burn-role-globally,unset-burn-role-globally,set-special-role-fungible,unset-special-role-fungible,set-special-role-semi-fungible,unset-special-role-semi-fungible,set-special-role-meta-esdt,unset-special-role-meta-esdt,set-special-role-nft,unset-special-role-nft,create-nft,pause,unpause,freeze,unfreeze,wipe,local-mint,local-burn,update-attributes,add-quantity,burn-quantity,modify-royalties,set-new-uris,modify-creator,update-metadata,nft-metadata-recreate,change-to-dynamic,update-token-id,register-dynamic,register-dynamic-and-set-all-roles,transfer-ownership,freeze-single-nft,unfreeze-single-nft,change-sft-to-meta-esdt,transfer-nft-create-role,stop-nft-creation,wipe-single-nft,add-uris} + +OPTIONS: + -h, --help show this help message and exit + +---------------- +COMMANDS summary +---------------- +issue-fungible Issue a new fungible ESDT token. +issue-semi-fungible Issue a new semi-fungible ESDT token. +issue-non-fungible Issue a new non-fungible ESDT token (NFT). +register-meta-esdt Register a MetaESDT token. +register-and-set-all-roles Register a token and set all roles. +set-burn-role-globally Set the burn role globally for a token. +unset-burn-role-globally Unset the burn role globally for a token. +set-special-role-fungible Set special roles on a fungible token for a user. +unset-special-role-fungible Unset special roles on a fungible token for a user. +set-special-role-semi-fungible Set special roles on a semi-fungible token for a user. +unset-special-role-semi-fungible Unset special roles on a semi-fungible token for a user. +set-special-role-meta-esdt Set special roles on a meta-esdt token for a user. +unset-special-role-meta-esdt Unset special roles on a meta-esdt token for a user. +set-special-role-nft Set special roles on a non-fungible token for a user. +unset-special-role-nft Unset special roles on a non-fungible token for a user. +create-nft Create a non-fungible token. +pause Pause a token. +unpause Unpause a token. +freeze Freeze a token for a user. +unfreeze Unfreeze a token for a user. +wipe Wipe a token for a user. +local-mint Mint new tokens. +local-burn Burn tokens. +update-attributes Update token attributes. +add-quantity Increase token quantity. +burn-quantity Burn token quantity. +modify-royalties Modify token royalties. +set-new-uris Set new uris. +modify-creator Modify the creator of the token. +update-metadata Update the metadata of the token. +nft-metadata-recreate Recreate the metadata of the token. +change-to-dynamic Change a token to a dynamic token. +update-token-id Update token id. +register-dynamic Register a dynamic token. +register-dynamic-and-set-all-roles Register a dynamic token and set all roles. +transfer-ownership Transfer the ownership of a token to another user. +freeze-single-nft Freeze the NFT of a user. +unfreeze-single-nft Unfreeze the NFT of a user. +change-sft-to-meta-esdt Change a semi fungible token to a Meta ESDT. +transfer-nft-create-role Transfer the nft create role to a user. +stop-nft-creation Stop the creation of new NFTs. +wipe-single-nft Wipe the NFT of a user. +add-uris Add uris for a token. + +``` +### Token.IssueFungbile + + +``` +$ mxpy token issue-fungible --help +usage: mxpy token issue-fungible [-h] ... + +Issue a new fungible ESDT token. + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME the name of the token to be issued: 3-20 alphanumerical characters + --token-ticker TOKEN_TICKER the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical + characters + --initial-supply INITIAL_SUPPLY the initial supply of the token to be issued + --num-decimals NUM_DECIMALS a numerical value between 0 and 18 representing number of decimals + --cannot-freeze make token not freezable + --cannot-wipe make token not wipeable + --cannot-pause make token not pausable + --cannot-change-owner don't allow changing the token's owner + --cannot-upgrade don't allow upgrading the token + --cannot-add-special-roles don't allow special roles to be added for the token + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.IssueNonFungbile + + +``` +$ mxpy token issue-non-fungible --help +usage: mxpy token issue-non-fungible [-h] ... + +Issue a new non-fungible ESDT token (NFT). + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME the name of the token to be issued: 3-20 alphanumerical characters + --token-ticker TOKEN_TICKER the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical + characters + --cannot-freeze make token not freezable + --cannot-wipe make token not wipeable + --cannot-pause make token not pausable + --cannot-change-owner don't allow changing the token's owner + --cannot-upgrade don't allow upgrading the token + --cannot-add-special-roles don't allow special roles to be added for the token + --cannot-transfer-nft-create-role don't allow for nft create roles to be transferred for the token + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.RegisterMetaEsdt + + +``` +$ mxpy token register-meta-esdt --help +usage: mxpy token register-meta-esdt [-h] ... + +Register a MetaESDT token. + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME the name of the token to be issued: 3-20 alphanumerical characters + --token-ticker TOKEN_TICKER the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical + characters + --num-decimals NUM_DECIMALS a numerical value between 0 and 18 representing number of decimals + --cannot-freeze make token not freezable + --cannot-wipe make token not wipeable + --cannot-pause make token not pausable + --cannot-change-owner don't allow changing the token's owner + --cannot-upgrade don't allow upgrading the token + --cannot-add-special-roles don't allow special roles to be added for the token + --cannot-transfer-nft-create-role don't allow for nft create roles to be transferred for the token + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.RegisterAndSetAllRoles + + +``` +$ mxpy token register-and-set-all-roles --help +usage: mxpy token register-and-set-all-roles [-h] ... + +Register a token and set all roles. + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME the name of the token to be issued: 3-20 alphanumerical characters + --token-ticker TOKEN_TICKER the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical + characters + --num-decimals NUM_DECIMALS a numerical value between 0 and 18 representing number of decimals + --token-type {NFT,SFT,META,FNG} the token type + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetBurnRoleGlobally + + +``` +$ mxpy token set-burn-role-globally --help +usage: mxpy token set-burn-role-globally [-h] ... + +Set the burn role globally for a token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnsetBurnRoleGlobally + + +``` +$ mxpy token unset-burn-role-globally --help +usage: mxpy token unset-burn-role-globally [-h] ... + +Unset the burn role globally for a token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetSpecialRoleFungible + + +``` +$ mxpy token set-special-role-fungible --help +usage: mxpy token set-special-role-fungible [-h] ... + +Set special roles on a fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --local-mint role for local minting + --local-burn role for local burning + --esdt-transfer-role role for esdt transfer + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnsetSpecialRoleFungible + + +``` +$ mxpy token unset-special-role-fungible --help +usage: mxpy token unset-special-role-fungible [-h] ... + +Unset special roles on a fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --local-mint role for local minting + --local-burn role for local burning + --esdt-transfer-role role for esdt transfer + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetSpecialRoleSemiFungible + + +``` +$ mxpy token set-special-role-semi-fungible --help +usage: mxpy token set-special-role-semi-fungible [-h] ... + +Set special roles on a semi-fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-create role for nft create + --nft-burn role for nft burn + --nft-add-quantity role for adding quantity + --esdt-transfer-role role for esdt transfer + --nft-update role for updating nft + --esdt-modify-royalties role for modifying royalties + --esdt-set-new-uri role for setting new uri + --esdt-modify-creator role for modifying creator + --nft-recreate role for recreating nft + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnsetSpecialRoleSemiFungible + + +``` +$ mxpy token unset-special-role-semi-fungible --help +usage: mxpy token unset-special-role-semi-fungible [-h] ... + +Unset special roles on a semi-fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-burn role for nft burn + --nft-add-quantity role for adding quantity + --esdt-transfer-role role for esdt transfer + --nft-update role for updating nft + --esdt-modify-royalties role for modifying royalties + --esdt-set-new-uri role for setting new uri + --esdt-modify-creator role for modifying creator + --nft-recreate role for recreating nft + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetSpecialRoleMetaEsdt + + +``` +$ mxpy token set-special-role-meta-esdt --help +usage: mxpy token set-special-role-meta-esdt [-h] ... + +Set special roles on a meta-esdt token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-create role for nft create + --nft-burn role for nft burn + --nft-add-quantity role for adding quantity + --esdt-transfer-role role for esdt transfer + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnsetSpecialRoleMetaEsdt + + +``` +$ mxpy token unset-special-role-meta-esdt --help +usage: mxpy token unset-special-role-meta-esdt [-h] ... + +Unset special roles on a meta-esdt token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-burn role for nft burn + --nft-add-quantity role for adding quantity + --esdt-transfer-role role for esdt transfer + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetSpecialRoleNft + + +``` +$ mxpy token set-special-role-nft --help +usage: mxpy token set-special-role-nft [-h] ... + +Set special roles on a non-fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-create role for nft create + --nft-burn role for nft burn + --nft-update-attributes role for updating attributes + --nft-add-uri role for adding uri + --esdt-transfer-role role for esdt transfer + --nft-update role for updating nft + --esdt-modify-royalties role for modifying royalties + --esdt-set-new-uri role for setting new uri + --esdt-modify-creator role for modifying creator + --nft-recreate role for recreating nft + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnsetSpecialRoleNft + + +``` +$ mxpy token unset-special-role-nft --help +usage: mxpy token unset-special-role-nft [-h] ... + +Unset special roles on a non-fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-create role for nft create + --nft-burn role for nft burn + --nft-update-attributes role for updating attributes + --nft-add-uri role for adding uri + --esdt-transfer-role role for esdt transfer + --nft-update role for updating nft + --esdt-modify-royalties role for modifying royalties + --esdt-set-new-uri role for setting new uri + --esdt-modify-creator role for modifying creator + --nft-recreate role for recreating nft + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.CreateNft + + +``` +$ mxpy token create-nft --help +usage: mxpy token create-nft [-h] ... + +Create a non-fungible token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --initial-quantity INITIAL_QUANTITY The initial quantity of the token. + --name NAME The name of the token. + --royalties ROYALTIES The royalties of the token. + --hash HASH The hash of the token. + --attributes ATTRIBUTES The hex-string attributes of the token. + --uris URIS [URIS ...] The uris of the token. + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.Pause + + +``` +$ mxpy token pause --help +usage: mxpy token pause [-h] ... + +Pause a token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.Unpause + + +``` +$ mxpy token unpause --help +usage: mxpy token unpause [-h] ... + +Unpause a token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.Freeze + + +``` +$ mxpy token freeze --help +usage: mxpy token freeze [-h] ... + +Freeze a token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.Unfreeze + + +``` +$ mxpy token unfreeze --help +usage: mxpy token unfreeze [-h] ... + +Unfreeze a token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.Wipe + + +``` +$ mxpy token wipe --help +usage: mxpy token wipe [-h] ... + +Wipe a token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.LocalMint + + +``` +$ mxpy token local-mint --help +usage: mxpy token local-mint [-h] ... + +Mint new tokens. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --supply-to-mint SUPPLY_TO_MINT The amount of new tokens to mint + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.LocalBurn + + +``` +$ mxpy token local-burn --help +usage: mxpy token local-burn [-h] ... + +Burn tokens. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --supply-to-burn SUPPLY_TO_BURN The amount of tokens to burn + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UpdateAttributes + + +``` +$ mxpy token update-attributes --help +usage: mxpy token update-attributes [-h] ... + +Update token attributes. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --attributes ATTRIBUTES The hex-string attributes of the token + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.AddQuantity + + +``` +$ mxpy token add-quantity --help +usage: mxpy token add-quantity [-h] ... + +Increase token quantity. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --quantity QUANTITY The quantity to add + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.BurnQuantity + + +``` +$ mxpy token burn-quantity --help +usage: mxpy token burn-quantity [-h] ... + +Burn token quantity. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --quantity QUANTITY The quantity to burn + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.ModifyRolaties + + +``` +$ mxpy token modify-royalties --help +usage: mxpy token modify-royalties [-h] ... + +Modify token royalties. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --royalties ROYALTIES The new token royalties (e.g. 1234 for 12.34%) + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetNewUris + + +``` +$ mxpy token set-new-uris --help +usage: mxpy token set-new-uris [-h] ... + +Set new uris. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --uris URIS [URIS ...] The new uris + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.ModifyCreator + + +``` +$ mxpy token modify-creator --help +usage: mxpy token modify-creator [-h] ... + +Modify the creator of the token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UpdateMetadata + + +``` +$ mxpy token update-metadata --help +usage: mxpy token update-metadata [-h] ... + +Update the metadata of the token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --token-name TOKEN_NAME The new name of the token + --royalties ROYALTIES The new token royalties (e.g. 1234 for 12.34%) + --hash HASH The new hash of the token + --attributes ATTRIBUTES The new attributes of the token as a hex-encoded string + --uris URIS [URIS ...] The new uris + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.NftMetadataRecreate + + +``` +$ mxpy token nft-metadata-recreate --help +usage: mxpy token nft-metadata-recreate [-h] ... + +Recreate the metadata of the token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --token-name TOKEN_NAME The new name of the token + --royalties ROYALTIES The new token royalties (e.g. 1234 for 12.34%) + --hash HASH The new hash of the token + --attributes ATTRIBUTES The new attributes of the token as a hex-encoded string + --uris URIS [URIS ...] The new uris + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.ChangeToDynamic + + +``` +$ mxpy token change-to-dynamic --help +usage: mxpy token change-to-dynamic [-h] ... + +Change a token to a dynamic token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UpdateTokenId + + +``` +$ mxpy token update-token-id --help +usage: mxpy token update-token-id [-h] ... + +Update token id. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.RegisterDynamic + + +``` +$ mxpy token register-dynamic --help +usage: mxpy token register-dynamic [-h] ... + +Register a dynamic token. + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME The token name + --token-ticker TOKEN_TICKER The token ticker + --token-type {NFT,SFT,FNG,META} The token type + --denominator DENOMINATOR The number of decimals, only needed when token type is META ESDT + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.RegisterDynamicAndSetAllRoles + + +``` +$ mxpy token register-dynamic-and-set-all-roles --help +usage: mxpy token register-dynamic-and-set-all-roles [-h] ... + +Register a dynamic token and set all roles. + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME The token name + --token-ticker TOKEN_TICKER The token ticker + --token-type {NFT,SFT,FNG,META} The token type + --denominator DENOMINATOR The number of decimals, only needed when token type is META ESDT + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.TransferOwnership + + +``` +$ mxpy token transfer-ownership --help +usage: mxpy token transfer-ownership [-h] ... + +Transfer the ownership of a token to another user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --new-owner NEW_OWNER The new token owner + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.FreezeSingleNft + + +``` +$ mxpy token freeze-single-nft --help +usage: mxpy token freeze-single-nft [-h] ... + +Freeze the NFT of a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnfreezeSingleNft + + +``` +$ mxpy token unfreeze-single-nft --help +usage: mxpy token unfreeze-single-nft [-h] ... + +Unfreeze the NFT of a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.ChangeSftToMetaEsdt + + +``` +$ mxpy token change-sft-to-meta-esdt --help +usage: mxpy token change-sft-to-meta-esdt [-h] ... + +Change a semi fungible token to a Meta ESDT. + +options: + -h, --help show this help message and exit + --collection COLLECTION The collection identifier + --decimals DECIMALS The number of decimals the meta esdt will have + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.TransferNftCreateRole + + +``` +$ mxpy token transfer-nft-create-role --help +usage: mxpy token transfer-nft-create-role [-h] ... + +Transfer the nft create role to a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.StopNftCreation + + +``` +$ mxpy token stop-nft-creation --help +usage: mxpy token stop-nft-creation [-h] ... + +Stop the creation of new NFTs. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.WipeSingleNft + + +``` +$ mxpy token wipe-single-nft --help +usage: mxpy token wipe-single-nft [-h] ... + +Wipe the NFT of a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the NFT as a decimal number + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.AddUris + + +``` +$ mxpy token add-uris --help +usage: mxpy token add-uris [-h] ... + +Add uris for a token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the NFT as a decimal number + --uris URIS [URIS ...] The new uris to be added to the token. + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --sender-username SENDER_USERNAME 🖄 the username of the sender + --hrp HRP The hrp used to convert the address to its bech32 representation + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` diff --git a/CLI.md.sh b/CLI.md.sh index 9c7dc806..2c9a3b65 100755 --- a/CLI.md.sh +++ b/CLI.md.sh @@ -212,6 +212,50 @@ generate() { command "Get.StorageEntry" "get storage-entry" command "Get.Token" "get token" command "Get.Transaction" "get transaction" + + group "Token" "token" + command "Token.IssueFungbile" "token issue-fungible" + command "Token.IssueNonFungbile" "token issue-non-fungible" + command "Token.RegisterMetaEsdt" "token register-meta-esdt" + command "Token.RegisterAndSetAllRoles" "token register-and-set-all-roles" + command "Token.SetBurnRoleGlobally" "token set-burn-role-globally" + command "Token.UnsetBurnRoleGlobally" "token unset-burn-role-globally" + command "Token.SetSpecialRoleFungible" "token set-special-role-fungible" + command "Token.UnsetSpecialRoleFungible" "token unset-special-role-fungible" + command "Token.SetSpecialRoleSemiFungible" "token set-special-role-semi-fungible" + command "Token.UnsetSpecialRoleSemiFungible" "token unset-special-role-semi-fungible" + command "Token.SetSpecialRoleMetaEsdt" "token set-special-role-meta-esdt" + command "Token.UnsetSpecialRoleMetaEsdt" "token unset-special-role-meta-esdt" + command "Token.SetSpecialRoleNft" "token set-special-role-nft" + command "Token.UnsetSpecialRoleNft" "token unset-special-role-nft" + command "Token.CreateNft" "token create-nft" + command "Token.Pause" "token pause" + command "Token.Unpause" "token unpause" + command "Token.Freeze" "token freeze" + command "Token.Unfreeze" "token unfreeze" + command "Token.Wipe" "token wipe" + command "Token.LocalMint" "token local-mint" + command "Token.LocalBurn" "token local-burn" + command "Token.UpdateAttributes" "token update-attributes" + command "Token.AddQuantity" "token add-quantity" + command "Token.BurnQuantity" "token burn-quantity" + command "Token.ModifyRolaties" "token modify-royalties" + command "Token.SetNewUris" "token set-new-uris" + command "Token.ModifyCreator" "token modify-creator" + command "Token.UpdateMetadata" "token update-metadata" + command "Token.NftMetadataRecreate" "token nft-metadata-recreate" + command "Token.ChangeToDynamic" "token change-to-dynamic" + command "Token.UpdateTokenId" "token update-token-id" + command "Token.RegisterDynamic" "token register-dynamic" + command "Token.RegisterDynamicAndSetAllRoles" "token register-dynamic-and-set-all-roles" + command "Token.TransferOwnership" "token transfer-ownership" + command "Token.FreezeSingleNft" "token freeze-single-nft" + command "Token.UnfreezeSingleNft" "token unfreeze-single-nft" + command "Token.ChangeSftToMetaEsdt" "token change-sft-to-meta-esdt" + command "Token.TransferNftCreateRole" "token transfer-nft-create-role" + command "Token.StopNftCreation" "token stop-nft-creation" + command "Token.WipeSingleNft" "token wipe-single-nft" + command "Token.AddUris" "token add-uris" } generate diff --git a/multiversx_sdk_cli/args_converter.py b/multiversx_sdk_cli/args_converter.py new file mode 100644 index 00000000..963856d9 --- /dev/null +++ b/multiversx_sdk_cli/args_converter.py @@ -0,0 +1,69 @@ +import logging +from typing import Any + +from multiversx_sdk import Address +from multiversx_sdk.abi import ( + AddressValue, + BigUIntValue, + BoolValue, + BytesValue, + StringValue, +) + +from multiversx_sdk_cli.config_env import get_address_hrp +from multiversx_sdk_cli.constants import ( + ADDRESS_PREFIX, + FALSE_STR_LOWER, + HEX_PREFIX, + MAINCHAIN_ADDRESS_HRP, + STR_PREFIX, + TRUE_STR_LOWER, +) +from multiversx_sdk_cli.errors import BadUserInput + +logger = logging.getLogger("args_converter") + + +def convert_args_to_typed_values(arguments: list[str]) -> list[Any]: + args: list[Any] = [] + + for arg in arguments: + if arg.startswith(HEX_PREFIX): + args.append(BytesValue(_hex_to_bytes(arg))) + elif arg.isnumeric(): + args.append(BigUIntValue(int(arg))) + elif arg.startswith(ADDRESS_PREFIX): + args.append(AddressValue.new_from_address(Address.new_from_bech32(arg[len(ADDRESS_PREFIX) :]))) + elif arg.startswith(MAINCHAIN_ADDRESS_HRP): + # this flow will be removed in the future + logger.warning( + "Address argument has no prefix. This flow will be removed in the future. Please provide each address using the `addr:` prefix. (e.g. --arguments addr:erd1...)" + ) + args.append(AddressValue.new_from_address(Address.new_from_bech32(arg))) + elif arg.startswith(get_address_hrp()): + args.append(AddressValue.new_from_address(Address.new_from_bech32(arg))) + elif arg.lower() == FALSE_STR_LOWER: + args.append(BoolValue(False)) + elif arg.lower() == TRUE_STR_LOWER: + args.append(BoolValue(True)) + elif arg.startswith(STR_PREFIX): + args.append(StringValue(arg[len(STR_PREFIX) :])) + else: + raise BadUserInput( + f"Unknown argument type for argument: `{arg}`. Use `mxpy contract --help` to check all supported arguments" + ) + + return args + + +def _hex_to_bytes(arg: str): + argument = arg[len(HEX_PREFIX) :] + argument = argument.upper() + argument = _ensure_even_length(argument) + return bytes.fromhex(argument) + + +def _ensure_even_length(string: str) -> str: + if len(string) % 2 == 1: + return "0" + string + return string diff --git a/multiversx_sdk_cli/base_transactions_controller.py b/multiversx_sdk_cli/base_transactions_controller.py deleted file mode 100644 index 8db775a6..00000000 --- a/multiversx_sdk_cli/base_transactions_controller.py +++ /dev/null @@ -1,172 +0,0 @@ -import logging -from typing import Any, Optional, Union - -from multiversx_sdk import Address, LedgerAccount, Transaction, TransactionComputer -from multiversx_sdk.abi import ( - AddressValue, - BigUIntValue, - BoolValue, - BytesValue, - StringValue, -) - -from multiversx_sdk_cli.config_env import get_address_hrp -from multiversx_sdk_cli.constants import ( - ADDRESS_PREFIX, - EXTRA_GAS_LIMIT_FOR_GUARDED_TRANSACTIONS, - EXTRA_GAS_LIMIT_FOR_RELAYED_TRANSACTIONS, - FALSE_STR_LOWER, - HEX_PREFIX, - MAINCHAIN_ADDRESS_HRP, - STR_PREFIX, - TRUE_STR_LOWER, -) -from multiversx_sdk_cli.cosign_transaction import cosign_transaction -from multiversx_sdk_cli.errors import BadUserInput, TransactionSigningError -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - -logger = logging.getLogger("base_controller") - - -class BaseTransactionsController: - def __init__(self) -> None: - pass - - def sign_transaction( - self, - transaction: Transaction, - sender: Optional[IAccount] = None, - guardian: Optional[IAccount] = None, - relayer: Optional[IAccount] = None, - guardian_service_url: Optional[str] = None, - guardian_2fa_code: Optional[str] = None, - ): - """Signs the transaction using the sender's account and, if required, additionally signs with the guardian's and relayer's accounts. Ensures the appropriate transaction options are set as needed.""" - self._set_options_for_guarded_transaction_if_needed(transaction) - self._set_options_for_hash_signing_if_needed(transaction, sender, guardian, relayer) - - if sender: - try: - transaction.signature = sender.sign_transaction(transaction) - except Exception as e: - raise TransactionSigningError(f"Could not sign transaction: {str(e)}") - - self._sign_guarded_transaction_if_guardian( - transaction, - guardian, - guardian_service_url, - guardian_2fa_code, - ) - self._sign_relayed_transaction_if_relayer(transaction, relayer) - - def add_extra_gas_limit_if_required(self, transaction: Transaction): - """In case of guarded or relayed transactions, extra gas limit is added.""" - if transaction.guardian: - transaction.gas_limit += EXTRA_GAS_LIMIT_FOR_GUARDED_TRANSACTIONS - - if transaction.relayer: - transaction.gas_limit += EXTRA_GAS_LIMIT_FOR_RELAYED_TRANSACTIONS - - def _set_options_for_guarded_transaction_if_needed(self, transaction: Transaction): - if transaction.guardian: - transaction_computer = TransactionComputer() - transaction_computer.apply_guardian(transaction, transaction.guardian) - - def _set_options_for_hash_signing_if_needed( - self, - transaction: Transaction, - sender: Union[IAccount, None], - guardian: Union[IAccount, None], - relayer: Union[IAccount, None], - ): - if ( - isinstance(sender, LedgerAccount) - or isinstance(guardian, LedgerAccount) - or isinstance(relayer, LedgerAccount) - ): - transaction_computer = TransactionComputer() - transaction_computer.apply_options_for_hash_signing(transaction) - - def _sign_guarded_transaction_if_guardian( - self, - transaction: Transaction, - guardian: Union[IAccount, None], - guardian_service_url: Union[str, None], - guardian_2fa_code: Union[str, None], - ) -> Transaction: - # If the guardian account is provided, we sign locally. Otherwise, we reach for the trusted cosign service. - if guardian: - try: - transaction.guardian_signature = guardian.sign_transaction(transaction) - except Exception as e: - raise TransactionSigningError(f"Could not sign transaction: {str(e)}") - elif transaction.guardian and guardian_service_url and guardian_2fa_code: - cosign_transaction(transaction, guardian_service_url, guardian_2fa_code) - - return transaction - - def _sign_relayed_transaction_if_relayer(self, transaction: Transaction, relayer: Union[IAccount, None]): - if relayer and transaction.relayer: - try: - transaction.relayer_signature = relayer.sign_transaction(transaction) - except Exception as e: - raise TransactionSigningError(f"Could not sign transaction: {str(e)}") - - def _convert_args_to_typed_values(self, arguments: list[str]) -> list[Any]: - args: list[Any] = [] - - for arg in arguments: - if arg.startswith(HEX_PREFIX): - args.append(BytesValue(self._hex_to_bytes(arg))) - elif arg.isnumeric(): - args.append(BigUIntValue(int(arg))) - elif arg.startswith(ADDRESS_PREFIX): - args.append(AddressValue.new_from_address(Address.new_from_bech32(arg[len(ADDRESS_PREFIX) :]))) - elif arg.startswith(MAINCHAIN_ADDRESS_HRP): - # this flow will be removed in the future - logger.warning( - "Address argument has no prefix. This flow will be removed in the future. Please provide each address using the `addr:` prefix. (e.g. --arguments addr:erd1...)" - ) - args.append(AddressValue.new_from_address(Address.new_from_bech32(arg))) - elif arg.startswith(get_address_hrp()): - args.append(AddressValue.new_from_address(Address.new_from_bech32(arg))) - elif arg.lower() == FALSE_STR_LOWER: - args.append(BoolValue(False)) - elif arg.lower() == TRUE_STR_LOWER: - args.append(BoolValue(True)) - elif arg.startswith(STR_PREFIX): - args.append(StringValue(arg[len(STR_PREFIX) :])) - else: - raise BadUserInput( - f"Unknown argument type for argument: `{arg}`. Use `mxpy contract --help` to check all supported arguments" - ) - - return args - - def _hex_to_bytes(self, arg: str): - argument = arg[len(HEX_PREFIX) :] - argument = argument.upper() - argument = self.ensure_even_length(argument) - return bytes.fromhex(argument) - - def ensure_even_length(self, string: str) -> str: - if len(string) % 2 == 1: - return "0" + string - return string - - def _set_transaction_fields( - self, - transaction: Transaction, - nonce: int, - version: int, - options: int, - gas_price: int, - guardian_and_relayer_data: GuardianRelayerData, - ): - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.gas_price = gas_price - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address diff --git a/multiversx_sdk_cli/cli.py b/multiversx_sdk_cli/cli.py index 8ad91fd5..f6be73cc 100644 --- a/multiversx_sdk_cli/cli.py +++ b/multiversx_sdk_cli/cli.py @@ -23,6 +23,7 @@ import multiversx_sdk_cli.cli_ledger import multiversx_sdk_cli.cli_localnet import multiversx_sdk_cli.cli_multisig +import multiversx_sdk_cli.cli_tokens import multiversx_sdk_cli.cli_transactions import multiversx_sdk_cli.cli_validator_wallet import multiversx_sdk_cli.cli_validators @@ -142,6 +143,7 @@ def setup_parser(args: list[str]): commands.append(multiversx_sdk_cli.cli_governance.setup_parser(args, subparsers)) commands.append(multiversx_sdk_cli.cli_config_env.setup_parser(subparsers)) commands.append(multiversx_sdk_cli.cli_get.setup_parser(subparsers)) + commands.append(multiversx_sdk_cli.cli_tokens.setup_parser(args, subparsers)) parser.epilog = """ ---------------------- diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index bcbc0a96..539c9238 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -11,12 +11,13 @@ AddressComputer, Message, ProxyNetworkProvider, + SmartContractController, Transaction, - TransactionsFactoryConfig, ) from multiversx_sdk.abi import Abi from multiversx_sdk_cli import cli_shared, utils +from multiversx_sdk_cli.args_converter import convert_args_to_typed_values from multiversx_sdk_cli.args_validation import ( validate_broadcast_args, validate_chain_id_args, @@ -28,9 +29,8 @@ from multiversx_sdk_cli.config_env import MxpyEnv from multiversx_sdk_cli.constants import NUMBER_OF_SHARDS from multiversx_sdk_cli.contract_verification import trigger_contract_verification -from multiversx_sdk_cli.contracts import SmartContract from multiversx_sdk_cli.docker import is_docker_installed, run_docker -from multiversx_sdk_cli.errors import DockerMissingError +from multiversx_sdk_cli.errors import BadUsage, DockerMissingError, QueryContractError from multiversx_sdk_cli.ux import show_warning logger = logging.getLogger("cli.contracts") @@ -295,6 +295,7 @@ def _add_arguments_arg(sub: Any): sub.add_argument( "--arguments", nargs="+", + default=[], help="arguments for the contract transaction, as [number, bech32-address, ascii string, " "boolean] or hex-encoded. E.g. --arguments 42 0x64 1000 0xabba str:TOK-a1c2ef true addr:erd1[..]", ) @@ -315,6 +316,27 @@ def build(args: Any): show_warning(message) +def _initialize_controller(args: Any) -> SmartContractController: + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + config = get_config_for_network_providers() + proxy_url = args.proxy if args.proxy else "" + proxy = ProxyNetworkProvider(url=proxy_url, config=config) + abi = Abi.load(Path(args.abi)) if args.abi else None + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + + return SmartContractController( + chain_id=chain_id, + network_provider=proxy, + abi=abi, + gas_limit_estimator=gas_estimator, + ) + + +def _ensure_args_for_gas_estimation(args: Any): + if not args.proxy and not args.gas_limit: + raise BadUsage("To estimate the gas limit, you need to provide `--proxy` or set a value using `--gas-limit`") + + def deploy(args: Any): logger.debug("deploy") @@ -322,37 +344,33 @@ def deploy(args: Any): validate_broadcast_args(args) validate_chain_id_args(args) + _ensure_args_for_gas_estimation(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - config = TransactionsFactoryConfig(chain_id) - - abi = Abi.load(Path(args.abi)) if args.abi else None - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - contract = SmartContract(config, abi, gas_estimator) - arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) - tx = contract.prepare_deploy_transaction( - owner=sender, + controller = _initialize_controller(args) + tx = controller.create_transaction_for_deploy( + sender=sender, + nonce=sender.nonce, bytecode=Path(args.bytecode), arguments=arguments, - should_prepare_args=should_prepare_args, - upgradeable=args.metadata_upgradeable, - readable=args.metadata_readable, - payable=args.metadata_payable, - payable_by_sc=args.metadata_payable_by_sc, + native_transfer_amount=int(args.value), + is_upgradeable=args.metadata_upgradeable, + is_readable=args.metadata_readable, + is_payable=args.metadata_payable, + is_payable_by_sc=args.metadata_payable_by_sc, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) address_computer = AddressComputer(NUMBER_OF_SHARDS) @@ -361,8 +379,18 @@ def deploy(args: Any): logger.info("Contract address: %s", contract_address.to_bech32()) cli_config = MxpyEnv.from_active_env() - utils.log_explorer_contract_address(args.chain, contract_address.to_bech32(), cli_config.explorer_url) + utils.log_explorer_contract_address( + chain=cli_shared.get_chain_id(args.proxy, args.chain), + address=contract_address.to_bech32(), + explorer_url=cli_config.explorer_url, + ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract_address, args) @@ -373,42 +401,45 @@ def call(args: Any): validate_broadcast_args(args) validate_chain_id_args(args) + _ensure_args_for_gas_estimation(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - config = TransactionsFactoryConfig(chain_id) - - abi = Abi.load(Path(args.abi)) if args.abi else None - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - contract = SmartContract(config, abi, gas_estimator) - arguments, should_prepare_args = _get_contract_arguments(args) - contract_address = Address.new_from_bech32(args.contract) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) - token_transfers = None + token_transfers = [] if args.token_transfers: token_transfers = cli_shared.prepare_token_transfers(args.token_transfers) - tx = contract.prepare_execute_transaction( - caller=sender, + contract_address = Address.new_from_bech32(args.contract) + controller = _initialize_controller(args) + + tx = controller.create_transaction_for_execute( + sender=sender, + nonce=sender.nonce, contract=contract_address, function=args.function, arguments=arguments, - should_prepare_args=should_prepare_args, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), + native_transfer_amount=int(args.value), token_transfers=token_transfers, - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract_address, args) @@ -419,41 +450,44 @@ def upgrade(args: Any): validate_broadcast_args(args) validate_chain_id_args(args) + _ensure_args_for_gas_estimation(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - config = TransactionsFactoryConfig(chain_id) - - abi = Abi.load(Path(args.abi)) if args.abi else None - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - contract = SmartContract(config, abi, gas_estimator) - arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) + contract_address = Address.new_from_bech32(args.contract) + controller = _initialize_controller(args) - tx = contract.prepare_upgrade_transaction( - owner=sender, + tx = controller.create_transaction_for_upgrade( + sender=sender, + nonce=sender.nonce, contract=contract_address, bytecode=Path(args.bytecode), arguments=arguments, - should_prepare_args=should_prepare_args, - upgradeable=args.metadata_upgradeable, - readable=args.metadata_readable, - payable=args.metadata_payable, - payable_by_sc=args.metadata_payable_by_sc, + native_transfer_amount=int(args.value), + is_upgradeable=args.metadata_upgradeable, + is_readable=args.metadata_readable, + is_payable=args.metadata_payable, + is_payable_by_sc=args.metadata_payable_by_sc, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract_address, args) @@ -462,26 +496,32 @@ def query(args: Any): validate_proxy_argument(args) - # we don't need chainID to query a contract; we use the provided proxy - factory_config = TransactionsFactoryConfig("") abi = Abi.load(Path(args.abi)) if args.abi else None - contract = SmartContract(factory_config, abi) + contract_address = Address.new_from_bech32(args.contract) + function = args.function arguments, should_prepare_args = _get_contract_arguments(args) - contract_address = Address.new_from_bech32(args.contract) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) network_provider_config = get_config_for_network_providers() proxy = ProxyNetworkProvider(url=args.proxy, config=network_provider_config) - function = args.function - result = contract.query_contract( - contract_address=contract_address, - proxy=proxy, - function=function, - arguments=arguments, - should_prepare_args=should_prepare_args, + controller = SmartContractController( + chain_id="", + network_provider=proxy, + abi=abi, ) + try: + result = controller.query( + contract=contract_address, + function=function, + arguments=arguments, + ) + except Exception as e: + raise QueryContractError("Couldn't query contract: ", e) + utils.dump_out_json(result) diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index d76a52b9..845e1bab 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -3,10 +3,11 @@ from multiversx_sdk import ( Address, + DelegationController, DelegationTransactionsOutcomeParser, ProxyNetworkProvider, - TransactionsFactoryConfig, ValidatorPublicKey, + ValidatorsController, ValidatorsSigners, ) @@ -19,7 +20,6 @@ validate_receiver_args, ) from multiversx_sdk_cli.config import get_config_for_network_providers -from multiversx_sdk_cli.delegation import DelegationOperations def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -394,10 +394,16 @@ def validate_arguments(args: Any): def _get_delegation_controller(args: Any): chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - config = TransactionsFactoryConfig(chain_id) + config = get_config_for_network_providers() + proxy_url = args.proxy if args.proxy else "" + proxy = ProxyNetworkProvider(url=proxy_url, config=config) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - delegation = DelegationOperations(config=config, gas_limit_estimator=gas_estimator) - return delegation + + return DelegationController( + chain_id=chain_id, + network_provider=proxy, + gas_limit_estimator=gas_estimator, + ) def do_create_delegation_contract(args: Any): @@ -410,17 +416,22 @@ def do_create_delegation_contract(args: Any): ) delegation = _get_delegation_controller(args) - - tx = delegation.prepare_transaction_for_new_delegation_contract( - owner=sender, - native_amount=int(args.value), + tx = delegation.create_transaction_for_new_delegation_contract( + sender=sender, + nonce=sender.nonce, + amount=int(args.value), total_delegation_cap=int(args.total_delegation_cap), service_fee=int(args.service_fee), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -456,17 +467,22 @@ def add_new_nodes(args: Any): public_keys, signed_messages = _get_public_keys_and_signed_messages(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_adding_nodes( - owner=sender, + tx = delegation.create_transaction_for_adding_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, signed_messages=signed_messages, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -504,16 +520,21 @@ def remove_nodes(args: Any): public_keys = _load_validators_public_keys(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_removing_nodes( - owner=sender, + tx = delegation.create_transaction_for_removing_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -552,16 +573,21 @@ def stake_nodes(args: Any): public_keys = _load_validators_public_keys(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_staking_nodes( - owner=sender, + tx = delegation.create_transaction_for_staking_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -589,16 +615,21 @@ def unbond_nodes(args: Any): public_keys = _load_validators_public_keys(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_unbonding_nodes( - owner=sender, + tx = delegation.create_transaction_for_unbonding_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -618,16 +649,21 @@ def unstake_nodes(args: Any): public_keys = _load_validators_public_keys(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_unstaking_nodes( - owner=sender, + tx = delegation.create_transaction_for_unstaking_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -637,6 +673,8 @@ def unstake_nodes(args: Any): def unjail_nodes(args: Any): _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) + if not args.value or int(args.value) <= 0: + raise errors.BadUsage("Value must be provided for unjailing nodes") sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -647,16 +685,22 @@ def unjail_nodes(args: Any): public_keys = _load_validators_public_keys(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_unjailing_nodes( - owner=sender, + tx = delegation.create_transaction_for_unjailing_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, + amount=int(args.value), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -665,6 +709,8 @@ def unjail_nodes(args: Any): def delegate(args: Any): validate_arguments(args) + if not args.value or int(args.value) <= 0: + raise errors.BadUsage("Value must be provided for delegating") sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -673,15 +719,21 @@ def delegate(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_delegating( - owner=sender, + tx = delegation.create_transaction_for_delegating( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), + amount=int(args.value), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -698,17 +750,23 @@ def claim_rewards(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_claiming_rewards( - owner=sender, + tx = delegation.create_transaction_for_claiming_rewards( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.send_or_simulate(tx, args) @@ -722,22 +780,30 @@ def redelegate_rewards(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_redelegating_rewards( - owner=sender, + tx = delegation.create_transaction_for_redelegating_rewards( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.send_or_simulate(tx, args) def undelegate(args: Any): validate_arguments(args) + if not args.value or int(args.value) <= 0: + raise errors.BadUsage("Value must be provided for undelegating") sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -746,15 +812,21 @@ def undelegate(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_undelegating( - owner=sender, + tx = delegation.create_transaction_for_undelegating( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), + amount=int(args.value), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -771,15 +843,20 @@ def withdraw(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_withdrawing( - owner=sender, + tx = delegation.create_transaction_for_withdrawing( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -796,16 +873,21 @@ def change_service_fee(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_changing_service_fee( - owner=sender, + tx = delegation.create_transaction_for_changing_service_fee( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), service_fee=int(args.service_fee), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -822,16 +904,21 @@ def modify_delegation_cap(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_modifying_delegation_cap( - owner=sender, + tx = delegation.create_transaction_for_modifying_delegation_cap( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), delegation_cap=int(args.delegation_cap), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -848,17 +935,37 @@ def automatic_activation(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_automatic_activation( - owner=sender, - delegation_contract=Address.new_from_bech32(args.delegation_contract), - set=args.set, - unset=args.unset, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + + if args.set and args.unset: + raise errors.BadUsage("Cannot set and unset at the same time") + + if args.set: + tx = delegation.create_transaction_for_setting_automatic_activation( + sender=sender, + nonce=sender.nonce, + delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + elif args.unset: + tx = delegation.create_transaction_for_unsetting_automatic_activation( + sender=sender, + nonce=sender.nonce, + delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + else: + raise errors.BadUsage("Both set and unset automatic activation are False") + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -875,17 +982,36 @@ def redelegate_cap(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_redelegate_cap( - owner=sender, - delegation_contract=Address.new_from_bech32(args.delegation_contract), - set=args.set, - unset=args.unset, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + if args.set and args.unset: + raise errors.BadUsage("Cannot set and unset at the same time") + + if args.set: + tx = delegation.create_transaction_for_setting_cap_check_on_redelegate_rewards( + sender=sender, + nonce=sender.nonce, + delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + elif args.unset: + tx = delegation.create_transaction_for_unsetting_cap_check_on_redelegate_rewards( + sender=sender, + nonce=sender.nonce, + delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + else: + raise errors.BadUsage("Either set or unset should be True") + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -902,18 +1028,23 @@ def set_metadata(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_setting_metadata( - owner=sender, + tx = delegation.create_transaction_for_setting_metadata( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), name=args.name, website=args.website, identifier=args.identifier, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) @@ -929,17 +1060,25 @@ def make_new_contract_from_validator_data(args: Any): args=args, ) - delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_creating_delegation_contract_from_validator( - owner=sender, + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + validators_controller = ValidatorsController(chain_id=chain_id, gas_limit_estimator=gas_estimator) + + tx = validators_controller.create_transaction_for_new_delegation_contract_from_validator_data( + sender=sender, + nonce=sender.nonce, max_cap=args.max_cap, - service_fee=args.fee, + fee=args.fee, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, guardian_and_relayer_data=guardian_and_relayer_data, ) diff --git a/multiversx_sdk_cli/cli_get.py b/multiversx_sdk_cli/cli_get.py index 45bd6d3a..9daffffe 100644 --- a/multiversx_sdk_cli/cli_get.py +++ b/multiversx_sdk_cli/cli_get.py @@ -107,7 +107,7 @@ def get_account(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared._get_address_hrp(args) + hrp = cli_shared.get_address_hrp_with_fallback(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) @@ -128,7 +128,7 @@ def get_storage(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared._get_address_hrp(args) + hrp = cli_shared.get_address_hrp_with_fallback(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) @@ -146,7 +146,7 @@ def get_key(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared._get_address_hrp(args) + hrp = cli_shared.get_address_hrp_with_fallback(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) @@ -167,7 +167,7 @@ def get_token(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared._get_address_hrp(args) + hrp = cli_shared.get_address_hrp_with_fallback(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) diff --git a/multiversx_sdk_cli/cli_governance.py b/multiversx_sdk_cli/cli_governance.py index f4b240b0..4d31c650 100644 --- a/multiversx_sdk_cli/cli_governance.py +++ b/multiversx_sdk_cli/cli_governance.py @@ -7,7 +7,7 @@ GovernanceController, ProposalInfo, ProxyNetworkProvider, - TransactionsFactoryConfig, + VoteType, ) from multiversx_sdk_cli import cli_shared, utils @@ -18,7 +18,6 @@ ) from multiversx_sdk_cli.cli_output import CLIOutputBuilder from multiversx_sdk_cli.config import get_config_for_network_providers -from multiversx_sdk_cli.governance import GovernanceWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -196,6 +195,22 @@ def _ensure_args(args: Any): validate_chain_id_args(args) +def _initialize_controller(args: Any) -> GovernanceController: + chain = getattr(args, "chain", None) + chain_id = cli_shared.get_chain_id(args.proxy, chain) + config = get_config_for_network_providers() + proxy_url = args.proxy if args.proxy else "" + proxy = ProxyNetworkProvider(url=proxy_url, config=config) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + + return GovernanceController( + chain_id=chain_id, + network_provider=proxy, + address_hrp=cli_shared.get_address_hrp_with_fallback(args), + gas_limit_estimator=gas_estimator, + ) + + def create_proposal(args: Any): _ensure_args(args) @@ -204,10 +219,8 @@ def create_proposal(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_new_proposal( sender=sender, nonce=sender.nonce, @@ -215,13 +228,18 @@ def create_proposal(args: Any): start_vote_epoch=args.start_vote_epoch, end_vote_epoch=args.end_vote_epoch, native_token_amount=args.value, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -233,22 +251,27 @@ def vote(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + + [vote_value] = [v for v in VoteType if v.value == args.vote] + controller = _initialize_controller(args) transaction = controller.create_transaction_for_voting( sender=sender, nonce=sender.nonce, proposal_nonce=args.proposal_nonce, - vote=args.vote, + vote=vote_value, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -260,21 +283,24 @@ def close_proposal(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_closing_proposal( sender=sender, nonce=sender.nonce, proposal_nonce=args.proposal_nonce, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -286,22 +312,26 @@ def clear_ended_proposals(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) proposers = [Address.new_from_bech32(proposer) for proposer in args.proposers] + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_clearing_ended_proposals( sender=sender, nonce=sender.nonce, proposers=proposers, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -313,20 +343,23 @@ def claim_accumulated_fees(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_claiming_accumulated_fees( sender=sender, nonce=sender.nonce, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -338,10 +371,8 @@ def change_config(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_changing_config( sender=sender, nonce=sender.nonce, @@ -350,24 +381,25 @@ def change_config(args: Any): min_quorum=args.min_quorum, min_veto_threshold=args.min_veto_threshold, min_pass_threshold=args.min_pass_threshold, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) def get_voting_power(args: Any): validate_proxy_argument(args) - config = get_config_for_network_providers() - proxy = ProxyNetworkProvider(url=args.proxy, config=config) - chain_id = proxy.get_network_config().chain_id - controller = GovernanceController(chain_id, proxy) - + controller = _initialize_controller(args) user = Address.new_from_bech32(args.user) voting_power = controller.get_voting_power(user) @@ -377,10 +409,7 @@ def get_voting_power(args: Any): def get_config(args: Any): validate_proxy_argument(args) - config = get_config_for_network_providers() - proxy = ProxyNetworkProvider(url=args.proxy, config=config) - chain_id = proxy.get_network_config().chain_id - controller = GovernanceController(chain_id, proxy) + controller = _initialize_controller(args) contract_config = controller.get_config() utils.dump_out_json(_config_to_dict(contract_config)) @@ -389,10 +418,7 @@ def get_config(args: Any): def get_proposal(args: Any): validate_proxy_argument(args) - config = get_config_for_network_providers() - proxy = ProxyNetworkProvider(url=args.proxy, config=config) - chain_id = proxy.get_network_config().chain_id - controller = GovernanceController(chain_id, proxy) + controller = _initialize_controller(args) info = controller.get_proposal(args.proposal_nonce) utils.dump_out_json(_proposal_to_dict(info)) @@ -401,10 +427,7 @@ def get_proposal(args: Any): def get_delegated_vote_info(args: Any): validate_proxy_argument(args) - config = get_config_for_network_providers() - proxy = ProxyNetworkProvider(url=args.proxy, config=config) - chain_id = proxy.get_network_config().chain_id - controller = GovernanceController(chain_id, proxy) + controller = _initialize_controller(args) contract = Address.new_from_bech32(args.contract) user = Address.new_from_bech32(args.user) diff --git a/multiversx_sdk_cli/cli_multisig.py b/multiversx_sdk_cli/cli_multisig.py index fe042cb9..a3a55db4 100644 --- a/multiversx_sdk_cli/cli_multisig.py +++ b/multiversx_sdk_cli/cli_multisig.py @@ -23,11 +23,11 @@ SendTransferExecuteEgld, SendTransferExecuteEsdt, Transaction, - TransactionsFactoryConfig, ) from multiversx_sdk.abi import Abi from multiversx_sdk_cli import cli_shared, utils +from multiversx_sdk_cli.args_converter import convert_args_to_typed_values from multiversx_sdk_cli.args_validation import ( validate_broadcast_args, validate_chain_id_args, @@ -37,7 +37,6 @@ from multiversx_sdk_cli.cli_output import CLIOutputBuilder from multiversx_sdk_cli.config import get_config_for_network_providers from multiversx_sdk_cli.constants import NUMBER_OF_SHARDS -from multiversx_sdk_cli.multisig import MultisigWrapper logger = logging.getLogger("cli.multisig") @@ -629,6 +628,7 @@ def _add_arguments_arg(sub: Any): nargs="+", help="arguments for the contract transaction, as [number, bech32-address, ascii string, " "boolean] or hex-encoded. E.g. --arguments 42 0x64 1000 0xabba str:TOK-a1c2ef true addr:erd1[..]", + default=[], ) sub.add_argument( "--arguments-file", @@ -659,13 +659,21 @@ def _ensure_args(args: Any): validate_chain_id_args(args) -def _initialize_multisig_wrapper(args: Any) -> MultisigWrapper: +def _initialize_multisig_controller(args: Any) -> MultisigController: abi = Abi.load(Path(args.abi)) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + chain = getattr(args, "chain", None) + chain_id = cli_shared.get_chain_id(args.proxy, chain) + + config = get_config_for_network_providers() + proxy_url = args.proxy if args.proxy else "" gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - return MultisigWrapper( - config=TransactionsFactoryConfig(chain_id), + proxy = ProxyNetworkProvider(url=proxy_url, config=config) + + return MultisigController( + chain_id=chain_id, + network_provider=proxy, abi=abi, + address_hrp=cli_shared.get_address_hrp_with_fallback(args), gas_limit_estimator=gas_estimator, ) @@ -683,30 +691,35 @@ def deploy(args: Any): quorum = args.quorum board_members = [Address.new_from_bech32(addr) for addr in args.board_members] - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_deploy_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_deploy( + sender=sender, nonce=sender.nonce, bytecode=Path(args.bytecode), quorum=quorum, - board_members=board_members, - upgradeable=args.metadata_upgradeable, - readable=args.metadata_readable, - payable=args.metadata_payable, - payable_by_sc=args.metadata_payable_by_sc, + board=board_members, + is_upgradeable=args.metadata_upgradeable, + is_readable=args.metadata_readable, + is_payable=args.metadata_payable, + is_payable_by_sc=args.metadata_payable_by_sc, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) address_computer = AddressComputer(NUMBER_OF_SHARDS) contract_address = address_computer.compute_contract_address(deployer=sender.address, deployment_nonce=tx.nonce) logger.info("Contract address: %s", contract_address.to_bech32()) - utils.log_explorer_contract_address(args.chain, contract_address.to_bech32()) + utils.log_explorer_contract_address(cli_shared.get_chain_id(args.proxy, args.chain), contract_address.to_bech32()) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract_address, args) @@ -726,20 +739,25 @@ def deposit(args: Any): if token_transfers: token_transfers = cli_shared.prepare_token_transfers(token_transfers) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_deposit_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_deposit( + sender=sender, nonce=sender.nonce, contract=contract, - native_amount=native_amount, + native_token_amount=native_amount, token_transfers=token_transfers, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -755,19 +773,24 @@ def discard_action(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_discard_action_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_discard_action( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -783,19 +806,24 @@ def discard_batch(args: Any): contract = Address.new_from_bech32(args.contract) actions = args.action_ids - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_discard_batch_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_discard_batch( + sender=sender, nonce=sender.nonce, contract=contract, - action_ids=actions, + actions_ids=actions, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -811,19 +839,24 @@ def add_board_member(args: Any): contract = Address.new_from_bech32(args.contract) board_member = Address.new_from_bech32(args.board_member) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_add_board_member_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_add_board_member( + sender=sender, nonce=sender.nonce, contract=contract, board_member=board_member, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -839,19 +872,24 @@ def add_proposer(args: Any): contract = Address.new_from_bech32(args.contract) proposer = Address.new_from_bech32(args.proposer) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_add_proposer_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_add_proposer( + sender=sender, nonce=sender.nonce, contract=contract, proposer=proposer, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -867,19 +905,24 @@ def remove_user(args: Any): contract = Address.new_from_bech32(args.contract) user = Address.new_from_bech32(args.user) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_remove_user_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_remove_user( + sender=sender, nonce=sender.nonce, contract=contract, user=user, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -895,19 +938,24 @@ def change_quorum(args: Any): contract = Address.new_from_bech32(args.contract) quorum = int(args.quorum) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_change_quorum_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_change_quorum( + sender=sender, nonce=sender.nonce, contract=contract, - quorum=quorum, + new_quorum=quorum, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -925,27 +973,34 @@ def transfer_and_execute(args: Any): opt_gas_limit = int(args.opt_gas_limit) if args.opt_gas_limit else None function = args.function if args.function else None contract_abi = Abi.load(Path(args.contract_abi)) if args.contract_abi else None + arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_transfer_execute_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_transfer_execute( + sender=sender, nonce=sender.nonce, contract=contract, receiver=receiver, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - should_prepare_args_for_factory=should_prepare_args, - guardian_and_relayer_data=guardian_and_relayer_data, opt_gas_limit=opt_gas_limit, function=function, abi=contract_abi, arguments=arguments, native_token_amount=int(args.value), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -969,28 +1024,35 @@ def transfer_and_execute_esdt(args: Any): opt_gas_limit = int(args.opt_gas_limit) if args.opt_gas_limit else None function = args.function if args.function else None contract_abi = Abi.load(Path(args.contract_abi)) if args.contract_abi else None - arguments, should_prepare_args = _get_contract_arguments(args) token_transfers = cli_shared.prepare_token_transfers(args.token_transfers) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_transfer_execute_esdt_transaction( - owner=sender, + arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) + + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_transfer_execute_esdt( + sender=sender, nonce=sender.nonce, contract=contract, receiver=receiver, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - should_prepare_args_for_factory=should_prepare_args, - guardian_and_relayer_data=guardian_and_relayer_data, token_transfers=token_transfers, opt_gas_limit=opt_gas_limit, function=function, abi=contract_abi, arguments=arguments, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1008,32 +1070,39 @@ def async_call(args: Any): opt_gas_limit = int(args.opt_gas_limit) if args.opt_gas_limit else None function = args.function if args.function else None contract_abi = Abi.load(Path(args.contract_abi)) if args.contract_abi else None + arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) token_transfers = args.token_transfers or None if token_transfers: token_transfers = cli_shared.prepare_token_transfers(args.token_transfers) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_async_call_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_async_call( + sender=sender, nonce=sender.nonce, contract=contract, receiver=receiver, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - should_prepare_args_for_factory=should_prepare_args, - guardian_and_relayer_data=guardian_and_relayer_data, native_token_amount=int(args.value), token_transfers=token_transfers, opt_gas_limit=opt_gas_limit, function=function, abi=contract_abi, arguments=arguments, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1048,31 +1117,37 @@ def deploy_from_source(args: Any): contract = Address.new_from_bech32(args.contract) contract_to_copy = Address.new_from_bech32(args.contract_to_copy) - contract_abi = Abi.load(Path(args.contract_abi)) if args.contract_abi else None + arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_contract_deploy_from_source_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_contract_deploy_from_source( + sender=sender, nonce=sender.nonce, contract=contract, contract_to_copy=contract_to_copy, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - upgradeable=args.metadata_upgradeable, - readable=args.metadata_readable, - payable=args.metadata_payable, - payable_by_sc=args.metadata_payable_by_sc, - should_prepare_args_for_factory=should_prepare_args, - guardian_and_relayer_data=guardian_and_relayer_data, + is_upgradeable=args.metadata_upgradeable, + is_readable=args.metadata_readable, + is_payable=args.metadata_payable, + is_payable_by_sc=args.metadata_payable_by_sc, native_token_amount=int(args.value), abi=contract_abi, arguments=arguments, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1088,32 +1163,38 @@ def upgrade_from_source(args: Any): contract = Address.new_from_bech32(args.contract) contract_to_upgrade = Address.new_from_bech32(args.contract_to_upgrade) contract_to_copy = Address.new_from_bech32(args.contract_to_copy) - contract_abi = Abi.load(Path(args.contract_abi)) if args.contract_abi else None + arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_contract_upgrade_from_source_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_contract_upgrade_from_source( + sender=sender, nonce=sender.nonce, contract=contract, contract_to_upgrade=contract_to_upgrade, contract_to_copy=contract_to_copy, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - upgradeable=args.metadata_upgradeable, - readable=args.metadata_readable, - payable=args.metadata_payable, - payable_by_sc=args.metadata_payable_by_sc, - should_prepare_args_for_factory=should_prepare_args, - guardian_and_relayer_data=guardian_and_relayer_data, + is_upgradeable=args.metadata_upgradeable, + is_readable=args.metadata_readable, + is_payable=args.metadata_payable, + is_payable_by_sc=args.metadata_payable_by_sc, native_token_amount=int(args.value), abi=contract_abi, arguments=arguments, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1129,19 +1210,24 @@ def sign_action(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_sign_action_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_sign_action( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1157,19 +1243,24 @@ def sign_batch(args: Any): contract = Address.new_from_bech32(args.contract) batch_id = int(args.batch) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_sign_batch_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_sign_batch( + sender=sender, nonce=sender.nonce, contract=contract, batch_id=batch_id, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1185,19 +1276,24 @@ def sign_and_perform(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_sign_and_perform_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_sign_and_perform( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1213,19 +1309,24 @@ def sign_batch_and_perform(args: Any): contract = Address.new_from_bech32(args.contract) batch_id = int(args.batch) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_sign_batch_and_perform_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_sign_batch_and_perform( + sender=sender, nonce=sender.nonce, contract=contract, batch_id=batch_id, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1241,19 +1342,24 @@ def unsign_action(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_unsign_action_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_unsign_action( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1269,19 +1375,24 @@ def unsign_batch(args: Any): contract = Address.new_from_bech32(args.contract) batch_id = int(args.batch) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_unsign_batch_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_unsign_batch( + sender=sender, nonce=sender.nonce, contract=contract, batch_id=batch_id, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1297,20 +1408,25 @@ def unsign_for_outdated_board_members(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_unsign_for_outdated_board_members_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_unsign_for_outdated_board_members( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, outdated_board_members=args.outdated_members, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1326,19 +1442,24 @@ def perform_action(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_perform_action_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_perform_action( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1354,30 +1475,27 @@ def perform_batch(args: Any): contract = Address.new_from_bech32(args.contract) batch_id = int(args.batch) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_perform_batch_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_perform_batch( + sender=sender, nonce=sender.nonce, contract=contract, batch_id=batch_id, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) -def _initialize_multisig_controller(args: Any) -> MultisigController: - abi = Abi.load(Path(args.abi)) - config = get_config_for_network_providers() - proxy = ProxyNetworkProvider(url=args.proxy, config=config) - chain_id = proxy.get_network_config().chain_id - return MultisigController(chain_id, proxy, abi) - - def get_quorum(args: Any): validate_proxy_argument(args) diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 29ed140e..9d5ad4c6 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -20,6 +20,7 @@ TokenComputer, TokenTransfer, Transaction, + TransactionComputer, ) from multiversx_sdk_cli import config, utils @@ -39,6 +40,7 @@ DEFAULT_GAS_PRICE, DEFAULT_TX_VERSION, TCS_SERVICE_ID, + TRANSACTION_OPTIONS_TX_HASH_SIGN, ) from multiversx_sdk_cli.errors import ( AddressConfigFileError, @@ -52,6 +54,7 @@ ) from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData from multiversx_sdk_cli.interfaces import IAccount +from multiversx_sdk_cli.signing_wrapper import SigningWrapper from multiversx_sdk_cli.simulation import Simulator from multiversx_sdk_cli.transactions import send_and_wait_for_result from multiversx_sdk_cli.utils import log_explorer_transaction @@ -350,17 +353,31 @@ def parse_omit_fields_arg(args: Any) -> list[str]: return cast(list[str], parsed) +def _has_options_set_for_hash_signing(args: Any) -> bool: + if hasattr(args, "options") and args.options: + if args.options & TRANSACTION_OPTIONS_TX_HASH_SIGN == TRANSACTION_OPTIONS_TX_HASH_SIGN: + return True + + return False + + def prepare_account(args: Any): - hrp = _get_address_hrp(args) + hrp = get_address_hrp_with_fallback(args) if args.pem: - return Account.new_from_pem(file_path=Path(args.pem), index=args.sender_wallet_index, hrp=hrp) + acc = Account.new_from_pem(file_path=Path(args.pem), index=args.sender_wallet_index, hrp=hrp) + if _has_options_set_for_hash_signing(args): + acc.use_hash_signing = True + return acc elif args.keyfile: password = load_password(args) index = args.sender_wallet_index if args.sender_wallet_index != 0 else None try: - return Account.new_from_keystore(Path(args.keyfile), password=password, address_index=index, hrp=hrp) + acc = Account.new_from_keystore(Path(args.keyfile), password=password, address_index=index, hrp=hrp) + if _has_options_set_for_hash_signing(args): + acc.use_hash_signing = True + return acc except Exception as e: raise WalletError(str(e)) elif args.ledger: @@ -369,9 +386,15 @@ def prepare_account(args: Any): except Exception as e: raise LedgerError(str(e)) elif args.sender: - return load_wallet_by_alias(alias=args.sender, hrp=hrp) + acc = load_wallet_by_alias(alias=args.sender, hrp=hrp) + if _has_options_set_for_hash_signing(args): + acc.use_hash_signing = True + return acc else: - return load_default_wallet(hrp=hrp) + acc = load_default_wallet(hrp=hrp) + if _has_options_set_for_hash_signing(args): + acc.use_hash_signing = True + return acc def load_wallet_by_alias(alias: str, hrp: str) -> Account: @@ -426,7 +449,7 @@ def _load_wallet_from_wallet_config(wallet: dict[str, str], hrp: str) -> Account raise WalletError(f"Unsupported wallet file type: [{path.suffix}]. Supported types are: `.pem` and `.json`.") -def _get_address_hrp(args: Any) -> str: +def get_address_hrp_with_fallback(args: Any) -> str: """Use hrp provided by the user. If not provided, fetch from network. If proxy not provided, get hrp from config.""" hrp: str = "" @@ -462,7 +485,7 @@ def _get_hrp_from_api(args: Any) -> str: def load_guardian_account(args: Any) -> Union[IAccount, None]: - hrp = _get_address_hrp(args) + hrp = get_address_hrp_with_fallback(args) if args.guardian_pem: return Account.new_from_pem(file_path=Path(args.guardian_pem), index=args.guardian_wallet_index, hrp=hrp) @@ -599,7 +622,7 @@ def _is_matching_address(account_address: Union[Address, None], args_address: Un def load_relayer_account(args: Any) -> Union[IAccount, None]: - hrp = _get_address_hrp(args) + hrp = get_address_hrp_with_fallback(args) if args.relayer_pem: return Account.new_from_pem(file_path=Path(args.relayer_pem), index=args.relayer_wallet_index, hrp=hrp) @@ -800,6 +823,10 @@ def set_proxy_from_config_if_not_provided(args: Any) -> None: def initialize_gas_limit_estimator(args: Any) -> Union[GasLimitEstimator, None]: + # if gas limit is provided, we don't need GasLimitEstimator + if hasattr(args, "gas_limit") and args.gas_limit: + return None + # if proxy is not provided, we can't use GasLimitEstimator if hasattr(args, "proxy") and not args.proxy: return None @@ -812,3 +839,76 @@ def initialize_gas_limit_estimator(args: Any) -> Union[GasLimitEstimator, None]: network_provider_config = config.get_config_for_network_providers() proxy = ProxyNetworkProvider(url=args.proxy, config=network_provider_config) return GasLimitEstimator(network_provider=proxy, gas_multiplier=multiplier) + + +def set_options_for_hash_signing_if_needed( + transaction: Transaction, + guardian: Union[IAccount, None], + relayer: Union[IAccount, None], +): + transaction_computer = TransactionComputer() + + if guardian and guardian.use_hash_signing: + transaction_computer.apply_options_for_hash_signing(transaction) + return + + if relayer and relayer.use_hash_signing: + transaction_computer.apply_options_for_hash_signing(transaction) + + +def alter_transaction_and_sign_again_if_needed( + args: Any, + tx: Transaction, + sender: IAccount, + guardian_and_relayer_data: GuardianRelayerData, +): + set_options_for_hash_signing_if_needed( + transaction=tx, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) + + altered = _alter_version_and_options_if_provided( + args=args, + transaction=tx, + ) + + if altered: + # sign only if something was altered + _sign_transaction(tx, sender, guardian_and_relayer_data) + else: + # sign only with guardian/relayer if needed + _sign_transaction(tx, None, guardian_and_relayer_data) + + +def _alter_version_and_options_if_provided( + args: Any, + transaction: Transaction, +) -> bool: + """Alters the transaction version and options if they are provided in args. + Returns True if any alteration was made, False otherwise. + """ + altered = False + + if args.version != DEFAULT_TX_VERSION and transaction.version != args.version: + transaction.version = args.version + altered = True + + if args.options and transaction.options != args.options: + transaction.options = args.options + altered = True + + return altered + + +def _sign_transaction( + transaction: Transaction, + sender: Optional[IAccount] = None, + guardian_and_relayer_data: GuardianRelayerData = GuardianRelayerData(), +): + signer = SigningWrapper() + signer.sign_transaction( + transaction=transaction, + sender=sender, + guardian_and_relayer=guardian_and_relayer_data, + ) diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py new file mode 100644 index 00000000..a81987f4 --- /dev/null +++ b/multiversx_sdk_cli/cli_tokens.py @@ -0,0 +1,2231 @@ +from typing import Any + +from multiversx_sdk import ( + Address, + ProxyNetworkProvider, + TokenManagementController, + TokenType, +) + +from multiversx_sdk_cli import cli_shared +from multiversx_sdk_cli.args_validation import ( + validate_broadcast_args, + validate_chain_id_args, +) + + +def setup_parser(args: list[str], subparsers: Any) -> Any: + parser = cli_shared.add_group_subparser( + subparsers, "token", "Perform token management operations (issue tokens, create NFTs, set roles, etc.)" + ) + subparsers = parser.add_subparsers() + + sub = cli_shared.add_command_subparser(subparsers, "token", "issue-fungible", "Issue a new fungible ESDT token.") + add_issuing_tokens_args( + sub, + with_initial_supply=True, + with_num_decimals=True, + with_transfer_nft_create_role=False, + ) + add_common_args(args, sub) + sub.set_defaults(func=issue_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "issue-semi-fungible", + "Issue a new semi-fungible ESDT token.", + ) + add_issuing_tokens_args(sub) + add_common_args(args, sub) + sub.set_defaults(func=issue_semi_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "issue-non-fungible", "Issue a new non-fungible ESDT token (NFT)." + ) + add_issuing_tokens_args(sub) + add_common_args(args, sub) + sub.set_defaults(func=issue_non_fungible) + + sub = cli_shared.add_command_subparser(subparsers, "token", "register-meta-esdt", "Register a MetaESDT token.") + add_issuing_tokens_args(sub, with_num_decimals=True) + add_common_args(args, sub) + sub.set_defaults(func=register_meta_esdt) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "register-and-set-all-roles", "Register a token and set all roles." + ) + sub.add_argument( + "--token-name", + required=True, + type=str, + help="the name of the token to be issued: 3-20 alphanumerical characters", + ) + sub.add_argument( + "--token-ticker", + required=True, + type=str, + help="the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical characters", + ) + sub.add_argument( + "--num-decimals", + required=True, + type=int, + help="a numerical value between 0 and 18 representing number of decimals", + ) + sub.add_argument( + "--token-type", + required=True, + type=str, + choices=["NFT", "SFT", "META", "FNG"], + help="the token type", + ) + add_common_args(args, sub) + sub.set_defaults(func=register_and_set_all_roles) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "set-burn-role-globally", "Set the burn role globally for a token." + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=set_burn_role_globally) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "unset-burn-role-globally", "Unset the burn role globally for a token." + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unset_burn_role_globally) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "set-special-role-fungible", "Set special roles on a fungible token for a user." + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_fungible(sub) + add_common_args(args, sub) + sub.set_defaults(func=set_special_role_on_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "unset-special-role-fungible", "Unset special roles on a fungible token for a user." + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_fungible(sub) + add_common_args(args, sub) + sub.set_defaults(func=unset_special_role_on_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "set-special-role-semi-fungible", "Set special roles on a semi-fungible token for a user." + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_semi_fungible(sub) + add_common_args(args, sub) + sub.set_defaults(func=set_special_role_on_semi_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unset-special-role-semi-fungible", + "Unset special roles on a semi-fungible token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_semi_fungible(sub, with_nft_create=False) + add_common_args(args, sub) + sub.set_defaults(func=unset_special_role_on_semi_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "set-special-role-meta-esdt", + "Set special roles on a meta-esdt token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_meta_esdt(sub) + add_common_args(args, sub) + sub.set_defaults(func=set_special_role_on_meta_esdt) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unset-special-role-meta-esdt", + "Unset special roles on a meta-esdt token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_meta_esdt(sub, with_nft_create=False) + add_common_args(args, sub) + sub.set_defaults(func=unset_special_role_on_meta_esdt) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "set-special-role-nft", + "Set special roles on a non-fungible token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_nft(sub) + add_common_args(args, sub) + sub.set_defaults(func=set_special_role_on_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unset-special-role-nft", + "Unset special roles on a non-fungible token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_nft(sub) + add_common_args(args, sub) + sub.set_defaults(func=unset_special_role_on_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "create-nft", + "Create a non-fungible token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--initial-quantity", type=int, required=True, help="The initial quantity of the token.") + sub.add_argument("--name", type=str, required=True, help="The name of the token.") + sub.add_argument("--royalties", type=int, required=True, help="The royalties of the token.") + sub.add_argument("--hash", type=str, required=True, help="The hash of the token.") + sub.add_argument("--attributes", type=str, required=True, help="The hex-string attributes of the token.") + sub.add_argument("--uris", nargs="+", required=True, help="The uris of the token.") + add_common_args(args, sub) + sub.set_defaults(func=create_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "pause", + "Pause a token.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=pause_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unpause", + "Unpause a token.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unpause_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "freeze", + "Freeze a token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=freeze_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unfreeze", + "Unfreeze a token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unfreeze_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "wipe", + "Wipe a token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=wipe_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "local-mint", + "Mint new tokens.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--supply-to-mint", required=True, type=int, help="The amount of new tokens to mint") + add_common_args(args, sub) + sub.set_defaults(func=local_mint) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "local-burn", + "Burn tokens.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--supply-to-burn", required=True, type=int, help="The amount of tokens to burn") + add_common_args(args, sub) + sub.set_defaults(func=local_burn) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "update-attributes", + "Update token attributes.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--attributes", required=True, type=str, help="The hex-string attributes of the token") + add_common_args(args, sub) + sub.set_defaults(func=update_attributes) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "add-quantity", + "Increase token quantity.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--quantity", required=True, type=int, help="The quantity to add") + add_common_args(args, sub) + sub.set_defaults(func=add_quantity) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "burn-quantity", + "Burn token quantity.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--quantity", required=True, type=int, help="The quantity to burn") + add_common_args(args, sub) + sub.set_defaults(func=burn_quantity) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "modify-royalties", + "Modify token royalties.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%%)") + add_common_args(args, sub) + sub.set_defaults(func=modify_royalties) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "set-new-uris", + "Set new uris.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--uris", required=True, nargs="+", help="The new uris") + add_common_args(args, sub) + sub.set_defaults(func=set_new_uris) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "modify-creator", + "Modify the creator of the token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + add_common_args(args, sub) + sub.set_defaults(func=modify_creator) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "update-metadata", + "Update the metadata of the token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--token-name", required=True, type=str, help="The new name of the token") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%%)") + sub.add_argument("--hash", required=True, type=str, help="The new hash of the token") + sub.add_argument( + "--attributes", required=True, type=str, help="The new attributes of the token as a hex-encoded string" + ) + sub.add_argument("--uris", required=True, nargs="+", help="The new uris") + add_common_args(args, sub) + sub.set_defaults(func=update_metadata) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "nft-metadata-recreate", + "Recreate the metadata of the token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--token-name", required=True, type=str, help="The new name of the token") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%%)") + sub.add_argument("--hash", required=True, type=str, help="The new hash of the token") + sub.add_argument( + "--attributes", required=True, type=str, help="The new attributes of the token as a hex-encoded string" + ) + sub.add_argument("--uris", required=True, nargs="+", help="The new uris") + add_common_args(args, sub) + sub.set_defaults(func=nft_metadata_recreate) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "change-to-dynamic", + "Change a token to a dynamic token.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=change_to_dynamic) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "update-token-id", + "Update token id.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=update_token_id) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "register-dynamic", + "Register a dynamic token.", + ) + sub.add_argument("--token-name", type=str, required=True, help="The token name") + sub.add_argument("--token-ticker", type=str, required=True, help="The token ticker") + sub.add_argument( + "--token-type", type=str, required=True, choices=["NFT", "SFT", "FNG", "META"], help="The token type" + ) + sub.add_argument( + "--denominator", type=int, default=None, help="The number of decimals, only needed when token type is META ESDT" + ) + add_common_args(args, sub) + sub.set_defaults(func=register_dynamic_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "register-dynamic-and-set-all-roles", + "Register a dynamic token and set all roles.", + ) + sub.add_argument("--token-name", type=str, required=True, help="The token name") + sub.add_argument("--token-ticker", type=str, required=True, help="The token ticker") + sub.add_argument( + "--token-type", type=str, required=True, choices=["NFT", "SFT", "FNG", "META"], help="The token type" + ) + sub.add_argument( + "--denominator", type=int, default=None, help="The number of decimals, only needed when token type is META ESDT" + ) + add_common_args(args, sub) + sub.set_defaults(func=register_dynamic_and_set_all_roles) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "transfer-ownership", + "Transfer the ownership of a token to another user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--new-owner", type=str, required=True, help="The new token owner") + add_common_args(args, sub) + sub.set_defaults(func=transfer_ownership) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "freeze-single-nft", + "Freeze the NFT of a user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=freeze_single_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unfreeze-single-nft", + "Unfreeze the NFT of a user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unfreeze_single_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "change-sft-to-meta-esdt", + "Change a semi fungible token to a Meta ESDT.", + ) + sub.add_argument("--collection", required=True, type=str, help="The collection identifier") + sub.add_argument("--decimals", type=int, required=True, help="The number of decimals the meta esdt will have") + add_common_args(args, sub) + sub.set_defaults(func=change_sft_to_meta_esdt) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "transfer-nft-create-role", + "Transfer the nft create role to a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=transfer_nft_create_role) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "stop-nft-creation", + "Stop the creation of new NFTs.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=stop_nft_creation) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "wipe-single-nft", + "Wipe the NFT of a user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", type=int, required=True, help="The nonce of the NFT as a decimal number") + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=wipe_single_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "add-uris", + "Add uris for a token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", type=int, required=True, help="The nonce of the NFT as a decimal number") + sub.add_argument("--uris", nargs="+", required=True, help="The new uris to be added to the token.") + add_common_args(args, sub) + sub.set_defaults(func=add_uris) + + parser.epilog = cli_shared.build_group_epilog(subparsers) + return subparsers + + +def add_common_args(args: list[str], sub: Any): + cli_shared.add_wallet_args(args, sub) + cli_shared.add_tx_args(args, sub, with_receiver=False, with_data=False) + cli_shared.add_proxy_arg(sub) + cli_shared.add_broadcast_args(sub) + cli_shared.add_wait_result_and_timeout_args(sub) + cli_shared.add_guardian_wallet_args(args, sub) + cli_shared.add_relayed_v3_wallet_args(args, sub) + cli_shared.add_outfile_arg(sub) + + +def add_issuing_tokens_args( + sub: Any, + with_initial_supply: bool = False, + with_num_decimals: bool = False, + with_transfer_nft_create_role: bool = True, +): + sub.add_argument( + "--token-name", + required=True, + type=str, + help="the name of the token to be issued: 3-20 alphanumerical characters", + ) + sub.add_argument( + "--token-ticker", + required=True, + type=str, + help="the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical characters", + ) + + if with_initial_supply: + sub.add_argument( + "--initial-supply", required=True, type=int, help="the initial supply of the token to be issued" + ) + + if with_num_decimals: + sub.add_argument( + "--num-decimals", + required=True, + type=int, + help="a numerical value between 0 and 18 representing number of decimals", + ) + + sub.add_argument( + "--cannot-freeze", + action="store_false", + dest="can_freeze", + default=True, + help="make token not freezable", + ) + sub.add_argument( + "--cannot-wipe", + action="store_false", + dest="can_wipe", + default=True, + help="make token not wipeable", + ) + sub.add_argument( + "--cannot-pause", + action="store_false", + dest="can_pause", + default=True, + help="make token not pausable", + ) + sub.add_argument( + "--cannot-change-owner", + action="store_false", + dest="can_change_owner", + default=True, + help="don't allow changing the token's owner", + ) + sub.add_argument( + "--cannot-upgrade", + action="store_false", + dest="can_upgrade", + default=True, + help="don't allow upgrading the token", + ) + sub.add_argument( + "--cannot-add-special-roles", + action="store_false", + dest="can_add_special_roles", + default=True, + help="don't allow special roles to be added for the token", + ) + + if with_transfer_nft_create_role: + sub.add_argument( + "--cannot-transfer-nft-create-role", + action="store_false", + dest="can_transfer_nft_create_role", + default=True, + help="don't allow for nft create roles to be transferred for the token", + ) + + +def _add_token_identifier_arg(sub: Any): + sub.add_argument("--token-identifier", required=True, type=str, help="the token identifier") + + +def _add_user_arg(sub: Any): + sub.add_argument("--user", required=True, type=str, help="the bech32 address of the user") + + +def _add_special_roles_args_for_fungible(sub: Any): + sub.add_argument( + "--local-mint", + action="store_true", + default=False, + help="role for local minting", + ) + sub.add_argument( + "--local-burn", + action="store_true", + default=False, + help="role for local burning", + ) + sub.add_argument( + "--esdt-transfer-role", + action="store_true", + default=False, + help="role for esdt transfer", + ) + + +def _add_special_roles_args_for_meta_esdt(sub: Any, with_nft_create: bool = True): + if with_nft_create: + sub.add_argument( + "--nft-create", + action="store_true", + default=False, + help="role for nft create", + ) + + sub.add_argument( + "--nft-burn", + action="store_true", + default=False, + help="role for nft burn", + ) + sub.add_argument( + "--nft-add-quantity", + action="store_true", + default=False, + help="role for adding quantity", + ) + sub.add_argument( + "--esdt-transfer-role", + action="store_true", + default=False, + help="role for esdt transfer", + ) + + +def _add_special_roles_args_for_nft(sub: Any, with_nft_create: bool = True): + if with_nft_create: + sub.add_argument( + "--nft-create", + action="store_true", + default=False, + help="role for nft create", + ) + + sub.add_argument( + "--nft-burn", + action="store_true", + default=False, + help="role for nft burn", + ) + sub.add_argument( + "--nft-update-attributes", + action="store_true", + default=False, + help="role for updating attributes", + ) + + sub.add_argument( + "--nft-add-uri", + action="store_true", + default=False, + help="role for adding uri", + ) + + sub.add_argument( + "--esdt-transfer-role", + action="store_true", + default=False, + help="role for esdt transfer", + ) + + sub.add_argument( + "--nft-update", + action="store_true", + default=False, + help="role for updating nft", + ) + + sub.add_argument( + "--esdt-modify-royalties", + action="store_true", + default=False, + help="role for modifying royalties", + ) + + sub.add_argument( + "--esdt-set-new-uri", + action="store_true", + default=False, + help="role for setting new uri", + ) + + sub.add_argument( + "--esdt-modify-creator", + action="store_true", + default=False, + help="role for modifying creator", + ) + + sub.add_argument( + "--nft-recreate", + action="store_true", + default=False, + help="role for recreating nft", + ) + + +def _add_special_roles_args_for_semi_fungible(sub: Any, with_nft_create: bool = True): + if with_nft_create: + sub.add_argument( + "--nft-create", + action="store_true", + default=False, + help="role for nft create", + ) + + sub.add_argument( + "--nft-burn", + action="store_true", + default=False, + help="role for nft burn", + ) + sub.add_argument( + "--nft-add-quantity", + action="store_true", + default=False, + help="role for adding quantity", + ) + sub.add_argument( + "--esdt-transfer-role", + action="store_true", + default=False, + help="role for esdt transfer", + ) + sub.add_argument( + "--nft-update", + action="store_true", + default=False, + help="role for updating nft", + ) + sub.add_argument( + "--esdt-modify-royalties", + action="store_true", + default=False, + help="role for modifying royalties", + ) + sub.add_argument( + "--esdt-set-new-uri", + action="store_true", + default=False, + help="role for setting new uri", + ) + sub.add_argument( + "--esdt-modify-creator", + action="store_true", + default=False, + help="role for modifying creator", + ) + sub.add_argument( + "--nft-recreate", + action="store_true", + default=False, + help="role for recreating nft", + ) + + +def _ensure_args(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + +def _initialize_controller(args: Any) -> TokenManagementController: + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + + proxy_url = args.proxy if args.proxy else "" + return TokenManagementController( + chain_id=chain_id, + network_provider=ProxyNetworkProvider(proxy_url), + gas_limit_estimator=gas_estimator, + ) + + +def issue_fungible(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_issuing_fungible( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + initial_supply=args.initial_supply, + num_decimals=args.num_decimals, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def issue_semi_fungible(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_issuing_semi_fungible( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_transfer_nft_create_role=args.can_transfer_nft_create_role, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def issue_non_fungible(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_issuing_non_fungible( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_transfer_nft_create_role=args.can_transfer_nft_create_role, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def register_meta_esdt(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_registering_meta_esdt( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + num_decimals=args.num_decimals, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_transfer_nft_create_role=args.can_transfer_nft_create_role, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def register_and_set_all_roles(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + [token_type] = [type for type in TokenType if args.token_type == type.value] + + transaction = controller.create_transaction_for_registering_and_setting_roles( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + num_decimals=args.num_decimals, + token_type=token_type, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def set_burn_role_globally(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_setting_burn_role_globally( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def unset_burn_role_globally(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + controller = _initialize_controller(args) + + transaction = controller.create_transaction_for_unsetting_burn_role_globally( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def set_special_role_on_fungible(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_setting_special_role_on_fungible_token( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + add_role_local_mint=args.local_mint, + add_role_local_burn=args.local_burn, + add_role_esdt_transfer_role=args.esdt_transfer_role, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def unset_special_role_on_fungible(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unsetting_special_role_on_fungible_token( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + remove_role_local_mint=args.local_mint, + remove_role_local_burn=args.local_burn, + remove_role_esdt_transfer_role=args.esdt_transfer_role, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def set_special_role_on_semi_fungible(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_setting_special_role_on_semi_fungible_token( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + add_role_nft_create=args.nft_create, + add_role_nft_burn=args.nft_burn, + add_role_nft_add_quantity=args.nft_add_quantity, + add_role_esdt_transfer_role=args.esdt_transfer_role, + add_role_nft_update=args.nft_update, + add_role_esdt_modify_royalties=args.esdt_modify_royalties, + add_role_esdt_set_new_uri=args.esdt_set_new_uri, + add_role_esdt_modify_creator=args.esdt_modify_creator, + add_role_nft_recreate=args.nft_recreate, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def unset_special_role_on_semi_fungible(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unsetting_special_role_on_semi_fungible_token( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + remove_role_nft_burn=args.nft_burn, + remove_role_nft_add_quantity=args.nft_add_quantity, + remove_role_esdt_transfer_role=args.esdt_transfer_role, + remove_role_nft_update=args.nft_update, + remove_role_esdt_modify_royalties=args.esdt_modify_royalties, + remove_role_esdt_set_new_uri=args.esdt_set_new_uri, + remove_role_esdt_modify_creator=args.esdt_modify_creator, + remove_role_nft_recreate=args.nft_recreate, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def set_special_role_on_meta_esdt(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_setting_special_role_on_meta_esdt( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + add_role_nft_create=args.nft_create, + add_role_nft_burn=args.nft_burn, + add_role_nft_add_quantity=args.nft_add_quantity, + add_role_esdt_transfer_role=args.esdt_transfer_role, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def unset_special_role_on_meta_esdt(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unsetting_special_role_on_meta_esdt( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + remove_role_nft_burn=args.nft_burn, + remove_role_nft_add_quantity=args.nft_add_quantity, + remove_role_esdt_transfer_role=args.esdt_transfer_role, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def set_special_role_on_nft(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_setting_special_role_on_non_fungible_token( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + add_role_nft_create=args.nft_create, + add_role_nft_burn=args.nft_burn, + add_role_nft_update_attributes=args.nft_update_attributes, + add_role_nft_add_uri=args.nft_add_uri, + add_role_esdt_transfer_role=args.esdt_transfer_role, + add_role_nft_update=args.nft_update, + add_role_esdt_modify_royalties=args.esdt_modify_royalties, + add_role_esdt_set_new_uri=args.esdt_set_new_uri, + add_role_esdt_modify_creator=args.esdt_modify_creator, + add_role_nft_recreate=args.nft_recreate, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def unset_special_role_on_nft(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unsetting_special_role_on_non_fungible_token( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + remove_role_nft_burn=args.nft_burn, + remove_role_nft_update_attributes=args.nft_update_attributes, + remove_role_nft_remove_uri=args.nft_add_uri, + remove_role_esdt_transfer_role=args.esdt_transfer_role, + remove_role_nft_update=args.nft_update, + remove_role_esdt_modify_royalties=args.esdt_modify_royalties, + remove_role_esdt_set_new_uri=args.esdt_set_new_uri, + remove_role_esdt_modify_creator=args.esdt_modify_creator, + remove_role_nft_recreate=args.nft_recreate, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def create_nft(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_creating_nft( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + initial_quantity=args.initial_quantity, + name=args.name, + royalties=args.royalties, + hash=args.hash, + attributes=bytes.fromhex(args.attributes), + uris=args.uris, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def pause_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_pausing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def unpause_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unpausing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def freeze_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_freezing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def unfreeze_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unfreezing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def wipe_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_wiping( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def local_mint(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_local_minting( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + supply_to_mint=args.supply_to_mint, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def local_burn(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_local_burning( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + supply_to_burn=args.supply_to_burn, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def update_attributes(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_updating_attributes( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + attributes=bytes.fromhex(args.attributes), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def add_quantity(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_adding_quantity( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + quantity_to_add=args.quantity, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def burn_quantity(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_burning_quantity( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + quantity_to_burn=args.quantity, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def modify_royalties(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_modifying_royalties( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + new_royalties=args.royalties, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def set_new_uris(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_setting_new_uris( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + new_uris=args.uris, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def modify_creator(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_modifying_creator( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def update_metadata(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_updating_metadata( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + new_token_name=args.token_name, + new_royalties=args.royalties, + new_hash=args.hash, + new_attributes=bytes.fromhex(args.attributes), + new_uris=args.uris, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def nft_metadata_recreate(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_nft_metadata_recreate( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + new_token_name=args.token_name, + new_royalties=args.royalties, + new_hash=args.hash, + new_attributes=bytes.fromhex(args.attributes), + new_uris=args.uris, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def change_to_dynamic(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_changing_token_to_dynamic( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def update_token_id(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_updating_token_id( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def register_dynamic_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + [token_type] = [token_type for token_type in TokenType if token_type.value == args.token_type] + + transaction = controller.create_transaction_for_registering_dynamic_token( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + token_type=token_type, + denominator=args.denominator, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def register_dynamic_and_set_all_roles(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + [token_type] = [token_type for token_type in TokenType if token_type.value == args.token_type] + + transaction = controller.create_transaction_for_registering_dynamic_and_setting_roles( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + token_type=token_type, + denominator=args.denominator, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def transfer_ownership(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_transferring_ownership( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + new_owner=Address.new_from_bech32(args.new_owner), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def freeze_single_nft(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_freezing_single_nft( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def unfreeze_single_nft(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unfreezing_single_nft( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def change_sft_to_meta_esdt(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_changing_sft_to_meta_esdt( + sender=sender, + nonce=sender.nonce, + collection=args.collection, + num_decimals=args.decimals, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def transfer_nft_create_role(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_transferring_nft_create_role( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def stop_nft_creation(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_stopping_nft_creation( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def wipe_single_nft(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_wiping_single_nft( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) + + +def add_uris(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_adding_uris( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + uris=args.uris, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) diff --git a/multiversx_sdk_cli/cli_transactions.py b/multiversx_sdk_cli/cli_transactions.py index 1249cafd..fd97ae51 100644 --- a/multiversx_sdk_cli/cli_transactions.py +++ b/multiversx_sdk_cli/cli_transactions.py @@ -2,7 +2,12 @@ from pathlib import Path from typing import Any -from multiversx_sdk import Address, ProxyNetworkProvider, TransactionComputer +from multiversx_sdk import ( + Address, + ProxyNetworkProvider, + TransactionComputer, + TransfersController, +) from multiversx_sdk_cli import cli_shared, utils from multiversx_sdk_cli.args_validation import ( @@ -13,14 +18,12 @@ validate_proxy_argument, validate_receiver_args, ) -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController from multiversx_sdk_cli.cli_output import CLIOutputBuilder from multiversx_sdk_cli.config import get_config_for_network_providers from multiversx_sdk_cli.errors import BadUsage, IncorrectWalletError, NoWalletProvided -from multiversx_sdk_cli.transactions import ( - TransactionsController, - load_transaction_from_file, -) +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.signing_wrapper import SigningWrapper +from multiversx_sdk_cli.transactions import load_transaction_from_file logger = logging.getLogger("cli.transactions") @@ -101,38 +104,59 @@ def create_transaction(args: Any): validate_broadcast_args(args) validate_chain_id_args(args) + if args.data_file: + args.data = Path(args.data_file).read_text() + + transfers = getattr(args, "token_transfers", None) + + if transfers and args.data: + raise BadUsage("You cannot provide both data and token transfers") + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), args=args, ) - if args.data_file: - args.data = Path(args.data_file).read_text() - native_amount = int(args.value) - - transfers = getattr(args, "token_transfers", None) + receiver = Address.new_from_bech32(args.receiver) transfers = cli_shared.prepare_token_transfers(transfers) if transfers else None chain_id = cli_shared.get_chain_id(args.proxy, args.chain) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - tx_controller = TransactionsController(chain_id, gas_estimator) - - tx = tx_controller.create_transaction( + controller = TransfersController(chain_id=chain_id, gas_limit_estimator=gas_estimator) + + if not transfers: + tx = controller.create_transaction_for_native_token_transfer( + sender=sender, + nonce=sender.nonce, + receiver=receiver, + native_transfer_amount=native_amount, + data=args.data.encode() if args.data else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + else: + tx = controller.create_transaction_for_transfer( + sender=sender, + nonce=sender.nonce, + receiver=receiver, + native_transfer_amount=native_amount, + token_transfers=transfers, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - receiver=Address.new_from_bech32(args.receiver), - native_amount=native_amount, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - token_transfers=transfers, - data=args.data, guardian_and_relayer_data=guardian_and_relayer_data, ) - cli_shared.send_or_simulate(tx, args) @@ -180,18 +204,24 @@ def sign_transaction(args: Any): tx_computer = TransactionComputer() if tx.guardian and not tx_computer.has_options_set_for_guarded_transaction(tx): - raise BadUsage("Guardian wallet provided but the transaction has incorrect options.") + raise BadUsage("Guardian wallet provided but the transaction has incorrect options") - tx_controller = BaseTransactionsController() - tx_controller.sign_transaction( - transaction=tx, - sender=sender, + guardian_and_relayer = GuardianRelayerData( guardian=guardian, + guardian_address=tx.guardian, relayer=relayer, + relayer_address=tx.relayer, guardian_service_url=args.guardian_service_url, guardian_2fa_code=args.guardian_2fa_code, ) + signer = SigningWrapper() + signer.sign_transaction( + transaction=tx, + sender=sender, + guardian_and_relayer=guardian_and_relayer, + ) + cli_shared.send_or_simulate(tx, args) diff --git a/multiversx_sdk_cli/cli_validators.py b/multiversx_sdk_cli/cli_validators.py index f28e0814..fdbcb681 100644 --- a/multiversx_sdk_cli/cli_validators.py +++ b/multiversx_sdk_cli/cli_validators.py @@ -1,7 +1,12 @@ from pathlib import Path from typing import Any -from multiversx_sdk import Address, ValidatorPublicKey, ValidatorsSigners +from multiversx_sdk import ( + Address, + ValidatorPublicKey, + ValidatorsController, + ValidatorsSigners, +) from multiversx_sdk_cli import cli_shared, utils from multiversx_sdk_cli.args_validation import ( @@ -10,7 +15,6 @@ validate_nonce_args, validate_receiver_args, ) -from multiversx_sdk_cli.validators import ValidatorsController def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -153,6 +157,7 @@ def validate_args(args: Any) -> None: def do_stake(args: Any): validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -167,37 +172,40 @@ def do_stake(args: Any): if args.top_up: tx = controller.create_transaction_for_topping_up( sender=sender, - native_amount=native_amount, + nonce=sender.nonce, + amount=native_amount, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) else: validators_signers = _load_validators_signers(args.validators_pem) tx = controller.create_transaction_for_staking( sender=sender, - validators=validators_signers, - native_amount=native_amount, - gas_limit=args.gas_limit, - gas_price=args.gas_price, nonce=sender.nonce, - version=args.version, - options=args.options, + validators_file=validators_signers, + amount=native_amount, rewards_address=rewards_address, - guardian_and_relayer_data=guardian_and_relayer_data, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) -def _get_validators_controller(args: Any): +def _get_validators_controller(args: Any) -> ValidatorsController: chain_id = cli_shared.get_chain_id(args.proxy, args.chain) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - validators = ValidatorsController(chain_id=chain_id, gas_limit_estimator=gas_estimator) - return validators + return ValidatorsController(chain_id=chain_id, gas_limit_estimator=gas_estimator) def _load_validators_signers(validators_pem: str) -> ValidatorsSigners: @@ -224,22 +232,25 @@ def do_unstake(args: Any): args=args, ) - native_amount = int(args.value) keys = _parse_public_bls_keys(args.nodes_public_keys) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unstaking( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -258,16 +269,21 @@ def do_unjail(args: Any): controller = _get_validators_controller(args) tx = controller.create_transaction_for_unjailing( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + amount=native_amount, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -280,22 +296,25 @@ def do_unbond(args: Any): args=args, ) - native_amount = int(args.value) keys = _parse_public_bls_keys(args.nodes_public_keys) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unbonding( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -308,22 +327,25 @@ def change_reward_address(args: Any): args=args, ) - native_amount = int(args.value) rewards_address = Address.new_from_bech32(args.reward_address) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_changing_rewards_address( sender=sender, + nonce=sender.nonce, rewards_address=rewards_address, - native_amount=native_amount, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -336,20 +358,22 @@ def do_claim(args: Any): args=args, ) - native_amount = int(args.value) - controller = _get_validators_controller(args) tx = controller.create_transaction_for_claiming( sender=sender, - native_amount=native_amount, + nonce=sender.nonce, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -362,22 +386,25 @@ def do_unstake_nodes(args: Any): args=args, ) - native_amount = int(args.value) keys = _parse_public_bls_keys(args.nodes_public_keys) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unstaking_nodes( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -390,22 +417,25 @@ def do_unstake_tokens(args: Any): args=args, ) - native_amount = int(args.value) value = int(args.unstake_value) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unstaking_tokens( sender=sender, - value=value, - native_amount=native_amount, + nonce=sender.nonce, + amount=value, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -418,22 +448,25 @@ def do_unbond_nodes(args: Any): args=args, ) - native_amount = int(args.value) keys = _parse_public_bls_keys(args.nodes_public_keys) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unbonding_nodes( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -446,22 +479,25 @@ def do_unbond_tokens(args: Any): args=args, ) - native_amount = int(args.value) value = int(args.unbond_value) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unbonding_tokens( sender=sender, - value=value, - native_amount=native_amount, + nonce=sender.nonce, + amount=value, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -474,20 +510,22 @@ def do_clean_registered_data(args: Any): args=args, ) - native_amount = int(args.value) - controller = _get_validators_controller(args) tx = controller.create_transaction_for_cleaning_registered_data( sender=sender, - native_amount=native_amount, + nonce=sender.nonce, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -500,20 +538,23 @@ def do_restake_unstaked_nodes(args: Any): args=args, ) - native_amount = int(args.value) keys = _parse_public_bls_keys(args.nodes_public_keys) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_restaking_unstaked_nodes( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) diff --git a/multiversx_sdk_cli/constants.py b/multiversx_sdk_cli/constants.py index 803889fe..54135562 100644 --- a/multiversx_sdk_cli/constants.py +++ b/multiversx_sdk_cli/constants.py @@ -7,6 +7,7 @@ SC_HEX_PUBKEY_PREFIX_WASM_VM = SC_HEX_PUBKEY_PREFIX + VM_TYPE_WASM_VM DEFAULT_CARGO_TARGET_DIR_NAME = "default_cargo_target" TRANSACTION_OPTIONS_TX_GUARDED = 0b0010 +TRANSACTION_OPTIONS_TX_HASH_SIGN = 0b0001 ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365 DEFAULT_TX_VERSION = 2 diff --git a/multiversx_sdk_cli/contracts.py b/multiversx_sdk_cli/contracts.py deleted file mode 100644 index 91f7a7c2..00000000 --- a/multiversx_sdk_cli/contracts.py +++ /dev/null @@ -1,221 +0,0 @@ -import logging -from pathlib import Path -from typing import Any, Optional, Protocol, Union - -from multiversx_sdk import ( - Address, - AwaitingOptions, - GasLimitEstimator, - SmartContractController, - SmartContractQuery, - SmartContractQueryResponse, - SmartContractTransactionsFactory, - TokenTransfer, - Transaction, - TransactionOnNetwork, - TransactionsFactoryConfig, -) -from multiversx_sdk.abi import Abi - -from multiversx_sdk_cli import errors -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - -logger = logging.getLogger("contracts") - - -# fmt: off -class INetworkProvider(Protocol): - def query_contract(self, query: SmartContractQuery) -> SmartContractQueryResponse: - ... - - def await_transaction_completed( - self, transaction_hash: Union[bytes, str], options: Optional[AwaitingOptions] = None - ) -> TransactionOnNetwork: - ... -# fmt: on - - -class SmartContract(BaseTransactionsController): - def __init__( - self, - config: TransactionsFactoryConfig, - abi: Optional[Abi] = None, - gas_limit_estimator: Optional[GasLimitEstimator] = None, - ): - self._abi = abi - self._config = config - self._factory = SmartContractTransactionsFactory(config, abi, gas_limit_estimator) - - def prepare_deploy_transaction( - self, - owner: IAccount, - bytecode: Path, - arguments: Union[list[Any], None], - should_prepare_args: bool, - upgradeable: bool, - readable: bool, - payable: bool, - payable_by_sc: bool, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_deploy( - sender=owner.address, - bytecode=bytecode, - gas_limit=gas_limit, - arguments=args, - native_transfer_amount=value, - is_upgradeable=upgradeable, - is_readable=readable, - is_payable=payable, - is_payable_by_sc=payable_by_sc, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_execute_transaction( - self, - caller: IAccount, - contract: Address, - function: str, - arguments: Union[list[Any], None], - should_prepare_args: bool, - gas_limit: Union[int, None], - gas_price: int, - value: int, - token_transfers: Union[list[TokenTransfer], None], - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_execute( - sender=caller.address, - contract=contract, - function=function, - gas_limit=gas_limit, - arguments=args, - native_transfer_amount=value, - token_transfers=token_transfers or [], - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=caller, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_upgrade_transaction( - self, - owner: IAccount, - contract: Address, - bytecode: Path, - arguments: Union[list[str], None], - should_prepare_args: bool, - upgradeable: bool, - readable: bool, - payable: bool, - payable_by_sc: bool, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_upgrade( - sender=owner.address, - contract=contract, - bytecode=bytecode, - gas_limit=gas_limit, - arguments=args, - native_transfer_amount=value, - is_upgradeable=upgradeable, - is_readable=readable, - is_payable=payable, - is_payable_by_sc=payable_by_sc, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def query_contract( - self, - contract_address: Address, - proxy: INetworkProvider, - function: str, - arguments: Optional[list[Any]], - should_prepare_args: bool, - ) -> list[Any]: - args = arguments if arguments else [] - if should_prepare_args: - args = self._convert_args_to_typed_values(args) - - sc_query_controller = SmartContractController(self._config.chain_id, proxy, self._abi) - - try: - response = sc_query_controller.query(contract=contract_address, function=function, arguments=args) - except Exception as e: - raise errors.QueryContractError("Couldn't query contract: ", e) - - return response diff --git a/multiversx_sdk_cli/delegation.py b/multiversx_sdk_cli/delegation.py deleted file mode 100644 index 6526d02d..00000000 --- a/multiversx_sdk_cli/delegation.py +++ /dev/null @@ -1,806 +0,0 @@ -from typing import Optional, Union - -from multiversx_sdk import ( - Address, - DelegationTransactionsFactory, - GasLimitEstimator, - Transaction, - TransactionsFactoryConfig, - ValidatorPublicKey, -) -from multiversx_sdk.abi import BigUIntValue, Serializer - -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.config_env import get_address_hrp -from multiversx_sdk_cli.errors import BadUsage -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - -DELEGATION_MANAGER_SC_ADDRESS_HEX = "000000000000000000010000000000000000000000000000000000000004ffff" - - -class DelegationOperations(BaseTransactionsController): - def __init__( - self, - config: TransactionsFactoryConfig, - gas_limit_estimator: Optional[GasLimitEstimator] = None, - ) -> None: - self._factory = DelegationTransactionsFactory(config=config, gas_limit_estimator=gas_limit_estimator) - self.chain_id = config.chain_id - - def prepare_transaction_for_new_delegation_contract( - self, - owner: IAccount, - native_amount: int, - total_delegation_cap: int, - service_fee: int, - gas_limit: Union[int, None], - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_new_delegation_contract( - sender=owner.address, - total_delegation_cap=total_delegation_cap, - service_fee=service_fee, - amount=native_amount, - ) - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_adding_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - signed_messages: list[bytes], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_adding_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - signed_messages=signed_messages, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_removing_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_removing_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_staking_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_staking_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_unbonding_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unbonding_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_unstaking_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unstaking_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_unjailing_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unjailing_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - amount=value, - ) - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_delegating( - self, - owner: IAccount, - delegation_contract: Address, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_delegating( - sender=owner.address, - delegation_contract=delegation_contract, - amount=value, - ) - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_claiming_rewards( - self, - owner: IAccount, - delegation_contract: Address, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_claiming_rewards( - sender=owner.address, delegation_contract=delegation_contract - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_redelegating_rewards( - self, - owner: IAccount, - delegation_contract: Address, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_redelegating_rewards( - sender=owner.address, delegation_contract=delegation_contract - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_undelegating( - self, - owner: IAccount, - delegation_contract: Address, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_undelegating( - sender=owner.address, - delegation_contract=delegation_contract, - amount=value, - ) - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_withdrawing( - self, - owner: IAccount, - delegation_contract: Address, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_withdrawing( - sender=owner.address, delegation_contract=delegation_contract - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_changing_service_fee( - self, - owner: IAccount, - delegation_contract: Address, - service_fee: int, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_changing_service_fee( - sender=owner.address, - delegation_contract=delegation_contract, - service_fee=service_fee, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_modifying_delegation_cap( - self, - owner: IAccount, - delegation_contract: Address, - delegation_cap: int, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_modifying_delegation_cap( - sender=owner.address, - delegation_contract=delegation_contract, - delegation_cap=delegation_cap, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_automatic_activation( - self, - owner: IAccount, - delegation_contract: Address, - set: bool, - unset: bool, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - if set and unset: - raise BadUsage("Cannot set and unset at the same time") - - if set: - tx = self._factory.create_transaction_for_setting_automatic_activation( - sender=owner.address, delegation_contract=delegation_contract - ) - elif unset: - tx = self._factory.create_transaction_for_unsetting_automatic_activation( - sender=owner.address, delegation_contract=delegation_contract - ) - else: - raise BadUsage("Both set and unset automatic activation are False") - - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_redelegate_cap( - self, - owner: IAccount, - delegation_contract: Address, - set: bool, - unset: bool, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - if set and unset: - raise BadUsage("Cannot set and unset at the same time") - - if set: - tx = self._factory.create_transaction_for_setting_cap_check_on_redelegate_rewards( - sender=owner.address, delegation_contract=delegation_contract - ) - elif unset: - tx = self._factory.create_transaction_for_unsetting_cap_check_on_redelegate_rewards( - sender=owner.address, delegation_contract=delegation_contract - ) - else: - raise BadUsage("Either set or unset should be True") - - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_setting_metadata( - self, - owner: IAccount, - delegation_contract: Address, - name: str, - website: str, - identifier: str, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_setting_metadata( - sender=owner.address, - delegation_contract=delegation_contract, - name=name, - website=website, - identifier=identifier, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - # will be replaced in the future once it's implemented in sdk-py - def prepare_transaction_for_creating_delegation_contract_from_validator( - self, - owner: IAccount, - max_cap: int, - service_fee: int, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - receiver = Address.new_from_hex(DELEGATION_MANAGER_SC_ADDRESS_HEX, get_address_hrp()) - - serializer = Serializer() - data = "makeNewContractFromValidatorData@" + serializer.serialize( - [BigUIntValue(max_cap), BigUIntValue(service_fee)] - ) - - tx = Transaction( - sender=owner.address, - receiver=receiver, - gas_limit=510000000, - chain_id=self.chain_id, - data=data.encode(), - nonce=nonce, - version=version, - options=options, - guardian=guardian_and_relayer_data.guardian_address, - relayer=guardian_and_relayer_data.relayer_address, - gas_price=gas_price, - value=value, - ) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx diff --git a/multiversx_sdk_cli/dns.py b/multiversx_sdk_cli/dns.py index c1a70277..486ce0d6 100644 --- a/multiversx_sdk_cli/dns.py +++ b/multiversx_sdk_cli/dns.py @@ -6,6 +6,7 @@ AddressComputer, SmartContractQuery, SmartContractQueryResponse, + TransfersController, ) from multiversx_sdk_cli import cli_shared @@ -16,7 +17,6 @@ ) from multiversx_sdk_cli.config_env import get_address_hrp from multiversx_sdk_cli.constants import ADDRESS_ZERO_HEX -from multiversx_sdk_cli.transactions import TransactionsController MaxNumShards = 256 ShardIdentiferLen = 2 @@ -77,21 +77,26 @@ def register(args: Any): chain_id = cli_shared.get_chain_id(args.proxy, args.chain) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TransactionsController(chain_id=chain_id, gas_limit_estimator=gas_estimator) + controller = TransfersController(chain_id=chain_id, gas_limit_estimator=gas_estimator) - tx = controller.create_transaction( + tx = controller.create_transaction_for_native_token_transfer( sender=sender, receiver=receiver, - native_amount=native_amount, + native_transfer_amount=native_amount, gas_limit=args.gas_limit, gas_price=args.gas_price, nonce=sender.nonce, - version=args.version, - options=args.options, - data=data, - guardian_and_relayer_data=guardian_and_relayer_data, + data=data.encode(), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) diff --git a/multiversx_sdk_cli/errors.py b/multiversx_sdk_cli/errors.py index d03c7983..ee5ca246 100644 --- a/multiversx_sdk_cli/errors.py +++ b/multiversx_sdk_cli/errors.py @@ -2,8 +2,6 @@ class KnownError(Exception): - inner = None - def __init__(self, message: str, inner: Union[Any, None] = None): super().__init__(message) self.inner = inner diff --git a/multiversx_sdk_cli/governance.py b/multiversx_sdk_cli/governance.py deleted file mode 100644 index 8477c4f1..00000000 --- a/multiversx_sdk_cli/governance.py +++ /dev/null @@ -1,269 +0,0 @@ -from typing import Optional, Union - -from multiversx_sdk import ( - Address, - GasLimitEstimator, - GovernanceTransactionsFactory, - Transaction, - TransactionsFactoryConfig, - VoteType, -) - -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - - -class GovernanceWrapper(BaseTransactionsController): - def __init__( - self, - config: TransactionsFactoryConfig, - gas_limit_estimator: Optional[GasLimitEstimator] = None, - ) -> None: - self.factory = GovernanceTransactionsFactory(config=config, gas_limit_estimator=gas_limit_estimator) - - def create_transaction_for_new_proposal( - self, - sender: IAccount, - nonce: int, - commit_hash: str, - start_vote_epoch: int, - end_vote_epoch: int, - native_token_amount: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_new_proposal( - sender=sender.address, - commit_hash=commit_hash, - start_vote_epoch=start_vote_epoch, - end_vote_epoch=end_vote_epoch, - native_token_amount=native_token_amount, - ) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_voting( - self, - sender: IAccount, - nonce: int, - proposal_nonce: int, - vote: str, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - vote_value = self._vote_type_from_string(vote) - - tx = self.factory.create_transaction_for_voting( - sender=sender.address, proposal_nonce=proposal_nonce, vote=vote_value - ) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_closing_proposal( - self, - sender: IAccount, - nonce: int, - proposal_nonce: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_closing_proposal(sender=sender.address, proposal_nonce=proposal_nonce) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_clearing_ended_proposals( - self, - sender: IAccount, - nonce: int, - proposers: list[Address], - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_clearing_ended_proposals(sender=sender.address, proposers=proposers) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_claiming_accumulated_fees( - self, - sender: IAccount, - nonce: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_claiming_accumulated_fees(sender=sender.address) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_changing_config( - self, - sender: IAccount, - nonce: int, - proposal_fee: int, - lost_proposal_fee: int, - min_quorum: int, - min_veto_threshold: int, - min_pass_threshold: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_changing_config( - sender=sender.address, - proposal_fee=proposal_fee, - lost_proposal_fee=lost_proposal_fee, - min_quorum=min_quorum, - min_veto_threshold=min_veto_threshold, - min_pass_threshold=min_pass_threshold, - ) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def _vote_type_from_string(self, value: str) -> VoteType: - for vote in VoteType: - if vote.value == value: - return vote - raise ValueError(f"Unknown vote type: {value}") diff --git a/multiversx_sdk_cli/interfaces.py b/multiversx_sdk_cli/interfaces.py index 8a533e7c..d9518f65 100644 --- a/multiversx_sdk_cli/interfaces.py +++ b/multiversx_sdk_cli/interfaces.py @@ -6,6 +6,7 @@ # fmt: off class IAccount(Protocol): address: Address + use_hash_signing: bool def sign_transaction(self, transaction: Transaction) -> bytes: ... diff --git a/multiversx_sdk_cli/multisig.py b/multiversx_sdk_cli/multisig.py deleted file mode 100644 index 12c8f6c7..00000000 --- a/multiversx_sdk_cli/multisig.py +++ /dev/null @@ -1,922 +0,0 @@ -import logging -from pathlib import Path -from typing import Any, Optional, Union - -from multiversx_sdk import ( - Address, - GasLimitEstimator, - MultisigTransactionsFactory, - TokenTransfer, - Transaction, - TransactionsFactoryConfig, -) -from multiversx_sdk.abi import Abi - -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - -logger = logging.getLogger("multisig") - - -class MultisigWrapper(BaseTransactionsController): - def __init__( - self, - config: TransactionsFactoryConfig, - abi: Abi, - gas_limit_estimator: Optional[GasLimitEstimator] = None, - ): - self._factory = MultisigTransactionsFactory(config=config, abi=abi, gas_limit_estimator=gas_limit_estimator) - - def prepare_deploy_transaction( - self, - owner: IAccount, - nonce: int, - bytecode: Path, - quorum: int, - board_members: list[Address], - upgradeable: bool, - readable: bool, - payable: bool, - payable_by_sc: bool, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_deploy( - sender=owner.address, - bytecode=bytecode, - quorum=quorum, - board=board_members, - gas_limit=gas_limit, - is_upgradeable=upgradeable, - is_readable=readable, - is_payable=payable, - is_payable_by_sc=payable_by_sc, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_deposit_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - native_amount: Optional[int] = None, - token_transfers: Optional[list[TokenTransfer]] = None, - ) -> Transaction: - tx = self._factory.create_transaction_for_deposit( - sender=owner.address, - contract=contract, - gas_limit=gas_limit, - native_token_amount=native_amount, - token_transfers=token_transfers, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_discard_action_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_discard_action( - sender=owner.address, - contract=contract, - action_id=action_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_discard_batch_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_ids: list[int], - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_discard_batch( - sender=owner.address, - contract=contract, - action_ids=action_ids, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_add_board_member_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - board_member: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_propose_add_board_member( - sender=owner.address, - contract=contract, - board_member=board_member, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_add_proposer_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - proposer: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_propose_add_proposer( - sender=owner.address, - contract=contract, - proposer=proposer, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_remove_user_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - user: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_propose_remove_user( - sender=owner.address, - contract=contract, - user=user, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_change_quorum_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - quorum: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_propose_change_quorum( - sender=owner.address, - contract=contract, - quorum=quorum, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transfer_execute_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - receiver: Address, - native_token_amount: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - should_prepare_args_for_factory: bool, - guardian_and_relayer_data: GuardianRelayerData, - opt_gas_limit: Optional[int] = None, - abi: Optional[Abi] = None, - function: Optional[str] = None, - arguments: Optional[list[Any]] = None, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args_for_factory: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_propose_transfer_execute( - sender=owner.address, - contract=contract, - receiver=receiver, - native_token_amount=native_token_amount, - gas_limit=gas_limit, - opt_gas_limit=opt_gas_limit, - abi=abi, - function=function, - arguments=args, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transfer_execute_esdt_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - receiver: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - should_prepare_args_for_factory: bool, - guardian_and_relayer_data: GuardianRelayerData, - token_transfers: list[TokenTransfer], - opt_gas_limit: Optional[int] = None, - abi: Optional[Abi] = None, - function: Optional[str] = None, - arguments: Optional[list[Any]] = None, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args_for_factory: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_propose_transfer_esdt_execute( - sender=owner.address, - contract=contract, - receiver=receiver, - token_transfers=token_transfers, - gas_limit=gas_limit, - opt_gas_limit=opt_gas_limit, - abi=abi, - function=function, - arguments=args, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_async_call_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - receiver: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - should_prepare_args_for_factory: bool, - guardian_and_relayer_data: GuardianRelayerData, - native_token_amount: int = 0, - token_transfers: Optional[list[TokenTransfer]] = None, - opt_gas_limit: Optional[int] = None, - abi: Optional[Abi] = None, - function: Optional[str] = None, - arguments: Optional[list[Any]] = None, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args_for_factory: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_propose_async_call( - sender=owner.address, - contract=contract, - receiver=receiver, - gas_limit=gas_limit, - native_token_amount=native_token_amount, - token_transfers=token_transfers, - opt_gas_limit=opt_gas_limit, - abi=abi, - function=function, - arguments=args, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_contract_deploy_from_source_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - contract_to_copy: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - upgradeable: bool, - readable: bool, - payable: bool, - payable_by_sc: bool, - should_prepare_args_for_factory: bool, - guardian_and_relayer_data: GuardianRelayerData, - native_token_amount: int = 0, - abi: Optional[Abi] = None, - arguments: Optional[list[Any]] = None, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args_for_factory: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_propose_contract_deploy_from_source( - sender=owner.address, - contract=contract, - gas_limit=gas_limit, - contract_to_copy=contract_to_copy, - is_upgradeable=upgradeable, - is_readable=readable, - is_payable=payable, - is_payable_by_sc=payable_by_sc, - native_token_amount=native_token_amount, - abi=abi, - arguments=args, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_contract_upgrade_from_source_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - contract_to_upgrade: Address, - contract_to_copy: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - upgradeable: bool, - readable: bool, - payable: bool, - payable_by_sc: bool, - should_prepare_args_for_factory: bool, - guardian_and_relayer_data: GuardianRelayerData, - native_token_amount: int = 0, - abi: Optional[Abi] = None, - arguments: Optional[list[Any]] = None, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args_for_factory: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_propose_contract_upgrade_from_source( - sender=owner.address, - contract=contract, - contract_to_upgrade=contract_to_upgrade, - contract_to_copy=contract_to_copy, - gas_limit=gas_limit, - is_upgradeable=upgradeable, - is_readable=readable, - is_payable=payable, - is_payable_by_sc=payable_by_sc, - native_token_amount=native_token_amount, - abi=abi, - arguments=args, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_sign_action_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_sign_action( - sender=owner.address, - contract=contract, - action_id=action_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_sign_batch_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - batch_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_sign_batch( - sender=owner.address, - contract=contract, - batch_id=batch_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_sign_and_perform_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_sign_and_perform( - sender=owner.address, - contract=contract, - action_id=action_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_sign_batch_and_perform_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - batch_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_sign_batch_and_perform( - sender=owner.address, - contract=contract, - batch_id=batch_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_unsign_action_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unsign_action( - sender=owner.address, - contract=contract, - action_id=action_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_unsign_batch_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - batch_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unsign_batch( - sender=owner.address, - contract=contract, - batch_id=batch_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_unsign_for_outdated_board_members_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - outdated_board_members: list[int], - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unsign_for_outdated_board_members( - sender=owner.address, - contract=contract, - action_id=action_id, - outdated_board_members=outdated_board_members, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_perform_action_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_perform_action( - sender=owner.address, - contract=contract, - action_id=action_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_perform_batch_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - batch_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_perform_batch( - sender=owner.address, - contract=contract, - batch_id=batch_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx diff --git a/multiversx_sdk_cli/signing_wrapper.py b/multiversx_sdk_cli/signing_wrapper.py new file mode 100644 index 00000000..b9f834ee --- /dev/null +++ b/multiversx_sdk_cli/signing_wrapper.py @@ -0,0 +1,69 @@ +from typing import Optional, Union + +from multiversx_sdk import Transaction, TransactionComputer + +from multiversx_sdk_cli.cosign_transaction import cosign_transaction +from multiversx_sdk_cli.errors import TransactionSigningError +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.interfaces import IAccount + + +class SigningWrapper: + def __init__(self): + pass + + def sign_transaction( + self, + transaction: Transaction, + sender: Optional[IAccount] = None, + guardian_and_relayer: GuardianRelayerData = GuardianRelayerData(), + ): + """Signs the transaction using the sender's account and, if required, additionally signs with the guardian's and relayer's accounts. Ensures the appropriate transaction options are set as needed.""" + guardian = guardian_and_relayer.guardian + relayer = guardian_and_relayer.relayer + guardian_service_url = guardian_and_relayer.guardian_service_url + guardian_2fa_code = guardian_and_relayer.guardian_2fa_code + + if sender: + try: + transaction.signature = sender.sign_transaction(transaction) + except Exception as e: + raise TransactionSigningError(f"Could not sign transaction: {str(e)}") + + self._sign_guarded_transaction_if_guardian( + transaction, + guardian, + guardian_service_url, + guardian_2fa_code, + ) + self._sign_relayed_transaction_if_relayer(transaction, relayer) + + def _set_options_for_guarded_transaction_if_needed(self, transaction: Transaction): + if transaction.guardian: + transaction_computer = TransactionComputer() + transaction_computer.apply_guardian(transaction, transaction.guardian) + + def _sign_guarded_transaction_if_guardian( + self, + transaction: Transaction, + guardian: Union[IAccount, None], + guardian_service_url: Union[str, None], + guardian_2fa_code: Union[str, None], + ) -> Transaction: + # If the guardian account is provided, we sign locally. Otherwise, we reach for the trusted cosign service. + if guardian: + try: + transaction.guardian_signature = guardian.sign_transaction(transaction) + except Exception as e: + raise TransactionSigningError(f"Could not sign transaction: {str(e)}") + elif transaction.guardian and guardian_service_url and guardian_2fa_code: + cosign_transaction(transaction, guardian_service_url, guardian_2fa_code) + + return transaction + + def _sign_relayed_transaction_if_relayer(self, transaction: Transaction, relayer: Union[IAccount, None]): + if relayer and transaction.relayer: + try: + transaction.relayer_signature = relayer.sign_transaction(transaction) + except Exception as e: + raise TransactionSigningError(f"Could not sign transaction: {str(e)}") diff --git a/multiversx_sdk_cli/tests/test_cli_staking_provider.py b/multiversx_sdk_cli/tests/test_cli_staking_provider.py index 5c3da677..b14756a6 100644 --- a/multiversx_sdk_cli/tests/test_cli_staking_provider.py +++ b/multiversx_sdk_cli/tests/test_cli_staking_provider.py @@ -6,6 +6,8 @@ parent = Path(__file__).parent alice = parent / "testdata" / "alice.pem" +guardian = parent / "testdata" / "testUser.pem" +relayer = parent / "testdata" / "testUser2.pem" first_bls_key = "f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d" second_bls_key = "1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d" @@ -41,12 +43,184 @@ def test_create_new_delegation_contract(capsys: Any): assert transaction["chainID"] == "T" assert transaction["gasLimit"] == 60126500 assert transaction["value"] == "1250000000000000000000" + assert transaction["options"] == 0 + assert transaction["version"] == 2 assert ( transaction["signature"] == "0a6d7249c671b1db00f1b8807770bb64eac51e2e2779e426f35439c6cb7b00dadd023392a061ba1b6ee35d235ac2c0ad87283413b1d5558d8526bc5712588702" ) +def test_create_new_delegation_contract_sign_by_hash(capsys: Any): + main( + [ + "staking-provider", + "create-new-delegation-contract", + "--pem", + str(alice), + "--nonce", + "7", + "--value", + "1250000000000000000000", + "--total-delegation-cap", + "10000000000000000000000", + "--service-fee", + "100", + "--chain", + "T", + "--options", + "1", + ] + ) + 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"] == 60126500 + assert transaction["value"] == "1250000000000000000000" + assert transaction["options"] == 1 + assert transaction["version"] == 2 + assert ( + transaction["signature"] + == "16cfcdeb6cd7e72b0c332793c0498448665427bb992efed17f873f4917bcd000857d0babb7799dcd97933a060b0e5e4b3edbf248db3f78e74f9b71710adbdf08" + ) + + +def test_create_new_delegation_contract_with_guardian_and_relayer(capsys: Any): + main( + [ + "staking-provider", + "create-new-delegation-contract", + "--pem", + str(alice), + "--nonce", + "7", + "--value", + "1250000000000000000000", + "--total-delegation-cap", + "10000000000000000000000", + "--service-fee", + "100", + "--chain", + "T", + "--guardian-pem", + str(guardian), + "--relayer-pem", + str(relayer), + ] + ) + 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"] == 60226500 + assert transaction["value"] == "1250000000000000000000" + assert transaction["options"] == 2 + assert transaction["version"] == 2 + assert transaction["guardian"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" + assert transaction["relayer"] == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" + assert ( + transaction["signature"] + == "2138154667f573451ecb7ca9bd280f12e8240d5a689886f69b9159be6c0207297a3216b8868e2bf1040f435b3bc8208ed7f124674a20976033787c4ee0ff7907" + ) + + +def test_create_new_delegation_contract_with_guardian_and_relayer_and_provided_version_and_options(capsys: Any): + main( + [ + "staking-provider", + "create-new-delegation-contract", + "--pem", + str(alice), + "--nonce", + "7", + "--value", + "1250000000000000000000", + "--total-delegation-cap", + "10000000000000000000000", + "--service-fee", + "100", + "--chain", + "T", + "--guardian-pem", + str(guardian), + "--relayer-pem", + str(relayer), + "--version", + "7", + "--options", + "77", + ] + ) + 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"] == 60226500 + assert transaction["value"] == "1250000000000000000000" + assert transaction["options"] == 77 + assert transaction["version"] == 7 + assert transaction["guardian"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" + assert transaction["relayer"] == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" + + +def test_create_new_delegation_contract_with_guardian_and_relayer_and_sign_by_hash(capsys: Any): + main( + [ + "staking-provider", + "create-new-delegation-contract", + "--pem", + str(alice), + "--nonce", + "7", + "--value", + "1250000000000000000000", + "--total-delegation-cap", + "10000000000000000000000", + "--service-fee", + "100", + "--chain", + "T", + "--guardian-pem", + str(guardian), + "--relayer-pem", + str(relayer), + "--options", + "1", + ] + ) + 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"] == 60226500 + assert transaction["value"] == "1250000000000000000000" + assert transaction["options"] == 1 + assert transaction["version"] == 2 + assert transaction["guardian"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" + assert transaction["relayer"] == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" + assert ( + transaction["signature"] + == "2eecebb89627b4f60431a515bc9bce12bc58a7c864654634556a9d03cec9f85bde667f60fb6a0a773faf4560343a447e38d0adea836c8cc421aaf07c11e39d03" + ) + + def test_create_new_delegation_contract_with_provided_gas_limit(capsys: Any): main( [ @@ -586,7 +760,7 @@ def test_create_delegation_contract_from_validator(capsys: Any): assert data == "makeNewContractFromValidatorData@@0ea1" assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6" - assert transaction["gasLimit"] == 510000000 + assert transaction["gasLimit"] == 51107000 def test_delegate(capsys: Any): diff --git a/multiversx_sdk_cli/tests/test_cli_token.py b/multiversx_sdk_cli/tests/test_cli_token.py new file mode 100644 index 00000000..05b8a916 --- /dev/null +++ b/multiversx_sdk_cli/tests/test_cli_token.py @@ -0,0 +1,1468 @@ +import base64 +import json +from pathlib import Path +from typing import Any + +from multiversx_sdk_cli.cli import main + +testdata = Path(__file__).parent / "testdata" +user = testdata / "testUser.pem" +user_address = "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" +grace = "erd1r69gk66fmedhhcg24g2c5kn2f2a5k4kvpr6jfw67dn2lyydd8cfswy6ede" +frank = "erd1kdl46yctawygtwg2k462307dmz2v55c605737dp3zkxh04sct7asqylhyv" + + +def test_issue_fungible(capsys: Any): + return_code = main( + [ + "token", + "issue-fungible", + "--token-name", + "FRANK", + "--token-ticker", + "FRANK", + "--initial-supply", + "100", + "--num-decimals", + "0", + "--cannot-upgrade", + "--cannot-add-special-roles", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365" + ) + + +def test_issue_semi_fungible(capsys: Any): + return_code = main( + [ + "token", + "issue-semi-fungible", + "--token-name", + "FRANK", + "--token-ticker", + "FRANK", + "--cannot-upgrade", + "--cannot-add-special-roles", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365" + ) + + +def test_issue_non_fungible(capsys: Any): + return_code = main( + [ + "token", + "issue-non-fungible", + "--token-name", + "FRANK", + "--token-ticker", + "FRANK", + "--cannot-upgrade", + "--cannot-add-special-roles", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365" + ) + + +def test_register_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "register-meta-esdt", + "--token-name", + "FRANK", + "--token-ticker", + "FRANK", + "--num-decimals", + "10", + "--cannot-upgrade", + "--cannot-add-special-roles", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365" + ) + + +def test_register_and_set_all_roles(capsys: Any): + return_code = main( + [ + "token", + "register-and-set-all-roles", + "--token-name", + "TEST", + "--token-ticker", + "TEST", + "--num-decimals", + "2", + "--token-type", + "FNG", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerAndSetAllRoles@54455354@54455354@464e47@02" + + +def test_set_special_role_nft(capsys: Any): + return_code = main( + [ + "token", + "set-special-role-nft", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-create", + "--nft-update-attributes", + "--nft-add-uri", + "--esdt-modify-creator", + "--nft-recreate", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249@45534454526f6c654d6f6469667943726561746f72@45534454526f6c654e46545265637265617465" + ) + + +def test_unset_special_role_nft(capsys: Any): + return_code = main( + [ + "token", + "unset-special-role-nft", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-update-attributes", + "--nft-add-uri", + "--esdt-modify-creator", + "--nft-recreate", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unSetSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249@45534454526f6c654d6f6469667943726561746f72@45534454526f6c654e46545265637265617465" + ) + + +def test_create_nft(capsys: Any): + return_code = main( + [ + "token", + "create-nft", + "--token-identifier", + "FRANK-aa9e8d", + "--initial-quantity", + "1", + "--name", + "test", + "--royalties", + "1000", + "--hash", + "abba", + "--attributes", + "74657374", + "--uris", + "a", + "b", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTCreate@4652414e4b2d616139653864@01@74657374@03e8@61626261@74657374@61@62" + + +def test_set_special_role_on_fungible_token(capsys: Any): + return_code = main( + [ + "token", + "set-special-role-fungible", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--local-mint", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654c6f63616c4d696e74" + ) + + +def test_unset_special_role_on_fungible_token(capsys: Any): + return_code = main( + [ + "token", + "unset-special-role-fungible", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--local-mint", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unSetSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654c6f63616c4d696e74" + ) + + +def test_set_all_roles_on_fungible_token(capsys: Any): + return_code = main( + [ + "token", + "set-special-role-fungible", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--local-mint", + "--local-burn", + "--esdt-transfer-role", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654c6f63616c4d696e74@45534454526f6c654c6f63616c4275726e@455344545472616e73666572526f6c65" + ) + + +def test_set_special_roles_on_semi_fungible(capsys: Any): + return_code = main( + [ + "token", + "set-special-role-semi-fungible", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-create", + "--nft-burn", + "--nft-add-quantity", + "--esdt-transfer-role", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e46544275726e@45534454526f6c654e46544164645175616e74697479@455344545472616e73666572526f6c65" + ) + + +def test_unset_special_roles_on_semi_fungible(capsys: Any): + return_code = main( + [ + "token", + "unset-special-role-semi-fungible", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-burn", + "--nft-add-quantity", + "--esdt-transfer-role", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unSetSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e46544275726e@45534454526f6c654e46544164645175616e74697479@455344545472616e73666572526f6c65" + ) + + +def test_set_special_roles_on_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "set-special-role-meta-esdt", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-create", + "--nft-burn", + "--nft-add-quantity", + "--esdt-transfer-role", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e46544275726e@45534454526f6c654e46544164645175616e74697479@455344545472616e73666572526f6c65" + ) + + +def test_unset_special_roles_on_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "unset-special-role-meta-esdt", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-burn", + "--nft-add-quantity", + "--esdt-transfer-role", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unSetSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e46544275726e@45534454526f6c654e46544164645175616e74697479@455344545472616e73666572526f6c65" + ) + + +def test_pause_token(capsys: Any): + return_code = main( + [ + "token", + "pause", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "pause@4652414e4b2d313163653365" + + +def test_unpause_token(capsys: Any): + return_code = main( + [ + "token", + "unpause", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "unPause@4652414e4b2d313163653365" + + +def test_freeze_token(capsys: Any): + return_code = main( + [ + "token", + "freeze", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "freeze@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" + + +def test_unfreeze_token(capsys: Any): + return_code = main( + [ + "token", + "unfreeze", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "unFreeze@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" + + +def test_local_mint(capsys: Any): + return_code = main( + [ + "token", + "local-mint", + "--token-identifier", + "FRANK-11ce3e", + "--supply-to-mint", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTLocalMint@4652414e4b2d313163653365@0a" + + +def test_local_burn(capsys: Any): + return_code = main( + [ + "token", + "local-burn", + "--token-identifier", + "FRANK-11ce3e", + "--supply-to-burn", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTLocalBurn@4652414e4b2d313163653365@0a" + + +def test_update_attributes(capsys: Any): + return_code = main( + [ + "token", + "update-attributes", + "--token-identifier", + "FRANK-11ce3e", + "--token-nonce", + "10", + "--attributes", + "74657374", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTUpdateAttributes@4652414e4b2d313163653365@0a@74657374" + + +def test_add_quantity(capsys: Any): + return_code = main( + [ + "token", + "add-quantity", + "--token-identifier", + "FRANK-11ce3e", + "--token-nonce", + "10", + "--quantity", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTAddQuantity@4652414e4b2d313163653365@0a@0a" + + +def test_burn_quantity(capsys: Any): + return_code = main( + [ + "token", + "burn-quantity", + "--token-identifier", + "FRANK-11ce3e", + "--token-nonce", + "10", + "--quantity", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTBurn@4652414e4b2d313163653365@0a@0a" + + +def test_set_burn_role_globally(capsys: Any): + return_code = main( + [ + "token", + "set-burn-role-globally", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "setBurnRoleGlobally@4652414e4b2d313163653365" + + +def test_unset_burn_role_globally(capsys: Any): + return_code = main( + [ + "token", + "unset-burn-role-globally", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "unsetBurnRoleGlobally@4652414e4b2d313163653365" + + +def test_wipe(capsys: Any): + return_code = main( + [ + "token", + "wipe", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "wipe@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" + + +def test_modify_royalties(capsys: Any): + return_code = main( + [ + "token", + "modify-royalties", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--royalties", + "1234", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTModifyRoyalties@544553542d313233343536@01@04d2" + + +def test_set_new_uris(capsys: Any): + return_code = main( + [ + "token", + "set-new-uris", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTSetNewURIs@544553542d313233343536@01@6669727374555249@7365636f6e64555249" + + +def test_modify_creator(capsys: Any): + return_code = main( + [ + "token", + "modify-creator", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTModifyCreator@544553542d313233343536@01" + + +def test_update_metadata(capsys: Any): + return_code = main( + [ + "token", + "update-metadata", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--token-name", + "Test", + "--royalties", + "1234", + "--hash", + "abba", + "--attributes", + "74657374", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "ESDTMetaDataUpdate@544553542d313233343536@01@54657374@04d2@61626261@74657374@6669727374555249@7365636f6e64555249" + ) + + +def test_recreate_metadata(capsys: Any): + return_code = main( + [ + "token", + "nft-metadata-recreate", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--token-name", + "Test", + "--royalties", + "1234", + "--hash", + "abba", + "--attributes", + "74657374", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "ESDTMetaDataRecreate@544553542d313233343536@01@54657374@04d2@61626261@74657374@6669727374555249@7365636f6e64555249" + ) + + +def test_change_token_to_dynamic(capsys: Any): + return_code = main( + [ + "token", + "change-to-dynamic", + "--token-identifier", + "TEST-123456", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "changeToDynamic@544553542d313233343536" + + +def test_update_token_id(capsys: Any): + return_code = main( + [ + "token", + "update-token-id", + "--token-identifier", + "TEST-123456", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "updateTokenID@544553542d313233343536" + + +def test_register_dynamic(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic", + "--token-name", + "Test", + "--token-ticker", + "TEST-123456", + "--token-type", + "SFT", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerDynamic@54657374@544553542d313233343536@534654" + + +def test_register_dynamic_and_set_all_roles(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic-and-set-all-roles", + "--token-name", + "Test", + "--token-ticker", + "TEST-123456", + "--token-type", + "SFT", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerAndSetAllRolesDynamic@54657374@544553542d313233343536@534654" + + +def test_register_dynamic_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic", + "--token-name", + "Test", + "--token-ticker", + "TEST-987654", + "--token-type", + "META", + "--denominator", + "18", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerDynamic@54657374@544553542d393837363534@4d455441@12" + + +def test_register_dynamic_and_set_all_roles_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic-and-set-all-roles", + "--token-name", + "Test", + "--token-ticker", + "TEST-987654", + "--token-type", + "META", + "--denominator", + "18", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerAndSetAllRolesDynamic@54657374@544553542d393837363534@4d455441@12" + + +def test_transfer_ownership(capsys: Any): + return_code = main( + [ + "token", + "transfer-ownership", + "--token-identifier", + "AND-1d56f2", + "--new-owner", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "transferOwnership@414e442d316435366632@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_freeze_single_nft(capsys: Any): + return_code = main( + [ + "token", + "freeze-single-nft", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "freezeSingleNFT@544553542d313233343536@01@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_unfreeze_single_nft(capsys: Any): + return_code = main( + [ + "token", + "unfreeze-single-nft", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unFreezeSingleNFT@544553542d313233343536@01@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_change_sft_to_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "change-sft-to-meta-esdt", + "--collection", + "SFT-123456", + "--decimals", + "6", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "changeSFTToMetaESDT@5346542d313233343536@06" + + +def test_transfer_nft_create_role(capsys: Any): + return_code = main( + [ + "token", + "transfer-nft-create-role", + "--token-identifier", + "SFT-123456", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "transferNFTCreateRole@5346542d313233343536@c0006edaaee4fd479f2f248b341eb11eaecaec4d7dee190619958332bba5200f@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_stop_nft_create(capsys: Any): + return_code = main( + [ + "token", + "stop-nft-creation", + "--token-identifier", + "SFT-123456", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "stopNFTCreate@5346542d313233343536" + + +def test_wipe_single_nft(capsys: Any): + return_code = main( + [ + "token", + "wipe-single-nft", + "--token-identifier", + "SFT-123456", + "--token-nonce", + "10", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data == "wipeSingleNFT@5346542d313233343536@0a@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_add_uris(capsys: Any): + return_code = main( + [ + "token", + "add-uris", + "--token-identifier", + "SFT-123456", + "--token-nonce", + "10", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTAddURI@5346542d313233343536@0a@6669727374555249@7365636f6e64555249" + + +def _read_stdout(capsys: Any) -> str: + stdout: str = capsys.readouterr().out.strip() + return stdout + + +def get_transaction(capsys: Any) -> dict[str, Any]: + out = _read_stdout(capsys) + output: dict[str, Any] = json.loads(out) + tx: dict[str, Any] = output["emittedTransaction"] + return tx diff --git a/multiversx_sdk_cli/tests/test_cli_transactions.py b/multiversx_sdk_cli/tests/test_cli_transactions.py index 128cf63a..fb522b58 100644 --- a/multiversx_sdk_cli/tests/test_cli_transactions.py +++ b/multiversx_sdk_cli/tests/test_cli_transactions.py @@ -463,6 +463,28 @@ def test_estimate_gas_with_multiplier(capsys: Any): assert tx_json["gasLimit"] == 75000 +def test_raise_error_when_data_and_transfers_provided(capsys: Any): + return_code = main( + [ + "tx", + "new", + "--pem", + str(testdata_path / "alice.pem"), + "--receiver", + "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + "--nonce", + "7", + "--chain", + "D", + "--data", + "hello", + "--token-transfers", + "TEST-123456", + ] + ) + assert return_code == 1 + + def _read_stdout(capsys: Any) -> str: stdout: str = capsys.readouterr().out.strip() return stdout diff --git a/multiversx_sdk_cli/tests/test_cli_validators_localnet.py b/multiversx_sdk_cli/tests/test_cli_validators_localnet.py index c54a2545..18758752 100644 --- a/multiversx_sdk_cli/tests/test_cli_validators_localnet.py +++ b/multiversx_sdk_cli/tests/test_cli_validators_localnet.py @@ -32,6 +32,8 @@ def test_stake(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -54,6 +56,8 @@ def test_stake(): "--proxy", "http://127.0.0.1:7950", "--nonce=0", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -75,6 +79,8 @@ def test_stake_top_up(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -95,6 +101,8 @@ def test_unstake(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -115,6 +123,8 @@ def test_unbond(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -137,6 +147,8 @@ def test_unjail(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -157,6 +169,8 @@ def test_change_reward_address(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -177,6 +191,8 @@ def test_unstake_nodes(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -197,6 +213,8 @@ def test_unstake_tokens(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -217,6 +235,8 @@ def test_unbond_nodes(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -237,6 +257,8 @@ def test_unbond_tokens(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -255,6 +277,8 @@ def test_clean_registration_data(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -275,6 +299,8 @@ def test_re_stake_unstaked_nodes(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 diff --git a/multiversx_sdk_cli/tests/test_contracts.py b/multiversx_sdk_cli/tests/test_contracts.py index d3397f99..21f8b59d 100644 --- a/multiversx_sdk_cli/tests/test_contracts.py +++ b/multiversx_sdk_cli/tests/test_contracts.py @@ -2,10 +2,9 @@ from pathlib import Path from Cryptodome.Hash import keccak -from multiversx_sdk import Account, Address, TransactionsFactoryConfig +from multiversx_sdk import Account, Address from multiversx_sdk_cli.contract_verification import _create_request_signature -from multiversx_sdk_cli.contracts import SmartContract logging.basicConfig(level=logging.INFO) @@ -27,26 +26,3 @@ def test_contract_verification_create_request_signature(): signature.hex() == "30111258cc42ea08e0c6a3e053cc7086a88d614b8b119a244904e9a19896c73295b2fe5c520a1cb07cfe20f687deef9f294a0a05071e85c78a70a448ea5f0605" ) - - -def test_prepare_args_for_factories(): - sc = SmartContract(TransactionsFactoryConfig("mock")) - args = [ - "0x5", - "123", - "false", - "true", - "str:test-string", - "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", - ] - - arguments = sc._convert_args_to_typed_values(args) - assert arguments[0].get_payload() == b"\x05" - assert arguments[1].get_payload() == 123 - assert arguments[2].get_payload() is False - assert arguments[3].get_payload() is True - assert arguments[4].get_payload() == "test-string" - assert ( - arguments[5].get_payload() - == Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th").get_public_key() - ) diff --git a/multiversx_sdk_cli/tests/test_shared.py b/multiversx_sdk_cli/tests/test_shared.py index 53c8b21d..8c21bac5 100644 --- a/multiversx_sdk_cli/tests/test_shared.py +++ b/multiversx_sdk_cli/tests/test_shared.py @@ -1,3 +1,6 @@ +from multiversx_sdk import Address + +from multiversx_sdk_cli.args_converter import convert_args_to_typed_values from multiversx_sdk_cli.cli_shared import prepare_token_transfers @@ -31,3 +34,25 @@ def test_prepare_token_tranfers(): assert transfers[3].token.identifier == "META-777777" assert transfers[3].token.nonce == 16 assert transfers[3].amount == 123456789 + + +def test_prepare_args_for_factories(): + args = [ + "0x5", + "123", + "false", + "true", + "str:test-string", + "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + ] + + arguments = convert_args_to_typed_values(args) + assert arguments[0].get_payload() == b"\x05" + assert arguments[1].get_payload() == 123 + assert arguments[2].get_payload() is False + assert arguments[3].get_payload() is True + assert arguments[4].get_payload() == "test-string" + assert ( + arguments[5].get_payload() + == Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th").get_public_key() + ) diff --git a/multiversx_sdk_cli/tests/test_transactions.py b/multiversx_sdk_cli/tests/test_transactions.py deleted file mode 100644 index 8a8c4e4c..00000000 --- a/multiversx_sdk_cli/tests/test_transactions.py +++ /dev/null @@ -1,256 +0,0 @@ -from pathlib import Path - -from multiversx_sdk import Account, Address - -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.transactions import TransactionsController - -testdata = Path(__file__).parent / "testdata" - - -class TestTransactionsController: - controller = TransactionsController("D") - alice = Account.new_from_pem(testdata / "alice.pem") - - def test_create_transaction_without_data_and_value(self): - guardian_relayer_data = GuardianRelayerData() - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=0, - gas_limit=50000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 0 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 50000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 0 - assert not transaction.data - assert not transaction.guardian - assert not transaction.relayer - assert not transaction.guardian_signature - assert not transaction.relayer_signature - assert ( - transaction.signature.hex() - == "ecf9e9f8d395741c0fbb61eaba74295448ba380dd00a228463e29a278d4e3c9219b2fa54133e32510837e03d7cc9f17738b99b701e148ce098b8340064a5f409" - ) - - def test_create_transfer_transaction(self): - guardian_relayer_data = GuardianRelayerData() - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=123456789, - gas_limit=50000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 123456789 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 50000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 0 - assert not transaction.data - assert not transaction.guardian - assert not transaction.relayer - assert not transaction.guardian_signature - assert not transaction.relayer_signature - assert ( - transaction.signature.hex() - == "fe0ff59c06c453eed882db562f98c0684a32763a79580a33e269af6edbebc150007118b298f34d17c54b90d55cee76ed1e5254832db8acb2c34ef12f14b8b40d" - ) - - def test_create_transaction_with_data(self): - guardian_relayer_data = GuardianRelayerData() - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=0, - gas_limit=50000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - data="testdata", - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 0 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 50000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 0 - assert transaction.data == b"testdata" - assert not transaction.guardian - assert not transaction.relayer - assert not transaction.guardian_signature - assert not transaction.relayer_signature - assert ( - transaction.signature.hex() - == "74bb3bd0c4e87ed64a01456f888236a74b5672cf194a33a2225d868f5f43d65e9149f3145b9431075828ff842f70b977b778895925f37037db979e71563c540c" - ) - - def test_create_guarded_transaction(self): - guardian_relayer_data = GuardianRelayerData( - guardian=Account.new_from_pem(testdata / "testUser2.pem"), - guardian_address=Address.new_from_bech32("erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4"), - ) - - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=0, - gas_limit=200000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - data="testdata", - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 0 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 200000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 2 - assert transaction.data == b"testdata" - assert not transaction.relayer - assert not transaction.relayer_signature - assert ( - transaction.guardian - and transaction.guardian.to_bech32() == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" - ) - assert ( - transaction.guardian_signature.hex() - == "c8b186f85c6e79e157aac48ec55d3f915abbc396e257d30aff193135485395c4b026e7921853366a16bcbbb8dbe5f6cf98a917a8ca11ccdc3f29f5a5a7d7af0c" - ) - assert ( - transaction.signature.hex() - == "8e9338de8f1d66bc6cd2f8e42cb62b5456d82ba66fdf9b8ace750ab3fa697f348084b41996b19d172b627b0b0a312ef76d29191d627b4d9959a3bf17409f780b" - ) - - def test_create_relayed_transaction(self): - guardian_relayer_data = GuardianRelayerData( - relayer=Account.new_from_pem(testdata / "testUser2.pem"), - relayer_address=Address.new_from_bech32("erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4"), - ) - - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=0, - gas_limit=200000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - data="testdata", - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 0 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 200000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 0 - assert transaction.data == b"testdata" - assert not transaction.guardian - assert not transaction.guardian_signature - assert ( - transaction.relayer - and transaction.relayer.to_bech32() == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" - ) - assert ( - transaction.relayer_signature.hex() - == "385fb15816d52118b97a20451c2b225a81ce9be130ad13987453cab36e858f79af0473effc845bef1537ad9f878001e6fcdfeefa36c46c5e8bb6aab83c9b2a0b" - ) - assert ( - transaction.signature.hex() - == "89c2de2939bdd4ed2bdaf8f859f9020b6f7510b3a7298daaebdef53ce1de588181e1c27f8933745927e610ebfe6c41a8875e2b052a48fa22464903f3821b830e" - ) - - def test_create_guarded_relayed_transaction(self): - guardian_relayer_data = GuardianRelayerData( - guardian=Account.new_from_pem(testdata / "testUser.pem"), - guardian_address=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - relayer=Account.new_from_pem(testdata / "testUser2.pem"), - relayer_address=Address.new_from_bech32("erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4"), - ) - - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=0, - gas_limit=200000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - data="testdata", - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 0 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 200000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 2 - assert transaction.data == b"testdata" - - assert ( - transaction.guardian - and transaction.guardian.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - ) - assert ( - transaction.guardian_signature.hex() - == "06bc457b510cae975e1cc6ab863ed765aadbd948ad23cbd204d66a2b92bee683922d308148af47e28d186bceba13474c79f16b26803c65c908f1d4a2e2ac6a0e" - ) - - assert ( - transaction.relayer - and transaction.relayer.to_bech32() == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" - ) - assert ( - transaction.relayer_signature.hex() - == "86e2460a6045ac3142c23f06c3b31fc132f38227faa25ffc8f7e9ce32c4542f6ed37d740d3c83c4454f2390befd223b968d4767c28991f574689b36faa978209" - ) - - assert ( - transaction.signature.hex() - == "b0bce606f2cfd52d6641f8e96aa29dcfd334af4707d88f81dba01dac67e72a99d7143dccadc8d120b387c4eaac84dc01865e57488a2162480a0f15acf50b6306" - ) diff --git a/multiversx_sdk_cli/transactions.py b/multiversx_sdk_cli/transactions.py index d5f9503f..327ffff4 100644 --- a/multiversx_sdk_cli/transactions.py +++ b/multiversx_sdk_cli/transactions.py @@ -2,22 +2,9 @@ import logging from typing import Optional, Protocol, TextIO, Union -from multiversx_sdk import ( - Address, - AwaitingOptions, - GasLimitEstimator, - TokenTransfer, - Transaction, - TransactionOnNetwork, - TransactionsFactoryConfig, - TransferTransactionsFactory, -) +from multiversx_sdk import AwaitingOptions, Transaction, TransactionOnNetwork from multiversx_sdk_cli import errors -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.constants import MIN_GAS_LIMIT -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount logger = logging.getLogger("transactions") @@ -30,75 +17,11 @@ class INetworkProvider(Protocol): def send_transaction(self, transaction: Transaction) -> bytes: ... - def get_transaction(self, transaction_hash: Union[bytes, str]) -> TransactionOnNetwork: - ... - def await_transaction_completed(self, transaction_hash: Union[bytes, str], options: Optional[AwaitingOptions] = None) -> TransactionOnNetwork: ... # fmt: on -class TransactionsController(BaseTransactionsController): - def __init__(self, chain_id: str, gas_limit_estimator: Optional[GasLimitEstimator] = None) -> None: - config = TransactionsFactoryConfig(chain_id) - self.chain_id = chain_id - self.factory = TransferTransactionsFactory(config, gas_limit_estimator) - - def create_transaction( - self, - sender: IAccount, - receiver: Address, - native_amount: int, - gas_limit: Union[int, None], - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - token_transfers: Optional[list[TokenTransfer]] = None, - data: Optional[str] = None, - ) -> Transaction: - # if no value, token transfers or data provided, create plain transaction - if not native_amount and not token_transfers and not data: - transaction = Transaction( - sender=sender.address, - receiver=receiver, - gas_limit=MIN_GAS_LIMIT, - chain_id=self.chain_id, - ) - else: - transaction = self.factory.create_transaction_for_transfer( - sender=sender.address, - receiver=receiver, - native_amount=native_amount, - token_transfers=token_transfers, - data=data.encode() if data else None, - ) - - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def send_and_wait_for_result(transaction: Transaction, proxy: INetworkProvider, timeout: int) -> TransactionOnNetwork: if not transaction.signature: raise errors.TransactionIsNotSigned() diff --git a/multiversx_sdk_cli/validators.py b/multiversx_sdk_cli/validators.py deleted file mode 100644 index 05eb9871..00000000 --- a/multiversx_sdk_cli/validators.py +++ /dev/null @@ -1,539 +0,0 @@ -from typing import Optional - -from multiversx_sdk import ( - Address, - GasLimitEstimator, - Transaction, - TransactionsFactoryConfig, - ValidatorPublicKey, - ValidatorsSigners, - ValidatorsTransactionsFactory, -) - -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - - -class ValidatorsController(BaseTransactionsController): - def __init__(self, chain_id: str, gas_limit_estimator: Optional[GasLimitEstimator] = None) -> None: - self.factory = ValidatorsTransactionsFactory( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_limit_estimator, - ) - - def create_transaction_for_staking( - self, - sender: IAccount, - validators: ValidatorsSigners, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - rewards_address: Optional[Address] = None, - ) -> Transaction: - transaction = self.factory.create_transaction_for_staking( - sender=sender.address, - validators_file=validators, - amount=native_amount, - rewards_address=rewards_address, - ) - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_topping_up( - self, - sender: IAccount, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_topping_up( - sender=sender.address, - amount=native_amount, - ) - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unstaking( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unstaking( - sender=sender.address, - public_keys=keys, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unjailing( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unjailing( - sender=sender.address, - public_keys=keys, - amount=native_amount, - ) - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unbonding( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unbonding( - sender=sender.address, - public_keys=keys, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_changing_rewards_address( - self, - sender: IAccount, - rewards_address: Address, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_changing_rewards_address( - sender=sender.address, - rewards_address=rewards_address, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_claiming( - self, - sender: IAccount, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_claiming( - sender=sender.address, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unstaking_nodes( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unstaking_nodes( - sender=sender.address, - public_keys=keys, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unstaking_tokens( - self, - sender: IAccount, - value: int, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unstaking_tokens( - sender=sender.address, - amount=value, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unbonding_nodes( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unbonding_nodes( - sender=sender.address, - public_keys=keys, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unbonding_tokens( - self, - sender: IAccount, - value: int, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unbonding_tokens( - sender=sender.address, - amount=value, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_cleaning_registered_data( - self, - sender: IAccount, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_cleaning_registered_data( - sender=sender.address, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_restaking_unstaked_nodes( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_restaking_unstaked_nodes( - sender=sender.address, - public_keys=keys, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction diff --git a/pyproject.toml b/pyproject.toml index f6e3ab7e..b62d8f27 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "multiversx-sdk-cli" -version = "11.1.1" +version = "11.2.0" authors = [ { name="MultiversX" }, ] @@ -25,7 +25,7 @@ dependencies = [ "ledgercomm[hid]", "rich==13.3.4", "argcomplete==3.2.2", - "multiversx-sdk[ledger]==2.0.1" + "multiversx-sdk[ledger]==2.2.0" ] [project.scripts] diff --git a/requirements.txt b/requirements.txt index 33c1b918..01f3c357 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,4 @@ ledgercomm[hid] rich==13.3.4 argcomplete==3.2.2 -multiversx-sdk[ledger]==2.0.1 +multiversx-sdk[ledger]==2.2.0