diff --git a/.github/workflows/postman-kdf-tests.yml b/.github/workflows/postman-kdf-tests.yml new file mode 100644 index 000000000..68de2235a --- /dev/null +++ b/.github/workflows/postman-kdf-tests.yml @@ -0,0 +1,252 @@ +name: KDF Postman API Tests + +on: + push: + branches: ["main", "dev"] + paths: + - 'postman/**' + - 'src/data/responses/**' + - '.github/workflows/postman-kdf-tests.yml' + - 'docker-compose.yml' + pull_request: + branches: ["main", "dev"] + paths: + - 'postman/**' + - 'src/data/responses/**' + - '.github/workflows/postman-kdf-tests.yml' + - 'docker-compose.yml' + workflow_dispatch: + inputs: + test_environment: + description: 'Test environment to run' + required: true + default: 'all' + type: choice + options: + - all + - native_hd + - native_iguana + kdf_branch: + description: 'KDF branch to test' + required: false + default: 'dev' + type: string + +jobs: + kdf-postman-tests: + runs-on: ubuntu-22.04 + + env: + DOCKER_BUILDKIT: 1 + COMPOSE_DOCKER_CLI_BUILD: 1 + KDF_BRANCH: ${{ github.event.inputs.kdf_branch || 'dev' }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub (if needed for base images) + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + continue-on-error: true + + - name: Create test reports directory + run: | + mkdir -p test-reports + chmod 777 test-reports + + - name: Display build information + run: | + echo "Building KDF from branch: ${{ env.KDF_BRANCH }}" + echo "Test environment: ${{ github.event.inputs.test_environment || 'all' }}" + + - name: Clone and prepare KDF source + run: | + # Clone KDF repository for building + echo "Cloning KDF from branch: ${{ env.KDF_BRANCH }}" + rm -rf tmp/kdf-build || true + git clone https://github.com/KomodoPlatform/komodo-defi-framework.git tmp/kdf-build + cd tmp/kdf-build + git checkout ${{ env.KDF_BRANCH }} + echo "KDF source prepared at $(pwd)" + + - name: Build response processor image + run: | + # Build response processor image + docker build -f utils/docker/Dockerfile.processor \ + -t response-processor:latest . + + - name: Start KDF instances and run tests + run: | + # Start services with docker compose (will build KDF containers from source) + echo "Building and starting KDF containers..." + docker compose up --build -d kdf-native-hd kdf-native-nonhd + + # Wait for services to be healthy (extended timeout for build + startup) + echo "Waiting for KDF instances to be ready..." + timeout 600 bash -c 'until docker compose ps | grep -E "(kdf-native-hd|kdf-native-nonhd)" | grep -q "healthy"; do sleep 15; echo "Still waiting..."; done' || { + echo "Services failed to become healthy within timeout" + echo "=== Container status ===" + docker compose ps + echo "=== KDF Native HD logs ===" + docker compose logs kdf-native-hd + echo "=== KDF Native NonHD logs ===" + docker compose logs kdf-native-nonhd + exit 1 + } + + - name: Run Postman tests for Native HD + if: ${{ github.event.inputs.test_environment == 'all' || github.event.inputs.test_environment == 'native_hd' || github.event.inputs.test_environment == '' }} + run: | + docker compose up --no-deps newman-native-hd + continue-on-error: true + + - name: Run Postman tests for Native Iguana + if: ${{ github.event.inputs.test_environment == 'all' || github.event.inputs.test_environment == 'native_iguana' || github.event.inputs.test_environment == '' }} + run: | + docker compose up --no-deps newman-native-nonhd + continue-on-error: true + + - name: Process test results + run: | + docker compose up --no-deps response-processor + continue-on-error: true + + - name: Collect logs and results + if: always() + run: | + # Create logs directory + mkdir -p logs + + # Collect container logs + docker compose logs kdf-native-hd > logs/kdf-native-hd.log 2>&1 || true + docker compose logs kdf-native-nonhd > logs/kdf-native-nonhd.log 2>&1 || true + docker compose logs newman-native-hd > logs/newman-native-hd.log 2>&1 || true + docker compose logs newman-native-nonhd > logs/newman-native-nonhd.log 2>&1 || true + docker compose logs response-processor > logs/response-processor.log 2>&1 || true + + # List generated files + echo "=== Generated test reports ===" + find test-reports -type f -ls || echo "No test reports found" + + echo "=== Generated response reports ===" + find postman/reports -type f -name "*.json" -ls || echo "No response reports found" + + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: kdf-postman-test-results-${{ github.run_number }} + path: | + test-reports/ + postman/reports/postman_test_results_*.json + postman/reports/test_summary_*.json + logs/ + retention-days: 30 + + - name: Upload Newman results as GitHub test results + uses: dorny/test-reporter@v1 + if: always() + with: + name: KDF API Tests + path: 'test-reports/**/results.xml' + reporter: java-junit + fail-on-error: false + + - name: Comment on PR with test results + if: github.event_name == 'pull_request' && always() + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs'); + const path = require('path'); + + // Look for test summary files + const summaryFiles = []; + const reportsDir = 'postman/reports'; + + if (fs.existsSync(reportsDir)) { + const files = fs.readdirSync(reportsDir); + summaryFiles.push(...files.filter(f => f.startsWith('test_summary_'))); + } + + let commentBody = '## ๐Ÿงช KDF API Test Results\n\n'; + + if (summaryFiles.length > 0) { + const latestSummary = summaryFiles.sort().pop(); + const summaryPath = path.join(reportsDir, latestSummary); + + try { + const summary = JSON.parse(fs.readFileSync(summaryPath, 'utf8')); + + commentBody += `**Test Run:** ${summary.generated_at}\n`; + commentBody += `**Environments Tested:** ${summary.environments_tested}\n`; + commentBody += `**Total Methods:** ${summary.total_methods}\n\n`; + + commentBody += '### Method Test Summary\n\n'; + commentBody += '| Method | Success | Errors |\n'; + commentBody += '|--------|---------|--------|\n'; + + for (const [method, stats] of Object.entries(summary.summary_by_method)) { + const successIcon = stats.success_count > 0 ? 'โœ…' : 'โŒ'; + const errorIcon = stats.error_count > 0 ? 'โš ๏ธ' : 'โœ…'; + commentBody += `| ${method} | ${successIcon} ${stats.success_count} | ${errorIcon} ${stats.error_count} |\n`; + } + + } catch (e) { + commentBody += `Error reading test summary: ${e.message}\n`; + } + } else { + commentBody += 'โš ๏ธ No test summary found. Check the workflow logs for details.\n'; + } + + commentBody += '\n๐Ÿ“Š Full test results are available in the workflow artifacts.\n'; + + // Post or update comment + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + const marker = ''; + const existing = comments.find(c => + c.user.login === 'github-actions[bot]' && + c.body.includes(marker) + ); + + const finalComment = marker + '\n' + commentBody; + + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body: finalComment + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: finalComment + }); + } + + - name: Cleanup + if: always() + run: | + docker compose down -v || true + # Clean up build context and images + rm -rf tmp/kdf-build || true + docker image rm response-processor:latest 2>/dev/null || true + docker image prune -f --filter "dangling=true" || true diff --git a/.gitignore b/.gitignore index 9596237a6..40915c224 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,6 @@ links-to-manually-check .env MM2.json utils/docker/kdf-config/coins +tmp/* +utils/py/tmp/coins_config_cache.json +postman/generated/**/*.json \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..a60d7abf7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,114 @@ +services: + # Native KDF with HD wallet support + kdf-native-hd: + build: + context: . + dockerfile: utils/docker/Dockerfile.kdf_native + args: + KDF_BRANCH: ${KDF_BRANCH:-dev} + KDF_BUILD_COMMIT: ${KDF_BUILD_COMMIT:-unknown} + container_name: kdf-native-hd + ports: + - "7783:8779" # External:Internal port mapping (8779 is configured in MM2.json) + volumes: + - ./utils/docker/kdf-config-kdf-native-hd/MM2.json:/kdf/MM2.json:ro + - ./utils/docker/kdf-config/coins:/kdf/coins:ro + - ./utils/docker/kdf-db-native-hd:/kdf/db + environment: + - RUST_LOG=info + networks: + - kdf-network + healthcheck: + test: ["CMD-SHELL", "curl --url 'http://127.0.0.1:8779' --data '{\"method\":\"version\"}' || exit 1"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 180s + + # Native KDF with non-HD wallet support + kdf-native-nonhd: + build: + context: . + dockerfile: utils/docker/Dockerfile.kdf_native + args: + KDF_BRANCH: ${KDF_BRANCH:-dev} + KDF_BUILD_COMMIT: ${KDF_BUILD_COMMIT:-unknown} + container_name: kdf-native-nonhd + ports: + - "7784:8778" # External:Internal port mapping (8778 is configured in MM2.json) + volumes: + - ./utils/docker/kdf-config-kdf-native-nonhd/MM2.json:/kdf/MM2.json:ro + - ./utils/docker/kdf-config/coins:/kdf/coins:ro + - ./utils/docker/kdf-db-native-nonhd:/kdf/db + environment: + - RUST_LOG=info + networks: + - kdf-network + healthcheck: + test: ["CMD-SHELL", "curl --url 'http://127.0.0.1:8778' --data '{\"method\":\"version\"}' || exit 1"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 180s + + # Newman test runner for Native HD + newman-native-hd: + image: postman/newman:latest + container_name: newman-native-hd + depends_on: + kdf-native-hd: + condition: service_healthy + volumes: + - ./postman/generated:/postman:ro + - ./test-reports:/var/newman:rw + networks: + - kdf-network + environment: + - KDF_BASE_URL=http://kdf-native-hd:8779 + - WALLET_TYPE=hd + - ENVIRONMENT=native_hd + command: [ + "run", "/postman/environments/kdf_native_hd_collection.json", + "--reporters", "cli,json,junit", + "--reporter-json-export", "/var/newman/results.json", + "--reporter-junit-export", "/var/newman/results.xml", + "--timeout", "60000", + "--delay-request", "1000", + "--bail", "folder" + ] + + # Newman test runner for Native Non-HD + newman-native-nonhd: + image: postman/newman:latest + container_name: newman-native-nonhd + depends_on: + kdf-native-nonhd: + condition: service_healthy + volumes: + - ./postman/generated:/postman:ro + - ./test-reports:/var/newman:rw + networks: + - kdf-network + environment: + - KDF_BASE_URL=http://kdf-native-nonhd:8778 + - WALLET_TYPE=iguana + - ENVIRONMENT=native_iguana + command: [ + "run", "/postman/environments/kdf_native_iguana_collection.json", + "--reporters", "cli,json,junit", + "--reporter-json-export", "/var/newman/results.json", + "--reporter-junit-export", "/var/newman/results.xml", + "--timeout", "60000", + "--delay-request", "1000", + "--bail", "folder" + ] + + +networks: + kdf-network: + driver: bridge + +volumes: + kdf-db-native-hd: + kdf-db-native-nonhd: + test-reports: diff --git a/filepathSlugs.json b/filepathSlugs.json index 5a06e332b..db9b75972 100644 --- a/filepathSlugs.json +++ b/filepathSlugs.json @@ -2651,10 +2651,7 @@ "coins-needed-for-kick-start", "arguments", "response", - "examples", - "command", - "response-btc-and-kmd-should-be-activated-asap-in-this-case", - "response-no-swaps-and-orders-waiting-to-be-started" + "examples" ], "src/pages/komodo-defi-framework/api/legacy/consolidate_utxos/index.mdx": [ "consolidate-utxos", @@ -2715,11 +2712,9 @@ ], "src/pages/komodo-defi-framework/api/legacy/get_enabled_coins/index.mdx": [ "get-enabled-coins", - "arguments", - "response", - "examples", - "command", - "response-2" + "request-parameters", + "response-parameters", + "examples" ], "src/pages/komodo-defi-framework/api/legacy/get_gossip_mesh/index.mdx": [ "get-gossip-mesh", @@ -2747,11 +2742,9 @@ ], "src/pages/komodo-defi-framework/api/legacy/get_my_peer_id/index.mdx": [ "get-my-peer-id", - "arguments", - "response", - "examples", - "command", - "response-success" + "request-parameters", + "response-parameters", + "examples" ], "src/pages/komodo-defi-framework/api/legacy/get_relay_mesh/index.mdx": [ "get-relay-mesh", @@ -2882,6 +2875,8 @@ "response-sync-in-progress-for-utxo-coins", "response-sync-in-progress-for-eth-erc-20-coins", "response-successful-result-in-case-of-eth-erc-20-coins", + "command-sia-protocol", + "error-responses", "error-coin-not-active", "error-coin-not-compatible", "error-coin-enabled-without-tx-history-true", @@ -2966,11 +2961,12 @@ ], "src/pages/komodo-defi-framework/api/legacy/send_raw_transaction/index.mdx": [ "send-raw-transaction", - "arguments", - "response", - "examples", - "command", - "response-success" + "send-raw-transaction-2", + "request-arguments", + "response-parameters", + "example", + "request", + "request-sia-protocol" ], "src/pages/komodo-defi-framework/api/legacy/set_required_confirmations/index.mdx": [ "set-required-confirmations", @@ -3059,19 +3055,13 @@ "validateaddress", "arguments", "response", - "examples", - "command", - "response-valid-address", - "response-invalid-cash-address", - "response-invalid-eth-address" + "examples" ], "src/pages/komodo-defi-framework/api/legacy/version/index.mdx": [ "version", - "arguments", - "response", - "examples", - "command", - "response-2" + "request-parameters", + "response-parameters", + "examples" ], "src/pages/komodo-defi-framework/api/legacy/withdraw/index.mdx": [ "withdraw", @@ -3103,9 +3093,8 @@ "response-parameters", "examples", "request-with-tx-history-cashaddress-format-and-automated-utxo-merging", - "response", "request-with-get-balances-set-to-false", - "response-2", + "response", "error-types", "platform-is-already-activated-error", "platform-config-is-not-found-error", @@ -3117,10 +3106,7 @@ ], "src/pages/komodo-defi-framework/api/v20/coin_activation/enable_erc20/index.mdx": [ "enable-erc20", - "response", - "error-platform-coin-is-not-yet-activated", - "error-token-already-activated", - "error-token-config-not-found-in-coins-file" + "error-types" ], "src/pages/komodo-defi-framework/api/v20/coin_activation/enable_eth_with_tokens/index.mdx": [ "enable-eth-with-tokens", @@ -3128,24 +3114,10 @@ "response-parameters", "examples", "request-including-optional-gas-station-parameters", - "response", "request-with-get-balances-set-to-false", - "response-2", "request-including-nft-initialization", - "response-3", "request-using-wallet-connect", - "response-4", - "error-responses", - "error-types", - "platform-is-already-activated-error", - "platform-config-is-not-found-error", - "coin-protocol-parse-error-error", - "unexpected-platform-protocol-error", - "token-config-is-not-found-error", - "token-protocol-parse-error-error", - "unexpected-token-protocol-error", - "invalid-request-error", - "transport-error" + "error-types" ], "src/pages/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_token/index.mdx": [ "enable-tendermint-token", @@ -3160,11 +3132,8 @@ "response-parameters", "examples", "request-with-get-balances-set-to-false", - "response", "request-with-token-activation-and-get-balances-as-true", - "response-2", "request-for-metamask-wallet-connect-activation", - "response-3", "error-types", "platform-config-is-not-found-error", "platform-is-already-activated-error", @@ -3183,7 +3152,6 @@ "response", "examples", "activation-in-trezor-mode", - "response-2", "task-enable-bch-status", "arguments-2", "command", @@ -3193,16 +3161,12 @@ "response-ready-error", "task-enable-bch-user-action", "arguments-3", - "response-3", + "response-2", "examples-2", "command-2", - "response-success", "task-enable-bch-cancel", "arguments-4", - "response-4", - "response-success-2", - "response-success-already-finished", - "response-error-no-such-task" + "response-3" ], "src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/index.mdx": [ "task-eth-evm-activation", @@ -3212,7 +3176,6 @@ "response-2", "examples", "activation-in-trezor-mode", - "response-3", "task-enable-eth-status", "arguments-2", "command", @@ -3221,16 +3184,12 @@ "response-ready-error", "task-enable-eth-user-action", "arguments-3", - "response-4", + "response-3", "examples-2", "command-2", - "response-success", "task-enable-eth-cancel", "arguments-4", - "response-5", - "response-success-2", - "response-success-already-finished", - "response-error-no-such-task" + "response-4" ], "src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_qtum/index.mdx": [ "task-qtum-activation", @@ -3239,23 +3198,45 @@ "response", "examples", "command", - "response-2", "task-enable-qtum-status", "arguments-2", "request", "task-enable-qtum-user-action", "arguments-3", - "response-3", + "response-2", "examples-2", "command-2", - "response-success", "error-cases", "task-enable-qtum-cancel", "arguments-4", - "response-4", + "response-3", "examples-3", - "command-3", - "response-success-2" + "command-3" + ], + "src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/cancel/index.mdx": [ + "task-enable-sia-cancel", + "arguments", + "response" + ], + "src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/index.mdx": [ + "task-sia-activation" + ], + "src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/init/index.mdx": [ + "task-enable-sia-init", + "arguments", + "response", + "examples" + ], + "src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/status/index.mdx": [ + "task-enable-sia-status", + "arguments", + "command", + "response-ready-successful" + ], + "src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/user_action/index.mdx": [ + "task-enable-sia-user-action", + "arguments", + "response" ], "src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/index.mdx": [ "task-tendermint-activation", @@ -3264,11 +3245,10 @@ "response", "examples", "activation-in-trezor-mode", - "response-2", "task-enable-tendermint-status", "arguments-2", "command", - "response-3", + "response-2", "response-in-progress", "error-types", "platform-config-is-not-found-error", @@ -3280,16 +3260,12 @@ "unexpected-token-protocol-error", "task-enable-tendermint-user-action", "arguments-3", - "response-4", + "response-3", "examples-2", "command-2", - "response-success", "task-enable-tendermint-cancel", "arguments-4", - "response-5", - "response-success-2", - "response-success-already-finished", - "response-error-no-such-task" + "response-4" ], "src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/index.mdx": [ "task-utxo-activation", @@ -3298,7 +3274,6 @@ "response", "examples", "activation-in-trezor-mode", - "response-2", "task-enable-utxo-status", "arguments-2", "command", @@ -3307,16 +3282,12 @@ "response-ready-error", "task-enable-utxo-user-action", "arguments-3", - "response-3", + "response-2", "examples-2", "command-2", - "response-success", "task-enable-utxo-cancel", "arguments-4", - "response-4", - "response-success-2", - "response-success-already-finished", - "response-error-no-such-task" + "response-3" ], "src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_z_coin/index.mdx": [ "task-z-coin-activation", @@ -3328,16 +3299,11 @@ "sync-from-block-2528700-with-custom-zcash-params-path-and-scan-params", "sync-from-sapling-activation-height-earliest", "using-websockets-to-sync-from-proof-of-keys-day-2023", - "response-2", "task-enable-z-coin-status", "arguments-2", - "response-3", + "response-2", "examples-2", "status-of-z-coin-activation", - "response-activating-coin-enabling-has-started", - "response-updating-blocks-cache", - "response-building-wallet-db", - "response-enabling-complete", "response-coin-creation-error-no-zcash-params", "response-error-no-such-task", "response-error-invalid-request", @@ -3345,14 +3311,12 @@ "response-error-no-such-task-2", "task-enable-z-coin-user-action", "arguments-3", - "response-4", - "response-success", + "response-3", "task-enable-z-coin-cancel", "arguments-4", - "response-5", + "response-4", "examples-3", "command", - "response-success-2", "response-success-already-finished", "response-error-no-such-task-3" ], @@ -3840,8 +3804,6 @@ "add-node-to-version-stat-2", "request-parameters", "response-parameters", - "examples", - "response-success", "error-types", "error-responses", "database-error-unique-constraint-peer-id", @@ -4109,6 +4071,17 @@ "error-responses", "not-running" ], + "src/pages/komodo-defi-framework/api/v20/wallet/consolidate_utxos/index.mdx": [ + "consolidate-utxos", + "consolidate-utxos-2", + "request-parameters", + "response-parameters", + "examples", + "error-types", + "error-response-coin-not-found", + "error-response-merge-error", + "error-response-missing-parameter" + ], "src/pages/komodo-defi-framework/api/v20/wallet/delete_wallet/index.mdx": [ "delete-wallet", "delete-wallet-2", @@ -4149,17 +4122,25 @@ "request", "response" ], + "src/pages/komodo-defi-framework/api/v20/wallet/fetch_utxos/index.mdx": [ + "fetch-utxos", + "fetch-utxos-2", + "request-parameters", + "response-parameters", + "examples", + "error-types", + "error-response-coin-not-found", + "error-response-missing-parameter" + ], "src/pages/komodo-defi-framework/api/v20/wallet/get_private_keys/index.mdx": [ "get-private-keys", - "arguments", - "response", - "hd-mode-response", - "iguana-mode-response", + "request-parameters", + "response-parameters", + "hd-mode", + "iguana-mode", "examples", "command-hd-mode", - "response-hd-mode", "command-iguana-mode", - "response-iguana-mode", "error-types", "response-error", "hd-range-too-large-negative-index", @@ -4381,11 +4362,10 @@ "examples", "request-doc", "response-success", - "request-eth", + "request-sia", "response-success-2", - "error-response-no-such-coin", - "error-invalid-hash", - "error-invalid-ec-signature", + "request-eth", + "response-success-3", "error-types" ], "src/pages/komodo-defi-framework/api/v20/wallet/tx/index.mdx": [ @@ -4403,7 +4383,8 @@ "request-bch-with-from-id", "response-5", "request-iris-with-limit-50", - "response-6" + "response-6", + "error-response" ], "src/pages/komodo-defi-framework/api/v20/wallet/tx/sign_raw_transaction/index.mdx": [ "sign-raw-transaction", @@ -4429,9 +4410,7 @@ "withdraw-btc-kmd-and-other-btc-based-forks", "response-kmd-success", "hd-withdraw-with-derivation-path", - "response-kmd-success-2", "hd-withdraw-with-account-id-chain-and-address-id", - "response-kmd-success-3", "withdraw-btc-kmd-and-other-btc-based-forks-fixed-fee", "response-success", "withdraw-btc-kmd-and-other-btc-based-forks-1-coin-per-kbyte-fee", @@ -4440,10 +4419,12 @@ "response-success-3", "eth-erc-20-and-other-eth-based-forks-with-gas-fee", "response-success-4", - "withdraw-maximum", + "withdraw-sia-protocol", "response-success-5", - "withdraw-qrc-20-coins", + "withdraw-maximum", "response-success-6", + "withdraw-qrc-20-coins", + "response-success-7", "withdraw-qrc-20-coins-with-gas-limit", "withdraw-with-broadcast-true", "withdraw-tendermint-coins-with-a-memo-and-custom-gas-fee", diff --git a/postman/generated/NOTES.md b/postman/generated/NOTES.md new file mode 100644 index 000000000..0b820d607 --- /dev/null +++ b/postman/generated/NOTES.md @@ -0,0 +1,260 @@ +# Adding new methods + +#### Add table data for requests, responses, or errors in `src/data/tables/v2` to populate tables in the documentation. + +The filename should match the existing folder structure in `src/pages/komodo-defi-framework` + +For example, for `src/pages/komodo-defi-framework/api/v20/utils` place table parameters descriptions in `src/data/tables/v2/utils.json`, as below: + +```json +{ + "AddNodeToVersionStatErrors": { + "data": [ + { + "parameter": "DatabaseError", + "type": "string", + "required": false, + "description": "Database constraint error occurred." + }, + { + "parameter": "PeerIdParseError", + "type": "string", + "required": false, + "description": "The provided peer ID format is invalid." + } + ] + }, + "AddNodeToVersionStatRequest": { + "data": [ + { + "parameter": "name", + "type": "string", + "required": true, + "description": "The name assigned to the node" + }, + { + "parameter": "address", + "type": "string", + "required": true, + "description": "The IP address of the node" + }, + { + "parameter": "peer_id", + "type": "string", + "required": true, + "description": "The node's unique Peer ID" + } + ] + }, + "AddNodeToVersionStatResponse": { + "data": [ + { + "parameter": "result", + "type": "string", + "required": true, + "description": "The outcome of the request." + } + ] + } +} +``` + + +#### Add request bodies in `src/data/requests/kdf` + +The filename should match the existing folder structure in `src/pages/komodo-defi-framework` + +For example, for `src/pages/komodo-defi-framework/api/v20/utils` place sample request bodies in `src/data/requests/kdf/v2/utils.json`, as below: + +```json + { + "AddNodeToVersionStat": { + "method": "add_node_to_version_stat", + "mmrpc": "2.0", + "params": { + "address": "168.119.236.241", + "name": "seed1", + "peer_id": "12D3KooWEsuiKcQaBaKEzuMtT6uFjs89P1E8MK3wGRZbeuCbCw6P" + }, + "userpass": "RPC_UserP@SSW0RD" + } + } +``` + +Each object in the json file should have a unique name, with a common prefix for variations of the same method. + + +#### Add methods to the kdf_methods_v2.json or kdf_methods_legacy.json files + +This file links the method name to the request examples and parameters table data. +It also includes optional metadata fields to indicate environment and wallet type requirements, prerequisite methods, and response timeout. +The `tags` field is used to categorize the method for reference. + +```json +{ + "enable_eth_with_tokens": { + "examples": { + "EnableEthWithTokensGasStation": "Enable Eth With Tokens Gas Station", + "EnableEthWithTokensMaticBalancesFalse": "Enable Eth With Tokens Matic Balances False", + "EnableEthWithTokensMaticNft": "Enable Eth With Tokens Matic Nft", + "EnableEthWithTokensWalletConnect": "Enable Eth With Tokens Wallet Connect" + }, + "prerequisites": [], + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "table": "EnableEthWithTokensArguments", + "tags": [ + "v2" + ], + "timeout": 300 + } +} +``` + + +## Reporting + +#### Missing methods + +If a method is missing from the `kdf_methods_v2.json`/`kdf_methods_legacy.json` files, it will be reported as missing in split files: +`postman/generated/reports/missing_methods_v2.json` and `postman/generated/reports/missing_methods_legacy.json`. + +#### Missing requests + +Any request key detected in the param tables or responses json files, but not seen in the request json files, will be reported as missing in +`postman/generated/reports/missing_requests_v2.json` and `postman/generated/reports/missing_requests_legacy.json`. + +```json +{ + "v2": [ + "LegacyElectrumBch", + "LegacyElectrumKmd", + "LegacyElectrumQtum", + "LegacyEnableBnb", + "LegacyEnableMatic", + "TaskEnableZCoinStatusBasic" + ] +} +``` + +#### Missing responses + +Any response key detected in the param table or request json files, but not seen in the responses json files, will be reported as missing in +`postman/generated/reports/missing_responses_v2.json` and `postman/generated/reports/missing_responses_legacy.json` as a simple list for each method. + +```json +{ + "add_node_to_version_stat": [ + "AddNodeToVersionStat" + ], + "enable_eth_with_tokens": [ + "EnableEthWithTokensMaticNft" + ] +} +``` + +#### Missing tables + +Any method detected in the `kdf_methods_v2.json`/`kdf_methods_legacy.json` files, but not seen in the param tables json files, will be reported as missing in +`postman/generated/reports/missing_tables_v2.json` and `postman/generated/reports/missing_tables_legacy.json` as a simple list. + +```json +[ + "add_node_to_version_stat" +] +``` + +#### Untranslated keys + +In `kdf_methods_v2.json`/`kdf_methods_legacy.json`, every request key is given a human-readable name in the `examples` field. +If a request key is missing from the `examples` field, it will be reported as untranslated in `postman/generated/reports/untranslated_keys.json` as a simple list. + +```json + "task::enable_z_coin::init": { + "examples": { + "TaskEnableZCoinInit": "Initialize Z-coin", + "TaskEnableZCoinInitBasic": "Initialize Z-coin with basic params", + "TaskEnableZCoinInitWithSyncParams": "Initialize Z-coin with sync params" + } + ... + } +``` + +#### KDF response delays + +In `postman/generated/reports/kdf_response_delays.json`, we track the response `delay` and `status code` for each method and request key across different environments. This is useful for identifying performance characteristics and optimization opportunities, or to compare performance between different environments. + +```json + "enable_tendermint_with_assets": { + "EnableTendermintWithAssetsBalancesFalse": { + "native-hd": { + "delay": 0.753, + "status_code": 200 + }, + "native-nonhd": { + "delay": 0.752, + "status_code": 200 + } + }, + "EnableTendermintWithAssetsBalancesTrue": { + "native-hd": { + "delay": 2.25, + "status_code": 200 + }, + "native-nonhd": { + "delay": 2.262, + "status_code": 200 + } + } + } +``` + + +#### Inconsistent responses + +In `postman/generated/reports/inconsistent_responses.json` the responses from each environment is compared to the native-hd response to detect structural differences or success/failure patterns. This helps identify where more than one response structure needs to be documented, or highlight methods which have compatibility limited to a subset of environments or wallet types. + +```json +"enable_eth_with_tokens": { + "EnableEthWithTokensGasStation": { + "instances": { + "native-hd": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 23367217, + "nfts_infos": {}, + "ticker": "ETH", + "wallet_balance": { + "accounts": [ + ... + ], + "wallet_type": "HD" + } + } + }, + "native-nonhd": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 23367228, + "erc20_addresses_infos": { + ... + } + }, + "eth_addresses_infos": { + ... + }, + "nfts_infos": {} + } + } + } +} +``` \ No newline at end of file diff --git a/postman/generated/README.md b/postman/generated/README.md new file mode 100644 index 000000000..a95312a75 --- /dev/null +++ b/postman/generated/README.md @@ -0,0 +1,98 @@ +# Komodo DeFi Framework (KDF) Postman Collection + +This directory contains the automatically generated Postman collection for the Komodo DeFi Framework API. + +## Files + +### `kdf_postman_collection.json` +The main Postman collection file containing all API requests organized by version and method groups. + +**Features:** +- โœ… Organized folder structure matching the KDF directory hierarchy +- โœ… Automatic userpass variable substitution (`{{ userpass }}`) +- โœ… Task ID variable management for method groups +- โœ… Pre-request and test scripts for task ID capture +- โœ… Proper request formatting with headers and JSON bodies +- โœ… Translated request names using kdf_methods_v2.json / kdf_methods_legacy.json +- โœ… Multiple examples per method (variants) in response section +- โœ… Parameter documentation tables from @tables/ files + +**Collection Structure:** +``` +โ”œโ”€โ”€ legacy/ +โ”‚ โ””โ”€โ”€ coin_activation/ +โ”‚ โ””โ”€โ”€ enable/ +โ”‚ โ””โ”€โ”€ Enable Matic Token (Legacy) +โ””โ”€โ”€ v2/ + โ””โ”€โ”€ coin_activation/ + โ””โ”€โ”€ task/ + โ””โ”€โ”€ enable_utxo/ + โ”œโ”€โ”€ init/ โ†’ Initialize UTXO Coin + โ”œโ”€โ”€ status/ โ†’ Check UTXO Task Status + โ”œโ”€โ”€ user_action/ โ†’ task::enable_utxo::user_action (with examples) + โ””โ”€โ”€ cancel/ โ†’ Cancel UTXO Task +``` + +**Collection Variables:** +- `base_url`: Default KDF API endpoint (http://127.0.0.1:7783) +- `userpass`: RPC authentication password +- `TaskEnableUtxo_TaskId`: Automatically captured from init responses + +## Usage Instructions + +### Importing to Postman + +1. Open Postman +2. Click "Import" +3. Select `kdf_postman_collection.json` +4. The collection will be imported with all requests and variables + +### Configuration + +Before using the collection, configure these variables: + +1. **base_url**: Update if your KDF instance runs on a different host/port +2. **userpass**: Set your actual RPC password +3. **Task ID variables**: These are automatically populated by init requests + +### Request Flow + +For task-based methods (like TaskEnableUtxo): + +1. **Run Init request first**: This captures the `task_id` in a collection variable +2. **Use Status/UserAction/Cancel**: These will automatically use the captured `task_id` + +### Example Workflow + +1. Run `Initialize UTXO Coin` - captures task_id automatically +2. Run `Check UTXO Task Status` - uses the captured task_id +3. If needed, run `task::enable_utxo::user_action` with PIN or Passphrase (see examples) +4. Finally run `Cancel UTXO Task` to cancel the task + +### Multiple Examples Per Method + +Methods with multiple variants show all examples in the response section: +- Main request uses method name for multi-example methods +- Additional variants appear as response examples +- Perfect for documenting different parameter combinations + +### Parameter Documentation + +Each request includes a formatted table showing all available parameters: +- Parameter name, type (with required/default info), and descriptions +- Generated from table definitions in `src/data/tables/` + +## Reports + +Validation reports are available in the `../reports/` directory: + +- `unused_params.json` - Parameters in tables but not used in examples +- `untranslated_keys.json` - Request keys without translations +- `missing_responses_v2.json` / `missing_responses_legacy.json` - Request keys without corresponding responses (split by version) +- `missing_tables_v2.json` / `missing_tables_legacy.json` - Methods without table documentation (split by version) +- `missing_requests_v2.json` / `missing_requests_legacy.json` - Responses without matching requests (split by version) +- `missing_methods_v2.json` / `missing_methods_legacy.json` - Requests whose methods are missing in config (split by version) + +--- + +Generated by the KDF Postman Collection Generator. \ No newline at end of file diff --git a/src/data/kdf_methods_legacy.json b/src/data/kdf_methods_legacy.json new file mode 100644 index 000000000..d805b2023 --- /dev/null +++ b/src/data/kdf_methods_legacy.json @@ -0,0 +1,283 @@ +{ + "coins_needed_for_kick_start": { + "errors_table": "CoinsNeededForKickStartErrors", + "examples": { + "CoinsNeededForKickStart": "Coins needed for kick start" + }, + "prerequisites": [], + "request_table": "NoParams", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "CoinsNeededForKickStartResponse", + "sequence": 260, + "tags": [ + "legacy" + ] + }, + "electrum": { + "errors_table": "ElectrumErrors", + "examples": { + "LegacyElectrumBch": "Electrum Bch", + "LegacyElectrumDoc": "Electrum Doc", + "LegacyElectrumKmd": "Electrum Kmd", + "LegacyElectrumMarty": "Electrum Marty", + "LegacyElectrumQtum": "Electrum Qtum" + }, + "prerequisites": [], + "request_table": "ElectrumArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "ElectrumResponse", + "sequence": 25, + "tags": [ + "legacy" + ] + }, + "enable": { + "errors_table": "EnableErrors", + "examples": { + "LegacyEnableBnb": "Enable BNB Token (Legacy)", + "LegacyEnableEth": "Enable Ethereum Token (Legacy)", + "LegacyEnableEthGasStation": "Enable Ethereum Token (Legacy) with Gas Station", + "LegacyEnableMatic": "Enable Matic Token (Legacy)", + "LegacyEnableNative": "Enable UTXO coin with local blockchain data", + "LegacyEnableNativeWithParams": "Enable UTXO coin with local blockchain data with basic parameters" + }, + "prerequisites": [], + "request_table": "EnableArguments", + "requirements": { + "conditional_params": { + "hd_only": [ + "gap_limit", + "min_addresses_number", + "path_to_address", + "scan_policy" + ], + "non_hd_only": [] + }, + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "EnableResponse", + "sequence": 25, + "tags": [ + "legacy" + ] + }, + "get_enabled_coins": { + "errors_table": "N/A", + "examples": { + "LegacyGetEnabledCoins": "Get Enabled Coins" + }, + "prerequisites": [], + "request_table": "NoParams", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "GetEnabledCoinsResponse", + "sequence": 210, + "tags": [ + "legacy" + ] + }, + "get_my_peer_id": { + "errors_table": "GetMyPeerIdErrors", + "examples": { + "LegacyGetMyPeerId": "Get My Peer ID" + }, + "prerequisites": [], + "request_table": "NoParams", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "GetMyPeerIdResponse", + "sequence": 205, + "tags": [ + "legacy" + ] + }, + "my_balance": { + "errors_table": "MyBalanceErrors", + "examples": { + "MyBalance": "Get current Sia balance" + }, + "prerequisites": [], + "request_table": "MyBalanceRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "MyBalanceResponse", + "sequence": 200, + "tags": [ + "legacy" + ] + }, + "my_tx_history": { + "errors_table": "MyTxHistoryErrors", + "examples": { + "MyTxHistoryDoc": "Tx history (DOC)", + "MyTxHistoryDocMax": "My Tx History Doc Max", + "MyTxHistoryErrors": "My Tx History Errors", + "MyTxHistoryEthSuccess": "My Tx History Eth Success", + "MyTxHistorySia": "Tx history (SIA)", + "MyTxHistorySyncEthInProgress": "My Tx History Sync Eth In Progress", + "MyTxHistorySyncUtxoInProgress": "My Tx History Sync Utxo In Progress" + }, + "prerequisites": [], + "request_table": "MyTxHistoryRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "MyTxHistoryResponse", + "sequence": 230, + "tags": [ + "legacy" + ] + }, + "send_raw_transaction": { + "errors_table": "SendRawTransactionErrors", + "examples": { + "SendRawTransaction": "Broadcast Sia transaction", + "SendRawTransactionKmd": "Send Raw Transaction Kmd", + "SendRawTransactionSiaFull": "Send Raw Transaction Sia Full" + }, + "prerequisites": [], + "request_table": "SendRawTransactionRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "SendRawTransactionResponse", + "sequence": 240, + "tags": [ + "legacy" + ] + }, + "validateaddress": { + "errors_table": "ValidateAddressErrors", + "examples": { + "ValidateAddress": "Validate Sia address" + }, + "prerequisites": [], + "request_table": "ValidateAddressRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "ValidateAddressResponse", + "sequence": 250, + "tags": [ + "legacy" + ] + }, + "version": { + "errors_table": "VersionErrors", + "examples": { + "LegacyVersion": "Version" + }, + "prerequisites": [], + "request_table": "NoParams", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "VersionResponse", + "sequence": 25, + "tags": [ + "legacy" + ] + }, + "withdraw": { + "errors_table": "WithdrawLegacyErrors", + "examples": { + "WithdrawLegacyDocFixedFee": "Withdraw Doc Fixed Fee", + "WithdrawLegacyDocPerKbyte": "Withdraw Doc Per Kbyte", + "WithdrawLegacyEth": "Withdraw Eth", + "WithdrawLegacyEthGas": "Withdraw Eth Gas", + "WithdrawLegacyEthMax": "Withdraw Eth Max", + "WithdrawLegacyKmd": "Withdraw Kmd", + "WithdrawLegacyQrc20": "Withdraw Qrc20", + "WithdrawLegacyQrc20Gas": "Withdraw Qrc20 Gas", + "WithdrawLegacySia": "Withdraw Sia" + }, + "prerequisites": [], + "request_table": "WithdrawLegacyRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "WithdrawLegacyResponse", + "sequence": 220, + "tags": [ + "legacy" + ] + } +} \ No newline at end of file diff --git a/src/data/kdf_methods_v2.json b/src/data/kdf_methods_v2.json new file mode 100644 index 000000000..165dee6e6 --- /dev/null +++ b/src/data/kdf_methods_v2.json @@ -0,0 +1,1199 @@ +{ + "add_node_to_version_stat": { + "errors_table": "AddNodeToVersionStatErrors", + "examples": { + "AddNodeToVersionStat": "Add Node To Version Stat" + }, + "prerequisites": [], + "request_table": "AddNodeToVersionStatRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "AddNodeToVersionStatResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "consolidate_utxos": { + "errors_table": "ConsolidateUtxosErrors", + "examples": { + "ConsolidateUtxos": "Consolidate Utxos" + }, + "prerequisites": [], + "request_table": "ConsolidateUtxosRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "ConsolidateUtxosResponse", + "sequence": 200, + "tags": [ + "v2" + ] + }, + "enable_bch_with_tokens": { + "deprecated": true, + "errors_table": "", + "examples": { + "EnableBchWithTokensBalancesFalse": "Enable Bch With Tokens Balances False", + "EnableBchWithTokensTxHistory": "Enable Bch With Tokens Tx History" + }, + "prerequisites": [], + "request_table": "EnableBchWithTokensArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "", + "sequence": 25, + "tags": [ + "deprecated", + "v2" + ] + }, + "enable_erc20": { + "errors_table": "EnableErc20ErrorTypes", + "examples": { + "EnableErc20Basic": "Enable Erc20 Basic" + }, + "prerequisites": [], + "request_table": "EnableErc20Arguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "EnableErc20Response", + "sequence": 25, + "tags": [ + "v2" + ] + }, + "enable_eth_with_tokens": { + "errors_table": "EnableEthWithTokensErrorTypes", + "examples": { + "EnableEthWithTokensGasStation": "Enable Eth With Tokens Gas Station", + "EnableEthWithTokensMaticBalancesFalse": "Enable Eth With Tokens Matic Balances False", + "EnableEthWithTokensMaticNft": "Enable Eth With Tokens Matic Nft", + "EnableEthWithTokensWalletConnect": "Enable Eth With Tokens Wallet Connect" + }, + "prerequisites": [], + "request_table": "EnableEthWithTokensArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "EnableEthWithTokensResponse", + "sequence": 25, + "tags": [ + "v2" + ], + "timeout": 300 + }, + "enable_sia": { + "errors_table": "EnableSiaErrors", + "examples": { + "EnableSia": "Enable Sia (returns task_id)" + }, + "prerequisites": [], + "request_table": "EnableSiaRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "EnableSiaResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "enable_sia::cancel": { + "errors_table": "EnableSiaCancelErrors", + "examples": {}, + "prerequisites": [], + "request_table": "EnableSiaCancelRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "EnableSiaCancelResponse", + "sequence": 104, + "tags": [ + "v2" + ] + }, + "enable_sia::init": { + "errors_table": "EnableSiaInitErrors", + "examples": { + "EnableSiaInit": "Enable Sia (task::init)" + }, + "prerequisites": [], + "request_table": "EnableSiaInitRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "EnableSiaInitResponse", + "sequence": 101, + "tags": [ + "v2" + ] + }, + "enable_sia::status": { + "errors_table": "EnableSiaStatusErrors", + "examples": { + "EnableSiaStatus": "Enable Sia (task::status)" + }, + "prerequisites": [], + "request_table": "EnableSiaStatusRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "EnableSiaStatusResponse", + "sequence": 102, + "tags": [ + "v2" + ] + }, + "enable_sia::user_action": { + "errors_table": "EnableSiaUserActionErrors", + "examples": {}, + "prerequisites": [], + "request_table": "EnableSiaUserActionRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "EnableSiaUserActionResponse", + "sequence": 103, + "tags": [ + "v2" + ] + }, + "enable_tendermint_token": { + "errors_table": "EnableTendermintTokenErrors", + "examples": { + "EnableTendermintTokenBasic": "Enable Tendermint Token Basic" + }, + "prerequisites": [], + "request_table": "EnableTendermintTokenArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "prerequisite_methods": [ + "enable_tendermint_with_assets" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "EnableTendermintWithAssetsResponse", + "sequence": 25, + "tags": [ + "v2" + ] + }, + "enable_tendermint_with_assets": { + "errors_table": "EnableTendermintWithAssetsErrors", + "examples": { + "EnableTendermintWithAssetsBalancesFalse": "Enable Tendermint With Assets Balances False", + "EnableTendermintWithAssetsBalancesTrue": "Enable Tendermint With Assets Balances True", + "EnableTendermintWithAssetsWalletConnect": "Enable Tendermint With Assets Wallet Connect" + }, + "prerequisites": [], + "request_table": "EnableTendermintWithAssetsArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "EnableTendermintWithAssetsResponse", + "sequence": 25, + "tags": [ + "v2" + ] + }, + "fetch_utxos": { + "errors_table": "FetchUtxosErrors", + "examples": { + "FetchUtxos": "Fetch Utxos" + }, + "prerequisites": [], + "request_table": "FetchUtxosRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "FetchUtxosResponse", + "sequence": 50, + "tags": [ + "v2" + ] + }, + "get_my_address": { + "errors_table": "GetMyAddressErrors", + "examples": { + "GetMyAddress": "Get Sia address" + }, + "prerequisites": [], + "request_table": "GetMyAddressRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "GetMyAddressResponse", + "sequence": 210, + "tags": [ + "v2" + ] + }, + "get_private_keys": { + "errors_table": "GetPrivateKeysErrors", + "examples": { + "GetPrivateKeysHd": "Export HD Private Keys", + "GetPrivateKeysIguana": "Export Iguana Private Keys" + }, + "prerequisites": [], + "request_table": "GetPrivateKeysRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "GetPrivateKeysHdResponse", + "sequence": 60, + "tags": [ + "v2" + ] + }, + "get_raw_transaction": { + "errors_table": "GetRawTransactionErrors", + "examples": { + "GetRawTransactionSia": "Get raw Sia transaction" + }, + "prerequisites": [], + "request_table": "GetRawTransactionRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "GetRawTransactionResponse", + "sequence": 230, + "tags": [ + "v2" + ] + }, + "my_tx_history": { + "errors_table": "MyTxHistoryV2Errors", + "examples": { + "MyTxHistoryAccountDoc": "Tx history (by account - DOC)", + "MyTxHistoryAddressDoc": "Tx history (by address - DOC)", + "MyTxHistoryBchFromId": "Tx history (BCH - from_id)", + "MyTxHistoryBchPage2": "Tx history (BCH - page 2)", + "MyTxHistoryIrisLimit50": "Tx history (IRIS - limit 50)", + "MyTxHistorySiaUnsupported": "Tx history (SIA - unsupported)" + }, + "prerequisites": [], + "request_table": "MyTxHistoryV2Request", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "MyTxHistoryV2Response", + "sequence": 230, + "tags": [ + "v2" + ] + }, + "send_raw_transaction": { + "errors_table": "SendRawTransactionErrors", + "examples": { + "SendRawTransaction": "Broadcast Sia transaction", + "SendRawTransactionKmd": "Broadcast KMD transaction", + "SendRawTransactionSiaFull": "Broadcast full Sia JSON transaction" + }, + "prerequisites": [], + "request_table": "SendRawTransactionRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "SendRawTransactionResponse", + "sequence": 240, + "tags": [ + "v2" + ] + }, + "validateaddress": { + "errors_table": "ValidateAddressErrors", + "examples": { + "ValidateAddress": "Validate Sia address" + }, + "prerequisites": [], + "request_table": "ValidateAddressRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "ValidateAddressResponse", + "sequence": 250, + "tags": [ + "v2" + ] + }, + "task::enable_bch::cancel": { + "deprecated": true, + "errors_table": "", + "examples": { + "TaskEnableBchCancel": "Cancel Bitcoin Cash Activation Task" + }, + "prerequisites": [], + "request_table": "TaskCancelArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "", + "sequence": 110, + "tags": [ + "deprecated", + "v2" + ] + }, + "task::enable_bch::init": { + "deprecated": true, + "errors_table": "", + "examples": { + "TaskEnableBchInit": "Initialize Bitcoin Cash" + }, + "prerequisites": [], + "request_table": "TaskEnableBchArguments", + "requirements": { + "conditional_params": { + "hd_only": [ + "gap_limit", + "min_addresses_number", + "path_to_address", + "scan_policy" + ], + "non_hd_only": [] + }, + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "", + "sequence": 25, + "tags": [ + "deprecated", + "v2" + ] + }, + "task::enable_bch::status": { + "deprecated": true, + "errors_table": "", + "examples": { + "TaskEnableBchStatus": "Check Bitcoin Cash Activation Task Status" + }, + "prerequisites": [], + "request_table": "TaskStatusArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "", + "sequence": 100, + "tags": [ + "deprecated", + "v2" + ] + }, + "task::enable_bch::user_action": { + "deprecated": true, + "errors_table": "", + "examples": { + "TaskEnableBchUserActionPin": "Provide Trezor PIN" + }, + "prerequisites": [], + "request_table": "TaskUserActionArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "hardware": [ + "trezor" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "", + "sequence": 100, + "tags": [ + "deprecated", + "v2" + ] + }, + "task::enable_eth::cancel": { + "errors_table": "TaskCancelErrors", + "examples": { + "TaskEnableEthCancel": "Cancel EVM Activation Task" + }, + "prerequisites": [], + "request_table": "TaskCancelArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskCancelResponse", + "sequence": 110, + "tags": [ + "v2" + ] + }, + "task::enable_eth::init": { + "errors_table": "TaskInitErrors", + "examples": { + "TaskEnableEthInit": "Initialize EVM coin (ETH, AVAX, etc.)", + "TaskEnableEthInitTrezor": "Initialize EVM coin (ETH, AVAX, etc.) with Trezor" + }, + "prerequisites": [], + "request_table": "TaskEnableEthArguments", + "requirements": { + "conditional_params": { + "hd_only": [ + "gap_limit", + "min_addresses_number", + "path_to_address", + "scan_policy" + ], + "non_hd_only": [ + "nft_req" + ] + }, + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskResponse", + "sequence": 25, + "tags": [ + "v2" + ] + }, + "task::enable_eth::status": { + "errors_table": "TaskStatusErrors", + "examples": { + "TaskEnableEthStatus": "Check EVM Task Status" + }, + "prerequisites": [], + "request_table": "TaskStatusArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskStatusResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "task::enable_eth::user_action": { + "errors_table": "TaskUserActionErrors", + "examples": { + "TaskEnableEthUserActionPin": "Provide Trezor PIN" + }, + "prerequisites": [], + "request_table": "TaskUserActionArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "hardware": [ + "trezor" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskUserActionResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "task::enable_qtum::cancel": { + "errors_table": "TaskCancelErrors", + "examples": { + "TaskEnableQtumCancel": "Cancel Qtum Activation Task" + }, + "prerequisites": [], + "request_table": "TaskCancelArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskCancelResponse", + "sequence": 110, + "tags": [ + "v2" + ] + }, + "task::enable_qtum::init": { + "errors_table": "TaskInitErrors", + "examples": { + "TaskEnableQtumInit": "Initialize Qtum" + }, + "prerequisites": [], + "request_table": "TaskEnableQtumArguments", + "requirements": { + "conditional_params": { + "hd_only": [ + "gap_limit", + "min_addresses_number", + "path_to_address", + "scan_policy" + ], + "non_hd_only": [] + }, + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskResponse", + "sequence": 25, + "tags": [ + "v2" + ] + }, + "task::enable_qtum::status": { + "errors_table": "TaskStatusErrors", + "examples": { + "TaskEnableQtumStatus": "Check Qtum Activation Task Status" + }, + "prerequisites": [], + "request_table": "TaskStatusArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskStatusResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "task::enable_qtum::user_action": { + "errors_table": "TaskUserActionErrors", + "examples": { + "TaskEnableQtumUserActionPin": "Provide Trezor PIN" + }, + "prerequisites": [], + "request_table": "TaskUserActionArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "hardware": [ + "trezor" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskUserActionResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "task::enable_tendermint::cancel": { + "errors_table": "TaskCancelErrors", + "examples": { + "TaskEnableTendermintCancel": "Cancel Tendermint Activation Task" + }, + "prerequisites": [], + "request_table": "TaskCancelArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskCancelResponse", + "sequence": 110, + "tags": [ + "v2" + ] + }, + "task::enable_tendermint::init": { + "errors_table": "TaskInitErrors", + "examples": { + "TaskEnableTendermintInit": "Initialize Tendermint Coin" + }, + "prerequisites": [], + "request_table": "TaskEnableTendermintArguments", + "requirements": { + "conditional_params": { + "hd_only": [ + "gap_limit", + "min_addresses_number", + "path_to_address", + "scan_policy" + ], + "non_hd_only": [] + }, + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskResponse", + "sequence": 25, + "tags": [ + "v2" + ] + }, + "task::enable_tendermint::status": { + "errors_table": "TaskStatusErrors", + "examples": { + "TaskEnableTendermintStatus": "Check Tendermint Activation Task Status" + }, + "prerequisites": [], + "request_table": "TaskStatusArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskStatusResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "task::enable_tendermint::user_action": { + "errors_table": "TaskUserActionErrors", + "examples": { + "TaskEnableTendermintUserActionPin": "Provide Trezor PIN" + }, + "prerequisites": [], + "request_table": "TaskUserActionArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "hardware": [ + "trezor" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskUserActionResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "task::enable_utxo::cancel": { + "errors_table": "TaskCancelErrors", + "examples": { + "TaskEnableUtxoCancel": "Cancel UTXO Activation Task" + }, + "prerequisites": [], + "request_table": "TaskCancelArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskCancelResponse", + "sequence": 110, + "tags": [ + "v2" + ] + }, + "task::enable_utxo::init": { + "errors_table": "TaskInitErrors", + "examples": { + "TaskEnableUtxoInit": "Initialize UTXO Coin" + }, + "prerequisites": [], + "request_table": "ActivationParams", + "requirements": { + "conditional_params": { + "hd_only": [ + "gap_limit", + "min_addresses_number", + "path_to_address", + "scan_policy" + ], + "non_hd_only": [] + }, + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskResponse", + "sequence": 25, + "tags": [ + "v2" + ] + }, + "task::enable_utxo::status": { + "errors_table": "TaskStatusErrors", + "examples": { + "TaskEnableUtxoStatus": "Check UTXO Task Status" + }, + "prerequisites": [], + "request_table": "TaskStatusArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskStatusResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "task::enable_utxo::user_action": { + "errors_table": "TaskUserActionErrors", + "examples": { + "TaskEnableUtxoUserActionPin": "Provide Trezor PIN" + }, + "prerequisites": [], + "request_table": "TaskUserActionArguments", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "example_requirements": { + "TaskEnableUtxoUserActionPin": { + "hardware": [ + "trezor" + ] + } + }, + "hardware": [ + "trezor" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "TaskUserActionResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "task::enable_z_coin::cancel": { + "errors_table": "TaskCancelErrors", + "examples": { + "TaskEnableZCoinCancel": "Cancel Z-coin Activation Task" + }, + "prerequisites": [], + "request_table": "TaskCancelArguments", + "requirements": { + "environments": [ + "native" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "TaskCancelResponse", + "sequence": 110, + "tags": [ + "v2" + ] + }, + "task::enable_z_coin::init": { + "errors_table": "TaskInitErrors", + "examples": { + "TaskEnableZCoinInit": "Initialize Z-coin", + "TaskEnableZCoinInitBasic": "Initialize Z-coin with basic params", + "TaskEnableZCoinInitWasm": "Enable Z Coin Initialization Wasm", + "TaskEnableZCoinInitWithSyncParams": "Initialize Z-coin with sync params" + }, + "prerequisites": [], + "request_table": "TaskEnableZCoinArguments", + "requirements": { + "environments": [ + "native" + ], + "notes": "Z-coin activation requires native environment for zcash params and non-HD wallet", + "wallet_types": [ + "iguana" + ] + }, + "response_table": "TaskResponse", + "sequence": 25, + "tags": [ + "v2" + ] + }, + "task::enable_z_coin::status": { + "errors_table": "TaskStatusErrors", + "examples": { + "TaskEnableZCoinStatus": "Check Z-coin Activation Task Status" + }, + "prerequisites": [], + "request_table": "TaskStatusArguments", + "requirements": { + "environments": [ + "native" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "TaskStatusResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "task::enable_z_coin::user_action": { + "errors_table": "TaskUserActionErrors", + "examples": { + "TaskEnableZCoinUserActionPin": "Provide Trezor PIN" + }, + "prerequisites": [], + "request_table": "TaskUserActionArguments", + "requirements": { + "environments": [ + "native" + ], + "hardware": [ + "trezor" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "TaskUserActionResponse", + "sequence": 100, + "tags": [ + "v2" + ] + }, + "task::withdraw::cancel": { + "errors_table": "WithdrawTaskErrors", + "examples": {}, + "prerequisites": [ + "task::withdraw::init" + ], + "request_table": "WithdrawCancelRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "WithdrawStatusResponse", + "sequence": 224, + "tags": [ + "v2" + ] + }, + "task::withdraw::init": { + "errors_table": "WithdrawTaskErrors", + "examples": {}, + "prerequisites": [], + "request_table": "WithdrawInitRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "WithdrawInitResponse", + "sequence": 221, + "tags": [ + "v2" + ] + }, + "task::withdraw::status": { + "errors_table": "WithdrawTaskErrors", + "examples": {}, + "prerequisites": [ + "task::withdraw::init" + ], + "request_table": "WithdrawStatusRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "WithdrawStatusResponse", + "sequence": 222, + "tags": [ + "v2" + ] + }, + "task::withdraw::user_action": { + "errors_table": "WithdrawTaskErrors", + "examples": {}, + "prerequisites": [ + "task::withdraw::init" + ], + "request_table": "WithdrawUserActionRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "iguana" + ] + }, + "response_table": "WithdrawStatusResponse", + "sequence": 223, + "tags": [ + "v2" + ] + }, + "withdraw": { + "errors_table": "WithdrawErrors", + "examples": { + "WithdrawBroadcastTrue": "Withdraw Broadcast True", + "WithdrawDocFixedFee": "Withdraw Doc Fixed Fee", + "WithdrawDocPerKbyte": "Withdraw Doc Per Kbyte", + "WithdrawEth": "Withdraw Eth", + "WithdrawEthGas": "Withdraw Eth Gas", + "WithdrawEthMax": "Withdraw Eth Max", + "WithdrawIbcAtom": "Withdraw Ibc Atom", + "WithdrawIrisMemoCosmosGas": "Withdraw Iris Memo Cosmos Gas", + "WithdrawKmd": "Withdraw Kmd", + "WithdrawMartyAccountId": "Withdraw Marty Account Id", + "WithdrawMartyDerivationPath": "Withdraw Marty Derivation Path", + "WithdrawMartyFixedFee": "Withdraw Marty Fixed Fee", + "WithdrawMartyNonHD": "Withdraw Marty (Non HD)", + "WithdrawMartyPerKbyte": "Withdraw Marty Per Kbyte", + "WithdrawQrc20": "Withdraw Qrc20", + "WithdrawQrc20Gas": "Withdraw Qrc20 Gas", + "WithdrawSia": "Withdraw Sia", + "WithdrawSiaProtocol": "Withdraw Sia Protocol" + }, + "prerequisites": [], + "request_table": "WithdrawRequest", + "requirements": { + "environments": [ + "native", + "wasm" + ], + "wallet_types": [ + "hd", + "iguana" + ] + }, + "response_table": "WithdrawResponse", + "sequence": 50, + "tags": [ + "v2" + ] + } +} \ No newline at end of file diff --git a/src/data/kdf_responses/legacy/coin_activation.json b/src/data/kdf_responses/legacy/coin_activation.json deleted file mode 100644 index f155526d6..000000000 --- a/src/data/kdf_responses/legacy/coin_activation.json +++ /dev/null @@ -1,280 +0,0 @@ -{ - "LegacyEnableEth": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "address": "0x7Bc1bBDD6A0a722fC9bffc49c921B685ECB84b94", - "balance": "12.00283000", - "locked_by_swaps": "0.00000000", - "required_confirmations": 1, - "requires_notarization": false, - "mature_confirmations": 0, - "result": "success" - } - } - ], - "error": [ - { - "title": "Transport error", - "notes": "Connection to ETH node failed", - "json": { - "error": "Transport error: JsonRpcError { client_info: \"coin: ETH\", request: JsonRpcRequest { jsonrpc: \"2.0\", id: \"9\", method: \"eth_getBalance\", params: [String(\"0x7Bc1bBDD6A0a722fC9bffc49c921B685ECB84b94\"), String(\"latest\")] }, error: Transport(\"All electrum servers unavailable!\") }" - } - }, - { - "title": "Already enabled", - "notes": "The coin is already activated", - "json": { - "error": "lp_coins:1308] eth:295] Coin ETH is already activated" - } - } - ] - }, - "LegacyElectrumBch": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "address": "1DgpBvyeUNHasBt3h3qzC1p9Z8qTgr6t5m", - "balance": "0.12345678", - "required_confirmations": 1, - "requires_notarization": false, - "result": "success" - } - } - ], - "error": [ - { - "title": "Connection failed", - "notes": "Unable to connect to electrum servers", - "json": { - "error": "All electrum servers for BCH are unavailable" - } - } - ] - }, - "LegacyElectrumKmd": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "KMD", - "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ", - "balance": "762", - "unspendable_balance": "0", - "mature_confirmations": 100, - "required_confirmations": 10, - "requires_notarization": true, - "result": "success" - } - } - ], - "error": [ - { - "title": "Missing mm2 parameter", - "notes": "mm2 param is not set in coins config or enable request", - "json": { - "error": "lp_coins:943] lp_coins:693] mm2 param is not set neither in coins config nor enable request, assuming that coin is not supported" - } - }, - { - "title": "Invalid min_connected", - "notes": "min_connected should be greater than 0", - "json": { - "error": "rpc:184] dispatcher_legacy:141] lp_commands_legacy:141] lp_coins:4462] utxo_standard:73] utxo_coin_builder:616] Internal error: manager:129] min_connected should be greater than 0" - } - }, - { - "title": "Invalid connection range", - "notes": "min_connected must be <= max_connected", - "json": { - "error": "rpc:184] dispatcher_legacy:141] lp_commands_legacy:141] lp_coins:4462] utxo_standard:73] utxo_coin_builder:616] Internal error: manager:132] min_connected (2) must be <= max_connected (1)" - } - } - ] - }, - "LegacyElectrumQtum": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "QTUM", - "address": "QjXkGgoiycYRm2NbiMpkEHuQt7SB9BKHjz", - "balance": "7.77", - "required_confirmations": 3, - "requires_notarization": false, - "unspendable_balance": "0", - "mature_confirmations": 100, - "result": "success" - } - } - ], - "error": [ - { - "title": "Missing mm2 parameter", - "notes": "mm2 param is not set in coins config or enable request", - "json": { - "error": "lp_coins:943] lp_coins:693] mm2 param is not set neither in coins config nor enable request, assuming that coin is not supported" - } - } - ] - }, - "LegacyEnableNative": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "TKL", - "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ", - "balance": "333", - "required_confirmations": 1, - "requires_notarization": false, - "unspendable_balance": "0", - "mature_confirmations": 100, - "result": "success" - } - } - ], - "error": [ - { - "title": "Connection failed", - "notes": "Unable to connect to daemon", - "json": { - "error": "Failed to connect to native daemon" - } - } - ] - }, - "LegacyEnableNativeWithParams": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "TKL", - "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ", - "balance": "777", - "required_confirmations": 10, - "requires_notarization": true, - "unspendable_balance": "0", - "mature_confirmations": 100, - "result": "success" - } - } - ], - "error": [ - { - "title": "Connection failed", - "notes": "Unable to connect to daemon", - "json": { - "error": "Failed to connect to native daemon" - } - } - ] - }, - "LegacyEnableEthGasStation": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "ETH", - "address": "0x3c7aad7b693e94f13b61d4be4abaeaf802b2e3b5", - "balance": "50", - "required_confirmations": 1, - "requires_notarization": false, - "unspendable_balance": "0", - "result": "success" - } - } - ], - "error": [ - { - "title": "Gas station error", - "notes": "Unable to fetch gas price from station", - "json": { - "error": "Failed to get gas price from station" - } - }, - { - "title": "Already enabled", - "notes": "The coin is already activated", - "json": { - "error": "lp_coins:1308] eth:295] Coin ETH is already activated" - } - } - ] - }, - "LegacyEnableMatic": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "NZDS-PLG20", - "address": "0x3c7aad7b693e94f13b61d4be4abaeaf802b2e3b5", - "balance": "350", - "required_confirmations": 1, - "requires_notarization": false, - "unspendable_balance": "0", - "result": "success" - } - } - ], - "error": [ - { - "title": "Connection failed", - "notes": "Unable to connect to Polygon RPC", - "json": { - "error": "All Polygon RPC servers unavailable" - } - }, - { - "title": "Already enabled", - "notes": "The coin is already activated", - "json": { - "error": "lp_coins:1308] Coin NZDS-PLG20 is already activated" - } - } - ] - }, - "LegacyEnableBnb": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "BUSD-BEP20", - "address": "0x3c7aad7b693e94f13b61d4be4abaeaf802b2e3b5", - "balance": "45", - "required_confirmations": 1, - "requires_notarization": false, - "unspendable_balance": "0", - "result": "success" - } - } - ], - "error": [ - { - "title": "Connection failed", - "notes": "Unable to connect to BSC RPC", - "json": { - "error": "All BSC RPC servers unavailable" - } - }, - { - "title": "Already enabled", - "notes": "The coin is already activated", - "json": { - "error": "lp_coins:1308] Coin BUSD-BEP20 is already activated" - } - } - ] - } -} \ No newline at end of file diff --git a/src/data/kdf_responses/v2/coin_activation.json b/src/data/kdf_responses/v2/coin_activation.json deleted file mode 100644 index 0a066a5d7..000000000 --- a/src/data/kdf_responses/v2/coin_activation.json +++ /dev/null @@ -1,188 +0,0 @@ -{ - "TaskEnableZCoinStatus": { - "success": [ - { - "title": "ActivatingCoin - enabling has started", - "notes": "", - "json": { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": "ActivatingCoin" - }, - "id": null - } - }, - { - "title": "UpdatingBlocksCache", - "notes": "", - "json": { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": { - "UpdatingBlocksCache": { - "current_scanned_block": 265930, - "latest_block": 269656 - } - } - }, - "id": null - } - }, - { - "title": "BuildingWalletDb", - "notes": "", - "json": { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": { - "BuildingWalletDb": { - "current_scanned_block": 265311, - "latest_block": 269656 - } - } - }, - "id": null - } - }, - { - "title": "Enabling complete", - "notes": "", - "json": { - "mmrpc": "2.0", - "result": { - "status": "Ok", - "details": { - "ticker": "ZOMBIE", - "current_block": 269657, - "wallet_balance": { - "wallet_type": "Iguana", - "address": "zs1e3puxpnal8ljjrqlxv4jctlyndxnm5a3mj5rarjvp0qv72hmm9caduxk9asu9kyc6erfx4zsauj", - "balance": { - "spendable": "29.99989008", - "unspendable": "0" - } - } - } - }, - "id": null - } - } - ], - "error": [ - { - "title": "CoinCreationError - no Zcash Params", - "notes": "", - "json": { - "error": "Error on platform coin ZOMBIE creation: ZCashParamsNotFound", - "error_path": "lib.z_coin_activation.z_coin", - "error_trace": "lib:104] z_coin_activation:218] z_coin:1007]", - "error_type": "CoinCreationError", - "error_data": { - "ticker": "ZOMBIE", - "error": "ZCashParamsNotFound" - } - } - }, - { - "title": "NoSuchTask", - "notes": "You'll see this if the task number does not exist, or the task has already completed.", - "json": { - "mmrpc": "2.0", - "error": "No such task '1'", - "error_path": "init_standalone_coin", - "error_trace": "init_standalone_coin:119]", - "error_type": "NoSuchTask", - "error_data": 1, - "id": null - } - }, - { - "title": "InvalidRequest", - "notes": "", - "json": { - "mmrpc": "2.0", - "error": "Error parsing request: invalid value: integer `-205`, expected u64", - "error_path": "dispatcher", - "error_trace": "dispatcher:109]", - "error_type": "InvalidRequest", - "error_data": "invalid value: integer `-205`, expected u64", - "id": 42 - } - }, - { - "title": "No Zcash Params (alt format)", - "notes": "", - "json": { - "mmrpc": "2.0", - "result": { - "status": "Error", - "details": { - "error": "Error on platform coin ZOMBIE creation: ZCashParamsNotFound", - "error_path": "lib.z_coin_activation.z_coin", - "error_trace": "lib:103] z_coin_activation:192] z_coin:761]", - "error_type": "CoinCreationError", - "error_data": { - "ticker": "ZOMBIE", - "error": "ZCashParamsNotFound" - } - } - }, - "id": null - } - } - ] - }, - "TaskEnableEthStatus": { - "success": [ - { - "title": "InProgress - ActivatingCoin", - "notes": "", - "json": { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": "ActivatingCoin" - }, - "id": null - } - }, - { - "title": "Ok - Complete", - "notes": "", - "json": { - "mmrpc": "2.0", - "result": { - "status": "Ok", - "details": { - "ticker": "MATIC", - "platform_coin": { - "platform": "ETH", - "ticker": "MATIC" - }, - "current_block": 12345678 - } - }, - "id": null - } - } - ], - "error": [ - { - "title": "No such task", - "notes": "Task ID does not exist or has been completed", - "json": { - "mmrpc": "2.0", - "error": "No such task '5'", - "error_path": "init_standalone_coin", - "error_trace": "init_standalone_coin:119]", - "error_type": "NoSuchTask", - "error_data": 5, - "id": null - } - } - ] - } -} \ No newline at end of file diff --git a/src/data/requests/kdf/legacy/coin_activation.json b/src/data/requests/kdf/legacy/coin_activation.json index 3d4097e64..0e37b78fa 100644 --- a/src/data/requests/kdf/legacy/coin_activation.json +++ b/src/data/requests/kdf/legacy/coin_activation.json @@ -1,131 +1,185 @@ { "LegacyElectrumBch": { "coin": "BCH", + "max_connected": 2, "method": "electrum", + "min_connected": 1, "servers": [ { - "url": "bch.electrum3.cipig.net:10055", - "protocol": "TCP" + "protocol": "SSL", + "url": "bch.electrum3.cipig.net:20055" }, { - "url": "bch.electrum3.cipig.net:20055", - "protocol": "SSL" + "protocol": "SSL", + "url": "bch.imaginary.cash:50002" }, { - "url": "bch.electrum3.cipig.net:30055", - "protocol": "WSS" + "protocol": "SSL", + "url": "bch.soul-dev.com:50002" } ], - "min_connected": 1, - "max_connected": 2, + "tx_history": true, "userpass": "RPC_UserP@SSW0RD" }, + "LegacyElectrumDoc": { + "coin": "DOC", + "method": "electrum", + "mm2": 1, + "required_confirmations": 10, + "requires_notarization": true, + "servers": [ + { + "protocol": "SSL", + "url": "doc.electrum1.cipig.net:20020" + }, + { + "protocol": "SSL", + "url": "doc.electrum2.cipig.net:20020" + }, + { + "protocol": "SSL", + "url": "doc.electrum3.cipig.net:20020" + } + ], + "tx_history": true, + "userpass": "RPC_UserP@SSW0RD", + "utxo_merge_params": { + "check_every": 10, + "max_merge_at_once": 100, + "merge_at": 50 + } + }, "LegacyElectrumKmd": { "coin": "KMD", "method": "electrum", + "mm2": 1, + "required_confirmations": 10, + "requires_notarization": true, "servers": [ { - "url": "kmd.electrum3.cipig.net:10001", - "protocol": "TCP" + "protocol": "SSL", + "url": "kmd.electrum1.cipig.net:20001" }, { - "url": "kmd.electrum1.cipig.net:20001", - "protocol": "SSL" + "protocol": "SSL", + "url": "kmd.electrum2.cipig.net:20001" }, { - "url": "kmd.electrum3.cipig.net:20001", - "protocol": "SSL" + "protocol": "SSL", + "url": "kmd.electrum3.cipig.net:20001" } ], + "userpass": "RPC_UserP@SSW0RD" + }, + "LegacyElectrumMarty": { + "coin": "MARTY", + "max_connected": 2, + "method": "electrum", + "min_connected": 1, + "mm2": 1, "required_confirmations": 10, "requires_notarization": true, - "mm2": 1, + "servers": [ + { + "protocol": "SSL", + "url": "marty.electrum1.cipig.net:20021" + }, + { + "protocol": "SSL", + "url": "marty.electrum2.cipig.net:20021" + }, + { + "protocol": "SSL", + "url": "marty.electrum3.cipig.net:20021" + } + ], "userpass": "RPC_UserP@SSW0RD" }, "LegacyElectrumQtum": { "coin": "QTUM", + "fallback_swap_contract": "0x2f754733acd6d753731c00fee32cb484551cc15d", "method": "electrum", "servers": [ { - "url": "qtum.electrum1.cipig.net:20050", - "protocol": "SSL" + "protocol": "SSL", + "url": "qtum.electrum1.cipig.net:20050" }, { - "url": "qtum.electrum2.cipig.net:20050", - "protocol": "SSL" + "protocol": "SSL", + "url": "qtum.electrum2.cipig.net:20050" }, { - "url": "qtum.electrum2.cipig.net:10050", - "protocol": "TCP" + "protocol": "SSL", + "url": "qtum.electrum3.cipig.net:20050" } ], "swap_contract_address": "0x2f754733acd6d753731c00fee32cb484551cc15d", "userpass": "RPC_UserP@SSW0RD" }, - "LegacyEnableNative": { - "userpass": "RPC_UserP@SSW0RD", - "method": "enable", - "coin": "TKL" - }, - "LegacyEnableNativeWithParams": { - "userpass": "RPC_UserP@SSW0RD", + "LegacyEnableBnb": { + "coin": "BUSD-BEP20", + "fallback_swap_contract": "0xeDc5b89Fe1f0382F9E4316069971D90a0951DB31", "method": "enable", - "coin": "TKL", - "mm2": 1, - "required_confirmations": 10, - "requires_notarization": true + "swap_contract_address": "0xeDc5b89Fe1f0382F9E4316069971D90a0951DB31", + "urls": [ + "https://bsc1.cipig.net:18655", + "https://bsc2.cipig.net:18655", + "https://bsc3.cipig.net:18655" + ], + "userpass": "RPC_UserP@SSW0RD" }, "LegacyEnableEth": { "coin": "ETH", + "fallback_swap_contract": "0x8500AFc0bc5214728082163326C2FF0C73f4a871", "method": "enable", + "swap_contract_address": "0x24ABE4c71FC658C91313b6552cd40cD808b3Ea80", "urls": [ - "https://eth3.cipig.net:18555", - "https://mainnet.gateway.tenderly.co", - "https://ethereum-rpc.publicnode.com" + "https://0xrpc.io/eth", + "https://eth.drpc.org", + "https://eth3.cipig.net:18555" ], - "swap_contract_address": "0x24ABE4c71FC658C91313b6552cd40cD808b3Ea80", - "fallback_swap_contract": "0x8500AFc0bc5214728082163326C2FF0C73f4a871", "userpass": "RPC_UserP@SSW0RD" }, "LegacyEnableEthGasStation": { "coin": "ETH", - "userpass": "RPC_UserP@SSW0RD", - "method": "enable", - "urls": [ - "https://eth3.cipig.net:18555", - "https://0xrpc.io/eth", - "https://eth.drpc.org" - ], - "swap_contract_address": "0x24ABE4c71FC658C91313b6552cd40cD808b3Ea80", "fallback_swap_contract": "0x8500AFc0bc5214728082163326C2FF0C73f4a871", - "gas_station_url": "https://ethgasstation.info/json/ethgasAPI.json", "gas_station_decimals": 8, "gas_station_policy": { "policy": "MeanAverageFast" - } + }, + "gas_station_url": "https://ethgasstation.info/json/ethgasAPI.json", + "method": "enable", + "swap_contract_address": "0x24ABE4c71FC658C91313b6552cd40cD808b3Ea80", + "urls": [ + "https://0xrpc.io/eth", + "https://eth3.cipig.net:18555", + "https://mainnet.gateway.tenderly.co" + ], + "userpass": "RPC_UserP@SSW0RD" }, "LegacyEnableMatic": { "coin": "NZDS-PLG20", + "fallback_swap_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", "method": "enable", "swap_contract_address": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", - "fallback_swap_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", "urls": [ "https://node.komodo.earth:8080/polygon", "https://pol3.cipig.net:18755", - "https://polygon.gateway.tenderly.co" + "https://polygon.drpc.org" ], "userpass": "RPC_UserP@SSW0RD" }, - "LegacyEnableBnb": { - "coin": "BUSD-BEP20", + "LegacyEnableNative": { + "coin": "TKL", "method": "enable", - "swap_contract_address": "0xeDc5b89Fe1f0382F9E4316069971D90a0951DB31", - "fallback_swap_contract": "0xeDc5b89Fe1f0382F9E4316069971D90a0951DB31", - "urls": [ - "https://bsc1.cipig.net:18655", - "https://bsc2.cipig.net:18655", - "https://bsc3.cipig.net:18655" - ], + "userpass": "RPC_UserP@SSW0RD" + }, + "LegacyEnableNativeWithParams": { + "coin": "TKL", + "method": "enable", + "mm2": 1, + "required_confirmations": 10, + "requires_notarization": true, "userpass": "RPC_UserP@SSW0RD" } } \ No newline at end of file diff --git a/src/data/requests/kdf/legacy/utils.json b/src/data/requests/kdf/legacy/utils.json new file mode 100644 index 000000000..42f6dd559 --- /dev/null +++ b/src/data/requests/kdf/legacy/utils.json @@ -0,0 +1,18 @@ +{ + "CoinsNeededForKickStart": { + "method": "coins_needed_for_kick_start", + "userpass": "RPC_UserP@SSW0RD" + }, + "LegacyGetEnabledCoins": { + "method": "get_enabled_coins", + "userpass": "RPC_UserP@SSW0RD" + }, + "LegacyGetMyPeerId": { + "method": "get_my_peer_id", + "userpass": "RPC_UserP@SSW0RD" + }, + "LegacyVersion": { + "method": "version", + "userpass": "RPC_UserP@SSW0RD" + } +} \ No newline at end of file diff --git a/src/data/requests/kdf/legacy/wallet.json b/src/data/requests/kdf/legacy/wallet.json new file mode 100644 index 000000000..fb3106efb --- /dev/null +++ b/src/data/requests/kdf/legacy/wallet.json @@ -0,0 +1,197 @@ +{ + "MyTxHistoryDoc": { + "coin": "DOC", + "limit": 1, + "method": "my_tx_history", + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistoryDocMax": { + "coin": "DOC", + "from_id": "1d5c1b67f8ebd3fc480e25a1d60791bece278f5d1245c5f9474c91a142fee8e1", + "max": true, + "method": "my_tx_history", + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistoryErrors": { + "coin": "TTT-SLP", + "method": "my_tx_history", + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistoryEthSuccess": { + "coin": "ETH", + "limit": 3, + "method": "my_tx_history", + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistorySia": { + "coin": "SC", + "method": "my_tx_history", + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistorySyncEthInProgress": { + "coin": "ETH", + "limit": 0, + "method": "my_tx_history", + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistorySyncUtxoInProgress": { + "coin": "DOC", + "limit": 0, + "method": "my_tx_history", + "userpass": "RPC_UserP@SSW0RD" + }, + "SendRawTransactionKmd": { + "coin": "KMD", + "method": "send_raw_transaction", + "tx_hex": "0400008085202f8902d6a5b976db5e5c9e8f9ead50713b25f22cd061edc8ff0ff1049fd2cd775ba087000000006b483045022100bf2073c1ecfef3fc78f272045f46a722591401f61c2d2fac87fc474a17df7c3102200ca1bd0664ba75f3383e5cbbe96127ad534a86238dbea256e000b0fe2067ab8c012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffffd04d4e07ac5dacd08fb76e08d2a435fc4fe2b16eb0158695c820b44f42f044cb010000006a47304402200a0c21e8c0ae4a740f3663fe08aeff02cea6495157d531045b58d2dd79fb802702202f80dddd264db33f55e49799363997a175d39a91242a95f268c40f7ced97030b012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788acc3b3ca27000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac00000000000000000000000000000000000000", + "userpass": "RPC_UserP@SSW0RD" + }, + "SendRawTransactionSiaFull": { + "coin": "SC", + "method": "send_raw_transaction", + "tx_json": { + "minerFee": "10000000000000000000", + "siacoinInputs": [ + { + "parent": { + "id": "db712a113806580ec2cce966135ebf139d0e1086bf04cf84b7fe554ec25bb5a7", + "maturityHeight": 0, + "siacoinOutput": { + "address": "2c4a029ef67858d7c3ebf9ce7f1c257fd880b1b073fd3923091423e1658ae23d2b426be204db", + "value": "50000000000000000000000000" + }, + "stateElement": { + "leafIndex": 72996955, + "merkleProof": [ + "42a6529a8ef4a849b716071d66bb84d7e929fc1ad671d04229992ff670e3627f", + "5f728bfbc9494ec8ec9f76b229bf85f184fddd3c305b2a91e74546a821a664b6", + "64295af67329a2f6f91e10ace99a379e4df6cdfc2405db967f4857226dafaa53", + "665e3a2f25267de5e35b5076895438745cd1101ae7c337a3139b910460d8bb36", + "73c4dd35635c1707d322035c52a9cc9cf96766e9adcea4ed675c851d6ae50b3b", + "7dece8216b769ba9b15b27d00a728cbdbc2d4c72bc7cf93fe9ff48c7f739069e", + "80a16928a727b386dd824ba1f82a03da2f41a1583b14c21cc1fc0de7af2f5c4e", + "84b54d73a6b74c3abb152e7d6f30a1fae6b411522353a7f25220095ed4ae5cbf", + "a6f1306840881651aea186e25ae4de9932e58c8178fef43586a9f9fa52b99d1a", + "ab734606431ad3a6c50a5d3cbff9f340cedef606407e952af55476e6b51f43a6", + "bad7c9a405bbc576a99718cb4c3889b8710db975b2b03e327653170956457bef", + "c7158f7aba1d3954f0d56e8a96a1bfe360038b249b7cdcf941da4c974974be89", + "c72d15d701e5f83c3db6a0b2ab5f85a932541d4bef41028f19751081996e0f2c", + "c734b54b9e42c8aa3d6adf11ffa257b474d9cc7036a31aff7c11d0a02b7f2ca4", + "cd2dd16a38a0443dc2ad93faefaf7974842dcab419ea1ce1f1b82f97adb81b1a", + "d3a9e8d681ba7231fdcef7d795ff5acb1469bf7c17317c8ea59f60fd3963d776", + "f2eab142e8a752abb6fc6a0b3f2e3199ed22ff74c701e44676192696e784675a" + ] + } + }, + "satisfiedPolicy": { + "policy": { + "policy": "ed25519:c94acdcbd6a44c25a2640191afd80d6ef6c692c3a0faa0db3cec0189d90f6cd1", + "type": "pk" + }, + "signatures": [ + "2ab2ef985c6ebc396caddf60671a5205d4b62201293b90ccdb939fc70fb1a9dd5449a53d21541362cc194674d4e8bc215116b9014b1cee6d625176e647df670d" + ] + } + } + ], + "siacoinOutputs": [ + { + "address": "2c4a029ef67858d7c3ebf9ce7f1c257fd880b1b073fd3923091423e1658ae23d2b426be204db", + "value": "48974990000000000000000000" + }, + { + "address": "c67d77a585c13727dbba57cfc115995beb9b8737e9a8cb7bb0aa208744e646cdc0acc9c9fce2", + "value": "1025000000000000000000000" + } + ] + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "ValidateAddress": { + "address": "RRnMcSeKiLrNdbp91qNVQwwXx5azD4S4CD", + "coin": "DOC", + "method": "validateaddress", + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawLegacyDocFixedFee": { + "amount": "1.0", + "coin": "DOC", + "fee": { + "amount": "0.1", + "type": "UtxoFixed" + }, + "method": "withdraw", + "to": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW", + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawLegacyDocPerKbyte": { + "amount": "1.0", + "coin": "DOC", + "fee": { + "amount": "1", + "type": "UtxoPerKbyte" + }, + "method": "withdraw", + "to": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW", + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawLegacyEth": { + "amount": 10, + "coin": "ETH", + "method": "withdraw", + "to": "0xbab36286672fbdc7b250804bf6d14be0df69fa28", + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawLegacyEthGas": { + "amount": "AMOUNT", + "coin": "COIN_NAME", + "fee": { + "gas": 55000, + "gas_price": "3.5", + "type": "EthGas" + }, + "method": "withdraw", + "to": "RECIPIENT_ADDRESS", + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawLegacyEthMax": { + "coin": "ETH", + "max": true, + "method": "withdraw", + "to": "0xbab36286672fbdc7b250804bf6d14be0df69fa28", + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawLegacyKmd": { + "amount": "10", + "coin": "KMD", + "method": "withdraw", + "to": "RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh", + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawLegacyQrc20": { + "amount": 10, + "coin": "QRC20", + "method": "withdraw", + "to": "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs", + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawLegacyQrc20Gas": { + "amount": 10, + "coin": "QRC20", + "fee": { + "gas_limit": 250000, + "gas_price": 40, + "type": "Qrc20Gas" + }, + "method": "withdraw", + "to": "qHmJ3KA6ZAjR9wGjpFAS4gtUSeFAqdZgs", + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawLegacySia": { + "amount": "1.025", + "coin": "SC", + "method": "withdraw", + "to": "c67d77a585c13727dbba57cfc115995beb9b8737e9a8cb7bb0aa208744e646cdc0acc9c9fce2", + "userpass": "RPC_UserP@SSW0RD" + } +} \ No newline at end of file diff --git a/src/data/requests/kdf/v2/coin_activation.json b/src/data/requests/kdf/v2/coin_activation.json index fd45936de..e1c3cf44b 100644 --- a/src/data/requests/kdf/v2/coin_activation.json +++ b/src/data/requests/kdf/v2/coin_activation.json @@ -1,224 +1,219 @@ { - "TaskEnableEthInitTrezor": { - "userpass": "RPC_UserP@SSW0RD", + "EnableBchWithTokensBalancesFalse": { + "method": "enable_bch_with_tokens", "mmrpc": "2.0", - "method": "task::enable_eth::init", "params": { - "ticker": "MATIC", - "gas_station_url": "https://gasstation-mainnet.matic.network/", - "swap_contract_address": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", - "fallback_swap_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", - "swap_v2_contracts": { - "taker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", - "maker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", - "nft_maker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE" - }, - "nodes": [ - { - "url": "https://node.komodo.earth:8080/polygon", - "komodo_proxy": true - }, - { - "url": "https://pol3.cipig.net:18755", - "ws_url": "wss://pol3.cipig.net:38755" - }, - { - "url": "https://polygon-bor-rpc.publicnode.com", - "ws_url": "wss://polygon-bor-rpc.publicnode.com" - } + "allow_slp_unsafe_conf": false, + "bchd_urls": [ + "https://bchd.dragonhound.info" ], - "erc20_tokens_requests": [ - { - "ticker": "PGX-PLG20", - "required_confirmations": 4 - }, + "get_balances": false, + "mode": { + "rpc": "Electrum", + "rpc_data": { + "servers": [ + { + "protocol": "SSL", + "url": "bch.electrum3.cipig.net:20055" + }, + { + "protocol": "SSL", + "url": "bch.imaginary.cash:50002" + }, + { + "protocol": "SSL", + "url": "bch.soul-dev.com:50002" + } + ] + } + }, + "slp_tokens_requests": [ { - "ticker": "AAVE-PLG20", - "required_confirmations": 4 + "required_confirmations": 4, + "ticker": "ASLP-SLP" } ], - "required_confirmations": 5, - "path_to_address": { - "account_id": 0, - "chain": "External", - "address_id": 1 - }, - "gap_limit": 20, - "scan_policy": "scan_if_new_wallet", - "min_addresses_number": 3 - } - }, - "TaskEnableEthStatus": { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", - "method": "task::enable_eth::status", - "params": { - "task_id": 1, - "forget_if_finished": false - } - }, - "TaskEnableEthCancel": { - "userpass": "RPC_UserP@SSW0RD", - "method": "task::enable_eth::cancel", - "mmrpc": "2.0", - "params": { - "task_id": 3 - } + "ticker": "BCH", + "tx_history": true + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableEthUserAction": { - "userpass": "RPC_UserP@SSW0RD", + "EnableBchWithTokensTxHistory": { + "method": "enable_bch_with_tokens", "mmrpc": "2.0", - "method": "task::enable_eth::user_action", "params": { - "task_id": 0, - "user_action": { - "action_type": "TrezorPin", - "pin": "862743" + "address_format": { + "format": "cashaddress", + "network": "bitcoincash" + }, + "allow_slp_unsafe_conf": false, + "bchd_urls": [ + "https://bchd.dragonhound.info" + ], + "mode": { + "rpc": "Electrum", + "rpc_data": { + "servers": [ + { + "protocol": "SSL", + "url": "bch.electrum3.cipig.net:20055" + }, + { + "protocol": "SSL", + "url": "bch.imaginary.cash:50002" + }, + { + "protocol": "SSL", + "url": "bch.soul-dev.com:50002" + } + ] + } + }, + "required_confirmations": 5, + "requires_notarization": false, + "slp_tokens_requests": [ + { + "required_confirmations": 4, + "ticker": "ASLP-SLP" + } + ], + "ticker": "BCH", + "tx_history": true, + "utxo_merge_params": { + "check_every": 10, + "max_merge_at_once": 25, + "merge_at": 50 } - } + }, + "userpass": "RPC_UserP@SSW0RD" }, "EnableErc20Basic": { - "userpass": "RPC_UserP@SSW0RD", "method": "enable_erc20", "mmrpc": "2.0", "params": { - "ticker": "BAT-ERC20", - "activation_params": { - "required_confirmations": 3 - } - } - }, - "EnableTendermintTokenBasic": { - "userpass": "RPC_UserP@SSW0RD", - "method": "enable_tendermint_token", - "mmrpc": "2.0", - "params": { - "ticker": "ATOM-IBC_IRIS", "activation_params": { "required_confirmations": 3 - } - } + }, + "ticker": "BAT-ERC20" + }, + "userpass": "RPC_UserP@SSW0RD" }, "EnableEthWithTokensGasStation": { - "userpass": "RPC_UserP@SSW0RD", "method": "enable_eth_with_tokens", "mmrpc": "2.0", "params": { - "ticker": "ETH", - "gas_station_url": "https://ethgasstation.info/json/ethgasAPI.json", + "erc20_tokens_requests": [ + { + "required_confirmations": 4, + "ticker": "APE-ERC20" + }, + { + "required_confirmations": 4, + "ticker": "MINDS-ERC20" + } + ], + "fallback_swap_contract": "0x8500AFc0bc5214728082163326C2FF0C73f4a871", "gas_station_decimals": 8, "gas_station_policy": { "policy": "MeanAverageFast" }, + "gas_station_url": "https://ethgasstation.info/json/ethgasAPI.json", "mm2": 1, - "priv_key_policy": { - "type": "ContextPrivKey" - }, - "swap_contract_address": "0x24ABE4c71FC658C91313b6552cd40cD808b3Ea80", - "fallback_swap_contract": "0x8500AFc0bc5214728082163326C2FF0C73f4a871", "nodes": [ { - "url": "https://eth3.cipig.net:18555", - "ws_url": "wss://eth3.cipig.net:38555" - }, - { - "url": "https://node.komodo.earth:8080/ethereum", - "komodo_proxy": true + "url": "https://0xrpc.io/eth", + "ws_url": "wss://0xrpc.io/eth" }, { - "url": "https://eth.drpc.org", - "ws_url": "wss://eth.drpc.org" - } - ], - "tx_history": true, - "erc20_tokens_requests": [ - { - "ticker": "APE-ERC20", - "required_confirmations": 4 - }, - { - "ticker": "BCH-ERC20", - "required_confirmations": 4 - }, - { - "ticker": "MINDS-ERC20", - "required_confirmations": 4 + "url": "https://eth3.cipig.net:18555", + "ws_url": "wss://eth3.cipig.net:38555" }, { - "ticker": "BUSD-ERC20", - "required_confirmations": 4 + "url": "https://mainnet.gateway.tenderly.co", + "ws_url": "wss://mainnet.gateway.tenderly.co" } ], + "priv_key_policy": { + "type": "ContextPrivKey" + }, "required_confirmations": 5, - "requires_notarization": false - } + "requires_notarization": false, + "swap_contract_address": "0x24ABE4c71FC658C91313b6552cd40cD808b3Ea80", + "ticker": "ETH", + "tx_history": true + }, + "userpass": "RPC_UserP@SSW0RD" }, "EnableEthWithTokensMaticBalancesFalse": { - "userpass": "RPC_UserP@SSW0RD", "method": "enable_eth_with_tokens", "mmrpc": "2.0", "params": { - "ticker": "MATIC", - "get_balances": false, - "tx_history": false, - "gas_station_url": "https://gasstation-mainnet.matic.network/", - "swap_contract_address": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", - "fallback_swap_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", - "swap_v2_contracts": { - "maker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", - "taker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", - "nft_maker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE" - }, - "nodes": [ + "erc20_tokens_requests": [ { - "url": "https://node.komodo.earth:8080/polygon", - "komodo_proxy": true + "required_confirmations": 4, + "ticker": "PGX-PLG20" }, + { + "required_confirmations": 4, + "ticker": "AAVE-PLG20" + } + ], + "fallback_swap_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", + "gas_station_url": "https://gasstation-mainnet.matic.network/", + "get_balances": false, + "nodes": [ { "url": "https://pol3.cipig.net:18755", "ws_url": "wss://pol3.cipig.net:38755" }, { - "url": "https://polygon-bor-rpc.publicnode.com", - "ws_url": "wss://polygon-bor-rpc.publicnode.com" - } - ], - "erc20_tokens_requests": [ - { - "ticker": "PGX-PLG20", - "required_confirmations": 4 + "url": "https://polygon.drpc.org", + "ws_url": "wss://polygon.drpc.org" }, { - "ticker": "AAVE-PLG20", - "required_confirmations": 4 + "url": "https://polygon.gateway.tenderly.co", + "ws_url": "wss://polygon.gateway.tenderly.co" } ], "required_confirmations": 5, - "requires_notarization": false - } + "requires_notarization": false, + "swap_contract_address": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", + "swap_v2_contracts": { + "maker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", + "nft_maker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", + "taker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE" + }, + "ticker": "MATIC", + "tx_history": false + }, + "userpass": "RPC_UserP@SSW0RD" }, "EnableEthWithTokensMaticNft": { - "userpass": "RPC_UserP@SSW0RD", "method": "enable_eth_with_tokens", "mmrpc": "2.0", "params": { - "ticker": "MATIC", + "erc20_tokens_requests": [ + { + "required_confirmations": 4, + "ticker": "PGX-PLG20" + }, + { + "required_confirmations": 4, + "ticker": "AAVE-PLG20" + } + ], + "fallback_swap_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", + "gas_station_url": "https://gasstation-mainnet.matic.network/", "get_balances": false, - "tx_history": false, "nft_req": { - "type": "Moralis", - "info": { - "url": "https://moralis-proxy.komodo.earth" + "provider": { + "info": { + "url": "https://moralis-proxy.komodo.earth" + }, + "type": "Moralis" } }, - "gas_station_url": "https://gasstation-mainnet.matic.network/", - "swap_contract_address": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", - "fallback_swap_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", "nodes": [ - { - "url": "https://node.komodo.earth:8080/polygon", - "komodo_proxy": true - }, { "url": "https://pol3.cipig.net:18755", "ws_url": "wss://pol3.cipig.net:38755" @@ -226,599 +221,647 @@ { "url": "https://polygon-bor-rpc.publicnode.com", "ws_url": "wss://polygon-bor-rpc.publicnode.com" - } - ], - "erc20_tokens_requests": [ - { - "ticker": "PGX-PLG20", - "required_confirmations": 4 }, { - "ticker": "AAVE-PLG20", - "required_confirmations": 4 + "url": "https://polygon.gateway.tenderly.co", + "ws_url": "wss://polygon.gateway.tenderly.co" } ], "required_confirmations": 5, - "requires_notarization": false - } + "requires_notarization": false, + "swap_contract_address": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", + "ticker": "MATIC", + "tx_history": false + }, + "userpass": "RPC_UserP@SSW0RD" }, "EnableEthWithTokensWalletConnect": { - "userpass": "RPC_UserP@SSW0RD", "method": "enable_eth_with_tokens", "mmrpc": "2.0", "params": { - "ticker": "ETH", - "gas_station_url": "https://ethgasstation.info/json/ethgasAPI.json", + "erc20_tokens_requests": [ + { + "required_confirmations": 4, + "ticker": "PEPE-ERC20" + } + ], + "fallback_swap_contract": "0x8500AFc0bc5214728082163326C2FF0C73f4a871", "gas_station_decimals": 8, "gas_station_policy": { "policy": "MeanAverageFast" }, + "gas_station_url": "https://ethgasstation.info/json/ethgasAPI.json", "mm2": 1, - "rpc_mode": "Default", - "priv_key_policy": { - "type": "WalletConnect", - "data": "3569914dd09a5cc4ac92dedab354f06ff5db17ef616233a8ba562cbea51269fd" - }, - "swap_contract_address": "0x24ABE4c71FC658C91313b6552cd40cD808b3Ea80", - "fallback_swap_contract": "0x8500AFc0bc5214728082163326C2FF0C73f4a871", "nodes": [ { - "url": "https://eth3.cipig.net:18555", - "ws_url": "wss://eth3.cipig.net:38555" + "url": "https://eth.drpc.org", + "ws_url": "wss://eth.drpc.org" }, { - "url": "https://node.komodo.earth:8080/ethereum", - "komodo_proxy": true + "url": "https://eth3.cipig.net:18555", + "ws_url": "wss://eth3.cipig.net:38555" }, { - "url": "https://ethereum-rpc.publicnode.com", - "ws_url": "wss://ethereum-rpc.publicnode.com" + "url": "https://mainnet.gateway.tenderly.co", + "ws_url": "wss://mainnet.gateway.tenderly.co" } ], - "tx_history": true, - "erc20_tokens_requests": [ - { - "ticker": "PEPE-ERC20", - "required_confirmations": 4 - } - ], - "required_confirmations": 5 - } + "priv_key_policy": { + "data": "3569914dd09a5cc4ac92dedab354f06ff5db17ef616233a8ba562cbea51269fd", + "type": "WalletConnect" + }, + "required_confirmations": 5, + "rpc_mode": "Default", + "swap_contract_address": "0x24ABE4c71FC658C91313b6552cd40cD808b3Ea80", + "ticker": "ETH", + "tx_history": true + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "EnableSia": { + "id": 9, + "method": "enable_sia", + "mmrpc": "2.0", + "params": { + "activation_params": { + "client_conf": { + "headers": {}, + "server_url": "https://sia-walletd.komodo.earth/" + }, + "required_confirmations": 3, + "tx_history": true + }, + "client_id": 0, + "ticker": "SIA" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "EnableSiaInit": { + "id": 1, + "method": "enable_sia::init", + "mmrpc": "2.0", + "params": { + "activation_params": { + "client_conf": { + "headers": {}, + "server_url": "https://sia-walletd.komodo.earth/" + }, + "required_confirmations": 3, + "tx_history": true + }, + "client_id": 0, + "ticker": "SIA" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "EnableSiaStatus": { + "id": 2, + "method": "enable_sia::status", + "mmrpc": "2.0", + "params": { + "forget_if_finished": true, + "task_id": 12345 + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "EnableTendermintTokenBasic": { + "method": "enable_tendermint_token", + "mmrpc": "2.0", + "params": { + "activation_params": { + "required_confirmations": 3 + }, + "ticker": "ATOM-IBC_IRIS" + }, + "userpass": "RPC_UserP@SSW0RD" }, "EnableTendermintWithAssetsBalancesFalse": { "method": "enable_tendermint_with_assets", - "userpass": "RPC_UserP@SSW0RD", "mmrpc": "2.0", "params": { - "ticker": "IRIS", - "tokens_params": [ - { - "ticker": "ATOM-IBC_IRIS" - } - ], + "get_balances": false, + "mm2": 1, "nodes": [ { - "url": "https://iris-rpc.alpha.komodo.earth/", - "api_url": "https://iris-api.alpha.komodo.earth/", - "grpc_url": "https://iris-grpc.alpha.komodo.earth/", - "ws_url": "wss://iris-rpc.alpha.komodo.earth/websocket" + "url": "https://iris-rpc.publicnode.com" }, { "url": "https://rpc.irishub-1.irisnet.org" } ], - "tx_history": true, - "get_balances": false - } - }, - "EnableTendermintWithAssetsBalancesTrue": { - "method": "enable_tendermint_with_assets", - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", - "params": { "ticker": "IRIS", "tokens_params": [ { "ticker": "ATOM-IBC_IRIS" } ], - "nodes": [ - { - "url": "https://iris-rpc.alpha.komodo.earth/", - "api_url": "https://iris-api.alpha.komodo.earth/", - "grpc_url": "https://iris-grpc.alpha.komodo.earth/", - "ws_url": "wss://iris-rpc.alpha.komodo.earth/websocket" - }, - { - "url": "https://rpc.irishub-1.irisnet.org" - } - ], - "get_balances": true - } + "tx_history": true + }, + "userpass": "RPC_UserP@SSW0RD" }, - "EnableTendermintWithAssetsWalletConnect": { - "userpass": "RPC_UserP@SSW0RD", + "EnableTendermintWithAssetsBalancesTrue": { "method": "enable_tendermint_with_assets", "mmrpc": "2.0", "params": { - "ticker": "ATOM", - "tx_history": true, "get_balances": true, - "activation_params": { - "priv_key_policy": { - "type": "WalletConnect", - "data": "3569914dd09a5cc4ac92dedab354f06ff5db17ef616233a8ba562cbea51269fd" - } - }, "nodes": [ { - "url": "https://cosmos-rpc.alpha.komodo.earth/", - "api_url": "https://cosmos-api.alpha.komodo.earth/", - "grpc_url": "https://cosmos-grpc.alpha.komodo.earth/", - "ws_url": "wss://cosmos-rpc.alpha.komodo.earth/websocket" - }, - { - "url": "https://cosmoshub.rpc.stakin-nodes.com/" + "url": "https://iris-rpc.publicnode.com" }, { - "url": "https://node.komodo.earth:8080/cosmos", - "komodo_proxy": true + "url": "https://rpc.irishub-1.irisnet.org" } ], - "tokens_params": [] - } - }, - "EnableBchWithTokensTxHistory": { - "userpass": "RPC_UserP@SSW0RD", - "method": "enable_bch_with_tokens", - "mmrpc": "2.0", - "params": { - "ticker": "BCH", - "allow_slp_unsafe_conf": false, - "bchd_urls": [ - "https://bchd.dragonhound.info" - ], - "mode": { - "rpc": "Electrum", - "rpc_data": { - "servers": [ - { - "url": "bch.electrum3.cipig.net:10055", - "protocol": "TCP" - }, - { - "url": "bch.electrum3.cipig.net:20055", - "protocol": "SSL" - }, - { - "url": "bch.electrum3.cipig.net:30055", - "protocol": "WSS" - } - ] - } - }, - "tx_history": true, - "slp_tokens_requests": [ + "required_confirmations": 3, + "requires_notarization": false, + "ticker": "IRIS", + "tokens_params": [ { - "ticker": "ASLP-SLP", - "required_confirmations": 4 + "ticker": "ATOM-IBC_IRIS" } - ], - "required_confirmations": 5, - "requires_notarization": false, - "address_format": { - "format": "cashaddress", - "network": "bitcoincash" - }, - "utxo_merge_params": { - "merge_at": 50, - "check_every": 10, - "max_merge_at_once": 25 - } - } - }, - "EnableBchWithTokensBalancesFalse": { - "userpass": "RPC_UserP@SSW0RD", - "method": "enable_bch_with_tokens", + ] + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "EnableTendermintWithAssetsWalletConnect": { + "method": "enable_tendermint_with_assets", "mmrpc": "2.0", "params": { - "ticker": "BCH", - "allow_slp_unsafe_conf": false, - "bchd_urls": [ - "https://bchd.dragonhound.info" - ], - "mode": { - "rpc": "Electrum", - "rpc_data": { - "servers": [ - { - "url": "bch.electrum3.cipig.net:10055", - "protocol": "TCP" - }, - { - "url": "bch.electrum3.cipig.net:20055", - "protocol": "SSL" - }, - { - "url": "bch.electrum3.cipig.net:30055", - "protocol": "WSS" - } - ] + "activation_params": { + "priv_key_policy": { + "data": "3569914dd09a5cc4ac92dedab354f06ff5db17ef616233a8ba562cbea51269fd", + "type": "WalletConnect" } }, - "tx_history": true, - "get_balances": false, - "slp_tokens_requests": [ + "get_balances": true, + "nodes": [ + { + "api_url": "https://cosmos-api.alpha.komodo.earth/", + "grpc_url": "https://cosmos-grpc.alpha.komodo.earth/", + "url": "https://cosmos-rpc.alpha.komodo.earth/", + "ws_url": "wss://cosmos-rpc.alpha.komodo.earth/websocket" + }, { - "ticker": "ASLP-SLP", - "required_confirmations": 4 + "url": "https://cosmoshub.rpc.stakin-nodes.com/" } - ] - } + ], + "ticker": "ATOM", + "tokens_params": [], + "tx_history": true + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableQtumInit": { - "userpass": "RPC_UserP@SSW0RD", + "TaskEnableBchCancel": { + "method": "task::enable_bch::cancel", + "mmrpc": "2.0", + "params": { + "task_id": 3 + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "TaskEnableBchInit": { + "method": "task::enable_bch::init", "mmrpc": "2.0", - "method": "task::enable_qtum::init", "params": { - "ticker": "QTUM", "activation_params": { + "address_format": { + "format": "cashaddress", + "network": "bitcoincash" + }, + "bchd_urls": [ + "https://bchd.dragonhound.info" + ], "mode": { "rpc": "Electrum", "rpc_data": { "servers": [ { - "url": "qtum.electrum1.cipig.net:30050", - "protocol": "WSS" + "protocol": "SSL", + "url": "bch.electrum3.cipig.net:20055" }, { - "url": "qtum.electrum3.cipig.net:10050", - "protocol": "TCP" + "protocol": "SSL", + "url": "bch.imaginary.cash:50002" }, { - "url": "qtum.electrum3.cipig.net:30050", - "protocol": "WSS" + "protocol": "SSL", + "url": "bch.soul-dev.com:50002" } ] } }, - "scan_policy": "scan_if_new_wallet", - "priv_key_policy": { - "type": "Trezor" - }, - "min_addresses_number": 3, - "gap_limit": 20 - } - } + "required_confirmations": 5, + "requires_notarization": false, + "slp_tokens_requests": [ + { + "required_confirmations": 3, + "ticker": "ASLP-SLP" + }, + { + "ticker": "USDF" + } + ], + "tx_history": true, + "utxo_merge_params": { + "check_every": 10, + "max_merge_at_once": 25, + "merge_at": 50 + } + }, + "ticker": "BCH" + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableQtumStatus": { - "userpass": "RPC_UserP@SSW0RD", + "TaskEnableBchStatus": { + "method": "task::enable_bch::status", + "mmrpc": "2.0", + "params": { + "forget_if_finished": false, + "task_id": 0 + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "TaskEnableBchUserActionPin": { + "method": "task::enable_bch::user_action", "mmrpc": "2.0", - "method": "task::enable_qtum::status", "params": { "task_id": 0, - "forget_if_finished": false - } + "user_action": { + "action_type": "TrezorPin", + "pin": "862743" + } + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableQtumUserAction": { - "userpass": "RPC_UserP@SSW0RD", + "TaskEnableEthCancel": { + "method": "task::enable_eth::cancel", + "mmrpc": "2.0", + "params": { + "task_id": 3 + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "TaskEnableEthInitTrezor": { + "method": "task::enable_eth::init", + "mmrpc": "2.0", + "params": { + "erc20_tokens_requests": [ + { + "required_confirmations": 4, + "ticker": "PGX-PLG20" + }, + { + "required_confirmations": 4, + "ticker": "AAVE-PLG20" + } + ], + "fallback_swap_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", + "gap_limit": 20, + "gas_station_url": "https://gasstation-mainnet.matic.network/", + "min_addresses_number": 3, + "nodes": [ + { + "url": "https://pol3.cipig.net:18755", + "ws_url": "wss://pol3.cipig.net:38755" + }, + { + "url": "https://polygon.drpc.org", + "ws_url": "wss://polygon.drpc.org" + }, + { + "url": "https://polygon.gateway.tenderly.co", + "ws_url": "wss://polygon.gateway.tenderly.co" + } + ], + "path_to_address": { + "account_id": 0, + "address_id": 1, + "chain": "External" + }, + "required_confirmations": 5, + "scan_policy": "scan_if_new_wallet", + "swap_contract_address": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", + "swap_v2_contracts": { + "maker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", + "nft_maker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE", + "taker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE" + }, + "ticker": "MATIC" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "TaskEnableEthStatus": { + "method": "task::enable_eth::status", + "mmrpc": "2.0", + "params": { + "forget_if_finished": false, + "task_id": 1 + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "TaskEnableEthUserActionPin": { + "method": "task::enable_eth::user_action", "mmrpc": "2.0", - "method": "task::enable_qtum::user_action", "params": { "task_id": 0, "user_action": { "action_type": "TrezorPin", "pin": "862743" } - } + }, + "userpass": "RPC_UserP@SSW0RD" }, "TaskEnableQtumCancel": { - "userpass": "RPC_UserP@SSW0RD", "method": "task::enable_qtum::cancel", "mmrpc": "2.0", "params": { "task_id": 3 - } + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableUtxoInit": { - "userpass": "RPC_UserP@SSW0RD", + "TaskEnableQtumInit": { + "method": "task::enable_qtum::init", "mmrpc": "2.0", - "method": "task::enable_utxo::init", "params": { - "ticker": "KMD", "activation_params": { + "gap_limit": 20, + "min_addresses_number": 3, "mode": { "rpc": "Electrum", "rpc_data": { "servers": [ { - "url": "kmd.electrum3.cipig.net:20001", - "protocol": "SSL" + "protocol": "SSL", + "url": "qtum.electrum1.cipig.net:20050" }, { - "url": "kmd.electrum3.cipig.net:10001", - "protocol": "TCP" + "protocol": "SSL", + "url": "qtum.electrum2.cipig.net:20050" }, { - "url": "kmd.electrum2.cipig.net:30001", - "protocol": "WSS" + "protocol": "SSL", + "url": "qtum.electrum3.cipig.net:20050" } ] } }, - "scan_policy": "scan_if_new_wallet", - "priv_key_policy": { - "type": "Trezor" - }, - "min_addresses_number": 3, - "gap_limit": 20 - } - } + "priv_key_policy": "ContextPrivKey", + "scan_policy": "scan_if_new_wallet" + }, + "ticker": "QTUM" + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableUtxoStatus": { - "userpass": "RPC_UserP@SSW0RD", + "TaskEnableQtumStatus": { + "method": "task::enable_qtum::status", "mmrpc": "2.0", - "method": "task::enable_utxo::status", "params": { - "task_id": 1, - "forget_if_finished": false - } + "forget_if_finished": false, + "task_id": 0 + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableUtxoUserAction": { - "userpass": "RPC_UserP@SSW0RD", + "TaskEnableQtumUserActionPin": { + "method": "task::enable_qtum::user_action", "mmrpc": "2.0", - "method": "task::enable_utxo::user_action", "params": { - "task_id": 1, + "task_id": 0, "user_action": { "action_type": "TrezorPin", "pin": "862743" } - } + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableUtxoCancel": { - "userpass": "RPC_UserP@SSW0RD", - "method": "task::enable_utxo::cancel", + "TaskEnableTendermintCancel": { + "method": "task::enable_tendermint::cancel", "mmrpc": "2.0", "params": { - "task_id": 1 - } + "task_id": 3 + }, + "userpass": "RPC_UserP@SSW0RD" }, "TaskEnableTendermintInit": { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", "method": "task::enable_tendermint::init", + "mmrpc": "2.0", "params": { - "ticker": "IRIS", - "tokens_params": [ - { - "ticker": "ATOM-IBC_IRIS" - } - ], "nodes": [ { - "url": "https://iris-rpc.alpha.komodo.earth/", - "api_url": "https://iris-api.alpha.komodo.earth/", - "grpc_url": "https://iris-grpc.alpha.komodo.earth/", - "ws_url": "wss://iris-rpc.alpha.komodo.earth/websocket" + "url": "https://iris-rpc.publicnode.com" }, { "url": "https://rpc.irishub-1.irisnet.org" } + ], + "ticker": "IRIS", + "tokens_params": [ + { + "ticker": "ATOM-IBC_IRIS" + } ] - } + }, + "userpass": "RPC_UserP@SSW0RD" }, "TaskEnableTendermintStatus": { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", "method": "task::enable_tendermint::status", + "mmrpc": "2.0", "params": { - "task_id": 0, - "forget_if_finished": false - } + "forget_if_finished": false, + "task_id": 0 + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableTendermintUserAction": { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", + "TaskEnableTendermintUserActionPin": { "method": "task::enable_tendermint::user_action", + "mmrpc": "2.0", "params": { "task_id": 0, "user_action": { "action_type": "TrezorPin", "pin": "862743" } - } + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableTendermintCancel": { - "userpass": "RPC_UserP@SSW0RD", - "method": "task::enable_tendermint::cancel", + "TaskEnableUtxoCancel": { + "method": "task::enable_utxo::cancel", "mmrpc": "2.0", "params": { - "task_id": 3 - } + "task_id": 1 + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableBchInit": { - "userpass": "RPC_UserP@SSW0RD", + "TaskEnableUtxoInit": { + "method": "task::enable_utxo::init", "mmrpc": "2.0", - "method": "task::enable_bch::init", "params": { - "ticker": "BCH", "activation_params": { - "bchd_urls": [ - "https://bchd.dragonhound.info" - ], + "gap_limit": 20, + "min_addresses_number": 3, "mode": { "rpc": "Electrum", "rpc_data": { "servers": [ { - "url": "bch.electrum3.cipig.net:10055", - "protocol": "TCP" + "protocol": "SSL", + "url": "kmd.electrum1.cipig.net:20001" }, { - "url": "bch.electrum3.cipig.net:20055", - "protocol": "SSL" + "protocol": "SSL", + "url": "kmd.electrum2.cipig.net:20001" }, { - "url": "bch.electrum3.cipig.net:30055", - "protocol": "WSS" + "protocol": "SSL", + "url": "kmd.electrum3.cipig.net:20001" } ] } }, - "slp_tokens_requests": [ - { - "ticker": "USDF" - }, - { - "ticker": "ASLP-SLP", - "required_confirmations": 3 - } - ], - "tx_history": true, - "required_confirmations": 5, - "requires_notarization": false, - "address_format": { - "format": "cashaddress", - "network": "bitcoincash" - }, - "utxo_merge_params": { - "merge_at": 50, - "check_every": 10, - "max_merge_at_once": 25 - } - } - } + "priv_key_policy": "ContextPrivKey", + "scan_policy": "scan_if_new_wallet" + }, + "ticker": "KMD" + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableBchStatus": { - "userpass": "RPC_UserP@SSW0RD", + "TaskEnableUtxoStatus": { + "method": "task::enable_utxo::status", "mmrpc": "2.0", - "method": "task::enable_bch::status", "params": { - "task_id": 0, - "forget_if_finished": false - } + "forget_if_finished": false, + "task_id": 1 + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableBchUserAction": { - "userpass": "RPC_UserP@SSW0RD", + "TaskEnableUtxoUserActionPin": { + "method": "task::enable_utxo::user_action", "mmrpc": "2.0", - "method": "task::enable_bch::user_action", "params": { - "task_id": 0, + "task_id": 1, "user_action": { "action_type": "TrezorPin", "pin": "862743" } - } + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableBchCancel": { - "userpass": "RPC_UserP@SSW0RD", - "method": "task::enable_bch::cancel", + "TaskEnableZCoinCancel": { + "method": "task::enable_z_coin::cancel", "mmrpc": "2.0", "params": { "task_id": 3 - } + }, + "userpass": "RPC_UserP@SSW0RD" }, "TaskEnableZCoinInitBasic": { - "userpass": "RPC_UserP@SSW0RD", "method": "task::enable_z_coin::init", "mmrpc": "2.0", "params": { - "ticker": "ZOMBIE", "activation_params": { "mode": { "rpc": "Light", "rpc_data": { "electrum_servers": [ { - "url": "zombie.dragonhound.info:10133", - "protocol": "TCP" - }, - { - "url": "zombie.dragonhound.info:20133", - "protocol": "SSL" + "protocol": "SSL", + "url": "zombie.dragonhound.info:20133" }, { - "url": "zombie.dragonhound.info:30059", - "protocol": "WSS" + "protocol": "TCP", + "url": "zombie.dragonhound.info:10133" } ], "light_wallet_d_servers": [ - "https://zombie.dragonhound.info:1443" + "https://zombie.dragonhound.info:9447" ] } }, - "zcash_params_path": "/home/username/path_to/.zcash-params", "scan_blocks_per_iteration": 100, - "scan_interval_ms": 200 - } - } + "scan_interval_ms": 200, + "zcash_params_path": "/home/username/path_to/.zcash-params" + }, + "ticker": "ZOMBIE" + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableZCoinInitWithSyncParams": { - "userpass": "RPC_UserP@SSW0RD", + "TaskEnableZCoinInitWasm": { "method": "task::enable_z_coin::init", "mmrpc": "2.0", "params": { - "ticker": "ZOMBIE", "activation_params": { "mode": { "rpc": "Light", "rpc_data": { "electrum_servers": [ { - "url": "zombie.dragonhound.info:10133", - "protocol": "TCP" - }, + "protocol": "WSS", + "url": "zombie.dragonhound.info:30059" + } + ], + "light_wallet_d_servers": [ + "https://zombie.dragonhound.info:19447" + ] + } + }, + "tx_history": true + }, + "ticker": "ZOMBIE" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "TaskEnableZCoinInitWithSyncParams": { + "method": "task::enable_z_coin::init", + "mmrpc": "2.0", + "params": { + "activation_params": { + "mode": { + "rpc": "Light", + "rpc_data": { + "electrum_servers": [ { - "url": "zombie.dragonhound.info:20133", - "protocol": "SSL" + "protocol": "SSL", + "url": "zombie.dragonhound.info:20133" }, { - "url": "zombie.dragonhound.info:30059", - "protocol": "WSS" + "protocol": "TCP", + "url": "zombie.dragonhound.info:10133" } ], "light_wallet_d_servers": [ - "https://zombie.dragonhound.info:1443" + "https://zombie.dragonhound.info:9447" ], "sync_params": { "height": 2528700 } } }, - "zcash_params_path": "/home/username/path_to/.zcash-params", "scan_blocks_per_iteration": 100, - "scan_interval_ms": 200 - } - } + "scan_interval_ms": 200, + "zcash_params_path": "/home/username/path_to/.zcash-params" + }, + "ticker": "ZOMBIE" + }, + "userpass": "RPC_UserP@SSW0RD" }, "TaskEnableZCoinStatus": { - "userpass": "RPC_UserP@SSW0RD", "method": "task::enable_z_coin::status", "mmrpc": "2.0", "params": { - "task_id": 0, - "forget_if_finished": false - } + "forget_if_finished": false, + "task_id": 0 + }, + "userpass": "RPC_UserP@SSW0RD" }, - "TaskEnableZCoinUserAction": { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", + "TaskEnableZCoinUserActionPin": { "method": "task::enable_z_coin::user_action", + "mmrpc": "2.0", "params": { "task_id": 3, "user_action": { "action_type": "TrezorPin", "pin": "862743" } - } - }, - "TaskEnableZCoinCancel": { - "userpass": "RPC_UserP@SSW0RD", - "method": "task::enable_z_coin::cancel", - "mmrpc": "2.0", - "params": { - "task_id": 3 - } + }, + "userpass": "RPC_UserP@SSW0RD" } } \ No newline at end of file diff --git a/src/data/requests/kdf/v2/utils.json b/src/data/requests/kdf/v2/utils.json new file mode 100644 index 000000000..c57531481 --- /dev/null +++ b/src/data/requests/kdf/v2/utils.json @@ -0,0 +1,12 @@ +{ + "AddNodeToVersionStat": { + "method": "add_node_to_version_stat", + "mmrpc": "2.0", + "params": { + "address": "168.119.236.241", + "name": "seed1", + "peer_id": "12D3KooWEsuiKcQaBaKEzuMtT6uFjs89P1E8MK3wGRZbeuCbCw6P" + }, + "userpass": "RPC_UserP@SSW0RD" + } +} \ No newline at end of file diff --git a/src/data/requests/kdf/v2/wallet.json b/src/data/requests/kdf/v2/wallet.json new file mode 100644 index 000000000..e3f5d8ba5 --- /dev/null +++ b/src/data/requests/kdf/v2/wallet.json @@ -0,0 +1,451 @@ +{ + "ConsolidateUtxos": { + "method": "consolidate_utxos", + "mmrpc": "2.0", + "params": { + "coin": "MARTY", + "merge_conditions": { + "max_merge_at_once": 2, + "merge_at": 2 + } + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "GetRawTransactionDoc": { + "id": 1, + "method": "get_raw_transaction", + "mmrpc": "2.0", + "params": { + "coin": "DOC", + "tx_hash": "eb17aa87eececc3c0144432a97b5effa9f2b3e338083bf17fade8f557bf834e5" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "GetRawTransactionEth": { + "id": 1, + "method": "get_raw_transaction", + "mmrpc": "2.0", + "params": { + "coin": "ETH", + "tx_hash": "0x529aca42b6b592cca5d400832c83854135b924cada6e1c41b85f27fa0a0984b9" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "FetchUtxos": { + "method": "fetch_utxos", + "mmrpc": "2.0", + "params": { + "coin": "MARTY" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "GetMyAddress": { + "id": 4, + "method": "get_my_address", + "mmrpc": "2.0", + "params": { + "coin": "SIA" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "GetPrivateKeysHd": { + "method": "get_private_keys", + "mmrpc": "2.0", + "params": { + "account_index": 0, + "coins": [ + "ARRR", + "ATOM", + "ETH", + "KMD", + "LTC-segwit" + ], + "end_index": 1, + "mode": "hd", + "start_index": 0 + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "GetPrivateKeysIguana": { + "method": "get_private_keys", + "mmrpc": "2.0", + "params": { + "coins": [ + "ARRR", + "ATOM", + "ETH", + "KMD", + "LTC-segwit" + ], + "mode": "iguana" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "GetRawTransactionSia": { + "id": 7, + "method": "get_raw_transaction", + "mmrpc": "2.0", + "params": { + "coin": "SIA", + "tx_hash": "h:abcdef...1234" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistoryAccountDoc": { + "method": "my_tx_history", + "mmrpc": "2.0", + "params": { + "coin": "DOC", + "limit": 10, + "paging_options": { + "PageNumber": 1 + }, + "target": { + "account_id": 77, + "type": "account_id" + } + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistoryAddressDoc": { + "method": "my_tx_history", + "mmrpc": "2.0", + "params": { + "coin": "DOC", + "limit": 1, + "paging_options": { + "PageNumber": 1 + }, + "target": { + "account_id": 0, + "address_id": 1, + "chain": "External", + "type": "address_id" + } + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistoryBchFromId": { + "method": "my_tx_history", + "mmrpc": "2.0", + "params": { + "coin": "BCH", + "limit": 2, + "paging_options": { + "FromId": "433b641bc89e1b59c22717918583c60ec98421805c8e85b064691705d9aeb970" + } + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistoryBchPage2": { + "method": "my_tx_history", + "mmrpc": "2.0", + "params": { + "coin": "BCH", + "limit": 2, + "paging_options": { + "PageNumber": 2 + } + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistoryIrisLimit50": { + "method": "my_tx_history", + "mmrpc": "2.0", + "params": { + "coin": "IRIS", + "limit": 50 + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "MyTxHistorySiaUnsupported": { + "method": "my_tx_history", + "mmrpc": "2.0", + "params": { + "coin": "SC", + "limit": 50 + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "SendRawTransaction": { + "id": 6, + "method": "send_raw_transaction", + "mmrpc": "2.0", + "params": { + "coin": "SIA", + "tx_json": { + "minerFee": "10000000000000000000", + "siacoinInputs": [], + "siacoinOutputs": [] + } + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "ValidateAddress": { + "id": 8, + "method": "validateaddress", + "mmrpc": "2.0", + "params": { + "address": "addr:1599ea80d9af168c...17030fb3", + "coin": "SIA" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawBroadcastTrue": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": 0.1, + "broadcast": true, + "coin": "MATIC", + "to": "0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawDocFixedFee": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": "1.0", + "coin": "DOC", + "fee": { + "amount": "0.1", + "type": "UtxoFixed" + }, + "to": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawDocPerKbyte": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": "1.0", + "coin": "DOC", + "fee": { + "amount": "1", + "type": "UtxoPerKbyte" + }, + "to": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawEth": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": 10, + "coin": "ETH", + "to": "0xbab36286672fbdc7b250804bf6d14be0df69fa28" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawEthGas": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": "AMOUNT", + "coin": "COIN_NAME", + "fee": { + "gas": 55000, + "gas_price": "3.5", + "type": "EthGas" + }, + "to": "RECIPIENT_ADDRESS" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawEthMax": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "coin": "ETH", + "max": true, + "to": "0xbab36286672fbdc7b250804bf6d14be0df69fa28" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawIbcAtom": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": 0.1, + "coin": "ATOM", + "fee": { + "gas_limit": 150000, + "gas_price": 0.05, + "type": "CosmosGas" + }, + "ibc_source_channel": 141, + "memo": "In the blackest of your moments, wait with no fear.", + "to": "osmo16drqvl3u8sukfsu4lm3qsk28jr3fahjac4rdw4" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawIrisMemoCosmosGas": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": 13, + "coin": "IRIS", + "fee": { + "gas_limit": 150000, + "gas_price": 0.05, + "type": "CosmosGas" + }, + "memo": "It was a bright cold day in April, and the clocks were striking thirteen.", + "to": "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawKmd": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": "10", + "coin": "KMD", + "to": "RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawMartyAccountId": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": 0.01, + "broadcast": true, + "coin": "MARTY", + "from": { + "account_id": 0, + "address_id": 1, + "chain": "External" + }, + "to": "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawMartyDerivationPath": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": 1.025, + "broadcast": true, + "coin": "MARTY", + "from": { + "derivation_path": "m/44'/141'/0'/0/0" + }, + "to": "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawMartyFixedFee": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": "1.0", + "broadcast": true, + "coin": "MARTY", + "fee": { + "amount": "0.1", + "type": "UtxoFixed" + }, + "from": { + "derivation_path": "m/44'/141'/0'/0/0" + }, + "to": "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawMartyNonHD": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": "0.1", + "broadcast": true, + "coin": "MARTY", + "to": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawMartyPerKbyte": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": "1.0", + "broadcast": true, + "coin": "MARTY", + "fee": { + "amount": "1", + "type": "UtxoPerKbyte" + }, + "from": { + "derivation_path": "m/44'/141'/0'/0/0" + }, + "to": "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawQrc20": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": 10, + "coin": "QRC20", + "to": "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawQrc20Gas": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": 10, + "coin": "QRC20", + "fee": { + "gas_limit": 250000, + "gas_price": 40, + "type": "Qrc20Gas" + }, + "to": "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawSia": { + "id": 5, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "amount": "1", + "coin": "SIA", + "to": "addr:1d9a926b1e14b542...8204" + }, + "userpass": "RPC_UserP@SSW0RD" + }, + "WithdrawSiaProtocol": { + "id": 0, + "method": "withdraw", + "mmrpc": "2.0", + "params": { + "coin": "SC", + "max": true, + "to": "c67d77a585c13727dbba57cfc115995beb9b8737e9a8cb7bb0aa208744e646cdc0acc9c9fce2" + }, + "userpass": "RPC_UserP@SSW0RD" + } +} \ No newline at end of file diff --git a/src/data/responses/kdf/common.json b/src/data/responses/kdf/common.json new file mode 100644 index 000000000..746875281 --- /dev/null +++ b/src/data/responses/kdf/common.json @@ -0,0 +1,57 @@ +{ + "CancelTaskId": { + "title": "Success", + "notes": "The task has been cancelled successfully.", + "json": { + "mmrpc": "2.0", + "result": "success", + "id": null + } + }, + "NoSuchTask": { + "title": "NoSuchTask", + "notes": "You'll see this if the task number does not exist, or the task has already completed.", + "json": { + "mmrpc": "2.0", + "error": "No such task '1'", + "error_path": "init_standalone_coin", + "error_trace": "init_standalone_coin:119]", + "error_type": "NoSuchTask", + "error_data": 1, + "id": null + } + }, + "SuccessTaskId": { + "title": "Success", + "notes": "The task has been initiated successfully.", + "json": { + "mmrpc": "2.0", + "result": { + "task_id": 0 + }, + "id": null + } + }, + "TaskFinished": { + "title": "NoSuchTask", + "notes": "You'll see this if the task has already completed.", + "json": { + "mmrpc": "2.0", + "error": "Task is finished already", + "error_path": "init_standalone_coin.manager", + "error_trace": "init_standalone_coin:165] manager:138]", + "error_type": "TaskFinished", + "error_data": 0, + "id": null + } + }, + "UserActionSuccess": { + "title": "Success", + "notes": "The request was successful.", + "json": { + "mmrpc": "2.0", + "result": "success", + "id": null + } + } +} \ No newline at end of file diff --git a/src/data/responses/kdf/legacy/coin_activation.json b/src/data/responses/kdf/legacy/coin_activation.json index a9137df67..f3b38d0ab 100644 --- a/src/data/responses/kdf/legacy/coin_activation.json +++ b/src/data/responses/kdf/legacy/coin_activation.json @@ -1,266 +1,388 @@ { - "LegacyEnableEth": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "address": "0x7Bc1bBDD6A0a722fC9bffc49c921B685ECB84b94", - "balance": "12.00283000", - "locked_by_swaps": "0.00000000", - "required_confirmations": 1, - "requires_notarization": false, - "mature_confirmations": 0, - "result": "success" - } - } - ], - "error": [ - ] - }, - "LegacyElectrumBch": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "address": "1DgpBvyeUNHasBt3h3qzC1p9Z8qTgr6t5m", - "balance": "0.12345678", - "required_confirmations": 1, - "requires_notarization": false, - "result": "success" - } - } - ], - "error": [ - { - "title": "Connection failed", - "notes": "Unable to connect to electrum servers", - "json": { - "error": "All electrum servers for BCH are unavailable" - } - } - ] - }, - "LegacyElectrumKmd": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "KMD", - "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ", - "balance": "762", - "unspendable_balance": "0", - "mature_confirmations": 100, - "required_confirmations": 10, - "requires_notarization": true, - "result": "success" - } - } - ], - "error": [ - { - "title": "Missing mm2 parameter", - "notes": "mm2 param is not set in coins config or enable request", - "json": { - "error": "lp_coins:943] lp_coins:693] mm2 param is not set neither in coins config nor enable request, assuming that coin is not supported" - } + "LegacyElectrumBch": { + "error": [ + { + "json": { + "error": "All electrum servers for BCH are unavailable" }, - { - "title": "Invalid min_connected", - "notes": "min_connected should be greater than 0", - "json": { - "error": "rpc:184] dispatcher_legacy:141] lp_commands_legacy:141] lp_coins:4462] utxo_standard:73] utxo_coin_builder:616] Internal error: manager:129] min_connected should be greater than 0" - } + "notes": "Unable to connect to electrum servers", + "title": "Connection failed" + } + ], + "success": [ + { + "json": { + "address": "1DgpBvyeUNHasBt3h3qzC1p9Z8qTgr6t5m", + "balance": "0.12345678", + "required_confirmations": 1, + "requires_notarization": false, + "result": "success" }, - { - "title": "Invalid connection range", - "notes": "min_connected must be <= max_connected", - "json": { - "error": "rpc:184] dispatcher_legacy:141] lp_commands_legacy:141] lp_coins:4462] utxo_standard:73] utxo_coin_builder:616] Internal error: manager:132] min_connected (2) must be <= max_connected (1)" - } - } - ] - }, - "LegacyElectrumQtum": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "QTUM", - "address": "QjXkGgoiycYRm2NbiMpkEHuQt7SB9BKHjz", - "balance": "7.77", - "required_confirmations": 3, - "requires_notarization": false, - "unspendable_balance": "0", - "mature_confirmations": 100, - "result": "success" - } - } - ], - "error": [ - { - "title": "Missing mm2 parameter", - "notes": "mm2 param is not set in coins config or enable request", - "json": { - "error": "lp_coins:943] lp_coins:693] mm2 param is not set neither in coins config nor enable request, assuming that coin is not supported" - } - } - ] - }, - "LegacyEnableNative": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "TKL", - "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ", - "balance": "333", - "required_confirmations": 1, - "requires_notarization": false, - "unspendable_balance": "0", - "mature_confirmations": 100, - "result": "success" - } - } - ], - "error": [ - { - "title": "Connection failed", - "notes": "Unable to connect to daemon", - "json": { - "error": "Failed to connect to native daemon" - } - } - ] - }, - "LegacyEnableNativeWithParams": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "TKL", - "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ", - "balance": "777", - "required_confirmations": 10, - "requires_notarization": true, - "unspendable_balance": "0", - "mature_confirmations": 100, - "result": "success" - } - } - ], - "error": [ - { - "title": "Connection failed", - "notes": "Unable to connect to daemon", - "json": { - "error": "Failed to connect to native daemon" - } - } - ] - }, - "LegacyEnableEthGasStation": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "ETH", - "address": "0x3c7aad7b693e94f13b61d4be4abaeaf802b2e3b5", - "balance": "50", - "required_confirmations": 1, - "requires_notarization": false, - "unspendable_balance": "0", - "result": "success" - } - } - ], - "error": [ - { - "title": "Gas station error", - "notes": "Unable to fetch gas price from station", - "json": { - "error": "Failed to get gas price from station" - } + "notes": "", + "title": "Success" + }, + { + "json": { + "address": "bitcoincash:qqedg0nm5rcg6vs2yfzqu4dcgfq87jq7hujzrcwk5w", + "balance": "0", + "coin": "BCH", + "mature_confirmations": 100, + "required_confirmations": 1, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" }, - { - "title": "Already enabled", - "notes": "The coin is already activated", - "json": { - "error": "lp_coins:1308] eth:295] Coin ETH is already activated" - } - } - ] - }, - "LegacyEnableMatic": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "NZDS-PLG20", - "address": "0x3c7aad7b693e94f13b61d4be4abaeaf802b2e3b5", - "balance": "350", - "required_confirmations": 1, - "requires_notarization": false, - "unspendable_balance": "0", - "result": "success" - } - } - ], - "error": [ - { - "title": "Connection failed", - "notes": "Unable to connect to Polygon RPC", - "json": { - "error": "All Polygon RPC servers unavailable" - } + "title": "Success" + } + ] + }, + "LegacyElectrumDoc": { + "error": [], + "success": [ + { + "json": { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "balance": "7.62", + "coin": "DOC", + "mature_confirmations": 100, + "required_confirmations": 10, + "requires_notarization": true, + "result": "success", + "unspendable_balance": "0" }, - { - "title": "Already enabled", - "notes": "The coin is already activated", - "json": { - "error": "lp_coins:1308] Coin NZDS-PLG20 is already activated" - } - } - ] - }, - "LegacyEnableBnb": { - "success": [ - { - "title": "Success", - "notes": "", - "json": { - "coin": "BUSD-BEP20", - "address": "0x3c7aad7b693e94f13b61d4be4abaeaf802b2e3b5", - "balance": "45", - "required_confirmations": 1, - "requires_notarization": false, - "unspendable_balance": "0", - "result": "success" - } - } - ], - "error": [ - { - "title": "Connection failed", - "notes": "Unable to connect to BSC RPC", - "json": { - "error": "All BSC RPC servers unavailable" - } + "title": "Success" + } + ] + }, + "LegacyElectrumKmd": { + "error": [ + { + "json": { + "error": "rpc:184] dispatcher_legacy:141] lp_commands_legacy:141] lp_coins:4462] utxo_standard:73] utxo_coin_builder:616] Internal error: manager:132] min_connected (2) must be <= max_connected (1)" }, - { - "title": "Already enabled", - "notes": "The coin is already activated", - "json": { - "error": "lp_coins:1308] Coin BUSD-BEP20 is already activated" - } - } - ] - } - } \ No newline at end of file + "notes": "min_connected must be <= max_connected", + "title": "Invalid connection range" + }, + { + "json": { + "error": "rpc:184] dispatcher_legacy:141] lp_commands_legacy:141] lp_coins:4462] utxo_standard:73] utxo_coin_builder:616] Internal error: manager:129] min_connected should be greater than 0" + }, + "notes": "min_connected should be greater than 0", + "title": "Invalid min_connected" + }, + { + "json": { + "error": "lp_coins:943] lp_coins:693] mm2 param is not set neither in coins config nor enable request, assuming that coin is not supported" + }, + "notes": "mm2 param is not set in coins config or enable request", + "title": "Missing mm2 parameter" + } + ], + "success": [ + { + "json": { + "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ", + "balance": "762", + "coin": "KMD", + "mature_confirmations": 100, + "required_confirmations": 10, + "requires_notarization": true, + "result": "success", + "unspendable_balance": "0" + }, + "notes": "", + "title": "Success" + }, + { + "json": { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "balance": "0", + "coin": "KMD", + "mature_confirmations": 100, + "required_confirmations": 10, + "requires_notarization": true, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyElectrumMarty": { + "error": [], + "success": [ + { + "json": { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "balance": "7.62", + "coin": "MARTY", + "mature_confirmations": 100, + "required_confirmations": 10, + "requires_notarization": true, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyElectrumQtum": { + "error": [ + { + "json": { + "error": "lp_coins:943] lp_coins:693] mm2 param is not set neither in coins config nor enable request, assuming that coin is not supported" + }, + "notes": "mm2 param is not set in coins config or enable request", + "title": "Missing mm2 parameter" + } + ], + "success": [ + { + "json": { + "address": "QjXkGgoiycYRm2NbiMpkEHuQt7SB9BKHjz", + "balance": "7.77", + "coin": "QTUM", + "mature_confirmations": 100, + "required_confirmations": 3, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "notes": "", + "title": "Success" + }, + { + "json": { + "address": "QREk9sFW6sCDGcauAMoF9UuxkbnfyE6Eg5", + "balance": "0", + "coin": "QTUM", + "mature_confirmations": 2000, + "required_confirmations": 3, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyEnableBnb": { + "error": [ + { + "json": { + "error": "lp_coins:1308] Coin BUSD-BEP20 is already activated" + }, + "notes": "The coin is already activated", + "title": "Already enabled" + }, + { + "json": { + "error": "All BSC RPC servers unavailable" + }, + "notes": "Unable to connect to BSC RPC", + "title": "Connection failed" + } + ], + "success": [ + { + "json": { + "address": "0x3c7aad7b693e94f13b61d4be4abaeaf802b2e3b5", + "balance": "45", + "coin": "BUSD-BEP20", + "required_confirmations": 1, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "notes": "", + "title": "Success" + }, + { + "json": { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "balance": "0", + "coin": "BUSD-BEP20", + "required_confirmations": 3, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyEnableEth": { + "error": [], + "success": [ + { + "json": { + "address": "0x7Bc1bBDD6A0a722fC9bffc49c921B685ECB84b94", + "balance": "12.00283000", + "locked_by_swaps": "0.00000000", + "mature_confirmations": 0, + "required_confirmations": 1, + "requires_notarization": false, + "result": "success" + }, + "notes": "", + "title": "Success" + }, + { + "json": { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "balance": "0", + "coin": "ETH", + "required_confirmations": 3, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyEnableEthGasStation": { + "error": [ + { + "json": { + "error": "lp_coins:1308] eth:295] Coin ETH is already activated" + }, + "notes": "The coin is already activated", + "title": "Already enabled" + }, + { + "json": { + "error": "Failed to get gas price from station" + }, + "notes": "Unable to fetch gas price from station", + "title": "Gas station error" + } + ], + "success": [ + { + "json": { + "address": "0x3c7aad7b693e94f13b61d4be4abaeaf802b2e3b5", + "balance": "50", + "coin": "ETH", + "required_confirmations": 1, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "notes": "", + "title": "Success" + }, + { + "json": { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "balance": "0", + "coin": "ETH", + "required_confirmations": 3, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyEnableMatic": { + "error": [ + { + "json": { + "error": "lp_coins:1308] Coin NZDS-PLG20 is already activated" + }, + "notes": "The coin is already activated", + "title": "Already enabled" + }, + { + "json": { + "error": "All Polygon RPC servers unavailable" + }, + "notes": "Unable to connect to Polygon RPC", + "title": "Connection failed" + } + ], + "success": [ + { + "json": { + "address": "0x3c7aad7b693e94f13b61d4be4abaeaf802b2e3b5", + "balance": "350", + "coin": "NZDS-PLG20", + "required_confirmations": 1, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "notes": "", + "title": "Success" + }, + { + "json": { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "balance": "0", + "coin": "NZDS-PLG20", + "required_confirmations": 20, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyEnableNative": { + "error": [ + { + "json": { + "error": "Failed to connect to native daemon" + }, + "notes": "Unable to connect to daemon", + "title": "Connection failed" + } + ], + "success": [ + { + "json": { + "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ", + "balance": "333", + "coin": "TKL", + "mature_confirmations": 100, + "required_confirmations": 1, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "notes": "", + "title": "Success" + } + ] + }, + "LegacyEnableNativeWithParams": { + "error": [ + { + "json": { + "error": "Failed to connect to native daemon" + }, + "notes": "Unable to connect to daemon", + "title": "Connection failed" + } + ], + "success": [ + { + "json": { + "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ", + "balance": "777", + "coin": "TKL", + "mature_confirmations": 100, + "required_confirmations": 10, + "requires_notarization": true, + "result": "success", + "unspendable_balance": "0" + }, + "notes": "", + "title": "Success" + } + ] + } +} \ No newline at end of file diff --git a/src/data/responses/kdf/legacy/utils.json b/src/data/responses/kdf/legacy/utils.json new file mode 100644 index 000000000..5afcd22a4 --- /dev/null +++ b/src/data/responses/kdf/legacy/utils.json @@ -0,0 +1,458 @@ +{ + "CoinsNeededForKickStart": { + "error": [], + "success": [ + { + "json": { + "result": [ + "BTC", + "KMD" + ] + }, + "notes": "", + "title": "Success (BTC and KMD should be activated ASAP in this case)" + }, + { + "json": { + "result": [] + }, + "notes": "", + "title": "Success (no swaps and orders waiting to be started)" + } + ] + }, + "LegacyGetEnabledCoins": { + "error": [], + "success": [ + { + "json": { + "result": [ + { + "address": "1WxswvLF2HdaDr4k77e92VjaXuPQA8Uji", + "ticker": "BTC" + } + ] + }, + "notes": "", + "title": "Success" + }, + { + "json": { + "result": [ + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "BUSD-BEP20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "NZDS-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "APE-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "NFT_MATIC" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "MINDS-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "BAT-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "AAVE-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "ETH" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "MATIC" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "PGX-PLG20" + }, + { + "address": "bitcoincash:qqedg0nm5rcg6vs2yfzqu4dcgfq87jq7hujzrcwk5w", + "ticker": "BCH" + }, + { + "address": "cosmos1xt2ru7aq7zxnyz3zgs89twzzgpl5s84lxkx0h5", + "ticker": "ATOM" + }, + { + "address": "iaa1xt2ru7aq7zxnyz3zgs89twzzgpl5s84ln5x749", + "ticker": "ATOM-IBC_IRIS" + }, + { + "address": "iaa1xt2ru7aq7zxnyz3zgs89twzzgpl5s84ln5x749", + "ticker": "IRIS" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "ticker": "MARTY" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "ticker": "DOC" + } + ] + }, + "title": "Success" + }, + { + "json": { + "result": [ + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "BAT-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "NFT_MATIC" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "MINDS-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "PGX-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "NZDS-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "APE-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "MATIC" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "BUSD-BEP20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "ETH" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "AAVE-PLG20" + }, + { + "address": "bitcoincash:qqedg0nm5rcg6vs2yfzqu4dcgfq87jq7hujzrcwk5w", + "ticker": "BCH" + }, + { + "address": "cosmos1xt2ru7aq7zxnyz3zgs89twzzgpl5s84lxkx0h5", + "ticker": "ATOM" + }, + { + "address": "iaa1xt2ru7aq7zxnyz3zgs89twzzgpl5s84ln5x749", + "ticker": "IRIS" + }, + { + "address": "iaa1xt2ru7aq7zxnyz3zgs89twzzgpl5s84ln5x749", + "ticker": "ATOM-IBC_IRIS" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "ticker": "MARTY" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "ticker": "DOC" + } + ] + }, + "title": "Success" + }, + { + "json": { + "result": [ + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "BAT-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "PGX-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "ETH" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "NZDS-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "APE-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "NFT_MATIC" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "MINDS-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "AAVE-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "BUSD-BEP20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "MATIC" + }, + { + "address": "bitcoincash:qqedg0nm5rcg6vs2yfzqu4dcgfq87jq7hujzrcwk5w", + "ticker": "BCH" + }, + { + "address": "cosmos1xt2ru7aq7zxnyz3zgs89twzzgpl5s84lxkx0h5", + "ticker": "ATOM" + }, + { + "address": "iaa1xt2ru7aq7zxnyz3zgs89twzzgpl5s84ln5x749", + "ticker": "ATOM-IBC_IRIS" + }, + { + "address": "iaa1xt2ru7aq7zxnyz3zgs89twzzgpl5s84ln5x749", + "ticker": "IRIS" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "ticker": "MARTY" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "ticker": "DOC" + } + ] + }, + "title": "Success" + }, + { + "json": { + "result": [ + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "MINDS-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "MATIC" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "ETH" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "APE-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "NFT_MATIC" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "AAVE-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "BUSD-BEP20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "BAT-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "NZDS-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "PGX-PLG20" + }, + { + "address": "bitcoincash:qqedg0nm5rcg6vs2yfzqu4dcgfq87jq7hujzrcwk5w", + "ticker": "BCH" + }, + { + "address": "cosmos1xt2ru7aq7zxnyz3zgs89twzzgpl5s84lxkx0h5", + "ticker": "ATOM" + }, + { + "address": "iaa1xt2ru7aq7zxnyz3zgs89twzzgpl5s84ln5x749", + "ticker": "ATOM-IBC_IRIS" + }, + { + "address": "iaa1xt2ru7aq7zxnyz3zgs89twzzgpl5s84ln5x749", + "ticker": "IRIS" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "ticker": "MARTY" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "ticker": "DOC" + } + ] + }, + "title": "Success" + }, + { + "json": { + "result": [ + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "APE-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "MATIC" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "NFT_MATIC" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "BUSD-BEP20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "NZDS-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "BAT-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "ETH" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "AAVE-PLG20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "MINDS-ERC20" + }, + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "ticker": "PGX-PLG20" + }, + { + "address": "bitcoincash:qqedg0nm5rcg6vs2yfzqu4dcgfq87jq7hujzrcwk5w", + "ticker": "BCH" + }, + { + "address": "cosmos1xt2ru7aq7zxnyz3zgs89twzzgpl5s84lxkx0h5", + "ticker": "ATOM" + }, + { + "address": "iaa1xt2ru7aq7zxnyz3zgs89twzzgpl5s84ln5x749", + "ticker": "ATOM-IBC_IRIS" + }, + { + "address": "iaa1xt2ru7aq7zxnyz3zgs89twzzgpl5s84ln5x749", + "ticker": "IRIS" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "ticker": "DOC" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "ticker": "MARTY" + } + ] + }, + "title": "Success" + } + ] + }, + "LegacyGetMyPeerId": { + "error": [], + "success": [ + { + "json": { + "result": "12D3KooWS9MeuFZhJCfQTntwbTVnXMAJpz9Tvd1XYFuURrGqnJVR" + }, + "notes": "", + "title": "Success" + }, + { + "json": { + "result": "12D3KooWGupVg2L4DzKDXucStTHFGXCiqHTZNWg9TWe1HJhWn2cJ" + }, + "title": "Success" + }, + { + "json": { + "result": "12D3KooWBMXxAErf25fSBDUnbtALf6kkLVdSxvx98VJz4fJbyeyM" + }, + "title": "Success" + }, + { + "json": { + "result": "12D3KooWGdekExbPkFRqxpHDPHJ5ZPfbn8VBuHYUuBmrptVfrWH9" + }, + "title": "Success" + }, + { + "json": { + "result": "12D3KooWFcBvrgpJVgGL5z9KcYfWSSdZpdn4pbFejE7V1N1WPgcv" + }, + "title": "Success" + }, + { + "json": { + "result": "12D3KooWQjz7VDgaHvug5yPJ4rYTAnpJtLbNFRtvdMyCmC1RWGwF" + }, + "title": "Success" + } + ] + }, + "LegacyVersion": { + "error": [], + "success": [ + { + "json": { + "datetime": "2024-05-05T12:34:56Z", + "result": "2.0.996_mm2_3bb412578_Linux" + }, + "notes": "", + "title": "Success" + }, + { + "json": { + "datetime": "2025-09-19T08:42:42.719348125+00:00", + "result": "2.5.1-beta_dev-d6e2324" + }, + "title": "Success" + } + ] + } +} \ No newline at end of file diff --git a/src/data/responses/kdf/legacy/wallet.json b/src/data/responses/kdf/legacy/wallet.json new file mode 100644 index 000000000..2f6bca147 --- /dev/null +++ b/src/data/responses/kdf/legacy/wallet.json @@ -0,0 +1,1310 @@ +{ + "MyTxHistoryDoc": { + "error": [], + "success": [ + { + "json": { + "result": { + "current_block": 172418, + "from_id": null, + "limit": 1, + "page_number": null, + "skipped": 0, + "sync_status": { + "additional_info": { + "transactions_left": 126 + }, + "state": "InProgress" + }, + "total": 5915, + "total_pages": 5915, + "transactions": [ + { + "block_height": 172409, + "coin": "ETOMIC", + "confirmations": 10, + "fee_details": { + "amount": "0.00001", + "type": "Utxo" + }, + "from": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "internal_id": "903e5d71b8717205314a71055fe8bbb868e7b76d001fbe813a34bd71ff131e93", + "my_balance_change": "-0.10001", + "received_by_me": "0.8998513", + "spent_by_me": "0.9998613", + "timestamp": 1566539526, + "to": [ + "bJrMTiiRiLHJHc6RKQgesKTg1o9VVuKwT5", + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "0.9998613", + "tx_hash": "903e5d71b8717205314a71055fe8bbb868e7b76d001fbe813a34bd71ff131e93", + "tx_hex": "0400008085202f8901a242dc691de64c732e823ed0a4d8cfa6a230f8e31bc9bd21499009f1a90b855a010000006b483045022100d83113119004ac0504f812a853a831039dfc4b0bc1cb863d2c7a94c0670f07e902206af87b846b18c0d5e38bd874d43918e0400e4b6b838ab0793f5976843daa20cd012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff02809698000000000017a9144327a5516b28f66249576c18d15debf6dfbd1124876a105d05000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac047f5f5d000000000000000000000000000000" + } + ] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 1311197, + "from_id": "8f24729f566e2b08828ec3e9be34530ace752fe52fad62e8acb46a0090e65eb5", + "limit": 1, + "page_number": null, + "skipped": 1, + "sync_status": { + "state": "Finished" + }, + "total": 1, + "total_pages": 1, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 1311216, + "from_id": null, + "limit": 1, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + } + ] + }, + "MyTxHistoryDocMax": { + "error": [], + "success": [ + { + "json": { + "result": { + "current_block": 1311197, + "from_id": "8f24729f566e2b08828ec3e9be34530ace752fe52fad62e8acb46a0090e65eb5", + "limit": 1, + "page_number": null, + "skipped": 1, + "sync_status": { + "state": "Finished" + }, + "total": 1, + "total_pages": 1, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 1311216, + "from_id": "8f24729f566e2b08828ec3e9be34530ace752fe52fad62e8acb46a0090e65eb5", + "limit": 1, + "page_number": null, + "skipped": 1, + "sync_status": { + "state": "Finished" + }, + "total": 1, + "total_pages": 1, + "transactions": [] + } + }, + "title": "Success" + } + ] + }, + "MyTxHistoryErrors": { + "error": [ + { + "json": { + "error": "TTT-SLP", + "error_data": "TTT-SLP", + "error_path": "my_tx_history_v2.lp_coins", + "error_trace": "my_tx_history_v2:389] lp_coins:2847]", + "error_type": "CoinIsNotActive", + "id": null, + "mmrpc": "2.0" + }, + "title": "Coin not active" + }, + { + "json": { + "error": "TTT-SLP", + "error_data": "TTT-SLP", + "error_path": "my_tx_history_v2", + "error_trace": "my_tx_history_v2:336]", + "error_type": "NotSupportedFor", + "id": null, + "mmrpc": "2.0" + }, + "title": "Coin not compatible" + }, + { + "json": { + "error": "lp_coins:1011] from_id 1d5c1b67f8ebd3fc480e25a1d60791bece278f5d1245c5f9474c91a142fee8e2 is not found" + }, + "title": "From ID not found" + }, + { + "json": { + "error": "SqliteFailure(Error { code: Unknown, extended_code: 1 }, Some(\"no such column: block_height\"))", + "error_data": "SqliteFailure(Error { code: Unknown, extended_code: 1 }, Some(\"no such column: block_height\"))", + "error_path": "my_tx_history_v2.sql_tx_history_storage", + "error_trace": "my_tx_history_v2:351] sql_tx_history_storage:472]", + "error_type": "StorageError", + "id": null, + "mmrpc": "2.0" + }, + "title": "Local database failed" + }, + { + "json": { + "error": "Storage is not initialized for TTT-SLP", + "error_data": "Storage is not initialized for TTT-SLP", + "error_path": "my_tx_history_v2", + "error_trace": "my_tx_history_v2:343]", + "error_type": "StorageIsNotInitialized", + "id": null, + "mmrpc": "2.0" + }, + "title": "Tx history not enabled" + } + ], + "success": [ + { + "json": { + "result": { + "current_block": 144753, + "from_id": null, + "limit": 0, + "skipped": 0, + "sync_status": { + "additional_info": { + "code": -1, + "message": "Got `history too large` error from Electrum server. History is not available" + }, + "state": "Error" + }, + "total": 0, + "transactions": [] + } + }, + "title": "History too large (server)" + } + ] + }, + "MyTxHistoryEthSuccess": { + "error": [], + "success": [ + { + "json": { + "result": { + "current_block": 23782066, + "from_id": null, + "limit": 3, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 23782167, + "from_id": null, + "limit": 3, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 23782248, + "from_id": null, + "limit": 3, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 23782330, + "from_id": null, + "limit": 3, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 23782482, + "from_id": null, + "limit": 3, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 9071551, + "from_id": null, + "limit": 3, + "page_number": 1, + "skipped": 0, + "sync_status": { + "state": "Finished" + }, + "sync_status_2": "omitted additional examples for brevity", + "total": 41, + "total_pages": 14, + "transactions": [ + { + "block_height": 8980257, + "coin": "ETH", + "confirmations": 91295, + "fee_details": { + "coin": "ETH", + "gas": 57196, + "gas_price": "0.000000027", + "total_fee": "0.001544292", + "type": "Eth" + }, + "from": [ + "0xE4406Af4CA1dcB05AFE384eBfF3c1F233dCA176A" + ], + "internal_id": "3978545ce08ca4c7f4b92e10b6c61efc6ce436f35f8a23f4e6a2e74f309cfd0a", + "my_balance_change": "-0.010193732", + "received_by_me": "0", + "spent_by_me": "0.010193732", + "timestamp": 1574423598, + "to": [ + "0x8500AFc0bc5214728082163326C2FF0C73f4a871" + ], + "total_amount": "0.00864944", + "tx_hash": "e578a719896ec5f1475c273e02fbdd3cf283d9808c20db336f110e4b4faef10c", + "tx_hex": "f8f11b850649534e00830249f0948500afc0bc5214728082163326c2ff0c73f4a871871eba9eaeb4c000b884152cf3af1b065716fc0c8254828abed3061c181f73a3c698cf1bc0fc8620e158448988050000000000000000000000007296a0cbae6ccfa5cddff9130569731a3b7da419d068b8936743ace66f192407debdcfc38445674e000000000000000000000000000000000000000000000000000000000000000000000000000000005dd808491ba0c78ad466381e0db9fb01f103d9e5c9d9c0c9cb28ee02bf990dc6371313c71bc3a0624e653559cfb19141a67e567e2e1fd4ca1ccd73f40d8b3672d14bd37072dad1" + } + ] + } + }, + "title": "Success (ETH)" + } + ] + }, + "MyTxHistorySia": { + "error": [], + "success": [ + { + "json": { + "result": { + "current_block": 529014, + "from_id": null, + "limit": 10, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 1, + "total_pages": 1, + "transactions": [ + { + "block_height": 528310, + "coin": "SC", + "confirmations": 705, + "fee_details": { + "coin": "SC", + "policy": "Unknown", + "total_amount": "0.000010000000000000000000", + "type": "Sia" + }, + "from": [ + "0b57980ab60cab20c0d77fc3142eb29c440d4d7739b835b791765fcad8328672c799f7c8df8a" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "50.000000000000000000000000", + "received_by_me": "50.000000000000000000000000", + "spent_by_me": "0.000000000000000000000000", + "timestamp": 1750438004, + "to": [ + "0b57980ab60cab20c0d77fc3142eb29c440d4d7739b835b791765fcad8328672c799f7c8df8a", + "2c4a029ef67858d7c3ebf9ce7f1c257fd880b1b073fd3923091423e1658ae23d2b426be204db" + ], + "total_amount": "500.000000000000000000000000", + "transaction_type": "SiaV2Transaction", + "tx_hash": "bdf2c3885adaacf88f0042d2738daff4dc5ae8b3d3a61ea3c3497c28be6d2499", + "tx_json": { + "minerFee": "10000000000000000000", + "siacoinInputs": [], + "siacoinOutputs": [] + } + } + ] + } + }, + "title": "Success (SIA)" + } + ] + }, + "MyTxHistorySyncEthInProgress": { + "error": [], + "success": [ + { + "json": { + "result": { + "current_block": 23782066, + "from_id": null, + "limit": 0, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 23782168, + "from_id": null, + "limit": 0, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 23782249, + "from_id": null, + "limit": 0, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 23782330, + "from_id": null, + "limit": 0, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 23782482, + "from_id": null, + "limit": 0, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 8039935, + "from_id": null, + "limit": 0, + "skipped": 0, + "sync_status": { + "additional_info": { + "blocks_left": 2158991 + }, + "state": "InProgress" + }, + "total": 0, + "transactions": [] + } + }, + "title": "Sync In Progress (ETH)" + } + ] + }, + "MyTxHistorySyncUtxoInProgress": { + "error": [], + "success": [ + { + "json": { + "result": { + "current_block": 1311173, + "from_id": null, + "limit": 0, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 1311183, + "from_id": null, + "limit": 0, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 1311189, + "from_id": null, + "limit": 0, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 1311197, + "from_id": null, + "limit": 0, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 1311216, + "from_id": null, + "limit": 0, + "page_number": null, + "skipped": 0, + "sync_status": { + "state": "NotEnabled" + }, + "total": 0, + "total_pages": 0, + "transactions": [] + } + }, + "title": "Success" + }, + { + "json": { + "result": { + "current_block": 148300, + "from_id": null, + "limit": 0, + "skipped": 0, + "sync_status": { + "additional_info": { + "transactions_left": 1656 + }, + "state": "InProgress" + }, + "total": 3956, + "transactions": [] + } + }, + "title": "Sync In Progress (UTXO)" + } + ] + }, + "SendRawTransactionKmd": { + "error": [], + "success": [ + { + "json": { + "tx_hash": "0b024ea6997e16387c0931de9f203d534c6b2b8500e4bda2df51a36b52a3ef33" + }, + "title": "Success" + } + ] + }, + "SendRawTransactionSiaFull": { + "error": [], + "success": [ + { + "json": { + "tx_hash": "d58e0d8540a892706a6ca0b8583f34a98a5ec0696834e2068daf6bd872459a48" + }, + "title": "Success" + } + ] + }, + "ValidateAddress": { + "error": [], + "success": [ + { + "json": { + "result": { + "is_valid": false, + "reason": "utxo:415] Checksum verification failed" + } + }, + "title": "Response (invalid cash address)" + }, + { + "json": { + "result": { + "is_valid": false, + "reason": "eth:360] eth:2522] Invalid address checksum" + } + }, + "title": "Response (invalid ETH address)" + }, + { + "json": { + "result": { + "is_valid": true + } + }, + "title": "Response (valid address)" + } + ] + }, + "WithdrawLegacyDocFixedFee": { + "error": [], + "success": [ + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.1", + "type": "Utxo" + }, + "from": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "internal_id": "", + "my_balance_change": "-0.1", + "received_by_me": "60.00253836", + "spent_by_me": "60.10253836", + "timestamp": 1566472936, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "60.10253836", + "tx_hash": "1ab3bc9308695960bc728fa427ac00d1812c4ae89aaa714c7618cb96d111be58", + "tx_hex": "0400008085202f8901ef25b1b7417fe7693097918ff90e90bba1351fff1f3a24cb51a9b45c5636e57e010000006b483045022100b05c870fcd149513d07b156e150a22e3e47fab4bb4776b5c2c1b9fc034a80b8f022038b1bf5b6dad923e4fb1c96e2c7345765ff09984de12bbb40b999b88b628c0f9012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac8cbaae5f010000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ace87a5e5d000000000000000000000000000000" + }, + "title": "Success" + }, + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.0245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762937446, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "fc529a042cb59734ff8640ce80e93e2500c4c65cca7720ad7de081d4c5244578", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a473044022038c667809431011eea1f8a4cd64e28613613f2716df5b02bfa4eec818e4acc1c022077da58037f9f17a9af0e33ede490bb12ed22e9c105634b28ebad6eeedc61dc0801210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac30ef4f27000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac664a1469000000000000000000000000000000" + }, + "title": "Success" + }, + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.0245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762938672, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "ce6d2b5c632408f83dc9f114378baf121445cb16b83644fb022b7506c928bbb6", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a47304402207dfffb16841491f9a142aad7dba3e7037a0b0e496103e5a3176d42538d7b5b3702206b11a5b8faf453fd59b0f66065fe2f1439ceefdd85b3a5c4403dc08f7ed0dc8401210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac30ef4f27000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac304f1469000000000000000000000000000000" + }, + "title": "Success" + }, + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.0245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762939658, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "a93c2eca0785d317fbf1eb86f8f241658d91a75ce69162113a1e2fb71c8ea541", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a473044022047baf0cfd35589f3327da2cbd48c5f8554288be987d48f8dd83a289d80b7908f02207101403a8a980a0fc959931e7ed07cf058b8029a3aa9a98d3bacaf20542287cf01210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac30ef4f27000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac0a531469000000000000000000000000000000" + }, + "title": "Success" + }, + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.0245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762940651, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "862969bff0bacbab49dcdb06938e1ffbdaafddcc5c50c96e94a74615a9f0c96e", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a473044022067aeae10e76e8d89c20111d8bc39c02c8ce1ccfca5abea1fc6a04f273e7d423102206e51bedb2c78b61b879e56ae9b8642283c97cdbef9c9f57d0a0fbf0768804a7701210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac30ef4f27000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88aceb561469000000000000000000000000000000" + }, + "title": "Success" + }, + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.0245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762942483, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "c539484e87bb7f0b1e0181589d5a7701c0d1ff64b6e4856718192a3a46a33b32", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a473044022003dad4021cda105b9eb4ff24142dcf34cf1e73ac9b3045997ba78e5e2f0410d202201a1edf942addbdcf5f5adec52932c20c7811207f65f2c8b17b569ba1a03c665d01210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac30ef4f27000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac135e1469000000000000000000000000000000" + }, + "title": "Success" + } + ] + }, + "WithdrawLegacyDocPerKbyte": { + "error": [], + "success": [ + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.38378905", + "type": "Utxo" + }, + "from": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "internal_id": "", + "my_balance_change": "-0.38378905", + "received_by_me": "59.61874931", + "spent_by_me": "60.00253836", + "timestamp": 1566473421, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "60.00253836", + "tx_hash": "fd115190feec8c0c14df2696969295c59c674886344e5072d64000379101b78c", + "tx_hex": "0400008085202f890258be11d196cb18764c71aa9ae84a2c81d100ac27a48f72bc6059690893bcb31a000000006b483045022100ef11280e981be280ca5d24c947842ca6a8689d992b73e3a7eb9ff21070b0442b02203e458a2bbb1f2bf8448fc47c51485015904a5271bb17e14be5afa6625d67b1e8012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff58be11d196cb18764c71aa9ae84a2c81d100ac27a48f72bc6059690893bcb31a010000006b483045022100daaa10b09e7abf9d4f596fc5ac1f2542b8ecfab9bb9f2b02201644944ddc0280022067aa1b91ec821aa48f1d06d34cd26fb69a9f27d59d5eecdd451006940d9e83db012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788acf31c655d010000001976a91405aab5342166f8594baf17a7d9bef5d56744332788accd7c5e5d000000000000000000000000000000" + }, + "title": "Success" + }, + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.245", + "received_by_me": "6.375", + "spent_by_me": "7.62", + "timestamp": 1762937447, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "025b982ae830639f3b69bac86465a133a3a0c76da35aea5a93294991ed7041c9", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a473044022003b097a20c2433fccade1c156cd8425fb823e8e076c5a25d5b493cd91f8a9ed102202e288f5495463a025b72237a3bf6b683318fb819538fc4a0132b81ea9e097a4901210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac607aff25000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac674a1469000000000000000000000000000000" + }, + "title": "Success" + }, + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.245", + "received_by_me": "6.375", + "spent_by_me": "7.62", + "timestamp": 1762938673, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "b30ddaaa8dd802235b5a8baed536a20f3422e91b34de41538c929363f838c682", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a47304402205c48d1b78ccb74ad2efa91df1f3e5ec4a6347cdc278d70f214ff823460e828cd02204d47556c27c829534c20d0fe09c4bf696a8bdeec92a241eeb5b14a32fa0c882501210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac607aff25000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac314f1469000000000000000000000000000000" + }, + "title": "Success" + }, + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.245", + "received_by_me": "6.375", + "spent_by_me": "7.62", + "timestamp": 1762939659, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "94079ea544f8ea26ccdf780d9f4258c484049444d2ad8801e13a971f1d8900eb", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a473044022047905448945031d8fcf304135a129d27b13899a72c72ee1339f2c6b7362f299a0220648e647c886b14f6827a83db532a7b0d29c9181815835566764d9985e6b42b2201210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac607aff25000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac0b531469000000000000000000000000000000" + }, + "title": "Success" + }, + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.245", + "received_by_me": "6.375", + "spent_by_me": "7.62", + "timestamp": 1762940652, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "c8b5ab3732ce475cb3128ebf4af2c6a101ab7bf9d37ed637bcc441c8461c1f71", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a4730440220220940e6b143409896846c013b08b0ef16804beb61f96267b7b4b30d5f120770022039c226a71ac831943711a472e8adb5c4b84cc1a481e5470de49ca7933101e97c01210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac607aff25000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88acec561469000000000000000000000000000000" + }, + "title": "Success" + }, + { + "json": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.245", + "received_by_me": "6.375", + "spent_by_me": "7.62", + "timestamp": 1762942484, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "5e8d4a4ccb34a96848409f148ecd54c1b4873927bf5476f9a926d28f20481f3a", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a47304402201b5bb119ee99853f5d12f6fa450e7f227916f9fb97b44c9fc2db4def314ef22b022054b4383dbca61fe4fc57d2d49e151f313bbb981c80d65d304e5bed7348d91a9301210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac607aff25000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac145e1469000000000000000000000000000000" + }, + "title": "Success" + } + ] + }, + "WithdrawLegacyEth": { + "error": [], + "success": [ + { + "json": { + "block_height": 0, + "coin": "ETH", + "fee_details": { + "coin": "ETH", + "gas": 21000, + "gas_price": "0.000000001", + "total_fee": "0.000021", + "type": "Eth" + }, + "from": [ + "0xbab36286672fbdc7b250804bf6d14be0df69fa29" + ], + "my_balance_change": "-10.000021", + "received_by_me": "0", + "spent_by_me": "10.000021", + "to": [ + "0xbab36286672fbdc7b250804bf6d14be0df69fa28" + ], + "total_amount": "10.000021", + "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", + "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" + }, + "title": "Success" + } + ] + }, + "WithdrawLegacyEthGas": { + "error": [], + "success": [ + { + "json": { + "block_height": 0, + "coin": "ETH", + "fee_details": { + "coin": "ETH", + "gas": 55000, + "gas_price": "0.0000000035", + "total_fee": "0.0001925", + "type": "Eth" + }, + "from": [ + "0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29" + ], + "internal_id": "", + "my_balance_change": "-0.0001925", + "received_by_me": "10", + "spent_by_me": "10.0001925", + "timestamp": 1566474670, + "to": [ + "0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29" + ], + "total_amount": "10", + "tx_hash": "a26c4dcacf63c04e385dd973ca7e7ca1465a3b904a0893bcadb7e37681d38c95", + "tx_hex": "f86d820b2884d09dc30082d6d894bab36286672fbdc7b250804bf6d14be0df69fa29888ac7230489e80000801ca0ef0167b0e53ed50d87b6fd630925f2bce6ee72e9b5fdb51c6499a7caaecaed96a062e5cb954e503ff83f2d6ce082649fdcdf8a77c8d37c7d26d46d3f736b228d10" + }, + "title": "Success" + } + ] + }, + "WithdrawLegacyEthMax": { + "error": [], + "success": [ + { + "json": { + "block_height": 0, + "coin": "ETH", + "fee_details": { + "coin": "ETH", + "gas": 21000, + "gas_price": "0.000000001", + "total_fee": "0.000021", + "type": "Eth" + }, + "from": [ + "0xbab36286672fbdc7b250804bf6d14be0df69fa29" + ], + "my_balance_change": "-10.000021", + "received_by_me": "0", + "spent_by_me": "10.000021", + "to": [ + "0xbab36286672fbdc7b250804bf6d14be0df69fa28" + ], + "total_amount": "10.000021", + "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", + "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" + }, + "title": "Success" + } + ] + }, + "WithdrawLegacyKmd": { + "error": [], + "success": [ + { + "json": { + "block_height": 0, + "coin": "KMD", + "fee_details": { + "amount": "0.00001", + "type": "Utxo" + }, + "from": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "kmd_rewards": { + "amount": "0.0791809", + "claimed_by_my": true + }, + "my_balance_change": "-10.00001", + "received_by_me": "0.34417325", + "spent_by_me": "10.34418325", + "to": [ + "RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh" + ], + "total_amount": "10.34418325", + "tx_hash": "3a1c382c50a7d12e4675d12ed7e723ce9f0167693dd75fd772bae8524810e605", + "tx_hex": "0400008085202f890207a8e96978acfb8f0d002c3e4390142810dc6568b48f8cd6d8c71866ad8743c5010000006a47304402201960a7089f2d93480fff68ce0b7ca7bb7a32a52915753ac7ae780abd6162cb1d02202c9b11d442e5f72a532f44ceb10122898d486b1474a10eb981c60c5538b9c82d012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff97f56bf3b0f815bb737b7867e71ddb8198bba3574bb75737ba9c389a4d08edc6000000006a473044022055199d80bd7e2d1b932e54f097c6a15fc4b148d21299dc50067c1da18045f0ed02201d26d85333df65e6daab40a07a0e8a671af9d9b9d92fdf7d7ef97bd868ca545a012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200ca9a3b000000001976a91464ae8510aac9546d5e7704e31ce177451386455588acad2a0d02000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac00000000000000000000000000000000000000" + }, + "title": "Success" + } + ] + }, + "WithdrawLegacyQrc20": { + "error": [], + "success": [ + { + "json": { + "block_height": 0, + "coin": "QRC20", + "fee_details": { + "coin": "tQTUM", + "gas_limit": 100000, + "gas_price": 40, + "miner_fee": "0.00000447", + "total_gas_fee": "0.04", + "type": "Qrc20" + }, + "from": [ + "qXxsj5RtciAby9T7m98AgAATL4zTi4UwDG" + ], + "my_balance_change": "-10", + "received_by_me": "0", + "spent_by_me": "10", + "timestamp": 1608725061, + "to": [ + "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs" + ], + "total_amount": "10", + "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", + "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" + }, + "title": "Success" + } + ] + }, + "WithdrawLegacyQrc20Gas": { + "error": [], + "success": [ + { + "json": { + "block_height": 0, + "coin": "QRC20", + "fee_details": { + "coin": "tQTUM", + "gas_limit": 250000, + "gas_price": 40, + "miner_fee": "0.00000447", + "total_gas_fee": "0.1", + "type": "Qrc20" + }, + "from": [ + "qXxsj5RtciAby9T7m98AgAATL4zTi4UwDG" + ], + "my_balance_change": "-10", + "received_by_me": "0", + "spent_by_me": "10", + "timestamp": 1608725061, + "to": [ + "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs" + ], + "total_amount": "10", + "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", + "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" + }, + "title": "Success" + } + ] + }, + "WithdrawLegacySia": { + "error": [], + "success": [ + { + "json": { + "block_height": 0, + "coin": "SC", + "fee_details": { + "coin": "SC", + "policy": "Fixed", + "total_amount": "0.000010000000000000000000", + "type": "Sia" + }, + "from": [ + "2c4a029ef67858d7c3ebf9ce7f1c257fd880b1b073fd3923091423e1658ae23d2b426be204db" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.025010000000000000000000", + "received_by_me": "48.974990000000000000000000", + "spent_by_me": "50.000000000000000000000000", + "timestamp": 1750748326, + "to": [ + "c67d77a585c13727dbba57cfc115995beb9b8737e9a8cb7bb0aa208744e646cdc0acc9c9fce2" + ], + "total_amount": "50.000000000000000000000000", + "transaction_type": "SiaV2Transaction", + "tx_hash": "d58e0d8540a892706a6ca0b8583f34a98a5ec0696834e2068daf6bd872459a48", + "tx_json": { + "minerFee": "10000000000000000000", + "siacoinInputs": [ + { + "parent": { + "id": "db712a113806580ec2cce966135ebf139d0e1086bf04cf84b7fe554ec25bb5a7", + "maturityHeight": 0, + "siacoinOutput": { + "address": "2c4a029ef67858d7c3ebf9ce7f1c257fd880b1b073fd3923091423e1658ae23d2b426be204db", + "value": "50000000000000000000000000" + }, + "stateElement": { + "leafIndex": 72996955, + "merkleProof": [ + "42a6529a8ef4a849b716071d66bb84d7e929fc1ad671d04229992ff670e3627f", + "5f728bfbc9494ec8ec9f76b229bf85f184fddd3c305b2a91e74546a821a664b6", + "64295af67329a2f6f91e10ace99a379e4df6cdfc2405db967f4857226dafaa53", + "665e3a2f25267de5e35b5076895438745cd1101ae7c337a3139b910460d8bb36", + "73c4dd35635c1707d322035c52a9cc9cf96766e9adcea4ed675c851d6ae50b3b", + "7dece8216b769ba9b15b27d00a728cbdbc2d4c72bc7cf93fe9ff48c7f739069e", + "80a16928a727b386dd824ba1f82a03da2f41a1583b14c21cc1fc0de7af2f5c4e", + "84b54d73a6b74c3abb152e7d6f30a1fae6b411522353a7f25220095ed4ae5cbf", + "a6f1306840881651aea186e25ae4de9932e58c8178fef43586a9f9fa52b99d1a", + "ab734606431ad3a6c50a5d3cbff9f340cedef606407e952af55476e6b51f43a6", + "bad7c9a405bbc576a99718cb4c3889b8710db975b2b03e327653170956457bef", + "c7158f7aba1d3954f0d56e8a96a1bfe360038b249b7cdcf941da4c974974be89", + "c72d15d701e5f83c3db6a0b2ab5f85a932541d4bef41028f19751081996e0f2c", + "c734b54b9e42c8aa3d6adf11ffa257b474d9cc7036a31aff7c11d0a02b7f2ca4", + "cd2dd16a38a0443dc2ad93faefaf7974842dcab419ea1ce1f1b82f97adb81b1a", + "d3a9e8d681ba7231fdcef7d795ff5acb1469bf7c17317c8ea59f60fd3963d776", + "f2eab142e8a752abb6fc6a0b3f2e3199ed22ff74c701e44676192696e784675a" + ] + } + }, + "satisfiedPolicy": { + "policy": { + "policy": "ed25519:c94acdcbd6a44c25a2640191afd80d6ef6c692c3a0faa0db3cec0189d90f6cd1", + "type": "pk" + }, + "signatures": [ + "2ab2ef985c6ebc396caddf60671a5205d4b62201293b90ccdb939fc70fb1a9dd5449a53d21541362cc194674d4e8bc215116b9014b1cee6d625176e647df670d" + ] + } + } + ], + "siacoinOutputs": [ + { + "address": "2c4a029ef67858d7c3ebf9ce7f1c257fd880b1b073fd3923091423e1658ae23d2b426be204db", + "value": "48974990000000000000000000" + }, + { + "address": "c67d77a585c13727dbba57cfc115995beb9b8737e9a8cb7bb0aa208744e646cdc0acc9c9fce2", + "value": "1025000000000000000000000" + } + ] + } + }, + "title": "Success" + } + ] + } +} \ No newline at end of file diff --git a/src/data/responses/kdf/v2/coin_activation.json b/src/data/responses/kdf/v2/coin_activation.json index 069168595..400662633 100644 --- a/src/data/responses/kdf/v2/coin_activation.json +++ b/src/data/responses/kdf/v2/coin_activation.json @@ -1,168 +1,2849 @@ { - "TaskEnableZCoinStatus": { + "EnableBchWithTokensBalancesFalse": { + "error": [], + "success": [] + }, + "EnableBchWithTokensTxHistory": { + "error": [], + "success": [] + }, + "EnableErc20Basic": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "balances": { + "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375": { + "spendable": "0", + "unspendable": "0" + } + }, + "platform_coin": "ETH", + "required_confirmations": 3, + "token_contract_address": "0x0d8775f648430679a709e98d2b0cb6250d2887ef" + } + }, + "title": "Success" + } + ] + }, + "EnableEthWithTokensGasStation": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 23287401, + "nfts_infos": {}, + "ticker": "ETH", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 23782043, + "nfts_infos": {}, + "ticker": "ETH", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 23782131, + "nfts_infos": {}, + "ticker": "ETH", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 23782215, + "nfts_infos": {}, + "ticker": "ETH", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 23782302, + "nfts_infos": {}, + "ticker": "ETH", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 23782447, + "nfts_infos": {}, + "ticker": "ETH", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "APE-ERC20": { + "spendable": "0", + "unspendable": "0" + }, + "ETH": { + "spendable": "0", + "unspendable": "0" + }, + "MINDS-ERC20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + } + ] + }, + "EnableEthWithTokensMaticBalancesFalse": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 76029528, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 78916175, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 78916799, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 78917278, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 78917777, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 78918616, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + } + ] + }, + "EnableEthWithTokensMaticNft": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 76517714, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 78916205, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 78916819, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 78917307, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 78917805, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "current_block": 78918726, + "nfts_infos": {}, + "ticker": "MATIC", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/60'/0'/0/0" + } + ], + "derivation_path": "m/44'/60'/0'", + "total_balance": { + "AAVE-PLG20": { + "spendable": "0", + "unspendable": "0" + }, + "MATIC": { + "spendable": "0", + "unspendable": "0" + }, + "PGX-PLG20": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + } + }, + "title": "Success" + } + ] + }, + "EnableEthWithTokensWalletConnect": { + "error": [], + "success": [] + }, + "EnableSia": { + "error": [], + "success": [ + { + "json": { + "id": 9, + "mmrpc": "2.0", + "result": { + "task_id": 12346 + } + }, + "title": "Success" + } + ] + }, + "EnableSiaInit": { + "error": [], + "success": [ + { + "json": { + "id": 1, + "mmrpc": "2.0", + "result": { + "task_id": 12345 + } + }, + "title": "Success" + } + ] + }, + "EnableSiaStatus": { + "error": [], + "success": [ + { + "json": { + "id": 2, + "mmrpc": "2.0", + "result": { + "details": { + "current_block": 123456, + "ticker": "SIA", + "wallet_balance": { + "address": "addr:1599ea80d9af168c...17030fb3", + "balance": { + "spendable": "10", + "unspendable": "0" + }, + "wallet_type": "Iguana" + } + }, + "status": "Ok" + } + }, + "title": "Success" + } + ] + }, + "EnableTendermintTokenBasic": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "balances": { + "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m": { + "spendable": "0", + "unspendable": "0" + } + }, + "platform_coin": "IRIS" + } + }, + "title": "Success" + } + ] + }, + "EnableTendermintWithAssetsBalancesFalse": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "current_block": 31622007, + "ticker": "IRIS", + "tokens_tickers": [ + "ATOM-IBC_IRIS" + ] + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "current_block": 32705724, + "ticker": "IRIS", + "tokens_tickers": [ + "ATOM-IBC_IRIS" + ] + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "current_block": 32705929, + "ticker": "IRIS", + "tokens_tickers": [ + "ATOM-IBC_IRIS" + ] + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "current_block": 32706094, + "ticker": "IRIS", + "tokens_tickers": [ + "ATOM-IBC_IRIS" + ] + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "current_block": 32706262, + "ticker": "IRIS", + "tokens_tickers": [ + "ATOM-IBC_IRIS" + ] + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "current_block": 32706570, + "ticker": "IRIS", + "tokens_tickers": [ + "ATOM-IBC_IRIS" + ] + } + }, + "title": "Success" + } + ] + }, + "EnableTendermintWithAssetsBalancesTrue": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 31981983, + "ticker": "IRIS", + "tokens_balances": { + "ATOM-IBC_IRIS": { + "spendable": "0", + "unspendable": "0" + } + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 32705725, + "ticker": "IRIS", + "tokens_balances": { + "ATOM-IBC_IRIS": { + "spendable": "0", + "unspendable": "0" + } + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 32705930, + "ticker": "IRIS", + "tokens_balances": { + "ATOM-IBC_IRIS": { + "spendable": "0", + "unspendable": "0" + } + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 32706095, + "ticker": "IRIS", + "tokens_balances": { + "ATOM-IBC_IRIS": { + "spendable": "0", + "unspendable": "0" + } + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 32706263, + "ticker": "IRIS", + "tokens_balances": { + "ATOM-IBC_IRIS": { + "spendable": "0", + "unspendable": "0" + } + } + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 32706571, + "ticker": "IRIS", + "tokens_balances": { + "ATOM-IBC_IRIS": { + "spendable": "0", + "unspendable": "0" + } + } + } + }, + "title": "Success" + } + ] + }, + "EnableTendermintWithAssetsWalletConnect": { + "error": [], + "success": [] + }, + "LegacyElectrumBch": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "address": "bitcoincash:qqedg0nm5rcg6vs2yfzqu4dcgfq87jq7hujzrcwk5w", + "balance": "0", + "coin": "BCH", + "mature_confirmations": 100, + "required_confirmations": 1, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyElectrumKmd": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "balance": "0", + "coin": "KMD", + "mature_confirmations": 100, + "required_confirmations": 10, + "requires_notarization": true, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyElectrumQtum": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "address": "QREk9sFW6sCDGcauAMoF9UuxkbnfyE6Eg5", + "balance": "0", + "coin": "QTUM", + "mature_confirmations": 2000, + "required_confirmations": 3, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyEnableBnb": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "balance": "0", + "coin": "BUSD-BEP20", + "required_confirmations": 3, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "LegacyEnableEthGasStation_native-hd": { + "error": [ + { + "generated": true, + "json": { + "error": "HTTP 500", + "raw_response": "{\"error\":\"rpc:198] RPC call failed: legacy:172] lp_coins:5100] Coin ETH already initialized\"}" + }, + "title": "Error" + } + ], + "success": [] + }, + "LegacyEnableEth_native-hd": { + "error": [ + { + "generated": true, + "json": { + "error": "HTTP 500", + "raw_response": "{\"error\":\"rpc:198] RPC call failed: legacy:172] lp_coins:5100] Coin ETH already initialized\"}" + }, + "title": "Error" + } + ], + "success": [] + }, + "LegacyEnableMatic": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "balance": "0", + "coin": "NZDS-PLG20", + "required_confirmations": 20, + "requires_notarization": false, + "result": "success", + "unspendable_balance": "0" + }, + "title": "Success" + } + ] + }, + "TaskEnableBchCancel": { + "error": [ + "NoSuchTask", + "TaskFinished" + ], + "success": [ + "CancelTaskId" + ] + }, + "TaskEnableBchInit": { + "error": [], + "success": [] + }, + "TaskEnableBchStatus": { + "error": [], + "success": [] + }, + "TaskEnableBchUserActionPin": { + "error": [], + "success": [ + "UserActionSuccess" + ] + }, + "TaskEnableEthCancel": { + "error": [ + "NoSuchTask", + "TaskFinished" + ], + "success": [ + "CancelTaskId", + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": "success" + }, + "title": "Success" + } + ] + }, + "TaskEnableEthInitTrezor": { + "error": [], + "success": [] + }, + "TaskEnableEthStatus": { + "error": [ + "NoSuchTask" + ], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "ActivatingCoin", + "status": "InProgress" + } + }, + "notes": "", + "title": "InProgress - ActivatingCoin" + } + ] + }, + "TaskEnableEthUserActionPin": { + "error": [], + "success": [ + "UserActionSuccess" + ] + }, + "TaskEnableQtumCancel": { + "error": [ + "NoSuchTask", + "TaskFinished" + ], + "success": [ + "CancelTaskId", + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": "success" + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumInit": { + "error": [], + "success": [ + "SuccessTaskId", + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "task_id": 1 + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus": { + "error": [ + "NoSuchTask" + ], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "current_block": 5319137, + "ticker": "QTUM", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "QdGumZkwdNhnh9qNtcmBT6jPqWXq74ieiu", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/1" + }, + { + "address": "QgZi2XMapaq2HLZZpZQo1BAXtGyRmXCm7K", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/0" + }, + { + "address": "QUA2EaaWbyaY7oDxRjZbshdEaigAGXmyTv", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/2" + } + ], + "derivation_path": "m/44'/2301'/0'", + "total_balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + }, + "status": "Ok" + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "current_block": 5319173, + "ticker": "QTUM", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "QdGumZkwdNhnh9qNtcmBT6jPqWXq74ieiu", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/1" + }, + { + "address": "QgZi2XMapaq2HLZZpZQo1BAXtGyRmXCm7K", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/0" + }, + { + "address": "QUA2EaaWbyaY7oDxRjZbshdEaigAGXmyTv", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/2" + } + ], + "derivation_path": "m/44'/2301'/0'", + "total_balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + }, + "status": "Ok" + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "current_block": 5319207, + "ticker": "QTUM", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "QdGumZkwdNhnh9qNtcmBT6jPqWXq74ieiu", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/1" + }, + { + "address": "QgZi2XMapaq2HLZZpZQo1BAXtGyRmXCm7K", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/0" + }, + { + "address": "QUA2EaaWbyaY7oDxRjZbshdEaigAGXmyTv", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/2" + } + ], + "derivation_path": "m/44'/2301'/0'", + "total_balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + }, + "status": "Ok" + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "current_block": 5319238, + "ticker": "QTUM", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "QdGumZkwdNhnh9qNtcmBT6jPqWXq74ieiu", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/1" + }, + { + "address": "QgZi2XMapaq2HLZZpZQo1BAXtGyRmXCm7K", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/0" + }, + { + "address": "QUA2EaaWbyaY7oDxRjZbshdEaigAGXmyTv", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/2" + } + ], + "derivation_path": "m/44'/2301'/0'", + "total_balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + }, + "status": "Ok" + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "current_block": 5319300, + "ticker": "QTUM", + "wallet_balance": { + "accounts": [ + { + "account_index": 0, + "addresses": [ + { + "address": "QdGumZkwdNhnh9qNtcmBT6jPqWXq74ieiu", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/1" + }, + { + "address": "QgZi2XMapaq2HLZZpZQo1BAXtGyRmXCm7K", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/0" + }, + { + "address": "QUA2EaaWbyaY7oDxRjZbshdEaigAGXmyTv", + "balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + }, + "chain": "External", + "derivation_path": "m/44'/2301'/0'/0/2" + } + ], + "derivation_path": "m/44'/2301'/0'", + "total_balance": { + "QTUM": { + "spendable": "0", + "unspendable": "0" + } + } + } + ], + "wallet_type": "HD" + } + }, + "status": "Ok" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_10": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_11": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_12": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_13": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_14": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_15": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_16": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_17": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_18": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_19": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_2": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_20": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_3": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_4": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_5": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_6": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_7": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_8": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumStatus_9": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableQtumUserActionPin": { + "error": [], + "success": [ + "UserActionSuccess" + ] + }, + "TaskEnableTendermintCancel": { + "error": [ + "NoSuchTask", + "TaskFinished" + ], + "success": [ + "CancelTaskId", + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": "success" + }, + "title": "Success" + } + ] + }, + "TaskEnableTendermintInit": { + "error": [ + "NoSuchTask", + "TaskFinished" + ], + "success": [ + "SuccessTaskId", + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "task_id": 2 + } + }, + "title": "Success" + } + ] + }, + "TaskEnableTendermintStatus": { + "error": [], "success": [ { - "title": "ActivatingCoin - enabling has started", - "notes": "", + "generated": true, "json": { + "id": null, "mmrpc": "2.0", "result": { - "status": "InProgress", - "details": "ActivatingCoin" - }, - "id": null - } + "details": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 31625315, + "ticker": "IRIS", + "tokens_balances": { + "ATOM-IBC_IRIS": { + "spendable": "0", + "unspendable": "0" + } + } + }, + "status": "Ok" + } + }, + "title": "Success" }, { - "title": "UpdatingBlocksCache", - "notes": "", "json": { + "id": null, "mmrpc": "2.0", "result": { - "status": "InProgress", "details": { - "UpdatingBlocksCache": { - "current_scanned_block": 265930, - "latest_block": 269656 - } - } - }, - "id": null - } + "address": "cosmos1hkg6p4lqnxardx2878clge6vjhfknf6s57ac92", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 28381819, + "ticker": "ATOM", + "tokens_balances": {} + }, + "status": "Ok" + } + }, + "title": "Success" }, { - "title": "BuildingWalletDb", - "notes": "", "json": { + "id": null, "mmrpc": "2.0", "result": { - "status": "InProgress", "details": { - "BuildingWalletDb": { - "current_scanned_block": 265311, - "latest_block": 269656 - } - } - }, - "id": null - } + "address": "cosmos1hkg6p4lqnxardx2878clge6vjhfknf6s57ac92", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 28382025, + "ticker": "ATOM", + "tokens_balances": {} + }, + "status": "Ok" + } + }, + "title": "Success" }, { - "title": "Enabling complete", - "notes": "", "json": { + "id": null, "mmrpc": "2.0", "result": { - "status": "Ok", "details": { - "ticker": "ZOMBIE", - "current_block": 269657, - "wallet_balance": { - "wallet_type": "Iguana", - "address": "zs1e3puxpnal8ljjrqlxv4jctlyndxnm5a3mj5rarjvp0qv72hmm9caduxk9asu9kyc6erfx4zsauj", - "balance": { - "spendable": "29.99989008", + "address": "cosmos1hkg6p4lqnxardx2878clge6vjhfknf6s57ac92", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 28382192, + "ticker": "ATOM", + "tokens_balances": {} + }, + "status": "Ok" + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "address": "cosmos1hkg6p4lqnxardx2878clge6vjhfknf6s57ac92", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 28382361, + "ticker": "ATOM", + "tokens_balances": {} + }, + "status": "Ok" + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "address": "cosmos1hkg6p4lqnxardx2878clge6vjhfknf6s57ac92", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 28382672, + "ticker": "ATOM", + "tokens_balances": {} + }, + "status": "Ok" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableTendermintStatus_2": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "address": "iaa1hkg6p4lqnxardx2878clge6vjhfknf6spuaf8m", + "balance": { + "spendable": "0", + "unspendable": "0" + }, + "current_block": 31881684, + "ticker": "IRIS", + "tokens_balances": { + "ATOM-IBC_IRIS": { + "spendable": "0", "unspendable": "0" } } - } - }, - "id": null - } + }, + "status": "Ok" + } + }, + "title": "Success" } + ] + }, + "TaskEnableTendermintUserActionPin": { + "error": [], + "success": [ + "UserActionSuccess" + ] + }, + "TaskEnableUtxoCancel": { + "error": [ + "NoSuchTask", + "TaskFinished" ], + "success": [ + "CancelTaskId", + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": "success" + }, + "title": "Success" + } + ] + }, + "TaskEnableUtxoInit": { "error": [ + "NoSuchTask", + "TaskFinished" + ], + "success": [ + "SuccessTaskId", { - "title": "CoinCreationError - no Zcash Params", - "notes": "", "json": { - "error": "Error on platform coin ZOMBIE creation: ZCashParamsNotFound", - "error_path": "lib.z_coin_activation.z_coin", - "error_trace": "lib:104] z_coin_activation:218] z_coin:1007]", - "error_type": "CoinCreationError", - "error_data": { - "ticker": "ZOMBIE", - "error": "ZCashParamsNotFound" + "id": null, + "mmrpc": "2.0", + "result": { + "task_id": 3 } - } - }, + }, + "title": "Success" + } + ] + }, + "TaskEnableUtxoStatus": { + "error": [], + "success": [ { - "title": "NoSuchTask", - "notes": "You'll see this if the task number does not exist, or the task has already completed.", + "generated": true, "json": { + "id": null, "mmrpc": "2.0", - "error": "No such task '1'", - "error_path": "init_standalone_coin", - "error_trace": "init_standalone_coin:119]", - "error_type": "NoSuchTask", - "error_data": 1, - "id": null - } + "result": { + "details": "ActivatingCoin", + "status": "InProgress" + } + }, + "title": "Success" }, { - "title": "InvalidRequest", - "notes": "", "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "RequestingWalletBalance", + "status": "InProgress" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableUtxoUserActionPin": { + "error": [], + "success": [ + "UserActionSuccess" + ] + }, + "TaskEnableZCoinCancel": { + "error": [ + "NoSuchTask", + "TaskFinished" + ], + "success": [ + "CancelTaskId" + ] + }, + "TaskEnableZCoinInitBasic": { + "error": [ + "NoSuchTask", + "TaskFinished" + ], + "success": [ + "SuccessTaskId", + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "task_id": 4 + } + }, + "title": "Success" + } + ] + }, + "TaskEnableZCoinInitWasm": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "task_id": 5 + } + }, + "title": "Success" + } + ] + }, + "TaskEnableZCoinInitWithSyncParams": { + "error": [ + "NoSuchTask", + "TaskFinished" + ], + "success": [ + "SuccessTaskId", + { + "json": { + "id": null, "mmrpc": "2.0", + "result": { + "task_id": 6 + } + }, + "title": "Success" + } + ] + }, + "TaskEnableZCoinStatus": { + "error": [ + { + "json": { + "error": "Error on platform coin ZOMBIE creation: ZCashParamsNotFound", + "error_data": { + "error": "ZCashParamsNotFound", + "ticker": "ZOMBIE" + }, + "error_path": "lib.z_coin_activation.z_coin", + "error_trace": "lib:104] z_coin_activation:218] z_coin:1007]", + "error_type": "CoinCreationError" + }, + "notes": "", + "title": "CoinCreationError - no Zcash Params" + }, + "NoSuchTask", + { + "json": { "error": "Error parsing request: invalid value: integer `-205`, expected u64", + "error_data": "invalid value: integer `-205`, expected u64", "error_path": "dispatcher", "error_trace": "dispatcher:109]", "error_type": "InvalidRequest", - "error_data": "invalid value: integer `-205`, expected u64", - "id": 42 - } + "id": 42, + "mmrpc": "2.0" + }, + "notes": "", + "title": "InvalidRequest" }, { - "title": "No Zcash Params (alt format)", - "notes": "", "json": { + "id": null, "mmrpc": "2.0", "result": { - "status": "Error", "details": { "error": "Error on platform coin ZOMBIE creation: ZCashParamsNotFound", + "error_data": { + "error": "ZCashParamsNotFound", + "ticker": "ZOMBIE" + }, "error_path": "lib.z_coin_activation.z_coin", "error_trace": "lib:103] z_coin_activation:192] z_coin:761]", - "error_type": "CoinCreationError", + "error_type": "CoinCreationError" + }, + "status": "Error" + } + }, + "notes": "", + "title": "No Zcash Params (alt format)" + } + ], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": "ActivatingCoin", + "status": "InProgress" + } + }, + "notes": "", + "title": "ActivatingCoin - enabling has started" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "BuildingWalletDb": { + "current_scanned_block": 265311, + "latest_block": 269656 + } + }, + "status": "InProgress" + } + }, + "notes": "", + "title": "BuildingWalletDb" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "current_block": 269657, + "ticker": "ZOMBIE", + "wallet_balance": { + "address": "zs1e3puxpnal8ljjrqlxv4jctlyndxnm5a3mj5rarjvp0qv72hmm9caduxk9asu9kyc6erfx4zsauj", + "balance": { + "spendable": "29.99989008", + "unspendable": "0" + }, + "wallet_type": "Iguana" + } + }, + "status": "Ok" + } + }, + "notes": "", + "title": "Enabling complete" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "error": "Error on platform coin ZOMBIE creation: ZCashParamsNotFound", "error_data": { - "ticker": "ZOMBIE", - "error": "ZCashParamsNotFound" + "error": "ZCashParamsNotFound", + "ticker": "ZOMBIE" + }, + "error_path": "lib.init_standalone_coin.z_coin_activation.z_coin", + "error_trace": "lib:107] init_standalone_coin:216] z_coin_activation:263] z_coin:1138]", + "error_type": "CoinCreationError" + }, + "status": "Error" + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "UpdatingBlocksCache": { + "current_scanned_block": 265930, + "latest_block": 269656 } - } - }, - "id": null - } + }, + "status": "InProgress" + } + }, + "notes": "", + "title": "UpdatingBlocksCache" } ] }, - "TaskEnableEthStatus": { + "TaskEnableZCoinStatusBasic": { + "error": [], "success": [ { - "title": "InProgress - ActivatingCoin", - "notes": "", + "generated": true, "json": { + "id": null, "mmrpc": "2.0", "result": { - "status": "InProgress", - "details": "ActivatingCoin" - }, - "id": null - } + "details": { + "error": "Error on platform coin ZOMBIE creation: ZCashParamsNotFound", + "error_data": { + "error": "ZCashParamsNotFound", + "ticker": "ZOMBIE" + }, + "error_path": "lib.init_standalone_coin.z_coin_activation.z_coin", + "error_trace": "lib:107] init_standalone_coin:216] z_coin_activation:263] z_coin:1138]", + "error_type": "CoinCreationError" + }, + "status": "Error" + } + }, + "title": "Success" + } + ] + }, + "TaskEnableZCoinUserActionPin": { + "error": [], + "success": [ + "UserActionSuccess" + ] + }, + "TestDirectError": { + "error": [ + { + "generated": true, + "json": { + "error": "Invalid parameters", + "error_path": "test.path", + "error_type": "ValidationError", + "id": null, + "mmrpc": "2.0" + }, + "title": "Error" } ], + "success": [] + }, + "TestErrorStatus": { "error": [ { - "title": "No such task", - "notes": "Task ID does not exist or has been completed", + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "details": { + "error": "Test error message", + "error_type": "TestError" + }, + "status": "Error" + } + }, + "title": "Error" + } + ], + "success": [] + }, + "TestMethodError": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "error": "Invalid parameters", + "error_path": "test.path", + "error_type": "ValidationError", + "id": null, + "mmrpc": "2.0" + }, + "title": "Success" + } + ] + }, + "TestMethodSuccess": { + "error": [], + "success": [ + { + "generated": true, "json": { - "mmrpc": "2.0", - "error": "No such task '5'", - "error_path": "init_standalone_coin", - "error_trace": "init_standalone_coin:119]", - "error_type": "NoSuchTask", - "error_data": 5, - "id": null - } + "id": null, + "mmrpc": "2.0", + "result": "success" + }, + "title": "Success" + } + ] + }, + "TestSuccess": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": "success" + }, + "title": "Success" } ] } diff --git a/src/data/responses/kdf/v2/utils.json b/src/data/responses/kdf/v2/utils.json new file mode 100644 index 000000000..36fc725fc --- /dev/null +++ b/src/data/responses/kdf/v2/utils.json @@ -0,0 +1,16 @@ +{ + "AddNodeToVersionStat": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": "success" + }, + "title": "Success" + } + ] + } +} \ No newline at end of file diff --git a/src/data/responses/kdf/v2/wallet.json b/src/data/responses/kdf/v2/wallet.json new file mode 100644 index 000000000..ddb1e4e74 --- /dev/null +++ b/src/data/responses/kdf/v2/wallet.json @@ -0,0 +1,2834 @@ +{ + "ConsolidateUtxos": { + "error": [], + "success": [] + }, + "FetchUtxos": { + "error": [], + "success": [ + { + "generated": true, + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "addresses": [ + { + "address": "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5", + "count": 1, + "derivation_path": "m/44'/141'/0'/0/0", + "utxos": [ + { + "txid": "29d5bcb128f0de67fdd9f5c5afee8cef7b48e05b07822ec56aa3874b8f408a37", + "value": "7.62", + "vout": 0 + } + ] + }, + { + "address": "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi", + "count": 1, + "derivation_path": "m/44'/141'/0'/0/2", + "utxos": [ + { + "txid": "7ec96b2d0abac2edaafaa434f20106ac64a689d6d774fcdd69997c2ead59d66e", + "value": "7.62", + "vout": 0 + } + ] + }, + { + "address": "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa", + "count": 1, + "derivation_path": "m/44'/141'/0'/0/1", + "utxos": [ + { + "txid": "31896165d0f4dbf2dbfaff409af976634ac16fab69440ace7652a1fcd5bc9af1", + "value": "7.62", + "vout": 0 + } + ] + } + ], + "total_count": 3 + } + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "addresses": [ + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "count": 1, + "utxos": [ + { + "txid": "15734e22b9e3f3eae1be74ec8971de0e19245770b0e78cb5490494d7f17d16c9", + "value": "7.62", + "vout": 0 + } + ] + } + ], + "total_count": 1 + } + }, + "title": "Success" + } + ] + }, + "GetMyAddress": { + "error": [], + "success": [ + { + "json": { + "id": 4, + "mmrpc": "2.0", + "result": { + "coin": "SIA", + "wallet_address": "addr:1599ea80d9af168c...17030fb3" + } + }, + "title": "Success" + } + ] + }, + "GetPrivateKeysHd": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "addresses": [ + { + "address": "0x614b89716A94b5be94a67540dF9A5bF1bE1685F3", + "derivation_path": "m/44'/60'/0/0/0", + "priv_key": "0x4718e83c33159c53c19fbb44b98a5006a902d682ad096b2e1dbb7c55619463ac", + "pubkey": "0x47d306e1d039d958539d7b292c62a1da1d61eff2f4d8d96d35f3074032ef4a28f2434dab1170092591b955043792e6d8278d16b37363d79d34b5029dbe2d9a51" + } + ], + "coin": "ETH" + }, + { + "addresses": [ + { + "address": "RJyVMQknrJnGBQVUrSBNffc2BD8j7kM6w1", + "derivation_path": "m/44'/141'/0/0/1", + "priv_key": "UuMf4R7qEccYNDQWKYeooBANodhfev37QyoAnqZyb2VQz3CFGPH2", + "pubkey": "02acd4bb36d93065879be4aae17c62791898ce366adb732b03dc0ce8092d04944b" + }, + { + "address": "RLEiXpHJrBBFGLHfBVyKwB8pWyuZvTX46Q", + "derivation_path": "m/44'/141'/0/0/0", + "priv_key": "Ur57s4Btk5zv7ts2Rb1vHUjDzcBUuPGXZtuLUKK2yUTSCyNiA82f", + "pubkey": "02416813acfc3d051f2a3163241528331cb1407814ca7eda035e29dd81ce1a7360" + } + ], + "coin": "KMD" + } + ] + }, + "notes": "Each coin contains an array of HdKeysInfo objects", + "title": "HD Mode" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "addresses": [ + { + "address": "zs1kzmm3n8ux0p0ssku699seasfpscwmths8v4vml9k8mgqxjhjejhqr5ugkway9z9h9r8k7f9kar3", + "derivation_path": "m/44'/133'/0'", + "priv_key": "secret-extended-key-main1qwyyyk73qqqqpq95c6xu8dzqmxwjc6hwgm400j56qwshjdetu7cd8zgzgcglg43q520j3ntw8ap0zuu90ljr7tuqh6ynxg0u0huyw6443z3yjjz492csgp9cffacgq3ncp5lc7dhyrdjlhdzqvlvgs6qrgvy9kfvxg09jgcdnj2zdnxedg39y66fr3gegmsvstjkzuraqh9y00tvcnmnaejmz7lqkqahx3vu70p28m62reurmz0x79szzzh5p2yeg4hf88rhlx3u3hs66c3s2", + "pubkey": "", + "viewing_key": "zxviews1qwyyyk73qqqqpq95c6xu8dzqmxwjc6hwgm400j56qwshjdetu7cd8zgzgcglg43q5g3v327uwyn0dhpeu7fs7jk0fa0lus7a8alnrqqh8gxkl5pua6ern0vc3xceq5vslhgt9lzjx9md853jnwm5pm8c926ef5t4qdqj6t4wnj2zdnxedg39y66fr3gegmsvstjkzuraqh9y00tvcnmnaejmz7lqkqahx3vu70p28m62reurmz0x79szzzh5p2yeg4hf88rhlx3u3hsl3mh2e", + "z_derivation_path": "m/32'/133'/0" + } + ], + "coin": "ARRR" + }, + { + "addresses": [ + { + "address": "cosmos1ehy9ncnal5dv7ydzmupngh2lftz2tkfdm84phc", + "derivation_path": "m/44'/118'/0'/0/1", + "priv_key": "8f921063fe8893525908470ea254c4ebce9c3735e0844de19bd1343474a1b9f9", + "pubkey": "020912a98b604463c91a60c9512fa858a003a4d5380e05b38f56764672e5c414df" + }, + { + "address": "cosmos1hkg6p4lqnxardx2878clge6vjhfknf6s57ac92", + "derivation_path": "m/44'/118'/0'/0/0", + "priv_key": "bb1495023671d607e30c52b085706c87db3e9133d3826d9337b80f094af3d147", + "pubkey": "0339d31bbc2b130371ff830b1af26de3eb3b1152a4f90abd0cf0b4d3bc974a93b4" + } + ], + "coin": "ATOM" + }, + { + "addresses": [ + { + "address": "0x2AFB7a2d7b122D14366E114d17078d7B27383970", + "derivation_path": "m/44'/60'/0'/0/1", + "priv_key": "0x31c8f1844906139ecba4c8ea4d0ab22f2f6a6d9baf6b6e5f9655e578dfcc4717", + "pubkey": "0xd7f114222b3e3a753df8237d6c51a000a13df2c3740287c27dd6b1f80dd0abec287135edc23ab001511412e1a8b6d2b2bc9976e6beb699c40efe8e4b0399af38" + }, + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "derivation_path": "m/44'/60'/0'/0/0", + "priv_key": "0x37a37c2db4d5fb22cb93c593dde0ef2fecd3fc862dae9d1ff9ea9eb984968fa9", + "pubkey": "0x77e368739cf5f8c55acf8ddfcc8b06d7dc591aa44a0cbe69c66e1e0fd5f094cd6cdea840ae143e071615f1c386dec6da9a1c33a6907b6c807c247594c3ef9051" + } + ], + "coin": "ETH" + }, + { + "addresses": [ + { + "address": "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5", + "derivation_path": "m/44'/141'/0'/0/0", + "priv_key": "UxEBdQAQyqJyAgpFgALQwjkbq7jL73TvBMqpyHrXRjbrHSgzKLeq", + "pubkey": "033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1c" + }, + { + "address": "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa", + "derivation_path": "m/44'/141'/0'/0/1", + "priv_key": "Ur4kSNs8pBMMUnuv2yoS4T2GRrTQ42UpUu6bjs9TYEXNd5fbUvvi", + "pubkey": "0339e82bb13d3bb65a01b8ddb57fa56382e2020e67f825cb9113fcb97ea07fb9a6" + } + ], + "coin": "KMD" + }, + { + "addresses": [ + { + "address": "ltc1qfmtyjrvvavs3xffn4ntythp92cxpqzvmsae8mz", + "derivation_path": "m/84'/2'/0'/0/0", + "priv_key": "T4PiLD88Gm3r2HaeJZnK7KbGVCGeb3XMzRudG6y4FcFtnLJKoEQS", + "pubkey": "039b72983e890af8ec22e8bd530e40b12b1eea4d16ae4b8008f62a7df85c7501fc" + }, + { + "address": "ltc1qv3tlup2kkyqgyskktcvp33872pxzw3t6re0s42", + "derivation_path": "m/84'/2'/0'/0/1", + "priv_key": "T4Qe9PQCe1wV5DgD1n6zSeP74qe8fxDjAFcyTnsPsAAEqoRu9JAs", + "pubkey": "028411bf828cbcece736a4e1c23c6a0641eeb11f0e38e5e75314d614e7888c87a2" + } + ], + "coin": "LTC-segwit" + } + ] + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "addresses": [ + { + "address": "zs1kzmm3n8ux0p0ssku699seasfpscwmths8v4vml9k8mgqxjhjejhqr5ugkway9z9h9r8k7f9kar3", + "derivation_path": "m/44'/133'/0'", + "priv_key": "secret-extended-key-main1qwyyyk73qqqqpq95c6xu8dzqmxwjc6hwgm400j56qwshjdetu7cd8zgzgcglg43q520j3ntw8ap0zuu90ljr7tuqh6ynxg0u0huyw6443z3yjjz492csgp9cffacgq3ncp5lc7dhyrdjlhdzqvlvgs6qrgvy9kfvxg09jgcdnj2zdnxedg39y66fr3gegmsvstjkzuraqh9y00tvcnmnaejmz7lqkqahx3vu70p28m62reurmz0x79szzzh5p2yeg4hf88rhlx3u3hs66c3s2", + "pubkey": "", + "viewing_key": "zxviews1qwyyyk73qqqqpq95c6xu8dzqmxwjc6hwgm400j56qwshjdetu7cd8zgzgcglg43q5g3v327uwyn0dhpeu7fs7jk0fa0lus7a8alnrqqh8gxkl5pua6ern0vc3xceq5vslhgt9lzjx9md853jnwm5pm8c926ef5t4qdqj6t4wnj2zdnxedg39y66fr3gegmsvstjkzuraqh9y00tvcnmnaejmz7lqkqahx3vu70p28m62reurmz0x79szzzh5p2yeg4hf88rhlx3u3hsl3mh2e", + "z_derivation_path": "m/32'/133'/0" + } + ], + "coin": "ARRR" + }, + { + "addresses": [ + { + "address": "cosmos1ehy9ncnal5dv7ydzmupngh2lftz2tkfdm84phc", + "derivation_path": "m/44'/118'/0'/0/1", + "priv_key": "8f921063fe8893525908470ea254c4ebce9c3735e0844de19bd1343474a1b9f9", + "pubkey": "020912a98b604463c91a60c9512fa858a003a4d5380e05b38f56764672e5c414df" + }, + { + "address": "cosmos1hkg6p4lqnxardx2878clge6vjhfknf6s57ac92", + "derivation_path": "m/44'/118'/0'/0/0", + "priv_key": "bb1495023671d607e30c52b085706c87db3e9133d3826d9337b80f094af3d147", + "pubkey": "0339d31bbc2b130371ff830b1af26de3eb3b1152a4f90abd0cf0b4d3bc974a93b4" + } + ], + "coin": "ATOM" + }, + { + "addresses": [ + { + "address": "0x2AFB7a2d7b122D14366E114d17078d7B27383970", + "derivation_path": "m/44'/60'/0'/0/1", + "priv_key": "0x31c8f1844906139ecba4c8ea4d0ab22f2f6a6d9baf6b6e5f9655e578dfcc4717", + "pubkey": "0xd7f114222b3e3a753df8237d6c51a000a13df2c3740287c27dd6b1f80dd0abec287135edc23ab001511412e1a8b6d2b2bc9976e6beb699c40efe8e4b0399af38" + }, + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "derivation_path": "m/44'/60'/0'/0/0", + "priv_key": "0x37a37c2db4d5fb22cb93c593dde0ef2fecd3fc862dae9d1ff9ea9eb984968fa9", + "pubkey": "0x77e368739cf5f8c55acf8ddfcc8b06d7dc591aa44a0cbe69c66e1e0fd5f094cd6cdea840ae143e071615f1c386dec6da9a1c33a6907b6c807c247594c3ef9051" + } + ], + "coin": "ETH" + }, + { + "addresses": [ + { + "address": "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5", + "derivation_path": "m/44'/141'/0'/0/0", + "priv_key": "UxEBdQAQyqJyAgpFgALQwjkbq7jL73TvBMqpyHrXRjbrHSgzKLeq", + "pubkey": "033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1c" + }, + { + "address": "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa", + "derivation_path": "m/44'/141'/0'/0/1", + "priv_key": "Ur4kSNs8pBMMUnuv2yoS4T2GRrTQ42UpUu6bjs9TYEXNd5fbUvvi", + "pubkey": "0339e82bb13d3bb65a01b8ddb57fa56382e2020e67f825cb9113fcb97ea07fb9a6" + } + ], + "coin": "KMD" + }, + { + "addresses": [ + { + "address": "ltc1qfmtyjrvvavs3xffn4ntythp92cxpqzvmsae8mz", + "derivation_path": "m/84'/2'/0'/0/0", + "priv_key": "T4PiLD88Gm3r2HaeJZnK7KbGVCGeb3XMzRudG6y4FcFtnLJKoEQS", + "pubkey": "039b72983e890af8ec22e8bd530e40b12b1eea4d16ae4b8008f62a7df85c7501fc" + }, + { + "address": "ltc1qv3tlup2kkyqgyskktcvp33872pxzw3t6re0s42", + "derivation_path": "m/84'/2'/0'/0/1", + "priv_key": "T4Qe9PQCe1wV5DgD1n6zSeP74qe8fxDjAFcyTnsPsAAEqoRu9JAs", + "pubkey": "028411bf828cbcece736a4e1c23c6a0641eeb11f0e38e5e75314d614e7888c87a2" + } + ], + "coin": "LTC-segwit" + } + ] + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "addresses": [ + { + "address": "zs1kzmm3n8ux0p0ssku699seasfpscwmths8v4vml9k8mgqxjhjejhqr5ugkway9z9h9r8k7f9kar3", + "derivation_path": "m/44'/133'/0'", + "priv_key": "secret-extended-key-main1qwyyyk73qqqqpq95c6xu8dzqmxwjc6hwgm400j56qwshjdetu7cd8zgzgcglg43q520j3ntw8ap0zuu90ljr7tuqh6ynxg0u0huyw6443z3yjjz492csgp9cffacgq3ncp5lc7dhyrdjlhdzqvlvgs6qrgvy9kfvxg09jgcdnj2zdnxedg39y66fr3gegmsvstjkzuraqh9y00tvcnmnaejmz7lqkqahx3vu70p28m62reurmz0x79szzzh5p2yeg4hf88rhlx3u3hs66c3s2", + "pubkey": "", + "viewing_key": "zxviews1qwyyyk73qqqqpq95c6xu8dzqmxwjc6hwgm400j56qwshjdetu7cd8zgzgcglg43q5g3v327uwyn0dhpeu7fs7jk0fa0lus7a8alnrqqh8gxkl5pua6ern0vc3xceq5vslhgt9lzjx9md853jnwm5pm8c926ef5t4qdqj6t4wnj2zdnxedg39y66fr3gegmsvstjkzuraqh9y00tvcnmnaejmz7lqkqahx3vu70p28m62reurmz0x79szzzh5p2yeg4hf88rhlx3u3hsl3mh2e", + "z_derivation_path": "m/32'/133'/0" + } + ], + "coin": "ARRR" + }, + { + "addresses": [ + { + "address": "cosmos1ehy9ncnal5dv7ydzmupngh2lftz2tkfdm84phc", + "derivation_path": "m/44'/118'/0'/0/1", + "priv_key": "8f921063fe8893525908470ea254c4ebce9c3735e0844de19bd1343474a1b9f9", + "pubkey": "020912a98b604463c91a60c9512fa858a003a4d5380e05b38f56764672e5c414df" + }, + { + "address": "cosmos1hkg6p4lqnxardx2878clge6vjhfknf6s57ac92", + "derivation_path": "m/44'/118'/0'/0/0", + "priv_key": "bb1495023671d607e30c52b085706c87db3e9133d3826d9337b80f094af3d147", + "pubkey": "0339d31bbc2b130371ff830b1af26de3eb3b1152a4f90abd0cf0b4d3bc974a93b4" + } + ], + "coin": "ATOM" + }, + { + "addresses": [ + { + "address": "0x2AFB7a2d7b122D14366E114d17078d7B27383970", + "derivation_path": "m/44'/60'/0'/0/1", + "priv_key": "0x31c8f1844906139ecba4c8ea4d0ab22f2f6a6d9baf6b6e5f9655e578dfcc4717", + "pubkey": "0xd7f114222b3e3a753df8237d6c51a000a13df2c3740287c27dd6b1f80dd0abec287135edc23ab001511412e1a8b6d2b2bc9976e6beb699c40efe8e4b0399af38" + }, + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "derivation_path": "m/44'/60'/0'/0/0", + "priv_key": "0x37a37c2db4d5fb22cb93c593dde0ef2fecd3fc862dae9d1ff9ea9eb984968fa9", + "pubkey": "0x77e368739cf5f8c55acf8ddfcc8b06d7dc591aa44a0cbe69c66e1e0fd5f094cd6cdea840ae143e071615f1c386dec6da9a1c33a6907b6c807c247594c3ef9051" + } + ], + "coin": "ETH" + }, + { + "addresses": [ + { + "address": "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5", + "derivation_path": "m/44'/141'/0'/0/0", + "priv_key": "UxEBdQAQyqJyAgpFgALQwjkbq7jL73TvBMqpyHrXRjbrHSgzKLeq", + "pubkey": "033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1c" + }, + { + "address": "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa", + "derivation_path": "m/44'/141'/0'/0/1", + "priv_key": "Ur4kSNs8pBMMUnuv2yoS4T2GRrTQ42UpUu6bjs9TYEXNd5fbUvvi", + "pubkey": "0339e82bb13d3bb65a01b8ddb57fa56382e2020e67f825cb9113fcb97ea07fb9a6" + } + ], + "coin": "KMD" + }, + { + "addresses": [ + { + "address": "ltc1qfmtyjrvvavs3xffn4ntythp92cxpqzvmsae8mz", + "derivation_path": "m/84'/2'/0'/0/0", + "priv_key": "T4PiLD88Gm3r2HaeJZnK7KbGVCGeb3XMzRudG6y4FcFtnLJKoEQS", + "pubkey": "039b72983e890af8ec22e8bd530e40b12b1eea4d16ae4b8008f62a7df85c7501fc" + }, + { + "address": "ltc1qv3tlup2kkyqgyskktcvp33872pxzw3t6re0s42", + "derivation_path": "m/84'/2'/0'/0/1", + "priv_key": "T4Qe9PQCe1wV5DgD1n6zSeP74qe8fxDjAFcyTnsPsAAEqoRu9JAs", + "pubkey": "028411bf828cbcece736a4e1c23c6a0641eeb11f0e38e5e75314d614e7888c87a2" + } + ], + "coin": "LTC-segwit" + } + ] + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "addresses": [ + { + "address": "zs1kzmm3n8ux0p0ssku699seasfpscwmths8v4vml9k8mgqxjhjejhqr5ugkway9z9h9r8k7f9kar3", + "derivation_path": "m/44'/133'/0'", + "priv_key": "secret-extended-key-main1qwyyyk73qqqqpq95c6xu8dzqmxwjc6hwgm400j56qwshjdetu7cd8zgzgcglg43q520j3ntw8ap0zuu90ljr7tuqh6ynxg0u0huyw6443z3yjjz492csgp9cffacgq3ncp5lc7dhyrdjlhdzqvlvgs6qrgvy9kfvxg09jgcdnj2zdnxedg39y66fr3gegmsvstjkzuraqh9y00tvcnmnaejmz7lqkqahx3vu70p28m62reurmz0x79szzzh5p2yeg4hf88rhlx3u3hs66c3s2", + "pubkey": "", + "viewing_key": "zxviews1qwyyyk73qqqqpq95c6xu8dzqmxwjc6hwgm400j56qwshjdetu7cd8zgzgcglg43q5g3v327uwyn0dhpeu7fs7jk0fa0lus7a8alnrqqh8gxkl5pua6ern0vc3xceq5vslhgt9lzjx9md853jnwm5pm8c926ef5t4qdqj6t4wnj2zdnxedg39y66fr3gegmsvstjkzuraqh9y00tvcnmnaejmz7lqkqahx3vu70p28m62reurmz0x79szzzh5p2yeg4hf88rhlx3u3hsl3mh2e", + "z_derivation_path": "m/32'/133'/0" + } + ], + "coin": "ARRR" + }, + { + "addresses": [ + { + "address": "cosmos1ehy9ncnal5dv7ydzmupngh2lftz2tkfdm84phc", + "derivation_path": "m/44'/118'/0'/0/1", + "priv_key": "8f921063fe8893525908470ea254c4ebce9c3735e0844de19bd1343474a1b9f9", + "pubkey": "020912a98b604463c91a60c9512fa858a003a4d5380e05b38f56764672e5c414df" + }, + { + "address": "cosmos1hkg6p4lqnxardx2878clge6vjhfknf6s57ac92", + "derivation_path": "m/44'/118'/0'/0/0", + "priv_key": "bb1495023671d607e30c52b085706c87db3e9133d3826d9337b80f094af3d147", + "pubkey": "0339d31bbc2b130371ff830b1af26de3eb3b1152a4f90abd0cf0b4d3bc974a93b4" + } + ], + "coin": "ATOM" + }, + { + "addresses": [ + { + "address": "0x2AFB7a2d7b122D14366E114d17078d7B27383970", + "derivation_path": "m/44'/60'/0'/0/1", + "priv_key": "0x31c8f1844906139ecba4c8ea4d0ab22f2f6a6d9baf6b6e5f9655e578dfcc4717", + "pubkey": "0xd7f114222b3e3a753df8237d6c51a000a13df2c3740287c27dd6b1f80dd0abec287135edc23ab001511412e1a8b6d2b2bc9976e6beb699c40efe8e4b0399af38" + }, + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "derivation_path": "m/44'/60'/0'/0/0", + "priv_key": "0x37a37c2db4d5fb22cb93c593dde0ef2fecd3fc862dae9d1ff9ea9eb984968fa9", + "pubkey": "0x77e368739cf5f8c55acf8ddfcc8b06d7dc591aa44a0cbe69c66e1e0fd5f094cd6cdea840ae143e071615f1c386dec6da9a1c33a6907b6c807c247594c3ef9051" + } + ], + "coin": "ETH" + }, + { + "addresses": [ + { + "address": "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5", + "derivation_path": "m/44'/141'/0'/0/0", + "priv_key": "UxEBdQAQyqJyAgpFgALQwjkbq7jL73TvBMqpyHrXRjbrHSgzKLeq", + "pubkey": "033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1c" + }, + { + "address": "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa", + "derivation_path": "m/44'/141'/0'/0/1", + "priv_key": "Ur4kSNs8pBMMUnuv2yoS4T2GRrTQ42UpUu6bjs9TYEXNd5fbUvvi", + "pubkey": "0339e82bb13d3bb65a01b8ddb57fa56382e2020e67f825cb9113fcb97ea07fb9a6" + } + ], + "coin": "KMD" + }, + { + "addresses": [ + { + "address": "ltc1qfmtyjrvvavs3xffn4ntythp92cxpqzvmsae8mz", + "derivation_path": "m/84'/2'/0'/0/0", + "priv_key": "T4PiLD88Gm3r2HaeJZnK7KbGVCGeb3XMzRudG6y4FcFtnLJKoEQS", + "pubkey": "039b72983e890af8ec22e8bd530e40b12b1eea4d16ae4b8008f62a7df85c7501fc" + }, + { + "address": "ltc1qv3tlup2kkyqgyskktcvp33872pxzw3t6re0s42", + "derivation_path": "m/84'/2'/0'/0/1", + "priv_key": "T4Qe9PQCe1wV5DgD1n6zSeP74qe8fxDjAFcyTnsPsAAEqoRu9JAs", + "pubkey": "028411bf828cbcece736a4e1c23c6a0641eeb11f0e38e5e75314d614e7888c87a2" + } + ], + "coin": "LTC-segwit" + } + ] + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "addresses": [ + { + "address": "zs1kzmm3n8ux0p0ssku699seasfpscwmths8v4vml9k8mgqxjhjejhqr5ugkway9z9h9r8k7f9kar3", + "derivation_path": "m/44'/133'/0'", + "priv_key": "secret-extended-key-main1qwyyyk73qqqqpq95c6xu8dzqmxwjc6hwgm400j56qwshjdetu7cd8zgzgcglg43q520j3ntw8ap0zuu90ljr7tuqh6ynxg0u0huyw6443z3yjjz492csgp9cffacgq3ncp5lc7dhyrdjlhdzqvlvgs6qrgvy9kfvxg09jgcdnj2zdnxedg39y66fr3gegmsvstjkzuraqh9y00tvcnmnaejmz7lqkqahx3vu70p28m62reurmz0x79szzzh5p2yeg4hf88rhlx3u3hs66c3s2", + "pubkey": "", + "viewing_key": "zxviews1qwyyyk73qqqqpq95c6xu8dzqmxwjc6hwgm400j56qwshjdetu7cd8zgzgcglg43q5g3v327uwyn0dhpeu7fs7jk0fa0lus7a8alnrqqh8gxkl5pua6ern0vc3xceq5vslhgt9lzjx9md853jnwm5pm8c926ef5t4qdqj6t4wnj2zdnxedg39y66fr3gegmsvstjkzuraqh9y00tvcnmnaejmz7lqkqahx3vu70p28m62reurmz0x79szzzh5p2yeg4hf88rhlx3u3hsl3mh2e", + "z_derivation_path": "m/32'/133'/0" + } + ], + "coin": "ARRR" + }, + { + "addresses": [ + { + "address": "cosmos1ehy9ncnal5dv7ydzmupngh2lftz2tkfdm84phc", + "derivation_path": "m/44'/118'/0'/0/1", + "priv_key": "8f921063fe8893525908470ea254c4ebce9c3735e0844de19bd1343474a1b9f9", + "pubkey": "020912a98b604463c91a60c9512fa858a003a4d5380e05b38f56764672e5c414df" + }, + { + "address": "cosmos1hkg6p4lqnxardx2878clge6vjhfknf6s57ac92", + "derivation_path": "m/44'/118'/0'/0/0", + "priv_key": "bb1495023671d607e30c52b085706c87db3e9133d3826d9337b80f094af3d147", + "pubkey": "0339d31bbc2b130371ff830b1af26de3eb3b1152a4f90abd0cf0b4d3bc974a93b4" + } + ], + "coin": "ATOM" + }, + { + "addresses": [ + { + "address": "0x2AFB7a2d7b122D14366E114d17078d7B27383970", + "derivation_path": "m/44'/60'/0'/0/1", + "priv_key": "0x31c8f1844906139ecba4c8ea4d0ab22f2f6a6d9baf6b6e5f9655e578dfcc4717", + "pubkey": "0xd7f114222b3e3a753df8237d6c51a000a13df2c3740287c27dd6b1f80dd0abec287135edc23ab001511412e1a8b6d2b2bc9976e6beb699c40efe8e4b0399af38" + }, + { + "address": "0xAEeF0f62Ff189D1e4B1b62E7efF453b15d32886f", + "derivation_path": "m/44'/60'/0'/0/0", + "priv_key": "0x37a37c2db4d5fb22cb93c593dde0ef2fecd3fc862dae9d1ff9ea9eb984968fa9", + "pubkey": "0x77e368739cf5f8c55acf8ddfcc8b06d7dc591aa44a0cbe69c66e1e0fd5f094cd6cdea840ae143e071615f1c386dec6da9a1c33a6907b6c807c247594c3ef9051" + } + ], + "coin": "ETH" + }, + { + "addresses": [ + { + "address": "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5", + "derivation_path": "m/44'/141'/0'/0/0", + "priv_key": "UxEBdQAQyqJyAgpFgALQwjkbq7jL73TvBMqpyHrXRjbrHSgzKLeq", + "pubkey": "033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1c" + }, + { + "address": "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa", + "derivation_path": "m/44'/141'/0'/0/1", + "priv_key": "Ur4kSNs8pBMMUnuv2yoS4T2GRrTQ42UpUu6bjs9TYEXNd5fbUvvi", + "pubkey": "0339e82bb13d3bb65a01b8ddb57fa56382e2020e67f825cb9113fcb97ea07fb9a6" + } + ], + "coin": "KMD" + }, + { + "addresses": [ + { + "address": "ltc1qfmtyjrvvavs3xffn4ntythp92cxpqzvmsae8mz", + "derivation_path": "m/84'/2'/0'/0/0", + "priv_key": "T4PiLD88Gm3r2HaeJZnK7KbGVCGeb3XMzRudG6y4FcFtnLJKoEQS", + "pubkey": "039b72983e890af8ec22e8bd530e40b12b1eea4d16ae4b8008f62a7df85c7501fc" + }, + { + "address": "ltc1qv3tlup2kkyqgyskktcvp33872pxzw3t6re0s42", + "derivation_path": "m/84'/2'/0'/0/1", + "priv_key": "T4Qe9PQCe1wV5DgD1n6zSeP74qe8fxDjAFcyTnsPsAAEqoRu9JAs", + "pubkey": "028411bf828cbcece736a4e1c23c6a0641eeb11f0e38e5e75314d614e7888c87a2" + } + ], + "coin": "LTC-segwit" + } + ] + }, + "title": "Success" + } + ] + }, + "GetPrivateKeysIguana": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "address": "RQbyMz5jSBjidHkM4wRAhmbHUTSR7UehXG", + "coin": "KMD", + "priv_key": "UpaMPnKdPZJWBGb8whpQWjP5A61WpT6e2SUYQz4KyfkE4JzVU9ZF", + "pubkey": "0399e7edd441d026ab62d915c6542464002c1634cacfa3afd69fb9c08b7b76355f" + } + ] + }, + "notes": "Each item is an IguanaKeysInfo object", + "title": "Iguana Mode" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "coin": "ETH", + "priv_key": "0x9066762458bf44c701d8fd9f592254166cb7b680e95f0b9d0b82bae32c7a8167", + "pubkey": "0x88533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4c2c88524377452dd615ad296399043265c24d3fa8b9f2a6b89f1db78ba0e6baf" + }, + { + "address": "cosmos1xt2ru7aq7zxnyz3zgs89twzzgpl5s84lxkx0h5", + "coin": "ATOM", + "priv_key": "9066762458bf44c701d8fd9f592254166cb7b680e95f0b9d0b82bae32c7a8167", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "LPriJnGd14ZT6HC2vAU4JEC6TZDEsPd73u", + "coin": "LTC-segwit", + "priv_key": "T7tfx3ogYSrxZuUgYfzDNw1sAkHZGa4DzRRicJuckWB8z988TXxH", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "coin": "KMD", + "priv_key": "UtrEoz8UeHrcG7duBaivw29i9xhPHbJwwiuHKm4keFDgN7Ueduv7", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "zs16g3ghhppmrtfw2mvca6zar65nk87vfventucjjyslwcaqpreq67mrph9ngzayklmqt4dgf7ntuq", + "coin": "ARRR", + "priv_key": "secret-extended-key-main1qqqqqqqqqqqqqqxclwzn838nz8mshqywdxzd4s8wpv559rvs53xyfu6dhuhhl0k9vn8sgzq3pymlk6k5szyuzvt9ze8cpqn9wgw02ya2e0h0hadyujsqhnssv63j2ld4sh92qm4zyn6ham56czsf25zgk8jtwrakukvfavst5u8thk23x6e6zyp5p27tr9yerzua46wvqcu6kwea3ktxm44f3v4arnrqvhwrgjj8lncvs7ersx642asxzclkxatfnmaj9n4gfjrx4zsvcyusf", + "pubkey": "", + "viewing_key": "zxviews1qqqqqqqqqqqqqqxclwzn838nz8mshqywdxzd4s8wpv559rvs53xyfu6dhuhhl0k9vjw8erw00752g4c3wjhe27qp5hc2e7458qhz6x3rt0x53e65mmwgwfkrd3ang52e0m6puh003vvrg7ylrllmpkf2xq8yaa70yqscy0w45u8thk23x6e6zyp5p27tr9yerzua46wvqcu6kwea3ktxm44f3v4arnrqvhwrgjj8lncvs7ersx642asxzclkxatfnmaj9n4gfjrx4zsd3xsef" + } + ] + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "coin": "ETH", + "priv_key": "0x9066762458bf44c701d8fd9f592254166cb7b680e95f0b9d0b82bae32c7a8167", + "pubkey": "0x88533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4c2c88524377452dd615ad296399043265c24d3fa8b9f2a6b89f1db78ba0e6baf" + }, + { + "address": "cosmos1xt2ru7aq7zxnyz3zgs89twzzgpl5s84lxkx0h5", + "coin": "ATOM", + "priv_key": "9066762458bf44c701d8fd9f592254166cb7b680e95f0b9d0b82bae32c7a8167", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "LPriJnGd14ZT6HC2vAU4JEC6TZDEsPd73u", + "coin": "LTC-segwit", + "priv_key": "T7tfx3ogYSrxZuUgYfzDNw1sAkHZGa4DzRRicJuckWB8z988TXxH", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "coin": "KMD", + "priv_key": "UtrEoz8UeHrcG7duBaivw29i9xhPHbJwwiuHKm4keFDgN7Ueduv7", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "zs16g3ghhppmrtfw2mvca6zar65nk87vfventucjjyslwcaqpreq67mrph9ngzayklmqt4dgf7ntuq", + "coin": "ARRR", + "priv_key": "secret-extended-key-main1qqqqqqqqqqqqqqxclwzn838nz8mshqywdxzd4s8wpv559rvs53xyfu6dhuhhl0k9vn8sgzq3pymlk6k5szyuzvt9ze8cpqn9wgw02ya2e0h0hadyujsqhnssv63j2ld4sh92qm4zyn6ham56czsf25zgk8jtwrakukvfavst5u8thk23x6e6zyp5p27tr9yerzua46wvqcu6kwea3ktxm44f3v4arnrqvhwrgjj8lncvs7ersx642asxzclkxatfnmaj9n4gfjrx4zsvcyusf", + "pubkey": "", + "viewing_key": "zxviews1qqqqqqqqqqqqqqxclwzn838nz8mshqywdxzd4s8wpv559rvs53xyfu6dhuhhl0k9vjw8erw00752g4c3wjhe27qp5hc2e7458qhz6x3rt0x53e65mmwgwfkrd3ang52e0m6puh003vvrg7ylrllmpkf2xq8yaa70yqscy0w45u8thk23x6e6zyp5p27tr9yerzua46wvqcu6kwea3ktxm44f3v4arnrqvhwrgjj8lncvs7ersx642asxzclkxatfnmaj9n4gfjrx4zsd3xsef" + } + ] + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "coin": "ETH", + "priv_key": "0x9066762458bf44c701d8fd9f592254166cb7b680e95f0b9d0b82bae32c7a8167", + "pubkey": "0x88533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4c2c88524377452dd615ad296399043265c24d3fa8b9f2a6b89f1db78ba0e6baf" + }, + { + "address": "cosmos1xt2ru7aq7zxnyz3zgs89twzzgpl5s84lxkx0h5", + "coin": "ATOM", + "priv_key": "9066762458bf44c701d8fd9f592254166cb7b680e95f0b9d0b82bae32c7a8167", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "LPriJnGd14ZT6HC2vAU4JEC6TZDEsPd73u", + "coin": "LTC-segwit", + "priv_key": "T7tfx3ogYSrxZuUgYfzDNw1sAkHZGa4DzRRicJuckWB8z988TXxH", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "coin": "KMD", + "priv_key": "UtrEoz8UeHrcG7duBaivw29i9xhPHbJwwiuHKm4keFDgN7Ueduv7", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "zs16g3ghhppmrtfw2mvca6zar65nk87vfventucjjyslwcaqpreq67mrph9ngzayklmqt4dgf7ntuq", + "coin": "ARRR", + "priv_key": "secret-extended-key-main1qqqqqqqqqqqqqqxclwzn838nz8mshqywdxzd4s8wpv559rvs53xyfu6dhuhhl0k9vn8sgzq3pymlk6k5szyuzvt9ze8cpqn9wgw02ya2e0h0hadyujsqhnssv63j2ld4sh92qm4zyn6ham56czsf25zgk8jtwrakukvfavst5u8thk23x6e6zyp5p27tr9yerzua46wvqcu6kwea3ktxm44f3v4arnrqvhwrgjj8lncvs7ersx642asxzclkxatfnmaj9n4gfjrx4zsvcyusf", + "pubkey": "", + "viewing_key": "zxviews1qqqqqqqqqqqqqqxclwzn838nz8mshqywdxzd4s8wpv559rvs53xyfu6dhuhhl0k9vjw8erw00752g4c3wjhe27qp5hc2e7458qhz6x3rt0x53e65mmwgwfkrd3ang52e0m6puh003vvrg7ylrllmpkf2xq8yaa70yqscy0w45u8thk23x6e6zyp5p27tr9yerzua46wvqcu6kwea3ktxm44f3v4arnrqvhwrgjj8lncvs7ersx642asxzclkxatfnmaj9n4gfjrx4zsd3xsef" + } + ] + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "coin": "ETH", + "priv_key": "0x9066762458bf44c701d8fd9f592254166cb7b680e95f0b9d0b82bae32c7a8167", + "pubkey": "0x88533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4c2c88524377452dd615ad296399043265c24d3fa8b9f2a6b89f1db78ba0e6baf" + }, + { + "address": "cosmos1xt2ru7aq7zxnyz3zgs89twzzgpl5s84lxkx0h5", + "coin": "ATOM", + "priv_key": "9066762458bf44c701d8fd9f592254166cb7b680e95f0b9d0b82bae32c7a8167", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "LPriJnGd14ZT6HC2vAU4JEC6TZDEsPd73u", + "coin": "LTC-segwit", + "priv_key": "T7tfx3ogYSrxZuUgYfzDNw1sAkHZGa4DzRRicJuckWB8z988TXxH", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "coin": "KMD", + "priv_key": "UtrEoz8UeHrcG7duBaivw29i9xhPHbJwwiuHKm4keFDgN7Ueduv7", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "zs16g3ghhppmrtfw2mvca6zar65nk87vfventucjjyslwcaqpreq67mrph9ngzayklmqt4dgf7ntuq", + "coin": "ARRR", + "priv_key": "secret-extended-key-main1qqqqqqqqqqqqqqxclwzn838nz8mshqywdxzd4s8wpv559rvs53xyfu6dhuhhl0k9vn8sgzq3pymlk6k5szyuzvt9ze8cpqn9wgw02ya2e0h0hadyujsqhnssv63j2ld4sh92qm4zyn6ham56czsf25zgk8jtwrakukvfavst5u8thk23x6e6zyp5p27tr9yerzua46wvqcu6kwea3ktxm44f3v4arnrqvhwrgjj8lncvs7ersx642asxzclkxatfnmaj9n4gfjrx4zsvcyusf", + "pubkey": "", + "viewing_key": "zxviews1qqqqqqqqqqqqqqxclwzn838nz8mshqywdxzd4s8wpv559rvs53xyfu6dhuhhl0k9vjw8erw00752g4c3wjhe27qp5hc2e7458qhz6x3rt0x53e65mmwgwfkrd3ang52e0m6puh003vvrg7ylrllmpkf2xq8yaa70yqscy0w45u8thk23x6e6zyp5p27tr9yerzua46wvqcu6kwea3ktxm44f3v4arnrqvhwrgjj8lncvs7ersx642asxzclkxatfnmaj9n4gfjrx4zsd3xsef" + } + ] + }, + "title": "Success" + }, + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": [ + { + "address": "0x9A8ED9876E0D06DF80f16e7d1ad6271055C0E375", + "coin": "ETH", + "priv_key": "0x9066762458bf44c701d8fd9f592254166cb7b680e95f0b9d0b82bae32c7a8167", + "pubkey": "0x88533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4c2c88524377452dd615ad296399043265c24d3fa8b9f2a6b89f1db78ba0e6baf" + }, + { + "address": "cosmos1xt2ru7aq7zxnyz3zgs89twzzgpl5s84lxkx0h5", + "coin": "ATOM", + "priv_key": "9066762458bf44c701d8fd9f592254166cb7b680e95f0b9d0b82bae32c7a8167", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "LPriJnGd14ZT6HC2vAU4JEC6TZDEsPd73u", + "coin": "LTC-segwit", + "priv_key": "T7tfx3ogYSrxZuUgYfzDNw1sAkHZGa4DzRRicJuckWB8z988TXxH", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW", + "coin": "KMD", + "priv_key": "UtrEoz8UeHrcG7duBaivw29i9xhPHbJwwiuHKm4keFDgN7Ueduv7", + "pubkey": "0388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4" + }, + { + "address": "zs16g3ghhppmrtfw2mvca6zar65nk87vfventucjjyslwcaqpreq67mrph9ngzayklmqt4dgf7ntuq", + "coin": "ARRR", + "priv_key": "secret-extended-key-main1qqqqqqqqqqqqqqxclwzn838nz8mshqywdxzd4s8wpv559rvs53xyfu6dhuhhl0k9vn8sgzq3pymlk6k5szyuzvt9ze8cpqn9wgw02ya2e0h0hadyujsqhnssv63j2ld4sh92qm4zyn6ham56czsf25zgk8jtwrakukvfavst5u8thk23x6e6zyp5p27tr9yerzua46wvqcu6kwea3ktxm44f3v4arnrqvhwrgjj8lncvs7ersx642asxzclkxatfnmaj9n4gfjrx4zsvcyusf", + "pubkey": "", + "viewing_key": "zxviews1qqqqqqqqqqqqqqxclwzn838nz8mshqywdxzd4s8wpv559rvs53xyfu6dhuhhl0k9vjw8erw00752g4c3wjhe27qp5hc2e7458qhz6x3rt0x53e65mmwgwfkrd3ang52e0m6puh003vvrg7ylrllmpkf2xq8yaa70yqscy0w45u8thk23x6e6zyp5p27tr9yerzua46wvqcu6kwea3ktxm44f3v4arnrqvhwrgjj8lncvs7ersx642asxzclkxatfnmaj9n4gfjrx4zsd3xsef" + } + ] + }, + "title": "Success" + } + ] + }, + "GetRawTransaction": { + "error": [ + { + "json": { + "id": 0, + "mmrpc": "2.0", + "error": "No such coin KMD", + "error_path": "lp_coins", + "error_trace": "lp_coins:2234] lp_coins:2156]", + "error_type": "NoSuchCoin", + "error_data": { + "coin": "KMD" + }, + "hint": "If you don't have a known tx_hash, check postman/generated/reports/test_data.json for sample addresses and known_txids (e.g., DOC). You can also use my_tx_history to discover txids for enabled coins." + }, + "title": "Error (no such coin)" + }, + { + "json": { + "id": 1, + "mmrpc": "2.0", + "error": "Invalid hash: Invalid input length", + "error_path": "utxo_common", + "error_trace": "utxo_common:1809]", + "error_type": "InvalidHashError", + "error_data": "Invalid input length", + "hint": "Provide a valid tx_hash. For testable values, see postman/generated/reports/test_data.json under native-hd.DOC.addresses[...].known_txids, or fetch via my_tx_history." + }, + "title": "Error (invalid hash)" + }, + { + "json": { + "id": 1, + "mmrpc": "2.0", + "error": "Internal error: eth:3221] Crypto error (Invalid EC signature)", + "error_path": "eth", + "error_trace": "eth:543]", + "error_type": "InternalError", + "error_data": "eth:3221] Crypto error (Invalid EC signature)", + "hint": "Verify the tx_hash and that the coin is enabled and synced. If you need a known-good tx for testing, prefer DOC from test_data.json." + }, + "title": "Error (internal)" + } + ], + "success": [ + { + "json": { + "id": 7, + "mmrpc": "2.0", + "result": { + "tx_hex": "7b22736961636f696e496e70757473223a5b5d2c22736961636f696e4f757470757473223a5b5d2c226d696e6572466565223a2231303030303030303030303030303030303030227d" + } + }, + "title": "Success" + } + ] + }, + "MyTxHistoryAccountDoc": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "coin": "DOC", + "current_block": 2066531, + "limit": 10, + "paging_options": { + "PageNumber": 1 + }, + "skipped": 0, + "sync_status": { + "state": "Finished" + }, + "target": { + "account_id": 77, + "type": "account_id" + }, + "total": 1, + "total_pages": 1, + "transactions": [ + { + "block_height": 2051968, + "coin": "DOC", + "confirmations": 14564, + "fee_details": { + "amount": "0.0001", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RNTv4xTLLm26p3SvsQCBy9qNK7s1RgGYSB" + ], + "internal_id": "e5cd671c71f9a2564cd05057ee94be86bd215df257bfb7408b9ee6deb1e461c5", + "memo": null, + "my_balance_change": "7.777", + "received_by_me": "7.777", + "spent_by_me": "0", + "timestamp": 1693906841, + "to": [ + "RLNu8gszQ8ENUrY3VSyBS2714CNVwn1f7P", + "RNTv4xTLLm26p3SvsQCBy9qNK7s1RgGYSB" + ], + "total_amount": "24734.9033", + "transaction_type": "StandardTransfer", + "tx_hash": "e5cd671c71f9a2564cd05057ee94be86bd215df257bfb7408b9ee6deb1e461c5", + "tx_hex": "0400008085202f890165d40f00c0b4395ccdbe6d4f3124fa8b06d4910e5327b67c8186dd4b55afa124030000006b483045022100a3fe466d53ce9e5429608427e0d0224e8923d86dabf5b6c4b4d54dae7c060acd022039d165e1e245efd93a9172ab0a7837985310b4beccd6e05be1894cd66e0912cc012102d09f2cb1693be9c0ea73bb48d45ce61805edd1c43590681b02f877206078a5b3ffffffff0400e1f505000000001976a91479bdbbf2302fa86c7c5861ddc782e6e5776a546d88ac00c2eb0b000000001976a91479bdbbf2302fa86c7c5861ddc782e6e5776a546d88aca01f791c000000001976a91479bdbbf2302fa86c7c5861ddc782e6e5776a546d88ace04728b93f0200001976a91490a0d8ba62c339ade97a14e81b6f531de03fdbb288ac00000000000000000000000000000000000000" + } + ] + } + }, + "title": "Success" + } + ] + }, + "MyTxHistoryAddressDoc": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "coin": "DOC", + "current_block": 2066531, + "limit": 1, + "paging_options": { + "PageNumber": 1 + }, + "skipped": 0, + "sync_status": { + "state": "Finished" + }, + "target": { + "account_id": 0, + "address_id": 1, + "chain": "External", + "type": "address_id" + }, + "total": 10, + "total_pages": 10, + "transactions": [ + { + "block_height": 2046628, + "coin": "DOC", + "confirmations": 19904, + "fee_details": { + "amount": "0.00001", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RVyndZp3ZrhGKSwHryyM3Kcz9aq2EJrW1z" + ], + "internal_id": "8c6456383d7d112ec400597739e07a3c50557a4ec399b8993312d8c4780ce973", + "memo": null, + "my_balance_change": "-0.00001", + "received_by_me": "0.99292", + "spent_by_me": "0.99293", + "timestamp": 1693584717, + "to": [ + "RVyndZp3ZrhGKSwHryyM3Kcz9aq2EJrW1z", + "RXNtAyDSsY3DS3VxTpJegzoHU9bUX54j56" + ], + "total_amount": "0.99293", + "transaction_type": "StandardTransfer", + "tx_hash": "8c6456383d7d112ec400597739e07a3c50557a4ec399b8993312d8c4780ce973", + "tx_hex": "0400008085202f8901c97b980d21538685a1fa82e1bb0c3a25b2dfaeaecb10647403b48afaefdcef3d010000006b483045022100d4ec136c54cda3861916e2390f0c8afc5348ce7844eaecb98da1bd2c964703280220107bb95194bdb51b9fd584d1834357376288b1ed5185a2bae34b290947683f5a01210325f62245ee44b9e586e71ef462833d8aa32ae2a05d06a9b78a9fb95b7a7d2a3fffffffff0280969800000000001976a914f26650dc9aa4e4505978ad635cdb15491cee70e188ace07c5205000000001976a914e30fff4883a28b09889f3e94c24392c899d2833e88ac930cf264000000000000000000000000000000" + } + ] + } + }, + "title": "Success" + } + ] + }, + "MyTxHistoryBchFromId": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "coin": "BCH", + "current_block": 772612, + "limit": 10, + "paging_options": { + "FromId": "433b641bc89e1b59c22717918583c60ec98421805c8e85b064691705d9aeb970" + }, + "skipped": 0, + "sync_status": { + "state": "Finished" + }, + "target": { + "type": "iguana" + }, + "total": 1, + "total_pages": 1, + "transactions": [ + { + "block_height": 772211, + "coin": "BCH", + "confirmations": 402, + "fee_details": { + "amount": "0.00000482", + "coin": "BCH", + "type": "Utxo" + }, + "from": [ + "simpleledger:qpvq4u67x4fa276t8gsrday4nugzgm5ccu4usawss8" + ], + "internal_id": "57b78eb912a704921640a589d8bb42bb147dfb88c3d1b4b2e3df910be6b9ab31", + "my_balance_change": "100", + "received_by_me": "100", + "spent_by_me": "0", + "timestamp": 1671817336, + "to": [ + "simpleledger:qpvq4u67x4fa276t8gsrday4nugzgm5ccu4usawss8", + "simpleledger:qrf5vpn78s7rjexrjhlwyzzeg7gw98k7t5va3wuz4v" + ], + "total_amount": "1480551016.67", + "transaction_type": { + "TokenTransfer": "5321508197ffed321c5fc9a1427e5c68b31d2c1ec92ae1c495f8acb08d8d66cd" + }, + "tx_hash": "7b58248f3486079951a57d6dbd41c019a83f2b876c9fa3afa6fcc5a7c595b837", + "tx_hex": "0200000002365a29eb638da7fc57720ad6c99fdbc6cfb9c957920cfb62fd69e494b412c1c1020000006b483045022100de81bca8cfef2f95b3da8aa89edf4f5cc6cf489c565d0965b8142380ef3986f1022062d6ed47f2cd281f4860a27e835949aafbab89eeb0865fbf2280a283dfb7c417412102b9fdfedefde71b21523974b9f24a4b6a1b83c5640b839baa6eb14418cae08191ffffffffc1f73b403f893f93d95b8c7dfa1b59bb5445109d4c51107da1e08fb770e54136010000006a47304402203658375dac3b84ae17e72cf3f5157b8ad25e7caee0629fa8708868974f8d58b402206f38d016ed4e390d783627441685692d21b889d83919abd39368cba28f43f544412102b9fdfedefde71b21523974b9f24a4b6a1b83c5640b839baa6eb14418cae08191ffffffff040000000000000000406a04534c500001010453454e44205321508197ffed321c5fc9a1427e5c68b31d2c1ec92ae1c495f8acb08d8d66cd080000000000002710080000002278c569d322020000000000001976a914d346067e3c3c3964c395fee208594790e29ede5d88ac22020000000000001976a914580af35e3553d57b4b3a2036f4959f10246e98c788ac68955e03000000001976a914580af35e3553d57b4b3a2036f4959f10246e98c788ac00000000" + } + ] + } + }, + "title": "Success" + } + ] + }, + "MyTxHistoryBchPage2": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "coin": "BCH", + "current_block": 772607, + "limit": 2, + "paging_options": { + "PageNumber": 2 + }, + "skipped": 2, + "sync_status": { + "state": "Finished" + }, + "target": { + "type": "iguana" + }, + "total": 16, + "total_pages": 8, + "transactions": [ + { + "block_height": 766923, + "coin": "BCH", + "confirmations": 5685, + "fee_details": { + "amount": "0.00001", + "coin": "BCH", + "type": "Utxo" + }, + "from": [ + "bitcoincash:ppaa62685yaucdf2a54g3rgtyc9g7yawrvvmqsfumc" + ], + "internal_id": "e2167df56142bccdb8c620297f1b6ca3f7c8a955332838430d4d0f62530870f9", + "my_balance_change": "0.00170035", + "received_by_me": "0.00170035", + "spent_by_me": "0", + "timestamp": 1668615553, + "to": [ + "bitcoincash:qqg6z43mlf26up06vgdjufz6hedrtry99cvk5dgcnt" + ], + "total_amount": "0.00171035", + "transaction_type": "StandardTransfer", + "tx_hash": "e2167df56142bccdb8c620297f1b6ca3f7c8a955332838430d4d0f62530870f9", + "tx_hex": "0100000001b7b45d92f8f3413a0e5656258e0a51f5c7e8230c0a08cef2ebec1ddbb8f7c28200000000d747304402203ca957fdfcfbba6123d78afe28b17fd4103cc04f6ada4110eb61c2a0350c29b802204215f203d583e8bcc79bd70f33af4f4e27500b5a5375efe75a1c31ec112f3c344120b3f71dbea00eeace7f09b0911de31e46f76a48036b86ccc207dac55540912e01004c6b6304dbf67563b175210315d9c51c657ab1be4ae9d3ab6e76a619d3bccfe830d5363fa168424c0d044732ac6782012088a914dde61fe24ea3cfa39379c475702692fa2f080900882103ed00156316c46094c0cbcf21a5ee549a1b3a50938c43096ef499ca28059edca6ac68ffffffff0133980200000000001976a91411a1563bfa55ae05fa621b2e245abe5a358c852e88acdbf67563" + } + ] + } + }, + "title": "Success" + } + ] + }, + "MyTxHistoryIrisLimit50": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "coin": "IRIS", + "current_block": 18120346, + "limit": 50, + "paging_options": { + "PageNumber": 1 + }, + "skipped": 0, + "sync_status": { + "state": "NotStarted" + }, + "target": { + "type": "iguana" + }, + "total": 3, + "total_pages": 1, + "transactions": [ + { + "block_height": 18120218, + "coin": "IRIS", + "confirmations": 129, + "fee_details": { + "amount": "0.044559", + "coin": "IRIS", + "gas_limit": 100000, + "type": "Tendermint" + }, + "from": [ + "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k" + ], + "internal_id": "4644373032304131304637363034374441354438413433420000000000000000", + "memo": "while you are out, buy milk", + "my_balance_change": "-0.044559", + "received_by_me": "10", + "spent_by_me": "10.044559", + "timestamp": 1673016440, + "to": [ + "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k" + ], + "total_amount": "10.044559", + "transaction_type": "StandardTransfer", + "tx_hash": "B34A8D5AD74067F01A0207DF1851A14673C859D8A6F4FB0CBE292D2104C143CA", + "tx_hex": "0a2a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b122a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b1a110a05756972697312083130303030303030" + } + ] + } + }, + "title": "Success" + } + ] + }, + "MyTxHistorySia": { + "error": [], + "success": [ + { + "json": { + "id": 5, + "mmrpc": "2.0", + "result": { + "tx": { + "coin": "SIA", + "tx_hash": "h:abcdef...1234" + } + } + }, + "title": "Success" + } + ] + }, + "MyTxHistorySiaUnsupported": { + "error": [ + { + "json": { + "error": "SC", + "error_data": "SC", + "error_path": "my_tx_history_v2", + "error_trace": "my_tx_history_v2:385]", + "error_type": "NotSupportedFor", + "id": null, + "mmrpc": "2.0" + }, + "title": "SIA unsupported" + } + ], + "success": [] + }, + "SendRawTransaction": { + "error": [], + "success": [ + { + "json": { + "id": 6, + "mmrpc": "2.0", + "result": { + "tx_hash": "h:deadbeef...cafe" + } + }, + "title": "Success" + } + ] + }, + "ValidateAddress": { + "error": [], + "success": [ + { + "json": { + "id": 8, + "mmrpc": "2.0", + "result": { + "is_valid": true + } + }, + "title": "Success" + } + ] + }, + "WithdrawBroadcastTrue": { + "error": [], + "success": [ + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "IRIS", + "fee_details": { + "amount": "0.038553", + "coin": "IRIS", + "gas_limit": 100000, + "type": "Tendermint" + }, + "from": [ + "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k" + ], + "internal_id": "e00982a2a8442d7140916a34e29e287a0b1cbb4b38940372d1966ba7acde5bd6", + "memo": "It was a bright cold day in April, and the clocks were striking thirteen.", + "my_balance_change": "-0.038553", + "received_by_me": "13", + "spent_by_me": "13.038553", + "timestamp": 0, + "to": [ + "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k" + ], + "total_amount": "13.038553", + "transaction_type": "StandardTransfer", + "tx_hash": "E00982A2A8442D7140916A34E29E287A0B1CBB4B38940372D1966BA7ACDE5BD6", + "tx_hex": "0ade010a8b010a1c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e64126b0a2a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b122a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b1a110a05756972697312083133303030303030124949742077617320612062726967687420636f6c642064617920696e20417072696c2c20616e642074686520636c6f636b73207765726520737472696b696e6720746869727465656e2e188f85b50812680a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a2103d8064eece4fa5c0f8dc0267f68cee9bdd527f9e88f3594a323428718c391ecc212040a020801181d12140a0e0a0575697269731205333835353310a08d061a40a9ac8c4112d7d7252062e289d222a438258a7c49c6657fdcbf831d62fc5eb2d05af46d6b86881335b3bc7ca98b2bfc3ef02ec5adf6768de9a778b282f9cc868e" + } + }, + "title": "Success" + } + ] + }, + "WithdrawDocFixedFee": { + "error": [], + "success": [ + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.1", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "internal_id": "", + "my_balance_change": "-0.1", + "received_by_me": "60.00253836", + "spent_by_me": "60.10253836", + "timestamp": 1566472936, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "60.10253836", + "tx_hash": "1ab3bc9308695960bc728fa427ac00d1812c4ae89aaa714c7618cb96d111be58", + "tx_hex": "0400008085202f8901ef25b1b7417fe7693097918ff90e90bba1351fff1f3a24cb51a9b45c5636e57e010000006b483045022100b05c870fcd149513d07b156e150a22e3e47fab4bb4776b5c2c1b9fc034a80b8f022038b1bf5b6dad923e4fb1c96e2c7345765ff09984de12bbb40b999b88b628c0f9012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac8cbaae5f010000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ace87a5e5d000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.0245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762937399, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "eeab6a58d326aeca24b843e45f3ea70ba82aba92df73f404abcb1f500aedeb36", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a47304402207bf0b53482377992673504020492dafccf04c5d58b4a1626f5c16669fa6671e902207d852c17bcef01fd79dfd6d8901c9f085a4bc753893b3229b1cf25eb8add1d1f01210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac30ef4f27000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac374a1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.0245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762938622, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "122a5a117da13038cf5732c19832a4326f9fe7bdf1ecd46a83776d496d925417", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a473044022003ca8d863227a28ad03fd77d63894c29654df374acd493457cc5cbf24b5012a102201b3d7c7667045ca06553c4ddaeda052a26ecd9394aec8cf49aa59b73fca9746701210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac30ef4f27000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88acfe4e1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.0245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762939607, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "e46148071ea12a65afc25bb8051c209ecb9453c9da480ee931ccff02b02a9179", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a4730440220196df6fce78aafb7b25ed1b8cd6217dd4a23b42b7a9ea4bda77e1fe80bafb1fa0220137aaec84e0b1c8ebf01033d76aa888c5ee43c90cd21e3d41d7dde36de67ffc801210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac30ef4f27000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88acd7521469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.0245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762940605, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "78a96b5b7f17e237b1218c5f210a26bf8e09ab1f83c86428bfd6c093cceaceff", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a473044022021d844de4487587dc97ea09de1a59a57ebefb5902a4bebbcd920b9c44f2778ea0220092dd8e7e17654536dd4d26c7e6322b929fe6dfc33081c8e405c8165dfa4e4f301210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac30ef4f27000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88acbd561469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.0245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762942438, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "ec0fdc13fab843d3e2d80270fa01e7dca728cc59a968e02e6105a83c559309e2", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a473044022039fe06880fd3578a09dec2f28eece38385cb3b9d05a3b10da3145483f4b9427402205e144983f7bc2969bcac3b4bc057d4ec9e20e1e92dbedb637d7f543cb7fb49d401210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac30ef4f27000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ace65d1469000000000000000000000000000000" + } + }, + "title": "Success" + } + ] + }, + "WithdrawDocPerKbyte": { + "error": [], + "success": [ + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.38378905", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "internal_id": "", + "my_balance_change": "-0.38378905", + "received_by_me": "59.61874931", + "spent_by_me": "60.00253836", + "timestamp": 1566473421, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "60.00253836", + "tx_hash": "fd115190feec8c0c14df2696969295c59c674886344e5072d64000379101b78c", + "tx_hex": "0400008085202f890258be11d196cb18764c71aa9ae84a2c81d100ac27a48f72bc6059690893bcb31a000000006b483045022100ef11280e981be280ca5d24c947842ca6a8689d992b73e3a7eb9ff21070b0442b02203e458a2bbb1f2bf8448fc47c51485015904a5271bb17e14be5afa6625d67b1e8012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff58be11d196cb18764c71aa9ae84a2c81d100ac27a48f72bc6059690893bcb31a010000006b483045022100daaa10b09e7abf9d4f596fc5ac1f2542b8ecfab9bb9f2b02201644944ddc0280022067aa1b91ec821aa48f1d06d34cd26fb69a9f27d59d5eecdd451006940d9e83db012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788acf31c655d010000001976a91405aab5342166f8594baf17a7d9bef5d56744332788accd7c5e5d000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.245", + "received_by_me": "6.375", + "spent_by_me": "7.62", + "timestamp": 1762937401, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "0065ff7dde84a6720a8f6a034b8721aae62b21cbfc7c79a2c572b8e567bdb0fa", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a47304402203a063e625c9fe62bde238a63720e57dc894a43db2a1fd0fe9d295b1c1d24bd1f022039c1ee4fa214f6264e9fc704a6431bc9f6eac216224067fabddde8c3d10c39bf01210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac607aff25000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac394a1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.245", + "received_by_me": "6.375", + "spent_by_me": "7.62", + "timestamp": 1762938624, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "54b8dc10d271ede4ba893fc00b2091d1b9db8b42deb6ef9df85ad887fa588677", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a473044022065d8f93037bd2a10ee2c6c61d21e9769a016c62d34188665956ae3d06b3ffb8602206aa5b4e07f4ecffd987908c550b528ce9c211ed3ca58dc656f0b1bf4b5aa2d6f01210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac607aff25000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac004f1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.245", + "received_by_me": "6.375", + "spent_by_me": "7.62", + "timestamp": 1762939609, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "12a5af5af79cfea5d0919fe44a6c21cfa0489d0fa4ed712dad7b98faf04a9b4f", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a4730440220621493d1055e31fac396230d5d42209ee57fed7242c094986da4d4fa9541e42d02207a373cee80204430bd6a52a35fd496231410c53f510456400d19010c06b0460501210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac607aff25000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88acd9521469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.245", + "received_by_me": "6.375", + "spent_by_me": "7.62", + "timestamp": 1762940606, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "bafeba8aa2bbf2bddc88cbed5a67a8a23e3fb0610f270e889a31bf7218a9a956", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a4730440220122cac26e6c0296c768d47d4dca4102f89370e1cebb13c205112619c147d23160220045101c130f2261a31ff42b45a03a552d556e61ef302b7eb693bb6043047077901210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac607aff25000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88acbe561469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "DOC", + "fee_details": { + "amount": "0.245", + "coin": "DOC", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.245", + "received_by_me": "6.375", + "spent_by_me": "7.62", + "timestamp": 1762942439, + "to": [ + "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "a0ae0747106604245a12d211e34c9e70c6d5e975cdc8b40595ea800de0acbf4c", + "tx_hex": "0400008085202f8901b55ee690006ab4ace862ad2fe52f75ce0a5334bee9c38e82082b6e569f72248f000000006a47304402207fd26f79bfcb7dd0ae6721e802c701a9482c4077aeb68c4503e0de82234bd03302206d70593975786e9c2492231598875a9ba8b6f6136523caf4b6392c6e66bfbdc601210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac607aff25000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ace75d1469000000000000000000000000000000" + } + }, + "title": "Success" + } + ] + }, + "WithdrawEth": { + "error": [], + "success": [ + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "ETH", + "fee_details": { + "coin": "ETH", + "gas": 21000, + "gas_price": "0.000000001", + "total_fee": "0.000021", + "type": "Eth" + }, + "from": [ + "0xbab36286672fbdc7b250804bf6d14be0df69fa29" + ], + "my_balance_change": "-10.000021", + "received_by_me": "0", + "spent_by_me": "10.000021", + "to": [ + "0xbab36286672fbdc7b250804bf6d14be0df69fa28" + ], + "total_amount": "10.000021", + "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", + "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" + } + }, + "title": "Success" + } + ] + }, + "WithdrawEthGas": { + "error": [], + "success": [ + { + "json": { + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "ETH", + "fee_details": { + "coin": "ETH", + "gas": 55000, + "gas_price": "0.0000000035", + "total_fee": "0.0001925", + "type": "Eth" + }, + "from": [ + "0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29" + ], + "internal_id": "", + "my_balance_change": "-0.0001925", + "received_by_me": "10", + "spent_by_me": "10.0001925", + "timestamp": 1566474670, + "to": [ + "0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29" + ], + "total_amount": "10", + "tx_hash": "a26c4dcacf63c04e385dd973ca7e7ca1465a3b904a0893bcadb7e37681d38c95", + "tx_hex": "f86d820b2884d09dc30082d6d894bab36286672fbdc7b250804bf6d14be0df69fa29888ac7230489e80000801ca0ef0167b0e53ed50d87b6fd630925f2bce6ee72e9b5fdb51c6499a7caaecaed96a062e5cb954e503ff83f2d6ce082649fdcdf8a77c8d37c7d26d46d3f736b228d10" + } + }, + "title": "Success" + } + ] + }, + "WithdrawEthMax": { + "error": [], + "success": [ + { + "json": { + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "ETH", + "fee_details": { + "coin": "ETH", + "gas": 21000, + "gas_price": "0.000000001", + "total_fee": "0.000021", + "type": "Eth" + }, + "from": [ + "0xbab36286672fbdc7b250804bf6d14be0df69fa29" + ], + "my_balance_change": "-10.000021", + "received_by_me": "0", + "spent_by_me": "10.000021", + "to": [ + "0xbab36286672fbdc7b250804bf6d14be0df69fa28" + ], + "total_amount": "10.000021", + "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", + "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" + } + }, + "title": "Success" + } + ] + }, + "WithdrawIbcAtom": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "ATOM", + "fee_details": { + "amount": "0.017359", + "coin": "ATOM", + "gas_limit": 1500000, + "type": "Tendermint" + }, + "from": [ + "cosmos16drqvl3u8sukfsu4lm3qsk28jr3fahjaswsac8" + ], + "internal_id": "06174e488b7bbc35180e841f2d170327bb7de0a291ca69050d81f82a7cf103cb", + "memo": "In the blackest of your moments, wait with no fear.", + "my_balance_change": "-0.1173590000000000", + "received_by_me": "0", + "spent_by_me": "0.1173590000000000", + "timestamp": 0, + "to": [ + "osmo16drqvl3u8sukfsu4lm3qsk28jr3fahjac4rdw4" + ], + "total_amount": "0.1173590000000000", + "transaction_type": "TendermintIBCTransfer", + "tx_hash": "06174E488B7BBC35180E841F2D170327BB7DE0A291CA69050D81F82A7CF103CB", + "tx_hex": "0af9010abc010a292f6962632e6170706c69636174696f6e732e7472616e736665722e76312e4d73675472616e73666572128e010a087472616e73666572120b6368616e6e656c2d3134311a0f0a057561746f6d1206313030303030222d636f736d6f733136647271766c33753873756b667375346c6d3371736b32386a72336661686a617377736163382a2b6f736d6f3136647271766c33753873756b667375346c6d3371736b32386a72336661686a6163347264773438a6c5b9a089f29efa171233496e2074686520626c61636b657374206f6620796f7572206d6f6d656e74732c20776169742077697468206e6f20666561722e188df8c70a12680a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a2103d8064eece4fa5c0f8dc0267f68cee9bdd527f9e88f3594a323428718c391ecc212040a020801180b12140a0e0a057561746f6d1205313733353910e0c65b1a40042c4fa45d77405ee94e737a000b146f5019137d5a2d3275849c9ad66dd8ef1d0f087fb584f34b1ebcf7989e41bc0675e96c83f0eec4ffe355e078b6615d7a72" + } + }, + "title": "Success" + } + ] + }, + "WithdrawIrisMemoCosmosGas": { + "error": [], + "success": [ + { + "json": { + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "IRIS", + "fee_details": { + "amount": "0.038553", + "coin": "IRIS", + "gas_limit": 100000, + "type": "Tendermint" + }, + "from": [ + "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k" + ], + "internal_id": "e00982a2a8442d7140916a34e29e287a0b1cbb4b38940372d1966ba7acde5bd6", + "memo": "It was a bright cold day in April, and the clocks were striking thirteen.", + "my_balance_change": "-0.038553", + "received_by_me": "13", + "spent_by_me": "13.038553", + "timestamp": 0, + "to": [ + "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k" + ], + "total_amount": "13.038553", + "transaction_type": "StandardTransfer", + "tx_hash": "E00982A2A8442D7140916A34E29E287A0B1CBB4B38940372D1966BA7ACDE5BD6", + "tx_hex": "0ade010a8b010a1c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e64126b0a2a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b122a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b1a110a05756972697312083133303030303030124949742077617320612062726967687420636f6c642064617920696e20417072696c2c20616e642074686520636c6f636b73207765726520737472696b696e6720746869727465656e2e188f85b50812680a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a2103d8064eece4fa5c0f8dc0267f68cee9bdd527f9e88f3594a323428718c391ecc212040a020801181d12140a0e0a0575697269731205333835353310a08d061a40a9ac8c4112d7d7252062e289d222a438258a7c49c6657fdcbf831d62fc5eb2d05af46d6b86881335b3bc7ca98b2bfc3ef02ec5adf6768de9a778b282f9cc868e" + } + }, + "title": "Success" + } + ] + }, + "WithdrawKmd": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "KMD", + "fee_details": { + "amount": "0.00001", + "coin": "KMD", + "type": "Utxo" + }, + "from": [ + "RHound8PpyhVLfi56dC7MK3ZvvkAmB3bvQ" + ], + "internal_id": "", + "kmd_rewards": { + "amount": "0", + "claimed_by_my": true + }, + "memo": null, + "my_balance_change": "-10", + "received_by_me": "0", + "spent_by_me": "10", + "timestamp": 1743589636, + "to": [ + "RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh" + ], + "total_amount": "10", + "transaction_type": "StandardTransfer", + "tx_hash": "aa456a6288292c4980637083871a6a4a1fb0a2242f6a30ae974069311691f37c", + "tx_hex": "0400008085202f890152db2e550ca2d69eed487c95b6089b0f12e7a8937a89b8754c38a8c361560fca000000006a47304402200220239769f48c8bc96fbbcb66bcc0483f6234cb48ab823e13f0b791cdd501b902204f8b2dd875609e35f1677e39e403a18e9d2d98cd9916f51a62ac1edfc350cd47012102b3c168ed4acd96594288cee3114c77de51b6afe1ab6a866887a13a96ee80f33cffffffff0290a00b00000000001976a9145d904d4531f4c74f760a14ef057c866a06705dda88ac37040700000000001976a9145d904d4531f4c74f760a14ef057c866a06705dda88ac0609ed67000000000000000000000000000000" + } + }, + "title": "Success" + } + ] + }, + "WithdrawMartyAccountId": { + "error": [], + "success": [ + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.01000245", + "received_by_me": "7.60999755", + "spent_by_me": "7.62", + "timestamp": 1762937412, + "to": [ + "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "9d1b4080c024d88ebe3c2ee8a1f4da1e58a08cfc0513f4d86a645214e3f1b569", + "tx_hex": "0400008085202f8901f19abcd5fca15276ce0a4469ab6fc14a6376f99a40fffadbf2dbf4d065618931000000006a47304402201017a6f2eace3396c19b383e4c6eabaa13bf096d16e0a65943705cf0da0e97dc02205bd6d33da641b8a995738e46f73503363aac3db7907148245c534c0ed7fe522e01210339e82bb13d3bb65a01b8ddb57fa56382e2020e67f825cb9113fcb97ea07fb9a6ffffffff0240420f00000000001976a9140b5346ab6e60cd7f69823fb3b3b289b5e1d70e0b88ac4bef5b2d000000001976a914382a99167bf08019a1bf480eda14caba638b3c0688ac444a1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.01000245", + "received_by_me": "7.60999755", + "spent_by_me": "7.62", + "timestamp": 1762938638, + "to": [ + "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "6053397bfdfe7ed75145cabc644540bddd93de8076230d29be2b0b9a352b003c", + "tx_hex": "0400008085202f8901f19abcd5fca15276ce0a4469ab6fc14a6376f99a40fffadbf2dbf4d065618931000000006a473044022010c65ff2482976103e23f57a4c0de6c9b1db06e938de71fb8eb364cf2e763ba602204f289dbd5e2835e743cc53e04d7cde0e649bbf3362d2eeb5764d5c0653dcbd2f01210339e82bb13d3bb65a01b8ddb57fa56382e2020e67f825cb9113fcb97ea07fb9a6ffffffff0240420f00000000001976a9140b5346ab6e60cd7f69823fb3b3b289b5e1d70e0b88ac4bef5b2d000000001976a914382a99167bf08019a1bf480eda14caba638b3c0688ac0e4f1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.01000245", + "received_by_me": "7.60999755", + "spent_by_me": "7.62", + "timestamp": 1762939624, + "to": [ + "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "03a799e72a4b5b184659b17ed8de368953248a52485a57a962d9264e2767078c", + "tx_hex": "0400008085202f8901f19abcd5fca15276ce0a4469ab6fc14a6376f99a40fffadbf2dbf4d065618931000000006a473044022042de0fafa6029b40fc14a7bc45f7afb41eb0aa2bdede4d40eb782ebc0a64465c022060877745a4ea5da8693648d7a18d8110020907e68fed75b427dd5bdcfd1bcdcf01210339e82bb13d3bb65a01b8ddb57fa56382e2020e67f825cb9113fcb97ea07fb9a6ffffffff0240420f00000000001976a9140b5346ab6e60cd7f69823fb3b3b289b5e1d70e0b88ac4bef5b2d000000001976a914382a99167bf08019a1bf480eda14caba638b3c0688ace8521469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.01000245", + "received_by_me": "7.60999755", + "spent_by_me": "7.62", + "timestamp": 1762940616, + "to": [ + "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "b53811756a5044dbdcc6b489737d2238f1c4153351ecd0b1b8caf5ccbe707adc", + "tx_hex": "0400008085202f8901f19abcd5fca15276ce0a4469ab6fc14a6376f99a40fffadbf2dbf4d065618931000000006a47304402200e9d74341b2fca90734b5dddb160d60afb3e5283473f789a050aadd187b1eafe02201cc722f154c20e7caaa63e6ddcb6b298b2c6f4e73b5d2924c008e4f36e62768201210339e82bb13d3bb65a01b8ddb57fa56382e2020e67f825cb9113fcb97ea07fb9a6ffffffff0240420f00000000001976a9140b5346ab6e60cd7f69823fb3b3b289b5e1d70e0b88ac4bef5b2d000000001976a914382a99167bf08019a1bf480eda14caba638b3c0688acc8561469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.01000245", + "received_by_me": "7.60999755", + "spent_by_me": "7.62", + "timestamp": 1762942449, + "to": [ + "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "c660ba50aad42c7d90110d5ac817de0fcc5f0183cadbb0a0a7305f4b65bf1530", + "tx_hex": "0400008085202f8901f19abcd5fca15276ce0a4469ab6fc14a6376f99a40fffadbf2dbf4d065618931000000006a47304402201a30768d12e43aacffc31d70928ff63fd9242c8e5d21eeae683de7bb1c97b4b102202907a6db9324f904384d9cdb87ddcb2c3e02253c386b195ef31f5bdf988af74701210339e82bb13d3bb65a01b8ddb57fa56382e2020e67f825cb9113fcb97ea07fb9a6ffffffff0240420f00000000001976a9140b5346ab6e60cd7f69823fb3b3b289b5e1d70e0b88ac4bef5b2d000000001976a914382a99167bf08019a1bf480eda14caba638b3c0688acf15d1469000000000000000000000000000000" + } + }, + "title": "Success" + } + ] + }, + "WithdrawMartyDerivationPath": { + "error": [], + "success": [ + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.02500245", + "received_by_me": "6.59499755", + "spent_by_me": "7.62", + "timestamp": 1762937413, + "to": [ + "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "87f331dccea08895da4aaf3ad2fec431ddeb61233e0394b7bbfbd268da31ca2b", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a4730440220251dbf3b3155f48cddccadf06391583efe37b3271c952f996c0aebbea2f93eed022032b2cebed564674f91e7a664c437124ec3407168519be2553232a4adab7cf2820121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff02a0061c06000000001976a9140b5346ab6e60cd7f69823fb3b3b289b5e1d70e0b88aceb2a4f27000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac454a1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.02500245", + "received_by_me": "6.59499755", + "spent_by_me": "7.62", + "timestamp": 1762938639, + "to": [ + "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "08a09727019bc0cd429b835b120966aee3a1dc016f438964a8571baad8d92da8", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a473044022046f99f8b8cc1bbd10e740fa668642c8792ca409476863aa274d324e6e045c115022019743fe1a5ef66a5bb9958fe35323dc8c88da7e8649fb900a78f171073df86e90121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff02a0061c06000000001976a9140b5346ab6e60cd7f69823fb3b3b289b5e1d70e0b88aceb2a4f27000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac0f4f1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.02500245", + "received_by_me": "6.59499755", + "spent_by_me": "7.62", + "timestamp": 1762939625, + "to": [ + "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "97790cbc78b65a676142f7d7d03fbb44d94d1a9080b98429782d00ea850020c6", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a473044022025e1fc267dba9d965dea47903f53e7ebf6c7c59e09f7d87c44209d80de16f4fe02200f5e586bf9d5c55784c7601d1233ab6ddc94a94bd233def0fde4666e633b522d0121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff02a0061c06000000001976a9140b5346ab6e60cd7f69823fb3b3b289b5e1d70e0b88aceb2a4f27000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ace9521469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.02500245", + "received_by_me": "6.59499755", + "spent_by_me": "7.62", + "timestamp": 1762940617, + "to": [ + "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "8e774c1aa7212791d4f9d67c913464e185a7a7cb29e4d346f54386d4ef563d66", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a47304402207f0ab5b99fd1a5d6791677e1ecc882cdbf574d9fa9faf98dd5282f994e0d7df902204f3559a83be9560f5ea78f333199630cc692635c77136d1439a9b9d61d2dd6670121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff02a0061c06000000001976a9140b5346ab6e60cd7f69823fb3b3b289b5e1d70e0b88aceb2a4f27000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88acc9561469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.02500245", + "received_by_me": "6.59499755", + "spent_by_me": "7.62", + "timestamp": 1762942450, + "to": [ + "RAK5GkKvJKYehFvMavi5QKucriaCu9enHi" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "46d2afb5020caa4d5a96ae84536ee3f9425216c3fbbbebb15f9a0922eb05bd14", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a47304402200fea0e38a94730f9b776f094d0675b50437d0dc95abe5a8d577cd38dfff067830220420fa4b3645d29cb0357b83154becfb9835b082f3db99a6667706bac2ab884c00121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff02a0061c06000000001976a9140b5346ab6e60cd7f69823fb3b3b289b5e1d70e0b88aceb2a4f27000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88acf25d1469000000000000000000000000000000" + } + }, + "title": "Success" + } + ] + }, + "WithdrawMartyFixedFee": { + "error": [], + "success": [ + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.0245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762937414, + "to": [ + "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "c774290fc8e7bc7acaabc0b09aa88aaef1e6b3f5bf6119b8d658d543f86a324e", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a473044022022a4f644446a739275eec986084b90b3f773856deb94d0e5e6beb1a309abad5a022007011040d60aa85aad233f339a4f5252b1cf3bd4d49a7fbcde01cbaf167088f80121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff0200e1f505000000001976a914382a99167bf08019a1bf480eda14caba638b3c0688ac30ef4f27000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac464a1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.0245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762938640, + "to": [ + "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "630902d45fc0994ee1d3e5d73a13a0b2cfc4751c9f0537cc95dd3347001c8b3e", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a47304402202bcefb34bf0cbc0e36af42caa79b8d465727ccbcaf94b25317843c991ae81cb4022023de84329d147bd622bbf9948b9683e7809de422e98f63fc717972b15847cdc70121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff0200e1f505000000001976a914382a99167bf08019a1bf480eda14caba638b3c0688ac30ef4f27000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac104f1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.0245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762939626, + "to": [ + "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "71cac19a5e7cb5edb534d57dabe54c3c21c23d500c2bbc70867b12ad60cb6464", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a473044022022d52effd8d81b14ea587b3575354e52a8da3d9eb7936a1b1908da313cf9c8b002202b77a00ab857b4888a0996275d49cf310b1a1b506c0592bc4b0fb76587df25d60121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff0200e1f505000000001976a914382a99167bf08019a1bf480eda14caba638b3c0688ac30ef4f27000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88acea521469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.0245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762940618, + "to": [ + "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "9f222ec6d4d6ca80994ec13d3925de62dd97fd05cca4637d08ea416fe67e8df4", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a473044022012721077efc0a38965e474b61b58a1bb7608e9f05cf94c36e9452620ad18da96022059646b61d1f4ccec22cc79e706abce8df76522f0832577cbec9daecd3f4d92390121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff0200e1f505000000001976a914382a99167bf08019a1bf480eda14caba638b3c0688ac30ef4f27000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88acca561469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.0245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-1.0245", + "received_by_me": "6.5955", + "spent_by_me": "7.62", + "timestamp": 1762942451, + "to": [ + "REQAx25g5D1xj3GzQ3PRBMcHP4TegZwsCa" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "3b1f318e338fd7b0d47a3fa4304d4f710a1be891945e4bdc2a9def836c4b78f9", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a47304402207f66658f9944ca9c9a2072bda4129ae3d92183cec644295c7069e67040b369d502207d5964e7c13fd3b1b6c5da0e4997202591cfb796d618b4d3202ab28cbadd5ea80121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff0200e1f505000000001976a914382a99167bf08019a1bf480eda14caba638b3c0688ac30ef4f27000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88acf35d1469000000000000000000000000000000" + } + }, + "title": "Success" + } + ] + }, + "WithdrawMartyNonHD": { + "error": [], + "success": [ + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.00000245", + "received_by_me": "7.61999755", + "spent_by_me": "7.62", + "timestamp": 1762937415, + "to": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "54dedf9593cd5629338c1ccda68b0cd75d1fa60da9eba03bb0f61d51a03c0397", + "tx_hex": "0400008085202f8901c9167df1d7940449b58ce7b0705724190ede7189ec74bee1eaf3e3b9224e7315000000006a473044022009e62d5c60fdc002cd445c402ddadfd3eafc6265c598c6b03dc48f7d163ba79702206eb42912551ac603a2ad60a10177f4cbdd6733c95cf54131d4fe8ef12c955e8501210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0280969800000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac0b9bd22c000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac474a1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.00000245", + "received_by_me": "7.61999755", + "spent_by_me": "7.62", + "timestamp": 1762938641, + "to": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "02caa4a8fb12bb0ece106dab83f546384a344555d7fabeb316e3e7f9d5714527", + "tx_hex": "0400008085202f8901c9167df1d7940449b58ce7b0705724190ede7189ec74bee1eaf3e3b9224e7315000000006a47304402203efa2e1082f8f494642cfcb92061c337b8e88d8305706536e1c797ff592f3dcc02207b2e9638ce8097de3debcda01d3f06b21f6517a002f1cf6c172728e20b06a55901210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0280969800000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac0b9bd22c000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac114f1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.00000245", + "received_by_me": "7.61999755", + "spent_by_me": "7.62", + "timestamp": 1762939627, + "to": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "550d8feabade751c45f7af38ef8a77bf0c4aab62f571898eb8c570ad987fff87", + "tx_hex": "0400008085202f8901c9167df1d7940449b58ce7b0705724190ede7189ec74bee1eaf3e3b9224e7315000000006a473044022059d5bb4b7977c1d5dd75f59fb9b710501c701f9cb1f3feea39314ac4238fc2c00220572b249b530a97029badba9bd726def5f437df95bddf251c3f5e6ae22dd5aaef01210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0280969800000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac0b9bd22c000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88aceb521469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.00000245", + "received_by_me": "7.61999755", + "spent_by_me": "7.62", + "timestamp": 1762940619, + "to": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "1262de8b29b8f8a4d8f2292861931f936b1a5c39745746e843c67e625ead33c1", + "tx_hex": "0400008085202f8901c9167df1d7940449b58ce7b0705724190ede7189ec74bee1eaf3e3b9224e7315000000006a47304402201132c8ac212826c059e0ed1a678a2b02d6894fb89e7a282cd3e59e3a674d8f00022055cc704e1174c0f39f447d07fc2fb6fa5784e70f96feb798a04a1442292b7cf001210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0280969800000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac0b9bd22c000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88accb561469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.00000245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.00000245", + "received_by_me": "7.61999755", + "spent_by_me": "7.62", + "timestamp": 1762942452, + "to": [ + "RDux85r5XE7xuUs5DCTt7jTY1cJZT7SKAW" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "39faa13867d63a5ccc5a7d77df417b7466cab36f81b1b9a05692951b2322fc2c", + "tx_hex": "0400008085202f8901c9167df1d7940449b58ce7b0705724190ede7189ec74bee1eaf3e3b9224e7315000000006a4730440220555e36dd280eb05502a5b909ed9d43dd5454ec255125549a44d663a537ee627e0220051a9bc6aa7e8aea9cadc2238002521aa43e26f7f94f52ebac033a2782db3d2e01210388533bd49d81742f1598b9048921646f08d06dcd31d38f7e37cca79f64b977c4ffffffff0280969800000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88ac0b9bd22c000000001976a91432d43e7ba0f08d320a22440e55b842407f481ebf88acf45d1469000000000000000000000000000000" + } + }, + "title": "Success" + } + ] + }, + "WithdrawMartyPerKbyte": { + "error": [], + "success": [ + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.245", + "received_by_me": "7.375", + "spent_by_me": "7.62", + "timestamp": 1762937416, + "to": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "2b63e9fbccd9fa1b169b1d45822dbe48d2e78afd1d509b84858ee1d8cbb1f8eb", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a47304402203d7c3fdff1a559467d4352547cbbd50cb2fed29ed6936e1da650b995d1f2a6d002206d4dcf6ee228df80d056a418ced9fa345a03e4de07c5244193e32b8c388cb7b70121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff0200e1f505000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac607aff25000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac484a1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.245", + "received_by_me": "7.375", + "spent_by_me": "7.62", + "timestamp": 1762938642, + "to": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "b9cc117626e79c16482798b78945190556c1f68f2f4740695e2ffbe5b159aeac", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a47304402207d0041a9f59f64a3a26e708a76f1a45f915f892aa74d81c343fea9d577896c48022057b176fd3b867137d0d4d496c3183d8ff772fcf03192392b3dbbdbd4c8467a260121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff0200e1f505000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac607aff25000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac124f1469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.245", + "received_by_me": "7.375", + "spent_by_me": "7.62", + "timestamp": 1762939628, + "to": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "ffbe4482f65d1aa2ad6b0898ee740a3f1342a916ebdef9d34406a17bf5164e08", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a4730440220706b47dc5060d93c37e045062ef8c8191b4c1d3574405b8e324755a263ddbe1a02205a2250e87d3b3122b7aed512e851990f52ab831c4d96351a977919cc8259891b0121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff0200e1f505000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac607aff25000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88acec521469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.245", + "received_by_me": "7.375", + "spent_by_me": "7.62", + "timestamp": 1762940620, + "to": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "325096257177aa36117836dca2bba06fedf23f077ab5defe9c5b5f1c0418f1ba", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a473044022026c278d561713593b2dfefe31bd42025223f22c4a787b642989b6fc58bcc37d002201cc256ed9dda5108e128ce157af5b96171350dade8f7ae56384b628699f266270121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff0200e1f505000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac607aff25000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88accc561469000000000000000000000000000000" + } + }, + "title": "Success" + }, + { + "json": { + "id": 0, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "MARTY", + "fee_details": { + "amount": "0.245", + "coin": "MARTY", + "type": "Utxo" + }, + "from": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.245", + "received_by_me": "7.375", + "spent_by_me": "7.62", + "timestamp": 1762942453, + "to": [ + "R9oNwVG9pCZZNu8cUbbKvFxuzFyUAYWZw5" + ], + "total_amount": "7.62", + "transaction_type": "StandardTransfer", + "tx_hash": "1a325d6458d84f749659e92a50f5c2040e2aa24d7f6bcba4c7df4493689dd798", + "tx_hex": "0400008085202f8901378a408f4b87a36ac52e82075be0487bef8ceeafc5f5d9fd67def028b1bcd529000000006a4730440220086c0e4366b984c0decbe79095caf93ca9ea6cbbb302f54283435fafea762f5702202b54f435f305b2623af0cf86286db171df5875a01933a4668a62afc5a92bd40a0121033a546ac195fa8a1f70cda975d035e811d3b903b2ef0253c47ee3a1fedad83c1cffffffff0200e1f505000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88ac607aff25000000001976a91405b58bafaf5acc706232861edf0478f5cb69e70c88acf55d1469000000000000000000000000000000" + } + }, + "title": "Success" + } + ] + }, + "WithdrawQrc20": { + "error": [], + "success": [ + { + "json": { + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "QRC20", + "fee_details": { + "coin": "tQTUM", + "gas_limit": 100000, + "gas_price": 40, + "miner_fee": "0.00000447", + "total_gas_fee": "0.04", + "type": "Qrc20" + }, + "from": [ + "qXxsj5RtciAby9T7m98AgAATL4zTi4UwDG" + ], + "my_balance_change": "-10", + "received_by_me": "0", + "spent_by_me": "10", + "timestamp": 1608725061, + "to": [ + "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs" + ], + "total_amount": "10", + "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", + "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" + } + }, + "title": "Success" + } + ] + }, + "WithdrawQrc20Gas": { + "error": [], + "success": [ + { + "json": { + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "QRC20", + "fee_details": { + "coin": "tQTUM", + "gas_limit": 250000, + "gas_price": 40, + "miner_fee": "0.00000447", + "total_gas_fee": "0.1", + "type": "Qrc20" + }, + "from": [ + "qXxsj5RtciAby9T7m98AgAATL4zTi4UwDG" + ], + "my_balance_change": "-10", + "received_by_me": "0", + "spent_by_me": "10", + "timestamp": 1608725061, + "to": [ + "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs" + ], + "total_amount": "10", + "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", + "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" + } + }, + "title": "Success" + } + ] + }, + "WithdrawSia": { + "error": [], + "success": [ + { + "json": { + "id": 5, + "mmrpc": "2.0", + "result": { + "tx": { + "coin": "SIA", + "tx_hash": "h:abcdef...1234" + } + } + }, + "title": "Success" + } + ] + }, + "WithdrawSiaProtocol": { + "error": [], + "success": [ + { + "json": { + "id": null, + "mmrpc": "2.0", + "result": { + "block_height": 0, + "coin": "SC", + "fee_details": { + "coin": "SC", + "policy": "Fixed", + "total_amount": "0.000010000000000000000000", + "type": "Sia" + }, + "from": [ + "2c4a02...04db" + ], + "internal_id": "", + "memo": null, + "my_balance_change": "-0.076210000000000000000000", + "received_by_me": "49.923790000000000000000000", + "spent_by_me": "50.000000000000000000000000", + "timestamp": 1750747840, + "to": [ + "c67d77...fce2" + ], + "total_amount": "50.000000000000000000000000", + "transaction_type": "SiaV2Transaction", + "tx_hash": "37dbf68cba4125714b7ca10e00e3166c434fa622b61837b43b74e4eefc179f0d", + "tx_json": { + "minerFee": "10000000000000000000", + "siacoinInputs": [], + "siacoinOutputs": [] + } + } + }, + "title": "Success" + } + ] + } +} \ No newline at end of file diff --git a/src/data/schemas/compact-table.schema.json b/src/data/schemas/compact-table.schema.json index d4dd15f9c..be0b8db14 100644 --- a/src/data/schemas/compact-table.schema.json +++ b/src/data/schemas/compact-table.schema.json @@ -36,6 +36,15 @@ "description": { "type": "string", "description": "Parameter description" + }, + "substructure": { + "type": "string", + "description": "Reference to another table structure (e.g., activation.ActivationRpcData)" + }, + "context": { + "type": "array", + "items": { "type": "string" }, + "description": "Optional context tags (e.g., Metamask, Keplr, WalletConnect)" } }, "required": ["parameter", "type", "required", "description"], diff --git a/src/data/sidebar.json b/src/data/sidebar.json index 2f34feb3e..468f93cea 100644 --- a/src/data/sidebar.json +++ b/src/data/sidebar.json @@ -402,6 +402,26 @@ "title": "Overview", "href": "/komodo-defi-framework/api/v20/coin_activation/task_managed/" }, + { + "title": "Task: Enable SIA", + "href": "/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/" + }, + { + "title": "task::enable_sia::init", + "href": "/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/init/" + }, + { + "title": "task::enable_sia::status", + "href": "/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/status/" + }, + { + "title": "task::enable_sia::user_action", + "href": "/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/user_action/" + }, + { + "title": "task::enable_sia::cancel", + "href": "/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/cancel/" + }, { "title": "Task: Enable BCH", "href": "/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_bch/" @@ -417,7 +437,7 @@ { "title": "Task: Enable Tendermint", "href": "/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/" - }, + }, { "title": "Task: Enable UTXO", "href": "/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/" @@ -620,7 +640,7 @@ { "title": "Validators", "href": "/komodo-defi-framework/api/v20/wallet/staking/validators/" - } + } ] }, { @@ -714,6 +734,14 @@ { "title": "get_private_keys", "href": "/komodo-defi-framework/api/v20/wallet/get_private_keys/" + }, + { + "title": "consolidate_utxos", + "href": "/komodo-defi-framework/api/v20/wallet/consolidate_utxos/" + }, + { + "title": "fetch_utxos", + "href": "/komodo-defi-framework/api/v20/wallet/fetch_utxos/" } ] }, @@ -1967,4 +1995,4 @@ } ] } -} \ No newline at end of file +} diff --git a/src/data/tables/common-structures/activation.json b/src/data/tables/common-structures/activation.json index 59b41f5bd..a0ce92d2d 100644 --- a/src/data/tables/common-structures/activation.json +++ b/src/data/tables/common-structures/activation.json @@ -11,7 +11,8 @@ "parameter": "rpc_data", "type": "object", "required": false, - "description": "`Electrum` or `Light` mode only. A standard [ActivationRpcData](/komodo-defi-framework/api/common_structures/activation/#activation-rpc-data) object." + "description": "`Electrum` or `Light` mode only. A standard [ActivationRpcData](/komodo-defi-framework/api/common_structures/activation/#activation-rpc-data) object.", + "substructure": "activation.ActivationRpcData" } ] }, @@ -34,7 +35,8 @@ "parameter": "mode", "type": "object", "required": false, - "description": "QTUM, UTXO & ZHTLC coins only. A standard [ActivationMode](/komodo-defi-framework/api/common_structures/activation/#activation-mode) object." + "description": "QTUM, UTXO & ZHTLC coins only. A standard [ActivationMode](/komodo-defi-framework/api/common_structures/activation/#activation-mode) object.", + "substructure": "activation.ActivationMode" }, { "parameter": "zcash_params_path", @@ -86,7 +88,8 @@ "parameter": "path_to_address", "type": "object", "required": false, - "description": "HD wallets only. A standard [AddressPath](/komodo-defi-framework/api/common_structures/wallet/#address-path) object." + "description": "HD wallets only. A standard [AddressPath](/komodo-defi-framework/api/common_structures/wallet/#address-path) object.", + "substructure": "wallet.AddressPath" }, { "parameter": "get_balances", @@ -134,13 +137,15 @@ "parameter": "balances", "type": "object", "required": false, - "description": "A standard [BalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object. Not included in responses where `get_balances` is `false`" + "description": "A standard [BalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object. Not included in responses where `get_balances` is `false`", + "substructure": "wallet.BalanceInfo" }, { "parameter": "derivation_method", "type": "object", "required": true, - "description": "A standard [DerivationMethod](/komodo-defi-framework/api/common_structures/wallet/#derivation-method) object" + "description": "A standard [DerivationMethod](/komodo-defi-framework/api/common_structures/wallet/#derivation-method) object", + "substructure": "wallet.DerivationMethod" }, { "parameter": "pubkey", @@ -156,6 +161,23 @@ } ] }, + "CoinNode": { + "data": [ + { + "parameter": "url", + "type": "string", + "required": true, + "description": "URL of an RPC node" + }, + { + "parameter": "komodo_auth", + "type": "boolean", + "required": false, + "default": "false", + "description": "Must be set to `true` to access RPC nodes run behind [komodo-defi-proxy](https://github.com/KomodoPlatform/komodo-defi-proxy)" + } + ] + }, "CoinProtocol": { "data": [ { @@ -168,7 +190,8 @@ "parameter": "protocol_data", "type": "object", "required": true, - "description": "A standard [CoinProtocolData](/komodo-defi-framework/api/common_structures/activation/#coin-protocol-data) object." + "description": "A standard [CoinProtocolData](/komodo-defi-framework/api/common_structures/activation/#coin-protocol-data) object.", + "substructure": "activation.CoinProtocolData" } ] }, @@ -190,24 +213,8 @@ "parameter": "confirmation_targets", "type": "object", "required": true, - "description": "A standard [ConfirmationTargets](/komodo-defi-framework/api/common_structures/lightning/#confirmation-targets) object." - } - ] - }, - "CoinNode": { - "data": [ - { - "parameter": "url", - "type": "string", - "required": true, - "description": "URL of an RPC node" - }, - { - "parameter": "komodo_auth", - "type": "boolean", - "required": false, - "default": "false", - "description": "Must be set to `true` to access RPC nodes run behind [komodo-defi-proxy](https://github.com/KomodoPlatform/komodo-defi-proxy)" + "description": "A standard [ConfirmationTargets](/komodo-defi-framework/api/common_structures/lightning/#confirmation-targets) object.", + "substructure": "lightning.ConfirmationTargets" } ] }, @@ -259,5 +266,27 @@ "description": "The maximum nouber of UTXOs to inlude as inputs for a merge transaction. Note that more input UTXOs means a larger transaction and greater fees, and that each blockchain has a limit to the maximum size of a transaction." } ] + }, + "SwapV2Contracts": { + "data": [ + { + "parameter": "maker_swap_v2_contract", + "type": "string", + "required": true, + "description": "Address of the Maker Swap V2 smart contract." + }, + { + "parameter": "taker_swap_v2_contract", + "type": "string", + "required": true, + "description": "Address of the Taker Swap V2 smart contract." + }, + { + "parameter": "nft_maker_swap_v2_contract", + "type": "string", + "required": true, + "description": "Address of the NFT Maker Swap V2 smart contract." + } + ] } } \ No newline at end of file diff --git a/src/data/tables/common-structures/common.json b/src/data/tables/common-structures/common.json index b001a24cf..78977aa41 100644 --- a/src/data/tables/common-structures/common.json +++ b/src/data/tables/common-structures/common.json @@ -1,4 +1,38 @@ { + "ErrorResponse": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "A human-readable error message." + }, + { + "parameter": "error_path", + "type": "string", + "required": true, + "description": "The path in the code where the error occurred." + }, + { + "parameter": "error_trace", + "type": "string", + "required": true, + "description": "A stack trace of the error." + }, + { + "parameter": "error_type", + "type": "string", + "required": true, + "description": "The type of the error." + }, + { + "parameter": "error_data", + "type": "object", + "required": true, + "description": "Additional data related to the error." + } + ] + }, "EventStreamConfig": { "data": [ { @@ -43,13 +77,32 @@ "parameter": "rational", "type": "object", "required": true, - "description": "A standard [RationalValue](/komodo-defi-framework/api/common_structures/#rational-value) object." + "description": "A standard [RationalValue](/komodo-defi-framework/api/common_structures/#rational-value) object.", + "substructure": "common.RationalValue" }, { "parameter": "fraction", "type": "object", "required": true, - "description": "A standard [FractionalValue](/komodo-defi-framework/api/common_structures/#fractional-value) object." + "description": "A standard [FractionalValue](/komodo-defi-framework/api/common_structures/#fractional-value) object.", + "substructure": "common.FractionalValue" + } + ] + }, + "Pagination": { + "data": [ + { + "parameter": "PageNumber", + "type": "integer", + "required": false, + "default": "1", + "description": "Offset for paginated results" + }, + { + "parameter": "FromId", + "type": "integer", + "required": false, + "description": "Ignores any results prior to this UUID" } ] }, @@ -76,23 +129,6 @@ } ] }, - "Pagination": { - "data": [ - { - "parameter": "PageNumber", - "type": "integer", - "required": false, - "default": "1", - "description": "Offset for paginated results" - }, - { - "parameter": "FromId", - "type": "integer", - "required": false, - "description": "Ignores any results prior to this UUID" - } - ] - }, "StreamingConfig": { "data": [ { @@ -141,7 +177,8 @@ "parameter": "additional_info", "type": "object", "required": true, - "description": "A standard [SyncStatusExtended](/komodo-defi-framework/api/common_structures/#sync-status-extended) object. Additional info that helps to track the progress; present for `InProgress` and `Error` states only." + "description": "A standard [SyncStatusExtended](/komodo-defi-framework/api/common_structures/#sync-status-extended) object. Additional info that helps to track the progress; present for `InProgress` and `Error` states only.", + "substructure": "common.SyncStatusExtended" } ] }, @@ -219,7 +256,8 @@ "parameter": "namespaces", "type": "object", "required": true, - "description": "Contains the same two [WcConnNs](/komodo-defi-framework/api/common_structures/#wc-conn-ns) objects for Cosmos/EIP155 which were input when initialising the connection via [wc_new_connection](/komodo-defi-framework/api/v20-dev/wc_new_connection/#wc-new-connection)." + "description": "Contains the same two [WcConnNs](/komodo-defi-framework/api/common_structures/#wc-conn-ns) objects for Cosmos/EIP155 which were input when initialising the connection via [wc_new_connection](/komodo-defi-framework/api/v20-dev/wc_new_connection/#wc-new-connection).", + "substructure": "common.WcConnNs" }, { "parameter": "expiry", @@ -228,39 +266,5 @@ "description": "A timestamp in [unix epoch format](https://www.epochconverter.com/) indicating when the connection will expire if not otherwise closed." } ] - }, - "ErrorResponse": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "A human-readable error message." - }, - { - "parameter": "error_path", - "type": "string", - "required": true, - "description": "The path in the code where the error occurred." - }, - { - "parameter": "error_trace", - "type": "string", - "required": true, - "description": "A stack trace of the error." - }, - { - "parameter": "error_type", - "type": "string", - "required": true, - "description": "The type of the error." - }, - { - "parameter": "error_data", - "type": "object", - "required": true, - "description": "Additional data related to the error." - } - ] } } \ No newline at end of file diff --git a/src/data/tables/common-structures/lightning.json b/src/data/tables/common-structures/lightning.json index 026ed2261..7aae8c5ea 100644 --- a/src/data/tables/common-structures/lightning.json +++ b/src/data/tables/common-structures/lightning.json @@ -1,4 +1,65 @@ { + "ChannelConfigLimits": { + "data": [ + { + "parameter": "force_announced_channel_preference", + "type": "boolean", + "required": false, + "default": "false", + "description": "Optional, defaults to `false`. The user may override this preference in the channel opening request method call." + }, + { + "parameter": "their_to_self_delay", + "type": "integer", + "required": false, + "default": "1008", + "description": "Optional, defaults to `1008`. The time that we require our counterparty to wait to claim their money, if they broadcast a revoked transaction. This can be increased to provide more punishment for broadcasting old states, but will result in higher fees (since emergency transactions will be larger)." + }, + { + "parameter": "our_to_self_delay", + "type": "integer", + "required": false, + "default": "1008", + "description": "Optional, defaults to `1008`. The time that our counterparty requires us to wait to claim our money, if we broadcast a revoked transaction." + }, + { + "parameter": "our_htlc_minimum_msat", + "type": "integer", + "required": false, + "default": "0", + "description": "Optional, defaults to `0`. The smallest value [HTLC](https://academy.binance.com/en/glossary/hashed-timelock-contract) we will accept to forward from the counterparty." + }, + { + "parameter": "max_accepted_htlcs", + "type": "integer", + "required": false, + "default": "483", + "description": "Optional, defaults to `483`. The maximum number of [HTLCs](https://academy.binance.com/en/glossary/hashed-timelock-contract) we will accept from the counterparty." + }, + { + "parameter": "min_max_htlc_value_in_flight_msat", + "type": "boolean", + "required": false, + "default": "0", + "description": "Optional, defaults to `0`. The remote node sets a limit on the maximum value of pending HTLCs to them at any given time to limit their funds exposure to [HTLCs](https://academy.binance.com/en/glossary/hashed-timelock-contract). This allows us to set a minimum such value." + }, + { + "parameter": "max_channel_reserve_sats", + "type": "boolean", + "required": false, + "default": "18446744073709551615", + "description": "Optional, defaults to `18446744073709551615`. The remote node will require us to keep a certain amount in direct payment to ourselves at all time, ensuring that we are able to be punished if we broadcast an old state. This allows us to limit the amount which we will have to keep to ourselves (and cannot use for [HTLCs](https://academy.binance.com/en/glossary/hashed-timelock-contract))." + }, + { + "parameter": "min_max_accepted_htlcs", + "type": "boolean", + "required": false, + "default": "0", + "description": "Optional, defaults to `0`. The remote node sets a limit on the maximum number of pending HTLCs to them at any given time. This allows us to set a minimum such value." + } + ], + "variant": "compact" + }, "ConfirmationTargets": { "data": [ { @@ -133,6 +194,29 @@ } ] }, + "LightningActivationParams_1": { + "data": [ + { + "parameter": "node_pubkey", + "type": "string", + "required": true, + "description": "Lightning node pubkey" + }, + { + "parameter": "backup_password", + "type": "string", + "required": true, + "description": "Backup password used to encrypt channel backups" + }, + { + "parameter": "listening_port", + "type": "integer", + "required": false, + "default": "9735", + "description": "Optional, defaults to `9735`. Listening port for the Lightning network" + } + ] + }, "LightningChannelAmount": { "data": [ { @@ -210,6 +294,41 @@ ], "variant": "compact" }, + "LightningChannelConfig_1": { + "data": [ + { + "parameter": "forwarding_fee_proportional_millionths", + "type": "integer", + "required": false, + "description": "Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in excess of proportional_fee_in_millionths_sats." + }, + { + "parameter": "forwarding_fee_base_msat", + "type": "integer", + "required": false, + "description": "Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in excess of proportional_fee_in_millionths_sats." + }, + { + "parameter": "cltv_expiry_delta", + "type": "integer", + "required": false, + "description": "Blocks until [CheckLockTimeVerify (CLTV)](https://academy.bit2me.com/en/que-es-cltv-bitcoin/) expiry." + }, + { + "parameter": "max_dust_htlc_exposure_msat", + "type": "integer", + "required": false, + "description": "Limit our total exposure to in-flight [HTLCs](https://academy.binance.com/en/glossary/hashed-timelock-contract) which are burned to fees as they are too small to claim on-chain." + }, + { + "parameter": "force_close_avoidance_max_fee_sats", + "type": "integer", + "required": false, + "description": "The additional fee we're willing to pay to avoid waiting for the counterparty's locktime to reclaim funds." + } + ], + "variant": "compact" + }, "LightningChannelOptions": { "data": [ { @@ -249,6 +368,22 @@ } ] }, + "LightningChannelValue": { + "data": [ + { + "parameter": "type", + "type": "string", + "required": true, + "description": "`Exact` for a specific amount or `Max` for whole balance." + }, + { + "parameter": "value", + "type": "object", + "required": false, + "description": "Optional. Required if type is `Exact`. The amount in BTC you want to open the channel with." + } + ] + }, "LightningClosedChannelsFilter": { "data": [ { @@ -325,6 +460,82 @@ } ] }, + "LightningClosedChannelsFilter_1": { + "data": [ + { + "parameter": "channel_id", + "type": "string", + "required": false, + "description": "Unique string identifying a channel by its ID." + }, + { + "parameter": "counterparty_node_id", + "type": "string", + "required": false, + "description": "A hexadecimal string identifying a counterparty node." + }, + { + "parameter": "funding_tx", + "type": "string", + "required": false, + "description": "A transaction ID which added funds." + }, + { + "parameter": "from_funding_value", + "type": "integer", + "required": false, + "description": "The minimum value of channel funding in satoshis." + }, + { + "parameter": "to_funding_value", + "type": "integer", + "required": false, + "description": "The maximum value of channel funding in satoshis." + }, + { + "parameter": "channel_type", + "type": "string", + "required": false, + "description": "`Inbound` or `Outbound`." + }, + { + "parameter": "closing_tx", + "type": "integer", + "required": false, + "description": "A transaction ID which closed the channel." + }, + { + "parameter": "closure_reason", + "type": "integer", + "required": false, + "description": "The reason a channel was closed." + }, + { + "parameter": "claiming_tx", + "type": "integer", + "required": false, + "description": "The ID of the transaction that returned the remaining outbound funds when the channel was closed to our on-chain address." + }, + { + "parameter": "from_claimed_balance", + "type": "integer", + "required": false, + "description": "The minimum balance of channel funds claimed in satoshis." + }, + { + "parameter": "to_claimed_balance", + "type": "integer", + "required": false, + "description": "The maximum balance of channel funds claimed in satoshis." + }, + { + "parameter": "channel_visibility", + "type": "integer", + "required": false, + "description": "`Public` or `Private`." + } + ] + }, "LightningOpenChannelsFilter": { "data": [ { @@ -460,7 +671,8 @@ "parameter": "payment_type", "type": "object", "required": false, - "description": "A standard [LightningPaymentType](/komodo-defi-framework/api/common_structures/lightning/#lightning-payment-type) object." + "description": "A standard [LightningPaymentType](/komodo-defi-framework/api/common_structures/lightning/#lightning-payment-type) object.", + "substructure": "lightning.LightningPaymentType" }, { "parameter": "description", @@ -528,216 +740,5 @@ "description": "Only used if `type` is `Outbound Payment`. A pubkey which will receive the payment." } ] - }, - "ChannelConfigLimits": { - "data": [ - { - "parameter": "force_announced_channel_preference", - "type": "boolean", - "required": false, - "default": "false", - "description": "Optional, defaults to `false`. The user may override this preference in the channel opening request method call." - }, - { - "parameter": "their_to_self_delay", - "type": "integer", - "required": false, - "default": "1008", - "description": "Optional, defaults to `1008`. The time that we require our counterparty to wait to claim their money, if they broadcast a revoked transaction. This can be increased to provide more punishment for broadcasting old states, but will result in higher fees (since emergency transactions will be larger)." - }, - { - "parameter": "our_to_self_delay", - "type": "integer", - "required": false, - "default": "1008", - "description": "Optional, defaults to `1008`. The time that our counterparty requires us to wait to claim our money, if we broadcast a revoked transaction." - }, - { - "parameter": "our_htlc_minimum_msat", - "type": "integer", - "required": false, - "default": "0", - "description": "Optional, defaults to `0`. The smallest value [HTLC](https://academy.binance.com/en/glossary/hashed-timelock-contract) we will accept to forward from the counterparty." - }, - { - "parameter": "max_accepted_htlcs", - "type": "integer", - "required": false, - "default": "483", - "description": "Optional, defaults to `483`. The maximum number of [HTLCs](https://academy.binance.com/en/glossary/hashed-timelock-contract) we will accept from the counterparty." - }, - { - "parameter": "min_max_htlc_value_in_flight_msat", - "type": "boolean", - "required": false, - "default": "0", - "description": "Optional, defaults to `0`. The remote node sets a limit on the maximum value of pending HTLCs to them at any given time to limit their funds exposure to [HTLCs](https://academy.binance.com/en/glossary/hashed-timelock-contract). This allows us to set a minimum such value." - }, - { - "parameter": "max_channel_reserve_sats", - "type": "boolean", - "required": false, - "default": "18446744073709551615", - "description": "Optional, defaults to `18446744073709551615`. The remote node will require us to keep a certain amount in direct payment to ourselves at all time, ensuring that we are able to be punished if we broadcast an old state. This allows us to limit the amount which we will have to keep to ourselves (and cannot use for [HTLCs](https://academy.binance.com/en/glossary/hashed-timelock-contract))." - }, - { - "parameter": "min_max_accepted_htlcs", - "type": "boolean", - "required": false, - "default": "0", - "description": "Optional, defaults to `0`. The remote node sets a limit on the maximum number of pending HTLCs to them at any given time. This allows us to set a minimum such value." - } - ], - "variant": "compact" - }, - "LightningActivationParams_1": { - "data": [ - { - "parameter": "node_pubkey", - "type": "string", - "required": true, - "description": "Lightning node pubkey" - }, - { - "parameter": "backup_password", - "type": "string", - "required": true, - "description": "Backup password used to encrypt channel backups" - }, - { - "parameter": "listening_port", - "type": "integer", - "required": false, - "default": "9735", - "description": "Optional, defaults to `9735`. Listening port for the Lightning network" - } - ] - }, - "LightningChannelValue": { - "data": [ - { - "parameter": "type", - "type": "string", - "required": true, - "description": "`Exact` for a specific amount or `Max` for whole balance." - }, - { - "parameter": "value", - "type": "object", - "required": false, - "description": "Optional. Required if type is `Exact`. The amount in BTC you want to open the channel with." - } - ] - }, - "LightningChannelConfig_1": { - "data": [ - { - "parameter": "forwarding_fee_proportional_millionths", - "type": "integer", - "required": false, - "description": "Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in excess of proportional_fee_in_millionths_sats." - }, - { - "parameter": "forwarding_fee_base_msat", - "type": "integer", - "required": false, - "description": "Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in excess of proportional_fee_in_millionths_sats." - }, - { - "parameter": "cltv_expiry_delta", - "type": "integer", - "required": false, - "description": "Blocks until [CheckLockTimeVerify (CLTV)](https://academy.bit2me.com/en/que-es-cltv-bitcoin/) expiry." - }, - { - "parameter": "max_dust_htlc_exposure_msat", - "type": "integer", - "required": false, - "description": "Limit our total exposure to in-flight [HTLCs](https://academy.binance.com/en/glossary/hashed-timelock-contract) which are burned to fees as they are too small to claim on-chain." - }, - { - "parameter": "force_close_avoidance_max_fee_sats", - "type": "integer", - "required": false, - "description": "The additional fee we're willing to pay to avoid waiting for the counterparty's locktime to reclaim funds." - } - ], - "variant": "compact" - }, - "LightningClosedChannelsFilter_1": { - "data": [ - { - "parameter": "channel_id", - "type": "string", - "required": false, - "description": "Unique string identifying a channel by its ID." - }, - { - "parameter": "counterparty_node_id", - "type": "string", - "required": false, - "description": "A hexadecimal string identifying a counterparty node." - }, - { - "parameter": "funding_tx", - "type": "string", - "required": false, - "description": "A transaction ID which added funds." - }, - { - "parameter": "from_funding_value", - "type": "integer", - "required": false, - "description": "The minimum value of channel funding in satoshis." - }, - { - "parameter": "to_funding_value", - "type": "integer", - "required": false, - "description": "The maximum value of channel funding in satoshis." - }, - { - "parameter": "channel_type", - "type": "string", - "required": false, - "description": "`Inbound` or `Outbound`." - }, - { - "parameter": "closing_tx", - "type": "integer", - "required": false, - "description": "A transaction ID which closed the channel." - }, - { - "parameter": "closure_reason", - "type": "integer", - "required": false, - "description": "The reason a channel was closed." - }, - { - "parameter": "claiming_tx", - "type": "integer", - "required": false, - "description": "The ID of the transaction that returned the remaining outbound funds when the channel was closed to our on-chain address." - }, - { - "parameter": "from_claimed_balance", - "type": "integer", - "required": false, - "description": "The minimum balance of channel funds claimed in satoshis." - }, - { - "parameter": "to_claimed_balance", - "type": "integer", - "required": false, - "description": "The maximum balance of channel funds claimed in satoshis." - }, - { - "parameter": "channel_visibility", - "type": "integer", - "required": false, - "description": "`Public` or `Private`." - } - ] } } \ No newline at end of file diff --git a/src/data/tables/common-structures/maker-events.json b/src/data/tables/common-structures/maker-events.json index a60dd83af..409e7a020 100644 --- a/src/data/tables/common-structures/maker-events.json +++ b/src/data/tables/common-structures/maker-events.json @@ -1,4 +1,112 @@ { + "MakerPaymentDataSendFailed": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "error description with stack trace" + } + ] + }, + "MakerPaymentRefunded": { + "data": [ + { + "parameter": "tx_hash", + "type": "string", + "required": true, + "description": "the hash of the transaction" + }, + { + "parameter": "tx_hex", + "type": "string", + "required": true, + "description": "transaction bytes in hexadecimal format" + } + ] + }, + "MakerPaymentRefundFailed": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "error description with stack trace" + } + ] + }, + "MakerPaymentSent": { + "data": [ + { + "parameter": "tx_hash", + "type": "string", + "required": true, + "description": "the hash of the transaction" + }, + { + "parameter": "tx_hex", + "type": "string", + "required": true, + "description": "transaction bytes in hexadecimal format" + } + ] + }, + "MakerPaymentTransactionFailed": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "error description with stack trace" + } + ] + }, + "MakerPaymentWaitConfirmFailed": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "error description with stack trace" + } + ] + }, + "MakerPaymentWaitRefundStarted": { + "data": [ + { + "parameter": "wait_until", + "type": "number (UTC timestamp)", + "required": true, + "description": "the timestamp at which a refund will occur" + } + ] + }, + "Negotiated": { + "data": [ + { + "parameter": "taker_payment_locktime", + "type": "number (UTC timestamp in seconds)", + "required": true, + "description": "the taker payment is locked until this timestamp" + }, + { + "parameter": "taker_pubkey", + "type": "string (hexadecimal)", + "required": true, + "description": "a persistent secp256k1 public key of taker node" + } + ] + }, + "NegotiateFailed": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "error description with stack trace" + } + ] + }, "Started": { "data": [ { @@ -122,32 +230,6 @@ } ] }, - "Negotiated": { - "data": [ - { - "parameter": "taker_payment_locktime", - "type": "number (UTC timestamp in seconds)", - "required": true, - "description": "the taker payment is locked until this timestamp" - }, - { - "parameter": "taker_pubkey", - "type": "string (hexadecimal)", - "required": true, - "description": "a persistent secp256k1 public key of taker node" - } - ] - }, - "NegotiateFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, "TakerFeeValidated": { "data": [ { @@ -174,52 +256,6 @@ } ] }, - "MakerPaymentTransactionFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, - "MakerPaymentSent": { - "data": [ - { - "parameter": "tx_hash", - "type": "string", - "required": true, - "description": "the hash of the transaction" - }, - { - "parameter": "tx_hex", - "type": "string", - "required": true, - "description": "transaction bytes in hexadecimal format" - } - ] - }, - "MakerPaymentDataSendFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, - "MakerPaymentWaitConfirmFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, "TakerPaymentReceived": { "data": [ { @@ -236,17 +272,7 @@ } ] }, - "TakerPaymentValidateFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, - "TakerPaymentWaitConfirmFailed": { + "TakerPaymentSpendConfirmFailed": { "data": [ { "parameter": "error", @@ -282,7 +308,7 @@ } ] }, - "TakerPaymentSpendConfirmFailed": { + "TakerPaymentValidateFailed": { "data": [ { "parameter": "error", @@ -292,17 +318,7 @@ } ] }, - "MakerPaymentWaitRefundStarted": { - "data": [ - { - "parameter": "wait_until", - "type": "number (UTC timestamp)", - "required": true, - "description": "the timestamp at which a refund will occur" - } - ] - }, - "MakerPaymentRefundFailed": { + "TakerPaymentWaitConfirmFailed": { "data": [ { "parameter": "error", @@ -311,21 +327,5 @@ "description": "error description with stack trace" } ] - }, - "MakerPaymentRefunded": { - "data": [ - { - "parameter": "tx_hash", - "type": "string", - "required": true, - "description": "the hash of the transaction" - }, - { - "parameter": "tx_hex", - "type": "string", - "required": true, - "description": "transaction bytes in hexadecimal format" - } - ] } } \ No newline at end of file diff --git a/src/data/tables/common-structures/nfts.json b/src/data/tables/common-structures/nfts.json index ca39ff9e0..c248fa19e 100644 --- a/src/data/tables/common-structures/nfts.json +++ b/src/data/tables/common-structures/nfts.json @@ -43,31 +43,25 @@ } ] }, - "NftFilter": { + "MoralisNftDetails": { "data": [ { - "parameter": "exclude_spam", - "type": "boolean", - "required": false, - "default": "false", - "description": "Optional, defaults to `false`. If `true`, only tokens which have param `possible_spam:false` are included in the response." + "parameter": "amount", + "type": "string", + "required": true, + "description": "The amount of this NFT the user owns (used by `ERC1155`)." }, { - "parameter": "exclude_phishing", - "type": "boolean", + "parameter": "block_number_minted", + "type": "integer", "required": false, - "default": "false", - "description": "Optional, defaults to `false`. If `true`, only tokens which have param `possible_phishing:false` are included in the response." - } - ] - }, - "NftInfoBasic": { - "data": [ + "description": "The block height when the NFT was minted. May be `null`." + }, { - "parameter": "amount", - "type": "string", + "parameter": "block_number", + "type": "integer", "required": true, - "description": "The amount of this NFT the user owns (used by `ERC1155`)." + "description": "The block height when the amount or owner changed." }, { "parameter": "chain", @@ -75,23 +69,102 @@ "required": true, "description": "Chain name. One of `AVALANCHE`, `BSC`, `ETH`, `FANTOM`, or `POLYGON`." }, + { + "parameter": "name", + "type": "string", + "required": false, + "description": "May be `null`. An NFT collection name." + }, { "parameter": "contract_type", "type": "string", "required": true, "description": "The type of NFT contract standard. One of `ERC721` or `ERC1155`." }, + { + "parameter": "last_token_uri_sync", + "type": "string", + "required": true, + "description": "When the token_uri was last updated." + }, + { + "parameter": "metadata", + "type": "string", + "required": false, + "description": "May be `null` or a JSON stringified object containing NFT metadata." + }, + { + "parameter": "normalized_metadata", + "type": "object", + "required": false, + "description": "A JSON object containing NFT metadata." + }, + { + "parameter": "possible_spam", + "type": "boolean", + "required": true, + "description": "Indicates if the NFT collection is flagged as spam." + }, + { + "parameter": "symbol", + "type": "string", + "required": false, + "description": "May be `null`. The symbol of the NFT collection." + }, + { + "parameter": "synced_at", + "type": "string", + "required": true, + "description": "When the NFT was last synced with the node." + }, { "parameter": "token_address", "type": "string", "required": true, - "description": "The address of the NFT contract." + "description": "The smart contract address of this NFT." + }, + { + "parameter": "token_hash", + "type": "string", + "required": true, + "description": "A hash uniquely identifying this NFT's metadata." }, { "parameter": "token_id", "type": "string", "required": true, - "description": "The token ID of the NFT." + "description": "The token ID of this NFT." + }, + { + "parameter": "token_uri", + "type": "string", + "required": false, + "description": "May be `null`. A URI to the NFT metadata (Usually an IPFS link)." + }, + { + "parameter": "possible_phishing", + "type": "boolean", + "required": true, + "description": "Indicates if the NFT is flagged as phishing." + } + ], + "variant": "compact" + }, + "NftFilter": { + "data": [ + { + "parameter": "exclude_spam", + "type": "boolean", + "required": false, + "default": "false", + "description": "Optional, defaults to `false`. If `true`, only tokens which have param `possible_spam:false` are included in the response." + }, + { + "parameter": "exclude_phishing", + "type": "boolean", + "required": false, + "default": "false", + "description": "Optional, defaults to `false`. If `true`, only tokens which have param `possible_phishing:false` are included in the response." } ] }, @@ -209,11 +282,46 @@ "parameter": "uri_meta", "type": "object", "required": true, - "description": "A standard [NftMetadata](/komodo-defi-framework/api/common_structures/nfts/#nft-metadata) object." + "description": "A standard [NftMetadata](/komodo-defi-framework/api/common_structures/nfts/#nft-metadata) object.", + "substructure": "nfts.NftMetadata" } ], "variant": "compact" }, + "NftInfoBasic": { + "data": [ + { + "parameter": "amount", + "type": "string", + "required": true, + "description": "The amount of this NFT the user owns (used by `ERC1155`)." + }, + { + "parameter": "chain", + "type": "string", + "required": true, + "description": "Chain name. One of `AVALANCHE`, `BSC`, `ETH`, `FANTOM`, or `POLYGON`." + }, + { + "parameter": "contract_type", + "type": "string", + "required": true, + "description": "The type of NFT contract standard. One of `ERC721` or `ERC1155`." + }, + { + "parameter": "token_address", + "type": "string", + "required": true, + "description": "The address of the NFT contract." + }, + { + "parameter": "token_id", + "type": "string", + "required": true, + "description": "The token ID of the NFT." + } + ] + }, "NftMetadata": { "data": [ { @@ -297,7 +405,8 @@ "parameter": "info", "type": "object", "required": true, - "description": "Additional information about the provider" + "description": "Additional information about the provider", + "substructure": "nfts.NftProviderInfo" }, { "parameter": "info.url", @@ -475,7 +584,8 @@ "parameter": "fee_details", "type": "object", "required": false, - "description": "A standard [FeeInfo](/komodo-defi-framework/api/common_structures/wallet/#fee-info) object." + "description": "A standard [FeeInfo](/komodo-defi-framework/api/common_structures/wallet/#fee-info) object.", + "substructure": "wallet.FeeInfo" }, { "parameter": "confirmations", @@ -530,113 +640,6 @@ } ] }, - "MoralisNftDetails": { - "data": [ - { - "parameter": "amount", - "type": "string", - "required": true, - "description": "The amount of this NFT the user owns (used by `ERC1155`)." - }, - { - "parameter": "block_number_minted", - "type": "integer", - "required": false, - "description": "The block height when the NFT was minted. May be `null`." - }, - { - "parameter": "block_number", - "type": "integer", - "required": true, - "description": "The block height when the amount or owner changed." - }, - { - "parameter": "chain", - "type": "string", - "required": true, - "description": "Chain name. One of `AVALANCHE`, `BSC`, `ETH`, `FANTOM`, or `POLYGON`." - }, - { - "parameter": "name", - "type": "string", - "required": false, - "description": "May be `null`. An NFT collection name." - }, - { - "parameter": "contract_type", - "type": "string", - "required": true, - "description": "The type of NFT contract standard. One of `ERC721` or `ERC1155`." - }, - { - "parameter": "last_token_uri_sync", - "type": "string", - "required": true, - "description": "When the token_uri was last updated." - }, - { - "parameter": "metadata", - "type": "string", - "required": false, - "description": "May be `null` or a JSON stringified object containing NFT metadata." - }, - { - "parameter": "normalized_metadata", - "type": "object", - "required": false, - "description": "A JSON object containing NFT metadata." - }, - { - "parameter": "possible_spam", - "type": "boolean", - "required": true, - "description": "Indicates if the NFT collection is flagged as spam." - }, - { - "parameter": "symbol", - "type": "string", - "required": false, - "description": "May be `null`. The symbol of the NFT collection." - }, - { - "parameter": "synced_at", - "type": "string", - "required": true, - "description": "When the NFT was last synced with the node." - }, - { - "parameter": "token_address", - "type": "string", - "required": true, - "description": "The smart contract address of this NFT." - }, - { - "parameter": "token_hash", - "type": "string", - "required": true, - "description": "A hash uniquely identifying this NFT's metadata." - }, - { - "parameter": "token_id", - "type": "string", - "required": true, - "description": "The token ID of this NFT." - }, - { - "parameter": "token_uri", - "type": "string", - "required": false, - "description": "May be `null`. A URI to the NFT metadata (Usually an IPFS link)." - }, - { - "parameter": "possible_phishing", - "type": "boolean", - "required": true, - "description": "Indicates if the NFT is flagged as phishing." - } - ], - "variant": "compact" - }, "TokenProtocol": { "data": [ { diff --git a/src/data/tables/common-structures/orders.json b/src/data/tables/common-structures/orders.json index 5eab673ed..1231cf6f9 100644 --- a/src/data/tables/common-structures/orders.json +++ b/src/data/tables/common-structures/orders.json @@ -160,7 +160,8 @@ "parameter": "data", "type": "object", "required": false, - "description": "Optional. additional data the cancel condition; present with `Pair` and `Coin` types" + "description": "Optional. additional data the cancel condition; present with `Pair` and `Coin` types", + "substructure": "orders.CancelByData" }, { "parameter": "data.base", @@ -210,6 +211,22 @@ } ] }, + "DepthInfo": { + "data": [ + { + "parameter": "asks", + "type": "number", + "required": true, + "description": "The number of asks for this trading pair" + }, + { + "parameter": "bids", + "type": "number", + "required": true, + "description": "The number of bids for this trading pair" + } + ] + }, "MatchBy": { "data": [ { @@ -451,207 +468,6 @@ } ] }, - "OrderDataV2": { - "data": [ - { - "parameter": "coin", - "type": "string", - "required": false, - "description": "The ticker of the coin" - }, - { - "parameter": "address", - "type": "object", - "required": false, - "description": "A standard [OrderAddress](/komodo-defi-framework/api/common_structures/orders/#order-address) object." - }, - { - "parameter": "price", - "type": "object", - "required": false, - "description": "A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the coin price." - }, - { - "parameter": "base_min_volume", - "type": "object", - "required": false, - "description": "A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the minimum base volume." - }, - { - "parameter": "base_max_volume", - "type": "object", - "required": false, - "description": "A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the maximum base volume." - }, - { - "parameter": "base_max_volume_aggr", - "type": "object", - "required": false, - "description": "Orderbook (v2) only. A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the maximum aggregated base amount at the specified price. The sum of max base volumes of the current order and all orders with a worse price." - }, - { - "parameter": "rel_min_volume", - "type": "object", - "required": false, - "description": "A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the minimum rel volume." - }, - { - "parameter": "rel_max_volume", - "type": "object", - "required": false, - "description": "A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the maximum rel volume." - }, - { - "parameter": "rel_max_volume_aggr", - "type": "object", - "required": false, - "description": "Orderbook (v2) only. A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the maximum aggregated rel amount at the specified price. The sum of max rel volumes of the current order and all orders with a worse price." - }, - { - "parameter": "pubkey", - "type": "string", - "required": false, - "description": "The pubkey of the offer provider" - }, - { - "parameter": "uuid", - "type": "string", - "required": false, - "description": "The uuid of order" - }, - { - "parameter": "is_mine", - "type": "bool", - "required": false, - "description": "Whether the order is placed by me" - }, - { - "parameter": "conf_settings", - "type": "object", - "required": false, - "description": "A standard [ConfSettings](/komodo-defi-framework/api/common_structures/orders/#conf-settings) object." - } - ] - }, - "OrderStatusData": { - "data": [ - { - "parameter": "base", - "type": "string", - "required": true, - "description": "base currency" - }, - { - "parameter": "rel", - "type": "string", - "required": true, - "description": "rel currency" - }, - { - "parameter": "price", - "type": "number", - "required": true, - "description": "order price as decimal number" - }, - { - "parameter": "price_rat", - "type": "rational number", - "required": true, - "description": "order price as rational number" - }, - { - "parameter": "max_base_vol", - "type": "number", - "required": true, - "description": "Maximum trade volume" - }, - { - "parameter": "max_base_vol_rat", - "type": "rational number", - "required": true, - "description": "Maximum trade volume as rational number" - }, - { - "parameter": "min_base_vol", - "type": "number", - "required": true, - "description": "Minimum trade volume" - }, - { - "parameter": "min_base_vol_rat", - "type": "rational number", - "required": true, - "description": "Minimum trade volume as rational number" - }, - { - "parameter": "created_at", - "type": "number", - "required": true, - "description": "Timestamp of order creation" - }, - { - "parameter": "updated_at", - "type": "number", - "required": true, - "description": "Timestamp of last order update" - }, - { - "parameter": "matches", - "type": "list", - "required": true, - "description": "UUIDS of matching orders" - }, - { - "parameter": "started_swaps", - "type": "list", - "required": true, - "description": "UUIDS of swaps started" - }, - { - "parameter": "uuid", - "type": "string", - "required": true, - "description": "UUID of this order" - }, - { - "parameter": "conf_settings", - "type": "object", - "required": true, - "description": "Confirmation / Notarisation settings for order" - }, - { - "parameter": "base_orderbook_ticker", - "type": "string", - "required": false, - "description": "The ticker of the base currency if `orderbook_ticker` is configured for the base currency in `coins` file. If not defined, will return a null value." - }, - { - "parameter": "rel_orderbook_ticker", - "type": "string", - "required": false, - "description": "The ticker of the rel currency if `orderbook_ticker` is configured for the rel currency in `coins` file. If not defined, will return a null value." - }, - { - "parameter": "cancellable", - "type": "boolean", - "required": true, - "description": "`true` if order is in a state which it can be cancelled. `false` if not (e.g. swap is in progress)" - }, - { - "parameter": "cancellation_reason", - "type": "string", - "required": false, - "description": "`Cancelled` indicates order was withdrawn by user. `Fulfilled` indicates order was swapped successfully. `TimedOut` indicates a taker order with type `FillOrKill` expired before matching." - }, - { - "parameter": "available_amount", - "type": "string", - "required": true, - "description": "Funds available for order to be matched against, taking into account current spendable balance and `max_volume`" - } - ], - "variant": "compact" - }, "OrderDataV1_1": { "data": [ { @@ -860,6 +676,88 @@ } ] }, + "OrderDataV2": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": false, + "description": "The ticker of the coin" + }, + { + "parameter": "address", + "type": "object", + "required": false, + "description": "A standard [OrderAddress](/komodo-defi-framework/api/common_structures/orders/#order-address) object." + }, + { + "parameter": "price", + "type": "object", + "required": false, + "description": "A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the coin price." + }, + { + "parameter": "base_min_volume", + "type": "object", + "required": false, + "description": "A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the minimum base volume." + }, + { + "parameter": "base_max_volume", + "type": "object", + "required": false, + "description": "A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the maximum base volume." + }, + { + "parameter": "base_max_volume_aggr", + "type": "object", + "required": false, + "description": "Orderbook (v2) only. A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the maximum aggregated base amount at the specified price. The sum of max base volumes of the current order and all orders with a worse price." + }, + { + "parameter": "rel_min_volume", + "type": "object", + "required": false, + "description": "A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the minimum rel volume." + }, + { + "parameter": "rel_max_volume", + "type": "object", + "required": false, + "description": "A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the maximum rel volume." + }, + { + "parameter": "rel_max_volume_aggr", + "type": "object", + "required": false, + "description": "Orderbook (v2) only. A standard [NumericFormatsValue](/komodo-defi-framework/api/common_structures/#numeric-formats-value) object representing the maximum aggregated rel amount at the specified price. The sum of max rel volumes of the current order and all orders with a worse price." + }, + { + "parameter": "pubkey", + "type": "string", + "required": false, + "description": "The pubkey of the offer provider" + }, + { + "parameter": "uuid", + "type": "string", + "required": false, + "description": "The uuid of order" + }, + { + "parameter": "is_mine", + "type": "bool", + "required": false, + "description": "Whether the order is placed by me" + }, + { + "parameter": "conf_settings", + "type": "object", + "required": false, + "description": "A standard [ConfSettings](/komodo-defi-framework/api/common_structures/orders/#conf-settings) object." + } + ] + }, "OrderDataV2_1": { "data": [ { @@ -1006,29 +904,132 @@ } ] }, - "OrderType": { + "OrderStatusData": { "data": [ { - "parameter": "Type", + "parameter": "base", "type": "string", "required": true, - "description": "There are two types from which to choose: `GoodTillCancelled` and `FillOrKill`. The `GoodTillCancelled` order is automatically converted to a `maker` order if the order is not matched in 30 seconds, and this `maker` order stays in the orderbook until explicitly cancelled. On the other hand, a `FillOrKill` order is cancelled if it is not matched within 30 seconds. The default type is `GoodTillCancelled`" - } - ] - }, - "RequestBy": { - "data": [ + "description": "base currency" + }, { - "parameter": "type", - "type": "integer", + "parameter": "rel", + "type": "string", "required": true, - "description": "Defines whether requesting by `volume` or by `number`." + "description": "rel currency" }, { - "parameter": "value", - "type": "numeric string", + "parameter": "price", + "type": "number", "required": true, - "description": "If `type` is `volume`, the amount of `coin` (defined in the parent object) the user is willing to buy or sell. If `type` is `number`, the number of best price trades to return." + "description": "order price as decimal number" + }, + { + "parameter": "price_rat", + "type": "rational number", + "required": true, + "description": "order price as rational number" + }, + { + "parameter": "max_base_vol", + "type": "number", + "required": true, + "description": "Maximum trade volume" + }, + { + "parameter": "max_base_vol_rat", + "type": "rational number", + "required": true, + "description": "Maximum trade volume as rational number" + }, + { + "parameter": "min_base_vol", + "type": "number", + "required": true, + "description": "Minimum trade volume" + }, + { + "parameter": "min_base_vol_rat", + "type": "rational number", + "required": true, + "description": "Minimum trade volume as rational number" + }, + { + "parameter": "created_at", + "type": "number", + "required": true, + "description": "Timestamp of order creation" + }, + { + "parameter": "updated_at", + "type": "number", + "required": true, + "description": "Timestamp of last order update" + }, + { + "parameter": "matches", + "type": "list", + "required": true, + "description": "UUIDS of matching orders" + }, + { + "parameter": "started_swaps", + "type": "list", + "required": true, + "description": "UUIDS of swaps started" + }, + { + "parameter": "uuid", + "type": "string", + "required": true, + "description": "UUID of this order" + }, + { + "parameter": "conf_settings", + "type": "object", + "required": true, + "description": "Confirmation / Notarisation settings for order" + }, + { + "parameter": "base_orderbook_ticker", + "type": "string", + "required": false, + "description": "The ticker of the base currency if `orderbook_ticker` is configured for the base currency in `coins` file. If not defined, will return a null value." + }, + { + "parameter": "rel_orderbook_ticker", + "type": "string", + "required": false, + "description": "The ticker of the rel currency if `orderbook_ticker` is configured for the rel currency in `coins` file. If not defined, will return a null value." + }, + { + "parameter": "cancellable", + "type": "boolean", + "required": true, + "description": "`true` if order is in a state which it can be cancelled. `false` if not (e.g. swap is in progress)" + }, + { + "parameter": "cancellation_reason", + "type": "string", + "required": false, + "description": "`Cancelled` indicates order was withdrawn by user. `Fulfilled` indicates order was swapped successfully. `TimedOut` indicates a taker order with type `FillOrKill` expired before matching." + }, + { + "parameter": "available_amount", + "type": "string", + "required": true, + "description": "Funds available for order to be matched against, taking into account current spendable balance and `max_volume`" + } + ], + "variant": "compact" + }, + "OrderType": { + "data": [ + { + "parameter": "Type", + "type": "string", + "required": true, + "description": "There are two types from which to choose: `GoodTillCancelled` and `FillOrKill`. The `GoodTillCancelled` order is automatically converted to a `maker` order if the order is not matched in 30 seconds, and this `maker` order stays in the orderbook until explicitly cancelled. On the other hand, a `FillOrKill` order is cancelled if it is not matched within 30 seconds. The default type is `GoodTillCancelled`" } ] }, @@ -1054,19 +1055,19 @@ } ] }, - "DepthInfo": { + "RequestBy": { "data": [ { - "parameter": "asks", - "type": "number", + "parameter": "type", + "type": "integer", "required": true, - "description": "The number of asks for this trading pair" + "description": "Defines whether requesting by `volume` or by `number`." }, { - "parameter": "bids", - "type": "number", + "parameter": "value", + "type": "numeric string", "required": true, - "description": "The number of bids for this trading pair" + "description": "If `type` is `volume`, the amount of `coin` (defined in the parent object) the user is willing to buy or sell. If `type` is `number`, the number of best price trades to return." } ] } diff --git a/src/data/tables/common-structures/taker-events.json b/src/data/tables/common-structures/taker-events.json index 60b940cd6..d848c0733 100644 --- a/src/data/tables/common-structures/taker-events.json +++ b/src/data/tables/common-structures/taker-events.json @@ -1,4 +1,134 @@ { + "MakerPaymentReceived": { + "data": [ + { + "parameter": "tx_hash", + "type": "string", + "required": true, + "description": "the hash of the transaction" + }, + { + "parameter": "tx_hex", + "type": "string", + "required": true, + "description": "transaction bytes in hexadecimal format" + } + ] + }, + "MakerPaymentSpendConfirmed": { + "data": [ + { + "parameter": "tx_hash", + "type": "string", + "required": true, + "description": "the hash of the transaction" + }, + { + "parameter": "tx_hex", + "type": "string", + "required": true, + "description": "transaction bytes in hexadecimal format" + } + ] + }, + "MakerPaymentSpendConfirmFailed": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "error description with stack trace" + } + ] + }, + "MakerPaymentSpendFailed": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "error description with stack trace" + } + ] + }, + "MakerPaymentSpent": { + "data": [ + { + "parameter": "tx_hash", + "type": "string", + "required": true, + "description": "the hash of the transaction" + }, + { + "parameter": "tx_hex", + "type": "string", + "required": true, + "description": "transaction bytes in hexadecimal format" + } + ] + }, + "MakerPaymentSpentByWatcher": { + "data": [ + { + "parameter": "tx_hash", + "type": "string", + "required": true, + "description": "the hash of the transaction" + }, + { + "parameter": "tx_hex", + "type": "string", + "required": true, + "description": "transaction bytes in hexadecimal format" + } + ] + }, + "MakerPaymentValidateFailed": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "error description with stack trace" + } + ] + }, + "MakerPaymentWaitConfirmFailed": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "error description with stack trace" + } + ] + }, + "Negotiated": { + "data": [ + { + "parameter": "maker_payment_locktime", + "type": "number (UTC timestamp in seconds)", + "required": true, + "description": "the maker payment is locked until this timestamp" + }, + { + "parameter": "maker_pubkey", + "type": "string (hexadecimal)", + "required": true, + "description": "a persistent secp256k1 public key of maker node" + } + ] + }, + "NegotiateFailed": { + "data": [ + { + "parameter": "error", + "type": "string", + "required": true, + "description": "error description with stack trace" + } + ] + }, "Started": { "data": [ { @@ -71,7 +201,7 @@ "parameter": "uuid", "type": "string", "required": true, - "description": "the swap uuid" + "description": "the swap uuid" }, { "parameter": "started_at", @@ -104,23 +234,7 @@ } ] }, - "Negotiated": { - "data": [ - { - "parameter": "maker_payment_locktime", - "type": "number (UTC timestamp in seconds)", - "required": true, - "description": "the maker payment is locked until this timestamp" - }, - { - "parameter": "maker_pubkey", - "type": "string (hexadecimal)", - "required": true, - "description": "a persistent secp256k1 public key of maker node" - } - ] - }, - "NegotiateFailed": { + "TakerFeeSendFailed": { "data": [ { "parameter": "error", @@ -146,17 +260,7 @@ } ] }, - "TakerFeeSendFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, - "MakerPaymentValidateFailed": { + "TakerPaymentDataSendFailed": { "data": [ { "parameter": "error", @@ -166,7 +270,7 @@ } ] }, - "MakerPaymentReceived": { + "TakerPaymentRefunded": { "data": [ { "parameter": "tx_hash", @@ -182,17 +286,7 @@ } ] }, - "MakerPaymentWaitConfirmFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, - "TakerPaymentSent": { + "TakerPaymentRefundedByWatcher": { "data": [ { "parameter": "tx_hash", @@ -208,27 +302,7 @@ } ] }, - "TakerPaymentTransactionFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, - "TakerPaymentWaitConfirmFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, - "TakerPaymentDataSendFailed": { + "TakerPaymentRefundFailed": { "data": [ { "parameter": "error", @@ -238,7 +312,7 @@ } ] }, - "TakerPaymentSpent": { + "TakerPaymentSent": { "data": [ { "parameter": "tx_hash", @@ -254,27 +328,7 @@ } ] }, - "TakerPaymentWaitForSpendFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, - "MakerPaymentSpendFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, - "MakerPaymentSpent": { + "TakerPaymentSpent": { "data": [ { "parameter": "tx_hash", @@ -290,23 +344,17 @@ } ] }, - "MakerPaymentSpendConfirmed": { + "TakerPaymentTransactionFailed": { "data": [ { - "parameter": "tx_hash", - "type": "string", - "required": true, - "description": "the hash of the transaction" - }, - { - "parameter": "tx_hex", + "parameter": "error", "type": "string", "required": true, - "description": "transaction bytes in hexadecimal format" + "description": "error description with stack trace" } ] }, - "MakerPaymentSpendConfirmFailed": { + "TakerPaymentWaitConfirmFailed": { "data": [ { "parameter": "error", @@ -316,19 +364,13 @@ } ] }, - "MakerPaymentSpentByWatcher": { + "TakerPaymentWaitForSpendFailed": { "data": [ { - "parameter": "tx_hash", - "type": "string", - "required": true, - "description": "the hash of the transaction" - }, - { - "parameter": "tx_hex", + "parameter": "error", "type": "string", "required": true, - "description": "transaction bytes in hexadecimal format" + "description": "error description with stack trace" } ] }, @@ -341,47 +383,5 @@ "description": "the timestamp at which a refund will occur" } ] - }, - "TakerPaymentRefundedByWatcher": { - "data": [ - { - "parameter": "tx_hash", - "type": "string", - "required": true, - "description": "the hash of the transaction" - }, - { - "parameter": "tx_hex", - "type": "string", - "required": true, - "description": "transaction bytes in hexadecimal format" - } - ] - }, - "TakerPaymentRefundFailed": { - "data": [ - { - "parameter": "error", - "type": "string", - "required": true, - "description": "error description with stack trace" - } - ] - }, - "TakerPaymentRefunded": { - "data": [ - { - "parameter": "tx_hash", - "type": "string", - "required": true, - "description": "the hash of the transaction" - }, - { - "parameter": "tx_hex", - "type": "string", - "required": true, - "description": "transaction bytes in hexadecimal format" - } - ] } } \ No newline at end of file diff --git a/src/data/tables/common-structures/wallet.json b/src/data/tables/common-structures/wallet.json index f8ad3d0a1..99432c3f5 100644 --- a/src/data/tables/common-structures/wallet.json +++ b/src/data/tables/common-structures/wallet.json @@ -23,7 +23,8 @@ "parameter": "balance", "type": "object", "required": true, - "description": "A standard [BalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object." + "description": "A standard [BalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object.", + "substructure": "wallet.BalanceInfo" } ] }, @@ -43,19 +44,63 @@ } ] }, + "AccountId": { + "data": [ + { + "parameter": "type", + "type": "string", + "required": true, + "description": "Defines account kind. Possible values: `iguana`, `hd`, `hw`." + }, + { + "parameter": "account_idx", + "type": "integer", + "required": false, + "description": "Only when `type` = `hd`. Index of the HD account (starting at 0)." + }, + { + "parameter": "device_pubkey", + "type": "string", + "required": false, + "description": "Only when `type` = `hw`. Hex-encoded pubkey of the hardware wallet device." + } + ] + }, + "AccruedRewards": { + "data": [ + { + "parameter": "amount", + "type": "string (numeric)", + "required": true, + "description": "the amount of accrued rewards" + } + ] + }, + "AccruedVariant": { + "data": [ + { + "parameter": "Accrued", + "type": "string (numeric)", + "required": true, + "description": "the amount of accrued rewards" + } + ] + }, "AddressInfo": { "data": [ { "parameter": "balances", "type": "object", "required": false, - "description": "A standard [balanceInfos](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object. Not included in responses where `get_balances` is `false`" + "description": "A standard [balanceInfos](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object. Not included in responses where `get_balances` is `false`", + "substructure": "wallet.BalanceInfo" }, { "parameter": "derivation_method", "type": "object", "required": true, - "description": "A standard [DerivationMethod](/komodo-defi-framework/api/common_structures/wallet/#derivation-method) object" + "description": "A standard [DerivationMethod](/komodo-defi-framework/api/common_structures/wallet/#derivation-method) object", + "substructure": "wallet.DerivationMethod" }, { "parameter": "pubkey", @@ -99,6 +144,22 @@ } ] }, + "AmountTooLow": { + "data": [ + { + "parameter": "amount", + "type": "string (numeric)", + "required": true, + "description": "the amount the user was willing to transfer" + }, + { + "parameter": "threshold", + "type": "string (numeric)", + "required": true, + "description": "the `amount` has not to be less than the `threshold`" + } + ] + }, "BalanceInfo": { "data": [ { @@ -115,6 +176,28 @@ } ] }, + "ClaimingDetails": { + "data": [ + { + "parameter": "type", + "type": "string", + "required": true, + "description": "The coin type. Currently, only 'Cosmos' and `Qtum` are supported." + }, + { + "parameter": "validator_address", + "type": "string", + "required": true, + "description": "The address of the validator to delegate staking to." + }, + { + "parameter": "force", + "type": "boolean", + "required": false, + "description": "Defaults to `false`. If `true`, will process unprofitable transactions (reward value less than network fees)" + } + ] + }, "DerivationMethod": { "data": [ { @@ -125,6 +208,22 @@ } ] }, + "EnabledAccountId": { + "data": [ + { + "parameter": "type", + "type": "string", + "required": true, + "description": "Account kind. Accepted values are `iguana` and `hd`." + }, + { + "parameter": "account_idx", + "type": "integer", + "required": false, + "description": "Optional. Required only when `type` = `hd`. The index of the HD account to enable (starting from `0`)." + } + ] + }, "ExtendedFeeInfo": { "data": [ { @@ -205,6 +304,56 @@ } ] }, + "HdCoinKeys": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "The ticker symbol of the coin." + }, + { + "parameter": "addresses", + "type": "array", + "required": true, + "description": "Array of [HdKeysInfo](/komodo-defi-framework/api/common_structures/wallet/#hd-keys-info) objects for each address." + } + ] + }, + "HdKeysInfo": { + "data": [ + { + "parameter": "derivation_path", + "type": "string", + "required": true, + "description": "The [BIP44 derivation path](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) of the address." + }, + { + "parameter": "pubkey", + "type": "string", + "required": true, + "description": "The public key for the address." + }, + { + "parameter": "address", + "type": "string", + "required": true, + "description": "The wallet address." + }, + { + "parameter": "priv_key", + "type": "string", + "required": true, + "description": "The private key for the address." + }, + { + "parameter": "viewing_key", + "type": "string", + "required": false, + "description": "The viewing key for the address. Only included for ZHTLC coins like ARRR that support enhanced privacy features." + } + ] + }, "HistoryTarget": { "data": [ { @@ -233,6 +382,34 @@ } ] }, + "IguanaKeysInfo": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "The ticker symbol of the coin." + }, + { + "parameter": "pubkey", + "type": "string", + "required": true, + "description": "The public key for the coin." + }, + { + "parameter": "address", + "type": "string", + "required": true, + "description": "The wallet address for the coin." + }, + { + "parameter": "priv_key", + "type": "string", + "required": true, + "description": "The private key for the coin." + } + ] + }, "InputTxns": { "data": [ { @@ -261,6 +438,55 @@ } ] }, + "InvalidAddress": { + "data": [ + { + "parameter": "(none)", + "type": "string", + "required": true, + "description": "the error description" + } + ] + }, + "InvalidFeePolicy": { + "data": [ + { + "parameter": "(none)", + "type": "string", + "required": true, + "description": "the error description" + } + ] + }, + "NewAccount": { + "data": [ + { + "parameter": "account_id", + "type": "EnabledAccountId", + "required": true, + "description": "Identifier of the new account." + }, + { + "parameter": "name", + "type": "string", + "required": true, + "description": "User-friendly name for the account (maximum 255 characters)." + }, + { + "parameter": "description", + "type": "string", + "required": false, + "description": "Optional. Optional longer description (maximum 600 characters)." + }, + { + "parameter": "balance_usd", + "type": "string (numeric)", + "required": false, + "default": "0", + "description": "Optional, defaults to `0`. Optional initial USD balance shown in GUIs." + } + ] + }, "NewAddressInfo": { "data": [ { @@ -279,7 +505,8 @@ "parameter": "balance", "type": "object", "required": true, - "description": "A standard [BalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object." + "description": "A standard [BalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object.", + "substructure": "wallet.BalanceInfo" }, { "parameter": "chain", @@ -289,6 +516,38 @@ } ] }, + "NotAccruedReason": { + "data": [ + { + "parameter": "reason", + "type": "string", + "required": true, + "description": "the reason why rewards were not accrued" + } + ] + }, + "NotSufficientBalance": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "the name of the coin which balance is not sufficient. This coin name may differ from the requested coin. For example, ERC20 fees are paid by ETH (gas)" + }, + { + "parameter": "available", + "type": "string (numeric)", + "required": true, + "description": "the balance available for transfer" + }, + { + "parameter": "required", + "type": "string (numeric)", + "required": true, + "description": "the amount required to transfer the specified amount. This amount is necessary but may not be sufficient" + } + ] + }, "PayForGas": { "data": [ { @@ -330,91 +589,35 @@ ], "variant": "compact" }, - "StakingDetails": { - "data": [ - { - "parameter": "type", - "type": "string", - "required": true, - "description": "The coin type. Currently, only 'Cosmos' and `Qtum` are supported." - }, - { - "parameter": "validator_address", - "type": "string", - "required": true, - "description": "The address of the validator to delegate staking to." - }, - { - "parameter": "amount", - "type": "string", - "required": true, - "description": "The amount of coins to stake send to the validator for delegated staking (Cosmos only - QTUM will stake your whole balance)." - } - ] - }, - "StakingInfoDetails": { - "data": [ - { - "parameter": "type", - "type": "string", - "required": true, - "description": "The coin type. Currently, only 'Cosmos' is supported." - }, - { - "parameter": "filter_by_status", - "type": "string", - "required": true, - "description": "Return only validators matching a specific status. Options are `Bonded`, `Unbonded`, and `All`. Defaults to `Bonded`." - }, - { - "parameter": "limit", - "type": "integer", - "required": false, - "description": "Optional, defaults to `10`. The number of validators displayed per page in response." - }, - { - "parameter": "page_number", - "type": "integer", - "required": false, - "description": "Optional, defaults to `1`. The page offset for items in response." - } - ] - }, - "ClaimingDetails": { + "PrivKeyPolicy": { "data": [ { "parameter": "type", "type": "string", "required": true, - "description": "The coin type. Currently, only 'Cosmos' and `Qtum` are supported." - }, - { - "parameter": "validator_address", - "type": "string", - "required": true, - "description": "The address of the validator to delegate staking to." + "description": "Options are `ContextPrivKey`, `WalletConnect`, `Metamask`, or `Trezor`. Defaults to `ContextPrivKey`." }, { - "parameter": "force", - "type": "boolean", + "parameter": "data", + "type": "list", "required": false, - "description": "Defaults to `false`. If `true`, will process unprofitable transactions (reward value less than network fees)" + "description": "`WalletConnect` type only. The `session_topic` hex string, returned from the response to [wc_new_connection](/komodo-defi-framework/api/v20-dev/wc_new_connection/#wc-new-connection)." } ] }, - "PrivKeyPolicy": { + "AddressFormat": { "data": [ { - "parameter": "type", - "type": "string", + "parameter": "format", + "type": "string (enum)", "required": true, - "description": "Options are `ContextPrivKey`, `WalletConnect`, `Metamask`, or `Trezor`. Defaults to `ContextPrivKey`." + "description": "address format to which the input address should be converted. Possible values: `mixedcase` for ETH/ERC20 coins; `cashaddress` or `standard` for UTXO coins; `contract` or `wallet` for QTUM/QRC20" }, { - "parameter": "data", - "type": "list", + "parameter": "network", + "type": "string (enum)", "required": false, - "description": "`WalletConnect` type only. The `session_topic` hex string, returned from the response to [wc_new_connection](/komodo-defi-framework/api/v20-dev/wc_new_connection/#wc-new-connection)." + "description": "Optional. Network prefix for `cashaddress` format. Possible values: `bitcoincash` for BCH mainnet; `bchtest` for BCH testnet; `bchreg` for BCH regtest" } ] }, @@ -454,7 +657,8 @@ "parameter": "pay_for_gas", "type": "object", "required": false, - "description": "ETH/EVM only. Used for EIP-1559 fee policy config. A standard [PayForGas](/komodo-defi-framework/api/common_structures/wallet/#pay-for-gas) object." + "description": "ETH/EVM only. Used for EIP-1559 fee policy config. A standard [PayForGas](/komodo-defi-framework/api/common_structures/wallet/#pay-for-gas) object.", + "substructure": "wallet.PayForGas" } ] }, @@ -480,6 +684,56 @@ } ] }, + "StakingDetails": { + "data": [ + { + "parameter": "type", + "type": "string", + "required": true, + "description": "The coin type. Currently, only 'Cosmos' and `Qtum` are supported." + }, + { + "parameter": "validator_address", + "type": "string", + "required": true, + "description": "The address of the validator to delegate staking to." + }, + { + "parameter": "amount", + "type": "string", + "required": true, + "description": "The amount of coins to stake send to the validator for delegated staking (Cosmos only - QTUM will stake your whole balance)." + } + ] + }, + "StakingInfoDetails": { + "data": [ + { + "parameter": "type", + "type": "string", + "required": true, + "description": "The coin type. Currently, only 'Cosmos' is supported." + }, + { + "parameter": "filter_by_status", + "type": "string", + "required": true, + "description": "Return only validators matching a specific status. Options are `Bonded`, `Unbonded`, and `All`. Defaults to `Bonded`." + }, + { + "parameter": "limit", + "type": "integer", + "required": false, + "description": "Optional, defaults to `10`. The number of validators displayed per page in response." + }, + { + "parameter": "page_number", + "type": "integer", + "required": false, + "description": "Optional, defaults to `1`. The page offset for items in response." + } + ] + }, "TotalFeeInfo": { "data": [ { @@ -526,64 +780,6 @@ } ] }, - "WithdrawFee": { - "data": [ - { - "parameter": "type", - "type": "string", - "required": true, - "description": "The fee type. Either `Utxo`, `Tendermint`, `Qrc20` or `Eth`." - }, - { - "parameter": "amount", - "type": "numeric string", - "required": false, - "description": "`Utxo` or `Tendermint` type only. The fee amount." - }, - { - "parameter": "coin", - "type": "string", - "required": true, - "description": "The coin which will be used to pay the transaction fee." - }, - { - "parameter": "gas", - "type": "integer", - "required": false, - "description": "`Eth` type only. The amount of gas to be used for the transaction." - }, - { - "parameter": "gas_price", - "type": "numeric string", - "required": false, - "description": "`Eth` or `Qrc20` type only. Price per unit of gas to be used for the transaction." - }, - { - "parameter": "gas_limit", - "type": "numeric string", - "required": false, - "description": "`Tendermint` or `Qrc20` type only. Maximum gas to be used for the transaction." - }, - { - "parameter": "miner_fee", - "type": "numeric string", - "required": false, - "description": "`Tendermint` type only. Fee to mine the transaction." - }, - { - "parameter": "total_fee", - "type": "numeric string", - "required": false, - "description": "`Eth` type only. Gas price multiplied by gas amount." - }, - { - "parameter": "total_gas_fee", - "type": "numeric string", - "required": false, - "description": "`Qrc20` type only. Gas price multiplied by gas amount." - } - ] - }, "WalletAccountInfo": { "data": [ { @@ -602,7 +798,8 @@ "parameter": "total_balance", "type": "object", "required": true, - "description": "A standard [BalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object." + "description": "A standard [BalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object.", + "substructure": "wallet.BalanceInfo" }, { "parameter": "addresses", @@ -624,268 +821,94 @@ "parameter": "accounts", "type": "object", "required": true, - "description": "A standard [WalletAccountInfo](/komodo-defi-framework/api/common_structures/wallet/#wallet-account-info) object." + "description": "A standard [WalletAccountInfo](/komodo-defi-framework/api/common_structures/wallet/#wallet-account-info) object.", + "substructure": "wallet.WalletAccountInfo" } ] }, - "WithdrawFromInfo": { - "data": [ - { - "parameter": "derivation_path", - "type": "string", - "required": false, - "description": "Optional. The [BIP44 derivation path](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) of the address." - }, - { - "parameter": "account_id", - "type": "integer", - "required": false, - "description": "Optional. `ACCOUNT_ID` child in the `m/44'/COIN'/ACCOUNT_ID'/CHAIN/ADDRESS_ID` BIP44 derivation path. **Please don't confuse with the global account.**" - }, - { - "parameter": "address_id", - "type": "integer", - "required": false, - "description": "Optional. `ADDRESS_ID` child in the `m/44'/COIN'/ACCOUNT_ID'/CHAIN/ADDRESS_ID` BIP44 derivation path." - }, - { - "parameter": "chain", - "type": "string", - "required": false, - "description": "Optional. `Internal`, or `External`. External is used for addresses that are meant to be visible outside of the wallet (e.g. for receiving payments). Internal is used for addresses which are not meant to be visible outside of the wallet and is used for return transaction change." - } - ] - }, - "AccountId": { + "WithdrawFee": { "data": [ { "parameter": "type", "type": "string", "required": true, - "description": "Defines account kind. Possible values: `iguana`, `hd`, `hw`." + "description": "The fee type. Either `Utxo`, `Tendermint`, `Qrc20` or `Eth`." }, { - "parameter": "account_idx", - "type": "integer", + "parameter": "amount", + "type": "numeric string", "required": false, - "description": "Only when `type` = `hd`. Index of the HD account (starting at 0)." + "description": "`Utxo` or `Tendermint` type only. The fee amount." }, - { - "parameter": "device_pubkey", - "type": "string", - "required": false, - "description": "Only when `type` = `hw`. Hex-encoded pubkey of the hardware wallet device." - } - ] - }, - "HdCoinKeys": { - "data": [ { "parameter": "coin", "type": "string", "required": true, - "description": "The ticker symbol of the coin." - }, - { - "parameter": "addresses", - "type": "array", - "required": true, - "description": "Array of [HdKeysInfo](/komodo-defi-framework/api/common_structures/wallet/#hd-keys-info) objects for each address." - } - ] - }, - "HdKeysInfo": { - "data": [ - { - "parameter": "derivation_path", - "type": "string", - "required": true, - "description": "The [BIP44 derivation path](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) of the address." - }, - { - "parameter": "pubkey", - "type": "string", - "required": true, - "description": "The public key for the address." - }, - { - "parameter": "address", - "type": "string", - "required": true, - "description": "The wallet address." - }, - { - "parameter": "priv_key", - "type": "string", - "required": true, - "description": "The private key for the address." + "description": "The coin which will be used to pay the transaction fee." }, { - "parameter": "viewing_key", - "type": "string", + "parameter": "gas", + "type": "integer", "required": false, - "description": "The viewing key for the address. Only included for ZHTLC coins like ARRR that support enhanced privacy features." - } - ] - }, - "IguanaKeysInfo": { - "data": [ - { - "parameter": "coin", - "type": "string", - "required": true, - "description": "The ticker symbol of the coin." - }, - { - "parameter": "pubkey", - "type": "string", - "required": true, - "description": "The public key for the coin." + "description": "`Eth` type only. The amount of gas to be used for the transaction." }, { - "parameter": "address", - "type": "string", - "required": true, - "description": "The wallet address for the coin." + "parameter": "gas_price", + "type": "numeric string", + "required": false, + "description": "`Eth` or `Qrc20` type only. Price per unit of gas to be used for the transaction." }, { - "parameter": "priv_key", - "type": "string", - "required": true, - "description": "The private key for the coin." - } - ] - }, - "NotSufficientBalance": { - "data": [ - { - "parameter": "coin", - "type": "string", - "required": true, - "description": "the name of the coin which balance is not sufficient. This coin name may differ from the requested coin. For example, ERC20 fees are paid by ETH (gas)" + "parameter": "gas_limit", + "type": "numeric string", + "required": false, + "description": "`Tendermint` or `Qrc20` type only. Maximum gas to be used for the transaction." }, { - "parameter": "available", - "type": "string (numeric)", - "required": true, - "description": "the balance available for transfer" + "parameter": "miner_fee", + "type": "numeric string", + "required": false, + "description": "`Tendermint` type only. Fee to mine the transaction." }, { - "parameter": "required", - "type": "string (numeric)", - "required": true, - "description": "the amount required to transfer the specified amount. This amount is necessary but may not be sufficient" - } - ] - }, - "AmountTooLow": { - "data": [ - { - "parameter": "amount", - "type": "string (numeric)", - "required": true, - "description": "the amount the user was willing to transfer" + "parameter": "total_fee", + "type": "numeric string", + "required": false, + "description": "`Eth` type only. Gas price multiplied by gas amount." }, { - "parameter": "threshold", - "type": "string (numeric)", - "required": true, - "description": "the `amount` has not to be less than the `threshold`" - } - ] - }, - "InvalidAddress": { - "data": [ - { - "parameter": "(none)", - "type": "string", - "required": true, - "description": "the error description" - } - ] - }, - "InvalidFeePolicy": { - "data": [ - { - "parameter": "(none)", - "type": "string", - "required": true, - "description": "the error description" - } - ] - }, - "AccruedVariant": { - "data": [ - { - "parameter": "Accrued", - "type": "string (numeric)", - "required": true, - "description": "the amount of accrued rewards" - } - ] - }, - "AccruedRewards": { - "data": [ - { - "parameter": "amount", - "type": "string (numeric)", - "required": true, - "description": "the amount of accrued rewards" - } - ] - }, - "NotAccruedReason": { - "data": [ - { - "parameter": "reason", - "type": "string", - "required": true, - "description": "the reason why rewards were not accrued" + "parameter": "total_gas_fee", + "type": "numeric string", + "required": false, + "description": "`Qrc20` type only. Gas price multiplied by gas amount." } ] }, - "EnabledAccountId": { + "WithdrawFromInfo": { "data": [ { - "parameter": "type", + "parameter": "derivation_path", "type": "string", - "required": true, - "description": "Account kind. Accepted values are `iguana` and `hd`." + "required": false, + "description": "Optional. The [BIP44 derivation path](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) of the address." }, { - "parameter": "account_idx", + "parameter": "account_id", "type": "integer", "required": false, - "description": "Optional. Required only when `type` = `hd`. The index of the HD account to enable (starting from `0`)." - } - ] - }, - "NewAccount": { - "data": [ - { - "parameter": "account_id", - "type": "EnabledAccountId", - "required": true, - "description": "Identifier of the new account." - }, - { - "parameter": "name", - "type": "string", - "required": true, - "description": "User-friendly name for the account (maximum 255 characters)." + "description": "Optional. `ACCOUNT_ID` child in the `m/44'/COIN'/ACCOUNT_ID'/CHAIN/ADDRESS_ID` BIP44 derivation path. **Please don't confuse with the global account.**" }, { - "parameter": "description", - "type": "string", + "parameter": "address_id", + "type": "integer", "required": false, - "description": "Optional. Optional longer description (maximum 600 characters)." + "description": "Optional. `ADDRESS_ID` child in the `m/44'/COIN'/ACCOUNT_ID'/CHAIN/ADDRESS_ID` BIP44 derivation path." }, { - "parameter": "balance_usd", - "type": "string (numeric)", + "parameter": "chain", + "type": "string", "required": false, - "default": "0", - "description": "Optional, defaults to `0`. Optional initial USD balance shown in GUIs." + "description": "Optional. `Internal`, or `External`. External is used for addresses that are meant to be visible outside of the wallet (e.g. for receiving payments). Internal is used for addresses which are not meant to be visible outside of the wallet and is used for return transaction change." } ] } diff --git a/src/data/tables/legacy/coin_activation.json b/src/data/tables/legacy/coin_activation.json index 813c8cecc..db9273697 100644 --- a/src/data/tables/legacy/coin_activation.json +++ b/src/data/tables/legacy/coin_activation.json @@ -11,7 +11,8 @@ "parameter": "servers", "type": "list of objects", "required": true, - "description": "A list of standard [ActivationServers](/komodo-defi-framework/api/common_structures/activation/#activation-servers) objects." + "description": "A list of standard [ActivationServers](/komodo-defi-framework/api/common_structures/activation/#activation-servers) objects.", + "substructure": "activation.ActivationServers" }, { "parameter": "mm2", @@ -62,7 +63,8 @@ "parameter": "utxo_merge_params", "type": "object", "required": false, - "description": "A standard [UtxoMergeParams](/komodo-defi-framework/api/common_structures/activation/#utxo-merge-params) object. Used to reduce a wallet's UTXO count in cases where it is causing significantly slower RPC responses." + "description": "A standard [UtxoMergeParams](/komodo-defi-framework/api/common_structures/activation/#utxo-merge-params) object. Used to reduce a wallet's UTXO count in cases where it is causing significantly slower RPC responses.", + "substructure": "activation.UtxoMergeParams" } ] }, @@ -237,5 +239,49 @@ "description": "the result of the request; this value either indicates `success`, or an error or other type of failure" } ] + }, + "ElectrumErrors": { + "data": [ + { + "parameter": "NoSuchCoin", + "type": "string", + "required": false, + "description": "The selected coin was not found or is not activated yet." + }, + { + "parameter": "InvalidRequest", + "type": "string", + "required": false, + "description": "The request is malformed or missing required parameters." + }, + { + "parameter": "InternalError", + "type": "string", + "required": false, + "description": "Unhandled internal error." + } + ] + }, + "EnableErrors": { + "data": [ + { + "parameter": "NoSuchCoin", + "type": "string", + "required": false, + "description": "The selected coin was not found or is not activated yet." + }, + { + "parameter": "InvalidRequest", + "type": "string", + "required": false, + "description": "The request is malformed or missing required parameters." + }, + { + "parameter": "InternalError", + "type": "string", + "required": false, + "description": "Unhandled internal error." + } + ] } } \ No newline at end of file diff --git a/src/data/tables/legacy/utils.json b/src/data/tables/legacy/utils.json new file mode 100644 index 000000000..d05de797c --- /dev/null +++ b/src/data/tables/legacy/utils.json @@ -0,0 +1,105 @@ +{ + "NoParams": { + "data": [ + { + "parameter": "(none)", + "type": "", + "required": false, + "description": "" + } + ] + }, + "VersionResponse": { + "data": [ + { + "parameter": "result", + "type": "string", + "required": true, + "description": "The Komodo DeFi Framework API version" + }, + { + "parameter": "datetime", + "type": "string", + "required": true, + "description": "A formatted datetime string" + } + ] + }, + "GetMyPeerIdResponse": { + "data": [ + { + "parameter": "result", + "type": "string", + "required": true, + "description": "The Peer ID of your node on the network" + } + ] + }, + "EnabledCoinEntry": { + "data": [ + { + "parameter": "address", + "type": "string", + "required": true, + "description": "The user's address for this coin" + }, + { + "parameter": "ticker", + "type": "string", + "required": true, + "description": "The ticker symbol of the enabled coin" + } + ] + }, + "GetEnabledCoinsResponse": { + "data": [ + { + "parameter": "result", + "type": "list of objects", + "required": true, + "description": "Tickers and addresses of enabled coins", + "substructure": "legacy/utils.EnabledCoinEntry" + } + ] + }, + "CoinsNeededForKickStartResponse": { + "data": [ + { + "parameter": "result", + "type": "array of strings", + "required": true, + "description": "Tickers of coins that should be activated to kick-start swaps and orders" + } + ] + }, + "VersionErrors": { + "data": [ + { + "parameter": "InternalError", + "type": "string", + "required": false, + "description": "Unhandled internal error." + } + ] + }, + "CoinsNeededForKickStartErrors": { + "data": [ + { + "parameter": "InternalError", + "type": "string", + "required": false, + "description": "Unhandled internal error." + } + ] + }, + "GetMyPeerIdErrors": { + "data": [ + { + "parameter": "InternalError", + "type": "string", + "required": false, + "description": "Unhandled internal error." + } + ] + } +} \ No newline at end of file diff --git a/src/data/tables/legacy/wallet.json b/src/data/tables/legacy/wallet.json new file mode 100644 index 000000000..f020a552f --- /dev/null +++ b/src/data/tables/legacy/wallet.json @@ -0,0 +1,399 @@ +{ + "SendRawTransactionRequest": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "The name of the coin network on which to broadcast the transaction." + }, + { + "parameter": "tx_hex", + "type": "string", + "required": false, + "description": "The transaction bytes in hexadecimal format; typically generated by the withdraw method. Not used for Sia protocol coins." + }, + { + "parameter": "tx_json", + "type": "object", + "required": false, + "description": "For Sia protocol coins only. The transaction details in JSON format; typically generated by the withdraw method." + } + ] + }, + "SendRawTransactionResponse": { + "data": [ + { + "parameter": "tx_hash", + "type": "string", + "required": true, + "description": "The hash of the broadcast transaction" + } + ] + }, + "WithdrawLegacyRequest": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "The name of the coin the user desires to withdraw." + }, + { + "parameter": "to", + "type": "string", + "required": true, + "description": "Coins are withdrawn to this address." + }, + { + "parameter": "amount", + "type": "string (numeric)", + "required": false, + "description": "The amount to withdraw; ignored when max=true." + }, + { + "parameter": "max", + "type": "boolean", + "required": false, + "description": "Withdraw the maximum available amount." + }, + { + "parameter": "fee", + "type": "object", + "required": false, + "description": "Optional. A standard FeeInfo object with type-specific fee control." + } + ] + }, + "WithdrawLegacyResponse": { + "data": [ + { + "parameter": "from", + "type": "array of strings", + "required": true, + "description": "Coins are withdrawn from this address." + }, + { + "parameter": "to", + "type": "array of strings", + "required": true, + "description": "Coins are withdrawn to this address." + }, + { + "parameter": "my_balance_change", + "type": "string (numeric)", + "required": true, + "description": "Expected balance change in my_address after broadcast." + }, + { + "parameter": "received_by_me", + "type": "string (numeric)", + "required": true, + "description": "Amount received by my_address after broadcast." + }, + { + "parameter": "spent_by_me", + "type": "string (numeric)", + "required": true, + "description": "Amount spent by my_address (includes fees)." + }, + { + "parameter": "total_amount", + "type": "string (numeric)", + "required": true, + "description": "Total amount transferred." + }, + { + "parameter": "fee_details", + "type": "object", + "required": true, + "description": "Fee details of the generated transaction." + }, + { + "parameter": "tx_hash", + "type": "string", + "required": true, + "description": "Hash of the generated transaction." + }, + { + "parameter": "tx_hex", + "type": "string", + "required": false, + "description": "Transaction bytes in hex; used by non-SIA protocols." + }, + { + "parameter": "tx_json", + "type": "object", + "required": false, + "description": "For SIA protocol coins only. The transaction JSON object." + }, + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "The coin of the transaction." + }, + { + "parameter": "kmd_rewards", + "type": "object", + "required": false, + "description": "Accrued rewards information (KMD only)." + } + ] + }, + "MyTxHistoryRequest": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "The name of the coin for the history request." + }, + { + "parameter": "limit", + "type": "number", + "required": false, + "description": "Limits number of returned transactions; ignored if max=true." + }, + { + "parameter": "max", + "type": "boolean", + "required": false, + "description": "Return all available records." + }, + { + "parameter": "from_id", + "type": "string", + "required": false, + "description": "Skip records until this internal_id (exclusive)." + }, + { + "parameter": "page_number", + "type": "number", + "required": false, + "description": "Page number to fetch; ignored if from_id is set." + } + ] + }, + "MyTxHistoryResponse": { + "data": [ + { + "parameter": "transactions", + "type": "array of objects", + "required": true, + "description": "List of transactions affecting this wallet." + }, + { + "parameter": "from_id", + "type": "string|null", + "required": true, + "description": "Echo of request from_id; null if not set." + }, + { + "parameter": "skipped", + "type": "number", + "required": true, + "description": "Number of skipped records." + }, + { + "parameter": "limit", + "type": "number", + "required": true, + "description": "Requested limit." + }, + { + "parameter": "total", + "type": "number", + "required": true, + "description": "Total number of transactions available." + }, + { + "parameter": "page_number", + "type": "number|null", + "required": true, + "description": "Requested page number; null if not used." + }, + { + "parameter": "total_pages", + "type": "number", + "required": true, + "description": "Total pages available with selected limit." + }, + { + "parameter": "current_block", + "type": "number", + "required": true, + "description": "Latest block number." + }, + { + "parameter": "sync_status", + "type": "object", + "required": true, + "description": "Standard SyncStatus object." + } + ] + }, + "ValidateAddressRequest": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "The coin to validate address for." + }, + { + "parameter": "address", + "type": "string", + "required": true, + "description": "The input string to validate." + } + ] + }, + "ValidateAddressResponse": { + "data": [ + { + "parameter": "is_valid", + "type": "bool", + "required": true, + "description": "Whether the input string is a valid coin address." + }, + { + "parameter": "reason", + "type": "string (optional)", + "required": false, + "description": "Only present if not valid. The reason why the input string is not a valid address." + } + ] + }, + "WithdrawLegacyErrors": { + "data": [ + { + "parameter": "NoSuchCoin", + "type": "string", + "required": false, + "description": "The selected coin was not found or is not activated yet." + }, + { + "parameter": "NotSufficientBalance", + "type": "string", + "required": false, + "description": "Insufficient balance to complete withdrawal." + }, + { + "parameter": "InvalidAddress|InvalidFeePolicy|InvalidFee", + "type": "string", + "required": false, + "description": "Invalid address or fee parameters." + }, + { + "parameter": "Timeout|InternalError", + "type": "string", + "required": false, + "description": "Operation timed out or internal error." + } + ] + }, + "ValidateAddressErrors": { + "data": [ + { + "parameter": "NoSuchCoin", + "type": "string", + "required": false, + "description": "The specified coin is not enabled." + }, + { + "parameter": "InvalidRequest", + "type": "string", + "required": false, + "description": "Malformed request or unsupported operation for this coin." + }, + { + "parameter": "InternalError", + "type": "string", + "required": false, + "description": "Unhandled internal error." + } + ] + }, + "SendRawTransactionErrors": { + "data": [ + { + "parameter": "NoSuchCoin", + "type": "string", + "required": false, + "description": "No such coin is enabled." + }, + { + "parameter": "InvalidHashError|HashNotExist|InvalidParam|DecodeError|NotImplemented", + "type": "string", + "required": false, + "description": "Invalid parameters, not found, or not supported for this protocol." + }, + { + "parameter": "Transport|InternalError|TransactionError", + "type": "string", + "required": false, + "description": "Transport or internal error." + } + ] + }, + "MyBalanceRequest": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "The ticker of the coin to query." + } + ] + }, + "MyBalanceResponse": { + "data": [ + { + "parameter": "address", + "type": "string", + "required": false, + "description": "Wallet address (for single-address coins)." + }, + { + "parameter": "balance", + "type": "object", + "required": true, + "description": "Summary of wallet balance fields." + } + ] + }, + "MyBalanceErrors": { + "data": [ + { + "parameter": "NoSuchCoin", + "type": "string", + "required": false, + "description": "The specified coin is not enabled." + }, + { + "parameter": "InternalError", + "type": "string", + "required": false, + "description": "Unhandled internal error." + } + ] + }, + "MyTxHistoryErrors": { + "data": [ + { + "parameter": "NoSuchCoin", + "type": "string", + "required": false, + "description": "The specified coin is not enabled." + }, + { + "parameter": "Transport|InternalError", + "type": "string", + "required": false, + "description": "Network or internal error occurred." + } + ] + } +} + diff --git a/src/data/tables/v2/coin_activation.json b/src/data/tables/v2/coin_activation.json index 75d2d5bc4..aed1085c8 100644 --- a/src/data/tables/v2/coin_activation.json +++ b/src/data/tables/v2/coin_activation.json @@ -17,7 +17,8 @@ "parameter": "mode", "type": "object", "required": true, - "description": "A standard [ActivationMode](/komodo-defi-framework/api/common_structures/activation/#activation-mode) object." + "description": "A standard [ActivationMode](/komodo-defi-framework/api/common_structures/activation/#activation-mode) object.", + "substructure": "activation.ActivationMode" }, { "parameter": "tx_history", @@ -36,7 +37,8 @@ "parameter": "address_format", "type": "object", "required": false, - "description": "Overwrites the address format from coins file, if set. A standard [AddressFormat](/komodo-defi-framework/api/common_structures/wallet/#address-format) object." + "description": "Overwrites the address format from coins file, if set. A standard [AddressFormat](/komodo-defi-framework/api/common_structures/wallet/#address-format) object.", + "substructure": "wallet.AddressFormat" }, { "parameter": "allow_slp_unsafe_conf", @@ -77,7 +79,8 @@ "parameter": "utxo_merge_params", "type": "object", "required": true, - "description": "A standard [UtxoMergeParams](/komodo-defi-framework/api/common_structures/activation/#utxo-merge-params) object. Used to reduce a wallet's UTXO count in cases where it is causing significantly slower RPC responses." + "description": "A standard [UtxoMergeParams](/komodo-defi-framework/api/common_structures/activation/#utxo-merge-params) object. Used to reduce a wallet's UTXO count in cases where it is causing significantly slower RPC responses.", + "substructure": "activation.UtxoMergeParams" } ] }, @@ -93,13 +96,15 @@ "parameter": "bch_addresses_infos", "type": "object", "required": true, - "description": "A standard [AddressInfo](/komodo-defi-framework/api/common_structures/wallet/#address-info) object. Note: the structure may vary based on the value of the `get_balances` parameter." + "description": "A standard [AddressInfo](/komodo-defi-framework/api/common_structures/wallet/#address-info) object. Note: the structure may vary based on the value of the `get_balances` parameter.", + "substructure": "wallet.AddressInfo" }, { "parameter": "slp_addresses_infos", "type": "object", "required": true, - "description": "A standard [AddressInfo](/komodo-defi-framework/api/common_structures/wallet/#address-info) object. Note: the structure may vary based on the value of the `get_balances` parameter." + "description": "A standard [AddressInfo](/komodo-defi-framework/api/common_structures/wallet/#address-info) object. Note: the structure may vary based on the value of the `get_balances` parameter.", + "substructure": "wallet.AddressInfo" } ] }, @@ -120,23 +125,6 @@ } ] }, - "EnableTendermintTokenArguments": { - "data": [ - { - "parameter": "ticker", - "type": "string", - "required": true, - "description": "Ticker of the Tendermint asset." - }, - { - "parameter": "activation_params.required_confirmations", - "type": "integer", - "required": false, - "default": "value in the coins file if not set", - "description": "Confirmations to wait for steps in swap." - } - ] - }, "EnableEthWithTokensArguments": { "data": [ { @@ -201,7 +189,8 @@ "type": "object", "required": false, "default": "`{\"type\": \"ContextPrivKey\"}`", - "description": "A standard [PrivKeyPolicy](/komodo-defi-framework/api/common_structures/wallet/#priv-key-policy) object." + "description": "A standard [PrivKeyPolicy](/komodo-defi-framework/api/common_structures/wallet/#priv-key-policy) object.", + "substructure": "wallet.PrivKeyPolicy" }, { "parameter": "required_confirmations", @@ -235,13 +224,15 @@ "parameter": "nft_req", "type": "object", "required": false, - "description": "Encapsulates the request parameters for NFT activation, including NFT provider configuration. A standard [NftProvider](/komodo-defi-framework/api/common_structures/nfts/#nft-provider) object." + "description": "Encapsulates the request parameters for NFT activation, including NFT provider configuration. A standard [NftProvider](/komodo-defi-framework/api/common_structures/nfts/#nft-provider) object.", + "substructure": "nfts.NftProvider" }, { "parameter": "swap_v2_contracts", "type": "object", "required": false, - "description": "Must be provided if \"use_trading_proto_v2\" is true in [your configuration](/komodo-defi-framework/setup/configure-mm2-json/). A standard [SwapV2Contracts](/komodo-defi-framework/api/common_structures/activation/#tokens-request) object." + "description": "Must be provided if \"use_trading_proto_v2\" is true in [your configuration](/komodo-defi-framework/setup/configure-mm2-json/). A standard [SwapV2Contracts](/komodo-defi-framework/api/common_structures/activation/#swap-v2-contracts) object.", + "substructure": "activation.SwapV2Contracts" } ] }, @@ -257,19 +248,39 @@ "parameter": "eth_addresses_infos", "type": "object", "required": true, - "description": "A standard [AddressInfo](/komodo-defi-framework/api/common_structures/wallet/#address-info) object. Note: the structure may vary based on the value of the `get_balances` parameter." + "description": "A standard [AddressInfo](/komodo-defi-framework/api/common_structures/wallet/#address-info) object. Note: the structure may vary based on the value of the `get_balances` parameter.", + "substructure": "wallet.AddressInfo" }, { "parameter": "erc20_addresses_infos", "type": "object", "required": true, - "description": "A standard [AddressInfo](/komodo-defi-framework/api/common_structures/wallet/#address-info) object. Note: the structure may vary based on the value of the `get_balances` parameter." + "description": "A standard [AddressInfo](/komodo-defi-framework/api/common_structures/wallet/#address-info) object. Note: the structure may vary based on the value of the `get_balances` parameter.", + "substructure": "wallet.AddressInfo" }, { "parameter": "nfts_infos", "type": "list", "required": true, - "description": "A list of standard [NftInfoBasic](/komodo-defi-framework/api/common_structures/nfts/#nft-info) objects." + "description": "A list of standard [NftInfoBasic](/komodo-defi-framework/api/common_structures/nfts/#nft-info) objects.", + "substructure": "nfts.NftInfoBasic" + } + ] + }, + "EnableTendermintTokenArguments": { + "data": [ + { + "parameter": "ticker", + "type": "string", + "required": true, + "description": "Ticker of the Tendermint asset." + }, + { + "parameter": "activation_params.required_confirmations", + "type": "integer", + "required": false, + "default": "value in the coins file if not set", + "description": "Confirmations to wait for steps in swap." } ] }, @@ -335,10 +346,12 @@ "description": "If `false`, coin and token balances will not be returned in the response, and the response will be returned more quickly." }, { - "parameter": "activation_params", + "parameter": "activation_params.priv_key_policy", "type": "object", "required": false, - "description": "Only used with Metamask, Keplr or WalletConnect activations. Defines the [PrivKeyPolicy](/komodo-defi-framework/api/common_structures/wallet/#priv-key-policy) of the connection." + "context": ["Metamask", "Keplr", "WalletConnect"], + "description": "Only used with Metamask, Keplr or WalletConnect activations. A standard [PrivKeyPolicy](/komodo-defi-framework/api/common_structures/wallet/#priv-key-policy) object.", + "substructure": "wallet.PrivKeyPolicy" } ] }, @@ -382,6 +395,250 @@ } ] }, + "EnableEthWithTokensErrorTypes": { + "data": [ + { + "parameter": "PlatformIsAlreadyActivated", + "type": "string", + "required": false, + "description": "The platform coin you are trying to activate is already activated" + }, + { + "parameter": "PlatformConfigIsNotFound", + "type": "string", + "required": false, + "description": "Config of the platform coin you are trying to activate is not found" + }, + { + "parameter": "CoinProtocolParseError", + "type": "string", + "required": false, + "description": "Parsing the protocol of the platform coin you are trying to activate failed" + }, + { + "parameter": "UnexpectedPlatformProtocol", + "type": "string", + "required": false, + "description": "Unexpected platform protocol found for the platform coin you are trying to activate" + }, + { + "parameter": "TokenConfigIsNotFound", + "type": "string", + "required": false, + "description": "Config of the token you are trying to activate is not found" + }, + { + "parameter": "TokenProtocolParseError", + "type": "string", + "required": false, + "description": "Parsing the protocol of the token you are trying to activate failed" + }, + { + "parameter": "Transport", + "type": "string", + "required": false, + "description": "The request failed due to a network error (e.g., node unresponsive)" + }, + { + "parameter": "InvalidRequest", + "type": "string", + "required": false, + "description": "The request is malformed or uses an unsupported configuration for the current build" + } + ] + }, + "EnableErc20ErrorTypes": { + "data": [ + { + "parameter": "PlatformCoinIsNotActivated", + "type": "string", + "required": false, + "description": "The platform coin is not activated" + }, + { + "parameter": "TokenIsAlreadyActivated", + "type": "string", + "required": false, + "description": "The token is already activated" + }, + { + "parameter": "TokenConfigIsNotFound", + "type": "string", + "required": false, + "description": "Token config is not found in coins file" + } + ] + }, + + "EnableBchWithTokensErrorTypes": { + "data": [ + { + "parameter": "PlatformIsAlreadyActivated", + "type": "string", + "required": false, + "description": "The platform coin is already activated" + }, + { + "parameter": "PlatformConfigIsNotFound", + "type": "string", + "required": false, + "description": "Config of the platform coin is not found" + }, + { + "parameter": "UnexpectedPlatformProtocol", + "type": "string", + "required": false, + "description": "Unexpected platform protocol found for the platform coin" + }, + { + "parameter": "UnexpectedTokenProtocol", + "type": "string", + "required": false, + "description": "Unexpected protocol found in the token config" + }, + { + "parameter": "PlatformCoinCreationError", + "type": "string", + "required": false, + "description": "There was an error when trying to activate the platform coin" + } + ] + }, + "TaskCancelArguments": { + "data": [ + { + "parameter": "task_id", + "type": "integer", + "required": true, + "description": "The identifying number returned when initiating the enabling process." + } + ] + }, + "TaskCancelResponse": { + "data": [ + { + "parameter": "result", + "type": "string", + "required": true, + "description": "Indicates task cancellation was succesful." + }, + { + "parameter": "error", + "type": "string", + "required": true, + "description": "An error message to explain what went wrong." + }, + { + "parameter": "error_path", + "type": "string", + "required": true, + "description": "An indicator of the class or function which reurned the error." + }, + { + "parameter": "error_trace", + "type": "string", + "required": true, + "description": "An indicator of where in the source code the error was thrown." + }, + { + "parameter": "error_type", + "type": "string", + "required": true, + "description": "An enumerated value for the returned error." + }, + { + "parameter": "error_data", + "type": "string", + "required": true, + "description": "The input task ID which resulted in the error." + } + ] + }, + "TaskEnableBchArguments": { + "data": [ + { + "parameter": "ticker", + "type": "string", + "required": true, + "description": "Ticker of the platform protocol coin. Options: `BCH` or `tBCH`" + }, + { + "parameter": "bchd_urls", + "type": "array of strings", + "required": true, + "description": "A list of BCHD gRPC API server URLs, used for validation of SLP token transactions. It's recommended to add as many servers as possible. The URLs list can be found at [https://bchd.fountainhead.cash/](https://bchd.fountainhead.cash/)." + }, + { + "parameter": "mode", + "type": "object", + "required": true, + "description": "A standard [ActivationMode](/komodo-defi-framework/api/common_structures/activation/#activation-mode) object.", + "substructure": "activation.ActivationMode" + }, + { + "parameter": "tx_history", + "type": "boolean", + "required": false, + "default": "`false`", + "description": "If `true`, spawns a background loop to store the local cache of address(es) transactions." + }, + { + "parameter": "slp_tokens_requests", + "type": "array of objects", + "required": true, + "description": "A list of standard [TokensRequest](/komodo-defi-framework/api/common_structures/activation/#tokens-request) objects." + }, + { + "parameter": "address_format", + "type": "object", + "required": false, + "description": "Overwrites the address format from coins file, if set. A standard [AddressFormat](/komodo-defi-framework/api/common_structures/wallet/#address-format) object.", + "substructure": "wallet.AddressFormat" + }, + { + "parameter": "allow_slp_unsafe_conf", + "type": "boolean", + "required": false, + "default": "`false`", + "description": "If `true`, allows bchd_urls to be empty. **Warning:** it is highly unsafe to do so as it may lead to invalid SLP transactions generation and tokens burning." + }, + { + "parameter": "get_balances", + "type": "boolean", + "required": false, + "default": "`true`", + "description": "If `false`, coin and token balances will not be returned in the response, and the response will be returned more quickly." + }, + { + "parameter": "required_confirmations", + "type": "integer", + "required": false, + "default": "value in the coins file, or `3` if not set", + "description": "Confirmations to wait for steps in swap." + }, + { + "parameter": "requires_notarization", + "type": "boolean", + "required": false, + "default": "`true`", + "description": "Has no effect on BCH." + }, + { + "parameter": "tx_history", + "type": "boolean", + "required": false, + "default": "`true`", + "description": "If `true` the Komodo DeFi Framework API will preload transaction history as a background process. Must be set to `true` to use the [my_tx_history](/komodo-defi-framework/api/legacy/my_tx_history/#my-tx-history) method" + }, + { + "parameter": "utxo_merge_params", + "type": "object", + "required": true, + "description": "A standard [UtxoMergeParams](/komodo-defi-framework/api/common_structures/activation/#utxo-merge-params) object. Used to reduce a wallet's UTXO count in cases where it is causing significantly slower RPC responses.", + "substructure": "activation.UtxoMergeParams" + } + ] + }, "TaskEnableEthArguments": { "data": [ { @@ -486,7 +743,8 @@ "parameter": "nft_req", "type": "object", "required": false, - "description": "Non-HD only. encapsulates the request parameters for NFT activation, including NFT provider configuration." + "description": "Non-HD only. Encapsulates the request parameters for NFT activation, including NFT provider configuration. A standard [NftProvider](/komodo-defi-framework/api/common_structures/nfts/#nft-provider) object.", + "substructure": "nfts.NftProvider" }, { "parameter": "min_addresses_number", @@ -510,27 +768,132 @@ "parameter": "path_to_address", "type": "object", "required": false, - "description": "HD wallets only. A standard [AddressPath](/komodo-defi-framework/api/common_structures/wallet/#address-path) object." + "description": "HD wallets only. A standard [AddressPath](/komodo-defi-framework/api/common_structures/wallet/#address-path) object.", + "substructure": "wallet.AddressPath" }, { "parameter": "swap_v2_contracts", "type": "object", "required": false, - "description": "Must be provided if \"use_trading_proto_v2\" is true in [your configuration](/komodo-defi-framework/setup/configure-mm2-json/). A standard [SwapV2Contracts](/komodo-defi-framework/api/common_structures/activation/#tokens-request) object." + "description": "Must be provided if \"use_trading_proto_v2\" is true in [your configuration](/komodo-defi-framework/setup/configure-mm2-json/). A standard [SwapV2Contracts](/komodo-defi-framework/api/common_structures/activation/#swap-v2-contracts) object.", + "substructure": "activation.SwapV2Contracts" } ] }, - "TaskResponse": { + "TaskEnableQtumArguments": { "data": [ { - "parameter": "task_id", - "type": "integer", + "parameter": "ticker", + "type": "string", "required": true, - "description": "An identifying number which is used to query task status." + "description": "The ticker of the coin you want to enable." + }, + { + "parameter": "activation_params", + "type": "object", + "required": true, + "description": "An object containing the activation parameters below. A standard [ActivationParams](/komodo-defi-framework/api/common_structures/activation/#activation-params) object.", + "substructure": "activation.ActivationParams" + }, + { + "parameter": "activation_params.mode", + "type": "object", + "required": true, + "description": "Activation mode configuration. A standard [ActivationMode](/komodo-defi-framework/api/common_structures/activation/#activation-mode) object.", + "substructure": "activation.ActivationMode" } ] }, - "TaskStatusArguments": { + "TaskEnableTendermintArguments": { + "data": [ + { + "parameter": "ticker", + "type": "string", + "required": true, + "description": "Ticker of the platform protocol coin. Options: `ATOM`, `IRIS`, `OSMOSIS`" + }, + { + "parameter": "mm2", + "type": "integer", + "required": false, + "description": "Required if not set in `coins` file. Informs the Komodo DeFi Framework API whether or not the coin is expected to function. Accepted values are `0` or `1`" + }, + { + "parameter": "tokens_params", + "type": "array of objects", + "required": true, + "description": "A list of standard [TokensRequest](/komodo-defi-framework/api/common_structures/activation/#tokens-request) objects." + }, + { + "parameter": "nodes", + "type": "array of objects", + "required": true, + "description": "A list of [CoinNode objects](/komodo-defi-framework/api/common_structures/activation/#coin-node)." + }, + { + "parameter": "priv_key_policy", + "type": "string", + "required": false, + "default": "`ContextPrivKey`", + "description": "Value can be `ContextPrivKey`,`Trezor` when Komodo DeFi Framework is built for native platforms. value can be `ContextPrivKey`, `Trezor`, `Metamask` when the Komodo DeFi Framework is built targeting `wasm`" + }, + { + "parameter": "tx_history", + "type": "boolean", + "required": false, + "default": "`false`", + "description": "If `true` the Komodo DeFi Framework API will preload transaction history as a background process. Must be set to `true` to use the [my_tx_history](/komodo-defi-framework/api/legacy/my_tx_history/#my-tx-history) method" + }, + { + "parameter": "required_confirmations", + "type": "integer", + "required": false, + "default": "`3`", + "description": "When the platform coin is involved, the number of confirmations for the Komodo DeFi Framework API to wait during the transaction steps of an atomic swap" + }, + { + "parameter": "requires_notarization", + "type": "boolean", + "required": false, + "default": "`false`", + "description": "If `true`, coins protected by [Komodo Platform's dPoW security](https://satindergrewal.medium.com/delayed-proof-of-work-explained-9a74250dbb86) will wait for a notarization before progressing to the next atomic swap transactions step." + }, + { + "parameter": "get_balances", + "type": "boolean", + "required": false, + "default": "`true`", + "description": "If `false`, coin and token balances will not be returned in the response, and the response will be returned more quickly." + } + ] + }, + "TaskEnableZCoinArguments": { + "data": [ + { + "parameter": "ticker", + "type": "string", + "required": true, + "description": "Ticker of coin to activate" + }, + { + "parameter": "activation_params", + "type": "object", + "required": true, + "description": "A standard [ActivationRpcData](/komodo-defi-framework/api/common_structures/activation/#activation-rpc-data) object." + } + ] + }, + "TaskResponse": { + "data": [ + { + "parameter": "task_id", + "type": "integer", + "required": true, + "description": "An identifying number which is used to query task status." + } + ] + }, + "TaskStatusArguments": { "data": [ { "parameter": "task_id", @@ -547,452 +910,665 @@ } ] }, - "TaskUserActionArguments": { + "TaskStatusErrorResponse": { "data": [ { - "parameter": "task_id", - "type": "integer", + "parameter": "status", + "type": "string", "required": true, - "description": "The identifying number returned when initiating the initialisation process." + "description": "A short indication of how the requested process is progressing." }, { - "parameter": "user_action", + "parameter": "details.result", "type": "object", "required": true, - "description": "Object containing the params below" - }, + "description": "Depending on the state of process progress, this will contain different information as detailed in the items below." + } + ] + }, + "TaskStatusInProgress": { + "data": [ { - "parameter": "user_action.action_type", + "parameter": "status", "type": "string", "required": true, - "description": "Will be `TrezorPin` for this method" + "description": "Will return `InProgress` if task is not yet comepleted" }, { - "parameter": "user_action.pin", - "type": "string (number)", + "parameter": "details", + "type": "string", "required": true, - "description": "When the Trezor device is displaying a grid of numbers for PIN entry, this param will contain your Trezor pin, as mapped through your keyboard numpad. See the image below for more information." + "description": "An indication of the current step of the activation process" } ] }, - "TaskUserActionResponse": { + "TaskStatusResponse": { "data": [ { - "parameter": "result", + "parameter": "status", "type": "string", "required": true, - "description": "The outcome of the request." + "description": "A short indication of how the enabling is progressing." + }, + { + "parameter": "details", + "type": "object", + "required": true, + "description": "Depending on the state of enabling progress, this will contain different information as shown in the responses below." } ] }, - "TaskCancelArguments": { + "TaskStatusResponseReady": { "data": [ { - "parameter": "task_id", + "parameter": "current_block", "type": "integer", "required": true, - "description": "The identifying number returned when initiating the enabling process." + "description": "Block height of the coin being activated" + }, + { + "parameter": "ticker", + "type": "string", + "required": true, + "description": "Ticker of the coin being activated." + }, + { + "parameter": "wallet_balance", + "type": "object", + "required": true, + "description": "A standard [WalletBalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#wallet-balance-info) object. Note: the structure may vary based on the `get_balances` parameter value in the activation request." } ] }, - "TaskCancelResponse": { + "TaskStatusTendermintResponse": { "data": [ { - "parameter": "result", - "type": "string", + "parameter": "current_block", + "type": "integer", "required": true, - "description": "Indicates task cancellation was succesful." + "description": "Block height of the coin being activated" }, { - "parameter": "error", + "parameter": "ticker", "type": "string", "required": true, - "description": "An error message to explain what went wrong." + "description": "Ticker of the platform protocol coin, as input in the request." }, { - "parameter": "error_path", + "parameter": "address", "type": "string", "required": true, - "description": "An indicator of the class or function which reurned the error." + "description": "An address for the activated coin" }, { - "parameter": "error_trace", - "type": "string", + "parameter": "balance", + "type": "object", + "required": false, + "description": "Only returned when `get_balances` is `true`. A standard [BalanceInfos](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object." + }, + { + "parameter": "tokens_balances", + "type": "array of objects", + "required": false, + "description": "Only returned when `get_balances` is `true`. A list of standard [AddressInfo](/komodo-defi-framework/api/common_structures/wallet/#address-info) objects, one for each token." + }, + { + "parameter": "tokens_tickers", + "type": "array", + "required": false, + "description": "Only returned when `get_balances` is `false`. A list of each token which was activated." + } + ] + }, + "TaskUserActionArguments": { + "data": [ + { + "parameter": "task_id", + "type": "integer", "required": true, - "description": "An indicator of where in the source code the error was thrown." + "description": "The identifying number returned when initiating the initialisation process." }, { - "parameter": "error_type", + "parameter": "user_action", + "type": "object", + "required": true, + "description": "Object containing the params below" + }, + { + "parameter": "user_action.action_type", "type": "string", "required": true, - "description": "An enumerated value for the returned error." + "description": "Will be `TrezorPin` or `TrezorPassphrase`." }, { - "parameter": "error_data", + "parameter": "user_action.pin", + "type": "string (number)", + "required": true, + "description": "When the Trezor device is displaying a grid of numbers for PIN entry, this param will contain your Trezor pin, as mapped through your keyboard numpad. See the image below for more information." + }, + { + "parameter": "user_action.passphrase", "type": "string", "required": true, - "description": "The input task ID which resulted in the error." + "description": "Your Trezor passphrase. This is the passphrase you use to unlock a hidden wallet on your Trezor device. Can be empty if you are using a non-hidden wallet." } ] }, - "TaskEnableQtumArguments": { + "TaskUserActionResponse": { + "data": [ + { + "parameter": "result", + "type": "string", + "required": true, + "description": "The outcome of the request." + } + ] + }, + "EnableSiaRequest": { "data": [ { "parameter": "ticker", "type": "string", "required": true, - "description": "The ticker of the coin you want to enable." + "description": "Ticker of the Sia coin to enable (e.g., \"SIA\")." }, { "parameter": "activation_params", "type": "object", "required": true, - "description": "An object containing the actvation parameters below." + "description": "Activation parameters specific to Sia.", + "substructure": "activation.EnableSiaActivationParams" + } + ] + }, + "EnableSiaActivationParams": { + "data": [ + { + "parameter": "tx_history", + "type": "boolean", + "required": false, + "description": "Whether to start background tx history sync." }, { - "parameter": ".priv_key_policy", - "type": "object", + "parameter": "required_confirmations", + "type": "integer", "required": false, - "default": "`{\"type\": \"ContextPrivKey\"}`", - "description": "A standard [PrivKeyPolicy](/komodo-defi-framework/api/common_structures/wallet/#priv-key-policy) object." + "description": "Override required confirmations; default from coins config." }, { - "parameter": ".min_addresses_number", + "parameter": "gap_limit", "type": "integer", - "required": true, - "description": "How many additional addreesses to generate at a minimum." + "required": false, + "description": "Gap limit for HD scanning (reserved; Sia currently uses iguana single-address)." }, { - "parameter": ".scan_policy", - "type": "string", + "parameter": "client_conf", + "type": "object", "required": true, - "description": "Whether or not to scan for new addresses. Select from `do_not_scan`, `scan_if_new_wallet` or `scan`. Note that `scan` will result in multple requests to the Komodo DeFi Framework." - }, + "description": "Sia client configuration.", + "substructure": "activation.EnableSiaClientConf" + } + ] + }, + "EnableSiaClientConf": { + "data": [ { - "parameter": ".gap_limit", - "type": "integer", + "parameter": "server_url", + "type": "string", "required": true, - "description": "The max number of empty addresses in a row. If transactions were sent to an address outside the `gap_limit`, they will not be identified when scanning." + "description": "Base URL of the Sia provider (walletd/indexer)." }, { - "parameter": ".mode", + "parameter": "headers", "type": "object", + "required": false, + "description": "Optional HTTP headers to include on requests." + } + ] + }, + "EnableSiaResponse": { + "data": [ + { + "parameter": "task_id", + "type": "integer", "required": true, - "description": "An object containing RPC type and data parameters as below." + "description": "Task identifier to track activation progress." + } + ] + }, + "EnableSiaErrors": { + "data": [ + { + "parameter": "TaskTimedOut", + "type": "string", + "required": false, + "description": "Initialization task timed out." }, { - "parameter": "..rpc", + "parameter": "CoinIsAlreadyActivated", "type": "string", - "required": true, - "description": "UTXO RPC mode. Options: `{ \"rpc\":\"Native\" }` if running a native blockchain node, or `\"rpc\":\"Electrum\"` to use electrum RPCs. If using electrum, a list of electrum servers is required under `rpc_data.servers`" + "required": false, + "description": "Coin is activated already." }, { - "parameter": "..rpc_data", - "type": "object", - "required": true, - "description": "An object containing electrum server information." + "parameter": "CoinConfigIsNotFound", + "type": "string", + "required": false, + "description": "Coin config is not found in the coins file." }, { - "parameter": "...servers", - "type": "list", - "required": true, - "description": "A list of electrum server URLs ([https://github.com/KomodoPlatform/coins/tree/master/electrums](https://github.com/KomodoPlatform/coins/tree/master/electrums))" + "parameter": "CoinProtocolParseError", + "type": "string", + "required": false, + "description": "Coin protocol parsing failed." }, { - "parameter": "....url", - "type": "object", - "required": true, - "description": "The url and port of a coins electrum server" + "parameter": "UnexpectedCoinProtocol", + "type": "string", + "required": false, + "description": "Unexpected protocol for the coin." }, { - "parameter": "....ws_url", - "type": "object", + "parameter": "CoinCreationError", + "type": "string", "required": false, - "description": "Used to define electrum server url/port for websocket connections." + "description": "Error on coin creation." }, { - "parameter": "....protocol", - "type": "object", + "parameter": "Transport", + "type": "string", "required": false, - "default": "`TCP`", - "description": "Defines electrum server protocol as `TCP` or `SSL`." + "description": "Transport-related error from underlying client." }, { - "parameter": "....disable_cert_verification", - "type": "boolean", + "parameter": "Internal", + "type": "string", "required": false, - "description": "For `SSL` electrum connections, this will allow expired certificates." + "description": "Internal server error." } ] }, - "TaskEnableBchArguments": { + "EnableSiaInitRequest": { + "data": [ + { + "parameter": "client_id", + "type": "integer", + "required": false, + "description": "Client identifier to receive streaming status updates." + }, + { + "parameter": "ticker", + "type": "string", + "required": true, + "description": "Ticker of the Sia coin to enable." + }, + { + "parameter": "activation_params", + "type": "object", + "required": true, + "description": "Activation parameters; see EnableSiaActivationParams." + } + ] + }, + "EnableSiaInitResponse": { + "data": [ + { + "parameter": "task_id", + "type": "integer", + "required": true, + "description": "Task identifier to track activation progress." + } + ] + }, + "EnableSiaInitErrors": { "data": [ { - "parameter": "ticker", + "parameter": "CoinIsAlreadyActivated", "type": "string", - "required": true, - "description": "Ticker of the platform protocol coin. Options: `BCH` or `tBCH`" + "required": false, + "description": "Coin is activated already." }, { - "parameter": "bchd_urls", - "type": "array of strings", - "required": true, - "description": "A list of BCHD gRPC API server URLs, used for validation of SLP token transactions. It's recommended to add as many servers as possible. The URLs list can be found at [https://bchd.fountainhead.cash/](https://bchd.fountainhead.cash/)." + "parameter": "CoinConfigIsNotFound", + "type": "string", + "required": false, + "description": "Coin config is not found in the coins file." }, { - "parameter": "mode", - "type": "object", - "required": true, - "description": "A standard [ActivationMode](/komodo-defi-framework/api/common_structures/activation/#activation-mode) object." + "parameter": "CoinProtocolParseError", + "type": "string", + "required": false, + "description": "Coin protocol parsing failed." }, { - "parameter": "tx_history", - "type": "boolean", + "parameter": "UnexpectedCoinProtocol", + "type": "string", "required": false, - "default": "`false`", - "description": "If `true`, spawns a background loop to store the local cache of address(es) transactions." + "description": "Unexpected coin protocol." }, { - "parameter": "slp_tokens_requests", - "type": "array of objects", - "required": true, - "description": "A list of standard [TokensRequest](/komodo-defi-framework/api/common_structures/activation/#tokens-request) objects." + "parameter": "CoinCreationError", + "type": "string", + "required": false, + "description": "Error on coin creation (details in message)." }, { - "parameter": "address_format", - "type": "object", + "parameter": "TaskTimedOut", + "type": "string", "required": false, - "description": "Overwrites the address format from coins file, if set. A standard [AddressFormat](/komodo-defi-framework/api/common_structures/wallet/#address-format) object." + "description": "Initialization task timed out." }, { - "parameter": "allow_slp_unsafe_conf", - "type": "boolean", + "parameter": "Transport", + "type": "string", "required": false, - "default": "`false`", - "description": "If `true`, allows bchd_urls to be empty. **Warning:** it is highly unsafe to do so as it may lead to invalid SLP transactions generation and tokens burning." + "description": "Transport-related error from underlying client." }, { - "parameter": "get_balances", - "type": "boolean", + "parameter": "Internal", + "type": "string", "required": false, - "default": "`true`", - "description": "If `false`, coin and token balances will not be returned in the response, and the response will be returned more quickly." - }, + "description": "Internal server error." + } + ] + }, + "EnableSiaStatusRequest": { + "data": [ { - "parameter": "required_confirmations", + "parameter": "task_id", "type": "integer", - "required": false, - "default": "value in the coins file, or `3` if not set", - "description": "Confirmations to wait for steps in swap." + "required": true, + "description": "Task identifier returned by enable_sia/init." }, { - "parameter": "requires_notarization", + "parameter": "forget_if_finished", "type": "boolean", "required": false, - "default": "`true`", - "description": "Has no effect on BCH." - }, + "description": "If true, the task is removed from memory if finished." + } + ] + }, + "EnableSiaStatusResponse": { + "data": [ { - "parameter": "tx_history", - "type": "boolean", - "required": false, - "default": "`true`", - "description": "If `true` the Komodo DeFi Framework API will preload transaction history as a background process. Must be set to `true` to use the [my_tx_history](/komodo-defi-framework/api/legacy/my_tx_history/#my-tx-history) method" + "parameter": "status", + "type": "string", + "required": true, + "description": "Current status of activation." }, { - "parameter": "utxo_merge_params", + "parameter": "details", "type": "object", "required": true, - "description": "A standard [UtxoMergeParams](/komodo-defi-framework/api/common_structures/activation/#utxo-merge-params) object. Used to reduce a wallet's UTXO count in cases where it is causing significantly slower RPC responses." + "description": "Details object depends on status: Ok (ActivationResult), Error (InitStandaloneCoinError), InProgress (SiaCoinInProgressStatus), UserActionRequired (SiaCoinAwaitingStatus)." } ] }, - "TaskEnableTendermintArguments": { + "EnableSiaStatusErrors": { "data": [ { - "parameter": "ticker", + "parameter": "NoSuchTask", "type": "string", - "required": true, - "description": "Ticker of the platform protocol coin. Options: `ATOM`, `IRIS`, `OSMOSIS`" + "required": false, + "description": "No such task for provided task_id." }, { - "parameter": "mm2", - "type": "integer", + "parameter": "Internal", + "type": "string", "required": false, - "description": "Required if not set in `coins` file. Informs the Komodo DeFi Framework API whether or not the coin is expected to function. Accepted values are `0` or `1`" - }, + "description": "Internal server error while reading task status." + } + ] + }, + "EnableSiaActivationResult": { + "data": [ { - "parameter": "tokens_params", - "type": "array of objects", + "parameter": "ticker", + "type": "string", "required": true, - "description": "A list of standard [TokensRequest](/komodo-defi-framework/api/common_structures/activation/#tokens-request) objects." + "description": "Ticker of the enabled coin." }, { - "parameter": "nodes", - "type": "array of objects", + "parameter": "current_block", + "type": "integer", "required": true, - "description": "A list of [CoinNode objects](/komodo-defi-framework/api/common_structures/activation/#coin-node)." + "description": "Current block height." }, { - "parameter": "priv_key_policy", + "parameter": "wallet_balance", + "type": "object", + "required": true, + "description": "Wallet balance report (Iguana)." + } + ] + }, + "EnableSiaInProgressStatus": { + "data": [ + { + "parameter": "ActivatingCoin", "type": "string", "required": false, - "default": "`ContextPrivKey`", - "description": "Value can be `ContextPrivKey`,`Trezor` when Komodo DeFi Framework is built for native platforms. value can be `ContextPrivKey`, `Trezor`, `Metamask` when the Komodo DeFi Framework is built targeting `wasm`" + "description": "Activation has started." }, { - "parameter": "tx_history", - "type": "boolean", + "parameter": "RequestingWalletBalance", + "type": "string", "required": false, - "default": "`false`", - "description": "If `true` the Komodo DeFi Framework API will preload transaction history as a background process. Must be set to `true` to use the [my_tx_history](/komodo-defi-framework/api/legacy/my_tx_history/#my-tx-history) method" + "description": "Requesting wallet balance." }, { - "parameter": "required_confirmations", - "type": "integer", + "parameter": "Finishing", + "type": "string", "required": false, - "default": "`3`", - "description": "When the platform coin is involved, the number of confirmations for the Komodo DeFi Framework API to wait during the transaction steps of an atomic swap" - }, + "description": "Finishing activation." + } + ] + }, + "EnableSiaUserActionRequest": { + "data": [ { - "parameter": "requires_notarization", - "type": "boolean", - "required": false, - "default": "`false`", - "description": "If `true`, coins protected by [Komodo Platform's dPoW security](https://satindergrewal.medium.com/delayed-proof-of-work-explained-9a74250dbb86) will wait for a notarization before progressing to the next atomic swap transactions step." + "parameter": "task_id", + "type": "integer", + "required": true, + "description": "Task identifier returned by enable_sia/init." }, { - "parameter": "get_balances", - "type": "boolean", - "required": false, - "default": "`true`", - "description": "If `false`, coin and token balances will not be returned in the response, and the response will be returned more quickly." + "parameter": "user_action", + "type": "object", + "required": true, + "description": "User action payload (reserved; not used for Sia as hardware wallets are not supported yet)." } ] }, - "TaskEnableZCoinArguments": { + "EnableSiaUserActionResponse": { "data": [ { - "parameter": "ticker", + "parameter": "result", "type": "string", "required": true, - "description": "Ticker of coin to activate" + "description": "Indicates success." + } + ] + }, + "EnableSiaUserActionErrors": { + "data": [ + { + "parameter": "NoSuchTask", + "type": "string", + "required": false, + "description": "No such task for provided task_id." }, { - "parameter": "activation_params", - "type": "object", + "parameter": "Internal", + "type": "string", + "required": false, + "description": "Internal server error while sending user action." + } + ] + }, + "EnableSiaCancelRequest": { + "data": [ + { + "parameter": "task_id", + "type": "integer", "required": true, - "description": "A standard [ActivationRpcData](/komodo-defi-framework/api/common_structures/activation/#activation-rpc-data) object." + "description": "Task identifier returned by enable_sia/init." } ] }, - "TaskStatusResponse": { + "EnableSiaCancelResponse": { "data": [ { - "parameter": "status", + "parameter": "result", "type": "string", "required": true, - "description": "A short indication of how the enabling is progressing." + "description": "Indicates success." + } + ] + }, + "EnableSiaCancelErrors": { + "data": [ + { + "parameter": "NoSuchTask", + "type": "string", + "required": false, + "description": "No such task for provided task_id." }, { - "parameter": "details", - "type": "object", - "required": true, - "description": "Depending on the state of enabling progress, this will contain different information as shown in the responses below." + "parameter": "TaskFinished", + "type": "string", + "required": false, + "description": "Task already finished and cannot be cancelled." + }, + { + "parameter": "Internal", + "type": "string", + "required": false, + "description": "Internal server error while cancelling task." } ] }, - "TaskStatusResponseReady": { + "EnableErc20Response": { "data": [ { "parameter": "current_block", "type": "integer", "required": true, - "description": "Block height of the coin being activated" + "description": "Block height of the platform coin being activated" }, { "parameter": "ticker", "type": "string", "required": true, - "description": "Ticker of the coin being activated." + "description": "Ticker of the ERC20 token platform (e.g., ETH)." + } + ] + }, + "EnableTendermintTokenErrors": { + "data": [ + { + "parameter": "InvalidRequest", + "type": "string", + "required": false, + "description": "The request is malformed or contains unsupported parameters." }, { - "parameter": "wallet_balance", - "type": "object", - "required": true, - "description": "A standard [WalletBalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#wallet-balance-info) object. Note: the structure may vary based on the `get_balances` parameter value in the activation request." + "parameter": "NoSuchCoin", + "type": "string", + "required": false, + "description": "Platform coin not activated or not found." } ] }, - "TaskStatusTendermintResponse": { + "EnableTendermintWithAssetsErrors": { "data": [ { - "parameter": "current_block", - "type": "integer", - "required": true, - "description": "Block height of the coin being activated" + "parameter": "InvalidRequest", + "type": "string", + "required": false, + "description": "The request is malformed or contains unsupported parameters." }, { - "parameter": "ticker", + "parameter": "NoSuchCoin", "type": "string", - "required": true, - "description": "Ticker of the platform protocol coin, as input in the request." + "required": false, + "description": "Platform coin not activated or not found." + } + ] + }, + "TaskCancelErrors": { + "data": [ + { + "parameter": "NoSuchTask", + "type": "string", + "required": false, + "description": "No such task for provided task_id." }, { - "parameter": "address", + "parameter": "TaskFinished", "type": "string", - "required": true, - "description": "An address for the activated coin" + "required": false, + "description": "Task already finished and cannot be cancelled." }, { - "parameter": "balance", - "type": "object", + "parameter": "Internal", + "type": "string", "required": false, - "description": "Only returned when `get_balances` is `true`. A standard [BalanceInfos](/komodo-defi-framework/api/common_structures/wallet/#balance-info) object." + "description": "Internal server error while cancelling task." + } + ] + }, + "TaskInitErrors": { + "data": [ + { + "parameter": "CoinConfigIsNotFound|CoinCreationError", + "type": "string", + "required": false, + "description": "Activation failed due to invalid or missing configuration." }, { - "parameter": "tokens_balances", - "type": "array of objects", + "parameter": "TaskTimedOut", + "type": "string", "required": false, - "description": "Only returned when `get_balances` is `true`. A list of standard [AddressInfo](/komodo-defi-framework/api/common_structures/wallet/#address-info) objects, one for each token." + "description": "Initialization task timed out." }, { - "parameter": "tokens_tickers", - "type": "array", + "parameter": "Internal", + "type": "string", "required": false, - "description": "Only returned when `get_balances` is `false`. A list of each token which was activated." + "description": "Internal server error." } ] }, - "TaskStatusInProgress": { + "TaskStatusErrors": { "data": [ { - "parameter": "status", + "parameter": "NoSuchTask", "type": "string", - "required": true, - "description": "Will return `InProgress` if task is not yet comepleted" + "required": false, + "description": "No such task for provided task_id." }, { - "parameter": "details", + "parameter": "Internal", "type": "string", - "required": true, - "description": "An indication of the current step of the activation process" + "required": false, + "description": "Internal server error while reading task status." } ] }, - "TaskStatusErrorResponse": { + "TaskUserActionErrors": { "data": [ { - "parameter": "status", + "parameter": "NoSuchTask", "type": "string", - "required": true, - "description": "A short indication of how the requested process is progressing." + "required": false, + "description": "No such task for provided task_id." }, { - "parameter": "details.result", - "type": "object", - "required": true, - "description": "Depending on the state of process progress, this will contain different information as detailed in the items below." + "parameter": "Internal", + "type": "string", + "required": false, + "description": "Internal server error while sending user action." } ] } diff --git a/src/data/tables/v2/streaming.json b/src/data/tables/v2/streaming.json index a72c93757..70d344978 100644 --- a/src/data/tables/v2/streaming.json +++ b/src/data/tables/v2/streaming.json @@ -1,37 +1,4 @@ { - "BalanceEnableRequestParameters": { - "data": [ - { - "parameter": "coin", - "type": "string", - "required": true, - "description": "Ticker of the coin to activate streaming for. The coin must be activated first." - }, - { - "parameter": "client_id", - "type": "integer", - "required": false, - "default": "`0`", - "description": "In the case of a single client, this defaults to `0`. This ID can be used to access data via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1)" - }, - { - "parameter": "config", - "type": "object", - "required": false, - "description": "EVM only. A standard [StreamingConfig](/komodo-defi-framework/api/common_structures/#streaming-config) object." - } - ] - }, - "BalanceEnableResponseParameters": { - "data": [ - { - "parameter": "streamer_id", - "type": "string", - "required": false, - "description": "An identifier for the data stream. This can be used later to disable streaming for the event with [stream::disable](/komodo-defi-framework/api/v20/streaming/disable/)." - } - ] - }, "BalanceEnableErrorTypes": { "data": [ { @@ -60,29 +27,37 @@ } ] }, - "DisableRequestParameters": { + "BalanceEnableRequestParameters": { "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "Ticker of the coin to activate streaming for. The coin must be activated first." + }, { "parameter": "client_id", "type": "integer", - "required": true, - "description": "This ID can be used to access data (e.g. via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1))" + "required": false, + "default": "`0`", + "description": "In the case of a single client, this defaults to `0`. This ID can be used to access data via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1)" }, { - "parameter": "streamer_id", - "type": "string", - "required": true, - "description": "An identifier for the data stream to disable." + "parameter": "config", + "type": "object", + "required": false, + "description": "EVM only. A standard [StreamingConfig](/komodo-defi-framework/api/common_structures/#streaming-config) object.", + "substructure": "common.StreamingConfig" } ] }, - "DisableResponseParameters": { + "BalanceEnableResponseParameters": { "data": [ { - "parameter": "result", + "parameter": "streamer_id", "type": "string", "required": false, - "description": "Success message confirming the stream was disabled" + "description": "An identifier for the data stream. This can be used later to disable streaming for the event with [stream::disable](/komodo-defi-framework/api/v20/streaming/disable/)." } ] }, @@ -102,7 +77,7 @@ } ] }, - "FeeEstimatorRequestParameters": { + "DisableRequestParameters": { "data": [ { "parameter": "client_id", @@ -111,20 +86,20 @@ "description": "This ID can be used to access data (e.g. via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1))" }, { - "parameter": "coin", + "parameter": "streamer_id", "type": "string", "required": true, - "description": "The coin or token to enable the fee estimation stream for." + "description": "An identifier for the data stream to disable." } ] }, - "FeeEstimatorResponseParameters": { + "DisableResponseParameters": { "data": [ { - "parameter": "streamer_id", + "parameter": "result", "type": "string", "required": false, - "description": "An identifier for the data stream. This can be used later to disable streaming for the event with [stream::disable](/komodo-defi-framework/api/v20/streaming/disable/)." + "description": "Success message confirming the stream was disabled" } ] }, @@ -162,24 +137,23 @@ } ] }, - "HeartbeatEnableRequestParameters": { + "FeeEstimatorRequestParameters": { "data": [ { "parameter": "client_id", "type": "integer", - "required": false, - "default": "`0`", - "description": "In the case of a single client, this defaults to `0`. This ID can be used to access data via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1)." + "required": true, + "description": "This ID can be used to access data (e.g. via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1))" }, { - "parameter": "config", - "type": "object", - "required": false, - "description": "A standard [StreamingConfig](/komodo-defi-framework/api/common_structures/#streaming-config) object." + "parameter": "coin", + "type": "string", + "required": true, + "description": "The coin or token to enable the fee estimation stream for." } ] }, - "HeartbeatEnableResponseParameters": { + "FeeEstimatorResponseParameters": { "data": [ { "parameter": "streamer_id", @@ -205,24 +179,25 @@ } ] }, - "NetworkEnableRequestParameters": { + "HeartbeatEnableRequestParameters": { "data": [ { "parameter": "client_id", "type": "integer", "required": false, "default": "`0`", - "description": "In the case of a single client, this defaults to `0`. This ID can be used to access data via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1)" + "description": "In the case of a single client, this defaults to `0`. This ID can be used to access data via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1)." }, { "parameter": "config", "type": "object", "required": false, - "description": "A standard [StreamingConfig](/komodo-defi-framework/api/common_structures/#streaming-config) object." + "description": "A standard [StreamingConfig](/komodo-defi-framework/api/common_structures/#streaming-config) object.", + "substructure": "common.StreamingConfig" } ] }, - "NetworkEnableResponseParameters": { + "HeartbeatEnableResponseParameters": { "data": [ { "parameter": "streamer_id", @@ -248,17 +223,25 @@ } ] }, - "OrderStatusEnableRequestParameters": { + "NetworkEnableRequestParameters": { "data": [ { "parameter": "client_id", "type": "integer", - "required": true, - "description": "This ID can be used to access data (e.g. via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1))" + "required": false, + "default": "`0`", + "description": "In the case of a single client, this defaults to `0`. This ID can be used to access data via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1)" + }, + { + "parameter": "config", + "type": "object", + "required": false, + "description": "A standard [StreamingConfig](/komodo-defi-framework/api/common_structures/#streaming-config) object.", + "substructure": "common.StreamingConfig" } ] }, - "OrderStatusEnableResponseParameters": { + "NetworkEnableResponseParameters": { "data": [ { "parameter": "streamer_id", @@ -268,7 +251,7 @@ } ] }, - "OrderStatusEnableErrorTypes": { + "OrderbookEnableErrorTypes": { "data": [ { "parameter": "UnknownClient", @@ -316,7 +299,7 @@ } ] }, - "OrderbookEnableErrorTypes": { + "OrderStatusEnableErrorTypes": { "data": [ { "parameter": "UnknownClient", @@ -332,7 +315,7 @@ } ] }, - "SwapStatusEnableRequestParameters": { + "OrderStatusEnableRequestParameters": { "data": [ { "parameter": "client_id", @@ -342,7 +325,7 @@ } ] }, - "SwapStatusEnableResponseParameters": { + "OrderStatusEnableResponseParameters": { "data": [ { "parameter": "streamer_id", @@ -368,24 +351,17 @@ } ] }, - "TxHistoryEnableRequestParameters": { + "SwapStatusEnableRequestParameters": { "data": [ - { - "parameter": "coin", - "type": "string", - "required": true, - "description": "Ticker of the coin to activate streaming for. The coin must be activated first." - }, { "parameter": "client_id", "type": "integer", - "required": false, - "default": "`0`", - "description": "This ID can be used to access data via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1)" + "required": true, + "description": "This ID can be used to access data (e.g. via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1))" } ] }, - "TxHistoryEnableResponseParameters": { + "SwapStatusEnableResponseParameters": { "data": [ { "parameter": "streamer_id", @@ -422,5 +398,32 @@ "description": "The coin type is not supported for this stream" } ] + }, + "TxHistoryEnableRequestParameters": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "Ticker of the coin to activate streaming for. The coin must be activated first." + }, + { + "parameter": "client_id", + "type": "integer", + "required": false, + "default": "`0`", + "description": "This ID can be used to access data via [http://localhost:7783/event-stream?id=1](http://localhost:7783/event-stream?id=1)" + } + ] + }, + "TxHistoryEnableResponseParameters": { + "data": [ + { + "parameter": "streamer_id", + "type": "string", + "required": false, + "description": "An identifier for the data stream. This can be used later to disable streaming for the event with [stream::disable](/komodo-defi-framework/api/v20/streaming/disable/)." + } + ] } } \ No newline at end of file diff --git a/src/data/tables/v2/utils.json b/src/data/tables/v2/utils.json index bef42e3c5..e1225d911 100644 --- a/src/data/tables/v2/utils.json +++ b/src/data/tables/v2/utils.json @@ -1,4 +1,20 @@ { + "AddNodeToVersionStatErrors": { + "data": [ + { + "parameter": "DatabaseError", + "type": "string", + "required": false, + "description": "Database constraint error occurred." + }, + { + "parameter": "PeerIdParseError", + "type": "string", + "required": false, + "description": "The provided peer ID format is invalid." + } + ] + }, "AddNodeToVersionStatRequest": { "data": [ { @@ -31,19 +47,13 @@ } ] }, - "AddNodeToVersionStatErrors": { + "ChangeMnemonicPasswordErrors": { "data": [ { - "parameter": "DatabaseError", - "type": "string", - "required": false, - "description": "Database constraint error occurred." - }, - { - "parameter": "PeerIdParseError", + "parameter": "WalletsStorageError", "type": "string", "required": false, - "description": "The provided peer ID format is invalid." + "description": "Error decrypting or accessing wallet storage." } ] }, @@ -73,16 +83,6 @@ } ] }, - "ChangeMnemonicPasswordErrors": { - "data": [ - { - "parameter": "WalletsStorageError", - "type": "string", - "required": false, - "description": "Error decrypting or accessing wallet storage." - } - ] - }, "GetCurrentMtpRequest": { "data": [ { @@ -143,6 +143,16 @@ } ] }, + "GetEnabledCoinsErrors": { + "data": [ + { + "parameter": "Internal", + "type": "string", + "required": false, + "description": "Unhandled internal error." + } + ] + }, "GetMnemonicRequest": { "data": [ { @@ -182,7 +192,7 @@ } ] }, - "GetPublicKeyRequest": { + "GetPublicKeyHashRequest": { "data": [ { "parameter": "*None*", @@ -192,17 +202,17 @@ } ] }, - "GetPublicKeyResponse": { + "GetPublicKeyHashResponse": { "data": [ { - "parameter": "public_key", + "parameter": "public_key_hash", "type": "string", "required": true, - "description": "User's pubkey" + "description": "User's RIPEMD-160 public key hash" } ] }, - "GetPublicKeyHashRequest": { + "GetPublicKeyRequest": { "data": [ { "parameter": "*None*", @@ -212,13 +222,23 @@ } ] }, - "GetPublicKeyHashResponse": { + "GetPublicKeyResponse": { "data": [ { - "parameter": "public_key_hash", + "parameter": "public_key", "type": "string", "required": true, - "description": "User's RIPEMD-160 public key hash" + "description": "User's pubkey" + } + ] + }, + "GetSharedDbIdErrors": { + "data": [ + { + "parameter": "Internal", + "type": "string", + "required": false, + "description": "Unhandled internal error (rare)." } ] }, @@ -242,13 +262,13 @@ } ] }, - "GetSharedDbIdErrors": { + "GetTokenInfoErrors": { "data": [ { - "parameter": "Internal", + "parameter": "NoSuchCoin", "type": "string", "required": false, - "description": "Unhandled internal error (rare)." + "description": "The specified platform coin was not found or is not activated yet." } ] }, @@ -258,7 +278,8 @@ "parameter": "protocol", "type": "object", "required": true, - "description": "A standard [TokenProtocol](/komodo-defi-framework/api/common_structures/nfts/#token-protocol) object." + "description": "A standard [TokenProtocol](/komodo-defi-framework/api/common_structures/nfts/#token-protocol) object.", + "substructure": "nfts.TokenProtocol" } ] }, @@ -268,7 +289,7 @@ "parameter": "type", "type": "string", "required": true, - "description": "Token typeโ€”e.g., `PLG20` for tokens on the Polygon network." + "description": "Token type\u2014e.g., `PLG20` for tokens on the Polygon network." }, { "parameter": "info.symbol", @@ -284,16 +305,6 @@ } ] }, - "GetTokenInfoErrors": { - "data": [ - { - "parameter": "NoSuchCoin", - "type": "string", - "required": false, - "description": "The specified platform coin was not found or is not activated yet." - } - ] - }, "PeerConnectionHealthcheckRequest": { "data": [ { @@ -334,6 +345,22 @@ } ] }, + "SendAskedDataErrors": { + "data": [ + { + "parameter": "NotFound", + "type": "integer", + "required": false, + "description": "No awaiting `ask_for_data` with the specified `data_id`." + }, + { + "parameter": "Internal", + "type": "string", + "required": false, + "description": "Internal error while delivering data (rare)." + } + ] + }, "SendAskedDataRequest": { "data": [ { @@ -360,19 +387,80 @@ } ] }, - "SendAskedDataErrors": { + "SignMessageErrors": { "data": [ { - "parameter": "NotFound", - "type": "integer", + "parameter": "PrefixNotFound", + "type": "string", "required": false, - "description": "No awaiting `ask_for_data` with the specified `data_id`." + "description": "`sign_message_prefix` is not set in coin config file" }, { - "parameter": "Internal", + "parameter": "CoinIsNotFound", "type": "string", "required": false, - "description": "Internal error while delivering data (rare)." + "description": "Specified coin is not found" + }, + { + "parameter": "SigningError", + "type": "string", + "required": false, + "description": "Error attempting to sign message" + }, + { + "parameter": "InvalidRequest", + "type": "string", + "required": false, + "description": "Message signing is not supported by the given coin type" + }, + { + "parameter": "InternalError", + "type": "string", + "required": false, + "description": "An internal error occurred during the signing process" + } + ] + }, + "SignMessageRequest": { + "data": [ + { + "parameter": "coin", + "type": "string", + "required": true, + "description": "The coin to sign a message with." + }, + { + "parameter": "message", + "type": "string", + "required": true, + "description": "The message you want to sign." + }, + { + "parameter": "address", + "type": "object", + "required": false, + "description": "HD wallets only. A standard [AddressPath](/komodo-defi-framework/api/common_structures/wallet/#address-path) object. The path to the address for signing the message. If not provided, the `account_id`, `chain`, and `address_id` will default to `0`.", + "substructure": "wallet.AddressPath" + } + ] + }, + "SignMessageResponse": { + "data": [ + { + "parameter": "signature", + "type": "string", + "required": true, + "description": "The signature generated for the message." + } + ] + }, + "StartVersionStatCollectionErrors": { + "data": [ + { + "parameter": "DatabaseError", + "type": "string", + "required": false, + "description": "Database constraint error occurred." } ] }, @@ -396,13 +484,13 @@ } ] }, - "StartVersionStatCollectionErrors": { + "StopVersionStatCollectionErrors": { "data": [ { - "parameter": "DatabaseError", + "parameter": "NotRunning", "type": "string", "required": false, - "description": "Database constraint error occurred." + "description": "Version stat collection is not currently running" } ] }, @@ -426,16 +514,6 @@ } ] }, - "StopVersionStatCollectionErrors": { - "data": [ - { - "parameter": "NotRunning", - "type": "string", - "required": false, - "description": "Version stat collection is not currently running" - } - ] - }, "TaskConnectMetamaskCancelRequest": { "data": [ { @@ -486,26 +564,6 @@ } ] }, - "TaskConnectMetamaskInitRequest": { - "data": [ - { - "parameter": "project", - "type": "string", - "required": true, - "description": "A short, human-readable identifier for the DApp or integration requesting the context." - } - ] - }, - "TaskConnectMetamaskInitResponse": { - "data": [ - { - "parameter": "task_id", - "type": "integer", - "required": true, - "description": "An identifying number that is used to query task status or to cancel it" - } - ] - }, "TaskConnectMetamaskInitErrors": { "data": [ { @@ -546,36 +604,23 @@ } ] }, - "TaskConnectMetamaskStatusRequest": { + "TaskConnectMetamaskInitRequest": { "data": [ { - "parameter": "task_id", - "type": "integer", + "parameter": "project", + "type": "string", "required": true, - "description": "The `task_id` returned by the *init* call." - }, - { - "parameter": "forget_if_finished", - "type": "boolean", - "required": false, - "default": "true", - "description": "If `false`, the final (completed) response is returned on every call." + "description": "A short, human-readable identifier for the DApp or integration requesting the context." } ] }, - "TaskConnectMetamaskStatusResponse": { + "TaskConnectMetamaskInitResponse": { "data": [ { - "parameter": "status", - "type": "string", - "required": true, - "description": "A short indication of how the connection process is progressing (`Initializing`, `SigningLoginMetadata`, `Ok`, or `Error`)." - }, - { - "parameter": "details", - "type": "object", + "parameter": "task_id", + "type": "integer", "required": true, - "description": "Extra data whose structure depends on the current `status`. See examples below. In the successful case it contains `eth_address`." + "description": "An identifying number that is used to query task status or to cancel it" } ] }, @@ -613,6 +658,39 @@ } ] }, + "TaskConnectMetamaskStatusRequest": { + "data": [ + { + "parameter": "task_id", + "type": "integer", + "required": true, + "description": "The `task_id` returned by the *init* call." + }, + { + "parameter": "forget_if_finished", + "type": "boolean", + "required": false, + "default": "true", + "description": "If `false`, the final (completed) response is returned on every call." + } + ] + }, + "TaskConnectMetamaskStatusResponse": { + "data": [ + { + "parameter": "status", + "type": "string", + "required": true, + "description": "A short indication of how the connection process is progressing (`Initializing`, `SigningLoginMetadata`, `Ok`, or `Error`)." + }, + { + "parameter": "details", + "type": "object", + "required": true, + "description": "Extra data whose structure depends on the current `status`. See examples below. In the successful case it contains `eth_address`." + } + ] + }, "TaskInitTrezorCancelRequest": { "data": [ { @@ -790,23 +868,31 @@ } ] }, - "TrezorConnectionStatusRequest": { + "TelegramAlertsConfig": { "data": [ { - "parameter": "device_pubkey", + "parameter": "api_key", "type": "string", - "required": false, - "description": "Expected public key of the Trezor device. If specified and a *different* device is connected, an error is returned." - } - ] - }, - "TrezorConnectionStatusResponse": { - "data": [ + "required": true, + "description": "A Telegram bot API token" + }, { - "parameter": "status", + "parameter": "chat_registry.default", "type": "string", "required": true, - "description": "One of: `Connected`, `Disconnected`, `Busy`." + "description": "A Telegram Chat ID" + }, + { + "parameter": "chat_registry.maker_bot", + "type": "string", + "required": true, + "description": "A Telegram Chat ID" + }, + { + "parameter": "chat_registry.swap_events", + "type": "string", + "required": true, + "description": "A Telegram Chat ID" } ] }, @@ -832,23 +918,23 @@ } ] }, - "UpdateVersionStatCollectionRequest": { + "TrezorConnectionStatusRequest": { "data": [ { - "parameter": "interval", - "type": "integer", - "required": true, - "description": "Polling rate (in seconds) to query node versions" + "parameter": "device_pubkey", + "type": "string", + "required": false, + "description": "Expected public key of the Trezor device. If specified and a *different* device is connected, an error is returned." } ] }, - "UpdateVersionStatCollectionResponse": { + "TrezorConnectionStatusResponse": { "data": [ { - "parameter": "result", + "parameter": "status", "type": "string", "required": true, - "description": "The outcome of the request." + "description": "One of: `Connected`, `Disconnected`, `Busy`." } ] }, @@ -862,45 +948,33 @@ } ] }, - "SignMessageRequest": { + "UpdateVersionStatCollectionRequest": { "data": [ { - "parameter": "coin", - "type": "string", - "required": true, - "description": "The coin to sign a message with." - }, - { - "parameter": "message", - "type": "string", + "parameter": "interval", + "type": "integer", "required": true, - "description": "The message you want to sign." - }, - { - "parameter": "address", - "type": "string", - "required": false, - "description": "HD wallets only. A standard [AddressPath](/komodo-defi-framework/api/common_structures/wallet/#address-path) object. The path to the address for signing the message. If not provided, the `account_id`, `chain`, and `address_id` will default to `0`." + "description": "Polling rate (in seconds) to query node versions" } ] }, - "SignMessageResponse": { + "UpdateVersionStatCollectionResponse": { "data": [ { - "parameter": "signature", + "parameter": "result", "type": "string", "required": true, - "description": "The signature generated for the message." + "description": "The outcome of the request." } ] }, - "SignMessageErrors": { + "VerifyMessageErrors": { "data": [ { "parameter": "PrefixNotFound", "type": "string", "required": false, - "description": "`sign_message_prefix` is not set in coin config file" + "description": "`sign_message_prefix` is not set in coin config" }, { "parameter": "CoinIsNotFound", @@ -909,22 +983,28 @@ "description": "Specified coin is not found" }, { - "parameter": "SigningError", + "parameter": "InvalidRequest", "type": "string", "required": false, - "description": "Error attempting to sign message" + "description": "Message verification is not supported by the given coin type" }, { - "parameter": "InvalidRequest", + "parameter": "InternalError", "type": "string", "required": false, - "description": "Message signing is not supported by the given coin type" + "description": "An internal error occurred during the verification process" }, { - "parameter": "InternalError", + "parameter": "SignatureDecodingError", "type": "string", "required": false, - "description": "An internal error occurred during the signing process" + "description": "Given signature could not be decoded" + }, + { + "parameter": "AddressDecodingError", + "type": "string", + "required": false, + "description": "Given address could not be decoded" } ] }, @@ -965,73 +1045,5 @@ "description": "`true` if the message signature is valid; `false` if it is not." } ] - }, - "VerifyMessageErrors": { - "data": [ - { - "parameter": "PrefixNotFound", - "type": "string", - "required": false, - "description": "`sign_message_prefix` is not set in coin config" - }, - { - "parameter": "CoinIsNotFound", - "type": "string", - "required": false, - "description": "Specified coin is not found" - }, - { - "parameter": "InvalidRequest", - "type": "string", - "required": false, - "description": "Message verification is not supported by the given coin type" - }, - { - "parameter": "InternalError", - "type": "string", - "required": false, - "description": "An internal error occurred during the verification process" - }, - { - "parameter": "SignatureDecodingError", - "type": "string", - "required": false, - "description": "Given signature could not be decoded" - }, - { - "parameter": "AddressDecodingError", - "type": "string", - "required": false, - "description": "Given address could not be decoded" - } - ] - }, - "TelegramAlertsConfig": { - "data": [ - { - "parameter": "api_key", - "type": "string", - "required": true, - "description": "A Telegram bot API token" - }, - { - "parameter": "chat_registry.default", - "type": "string", - "required": true, - "description": "A Telegram Chat ID" - }, - { - "parameter": "chat_registry.maker_bot", - "type": "string", - "required": true, - "description": "A Telegram Chat ID" - }, - { - "parameter": "chat_registry.swap_events", - "type": "string", - "required": true, - "description": "A Telegram Chat ID" - } - ] } } \ No newline at end of file diff --git a/src/data/tables/v2/wallet.json b/src/data/tables/v2/wallet.json index 1e1f10ac9..43a807262 100644 --- a/src/data/tables/v2/wallet.json +++ b/src/data/tables/v2/wallet.json @@ -1,57 +1,811 @@ { + "ConsolidateUtxosErrors": { + "data": [ + { + "description": "The request is malformed or missing required parameters.", + "parameter": "InvalidRequest", + "required": false, + "type": "string" + }, + { + "description": "The requested merge failed. See `error_data` for more details.", + "parameter": "MergeError", + "required": false, + "type": "string" + }, + { + "description": "The selected coin was not found or is not activated yet.", + "parameter": "NoSuchCoin", + "required": false, + "type": "string" + } + ] + }, + "GetPrivateKeysRequest": { + "data": [ + { + "parameter": "coins", + "type": "array of strings", + "required": true, + "description": "Array of coin tickers to export private keys for." + }, + { + "parameter": "mode", + "type": "string (enum)", + "required": false, + "description": "Export mode: \"hd\" for HD wallet export, \"iguana\" for legacy Iguana format. Defaults based on MM2.json config." + }, + { + "parameter": "start_index", + "type": "integer", + "required": false, + "description": "\"mode\": hd only. Starting address index for HD mode (default: 0)." + }, + { + "parameter": "end_index", + "type": "integer", + "required": false, + "description": "\"mode\": hd only. Ending address index for HD mode (default: start_index + 10)." + }, + { + "parameter": "account_index", + "type": "integer", + "required": false, + "description": "\"mode\": hd only. Account index for HD derivation path (default: 0)." + } + ] + }, + "GetPrivateKeysHdResponse": { + "data": [ + { + "parameter": "result", + "type": "list", + "required": true, + "description": "Array of coin key information with HD derivation data.", + "substructure": "wallet.HdCoinKeys" + } + ] + }, + "GetPrivateKeysIguanaResponse": { + "data": [ + { + "parameter": "result", + "type": "list", + "required": true, + "description": "Array of coin key information in Iguana format.", + "substructure": "wallet.IguanaKeysInfo" + } + ] + }, + "ConsolidateUtxosRequest": { + "data": [ + { + "description": "The coin to consolidate utxos for.", + "parameter": "coin", + "required": true, + "type": "string" + }, + { + "description": "The conditions to merge utxos.", + "parameter": "merge_conditions", + "required": true, + "type": "object" + } + ] + }, + "ConsolidateUtxosResponse": { + "data": [ + { + "description": "The outcome of the request.", + "parameter": "result", + "required": true, + "type": "string" + } + ] + }, + "ErrorTypes": { + "data": [ + { + "description": "A storage-related error occurred while accessing wallet data.", + "parameter": "WalletsStorageError", + "required": false, + "type": "string" + }, + { + "description": "An attempt was made to delete the currently active wallet.", + "parameter": "CannotDeleteActiveWallet", + "required": false, + "type": "string" + }, + { + "description": "An internal server error occurred.", + "parameter": "InternalError", + "required": false, + "type": "string" + }, + { + "description": "The provided `password` is incorrect.", + "parameter": "InvalidPassword", + "required": false, + "type": "string" + }, + { + "description": "The request is malformed or missing required parameters.", + "parameter": "InvalidRequest", + "required": false, + "type": "string" + }, + { + "description": "The specified `wallet_name` was not found.", + "parameter": "WalletNotFound", + "required": false, + "type": "string" + } + ] + }, + "FetchUtxosErrors": { + "data": [ + { + "description": "The request is malformed or missing required parameters.", + "parameter": "InvalidRequest", + "required": false, + "type": "string" + }, + { + "description": "The selected coin was not found or is not activated yet.", + "parameter": "NoSuchCoin", + "required": false, + "type": "string" + } + ] + }, + "FetchUtxosRequest": { + "data": [ + { + "description": "The coin to fetch utxos for.", + "parameter": "coin", + "required": true, + "type": "string" + } + ] + }, + "FetchUtxosResponse": { + "data": [ + { + "description": "The outcome of the request.", + "parameter": "result", + "required": true, + "type": "string" + } + ] + }, "RequestParameters": { "data": [ { + "description": "The name of the wallet to delete.", "parameter": "wallet_name", - "type": "string", "required": true, - "description": "The name of the wallet to delete." + "type": "string" }, { + "description": "The password of the wallet.", "parameter": "password", - "type": "string", "required": true, - "description": "The password of the wallet." + "type": "string" } ] }, - "ErrorTypes": { + "GetMyAddressRequest": { + "data": [ + { + "description": "Ticker of the enabled coin (e.g., \"SIA\").", + "parameter": "coin", + "required": true, + "type": "string" + }, + { + "description": "Optional HD path selector (unused for Sia Iguana).", + "parameter": "path_to_address", + "required": false, + "type": "object" + } + ] + }, + "GetMyAddressResponse": { + "data": [ + { + "description": "Ticker of the coin.", + "parameter": "coin", + "required": true, + "type": "string" + }, + { + "description": "Wallet address string.", + "parameter": "wallet_address", + "required": true, + "type": "string" + } + ] + }, + "GetMyAddressErrors": { "data": [ { + "description": "Coin not enabled or not supported.", + "parameter": "CoinIsNotSupported|NoSuchCoin", + "required": false, + "type": "string" + }, + { + "description": "Invalid request payload.", "parameter": "InvalidRequest", + "required": false, + "type": "string" + }, + { + "description": "Internal server error.", + "parameter": "Internal", + "required": false, + "type": "string" + } + ] + }, + "GetRawTransactionRequest": { + "data": [ + { + "description": "Ticker of the enabled coin (e.g., \"SIA\").", + "parameter": "coin", + "required": true, + "type": "string" + }, + { + "description": "Transaction hash string.", + "parameter": "tx_hash", + "required": true, + "type": "string" + } + ] + }, + "GetRawTransactionResponse": { + "data": [ + { + "description": "Raw transaction bytes encoded as hex string (for Sia this is JSON-serialized bytes).", + "parameter": "tx_hex", + "required": true, + "type": "string" + } + ] + }, + "GetRawTransactionErrors": { + "data": [ + { + "description": "No such coin is enabled.", + "parameter": "NoSuchCoin", + "required": false, + "type": "string" + }, + { + "description": "Invalid hash, not found, or invalid params.", + "parameter": "InvalidHashError|HashNotExist|InvalidParam|DecodeError", + "required": false, + "type": "string" + }, + { + "description": "Not implemented for this coin.", + "parameter": "NotImplemented", + "required": false, + "type": "string" + }, + { + "description": "Transport or internal error.", + "parameter": "Transport|InternalError|TransactionError", + "required": false, + "type": "string" + } + ] + }, + "GetPrivateKeysErrors": { + "data": [ + { + "parameter": "KeyDerivationFailed", "type": "string", "required": false, - "description": "The request is malformed or missing required parameters." + "description": "Failed to derive keys for one or more coins." }, { - "parameter": "WalletNotFound", + "parameter": "InvalidRequest", "type": "string", "required": false, - "description": "The specified `wallet_name` was not found." + "description": "Request parameters are invalid for the selected mode." }, { - "parameter": "InvalidPassword", + "parameter": "InternalError", "type": "string", "required": false, - "description": "The provided `password` is incorrect." + "description": "Unexpected internal error." + } + ] + }, + "MyBalanceRequest": { + "data": [ + { + "description": "Ticker of the enabled coin (e.g., \"SIA\").", + "parameter": "coin", + "required": true, + "type": "string" + } + ] + }, + "MyBalanceResponse": { + "data": [ + { + "description": "Ticker of the coin.", + "parameter": "coin", + "required": true, + "type": "string" }, { - "parameter": "CannotDeleteActiveWallet", + "description": "Spendable balance.", + "parameter": "balance", + "required": true, + "type": "string" + }, + { + "description": "Unspendable balance (e.g., immature).", + "parameter": "unspendable_balance", + "required": true, + "type": "string" + }, + { + "description": "Wallet address used for balance query.", + "parameter": "address", + "required": true, + "type": "string" + } + ] + }, + "MyBalanceErrors": { + "data": [ + { + "description": "No such coin is enabled.", + "parameter": "NoSuchCoin", + "required": false, + "type": "string" + }, + { + "description": "Transport or internal error during balance fetch.", + "parameter": "Transport|InternalError", + "required": false, + "type": "string" + } + ] + }, + "SendRawTransactionRequest": { + "data": [ + { + "description": "Ticker of the enabled coin (e.g., \"SIA\").", + "parameter": "coin", + "required": true, + "type": "string" + }, + { + "description": "Raw transaction hex string. For Sia, you may alternatively pass tx_json.", + "parameter": "tx_hex", + "required": false, + "type": "string" + }, + { + "description": "Raw transaction JSON object (Sia V2Transaction). Alternative to tx_hex.", + "parameter": "tx_json", + "required": false, + "type": "object" + } + ] + }, + "SendRawTransactionResponse": { + "data": [ + { + "description": "Broadcasted transaction hash.", + "parameter": "tx_hash", + "required": true, + "type": "string" + } + ] + }, + "SendRawTransactionErrors": { + "data": [ + { + "description": "No such coin is enabled.", + "parameter": "NoSuchCoin", + "required": false, + "type": "string" + }, + { + "description": "Neither tx_hex nor tx_json provided.", + "parameter": "InvalidRequest", + "required": false, + "type": "string" + }, + { + "description": "Transport or internal error broadcasting transaction.", + "parameter": "Transport|Internal", + "required": false, + "type": "string" + } + ] + }, + "ValidateAddressRequest": { + "data": [ + { + "description": "Ticker of the enabled coin (e.g., \"SIA\").", + "parameter": "coin", + "required": true, + "type": "string" + }, + { + "description": "Address string to validate.", + "parameter": "address", + "required": true, + "type": "string" + } + ] + }, + "ValidateAddressResponse": { + "data": [ + { + "description": "Whether the address is valid.", + "parameter": "is_valid", + "required": true, + "type": "boolean" + }, + { + "description": "Optional reason if invalid.", + "parameter": "reason", + "required": false, + "type": "string" + } + ] + }, + "ValidateAddressErrors": { + "data": [ + { + "description": "No such coin is enabled.", + "parameter": "NoSuchCoin", + "required": false, + "type": "string" + }, + { + "description": "Internal/transport error.", + "parameter": "Internal|Transport", + "required": false, + "type": "string" + } + ] + }, + "WithdrawRequest": { + "data": [ + { + "description": "Ticker of the enabled coin (e.g., \"SIA\").", + "parameter": "coin", + "required": true, + "type": "string" + }, + { + "description": "Optional HD address selector (unused for Sia Iguana).", + "parameter": "from", + "required": false, + "type": "object" + }, + { + "description": "Recipient address.", + "parameter": "to", + "required": true, + "type": "string" + }, + { + "description": "Amount to send in coin units.", + "parameter": "amount", + "required": false, + "type": "string" + }, + { + "description": "Send full balance if true.", + "parameter": "max", + "required": false, + "type": "boolean" + }, + { + "description": "Optional fee policy (Sia uses default fee when unspecified).", + "parameter": "fee", + "required": false, + "type": "object" + }, + { + "description": "Optional memo (unused for Sia).", + "parameter": "memo", + "required": false, + "type": "string" + }, + { + "description": "Tendermint IBC transfers only. The source channel for IBC transaction.", + "parameter": "ibc_source_channel", + "required": false, + "type": "integer" + }, + { + "description": "Set true for Metamask-managed transactions that must be broadcast immediately.", + "parameter": "broadcast", + "required": false, + "type": "boolean" + } + ] + }, + "WithdrawResponse": { + "data": [ + { + "description": "Transaction details object.", + "parameter": "tx", + "required": true, + "type": "object" + } + ] + }, + "WithdrawErrors": { + "data": [ + { + "description": "No such coin is enabled.", + "parameter": "NoSuchCoin", + "required": false, + "type": "string" + }, + { + "description": "Insufficient balance to complete withdrawal.", + "parameter": "NotSufficientBalance|NotSufficientPlatformBalanceForFee", + "required": false, + "type": "string" + }, + { + "description": "Amount is too low or zero with max flag.", + "parameter": "AmountTooLow|ZeroBalanceToWithdrawMax", + "required": false, + "type": "string" + }, + { + "description": "Invalid address or fee parameters.", + "parameter": "InvalidAddress|InvalidFeePolicy|InvalidFee", + "required": false, + "type": "string" + }, + { + "description": "Withdrawal timed out.", + "parameter": "Timeout", + "required": false, + "type": "string" + }, + { + "description": "Transport or internal error.", + "parameter": "Transport|InternalError", + "required": false, + "type": "string" + } + ] + }, + "WithdrawInitRequest": { + "data": [ + { + "description": "Client identifier to receive streaming status updates.", + "parameter": "client_id", + "required": false, + "type": "integer" + }, + { + "description": "Withdrawal parameters; same as WithdrawRequest.", + "parameter": "withdraw", + "required": true, + "type": "object" + } + ] + }, + "WithdrawInitResponse": { + "data": [ + { + "description": "Task identifier to track withdrawal progress.", + "parameter": "task_id", + "required": true, + "type": "integer" + } + ] + }, + "WithdrawStatusRequest": { + "data": [ + { + "description": "Task identifier returned by withdraw::init.", + "parameter": "task_id", + "required": true, + "type": "integer" + }, + { + "description": "If true, the task is removed from memory if finished.", + "parameter": "forget_if_finished", + "required": false, + "type": "boolean" + } + ] + }, + "WithdrawStatusResponse": { + "data": [ + { + "description": "Current status: Ok|Error|InProgress|UserActionRequired.", + "parameter": "status", + "required": true, + "type": "string" + }, + { + "description": "Details object depends on status; Ok contains TransactionDetails.", + "parameter": "details", + "required": true, + "type": "object" + } + ] + }, + "WithdrawUserActionRequest": { + "data": [ + { + "description": "Task identifier returned by withdraw::init.", + "parameter": "task_id", + "required": true, + "type": "integer" + }, + { + "description": "User action payload if required (hardware wallet etc.).", + "parameter": "user_action", + "required": true, + "type": "object" + } + ] + }, + "WithdrawCancelRequest": { + "data": [ + { + "description": "Task identifier returned by withdraw::init.", + "parameter": "task_id", + "required": true, + "type": "integer" + } + ] + }, + "WithdrawTaskErrors": { + "data": [ + { + "description": "No such task or task finished.", + "parameter": "NoSuchTask|TaskFinished", + "required": false, + "type": "string" + }, + { + "description": "Withdrawal errors (see WithdrawErrors).", + "parameter": "WithdrawError", + "required": false, + "type": "string" + }, + { + "description": "Internal/transport error.", + "parameter": "Internal|Transport", + "required": false, + "type": "string" + } + ] + }, + "MyTxHistoryV2Request": { + "data": [ + { + "parameter": "coin", "type": "string", + "required": true, + "description": "Ticker of the coin to get history for." + }, + { + "parameter": "limit", + "type": "integer", "required": false, - "description": "An attempt was made to delete the currently active wallet." + "description": "Limits the number of returned transactions. Ignored if max=true." }, { - "parameter": "WalletsStorageError", + "parameter": "paging_options", + "type": "object", + "required": false, + "description": "A standard Pagination object." + }, + { + "parameter": "target", + "type": "object", + "required": false, + "description": "A standard HistoryTarget object (e.g., account_id or address_id)." + } + ] + }, + "MyTxHistoryV2Response": { + "data": [ + { + "parameter": "transactions", + "type": "array of objects", + "required": true, + "description": "Transactions affecting the target." + }, + { + "parameter": "from_id", + "type": "string|null", + "required": true, + "description": "FromId echoed back (if any)." + }, + { + "parameter": "skipped", + "type": "number", + "required": true, + "description": "Number of skipped records." + }, + { + "parameter": "limit", + "type": "number", + "required": true, + "description": "Requested limit." + }, + { + "parameter": "total", + "type": "number", + "required": true, + "description": "Total number of transactions available." + }, + { + "parameter": "page_number", + "type": "number|null", + "required": true, + "description": "Requested page number (if any)." + }, + { + "parameter": "total_pages", + "type": "number", + "required": true, + "description": "Total pages with the chosen limit." + }, + { + "parameter": "current_block", + "type": "number", + "required": true, + "description": "Latest block number." + }, + { + "parameter": "sync_status", + "type": "object", + "required": true, + "description": "Standard SyncStatus object." + } + ] + }, + "MyTxHistoryV2Errors": { + "data": [ + { + "parameter": "NoSuchCoin|CoinIsNotSupported", "type": "string", "required": false, - "description": "A storage-related error occurred while accessing wallet data." + "description": "The selected coin was not found, not enabled, or not supported for v2 history." }, { - "parameter": "InternalError", + "parameter": "InvalidRequest", + "type": "string", + "required": false, + "description": "The request is malformed or contains invalid parameters." + }, + { + "parameter": "StorageIsNotInitialized|StorageError", + "type": "string", + "required": false, + "description": "The local history storage is not initialized or failed." + }, + { + "parameter": "Internal|Transport", "type": "string", "required": false, - "description": "An internal server error occurred." + "description": "Unexpected internal or transport error." } ] } diff --git a/src/pages/komodo-defi-framework/api/index.mdx b/src/pages/komodo-defi-framework/api/index.mdx index 31028cb82..4a834fa68 100644 --- a/src/pages/komodo-defi-framework/api/index.mdx +++ b/src/pages/komodo-defi-framework/api/index.mdx @@ -10,196 +10,155 @@ To test the methods in v2.0 (Dev), you will need to [build the Komodo DeFi Frame Below is a table of the currently available legacy, v2.0 and v2.0 (Dev) methods: -| Legacy | v2.0 (release) | v2.0 (dev) | -| ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [](/komodo-defi-framework/api/legacy/coin_activation/#coin-activation) | [](/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_with_assets/#enable-tendermint-with-assets) | [](/komodo-defi-framework/api/v20-dev/one_inch_v6_0_classic_swap_create/#1inch-v6-0-classic-swap-create) | -| | | [1inch\_v6\_0\_classic\_swap\_create](/komodo-defi-framework/api/v20-dev/one_inch_v6_0_classic_swap_create/#1inch-v6-0-classic-swap-create) | -| | | [1inch\_v6\_0\_classic\_swap\_liquidity\_sources](/komodo-defi-framework/api/v20-dev/one_inch_v6_0_classic_swap_liquidity_sources/#1inch-v6-0-classic-swap-liquidity-sources) | -| | | [1inch\_v6\_0\_classic\_swap\_quote](/komodo-defi-framework/api/v20-dev/one_inch_v6_0_classic_swap_quote/#1inch-v6-0-classic-swap-quote) | -| | | [1inch\_v6\_0\_classic\_swap\_tokens](/komodo-defi-framework/api/v20-dev/one_inch_v6_0_classic_swap_tokens/#1inch-v6-0-classic-swap-tokens) | -| [active\_swaps](/komodo-defi-framework/api/legacy/active_swaps/#active-swaps) | [active\_swaps](/komodo-defi-framework/api/v20/swaps_and_orders/active_swaps/#active-swaps) | | -| | [add\_node\_to\_version\_stat](/komodo-defi-framework/api/v20/utils/add_node_to_version_stat/#add-node-to-version-stat) | | -| [all\_swaps\_uuids\_by\_filter](/komodo-defi-framework/api/legacy/all_swaps_uuids_by_filter/#all-swaps-uuids-by-filter) | | | -| | | [approve\_token](/komodo-defi-framework/api/v20-dev/approve_token/#approve-token) | -| | [balance\_enable](/komodo-defi-framework/api/v20/streaming/balance_enable/#enable-balance-streaming) | | -| [ban\_pubkey](/komodo-defi-framework/api/legacy/ban_pubkey/#ban-pubkey) | | | -| [best\_orders](/komodo-defi-framework/api/legacy/best_orders/#best-orders) | [best\_orders](/komodo-defi-framework/api/v20/swaps_and_orders/best_orders/#best-orders) | | -| [buy](/komodo-defi-framework/api/legacy/buy/#buy) | | | -| [cancel\_all\_orders](/komodo-defi-framework/api/legacy/cancel_all_orders/#cancel-all-orders) | | | -| [cancel\_order](/komodo-defi-framework/api/legacy/cancel_order/#cancel-order) | | | -| | [change\_mnemonic\_password](/komodo-defi-framework/api/v20/utils/change_mnemonic_password/#change-mnemonic-password) | | -| | [clear\_nft\_db](/komodo-defi-framework/api/v20/non_fungible_tokens/clear_nft_db/#clear-nft-db) | | -| | [close\_channel](/komodo-defi-framework/api/v20/lightning/channels/#close-channel) | | -| [coins\_needed\_for\_kick\_start](/komodo-defi-framework/api/legacy/coins_needed_for_kick_start/#coins-needed-for-kick-start) | | | -| [consolidate\_utxos](/komodo-defi-framework/api/legacy/consolidate_utxos/#consolidate-utxos) | | | -| [convert\_utxo\_address](/komodo-defi-framework/api/legacy/convert_utxo_address/#convert-utxo-address) | | | -| [convertaddress](/komodo-defi-framework/api/legacy/convertaddress/#convertaddress) | | | -| | [delete\_wallet](/komodo-defi-framework/api/v20/wallet/delete_wallet/#delete-wallet) | | -| [disable\_coin](/komodo-defi-framework/api/legacy/disable_coin/#disable-coin) | | | -| [electrum](/komodo-defi-framework/api/legacy/coin_activation/#electrum) | | | -| [enable](/komodo-defi-framework/api/legacy/coin_activation/#enable) | | | -| | [enable\_bch\_with\_tokens](/komodo-defi-framework/api/v20/coin_activation/enable_bch_with_tokens/#enable-bch-with-tokens) | | -| | [enable\_erc20](/komodo-defi-framework/api/v20/coin_activation/enable_erc20/#enable-erc20) | | -| | [enable\_eth\_with\_tokens](/komodo-defi-framework/api/v20/coin_activation/enable_eth_with_tokens/#enable-eth-with-tokens) | | -| | [enable\_nft](/komodo-defi-framework/api/v20/non_fungible_tokens/enable_nft/#enable-nft) | | -| | [enable\_tendermint\_token](/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_token/#enable-tendermint-token) | | -| | [enable\_tendermint\_with\_assets](/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_with_assets/#enable-tendermint-with-assets) | | -| | [experimental::staking::claim\_rewards](/komodo-defi-framework/api/v20/wallet/staking/claim_rewards/#claim-rewards) | | -| | [experimental::staking::delegate](/komodo-defi-framework/api/v20/wallet/staking/delegate/#delegate) | | -| | [experimental::staking::delegations](/komodo-defi-framework/api/v20/wallet/staking/delegations/#delegations) | | -| | [experimental::staking::query::delegations](/komodo-defi-framework/api/v20/wallet/staking/delegations/#delegations) | | -| | [experimental::staking::query::ongoing\_undelegations](/komodo-defi-framework/api/v20/wallet/staking/ongoing_delegations/#ongoing-undelegations) | | -| | [experimental::staking::query::validators](/komodo-defi-framework/api/v20/wallet/staking/validators/#validators) | | -| | [experimental::staking::undelegate](/komodo-defi-framework/api/v20/wallet/staking/undelegate/#undelegate) | | -| | [fee\_estimator\_enable](/komodo-defi-framework/api/v20/streaming/fee_estimator/#fee-estimator-streaming) | | -| | [get\_channel\_details](/komodo-defi-framework/api/v20/lightning/channels/#get-channel-details) | | -| | [get\_claimable\_balances](/komodo-defi-framework/api/v20/lightning/channels/#get-claimable-balances) | | -| | [get\_current\_mtp](/komodo-defi-framework/api/v20/utils/get_current_mtp/#get-current-mtp) | | -| [get\_directly\_connected\_peers](/komodo-defi-framework/api/legacy/get_directly_connected_peers/#get-directly-connected-peers) | | | -| [get\_enabled\_coins](/komodo-defi-framework/api/legacy/get_enabled_coins/#get-enabled-coins) | [get\_enabled\_coins](/komodo-defi-framework/api/v20/utils/get_enabled_coins/#get-enabled-coins) | | -| | [get\_eth\_estimated\_fee\_per\_gas](/komodo-defi-framework/api/v20/wallet/fee_management/get_eth_estimated_fee_per_gas/#get-eth-estimated-fee-per-gas) | | -| [get\_gossip\_mesh](/komodo-defi-framework/api/legacy/get_gossip_mesh/#get-gossip-mesh) | | | -| [get\_gossip\_peer\_topics](/komodo-defi-framework/api/legacy/get_gossip_peer_topics/#get-gossip-peer-topics) | | | -| [get\_gossip\_topic\_peers](/komodo-defi-framework/api/legacy/get_gossip_topic_peers/#get-gossip-topic-peers) | | | -| | [get\_locked\_amount](/komodo-defi-framework/api/v20/swaps_and_orders/get_locked_amount/#get-locked-amount) | | -| | [get\_mnemonic](/komodo-defi-framework/api/v20/utils/get_mnemonic/#get-mnemonic) | | -| [get\_my\_peer\_id](/komodo-defi-framework/api/legacy/get_my_peer_id/#get-my-peer-id) | | | -| | [get\_nft\_list](/komodo-defi-framework/api/v20/non_fungible_tokens/get_nft_list/#get-a-list-of-nfts) | | -| | [get\_nft\_metadata](/komodo-defi-framework/api/v20/non_fungible_tokens/get_nft_metadata/#get-nft-metadata) | | -| | [get\_nft\_transfers](/komodo-defi-framework/api/v20/non_fungible_tokens/get_nft_transfers/#get-a-list-of-nft-transfers) | | -| | [get\_private\_keys](/komodo-defi-framework/api/v20/wallet/get_private_keys/#get-private-keys) | | -| | [get\_public\_key](/komodo-defi-framework/api/v20/utils/get_public_key/#get-public-key) | | -| | [get\_public\_key\_hash](/komodo-defi-framework/api/v20/utils/get_public_key_hash/#get-public-key-hash) | | -| | [get\_raw\_transaction](/komodo-defi-framework/api/v20/wallet/tx/get_raw_transaction/#get-raw-transaction) | | -| [get\_relay\_mesh](/komodo-defi-framework/api/legacy/get_relay_mesh/#get-relay-mesh) | | | -| | [get\_shared\_db\_id](/komodo-defi-framework/api/v20/utils/get_shared_db_id/#get-shared-db-id) | | -| | [get\_swap\_transaction\_fee\_policy](/komodo-defi-framework/api/v20/wallet/fee_management/get_swap_transaction_fee_policy/#get-swap-transaction-fee-policy) | | -| | | [get\_token\_allowance](/komodo-defi-framework/api/v20-dev/get_token_allowance/#get-token-allowance) | -| | [get\_token\_info](/komodo-defi-framework/api/v20/utils/get_token_info/#get-token-info) | | -| [get\_trade\_fee](/komodo-defi-framework/api/legacy/get_trade_fee/#get-trade-fee) | | | -| | [get\_wallet\_names](/komodo-defi-framework/api/v20/wallet/get_wallet_names/#get-wallet-names) | | -| [import\_swaps](/komodo-defi-framework/api/legacy/import_swaps/#import-swaps) | | | -| [kmd\_rewards\_info](/komodo-defi-framework/api/legacy/kmd_rewards_info/#kmd-rewards-info) | | | -| | [lightning](/komodo-defi-framework/api/v20/lightning/channels/#lightning-network-channels) | | -| | [lightning::nodes::add\_trusted\_node](/komodo-defi-framework/api/v20/lightning/nodes/#lightning-network-nodes) | | -| | [lightning::nodes::connect\_to\_node](/komodo-defi-framework/api/v20/lightning/nodes/#lightning-network-nodes) | | -| | [lightning::nodes::list\_trusted\_nodes](/komodo-defi-framework/api/v20/lightning/nodes/#lightning-network-nodes) | | -| | [lightning::nodes::remove\_trusted\_node](/komodo-defi-framework/api/v20/lightning/nodes/#lightning-network-nodes) | | -| | [lightning::payments::generate\_invoice](/komodo-defi-framework/api/v20/lightning/payments/#lightning-network-payments) | | -| | [lightning::payments::get\_payment\_details](/komodo-defi-framework/api/v20/lightning/payments/#lightning-network-payments) | | -| | [lightning::payments::list\_payments\_by\_filter](/komodo-defi-framework/api/v20/lightning/payments/#lightning-network-payments) | | -| | [lightning::payments::send\_payment](/komodo-defi-framework/api/v20/lightning/payments/#lightning-network-payments) | | -| [list\_banned\_pubkeys](/komodo-defi-framework/api/legacy/list_banned_pubkeys/#list-banned-pubkeys) | | | -| | [list\_closed\_channels\_by\_filter](/komodo-defi-framework/api/v20/lightning/channels/#list-closed-channels-by-filter) | | -| | [list\_open\_channels\_by\_filter](/komodo-defi-framework/api/v20/lightning/channels/#list-open-channels-by-filter) | | -| | [max\_maker\_vol](/komodo-defi-framework/api/v20/swaps_and_orders/max_maker_vol/#max-maker-vol) | | -| [max\_taker\_vol](/komodo-defi-framework/api/legacy/max_taker_vol/#max-taker-vol) | | | -| | [message\_signing](/komodo-defi-framework/api/v20/utils/message_signing/#message-signing) | | -| [metrics](/komodo-defi-framework/api/legacy/metrics/#metrics) | | | -| [min\_trading\_vol](/komodo-defi-framework/api/legacy/min_trading_vol/#min-trading-vol) | | | -| [my\_balance](/komodo-defi-framework/api/legacy/my_balance/#my-balance) | | | -| [my\_orders](/komodo-defi-framework/api/legacy/my_orders/#my-orders) | | | -| [my\_recent\_swaps](/komodo-defi-framework/api/legacy/my_recent_swaps/#my-recent-swaps) | [my\_recent\_swaps](/komodo-defi-framework/api/v20/swaps_and_orders/my_recent_swaps/#my-recent-swaps) | | -| [my\_swap\_status](/komodo-defi-framework/api/legacy/my_swap_status/#my-swap-status) | | | -| [my\_tx\_history](/komodo-defi-framework/api/legacy/my_tx_history/#my-tx-history) | [my\_tx\_history](/komodo-defi-framework/api/v20/wallet/tx/my_tx_history/#my-tx-history) | | -| | [network\_enable](/komodo-defi-framework/api/v20/streaming/network_enable/#enable-network-streaming) | | -| | [open\_channel](/komodo-defi-framework/api/v20/lightning/channels/#open-channel) | | -| [order\_status](/komodo-defi-framework/api/legacy/order_status/#order-status) | | | -| | [order\_status\_enable](/komodo-defi-framework/api/v20/streaming/order_status_enable/#enable-order-status-streaming) | | -| [orderbook](/komodo-defi-framework/api/legacy/orderbook/#orderbook) | [orderbook](/komodo-defi-framework/api/v20/swaps_and_orders/orderbook/#orderbook) | | -| [orderbook\_depth](/komodo-defi-framework/api/legacy/orderbook_depth/#orderbook-depth) | | | -| [orders\_history\_by\_filter](/komodo-defi-framework/api/legacy/orders_history_by_filter/#orders-history-by-filter) | | | -| | [peer\_connection\_healthcheck](/komodo-defi-framework/api/v20/utils/peer_connection_healthcheck/#peer-connection-healthcheck) | | -| [recover\_funds\_of\_swap](/komodo-defi-framework/api/legacy/recover_funds_of_swap/#recover-funds-of-swap) | | | -| | [recreate\_swap\_data](/komodo-defi-framework/api/v20/swaps_and_orders/recreate_swap_data/#recreate-swap-data) | | -| | [refresh\_nft\_metadata](/komodo-defi-framework/api/v20/non_fungible_tokens/refresh_nft_metadata/#refresh-nft-metadata) | | -| | [remove\_node\_from\_version\_stat](/komodo-defi-framework/api/v20/utils/remove_node_from_version_stat/#remove-node-from-version-stat) | | -| [sell](/komodo-defi-framework/api/legacy/sell/#sell) | | | -| | [send\_asked\_data](/komodo-defi-framework/api/v20/utils/send_asked_data/#send-asked-data) | | -| [send\_raw\_transaction](/komodo-defi-framework/api/legacy/send_raw_transaction/#send-raw-transaction) | | | -| [set\_required\_confirmations](/komodo-defi-framework/api/legacy/set_required_confirmations/#set-required-confirmations) | | | -| [set\_requires\_notarization](/komodo-defi-framework/api/legacy/set_requires_notarization/#set-requires-notarization) | | | -| | [set\_swap\_transaction\_fee\_policy](/komodo-defi-framework/api/v20/wallet/fee_management/set_swap_transaction_fee_policy/#set-swap-transaction-fee-policy) | | -| [setprice](/komodo-defi-framework/api/legacy/setprice/#setprice) | | | -| [show\_priv\_key](/komodo-defi-framework/api/legacy/show_priv_key/#show-priv-key) | | | -| | [sign\_message](/komodo-defi-framework/api/v20/utils/message_signing/sign_message/#sign-message) | | -| | [sign\_raw\_transaction](/komodo-defi-framework/api/v20/wallet/tx/sign_raw_transaction/#sign-raw-transaction) | | -| | [start\_simple\_market\_maker\_bot](/komodo-defi-framework/api/v20/swaps_and_orders/start_simple_market_maker_bot/#start-simple-market-maker-bot) | | -| | [start\_version\_stat\_collection](/komodo-defi-framework/api/v20/utils/start_version_stat_collection/#start-version-stat-collection) | | -| [stop](/komodo-defi-framework/api/legacy/stop/#stop) | | | -| | [stop\_simple\_market\_maker\_bot](/komodo-defi-framework/api/v20/swaps_and_orders/stop_simple_market_maker_bot/#stop-simple-market-maker-bot) | | -| | [stop\_version\_stat\_collection](/komodo-defi-framework/api/v20/utils/stop_version_stat_collection/#stop-version-stat-collection) | | -| | [stream](/komodo-defi-framework/api/v20/streaming/network_enable/#enable-network-streaming) | | -| | [stream::disable](/komodo-defi-framework/api/v20/streaming/disable/#disable-streaming) | | -| | [stream::heartbeat::enable](/komodo-defi-framework/api/v20/streaming/heartbeat_enable/#enable-heartbeat-streaming) | | -| | [stream::orderbook::enable](/komodo-defi-framework/api/v20/streaming/orderbook_enable/#orderbook-streaming) | | -| | [swap\_status\_enable](/komodo-defi-framework/api/v20/streaming/swap_status_enable/#enable-swap-status-streaming) | | -| | [task](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/#task-eth-evm-activation) | | -| | [task::account\_balance::cancel](/komodo-defi-framework/api/v20/wallet/task_managed/account_balance/#task-account-balance) | | -| | [task::account\_balance::init](/komodo-defi-framework/api/v20/wallet/task_managed/account_balance/#task-account-balance) | | -| | [task::account\_balance::status](/komodo-defi-framework/api/v20/wallet/task_managed/account_balance/#task-account-balance) | | -| | [task::connect\_metamask::cancel](/komodo-defi-framework/api/v20/utils/task_connect_metamask/cancel/#cancel-meta-mask-connection-task) | | -| | [task::connect\_metamask::init](/komodo-defi-framework/api/v20/utils/task_connect_metamask/init/#initialise-meta-mask-connection-task) | | -| | [task::connect\_metamask::status](/komodo-defi-framework/api/v20/utils/task_connect_metamask/status/#meta-mask-connection-task-status) | | -| | [task::create\_new\_account::init](/komodo-defi-framework/api/v20/wallet/task_managed/create_new_account/#task-create-new-account) | | -| | [task::create\_new\_account::status](/komodo-defi-framework/api/v20/wallet/task_managed/create_new_account/#task-create-new-account) | | -| | [task::enable\_bch::cancel](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_bch/#task-bch-slp-activation) | | -| | [task::enable\_bch::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_bch/#task-bch-slp-activation) | | -| | [task::enable\_bch::status](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_bch/#task-bch-slp-activation) | | -| | [task::enable\_bch::user\_action](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_bch/#task-bch-slp-activation) | | -| | [task::enable\_eth::cancel](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/#task-eth-evm-activation) | | -| | [task::enable\_eth::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/#task-eth-evm-activation) | | -| | [task::enable\_eth::status](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/#task-eth-evm-activation) | | -| | [task::enable\_eth::user\_action](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/#task-eth-evm-activation) | | -| | [task::enable\_lightning::cancel](/komodo-defi-framework/api/v20/lightning/activation/#lightning-network-initialization-tasks) | | -| | [task::enable\_lightning::init](/komodo-defi-framework/api/v20/lightning/activation/#lightning-network-initialization-tasks) | | -| | [task::enable\_lightning::status](/komodo-defi-framework/api/v20/lightning/activation/#lightning-network-initialization-tasks) | | -| | [task::enable\_qtum::cancel](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_qtum/#task-qtum-activation) | | -| | [task::enable\_qtum::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_qtum/#task-qtum-activation) | | -| | [task::enable\_qtum::status](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_qtum/#task-qtum-activation) | | -| | [task::enable\_qtum::user\_action](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_qtum/#task-qtum-activation) | | -| | [task::enable\_tendermint::cancel](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/#task-tendermint-activation) | | -| | [task::enable\_tendermint::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/#task-tendermint-activation) | | -| | [task::enable\_tendermint::status](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/#task-tendermint-activation) | | -| | [task::enable\_tendermint::user\_action](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/#task-tendermint-activation) | | -| | [task::enable\_utxo::cancel](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/#task-utxo-activation) | | -| | [task::enable\_utxo::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/#task-utxo-activation) | | -| | [task::enable\_utxo::status](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/#task-utxo-activation) | | -| | [task::enable\_utxo::user\_action](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/#task-utxo-activation) | | -| | [task::enable\_z\_coin::cancel](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_z_coin/#task-z-coin-activation) | | -| | [task::enable\_z\_coin::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_z_coin/#task-z-coin-activation) | | -| | [task::enable\_z\_coin::status](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_z_coin/#task-z-coin-activation) | | -| | [task::enable\_z\_coin::user\_action](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_z_coin/#task-z-coin-activation) | | -| | [task::get\_new\_address::cancel](/komodo-defi-framework/api/v20/wallet/task_managed/get_new_address/#task-get-new-address) | | -| | [task::get\_new\_address::init](/komodo-defi-framework/api/v20/wallet/task_managed/get_new_address/#task-get-new-address) | | -| | [task::get\_new\_address::status](/komodo-defi-framework/api/v20/wallet/task_managed/get_new_address/#task-get-new-address) | | -| | [task::get\_new\_address::user\_action](/komodo-defi-framework/api/v20/wallet/task_managed/get_new_address/#task-get-new-address) | | -| | [task::init\_trezor::cancel](/komodo-defi-framework/api/v20/utils/task_init_trezor/cancel/#cancel-trezor-initialization-task) | | -| | [task::init\_trezor::init](/komodo-defi-framework/api/v20/utils/task_init_trezor/init/#komodo-de-fi-framework-method-task-init-trezor-init) | | -| | [task::init\_trezor::status](/komodo-defi-framework/api/v20/utils/task_init_trezor/status/#komodo-de-fi-framework-method-task-init-trezor-status) | | -| | [task::init\_trezor::user\_action](/komodo-defi-framework/api/v20/utils/task_init_trezor/user_action/#komodo-de-fi-framework-method-task-init-trezor-user-action) | | -| | [task::scan\_for\_new\_addresses::init](/komodo-defi-framework/api/v20/wallet/task_managed/scan_for_new_addresses/#task-scan-for-new-addresses) | | -| | [task::scan\_for\_new\_addresses::status](/komodo-defi-framework/api/v20/wallet/task_managed/scan_for_new_addresses/#task-scan-for-new-addresses) | | -| | [task::withdraw::cancel](/komodo-defi-framework/api/v20/wallet/task_managed/withdraw/#withdraw-tasks) | | -| | [task::withdraw::init](/komodo-defi-framework/api/v20/wallet/task_managed/withdraw/#withdraw-tasks) | | -| | [task::withdraw::status](/komodo-defi-framework/api/v20/wallet/task_managed/withdraw/#withdraw-tasks) | | -| [trade\_preimage](/komodo-defi-framework/api/legacy/trade_preimage/#trade-preimage) | [trade\_preimage](/komodo-defi-framework/api/v20/swaps_and_orders/trade_preimage/#trade-preimage) | | -| | [trezor\_connection\_status](/komodo-defi-framework/api/v20/utils/trezor_connection_status/#trezor-connection-status) | | -| | [trezor\_initialisation](/komodo-defi-framework/api/v20/utils/task_init_trezor/#trezor-initialisation) | | -| | [tx\_history\_enable](/komodo-defi-framework/api/v20/streaming/tx_history_enable/#enable-transaction-history-streaming) | | -| [unban\_pubkeys](/komodo-defi-framework/api/legacy/unban_pubkeys/#unban-pubkeys) | | | -| | [update\_channel](/komodo-defi-framework/api/v20/lightning/channels/#update-channel) | | -| [update\_maker\_order](/komodo-defi-framework/api/legacy/update_maker_order/#update-maker-order) | | | -| | [update\_nft](/komodo-defi-framework/api/v20/non_fungible_tokens/update_nft/#update-nft) | | -| | [update\_version\_stat\_collection](/komodo-defi-framework/api/v20/utils/update_version_stat_collection/#update-version-stat-collection) | | -| [validateaddress](/komodo-defi-framework/api/legacy/validateaddress/#validateaddress) | | | -| | [verify\_message](/komodo-defi-framework/api/v20/utils/message_signing/verify_message/#verify-message) | | -| [version](/komodo-defi-framework/api/legacy/version/#version) | | | -| | | [wc\_delete\_session](/komodo-defi-framework/api/v20-dev/wc_delete_session/#wc-delete-session) | -| | | [wc\_get\_session](/komodo-defi-framework/api/v20-dev/wc_get_session/#wc-get-session) | -| | | [wc\_get\_sessions](/komodo-defi-framework/api/v20-dev/wc_get_sessions/#wc-get-sessions) | -| | | [wc\_new\_connection](/komodo-defi-framework/api/v20-dev/wc_new_connection/#wc-new-connection) | -| | | [wc\_ping\_session](/komodo-defi-framework/api/v20-dev/wc_ping_session/#wc-ping-session) | -| [withdraw](/komodo-defi-framework/api/legacy/withdraw/#withdraw) | [withdraw](/komodo-defi-framework/api/v20/wallet/tx/withdraw/#withdraw) | | -| | [withdraw\_nft](/komodo-defi-framework/api/v20/non_fungible_tokens/withdraw_nft/#withdraw-nfts) | | -| | [z\_coin\_tx\_history](/komodo-defi-framework/api/v20/wallet/tx/zhtlc_tx_history/#zhtlc-coin-transaction-history) | | +| Legacy | v2.0 (release) | v2.0 (dev) | +| ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| | | [1inch\_v6\_0\_classic\_swap\_create](/komodo-defi-framework/api/v20-dev/one_inch_v6_0_classic_swap_create/#1inch-v6-0-classic-swap-create) | +| | | [1inch\_v6\_0\_classic\_swap\_liquidity\_sources](/komodo-defi-framework/api/v20-dev/one_inch_v6_0_classic_swap_liquidity_sources/#1inch-v6-0-classic-swap-liquidity-sources) | +| | | [1inch\_v6\_0\_classic\_swap\_quote](/komodo-defi-framework/api/v20-dev/one_inch_v6_0_classic_swap_quote/#1inch-v6-0-classic-swap-quote) | +| | | [1inch\_v6\_0\_classic\_swap\_tokens](/komodo-defi-framework/api/v20-dev/one_inch_v6_0_classic_swap_tokens/#1inch-v6-0-classic-swap-tokens) | +| [active\_swaps](/komodo-defi-framework/api/legacy/active_swaps/#active-swaps) | [active\_swaps](/komodo-defi-framework/api/v20/swaps_and_orders/active_swaps/#active-swaps) | | +| | [add\_node\_to\_version\_stat](/komodo-defi-framework/api/v20/utils/add_node_to_version_stat/#add-node-to-version-stat) | | +| [all\_swaps\_uuids\_by\_filter](/komodo-defi-framework/api/legacy/all_swaps_uuids_by_filter/#all-swaps-uuids-by-filter) | | | +| | | [approve\_token](/komodo-defi-framework/api/v20-dev/approve_token/#approve-token) | +| [ban\_pubkey](/komodo-defi-framework/api/legacy/ban_pubkey/#ban-pubkey) | | | +| [best\_orders](/komodo-defi-framework/api/legacy/best_orders/#best-orders) | [best\_orders](/komodo-defi-framework/api/v20/swaps_and_orders/best_orders/#best-orders) | | +| [buy](/komodo-defi-framework/api/legacy/buy/#buy) | | | +| [cancel\_all\_orders](/komodo-defi-framework/api/legacy/cancel_all_orders/#cancel-all-orders) | | | +| [cancel\_order](/komodo-defi-framework/api/legacy/cancel_order/#cancel-order) | | | +| | [change\_mnemonic\_password](/komodo-defi-framework/api/v20/utils/change_mnemonic_password/#change-mnemonic-password) | | +| | [clear\_nft\_db](/komodo-defi-framework/api/v20/non_fungible_tokens/clear_nft_db/#clear-nft-db) | | +| [coins\_needed\_for\_kick\_start](/komodo-defi-framework/api/legacy/coins_needed_for_kick_start/#coins-needed-for-kick-start) | | | +| [consolidate\_utxos](/komodo-defi-framework/api/legacy/consolidate_utxos/#consolidate-utxos) | [consolidate\_utxos](/komodo-defi-framework/api/v20/wallet/consolidate_utxos/#consolidate-utxos) | | +| [convert\_utxo\_address](/komodo-defi-framework/api/legacy/convert_utxo_address/#convert-utxo-address) | | | +| [convertaddress](/komodo-defi-framework/api/legacy/convertaddress/#convertaddress) | | | +| | [delete\_wallet](/komodo-defi-framework/api/v20/wallet/delete_wallet/#delete-wallet) | | +| [disable\_coin](/komodo-defi-framework/api/legacy/disable_coin/#disable-coin) | | | +| [electrum](/komodo-defi-framework/api/legacy/coin_activation/#electrum) | | | +| | [enable\_bch\_with\_tokens](/komodo-defi-framework/api/v20/coin_activation/enable_bch_with_tokens/#enable-bch-with-tokens) | | +| | [enable\_erc20](/komodo-defi-framework/api/v20/coin_activation/enable_erc20/#enable-erc20) | | +| | [enable\_eth\_with\_tokens](/komodo-defi-framework/api/v20/coin_activation/enable_eth_with_tokens/#enable-eth-with-tokens) | | +| | [enable\_nft](/komodo-defi-framework/api/v20/non_fungible_tokens/enable_nft/#enable-nft) | | +| | [enable\_tendermint\_token](/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_token/#enable-tendermint-token) | | +| | [enable\_tendermint\_with\_assets](/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_with_assets/#enable-tendermint-with-assets) | | +| | [experimental::staking::claim\_rewards](/komodo-defi-framework/api/v20/wallet/staking/claim_rewards/#claim-rewards) | | +| | [experimental::staking::delegate](/komodo-defi-framework/api/v20/wallet/staking/delegate/#delegate) | | +| | [experimental::staking::query::delegations](/komodo-defi-framework/api/v20/wallet/staking/delegations/#delegations) | | +| | [experimental::staking::query::ongoing\_undelegations](/komodo-defi-framework/api/v20/wallet/staking/ongoing_delegations/#ongoing-undelegations) | | +| | [experimental::staking::query::validators](/komodo-defi-framework/api/v20/wallet/staking/validators/#validators) | | +| | [experimental::staking::undelegate](/komodo-defi-framework/api/v20/wallet/staking/undelegate/#undelegate) | | +| | [fetch\_utxos](/komodo-defi-framework/api/v20/wallet/fetch_utxos/#fetch-utxos) | | +| | [get\_current\_mtp](/komodo-defi-framework/api/v20/utils/get_current_mtp/#get-current-mtp) | | +| [get\_directly\_connected\_peers](/komodo-defi-framework/api/legacy/get_directly_connected_peers/#get-directly-connected-peers) | | | +| [get\_enabled\_coins](/komodo-defi-framework/api/legacy/get_enabled_coins/#get-enabled-coins) | [get\_enabled\_coins](/komodo-defi-framework/api/v20/utils/get_enabled_coins/#get-enabled-coins) | | +| | [get\_eth\_estimated\_fee\_per\_gas](/komodo-defi-framework/api/v20/wallet/fee_management/get_eth_estimated_fee_per_gas/#get-eth-estimated-fee-per-gas) | | +| [get\_gossip\_mesh](/komodo-defi-framework/api/legacy/get_gossip_mesh/#get-gossip-mesh) | | | +| [get\_gossip\_peer\_topics](/komodo-defi-framework/api/legacy/get_gossip_peer_topics/#get-gossip-peer-topics) | | | +| [get\_gossip\_topic\_peers](/komodo-defi-framework/api/legacy/get_gossip_topic_peers/#get-gossip-topic-peers) | | | +| | [get\_locked\_amount](/komodo-defi-framework/api/v20/swaps_and_orders/get_locked_amount/#get-locked-amount) | | +| | [get\_mnemonic](/komodo-defi-framework/api/v20/utils/get_mnemonic/#get-mnemonic) | | +| [get\_my\_peer\_id](/komodo-defi-framework/api/legacy/get_my_peer_id/#get-my-peer-id) | | | +| | [get\_nft\_list](/komodo-defi-framework/api/v20/non_fungible_tokens/get_nft_list/#get-a-list-of-nfts) | | +| | [get\_nft\_metadata](/komodo-defi-framework/api/v20/non_fungible_tokens/get_nft_metadata/#get-nft-metadata) | | +| | [get\_nft\_transfers](/komodo-defi-framework/api/v20/non_fungible_tokens/get_nft_transfers/#get-a-list-of-nft-transfers) | | +| | [get\_private\_keys](/komodo-defi-framework/api/v20/wallet/get_private_keys/#get-private-keys) | | +| | [get\_public\_key](/komodo-defi-framework/api/v20/utils/get_public_key/#get-public-key) | | +| | [get\_public\_key\_hash](/komodo-defi-framework/api/v20/utils/get_public_key_hash/#get-public-key-hash) | | +| | [get\_raw\_transaction](/komodo-defi-framework/api/v20/wallet/tx/get_raw_transaction/#get-raw-transaction) | | +| [get\_relay\_mesh](/komodo-defi-framework/api/legacy/get_relay_mesh/#get-relay-mesh) | | | +| | [get\_shared\_db\_id](/komodo-defi-framework/api/v20/utils/get_shared_db_id/#get-shared-db-id) | | +| | [get\_swap\_transaction\_fee\_policy](/komodo-defi-framework/api/v20/wallet/fee_management/get_swap_transaction_fee_policy/#get-swap-transaction-fee-policy) | | +| | | [get\_token\_allowance](/komodo-defi-framework/api/v20-dev/get_token_allowance/#get-token-allowance) | +| | [get\_token\_info](/komodo-defi-framework/api/v20/utils/get_token_info/#get-token-info) | | +| [get\_trade\_fee](/komodo-defi-framework/api/legacy/get_trade_fee/#get-trade-fee) | | | +| | [get\_wallet\_names](/komodo-defi-framework/api/v20/wallet/get_wallet_names/#get-wallet-names) | | +| [import\_swaps](/komodo-defi-framework/api/legacy/import_swaps/#import-swaps) | | | +| [kmd\_rewards\_info](/komodo-defi-framework/api/legacy/kmd_rewards_info/#kmd-rewards-info) | | | +| | [lightning::channels::open\_channel](/komodo-defi-framework/api/v20/lightning/channels/#lightning-network-channels) | | +| | [lightning::nodes::connect\_to\_node](/komodo-defi-framework/api/v20/lightning/nodes/#lightning-network-nodes) | | +| | [lightning::payments::generate\_invoice](/komodo-defi-framework/api/v20/lightning/payments/#lightning-network-payments) | | +| [list\_banned\_pubkeys](/komodo-defi-framework/api/legacy/list_banned_pubkeys/#list-banned-pubkeys) | | | +| | [max\_maker\_vol](/komodo-defi-framework/api/v20/swaps_and_orders/max_maker_vol/#max-maker-vol) | | +| [max\_taker\_vol](/komodo-defi-framework/api/legacy/max_taker_vol/#max-taker-vol) | | | +| | [message\_signing](/komodo-defi-framework/api/v20/utils/message_signing/#message-signing) | | +| [metrics](/komodo-defi-framework/api/legacy/metrics/#metrics) | | | +| [min\_trading\_vol](/komodo-defi-framework/api/legacy/min_trading_vol/#min-trading-vol) | | | +| [my\_balance](/komodo-defi-framework/api/legacy/my_balance/#my-balance) | | | +| [my\_orders](/komodo-defi-framework/api/legacy/my_orders/#my-orders) | | | +| [my\_recent\_swaps](/komodo-defi-framework/api/legacy/my_recent_swaps/#my-recent-swaps) | [my\_recent\_swaps](/komodo-defi-framework/api/v20/swaps_and_orders/my_recent_swaps/#my-recent-swaps) | | +| [my\_swap\_status](/komodo-defi-framework/api/legacy/my_swap_status/#my-swap-status) | | | +| [my\_tx\_history](/komodo-defi-framework/api/legacy/my_tx_history/#my-tx-history) | [my\_tx\_history](/komodo-defi-framework/api/v20/wallet/tx/my_tx_history/#my-tx-history) | | +| [order\_status](/komodo-defi-framework/api/legacy/order_status/#order-status) | | | +| [orderbook](/komodo-defi-framework/api/legacy/orderbook/#orderbook) | [orderbook](/komodo-defi-framework/api/v20/swaps_and_orders/orderbook/#orderbook) | | +| [orderbook\_depth](/komodo-defi-framework/api/legacy/orderbook_depth/#orderbook-depth) | | | +| [orders\_history\_by\_filter](/komodo-defi-framework/api/legacy/orders_history_by_filter/#orders-history-by-filter) | | | +| | [peer\_connection\_healthcheck](/komodo-defi-framework/api/v20/utils/peer_connection_healthcheck/#peer-connection-healthcheck) | | +| [recover\_funds\_of\_swap](/komodo-defi-framework/api/legacy/recover_funds_of_swap/#recover-funds-of-swap) | | | +| | [recreate\_swap\_data](/komodo-defi-framework/api/v20/swaps_and_orders/recreate_swap_data/#recreate-swap-data) | | +| | [refresh\_nft\_metadata](/komodo-defi-framework/api/v20/non_fungible_tokens/refresh_nft_metadata/#refresh-nft-metadata) | | +| | [remove\_node\_from\_version\_stat](/komodo-defi-framework/api/v20/utils/remove_node_from_version_stat/#remove-node-from-version-stat) | | +| [sell](/komodo-defi-framework/api/legacy/sell/#sell) | | | +| | [send\_asked\_data](/komodo-defi-framework/api/v20/utils/send_asked_data/#send-asked-data) | | +| [send\_raw\_transaction](/komodo-defi-framework/api/legacy/send_raw_transaction/#send-raw-transaction) | | | +| [set\_required\_confirmations](/komodo-defi-framework/api/legacy/set_required_confirmations/#set-required-confirmations) | | | +| [set\_requires\_notarization](/komodo-defi-framework/api/legacy/set_requires_notarization/#set-requires-notarization) | | | +| | [set\_swap\_transaction\_fee\_policy](/komodo-defi-framework/api/v20/wallet/fee_management/set_swap_transaction_fee_policy/#set-swap-transaction-fee-policy) | | +| [setprice](/komodo-defi-framework/api/legacy/setprice/#setprice) | | | +| [show\_priv\_key](/komodo-defi-framework/api/legacy/show_priv_key/#show-priv-key) | | | +| | [sign\_message](/komodo-defi-framework/api/v20/utils/message_signing/sign_message/#sign-message) | | +| | [sign\_raw\_transaction](/komodo-defi-framework/api/v20/wallet/tx/sign_raw_transaction/#sign-raw-transaction) | | +| | [start\_simple\_market\_maker\_bot](/komodo-defi-framework/api/v20/swaps_and_orders/start_simple_market_maker_bot/#start-simple-market-maker-bot) | | +| | [start\_version\_stat\_collection](/komodo-defi-framework/api/v20/utils/start_version_stat_collection/#start-version-stat-collection) | | +| [stop](/komodo-defi-framework/api/legacy/stop/#stop) | | | +| | [stop\_simple\_market\_maker\_bot](/komodo-defi-framework/api/v20/swaps_and_orders/stop_simple_market_maker_bot/#stop-simple-market-maker-bot) | | +| | [stop\_version\_stat\_collection](/komodo-defi-framework/api/v20/utils/stop_version_stat_collection/#stop-version-stat-collection) | | +| | [stream::balance::enable](/komodo-defi-framework/api/v20/streaming/balance_enable/#stream-balance-enable) | | +| | [stream::disable](/komodo-defi-framework/api/v20/streaming/disable/#stream-disable) | | +| | [stream::fee\_estimator::enable](/komodo-defi-framework/api/v20/streaming/fee_estimator/#stream-fee-estimator-enable) | | +| | [stream::heartbeat::enable](/komodo-defi-framework/api/v20/streaming/heartbeat_enable/#stream-heartbeat-enable) | | +| | [stream::network::enable](/komodo-defi-framework/api/v20/streaming/network_enable/#stream-network-enable) | | +| | [stream::order\_status::enable](/komodo-defi-framework/api/v20/streaming/order_status_enable/#stream-order-status-enable) | | +| | [stream::orderbook::enable](/komodo-defi-framework/api/v20/streaming/orderbook_enable/#stream-orderbook-enable) | | +| | [stream::swap\_status::enable](/komodo-defi-framework/api/v20/streaming/swap_status_enable/#stream-swap-status-enable) | | +| | [stream::tx\_history::enable](/komodo-defi-framework/api/v20/streaming/tx_history_enable/#stream-tx-history-enable) | | +| | [task::account\_balance::init](/komodo-defi-framework/api/v20/wallet/task_managed/account_balance/#task-account-balance-init) | | +| | [task::connect\_metamask](/komodo-defi-framework/api/v20/utils/task_connect_metamask/#task-connect-metamask) | | +| | [task::connect\_metamask::cancel](/komodo-defi-framework/api/v20/utils/task_connect_metamask/cancel/#task-connect-metamask-cancel) | | +| | [task::connect\_metamask::init](/komodo-defi-framework/api/v20/utils/task_connect_metamask/init/#task-connect-metamask-init) | | +| | [task::connect\_metamask::status](/komodo-defi-framework/api/v20/utils/task_connect_metamask/status/#task-connect-metamask-status) | | +| | [task::create\_new\_account::init](/komodo-defi-framework/api/v20/wallet/task_managed/create_new_account/#task-create-new-account-init) | | +| | [task::enable\_bch::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_bch/#task-enable-bch-init) | | +| | [task::enable\_eth::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/#task-enable-eth-init) | | +| | [task::enable\_lightning::init](/komodo-defi-framework/api/v20/lightning/activation/#lightning-network-initialization-tasks) | | +| | [task::enable\_qtum::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_qtum/#task-enable-qtum-init) | | +| | [task::enable\_sia::cancel](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/cancel/#task-enable-sia-cancel) | | +| | [task::enable\_sia::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/init/#task-enable-sia-init) | | +| | [task::enable\_sia::status](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/status/#task-enable-sia-status) | | +| | [task::enable\_sia::user\_action](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/user_action/#task-enable-sia-user-action) | | +| | [task::enable\_tendermint::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/#task-enable-tendermint-init) | | +| | [task::enable\_utxo::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/#task-enable-utxo-init) | | +| | [task::enable\_z\_coin::init](/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_z_coin/#task-enable-z-coin-init) | | +| | [task::get\_new\_address::init](/komodo-defi-framework/api/v20/wallet/task_managed/get_new_address/#task-get-new-address-init) | | +| | [task::init\_trezor::cancel](/komodo-defi-framework/api/v20/utils/task_init_trezor/cancel/#task-init-trezor-cancel) | | +| | [task::init\_trezor::init](/komodo-defi-framework/api/v20/utils/task_init_trezor/init/#task-init-trezor-init) | | +| | [task::init\_trezor::status](/komodo-defi-framework/api/v20/utils/task_init_trezor/status/#task-init-trezor-status) | | +| | [task::init\_trezor::user\_action](/komodo-defi-framework/api/v20/utils/task_init_trezor/user_action/#task-init-trezor-user-action) | | +| | [task::scan\_for\_new\_addresses::init](/komodo-defi-framework/api/v20/wallet/task_managed/scan_for_new_addresses/#task-scan-for-new-addresses-init) | | +| | [task::withdraw::init](/komodo-defi-framework/api/v20/wallet/task_managed/withdraw/#task-withdraw-init) | | +| [trade\_preimage](/komodo-defi-framework/api/legacy/trade_preimage/#trade-preimage) | [trade\_preimage](/komodo-defi-framework/api/v20/swaps_and_orders/trade_preimage/#trade-preimage) | | +| | [trezor\_connection\_status](/komodo-defi-framework/api/v20/utils/trezor_connection_status/#trezor-connection-status) | | +| | [trezor\_initialisation](/komodo-defi-framework/api/v20/utils/task_init_trezor/#trezor-initialisation) | | +| [unban\_pubkeys](/komodo-defi-framework/api/legacy/unban_pubkeys/#unban-pubkeys) | | | +| [update\_maker\_order](/komodo-defi-framework/api/legacy/update_maker_order/#update-maker-order) | | | +| | [update\_nft](/komodo-defi-framework/api/v20/non_fungible_tokens/update_nft/#update-nft) | | +| | [update\_version\_stat\_collection](/komodo-defi-framework/api/v20/utils/update_version_stat_collection/#update-version-stat-collection) | | +| [validateaddress](/komodo-defi-framework/api/legacy/validateaddress/#validateaddress) | | | +| | [verify\_message](/komodo-defi-framework/api/v20/utils/message_signing/verify_message/#verify-message) | | +| [version](/komodo-defi-framework/api/legacy/version/#version) | | | +| | | [wc\_delete\_session](/komodo-defi-framework/api/v20-dev/wc_delete_session/#wc-delete-session) | +| | | [wc\_get\_session](/komodo-defi-framework/api/v20-dev/wc_get_session/#wc-get-session) | +| | | [wc\_get\_sessions](/komodo-defi-framework/api/v20-dev/wc_get_sessions/#wc-get-sessions) | +| | | [wc\_new\_connection](/komodo-defi-framework/api/v20-dev/wc_new_connection/#wc-new-connection) | +| | | [wc\_ping\_session](/komodo-defi-framework/api/v20-dev/wc_ping_session/#wc-ping-session) | +| [withdraw](/komodo-defi-framework/api/legacy/withdraw/#withdraw) | [withdraw](/komodo-defi-framework/api/v20/wallet/tx/withdraw/#withdraw) | | +| | [withdraw\_nft](/komodo-defi-framework/api/v20/non_fungible_tokens/withdraw_nft/#withdraw-nfts) | | +| | [z\_coin\_tx\_history](/komodo-defi-framework/api/v20/wallet/tx/zhtlc_tx_history/#zhtlc-coin-transaction-history) | | diff --git a/src/pages/komodo-defi-framework/api/legacy/coins_needed_for_kick_start/index.mdx b/src/pages/komodo-defi-framework/api/legacy/coins_needed_for_kick_start/index.mdx index bb9b6dcd5..53199e630 100644 --- a/src/pages/komodo-defi-framework/api/legacy/coins_needed_for_kick_start/index.mdx +++ b/src/pages/komodo-defi-framework/api/legacy/coins_needed_for_kick_start/index.mdx @@ -9,39 +9,14 @@ If the Komodo DeFi Framework API is stopped while making a swap/having the activ ## Arguments -| Structure | Type | Description | -| --------- | ---- | ----------- | -| (none) | | | + #### Response -| Structure | Type | Description | -| --------- | ---------------- | ------------------------------------------------------------------------ | -| result | array of strings | tickers of coins that should be activated to kick-start swaps and orders | + #### ๐Ÿ“Œ Examples -#### Command + - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "coins_needed_for_kick_start" - } - ``` - - - - #### Response (BTC and KMD should be activated ASAP in this case) - - ```json - { "result": ["BTC", "KMD"] } - ``` - - #### Response (no swaps and orders waiting to be started) - - ```json - { "result": [] } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/legacy/get_enabled_coins/index.mdx b/src/pages/komodo-defi-framework/api/legacy/get_enabled_coins/index.mdx index a354d01af..8473579e6 100644 --- a/src/pages/komodo-defi-framework/api/legacy/get_enabled_coins/index.mdx +++ b/src/pages/komodo-defi-framework/api/legacy/get_enabled_coins/index.mdx @@ -3,8 +3,6 @@ export const description = "The get_enabled_coins method returns data of coins t # get\_enabled\_coins -**get\_enabled\_coins** - The `get_enabled_coins` method returns data of coins that are currently enabled on the user's Komodo DeFi Framework API node. @@ -12,68 +10,16 @@ The `get_enabled_coins` method returns data of coins that are currently enabled If you need to get the addresses for coins and have not set `enable_hd` in your [MM2.json file](/komodo-defi-framework/setup/configure-mm2-json/), use the v1 method. -## Arguments - -| Structure | Type | Description | -| --------- | ---- | ----------- | -| (none) | | | - -#### Response +### Request Parameters -| Structure | Type | Description | -| -------------- | ---------------- | -------------------------------------- | -| result | array of objects | tickers and addresses of enabled coins | -| result.address | string | the user's address for this coin | -| result.ticker | string | the ticker name of this coin | + -#### ๐Ÿ“Œ Examples +### Response Parameters -#### Command + - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "get_enabled_coins" - } - ``` - +### ๐Ÿ“Œ Examples - - #### Response + - ```json - { - "result": [ - { - "address": "1WxswvLF2HdaDr4k77e92VjaXuPQA8Uji", - "ticker": "BTC" - }, - { - "address": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW", - "ticker": "PIZZA" - }, - { - "address": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW", - "ticker": "BEER" - }, - { - "address": "0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29", - "ticker": "ETH" - }, - { - "address": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW", - "ticker": "ETOMIC" - }, - { - "address": "0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29", - "ticker": "DEC8" - }, - { - "address": "0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29", - "ticker": "BAT" - } - ] - } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/legacy/get_my_peer_id/index.mdx b/src/pages/komodo-defi-framework/api/legacy/get_my_peer_id/index.mdx index b3cd8c268..55a1cf84a 100644 --- a/src/pages/komodo-defi-framework/api/legacy/get_my_peer_id/index.mdx +++ b/src/pages/komodo-defi-framework/api/legacy/get_my_peer_id/index.mdx @@ -3,41 +3,18 @@ export const description = "The get_my_peer_id method returns your unique identi # get\_my\_peer\_id -**get\_my\_peer\_id** +The `get_my_peer_id` method returns your unique identifying Peer ID on the network. -The `get_my_peer_id` method returns your unique identifying Peer ID on the network +### Request Parameters -## Arguments + -| Structure | Type | Description | -| --------- | ---- | ----------- | -| (none) | | | +### Response Parameters -#### Response + -| Structure | Type | Description | -| --------- | ------ | -------------------------------------- | -| PeerID | string | The PeerID of your node on the network | +### ๐Ÿ“Œ Examples -#### ๐Ÿ“Œ Examples + -#### Command - - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "get_my_peer_id" - } - ``` - - - - #### Response (success) - - ```json - { - "result": "12D3KooWS9MeuFZhJCfQTntwbTVnXMAJpz9Tvd1XYFuURrGqnJVR" - } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/legacy/my_tx_history/index.mdx b/src/pages/komodo-defi-framework/api/legacy/my_tx_history/index.mdx index 64e28bd34..470503a61 100644 --- a/src/pages/komodo-defi-framework/api/legacy/my_tx_history/index.mdx +++ b/src/pages/komodo-defi-framework/api/legacy/my_tx_history/index.mdx @@ -16,146 +16,34 @@ The coin that is used must have `tx_history` set to true in its [enable](/komodo ## Arguments -| Structure | Type | Description | -| ------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| coin | string | the name of the coin for the history request | -| limit | number | limits the number of returned transactions; ignored if `max = true` | -| max | bool | whether to return all available records; defaults to `false` | -| from\_id | string | Komodo DeFi Framework API will skip records until it reaches this ID, skipping the `from_id` as well; track the `internal_id` of the last displayed transaction to find the value of this field for the next page | -| page\_number | number | Komodo DeFi Framework API will return limit swaps from the selected page; This param will be ignored if from\_uuid is set. | + ## Response -| Structure | Type | Description | -| -------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| transactions | array of objects | transactions data | -| from\_id | string | the from\_id specified in the request; this value is null if from\_id was not set | -| skipped | number | the number of skipped records (i.e. the position of `from_id` in the list + 1); this value is 0 if `from_id` was not set | -| limit | number | the limit that was set in the request; note that the actual number of transactions can differ from the specified limit (e.g. on the last page) | -| total | number | the total number of transactions available | -| page\_number | number | the page\_number that was set in the request | -| total\_pages | number | total pages available with the selected limit | -| current\_block | number | the number of the latest block of coin blockchain | -| sync\_status | object | A standard [SyncStatus](/komodo-defi-framework/api/common_structures/#sync-status) object. Provides the information that helps to track the progress of transaction history preloading at background | + #### ๐Ÿ“Œ Examples #### Command - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "my_tx_history", - "coin": "DOC", - "limit": 1, - "from_id": "1d5c1b67f8ebd3fc480e25a1d60791bece278f5d1245c5f9474c91a142fee8e1" - } - ``` - + #### Command (max = true) - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "my_tx_history", - "coin": "DOC", - "max": true, - "from_id": "1d5c1b67f8ebd3fc480e25a1d60791bece278f5d1245c5f9474c91a142fee8e1" - } - ``` - + #### Response (success) - ```json - { - "result": { - "current_block": 172418, - "from_id": null, - "limit": 1, - "skipped": 0, - "sync_status": { - "additional_info": { - "transactions_left": 126 - }, - "state": "InProgress" - }, - "total": 5915, - "total_pages": 5915, - "page_number": null, - "transactions": [ - { - "block_height": 172409, - "coin": "ETOMIC", - "confirmations": 10, - "fee_details": { - "type": "Utxo", - "amount": "0.00001" - }, - "from": ["R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW"], - "internal_id": "903e5d71b8717205314a71055fe8bbb868e7b76d001fbe813a34bd71ff131e93", - "my_balance_change": "-0.10001", - "received_by_me": "0.8998513", - "spent_by_me": "0.9998613", - "timestamp": 1566539526, - "to": [ - "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW", - "bJrMTiiRiLHJHc6RKQgesKTg1o9VVuKwT5" - ], - "total_amount": "0.9998613", - "tx_hash": "903e5d71b8717205314a71055fe8bbb868e7b76d001fbe813a34bd71ff131e93", - "tx_hex": "0400008085202f8901a242dc691de64c732e823ed0a4d8cfa6a230f8e31bc9bd21499009f1a90b855a010000006b483045022100d83113119004ac0504f812a853a831039dfc4b0bc1cb863d2c7a94c0670f07e902206af87b846b18c0d5e38bd874d43918e0400e4b6b838ab0793f5976843daa20cd012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff02809698000000000017a9144327a5516b28f66249576c18d15debf6dfbd1124876a105d05000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac047f5f5d000000000000000000000000000000" - } - ] - } - } - ``` + #### Response (Sync in progress for UTXO coins) - ```json - { - "result": { - "current_block": 148300, - "from_id": null, - "limit": 0, - "skipped": 0, - "sync_status": { - "additional_info": { - "transactions_left": 1656 - }, - "state": "InProgress" - }, - "total": 3956, - "transactions": [] - } - } - ``` + #### Response (Sync in progress for ETH/ERC20 coins) - ```json - { - "result": { - "current_block": 8039935, - "from_id": null, - "limit": 0, - "skipped": 0, - "sync_status": { - "additional_info": { - "blocks_left": 2158991 - }, - "state": "InProgress" - }, - "total": 0, - "transactions": [] - } - } - ``` + #### Response (Successful result in case of ETH/ERC20 coins) @@ -245,90 +133,38 @@ The coin that is used must have `tx_history` set to true in its [enable](/komodo ``` +#### Command (SIA protocol) + + + + + + + +### Error Responses + ### Error - Coin not active - ```json - { - "mmrpc": "2.0", - "error": "TTT-SLP", - "error_path": "my_tx_history_v2.lp_coins", - "error_trace": "my_tx_history_v2:389] lp_coins:2847]", - "error_type": "CoinIsNotActive", - "error_data": "TTT-SLP", - "id": null - } - ``` + ### Error - Coin not compatible - ```json - { - "mmrpc": "2.0", - "error": "TTT-SLP", - "error_path": "my_tx_history_v2", - "error_trace": "my_tx_history_v2:336]", - "error_type": "NotSupportedFor", - "error_data": "TTT-SLP", - "id": null - } - ``` + ### Error - Coin enabled without tx\_history = true - ```json - { - "mmrpc": "2.0", - "error": "Storage is not initialized for TTT-SLP", - "error_path": "my_tx_history_v2", - "error_trace": "my_tx_history_v2:343]", - "error_type": "StorageIsNotInitialized", - "error_data": "Storage is not initialized for TTT-SLP", - "id": null - } - ``` + ### Error - Local database failed - ```json - { - "mmrpc": "2.0", - "error": "SqliteFailure(Error { code: Unknown, extended_code: 1 }, Some(\"no such column: block_height\"))", - "error_path": "my_tx_history_v2.sql_tx_history_storage", - "error_trace": "my_tx_history_v2:351] sql_tx_history_storage:472]", - "error_type": "StorageError", - "error_data": "SqliteFailure(Error { code: Unknown, extended_code: 1 }, Some(\"no such column: block_height\"))", - "id": null - } - ``` + #### Error - From ID not found - ```json - { - "error": "lp_coins:1011] from_id 1d5c1b67f8ebd3fc480e25a1d60791bece278f5d1245c5f9474c91a142fee8e2 is not found" - } - ``` + #### Error - History too large - ```json - { - "result": { - "current_block": 144753, - "from_id": null, - "limit": 0, - "skipped": 0, - "sync_status": { - "additional_info": { - "code": -1, - "message": "Got `history too large` error from Electrum server. History is not available" - }, - "state": "Error" - }, - "total": 0, - "transactions": [] - } - } - ``` + diff --git a/src/pages/komodo-defi-framework/api/legacy/send_raw_transaction/index.mdx b/src/pages/komodo-defi-framework/api/legacy/send_raw_transaction/index.mdx index 145c87631..caaf787fd 100644 --- a/src/pages/komodo-defi-framework/api/legacy/send_raw_transaction/index.mdx +++ b/src/pages/komodo-defi-framework/api/legacy/send_raw_transaction/index.mdx @@ -1,46 +1,34 @@ export const title = "Komodo DeFi Framework Method: Send Raw Transaction"; -export const description = "The send_raw_transaction method broadcasts the transaction to the network of selected coin."; +export const description = "The send_raw_transaction method broadcasts the transaction to the network of the selected coin."; -# send\_raw\_transaction +# Send Raw Transaction -**send\_raw\_transaction coin tx\_hex** +## send\_raw\_transaction {{label: 'send_raw_transaction', tag: 'API-v1'}} -The `send_raw_transaction` method broadcasts the transaction to the network of selected coin. +The `send_raw_transaction` method broadcasts the transaction to the network of the selected coin. -## Arguments +### Request arguments -| Structure | Type | Description | -| --------- | ------ | ------------------------------------------------------------------------------------------------- | -| coin | string | the name of the coin network on which to broadcast the transaction | -| tx\_hex | string | the transaction bytes in hexadecimal format; this is typically generated by the `withdraw` method | + -## Response +One of `tx_hex` or `tx_json` is required. -| Structure | Type | Description | -| --------- | ------ | ------------------------------------- | -| tx\_hash | string | the hash of the broadcast transaction | +### Response parameters -#### ๐Ÿ“Œ Examples + -#### Command +#### ๐Ÿ“Œ Example - - ```json - { - "method": "send_raw_transaction", - "coin": "KMD", - "tx_hex": "0400008085202f8902d6a5b976db5e5c9e8f9ead50713b25f22cd061edc8ff0ff1049fd2cd775ba087000000006b483045022100bf2073c1ecfef3fc78f272045f46a722591401f61c2d2fac87fc474a17df7c3102200ca1bd0664ba75f3383e5cbbe96127ad534a86238dbea256e000b0fe2067ab8c012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffffd04d4e07ac5dacd08fb76e08d2a435fc4fe2b16eb0158695c820b44f42f044cb010000006a47304402200a0c21e8c0ae4a740f3663fe08aeff02cea6495157d531045b58d2dd79fb802702202f80dddd264db33f55e49799363997a175d39a91242a95f268c40f7ced97030b012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788acc3b3ca27000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac00000000000000000000000000000000000000", - "userpass": "RPC_UserP@SSW0RD" - } - ``` - +#### Request - - #### Response (success) + - ```json - { - "tx_hash": "0b024ea6997e16387c0931de9f203d534c6b2b8500e4bda2df51a36b52a3ef33" - } - ``` - + + +#### Request (SIA protocol) + +For SIA protocol withdrawals, instead of using the `tx_hex`, we use the `tx_json` value returned from the v1 [withdraw](/komodo-defi-framework/api/legacy/withdraw/#withdraw) method, or the non-task v2 [withdraw](/komodo-defi-framework/api/v20/wallet/tx/withdraw/#withdraw) method. + + + + diff --git a/src/pages/komodo-defi-framework/api/legacy/validateaddress/index.mdx b/src/pages/komodo-defi-framework/api/legacy/validateaddress/index.mdx index 4f277f142..6d5a45a02 100644 --- a/src/pages/komodo-defi-framework/api/legacy/validateaddress/index.mdx +++ b/src/pages/komodo-defi-framework/api/legacy/validateaddress/index.mdx @@ -9,63 +9,14 @@ The `validateaddress` method checks if an input string is a valid address of the ## Arguments -| Structure | Type | Description | -| --------- | ------ | -------------------------------- | -| coin | string | the coin to validate address for | -| address | string | the input string to validate | + ## Response -| Structure | Type | Description | -| --------- | ----------------- | ------------------------------------------------------------------------------ | -| is\_valid | bool | Whether input string is a valid coin address. | -| reason | string (optional) | Only present if not valid. The reason why input string is not a valid address. | + #### ๐Ÿ“Œ Examples -#### Command + - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "validateaddress", - "coin": "DOC", - "address": "RRnMcSeKiLrNdbp91qNVQwwXx5azD4S4CD" - } - ``` - - - - #### Response (valid address) - - ```json - { - "result": { - "is_valid": true - } - } - ``` - - #### Response (invalid cash address) - - ```json - { - "result": { - "is_valid": false, - "reason": "utxo:415] Checksum verification failed" - } - } - ``` - - #### Response (invalid ETH address) - - ```json - { - "result": { - "is_valid": false, - "reason": "eth:360] eth:2522] Invalid address checksum" - } - } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/legacy/version/index.mdx b/src/pages/komodo-defi-framework/api/legacy/version/index.mdx index 1f6c4017d..75d3bad8f 100644 --- a/src/pages/komodo-defi-framework/api/legacy/version/index.mdx +++ b/src/pages/komodo-defi-framework/api/legacy/version/index.mdx @@ -3,41 +3,18 @@ export const description = "The version method returns the Komodo DeFi Framework # version -**version()** - The `version` method returns the Komodo DeFi Framework API version. -## Arguments - -| Structure | Type | Description | -| --------- | ---- | ----------- | -| (none) | | | - -## Response +### Request Parameters -| Structure | Type | Description | -| --------- | ------ | ------------------------------------- | -| result | string | the Komodo DeFi Framework API version | + -#### ๐Ÿ“Œ Examples +### Response Parameters -#### Command + - - ```json - { - "method": "version", - "userpass": "RPC_UserP@SSW0RD" - } - ``` - +### ๐Ÿ“Œ Examples - - #### Response + - ```json - { - "result": "2.0.996_mm2_3bb412578_Linux" - } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/legacy/withdraw/index.mdx b/src/pages/komodo-defi-framework/api/legacy/withdraw/index.mdx index 6349d1361..1af4e15b1 100644 --- a/src/pages/komodo-defi-framework/api/legacy/withdraw/index.mdx +++ b/src/pages/komodo-defi-framework/api/legacy/withdraw/index.mdx @@ -11,116 +11,32 @@ This method generates a raw transaction which should then be broadcast using [se ## Arguments -| Structure | Type | Description | -| --------- | ---------------- | ----------------------------------------------------------------------------------------------------- | -| coin | string | the name of the coin the user desires to withdraw | -| to | string | coins are withdrawn to this address | -| amount | string (numeric) | the amount the user desires to withdraw, ignored when `max=true` | -| max | bool | withdraw the maximum available amount | -| fee | object | Optional. A standard [FeeInfo](/komodo-defi-framework/api/common_structures/wallet/#fee-info) object. | + ## Response -| Structure | Type | Description | -| ---------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| from | array of strings | coins are withdrawn from this address; the array contains a single element, but transactions may be sent from several addresses (UTXO coins) | -| to | array of strings | coins are withdrawn to this address; this may contain the `my_address` address, where change from UTXO coins is sent | -| my\_balance\_change | string (numeric) | the expected balance of change in `my_address` after the transaction broadcasts | -| received\_by\_me | string (numeric) | the amount of coins received by `my_address` after the transaction broadcasts; the value may be above zero when the transaction requires that the Komodo DeFi Framework API send change to `my_address` | -| spent\_by\_me | string (numeric) | the amount of coins spent by `my_address`; this value differ from the request amount, as the transaction fee is added here | -| total\_amount | string (numeric) | the total amount of coins transferred | -| fee\_details | object | the fee dsetails of the generated transaction; this value differs for utxo and ETH/ERC20 coins, check the examples for more details | -| tx\_hash | string | the hash of the generated transaction | -| tx\_hex | string | transaction bytes in hexadecimal format; use this value as input for the `send_raw_transaction` method | -| coin | string | the name of the coin the user wants to withdraw | -| kmd\_rewards | object (optional) | an object containing information about accrued rewards; always exists if the coin is `KMD` | -| kmd\_rewards.amount | string (numeric, optional) | the amount of accrued rewards | -| kmd\_rewards.claimed\_by\_me | bool (optional) | whether the rewards been claimed by me | + #### ๐Ÿ“Œ Examples #### Withdraw UTXO based coins - - ```json - { - "method": "withdraw", - "coin": "KMD", - "to": "RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh", - "amount": "10", - "userpass": "RPC_UserP@SSW0RD" - } - ``` - + #### Response (KMD success) - ```json - { - "block_height": 0, - "coin": "KMD", - "fee_details": { - "type": "Utxo", - "amount": "0.00001" - }, - "from": ["R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW"], - "my_balance_change": "-10.00001", - "received_by_me": "0.34417325", - "spent_by_me": "10.34418325", - "to": ["RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh"], - "total_amount": "10.34418325", - "tx_hash": "3a1c382c50a7d12e4675d12ed7e723ce9f0167693dd75fd772bae8524810e605", - "tx_hex": "0400008085202f890207a8e96978acfb8f0d002c3e4390142810dc6568b48f8cd6d8c71866ad8743c5010000006a47304402201960a7089f2d93480fff68ce0b7ca7bb7a32a52915753ac7ae780abd6162cb1d02202c9b11d442e5f72a532f44ceb10122898d486b1474a10eb981c60c5538b9c82d012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff97f56bf3b0f815bb737b7867e71ddb8198bba3574bb75737ba9c389a4d08edc6000000006a473044022055199d80bd7e2d1b932e54f097c6a15fc4b148d21299dc50067c1da18045f0ed02201d26d85333df65e6daab40a07a0e8a671af9d9b9d92fdf7d7ef97bd868ca545a012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200ca9a3b000000001976a91464ae8510aac9546d5e7704e31ce177451386455588acad2a0d02000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac00000000000000000000000000000000000000", - "kmd_rewards": { - "amount": "0.0791809", - "claimed_by_my": true - } - } - ``` + #### Withdraw UTXO based-coins with fixed fee - - ```json - { - "method": "withdraw", - "coin": "DOC", - "to": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW", - "amount": "1.0", - "fee": { - "type": "UtxoFixed", - "amount": "0.1" - }, - "userpass": "RPC_UserP@SSW0RD" - } - ``` - + #### Response (success) - ```json - { - "tx_hex": "0400008085202f8901ef25b1b7417fe7693097918ff90e90bba1351fff1f3a24cb51a9b45c5636e57e010000006b483045022100b05c870fcd149513d07b156e150a22e3e47fab4bb4776b5c2c1b9fc034a80b8f022038b1bf5b6dad923e4fb1c96e2c7345765ff09984de12bbb40b999b88b628c0f9012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac8cbaae5f010000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ace87a5e5d000000000000000000000000000000", - "tx_hash": "1ab3bc9308695960bc728fa427ac00d1812c4ae89aaa714c7618cb96d111be58", - "from": ["R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW"], - "to": ["R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW"], - "total_amount": "60.10253836", - "spent_by_me": "60.10253836", - "received_by_me": "60.00253836", - "my_balance_change": "-0.1", - "block_height": 0, - "timestamp": 1566472936, - "fee_details": { - "type": "Utxo", - "amount": "0.1" - }, - "coin": "DOC", - "internal_id": "" - } - ``` + #### Response (error - attempt to use EthGas for UTXO coin) @@ -131,45 +47,12 @@ This method generates a raw transaction which should then be broadcast using [se #### Withdraw UTXO based coins with custom fee per kbyte - - ```json - { - "method": "withdraw", - "coin": "DOC", - "to": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW", - "amount": "1.0", - "fee": { - "type": "UtxoPerKbyte", - "amount": "1" - }, - "userpass": "RPC_UserP@SSW0RD" - } - ``` - + #### Response (success) - ```json - { - "tx_hex": "0400008085202f890258be11d196cb18764c71aa9ae84a2c81d100ac27a48f72bc6059690893bcb31a000000006b483045022100ef11280e981be280ca5d24c947842ca6a8689d992b73e3a7eb9ff21070b0442b02203e458a2bbb1f2bf8448fc47c51485015904a5271bb17e14be5afa6625d67b1e8012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff58be11d196cb18764c71aa9ae84a2c81d100ac27a48f72bc6059690893bcb31a010000006b483045022100daaa10b09e7abf9d4f596fc5ac1f2542b8ecfab9bb9f2b02201644944ddc0280022067aa1b91ec821aa48f1d06d34cd26fb69a9f27d59d5eecdd451006940d9e83db012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788acf31c655d010000001976a91405aab5342166f8594baf17a7d9bef5d56744332788accd7c5e5d000000000000000000000000000000", - "tx_hash": "fd115190feec8c0c14df2696969295c59c674886344e5072d64000379101b78c", - "from": ["R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW"], - "to": ["R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW"], - "total_amount": "60.00253836", - "spent_by_me": "60.00253836", - "received_by_me": "59.61874931", - "my_balance_change": "-0.38378905", - "block_height": 0, - "timestamp": 1566473421, - "fee_details": { - "type": "Utxo", - "amount": "0.38378905" - }, - "coin": "DOC", - "internal_id": "" - } - ``` + #### Response (error - attempt to use EthGas for UTXO coin) @@ -180,89 +63,22 @@ This method generates a raw transaction which should then be broadcast using [se #### Withdraw ETH/ERC20 and other ETH-based forks - - ```json - { - "method": "withdraw", - "coin": "ETH", - "to": "0xbab36286672fbdc7b250804bf6d14be0df69fa28", - "amount": 10, - "userpass": "RPC_UserP@SSW0RD" - } - ``` - + #### Response (success) - ```json - { - "block_height": 0, - "coin": "ETH", - "fee_details": { - "type": "Eth", - "coin": "ETH", - "gas": 21000, - "gas_price": "0.000000001", - "total_fee": "0.000021" - }, - "from": ["0xbab36286672fbdc7b250804bf6d14be0df69fa29"], - "my_balance_change": "-10.000021", - "received_by_me": "0", - "spent_by_me": "10.000021", - "to": ["0xbab36286672fbdc7b250804bf6d14be0df69fa28"], - "total_amount": "10.000021", - "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", - "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" - } - ``` + #### Withdraw ETH/ERC20, and other ETH-based forks with gas limit - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "coin": "COIN_NAME", - "to": "RECIPIENT_ADDRESS", - "amount": "AMOUNT", - "fee": { - "type": "EthGas", - "gas_price": "3.5", - "gas": 55000 - } - } - ``` - + #### Response (success) - ```json - { - "tx_hex": "f86d820b2884d09dc30082d6d894bab36286672fbdc7b250804bf6d14be0df69fa29888ac7230489e80000801ca0ef0167b0e53ed50d87b6fd630925f2bce6ee72e9b5fdb51c6499a7caaecaed96a062e5cb954e503ff83f2d6ce082649fdcdf8a77c8d37c7d26d46d3f736b228d10", - "tx_hash": "a26c4dcacf63c04e385dd973ca7e7ca1465a3b904a0893bcadb7e37681d38c95", - "from": ["0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29"], - "to": ["0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29"], - "total_amount": "10", - "spent_by_me": "10.0001925", - "received_by_me": "10", - "my_balance_change": "-0.0001925", - "block_height": 0, - "timestamp": 1566474670, - "fee_details": { - "type": "Eth", - "coin": "ETH", - "gas": 55000, - "gas_price": "0.0000000035", - "total_fee": "0.0001925" - }, - "coin": "ETH", - "internal_id": "" - } - ``` + #### Response (error - attempt to use UtxoFixed or UtxoPerKbyte for ETH coin) @@ -273,127 +89,28 @@ This method generates a raw transaction which should then be broadcast using [se #### Withdraw Max - - ```json - { - "method": "withdraw", - "coin": "ETH", - "to": "0xbab36286672fbdc7b250804bf6d14be0df69fa28", - "max": true, - "userpass": "RPC_UserP@SSW0RD" - } - ``` - + #### Response (success) - ```json - { - "block_height": 0, - "coin": "ETH", - "fee_details": { - "type": "Eth", - "coin": "ETH", - "gas": 21000, - "gas_price": "0.000000001", - "total_fee": "0.000021" - }, - "from": ["0xbab36286672fbdc7b250804bf6d14be0df69fa29"], - "my_balance_change": "-10.000021", - "received_by_me": "0", - "spent_by_me": "10.000021", - "to": ["0xbab36286672fbdc7b250804bf6d14be0df69fa28"], - "total_amount": "10.000021", - "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", - "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" - } - ``` + #### Withdraw QRC20 - - ```json - { - "method": "withdraw", - "coin": "QRC20", - "to": "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs", - "amount": 10, - "userpass": "RPC_UserP@SSW0RD" - } - ``` - + #### Response (success) - ```json - { - "block_height": 0, - "coin": "QRC20", - "timestamp": 1608725061, - "fee_details": { - "type": "Qrc20", - "coin": "tQTUM", - "miner_fee": "0.00000447", - "gas_limit": 100000, - "gas_price": 40, - "total_gas_fee": "0.04" - }, - "from": ["qXxsj5RtciAby9T7m98AgAATL4zTi4UwDG"], - "my_balance_change": "-10", - "received_by_me": "0", - "spent_by_me": "10", - "to": ["qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs"], - "total_amount": "10", - "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", - "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" - } - ``` + #### Withdraw QRC20 with gas limit - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "coin": "QRC20", - "to": "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs", - "amount": 10, - "fee": { - "type": "Qrc20Gas", - "gas_limit": 250000, - "gas_price": 40 - } - } - ``` - + - ```json - { - "block_height": 0, - "coin": "QRC20", - "timestamp": 1608725061, - "fee_details": { - "type": "Qrc20", - "coin": "tQTUM", - "miner_fee": "0.00000447", - "gas_limit": 250000, - "gas_price": 40, - "total_gas_fee": "0.1" - }, - "from": ["qXxsj5RtciAby9T7m98AgAATL4zTi4UwDG"], - "my_balance_change": "-10", - "received_by_me": "0", - "spent_by_me": "10", - "to": ["qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs"], - "total_amount": "10", - "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", - "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" - } - ``` + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_bch_with_tokens/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_bch_with_tokens/index.mdx index 6e1367c38..8c3a07ff4 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_bch_with_tokens/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_bch_with_tokens/index.mdx @@ -31,45 +31,7 @@ The Komodo DeFi Framework supports Bitcoin Cash SLP tokens. Using this method, y - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "current_block": 1480481, - "bch_addresses_infos": { - "bitcoincash:qrf5vpn78s7rjexrjhlwyzzeg7gw98k7t5qx64fztj": { - "derivation_method": { - "type": "Iguana" - }, - "pubkey": "036879df230663db4cd083c8eeb0f293f46abc460ad3c299b0089b72e6d472202c", - "balances": { - "spendable": "0.11398301", - "unspendable": "0.00001" - } - } - }, - "slp_addresses_infos": { - "simpleledger:qrf5vpn78s7rjexrjhlwyzzeg7gw98k7t5va3wuz4v": { - "derivation_method": { - "type": "Iguana" - }, - "pubkey": "036879df230663db4cd083c8eeb0f293f46abc460ad3c299b0089b72e6d472202c", - "balances": { - "ASLP": { - "spendable": "5.2974", - "unspendable": "0" - } - } - } - } - }, - "id": null - } - ``` - + #### Request with `get_balances` set to false @@ -77,173 +39,131 @@ The Komodo DeFi Framework supports Bitcoin Cash SLP tokens. Using this method, y #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "current_block": 791267, - "bch_addresses_infos": { - "bitcoincash:qrf5vpn78s7rjexrjhlwyzzeg7gw98k7t5qx64fztj": { - "derivation_method": { - "type": "Iguana" - }, - "pubkey": "03d8064eece4fa5c0f8dc0267f68cee9bdd527f9e88f3594a323428718c391ecc2" - } - }, - "slp_addresses_infos": { - "simpleledger:qrf5vpn78s7rjexrjhlwyzzeg7gw98k7t5va3wuz4v": { - "derivation_method": { - "type": "Iguana" - }, - "pubkey": "03d8064eece4fa5c0f8dc0267f68cee9bdd527f9e88f3594a323428718c391ecc2", - "tickers": ["ASLP-SLP"] - } - } - }, - "id": null - } - ``` - - - - ### Error Types - - | Structure | Type | Description | - | -------------------------- | ------ | ----------------------------------------------------------------------------------- | - | CoinProtocolParseError | string | Parsing the protocol of the platform coin you are trying to activate failed | - | InternalError | string | The request was failed due to an Komodo DeFi Framework API internal error | - | PlatformCoinCreationError | string | There was an error when trying to activate the platform coin | - | PlatformConfigIsNotFound | string | Config of the platform coin you are trying to activate is not found | - | PlatformIsAlreadyActivated | string | The platform coin you are trying to activate is already activated | - | PrivKeyNotAllowed | string | The privkey is not allowed | - | TokenConfigIsNotFound | string | Config of the token you are trying to activate is not found | - | TokenProtocolParseError | string | Parsing the protocol of the token you are trying to activate failed | - | Transport | string | The request was failed due to a network error | - | UnexpectedDerivationMethod | string | The derivation method used is unexpected | - | UnexpectedPlatformProtocol | string | Unexpected platform protocol found for the platform coin you are trying to activate | - | UnexpectedTokenProtocol | string | Unexpected protocol is found in the config of the token you are trying to activate | - - #### PlatformIsAlreadyActivated Error - - In this case, you need to [disable](/komodo-defi-framework/api/legacy/disable_coin/) BCH and try again. - - ```json - { - "mmrpc": "2.0", - "error": "BCH", - "error_path": "platform_coin_with_tokens", - "error_trace": "platform_coin_with_tokens:281]", - "error_type": "PlatformIsAlreadyActivated", - "error_data": "BCH", - "id": null - } - ``` - - #### PlatformConfigIsNotFound Error - - ```json - { - "mmrpc": "2.0", - "error": "Platform BCH-wrong config is not found", - "error_path": "platform_coin_with_tokens.prelude", - "error_trace": "platform_coin_with_tokens:286] prelude:56]", - "error_type": "PlatformConfigIsNotFound", - "error_data": "BCH-wrong", - "id": null - } - ``` - - #### UnexpectedPlatformProtocol Error - - ```json - { - "mmrpc": "2.0", - "error": "Unexpected platform protocol UTXO for BTC", - "error_path": "platform_coin_with_tokens.prelude.bch_with_tokens_activation", - "error_trace": "platform_coin_with_tokens:286] prelude:67] bch_with_tokens_activation:127]", - "error_type": "UnexpectedPlatformProtocol", - "error_data": { - "ticker": "BTC", - "protocol": { - "type": "UTXO" - } - }, - "id": null - } - ``` - - #### UnexpectedTokenProtocol Error - - ```json - { - "mmrpc": "2.0", - "error": "Unexpected token protocol ERC20 { platform: \"ETH\", contract_address: \"0xdAC17F958D2ee523a2206206994597C13D831ec7\" } for USDT-ERC20", - "error_path": "platform_coin_with_tokens.prelude.slp_token_activation", - "error_trace": "platform_coin_with_tokens:301] platform_coin_with_tokens:114] prelude:67] slp_token_activation:47]", - "error_type": "UnexpectedTokenProtocol", - "error_data": { - "ticker": "USDT-ERC20", - "protocol": { - "type": "ERC20", - "protocol_data": { - "platform": "ETH", - "contract_address": "0xdAC17F958D2ee523a2206206994597C13D831ec7" - } - } - }, - "id": null - } - ``` - - #### PlatformCoinCreationError Error - - ```json - { - "mmrpc": "2.0", - "error": "Error Using empty bchd_urls is unsafe for SLP users! on platform coin BCH creation", - "error_path": "platform_coin_with_tokens.bch_with_tokens_activation", - "error_trace": "platform_coin_with_tokens:290] bch_with_tokens_activation:212]", - "error_type": "PlatformCoinCreationError", - "error_data": { - "ticker": "BCH", - "error": "Using empty bchd_urls is unsafe for SLP users!" - }, - "id": null - } - ``` - - #### PlatformCoinCreationError Error (native) - - ```json - { - "mmrpc": "2.0", - "error": "Error bch:633] utxo:1704] utxo:995] Error parsing the native wallet configuration '/home/user/.Bitcoin Cash Testnet/Bitcoin Cash Testnet.conf': No such file or directory (os error 2) on platform coin tBCH creation", - "error_path": "platform_coin_with_tokens.bch_with_tokens_activation", - "error_trace": "platform_coin_with_tokens:290] bch_with_tokens_activation:212]", - "error_type": "PlatformCoinCreationError", - "error_data": { - "ticker": "tBCH", - "error": "bch:633] utxo:1704] utxo:995] Error parsing the native wallet configuration '/home/user/.Bitcoin Cash Testnet/Bitcoin Cash Testnet.conf': No such file or directory (os error 2)" - }, - "id": null - } - ``` - - #### PlatformCoinCreationError Error (Electrum server not responding) - - ```json - { - "mmrpc": "2.0", - "error": "Error bch:633] utxo:1667] Failed to connect to at least 1 of [ElectrumRpcRequest { url: \"bch0.kister.net:5100\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"testnet.imaginary.cash:5000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"blackie.c3-soft.com:6000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"tbch.loping.net:6000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"electroncash.de:5000\", protocol: TCP, disable_cert_verification: false }] in 5 seconds. on platform coin tBCH creation", - "error_path": "platform_coin_with_tokens.bch_with_tokens_activation", - "error_trace": "platform_coin_with_tokens:290] bch_with_tokens_activation:212]", - "error_type": "PlatformCoinCreationError", - "error_data": { - "ticker": "tBCH", - "error": "bch:633] utxo:1667] Failed to connect to at least 1 of [ElectrumRpcRequest { url: \"bch0.kister.net:5100\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"testnet.imaginary.cash:5000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"blackie.c3-soft.com:6000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"tbch.loping.net:6000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"electroncash.de:5000\", protocol: TCP, disable_cert_verification: false }] in 5 seconds." - }, - "id": null - } - ``` - + + +### Error Types + + + +#### PlatformIsAlreadyActivated Error + +In this case, you need to [disable](/komodo-defi-framework/api/legacy/disable_coin/) BCH and try again. + +```json +{ + "mmrpc": "2.0", + "error": "BCH", + "error_path": "platform_coin_with_tokens", + "error_trace": "platform_coin_with_tokens:281]", + "error_type": "PlatformIsAlreadyActivated", + "error_data": "BCH", + "id": null +} +``` + +#### PlatformConfigIsNotFound Error + +```json +{ + "mmrpc": "2.0", + "error": "Platform BCH-wrong config is not found", + "error_path": "platform_coin_with_tokens.prelude", + "error_trace": "platform_coin_with_tokens:286] prelude:56]", + "error_type": "PlatformConfigIsNotFound", + "error_data": "BCH-wrong", + "id": null +} +``` + +#### UnexpectedPlatformProtocol Error + +```json +{ + "mmrpc": "2.0", + "error": "Unexpected platform protocol UTXO for BTC", + "error_path": "platform_coin_with_tokens.prelude.bch_with_tokens_activation", + "error_trace": "platform_coin_with_tokens:286] prelude:67] bch_with_tokens_activation:127]", + "error_type": "UnexpectedPlatformProtocol", + "error_data": { + "ticker": "BTC", + "protocol": { + "type": "UTXO" + } + }, + "id": null +} +``` + +#### UnexpectedTokenProtocol Error + +```json +{ + "mmrpc": "2.0", + "error": "Unexpected token protocol ERC20 { platform: \"ETH\", contract_address: \"0xdAC17F958D2ee523a2206206994597C13D831ec7\" } for USDT-ERC20", + "error_path": "platform_coin_with_tokens.prelude.slp_token_activation", + "error_trace": "platform_coin_with_tokens:301] platform_coin_with_tokens:114] prelude:67] slp_token_activation:47]", + "error_type": "UnexpectedTokenProtocol", + "error_data": { + "ticker": "USDT-ERC20", + "protocol": { + "type": "ERC20", + "protocol_data": { + "platform": "ETH", + "contract_address": "0xdAC17F958D2ee523a2206206994597C13D831ec7" + } + } + }, + "id": null +} +``` + +#### PlatformCoinCreationError Error + +```json +{ + "mmrpc": "2.0", + "error": "Error Using empty bchd_urls is unsafe for SLP users! on platform coin BCH creation", + "error_path": "platform_coin_with_tokens.bch_with_tokens_activation", + "error_trace": "platform_coin_with_tokens:290] bch_with_tokens_activation:212]", + "error_type": "PlatformCoinCreationError", + "error_data": { + "ticker": "BCH", + "error": "Using empty bchd_urls is unsafe for SLP users!" + }, + "id": null +} +``` + +#### PlatformCoinCreationError Error (native) + +```json +{ + "mmrpc": "2.0", + "error": "Error bch:633] utxo:1704] utxo:995] Error parsing the native wallet configuration '/home/user/.Bitcoin Cash Testnet/Bitcoin Cash Testnet.conf': No such file or directory (os error 2) on platform coin tBCH creation", + "error_path": "platform_coin_with_tokens.bch_with_tokens_activation", + "error_trace": "platform_coin_with_tokens:290] bch_with_tokens_activation:212]", + "error_type": "PlatformCoinCreationError", + "error_data": { + "ticker": "tBCH", + "error": "bch:633] utxo:1704] utxo:995] Error parsing the native wallet configuration '/home/user/.Bitcoin Cash Testnet/Bitcoin Cash Testnet.conf': No such file or directory (os error 2)" + }, + "id": null +} +``` + +#### PlatformCoinCreationError Error (Electrum server not responding) + +```json +{ + "mmrpc": "2.0", + "error": "Error bch:633] utxo:1667] Failed to connect to at least 1 of [ElectrumRpcRequest { url: \"bch0.kister.net:5100\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"testnet.imaginary.cash:5000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"blackie.c3-soft.com:6000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"tbch.loping.net:6000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"electroncash.de:5000\", protocol: TCP, disable_cert_verification: false }] in 5 seconds. on platform coin tBCH creation", + "error_path": "platform_coin_with_tokens.bch_with_tokens_activation", + "error_trace": "platform_coin_with_tokens:290] bch_with_tokens_activation:212]", + "error_type": "PlatformCoinCreationError", + "error_data": { + "ticker": "tBCH", + "error": "bch:633] utxo:1667] Failed to connect to at least 1 of [ElectrumRpcRequest { url: \"bch0.kister.net:5100\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"testnet.imaginary.cash:5000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"blackie.c3-soft.com:6000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"tbch.loping.net:6000\", protocol: TCP, disable_cert_verification: false }, ElectrumRpcRequest { url: \"electroncash.de:5000\", protocol: TCP, disable_cert_verification: false }] in 5 seconds." + }, + "id": null +} +``` diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_erc20/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_erc20/index.mdx index d9e42c558..191b2a75b 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_erc20/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_erc20/index.mdx @@ -10,64 +10,8 @@ The `enable_erc20` method allows you to activate additional ERC20 like tokens of -## Response + -```json -{ - "mmrpc": "2.0", - "result": { - "balances": { - "0x0d317904AF3BA3A993d557b6cba147FEA4DeB57E": { - "spendable": "0", - "unspendable": "0" - } - }, - "platform_coin": "ETH", - "token_contract_address": "0x0d8775f648430679a709e98d2b0cb6250d2887ef", - "required_confirmations": 3 - }, - "id": null -} -``` +### Error Types -## Error - Platform coin is not yet activated - -```json -{ - "mmrpc": "2.0", - "error": "Platform coin ETH is not activated", - "error_path": "token.lp_coins", - "error_trace": "token:126] lp_coins:2797]", - "error_type": "PlatformCoinIsNotActivated", - "error_data": "ETH", - "id": null -} -``` - -## Error - Token already activated - -```json -{ - "mmrpc": "2.0", - "error": "Token BAT-ERC20 is already activated", - "error_path": "token", - "error_trace": "token:119]", - "error_type": "TokenIsAlreadyActivated", - "error_data": "BAT-ERC20", - "id": null -} -``` - -## Error - Token config not found in coins file - -```json -{ - "mmrpc": "2.0", - "error": "Token BATT-ERC20 config is not found", - "error_path": "token.prelude", - "error_trace": "token:122] prelude:79]", - "error_type": "TokenConfigIsNotFound", - "error_data": "BATT-ERC20", - "id": null -} -``` + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_eth_with_tokens/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_eth_with_tokens/index.mdx index d8f565822..a9739e251 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_eth_with_tokens/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_eth_with_tokens/index.mdx @@ -24,151 +24,19 @@ Additionally, it supports ERC20 tokens on the ETH chain and associated ERC20 lik - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "current_block": 20590537, - "eth_addresses_infos": { - "0x083C32B38e8050473f6999e22f670d1404235592": { - "derivation_method": { - "type": "Iguana" - }, - "pubkey": "04ec603f83519cc2150bd99ed0ed6b3f7f029dedff2957cd22542e2504e3d2a7953c084f907cce2f0e26fb0cfc55e06925bf0f88a92b904224dba8ebafdf98ce7b", - "balances": { - "spendable": "0", - "unspendable": "0" - } - } - }, - "erc20_addresses_infos": { - "0x083C32B38e8050473f6999e22f670d1404235592": { - "derivation_method": { - "type": "Iguana" - }, - "pubkey": "04ec603f83519cc2150bd99ed0ed6b3f7f029dedff2957cd22542e2504e3d2a7953c084f907cce2f0e26fb0cfc55e06925bf0f88a92b904224dba8ebafdf98ce7b", - "balances": { - "BUSD-ERC20": { - "spendable": "0", - "unspendable": "0" - }, - "MINDS-ERC20": { - "spendable": "0", - "unspendable": "0" - }, - "APE-ERC20": { - "spendable": "0", - "unspendable": "0" - }, - "BCH-ERC20": { - "spendable": "0", - "unspendable": "0" - } - } - } - }, - "nfts_infos": {} - }, - "id": null - } - ``` - + #### Request with `get_balances` set to false - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "current_block": 60937035, - "eth_addresses_infos": { - "0x083C32B38e8050473f6999e22f670d1404235592": { - "derivation_method": { - "type": "Iguana" - }, - "pubkey": "04ec603f83519cc2150bd99ed0ed6b3f7f029dedff2957cd22542e2504e3d2a7953c084f907cce2f0e26fb0cfc55e06925bf0f88a92b904224dba8ebafdf98ce7b" - } - }, - "erc20_addresses_infos": { - "0x083C32B38e8050473f6999e22f670d1404235592": { - "derivation_method": { - "type": "Iguana" - }, - "pubkey": "04ec603f83519cc2150bd99ed0ed6b3f7f029dedff2957cd22542e2504e3d2a7953c084f907cce2f0e26fb0cfc55e06925bf0f88a92b904224dba8ebafdf98ce7b", - "tickers": [ - "PGX-PLG20", - "AAVE-PLG20" - ] - } - }, - "nfts_infos": {} - }, - "id": null - } - ``` - + #### Request including NFT initialization - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "current_block": 61329162, - "eth_addresses_infos": { - "0x083C32B38e8050473f6999e22f670d1404235592": { - "derivation_method": { - "type": "Iguana" - }, - "pubkey": "04d8064eece4fa5c0f8dc0267f68cee9bdd527f9e88f3594a323428718c391ecc2a91c9ce32b6fc5489c49e33b688423b655177168afee1b128be9b2fee67e3f3b" - } - }, - "erc20_addresses_infos": { - "0x083C32B38e8050473f6999e22f670d1404235592": { - "derivation_method": { - "type": "Iguana" - }, - "pubkey": "04d8064eece4fa5c0f8dc0267f68cee9bdd527f9e88f3594a323428718c391ecc2a91c9ce32b6fc5489c49e33b688423b655177168afee1b128be9b2fee67e3f3b", - "tickers": [ - "PGX-PLG20", - "AAVE-PLG20" - ] - } - }, - "nfts_infos": { - "0x73a5299824cd955af6377b56f5762dc3ca4cc078,1": { - "token_address": "0x73a5299824cd955af6377b56f5762dc3ca4cc078", - "token_id": "1", - "chain": "POLYGON", - "contract_type": "ERC721", - "amount": "1" - }, - "0x3987dfed574927e7a3309758ccf949ad2403fcbb,1": { - "token_address": "0x3987dfed574927e7a3309758ccf949ad2403fcbb", - "token_id": "1", - "chain": "POLYGON", - "contract_type": "ERC1155", - "amount": "1" - } - } - }, - "id": null - } - ``` - + #### Request using WalletConnect @@ -176,177 +44,8 @@ Prior to coin activation using WalletConnect, you need to establish a connection - - #### Response - - ```json - ``` - - -### Error Responses - - - ### Error Types - - | Structure | Type | Description | - | -------------------------- | ------ | ----------------------------------------------------------------------------------- | - | CoinProtocolParseError | string | Parsing the protocol of the platform coin you are trying to activate failed | - | InternalError | string | The request was failed due to an Komodo DeFi Framework API internal error | - | PlatformCoinCreationError | string | There was an error when trying to activate the platform coin | - | PlatformConfigIsNotFound | string | Config of the platform coin you are trying to activate is not found | - | PlatformIsAlreadyActivated | string | The platform coin you are trying to activate is already activated | - | PrivKeyNotAllowed | string | The privkey is not allowed | - | TokenConfigIsNotFound | string | Config of the token you are trying to activate is not found | - | TokenProtocolParseError | string | Parsing the protocol of the token you are trying to activate failed | - | Transport | string | The request was failed due to a network error | - | UnexpectedDerivationMethod | string | The derivation method used is unexpected | - | UnexpectedPlatformProtocol | string | Unexpected platform protocol found for the platform coin you are trying to activate | - | UnexpectedTokenProtocol | string | Unexpected protocol is found in the config of the token you are trying to activate | - - #### PlatformIsAlreadyActivated Error - - In this case, you need to [disable](/komodo-defi-framework/api/legacy/disable_coin/) the platform coin and try again. - - ```json - { - "mmrpc": "2.0", - "error": "ETH", - "error_path": "platform_coin_with_tokens", - "error_trace": "platform_coin_with_tokens:297]", - "error_type": "PlatformIsAlreadyActivated", - "error_data": "ETH", - "id": null - } - ``` - - #### PlatformConfigIsNotFound Error - - ```json - { - "mmrpc": "2.0", - "error": "Platform ETH config is not found", - "error_path": "platform_coin_with_tokens.prelude", - "error_trace": "platform_coin_with_tokens:302] prelude:79]", - "error_type": "PlatformConfigIsNotFound", - "error_data": "ETH", - "id": null - } - ``` - - #### CoinProtocolParseError Error - - ```json - { - "mmrpc": "2.0", - "error": "Platform coin ETH protocol parsing failed: invalid type: null, expected adjacently tagged enum CoinProtocol", - "error_path": "platform_coin_with_tokens.prelude", - "error_trace": "platform_coin_with_tokens:302] prelude:82]", - "error_type": "CoinProtocolParseError", - "error_data": { - "ticker": "ETH", - "error": "invalid type: null, expected adjacently tagged enum CoinProtocol" - }, - "id": null - } - ``` - - #### UnexpectedPlatformProtocol Error - - ```json - { - "mmrpc": "2.0", - "error": "Unexpected platform protocol QTUM for ETH", - "error_path": "platform_coin_with_tokens.prelude.eth_with_token_activation", - "error_trace": "platform_coin_with_tokens:302] prelude:90] eth_with_token_activation:64]", - "error_type": "UnexpectedPlatformProtocol", - "error_data": { "ticker": "ETH", "protocol": { "type": "QTUM" } }, - "id": null - } - ``` - - #### TokenConfigIsNotFound Error - - ```json - { - "mmrpc": "2.0", - "error": "Token BTUSD-ERC20 config is not found", - "error_path": "platform_coin_with_tokens.prelude", - "error_trace": "platform_coin_with_tokens:314] platform_coin_with_tokens:109] prelude:79]", - "error_type": "TokenConfigIsNotFound", - "error_data": "BTUSD-ERC20", - "id": null - } - ``` - - #### TokenProtocolParseError Error - - ```json - { - "mmrpc": "2.0", - "error": "Token BUSD-ERC20 protocol parsing failed: unknown variant `TERC20`, expected one of `UTXO`, `QTUM`, `QRC20`, `ETH`, `ERC20`, `TENDERMINT`, `TENDERMINTTOKEN`, `LIGHTNING`, `SOLANA`, `SPLTOKEN`, `ZHTLC`", - "error_path": "platform_coin_with_tokens.prelude", - "error_trace": "platform_coin_with_tokens:314] platform_coin_with_tokens:109] prelude:82]", - "error_type": "TokenProtocolParseError", - "error_data": { - "ticker": "BUSD-ERC20", - "error": "unknown variant `TERC20`, expected one of `UTXO`, `QTUM`, `QRC20`, `ETH`, `ERC20`, `TENDERMINT`, `TENDERMINTTOKEN`, `LIGHTNING`, `SOLANA`, `SPLTOKEN`, `ZHTLC`" - }, - "id": null - } - ``` - - #### UnexpectedTokenProtocol Error - - ```json - { - "mmrpc": "2.0", - "error": "Unexpected token protocol QRC20 { platform: \"ETH\", contract_address: \"0x4Fabb145d64652a948d72533023f6E7A623C7C53\" } for BUSD-ERC20", - "error_path": "platform_coin_with_tokens.prelude.erc20_token_activation", - "error_trace": "platform_coin_with_tokens:314] platform_coin_with_tokens:109] prelude:90] erc20_token_activation:58]", - "error_type": "UnexpectedTokenProtocol", - "error_data": { - "ticker": "BUSD-ERC20", - "protocol": { - "type": "QRC20", - "protocol_data": { - "platform": "ETH", - "contract_address": "0x4Fabb145d64652a948d72533023f6E7A623C7C53" - } - } - }, - "id": null - } - ``` - - #### InvalidRequest Error - - Returned when the `rpc_mode` parameter is set to `Metamask` but the Komodo DeFi Framework was not built targeting `wasm`. - - ```json - { - "mmrpc": "2.0", - "error": "Error parsing request: unknown variant `Metamask`, expected `Default`", - "error_path": "dispatcher", - "error_trace": "dispatcher:118]", - "error_type": "InvalidRequest", - "error_data": "unknown variant `Metamask`, expected `Default`", - "id": null - } - ``` - - #### Transport Error + - Returned when coin nodes are unresponsive. +### Error Types - ```json - { - "mmrpc": "2.0", - "error": "Failed to get client version for all nodes", - "error_path": "platform_coin_with_tokens.mod", - "error_trace": "platform_coin_with_tokens:454] mod:717]", - "error_type": "Transport", - "error_data": "Failed to get client version for all nodes", - "id": null - } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_token/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_token/index.mdx index 262e88906..48dbd4187 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_token/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_token/index.mdx @@ -12,21 +12,7 @@ The `enable_tendermint_token` method allows you to activate additional Tendermin ## Response -```json -{ - "mmrpc": "2.0", - "result": { - "balances": { - "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k": { - "spendable": "0.028306", - "unspendable": "0" - } - }, - "platform_coin": "IRIS" - }, - "id": null -} -``` + ## Error - Platform coin is not yet activated diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_with_assets/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_with_assets/index.mdx index 77de4f8f9..71d91fe67 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_with_assets/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/enable_tendermint_with_assets/index.mdx @@ -19,77 +19,19 @@ Use this method to activate Tendermint coins (COSMOS/IRIS/OSMOSIS) and IBC asset - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "ticker": "IRIS", - "address": "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k", - "current_block": 19769628, - "tokens_tickers": ["ATOM-IBC_IRIS"] - }, - "id": null - } - ``` - + #### Request with token activation and `get_balances` as `true` - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "ticker": "IRIS", - "address": "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k", - "current_block": 19769638, - "balance": { - "spendable": "44.147264", - "unspendable": "0" - }, - "tokens_balances": { - "ATOM-IBC_IRIS": { - "spendable": "0.028306", - "unspendable": "0" - } - } - }, - "id": null - } - ``` - + #### Request for Metamask / WalletConnect activation - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "ticker": "ATOM", - "address": "cosmos16drqvl3u8sukfsu4lm3qsk28jr3fahjaswsac8", - "current_block": 22148347, - "balance": { - "spendable": "1.003381", - "unspendable": "0" - }, - "tokens_balances": {} - }, - "id": null - } - ``` - + ### Error Types diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_bch/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_bch/index.mdx index e15b642f7..94655aba9 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_bch/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_bch/index.mdx @@ -28,19 +28,7 @@ Use this method for task managed activation of BCH and SLP tokens. Refer to the - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "task_id": 1 - }, - "id": null - } - ``` - + ## task::enable\_bch::status {{label : 'task::enable_bch::status', tag : 'API-v2'}} @@ -79,49 +67,7 @@ Once complete, `status` will be `Ok`, and the `details` object will have the fo | ticker | string | Ticker of the coin being activated. | | wallet\_balance | object | A standard [WalletBalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#wallet-balance-info) object. Note: the structure may vary based on the `get_balances` parameter value in the activation request. | - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "Ok", - "details": { - "ticker": "BCH", - "current_block": 895348, - "wallet_balance": { - "wallet_type": "HD", - "accounts": [ - { - "account_index": 0, - "derivation_path": "m/44'/145'/0'", - "total_balance": { - "BCH": { - "spendable": "0", - "unspendable": "0" - } - }, - "addresses": [ - { - "address": "bitcoincash:qq6qvc33strtjwnfktdqswwvxuhrhs2ussavvhv3a0", - "derivation_path": "m/44'/145'/0'/0/0", - "chain": "External", - "balance": { - "BCH": { - "spendable": "0", - "unspendable": "0" - } - } - } - ] - } - ] - } - } - }, - "id": null - } - ``` - + #### Response (ready, successful, Iguana mode) @@ -138,18 +84,7 @@ Once complete, `status` will be `Ok`, and the `details` object will have the fo #### Response (in progress) - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": "RequestingWalletBalance" - }, - "id": null - } - ``` - + #### Response (ready, error) @@ -194,19 +129,9 @@ If the `task::enable_bch::status` returns `UserActionRequired`, we need to use t #### Command - - - - #### Response (success) + - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - + ## task::enable\_bch::cancel {{label : 'task::enable_bch::cancel', tag : 'API-v2'}} @@ -231,44 +156,4 @@ If you want to cancel the enabling process before it has completed, you can use - - #### Response (success) - - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - - - - #### Response (success - already finished) - - ```json - { - "mmrpc": "2.0", - "error": "Task is finished already", - "error_path": "init_standalone_coin.manager", - "error_trace": "init_standalone_coin:144] manager:101]", - "error_type": "TaskFinished", - "error_data": 0, - "id": null - } - ``` - - #### Response (error - no such task) - - ```json - { - "mmrpc": "2.0", - "error": "No such task '1'", - "error_path": "init_standalone_coin", - "error_trace": "init_standalone_coin:119]", - "error_type": "NoSuchTask", - "error_data": 1, - "id": null - } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/index.mdx index 74bdece0c..febaa5340 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_eth/index.mdx @@ -41,19 +41,7 @@ Once complete, `status` will be `Ok`, and the `details` object will have the fo - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "task_id": 1 - }, - "id": null - } - ``` - + ## task::enable\_eth::status {{label : 'task::enable_eth::status', tag : 'API-v2'}} @@ -76,119 +64,11 @@ The response will return the following: - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "Ok", - "details": { - "current_block": 70970530, - "ticker": "MATIC", - "wallet_balance": { - "wallet_type": "HD", - "accounts": [ - { - "account_index": 0, - "derivation_path": "m/44'/60'/0'", - "total_balance": { - "AAVE-PLG20": { - "spendable": "0.0275928341263563", - "unspendable": "0" - }, - "PGX-PLG20": { - "spendable": "237.729414631067", - "unspendable": "0" - }, - "MATIC": { - "spendable": "66.36490013618242918", - "unspendable": "0" - } - }, - "addresses": [ - { - "address": "0xC11b6070c84A1E6Fc62B2A2aCf70831545d5eDD4", - "derivation_path": "m/44'/60'/0'/0/0", - "chain": "External", - "balance": { - "PGX-PLG20": { - "spendable": "237.729414631067", - "unspendable": "0" - }, - "AAVE-PLG20": { - "spendable": "0.0275928341263563", - "unspendable": "0" - }, - "MATIC": { - "spendable": "65.36490013618242918", - "unspendable": "0" - } - } - }, - { - "address": "0x1751bd0510fDAE2A4a81Ab8A3e70E59E4760eAB6", - "derivation_path": "m/44'/60'/0'/0/1", - "chain": "External", - "balance": { - "AAVE-PLG20": { - "spendable": "0", - "unspendable": "0" - }, - "PGX-PLG20": { - "spendable": "0", - "unspendable": "0" - }, - "MATIC": { - "spendable": "1", - "unspendable": "0" - } - } - }, - { - "address": "0xffCF6033C31ed4beBC72f77be45d97cd8a8BABB4", - "derivation_path": "m/44'/60'/0'/0/2", - "chain": "External", - "balance": { - "MATIC": { - "spendable": "0", - "unspendable": "0" - }, - "AAVE-PLG20": { - "spendable": "0", - "unspendable": "0" - }, - "PGX-PLG20": { - "spendable": "0", - "unspendable": "0" - } - } - } - ] - } - ] - }, - "nfts_infos": {} - } - }, - "id": null - } - ``` - + #### Response (in progress) - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": "RequestingWalletBalance" - }, - "id": null - } - ``` - + #### Response (ready, error) @@ -226,19 +106,9 @@ If the `task::enable_eth::status` returns `UserActionRequired`, we need to use t #### Command - + - - #### Response (success) - - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - + ## task::enable\_eth::cancel {{label : 'task::enable_eth::cancel', tag : 'API-v2'}} @@ -254,44 +124,4 @@ If you want to cancel the enabling process before it has completed, you can use - - #### Response (success) - - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - - - - #### Response (success - already finished) - - ```json - { - "mmrpc": "2.0", - "error": "Task is finished already", - "error_path": "init_standalone_coin.manager", - "error_trace": "init_standalone_coin:144] manager:101]", - "error_type": "TaskFinished", - "error_data": 0, - "id": null - } - ``` - - #### Response (error - no such task) - - ```json - { - "mmrpc": "2.0", - "error": "No such task '1'", - "error_path": "init_standalone_coin", - "error_trace": "init_standalone_coin:119]", - "error_type": "NoSuchTask", - "error_data": 1, - "id": null - } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_qtum/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_qtum/index.mdx index 523f2be40..8faf7b926 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_qtum/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_qtum/index.mdx @@ -24,19 +24,7 @@ Use this method for task managed activation of QTUM coins and tokens. Refer to t - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "task_id": 1 - }, - "id": null - } - ``` - + ## task::enable\_qtum::status {{label : 'task::enable_qtum::status', tag : 'API-v2'}} @@ -75,19 +63,9 @@ If the `task::enable_qtum::status` returns `UserActionRequired`, we need to use #### Command - + - - #### Response (success) - - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - + ## Error Cases @@ -131,14 +109,4 @@ If you want to cancel the enabling process before it has completed, you can use - - #### Response (success) - - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/cancel/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/cancel/index.mdx new file mode 100644 index 000000000..a455b49aa --- /dev/null +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/cancel/index.mdx @@ -0,0 +1,15 @@ +export const title = "Komodo DeFi Framework Method: task::enable_sia::cancel"; +export const description = + "Cancel an ongoing SIA activation task."; + +# task::enable\_sia::cancel {{label : 'task::enable_sia::cancel', tag : 'API-v2'}} + +If you want to cancel the enabling process before it has completed, use this method. + +#### Arguments + + + +#### Response + + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/index.mdx new file mode 100644 index 000000000..05b628cf9 --- /dev/null +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/index.mdx @@ -0,0 +1,14 @@ +export const title = "Komodo DeFi Framework Method: SIA Coin Activation Tasks"; +export const description = + "The methods in this document demonstrate the task-managed activation of SIA."; + +# Task: SIA Activation + +The task-managed SIA activation flow consists of: + +* `task::enable_sia::init`: Start activation, returns a `task_id` +* `task::enable_sia::status`: Poll activation progress and final result +* `task::enable_sia::user_action`: Provide user action when required (reserved for SIA) +* `task::enable_sia::cancel`: Cancel an ongoing activation + +Refer to each subpage for arguments, responses, and examples. diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/init/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/init/index.mdx new file mode 100644 index 000000000..aaec3d23a --- /dev/null +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/init/index.mdx @@ -0,0 +1,23 @@ +export const title = "Komodo DeFi Framework Method: task::enable_sia::init"; +export const description = + "Initialize SIA coin activation and receive a task_id."; + +# task::enable\_sia::init {{label : 'task::enable_sia::init', tag : 'API-v2'}} + +Use this method for task managed activation of SIA. Refer to the +[task managed activation overview](/komodo-defi-framework/api/v20/coin_activation/task_managed/) +for activation of other coin types. + +#### Arguments + + + +#### Response + + + +#### ๐Ÿ“Œ Examples + + + + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/status/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/status/index.mdx new file mode 100644 index 000000000..b2c7b9716 --- /dev/null +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/status/index.mdx @@ -0,0 +1,40 @@ +export const title = "Komodo DeFi Framework Method: task::enable_sia::status"; +export const description = + "Query the status of the SIA activation task."; + +# task::enable\_sia::status {{label : 'task::enable_sia::status', tag : 'API-v2'}} + +After running the `task::enable_sia::init` method, query the status of activation +to check its progress. The response returns: + +* Result of the task (success or error) +* Progress status (what state the task is in) +* Required user action (what user should do before the task can continue) + +#### Arguments + + + +#### Command + + + + + +Possible `status` values while activation is in progress: + +* ActivatingCoin: The first step of activation. No user action required. +* RequestingWalletBalance: Initial balances info is being requested. No user action required. +* Finishing: Activation process completed. + +Once complete, `status` will be `Ok`, and the `details` object will have the following structure: + +#### Response (ready, successful) + +| Parameter | Type | Description | +| --------------- | ------- | ---------------------------------------- | +| current\_block | integer | Block height of the coin being activated | +| ticker | string | Ticker of the coin being activated | +| wallet\_balance | object | Wallet balance object (Iguana for Sia) | + + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/user_action/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/user_action/index.mdx new file mode 100644 index 000000000..bd226fd20 --- /dev/null +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/user_action/index.mdx @@ -0,0 +1,18 @@ +export const title = "Komodo DeFi Framework Method: task::enable_sia::user_action"; +export const description = + "Provide user action for SIA activation task, if required."; + +# task::enable\_sia::user\_action {{label : 'task::enable_sia::user_action', tag : 'API-v2'}} + +If the `task::enable_sia::status` returns `UserActionRequired`, use this method to provide +the required user action payload. + +Note: Hardware-wallet user interactions are not currently required for SIA activation. + +#### Arguments + + + +#### Response + + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/index.mdx index 7ffc091e4..87b519843 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_tendermint/index.mdx @@ -24,19 +24,7 @@ Use this method for task managed activation of Tendermint coins & tokens. Refer - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "task_id": 2 - }, - "id": null - } - ``` - + ## task::enable\_tendermint::status {{label : 'task::enable_tendermint::status', tag : 'API-v2'}} @@ -59,34 +47,7 @@ The response will return the following: -\| | | | - - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "Ok", - "details": { - "ticker": "IRIS", - "address": "iaa1p8t6fh9tuq5c9mmnlhuuwuy4hw70cmpdcs8sc6", - "current_block": 29775307, - "balance": { - "spendable": "0", - "unspendable": "0" - }, - "tokens_balances": { - "ATOM-IBC_IRIS": { - "spendable": "0", - "unspendable": "0" - } - } - } - }, - "id": null - } - ``` - + #### Response (in progress) @@ -95,18 +56,7 @@ The response will return the following: | status | string | Will return `InProgress` if task is not yet comepleted | | details | string | An indication of the current step of the activation process | - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": "RequestingWalletBalance" - }, - "id": null - } - ``` - + ### Error Types @@ -269,19 +219,9 @@ If the `task::enable_tendermint::status` returns `UserActionRequired`, we need t #### Command - + - - #### Response (success) - - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - + ## task::enable\_tendermint::cancel {{label : 'task::enable_tendermint::cancel', tag : 'API-v2'}} @@ -306,44 +246,6 @@ If you want to cancel the enabling process before it has completed, you can use - - #### Response (success) + - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - - - - #### Response (success - already finished) - - ```json - { - "mmrpc": "2.0", - "error": "Task is finished already", - "error_path": "init_standalone_coin.manager", - "error_trace": "init_standalone_coin:144] manager:101]", - "error_type": "TaskFinished", - "error_data": 0, - "id": null - } - ``` - - #### Response (error - no such task) - - ```json - { - "mmrpc": "2.0", - "error": "No such task '1'", - "error_path": "init_standalone_coin", - "error_trace": "init_standalone_coin:119]", - "error_type": "NoSuchTask", - "error_data": 1, - "id": null - } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/index.mdx index f65e90619..a54b61973 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_utxo/index.mdx @@ -41,19 +41,7 @@ Use this method for task managed activation of UTXO coins like KMD, LTC, BTC & D - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "task_id": 1 - }, - "id": null - } - ``` - + ## task::enable\_utxo::status {{label : 'task::enable_utxo::status', tag : 'API-v2'}} @@ -98,49 +86,7 @@ Once complete, `status` will be `Ok`, and the `details` object will have the fo | ticker | string | Ticker of the coin being activated. | | wallet\_balance | object | A standard [WalletBalanceInfo](/komodo-defi-framework/api/common_structures/wallet/#wallet-balance-info) object. Note: the structure may vary based on the `get_balances` parameter value in the activation request. | - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "Ok", - "details": { - "ticker": "KMD", - "current_block": 4230457, - "wallet_balance": { - "wallet_type": "HD", - "accounts": [ - { - "account_index": 0, - "derivation_path": "m/44'/141'/0'", - "total_balance": { - "KMD": { - "spendable": "20", - "unspendable": "0" - } - }, - "addresses": [ - { - "address": "RMC1cWXngQf2117apEKoLh3x27NoG88yzd", - "derivation_path": "m/44'/141'/0'/0/0", - "chain": "External", - "balance": { - "KMD": { - "spendable": "20", - "unspendable": "0" - } - } - } - ] - } - ] - } - } - }, - "id": null - } - ``` - + ```json @@ -170,18 +116,7 @@ Once complete, `status` will be `Ok`, and the `details` object will have the fo #### Response (in progress) - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": "RequestingWalletBalance" - }, - "id": null - } - ``` - + #### Response (ready, error) @@ -226,19 +161,9 @@ If the `task::enable_utxo::status` returns `UserActionRequired`, we need to use #### Command - + - - #### Response (success) - - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - + ## task::enable\_utxo::cancel {{label : 'task::enable_utxo::cancel', tag : 'API-v2'}} @@ -263,44 +188,6 @@ If you want to cancel the enabling process before it has completed, you can use - - #### Response (success) - - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - - - - #### Response (success - already finished) - - ```json - { - "mmrpc": "2.0", - "error": "Task is finished already", - "error_path": "init_standalone_coin.manager", - "error_trace": "init_standalone_coin:144] manager:101]", - "error_type": "TaskFinished", - "error_data": 0, - "id": null - } - ``` - - #### Response (error - no such task) + - ```json - { - "mmrpc": "2.0", - "error": "No such task '3'", - "error_path": "init_standalone_coin", - "error_trace": "init_standalone_coin:119]", - "error_type": "NoSuchTask", - "error_data": 3, - "id": null - } - ``` - + diff --git a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_z_coin/index.mdx b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_z_coin/index.mdx index 6aebc4ad7..1d8732b86 100644 --- a/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_z_coin/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/coin_activation/task_managed/enable_z_coin/index.mdx @@ -124,19 +124,7 @@ The Z coin lightwallet client only supports blocks that are post-sapling. The sa ``` - - #### Response - - ```json - { - "mmrpc": "2.0", - "result": { - "task_id": 0 - }, - "id": null - } - ``` - + ## task::enable\_z\_coin::status {{label : 'task::enable_z_coin::status', tag : 'API-v2'}} @@ -172,80 +160,7 @@ Once complete, `status` will be `Ok`, and the `details` object will have the fo - - #### Response (ActivatingCoin - enabling has started) - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": "ActivatingCoin" - }, - "id": null - } - ``` - - #### Response (UpdatingBlocksCache) - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": { - "UpdatingBlocksCache": { - "current_scanned_block": 265930, - "latest_block": 269656 - } - } - }, - "id": null - } - ``` - - #### Response (BuildingWalletDb) - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "InProgress", - "details": { - "BuildingWalletDb": { - "current_scanned_block": 265311, - "latest_block": 269656 - } - } - }, - "id": null - } - ``` - - #### Response (Enabling complete) - - ```json - { - "mmrpc": "2.0", - "result": { - "status": "Ok", - "details": { - "ticker": "ZOMBIE", - "current_block": 269657, - "wallet_balance": { - "wallet_type": "Iguana", - "address": "zs1e3puxpnal8ljjrqlxv4jctlyndxnm5a3mj5rarjvp0qv72hmm9caduxk9asu9kyc6erfx4zsauj", - "balance": { - "spendable": "29.99989008", - "unspendable": "0" - } - } - } - }, - "id": null - } - ``` - + #### Response (CoinCreationError - no Zcash Params) @@ -353,19 +268,9 @@ If the `task::enable_z_coin::status` returns `UserActionRequired`, we need to us | --------- | ------ | --------------------------- | | result | string | The outcome of the request. | - - - - #### Response (success) + - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - + ## task::enable\_z\_coin::cancel {{label : 'task::enable_z_coin::cancel', tag : 'API-v2'}} @@ -394,17 +299,7 @@ If you want to cancel the enabling process before it has completed, you can use - - #### Response (success) - - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - + #### Response (success - already finished) diff --git a/src/pages/komodo-defi-framework/api/v20/utils/add_node_to_version_stat/index.mdx b/src/pages/komodo-defi-framework/api/v20/utils/add_node_to_version_stat/index.mdx index 1d85925c3..3058ec4a1 100644 --- a/src/pages/komodo-defi-framework/api/v20/utils/add_node_to_version_stat/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/utils/add_node_to_version_stat/index.mdx @@ -17,38 +17,13 @@ The `add_node_to_version_stat` method adds a node's name, IP address, and PeerID + + ### Response Parameters -#### ๐Ÿ“Œ Examples - - - ```json - { - "mmrpc": "2.0", - "method": "add_node_to_version_stat", - "userpass": "RPC_UserP@SSW0RD", - "params": { - "name": "seed1", - "address": "168.119.236.241", - "peer_id": "12D3KooWEsuiKcQaBaKEzuMtT6uFjs89P1E8MK3wGRZbeuCbCw6P" - } - } - ``` - - - - #### Response (success) - - ```json - { - "mmrpc": "2.0", - "result": "success", - "id": null - } - ``` - + ### Error Types diff --git a/src/pages/komodo-defi-framework/api/v20/wallet/consolidate_utxos/index.mdx b/src/pages/komodo-defi-framework/api/v20/wallet/consolidate_utxos/index.mdx new file mode 100644 index 000000000..42fdd7f50 --- /dev/null +++ b/src/pages/komodo-defi-framework/api/v20/wallet/consolidate_utxos/index.mdx @@ -0,0 +1,84 @@ +export const title = "Komodo DeFi Framework Method: Consolidate Utxos"; +export const description = "Merges multiple unspent transaction outputs for an address."; + +# Consolidate Utxos + +## consolidate\_utxos {{label : 'consolidate_utxos', tag : 'API-v2'}} + +Merges multiple unspent transaction outputs for an address. + + + After a wallet has cultivated a long history, or received many small mining payouts, it may become slower to respond. + Consolidating unspent transaction outputs should be routinely performed when mining to wallet in order to avoid this. + + +### Request Parameters + + + +### Response Parameters + + + +#### ๐Ÿ“Œ Examples + + + + + +### Error Types + + + + + #### Error Response (Coin Not Found) + + ```json + { + "mmrpc": "2.0", + "error": "NoSuchCoin", + "error_path": "consolidate_utxos.lp_coins", + "error_trace": "consolidate_utxos:72] lp_coins:5278]", + "error_type": "NoSuchCoin", + "id": null + } + ``` + + #### Error Response (Merge Error) + + ```json + { + "mmrpc": "2.0", + "error": "Failed to merge UTXOs: utxo_arc_builder:173] Not enough unspent UTXOs to merge for coin=MARTY, found=1, required=20", + "error_path": "consolidate_utxos", + "error_trace": "consolidate_utxos:89]", + "error_type": "MergeError", + "error_data": "Failed to merge UTXOs: utxo_arc_builder:173] Not enough unspent UTXOs to merge for coin=MARTY, found=1, required=20", + "id": null + } + ``` + + #### Error Response (Missing parameter) + + ```json + { + "mmrpc": "2.0", + "error": "Error parsing request: missing field `merge_at`", + "error_path": "dispatcher", + "error_trace": "dispatcher:143]", + "error_type": "InvalidRequest", + "error_data": "missing field `merge_at`", + "id": null + } + + { + "mmrpc": "2.0", + "error": "Error parsing request: missing field `max_merge_at_once`", + "error_path": "dispatcher", + "error_trace": "dispatcher:143]", + "error_type": "InvalidRequest", + "error_data": "missing field `max_merge_at_once`", + "id": null + } + ``` + diff --git a/src/pages/komodo-defi-framework/api/v20/wallet/fetch_utxos/index.mdx b/src/pages/komodo-defi-framework/api/v20/wallet/fetch_utxos/index.mdx new file mode 100644 index 000000000..2578e4678 --- /dev/null +++ b/src/pages/komodo-defi-framework/api/v20/wallet/fetch_utxos/index.mdx @@ -0,0 +1,60 @@ +export const title = "Komodo DeFi Framework Method: Fetch Utxos"; +export const description = "Returns all unspent transaction outputs (UTXOs) for an address."; + +# Fetch Utxos + +## fetch\_utxos {{label : 'fetch_utxos', tag : 'API-v2'}} + +Returns all unspent transaction outputs (UTXOs) for supported coins. + + + After a wallet has cultivated a long history, or received many small mining payouts, it may become slower to respond. + Consolidating unspent transaction outputs should be routinely performed when mining to wallet in order to avoid this. + + +### Request Parameters + + + +### Response Parameters + + + +#### ๐Ÿ“Œ Examples + + + + + +### Error Types + + + + + #### Error Response (Coin Not Found) + + ```json + { + "mmrpc": "2.0", + "error": "NoSuchCoin", + "error_path": "fetch_utxos.lp_coins", + "error_trace": "fetch_utxos:72] lp_coins:5278]", + "error_type": "NoSuchCoin", + "id": null + } + ``` + + #### Error Response (Missing parameter) + + ```json + { + "mmrpc": "2.0", + "error": "Error parsing request: missing field `coin`", + "error_path": "dispatcher", + "error_trace": "dispatcher:143]", + "error_type": "InvalidRequest", + "error_data": "missing field `coin`", + "id": null + } + ``` + diff --git a/src/pages/komodo-defi-framework/api/v20/wallet/get_private_keys/index.mdx b/src/pages/komodo-defi-framework/api/v20/wallet/get_private_keys/index.mdx index c444ebe6e..71fd46b51 100644 --- a/src/pages/komodo-defi-framework/api/v20/wallet/get_private_keys/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/wallet/get_private_keys/index.mdx @@ -7,31 +7,19 @@ The `get_private_keys` method provides unified offline private key export functi There are two export modes: `iguana` and `hd`. The mode to be used should match the MM2.json `enable_hd` configuration. This method supports various coin protocols including UTXO-based coins (Bitcoin, Komodo, etc.), Ethereum-based tokens, Tendermint-based coins, and ZHTLC. -## Arguments +### Request Parameters -| Structure | Type | Description | -| -------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------- | -| coins | array of strings | array of coin tickers to export private keys for | -| mode | string (optional) | export mode: `"hd"` for HD wallet export, `"iguana"` for legacy Iguana format. Defaults based on MM2.json config | -| start\_index | integer (optional) | `"mode": hd` only. starting address index for HD mode (default: 0). | -| end\_index | integer (optional) | `"mode": hd` only. ending address index for HD mode (default: start\_index + 10). | -| account\_index | integer (optional) | `"mode": hd` only. account index for HD derivation path (default: 0). | + -## Response +### Response Parameters -The response format depends on the `mode` value: +#### HD Mode -### HD Mode Response + -| Structure | Type | Description | -| --------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------- | -| result | array of [HdCoinKeys](/komodo-defi-framework/api/common_structures/wallet/#hd-coin-keys) | array of coin key information with HD derivation data | +#### Iguana Mode -### Iguana Mode Response - -| Structure | Type | Description | -| --------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------- | -| result | array of [IguanaKeysInfo](/komodo-defi-framework/api/common_structures/wallet/#iguana-keys-info) | array of coin key information in Iguana format | + For detailed information about the structure fields and examples for different coin types (UTXO, ETH, ZHTLC, Tendermint), refer to the [HdKeysInfo](/komodo-defi-framework/api/common_structures/wallet/#hd-keys-info) and [IguanaKeysInfo](/komodo-defi-framework/api/common_structures/wallet/#iguana-keys-info) common structures. @@ -46,194 +34,15 @@ For detailed information about the structure fields and examples for different c #### Command (HD Mode) - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", - "method": "get_private_keys", - "params": { - "mode": "hd", - "coins": [ - "KMD", - "ETH", - "ARRR", - "ATOM", - "LTC-segwit" - ], - "start_index": 0, - "end_index": 1, - "account_index": 0 - } - } - ``` - - - - #### Response (HD Mode) + - Each coin object contains an array of [HdKeysInfo](/komodo-defi-framework/api/common_structures/wallet/#hd-keys-info) objects: - - ```json - { - "mmrpc": "2.0", - "result": [ - { - "coin": "KMD", - "addresses": [ - { - "derivation_path": "m/44'/141'/0/0/0", - "pubkey": "02416813acfc3d051f2a3163241528331cb1407814ca7eda035e29dd81ce1a7360", - "address": "RLEiXpHJrBBFGLHfBVyKwB8pWyuZvTX46Q", - "priv_key": "Ur57s4Btk5zv7ts2Rb1vHUjDzcBUuPGXZtuLUKK2yUTSCyNiA82f" - }, - { - "derivation_path": "m/44'/141'/0/0/1", - "pubkey": "02acd4bb36d93065879be4aae17c62791898ce366adb732b03dc0ce8092d04944b", - "address": "RJyVMQknrJnGBQVUrSBNffc2BD8j7kM6w1", - "priv_key": "UuMf4R7qEccYNDQWKYeooBANodhfev37QyoAnqZyb2VQz3CFGPH2" - } - ] - }, - { - "coin": "ETH", - "addresses": [ - { - "derivation_path": "m/44'/60'/0/0/0", - "pubkey": "0x47d306e1d039d958539d7b292c62a1da1d61eff2f4d8d96d35f3074032ef4a28f2434dab1170092591b955043792e6d8278d16b37363d79d34b5029dbe2d9a51", - "address": "0x614b89716A94b5be94a67540dF9A5bF1bE1685F3", - "priv_key": "0x4718e83c33159c53c19fbb44b98a5006a902d682ad096b2e1dbb7c55619463ac" - }, - { - "derivation_path": "m/44'/60'/0/0/1", - "pubkey": "0xde36fe6b0b1eaea7447e4bb3a56c8755fd5cf5d3fd9885a0582c99777229052e1b7019075669c5d65d4878b3db06e0b534159b0ba762714737677711b3375a3f", - "address": "0x49F4A1c47579d9603100Fc50e227079794335f20", - "priv_key": "0xe6a0f10b28192d2823433ec7121633c5d85239799b50e1e93280d000ad6a1341" - } - ] - }, - { - "coin": "ARRR", - "addresses": [ - { - "derivation_path": "m/44'/141'/0/0/0", - "pubkey": "02416813acfc3d051f2a3163241528331cb1407814ca7eda035e29dd81ce1a7360", - "address": "zs1tc85uguljgmhrhreqnsphanu4xura9lcn6zmz7qr3unsq5yr34kvl6938rvz7d2uml5g53ae3ys", - "priv_key": "secret-extended-key-main1qd0cv2y2qqqqpqye077hevux884lgksjtcqrxnc2qtdrfs05qh3h2wc99s8zc2fpke4auwnrwhpzqfzdudqn2t34t08d8rfvx3df02cgff82x5spg7lq28tvsr9vvwx6sdsymjc7fgk2ued06z9rzkp6lfczlx5ykj3mrqcy4l4wavgqsgzem0nunwzllely77k0ra86nhl936auh2qkuc3j3k75nmdw3cwaaevty6pq5wv57nxfqhwc2q4a97wpg2duxezegpkqe4cg05smz", - "viewing_key": "zxviews1qd0cv2y2qqqqpqye077hevux884lgksjtcqrxnc2qtdrfs05qh3h2wc99s8zc2fpkepkc20seu8dr44353s5ydt2vmlzr9jmk6dnqx2su6g2tp7jetqalgd45qweck6r54dexp2397m3qj2kwd5d8rq4fdu3lddh7fjc4awv4l4wavgqsgzem0nunwzllely77k0ra86nhl936auh2qkuc3j3k75nmdw3cwaaevty6pq5wv57nxfqhwc2q4a97wpg2duxezegpkqe4czeh3g2" - }, - { - "derivation_path": "m/44'/141'/0/0/1", - "pubkey": "02acd4bb36d93065879be4aae17c62791898ce366adb732b03dc0ce8092d04944b", - "address": "zs1gzddrvely0w04ugfgqaqnmsfdastjpgncedzk9duepvfwfwv3gnz7sqtwypp3g76szhxvky9fct", - "priv_key": "secret-extended-key-main1qhcqkcgnqyqqqq9mxw0qagvy89vdgmxn97jekuuatm3vcta2ejc9ehqdj7zafu370h2ph55942ysapxklzx4mv79mzceh0yxx5xfe3kau0lt7l5c5hfqfqg93fwm9rjq2avx8rpq77j38cwk8zgezn22qa097r5pezmg5qcfq86sup92ffwjachkeqfmla94ta5vp5jp3fzl32d669602w05xxavm0zr4nc476dy8gk2dytl79zcwrvpmnl5mg94r5mdecnsnwwexqsp3k56y", - "viewing_key": "zxviews1qhcqkcgnqyqqqq9mxw0qagvy89vdgmxn97jekuuatm3vcta2ejc9ehqdj7zafu370k24wlc7y7w6we2eck5cxa675cjmmhu8ya8ujlq37fvf8sdkl0tvqad6s8qscj7aynlw9wpta7meyap5z02ha8hq5eta0v7je7zv6esuq86sup92ffwjachkeqfmla94ta5vp5jp3fzl32d669602w05xxavm0zr4nc476dy8gk2dytl79zcwrvpmnl5mg94r5mdecnsnwwexqs8ypfm4" - } - ] - }, - { - "coin": "ATOM", - "addresses": [ - { - "derivation_path": "m/44'/118'/0/0/0", - "pubkey": "03888f72d067742f86922ed59e2e9c5ed4ac169ab930a1ef09d1073e8315c9057f", - "address": "cosmos1cfzlpyygw0vnjsqvgp0gnx52pd8ca4xqjs5cfu", - "priv_key": "c53a59347d214359d8b180c7d9d0ed4571d3e28e073ed3d4e366ab7556eaaa44" - }, - { - "derivation_path": "m/44'/118'/0/0/1", - "pubkey": "03d4da08e60e30d01dd9a17f4056302139461b168dbc3ef1fe6e4a97d467106774", - "address": "cosmos1zx32jeyv22quwke3rl75076l53rqusve9vcnuy", - "priv_key": "f297934a5b4bfbd814e3201dd9ebfa806eec220eed0382253ecbca9bd153286d" - } - ] - }, - { - "coin": "LTC-segwit", - "addresses": [ - { - "derivation_path": "m/84'/2'/0/0/0", - "pubkey": "02e32887fa81f83a4ff7a19f0852fd81bd55777e9b18c5568c677ea15259072cab", - "address": "ltc1qmqpl475drzjhlun0fpap2ktq2ctflhzyqqzphl", - "priv_key": "T87JyKC4cVCEtjEHjUDEH5vZibLb6VjjvKiaS9pre9JM77NrDcMe" - }, - { - "derivation_path": "m/84'/2'/0/0/1", - "pubkey": "03a99ef21c9df994f508f893490efad0677697dffd7f16b61082b89e5057bd9196", - "address": "ltc1qrm26v0v6m58r3wa0nrzs90f7gd7tqrl92fpup8", - "priv_key": "T5BeXdbLb6JhJbUaLAiHJVLk2GB6ZZizGQWWBefQWuJuJrzYRtUZ" - } - ] - } - ], - "id": null - } - ``` - + #### Command (Iguana Mode) - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "get_private_keys", - "coins": [ - "KMD", - "ETH", - "ARRR", - "ATOM", - "LTC-segwit" - ], - "mode": "iguana" - } - ``` - - - - #### Response (Iguana Mode) - - Each item is an [IguanaKeysInfo](/komodo-defi-framework/api/common_structures/wallet/#iguana-keys-info) object: + - ```json - { - "mmrpc": "2.0", - "result": [ - { - "coin": "KMD", - "pubkey": "0399e7edd441d026ab62d915c6542464002c1634cacfa3afd69fb9c08b7b76355f", - "address": "RQbyMz5jSBjidHkM4wRAhmbHUTSR7UehXG", - "priv_key": "UpaMPnKdPZJWBGb8whpQWjP5A61WpT6e2SUYQz4KyfkE4JzVU9ZF" - }, - { - "coin": "ETH", - "pubkey": "0x99e7edd441d026ab62d915c6542464002c1634cacfa3afd69fb9c08b7b76355f4e4a134020143df1d5cc243bb558db3eb94060247efd2c0a92878378ec424957", - "address": "0x2E75c8e10541C1202bFA8E38440b51A78263a914", - "priv_key": "0x10e0c6d3fcfdfe38f9200d83d5d17383f8bc756bfbcf01d7ec147110eccaf67a" - }, - { - "coin": "ARRR", - "pubkey": "0399e7edd441d026ab62d915c6542464002c1634cacfa3afd69fb9c08b7b76355f", - "address": "zs1dapmqsrrepxxw9qy4x97k5wpztjd2z6tzkgtgnyhyukzks92tttm9cnye02c2yd8qd6ug7uysvf", - "priv_key": "secret-extended-key-main1qqqqqqqqqqqqqqqqn7vs773606gx6lu3yhnmefhmcq887pxauktferk7530gcjdag0ggkajtt2c0vprldflng26q20veqyeuywlfmzpvjypnup59mmcqzalxgdvh294lucfwa9dx9c4c5ufh8aqdnyuxcznuw87jdkcg6xg88f282k6f4vzkzprfqaxv0fe7spe7c7a0z35y4zrq9y8wllm0c680lp7rc6z555szreu2mh8kgztm2jp3u5e8erp320mftv30v7egzzg9tjxx5" - }, - { - "coin": "ATOM", - "pubkey": "0399e7edd441d026ab62d915c6542464002c1634cacfa3afd69fb9c08b7b76355f", - "address": "cosmos14qtjek3vhdavfxv5q4mtywe75uvuatvud6fvv4", - "priv_key": "10e0c6d3fcfdfe38f9200d83d5d17383f8bc756bfbcf01d7ec147110eccaf67a" - }, - { - "coin": "LTC-segwit", - "pubkey": "0399e7edd441d026ab62d915c6542464002c1634cacfa3afd69fb9c08b7b76355f", - "address": "LaYjYgWGv2BCp65JmuRLtGKqvQM6crcRD4", - "priv_key": "T3cnXqzqHiJrV4RvJo5gxeFEAsbgoRqv58zyhXuC5vhggLfJvQF7" - } - ], - "id": null - } - ``` - + ## Error Types diff --git a/src/pages/komodo-defi-framework/api/v20/wallet/task_managed/withdraw/index.mdx b/src/pages/komodo-defi-framework/api/v20/wallet/task_managed/withdraw/index.mdx index d383ff034..69090d630 100644 --- a/src/pages/komodo-defi-framework/api/v20/wallet/task_managed/withdraw/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/wallet/task_managed/withdraw/index.mdx @@ -15,8 +15,8 @@ It will return the transaction hex (via `task::withdraw::status`), which then ne To cancel the transaction generation, use the [withdraw\_cancel](/komodo-defi-framework/api/v20/wallet/task_managed/withdraw/#task-withdraw-cancel) method. - When used for ZHTLC coins like ARRR or ZOMBIE, it may take some time to - complete. + When used for ZHTLC coins like ARRR or ZOMBIE, it may take some time to complete. + SIA protocol coins should use the v1 [withdraw](/komodo-defi-framework/api/legacy/withdraw/#withdraw) method, or the non-task v2 [withdraw](/komodo-defi-framework/api/v20/wallet/tx/withdraw/#withdraw) method. ### Arguments diff --git a/src/pages/komodo-defi-framework/api/v20/wallet/tx/get_raw_transaction/index.mdx b/src/pages/komodo-defi-framework/api/v20/wallet/tx/get_raw_transaction/index.mdx index da6d2da20..c99e62e3a 100644 --- a/src/pages/komodo-defi-framework/api/v20/wallet/tx/get_raw_transaction/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/wallet/tx/get_raw_transaction/index.mdx @@ -7,133 +7,48 @@ The `get_raw_transaction` method takes `coin` and `tx_hash` as input, and return ## Arguments -| Structure | Type | Description | -| --------- | ------ | -------------------------------------------------------------------- | -| coin | string | the name of the coin the user desires to request for the transaction | -| tx\_hash | string | hash of the transaction | + ## Response -| Structure | Type | Description | -| --------- | ------ | -------------------------------------------- | -| tx\_hex | string | bytes of signed transaction in string format | + #### Examples: ##### Request (DOC) - - ```json - { - "mmrpc": "2.0", - "method": "get_raw_transaction", - "userpass": "RPC_UserP@SSW0RD", - "params": { - "coin": "DOC", - "tx_hash": "989360b0225b4e05fa13643e2e306c8eb5c52fa611615dfd30195089010b1c7b" - }, - "id": 1 - } - ``` - + ##### Response (success) - ```json - { - "mmrpc":"2.0", - "result":{ - "tx_hex":"0400008085202f89025655b6fec358091a4a6b34107e69b10bd7660056d8f2a1e5f8eef0db6aec960100000000494830450221008c89db5e2d93d7674fe152e37344dfd24a0b1d4d382a7e0bcfc5d8190a141d72022050ce4ef929429e7e1a6c4ebd3f72a1a2aa25da1e0df65553a2c657658077ed1d01feffffff79cc137b70c39c9c7c2b9230c818ec684ffe731bf1ae821f91ba9d3e526f55f00000000049483045022100868c71f4a8e1452a3bc8b1d053a846959ab7df63fb0d147e9173f69818bbb1f3022060c7e045a34cf6af61bc3a74dc2db7b8bfa4949bc5919acceed40fc07d8706d201feffffff0240043a0000000000232102afdbba3e3c90db5f0f4064118f79cf308f926c68afd64ea7afc930975663e4c4ac201efc01000000001976a914347f2aedf63bac168c2cc4f075a2850435e20ac188ac96d3c96036dd0e000000000000000000000000" - }, - "id":0 - } - ``` + -##### Request (ETH) +##### Request (SIA) - - ```json - { - "mmrpc": "2.0", - "method": "get_raw_transaction", - "userpass": "RPC_UserP@SSW0RD", - "params": { - "coin": "ETH", - "tx_hash": "0x529aca42b6b592cca5d400832c83854135b924cada6e1c41b85f27fa0a0984b9" - }, - "id": 1 - } - ``` - + ##### Response (success) - ```json - { - "mmrpc":"2.0", - "result":{ - "tx_hex":"f86e8227578503b6ed90e6825208943faaa59e42f616f859d5771cbc07a99412ae44b288026fe9cb1ec6e9a08026a08e04accc3733376cf7b8f8d51c8398fd244fca736277053a7e87093f6db67708a069cc7dbc57094c4cca7828e6f8d92a8221c457ac7b5d0b0562e9d8896f75d1a5" - }, - "id":0 - } - ``` + +##### Request (ETH) + + + - ##### Error response (no such coin) - - ```json - { - "mmrpc": "2.0", - "error": "No such coin KMD", - "error_path": "lp_coins", - "error_trace": "lp_coins:2234] lp_coins:2156]", - "error_type": "NoSuchCoin", - "error_data": { - "coin": "KMD" - }, - "id": 0 - } - ``` - - ##### Error (invalid hash) - - ```json - { - "mmrpc": "2.0", - "error": "Invalid hash: Invalid input length", - "error_path": "utxo_common", - "error_trace": "utxo_common:1809]", - "error_type": "InvalidHashError", - "error_data": "Invalid input length", - "id": 1 - } - ``` - - ##### Error (invalid EC Signature) - - ```json - { - "mmrpc": "2.0", - "error": "Internal error: eth:3221] Crypto error (Invalid EC signature)", - "error_path": "eth", - "error_trace": "eth:543]", - "error_type": "InternalError", - "error_data": "eth:3221] Crypto error (Invalid EC signature)", - "id": 1 - } - ``` + ##### Response (success) + + + + + + ## Error Types -| Structure | Type | Description | -| ---------------- | ------ | ------------------------------------------------------------------------- | -| NoSuchCoin | string | The specified coin was not found or is not activated yet | -| InvalidHashError | string | The specified `hash` is not valid | -| Transport | string | The request was failed due to a network error | -| HashNotExist | string | The specified `hash` is not exist | -| InternalError | string | The request was failed due to an Komodo DeFi Framework API internal error | + diff --git a/src/pages/komodo-defi-framework/api/v20/wallet/tx/my_tx_history/index.mdx b/src/pages/komodo-defi-framework/api/v20/wallet/tx/my_tx_history/index.mdx index e4dafd1a6..473496bfe 100644 --- a/src/pages/komodo-defi-framework/api/v20/wallet/tx/my_tx_history/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/wallet/tx/my_tx_history/index.mdx @@ -9,481 +9,69 @@ For all other coins, use the legacy [my\_tx\_history](/komodo-defi-framework/api ## Arguments -| parameter | Type | Description | -| --------------- | ------- | ----------------------------------------------------------------------------------------------------------------- | -| coin | string | Ticker of the coin to get history for. | -| limit | integer | Optional. Limits the number of returned transactions. Defaults to `10`. Ignored if `max = true`. | -| paging\_options | object | Optional. A standard [Pagination](/komodo-defi-framework/api/common_structures/#pagination) object. | -| target | object | Optional. A standard [HistoryTarget](/komodo-defi-framework/api/common_structures/wallet/#history-target) object. | + #### Response -| Structure | Type | Description | -| -------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| transactions | array of objects | transactions data | -| from\_id | string | the from\_id specified in the request; this value is null if from\_id was not set | -| skipped | number | the number of skipped records (i.e. the position of `from_id` in the list + 1); this value is 0 if `from_id` was not set | -| limit | number | the limit that was set in the request; note that the actual number of transactions can differ from the specified limit (e.g. on the last page) | -| total | number | the total number of transactions available | -| page\_number | number | the page\_number that was set in the request | -| total\_pages | number | total pages available with the selected limit | -| current\_block | number | the number of the latest block of coin blockchain | -| sync\_status | object | A standard [SyncStatus](/komodo-defi-framework/api/common_structures/#sync-status) object. Provides the information that helps to track the progress of transaction history preloading at background | + + + + For SIA protocol coins, use the legacy [my\_tx\_history](/komodo-defi-framework/api/legacy/my_tx_history/#my-tx-history) method. + The v2 [my\_tx\_history](/komodo-defi-framework/api/v20/wallet/tx/my_tx_history/#my-tx-history) method is not yet compatible. + ## HD Wallet Account Request - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", - "method": "my_tx_history", - "params": { - "coin": "DOC", - "limit": 10, - "paging_options": { - "PageNumber": 1 - }, - "target": { - "type": "account_id", - "account_id": 77 - } - } - } - ``` - + ### Response - ```json - { - "mmrpc": "2.0", - "result": { - "coin": "DOC", - "target": { - "type": "account_id", - "account_id": 77 - }, - "current_block": 2066531, - "transactions": [ - { - "tx_hex": "0400008085202f890165d40f00c0b4395ccdbe6d4f3124fa8b06d4910e5327b67c8186dd4b55afa124030000006b483045022100a3fe466d53ce9e5429608427e0d0224e8923d86dabf5b6c4b4d54dae7c060acd022039d165e1e245efd93a9172ab0a7837985310b4beccd6e05be1894cd66e0912cc012102d09f2cb1693be9c0ea73bb48d45ce61805edd1c43590681b02f877206078a5b3ffffffff0400e1f505000000001976a91479bdbbf2302fa86c7c5861ddc782e6e5776a546d88ac00c2eb0b000000001976a91479bdbbf2302fa86c7c5861ddc782e6e5776a546d88aca01f791c000000001976a91479bdbbf2302fa86c7c5861ddc782e6e5776a546d88ace04728b93f0200001976a91490a0d8ba62c339ade97a14e81b6f531de03fdbb288ac00000000000000000000000000000000000000", - "tx_hash": "e5cd671c71f9a2564cd05057ee94be86bd215df257bfb7408b9ee6deb1e461c5", - "from": [ - "RNTv4xTLLm26p3SvsQCBy9qNK7s1RgGYSB" - ], - "to": [ - "RLNu8gszQ8ENUrY3VSyBS2714CNVwn1f7P", - "RNTv4xTLLm26p3SvsQCBy9qNK7s1RgGYSB" - ], - "total_amount": "24734.9033", - "spent_by_me": "0", - "received_by_me": "7.777", - "my_balance_change": "7.777", - "block_height": 2051968, - "timestamp": 1693906841, - "fee_details": { - "type": "Utxo", - "coin": "DOC", - "amount": "0.0001" - }, - "coin": "DOC", - "internal_id": "e5cd671c71f9a2564cd05057ee94be86bd215df257bfb7408b9ee6deb1e461c5", - "transaction_type": "StandardTransfer", - "memo": null, - "confirmations": 14564 - } - ], - "sync_status": { - "state": "Finished" - }, - "limit": 10, - "skipped": 0, - "total": 1, - "total_pages": 1, - "paging_options": { - "PageNumber": 1 - } - }, - "id": null - } - ``` + ## HD Wallet Address Request - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", - "method": "my_tx_history", - "params": { - "coin": "DOC", - "limit": 1, - "paging_options": { - "PageNumber": 1 - }, - "target": { - "type": "address_id", - "account_id": 0, - "chain": "External", - "address_id": 1 - } - } - } - ``` - + ### Response - ```json - { - "mmrpc": "2.0", - "result": { - "coin": "DOC", - "target": { - "type": "address_id", - "account_id": 0, - "chain": "External", - "address_id": 1 - }, - "current_block": 2066531, - "transactions": [ - { - "tx_hex": "0400008085202f8901c97b980d21538685a1fa82e1bb0c3a25b2dfaeaecb10647403b48afaefdcef3d010000006b483045022100d4ec136c54cda3861916e2390f0c8afc5348ce7844eaecb98da1bd2c964703280220107bb95194bdb51b9fd584d1834357376288b1ed5185a2bae34b290947683f5a01210325f62245ee44b9e586e71ef462833d8aa32ae2a05d06a9b78a9fb95b7a7d2a3fffffffff0280969800000000001976a914f26650dc9aa4e4505978ad635cdb15491cee70e188ace07c5205000000001976a914e30fff4883a28b09889f3e94c24392c899d2833e88ac930cf264000000000000000000000000000000", - "tx_hash": "8c6456383d7d112ec400597739e07a3c50557a4ec399b8993312d8c4780ce973", - "from": [ - "RVyndZp3ZrhGKSwHryyM3Kcz9aq2EJrW1z" - ], - "to": [ - "RVyndZp3ZrhGKSwHryyM3Kcz9aq2EJrW1z", - "RXNtAyDSsY3DS3VxTpJegzoHU9bUX54j56" - ], - "total_amount": "0.99293", - "spent_by_me": "0.99293", - "received_by_me": "0.99292", - "my_balance_change": "-0.00001", - "block_height": 2046628, - "timestamp": 1693584717, - "fee_details": { - "type": "Utxo", - "coin": "DOC", - "amount": "0.00001" - }, - "coin": "DOC", - "internal_id": "8c6456383d7d112ec400597739e07a3c50557a4ec399b8993312d8c4780ce973", - "transaction_type": "StandardTransfer", - "memo": null, - "confirmations": 19904 - } - ], - "sync_status": { - "state": "Finished" - }, - "limit": 1, - "skipped": 0, - "total": 10, - "total_pages": 10, - "paging_options": { - "PageNumber": 1 - } - }, - "id": null - } - ``` + - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "my_tx_history", - "mmrpc": "2.0", - "params": { - "coin": "BCH", - "limit": 2, - "paging_options": { - "PageNumber": 2 - } - } - } - ``` - + ### Response - ```json - { - "mmrpc": "2.0", - "result": { - "coin": "BCH", - "target": { - "type": "iguana" - }, - "current_block": 772607, - "transactions": [ - { - "tx_hex": "0100000001b7b45d92f8f3413a0e5656258e0a51f5c7e8230c0a08cef2ebec1ddbb8f7c28200000000d747304402203ca957fdfcfbba6123d78afe28b17fd4103cc04f6ada4110eb61c2a0350c29b802204215f203d583e8bcc79bd70f33af4f4e27500b5a5375efe75a1c31ec112f3c344120b3f71dbea00eeace7f09b0911de31e46f76a48036b86ccc207dac55540912e01004c6b6304dbf67563b175210315d9c51c657ab1be4ae9d3ab6e76a619d3bccfe830d5363fa168424c0d044732ac6782012088a914dde61fe24ea3cfa39379c475702692fa2f080900882103ed00156316c46094c0cbcf21a5ee549a1b3a50938c43096ef499ca28059edca6ac68ffffffff0133980200000000001976a91411a1563bfa55ae05fa621b2e245abe5a358c852e88acdbf67563", - "tx_hash": "e2167df56142bccdb8c620297f1b6ca3f7c8a955332838430d4d0f62530870f9", - "from": [ - "bitcoincash:ppaa62685yaucdf2a54g3rgtyc9g7yawrvvmqsfumc" - ], - "to": [ - "bitcoincash:qqg6z43mlf26up06vgdjufz6hedrtry99cvk5dgcnt" - ], - "total_amount": "0.00171035", - "spent_by_me": "0", - "received_by_me": "0.00170035", - "my_balance_change": "0.00170035", - "block_height": 766923, - "timestamp": 1668615553, - "fee_details": { - "type": "Utxo", - "coin": "BCH", - "amount": "0.00001" - }, - "coin": "BCH", - "internal_id": "e2167df56142bccdb8c620297f1b6ca3f7c8a955332838430d4d0f62530870f9", - "transaction_type": "StandardTransfer", - "confirmations": 5685 - }, - { - "tx_hex": "0100000001eccfa8c296e7b3e229be28a8ca6a5e5a7e89ee07a2d9441faaf5905679286a3c00000000d7473044022077d38ae45bb7257b152d4cb803aab62ca879cab60e9b3a7ca05ef099078e000402203106be31513c6526c14bdf40b28b4d38f78bb1958fc995e040ac4b2165d9d79141203bffadbc5bf035674f0d0f6e1d1a121fc6d404720679ff9b6610b298b41375a3004c6b6304bc847463b175210315d9c51c657ab1be4ae9d3ab6e76a619d3bccfe830d5363fa168424c0d044732ac6782012088a91457c7ce14c0444edc37ee52ed32b68890b0647cd3882103ed00156316c46094c0cbcf21a5ee549a1b3a50938c43096ef499ca28059edca6ac68ffffffff0163b10200000000001976a91411a1563bfa55ae05fa621b2e245abe5a358c852e88acbc847463", - "tx_hash": "98ddc27aa161967519f53cb3e91146a23b76ac4e33605f8e827c69f4d9b6de37", - "from": [ - "bitcoincash:ppnzkha52y53d7r7qn6mq4mcmaadmxzj4clfgneaxv" - ], - "to": [ - "bitcoincash:qqg6z43mlf26up06vgdjufz6hedrtry99cvk5dgcnt" - ], - "total_amount": "0.00177483", - "spent_by_me": "0", - "received_by_me": "0.00176483", - "my_balance_change": "0.00176483", - "block_height": 766752, - "timestamp": 1668519015, - "fee_details": { - "type": "Utxo", - "coin": "BCH", - "amount": "0.00001" - }, - "coin": "BCH", - "internal_id": "98ddc27aa161967519f53cb3e91146a23b76ac4e33605f8e827c69f4d9b6de37", - "transaction_type": "StandardTransfer", - "confirmations": 5856 - } - ], - "sync_status": { - "state": "Finished" - }, - "limit": 2, - "skipped": 2, - "total": 16, - "total_pages": 8, - "paging_options": { - "PageNumber": 2 - } - }, - "id": null - } - ``` + ## Request (BCH with FromId) - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "my_tx_history", - "mmrpc": "2.0", - "params": { - "coin": "BCH", - "limit": 2, - "paging_options": { - "FromId": "433b641bc89e1b59c22717918583c60ec98421805c8e85b064691705d9aeb970" - } - } - } - ``` - + ### Response - ```json - { - "mmrpc": "2.0", - "result": { - "coin": "BCH", - "target": { - "type": "iguana" - }, - "current_block": 772612, - "transactions": [ - { - "tx_hex": "0200000002365a29eb638da7fc57720ad6c99fdbc6cfb9c957920cfb62fd69e494b412c1c1020000006b483045022100de81bca8cfef2f95b3da8aa89edf4f5cc6cf489c565d0965b8142380ef3986f1022062d6ed47f2cd281f4860a27e835949aafbab89eeb0865fbf2280a283dfb7c417412102b9fdfedefde71b21523974b9f24a4b6a1b83c5640b839baa6eb14418cae08191ffffffffc1f73b403f893f93d95b8c7dfa1b59bb5445109d4c51107da1e08fb770e54136010000006a47304402203658375dac3b84ae17e72cf3f5157b8ad25e7caee0629fa8708868974f8d58b402206f38d016ed4e390d783627441685692d21b889d83919abd39368cba28f43f544412102b9fdfedefde71b21523974b9f24a4b6a1b83c5640b839baa6eb14418cae08191ffffffff040000000000000000406a04534c500001010453454e44205321508197ffed321c5fc9a1427e5c68b31d2c1ec92ae1c495f8acb08d8d66cd080000000000002710080000002278c569d322020000000000001976a914d346067e3c3c3964c395fee208594790e29ede5d88ac22020000000000001976a914580af35e3553d57b4b3a2036f4959f10246e98c788ac68955e03000000001976a914580af35e3553d57b4b3a2036f4959f10246e98c788ac00000000", - "tx_hash": "7b58248f3486079951a57d6dbd41c019a83f2b876c9fa3afa6fcc5a7c595b837", - "from": ["simpleledger:qpvq4u67x4fa276t8gsrday4nugzgm5ccu4usawss8"], - "to": [ - "simpleledger:qpvq4u67x4fa276t8gsrday4nugzgm5ccu4usawss8", - "simpleledger:qrf5vpn78s7rjexrjhlwyzzeg7gw98k7t5va3wuz4v" - ], - "total_amount": "1480551016.67", - "spent_by_me": "0", - "received_by_me": "100", - "my_balance_change": "100", - "block_height": 772211, - "timestamp": 1671817336, - "fee_details": { - "type": "Utxo", - "coin": "BCH", - "amount": "0.00000482" - }, - "coin": "BCH", - "internal_id": "57b78eb912a704921640a589d8bb42bb147dfb88c3d1b4b2e3df910be6b9ab31", - "transaction_type": { - "TokenTransfer": "5321508197ffed321c5fc9a1427e5c68b31d2c1ec92ae1c495f8acb08d8d66cd" - }, - "confirmations": 402 - } - ], - "sync_status": { - "state": "Finished" - }, - "limit": 10, - "skipped": 0, - "total": 1, - "total_pages": 1, - "paging_options": { - "FromId": "433b641bc89e1b59c22717918583c60ec98421805c8e85b064691705d9aeb970" - } - }, - "id": null - } - ``` + ## Request (IRIS with limit = 50) - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "method": "my_tx_history", - "mmrpc": "2.0", - "params": { - "coin": "IRIS", - "limit": 50 - } - } - ``` - + ### Response - ```json - { - "mmrpc": "2.0", - "result": { - "coin": "IRIS", - "target": { - "type": "iguana" - }, - "current_block": 18120346, - "transactions": [ - { - "tx_hex": "0a2a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b122a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b1a110a05756972697312083130303030303030", - "tx_hash": "B34A8D5AD74067F01A0207DF1851A14673C859D8A6F4FB0CBE292D2104C143CA", - "from": ["iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k"], - "to": ["iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k"], - "total_amount": "10.044559", - "spent_by_me": "10.044559", - "received_by_me": "10", - "my_balance_change": "-0.044559", - "block_height": 18120218, - "timestamp": 1673016440, - "fee_details": { - "type": "Tendermint", - "coin": "IRIS", - "amount": "0.044559", - "gas_limit": 100000 - }, - "coin": "IRIS", - "internal_id": "4644373032304131304637363034374441354438413433420000000000000000", - "transaction_type": "StandardTransfer", - "memo": "while you are out, buy milk", - "confirmations": 129 - }, - { - "tx_hex": "0a2a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b122a696161317a78733476776c36326b687174376e7a7276687a676b34377467366365706677707a673537711a4d0a446962632f3237333934464230393244324543434435363132334337344633364534433146393236303031434541444139434139374541363232423235463431453545423212053130303030", - "tx_hash": "09ADDD3427A3BA4B0A94023456DF534DB5B9B6821EC17C7C1B2C168EFCF49F26", - "from": ["iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k"], - "to": [], - "total_amount": "0.051788", - "spent_by_me": "0.051788", - "received_by_me": "0", - "my_balance_change": "-0.051788", - "block_height": 17996530, - "timestamp": 1672232661, - "fee_details": { - "type": "Tendermint", - "coin": "IRIS", - "amount": "0.051788", - "gas_limit": 100000 - }, - "coin": "IRIS", - "internal_id": "0000000000000000303941444444333432374133424134423041393430323334", - "transaction_type": "FeeForTokenTx", - "memo": null, - "confirmations": 123817 - }, - { - "tx_hex": "0a2a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b1240343133433843414333434142363945454632344432423643414238314146454344383044413745323731433237343637453142324635463337314446353241441a4061353539343834666536316665383630326465383632353964643263663031613865393437306437666635346262323536336233393035646462366238366535", - "tx_hash": "4E30C074CED6825F3E1B6584C376A426C20FDEFC9A22EB17D8E7DA4139FA0AEB", - "from": ["iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k"], - "to": [], - "total_amount": "182.742425", - "spent_by_me": "0.053103", - "received_by_me": "182.689322", - "my_balance_change": "182.636219", - "block_height": 17981793, - "timestamp": 1672138900, - "fee_details": { - "type": "Tendermint", - "coin": "IRIS", - "amount": "0.053103", - "gas_limit": 100000 - }, - "coin": "IRIS", - "internal_id": "3438353642314533463532383644454334373043303345340000000000000000", - "transaction_type": { - "CustomTendermintMsg": { - "msg_type": "SignClaimHtlc", - "token_id": null - } - }, - "memo": null, - "confirmations": 138554 - } - ], - "sync_status": { - "state": "NotStarted" - }, - "limit": 50, - "skipped": 0, - "total": 3, - "total_pages": 1, - "paging_options": { - "PageNumber": 1 - } - }, - "id": null - } - ``` + + + + + + + ### Error Response + + diff --git a/src/pages/komodo-defi-framework/api/v20/wallet/tx/withdraw/index.mdx b/src/pages/komodo-defi-framework/api/v20/wallet/tx/withdraw/index.mdx index be5cfbe4e..5e1fa6ae3 100644 --- a/src/pages/komodo-defi-framework/api/v20/wallet/tx/withdraw/index.mdx +++ b/src/pages/komodo-defi-framework/api/v20/wallet/tx/withdraw/index.mdx @@ -9,692 +9,140 @@ This method generates a raw transaction which should then be broadcast using [se ## Arguments -| Structure | Type | Description | -| -------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| coin | string | The name of the coin the user desires to withdraw. | -| to | string | Coins are withdrawn to this address. | -| amount | string (numeric) | The amount the user desires to withdraw, ignored when `max=true`. | -| memo | string | Optional. Adds a transaction memo for compatible coins (e.g. Tendermint ecosystem). | -| max | bool | Optional. Withdraw the maximum available amount. | -| fee | object | Optional. A standard [FeeInfo](/komodo-defi-framework/api/common_structures/wallet/#fee-info) object. | -| from | object | HD wallets only. A standard [WithdrawFromInfo](/komodo-defi-framework/api/common_structures/wallet/#withdraw-from-info) object. | -| ibc\_source\_channel | integer | Tendermint IBC transfers only. The source channel for the [IBC](https://tutorials.cosmos.network/academy/3-ibc/1-what-is-ibc.html) transaction. | -| broadcast | bool | Optional, defaults to `false`. When `false`, signed transaction hex must be broadcast manually with [send\_raw\_transaction](/komodo-defi-framework/api/legacy/send_raw_transaction/). Must be set to `true` for Metamask managed transactions. | + ### Response -| Structure | Type | Description | -| ---------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| from | array of strings | coins are withdrawn from this address; the array contains a single element, but transactions may be sent from several addresses (UTXO coins) | -| to | array of strings | coins are withdrawn to this address; this may contain the `my_address` address, where change from UTXO coins is sent | -| my\_balance\_change | string (numeric) | the expected balance of change in `my_address` after the transaction broadcasts | -| received\_by\_me | string (numeric) | the amount of coins received by `my_address` after the transaction broadcasts; the value may be above zero when the transaction requires that the Komodo DeFi Framework API send change to `my_address` | -| spent\_by\_me | string (numeric) | the amount of coins spent by `my_address`; this value differ from the request amount, as the transaction fee is added here | -| total\_amount | string (numeric) | the total amount of coins transferred | -| fee\_details | object | the fee details of the generated transaction; this value differs for utxo and ETH/ERC20 coins, check the examples for more details | -| tx\_hash | string | the hash of the generated transaction | -| tx\_hex | string | transaction bytes in hexadecimal format; use this value as input for [send\_raw\_transaction](/komodo-defi-framework/api/legacy/send_raw_transaction/) | -| coin | string | the name of the coin the user wants to withdraw | -| kmd\_rewards | object (optional) | an object containing information about accrued rewards; always exists if the coin is `KMD` | -| kmd\_rewards.amount | string (numeric, optional) | the amount of accrued rewards | -| kmd\_rewards.claimed\_by\_me | bool (optional) | whether the rewards been claimed by me | + ### ๐Ÿ“Œ Examples #### Withdraw BTC, KMD, and other BTC-based forks - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", - "method": "withdraw", - "params": { - "coin": "KMD", - "to": "RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh", - "amount": "10" - }, - "id": 0 - } - ``` - + #### Response (KMD success) - ```json - { - "mmrpc": "2.0", - "result": { - "tx_hex": "0400008085202f890152db2e550ca2d69eed487c95b6089b0f12e7a8937a89b8754c38a8c361560fca000000006a47304402200220239769f48c8bc96fbbcb66bcc0483f6234cb48ab823e13f0b791cdd501b902204f8b2dd875609e35f1677e39e403a18e9d2d98cd9916f51a62ac1edfc350cd47012102b3c168ed4acd96594288cee3114c77de51b6afe1ab6a866887a13a96ee80f33cffffffff0290a00b00000000001976a9145d904d4531f4c74f760a14ef057c866a06705dda88ac37040700000000001976a9145d904d4531f4c74f760a14ef057c866a06705dda88ac0609ed67000000000000000000000000000000", - "tx_hash": "aa456a6288292c4980637083871a6a4a1fb0a2242f6a30ae974069311691f37c", - "from": [ - "RHound8PpyhVLfi56dC7MK3ZvvkAmB3bvQ" - ], - "to": [ - "RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh" - ], - "total_amount": "10", - "spent_by_me": "10", - "received_by_me": "0", - "my_balance_change": "-10", - "block_height": 0, - "timestamp": 1743589636, - "fee_details": { - "type": "Utxo", - "coin": "KMD", - "amount": "0.00001" - }, - "coin": "KMD", - "internal_id": "", - "kmd_rewards": { - "amount": "0", - "claimed_by_me": true - }, - "transaction_type": "StandardTransfer", - "memo": null - }, - "id": null - } - ``` + #### HD Withdraw with derivation\_path - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", - "method": "withdraw", - "params": { - "coin": "MCL", - "to": "RNBA756iaFCx2Uhya3pvCufbeyovAaknJL", - "amount": 1.025, - "from": { - "derivation_path": "m/44'/141'/0'/0/0" - } - }, - "id": 0 - } - ``` - + - #### Response (KMD success) - - ```json - # TODO: Add response - ``` + #### HD Withdraw with `account_id`, `chain` and `address_id` - - ```json - { - "userpass": "RPC_UserP@SSW0RD", - "mmrpc": "2.0", - "method": "withdraw", - "params": { - "coin": "VRSC", - "to": "RNBA756iaFCx2Uhya3pvCufbeyovAaknJL", - "amount": 1.025, - "from": { - "account_id": 0, - "chain": "External", - "address_id": 2 - } - }, - "id": 0 - } - ``` - + - #### Response (KMD success) - - ```json - # TODO: Add response - ``` + #### Withdraw BTC, KMD, and other BTC-based forks, fixed fee - - ```json - { - "mmrpc": "2.0", - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "params": { - "coin": "DOC", - "to": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW", - "amount": "1.0", - "fee": { - "type": "UtxoFixed", - "amount": "0.1" - } - }, - "id": 0 - } - ``` - + #### Response (success) - ```json - { - "mmrpc": "2.0", - "result": { - "tx_hex": "0400008085202f8901ef25b1b7417fe7693097918ff90e90bba1351fff1f3a24cb51a9b45c5636e57e010000006b483045022100b05c870fcd149513d07b156e150a22e3e47fab4bb4776b5c2c1b9fc034a80b8f022038b1bf5b6dad923e4fb1c96e2c7345765ff09984de12bbb40b999b88b628c0f9012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ac8cbaae5f010000001976a91405aab5342166f8594baf17a7d9bef5d56744332788ace87a5e5d000000000000000000000000000000", - "tx_hash": "1ab3bc9308695960bc728fa427ac00d1812c4ae89aaa714c7618cb96d111be58", - "from": ["R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW"], - "to": ["R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW"], - "total_amount": "60.10253836", - "spent_by_me": "60.10253836", - "received_by_me": "60.00253836", - "my_balance_change": "-0.1", - "block_height": 0, - "timestamp": 1566472936, - "fee_details": { - "type": "Utxo", - "coin": "DOC", - "amount": "0.1" - }, - "coin": "DOC", - "internal_id": "" - }, - "id": 0 - } - ``` + #### Withdraw BTC, KMD, and other BTC-based forks, 1 coin per Kbyte fee - - ```json - { - "mmrpc": "2.0", - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "params": { - "coin": "DOC", - "to": "R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW", - "amount": "1.0", - "fee": { - "type": "UtxoPerKbyte", - "amount": "1" - } - }, - "id": 0 - } - ``` - + #### Response (success) - ```json - { - "mmrpc": "2.0", - "result": { - "tx_hex": "0400008085202f890258be11d196cb18764c71aa9ae84a2c81d100ac27a48f72bc6059690893bcb31a000000006b483045022100ef11280e981be280ca5d24c947842ca6a8689d992b73e3a7eb9ff21070b0442b02203e458a2bbb1f2bf8448fc47c51485015904a5271bb17e14be5afa6625d67b1e8012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff58be11d196cb18764c71aa9ae84a2c81d100ac27a48f72bc6059690893bcb31a010000006b483045022100daaa10b09e7abf9d4f596fc5ac1f2542b8ecfab9bb9f2b02201644944ddc0280022067aa1b91ec821aa48f1d06d34cd26fb69a9f27d59d5eecdd451006940d9e83db012102031d4256c4bc9f99ac88bf3dba21773132281f65f9bf23a59928bce08961e2f3ffffffff0200e1f505000000001976a91405aab5342166f8594baf17a7d9bef5d56744332788acf31c655d010000001976a91405aab5342166f8594baf17a7d9bef5d56744332788accd7c5e5d000000000000000000000000000000", - "tx_hash": "fd115190feec8c0c14df2696969295c59c674886344e5072d64000379101b78c", - "from": ["R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW"], - "to": ["R9o9xTocqr6CeEDGDH6mEYpwLoMz6jNjMW"], - "total_amount": "60.00253836", - "spent_by_me": "60.00253836", - "received_by_me": "59.61874931", - "my_balance_change": "-0.38378905", - "block_height": 0, - "timestamp": 1566473421, - "fee_details": { - "type": "Utxo", - "coin": "DOC", - "amount": "0.38378905" - }, - "coin": "DOC", - "internal_id": "" - }, - "id": 0 - } - ``` + #### Withdraw ETH, ERC20, and other ETH-based forks - - ```json - { - "mmrpc": "2.0", - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "params": { - "coin": "ETH", - "to": "0xbab36286672fbdc7b250804bf6d14be0df69fa28", - "amount": 10 - }, - "id": 0 - } - ``` - + #### Response (success) - ```json - { - "mmrpc": "2.0", - "result": { - "block_height": 0, - "coin": "ETH", - "fee_details": { - "type": "Eth", - "coin": "ETH", - "gas": 21000, - "gas_price": "0.000000001", - "total_fee": "0.000021" - }, - "from": ["0xbab36286672fbdc7b250804bf6d14be0df69fa29"], - "my_balance_change": "-10.000021", - "received_by_me": "0", - "spent_by_me": "10.000021", - "to": ["0xbab36286672fbdc7b250804bf6d14be0df69fa28"], - "total_amount": "10.000021", - "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", - "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" - }, - "id": 0 - } - ``` + #### ETH/ERC20 and other ETH-based forks, with gas fee - - ```json - { - "mmrpc": "2.0", - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "params": { - "coin": "COIN_NAME", - "to": "RECIPIENT_ADDRESS", - "amount": "AMOUNT", - "fee": { - "type": "EthGas", - "gas_price": "3.5", - "gas": 55000 - } - }, - "id": 0 - } - ``` - + #### Response (success) - ```json - { - "mmrpc": "2.0", - "result": { - "tx_hex": "f86d820b2884d09dc30082d6d894bab36286672fbdc7b250804bf6d14be0df69fa29888ac7230489e80000801ca0ef0167b0e53ed50d87b6fd630925f2bce6ee72e9b5fdb51c6499a7caaecaed96a062e5cb954e503ff83f2d6ce082649fdcdf8a77c8d37c7d26d46d3f736b228d10", - "tx_hash": "a26c4dcacf63c04e385dd973ca7e7ca1465a3b904a0893bcadb7e37681d38c95", - "from": ["0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29"], - "to": ["0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29"], - "total_amount": "10", - "spent_by_me": "10.0001925", - "received_by_me": "10", - "my_balance_change": "-0.0001925", - "block_height": 0, - "timestamp": 1566474670, - "fee_details": { - "type": "Eth", - "coin": "ETH", - "gas": 55000, - "gas_price": "0.0000000035", - "total_fee": "0.0001925" - }, - "coin": "ETH", - "internal_id": "" - }, - "id": 0 - } - ``` + + + +#### Withdraw SIA protocol + + + + + ##### Response (success) + + #### Withdraw maximum - - ```json - { - "mmrpc": "2.0", - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "params": { - "coin": "ETH", - "to": "0xbab36286672fbdc7b250804bf6d14be0df69fa28", - "max": true - }, - "id": 0 - } - ``` - + ##### Response (success) - ```json - { - "mmrpc": "2.0", - "result": { - "block_height": 0, - "coin": "ETH", - "fee_details": { - "type": "Eth", - "coin": "ETH", - "gas": 21000, - "gas_price": "0.000000001", - "total_fee": "0.000021" - }, - "from": ["0xbab36286672fbdc7b250804bf6d14be0df69fa29"], - "my_balance_change": "-10.000021", - "received_by_me": "0", - "spent_by_me": "10.000021", - "to": ["0xbab36286672fbdc7b250804bf6d14be0df69fa28"], - "total_amount": "10.000021", - "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", - "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" - }, - "id": 0 - } - ``` + ##### Withdraw QRC20 coins - - ```json - { - "mmrpc": "2.0", - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "params": { - "coin": "QRC20", - "to": "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs", - "amount": 10 - }, - "id": 0 - } - ``` - + ##### Response (success) - ```json - { - "mmrpc": "2.0", - "result": { - "block_height": 0, - "coin": "QRC20", - "timestamp": 1608725061, - "fee_details": { - "type": "Qrc20", - "coin": "tQTUM", - "miner_fee": "0.00000447", - "gas_limit": 100000, - "gas_price": 40, - "total_gas_fee": "0.04" - }, - "from": ["qXxsj5RtciAby9T7m98AgAATL4zTi4UwDG"], - "my_balance_change": "-10", - "received_by_me": "0", - "spent_by_me": "10", - "to": ["qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs"], - "total_amount": "10", - "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", - "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" - }, - "id": 0 - } - ``` + ##### Withdraw QRC20 coins with gas limit - - ```json - { - "mmrpc": "2.0", - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "params": { - "coin": "QRC20", - "to": "qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs", - "amount": 10, - "fee": { - "type": "Qrc20Gas", - "gas_limit": 250000, - "gas_price": 40 - } - }, - "id": 0 - } - ``` - + - ```json - { - "mmrpc": "2.0", - "result": { - "block_height": 0, - "coin": "QRC20", - "timestamp": 1608725061, - "fee_details": { - "type": "Qrc20", - "coin": "tQTUM", - "miner_fee": "0.00000447", - "gas_limit": 250000, - "gas_price": 40, - "total_gas_fee": "0.1" - }, - "from": ["qXxsj5RtciAby9T7m98AgAATL4zTi4UwDG"], - "my_balance_change": "-10", - "received_by_me": "0", - "spent_by_me": "10", - "to": ["qHmJ3KA6ZAjR9wGjpFASn4gtUSeFAqdZgs"], - "total_amount": "10", - "tx_hash": "8fbc5538679e4c4b78f8b9db0faf9bf78d02410006e8823faadba8e8ae721d60", - "tx_hex": "f86d820a59843b9aca0082520894bab36286672fbdc7b250804bf6d14be0df69fa28888ac7230489e80000801ba0fee87414a3b40d58043a1ae143f7a75d7f47a24e872b638281c448891fd69452a05b0efcaed9dee1b6d182e3215d91af317d53a627404b0efc5102cfe714c93a28" - }, - "id": 0 - } - ``` + -##### Withdraw with broadcast = true - -Metamask doesn't allow `eth_signTransaction` for security reasons, so we can only use `eth_sendTransaction` for processing withdrawals. -As a result, when submitting a withdrawal via metamask it will be rejected unless `"broadcast": true`. +#### Withdraw with broadcast = true - - ```json - { - "mmrpc": "2.0", - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "params": { - "coin": "MATIC", - "to": "0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29", - "amount": 0.1, - "broadcast": true - }, - "id": 0 - } - ``` - + - ```json - { - "mmrpc": "2.0", - "result": { - "tx_hex": "0ade010a8b010a1c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e64126b0a2a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b122a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b1a110a05756972697312083133303030303030124949742077617320612062726967687420636f6c642064617920696e20417072696c2c20616e642074686520636c6f636b73207765726520737472696b696e6720746869727465656e2e188f85b50812680a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a2103d8064eece4fa5c0f8dc0267f68cee9bdd527f9e88f3594a323428718c391ecc212040a020801181d12140a0e0a0575697269731205333835353310a08d061a40a9ac8c4112d7d7252062e289d222a438258a7c49c6657fdcbf831d62fc5eb2d05af46d6b86881335b3bc7ca98b2bfc3ef02ec5adf6768de9a778b282f9cc868e", - "tx_hash": "E00982A2A8442D7140916A34E29E287A0B1CBB4B38940372D1966BA7ACDE5BD6", - "from": ["iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k"], - "to": ["iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k"], - "total_amount": "13.038553", - "spent_by_me": "13.038553", - "received_by_me": "13", - "my_balance_change": "-0.038553", - "block_height": 0, - "timestamp": 0, - "fee_details": { - "type": "Tendermint", - "coin": "IRIS", - "amount": "0.038553", - "gas_limit": 100000 - }, - "coin": "IRIS", - "internal_id": "e00982a2a8442d7140916a34e29e287a0b1cbb4b38940372d1966ba7acde5bd6", - "transaction_type": "StandardTransfer", - "memo": "It was a bright cold day in April, and the clocks were striking thirteen." - }, - "id": 0 - } - ``` - - You can see the memo is included on the [block explorer](https://irishub.iobscan.io/#/txs/E00982A2A8442D7140916A34E29E287A0B1CBB4B38940372D1966BA7ACDE5BD6) + ##### Withdraw Tendermint coins with a memo and custom gas fee - - ```json - { - "mmrpc": "2.0", - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "params": { - "coin": "IRIS", - "to": "iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k", - "amount": 13, - "memo": "It was a bright cold day in April, and the clocks were striking thirteen.", - "fee": { - "type": "CosmosGas", - "gas_price": 0.05, - "gas_limit": 150000 - } - }, - "id": 0 - } - ``` - + - ```json - { - "mmrpc": "2.0", - "result": { - "tx_hex": "0ade010a8b010a1c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e64126b0a2a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b122a6961613136647271766c33753873756b667375346c6d3371736b32386a72336661686a6139767376366b1a110a05756972697312083133303030303030124949742077617320612062726967687420636f6c642064617920696e20417072696c2c20616e642074686520636c6f636b73207765726520737472696b696e6720746869727465656e2e188f85b50812680a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a2103d8064eece4fa5c0f8dc0267f68cee9bdd527f9e88f3594a323428718c391ecc212040a020801181d12140a0e0a0575697269731205333835353310a08d061a40a9ac8c4112d7d7252062e289d222a438258a7c49c6657fdcbf831d62fc5eb2d05af46d6b86881335b3bc7ca98b2bfc3ef02ec5adf6768de9a778b282f9cc868e", - "tx_hash": "E00982A2A8442D7140916A34E29E287A0B1CBB4B38940372D1966BA7ACDE5BD6", - "from": ["iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k"], - "to": ["iaa16drqvl3u8sukfsu4lm3qsk28jr3fahja9vsv6k"], - "total_amount": "13.038553", - "spent_by_me": "13.038553", - "received_by_me": "13", - "my_balance_change": "-0.038553", - "block_height": 0, - "timestamp": 0, - "fee_details": { - "type": "Tendermint", - "coin": "IRIS", - "amount": "0.038553", - "gas_limit": 100000 - }, - "coin": "IRIS", - "internal_id": "e00982a2a8442d7140916a34e29e287a0b1cbb4b38940372d1966ba7acde5bd6", - "transaction_type": "StandardTransfer", - "memo": "It was a bright cold day in April, and the clocks were striking thirteen." - }, - "id": 0 - } - ``` - - You can see the memo is included on the [block explorer](https://irishub.iobscan.io/#/txs/E00982A2A8442D7140916A34E29E287A0B1CBB4B38940372D1966BA7ACDE5BD6) + ##### Withdraw Tendermint IBC coins -Using the Cosmos [Ecosystem IBC protocol](https://everstake.one/blog/cosmos-ibc-breaking-down-the-walls-between-blockchains), you can withdraw coins from one chain to another. This example shows a withdrawal from Cosmos to Osmosis. - - - ```json - { - "mmrpc": "2.0", - "userpass": "RPC_UserP@SSW0RD", - "method": "withdraw", - "params": { - "coin": "ATOM", - "to": "osmo16drqvl3u8sukfsu4lm3qsk28jr3fahjac4rdw4", - "amount": 0.1, - "memo": "In the blackest of your moments, wait with no fear.", - "ibc_source_channel": 141, - "fee": { - "type": "CosmosGas", - "gas_price": 0.05, - "gas_limit": 150000 - } - }, - "id": 0 - } - ``` - - - - The `ibc_source_channel` value above is for demonstration only. For more information regarding how to set a valid value, see our guide to [finding the right IBC channel](/komodo-wallet/guides/how-to-find-the-right-ibc-channel-for-transfers/). - + - ```json - { - "mmrpc": "2.0", - "result": { - "tx_hex": "0af9010abc010a292f6962632e6170706c69636174696f6e732e7472616e736665722e76312e4d73675472616e73666572128e010a087472616e73666572120b6368616e6e656c2d3134311a0f0a057561746f6d1206313030303030222d636f736d6f733136647271766c33753873756b667375346c6d3371736b32386a72336661686a617377736163382a2b6f736d6f3136647271766c33753873756b667375346c6d3371736b32386a72336661686a6163347264773438a6c5b9a089f29efa171233496e2074686520626c61636b657374206f6620796f7572206d6f6d656e74732c20776169742077697468206e6f20666561722e188df8c70a12680a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a2103d8064eece4fa5c0f8dc0267f68cee9bdd527f9e88f3594a323428718c391ecc212040a020801180b12140a0e0a057561746f6d1205313733353910e0c65b1a40042c4fa45d77405ee94e737a000b146f5019137d5a2d3275849c9ad66dd8ef1d0f087fb584f34b1ebcf7989e41bc0675e96c83f0eec4ffe355e078b6615d7a72", - "tx_hash": "06174E488B7BBC35180E841F2D170327BB7DE0A291CA69050D81F82A7CF103CB", - "from": [ - "cosmos16drqvl3u8sukfsu4lm3qsk28jr3fahjaswsac8" - ], - "to": [ - "osmo16drqvl3u8sukfsu4lm3qsk28jr3fahjac4rdw4" - ], - "total_amount": "0.1173590000000000", - "spent_by_me": "0.1173590000000000", - "received_by_me": "0", - "my_balance_change": "-0.1173590000000000", - "block_height": 0, - "timestamp": 0, - "fee_details": { - "type": "Tendermint", - "coin": "ATOM", - "amount": "0.017359", - "gas_limit": 1500000 - }, - "coin": "ATOM", - "internal_id": "06174e488b7bbc35180e841f2d170327bb7de0a291ca69050d81f82a7cf103cb", - "transaction_type": "TendermintIBCTransfer", - "memo": "In the blackest of your moments, wait with no fear." - }, - "id": null - } - ``` - - You can see the memo is included on the [block explorer](https://irishub.iobscan.io/#/txs/E00982A2A8442D7140916A34E29E287A0B1CBB4B38940372D1966BA7ACDE5BD6) + ### Error Responses diff --git a/utils/docker/Dockerfile.kdf_native b/utils/docker/Dockerfile.kdf_native new file mode 100644 index 000000000..ba7d67d03 --- /dev/null +++ b/utils/docker/Dockerfile.kdf_native @@ -0,0 +1,40 @@ +# Multi-stage build for KDF +FROM rust:1.75 as builder + +# Install required tools (protobuf compiler and git for cloning) +RUN apt-get update && apt-get install -y protobuf-compiler git ca-certificates && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +# Build arguments and env metadata +ARG KDF_BRANCH=dev +ARG KDF_BUILD_COMMIT=unknown +ENV KDF_BRANCH=$KDF_BRANCH +ENV KDF_BUILD_COMMIT=$KDF_BUILD_COMMIT +ENV KDF_BUILD_TAG="${KDF_BRANCH}-${KDF_BUILD_COMMIT}" + +# Clone the KDF repository at the specified branch +RUN git clone --depth 1 --branch "$KDF_BRANCH" https://github.com/KomodoPlatform/komodo-defi-framework.git . + +# Optionally checkout a specific commit if provided +RUN if [ "$KDF_BUILD_COMMIT" != "unknown" ] && [ -n "$KDF_BUILD_COMMIT" ]; then \ + git fetch --unshallow || true; \ + git checkout "$KDF_BUILD_COMMIT"; \ + fi + +RUN set -eux; \ + if [ "$KDF_BUILD_COMMIT" = "unknown" ] || [ -z "$KDF_BUILD_COMMIT" ]; then \ + KDF_BUILD_COMMIT=$(git rev-parse --short=7 HEAD); \ + fi; \ + KDF_BUILD_TAG="${KDF_BRANCH}-${KDF_BUILD_COMMIT}"; \ + printf "KDF_BRANCH=%s\nKDF_BUILD_COMMIT=%s\nKDF_BUILD_TAG=%s\n" "$KDF_BRANCH" "$KDF_BUILD_COMMIT" "$KDF_BUILD_TAG" > /app/.kdf_build_info; \ + cargo build --release + +# Runtime stage +FROM docker.io/debian:stable-slim +RUN apt-get update && apt-get install -y curl jq && rm -rf /var/lib/apt/lists/* +WORKDIR /kdf +COPY --from=builder /app/target/release/kdf /usr/local/bin/kdf +COPY --from=builder /app/.kdf_build_info /usr/local/share/kdf_build_info +EXPOSE 7783 +CMD ["kdf"] \ No newline at end of file diff --git a/utils/docker/Dockerfile.processor b/utils/docker/Dockerfile.processor new file mode 100644 index 000000000..2c1c7b2e2 --- /dev/null +++ b/utils/docker/Dockerfile.processor @@ -0,0 +1,15 @@ +FROM python:3.11-slim + +WORKDIR /app + +# Install required Python packages +RUN pip install --no-cache-dir requests jinja2 + +# Copy the response processor script +COPY utils/scripts/process_responses.py /app/ + +# Create directories for input/output +RUN mkdir -p /input /output /templates + +# Default command +CMD ["python", "process_responses.py", "--help"] \ No newline at end of file diff --git a/utils/gen_api_methods_table.py b/utils/gen_api_methods_table.py index 179720fb4..74a3b6cde 100755 --- a/utils/gen_api_methods_table.py +++ b/utils/gen_api_methods_table.py @@ -4,22 +4,92 @@ import re import sys import json +import logging +import unicodedata script_path = os.path.dirname(os.path.realpath(__file__)) root_path = os.path.dirname(script_path) +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") +logger = logging.getLogger(__name__) + def slugify_for_api_table(text): text = text.split("{{")[0].strip() + text = text.lower() + # Normalize common separators to hyphens text = text.replace("_", "-") - text = re.sub(r'[^a-zA-Z0-9\-]', '', text) - return text.lower() + text = re.sub(r"[:]+", "-", text) # convert :: to - + text = re.sub(r"\s+", "-", text) # spaces to - + # Remove anything that's not alphanumeric or hyphen + text = re.sub(r"[^a-z0-9\-]", "", text) + # Collapse multiple hyphens + text = re.sub(r"\-+", "-", text).strip("-") + return text + +def slugify_heading(text): + """ + Best-effort replication of heading slug generation used by docs: + - Drop MDX annotations (e.g., `{{ ... }}`) + - Normalize unicode, lowercase + - Replace spaces/underscores with hyphens + - Remove non-alphanumeric/hyphen chars + """ + text = text.split("{{")[0].strip() + text = unicodedata.normalize("NFKD", text) + text = text.lower() + text = text.replace("_", "-") + text = re.sub(r"[:]+", "-", text) # convert :: to - + text = re.sub(r"\s+", "-", text) # spaces to hyphens + text = re.sub(r"[^a-z0-9\-]", "", text) + text = re.sub(r"\-+", "-", text).strip("-") + return text + +def compute_file_slugs(path_to_file): + """ + Fallback slug collector when filepathSlugs.json is stale or missing entries. + Collects markdown headings and generates unique slugs. + """ + slugs = [] + slug_counts = {} + try: + with open(path_to_file, "r", encoding="utf-8") as f: + for raw_line in f: + line = raw_line.rstrip("\n") + if line.startswith("#"): + # Remove leading hashes and whitespace + heading_text = line.lstrip("#").strip() + if not heading_text: + continue + base = slugify_heading(heading_text) + if not base: + continue + # Ensure uniqueness similar to slugifyWithCounter + count = slug_counts.get(base, 0) + slug_counts[base] = count + 1 + if count == 0: + slugs.append(base) + else: + slugs.append(f"{base}-{count+1}") + except Exception as e: + logger.error(f"Failed to compute fallback slugs for {path_to_file}: {e}") + return [] + return slugs def get_method_name(line): + # Try to capture CodeGroup label="..." if 'CodeGroup' in line and "label" in line: - return line.split('label="')[1].split('"')[0] - elif line.startswith("## ") and "label" in line: - return line.split('label')[1].split(':')[1].split(',')[0].replace("'", "").replace('"', "").strip() + # Support both single and double quotes + m = re.search(r'label\s*=\s*["\']([^"\']+)["\']', line) + if m: + return m.group(1) + # Fallback: capture heading labels like: + # # title {{label : 'method_name', ...}} + # or with any heading level (##, ###, etc.) + if "label" in line: + m = re.search(r'label\s*:\s*["\']([^"\']+)["\']', line) + if m: + return m.group(1).strip() return "" def ignore_file(file): @@ -37,6 +107,7 @@ def ignore_file(file): "komodo-defi-framework/setup", "komodo-defi-framework/api/index.mdx", "komodo-defi-framework/api/v20/coin_activation/index.mdx", + "komodo-defi-framework/api/v20/coin_activation/task_managed/enable_sia/index.mdx", "task_managed/index.mdx", "non_fungible_tokens/index.mdx", "query_nft_database_tables/index.mdx", @@ -57,6 +128,22 @@ def get_method_slug(method): return "" return slugify_for_api_table(method) +def get_method_link(method_file, doc_path, file_slugs) -> dict: + with open(method_file, 'r') as f: + for line in f.readlines(): + method = get_method_name(line) + if method and method.strip(): + method_slug = slugify_for_api_table(method) + if method_slug not in file_slugs: + method_slug = file_slugs[0] + return { + "link": f"[{method}]({doc_path}/#{method_slug})", + "method": method, + "doc_url": doc_path + } + return {} + + def gen_api_methods_table(): slugs = json.loads(open(f'{root_path}/filepathSlugs.json', 'r').read()) komodefi_files = glob.glob(f'{root_path}/src/pages/komodo-defi-framework/**/index.mdx', recursive = True) @@ -66,31 +153,49 @@ def gen_api_methods_table(): "v20-dev": [] } methods_list = [] + updated_slugs = False for file in komodefi_files: if ignore_file(file): continue file_methods_list = [] relative_path = file.replace(f'{root_path}/', '') - file_slugs = slugs[file.replace(f'{root_path}/', '')] + key = relative_path + if key not in slugs: + logger.warning( + "Missing slug entry in filepathSlugs.json for '%s'. " + "Attempting to compute fallback slugs from file headings. " + "If you keep seeing this, regenerate slugs via: " + "node utils/js/validate_update_internal_links_userpass.js", key + ) + computed = compute_file_slugs(file) + if not computed: + sys.exit( + f"Missing slug entry for '{key}' and failed to compute fallback slugs.\n" + f"Please run: node utils/js/validate_update_internal_links_userpass.js\n" + f"Then re-run this script." + ) + slugs[key] = computed + updated_slugs = True + file_slugs = slugs[key] with open(file, 'r') as f: - for line in f.readlines(): - doc_path = file.replace(f'{root_path}/src/pages', '').replace('/index.mdx', '') - doc_split = doc_path.split('/') - if len(doc_split) > 3: - section = doc_split[3] - if section in methods_dict: - method = get_method_name(line) - method_slug = slugify_for_api_table(method) - if method_slug not in file_slugs: - method_slug = file_slugs[0] - methods_dict[section].append({ - "link": f"[{method}]({doc_path}/#{method_slug})", - "method": method, - "doc_url": doc_path - }) - file_methods_list.append(method) + doc_path = file.replace(f'{root_path}/src/pages', '').replace('/index.mdx', '') + doc_split = doc_path.split('/') + if len(doc_split) > 3: + section = doc_split[3] + else: + logger.error(f"###### No section found in {file}!") + continue + if section not in methods_dict: + logger.error(f"###### {section} section not found in methods_dict!") + continue + method_link = get_method_link(file, doc_path, file_slugs) + if "link" not in method_link: + logger.error(f"###### No method link found in {file}!") + continue + methods_dict[section].append(method_link) + file_methods_list.append(method_link["method"]) # print(f"###### Methods in {file}: {file_methods_list}") @@ -100,6 +205,15 @@ def gen_api_methods_table(): sys.exit(f"###### No methods found in {file}!") methods_list = sorted(list(set(methods_list))) + # Persist any newly computed slugs back to filepathSlugs.json to plug the gap for future runs + if updated_slugs: + try: + with open(f'{root_path}/filepathSlugs.json', 'w', encoding='utf-8') as f_slugs: + json.dump(slugs, f_slugs, indent=2, ensure_ascii=False) + logger.info("Updated filepathSlugs.json with missing entries.") + except Exception as e: + logger.warning("Failed to persist updated slugs to filepathSlugs.json: %s", e) + with open(f'{script_path}/methods_table.template', 'r') as f: template = f.read() with open(f'{root_path}/src/pages/komodo-defi-framework/api/index.mdx', 'w') as f2: @@ -117,6 +231,7 @@ def gen_api_methods_table(): v20 = j["link"] if i == "v20-dev": v20_dev = j["link"] + legacy = escape_underscores(legacy) v20 = escape_underscores(v20) v20_dev = escape_underscores(v20_dev) diff --git a/utils/js/auto_add_missing_sidebar_wallet_links.js b/utils/js/auto_add_missing_sidebar_wallet_links.js new file mode 100644 index 000000000..0295f26cc --- /dev/null +++ b/utils/js/auto_add_missing_sidebar_wallet_links.js @@ -0,0 +1,111 @@ +import fs from "fs"; +import path from "path"; + +const SIDEBAR_FILE = "./src/data/sidebar.json"; +const PAGES_ROOT = "./src/pages"; +const V20_WALLET_PREFIX = "/komodo-defi-framework/api/v20/wallet/"; +const V20_ROOT_KEY = "/komodo-defi-framework/api/v20/"; +const NAV_ROOT = "komodefiApi20MasterPageNavigation"; +const TARGET_SECTION_TITLE = "Wallet"; + +function walkDir(dirPath, onFile) { + fs.readdirSync(dirPath).forEach((file) => { + const filePath = path.join(dirPath, file); + const stat = fs.statSync(filePath); + if (stat.isDirectory()) { + walkDir(filePath, onFile); + } else { + onFile(filePath); + } + }); +} + +function collectAllPageHrefsFromSidebar(sidebarData) { + const hrefs = new Set(); + Object.keys(sidebarData).forEach((navKey) => { + const navigation = sidebarData[navKey]; + Object.keys(navigation).forEach((basePath) => { + const sections = navigation[basePath]; + sections.forEach((section) => { + if (section.titleLink) { + hrefs.add(section.titleLink); + } + if (Array.isArray(section.links)) { + section.links.forEach((l) => { + if (l && l.href) hrefs.add(l.href); + }); + } + }); + }); + }); + return hrefs; +} + +function ensureTrailingSlash(s) { + return s.endsWith("/") ? s : s + "/"; +} + +function deriveTitleFromHref(href) { + const parts = href.split("/").filter(Boolean); + return parts[parts.length - 1] || href; +} + +function findWalletSection(sidebarData) { + if (!sidebarData[NAV_ROOT] || !sidebarData[NAV_ROOT][V20_ROOT_KEY]) return null; + const sections = sidebarData[NAV_ROOT][V20_ROOT_KEY]; + for (const section of sections) { + if (section.title === TARGET_SECTION_TITLE && Array.isArray(section.links)) { + return section; + } + } + return null; +} + +function main() { + const args = process.argv.slice(2); + if (args.length === 0) { + console.log("[auto-add-sidebar] No target hrefs provided. No changes made."); + console.log(`[auto-add-sidebar] Usage: node ${path.basename(process.argv[1])} /komodo-defi-framework/api/v20/wallet/fetch_utxos/ [/komodo-defi-framework/api/v20/wallet/another/]`); + return; + } + + const sidebarData = JSON.parse(fs.readFileSync(SIDEBAR_FILE, "utf8")); + const allSidebarHrefs = collectAllPageHrefsFromSidebar(sidebarData); + const walletSection = findWalletSection(sidebarData); + if (!walletSection) { + console.warn( + `[auto-add-sidebar] Could not find '${TARGET_SECTION_TITLE}' section under ${NAV_ROOT}.${V20_ROOT_KEY}. No changes made.` + ); + return; + } + + const additions = []; + for (let rawHref of args) { + let href = ensureTrailingSlash(rawHref.trim()); + if (!href.startsWith(V20_WALLET_PREFIX)) { + console.warn(`[auto-add-sidebar] Skipping non-wallet href: ${href}`); + continue; + } + if (allSidebarHrefs.has(href)) { + console.log(`[auto-add-sidebar] Already present, skipping: ${href}`); + continue; + } + const title = deriveTitleFromHref(href); + walletSection.links.push({ title, href }); + additions.push({ title, href }); + } + + if (additions.length > 0) { + fs.writeFileSync(SIDEBAR_FILE, JSON.stringify(sidebarData, null, 2) + "\n"); + additions.forEach(({ href }) => { + console.log( + `[auto-add-sidebar] Added missing page to sidebar (derived placement): ${href} -> ${NAV_ROOT}.${V20_ROOT_KEY}['${TARGET_SECTION_TITLE}']` + ); + }); + } else { + console.log("[auto-add-sidebar] No additions needed. No changes made."); + } +} + +main(); + diff --git a/utils/js/cleanup_bad_sidebar_wallet_links.js b/utils/js/cleanup_bad_sidebar_wallet_links.js new file mode 100644 index 000000000..1b1b5607d --- /dev/null +++ b/utils/js/cleanup_bad_sidebar_wallet_links.js @@ -0,0 +1,31 @@ +import fs from "fs"; + +const SIDEBAR_FILE = "./src/data/sidebar.json"; + +function main() { + const sidebarData = JSON.parse(fs.readFileSync(SIDEBAR_FILE, "utf8")); + let removed = 0; + + if (!sidebarData["komodefiApi20MasterPageNavigation"] || !sidebarData["komodefiApi20MasterPageNavigation"]["/komodo-defi-framework/api/v20/"]) { + console.log("[cleanup-sidebar] v20 navigation not found. No changes made."); + return; + } + const sections = sidebarData["komodefiApi20MasterPageNavigation"]["/komodo-defi-framework/api/v20/"]; + for (const section of sections) { + if (section.title === "Wallet" && Array.isArray(section.links)) { + const before = section.links.length; + section.links = section.links.filter((l) => !(l && typeof l.href === "string" && l.href.startsWith("src/pages/"))); + removed += before - section.links.length; + } + } + + if (removed > 0) { + fs.writeFileSync(SIDEBAR_FILE, JSON.stringify(sidebarData, null, 2) + "\n"); + console.log(`[cleanup-sidebar] Removed ${removed} bad wallet href entries starting with 'src/pages/'.`); + } else { + console.log("[cleanup-sidebar] No bad wallet href entries found. No changes made."); + } +} + +main(); + diff --git a/utils/py/README_update_nodes.md b/utils/py/README_update_nodes.md deleted file mode 100644 index 4eac09eb1..000000000 --- a/utils/py/README_update_nodes.md +++ /dev/null @@ -1,305 +0,0 @@ -# Node Update Script - -This script addresses [GitHub Issue #360](https://github.com/KomodoPlatform/komodo-docs-mdx/issues/360) by automatically updating server and node values in documentation request examples with the latest data from the [coins repository](https://github.com/KomodoPlatform/coins). - -## Overview - -The Komodo DeFi Framework documentation includes example request JSON files that show how to interact with various APIs. These examples contain server URLs (electrum servers, RPC nodes, light wallet servers) that can become outdated over time. This script automates the process of keeping those server values synchronized with the authoritative source in the coins repository. - -## How It Works - -1. **Fetches Latest Data**: Downloads the latest `coins_config.json` from the coins repository -2. **Identifies Tickers**: Scans request JSON files for ticker symbols -3. **Detects Protocol Type**: Automatically determines coin protocol (ETH, Tendermint, UTXO, ZHTLC) -4. **Server Selection**: Selects up to 3 servers, prioritizing domains containing 'cipig' or 'komodo' -5. **Updates Servers**: Replaces server/node arrays with the selected values from the coins configuration -6. **Protocol-Specific Mapping**: Maps different server types based on coin protocol -7. **Preserves Structure**: Maintains the original JSON structure and formatting - -## Usage - -### Prerequisites - -Make sure you have the Python virtual environment activated: - -```bash -source utils/py/.venv/bin/activate -``` - -### Basic Usage - -Update a single file in-place: -```bash -python utils/py/update_request_nodes.py src/data/requests/kdf/v2/coin_activation.json -``` - -Update a file and save to a different location: -```bash -python utils/py/update_request_nodes.py input.json output.json -``` - -### Command Line Options - -- `input_file` (required): Path to the input request JSON file -- `output_file` (optional): Path to save the updated file. If not specified, updates the input file in-place -- `-v, --verbose`: Enable verbose logging for debugging - -### Examples - -#### Update coin activation examples -```bash -python utils/py/update_request_nodes.py src/data/requests/kdf/v2/coin_activation.json -``` - -#### Batch update multiple files -```bash -find src/data/requests/kdf/ -name "*.json" -exec python utils/py/update_request_nodes.py {} \; -``` - -#### Test mode (save to different file) -```bash -python utils/py/update_request_nodes.py src/data/requests/kdf/v2/coin_activation.json /tmp/test_output.json -``` - -## Supported Coin Protocols - -The script automatically detects and handles different coin protocols: - -### ETH/EVM Chains (ETH, MATIC, BNB, AVAX, etc.) -- **coins_config field**: `nodes` -- **request field**: `nodes` -- **Example coins**: ETH, MATIC, BNB, AVAX, FTM - -### Tendermint/Cosmos Chains -- **coins_config field**: `rpc_urls` -- **request field**: `nodes` -- **Example coins**: ATOM, IRIS, OSMOSIS - -### UTXO Chains (Bitcoin-like) -- **coins_config field**: `electrum` -- **request field**: `servers` (nested under `mode.rpc_data.servers`) -- **Example coins**: BTC, LTC, KMD, QTUM, BCH - -### ZHTLC Chains (Privacy coins) -- **coins_config fields**: `light_wallet_d_servers` + `electrum` -- **request fields**: `light_wallet_d_servers` + `electrum_servers` -- **Example coins**: ARRR, ZOMBIE - -## Supported JSON Formats - -The script can handle various JSON structures: - -### Single Request Object -```json -{ - "method": "task::enable_eth::init", - "params": { - "ticker": "MATIC", - "nodes": [...] - } -} -``` - -### Multiple Request Objects -```json -{ - "Request1": { - "params": { - "ticker": "MATIC", - "nodes": [...] - } - }, - "Request2": { - "params": { - "ticker": "BTC", - "nodes": [...] - } - } -} -``` - -### Array of Requests -```json -[ - { - "params": { - "ticker": "MATIC", - "nodes": [...] - } - } -] -``` - -## Server Format Conversion - -The script automatically converts between the coins repository format and the documentation format based on protocol type: - -### ETH/EVM Nodes -**Coins Repository Format:** -```json -"nodes": [ - { - "url": "https://example.com:8545", - "ws_url": "wss://example.com:8546", - "komodo_proxy": true - } -] -``` - -**Documentation Format:** -```json -"nodes": [ - { - "url": "https://example.com:8545" - } -] -``` - -### Tendermint RPC URLs -**Coins Repository Format:** -```json -"rpc_urls": [ - { - "url": "https://cosmos-rpc.example.com/", - "api_url": "https://cosmos-api.example.com/", - "grpc_url": "https://cosmos-grpc.example.com/", - "ws_url": "wss://cosmos-rpc.example.com/websocket" - } -] -``` - -**Documentation Format:** -```json -"nodes": [ - { - "url": "https://cosmos-rpc.example.com/", - "api_url": "https://cosmos-api.example.com/", - "grpc_url": "https://cosmos-grpc.example.com/", - "ws_url": "wss://cosmos-rpc.example.com/websocket" - } -] -``` - -### UTXO Electrum Servers -**Coins Repository Format:** -```json -"electrum": [ - { - "url": "btc.electrum1.cipig.net:10000", - "protocol": "TCP", - "contact": [...] - } -] -``` - -**Documentation Format:** -```json -"servers": [ - { - "url": "btc.electrum1.cipig.net:10000", - "protocol": "TCP" - } -] -``` - -### ZHTLC Light Wallet Servers -**Coins Repository Format:** -```json -"light_wallet_d_servers": [ - "https://piratelightd1.example.com:443" -], -"electrum": [ - { - "url": "arrr.electrum1.cipig.net:10008", - "protocol": "TCP" - } -] -``` - -**Documentation Format:** -```json -"light_wallet_d_servers": [ - "https://piratelightd1.example.com:443" -], -"electrum_servers": [ - { - "url": "arrr.electrum1.cipig.net:10008", - "protocol": "TCP" - } -] -``` - -## Automation - -For CI/CD integration, you can create a script that updates all request files: - -```bash -#!/bin/bash -# Update all request JSON files -find src/data/requests/kdf -name "*.json" | while read file; do - echo "Updating $file..." - python utils/py/update_request_nodes.py "$file" -done -``` - -## Error Handling - -The script includes comprehensive error handling: - -- **Network Issues**: Graceful handling of connection failures when fetching coins_config.json -- **Invalid JSON**: Clear error messages for malformed JSON files -- **Missing Files**: File existence validation before processing -- **Missing Tickers**: Warnings for tickers not found in the coins configuration -- **Missing Nodes**: Warnings for coins without node configurations - -## Logging - -The script provides detailed logging: - -- **INFO**: Normal operation status and update summaries -- **WARNING**: Non-critical issues like missing tickers -- **ERROR**: Critical failures that prevent execution -- **DEBUG**: Detailed operation information (with `-v` flag) - -## Server Selection Logic - -To keep JSON payloads lightweight, the script limits server selections to 3 maximum: - -1. **Priority Selection**: Servers containing 'cipig' or 'komodo' in their domains are preferred -2. **Random Selection**: If more than 3 servers are available, selection is randomized within priority groups -3. **Fallback**: If fewer than 3 priority servers exist, the remainder is filled from regular servers - -## Example Output - -``` -2025-08-07 15:56:34,085 - INFO - Loaded request file: coin_activation.json -2025-08-07 15:56:34,085 - INFO - Fetching coins configuration from https://raw.githubusercontent.com/... -2025-08-07 15:56:34,521 - INFO - Successfully fetched configuration for 769 coins -2025-08-07 15:56:34,521 - DEBUG - Detected protocol 'UTXO' for ticker 'KMD' -2025-08-07 15:56:34,521 - DEBUG - Selected 3 servers from 9 available (9 priority, 0 regular) -2025-08-07 15:56:34,521 - INFO - Updated UTXO electrum servers for ticker 'KMD': 9 -> 3 servers -2025-08-07 15:56:34,521 - INFO - Updated request object: TaskEnableUtxoInit -2025-08-07 15:56:34,522 - INFO - โœ… Successfully updated 16 request(s) with latest server/node values -2025-08-07 15:56:34,523 - INFO - ๐ŸŽ‰ Update completed successfully! -``` - -## Integration with CI/CD - -This script can be integrated into GitHub Actions workflows to automatically keep request examples up-to-date. See the example workflow in `.github/workflows/update-nodes.yml` for a complete CI/CD solution. - -## Troubleshooting - -### Script shows "No updates were needed" -- Verify that the JSON file contains a `ticker` field -- Check that the ticker exists in the coins repository -- Ensure the request has a `nodes` array to update - -### Network errors when fetching coins_config.json -- Check internet connectivity -- Verify that the coins repository URL is accessible -- Consider using a local copy of coins_config.json for testing - -### JSON parsing errors -- Validate your input JSON file with a JSON validator -- Check for trailing commas or other syntax issues -- Ensure proper UTF-8 encoding \ No newline at end of file diff --git a/utils/py/batch_update_nodes.py b/utils/py/batch_update_nodes.py index 1e85cc01f..a528be12f 100755 --- a/utils/py/batch_update_nodes.py +++ b/utils/py/batch_update_nodes.py @@ -99,7 +99,7 @@ def main(): args = parser.parse_args() if args.verbose: - logging.getLogger().setLevel(logging.DEBUG) + logging.getLogger().setLevel(logging.INFO) # Convert to absolute path relative to the script's location if not os.path.isabs(args.directory): diff --git a/utils/py/clean_slate.py b/utils/py/clean_slate.py new file mode 100644 index 000000000..d0160e30b --- /dev/null +++ b/utils/py/clean_slate.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +""" +Clean Slate - Disable all enabled coins to start fresh + +This script: +1. Gets all enabled coins using get_enabled_coins +2. Disables each coin to ensure a clean slate for testing +""" + +import sys +import logging +from pathlib import Path +from typing import List + +# Import from kdf_responses_manager to reuse existing functionality +sys.path.append(str(Path(__file__).parent / "lib")) +from managers.kdf_responses_manager import KdfResponseManager, KDFInstance, KDF_INSTANCES + +# Setup logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + + +def get_enabled_coins_from_instance(manager: KdfResponseManager, instance: KDFInstance) -> List[str]: + """Get list of enabled coins from a KDF instance.""" + request = { + "userpass": instance.userpass, + "method": "get_enabled_coins" + } + + outcome, response = manager.send_request(instance, request) + + if outcome.name == "SUCCESS" and "result" in response: + tickers = [] + result = response["result"] + + # Handle different response formats + if isinstance(result, list): + # List of coin objects like [{"ticker": "ETH", "address": "..."}, ...] + for coin in result: + if isinstance(coin, dict) and "ticker" in coin: + tickers.append(coin["ticker"]) + elif isinstance(coin, str): + tickers.append(coin) + elif isinstance(result, dict): + # Sometimes result is {"enabled_coins": [...]} + if "enabled_coins" in result: + for coin in result["enabled_coins"]: + if isinstance(coin, dict) and "ticker" in coin: + tickers.append(coin["ticker"]) + elif isinstance(coin, str): + tickers.append(coin) + # Or result contains coin objects directly + else: + tickers = list(result.keys()) + + logger.info(f"{instance.name}: Found {len(tickers)} enabled coins: {tickers}") + return tickers + else: + error_msg = response.get("error", "Unknown error") if isinstance(response, dict) else str(response) + logger.warning(f"{instance.name}: Failed to get enabled coins: {error_msg}") + return [] + + +def clean_slate(): + """Clean slate - disable all enabled coins on all instances.""" + logger.info("๐Ÿงน Starting clean slate process...") + + # Create a manager instance to reuse existing functionality + manager = KdfResponseManager() + total_disabled = 0 + + for instance in KDF_INSTANCES: + logger.info(f"\n๐Ÿ“‹ Processing instance: {instance.name}") + + # Get enabled coins using the manager + enabled_coins = get_enabled_coins_from_instance(manager, instance) + + if not enabled_coins: + logger.info(f"{instance.name}: No coins to disable") + continue + + # Disable each coin using the manager's disable_coin method + instance_disabled = 0 + for ticker in enabled_coins: + if manager.disable_coin(instance, ticker): + instance_disabled += 1 + + logger.info(f"{instance.name}: Disabled {instance_disabled}/{len(enabled_coins)} coins") + total_disabled += instance_disabled + + logger.info(f"\n๐ŸŽ‰ Clean slate complete! Disabled {total_disabled} coins total") + + # Verify clean state + logger.info("\n๐Ÿ” Verifying clean state...") + for instance in KDF_INSTANCES: + enabled_coins = get_enabled_coins_from_instance(manager, instance) + if enabled_coins: + logger.warning(f"{instance.name}: Still has {len(enabled_coins)} coins enabled: {enabled_coins}") + else: + logger.info(f"{instance.name}: โœ… Clean slate confirmed") + + +if __name__ == "__main__": + clean_slate() diff --git a/utils/py/generate_postman.py b/utils/py/generate_postman.py new file mode 100755 index 000000000..0f19b3277 --- /dev/null +++ b/utils/py/generate_postman.py @@ -0,0 +1,1781 @@ +#!/usr/bin/env python3 +""" +Unified Postman Collection Generator for KDF API + +This script generates comprehensive Postman collections from KDF JSON files, +supporting both standard collections and environment-specific collections. + +Features: +- Generates standard collections with full folder structure and validation +- Generates environment-specific collections (Native, WASM, Trezor variants) +- Parameter validation and reporting +- Protocol filtering for different environments +- Comprehensive CLI interface + +Usage: + python unified_postman_generator.py --help +""" + +import json +import os +import sys +import uuid +import argparse +from pathlib import Path +from typing import Dict, List, Set, Any, Optional, Tuple +from datetime import datetime +import logging + +# Add the lib directory to the path +sys.path.append(str(Path(__file__).parent / "lib")) + +from managers.environment_manager import EnvironmentManager +from managers.table_manager import TableManager +from utils.json_utils import dump_sorted_json + +# Setup logging +logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') +logger = logging.getLogger(__name__) + + +class UnifiedPostmanGenerator: + """Unified generator for both standard and environment-specific Postman collections.""" + + def __init__(self, workspace_root: Optional[str] = None): + """Initialize the generator. + + Args: + workspace_root: Path to the workspace root. If None, auto-detects. + """ + if workspace_root is None: + # Auto-detect workspace root from utils/py/ to workspace root + workspace_root = Path(__file__).parent.parent.parent + + self.workspace_root = Path(workspace_root) + self.requests_dir = self.workspace_root / "src" / "data" / "requests" / "kdf" + self.responses_dir = self.workspace_root / "src" / "data" / "responses" / "kdf" + self.tables_dir = self.workspace_root / "src" / "data" / "tables" + + # Initialize managers + self.env_manager = EnvironmentManager() + self.table_manager = TableManager(workspace_root=self.workspace_root, logger=logger) + + # Reports data + self.unused_params = {} + self.unused_params_detailed = {} + self.missing_responses = {} # combined (back-compat) + self.missing_responses_v2 = {} + self.missing_responses_legacy = {} + self.missing_requests = {} + self.missing_methods = [] # combined (back-compat) + self.missing_methods_v2 = [] + self.missing_methods_legacy = [] + self.untranslated_keys = [] + + # Task ID variables for method groups + self.task_variables = {} + + # Load configurations (keep v2 and legacy separate) + self.method_config_v2, self.method_config_legacy = self.load_method_configs() + self.common_responses = self.load_common_responses() + + # ===== COMMON UTILITIES ===== + + def load_json_file(self, file_path: Path) -> Optional[Dict]: + """Load JSON file and return its content.""" + try: + with open(file_path, 'r') as f: + return json.load(f) + except FileNotFoundError: + logger.warning(f"File not found: {file_path}") + return None + except json.JSONDecodeError as e: + logger.error(f"Invalid JSON in {file_path}: {e}") + return None + + def load_method_configs(self) -> Tuple[Dict[str, Dict], Dict[str, Dict]]: + """Load method configurations separately for v2 and legacy without merging.""" + data_dir = self.workspace_root / "src" / "data" + v2_file = data_dir / "kdf_methods_v2.json" + legacy_file = data_dir / "kdf_methods_legacy.json" + + v2_cfg = self.load_json_file(v2_file) or {} + legacy_cfg = self.load_json_file(legacy_file) or {} + + # No fallback to old single file; expect split files + + return v2_cfg, legacy_cfg + + def get_method_config(self, method: str, version: Optional[str] = None) -> Dict: + """Get method config for a method name, optionally constrained by version.""" + if version == 'legacy': + return self.method_config_legacy.get(method, {}) + if version == 'v2': + return self.method_config_v2.get(method, {}) + # Fallback search order: v2 then legacy + return self.method_config_v2.get(method, self.method_config_legacy.get(method, {})) + + def load_common_responses(self) -> Dict[str, Dict]: + """Load common responses from common.json.""" + common_file = self.responses_dir / "common.json" + common_responses = self.load_json_file(common_file) + return common_responses if common_responses else {} + + def _is_manual_example(self, request_key: str) -> bool: + """Check if a method requires manual intervention or external services.""" + manual_patterns = [ + "WalletConnect", # Requires external wallet connection + "Trezor", # Requires hardware wallet + "Metamask", # Requires browser extension + "Pin", # Requires user PIN entry + "UserAction" # Requires user interaction + ] + + return any(pattern in request_key for pattern in manual_patterns) + + def load_all_tables(self) -> Dict[str, Dict]: + """Load all table files and combine them.""" + return self.table_manager.load_all_tables() + + def load_request_data(self, version: str = "v2") -> Dict[str, Any]: + """Load ALL request data from JSON files in the specified version directory.""" + request_dir = self.requests_dir / version + + if not request_dir.exists(): + raise FileNotFoundError(f"Request directory not found: {request_dir}") + + all_requests = {} + for request_file in request_dir.glob("*.json"): + file_data = self.load_json_file(request_file) + if file_data: + all_requests.update(file_data) + + if not all_requests: + raise FileNotFoundError(f"No valid request files found in: {request_dir}") + + return all_requests + + # ===== DATA PROCESSING UTILITIES ===== + + def extract_method_name(self, method: str) -> str: + """Extract method name from KDF method string.""" + return method.replace("::", "_") + + def get_method_path_components(self, method: str) -> List[str]: + """Convert method name to folder path components.""" + if "::" in method: + # For v2 methods like "task::enable_utxo::init" + parts = method.split("::") + return parts # ["task", "enable_utxo", "init"] + else: + # For legacy methods like "enable" + return [method] # ["enable"] + + def get_method_group(self, request_key: str) -> str: + """Extract method group from request key.""" + suffixes = ["Init", "Status", "UserAction", "Cancel"] + group = request_key + for suffix in suffixes: + if group.endswith(suffix): + group = group[:-len(suffix)] + break + return group + + def get_task_variable_name(self, method: str) -> str: + """Generate task variable name from method.""" + if "::" in method: + parts = method.split("::") + if len(parts) >= 2: + method_part = parts[1].replace("_", " ").title().replace(" ", "") + return f"Task{method_part}_TaskId" + return "DefaultTask_TaskId" + + def get_translated_name(self, request_key: str, version: Optional[str] = None) -> str: + """Get translated name for request key, fallback to original.""" + # Search version-specific config first + search_spaces: List[Dict[str, Dict]] = [] + if version == 'v2': + search_spaces = [self.method_config_v2, self.method_config_legacy] + elif version == 'legacy': + search_spaces = [self.method_config_legacy, self.method_config_v2] + else: + search_spaces = [self.method_config_v2, self.method_config_legacy] + + for space in search_spaces: + for method, config in space.items(): + if config.get('deprecated', False): + continue + examples = config.get("examples", {}) + if request_key in examples: + return examples[request_key] + + if request_key not in self.untranslated_keys: + self.untranslated_keys.append(request_key) + return request_key + + # ===== DATA TRANSFORMATION ===== + + def replace_userpass(self, data: Any) -> Any: + """Replace userpass values with Postman variable.""" + if isinstance(data, dict): + new_dict = {} + for key, value in data.items(): + if key == "userpass" and value == "RPC_UserP@SSW0RD": + new_dict[key] = "{{ userpass }}" + else: + new_dict[key] = self.replace_userpass(value) + return new_dict + elif isinstance(data, list): + return [self.replace_userpass(item) for item in data] + else: + return data + + def replace_task_id(self, data: Any, task_var_name: str) -> Any: + """Replace task_id values with Postman variable.""" + if isinstance(data, dict): + new_dict = {} + for key, value in data.items(): + if key == "task_id" and isinstance(value, int): + new_dict[key] = f"{{{{ {task_var_name} }}}}" + else: + new_dict[key] = self.replace_task_id(value, task_var_name) + return new_dict + elif isinstance(data, list): + return [self.replace_task_id(item, task_var_name) for item in data] + else: + return data + + # ===== ENVIRONMENT-SPECIFIC FILTERING ===== + + def filter_protocols_for_environment(self, request_data: Dict[str, Any], + environment: str) -> Dict[str, Any]: + """Filter and update protocol configurations for specific environment.""" + filtered_data = json.loads(json.dumps(request_data)) # Deep copy + + # Parse environment components + env_parts = environment.split('_') + base_env = env_parts[0] # native, wasm + wallet_type = env_parts[1] if len(env_parts) > 1 and env_parts[1] in ['hd', 'iguana'] else None + + for request_key, request_body in filtered_data.items(): + if not isinstance(request_body, dict): + continue + + params = request_body.get('params', {}) + method = request_body.get('method', '') + + # Handle electrum servers + self._update_electrum_servers(params, base_env) + + # Handle WebSocket URLs + self._update_websocket_urls(params, base_env) + + # Handle nodes for ETH/Tendermint + self._update_node_urls(params, base_env) + + # Handle wallet type specific parameters + self._update_wallet_type_params(params, method, wallet_type) + + return filtered_data + + def _update_electrum_servers(self, params: Dict[str, Any], environment: str): + """Update electrum server configurations for environment.""" + # Handle nested electrum servers (UTXO coins) + if 'mode' in params and 'rpc_data' in params['mode']: + rpc_data = params['mode']['rpc_data'] + if 'servers' in rpc_data: + rpc_data['servers'] = self._filter_electrum_servers( + rpc_data['servers'], environment + ) + + # Handle direct electrum servers (Z-coins) + if 'electrum_servers' in params: + params['electrum_servers'] = self._filter_electrum_servers( + params['electrum_servers'], environment + ) + + def _filter_electrum_servers(self, servers: List[Dict], environment: str) -> List[Dict]: + """Filter electrum servers: exclude WSS, favor cipig and SSL, cap at 3.""" + if not isinstance(servers, list): + return [] + # Normalize protocol casing and exclude WSS + candidates: List[Dict] = [] + for s in servers: + if not isinstance(s, dict): + continue + proto = str(s.get('protocol') or s.get('proto') or '').upper() + if proto == 'WSS': + continue + candidates.append(s) + # Partition by protocol + ssl_list = [s for s in candidates if str(s.get('protocol') or s.get('proto') or '').upper() == 'SSL'] + tcp_list = [s for s in candidates if str(s.get('protocol') or s.get('proto') or '').upper() == 'TCP'] + other_list = [s for s in candidates if s not in ssl_list and s not in tcp_list] + # Prioritize cipig within each group + def prioritize_cipig(lst: List[Dict]) -> List[Dict]: + cipig = [] + rest = [] + for item in lst: + url = str(item.get('url', '')).lower() + if 'cipig' in url: + cipig.append(item) + else: + rest.append(item) + return cipig + rest + ordered = prioritize_cipig(ssl_list) + prioritize_cipig(tcp_list) + prioritize_cipig(other_list) + return ordered[:3] + + def _update_websocket_urls(self, params: Dict[str, Any], environment: str): + """Update WebSocket URLs for environment.""" + if environment == 'wasm': + # Ensure all WebSocket URLs use WSS + for key in ['nodes', 'ws_url']: + if key in params: + if key == 'nodes' and isinstance(params[key], list): + for node in params[key]: + if 'ws_url' in node and node['ws_url'].startswith('ws://'): + node['ws_url'] = node['ws_url'].replace('ws://', 'wss://') + + def _update_node_urls(self, params: Dict[str, Any], environment: str): + """Update node URLs for environment preferences.""" + if 'nodes' in params and isinstance(params['nodes'], list): + for node in params['nodes']: + if environment == 'wasm': + if 'ws_url' in node and not node['ws_url'].startswith('wss://'): + if node['ws_url'].startswith('ws://'): + node['ws_url'] = node['ws_url'].replace('ws://', 'wss://') + + def _update_wallet_type_params(self, params: Dict[str, Any], method: str, wallet_type: str): + """Update parameters based on wallet type requirements.""" + if wallet_type is None: + return + + if wallet_type == 'iguana': + # Remove HD-only parameters for Iguana wallet + hd_only_params = self.env_manager.get_conditional_params(method, 'hd') + for param in hd_only_params: + if param in params: + del params[param] + + # ===== VALIDATION ===== + + def validate_request_params(self, request_data: Dict, method: str, tables: Dict[str, Dict], version: Optional[str] = None): + """Validate request parameters against table definitions and return full validation result.""" + method_cfg = self.get_method_config(method, version) + if not method_cfg: + logger.warning(f"No method config found for method: {method} (version={version})") + return set() + + validation_result = self.table_manager.validate_request_params( + request_data, method, method_cfg + ) + + if validation_result: + if validation_result.unused_params: + logger.warning(f"Unused parameters in {method}: {validation_result.unused_params}") + return validation_result + + return None + + + def check_response_exists(self, request_key: str, version: str) -> bool: + """Check if response exists for the request in ANY response file and has actual content.""" + response_dir = self.responses_dir / version + if not response_dir.exists(): + return False + + # Check all response files in the version directory + for response_file in response_dir.glob("*.json"): + response_data = self.load_json_file(response_file) + if not response_data: + continue + + if request_key not in response_data: + continue + + # Resolve any common response references + response_value = response_data[request_key] + resolved_response = self.resolve_response_reference(response_value, self.common_responses) + + if resolved_response is None: + continue + + # Check if response has actual content (not just empty templates) + if isinstance(resolved_response, dict): + # Check for success and error arrays + success_responses = resolved_response.get("success", []) + error_responses = resolved_response.get("error", []) + + # If both arrays are empty, consider this as missing response + if (isinstance(success_responses, list) and len(success_responses) == 0 and + isinstance(error_responses, list) and len(error_responses) == 0): + continue + + # Found a valid response + return True + + return False + + def resolve_response_reference(self, response_value: Any, common_responses: Dict[str, Dict]) -> Any: + """Resolve response references to common responses.""" + if isinstance(response_value, str) and response_value in common_responses: + return common_responses[response_value] + elif isinstance(response_value, list): + resolved_list = [] + for item in response_value: + if isinstance(item, str) and item in common_responses: + resolved_list.append(common_responses[item]) + else: + resolved_list.append(item) + return resolved_list + else: + return response_value + + # ===== TABLE GENERATION ===== + + def _track_missing_table(self, method: str, table_type: str) -> None: + """Track a missing table by type.""" + self.table_manager.track_missing_table(method, table_type) + + def generate_table_markdown(self, method: str, tables: Dict[str, Dict], version: Optional[str] = None) -> str: + """Generate markdown table from table data for method.""" + if not self.get_method_config(method, version): + # Method not defined - will be tracked in the split missing methods report + return "" + + return self.table_manager.generate_table_markdown(method, self.get_method_config(method, version)) + + # ===== POSTMAN REQUEST CREATION ===== + + def create_postman_request(self, request_key: str, request_data: Dict, + version: str, tables: Dict[str, Dict], + method_examples: List[tuple] = None, + environment: str = None) -> Dict: + """Create a Postman request object.""" + method = request_data.get("method", "unknown") + + # Get translated name + if method_examples and len(method_examples) > 1: + translated_name = method + else: + translated_name = self.get_translated_name(request_key, version) + + # Add environment suffix for environment-specific collections + if environment and environment != "standard": + env_suffix = environment.replace('_', ' ').title() + if env_suffix not in translated_name: + translated_name += f" ({env_suffix})" + + # Handle task_id variables + task_var_name = None + if "task_id" in json.dumps(request_data): + task_var_name = self.get_task_variable_name(method) + self.task_variables[task_var_name] = "1" + + # Replace userpass and task_id + processed_data = self.replace_userpass(request_data) + if task_var_name: + processed_data = self.replace_task_id(processed_data, task_var_name) + + # Generate description with table markdown + description = self.generate_table_markdown(method, tables, version) + + # Add environment-specific description notes + if environment: + description += self._generate_environment_notes(environment, method) + + # Add examples if there are multiple variants + examples = [] + if method_examples and len(method_examples) > 1: + for example_key, example_data in method_examples: + example_name = self.get_translated_name(example_key) + processed_example = self.replace_userpass(example_data) + if task_var_name: + processed_example = self.replace_task_id(processed_example, task_var_name) + + examples.append({ + "name": example_name, + "originalRequest": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": json.dumps(processed_example, indent=2) + }, + "url": { + "raw": "{{base_url}}", + "host": ["{{base_url}}"] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json" + }) + + request_obj = { + "name": translated_name, + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": json.dumps(processed_data, indent=2) + }, + "url": { + "raw": "{{base_url}}", + "host": ["{{base_url}}"] + }, + "description": description + }, + "response": examples, + "event": [] + } + + # Add test for capturing task_id if this is an init request + if method.endswith("::init") and "task_id" not in json.dumps(request_data): + actual_task_var_name = self.get_task_variable_name(method) + test_script = f""" +pm.test("Capture task_id", function () {{ + const responseJson = pm.response.json(); + if (responseJson.result && responseJson.result.task_id) {{ + pm.collectionVariables.set("{actual_task_var_name}", responseJson.result.task_id); + }} +}}); +""" + request_obj["event"] = [{ + "listen": "test", + "script": { + "exec": test_script.strip().split('\n'), + "type": "text/javascript" + } + }] + + return request_obj + + def _generate_environment_notes(self, environment: str, method: str) -> str: + """Generate environment-specific notes for request description.""" + notes = "\n\n" + + if environment == 'wasm': + notes += "**Environment Notes:**\n" + notes += "- This request uses WebSocket Secure (WSS) protocols only\n" + notes += "- Electrum servers are filtered to WSS-compatible endpoints\n" + elif 'trezor' in environment: + notes += "**Hardware Requirements:**\n" + notes += "- This request requires Trezor hardware wallet\n" + + # Add protocol preferences + base_env = environment.split('_')[0] if environment else 'native' + protocol_prefs = self.env_manager.get_protocol_preferences(method, base_env) + if protocol_prefs: + notes += f"\n**Protocol Preferences:** {protocol_prefs}\n" + + return notes + + # ===== FOLDER STRUCTURE CREATION ===== + + def create_folder_structure(self, requests: Dict[str, Dict], version: str, + filename: str, tables: Dict[str, Dict], + environment: str = None) -> Dict: + """Create folder structure for Postman collection organized by method paths.""" + folder_tree = {} + + # Group requests by method + method_groups = {} + for request_key, request_data in requests.items(): + method = request_data.get("method") + if not method: + continue + + # Check environment compatibility if specified + if environment and environment != "standard": + base_env = environment.split('_')[0] + hardware = 'trezor' if 'trezor' in environment else None + wallet_type = environment.split('_')[1] if '_' in environment and environment.split('_')[1] in ['hd', 'iguana'] else None + + if not self._is_request_compatible(request_key, method, base_env, hardware, wallet_type): + continue + + if method not in method_groups: + method_groups[method] = [] + method_groups[method].append((request_key, request_data)) + + # Process each method group + for method, examples in method_groups.items(): + method_components = self.get_method_path_components(method) + path_parts = [version.lower(), filename.lower()] + method_components + + # Navigate/create the nested structure + current_level = folder_tree + for i, part in enumerate(path_parts): + if part not in current_level: + current_level[part] = { + "_folders": {}, + "_items": [] + } + + if i == len(path_parts) - 1: + # Last component - create request + primary_key, primary_data = examples[0] + + request_obj = self.create_postman_request( + primary_key, + primary_data, + version, + tables, + examples if len(examples) > 1 else None, + environment + ) + current_level[part]["_items"].append(request_obj) + else: + current_level = current_level[part]["_folders"] + + return folder_tree + + def _is_request_compatible(self, request_key: str, method: str, + environment: str, hardware: str = None, wallet_type: str = None) -> bool: + """Check if a request is compatible with the target environment.""" + # Check method compatibility + is_compatible, _ = self.env_manager.validate_method_compatibility( + method, environment, hardware, wallet_type + ) + + if not is_compatible: + return False + + # Check example-specific compatibility using pattern matching + return self.env_manager._matches_pattern_requirements( + request_key, environment, hardware, wallet_type + ) + + def convert_tree_to_postman_folders(self, tree: Dict, name: str = "") -> List[Dict]: + """Convert the folder tree to Postman folder structure.""" + items = [] + + for key, value in tree.items(): + if key.startswith("_"): + continue + + folder_items = [] + + if "_items" in value: + folder_items.extend(value["_items"]) + + if "_folders" in value: + for subfolder_name, subfolder_data in value["_folders"].items(): + subfolder_items = self.convert_tree_to_postman_folders({subfolder_name: subfolder_data}, subfolder_name) + folder_items.extend(subfolder_items) + + if folder_items: + items.append({ + "name": key, + "item": folder_items + }) + + return items + + # ===== COLLECTION GENERATION ===== + + def generate_standard_collection(self) -> Dict: + """Generate the standard comprehensive Postman collection.""" + tables = self.load_all_tables() + folder_tree = {} + + # Process each version directory + for version_dir in self.requests_dir.iterdir(): + if not version_dir.is_dir(): + continue + + version = version_dir.name + logger.info(f"Processing version: {version}") + + # Process all JSON files in the version directory + for json_file in version_dir.glob("*.json"): + filename = json_file.stem + logger.info(f"Processing file: {filename}") + + requests_data = self.load_json_file(json_file) + if not requests_data: + continue + + # Filter out deprecated methods and validate + filtered_requests_data = {} + for request_key, request_data in requests_data.items(): + method = request_data.get("method") + if method: + method_config = self.get_method_config(method, version) + if method_config.get('deprecated', False): + continue # Skip deprecated methods + filtered_requests_data[request_key] = request_data + + # Validate and collect reports + # Accumulate per-method used/table parameters across all examples + method_param_usage: Dict[str, Dict[str, Set[str]]] = {} + for request_key, request_data in filtered_requests_data.items(): + method = request_data.get("method") + if method: + validation = self.validate_request_params(request_data, method, tables, version) + if validation: + table_params_this = set(validation.valid_params) | set(validation.unused_params) + if method not in method_param_usage: + method_param_usage[method] = { + "table_params": set(table_params_this), + "used_params_union": set(validation.valid_params), + "request_params_union": set(validation.request_params) + } + else: + # Ensure table params are consistent; if not, take union to be safe + method_param_usage[method]["table_params"].update(table_params_this) + method_param_usage[method]["used_params_union"].update(validation.valid_params) + method_param_usage[method]["request_params_union"].update(validation.request_params) + + # After scanning all examples in this file, compute overall unused per method + for method, usage in method_param_usage.items(): + overall_unused = usage["table_params"] - usage["used_params_union"] + if overall_unused: + # Merge with any existing entries from previous files + existing = set(self.unused_params.get(method, [])) + self.unused_params[method] = sorted(existing.union(overall_unused)) + + # Build detailed entries (with context and common-structures hints) + detailed_list = self.unused_params_detailed.get(method, []) + detailed_list.extend(self._build_unused_param_details(method, overall_unused, version, usage)) + # De-duplicate by parameter name + seen = set() + deduped = [] + for item in detailed_list: + key = item.get("parameter") + if key in seen: + continue + seen.add(key) + deduped.append(item) + self.unused_params_detailed[method] = deduped + + # Continue with missing responses detection per example + for request_key, request_data in filtered_requests_data.items(): + method = request_data.get("method") + if method: + # Missing responses check + if not self.check_response_exists(request_key, version): + # Skip deprecated methods from missing responses report + method_config = self.get_method_config(method, version) + if not method_config.get('deprecated', False): + # Skip manual/external methods that can't be automated + if self._is_manual_example(request_key): + continue + # Track in combined and per-version dicts + if method not in self.missing_responses: + self.missing_responses[method] = [] + self.missing_responses[method].append(request_key) + target = self.missing_responses_v2 if version == "v2" else self.missing_responses_legacy + if method not in target: + target[method] = [] + target[method].append(request_key) + + # Add to folder tree (using filtered data) + file_tree = self.create_folder_structure(filtered_requests_data, version, filename, tables, "standard") + + # Merge into main tree + for key, value in file_tree.items(): + if key not in folder_tree: + folder_tree[key] = value + else: + if "_folders" in value: + for subfolder_name, subfolder_data in value["_folders"].items(): + if subfolder_name not in folder_tree[key]["_folders"]: + folder_tree[key]["_folders"][subfolder_name] = subfolder_data + if "_items" in value: + folder_tree[key]["_items"].extend(value["_items"]) + + # Convert tree to Postman folder structure + all_folders = self.convert_tree_to_postman_folders(folder_tree) + + # Create collection variables + variables = [ + {"key": "base_url", "value": "http://127.0.0.1:7783", "type": "string"}, + {"key": "userpass", "value": "RPC_UserP@SSW0RD", "type": "string"} + ] + + # Add task ID variables + for var_name, default_value in self.task_variables.items(): + variables.append({ + "key": var_name, + "value": default_value, + "type": "string" + }) + + # Create the collection + collection = { + "info": { + "name": "Komodo DeFi Framework API", + "description": "Comprehensive auto-generated Postman collection for KDF API", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_postman_id": str(uuid.uuid4()) + }, + "item": all_folders, + "variable": variables + } + + return collection + + def generate_environment_collection(self, environment: str) -> Dict[str, Any]: + """Generate a Postman collection for a specific environment.""" + # Load and filter request data + request_data = self.load_request_data('v2') + + # Filter out deprecated methods first + filtered_request_data = {} + for request_key, request_info in request_data.items(): + method = request_info.get('method') + if method: + method_config = self.get_method_config(method, 'v2') + if method_config.get('deprecated', False): + continue # Skip deprecated methods + filtered_request_data[request_key] = request_info + + filtered_data = self.filter_protocols_for_environment(filtered_request_data, environment) + + # Get environment configuration + env_configs = self.env_manager.get_environment_specific_postman_configs() + config = env_configs.get(environment, {}) + + # Load tables for descriptions + tables = self.load_all_tables() + + collection = { + "info": { + "name": config.get('name', f'KDF API ({environment.title()})'), + "description": self._generate_collection_description(environment, config), + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_postman_id": f"kdf-{environment}-{datetime.now().strftime('%Y%m%d')}" + }, + "variable": [ + { + "key": "base_url", + "value": config.get('base_url', 'http://127.0.0.1:7783'), + "type": "string" + }, + { + "key": "userpass", + "value": "RPC_UserP@SSW0RD", + "type": "string" + } + ], + "item": [] + } + + # Group requests by method family + method_groups = self._group_requests_by_method(filtered_data) + + for method_family, requests in method_groups.items(): + folder_item = { + "name": method_family, + "item": [] + } + + for request_key, request_body in requests.items(): + method = request_body.get('method', '') + hardware = 'trezor' if 'trezor' in environment else None + wallet_type = config.get('wallet_type', None) + base_env = environment.split('_')[0] + + if self._is_request_compatible(request_key, method, base_env, hardware, wallet_type): + postman_request = self.create_postman_request( + request_key, request_body, 'v2', tables, None, environment + ) + folder_item["item"].append(postman_request) + + if folder_item["item"]: + collection["item"].append(folder_item) + + return collection + + def _generate_collection_description(self, environment: str, config: Dict) -> str: + """Generate description for the collection.""" + description = config.get('description', f'KDF API for {environment} environment') + notes = config.get('notes', '') + + protocol_info = "" + if 'preferred_protocols' in config: + protocols = config['preferred_protocols'] + protocol_details = [] + for proto_type, proto_list in protocols.items(): + protocol_details.append(f"{proto_type}: {', '.join(proto_list)}") + protocol_info = f"\n\nSupported Protocols:\n- " + "\n- ".join(protocol_details) + + hardware_info = "" + if 'hardware' in config: + hardware_info = f"\n\nHardware Support: {', '.join(config['hardware'])}" + + return f"{description}\n\n{notes}{protocol_info}{hardware_info}" + + def _group_requests_by_method(self, request_data: Dict[str, Any]) -> Dict[str, Dict]: + """Group requests by method family for better organization.""" + groups = {} + + for request_key, request_body in request_data.items(): + if not isinstance(request_body, dict): + continue + + method = request_body.get('method', '') + + # Determine method family + if method.startswith('task::enable_'): + coin_type = method.split('::')[1].replace('enable_', '') + family = f"Task Enable {coin_type.upper()}" + elif method.startswith('enable_'): + family = "Legacy Enable" + else: + family = "Other Methods" + + if family not in groups: + groups[family] = {} + + groups[family][request_key] = request_body + + return groups + + # ===== REPORTS ===== + + def detect_missing_requests_and_methods(self) -> None: + """Detect missing requests (responses without corresponding requests) and missing methods. + + Excludes deprecated methods from all missing reports. + """ + # Get set of deprecated methods + deprecated_methods = set() + for space in [self.method_config_v2, self.method_config_legacy]: + for method_name, method_config in space.items(): + if method_config.get('deprecated', False): + deprecated_methods.add(method_name) + + # Load all request and response data from all files + for version in ['v2', 'legacy']: + version_responses_dir = self.responses_dir / version + version_requests_dir = self.requests_dir / version + + if not version_responses_dir.exists() or not version_requests_dir.exists(): + continue + + # Collect all requests from all files in this version + requests_data = {} + for request_file in version_requests_dir.glob("*.json"): + request_data = self.load_json_file(request_file) or {} + requests_data.update(request_data) + + # Collect all responses from all files in this version + responses_data = {} + for response_file in version_responses_dir.glob("*.json"): + response_data = self.load_json_file(response_file) or {} + responses_data.update(response_data) + + # Find missing requests (responses without corresponding requests) + missing_requests_for_version = [] + for response_key in responses_data.keys(): + # Check if there's a corresponding request + if response_key not in requests_data: + # Check if this response corresponds to a deprecated method + is_deprecated = False + for request_key, request_data in requests_data.items(): + if isinstance(request_data, dict) and "method" in request_data: + method_name = request_data["method"] + if method_name in deprecated_methods: + # This is a deprecated method's response - skip it + is_deprecated = True + break + + # Also check if the response key itself suggests a deprecated method + # by looking for the method name in existing requests + for request_key, request_data in requests_data.items(): + if isinstance(request_data, dict) and "method" in request_data: + method_name = request_data["method"] + if method_name in deprecated_methods and method_name in response_key.lower(): + is_deprecated = True + break + + if not is_deprecated: + missing_requests_for_version.append(response_key) + + if missing_requests_for_version: + self.missing_requests[version] = sorted(missing_requests_for_version) + + # Find missing methods (requests without method definitions in version-specific config) + for request_key, request_data in requests_data.items(): + if isinstance(request_data, dict) and "method" in request_data: + method_name = request_data["method"] + # Skip deprecated methods + if method_name not in deprecated_methods and not self.get_method_config(method_name, version): + if method_name not in self.missing_methods: + self.missing_methods.append(method_name) + # Track per-version + if version == 'v2': + if method_name not in self.missing_methods_v2: + self.missing_methods_v2.append(method_name) + elif version == 'legacy': + if method_name not in self.missing_methods_legacy: + self.missing_methods_legacy.append(method_name) + + # Sort missing methods + self.missing_methods = sorted(self.missing_methods) + self.missing_methods_v2 = sorted(self.missing_methods_v2) + self.missing_methods_legacy = sorted(self.missing_methods_legacy) + + def _build_missing_tables_by_version(self, reports_dir: Path) -> None: + """Build and save missing tables split by version using TableManager.""" + # v2 + self.table_manager.clear_missing_tables() + for method_name, cfg in sorted(self.method_config_v2.items()): + self.table_manager.validate_method_tables(method_name, cfg) + v2_report = self.table_manager.get_missing_tables_report() + dump_sorted_json(v2_report, reports_dir / "missing_tables_v2.json") + # legacy + self.table_manager.clear_missing_tables() + for method_name, cfg in sorted(self.method_config_legacy.items()): + self.table_manager.validate_method_tables(method_name, cfg) + legacy_report = self.table_manager.get_missing_tables_report() + dump_sorted_json(legacy_report, reports_dir / "missing_tables_legacy.json") + + def _check_table_version_mismatches(self) -> Dict[str, Any]: + """Detect v2 methods referencing legacy tables and legacy methods referencing v2 tables.""" + results = {"v2_methods_with_legacy_tables": [], "legacy_methods_with_v2_tables": []} + tables_all = self.table_manager.load_all_tables() + # Helper to test a single method config + def check_method(method_name: str, cfg: Dict[str, Any], expected: str) -> List[Dict[str, str]]: + issues: List[Dict[str, str]] = [] + for table_type, field in [("request", "request_table"), ("response", "response_table"), ("error", "errors_table")]: + table_name = cfg.get(field) + if not table_name or table_name == "N/A": + continue + # If table not found at all, skip here (handled by missing tables) + sources = self.table_manager.get_table_source(table_name) + if sources and expected not in sources and "common" not in sources: + issues.append({ + "method": method_name, + "table_type": table_type, + "table_name": table_name, + "source": sorted(list(sources)), + "expected": expected + }) + return issues + # v2 methods should use v2/common + for m, cfg in self.method_config_v2.items(): + issues = check_method(m, cfg, "v2") + if issues: + results["v2_methods_with_legacy_tables"].extend(issues) + # legacy methods should use legacy/common + for m, cfg in self.method_config_legacy.items(): + issues = check_method(m, cfg, "legacy") + if issues: + results["legacy_methods_with_v2_tables"].extend(issues) + return results + + def detect_missing_response_and_error_tables(self) -> None: + """Detect missing response and error tables for all methods.""" + for space in [self.method_config_v2, self.method_config_legacy]: + for method_name, method_config in space.items(): + # Skip deprecated methods + if method_config.get('deprecated', False): + continue + + # Use TableManager to validate all table references + self.table_manager.validate_method_tables(method_name, method_config) + + def _build_unused_param_details(self, method: str, unused_params: Set[str], version: str, usage: Dict[str, Set[str]]) -> List[Dict[str, Any]]: + """Create detailed entries for unused parameters including context and nested matches. + Also extracts a hint to common-structures from parameter description when available. + """ + details: List[Dict[str, Any]] = [] + try: + method_cfg = self.get_method_config(method, version) + # Resolve request table and its data + tmp_cfg = dict(method_cfg) + tmp_cfg["method_name"] = method + table_ref = self.table_manager.get_table_reference(tmp_cfg, 'request') + tables = self.table_manager.load_all_tables() + table_data = tables.get(table_ref.table_name, {}).get("data", []) + # Map param -> definition + param_to_def: Dict[str, Dict[str, Any]] = {p.get("parameter"): p for p in table_data if isinstance(p, dict)} + request_params_union = usage.get("request_params_union", set()) + for param in sorted(unused_params): + param_def = param_to_def.get(param, {}) + description = param_def.get("description") if isinstance(param_def, dict) else None + context = param_def.get("context") if isinstance(param_def, dict) else None + # nested matches present in examples (keep dotted forms) + nested_matches = sorted([rp for rp in request_params_union if rp.endswith(f".{param}") or rp.startswith(f"{param}.")]) + # extract common-structures path hint from description + common_struct_ref = None + if isinstance(description, str) and "/common_structures/" in description: + try: + idx = description.index("/common_structures/") + tail = description[idx:] + # end at first space, newline, or closing paren + for sep in [" ", "\n", ")", "`"]: + cut = tail.find(sep) + if cut > 0: + tail = tail[:cut] + break + common_struct_ref = tail + except Exception: + common_struct_ref = None + details.append({ + "parameter": param, + "method": method, + "version": version, + "request_table": table_ref.table_name, + "context": context, + "nested_matches_in_examples": nested_matches, + "common_structures_ref": common_struct_ref + }) + except Exception: + for p in sorted(unused_params): + details.append({ + "parameter": p, + "method": method, + "version": version + }) + return details + + def save_reports(self, reports_dir: Path) -> None: + """Save validation reports with consistent alphabetical sorting. + + Always writes all report files, even if empty, to indicate current state. + """ + reports_dir.mkdir(parents=True, exist_ok=True) + + # Save unused parameters report (always) + sorted_unused = {} + if self.unused_params: + for method in sorted(self.unused_params.keys()): + sorted_unused[method] = sorted(self.unused_params[method]) + + unused_file = reports_dir / "unused_params.json" + dump_sorted_json(sorted_unused, unused_file) + logger.info(f"Unused parameters report saved to {unused_file}") + + # Save detailed unused parameters report (always) + detailed_file = reports_dir / "unused_params_detailed.json" + dump_sorted_json(self.unused_params_detailed or {}, detailed_file) + logger.info(f"Detailed unused parameters report saved to {detailed_file}") + + # Save split missing responses by version (authoritative) + dump_sorted_json( + {k: sorted(v) for k, v in sorted(self.missing_responses_v2.items())} if self.missing_responses_v2 else {}, + reports_dir / "missing_responses_v2.json" + ) + dump_sorted_json( + {k: sorted(v) for k, v in sorted(self.missing_responses_legacy.items())} if self.missing_responses_legacy else {}, + reports_dir / "missing_responses_legacy.json" + ) + + # Save untranslated keys report (always) + untranslated_list = sorted(self.untranslated_keys) if self.untranslated_keys else [] + untranslated_file = reports_dir / "untranslated_keys.json" + dump_sorted_json(untranslated_list, untranslated_file) + logger.info(f"Untranslated keys report saved to {untranslated_file}") + + # Save missing tables by version (authoritative) + self._build_missing_tables_by_version(reports_dir) + + # Save split missing requests (authoritative) + sorted_missing_requests_v2 = sorted(self.missing_requests.get("v2", [])) + sorted_missing_requests_legacy = sorted(self.missing_requests.get("legacy", [])) + dump_sorted_json(sorted_missing_requests_v2, reports_dir / "missing_requests_v2.json") + dump_sorted_json(sorted_missing_requests_legacy, reports_dir / "missing_requests_legacy.json") + + # Save split missing methods (authoritative) + dump_sorted_json(self.missing_methods_v2, reports_dir / "missing_methods_v2.json") + dump_sorted_json(self.missing_methods_legacy, reports_dir / "missing_methods_legacy.json") + + # Save table version mismatch report + mismatches = self._check_table_version_mismatches() + dump_sorted_json(mismatches, reports_dir / "table_version_mismatches.json") + + # ===== EXAMPLE SYNC ===== + + def _collect_examples_from_requests(self) -> Dict[str, Dict[str, Set[str]]]: + """Collect request example keys per method, grouped by version. + + Returns: + { 'legacy': { method: {example_keys...} }, 'v2': { ... } } + """ + collected: Dict[str, Dict[str, Set[str]]] = { 'legacy': {}, 'v2': {} } + # Iterate version dirs under requests + for version_dir in self.requests_dir.iterdir(): + if not version_dir.is_dir(): + continue + version = version_dir.name + if version not in collected: + collected[version] = {} + for json_file in version_dir.glob("*.json"): + reqs = self.load_json_file(json_file) or {} + for request_key, request_data in reqs.items(): + if not isinstance(request_data, dict): + continue + method = request_data.get("method") + if not method: + continue + collected[version].setdefault(method, set()).add(request_key) + return collected + + def sync_examples_from_requests(self, dry_run: bool = False) -> Dict[str, Any]: + """Sync missing example keys into kdf_methods files based on request files. + + - Adds only missing examples; does not remove existing ones + - Uses inferred human-readable names for new examples + + Returns summary stats. + """ + collected = self._collect_examples_from_requests() + added_count = 0 + per_method_added: Dict[str, int] = {} + + # Helper to update a config dict + def update_config(config: Dict[str, Dict], version: str): + nonlocal added_count + for method, example_keys in collected.get(version, {}).items(): + method_cfg = config.get(method) + if not method_cfg: + # Skip methods not defined in this version config + continue + examples: Dict[str, str] = method_cfg.get("examples", {}) or {} + new_this_method = 0 + for ex_key in sorted(example_keys): + if ex_key not in examples: + examples[ex_key] = self._infer_example_name(ex_key, method) + new_this_method += 1 + if new_this_method: + method_cfg["examples"] = dict(sorted(examples.items())) + per_method_added[method] = per_method_added.get(method, 0) + new_this_method + added_count += new_this_method + + update_config(self.method_config_legacy, 'legacy') + update_config(self.method_config_v2, 'v2') + + if not dry_run and added_count: + self._save_method_config() + + return { + "added_examples": added_count, + "per_method": dict(sorted(per_method_added.items())), + "dry_run": dry_run + } + + # ===== SELF-REPAIR FUNCTIONALITY ===== + + def discover_missing_methods(self) -> Dict[str, Dict]: + """Discover methods in request files that are missing from method config.""" + missing_methods = {} + + # Scan all request files to find methods + for version_dir in self.requests_dir.iterdir(): + if not version_dir.is_dir(): + continue + + for json_file in version_dir.glob("*.json"): + requests_data = self.load_json_file(json_file) + if not requests_data: + continue + + for request_key, request_data in requests_data.items(): + method = request_data.get("method") + if method and not self.get_method_config(method, version_dir.name): + # Check if method exists in either config but is deprecated + existing_config = self.get_method_config(method) + if existing_config.get('deprecated', False): + continue # Skip deprecated methods + + if method not in missing_methods: + missing_methods[method] = { + "examples": {}, + "version": version_dir.name, + "file": json_file.stem + } + + # Infer a human-readable name for this example + example_name = self._infer_example_name(request_key, method) + missing_methods[method]["examples"][request_key] = example_name + + return missing_methods + + def _infer_example_name(self, request_key: str, method: str) -> str: + """Infer a human-readable name for a request example.""" + # Remove common prefixes + name = request_key + + # Convert CamelCase to Title Case with spaces + import re + name = re.sub(r'([A-Z])', r' \1', name).strip() + + # Clean up specific patterns + name = name.replace("Enable ", "Enable ") + name = name.replace("Task ", "") + name = name.replace("Legacy ", "") + + # Add context based on method type + if "enable_" in method: + if "Init" in request_key: + name = name.replace(" Init", " Initialization") + elif "Status" in request_key: + name = name.replace(" Status", " Status Check") + elif "Cancel" in request_key: + name = name.replace(" Cancel", " Cancellation") + elif "UserAction" in request_key: + if "Pin" in request_key: + name = name.replace(" User Action Pin", " (Trezor PIN)") + else: + name = name.replace(" User Action", " User Action") + + return name + + def _infer_method_requirements(self, method: str, examples: Dict[str, str]) -> Dict[str, Any]: + """Infer method requirements based on method name and examples.""" + requirements = { + "environments": ["native", "wasm"], + "wallet_types": ["hd", "iguana"] + } + + # Infer environment and wallet compatibility based on method patterns + + # Stream methods are wasm-only + if method.startswith("stream::"): + requirements["environments"] = ["wasm"] + + # Trezor methods require hardware + if "trezor" in method.lower() or "::user_action" in method.lower(): + requirements["wallet_types"] = ["trezor"] + + # Infer from example patterns + for example_key in examples.keys(): + if "Trezor" in example_key: + # Trezor examples indicate hardware wallet requirement + requirements["wallet_types"] = ["trezor"] + + if "WalletConnect" in example_key: + if "wallet_types" in requirements: + # WalletConnect typically works with both HD and iguana + pass + + return requirements + + def _infer_table_name(self, method: str) -> str: + """Infer a table name based on method name.""" + # Convert method name to a table name + table_name = method.replace("::", "_").replace("_", " ").title().replace(" ", "") + table_name += "Arguments" + return table_name + + def auto_repair_missing_methods(self, dry_run: bool = True) -> Dict[str, Any]: + """Automatically repair missing method configurations.""" + missing_methods = self.discover_missing_methods() + repair_plan = { + "discovered_methods": len(missing_methods), + "methods": {}, + "would_add": [] if not dry_run else list(missing_methods.keys()) + } + + if not missing_methods: + logger.info("No missing methods discovered - configuration is complete!") + return repair_plan + + logger.info(f"Discovered {len(missing_methods)} missing methods") + + for method, method_info in missing_methods.items(): + table_name = self._infer_table_name(method) + requirements = self._infer_method_requirements(method, method_info["examples"]) + + method_config = { + "request_table": table_name, + "response_table": "", + "errors_table": "", + "examples": method_info["examples"], + "requirements": requirements + } + + repair_plan["methods"][method] = method_config + + if dry_run: + logger.info(f"Would add method '{method}' with {len(method_info['examples'])} examples") + else: + self.method_config[method] = method_config + logger.info(f"Added method '{method}' with {len(method_info['examples'])} examples") + + if not dry_run: + self._save_method_config() + logger.info(f"Saved updated method configuration with {len(missing_methods)} new methods") + + return repair_plan + + def _save_method_config(self): + """Save the updated method configurations back to their respective files.""" + data_dir = self.workspace_root / "src" / "data" + v2_file = data_dir / "kdf_methods_v2.json" + legacy_file = data_dir / "kdf_methods_legacy.json" + dump_sorted_json(dict(sorted(self.method_config_legacy.items())), legacy_file) + dump_sorted_json(dict(sorted(self.method_config_v2.items())), v2_file) + + # ===== MAIN GENERATION METHODS ===== + + def _count_collection_items(self, collection_data: Dict) -> int: + """Count the total number of requests in a collection.""" + count = 0 + + def count_items(items): + nonlocal count + for item in items: + if "request" in item: + count += 1 + elif "item" in item: + count_items(item["item"]) + + if "item" in collection_data: + count_items(collection_data["item"]) + + return count + + def _count_report_items(self, report_data: Any) -> int: + """Count items in a report based on its structure.""" + if isinstance(report_data, dict): + # For reports like missing_responses and unused_params + total = 0 + for key, value in report_data.items(): + if isinstance(value, list): + total += len(value) + else: + total += 1 + return total + elif isinstance(report_data, list): + # For reports like untranslated_keys and missing_tables + return len(report_data) + else: + return 1 + + def generate_all_collections(self, output_dir: Path, auto_repair: bool = False) -> Dict[str, Dict]: + """Generate all collection types.""" + # Normalize output_dir to absolute within workspace + output_dir = Path(output_dir) + if not output_dir.is_absolute(): + output_dir = (self.workspace_root / output_dir).resolve() + generated_files = {} + + # Auto-repair missing method configurations if requested + if auto_repair: + logger.info("๐Ÿ”ง Running self-repair for missing method configurations...") + repair_plan = self.auto_repair_missing_methods(dry_run=False) + if repair_plan["discovered_methods"] > 0: + logger.info(f"โœ… Auto-repaired {repair_plan['discovered_methods']} missing method configurations") + else: + logger.info("โœ… No missing method configurations found") + + # Create output directories + standard_dir = output_dir / "collections" + environments_dir = output_dir / "environments" + reports_dir = output_dir / "reports" + + standard_dir.mkdir(parents=True, exist_ok=True) + environments_dir.mkdir(parents=True, exist_ok=True) + + # Generate standard collection + logger.info("Generating standard comprehensive collection...") + standard_collection = self.generate_standard_collection() + + standard_file = standard_dir / "kdf_comprehensive_collection.json" + dump_sorted_json(standard_collection, standard_file) + + # Count items in standard collection + standard_count = self._count_collection_items(standard_collection) + generated_files["standard"] = { + "file": str(standard_file.relative_to(self.workspace_root)), + "count": standard_count + } + logger.info(f"Standard collection saved to {standard_file}") + + # Generate environment-specific collections + env_configs = self.env_manager.get_environment_specific_postman_configs() + + for environment in env_configs.keys(): + logger.info(f"Generating collection for environment: {environment}") + + env_collection = self.generate_environment_collection(environment) + + env_file = environments_dir / f"kdf_{environment}_collection.json" + dump_sorted_json(env_collection, env_file) + + # Count items in environment collection + env_count = self._count_collection_items(env_collection) + generated_files[environment] = { + "file": str(env_file.relative_to(self.workspace_root)), + "count": env_count + } + logger.info(f"Environment collection saved to {env_file}") + + # Detect missing requests and methods before saving reports + self.detect_missing_requests_and_methods() + + # Detect missing response and error tables + self.detect_missing_response_and_error_tables() + + # Save reports + self.save_reports(reports_dir) + + # Prepare reports data with file paths and counts (always include all reports) + reports_data = {} + + # Unused params (always) + unused_params_file = reports_dir / "unused_params.json" + reports_data["unused_params"] = { + "file": str(unused_params_file.relative_to(self.workspace_root)), + "count": self._count_report_items(self.unused_params) if self.unused_params else 0 + } + + # Missing responses (split) + mr_v2 = reports_dir / "missing_responses_v2.json" + mr_legacy = reports_dir / "missing_responses_legacy.json" + reports_data["missing_responses_v2"] = { + "file": str(mr_v2.relative_to(self.workspace_root)), + "count": self._count_report_items(self.missing_responses_v2) if self.missing_responses_v2 else 0 + } + reports_data["missing_responses_legacy"] = { + "file": str(mr_legacy.relative_to(self.workspace_root)), + "count": self._count_report_items(self.missing_responses_legacy) if self.missing_responses_legacy else 0 + } + + # Untranslated keys (always) + untranslated_keys_file = reports_dir / "untranslated_keys.json" + reports_data["untranslated_keys"] = { + "file": str(untranslated_keys_file.relative_to(self.workspace_root)), + "count": len(self.untranslated_keys) if self.untranslated_keys else 0 + } + + # Missing tables (split) + reports_data["missing_tables_v2"] = { + "file": str((reports_dir / "missing_tables_v2.json").relative_to(self.workspace_root)) + } + reports_data["missing_tables_legacy"] = { + "file": str((reports_dir / "missing_tables_legacy.json").relative_to(self.workspace_root)) + } + + # Missing requests (split) + sorted_missing_requests_v2 = sorted(self.missing_requests.get("v2", [])) + sorted_missing_requests_legacy = sorted(self.missing_requests.get("legacy", [])) + reports_data["missing_requests_v2"] = { + "file": str((reports_dir / "missing_requests_v2.json").relative_to(self.workspace_root)), + "count": len(sorted_missing_requests_v2) + } + reports_data["missing_requests_legacy"] = { + "file": str((reports_dir / "missing_requests_legacy.json").relative_to(self.workspace_root)), + "count": len(sorted_missing_requests_legacy) + } + + # Missing methods (split) + reports_data["missing_methods_v2"] = { + "file": str((reports_dir / "missing_methods_v2.json").relative_to(self.workspace_root)), + "count": len(self.missing_methods_v2) + } + reports_data["missing_methods_legacy"] = { + "file": str((reports_dir / "missing_methods_legacy.json").relative_to(self.workspace_root)), + "count": len(self.missing_methods_legacy) + } + + # Generate summary + summary = { + "generation_timestamp": datetime.now().isoformat(), + "generated_files": generated_files, + "reports": reports_data + } + # Attempt to include KDF version extracted from response report (no extra requests) + try: + report_path = self.workspace_root / "postman/generated/reports/kdf_postman_responses.json" + if report_path.exists(): + with open(report_path, 'r', encoding='utf-8') as f: + report = json.load(f) + # Look for LegacyVersion + if isinstance(report, dict): + if "LegacyVersion" in report and isinstance(report["LegacyVersion"], dict): + ver = report["LegacyVersion"].get("result") + if isinstance(ver, str): + summary["kdf_version"] = ver + elif isinstance(report.get("responses"), dict): + lv = report["responses"].get("LegacyVersion") + if isinstance(lv, dict) and isinstance(lv.get("result"), str): + summary["kdf_version"] = lv["result"] + except Exception: + pass + + summary_file = output_dir / "generation_summary.json" + dump_sorted_json(summary, summary_file) + + return generated_files + + +def main(): + """Main CLI interface.""" + parser = argparse.ArgumentParser( + description="Unified Postman Collection Generator for KDF API", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Generate all collections (standard + all environments) + python unified_postman_generator.py --all + + # Generate with auto-repair of missing method configurations + python unified_postman_generator.py --all --auto-repair + + # Check what would be repaired without making changes + python unified_postman_generator.py --dry-run-repair + + # Generate only standard comprehensive collection + python unified_postman_generator.py --standard + + # Generate specific environment collection + python unified_postman_generator.py --environment native_hd + + # Generate with custom output directory + python unified_postman_generator.py --all --output-dir ./custom_output + + # Enable verbose logging + python unified_postman_generator.py --all --verbose + """ + ) + + # Mode selection (mutually exclusive) + mode_group = parser.add_mutually_exclusive_group(required=True) + mode_group.add_argument( + '--all', '-a', + action='store_true', + help="Generate all collections (standard + all environments)" + ) + mode_group.add_argument( + '--standard', '-s', + action='store_true', + help="Generate only the standard comprehensive collection" + ) + mode_group.add_argument( + '--environment', '-e', + choices=['native_hd', 'native_iguana', 'wasm_hd', 'wasm_iguana', 'trezor_native_hd', 'trezor_wasm_hd'], + help="Generate specific environment collection" + ) + mode_group.add_argument( + '--dry-run-repair', + action='store_true', + help="Show what would be repaired without making changes" + ) + mode_group.add_argument( + '--sync-examples', + action='store_true', + help="Sync missing request examples into kdf_methods files" + ) + + # Optional arguments + parser.add_argument( + '--workspace', '-w', + help="Path to workspace root (auto-detected if not provided)" + ) + parser.add_argument( + '--output-dir', '-o', + help="Output directory (default: postman/generated)" + ) + parser.add_argument( + '--verbose', '-v', + action='store_true', + help="Enable verbose output" + ) + parser.add_argument( + '--auto-repair', + action='store_true', + help="Automatically repair missing method configurations" + ) + + args = parser.parse_args() + + # Configure logging + if args.verbose: + logging.getLogger().setLevel(logging.INFO) + + try: + generator = UnifiedPostmanGenerator(args.workspace) + + # Set output directory + if args.output_dir: + output_dir = Path(args.output_dir) + else: + output_dir = generator.workspace_root / "postman" / "generated" + + output_dir.mkdir(parents=True, exist_ok=True) + + # Handle dry-run repair mode + if args.dry_run_repair: + print("๐Ÿ” Checking for missing method configurations...") + repair_plan = generator.auto_repair_missing_methods(dry_run=True) + + if repair_plan["discovered_methods"] == 0: + print("โœ… No missing method configurations found!") + else: + print(f"๐Ÿ“‹ Found {repair_plan['discovered_methods']} missing method configurations:") + for method in repair_plan["would_add"]: + examples_count = len(repair_plan["methods"][method]["examples"]) + print(f" โ€ข {method} (with {examples_count} examples)") + print(f"\nTo apply these fixes, run with --auto-repair") + return + + if args.all: + print("๐Ÿš€ Generating all collections...") + generated_files = generator.generate_all_collections(output_dir, auto_repair=args.auto_repair) + + print(f"\nโœ… Generated {len(generated_files)} collections:") + for collection_type, file_info in generated_files.items(): + file_path = file_info["file"] + count = file_info["count"] + print(f" {collection_type}: {file_path} ({count} requests)") + + print(f"\n๐Ÿ“Š Summary: {output_dir / 'generation_summary.json'}") + + elif args.standard: + print("๐Ÿš€ Generating standard comprehensive collection...") + collection = generator.generate_standard_collection() + + collections_dir = output_dir / "collections" + collections_dir.mkdir(parents=True, exist_ok=True) + + output_file = collections_dir / "kdf_comprehensive_collection.json" + dump_sorted_json(collection, output_file) + + # Detect missing requests and methods before saving reports + generator.detect_missing_requests_and_methods() + + # Detect missing response and error tables + generator.detect_missing_response_and_error_tables() + + # Save reports + reports_dir = output_dir / "reports" + generator.save_reports(reports_dir) + + print(f"โœ… Standard collection generated: {output_file}") + print(f"๐Ÿ“Š Reports saved to: {reports_dir}") + + elif args.environment: + print(f"๐Ÿš€ Generating collection for environment: {args.environment}") + collection = generator.generate_environment_collection(args.environment) + + environments_dir = output_dir / "environments" + environments_dir.mkdir(parents=True, exist_ok=True) + + output_file = environments_dir / f"kdf_{args.environment}_collection.json" + dump_sorted_json(collection, output_file) + + print(f"โœ… Environment collection generated: {output_file}") + elif args.sync_examples: + print("๐Ÿ”„ Syncing missing request examples into kdf_methods files...") + summary = generator.sync_examples_from_requests(dry_run=False) + print(json.dumps(summary, indent=2)) + print("โœ… Sync complete.") + + except Exception as e: + print(f"โŒ Error: {e}") + if args.verbose: + import traceback + traceback.print_exc() + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/utils/py/harvest_responses.md b/utils/py/harvest_responses.md new file mode 100644 index 000000000..3c4e9a05f --- /dev/null +++ b/utils/py/harvest_responses.md @@ -0,0 +1,77 @@ +# KDF Response Harvesting Script - Guide + +This document explains what the `utils/py/harvest_responses.sh` script does, its prerequisites, how to run it, and where to find the outputs. + +## Prerequisites + +- Docker and Docker Compose v2 (script uses `docker compose`). +- A working Python virtual environment located at `utils/py/.venv`. + - The script activates it automatically with: `source utils/py/.venv/bin/activate`. +- Internet access to pull images and reach external nodes where applicable. + +## What the script does (step-by-step) + +1. Ensures it is executing from the repository root and validates presence of `docker-compose.yml`. +2. Activates the Python virtual environment at `utils/py/.venv`. +3. Syncs request examples with the latest coin server URLs: + - `python utils/py/batch_update_nodes.py --directory src/data/requests/kdf` +4. Syncs request examples into the KDF method registries and Postman data: + - `python utils/py/generate_postman.py --sync-examples --output-dir postman/generated` +5. Sets the KDF branch used by downstream tasks: + - `export KDF_BRANCH="dev"` +6. Starts KDF services required for harvesting responses (runs in the background): + - `docker compose up kdf-native-hd kdf-native-nonhd -d` +7. Waits briefly for services to become ready (`sleep 10`). +8. Prepares a clean slate by disabling all enabled coins: + - `python utils/py/clean_slate.py` +9. Generates Postman collections (across methods and flows): + - `python utils/py/generate_postman.py --all` +10. Runs sequence-based response harvesting, which also integrates address collection: + - `cd utils/py && python lib/managers/sequence_responses_manager.py --update-files && cd ../..` +11. Cleans up older Newman reports, keeping only the two most recent reports in `postman/reports/`. +12. Stops the KDF Docker services: + - `docker compose down` +13. Prints a summary of where results were written. + +## How to run + +From the repository root: + +```bash +bash utils/py/harvest_responses.sh +``` + +Optional: +- You can override the KDF branch before running, for example: + +```bash +export KDF_BRANCH="dev" # or a different branch if supported by your environment +bash utils/py/harvest_responses.sh +``` + +## Outputs + +- `postman/generated/reports/` โ€” Unified response manager output from the sequence-based harvester. +- `postman/reports/` โ€” Newman run results. The script cleans older reports and keeps the two most recent. +- `src/data/responses/` โ€” Updated response JSON files used by documentation components. +- `src/data/requests/` โ€” Request example JSON files synced and used by components and tooling. + +## Troubleshooting + +- Virtual environment missing: + - Ensure the venv exists at `utils/py/.venv` and contains all required dependencies. + - If needed, recreate the venv and install project requirements per your local setup instructions. +- Docker not available or not running: + - Ensure Docker Desktop/Engine is installed and running. + - Confirm `docker compose` is available (Compose v2 CLI). +- Network or node connectivity issues: + - The batch update and harvesting steps may require external connectivity to nodes. + - Retry after verifying network access and node availability. +- Port conflicts: + - If the KDF services fail to start, check for port conflicts and stop/reconfigure competing services. + +## Notes + +- The script uses `set -e` and will exit on the first error. Check the console output for the failing step. +- The harvesting flow is designed to be reproducible; re-running will update requests/responses and generated artifacts. + diff --git a/utils/py/harvest_responses.sh b/utils/py/harvest_responses.sh new file mode 100755 index 000000000..4dc49a40d --- /dev/null +++ b/utils/py/harvest_responses.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +set -e # Exit on any error + +echo "๐Ÿš€ Starting KDF Response Harvesting Workflow" +echo "=============================================" + +# Navigate to workspace root if needed +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +echo "๐Ÿ“ Changing to workspace root: $WORKSPACE_ROOT" +cd "$WORKSPACE_ROOT" + +# Check if we're in the correct directory +if [ ! -f "docker-compose.yml" ]; then + echo "โŒ Error: Could not find docker-compose.yml in workspace root" + exit 1 +fi + +# Activate virtual environment +echo "๐Ÿ“ฆ Activating Python virtual environment..." +source utils/py/.venv/bin/activate + +# Sync request examples with latest coins config servers +echo "๐Ÿ”„ Syncing request examples with latest coin servers..." +python utils/py/batch_update_nodes.py --directory src/data/requests/kdf + +# Sync method examples into kdf_methods files +echo "๐Ÿ” Syncing method examples from requests into kdf_methods..." +python utils/py/generate_postman.py --sync-examples --output-dir postman/generated + +# Set KDF branch +export KDF_BRANCH="dev" + +# Start KDF Docker services +echo "๐Ÿณ Starting KDF Docker services..." +docker compose up kdf-native-hd kdf-native-nonhd -d + +# Wait for services to be ready +echo "โณ Waiting for KDF services to be ready..." +sleep 10 + +# Clean slate - disable all enabled coins for fresh start +echo "๐Ÿงน Preparing clean slate (disabling all enabled coins)..." +python utils/py/clean_slate.py + +# Generate Postman collections +echo "๐Ÿ“‹ Generating Postman collections..." +python utils/py/generate_postman.py --all + +# Run comprehensive response collection (includes address collection) +echo "๐Ÿ” Collecting responses with sequence-based processing..." +cd utils/py && python lib/managers/sequence_responses_manager.py --update-files && cd ../.. +echo "๐Ÿฆ Address collection integrated into sequence-based response harvesting" + +# Clean up old reports in postman/reports/ (if they exist) +echo "๐Ÿงน Cleaning up old Newman reports..." +if [ -d "postman/reports" ]; then + find postman/reports -name "postman_test_results_*.json" -type f | sort -r | tail -n +3 | xargs -r rm -f + find postman/reports -name "test_summary_*.json" -type f | sort -r | tail -n +3 | xargs -r rm -f + echo " Cleaned up old reports, keeping 2 most recent" +fi + +# Stop KDF services +echo "๐Ÿ›‘ Stopping KDF Docker services..." +docker compose down + +echo "" +echo "โœ… Response harvesting completed successfully!" +echo "๐Ÿ“Š Check these directories for results:" +echo " - postman/generated/reports/ (unified response manager output)" +echo " - postman/reports/ (Newman test results)" +echo " - src/data/responses/ (updated response files)" diff --git a/utils/py/lib/managers/activation_manager.py b/utils/py/lib/managers/activation_manager.py new file mode 100644 index 000000000..9a9c8e94a --- /dev/null +++ b/utils/py/lib/managers/activation_manager.py @@ -0,0 +1,1117 @@ +#!/usr/bin/env python3 +""" +Activation Manager - Comprehensive coin and token activation for KDF. + +This module provides intelligent coin activation based on protocol detection +and proper handling of tokens, platform dependencies, and task lifecycles. +""" + +import os +import json +import time +import threading +import random +import logging +from pathlib import Path +from typing import Any, Dict, Optional, Tuple, List, Callable +from dataclasses import dataclass + +# Import the coins config manager +try: + # Try relative import first (when used as module) + from .coins_config_manager import CoinsConfigManager, CoinProtocolInfo + from ..models.kdf_method import extract_ticker_from_request +except ImportError: + # Fall back to absolute import (when run directly) + import sys + from pathlib import Path + sys.path.append(str(Path(__file__).parent)) + from coins_config_manager import CoinsConfigManager, CoinProtocolInfo + sys.path.append(str(Path(__file__).parent.parent)) + from models.kdf_method import extract_ticker_from_request + +logger = logging.getLogger(__name__) + + + +# Configuration for activation state tracking +ACTIVATION_STATE: Dict[str, Dict[str, Any]] = {} + +@dataclass +class ActivationRequest: + """Represents a coin activation request.""" + method: str + params: Dict[str, Any] + timeout: int = 60 + is_task: bool = False + +@dataclass +class ActivationResult: + """Result of a coin activation attempt.""" + success: bool + response: Dict[str, Any] + task_id: Optional[str] = None + error: Optional[str] = None + already_enabled: bool = False + + +class ActivationRequestBuilder: + """Builds activation requests for different coin types and protocols.""" + + def __init__(self, coins_config_manager: CoinsConfigManager, userpass: str): + self.coins_config = coins_config_manager + self.userpass = userpass + self.logger = logger + + def _select_preferred_servers(self, servers: List[Dict[str, Any]], max_count: int = 3) -> List[Dict[str, Any]]: + """Select up to max_count servers, preferring cipig/komodo domains.""" + if len(servers) <= max_count: + return servers + + # Separate servers into priority and non-priority + priority_servers = [] + regular_servers = [] + + for server in servers: + url = server.get('url', '') + if 'cipig' in url.lower() or 'komodo' in url.lower(): + priority_servers.append(server) + else: + regular_servers.append(server) + + selected_servers = [] + + # First, add priority servers (up to max_count) + if priority_servers: + if len(priority_servers) <= max_count: + selected_servers.extend(priority_servers) + else: + selected_servers.extend(random.sample(priority_servers, max_count)) + + # If we need more servers and have regular ones available + remaining_slots = max_count - len(selected_servers) + if remaining_slots > 0 and regular_servers: + if len(regular_servers) <= remaining_slots: + selected_servers.extend(regular_servers) + else: + selected_servers.extend(random.sample(regular_servers, remaining_slots)) + + self.logger.info(f"Selected {len(selected_servers)} servers from {len(servers)} available") + return selected_servers + + # Public wrappers for reuse outside activation requests + def select_preferred_servers(self, servers: List[Dict[str, Any]], max_count: int = 3) -> List[Dict[str, Any]]: + """Public helper to select preferred servers (cipig/komodo prioritized).""" + return self._select_preferred_servers(servers, max_count) + + def select_preferred_urls(self, urls: List[str], max_count: int = 3) -> List[str]: + """Select up to max_count URLs, preferring cipig/komodo domains.""" + if len(urls) <= max_count: + return urls + priority_urls: List[str] = [] + regular_urls: List[str] = [] + for url in urls: + if isinstance(url, str) and ("cipig" in url.lower() or "komodo" in url.lower()): + priority_urls.append(url) + else: + regular_urls.append(url) + selected: List[str] = [] + if priority_urls: + if len(priority_urls) <= max_count: + selected.extend(priority_urls) + else: + selected.extend(random.sample(priority_urls, max_count)) + remaining = max_count - len(selected) + if remaining > 0 and regular_urls: + if len(regular_urls) <= remaining: + selected.extend(regular_urls) + else: + selected.extend(random.sample(regular_urls, remaining)) + return selected + + # -------- Generic request node update helpers (for CLI/tools reuse) -------- + + def update_tendermint_nodes_in_request(self, request_data: Dict[str, Any], protocol_info: CoinProtocolInfo, ticker: str) -> bool: + if not protocol_info.rpc_urls: + self.logger.warning(f"No rpc_urls found for Tendermint ticker '{ticker}' in coins configuration") + return False + selected_rpc_urls = self.select_preferred_servers(protocol_info.rpc_urls, max_count=3) + new_nodes: List[Dict[str, Any]] = [] + for rpc_url in selected_rpc_urls: + node: Dict[str, Any] = {"url": rpc_url.get("url")} + for field in ['api_url', 'grpc_url', 'ws_url', 'komodo_proxy']: + if rpc_url.get(field): + node[field] = rpc_url.get(field) + if node.get("url"): + new_nodes.append(node) + if 'params' in request_data and isinstance(request_data['params'], dict): + params = request_data['params'] + if 'nodes' in params: + old_nodes = params['nodes'] + params['nodes'] = new_nodes + self.logger.info(f"Updated Tendermint nodes for '{ticker}': {len(old_nodes)} -> {len(new_nodes)} nodes") + return True + if 'nodes' in request_data: + old_nodes = request_data['nodes'] + request_data['nodes'] = new_nodes + self.logger.info(f"Updated Tendermint nodes for '{ticker}': {len(old_nodes)} -> {len(new_nodes)} nodes") + return True + return False + + def update_utxo_electrum_in_request(self, request_data: Dict[str, Any], protocol_info: CoinProtocolInfo, ticker: str) -> bool: + if not protocol_info.electrum: + self.logger.warning(f"No electrum servers found for UTXO ticker '{ticker}' in coins configuration") + return False + # Wasm requests should use WSS servers; others prefer SSL then TCP + prefer_wss = self._is_wasm_mode(request_data) + selected = self._filter_electrum_servers_with_mode(protocol_info.electrum, prefer_wss=prefer_wss) + new_servers: List[Dict[str, Any]] = [] + for e in selected: + server: Dict[str, Any] = {"url": e.get("url")} + if e.get('protocol'): + server['protocol'] = e.get('protocol') + for field in ['ws_url', 'disable_cert_verification']: + if e.get(field) is not None: + server[field] = e.get(field) + new_servers.append(server) + if 'params' in request_data and isinstance(request_data['params'], dict): + params = request_data['params'] + if 'activation_params' in params and 'mode' in params['activation_params']: + mode = params['activation_params']['mode'] + if 'rpc_data' in mode and 'servers' in mode['rpc_data']: + old = mode['rpc_data']['servers'] + mode['rpc_data']['servers'] = new_servers + self.logger.info(f"Updated UTXO electrum servers for '{ticker}': {len(old)} -> {len(new_servers)} servers") + return True + if 'mode' in params and 'rpc_data' in params['mode'] and 'servers' in params['mode']['rpc_data']: + old = params['mode']['rpc_data']['servers'] + params['mode']['rpc_data']['servers'] = new_servers + self.logger.info(f"Updated UTXO electrum servers for '{ticker}': {len(old)} -> {len(new_servers)} servers") + return True + else: + if request_data.get('method') == 'electrum' and 'servers' in request_data: + old = request_data['servers'] + request_data['servers'] = new_servers + self.logger.info(f"Updated UTXO electrum servers for '{ticker}': {len(old)} -> {len(new_servers)} servers") + return True + if request_data.get('method') == 'enable' and 'urls' in request_data: + old = request_data['urls'] + request_data['urls'] = [s['url'] for s in new_servers] + self.logger.info(f"Updated UTXO electrum urls for '{ticker}': {len(old)} -> {len(new_servers)} servers") + return True + return False + + def update_zhtlc_in_request(self, request_data: Dict[str, Any], protocol_info: CoinProtocolInfo, ticker: str) -> bool: + updated = False + # Detect Wasm vs non-Wasm + prefer_wss = self._is_wasm_mode(request_data) + # light_wallet_d_servers + light_servers: List[str] = [] + try: + coin_config = self.coins_config.get_coin_config(ticker) + if coin_config: + lw_key = 'light_wallet_d_servers_wss' if prefer_wss else 'light_wallet_d_servers' + lw_servers = coin_config.get(lw_key) or [] + if isinstance(lw_servers, list) and lw_servers: + light_servers = self.select_preferred_urls(lw_servers, max_count=3) + except Exception: + pass + if light_servers: + if 'params' in request_data and isinstance(request_data['params'], dict): + params = request_data['params'] + if 'activation_params' in params and 'mode' in params['activation_params']: + mode = params['activation_params']['mode'] + if 'rpc_data' in mode and 'light_wallet_d_servers' in mode['rpc_data']: + old = mode['rpc_data']['light_wallet_d_servers'] + mode['rpc_data']['light_wallet_d_servers'] = light_servers + self.logger.info(f"Updated ZHTLC light_wallet_d_servers for '{ticker}': {len(old)} -> {len(light_servers)} servers") + updated = True + elif 'mode' in params and 'rpc_data' in params['mode'] and 'light_wallet_d_servers' in params['mode']['rpc_data']: + old = params['mode']['rpc_data']['light_wallet_d_servers'] + params['mode']['rpc_data']['light_wallet_d_servers'] = light_servers + self.logger.info(f"Updated ZHTLC light_wallet_d_servers for '{ticker}': {len(old)} -> {len(light_servers)} servers") + updated = True + # electrum_servers + if protocol_info.electrum: + # Wasm requests should use WSS servers; others prefer SSL then TCP + selected = self._filter_electrum_servers_with_mode(protocol_info.electrum, prefer_wss=prefer_wss) + new_electrum: List[Dict[str, Any]] = [] + for e in selected: + server: Dict[str, Any] = {"url": e.get("url")} + if e.get('protocol'): + server['protocol'] = e.get('protocol') + if e.get('ws_url'): + server['ws_url'] = e.get('ws_url') + new_electrum.append(server) + if 'params' in request_data and isinstance(request_data['params'], dict): + params = request_data['params'] + if 'activation_params' in params and 'mode' in params['activation_params']: + mode = params['activation_params']['mode'] + if 'rpc_data' in mode and 'electrum_servers' in mode['rpc_data']: + old = mode['rpc_data']['electrum_servers'] + mode['rpc_data']['electrum_servers'] = new_electrum + self.logger.info(f"Updated ZHTLC electrum_servers for '{ticker}': {len(old)} -> {len(new_electrum)} servers") + updated = True + elif 'mode' in params and 'rpc_data' in params['mode'] and 'electrum_servers' in params['mode']['rpc_data']: + old = params['mode']['rpc_data']['electrum_servers'] + params['mode']['rpc_data']['electrum_servers'] = new_electrum + self.logger.info(f"Updated ZHTLC electrum_servers for '{ticker}': {len(old)} -> {len(new_electrum)} servers") + updated = True + return updated + + def update_eth_nodes_in_request(self, request_data: Dict[str, Any], protocol_info: CoinProtocolInfo, ticker: str) -> bool: + if not protocol_info.nodes: + self.logger.warning(f"No nodes found for ETH ticker '{ticker}' in coins configuration") + return False + selected = self.select_preferred_servers(protocol_info.nodes, max_count=3) + new_nodes: List[Dict[str, Any]] = [] + for n in selected: + node: Dict[str, Any] = {"url": n.get("url")} + for field in ['ws_url', 'komodo_proxy']: + if n.get(field): + node[field] = n.get(field) + new_nodes.append(node) + if 'params' in request_data and isinstance(request_data['params'], dict): + params = request_data['params'] + if 'nodes' in params: + old = params['nodes'] + params['nodes'] = new_nodes + self.logger.info(f"Updated ETH nodes for '{ticker}': {len(old)} -> {len(new_nodes)} nodes") + return True + if 'nodes' in request_data: + old = request_data['nodes'] + request_data['nodes'] = new_nodes + self.logger.info(f"Updated ETH nodes for '{ticker}': {len(old)} -> {len(new_nodes)} nodes") + return True + if request_data.get('method') == 'enable' and 'urls' in request_data: + old_urls = request_data['urls'] + request_data['urls'] = [i['url'] for i in new_nodes] + self.logger.info(f"Updated ETH urls for '{ticker}': {len(old_urls)} -> {len(new_nodes)} nodes") + return True + return False + + def update_nodes_in_request(self, request_data: Dict[str, Any], request_name: str = "Unknown") -> bool: + ticker = extract_ticker_from_request(request_data) + if not ticker: + self.logger.info(f"No ticker found in request '{request_name}'") + return False + ticker_upper = str(ticker).upper() + protocol_info = self.coins_config.get_protocol_info(ticker_upper) + protocol = protocol_info.protocol_type or 'UNKNOWN' + self.logger.info(f"Detected protocol '{protocol}' for ticker '{ticker_upper}' via CoinsConfigManager") + if protocol == 'TENDERMINT': + return self.update_tendermint_nodes_in_request(request_data, protocol_info, ticker_upper) + if protocol == 'UTXO': + return self.update_utxo_electrum_in_request(request_data, protocol_info, ticker_upper) + if protocol == 'ZHTLC': + return self.update_zhtlc_in_request(request_data, protocol_info, ticker_upper) + if protocol == 'ETH': + return self.update_eth_nodes_in_request(request_data, protocol_info, ticker_upper) + self.logger.warning(f"Unknown or unsupported protocol '{protocol}' for ticker '{ticker_upper}'") + return False + + + def _normalize_eth_nodes(self, nodes: Optional[List[Any]]) -> List[Dict[str, str]]: + """Normalize ETH node list format.""" + norm: List[Dict[str, str]] = [] + for n in nodes or []: + if isinstance(n, dict) and n.get("url"): + node = {"url": n["url"]} + # Preserve additional fields + for field in ['ws_url', 'komodo_proxy']: + if field in n: + node[field] = n[field] + norm.append(node) + elif isinstance(n, str): + norm.append({"url": n}) + return norm + + def _normalize_tendermint_nodes(self, protocol_info: CoinProtocolInfo) -> List[Dict[str, str]]: + """Normalize Tendermint node list format.""" + nodes: List[Dict[str, str]] = [] + + if protocol_info.rpc_urls: + for e in protocol_info.rpc_urls: + if isinstance(e, dict): + node: Dict[str, str] = {} + if e.get("url"): + node["url"] = e.get("url") + # Preserve additional fields + for field in ['api_url', 'grpc_url', 'ws_url', 'komodo_proxy']: + if e.get(field): + node[field] = e.get(field) + if node.get("url"): + nodes.append(node) + elif isinstance(e, str): + nodes.append({"url": e}) + + # Fallback to nodes field if no rpc_urls + if not nodes and protocol_info.nodes: + for n in protocol_info.nodes: + if isinstance(n, dict) and n.get("url"): + nodes.append({"url": n.get("url")}) + + return nodes + + def _is_wasm_mode(self, request_data: Dict[str, Any]) -> bool: + """Detect whether the incoming request should be treated as Wasm. + + The updater script sets a transient flag `__wasm` on request objects whose + names include "Wasm". We rely exclusively on that flag here. + """ + try: + if request_data.get("__wasm") is True: + return True + params = request_data.get("params", {}) + if isinstance(params, dict) and params.get("__wasm") is True: + return True + except Exception: + pass + return False + + def _filter_electrum_servers_with_mode(self, servers: Optional[List[Any]], prefer_wss: bool) -> List[Dict[str, Any]]: + """Filter electrum servers based on whether WSS is preferred (Wasm) or not. + + - When prefer_wss is True: include only WSS servers, prioritize cipig/komodo, cap at 3. + - When prefer_wss is False: exclude WSS, prefer SSL then TCP, prioritize cipig/komodo, cap at 3. + """ + if not isinstance(servers, list): + return [] + + wss_list: List[Dict[str, Any]] = [] + ssl_list: List[Dict[str, Any]] = [] + tcp_list: List[Dict[str, Any]] = [] + other_list: List[Dict[str, Any]] = [] + + for s in servers: + if not isinstance(s, dict): + continue + url = s.get("url") + proto_val = s.get("protocol") or s.get("proto") or "" + proto = str(proto_val).upper() + if not url: + continue + if proto == "WSS": + wss_list.append(s) + elif proto == "SSL": + ssl_list.append(s) + elif proto == "TCP": + tcp_list.append(s) + else: + other_list.append(s) + + def prioritize_cipig(items: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + cipig: List[Dict[str, Any]] = [] + rest: List[Dict[str, Any]] = [] + for item in items: + url_val = str(item.get("url", "")).lower() + if "cipig" in url_val or "komodo" in url_val: + cipig.append(item) + else: + rest.append(item) + return cipig + rest + + if prefer_wss: + return prioritize_cipig(wss_list)[:3] + + ssl_ordered = prioritize_cipig(ssl_list) + tcp_ordered = prioritize_cipig(tcp_list) + ordered = ssl_ordered + tcp_ordered + prioritize_cipig(other_list) + return ordered[:3] + + def _filter_electrum_servers(self, servers: Optional[List[Any]]) -> List[Dict[str, Any]]: + """Filter and limit electrum servers: drop WSS, prefer SSL over TCP, prioritize cipig, cap at 3.""" + if not isinstance(servers, list): + return [] + + ssl_list: List[Dict[str, Any]] = [] + tcp_list: List[Dict[str, Any]] = [] + other_list: List[Dict[str, Any]] = [] + + for s in servers: + if not isinstance(s, dict): + continue + url = s.get("url") + proto_val = s.get("protocol") or s.get("proto") or "" + proto = str(proto_val).upper() + if not url: + continue + if proto == "WSS": + continue + if proto == "SSL": + ssl_list.append(s) + elif proto == "TCP": + tcp_list.append(s) + else: + other_list.append(s) + + def prioritize_cipig(items: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + cipig: List[Dict[str, Any]] = [] + rest: List[Dict[str, Any]] = [] + for item in items: + url_val = str(item.get("url", "")).lower() + if "cipig" in url_val: + cipig.append(item) + else: + rest.append(item) + return cipig + rest + + ssl_ordered = prioritize_cipig(ssl_list) + tcp_ordered = prioritize_cipig(tcp_list) + ordered = ssl_ordered + tcp_ordered + prioritize_cipig(other_list) + return ordered[:3] + + + def build_activation_request(self, ticker: str, enable_hd: bool = True) -> ActivationRequest: + """Build activation request for a coin based on its protocol. + + Args: + ticker: The coin ticker to activate. + enable_hd: Whether to use HD wallet mode (for non-HD instances, set False). + + Returns: + ActivationRequest object with method and parameters. + """ + ticker_upper = str(ticker).upper() + protocol_info = self.coins_config.get_protocol_info(ticker_upper) + + if protocol_info.protocol_type == "ETH": + return self._build_eth_activation(ticker_upper, protocol_info) + elif protocol_info.protocol_type == "TENDERMINT": + return self._build_tendermint_activation(ticker_upper, protocol_info) + elif protocol_info.protocol_type == "UTXO": + return self._build_utxo_activation(ticker_upper, protocol_info, enable_hd) + elif protocol_info.protocol_type == "ZHTLC": + return self._build_zhtlc_activation(ticker_upper, protocol_info, enable_hd) + elif protocol_info.protocol_type == "SIA": + return self._build_sia_activation(ticker_upper, protocol_info) + else: + raise ValueError(f"Unsupported protocol type: {protocol_info.protocol_type} for ticker: {ticker}") + + def _build_eth_activation(self, ticker: str, protocol_info: CoinProtocolInfo) -> ActivationRequest: + """Build ETH-like coin activation request.""" + params = { + "ticker": ticker, + "tx_history": True, + "get_balances": True, + "erc20_tokens_requests": [], + } + + # Add nodes if available + if protocol_info.nodes: + nodes = self._normalize_eth_nodes(protocol_info.nodes) + selected_nodes = self._select_preferred_servers(nodes, max_count=3) + if selected_nodes: + params["nodes"] = selected_nodes + + # Add swap contract addresses + if protocol_info.swap_contract_address: + params["swap_contract_address"] = protocol_info.swap_contract_address + if protocol_info.fallback_swap_contract: + params["fallback_swap_contract"] = protocol_info.fallback_swap_contract + + return ActivationRequest( + method="task::enable_eth::init", + params=params, + timeout=60, + is_task=True + ) + + def _build_tendermint_activation(self, ticker: str, protocol_info: CoinProtocolInfo) -> ActivationRequest: + """Build Tendermint-like coin activation request.""" + params = { + "ticker": ticker, + "tx_history": False, + "get_balances": True, + "tokens_params": [] + } + + # Add nodes from rpc_urls or nodes + nodes = self._normalize_tendermint_nodes(protocol_info) + if nodes: + selected_nodes = self._select_preferred_servers(nodes, max_count=3) + if selected_nodes: + params["nodes"] = selected_nodes + + return ActivationRequest( + method="task::enable_tendermint::init", + params=params, + timeout=60, + is_task=True + ) + + def _build_sia_activation(self, ticker: str, protocol_info: CoinProtocolInfo) -> ActivationRequest: + """Build SIA coin activation request.""" + # Use params aligned with v2 request template + params = { + "activation_params": { + "client_conf": { + "headers": {}, + "server_url": "https://sia-walletd.komodo.earth/" + }, + "required_confirmations": 3, + "tx_history": True + }, + "client_id": 0, + "ticker": ticker + } + return ActivationRequest( + method="enable_sia::init", + params=params, + timeout=60, + is_task=True + ) + + def _build_utxo_activation(self, ticker: str, protocol_info: CoinProtocolInfo, enable_hd: bool = True) -> ActivationRequest: + """Build UTXO coin activation request.""" + # Filter and select electrum servers + electrum_servers = self._filter_electrum_servers(protocol_info.electrum) + + params = { + "ticker": ticker, + "tx_history": True, + "get_balances": True, + "activation_params": { + "mode": { + "rpc": "Electrum", + "rpc_data": { + "servers": electrum_servers + }, + } + }, + } + + # Add HD wallet parameters for HD instances + if enable_hd: + params["activation_params"]["path_to_address"] = { + "account_id": 0, # This is where account_id should be + "address_id": 0, + "chain": "External" + } + params["activation_params"]["scan_policy"] = "scan_if_new_wallet" + params["activation_params"]["gap_limit"] = 20 + params["activation_params"]["min_addresses_number"] = 3 + params["activation_params"]["priv_key_policy"] = "ContextPrivKey" + + return ActivationRequest( + method="task::enable_utxo::init", + params=params, + timeout=60, + is_task=True + ) + + def _build_zhtlc_activation(self, ticker: str, protocol_info: CoinProtocolInfo, enable_hd: bool = True) -> ActivationRequest: + """Build ZHTLC coin activation request.""" + activation_params = { + "mode": { + "rpc": "Native", + "rpc_data": {} + } + } + + # Add light wallet servers if available + if hasattr(protocol_info, 'light_wallet_d_servers') and protocol_info.light_wallet_d_servers: + # Get from coin config since it's not in CoinProtocolInfo + coin_config = self.coins_config.get_coin_config(ticker) + light_wallet_servers = coin_config.get('light_wallet_d_servers', []) + if light_wallet_servers: + # Select up to 3 servers + selected_servers = light_wallet_servers[:3] + activation_params["mode"]["rpc_data"]["light_wallet_d_servers"] = selected_servers + + # Add electrum servers if available + if protocol_info.electrum: + electrum_servers = self._filter_electrum_servers(protocol_info.electrum) + if electrum_servers: + activation_params["mode"]["rpc_data"]["electrum_servers"] = electrum_servers + + params = { + "ticker": ticker, + "tx_history": True, + "get_balances": True, + "activation_params": activation_params, + } + + # Add HD wallet parameters for HD instances + if enable_hd: + params["activation_params"]["path_to_address"] = { + "account_id": 0, + "address_id": 0, + "chain": "External" + } + params["activation_params"]["scan_policy"] = "scan_if_new_wallet" + params["activation_params"]["gap_limit"] = 20 + params["activation_params"]["min_addresses_number"] = 3 + params["activation_params"]["priv_key_policy"] = "ContextPrivKey" + + return ActivationRequest( + method="task::enable_utxo::init", # ZHTLC uses UTXO activation + params=params, + timeout=60, + is_task=True + ) + + +# ----- Token activation helpers ----- + + def build_token_activation_request(self, ticker: str) -> Tuple[ActivationRequest, Optional[str]]: + """Build token activation request and return parent coin. + + Args: + ticker: The token ticker to activate. + + Returns: + Tuple of (ActivationRequest, parent_coin_ticker) + """ + ticker_upper = str(ticker).upper() + is_token, parent_coin = self.coins_config.is_token(ticker_upper) + + if not is_token: + raise ValueError(f"Ticker {ticker} is not recognized as a token") + + protocol_info = self.coins_config.get_protocol_info(ticker_upper) + + # Determine if it's an ERC20-like token or Tendermint token + is_evm_token = ( + ticker_upper.endswith("-ERC20") or + protocol_info.contract_address is not None or + parent_coin == "ETH" + ) + + if is_evm_token: + params = { + "ticker": ticker_upper, + "activation_params": {}, + } + + # Add required confirmations if specified + if protocol_info.required_confirmations is not None: + try: + params["activation_params"]["required_confirmations"] = int(protocol_info.required_confirmations) + except (ValueError, TypeError): + pass + + return ActivationRequest( + method="enable_erc20", + params=params, + timeout=30, + is_task=False + ), parent_coin + else: + # Tendermint token (IBC) + params = { + "ticker": ticker_upper, + "activation_params": {}, + } + + # Add required confirmations if specified + if protocol_info.required_confirmations is not None: + try: + params["activation_params"]["required_confirmations"] = int(protocol_info.required_confirmations) + except (ValueError, TypeError): + pass + + return ActivationRequest( + method="enable_tendermint_token", + params=params, + timeout=30, + is_task=False + ), parent_coin + + +class ActivationManager: + """Manages coin and token activation with intelligent protocol detection.""" + + def __init__(self, rpc_func: Callable[[str, Dict[str, Any]], Dict[str, Any]], + userpass: str, workspace_root: Optional[Path] = None, + instance_name: str = "default"): + """Initialize the activation manager. + + Args: + rpc_func: Callable for making RPC requests (method, params) -> response + userpass: The userpass for RPC authentication + workspace_root: Path to workspace root for config management + """ + self.rpc_func = rpc_func + self.userpass = userpass + self.logger = logger + self.instance_name = instance_name + + # Initialize config and request builder + self.coins_config = CoinsConfigManager(workspace_root) + self.request_builder = ActivationRequestBuilder(self.coins_config, userpass) + + def _state_key(self, ticker: str) -> str: + """Namespaced activation state key per instance.""" + return f"{self.instance_name}:{str(ticker).upper()}" + + @staticmethod + def _status_method_for_init(method: str) -> Optional[str]: + """Get the status method for a task init method.""" + if "enable_eth::init" in method: + return "task::enable_eth::status" + if "enable_tendermint::init" in method: + return "task::enable_tendermint::status" + if "enable_utxo::init" in method: + return "task::enable_utxo::status" + if "enable_sia::init" in method: + return "enable_sia::status" + return None + + def _poll_task(self, ticker: str, status_method: str, task_id: Any) -> None: + """Poll task status until completion or failure.""" + key = self._state_key(ticker) + max_polls = 40 # 200 seconds at 5 second intervals + poll_count = 0 + + while poll_count < max_polls: + try: + # Make status request + status_params = {"task_id": task_id, "forget_if_finished": False} + status_response = self.rpc_func(status_method, status_params) or {} + + # Update state + ACTIVATION_STATE.setdefault(key, {}) + ACTIVATION_STATE[key].update({"status_raw": status_response, "poll_count": poll_count}) + + # Extract status + status_val = None + if isinstance(status_response, dict): + result = status_response.get("result") + if isinstance(result, dict): + status_val = result.get("status") or result.get("state") + + # Check if task is complete + if status_val == "Ok": + ACTIVATION_STATE[key].update({ + "status": "enabled", + "completed_at": time.time(), + "result": status_response + }) + self.logger.info(f"Coin {ticker} activation completed successfully") + return + elif status_val == "Error": + error_details = result.get("details", "Unknown error") + ACTIVATION_STATE[key].update({ + "status": "failed", + "failed_at": time.time(), + "result": status_response, + "error": error_details + }) + self.logger.error(f"Coin {ticker} activation failed: {error_details}") + return + else: + # Handle case where result is the final response + ACTIVATION_STATE[key].update({ + "status": "enabled", + "completed_at": time.time(), + "result": status_response + }) + self.logger.info(f"Coin {ticker} activation completed") + return + + except Exception as e: + self.logger.info(f"Polling error for {ticker}: {e}") + # Continue polling on transient errors + + poll_count += 1 + time.sleep(5) + + # Timeout + ACTIVATION_STATE[key].update({ + "status": "timeout", + "failed_at": time.time(), + "error": f"Task polling timed out after {max_polls * 5} seconds" + }) + self.logger.error(f"Coin {ticker} activation timed out") + + def is_coin_enabled(self, ticker: str) -> bool: + """Check if a coin is currently enabled.""" + ticker_upper = str(ticker).upper() + state = ACTIVATION_STATE.get(self._state_key(ticker_upper), {}) + return state.get("status") == "enabled" + + def activate_coin(self, ticker: str, enable_hd: bool = True, + wait_for_completion: bool = True) -> ActivationResult: + """Activate a coin using appropriate protocol method. + + Args: + ticker: The coin ticker to activate + enable_hd: Whether to use HD wallet mode + wait_for_completion: Whether to wait for task completion + + Returns: + ActivationResult with success status and response + """ + ticker_upper = str(ticker).upper() + key = self._state_key(ticker_upper) + + # Check if already enabled + if self.is_coin_enabled(ticker_upper): + self.logger.info(f"Coin {ticker_upper} is already enabled") + return ActivationResult( + success=True, + response=ACTIVATION_STATE.get(key, {}).get("result", {}), + error=None + ) + + try: + # Check if already activated via get_enabled_coins first + enabled_coins_response = self.rpc_func("get_enabled_coins", {}) + if isinstance(enabled_coins_response, dict) and "result" in enabled_coins_response: + enabled_coins = enabled_coins_response["result"] + if isinstance(enabled_coins, list): + enabled_tickers = [coin.get("ticker", "").upper() for coin in enabled_coins if isinstance(coin, dict)] + if ticker_upper in enabled_tickers: + self.logger.info(f"Coin {ticker_upper} is already enabled") + ACTIVATION_STATE[key] = { + "status": "enabled", + "last_started": time.time(), + "result": {"status": "already_enabled"} + } + return ActivationResult( + success=True, + response={"status": "already_enabled"}, + already_enabled=True + ) + + # Build activation request + activation_request = self.request_builder.build_activation_request(ticker_upper, enable_hd) + + # Update state + ACTIVATION_STATE[key] = { + "status": "in_progress", + "last_started": time.time(), + "method": activation_request.method + } + + # Make the activation request + request_params = { + "userpass": self.userpass, + "mmrpc": "2.0", + "method": activation_request.method, + "params": activation_request.params, + "id": 0 + } + + response = self.rpc_func(activation_request.method, activation_request.params) or {} + + # Check if it's the "already activated" error and handle gracefully + if (isinstance(response, dict) and "error" in response and + "raw_response" in response): + raw_response = response.get("raw_response", "") + if "CoinIsAlreadyActivated" in raw_response or "is activated already" in raw_response: + self.logger.info(f"Coin {ticker_upper} is already activated") + ACTIVATION_STATE[key] = { + "status": "enabled", + "last_started": time.time(), + "result": {"status": "already_enabled"} + } + return ActivationResult( + success=True, + response={"status": "already_enabled"}, + already_enabled=True + ) + + + # Handle task-based methods + if activation_request.is_task: + task_id = None + # Extract response dict from tuple if needed + response_dict = response + if isinstance(response, tuple) and len(response) >= 2: + response_dict = response[1] + + if isinstance(response_dict, dict): + result = response_dict.get("result") + if isinstance(result, dict): + task_id = result.get("task_id") + + if task_id is not None: + status_method = self._status_method_for_init(activation_request.method) + if status_method: + ACTIVATION_STATE[key].update({ + "task_id": task_id, + "status_method": status_method + }) + + # Start polling in background + poll_thread = threading.Thread( + target=self._poll_task, + args=(ticker_upper, status_method, task_id), + daemon=True + ) + poll_thread.start() + + # Wait for completion if requested + if wait_for_completion: + poll_thread.join(timeout=300) # 5 minute timeout + + final_state = ACTIVATION_STATE.get(key, {}) + final_status = final_state.get("status") + + if final_status == "enabled": + self.logger.info(f"Successfully activated {ticker_upper}") + return ActivationResult( + success=True, + response=final_state.get("result", {}), + task_id=task_id + ) + else: + error_msg = final_state.get("error", f"Activation failed with status: {final_status}") + self.logger.warning(f"Failed to activate {ticker_upper}: {error_msg}") + return ActivationResult( + success=False, + response=final_state.get("result", {}), + task_id=task_id, + error=error_msg + ) + else: + return ActivationResult( + success=True, + response=response, + task_id=task_id + ) + else: + self.logger.error(f"No status method available for {activation_request.method}") + ACTIVATION_STATE[key].update({ + "status": "failed", + "error": "No status method available" + }) + return ActivationResult( + success=False, + response=response, + error="No status method available for task" + ) + else: + # Provide more context for debugging: include the raw init response + try: + self.logger.warning( + f"No task ID returned from {ticker_upper} activation request. " + f"Init response: {json.dumps(response) if isinstance(response, (dict, list)) else str(response)}" + ) + except Exception: + self.logger.warning(f"No task ID returned from {ticker_upper} activation request. Init response: ") + ACTIVATION_STATE[key].update({ + "status": "failed", + "error": "No task ID returned" + }) + return ActivationResult( + success=False, + response=response, + error="No task ID returned from activation request" + ) + else: + # Non-task method - immediate response + if isinstance(response, dict) and response.get("result"): + ACTIVATION_STATE[key].update({ + "status": "enabled", + "result": response, + "completed_at": time.time() + }) + return ActivationResult(success=True, response=response) + else: + ACTIVATION_STATE[key].update({ + "status": "failed", + "result": response + }) + return ActivationResult( + success=False, + response=response, + error="Activation request failed" + ) + + except Exception as e: + error_msg = f"Failed to activate {ticker_upper}: {str(e)}" + self.logger.error(error_msg) + ACTIVATION_STATE[key] = { + "status": "failed", + "error": error_msg, + "failed_at": time.time() + } + return ActivationResult(success=False, response={}, error=error_msg) + + def activate_token(self, ticker: str, parent_override: Optional[str] = None, + enable_hd: bool = True) -> ActivationResult: + """Activate a token, ensuring its parent coin is enabled first. + + Args: + ticker: The token ticker to activate + parent_override: Override for parent coin detection + enable_hd: Whether to use HD wallet mode for parent coin + + Returns: + ActivationResult with success status and response + """ + ticker_upper = str(ticker).upper() + key = self._state_key(ticker_upper) + + # Check if already enabled + if self.is_coin_enabled(ticker_upper): + self.logger.info(f"Token {ticker_upper} is already enabled") + return ActivationResult( + success=True, + response=ACTIVATION_STATE.get(key, {}).get("result", {}), + error=None + ) + + try: + # Build token activation request and get parent coin + token_request, parent_coin = self.request_builder.build_token_activation_request(ticker_upper) + parent_coin = parent_override or parent_coin + + # Ensure parent coin is enabled first + if parent_coin: + parent_result = self.activate_coin(parent_coin, enable_hd, wait_for_completion=True) + if not parent_result.success: + return ActivationResult( + success=False, + response=parent_result.response, + error=f"Failed to enable parent coin {parent_coin}: {parent_result.error}" + ) + self.logger.info(f"Parent coin {parent_coin} is enabled, proceeding with token {ticker_upper}") + + # Activate the token + ACTIVATION_STATE[key] = { + "status": "in_progress", + "last_started": time.time(), + "parent": parent_coin, + "method": token_request.method + } + + response = self.rpc_func(token_request.method, token_request.params) or {} + + if isinstance(response, dict) and response.get("result"): + ACTIVATION_STATE[key].update({ + "status": "enabled", + "result": response, + "completed_at": time.time() + }) + self.logger.info(f"Token {ticker_upper} activated successfully") + return ActivationResult(success=True, response=response) + else: + ACTIVATION_STATE[key].update({ + "status": "failed", + "result": response + }) + return ActivationResult( + success=False, + response=response, + error="Token activation request failed" + ) + + except Exception as e: + error_msg = f"Failed to activate token {ticker_upper}: {str(e)}" + self.logger.error(error_msg) + ACTIVATION_STATE[key] = { + "status": "failed", + "error": error_msg, + "failed_at": time.time() + } + return ActivationResult(success=False, response={}, error=error_msg) + + def get_activation_status(self, ticker: str) -> Dict[str, Any]: + """Get current activation status for a ticker.""" + ticker_upper = str(ticker).upper() + return ACTIVATION_STATE.get(self._state_key(ticker_upper), {"status": "not_started"}) + diff --git a/utils/py/lib/managers/coins_config_manager.py b/utils/py/lib/managers/coins_config_manager.py new file mode 100644 index 000000000..2bd59c0a6 --- /dev/null +++ b/utils/py/lib/managers/coins_config_manager.py @@ -0,0 +1,314 @@ +#!/usr/bin/env python3 +""" +CoinsConfigManager - Efficient management of coins configuration data. + +This module provides centralized access to coins configuration with intelligent +caching and single-fetch optimization. +""" + +import json +import time +import urllib.request +import logging +from pathlib import Path +from typing import Dict, List, Any, Optional, Tuple +from dataclasses import dataclass + +logger = logging.getLogger(__name__) + +# URL to fetch the latest coins configuration +COINS_CONFIG_URL = "https://raw.githubusercontent.com/KomodoPlatform/coins/master/utils/coins_config.json" + +@dataclass +class CoinProtocolInfo: + """Information about a coin's protocol and configuration.""" + protocol_type: str + nodes: Optional[List[Dict[str, Any]]] = None + electrum: Optional[List[Dict[str, Any]]] = None + rpc_urls: Optional[List[Dict[str, Any]]] = None + swap_contract_address: Optional[str] = None + fallback_swap_contract: Optional[str] = None + chain_id: Optional[str] = None + denom: Optional[str] = None + contract_address: Optional[str] = None + required_confirmations: Optional[int] = None + + +class CoinsConfigManager: + """Manages coins configuration with efficient caching and fetching.""" + + def __init__(self, workspace_root: Optional[Path] = None): + """Initialize the coins config manager. + + Args: + workspace_root: Path to the workspace root. If None, auto-detects. + """ + if workspace_root is None: + workspace_root = Path(__file__).parent.parent.parent.parent.parent + + self.workspace_root = Path(workspace_root) + self.logger = logger or logging.getLogger(__name__) + + # Cache for coins configuration + self._coins_config: Optional[Dict[str, Any]] = None + self._last_fetch_time: float = 0 + self._cache_duration: float = 3600 # 1 hour cache + + # Try to load from cache first + self._load_from_cache() + + def _load_from_cache(self) -> None: + """Try to load coins config from local cache file.""" + cache_file = self.workspace_root / "tmp" / "coins_config_cache.json" + + if cache_file.exists(): + try: + with open(cache_file, 'r', encoding='utf-8') as f: + cache_data = json.load(f) + + # Check if cache is still valid (within cache duration) + cache_time = cache_data.get('timestamp', 0) + if time.time() - cache_time < self._cache_duration: + self._coins_config = cache_data.get('data', {}) + self._last_fetch_time = cache_time + self.logger.info(f"Loaded coins config from cache ({len(self._coins_config)} coins)") + return + + except Exception as e: + self.logger.warning(f"Failed to load coins config from cache: {e}") + + def _save_to_cache(self) -> None: + """Save coins config to local cache file.""" + if not self._coins_config: + return + + cache_file = self.workspace_root / "tmp" / "coins_config_cache.json" + cache_file.parent.mkdir(parents=True, exist_ok=True) + + try: + cache_data = { + 'timestamp': self._last_fetch_time, + 'data': self._coins_config + } + + with open(cache_file, 'w', encoding='utf-8') as f: + json.dump(cache_data, f, indent=2) + + self.logger.info(f"Saved coins config to cache") + + except Exception as e: + self.logger.warning(f"Failed to save coins config to cache: {e}") + + def _fetch_coins_config(self) -> Dict[str, Any]: + """Fetch the latest coins configuration from the remote repository.""" + try: + self.logger.info(f"Fetching coins configuration from {COINS_CONFIG_URL}") + with urllib.request.urlopen(COINS_CONFIG_URL, timeout=30) as response: + data = json.loads(response.read().decode('utf-8')) + + # Normalize the data structure + normalized_data = {} + if isinstance(data, list): + for entry in data: + if isinstance(entry, dict): + ticker = ( + entry.get("ticker") or + entry.get("symbol") or + entry.get("coin") + ) + if ticker: + normalized_data[str(ticker).upper()] = entry + elif isinstance(data, dict): + normalized_data = data + + self.logger.info(f"Successfully fetched configuration for {len(normalized_data)} coins") + return normalized_data + + except Exception as e: + self.logger.error(f"Failed to fetch coins configuration: {e}") + raise + + def get_coins_config(self, force_refresh: bool = False) -> Dict[str, Any]: + """Get the coins configuration, fetching if needed. + + Args: + force_refresh: If True, forces a fresh fetch from remote. + + Returns: + Dictionary of coin configurations keyed by ticker. + """ + # Check if we need to refresh + current_time = time.time() + needs_refresh = ( + force_refresh or + self._coins_config is None or + (current_time - self._last_fetch_time) > self._cache_duration + ) + + if needs_refresh: + try: + self._coins_config = self._fetch_coins_config() + self._last_fetch_time = current_time + self._save_to_cache() + except Exception as e: + # If fetch fails and we have cached data, use it + if self._coins_config is not None: + self.logger.warning(f"Failed to refresh coins config, using cached data: {e}") + else: + # If no cached data available, re-raise the exception + raise + + return self._coins_config or {} + + def get_coin_config(self, ticker: str) -> Optional[Dict[str, Any]]: + """Get configuration for a specific coin. + + Args: + ticker: The coin ticker symbol. + + Returns: + Coin configuration dictionary or None if not found. + """ + coins_config = self.get_coins_config() + ticker_upper = str(ticker).upper() + + # Direct lookup first + if ticker_upper in coins_config: + return coins_config[ticker_upper] + + # Search by various ticker fields + for coin_ticker, config in coins_config.items(): + if isinstance(config, dict): + coin_identifiers = [ + config.get("ticker"), + config.get("symbol"), + config.get("coin") + ] + + if ticker_upper in [str(x).upper() for x in coin_identifiers if x]: + return config + + return None + + def get_protocol_info(self, ticker: str) -> CoinProtocolInfo: + """Get protocol information for a coin. + + Args: + ticker: The coin ticker symbol. + + Returns: + CoinProtocolInfo object with protocol details. + """ + config = self.get_coin_config(ticker) + if not config: + return CoinProtocolInfo(protocol_type="UNKNOWN") + + # Extract protocol information + protocol = config.get("protocol", {}) + protocol_type = protocol.get("type", "").upper() if isinstance(protocol, dict) else "" + + # Detect protocol type if not explicitly set + if not protocol_type: + if config.get("rpc_urls"): + protocol_type = "TENDERMINT" + elif config.get("light_wallet_d_servers") or config.get("light_wallet_d_servers_wss"): + protocol_type = "ZHTLC" + elif config.get("electrum"): + protocol_type = "UTXO" + elif config.get("nodes"): + protocol_type = "ETH" + else: + protocol_type = "UNKNOWN" + + # Normalize protocol type + if protocol_type in ['COSMOS']: + protocol_type = 'TENDERMINT' + elif protocol_type in ['QTUM', 'BCH']: + protocol_type = 'UTXO' + elif protocol_type in ['ZEC']: + protocol_type = 'ZHTLC' + elif protocol_type in ['ERC20', 'MATIC', 'BNB', 'AVAX', 'FTM', 'ONE']: + protocol_type = 'ETH' + + # Extract protocol data + protocol_data = protocol.get("protocol_data", {}) if isinstance(protocol, dict) else {} + + return CoinProtocolInfo( + protocol_type=protocol_type, + nodes=config.get("nodes") or protocol_data.get("nodes"), + electrum=config.get("electrum") or protocol_data.get("electrum"), + rpc_urls=config.get("rpc_urls") or protocol_data.get("rpc_urls"), + swap_contract_address=( + config.get("swap_contract_address") or + protocol_data.get("swap_contract_address") + ), + fallback_swap_contract=( + config.get("fallback_swap_contract") or + protocol_data.get("fallback_swap_contract") + ), + chain_id=( + config.get("chain_id") or + config.get("chainId") or + config.get("chain_registry_name") or + protocol_data.get("chain_id") + ), + denom=config.get("denom") or protocol_data.get("denom"), + contract_address=( + config.get("contract_address") or + config.get("token_contract_address") or + protocol_data.get("contract_address") + ), + required_confirmations=config.get("required_confirmations") + ) + + def is_token(self, ticker: str) -> Tuple[bool, Optional[str]]: + """Check if a ticker is a token and determine its parent coin. + + Args: + ticker: The coin ticker symbol. + + Returns: + Tuple of (is_token, parent_coin). + """ + config = self.get_coin_config(ticker) + if not config: + return False, None + + protocol_info = self.get_protocol_info(ticker) + + # Check for various parent coin indicators + parent_candidates = [ + config.get("platform"), + config.get("parent_coin"), + config.get("parent"), + config.get("base"), + config.get("platform_coin"), + ] + + for candidate in parent_candidates: + if isinstance(candidate, str) and candidate.strip(): + return True, str(candidate).upper() + + # Check if it has a contract address (token indicator) + if protocol_info.contract_address: + # Detect parent from ticker pattern + ticker_upper = str(ticker).upper() + if ticker_upper.endswith("-ERC20"): + return True, "ETH" + if "-IBC_" in ticker_upper: + try: + parent = ticker_upper.split("-IBC_")[1].split("-")[0].upper() + return True, parent + except Exception: + pass + + return False, None + + def get_all_coins(self) -> List[str]: + """Get list of all available coin tickers. + + Returns: + Sorted list of coin ticker symbols. + """ + coins_config = self.get_coins_config() + return sorted(coins_config.keys()) diff --git a/utils/py/lib/managers/environment_manager.py b/utils/py/lib/managers/environment_manager.py new file mode 100644 index 000000000..fad168b89 --- /dev/null +++ b/utils/py/lib/managers/environment_manager.py @@ -0,0 +1,505 @@ +#!/usr/bin/env python3 +""" +Environment Manager for KDF Methods + +Handles environment-specific requirements for KDF API methods, +including hardware requirements, protocol preferences, and example filtering. +""" + +import json +import os +import sys +from pathlib import Path +from typing import Dict, List, Optional, Set, Tuple, Any + +# Add lib path to import models without package context +sys.path.append(str(Path(__file__).parent.parent)) +from models.kdf_method import KdfMethod + +class EnvironmentManager: + """Manages environment-specific requirements for KDF methods.""" + + def __init__(self, kdf_methods_path: Optional[str] = None): + """Initialize the environment manager. + + Args: + kdf_methods_path: Path to kdf_methods.json file. If None, uses default path. + """ + if kdf_methods_path is None: + # Default path relative to the script location + # Navigate from utils/py/lib/managers/ to workspace root + # __file__ -> utils/py/lib/managers/environment_manager.py + # .parent -> utils/py/lib/managers/ + # .parent -> utils/py/lib/ + # .parent -> utils/py/ + # .parent -> utils/ + # .parent -> workspace root + script_dir = Path(__file__).parent.parent.parent.parent.parent + # Prefer merged view by loading both files; store directory path + kdf_methods_path = script_dir / "src" / "data" + + self.kdf_methods_path = Path(kdf_methods_path) + # Load split files separately to avoid merging conflicts + self.methods_v2: Dict[str, Any] = {} + self.methods_legacy: Dict[str, Any] = {} + self.methods_data = self._load_methods_data() + + def _load_methods_data(self) -> Dict[str, Any]: + """Load and parse the KDF methods data from v2 and legacy files.""" + base = self.kdf_methods_path + if base.is_dir(): + v2_file = base / "kdf_methods_v2.json" + legacy_file = base / "kdf_methods_legacy.json" + merged: Dict[str, Any] = {} + try: + with open(legacy_file, 'r') as f: + self.methods_legacy = json.load(f) + except Exception: + self.methods_legacy = {} + try: + with open(v2_file, 'r') as f: + self.methods_v2 = json.load(f) + except Exception: + self.methods_v2 = {} + # Build a non-destructive combined view but do not rely on it for version-specific lookups + merged.update(self.methods_legacy) + merged.update(self.methods_v2) + return merged + else: + # Backward compatibility if provided a file path + with open(base, 'r') as f: + data = json.load(f) + # Assume v2 if single file + self.methods_v2 = data + return data + + def _get_method_data(self, method: str) -> Dict[str, Any]: + """Select method data from the appropriate version without merging. + Heuristic: methods containing '::' are v2, others are legacy. + """ + if '::' in method: + return self.methods_v2.get(method, {}) + return self.methods_legacy.get(method, {}) + + def is_deprecated(self, method: str) -> bool: + """Check if a method is marked as deprecated. + + Args: + method: The KDF method name + + Returns: + True if the method is deprecated, False otherwise + """ + if method not in self.methods_data: + return False + + method_data = self.methods_data[method] + return method_data.get('deprecated', False) + + def get_prerequisite_methods(self, method: str) -> List[str]: + """Get list of prerequisite methods for a method. + + Args: + method: The KDF method name + + Returns: + List of prerequisite method names + """ + if method not in self.methods_data: + return [] + + method_data = self._get_method_data(method) or self.methods_data.get(method, {}) + km = KdfMethod.from_config(method, method_data) + return km.get_prerequisite_methods() + + def get_supported_environments(self, method: str) -> List[str]: + """Get list of environments where the method is supported. + + Args: + method: The KDF method name (e.g., 'task::enable_utxo::init') + + Returns: + List of supported environment names (e.g., ['native', 'wasm']) + """ + if method not in self.methods_data: + return [] + + method_data = self._get_method_data(method) or self.methods_data.get(method, {}) + km = KdfMethod.from_config(method, method_data) + return km.supported_environments + + def is_environment_supported(self, method: str, environment: str) -> bool: + """Check if a method is supported in a specific environment. + + Args: + method: The KDF method name + environment: Environment name ('native', 'wasm', etc.) + + Returns: + True if the method supports the environment + """ + method_data = self._get_method_data(method) or self.methods_data.get(method, {}) + km = KdfMethod.from_config(method, method_data) + return km.supports_environment(environment) + + def get_hardware_requirements(self, method: str) -> List[str]: + """Get hardware requirements for a method. + + Args: + method: The KDF method name + + Returns: + List of required hardware types (e.g., ['trezor']) + """ + if method not in self.methods_data: + return [] + + method_data = self._get_method_data(method) or self.methods_data.get(method, {}) + km = KdfMethod.from_config(method, method_data) + return km.required_hardware + + def requires_hardware(self, method: str, hardware_type: str = None) -> bool: + """Check if a method requires specific hardware. + + Args: + method: The KDF method name + hardware_type: Specific hardware type to check (e.g., 'trezor') + If None, checks if any hardware is required + + Returns: + True if the method requires the specified hardware (or any hardware) + """ + method_data = self._get_method_data(method) or self.methods_data.get(method, {}) + km = KdfMethod.from_config(method, method_data) + return km.requires_hardware(hardware_type) + + def get_protocol_preferences(self, method: str, environment: str) -> Dict[str, List[str]]: + """Get protocol preferences for a method in a specific environment. + + Args: + method: The KDF method name + environment: Environment name + + Returns: + Dictionary mapping protocol types to preferred options + Example: {'electrum': ['WSS'], 'websocket': ['wss']} + """ + method_data = self._get_method_data(method) or self.methods_data.get(method, {}) + km = KdfMethod.from_config(method, method_data) + return km.get_protocol_preferences(environment) + + def get_supported_wallet_types(self, method: str) -> List[str]: + """Get list of wallet types where the method is supported. + + Args: + method: The KDF method name (e.g., 'task::enable_utxo::init') + + Returns: + List of supported wallet types (e.g., ['hd', 'iguana']) + """ + if method not in self.methods_data: + return [] + + method_data = self._get_method_data(method) or self.methods_data.get(method, {}) + km = KdfMethod.from_config(method, method_data) + return km.supported_wallet_types + + def is_wallet_type_supported(self, method: str, wallet_type: str) -> bool: + """Check if a method is supported with a specific wallet type. + + Args: + method: The KDF method name + wallet_type: Wallet type ('hd', 'iguana') + + Returns: + True if the method supports the wallet type + """ + method_data = self._get_method_data(method) or self.methods_data.get(method, {}) + km = KdfMethod.from_config(method, method_data) + return km.supports_wallet_type(wallet_type) + + def get_conditional_params(self, method: str, wallet_type: str = None) -> List[str]: + """Get parameters that are conditional based on wallet type. + + Args: + method: The KDF method name + wallet_type: Wallet type to get conditional params for + + Returns: + List of parameter names that apply to the wallet type + """ + method_data = self._get_method_data(method) or self.methods_data.get(method, {}) + km = KdfMethod.from_config(method, method_data) + return km.get_conditional_params_for_wallet(wallet_type) + + def get_filtered_examples(self, method: str, environment: str = None, + hardware: str = None, wallet_type: str = None) -> Dict[str, str]: + """Get examples filtered by environment, hardware, and wallet type requirements. + + Args: + method: The KDF method name + environment: Filter by environment (optional) + hardware: Filter by hardware requirement (optional) + wallet_type: Filter by wallet type ('hd', 'iguana') (optional) + + Returns: + Dictionary of example_key -> description pairs that match criteria + """ + if method not in self.methods_data: + return {} + method_data = self._get_method_data(method) or self.methods_data.get(method, {}) + km = KdfMethod.from_config(method, method_data) + return km.filter_examples(environment, hardware, wallet_type) + + def _matches_pattern_requirements(self, example_key: str, environment: str = None, + hardware: str = None, wallet_type: str = None) -> bool: + """Check if an example matches pattern-based requirements (x_only patterns). + + Args: + example_key: The example identifier + environment: Target environment + hardware: Target hardware + wallet_type: Target wallet type + + Returns: + True if the example matches the requirements + """ + example_lower = example_key.lower() + + # Check for hardware-specific patterns + if 'trezor' in example_lower: + return hardware == 'trezor' or hardware is None + + # Check for environment-specific patterns + if 'native' in example_lower: + return environment == 'native' or environment is None + + if 'wasm' in example_lower: + return environment == 'wasm' or environment is None + + # Check for wallet type patterns + if 'hd' in example_lower and wallet_type is not None: + return wallet_type == 'hd' + + if 'iguana' in example_lower and wallet_type is not None: + return wallet_type == 'iguana' + + # Check for parameter-specific patterns (pin/passphrase = trezor) + if any(pattern in example_lower for pattern in ['pin', 'passphrase']): + return hardware == 'trezor' or hardware is None + + # Check for HD-specific parameter patterns + if any(pattern in example_lower for pattern in ['gap_limit', 'scan_policy', 'min_addresses', 'path_to_address']): + return wallet_type == 'hd' or wallet_type is None + + # If no specific patterns found, include the example + return True + + def get_environment_specific_postman_configs(self) -> Dict[str, Dict]: + """Generate environment-specific Postman collection configurations. + + Returns: + Dictionary mapping environment names to their configurations + """ + configs = { + 'native_hd': { + 'name': 'KDF API (Native + HD)', + 'description': 'Komodo DeFi Framework API for Native environments with HD wallets', + 'preferred_protocols': { + 'electrum': ['TCP', 'SSL'], + 'websocket': ['ws', 'wss'] + }, + 'base_url': 'http://kdf-native-hd:8779', + 'notes': 'Native environment with HD wallet support. Includes HD-specific parameters.', + 'wallet_type': 'hd' + }, + 'native_iguana': { + 'name': 'KDF API (Native + Iguana)', + 'description': 'Komodo DeFi Framework API for Native environments with Iguana wallets', + 'preferred_protocols': { + 'electrum': ['TCP', 'SSL'], + 'websocket': ['ws', 'wss'] + }, + 'base_url': 'http://kdf-native-nonhd:8778', + 'notes': 'Native environment with legacy Iguana wallet support.', + 'wallet_type': 'iguana' + }, + 'wasm_hd': { + 'name': 'KDF API (WASM + HD)', + 'description': 'Komodo DeFi Framework API for WASM environments with HD wallets', + 'preferred_protocols': { + 'electrum': ['WSS'], + 'websocket': ['wss'] + }, + 'base_url': 'http://kdf-native-hd:8779', + 'notes': 'WASM environment with HD wallet support. WSS protocols only.', + 'wallet_type': 'hd' + }, + 'wasm_iguana': { + 'name': 'KDF API (WASM + Iguana)', + 'description': 'Komodo DeFi Framework API for WASM environments with Iguana wallets', + 'preferred_protocols': { + 'electrum': ['WSS'], + 'websocket': ['wss'] + }, + 'base_url': 'http://kdf-native-nonhd:8778', + 'notes': 'WASM environment with legacy Iguana wallet support. WSS protocols only.', + 'wallet_type': 'iguana' + }, + 'trezor_native_hd': { + 'name': 'KDF API (Native + Trezor + HD)', + 'description': 'Komodo DeFi Framework API for Native with Trezor hardware wallet and HD support', + 'preferred_protocols': { + 'electrum': ['TCP', 'SSL'], + 'websocket': ['ws', 'wss'] + }, + 'base_url': 'http://kdf-native-hd:8779', + 'notes': 'Native environment with Trezor hardware wallet and HD wallet support', + 'hardware': ['trezor'], + 'wallet_type': 'hd' + }, + 'trezor_wasm_hd': { + 'name': 'KDF API (WASM + Trezor + HD)', + 'description': 'Komodo DeFi Framework API for WASM with Trezor hardware wallet and HD support', + 'preferred_protocols': { + 'electrum': ['WSS'], + 'websocket': ['wss'] + }, + 'base_url': 'http://kdf-native-hd:8779', + 'notes': 'WASM environment with Trezor hardware wallet and HD wallet support', + 'hardware': ['trezor'], + 'wallet_type': 'hd' + } + } + + return configs + + def validate_method_compatibility(self, method: str, environment: str, + hardware: str = None, wallet_type: str = None) -> Tuple[bool, List[str]]: + """Validate if a method is compatible with given environment, hardware, and wallet type. + + Args: + method: The KDF method name + environment: Target environment + hardware: Target hardware (optional) + wallet_type: Target wallet type (optional) + + Returns: + Tuple of (is_compatible, list_of_issues) + """ + issues = [] + + if method not in self.methods_data: + return False, [f"Method '{method}' not found in registry"] + + # Check environment compatibility + if not self.is_environment_supported(method, environment): + supported_envs = self.get_supported_environments(method) + issues.append(f"Method not supported in '{environment}' environment. " + f"Supported: {supported_envs}") + + # Check wallet type compatibility + if wallet_type is not None and not self.is_wallet_type_supported(method, wallet_type): + supported_wallet_types = self.get_supported_wallet_types(method) + issues.append(f"Method not supported with '{wallet_type}' wallet type. " + f"Supported: {supported_wallet_types}") + + # Check hardware requirements + required_hardware = self.get_hardware_requirements(method) + if len(required_hardware) > 0: + if hardware is None: + issues.append(f"Method requires hardware: {required_hardware}") + elif hardware not in required_hardware: + issues.append(f"Method requires different hardware. " + f"Required: {required_hardware}, provided: {hardware}") + + return len(issues) == 0, issues + + def generate_compatibility_report(self) -> Dict[str, Any]: + """Generate a comprehensive compatibility report for all methods. + + Returns: + Dictionary containing compatibility analysis for all methods + """ + report = { + 'methods_by_environment': {}, + 'hardware_only_methods': [], + 'environment_restrictions': {}, + 'protocol_preferences': {} + } + + # Analyze each method (excluding deprecated ones) + for method_name, method_data in self.methods_data.items(): + # Skip deprecated methods + if method_data.get('deprecated', False): + continue + + requirements = method_data.get('requirements', {}) + environments = requirements.get('environments', []) + hardware = requirements.get('hardware', []) + protocols = requirements.get('protocols', {}) + + # Group methods by environment + for env in environments: + if env not in report['methods_by_environment']: + report['methods_by_environment'][env] = [] + report['methods_by_environment'][env].append(method_name) + + # Track hardware-only methods + if len(hardware) > 0: + report['hardware_only_methods'].append({ + 'method': method_name, + 'hardware': hardware, + 'environments': environments + }) + + # Track environment restrictions + if len(environments) < 2: # Methods that don't support both native and wasm + report['environment_restrictions'][method_name] = environments + + # Track protocol preferences + if protocols: + report['protocol_preferences'][method_name] = protocols + + return report + + +if __name__ == "__main__": + # Example usage and testing + env_manager = EnvironmentManager() + + print("=== Environment Manager Test ===") + + # Test method compatibility + method = "task::enable_utxo::user_action" + print(f"\nTesting method: {method}") + print(f"Supported environments: {env_manager.get_supported_environments(method)}") + print(f"Supported wallet types: {env_manager.get_supported_wallet_types(method)}") + print(f"Hardware requirements: {env_manager.get_hardware_requirements(method)}") + + # Test HD-specific parameters + print(f"\nHD-only params (task::enable_utxo::init): {env_manager.get_conditional_params('task::enable_utxo::init', 'hd')}") + print(f"Non-HD params (task::enable_eth::init): {env_manager.get_conditional_params('task::enable_eth::init', 'iguana')}") + + # Test filtering + print(f"\nExamples (no filter): {env_manager.get_filtered_examples(method)}") + print(f"Examples (trezor hardware): {env_manager.get_filtered_examples(method, hardware='trezor')}") + print(f"Examples (HD wallet): {env_manager.get_filtered_examples(method, wallet_type='hd')}") + + # Test protocol preferences + print(f"\nProtocol preferences (native): {env_manager.get_protocol_preferences('task::enable_utxo::init', 'native')}") + print(f"Protocol preferences (wasm): {env_manager.get_protocol_preferences('task::enable_utxo::init', 'wasm')}") + + # Test compatibility validation + print(f"\n=== Compatibility Tests ===") + is_valid, issues = env_manager.validate_method_compatibility('task::enable_z_coin::init', 'wasm', wallet_type='hd') + print(f"Z-coin in WASM with HD: {is_valid} ({issues})") + + is_valid, issues = env_manager.validate_method_compatibility('task::enable_utxo::init', 'native', wallet_type='hd') + print(f"UTXO in Native with HD: {is_valid} ({issues})") + + # Generate compatibility report + print(f"\n=== Compatibility Report ===") + report = env_manager.generate_compatibility_report() + print(f"Hardware-only methods: {len(report['hardware_only_methods'])}") + print(f"Environment configs available: {len(env_manager.get_environment_specific_postman_configs())}") diff --git a/utils/py/lib/managers/kdf_responses_manager.py b/utils/py/lib/managers/kdf_responses_manager.py new file mode 100644 index 000000000..2cf10fd5d --- /dev/null +++ b/utils/py/lib/managers/kdf_responses_manager.py @@ -0,0 +1,1643 @@ +#!/usr/bin/env python3 +""" +Clean Response Manager - Simplified and modular KDF response collection. + +This is a cleaned-up version of the original responses_manager.py with: +- Removed deprecated/duplicate logic +- Modular wallet management +- Simplified prerequisite handling +- Better separation of concerns +""" + +import json +import requests +import time +import logging +import sys +from pathlib import Path +from typing import Dict, List, Any, Optional, Tuple +from enum import Enum +from dataclasses import dataclass + +# Add lib path for utilities +sys.path.append(str(Path(__file__).parent.parent)) +from utils.json_utils import dump_sorted_json + +# Import managers +try: + from .wallet_manager import WalletManager + from .activation_manager import ActivationManager + from .coins_config_manager import CoinsConfigManager +except ImportError: + # Fall back to absolute imports + import sys + from pathlib import Path + sys.path.append(str(Path(__file__).parent)) + from wallet_manager import WalletManager + from activation_manager import ActivationManager + from coins_config_manager import CoinsConfigManager + + +@dataclass +class KDFInstance: + """KDF instance configuration.""" + name: str + url: str + userpass: str + +@dataclass +class TaskInstance: + """KDF task methods instance.""" + task_name: str + init_request: Dict[str, Any] + task_id: Optional[int] = None + init_response: Optional[Dict[str, Any]] = None + status_request: Optional[Dict[str, Any]] = None + status_responses: Optional[List[Dict[str, Any]]] = None + user_action_request: Optional[Dict[str, Any]] + user_action_responses: Optional[Dict[str, Any]] = None + status_request: Optional[Dict[str, Any]] = None + status_responses: Optional[List[Dict[str, Any]]] = None + user_action_request: Optional[Dict[str, Any]] = None + user_action_responses: Optional[Dict[str, Any]] = None + cancel_request: Optional[Dict[str, Any]] = None + cancel_response: Optional[Dict[str, Any]] = None + + +@dataclass +class CollectionResult: + """Result of collecting responses for a method.""" + response_name: str + instance_responses: Dict[str, Any] + all_passed: bool + consistent_structure: bool + auto_updatable: bool + collection_method: str + notes: str = "" + original_request: Optional[Dict[str, Any]] = None + + +class Outcome(Enum): + SUCCESS = "success" + EXPECTED_ERROR = "expected_error" + FAILURE = "failure" + + +# Configuration +KDF_INSTANCES = [ + KDFInstance("native-hd", "http://localhost:7783", "RPC_UserP@SSW0RD"), + KDFInstance("native-nonhd", "http://localhost:7784", "RPC_UserP@SSW0RD"), +] + +# Manual methods that require hardware wallets or external services +SKIP_METHODS = { + "TaskEnableEthInitTrezor", "TaskEnableEthUserActionPin", "TaskEnableQtumUserActionPin", + "TaskEnableUtxoUserActionPin", "TaskEnableBchUserActionPin", "TaskEnableTendermintUserActionPin", + "TaskEnableZCoinUserActionPin", "EnableEthWithTokensWalletConnect", "EnableTendermintWithAssetsWalletConnect", +} + + +class KdfResponseManager: + """Simplified response manager with clean architecture.""" + + def __init__(self, workspace_root: Optional[Path] = None): + """Initialize the clean response manager.""" + self.setup_logging() + + # Set workspace root + if workspace_root: + self.workspace_root = workspace_root + else: + # Auto-detect workspace root + current_dir = Path(__file__).parent + workspace_root = current_dir + while workspace_root.name != "komodo-docs-mdx" and workspace_root.parent != workspace_root: + workspace_root = workspace_root.parent + + if workspace_root.name != "komodo-docs-mdx": + raise RuntimeError("Could not find workspace root (komodo-docs-mdx)") + + self.workspace_root = workspace_root + + # Initialize managers + self.wallet_manager = WalletManager(self.workspace_root) + self.coins_config = CoinsConfigManager(self.workspace_root) + self.activation_managers = self._init_activation_managers() + + # Results storage + self.results: List[CollectionResult] = [] + self.response_delays: Dict[str, Dict[str, Dict[str, Dict[str, Any]]]] = {} + self.inconsistent_responses: Dict[str, Dict[str, Any]] = {} + self.last_kdf_version: Optional[str] = None + self.expected_error_responses: Dict[str, Dict[str, Dict[str, Any]]] = {} + self._current_request_key: Optional[str] = None + self._current_method_name: Optional[str] = None + # Test data (addresses โ†’ known txids) for env-specific overrides + self.test_data: Optional[Dict[str, Any]] = None + + # Task tracking: registry and report path + self.task_registry: Dict[str, TaskInstance] = {} + self.task_report_path: Path = self.workspace_root / "postman/generated/reports/method_tasks.json" + def setup_logging(self): + """Setup logging configuration.""" + logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[logging.StreamHandler(sys.stdout)] + ) + self.logger = logging.getLogger(__name__) + + def get_kdf_version(self) -> Optional[str]: + """Fetch KDF version from a running instance using the version RPC.""" + for instance in KDF_INSTANCES: + try: + # version is a legacy (v1) method only + req_v1 = {"userpass": instance.userpass, "method": "version"} + outcome, resp = self.send_request(instance, req_v1, timeout=10) + if outcome == Outcome.SUCCESS and isinstance(resp, dict): + # Common legacy formats + if "result" in resp and isinstance(resp["result"], str): + self.last_kdf_version = resp["result"] + return self.last_kdf_version + for v in resp.values(): + if isinstance(v, str) and any(ch.isdigit() for ch in v): + self.last_kdf_version = v + return self.last_kdf_version + except Exception: + continue + return self.last_kdf_version + + def get_kdf_version_from_report(self) -> Optional[str]: + """Extract KDF version from postman/generated/reports/kdf_postman_responses.json. + + Returns the version string if found, otherwise None. + """ + try: + report_path = self.workspace_root / "postman/generated/reports/kdf_postman_responses.json" + if not report_path.exists(): + return None + with open(report_path, 'r', encoding='utf-8') as f: + data = json.load(f) + + # Direct top-level LegacyVersion pattern + if isinstance(data, dict) and "LegacyVersion" in data: + lv = data.get("LegacyVersion") + if isinstance(lv, dict): + ver = lv.get("result") + if isinstance(ver, str): + self.last_kdf_version = ver + return ver + + # Unified responses format: search in responses -> LegacyVersion + responses = data.get("responses") if isinstance(data, dict) else None + if isinstance(responses, dict) and "LegacyVersion" in responses: + lv_entry = responses.get("LegacyVersion") + # Try common fields + if isinstance(lv_entry, dict): + # direct result + if isinstance(lv_entry.get("result"), str): + self.last_kdf_version = lv_entry["result"] + return self.last_kdf_version + # scan nested values for a plausible version string + def scan(obj): + if isinstance(obj, str) and any(ch.isdigit() for ch in obj): + return obj + if isinstance(obj, dict): + for v in obj.values(): + s = scan(v) + if s: + return s + if isinstance(obj, list): + for v in obj: + s = scan(v) + if s: + return s + return None + found = scan(lv_entry) + if found: + self.last_kdf_version = found + return found + return None + except Exception: + return None + + def _init_activation_managers(self) -> Dict[str, ActivationManager]: + """Initialize activation managers for each KDF instance.""" + managers = {} + for instance in KDF_INSTANCES: + managers[instance.name] = ActivationManager( + rpc_func=lambda method, params, inst=instance: self._send_activation_request(inst, method, params), + userpass=instance.userpass, + workspace_root=self.workspace_root, + instance_name=instance.name + ) + return managers + + def _send_activation_request(self, instance: KDFInstance, method: str, params: Dict[str, Any]) -> Dict[str, Any]: + """Send activation request for ActivationManager. + + Uses v2 (mmrpc 2.0) for task:: methods; for legacy methods like 'electrum'/'enable', + send v1-style payload by merging params at root. + """ + # Determine if this is a v2 task method + is_v2 = isinstance(method, str) and ("task::" in method or method.startswith("enable_")) + if is_v2: + request_data = { + "userpass": instance.userpass, + "mmrpc": "2.0", + "method": method, + "params": params, + "id": 0 + } + else: + # Legacy v1 activation call: merge params into root + request_data = {"userpass": instance.userpass, "method": method} + # Merge only dict params at root level + if isinstance(params, dict): + request_data.update(params) + _outcome, response = self.send_request(instance, request_data) + return response # ActivationManager expects just the response dict + + def send_request(self, instance: KDFInstance, request_data: Dict[str, Any], + timeout: int = 30, allow_retry: bool = True) -> Tuple[Outcome, Dict[str, Any]]: + """Send a request to a KDF instance with tri-state outcome.""" + start_time = time.time() + status_code = None + outcome: Outcome = Outcome.FAILURE + + try: + headers = {"Content-Type": "application/json"} + + # Filter out metadata fields before sending to API + filtered_request_data = self._filter_request_data(request_data) + rpc_version = filtered_request_data.get("mmrpc", "1.0") + method_name = filtered_request_data.get("method", "") + # Ensure task status doesn't clear completed tasks + try: + if isinstance(method_name, str) and method_name.endswith("::status"): + params = filtered_request_data.setdefault("params", {}) + if isinstance(params, dict) and "forget_if_finished" not in params: + params["forget_if_finished"] = False + except Exception: + pass + + # Pre-flight: ensure tasks exist for ::status/::cancel and override task_id from registry + try: + if isinstance(method_name, str) and method_name.endswith("::status"): + filtered_request_data = self._ensure_task_for_status(instance, filtered_request_data, timeout) + # Re-evaluate method_name in case of mutation + method_name = filtered_request_data.get("method", method_name) + except Exception as e: + self.logger.warning(f"Status preflight failed for {method_name} on {instance.name}: {e}") + + response = requests.post( + instance.url, + json=filtered_request_data, + headers=headers, + timeout=timeout + ) + + status_code = response.status_code + + if response.status_code == 200: + try: + response_data = response.json() + if "error" not in response_data: + outcome = Outcome.SUCCESS + # Extract addresses/balances from successful responses + self.wallet_manager.extract_addresses_from_response( + instance.name, method_name, response_data, filtered_request_data + ) + data = response_data + # Task tracking: register/update task lifecycle on success + try: + self._maybe_track_task_success(instance, filtered_request_data, response_data) + except Exception: + pass + except json.JSONDecodeError: + data = {"error": "Invalid JSON response", "raw_response": response.text} + else: + data = {"error": f"HTTP {response.status_code}", "raw_response": response.text} + + except requests.exceptions.Timeout: + status_code = 408 + data = {"error": "Request timeout"} + except requests.exceptions.ConnectionError: + status_code = 503 + data = {"error": "Connection failed"} + except Exception as e: + status_code = 500 + data = {"error": f"Unexpected error: {str(e)}"} + finally: + # Record timing + end_time = time.time() + delay = round(end_time - start_time, 3) + + if hasattr(self, '_current_timing_context'): + self._current_timing_context['delay'] = delay + self._current_timing_context['status_code'] = status_code or 500 + + if outcome != Outcome.SUCCESS: + # Prefer raw body for matching; fallback to stringified dict + raw_body = data.get("raw_response") if isinstance(data, dict) else None + text = raw_body if isinstance(raw_body, str) and raw_body else str(data) + + # Attach address hint when coin context is known + try: + ticker_for_request = self._extract_ticker_from_request(filtered_request_data) + ticker_upper = str(ticker_for_request).upper() if ticker_for_request else None + if ticker_upper: + addr_hint = self.wallet_manager.get_address_hint(instance.name, ticker_upper) + if addr_hint: + data["address_hint"] = {"coin": ticker_upper, "address": addr_hint} + except Exception: + pass + + # Auto-activation + retry wiring + try: + # Extract ticker from original request + ticker_for_request = self._extract_ticker_from_request(filtered_request_data) + ticker_upper = str(ticker_for_request).upper() if ticker_for_request else None + + # Helper to try activation then retry once + def _retry_after_activation(activate_ticker: Optional[str], *, force_platform: bool = False, force_reenable: bool = False) -> Tuple[Outcome, Dict[str, Any]]: + if not activate_ticker: + return outcome, data + act_result = self._ensure_coin_activated( + instance, activate_ticker, + force_enable_platform=force_platform, + force_reenable=force_reenable + ) + if act_result.get("success"): + time.sleep(0.5) + return self.send_request(instance, request_data, timeout, allow_retry=False) + return Outcome.FAILURE, {"error": f"Activation failed for {activate_ticker}", "activation_error": act_result.get("error"), "activation_response": act_result.get("response")} + + # Parent platform not activated: activate parent and retry + if allow_retry and "PlatformCoinIsNotActivated" in text: + parent_coin = None + if ticker_upper: + is_token, parent = self.coins_config.is_token(ticker_upper) + parent_coin = parent if is_token else None + if not parent_coin and isinstance(raw_body, str): + try: + body_json = json.loads(raw_body) + parent_coin = str(body_json.get("error_data") or body_json.get("error", {}).get("error_data")).upper() + except Exception: + parent_coin = None + if parent_coin: + outcome, data = _retry_after_activation(parent_coin, force_platform=True) + raw_body = data.get("raw_response") if isinstance(data, dict) else None + text = raw_body if isinstance(raw_body, str) and raw_body else str(data) + + # NoSuchCoin for a known coin: activate coin and retry + if allow_retry and "NoSuchCoin" in text and ticker_upper and self.coins_config.get_coin_config(ticker_upper): + # Re-enable if already enabled but server reports 404 + outcome, data = _retry_after_activation(ticker_upper, force_reenable=True) + raw_body = data.get("raw_response") if isinstance(data, dict) else None + text = raw_body if isinstance(raw_body, str) and raw_body else str(data) + + # Handle cancel flows missing task id: run init -> sleep -> cancel + if allow_retry and "NoSuchTask" in text and isinstance(method_name, str) and method_name.endswith("::cancel"): + try: + init_method = method_name.replace("::cancel", "::init") + # Try to find example params for the init method + init_params = self._find_example_params_for_method(init_method) or {} + # If we can determine the ticker, disable it first to ensure a fresh task + ticker_for_init = None + if isinstance(init_params, dict): + ticker_for_init = init_params.get("ticker") or init_params.get("coin") + if isinstance(ticker_for_init, str) and ticker_for_init: + try: + self.disable_coin(instance, str(ticker_for_init).upper()) + time.sleep(0.5) + except Exception: + pass + # Proactively ensure coin is disabled before running ::init + if isinstance(ticker_for_init, str) and ticker_for_init: + try: + ticker_upper_for_init = str(ticker_for_init).upper() + # Attempt disable if enabled (up to 2 tries with short waits) + for _ in range(2): + if self._is_coin_enabled(instance, ticker_upper_for_init): + self.disable_coin(instance, ticker_upper_for_init) + time.sleep(0.5) + else: + break + except Exception: + pass + + init_request = { + "userpass": instance.userpass, + "mmrpc": "2.0", + "method": init_method, + "params": init_params, + "id": 0 + } + # Fire init to get a fresh task id + init_outcome, init_resp = self.send_request(instance, init_request, timeout, allow_retry=False) + task_id = None + if isinstance(init_resp, dict): + result = init_resp.get("result") + if isinstance(result, dict): + task_id = result.get("task_id") + if task_id is not None: + time.sleep(0.5) + cancel_request = { + "userpass": instance.userpass, + "mmrpc": "2.0", + "method": method_name, + "params": {"task_id": task_id}, + "id": 0 + } + outcome, data = self.send_request(instance, cancel_request, timeout, allow_retry=False) + raw_body = data.get("raw_response") if isinstance(data, dict) else None + text = raw_body if isinstance(raw_body, str) and raw_body else str(data) + except Exception as e: + self.logger.warning(f"Cancel retry wiring failed for {method_name} on {instance.name}: {e}") + except Exception as e: + self.logger.warning(f"Retry wiring failed for {method_name} on {instance.name}: {e}") + + expected_error = self._is_expected_error(text, instance, method_name) + if expected_error: + outcome = Outcome.EXPECTED_ERROR + try: + self._record_expected_error(method_name, instance.name, status_code or 500, data, filtered_request_data) + except AttributeError: + # If a subclass doesn't have recorder yet (e.g., older Sequence manager), safely ignore + pass + self.logger.info(f"{instance.name}: [{method_name} {rpc_version}] EXPECTED_ERROR - [{data.get('error', '')}] {expected_error}") + else: + self.logger.warning(f"{instance.name}: [{method_name} {rpc_version}] FAILED - [{status_code}] {data.get('error', '')}") + self.logger.warning(f"{instance.name}: [{method_name} {rpc_version}] Request - {request_data}") + self.logger.warning(f"{instance.name}: [{method_name} {rpc_version}] filtered_request_data - {filtered_request_data}") + self.logger.warning(f"{instance.name}: [{method_name} {rpc_version}] is params in filtered_request_data - {'params' in filtered_request_data}") + self.logger.warning(f"{instance.name}: [{method_name} {rpc_version}] Response - {data}") + elif method_name != "get_enabled_coins": + self.logger.info(f"{instance.name}: [{method_name} {rpc_version}] SUCCESS") + return outcome, data + + # ----- Task tracking helpers ----- + def _base_task_name(self, method_name: str) -> str: + try: + if not isinstance(method_name, str): + return "" + if method_name.startswith("task::"): + parts = method_name.split("::") + if len(parts) >= 2: + return "::".join(parts[:2]) + return method_name + except Exception: + return "" + + def _make_task_key(self, instance_name: str, base_task_name: str, task_id: Any) -> str: + return f"{instance_name}:{base_task_name}:{task_id}" + + def _find_active_task_for_base(self, instance_name: str, base_task_name: str) -> Optional[TaskInstance]: + for key, ti in getattr(self, "task_registry", {}).items(): + try: + if not isinstance(ti, TaskInstance): + continue + if key.startswith(f"{instance_name}:{base_task_name}:"): + if not getattr(ti, "completed", False): + return ti + except Exception: + continue + return None + + def _maybe_track_task_success(self, instance: KDFInstance, request: Dict[str, Any], response: Dict[str, Any]) -> None: + try: + method_name = request.get("method", "") + if not isinstance(method_name, str): + return + # Register new task on ::init + if method_name.endswith("::init"): + result = response.get("result") if isinstance(response, dict) else None + task_id = result.get("task_id") if isinstance(result, dict) else None + if task_id is not None: + base_name = self._base_task_name(method_name) + key = self._make_task_key(instance.name, base_name, task_id) + ti = TaskInstance(task_name=base_name, init_request=request, task_id=task_id, init_response=response) + setattr(ti, "created_at", time.time()) + setattr(ti, "completed", False) + if not hasattr(self, "task_registry"): + self.task_registry = {} + self.task_registry[key] = ti + # Update task on ::status + elif method_name.endswith("::status"): + params = request.get("params", {}) if isinstance(request, dict) else {} + task_id = params.get("task_id") if isinstance(params, dict) else None + if task_id is not None: + base_name = self._base_task_name(method_name) + key = self._make_task_key(instance.name, base_name, task_id) + ti = getattr(self, "task_registry", {}).get(key) + if ti: + if getattr(ti, "status_responses", None) is None: + ti.status_responses = [] + try: + ti.status_responses.append(response) + except Exception: + pass + result = response.get("result") if isinstance(response, dict) else None + status_val = result.get("status") if isinstance(result, dict) else None + if status_val == "Ok": + setattr(ti, "completed", True) + setattr(ti, "completed_at", time.time()) + # Update task on ::cancel + elif method_name.endswith("::cancel"): + params = request.get("params", {}) if isinstance(request, dict) else {} + task_id = params.get("task_id") if isinstance(params, dict) else None + if task_id is not None: + base_name = self._base_task_name(method_name) + key = self._make_task_key(instance.name, base_name, task_id) + ti = getattr(self, "task_registry", {}).get(key) + if ti: + ti.cancel_request = request + ti.cancel_response = response + except Exception: + pass + + def _ensure_task_for_status(self, instance: KDFInstance, request: Dict[str, Any], timeout: int) -> Dict[str, Any]: + """Ensure there is a valid task before querying ::status. + - If task_id missing or unknown, try to start one via matching ::init using example params. + - Wait 0.3s after init before returning. + - Override request.params.task_id with a known active id if found. + """ + if not isinstance(request, dict): + return request + method_name = request.get("method", "") + if not (isinstance(method_name, str) and method_name.endswith("::status")): + return request + params = request.setdefault("params", {}) if isinstance(request, dict) else {} + task_id = params.get("task_id") if isinstance(params, dict) else None + base_name = self._base_task_name(method_name) + chosen = self._find_active_task_for_base(instance.name, base_name) + # Use task from registry if available + if chosen and isinstance(params, dict): + params["task_id"] = chosen.task_id + created_at = getattr(chosen, "created_at", None) + if isinstance(created_at, (int, float)): + elapsed = time.time() - created_at + if elapsed < 0.3: + time.sleep(round(0.3 - elapsed, 3)) + return request + # Otherwise, attempt to start a fresh task via ::init (based on examples) + init_method = method_name.replace("::status", "::init") + init_params = self._find_example_params_for_method(init_method) or {} + # Best-effort: disable coin ahead of init if we can find ticker + try: + ticker_for_init = None + if isinstance(init_params, dict): + ticker_for_init = init_params.get("ticker") or init_params.get("coin") + if isinstance(ticker_for_init, str) and ticker_for_init: + ticker_upper = str(ticker_for_init).upper() + for _ in range(2): + if self._is_coin_enabled(instance, ticker_upper): + self.disable_coin(instance, ticker_upper) + time.sleep(0.5) + else: + break + except Exception: + pass + init_request = { + "userpass": instance.userpass, + "mmrpc": "2.0", + "method": init_method, + "params": init_params, + "id": 0 + } + _outcome, init_resp = self.send_request(instance, init_request, timeout, allow_retry=False) + new_task_id = None + if isinstance(init_resp, dict): + result = init_resp.get("result") + if isinstance(result, dict): + new_task_id = result.get("task_id") + if new_task_id is not None and isinstance(params, dict): + time.sleep(0.3) + params["task_id"] = new_task_id + return request + + def _find_example_params_for_method(self, method_name: str) -> Optional[Dict[str, Any]]: + """Find example params for a given method by scanning request definition files.""" + try: + # Prefer v2 requests + v2_requests_dir = self.workspace_root / "src/data/requests/kdf/v2" + legacy_requests_dir = self.workspace_root / "src/data/requests/kdf/legacy" + for req_dir in [v2_requests_dir, legacy_requests_dir]: + if not req_dir.exists(): + continue + for request_file in req_dir.glob("*.json"): + try: + requests_data = self.load_json_file(request_file) or {} + if isinstance(requests_data, dict): + for _key, req in requests_data.items(): + if not isinstance(req, dict): + continue + if req.get("method") == method_name: + params = req.get("params") + return params if isinstance(params, dict) else {} + except Exception: + continue + except Exception: + return None + return None + + def _is_expected_error(self, text: str, instance: KDFInstance, method_name: str) -> bool: + """Check if the response is an expected error.""" + expected_error = None + if instance.name.endswith("-nonhd"): + if "not supported if the coin is initialized with an Iguana private key" in text: + return "Iguana not supported" + + elif instance.name.endswith("-hd"): + # TODO: Use example name to tag where HD/nonHD param set + if method_name == "withdraw" and "Request should contain a 'from' address/account" in text: + return "HD withdraw request without 'from' address/account" + if "is deprecated for HD wallets" in text: + return "HD wallet is deprecated" + + if "Error parsing the native wallet configuration" in text: + return "Native wallet configuration error (no local blockchain data" + for i in [ + "UnexpectedDerivationMethod", + "SingleAddress", + ]: + if i in text: + return i + return None + + + def _filter_request_data(self, request_data: Dict[str, Any]) -> Dict[str, Any]: + """Filter out metadata fields from request data before sending to API.""" + metadata_fields = {'tags', 'prerequisites'} + return {k: v for k, v in request_data.items() if k not in metadata_fields} + + def _extract_ticker_from_request(self, request_data: Dict[str, Any]) -> Optional[str]: + """Extract ticker/coin from request data.""" + # Look for ticker in params + if "params" in request_data: + params = request_data["params"] + if isinstance(params, dict): + if "ticker" in params: + return params["ticker"] + elif "coin" in params: + return params["coin"] + + # Look for ticker at root level + if "ticker" in request_data: + return request_data["ticker"] + elif "coin" in request_data: + return request_data["coin"] + + return None + + def _ensure_coin_activated(self, instance: KDFInstance, ticker: str, + force_enable_platform: bool = False, + force_reenable: bool = False): + """Ensure a coin is activated using the ActivationManager. + + force_enable_platform: when True, allows enabling platform coins like ETH/IRIS + force_reenable: when True and coin appears enabled, disable then activate again + """ + if not ticker: + return {"success": True, "already_enabled": True} + + ticker_upper = str(ticker).upper() + + # Skip platform coins unless forced from retry logic + if not force_enable_platform and ticker_upper in ["ETH", "IRIS"]: + return {"success": True, "already_enabled": True} + + # Get the activation manager for this instance + activation_manager = self.activation_managers.get(instance.name) + if not activation_manager: + error_msg = f"No activation manager found for instance {instance.name}" + self.logger.error(error_msg) + return {"success": False, "error": error_msg} + + # Check if coin is already enabled + if activation_manager.is_coin_enabled(ticker_upper): + if force_reenable: + self.logger.info(f"๐Ÿ”„ Re-enabling {ticker_upper} on {instance.name} due to prior error") + self.disable_coin(instance, ticker_upper) + else: + self.logger.info(f"Coin {ticker_upper} is already enabled on {instance.name}") + return {"success": True, "already_enabled": True} + + try: + # Determine if this is a token + is_token, parent_coin = self.coins_config.is_token(ticker_upper) + enable_hd = "-hd" in instance.name.lower() and "nonhd" not in instance.name.lower() + + if is_token: + self.logger.info(f"Activating token {ticker_upper} on {instance.name}") + result = activation_manager.activate_token(ticker_upper, enable_hd=enable_hd) + else: + self.logger.info(f"Activating coin {ticker_upper} on {instance.name}") + result = activation_manager.activate_coin( + ticker_upper, + enable_hd=enable_hd, + wait_for_completion=True + ) + + if result.success: + self.logger.info(f"Successfully activated {ticker_upper} on {instance.name}") + return {"success": True, "result": result} + else: + self.logger.warning(f"Failed to activate {ticker_upper} on {instance.name}: {result.error}") + return {"success": False, "error": result.error, "response": result.response} + + except Exception as e: + error_msg = f"Error activating {ticker_upper} on {instance.name}: {e}" + self.logger.error(error_msg) + return {"success": False, "error": error_msg} + + def _is_coin_enabled(self, instance: KDFInstance, ticker: str) -> bool: + """Check if a coin is enabled using appropriate get_enabled_coins method.""" + if not ticker: + return False + + try: + # Determine which version of get_enabled_coins to use based on HD detection + enable_hd = "-hd" in instance.name.lower() and "nonhd" not in instance.name.lower() + + if enable_hd: + # HD wallet - use v2 API + request = { + "userpass": instance.userpass, + "mmrpc": "2.0", + "method": "get_enabled_coins" + } + else: + # Non-HD wallet - use v1 API + request = { + "userpass": instance.userpass, + "method": "get_enabled_coins" + } + + outcome, response = self.send_request(instance, request) + + if outcome == Outcome.SUCCESS and "result" in response: + result = response["result"] + ticker_upper = ticker.upper() + + # Handle v2 response format (HD wallets) + if isinstance(result, dict) and "coins" in result: + for coin in result["coins"]: + if isinstance(coin, dict) and coin.get("ticker", "").upper() == ticker_upper: + return True + elif isinstance(coin, str) and coin.upper() == ticker_upper: + return True + # Handle v1 response format (non-HD wallets) + elif isinstance(result, list): + for coin in result: + if isinstance(coin, dict) and coin.get("ticker", "").upper() == ticker_upper: + return True + elif isinstance(coin, str) and coin.upper() == ticker_upper: + return True + + return False + else: + self.logger.info(f"Failed to get enabled coins for {instance.name}: {response}") + return False + + except Exception as e: + self.logger.info(f"Error checking if {ticker} is enabled on {instance.name}: {e}") + return False + + def disable_coin(self, instance: KDFInstance, ticker: str) -> bool: + """Simple coin disable using disable_coin method.""" + disable_request = { + "userpass": instance.userpass, + "method": "disable_coin", + "coin": ticker + } + + outcome, response = self.send_request(instance, disable_request) + + if outcome == Outcome.SUCCESS: + self.logger.info(f"Successfully disabled {ticker} on {instance.name}") + return True + else: + # Check if it's already disabled (expected case) + if isinstance(response, dict): + error_msg = str(response.get("error", "")).lower() + if any(phrase in error_msg for phrase in [ + "not found", "not enabled", "is not activated", "not active", + "no such coin", "coin not found" + ]): + self.logger.info(f"{ticker} was not enabled on {instance.name}") + return True + + self.logger.warning(f"Failed to disable {ticker} on {instance.name}: {response}") + return False + + def normalize_request_for_non_hd(self, request_data: Dict[str, Any]) -> Dict[str, Any]: + """Modify request to work with non-HD wallets by removing HD-specific parameters.""" + request_copy = request_data.copy() + + # Remove HD-specific parameters from activation_params + if "params" in request_copy and "activation_params" in request_copy["params"]: + activation_params = request_copy["params"]["activation_params"] + + # Remove HD wallet specific fields + hd_fields = ["path_to_address", "gap_limit", "scan_policy", "min_addresses_number"] + for field in hd_fields: + activation_params.pop(field, None) + + + return request_copy + + def collect_regular_method(self, response_name: str, request_data: Dict[str, Any], + method_name: str) -> CollectionResult: + """Collect responses for regular (non-task) methods.""" + instance_responses = {} + all_passed = True + consistent_structure = True + first_response_structure = None + + # Extract ticker from request data + ticker = self._extract_ticker_from_request(request_data) + # Load test data if available + if self.test_data is None: + try: + with open(self.workspace_root / "postman/generated/reports/test_data.json", "r", encoding="utf-8") as f: + self.test_data = json.load(f) + except Exception: + self.test_data = {} + + for instance in KDF_INSTANCES: + # Ensure coin is activated if needed + if ticker: + # Check if this is an activation method + method_name_check = request_data.get("method", "") + is_activation_method = any(activation_term in method_name_check.lower() for activation_term in [ + "enable", "activate", "init", "electrum" + ]) + + if is_activation_method: + # For activation methods, check if coin is enabled first, then disable + # self.logger.info(f"๐Ÿ”„ Checking if {ticker} is enabled on {instance.name} before disabling") + if self._is_coin_enabled(instance, ticker): + self.logger.info(f"๐Ÿ”„ Pre-disabling {ticker} on {instance.name} before activation") + self.disable_coin(instance, ticker) + time.sleep(1.0) # Allow time for disable to complete + else: + # For other methods, ensure coin is activated + activation_result = self._ensure_coin_activated(instance, ticker) + if not activation_result["success"]: + self.logger.warning(f"Skipping {response_name} on {instance.name} - Could not activate {ticker}") + all_passed = False + + error_response = { + "error": f"Failed to activate coin {ticker}", + "error_type": "CoinActivationFailed" + } + + if activation_result.get("error"): + error_response["activation_error"] = activation_result["error"] + if activation_result.get("response"): + error_response["activation_response"] = activation_result["response"] + + instance_responses[instance.name] = error_response + continue + + # Modify request for non-HD instances + if "nonhd" in instance.name: + modified_request = self.normalize_request_for_non_hd(request_data) + else: + modified_request = request_data + # Apply test-data overrides for known examples (e.g., my_tx_history from_id) + try: + if isinstance(modified_request, dict): + # Deep copy to avoid mutating shared dict + import copy + modified_request = copy.deepcopy(modified_request) + method = modified_request.get("method", "") + if method == "my_tx_history": + # Override legacy from_id if available + inst_data = (self.test_data or {}).get(instance.name, {}) + coin_key = (ticker or "").upper() + known = None + # Prefer address-mapped txid if present + addresses = inst_data.get(coin_key, {}).get("addresses", {}) if isinstance(inst_data, dict) else {} + if isinstance(addresses, dict) and addresses: + # pick first address in report for this coin + addr_key = sorted(addresses.keys())[0] + txids = addresses.get(addr_key, {}).get("known_txids", []) + if isinstance(txids, list) and len(txids) > 0: + known = txids[0] + if known: + if "from_id" in modified_request: + modified_request["from_id"] = known + # Also support v2-style paging_options.FromId if seen under legacy by mistake + if "paging_options" in modified_request and isinstance(modified_request["paging_options"], dict): + modified_request["paging_options"]["FromId"] = known + except Exception: + pass + + # Set up timing context and send request + self._current_timing_context = {} + timeout = self._get_method_timeout(method_name) + # Set request context for reporting + self._current_request_key = response_name + self._current_method_name = method_name + outcome, response = self.send_request(instance, modified_request, timeout) + + # Record timing information + timing_info = getattr(self, '_current_timing_context', {}) + if timing_info: + self._record_response_delay( + method_name, response_name, instance.name, + timing_info.get('status_code', 500), + timing_info.get('delay', 0.0) + ) + + instance_responses[instance.name] = response + + if not (outcome == Outcome.SUCCESS or outcome == Outcome.EXPECTED_ERROR): + all_passed = False + else: + if first_response_structure is None: + first_response_structure = self._get_response_structure(response) + elif self._get_response_structure(response) != first_response_structure: + consistent_structure = False + + # Auto-updatable if we have successful responses + successful_responses = {k: v for k, v in instance_responses.items() if "error" not in v} + auto_updatable = len(successful_responses) > 0 + + # Record inconsistencies if any (mixed outcomes or structure differences) + self._maybe_record_inconsistency( + response_name=response_name, + method_name=method_name, + instance_responses=instance_responses, + consistent_structure=consistent_structure, + ) + + return CollectionResult( + response_name=response_name, + instance_responses=instance_responses, + all_passed=all_passed, + consistent_structure=consistent_structure, + auto_updatable=auto_updatable, + collection_method="regular", + notes=f"Method: {method_name}", + original_request=request_data + ) + + def _record_expected_error(self, method_name: str, instance_name: str, status_code: int, + response_data: Dict[str, Any], request_data: Dict[str, Any]) -> None: + """Record an expected error for reporting. + + Stores expected errors grouped by method -> example(request_key) -> instance. + """ + try: + request_key = self._current_request_key or method_name + if method_name not in self.expected_error_responses: + self.expected_error_responses[method_name] = {} + if request_key not in self.expected_error_responses[method_name]: + self.expected_error_responses[method_name][request_key] = {} + + # Extract a concise error summary + error_entry: Dict[str, Any] = { + "status_code": status_code, + } + if isinstance(response_data, dict): + # Copy common error fields if present + for key in ["error", "error_type", "error_path", "error_trace", "raw_response"]: + if key in response_data: + error_entry[key] = response_data[key] + # Store minimal request context for debugging + error_entry["request"] = { + "method": method_name, + "request_key": request_key, + } + + self.expected_error_responses[method_name][request_key][instance_name] = error_entry + except Exception as e: + # Do not let reporting failures affect collection flow + self.logger.warning(f"Failed to record expected error for {method_name} on {instance_name}: {e}") + + def _classify_instance_outcome(self, instance_name: str, method_name: str, request_key: str, + response: Dict[str, Any]) -> str: + """Classify outcome for a single instance as 'success', 'expected_error', or 'failure'.""" + if isinstance(response, dict) and "error" not in response: + return "success" + + # Check if this response was recorded as expected + method_map = self.expected_error_responses.get(method_name, {}) + example_map = method_map.get(request_key, {}) + if instance_name in example_map: + return "expected_error" + + return "failure" + + def _maybe_record_inconsistency(self, response_name: str, method_name: str, + instance_responses: Dict[str, Any], + consistent_structure: bool) -> None: + """Detect and record inconsistencies across environments for a single example. + + Inconsistencies include: + - Presence of failures in any instance + - Inconsistent structure among successful responses only + Expected errors alone should NOT trigger inclusion. + """ + try: + request_key = response_name + # Build outcome categories per instance + categories: Dict[str, str] = {} + for instance_name, resp in instance_responses.items(): + categories[instance_name] = self._classify_instance_outcome( + instance_name, method_name, request_key, resp if isinstance(resp, dict) else {} + ) + + reasons: List[str] = [] + + # Include if any failure is present (unexpected) + has_failure = any(outcome == "failure" for outcome in categories.values()) + if has_failure: + reasons.append("mixed_outcomes") + + # Structure inconsistency: compare ONLY successful responses + success_structures: List[str] = [] + for instance_name, resp in instance_responses.items(): + if categories.get(instance_name) == "success" and isinstance(resp, dict): + success_structures.append(self._get_response_structure(resp)) + if len(success_structures) >= 2 and len(set(success_structures)) > 1: + reasons.append("inconsistent_structure") + + # Do NOT include if the only differences are success vs expected_error + if reasons: + if response_name not in self.inconsistent_responses: + self.inconsistent_responses[response_name] = {} + self.inconsistent_responses[response_name] = { + "method": method_name, + "reasons": reasons, + "outcomes": categories, + "instances": instance_responses, + } + except Exception as e: + self.logger.warning(f"Failed to evaluate inconsistency for {response_name}: {e}") + + def _get_method_timeout(self, method_name: str) -> int: + """Get appropriate timeout for a method.""" + # Load method config to check for specific timeout (v2 preferred over legacy) + data_dir = self.workspace_root / "src/data" + files = [data_dir / "kdf_methods_legacy.json", data_dir / "kdf_methods_v2.json"] + kdf_methods = {} + # Load legacy first, then v2 to allow v2 to override + for fp in files: + try: + with open(fp, 'r') as f: + kdf_methods.update(json.load(f)) + except Exception: + continue + # No fallback to old single file + + if method_name in kdf_methods: + method_config = kdf_methods[method_name] + if isinstance(method_config, dict) and "timeout" in method_config: + return method_config["timeout"] + + # Default timeout + return 30 + + def _record_response_delay(self, method_name: str, request_key: str, instance_name: str, + status_code: int, delay: float) -> None: + """Record response delay information.""" + if method_name not in self.response_delays: + self.response_delays[method_name] = {} + + if request_key not in self.response_delays[method_name]: + self.response_delays[method_name][request_key] = {} + + self.response_delays[method_name][request_key][instance_name] = { + "status_code": status_code, + "delay": delay + } + + def _get_response_structure(self, response: Dict[str, Any]) -> str: + """Get a simplified structure representation of the response for comparison.""" + if not isinstance(response, dict): + return str(type(response).__name__) + + def simplify_structure(obj): + if isinstance(obj, dict): + result = {} + for k, v in obj.items(): + if k in ["address", "pubkey", "derivation_path", "account_index"]: + result[k] = "" + else: + result[k] = simplify_structure(v) + return result + elif isinstance(obj, list): + if len(obj) > 0: + return [simplify_structure(obj[0])] + return [] + else: + return type(obj).__name__ + + return json.dumps(simplify_structure(response), sort_keys=True) + + def load_json_file(self, file_path: Path) -> Dict[str, Any]: + """Load JSON file and return parsed content.""" + try: + with open(file_path, 'r') as f: + return json.load(f) + except (FileNotFoundError, json.JSONDecodeError) as e: + self.logger.warning(f"Error loading {file_path}: {e}") + return {} + + def _ensure_response_files_exist(self): + """Ensure all response files exist by scanning request files and creating missing response files.""" + self.logger.info("๐Ÿ”ง Ensuring all response files exist...") + + # Check all request files and create corresponding response files if missing + request_dirs = [ + self.workspace_root / "src/data/requests/kdf/v2", + self.workspace_root / "src/data/requests/kdf/legacy" + ] + + files_created = 0 + for request_dir in request_dirs: + if not request_dir.exists(): + continue + + for request_file in request_dir.glob("*.json"): + # Determine corresponding response file + if "v2" in str(request_file): + response_file = self.workspace_root / "src/data/responses/kdf/v2" / request_file.name + else: + response_file = self.workspace_root / "src/data/responses/kdf/legacy" / request_file.name + + if not response_file.exists(): + self.logger.info(f"๐Ÿ“ Creating missing response file: {response_file.relative_to(self.workspace_root)}") + response_file.parent.mkdir(parents=True, exist_ok=True) + + # Load request data to create empty templates + request_data = self.load_json_file(request_file) + if request_data: + empty_response_structure = {} + for request_name in request_data.keys(): + empty_response_structure[request_name] = { + "error": [], + "success": [] + } + + dump_sorted_json(empty_response_structure, response_file) + files_created += 1 + self.logger.info(f"โœ… Created {response_file.name} with {len(empty_response_structure)} method templates") + + if files_created > 0: + self.logger.info(f"๐ŸŽฏ Created {files_created} missing response files") + else: + self.logger.info("๐Ÿ“‹ All response files already exist") + + def save_results(self, results: Dict[str, Any], output_file: Path): + """Save results to output file.""" + output_file.parent.mkdir(parents=True, exist_ok=True) + dump_sorted_json(results, output_file) + self.logger.info(f"Results saved to: {output_file}") + # Also persist method_tasks.json from registry + try: + tasks_serialized: Dict[str, Any] = {} + for key, ti in getattr(self, "task_registry", {}).items(): + try: + entry = { + "task_name": ti.task_name, + "task_id": ti.task_id, + "created_at": getattr(ti, "created_at", None), + "completed": getattr(ti, "completed", False), + "completed_at": getattr(ti, "completed_at", None), + "init_request": ti.init_request, + "init_response": ti.init_response, + "status_responses": ti.status_responses, + "cancel_request": ti.cancel_request, + "cancel_response": ti.cancel_response, + } + tasks_serialized[key] = entry + except Exception: + continue + self.task_report_path.parent.mkdir(parents=True, exist_ok=True) + dump_sorted_json(tasks_serialized, self.task_report_path) + self.logger.info(f"Task report saved to: {self.task_report_path}") + except Exception as e: + self.logger.warning(f"Failed to save task report: {e}") + + def compile_results(self) -> Dict[str, Any]: + """Compile all results into a unified format.""" + unified_results = { + "metadata": { + "collection_timestamp": time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime()), + "total_responses_collected": len(self.results), + "auto_updatable_count": sum(1 for r in self.results if r.auto_updatable), + "collection_summary": { + "regular_methods": sum(1 for r in self.results if r.collection_method == "regular"), + } + }, + "responses": {}, + "auto_updatable": {}, + "manual_review_needed": {} + } + + for result in self.results: + # Add to main responses + response_entry = { + "instances": result.instance_responses, + "all_passed": result.all_passed, + "consistent_structure": result.consistent_structure, + "collection_method": result.collection_method, + "notes": result.notes + } + + # Add original request for manual verification + if hasattr(result, 'original_request') and result.original_request: + response_entry["request"] = result.original_request + + unified_results["responses"][result.response_name] = response_entry + + # Categorize for update processing + if result.auto_updatable: + # Get canonical response (prefer native-hd, then first successful one) + canonical_response = None + + if "native-hd" in result.instance_responses: + hd_response = result.instance_responses["native-hd"] + if "error" not in hd_response: + canonical_response = hd_response + + if canonical_response is None: + canonical_response = next( + (resp for resp in result.instance_responses.values() if "error" not in resp), + None + ) + + if canonical_response: + unified_results["auto_updatable"][result.response_name] = canonical_response + else: + # Analyze why it failed auto-update + reasons = [] + + has_errors = any("error" in resp for resp in result.instance_responses.values()) + if has_errors: + reasons.append("contains_errors") + + if not result.consistent_structure: + reasons.append("inconsistent_structure") + + if not reasons: + reasons.append("unknown") + + # Create detailed entry for manual review + manual_review_entry = { + "reasons": reasons, + "instances": result.instance_responses, + "collection_method": result.collection_method, + "notes": result.notes + } + + if hasattr(result, 'original_request') and result.original_request: + manual_review_entry["request"] = result.original_request + + unified_results["manual_review_needed"][result.response_name] = manual_review_entry + + # Save wallet addresses + wallet_output_file = self.workspace_root / "postman/generated/reports/test_addresses.json" + self.wallet_manager.save_test_addresses_report(wallet_output_file) + # Save expected error report + reports_dir = self.workspace_root / "postman/generated/reports" + self.save_expected_error_responses_report(reports_dir) + + return unified_results + + def validate_responses(self, validate_collected_responses: bool = False) -> Dict[str, Any]: + """Validate existing response files and optionally collected responses.""" + self.logger.info("Starting response validation") + + # For now, return a basic validation structure + # This can be expanded later with proper validation logic + validation_results = { + "existing_files": { + "success": True, + "errors": [], + "warnings": [], + "error_count": 0, + "warning_count": 0, + "sorted_files": {}, + "templated_files": {} + } + } + + if validate_collected_responses and self.results: + validation_results["collected_responses"] = { + "errors": [], + "warnings": [], + "error_count": 0, + "warning_count": 0 + } + + return validation_results + + def save_delay_report(self, output_dir: Path) -> None: + """Save response delay report to separate file.""" + delay_file = output_dir / "kdf_response_delays.json" + + # Add metadata to the delay report + delay_report = { + "metadata": { + "generated_at": time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime()), + "total_methods": len(self.response_delays), + "total_requests": sum(len(examples) for examples in self.response_delays.values()), + "description": "Response timing data for KDF methods across different environments" + }, + "delays": self.response_delays + } + + dump_sorted_json(delay_report, delay_file) + self.logger.info(f"Response delay report saved to: {delay_file}") + + def save_inconsistent_responses_report(self, output_dir: Path) -> None: + """Save inconsistent responses report to separate file.""" + inconsistent_file = output_dir / "inconsistent_responses.json" + + # Initialize empty inconsistent responses if not exists + if not hasattr(self, 'inconsistent_responses'): + self.inconsistent_responses = {} + + # Add metadata to the inconsistent responses report + inconsistent_report = { + "metadata": { + "generated_at": time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime()), + "total_inconsistent_methods": len(self.inconsistent_responses), + "total_inconsistent_examples": sum(len(examples) for examples in self.inconsistent_responses.values()), + "description": "Methods with inconsistent responses across KDF environments" + }, + "inconsistent_responses": self.inconsistent_responses + } + + dump_sorted_json(inconsistent_report, inconsistent_file) + self.logger.info(f"Inconsistent responses report saved to: {inconsistent_file}") + + def save_expected_error_responses_report(self, output_dir: Path) -> None: + """Save expected error responses report to separate file.""" + expected_file = output_dir / "expected_error_responses.json" + report = { + "metadata": { + "generated_at": time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime()), + "total_methods": len(self.expected_error_responses), + "total_examples": sum(len(ex) for ex in self.expected_error_responses.values()), + "description": "Requests that returned expected, acceptable error responses" + }, + "expected_errors": self.expected_error_responses + } + dump_sorted_json(report, expected_file) + self.logger.info(f"Expected error responses report saved to: {expected_file}") + + def rebuild_reports_from_unified(self, unified_report_path: Path, output_dir: Path) -> None: + """Rebuild expected_error_responses.json and inconsistent_responses.json from an existing unified report. + + This is useful when we want to re-derive these reports without re-running collection. + """ + try: + with open(unified_report_path, 'r', encoding='utf-8') as f: + data = json.load(f) + except Exception as e: + self.logger.error(f"Failed to load unified report: {e}") + return + + responses = data.get("responses", {}) if isinstance(data, dict) else {} + self.expected_error_responses = {} + self.inconsistent_responses = {} + + for response_name, entry in responses.items(): + if not isinstance(entry, dict): + continue + method_name = entry.get("notes", "").replace("Method: ", "") or entry.get("method", "") + instance_responses = entry.get("instances", {}) + + # Rebuild expected errors by scanning error responses that match the classifier + for instance_name, resp in instance_responses.items(): + if not isinstance(resp, dict): + continue + if "error" in resp: + text = json.dumps(resp) + if self._is_expected_error(text, instance_name, method_name) is not None: + if method_name not in self.expected_error_responses: + self.expected_error_responses[method_name] = {} + if response_name not in self.expected_error_responses[method_name]: + self.expected_error_responses[method_name][response_name] = {} + self.expected_error_responses[method_name][response_name][instance_name] = { + "status_code": None, + "error": resp.get("error"), + "error_type": resp.get("error_type"), + "error_path": resp.get("error_path"), + "error_trace": resp.get("error_trace"), + "raw_response": resp.get("raw_response") + } + + # Rebuild inconsistency entries based on mixed outcomes and structure flag + consistent_structure = bool(entry.get("consistent_structure", True)) + # Determine categories + categories = {} + for instance_name, resp in instance_responses.items(): + categories[instance_name] = self._classify_instance_outcome( + instance_name, method_name, response_name, resp if isinstance(resp, dict) else {} + ) + reasons = [] + if len(set(categories.values())) > 1: + reasons.append("mixed_outcomes") + if not consistent_structure: + reasons.append("inconsistent_structure") + if reasons: + self.inconsistent_responses[response_name] = { + "method": method_name, + "reasons": reasons, + "outcomes": categories, + "instances": instance_responses, + } + + # Save the rebuilt reports + self.save_expected_error_responses_report(output_dir) + self.save_inconsistent_responses_report(output_dir) + + def regenerate_missing_responses_report(self, reports_dir: Path) -> None: + """Regenerate missing responses split reports after response collection, validating actual response content.""" + self.logger.info("Regenerating missing responses (split) reports...") + # Manual example patterns to skip (require external interaction) + manual_patterns = ["WalletConnect", "Trezor", "Metamask", "UserAction"] + + # Load requests per version + def load_requests(version: str) -> Dict[str, Dict[str, Any]]: + reqs: Dict[str, Dict[str, Any]] = {} + req_dir = self.workspace_root / "src/data/requests/kdf" / version + for request_file in req_dir.glob("*.json"): + reqs.update(self.load_json_file(request_file) or {}) + return reqs + + v2_requests = load_requests("v2") + legacy_requests = load_requests("legacy") + + # Load responses per version into a single dict per version + def load_responses(version: str) -> Dict[str, Any]: + all_responses: Dict[str, Any] = {} + resp_dir = self.workspace_root / "src/data/responses/kdf" / version + for response_file in resp_dir.glob("*.json"): + data = self.load_json_file(response_file) or {} + if isinstance(data, dict): + all_responses.update(data) + # Load common for references if present + common_file = self.workspace_root / "src/data/responses/kdf/common.json" + common = self.load_json_file(common_file) or {} + return {"__all__": all_responses, "__common__": common} + + v2_responses = load_responses("v2") + legacy_responses = load_responses("legacy") + + # Helper to resolve response reference and check if it has any content + def has_response_content(request_key: str, responses_bundle: Dict[str, Any]) -> bool: + all_responses = responses_bundle.get("__all__", {}) + common = responses_bundle.get("__common__", {}) + if request_key not in all_responses: + return False + value = all_responses[request_key] + # Resolve if it's a string reference into common + if isinstance(value, str): + value = common.get(value) + # If it's a list, resolve any string refs inside + if isinstance(value, list): + resolved_list: List[Any] = [] + for item in value: + if isinstance(item, str): + resolved_list.append(common.get(item)) + else: + resolved_list.append(item) + value = resolved_list + # Now, determine content: + if isinstance(value, dict): + success = value.get("success", []) + error = value.get("error", []) + return (isinstance(success, list) and len(success) > 0) or (isinstance(error, list) and len(error) > 0) + # If it's a list of blocks, consider non-empty list as content + if isinstance(value, list): + return len(value) > 0 + return False + + # Load method configs to skip deprecated + data_dir = self.workspace_root / "src/data" + kdf_methods = {} + for fp in [data_dir / "kdf_methods_legacy.json", data_dir / "kdf_methods_v2.json"]: + kdf_methods.update(self.load_json_file(fp) or {}) + + def build_missing(requests: Dict[str, Dict[str, Any]], responses_bundle: Dict[str, Any]) -> Dict[str, List[str]]: + missing: Dict[str, List[str]] = {} + for request_key, request_data in requests.items(): + if not isinstance(request_data, dict): + continue + # Skip manual/external examples + if any(pat in request_key for pat in manual_patterns): + continue + method_name = request_data.get("method", "unknown") + # Skip deprecated methods + method_cfg = kdf_methods.get(method_name, {}) + if method_cfg.get("deprecated", False): + continue + # Check if response exists with content + if not has_response_content(request_key, responses_bundle): + missing.setdefault(method_name, []).append(request_key) + return missing + + missing_v2 = build_missing(v2_requests, v2_responses) + missing_legacy = build_missing(legacy_requests, legacy_responses) + + dump_sorted_json(missing_v2, reports_dir / "missing_responses_v2.json") + dump_sorted_json(missing_legacy, reports_dir / "missing_responses_legacy.json") + self.logger.info("Missing responses split reports regenerated.") + + def update_response_files(self, auto_updatable_responses: Dict[str, Any]) -> int: + """Update response files with successful responses.""" + self.logger.info("Updating response files") + if not auto_updatable_responses: + self.logger.info("No new successful responses to update.") + return 0 + + # Build lookup: request_key -> (version, response_file_path) + mapping: Dict[str, Tuple[str, Path]] = {} + base_requests = self.workspace_root / "src/data/requests/kdf" + for version in ["v2", "legacy"]: + req_dir = base_requests / version + resp_dir = self.workspace_root / "src/data/responses/kdf" / version + if not req_dir.exists(): + continue + for req_file in req_dir.glob("*.json"): + try: + data = self.load_json_file(req_file) or {} + for key in data.keys(): + mapping[key] = (version, resp_dir / req_file.name) + except Exception: + continue + + updated = 0 + for request_key, canonical_response in auto_updatable_responses.items(): + try: + if request_key not in mapping: + self.logger.info(f"Skipping update for {request_key}: request key not found in mapping") + continue + version, resp_path = mapping[request_key] + # Load current response file (create if missing) + if resp_path.exists(): + responses_data = self.load_json_file(resp_path) or {} + else: + responses_data = {} + resp_path.parent.mkdir(parents=True, exist_ok=True) + # Ensure request_key entry exists + entry = responses_data.get(request_key) + if not isinstance(entry, dict): + entry = {"error": [], "success": []} + responses_data[request_key] = entry + success_list = entry.setdefault("success", []) + # Prepare success item + item = {"title": "Success", "json": canonical_response} + # Deduplicate by JSON content + exists = any(isinstance(x, dict) and x.get("json") == canonical_response for x in success_list) + if not exists: + success_list.append(item) + # Save back + dump_sorted_json(responses_data, resp_path) + updated += 1 + self.logger.info(f"โœ… Updated {resp_path.name} with {request_key}") + except Exception as e: + self.logger.warning(f"Failed to update response for {request_key}: {e}") + continue + + self.logger.info(f"Updated response files for {updated} entries") + return updated + + +def main(): + """Main function for the clean response manager.""" + import argparse + + parser = argparse.ArgumentParser(description="Clean KDF Response Manager") + parser.add_argument("--update-files", action="store_true", help="Update response files") + args = parser.parse_args() + + try: + # Initialize manager + manager = KdfResponseManager() + + # For now, just demonstrate with a simple collection + # This would be called by the sequence manager + + print("โœ… Clean Response Manager initialized successfully!") + print(f"Workspace root: {manager.workspace_root}") + print(f"Wallet manager ready: {manager.wallet_manager is not None}") + print(f"Activation managers: {len(manager.activation_managers)}") + + except Exception as e: + print(f"Error: {e}") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/utils/py/lib/managers/sequence_responses_manager.py b/utils/py/lib/managers/sequence_responses_manager.py new file mode 100644 index 000000000..794a29117 --- /dev/null +++ b/utils/py/lib/managers/sequence_responses_manager.py @@ -0,0 +1,406 @@ +#!/usr/bin/env python3 +""" +Sequence-based Response Manager - Advanced KDF response collection with prerequisite handling. + +This manager processes KDF methods in sequence order, handling prerequisites automatically +and providing a cleaner, more maintainable approach to response harvesting. +""" + +import json +import logging +import time +from pathlib import Path +from typing import Dict, List, Optional, Set, Any +from dataclasses import dataclass + +# Import existing components +try: + from .kdf_responses_manager import KdfResponseManager, KDFInstance, KDF_INSTANCES, CollectionResult, Outcome + from ..models.kdf_method import KdfMethod, KdfExample, MethodRequestQueue, KdfMethodsLoader, MethodStatus + from ..utils.json_utils import dump_sorted_json +except ImportError: + # Fall back to absolute imports + import sys + sys.path.append(str(Path(__file__).parent.parent)) + from managers.kdf_responses_manager import KdfResponseManager, KDFInstance, KDF_INSTANCES, CollectionResult, Outcome + from models.kdf_method import KdfMethod, KdfExample, MethodRequestQueue, KdfMethodsLoader, MethodStatus + from utils.json_utils import dump_sorted_json + + +@dataclass +class ProcessingStats: + """Statistics for method processing.""" + total_methods: int = 0 + completed_methods: int = 0 + failed_methods: int = 0 + skipped_methods: int = 0 + prerequisite_cycles: int = 0 + total_examples: int = 0 + successful_examples: int = 0 + + @property + def completion_rate(self) -> float: + """Calculate completion rate as a percentage.""" + if self.total_methods == 0: + return 0.0 + return (self.completed_methods / self.total_methods) * 100 + + @property + def success_rate(self) -> float: + """Calculate example success rate as a percentage.""" + if self.total_examples == 0: + return 0.0 + return (self.successful_examples / self.total_examples) * 100 + + +class SequenceResponseManager(KdfResponseManager): + """Enhanced response manager with sequence-based processing and prerequisite handling.""" + + def __init__(self, workspace_root: Optional[Path] = None): + """Initialize the sequence-based response manager.""" + super().__init__(workspace_root) + + self.method_queue: Optional[MethodRequestQueue] = None + self.processed_prerequisites: Set[str] = set() + self.stats = ProcessingStats() + + # Setup logging + self.logger = logging.getLogger(__name__) + + def load_methods(self) -> MethodRequestQueue: + """Load all KDF methods and create the processing queue.""" + self.logger.info("๐Ÿ”„ Loading KDF methods and creating processing queue...") + + self.method_queue = KdfMethodsLoader.load_from_files(self.workspace_root) + + # Calculate statistics + self.stats.total_methods = len(self.method_queue.methods) + self.stats.total_examples = sum(len(method.examples) for method in self.method_queue.methods.values()) + + self.logger.info(f"๐Ÿ“Š Loaded {self.stats.total_methods} methods with {self.stats.total_examples} total examples") + self.logger.info(f"๐Ÿ” Methods by sequence:") + + # Group methods by sequence for logging + sequence_groups = {} + for method in self.method_queue.methods.values(): + if method.sequence not in sequence_groups: + sequence_groups[method.sequence] = [] + sequence_groups[method.sequence].append(method.name) + + for sequence in sorted(sequence_groups.keys()): + methods_list = sorted(sequence_groups[sequence]) + self.logger.info(f" Sequence {sequence}: {len(methods_list)} methods - {', '.join(methods_list[:3])}{'...' if len(methods_list) > 3 else ''}") + + return self.method_queue + + def process_method_with_prerequisites(self, method: KdfMethod) -> bool: + """Process a method, handling prerequisites automatically.""" + self.logger.info(f"๐ŸŽฏ Processing method: {method.name} (sequence: {method.sequence})") + + # Check if prerequisites need to be processed + unmet_prerequisites = [prereq for prereq in method.prerequisites + if prereq not in self.method_queue.completed_methods] + + if unmet_prerequisites: + self.logger.info(f"๐Ÿ“‹ Method {method.name} has unmet prerequisites: {unmet_prerequisites}") + + # Process each prerequisite + for prereq_name in unmet_prerequisites: + if prereq_name in self.processed_prerequisites: + self.logger.info(f" Prerequisite {prereq_name} already processed this cycle") + continue + + prereq_method = self.method_queue.methods.get(prereq_name) + if prereq_method: + self.logger.info(f"๐Ÿ”„ Processing prerequisite: {prereq_name}") + self.processed_prerequisites.add(prereq_name) + + # Recursively process prerequisite + prereq_success = self.process_method_with_prerequisites(prereq_method) + if prereq_success: + self.method_queue.mark_method_completed(prereq_name) + else: + self.logger.warning(f"โš ๏ธ Prerequisite {prereq_name} failed, but continuing...") + else: + self.logger.warning(f"โš ๏ธ Prerequisite method {prereq_name} not found in queue") + + # Update method's prerequisite status + method.mark_prerequisite_completed(prereq_name) + + # Now process the actual method + return self.process_single_method(method) + + def process_single_method(self, method: KdfMethod) -> bool: + """Process a single method and all its examples.""" + if not method.has_examples: + self.logger.info(f"โšช Skipping {method.name} - no examples available") + self.stats.skipped_methods += 1 + return True + + method.status = MethodStatus.IN_PROGRESS + method_success = True + examples_processed = 0 + examples_successful = 0 + + self.logger.info(f"๐Ÿ“ค Processing {len(method.examples)} examples for {method.name}") + + for example_name, example in method.examples.items(): + try: + # Skip manual methods/examples + if example.is_manual: + self.logger.info(f"โšช Skipping manual method/example: {method.name} ({example_name})") + self.stats.skipped_methods += 1 + continue + # Skip deprecated methods unless explicitly enabled + if method.deprecated: + self.logger.info(f"โšช Skipping deprecated method example: {example_name}") + continue + + self.logger.info(f" ๐Ÿ”„ Processing example: {example_name}") + + # Use the existing collection logic from UnifiedResponseManager + result = self.collect_regular_method(example_name, example.request_data, method.name) + + # Update example with results + if result.all_passed: + example.response_data = result.instance_responses + example.collected = True + examples_successful += 1 + self.logger.info(f" โœ… Example {example_name} succeeded") + else: + example.error_data = result.instance_responses + example.collected = True + method_success = False + self.logger.info(f" โŒ Example {example_name} had errors") + + examples_processed += 1 + + # Store the result in our results collection + self.results.append(result) + + # Skip response file updates for now - will be handled at the end + + # Small delay between examples to avoid overwhelming the API + time.sleep(0.5) + + except Exception as e: + self.logger.error(f"โŒ Error processing example {example_name}: {str(e)}") + example.error_data = {"error": str(e)} + example.collected = True + method_success = False + + # Update statistics + self.stats.successful_examples += examples_successful + + if method_success: + method.status = MethodStatus.COMPLETED + self.stats.completed_methods += 1 + self.logger.info(f"โœ… Method {method.name} completed successfully ({examples_successful}/{examples_processed} examples)") + else: + method.status = MethodStatus.FAILED + self.stats.failed_methods += 1 + self.logger.warning(f"โš ๏ธ Method {method.name} completed with errors ({examples_successful}/{examples_processed} examples)") + + return method_success + + def collect_all_responses_sequenced(self) -> Dict[str, CollectionResult]: + """Main method to collect all responses using sequence-based processing.""" + self.logger.info("๐Ÿš€ Starting sequence-based response collection") + + # Load methods + if not self.method_queue: + self.load_methods() + + # Ensure response files exist (this method exists in the parent class) + self._ensure_response_files_exist() + + # Process methods in sequence order + max_cycles = 10000 # Prevent infinite loops + cycle = 0 + + while cycle < max_cycles: + cycle += 1 + self.stats.prerequisite_cycles = cycle + + # Clear processed prerequisites for this cycle + self.processed_prerequisites.clear() + + # Get next processable method + next_method = self.method_queue.get_next_processable_method() + + if not next_method: + # Check if there are methods waiting for prerequisites + methods_needing_prereqs = self.method_queue.get_methods_needing_prerequisites() + if methods_needing_prereqs: + self.logger.warning(f"๐Ÿ”„ Cycle {cycle}: No processable methods, but {len(methods_needing_prereqs)} methods need prerequisites") + # Try to process them anyway (prerequisites might be external) + for method in methods_needing_prereqs[:3]: # Process up to 3 per cycle + self.logger.info(f"๐Ÿ”„ Attempting method with unmet prerequisites: {method.name}") + success = self.process_single_method(method) + if success: + self.method_queue.mark_method_completed(method.name) + else: + self.method_queue.mark_method_failed(method.name) + continue + else: + self.logger.info(f"โœ… All processable methods completed after {cycle} cycles") + break + + # Process the method + self.logger.info(f"๐Ÿ”„ Cycle {cycle}: Processing {next_method.name}") + success = self.process_method_with_prerequisites(next_method) + + if success: + self.method_queue.mark_method_completed(next_method.name) + else: + self.method_queue.mark_method_failed(next_method.name) + + # Log progress + if cycle % 5 == 0 or self.method_queue.pending_count <= 5: + pending = self.method_queue.pending_count + completed = self.method_queue.completed_count + failed = self.method_queue.failed_count + self.logger.info(f"๐Ÿ“Š Progress: {completed} completed, {failed} failed, {pending} pending") + + if cycle >= max_cycles: + self.logger.warning(f"โš ๏ธ Reached maximum cycles ({max_cycles}), stopping processing") + + # Final statistics + self.log_final_statistics() + + # Save collected addresses using wallet manager + wallet_output_file = self.workspace_root / "postman/generated/reports/test_addresses.json" + self.wallet_manager.save_test_addresses_report(wallet_output_file) + + # Fetch and log KDF version (prefer report extraction, no extra RPC) + kdf_version = self.get_kdf_version_from_report() or self.get_kdf_version() + if kdf_version: + self.logger.info(f"Completed collecting responses from KDF version {kdf_version}") + else: + self.logger.info("Completed collecting responses (KDF version unknown)") + + return self.results + + def log_final_statistics(self): + """Log comprehensive final statistics.""" + self.logger.info("๐Ÿ“Š Final Processing Statistics:") + self.logger.info(f" Total Methods: {self.stats.total_methods}") + self.logger.info(f" โœ… Completed: {self.stats.completed_methods} ({self.stats.completion_rate:.1f}%)") + self.logger.info(f" โŒ Failed: {self.stats.failed_methods}") + self.logger.info(f" โšช Skipped: {self.stats.skipped_methods}") + self.logger.info(f" ๐Ÿ”„ Prerequisite Cycles: {self.stats.prerequisite_cycles}") + self.logger.info(f" ๐Ÿ“ค Total Examples: {self.stats.total_examples}") + self.logger.info(f" โœ… Successful Examples: {self.stats.successful_examples} ({self.stats.success_rate:.1f}%)") + + # Address collection summary + wallet_summary = self.wallet_manager.get_summary() + self.logger.info(f" ๐Ÿฆ Addresses Collected: {wallet_summary['total_addresses']} across {wallet_summary['total_instances']} environments") + + # Save processing statistics + stats_file = self.workspace_root / "postman/generated/reports/processing_stats.json" + stats_data = { + "total_methods": self.stats.total_methods, + "completed_methods": self.stats.completed_methods, + "failed_methods": self.stats.failed_methods, + "skipped_methods": self.stats.skipped_methods, + "prerequisite_cycles": self.stats.prerequisite_cycles, + "total_examples": self.stats.total_examples, + "successful_examples": self.stats.successful_examples, + "completion_rate": self.stats.completion_rate, + "success_rate": self.stats.success_rate, + "kdf_version": getattr(self, 'last_kdf_version', None), + "addresses_collected": wallet_summary['total_addresses'], + "environments": wallet_summary['total_instances'] + } + + dump_sorted_json(stats_data, stats_file) + self.logger.info(f"๐Ÿ“ˆ Processing statistics saved to {stats_file}") + + +def main(): + """Main function for running the sequence-based response manager.""" + import argparse + import logging + + parser = argparse.ArgumentParser(description="KDF Sequence-based Response Manager") + parser.add_argument( + "--update-files", + action="store_true", + help="Automatically update response files with successful responses" + ) + + args = parser.parse_args() + + # Setup logging + logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s' + ) + + # Find workspace root + current_dir = Path(__file__).parent + workspace_root = current_dir + while workspace_root.name != "komodo-docs-mdx" and workspace_root.parent != workspace_root: + workspace_root = workspace_root.parent + + if workspace_root.name != "komodo-docs-mdx": + raise RuntimeError("Could not find workspace root (komodo-docs-mdx)") + + # Create and run the manager + manager = SequenceResponseManager(workspace_root) + + try: + results = manager.collect_all_responses_sequenced() + logging.info(f"๐ŸŽ‰ Collection completed successfully! Processed {len(results)} method examples") + + # Compile results into the unified format + unified_results = manager.compile_results() + + # Always validate both existing and collected responses + validation_results = manager.validate_responses(validate_collected_responses=True) + unified_results["validation"] = validation_results + + # Save results + output_file = manager.workspace_root / "postman/generated/reports/kdf_postman_responses.json" + manager.save_results(unified_results, output_file) + + # Save delay report + reports_dir = manager.workspace_root / "postman/generated/reports" + manager.save_delay_report(reports_dir) + + # Save inconsistent responses report + manager.save_inconsistent_responses_report(reports_dir) + + # Regenerate missing responses report after response collection + manager.regenerate_missing_responses_report(reports_dir) + + # Print collection summary + metadata = unified_results.get("metadata", {}) + logging.info(f"๐Ÿ“Š Total responses collected: {metadata.get('total_responses_collected', 0)}") + logging.info(f"๐Ÿ“Š Auto-updatable responses: {metadata.get('auto_updatable_count', 0)}") + logging.info(f"๐Ÿ“Š Inconsistent responses: {len(manager.inconsistent_responses)}") + logging.info(f"๐Ÿ“Š Manual review needed: {len(unified_results.get('manual_review_needed', {}))}") + logging.info(f"๐Ÿ“„ Results saved to: {output_file}") + # Final KDF version log + kdf_version = manager.get_kdf_version() + if kdf_version: + logging.info(f"Completed collecting responses from KDF version {kdf_version}") + else: + logging.info("Completed collecting responses (KDF version unknown)") + + # Update response files if requested + if args.update_files: + updated_count = manager.update_response_files(unified_results.get("auto_updatable", {})) + logging.info(f"๐Ÿ“„ Updated response files with {updated_count} new responses") + + except KeyboardInterrupt: + logging.info("โš ๏ธ Collection interrupted by user") + manager.log_final_statistics() + + except Exception as e: + logging.error(f"โŒ Collection failed: {str(e)}") + raise + + +if __name__ == "__main__": + main() diff --git a/utils/py/lib/managers/table_manager.py b/utils/py/lib/managers/table_manager.py new file mode 100644 index 000000000..2e396d261 --- /dev/null +++ b/utils/py/lib/managers/table_manager.py @@ -0,0 +1,556 @@ +#!/usr/bin/env python3 +""" +Table Manager - Centralized table operations for KDF API documentation + +This module provides a unified interface for: +- Loading and managing table definitions +- Validating parameter structures against tables +- Tracking missing table references +- Generating table-based documentation +""" + +import json +import logging +from pathlib import Path +from typing import Dict, Set, List, Optional, Any, Tuple +from dataclasses import dataclass + +# Add lib path for utilities +import sys +sys.path.append(str(Path(__file__).parent.parent)) +from utils.json_utils import dump_sorted_json + + +@dataclass +class TableReference: + """Represents a table reference with type and status.""" + table_name: str + table_type: str # 'request', 'response', 'error' + method_name: str + exists: bool = False + is_na: bool = False # True if table_name is "N/A" + is_empty: bool = False # True if table_name is "" + + +@dataclass +class ValidationResult: + """Result of parameter validation against a table.""" + method: str + table_name: str + unused_params: Set[str] + missing_params: Set[str] + valid_params: Set[str] + request_params: Set[str] + table_params: Set[str] + dot_params: Set[str] + + +class TableManager: + """Centralized manager for all table-related operations.""" + + def __init__(self, workspace_root: Optional[Path] = None, logger: Optional[logging.Logger] = None): + """Initialize the table manager. + + Args: + workspace_root: Path to the workspace root. If None, auto-detects. + logger: Logger instance. If None, creates a new one. + """ + if workspace_root is None: + workspace_root = Path(__file__).parent.parent.parent.parent + + self.workspace_root = Path(workspace_root) + self.tables_dir = self.workspace_root / "src" / "data" / "tables" + self.logger = logger or logging.getLogger(__name__) + + # Cache for loaded tables + self._tables_cache: Optional[Dict[str, Dict]] = None + # Track which source each table came from: 'legacy' | 'v2' | 'common' + self._table_sources: Dict[str, set] = {} + + # Missing table tracking + self.missing_tables = { + "missing_request_tables": [], + "missing_response_tables": [], + "missing_error_tables": [] + } + + def load_json_file(self, file_path: Path) -> Optional[Dict]: + """Load JSON file and return its content.""" + try: + with open(file_path, 'r', encoding='utf-8') as f: + return json.load(f) + except FileNotFoundError: + self.logger.warning(f"Table file not found: {file_path}") + return None + except json.JSONDecodeError as e: + self.logger.error(f"Invalid JSON in table file {file_path}: {e}") + return None + + def load_all_tables(self, force_reload: bool = False) -> Dict[str, Dict]: + """Load all table files and combine them. + + Args: + force_reload: If True, bypass cache and reload from disk. + + Returns: + Dictionary mapping table names to table definitions. + """ + if not force_reload and self._tables_cache is not None: + return self._tables_cache + + all_tables = {} + + # Load common structures + common_dir = self.tables_dir / "common-structures" + if common_dir.exists(): + for table_file in common_dir.glob("*.json"): + tables = self.load_json_file(table_file) + if tables: + all_tables.update(tables) + # record sources + for key in tables.keys(): + self._table_sources.setdefault(key, set()).add("common") + self.logger.info(f"Loaded {len(tables)} tables from {table_file}") + + # Load version-specific tables + for version_dir in ["legacy", "v2"]: + version_path = self.tables_dir / version_dir + if version_path.exists(): + for table_file in version_path.glob("*.json"): + tables = self.load_json_file(table_file) + if tables: + all_tables.update(tables) + # record sources + for key in tables.keys(): + self._table_sources.setdefault(key, set()).add(version_dir) + self.logger.info(f"Loaded {len(tables)} tables from {table_file}") + + self._tables_cache = all_tables + self.logger.info(f"Loaded {len(all_tables)} total table definitions") + + return all_tables + + def get_table_source(self, table_name: str) -> Optional[set]: + """Return the source set of a table key: {'legacy','v2','common'} or None.""" + # Ensure cache is populated + if self._tables_cache is None: + self.load_all_tables() + return self._table_sources.get(table_name) + + def get_table_reference(self, method_config: Dict[str, Any], table_type: str) -> TableReference: + """Get a table reference for a specific method and table type. + + Args: + method_config: Method configuration from kdf_methods.json + table_type: Type of table ('request', 'response', 'error') + + Returns: + TableReference object with metadata about the table reference. + """ + # Map table types to field names + field_mapping = { + 'request': 'request_table', + 'response': 'response_table', + 'error': 'errors_table' + } + + field_name = field_mapping.get(table_type) + if not field_name: + raise ValueError(f"Invalid table type: {table_type}") + + # Get table name from method config (with fallback for old 'table' field) + table_name = method_config.get(field_name) + if not table_name and table_type == 'request': + # Fallback to old 'table' field for backward compatibility + table_name = method_config.get('table', '') + + if not table_name: + table_name = '' + + method_name = method_config.get('method_name', 'unknown') + + return TableReference( + table_name=table_name, + table_type=table_type, + method_name=method_name, + exists=False, # Will be set by check_table_exists + is_na=(table_name == "N/A"), + is_empty=(table_name == "") + ) + + def check_table_exists(self, table_ref: TableReference) -> TableReference: + """Check if a table reference exists in the loaded tables. + + Args: + table_ref: TableReference to check + + Returns: + Updated TableReference with exists field set correctly. + """ + if table_ref.is_na or table_ref.is_empty: + table_ref.exists = False + return table_ref + + tables = self.load_all_tables() + table_ref.exists = table_ref.table_name in tables + + return table_ref + + def track_missing_table(self, method_name: str, table_type: str) -> None: + """Track a missing table by type. + + Args: + method_name: Name of the method missing the table + table_type: Type of table missing ('request', 'response', 'error') + """ + category_key = f"missing_{table_type}_tables" + if category_key in self.missing_tables: + if method_name not in self.missing_tables[category_key]: + self.missing_tables[category_key].append(method_name) + self.logger.info(f"Tracked missing {table_type} table for {method_name}") + + def validate_method_tables(self, method_name: str, method_config: Dict[str, Any]) -> List[TableReference]: + """Validate all table references for a method. + + Args: + method_name: Name of the method + method_config: Method configuration from kdf_methods.json + + Returns: + List of TableReference objects for all table types. + """ + results = [] + + # Add method name to config for reference tracking + method_config = method_config.copy() + method_config['method_name'] = method_name + + # Check all table types + for table_type in ['request', 'response', 'error']: + table_ref = self.get_table_reference(method_config, table_type) + table_ref = self.check_table_exists(table_ref) + + # Track missing tables (excluding N/A and deprecated methods) + if not table_ref.exists and not table_ref.is_na: + is_deprecated = method_config.get('deprecated', False) + if not is_deprecated: + if table_ref.is_empty: + self.track_missing_table(method_name, table_type) + elif table_ref.table_name: # Non-empty, non-N/A but doesn't exist + self.track_missing_table(method_name, table_type) + self.logger.warning(f"Table {table_ref.table_name} not found for method {method_name}") + + results.append(table_ref) + + return results + + def validate_request_params(self, request_data: Dict, method_name: str, method_config: Dict[str, Any]) -> Optional[ValidationResult]: + """Validate request parameters against table definitions. + + Args: + request_data: Request data to validate + method_name: Name of the method + method_config: Method configuration from kdf_methods.json + + Returns: + ValidationResult object or None if validation cannot be performed. + """ + # Get request table reference + table_ref = self.get_table_reference(method_config, 'request') + table_ref = self.check_table_exists(table_ref) + + if not table_ref.exists or table_ref.is_na: + return None + + tables = self.load_all_tables() + table_data = tables[table_ref.table_name] + + # Extract table parameters and expand substructures for object params + table_params: Set[str] = set() + dot_params_from_table: Set[str] = set() + for param_def in table_data.get("data", []): + param_name = param_def.get("parameter") + if not isinstance(param_name, str): + continue + table_params.add(param_name) + if "." in param_name: + dot_params_from_table.add(param_name) + # Expand common-structure subparams if declared/inferable and type is object + if str(param_def.get("type", "")).lower() == "object": + parent = param_name + substruct_path = param_def.get("substructure") or self._infer_substructure_from_description(param_def.get("description", "")) + if substruct_path: + for child in self._load_common_structure_params(substruct_path): + dotted = f"{parent}.{child}" + table_params.add(dotted) + dot_params_from_table.add(dotted) + + # Extract request parameters + request_params = set() + params_data = request_data.get("params") + + # If explicit params object exists, use it (v2 structure) + if isinstance(params_data, dict): + if "activation_params" in params_data: + # Add top-level params + for key in params_data.keys(): + if key != "activation_params": + request_params.add(key) + # Extract nested parameters with proper prefix so dotted names are captured + self._extract_param_names(params_data["activation_params"], request_params, prefix="activation_params") + else: + self._extract_param_names(params_data, request_params) + else: + # Legacy structure: parameters are at the top level of request_data + # Exclude non-parameter control fields + excluded_keys = {"method", "userpass"} + legacy_params: Dict[str, Any] = {} + for k, v in request_data.items(): + if k not in excluded_keys: + legacy_params[k] = v + self._extract_param_names(legacy_params, request_params) + + # Normalize: ensure parent keys are counted when nested keys are present + # e.g., if 'activation_params.priv_key_policy' exists, include 'activation_params' + parent_keys: Set[str] = set() + for param in list(request_params): + if '.' in param: + parts = param.split('.') + for i in range(1, len(parts)): + parent_keys.add('.'.join(parts[:i])) + if parent_keys: + request_params.update(parent_keys) + + # Build a set of leaf names from request params for matching non-dotted table params + request_leaf_names: Set[str] = set() + for param in request_params: + leaf = param.split('.')[-1] + request_leaf_names.add(leaf) + + # Calculate validation results with refined rules: + # - Non-dotted table params are considered used if present directly OR as a leaf under any dotted path + # - Dotted table params are considered used if any request path ends with the dotted param (suffix match) + valid_params: Set[str] = set() + for tp in table_params: + if '.' in tp: + # consider parent dotted param used if any request key is nested under it + if any(rp == tp or rp.startswith(f"{tp}.") for rp in request_params): + valid_params.add(tp) + else: + if tp in request_params or tp in request_leaf_names: + valid_params.add(tp) + + unused_params = table_params - valid_params + missing_params = request_params - table_params + + return ValidationResult( + method=method_name, + table_name=table_ref.table_name, + unused_params=unused_params, + missing_params=missing_params, + valid_params=valid_params, + request_params=request_params, + table_params=table_params, + dot_params=dot_params_from_table + ) + + def _infer_substructure_from_description(self, description: str) -> Optional[str]: + """Infer substructure path from markdown link in description. + Example: ...(/komodo-defi-framework/api/common_structures/wallet/#priv-key-policy)... -> wallet.PrivKeyPolicy + """ + if not isinstance(description, str): + return None + if "/common_structures/" not in description: + return None + try: + # Extract segment like common_structures//# + start = description.index("/common_structures/") + len("/common_structures/") + tail = description[start:] + # file segment up to next '/' + file_seg = tail.split('/', 1)[0] + # anchor after '#' + anchor = None + if '#"' in tail: + anchor = tail.split('#"', 1)[1].split('"', 1)[0] + elif '#' in tail: + anchor = tail.split('#', 1)[1].split(')', 1)[0] + if not file_seg or not anchor: + return None + # Convert kebab/underscore to PascalCase + parts = [p for p in anchor.replace('_', '-').split('-') if p] + table_name = ''.join(p.capitalize() for p in parts) + return f"{file_seg}.{table_name}" + except Exception: + return None + + def _load_common_structure_params(self, substructure: str) -> List[str]: + """Load parameter names from a common-structure table given a path like 'wallet.PrivKeyPolicy'.""" + try: + if not isinstance(substructure, str) or '.' not in substructure: + return [] + _, table_name = substructure.split('.', 1) + tables = self.load_all_tables() + table = tables.get(table_name) + if not isinstance(table, dict): + return [] + data = table.get("data", []) + names: List[str] = [] + for item in data: + if isinstance(item, dict) and isinstance(item.get("parameter"), str): + names.append(item["parameter"]) + return names + except Exception: + return [] + + def _extract_param_names(self, data: Any, param_names: Set[str], prefix: str = "") -> None: + """Recursively extract parameter names from nested data structure. + + Args: + data: Data structure to extract from + param_names: Set to add parameter names to + prefix: Current parameter path prefix + """ + if isinstance(data, dict): + for key, value in data.items(): + param_path = f"{prefix}.{key}" if prefix else key + param_names.add(param_path) + + if isinstance(value, (dict, list)): + self._extract_param_names(value, param_names, param_path) + elif isinstance(data, list): + for i, item in enumerate(data): + if isinstance(item, (dict, list)): + self._extract_param_names(item, param_names, prefix) + + def generate_table_markdown(self, method_name: str, method_config: Dict[str, Any]) -> str: + """Generate markdown table documentation for a method. + + Args: + method_name: Name of the method + method_config: Method configuration from kdf_methods.json + + Returns: + Markdown string for the table or empty string if no table available. + """ + # Skip deprecated methods + if method_config.get('deprecated', False): + return "" + + # Get request table reference + table_ref = self.get_table_reference(method_config, 'request') + table_ref = self.check_table_exists(table_ref) + + # Handle cases where no table is needed or available + if table_ref.is_na: + return "" # N/A means no table needed + + if table_ref.is_empty: + self.track_missing_table(method_name, 'request') + return "" + + if not table_ref.exists: + self.track_missing_table(method_name, 'request') + return "" + + tables = self.load_all_tables() + table_data = tables[table_ref.table_name].get("data", []) + + if not table_data: + self.track_missing_table(method_name, 'request') + return "" + + # Generate markdown table + markdown = "## Request Parameters\n\n" + markdown += "| Parameter | Type | Description |\n" + markdown += "|-----------|------|-------------|\n" + + for param in table_data: + parameter = param.get("parameter", "") + param_type = param.get("type", "") + required = param.get("required", False) + default = param.get("default", "") + description = param.get("description", "") + + # Build the type column with required/default info + type_column = param_type + if required and default: + type_column += f" (required. Default: `{default}`)" + elif required: + type_column += " (required)" + elif default: + type_column += f" (Default: `{default}`)" + + # Escape markdown characters + description = description.replace("|", "\\|").replace("\n", " ") + + markdown += f"| `{parameter}` | {type_column} | {description} |\n" + + return markdown + + def get_missing_tables_report(self) -> Dict[str, List[str]]: + """Get the current missing tables report. + + Returns: + Dictionary with missing table categories and methods. + """ + # Sort all missing table lists + sorted_missing_tables = {} + for table_type, methods in self.missing_tables.items(): + sorted_missing_tables[table_type] = sorted(methods) if methods else [] + + return sorted_missing_tables + + def save_missing_tables_report(self, output_file: Path) -> None: + """Save the missing tables report to a file. + + Args: + output_file: Path to save the report to + """ + report = self.get_missing_tables_report() + dump_sorted_json(report, output_file) + self.logger.info(f"Missing tables report saved to {output_file}") + + def clear_missing_tables(self) -> None: + """Clear the missing tables tracking.""" + for table_type in self.missing_tables: + self.missing_tables[table_type].clear() + + def get_table_statistics(self) -> Dict[str, Any]: + """Get statistics about loaded tables. + + Returns: + Dictionary with table statistics. + """ + tables = self.load_all_tables() + + stats = { + "total_tables": len(tables), + "tables_by_category": {}, + "tables_with_data": 0, + "empty_tables": 0, + "total_parameters": 0 + } + + # Categorize tables and count parameters + for table_name, table_data in tables.items(): + # Categorize by naming pattern + if "Arguments" in table_name: + category = "arguments" + elif "Response" in table_name: + category = "responses" + elif "Error" in table_name: + category = "errors" + else: + category = "other" + + stats["tables_by_category"][category] = stats["tables_by_category"].get(category, 0) + 1 + + # Count parameters + data = table_data.get("data", []) + if data: + stats["tables_with_data"] += 1 + stats["total_parameters"] += len(data) + else: + stats["empty_tables"] += 1 + + return stats diff --git a/utils/py/lib/managers/tag_manager.py b/utils/py/lib/managers/tag_manager.py new file mode 100644 index 000000000..8110333f2 --- /dev/null +++ b/utils/py/lib/managers/tag_manager.py @@ -0,0 +1,537 @@ +#!/usr/bin/env python3 +""" +TagManager - Derive and apply common tags for KDF methods based on defining characteristics. + +This module provides functionality to automatically tag KDF methods based on their properties +such as method names, request structure, wallet types, and environments. +""" + +import json +import re +from pathlib import Path +from typing import Dict, List, Set, Any, Optional, Union +import logging + +logger = logging.getLogger(__name__) + + +class TagManager: + """ + Manages automatic tag derivation and application for KDF methods. + + Tags are derived based on: + - Request structure (mmrpc version) + - Method name patterns (task::, trezor, metamask) + - Environment and wallet type singularity + """ + + def __init__(self, kdf_methods_path: Union[str, Path], requests_base_path: Union[str, Path]): + """ + Initialize the TagManager. + + Args: + kdf_methods_path: Path to the kdf_methods.json file + requests_base_path: Path to the base directory containing request files + """ + self.kdf_methods_path = Path(kdf_methods_path) + self.requests_base_path = Path(requests_base_path) + self.kdf_methods = {} + # Track which file each method came from for saving + self._method_source: Dict[str, Path] = {} + self.request_data = {} + + self._load_data() + + def _load_data(self) -> None: + """Load KDF methods and request data from files. + + Supports either a single file path or a directory containing + kdf_methods_v2.json and kdf_methods_legacy.json. Methods are + preserved from both files without merging on disk; in-memory we + combine for analysis while tracking the source file for each method. + """ + try: + methods: Dict[str, Any] = {} + if self.kdf_methods_path.is_dir(): + v2_file = self.kdf_methods_path / "kdf_methods_v2.json" + legacy_file = self.kdf_methods_path / "kdf_methods_legacy.json" + if legacy_file.exists(): + with open(legacy_file, 'r') as f: + legacy_methods = json.load(f) + methods.update(legacy_methods) + for m in legacy_methods.keys(): + self._method_source[m] = legacy_file + if v2_file.exists(): + with open(v2_file, 'r') as f: + v2_methods = json.load(f) + # v2 methods are distinct; if overlaps, track v2 as the source + methods.update(v2_methods) + for m in v2_methods.keys(): + self._method_source[m] = v2_file + if not methods: + raise FileNotFoundError(f"No methods files found in {self.kdf_methods_path}") + else: + with open(self.kdf_methods_path, 'r') as f: + methods = json.load(f) + for m in methods.keys(): + self._method_source[m] = self.kdf_methods_path + + self.kdf_methods = methods + logger.info(f"Loaded {len(self.kdf_methods)} KDF methods") + + # Load request data from all request files + self._load_request_data() + + except Exception as e: + logger.error(f"Error loading data: {e}") + raise + + def _load_request_data(self) -> None: + """Load all request data from the requests directory structure.""" + self.request_data = {} + + # Find all JSON files in the requests directory + request_files = list(self.requests_base_path.rglob("*.json")) + + for request_file in request_files: + try: + with open(request_file, 'r') as f: + file_data = json.load(f) + # Merge all request examples into a single dict + self.request_data.update(file_data) + logger.info(f"Loaded {len(file_data)} requests from {request_file}") + except Exception as e: + logger.warning(f"Error loading request file {request_file}: {e}") + + logger.info(f"Loaded {len(self.request_data)} total request examples") + + def derive_tags_for_method(self, method_name: str, method_data: Dict[str, Any]) -> Set[str]: + """ + Derive tags for a single KDF method based on its characteristics. + + Args: + method_name: The name of the KDF method + method_data: The method's data from kdf_methods.json + + Returns: + Set of derived tags + """ + tags = set() + + # Rule 1: Check if method's request(s) contain "mmrpc": "2.0" + if self._has_mmrpc_v2(method_data): + tags.add("v2") + + # Rule 2: Check if method name starts with "task::" + if method_name.startswith("task::"): + tags.add("task-based") + + # Rule 3: Check if wallet_types has a single value + wallet_type_tag = self._get_single_wallet_type_tag(method_data) + if wallet_type_tag: + tags.add(wallet_type_tag) + + # Rule 4: Check if environments has a single value + environment_tag = self._get_single_environment_tag(method_data) + if environment_tag: + tags.add(environment_tag) + + # Rule 5: Check if method name or request examples include "trezor" + if self._has_trezor_reference(method_name, method_data): + tags.add("trezor") + + # Rule 6: Check if method name or request examples include "metamask" + if self._has_metamask_reference(method_name, method_data): + tags.add("metamask") + + return tags + + def _has_mmrpc_v2(self, method_data: Dict[str, Any]) -> bool: + """ + Check if any of the method's request examples contain "mmrpc": "2.0". + + Args: + method_data: The method's data from kdf_methods.json + + Returns: + True if any request has mmrpc 2.0, False otherwise + """ + examples = method_data.get("examples", {}) + + for example_name in examples.keys(): + request_data = self.request_data.get(example_name, {}) + if request_data.get("mmrpc") == "2.0": + return True + + return False + + def _get_single_wallet_type_tag(self, method_data: Dict[str, Any]) -> Optional[str]: + """ + Get wallet type tag if there's only one wallet type. + + Args: + method_data: The method's data from kdf_methods.json + + Returns: + Wallet type tag if single, None otherwise + """ + requirements = method_data.get("requirements", {}) + wallet_types = requirements.get("wallet_types", []) + + if len(wallet_types) == 1: + return wallet_types[0] + + return None + + def _get_single_environment_tag(self, method_data: Dict[str, Any]) -> Optional[str]: + """ + Get environment tag if there's only one environment. + + Args: + method_data: The method's data from kdf_methods.json + + Returns: + Environment tag if single, None otherwise + """ + requirements = method_data.get("requirements", {}) + environments = requirements.get("environments", []) + + if len(environments) == 1: + return environments[0] + + return None + + def _has_trezor_reference(self, method_name: str, method_data: Dict[str, Any]) -> bool: + """ + Check if method name or request examples reference trezor. + + Args: + method_name: The method name + method_data: The method's data from kdf_methods.json + + Returns: + True if trezor is referenced, False otherwise + """ + # Check method name + if "trezor" in method_name.lower(): + return True + + # Check example names and descriptions + examples = method_data.get("examples", {}) + for example_name, description in examples.items(): + if "trezor" in example_name.lower() or "trezor" in description.lower(): + return True + + # Check request data for trezor references + for example_name in examples.keys(): + request_data = self.request_data.get(example_name, {}) + if self._contains_trezor_in_request(request_data): + return True + + return False + + def _has_metamask_reference(self, method_name: str, method_data: Dict[str, Any]) -> bool: + """ + Check if method name or request examples reference metamask. + + Args: + method_name: The method name + method_data: The method's data from kdf_methods.json + + Returns: + True if metamask is referenced, False otherwise + """ + # Check method name + if "metamask" in method_name.lower(): + return True + + # Check example names and descriptions + examples = method_data.get("examples", {}) + for example_name, description in examples.items(): + if "metamask" in example_name.lower() or "metamask" in description.lower(): + return True + + # Check request data for metamask references + for example_name in examples.keys(): + request_data = self.request_data.get(example_name, {}) + if self._contains_metamask_in_request(request_data): + return True + + return False + + def _contains_trezor_in_request(self, request_data: Dict[str, Any]) -> bool: + """ + Recursively search for trezor references in request data. + + Args: + request_data: The request data dictionary + + Returns: + True if trezor is found, False otherwise + """ + return self._contains_string_in_data(request_data, "trezor") + + def _contains_metamask_in_request(self, request_data: Dict[str, Any]) -> bool: + """ + Recursively search for metamask references in request data. + + Args: + request_data: The request data dictionary + + Returns: + True if metamask is found, False otherwise + """ + return self._contains_string_in_data(request_data, "metamask") + + def _contains_string_in_data(self, data: Any, search_string: str) -> bool: + """ + Recursively search for a string in any data structure. + + Args: + data: The data to search (can be dict, list, str, etc.) + search_string: The string to search for (case insensitive) + + Returns: + True if string is found, False otherwise + """ + if isinstance(data, str): + return search_string.lower() in data.lower() + elif isinstance(data, dict): + for key, value in data.items(): + if search_string.lower() in key.lower(): + return True + if self._contains_string_in_data(value, search_string): + return True + elif isinstance(data, list): + for item in data: + if self._contains_string_in_data(item, search_string): + return True + + return False + + def derive_tags_for_all_methods(self) -> Dict[str, Set[str]]: + """ + Derive tags for all KDF methods. + + Returns: + Dictionary mapping method names to their derived tags + """ + all_derived_tags = {} + + for method_name, method_data in self.kdf_methods.items(): + derived_tags = self.derive_tags_for_method(method_name, method_data) + all_derived_tags[method_name] = derived_tags + + return all_derived_tags + + def apply_derived_tags(self, dry_run: bool = True) -> Dict[str, Any]: + """ + Apply derived tags to all methods in the KDF methods data. + + Args: + dry_run: If True, don't modify files, just return what would be changed + + Returns: + Dictionary with statistics about tag changes + """ + derived_tags = self.derive_tags_for_all_methods() + changes = { + "methods_modified": 0, + "tags_added": 0, + "tags_removed": 0, + "modifications": {} + } + + # Create a working copy of the methods data + updated_methods = json.loads(json.dumps(self.kdf_methods)) + + for method_name, method_data in updated_methods.items(): + current_tags = set(method_data.get("tags", [])) + new_tags = derived_tags.get(method_name, set()) + + # Combine existing tags with derived tags (derived tags take precedence for conflicts) + combined_tags = current_tags.union(new_tags) + combined_tags_list = sorted(list(combined_tags)) + + # Track changes + if set(combined_tags_list) != current_tags: + changes["methods_modified"] += 1 + added = new_tags - current_tags + removed = current_tags - new_tags # In case we want to implement tag removal logic later + + changes["tags_added"] += len(added) + changes["tags_removed"] += len(removed) + + changes["modifications"][method_name] = { + "old_tags": sorted(list(current_tags)), + "new_tags": combined_tags_list, + "added_tags": sorted(list(added)), + "removed_tags": sorted(list(removed)) + } + + # Update the method data + method_data["tags"] = combined_tags_list + + # Save the changes if not a dry run + if not dry_run: + self._save_updated_methods(updated_methods) + logger.info(f"Applied tags to {changes['methods_modified']} methods") + else: + logger.info(f"Dry run: Would modify {changes['methods_modified']} methods") + + return changes + + def _save_updated_methods(self, updated_methods: Dict[str, Any]) -> None: + """ + Save the updated methods data back to the file. + + Args: + updated_methods: The updated methods data + """ + try: + if self.kdf_methods_path.is_dir(): + v2_file = self.kdf_methods_path / "kdf_methods_v2.json" + legacy_file = self.kdf_methods_path / "kdf_methods_legacy.json" + # Split by original source; default to v2 if unknown + v2_methods: Dict[str, Any] = {} + legacy_methods: Dict[str, Any] = {} + for name, data in updated_methods.items(): + src = self._method_source.get(name) + if src and src == legacy_file: + legacy_methods[name] = data + else: + v2_methods[name] = data + # Backups + if legacy_file.exists(): + with open(legacy_file.with_suffix('.json.backup'), 'w') as f: + json.dump(self._read_json_safe(legacy_file), f, indent=2) + logger.info(f"Created backup at {legacy_file.with_suffix('.json.backup')}") + if v2_file.exists(): + with open(v2_file.with_suffix('.json.backup'), 'w') as f: + json.dump(self._read_json_safe(v2_file), f, indent=2) + logger.info(f"Created backup at {v2_file.with_suffix('.json.backup')}") + # Save + with open(legacy_file, 'w') as f: + json.dump(legacy_methods, f, indent=2) + logger.info(f"Updated KDF methods file: {legacy_file}") + with open(v2_file, 'w') as f: + json.dump(v2_methods, f, indent=2) + logger.info(f"Updated KDF methods file: {v2_file}") + # Update internal data + self.kdf_methods = {**legacy_methods, **v2_methods} + else: + # Single file mode (backward compatibility) + backup_path = self.kdf_methods_path.with_suffix('.json.backup') + with open(backup_path, 'w') as f: + json.dump(self.kdf_methods, f, indent=2) + logger.info(f"Created backup at {backup_path}") + with open(self.kdf_methods_path, 'w') as f: + json.dump(updated_methods, f, indent=2) + logger.info(f"Updated KDF methods file: {self.kdf_methods_path}") + self.kdf_methods = updated_methods + except Exception as e: + logger.error(f"Error saving updated methods: {e}") + raise + + def _read_json_safe(self, file_path: Path) -> Dict[str, Any]: + try: + with open(file_path, 'r') as f: + return json.load(f) + except Exception: + return {} + + def get_tag_statistics(self) -> Dict[str, Any]: + """ + Get statistics about current and derived tags. + + Returns: + Dictionary with tag statistics + """ + current_tags = {} + derived_tags_stats = {} + + # Count current tags + for method_name, method_data in self.kdf_methods.items(): + tags = method_data.get("tags", []) + for tag in tags: + current_tags[tag] = current_tags.get(tag, 0) + 1 + + # Count derived tags + derived_tags = self.derive_tags_for_all_methods() + for method_name, tags in derived_tags.items(): + for tag in tags: + derived_tags_stats[tag] = derived_tags_stats.get(tag, 0) + 1 + + return { + "total_methods": len(self.kdf_methods), + "current_tags": dict(sorted(current_tags.items())), + "derived_tags": dict(sorted(derived_tags_stats.items())), + "total_current_tags": len(current_tags), + "total_derived_tags": len(derived_tags_stats) + } + + def preview_tag_changes(self, method_name: Optional[str] = None) -> Dict[str, Any]: + """ + Preview what tag changes would be made without applying them. + + Args: + method_name: Optional specific method to preview, or None for all methods + + Returns: + Dictionary with preview information + """ + if method_name: + if method_name not in self.kdf_methods: + raise ValueError(f"Method '{method_name}' not found") + + method_data = self.kdf_methods[method_name] + current_tags = set(method_data.get("tags", [])) + derived_tags = self.derive_tags_for_method(method_name, method_data) + + return { + "method": method_name, + "current_tags": sorted(list(current_tags)), + "derived_tags": sorted(list(derived_tags)), + "would_add": sorted(list(derived_tags - current_tags)), + "final_tags": sorted(list(current_tags.union(derived_tags))) + } + else: + # Preview all methods + changes = self.apply_derived_tags(dry_run=True) + return changes + + +def main(): + """Example usage of the TagManager.""" + import argparse + + parser = argparse.ArgumentParser(description="Manage KDF method tags") + parser.add_argument("--kdf-methods", required=True, help="Path to kdf_methods.json") + parser.add_argument("--requests-base", required=True, help="Path to requests base directory") + parser.add_argument("--apply", action="store_true", help="Apply changes (default is dry run)") + parser.add_argument("--method", help="Preview changes for specific method") + parser.add_argument("--stats", action="store_true", help="Show tag statistics") + parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose logging") + + args = parser.parse_args() + + # Setup logging + log_level = logging.INFO if args.verbose else logging.DEBUG + logging.basicConfig(level=log_level, format='%(levelname)s: %(message)s') + + # Initialize TagManager + tag_manager = TagManager(args.kdf_methods, args.requests_base) + + if args.stats: + stats = tag_manager.get_tag_statistics() + print(json.dumps(stats, indent=2)) + elif args.method: + preview = tag_manager.preview_tag_changes(args.method) + print(json.dumps(preview, indent=2)) + else: + changes = tag_manager.apply_derived_tags(dry_run=not args.apply) + print(json.dumps(changes, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/utils/py/lib/managers/test_addresses_collector.py b/utils/py/lib/managers/test_addresses_collector.py new file mode 100644 index 000000000..83fc92910 --- /dev/null +++ b/utils/py/lib/managers/test_addresses_collector.py @@ -0,0 +1,366 @@ +""" +Test Addresses Collector +Collects addresses and balances from all KDF instances for testing purposes. +""" + +import json +import time +from pathlib import Path +from typing import Dict, Any, Optional, List, Tuple +from dataclasses import dataclass +import logging + +# Lazy import to avoid circular dependency issues +def _get_kdf_classes(): + """Lazy import of KDF classes to avoid circular imports.""" + try: + from .kdf_responses_manager import KDFInstance, KdfResponseManager + return KDFInstance, KdfResponseManager + except ImportError: + import sys + from pathlib import Path + sys.path.append(str(Path(__file__).parent)) + from kdf_responses_manager import KDFInstance, KdfResponseManager + return KDFInstance, KdfResponseManager + +# Import utilities +try: + from ..utils.json_utils import dump_sorted_json +except ImportError: + import sys + from pathlib import Path + sys.path.append(str(Path(__file__).parent.parent)) + from utils.json_utils import dump_sorted_json + + +@dataclass +class AddressBalance: + """Container for address and balance information.""" + address: str + balance: str + unspendable_balance: Optional[str] = None + derivation_path: Optional[str] = None + chain: Optional[str] = None + + +class TestAddressesCollector: + """Collects addresses and balances from KDF instances for testing purposes.""" + + def __init__(self, workspace_root: Optional[Path] = None): + """Initialize the collector.""" + self.workspace_root = workspace_root or Path.cwd() + self.logger = logging.getLogger(__name__) + + # Initialize response manager to get send_request capability (lazy import) + KDFInstance, KdfResponseManager = _get_kdf_classes() + self.response_manager = KdfResponseManager() + self.KDFInstance = KDFInstance + + def send_request(self, instance, request_data: Dict[str, Any], timeout: int = 30) -> Tuple[Any, Dict[str, Any]]: + """Send request using the response manager.""" + return self.response_manager.send_request(instance, request_data, timeout) + + def get_enabled_coins(self, instance) -> List[str]: + """Get list of enabled coins for an instance.""" + try: + # For HD wallets, use v2 API; for non-HD wallets, use v1 API + if "hd" in instance.name.lower(): + # HD wallet - use v2 API + request = { + "userpass": instance.userpass, + "mmrpc": "2.0", + "method": "get_enabled_coins" + } + else: + # Non-HD wallet - use v1 API + request = { + "userpass": instance.userpass, + "method": "get_enabled_coins" + } + + outcome, response = self.send_request(instance, request) + + if getattr(outcome, 'name', str(outcome)) == "SUCCESS" and "result" in response: + enabled_coins = [] + result = response["result"] + + # Handle v2 response format (HD wallets) + if isinstance(result, dict) and "coins" in result: + for coin in result["coins"]: + if isinstance(coin, dict) and "ticker" in coin: + enabled_coins.append(coin["ticker"]) + elif isinstance(coin, str): + enabled_coins.append(coin) + # Handle v1 response format (non-HD wallets) + elif isinstance(result, list): + for coin in result: + if isinstance(coin, dict) and "ticker" in coin: + enabled_coins.append(coin["ticker"]) + elif isinstance(coin, str): + enabled_coins.append(coin) + + self.logger.info(f"{instance.name}: Found {len(enabled_coins)} enabled coins: {enabled_coins}") + return enabled_coins + else: + self.logger.warning(f"{instance.name}: Failed to get enabled coins: {response}") + return [] + + except Exception as e: + self.logger.error(f"{instance.name}: Error getting enabled coins: {e}") + return [] + + def get_balance_legacy(self, instance, coin: str) -> Optional[AddressBalance]: + """Get balance using legacy my_balance method.""" + try: + request = { + "userpass": instance.userpass, + "method": "my_balance", + "coin": coin + } + + outcome, response = self.send_request(instance, request) + + if getattr(outcome, 'name', str(outcome)) == "SUCCESS" and "address" in response: + return AddressBalance( + address=response["address"], + balance=response.get("balance", "0"), + unspendable_balance=response.get("unspendable_balance", "0") + ) + else: + self.logger.info(f"{instance.name}: my_balance failed for {coin}: {response}") + return None + + except Exception as e: + self.logger.info(f"{instance.name}: Error getting legacy balance for {coin}: {e}") + return None + + def get_balance_hd(self, instance, coin: str) -> List[AddressBalance]: + """Get balance using HD task::account_balance methods.""" + try: + # Initialize account balance task + init_request = { + "userpass": instance.userpass, + "mmrpc": "2.0", + "method": "task::account_balance::init", + "params": { + "coin": coin, + "account_index": 0 + } + } + + outcome, response = self.send_request(instance, init_request) + + if getattr(outcome, 'name', str(outcome)) != "SUCCESS" or "result" not in response: + self.logger.info(f"{instance.name}: account_balance init failed for {coin}: {response}") + return [] + + task_id = response["result"].get("task_id") + if task_id is None: + self.logger.info(f"{instance.name}: No task_id returned for {coin} account balance") + return [] + + # Poll for status + addresses = [] + max_attempts = 10 + for attempt in range(max_attempts): + status_request = { + "userpass": instance.userpass, + "mmrpc": "2.0", + "method": "task::account_balance::status", + "params": { + "task_id": task_id, + "forget_if_finished": False + } + } + + outcome, response = self.send_request(instance, status_request) + + if getattr(outcome, 'name', str(outcome)) == "SUCCESS" and "result" in response: + result = response["result"] + status = result.get("status") + + if status == "Ok" and "details" in result: + details = result["details"] + if "addresses" in details: + for addr_info in details["addresses"]: + address = addr_info.get("address") + balance_info = addr_info.get("balance", {}) + coin_balance = balance_info.get(coin, {}) + + if address and coin_balance: + addresses.append(AddressBalance( + address=address, + balance=coin_balance.get("spendable", "0"), + unspendable_balance=coin_balance.get("unspendable", "0"), + derivation_path=addr_info.get("derivation_path"), + chain=addr_info.get("chain") + )) + return addresses + elif status in ["InProgress", "UserActionRequired"]: + # Still processing, wait and retry + time.sleep(2) + continue + else: + # Failed or other status + self.logger.info(f"{instance.name}: account_balance failed for {coin} with status: {status}") + return [] + else: + self.logger.info(f"{instance.name}: account_balance status check failed for {coin}: {response}") + return [] + + self.logger.info(f"{instance.name}: account_balance timed out for {coin}") + return [] + + except Exception as e: + self.logger.info(f"{instance.name}: Error getting HD balance for {coin}: {e}") + return [] + + def get_coin_addresses_and_balances(self, instance, coin: str) -> List[AddressBalance]: + """Get addresses and balances for a coin, trying both HD and legacy methods.""" + addresses = [] + + # Choose method based on instance type + if "hd" in instance.name.lower(): + # HD wallet - use HD method + hd_addresses = self.get_balance_hd(instance, coin) + if hd_addresses: + addresses.extend(hd_addresses) + self.logger.info(f"{instance.name}: Got {len(hd_addresses)} HD addresses for {coin}") + else: + self.logger.info(f"{instance.name}: No HD addresses found for {coin}") + else: + # Non-HD wallet - use legacy method + legacy_balance = self.get_balance_legacy(instance, coin) + if legacy_balance: + addresses.append(legacy_balance) + self.logger.info(f"{instance.name}: Got legacy balance for {coin}") + else: + self.logger.info(f"{instance.name}: No legacy balance found for {coin}") + + return addresses + + def collect_all_addresses(self, instances: List) -> Dict[str, Dict[str, Dict[str, str]]]: + """ + Collect addresses and balances from all instances. + + Returns: + Dict in format: { + "instance_name": { + "COIN_TICKER": { + "address_string": "balance_value", + ... + }, + ... + }, + ... + } + """ + self.logger.info("๐Ÿฆ Starting test addresses collection...") + + all_addresses = {} + + for instance in instances: + self.logger.info(f"๐Ÿ“‹ Processing instance: {instance.name}") + instance_addresses = {} + + # Get enabled coins for this instance + enabled_coins = self.get_enabled_coins(instance) + + if not enabled_coins: + self.logger.info(f"{instance.name}: No enabled coins found") + all_addresses[instance.name] = {} + continue + + # Get addresses and balances for each coin + for coin in enabled_coins: + self.logger.info(f"{instance.name}: Getting addresses for {coin}") + addresses = self.get_coin_addresses_and_balances(instance, coin) + + if addresses: + coin_addresses = {} + for addr in addresses: + # Format balance (prefer spendable balance) + balance_str = addr.balance + if addr.unspendable_balance and addr.unspendable_balance != "0": + balance_str += f" (unspendable: {addr.unspendable_balance})" + + coin_addresses[addr.address] = balance_str + + if coin_addresses: + instance_addresses[coin] = coin_addresses + self.logger.info(f"{instance.name}: {coin} - {len(coin_addresses)} addresses") + else: + self.logger.info(f"{instance.name}: No addresses found for {coin}") + + all_addresses[instance.name] = instance_addresses + self.logger.info(f"{instance.name}: Found addresses for {len(instance_addresses)} coins") + + return all_addresses + + def save_test_addresses_report(self, addresses_data: Dict[str, Any], output_file: Optional[Path] = None) -> Path: + """Save the test addresses report to file.""" + if output_file is None: + output_file = self.workspace_root / "postman/generated/reports/test_addresses.json" + + # Ensure output directory exists + output_file.parent.mkdir(parents=True, exist_ok=True) + + # Save the report + dump_sorted_json(addresses_data, output_file) + + self.logger.info(f"๐Ÿ’พ Test addresses report saved to: {output_file}") + return output_file + + +def main(): + """Main function for standalone execution.""" + import sys + from pathlib import Path + + # Setup logging + logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + datefmt='%Y-%m-%d %H:%M:%S' + ) + + # Get workspace root + if len(sys.argv) > 1: + workspace_root = Path(sys.argv[1]) + else: + workspace_root = Path.cwd() + while not (workspace_root / "docker-compose.yml").exists() and workspace_root != workspace_root.parent: + workspace_root = workspace_root.parent + + logger = logging.getLogger(__name__) + logger.info(f"๐Ÿฆ Test Addresses Collector - Workspace: {workspace_root}") + + # Import KDF instances + sys.path.append(str(workspace_root / "utils/py/lib/managers")) + KDFInstance, KdfResponseManager = _get_kdf_classes() + from kdf_responses_manager import KDF_INSTANCES + + # Create collector and collect addresses + collector = TestAddressesCollector(workspace_root) + addresses = collector.collect_all_addresses(KDF_INSTANCES) + + # Save report + output_file = collector.save_test_addresses_report(addresses) + + # Print summary + total_instances = len(addresses) + total_coins = sum(len(instance_data) for instance_data in addresses.values()) + total_addresses = sum( + len(coin_data) for instance_data in addresses.values() + for coin_data in instance_data.values() + ) + + logger.info(f"๐Ÿ“Š Collection Summary:") + logger.info(f" Instances: {total_instances}") + logger.info(f" Coins: {total_coins}") + logger.info(f" Addresses: {total_addresses}") + logger.info(f"๐Ÿ“ Report: {output_file.relative_to(workspace_root)}") + + +if __name__ == "__main__": + main() diff --git a/utils/py/lib/managers/wallet_manager.py b/utils/py/lib/managers/wallet_manager.py new file mode 100644 index 000000000..3fa44c4f6 --- /dev/null +++ b/utils/py/lib/managers/wallet_manager.py @@ -0,0 +1,459 @@ +#!/usr/bin/env python3 +""" +Wallet Manager - Handles address and balance tracking for KDF instances. + +This module provides a clean interface for collecting and managing wallet addresses +and balances from various KDF method responses. +""" + +import logging +from dataclasses import dataclass, field +from typing import Dict, List, Any, Optional +from pathlib import Path + +try: + from ..utils.json_utils import dump_sorted_json +except ImportError: + import sys + sys.path.append(str(Path(__file__).parent.parent)) + from utils.json_utils import dump_sorted_json + + +@dataclass +class WalletAddress: + """Represents a single wallet address with its balance information.""" + address: str + coin: str + balance_spendable: str = "0" + balance_unspendable: str = "0" + instance_name: str = "" + source_method: str = "" + + @property + def balance_display(self) -> str: + """Get formatted balance string for display.""" + if self.balance_unspendable and self.balance_unspendable != "0": + return f"{self.balance_spendable} (unspendable: {self.balance_unspendable})" + return self.balance_spendable + + @property + def total_balance(self) -> float: + """Calculate total balance as float.""" + try: + spendable = float(self.balance_spendable) if self.balance_spendable else 0.0 + unspendable = float(self.balance_unspendable) if self.balance_unspendable else 0.0 + return spendable + unspendable + except (ValueError, TypeError): + return 0.0 + + def update_balance(self, spendable: str, unspendable: str = "0"): + """Update balance information.""" + self.balance_spendable = spendable + self.balance_unspendable = unspendable + + def __str__(self): + return f"{self.coin}:{self.address} = {self.balance_display}" + + +class WalletManager: + """Manages wallet addresses and balances across KDF instances.""" + + def __init__(self, workspace_root: Path): + """Initialize the wallet manager.""" + self.workspace_root = workspace_root + self.logger = logging.getLogger(__name__) + + # Storage: instance_name -> coin -> address -> WalletAddress + self.addresses: Dict[str, Dict[str, Dict[str, WalletAddress]]] = {} + + def add_address(self, instance_name: str, coin: str, address: str, + spendable: str = "0", unspendable: str = "0", + source_method: str = "") -> WalletAddress: + """Add or update a wallet address.""" + # Initialize nested dictionaries if needed + if instance_name not in self.addresses: + self.addresses[instance_name] = {} + if coin not in self.addresses[instance_name]: + self.addresses[instance_name][coin] = {} + + # Create or update the address + if address in self.addresses[instance_name][coin]: + # Update existing address + wallet_address = self.addresses[instance_name][coin][address] + wallet_address.update_balance(spendable, unspendable) + if source_method: + wallet_address.source_method = source_method + else: + # Create new address + wallet_address = WalletAddress( + address=address, + coin=coin, + balance_spendable=spendable, + balance_unspendable=unspendable, + instance_name=instance_name, + source_method=source_method + ) + self.addresses[instance_name][coin][address] = wallet_address + + self.logger.info(f"Added address: {instance_name}/{coin}/{address} = {wallet_address.balance_display}") + return wallet_address + + def get_addresses_for_coin(self, instance_name: str, coin: str) -> List[WalletAddress]: + """Get all addresses for a specific coin on an instance.""" + if instance_name in self.addresses and coin in self.addresses[instance_name]: + return list(self.addresses[instance_name][coin].values()) + return [] + + def get_all_addresses_for_instance(self, instance_name: str) -> List[WalletAddress]: + """Get all addresses for a specific instance.""" + all_addresses = [] + if instance_name in self.addresses: + for coin_addresses in self.addresses[instance_name].values(): + all_addresses.extend(coin_addresses.values()) + return all_addresses + + def get_instance_summary(self, instance_name: str) -> Dict[str, int]: + """Get summary statistics for an instance.""" + addresses = self.get_all_addresses_for_instance(instance_name) + coins = set(addr.coin for addr in addresses) + + return { + "total_addresses": len(addresses), + "total_coins": len(coins), + "coins": sorted(coins) + } + + def extract_addresses_from_response(self, instance_name: str, method_name: str, + response_data: Dict[str, Any], + request_data: Optional[Dict[str, Any]] = None): + """Extract address and balance information from method responses.""" + if not isinstance(response_data, dict): + return + + try: + # Handle legacy electrum/enable responses with direct address/balance fields + if "address" in response_data and "coin" in response_data: + coin = response_data["coin"] + address = response_data["address"] + balance = response_data.get("balance", "0") + unspendable = response_data.get("unspendable_balance", "0") + + self.add_address(instance_name, coin, address, balance, unspendable, method_name) + + # Handle account_balance responses (HD wallets) + elif "task::account_balance::status" in method_name and "result" in response_data: + self._extract_from_account_balance(instance_name, response_data["result"], method_name) + + # Handle get_enabled_coins responses (legacy - includes addresses) + elif method_name == "get_enabled_coins" and isinstance(response_data, list): + self._extract_from_enabled_coins(instance_name, response_data, method_name) + + # Handle coin activation responses with address info + elif "result" in response_data and isinstance(response_data["result"], dict): + self._extract_from_activation_response(instance_name, method_name, + response_data["result"], request_data) + + except Exception as e: + self.logger.info(f"Error extracting addresses from {method_name} response: {e}") + + def _extract_from_account_balance(self, instance_name: str, result: Dict[str, Any], method_name: str): + """Extract addresses from account_balance responses.""" + if isinstance(result, dict) and result.get("status") == "Ok" and "details" in result: + details = result["details"] + if "addresses" in details: + for addr_info in details["addresses"]: + address = addr_info.get("address") + balance_info = addr_info.get("balance", {}) + + if address and balance_info: + for coin, coin_balance in balance_info.items(): + spendable = coin_balance.get("spendable", "0") + unspendable = coin_balance.get("unspendable", "0") + self.add_address(instance_name, coin, address, spendable, unspendable, method_name) + + def _extract_from_enabled_coins(self, instance_name: str, response_data: List, method_name: str): + """Extract addresses from get_enabled_coins responses.""" + for coin_info in response_data: + if isinstance(coin_info, dict) and "ticker" in coin_info and "address" in coin_info: + coin = coin_info["ticker"] + address = coin_info["address"] + # For get_enabled_coins, we don't have balance info, so mark as "enabled" + self.add_address(instance_name, coin, address, "enabled", "0", method_name) + + def _extract_from_activation_response(self, instance_name: str, method_name: str, + result: Dict[str, Any], request_data: Optional[Dict[str, Any]] = None): + """Extract addresses from various coin activation response formats.""" + try: + # Handle task completion responses + if isinstance(result, dict) and result.get("status") == "Ok" and "details" in result: + self._extract_from_task_details(instance_name, result["details"], method_name) + + # Handle direct activation responses + if isinstance(result, dict) and "address" in result and "ticker" in result: + self._extract_from_direct_activation(instance_name, result, method_name) + + # Handle HD wallet responses + if isinstance(result, dict) and "wallet_balance" in result: + self._extract_from_wallet_balance(instance_name, result["wallet_balance"], method_name) + + # Handle ETH/Polygon non-HD responses (erc20_addresses_infos, eth_addresses_infos) + self._extract_from_addresses_infos(instance_name, result, method_name) + + # Handle token activation responses + if isinstance(result, dict) and "balances" in result and isinstance(result["balances"], dict): + self._extract_from_token_balances(instance_name, result, method_name, request_data) + + except Exception as e: + self.logger.info(f"Error extracting from activation response: {e}") + + def _extract_from_task_details(self, instance_name: str, details: Dict[str, Any], method_name: str): + """Extract addresses from task completion details.""" + # HD wallet format with wallet_balance + if "wallet_balance" in details and "ticker" in details: + ticker = details["ticker"] + self._extract_from_wallet_balance(instance_name, details["wallet_balance"], method_name, ticker) + + # Tendermint format (single address with balance and tokens) + elif "address" in details and "ticker" in details: + ticker = details["ticker"] + address = details["address"] + + # Main coin balance + if "balance" in details: + balance = details["balance"] + spendable = balance.get("spendable", "0") + unspendable = balance.get("unspendable", "0") + self.add_address(instance_name, ticker, address, spendable, unspendable, method_name) + + # Token balances + if "tokens_balances" in details: + for token_name, token_balance in details["tokens_balances"].items(): + spendable = token_balance.get("spendable", "0") + unspendable = token_balance.get("unspendable", "0") + self.add_address(instance_name, token_name, address, spendable, unspendable, method_name) + + def _extract_from_direct_activation(self, instance_name: str, result: Dict[str, Any], method_name: str): + """Extract addresses from direct activation responses.""" + ticker = result["ticker"] + address = result["address"] + + # Main coin balance + if "balance" in result: + balance = result["balance"] + spendable = balance.get("spendable", "0") + unspendable = balance.get("unspendable", "0") + self.add_address(instance_name, ticker, address, spendable, unspendable, method_name) + + # Token balances + if "tokens_balances" in result: + for token_name, token_balance in result["tokens_balances"].items(): + spendable = token_balance.get("spendable", "0") + unspendable = token_balance.get("unspendable", "0") + self.add_address(instance_name, token_name, address, spendable, unspendable, method_name) + + def _extract_from_wallet_balance(self, instance_name: str, wallet_balance: Dict[str, Any], + method_name: str, default_ticker: str = None): + """Extract addresses from wallet_balance structures.""" + if isinstance(wallet_balance, dict): + # HD wallet with accounts + if "accounts" in wallet_balance: + for account in wallet_balance["accounts"]: + if "addresses" in account: + for addr_info in account["addresses"]: + address = addr_info.get("address") + balance_info = addr_info.get("balance", {}) + + if address and balance_info: + for coin, coin_balance in balance_info.items(): + spendable = coin_balance.get("spendable", "0") + unspendable = coin_balance.get("unspendable", "0") + self.add_address(instance_name, coin, address, spendable, unspendable, method_name) + + # Iguana wallet format + elif "address" in wallet_balance and "balance" in wallet_balance: + address = wallet_balance["address"] + balance_info = wallet_balance["balance"] + + if address and balance_info: + for coin, coin_balance in balance_info.items(): + spendable = coin_balance.get("spendable", "0") + unspendable = coin_balance.get("unspendable", "0") + self.add_address(instance_name, coin, address, spendable, unspendable, method_name) + + def _extract_from_addresses_infos(self, instance_name: str, result: Dict[str, Any], method_name: str): + """Extract addresses from various addresses_infos structures.""" + if not isinstance(result, dict): + return + + for key in result: + if key.endswith("_addresses_infos"): + addresses_info = result[key] + if isinstance(addresses_info, dict): + for address, addr_data in addresses_info.items(): + if "balances" in addr_data: + balances = addr_data["balances"] + + if isinstance(balances, dict): + # Platform coin format: {"spendable": "0", "unspendable": "0"} + if "spendable" in balances: + coin = key.replace("_addresses_infos", "").upper() + if coin != "ERC20": # Skip ERC20, handled in token section + spendable = balances.get("spendable", "0") + unspendable = balances.get("unspendable", "0") + self.add_address(instance_name, coin, address, spendable, unspendable, method_name) + + # Token format: {"TOKEN-NAME": {"spendable": "0", "unspendable": "0"}} + else: + for token_name, token_balance in balances.items(): + if isinstance(token_balance, dict) and "spendable" in token_balance: + spendable = token_balance.get("spendable", "0") + unspendable = token_balance.get("unspendable", "0") + self.add_address(instance_name, token_name, address, spendable, unspendable, method_name) + + def _extract_from_token_balances(self, instance_name: str, result: Dict[str, Any], + method_name: str, request_data: Optional[Dict[str, Any]] = None): + """Extract addresses from token activation balances.""" + for address, balance_info in result["balances"].items(): + if "spendable" in balance_info: + # Extract token name from request data + token_name = self._extract_ticker_from_request_data(request_data) if request_data else "TOKEN" + spendable = balance_info.get("spendable", "0") + unspendable = balance_info.get("unspendable", "0") + self.add_address(instance_name, token_name, address, spendable, unspendable, method_name) + + def _extract_ticker_from_request_data(self, request_data: Dict[str, Any]) -> Optional[str]: + """Extract ticker from request data for token activation methods.""" + if not request_data: + return None + + # Check common ticker locations in request + if "ticker" in request_data: + return request_data["ticker"] + + # Check in params + params = request_data.get("params", {}) + if isinstance(params, dict): + if "ticker" in params: + return params["ticker"] + if "coin" in params: + return params["coin"] + + # Check direct coin field + if "coin" in request_data: + return request_data["coin"] + + return None + + def reprocess_responses_for_addresses(self, results: List[Any]): + """Reprocess all collected responses to extract any addresses we may have missed.""" + self.logger.info("๐Ÿ”„ Reprocessing collected responses to extract any missed addresses...") + + addresses_found = 0 + initial_count = self.get_total_addresses_count() + + for result in results: + if hasattr(result, 'instance_responses') and result.instance_responses: + for instance_name, response_data in result.instance_responses.items(): + # Skip error responses + if isinstance(response_data, dict) and "error" not in response_data: + self.extract_addresses_from_response(instance_name, "reprocess", response_data, None) + + final_count = self.get_total_addresses_count() + addresses_found = final_count - initial_count + + if addresses_found > 0: + self.logger.info(f"๐ŸŽฏ Reprocessing found {addresses_found} additional addresses") + else: + self.logger.info("๐Ÿ“‹ No additional addresses found during reprocessing") + + def get_total_addresses_count(self) -> int: + """Get total number of addresses across all instances.""" + return sum( + len(coin_addresses) + for instance_addresses in self.addresses.values() + for coin_addresses in instance_addresses.values() + ) + + def get_address_hint(self, instance_name: str, coin: str) -> Optional[str]: + """Return a representative address for a given instance/coin. + + Prefers in-memory addresses extracted during this run; falls back to the + latest saved test_addresses.json report if needed. + """ + try: + coin = str(coin).upper() + # Prefer in-memory + addrs = self.get_addresses_for_coin(instance_name, coin) + if addrs: + # Return the first address deterministically by sorting + first = sorted(a.address for a in addrs if a and a.address)[0] + return first + # Fallback to saved report + report_path = self.workspace_root / "postman/generated/reports/test_addresses.json" + if report_path.exists(): + import json + with open(report_path, "r", encoding="utf-8") as f: + data = json.load(f) + inst = data.get(instance_name, {}) + coin_map = inst.get(coin) if isinstance(inst, dict) else None + if isinstance(coin_map, dict) and coin_map: + return sorted(coin_map.keys())[0] + except Exception: + pass + return None + + def save_test_addresses_report(self, output_file: Path): + """Save addresses in the test_addresses.json format.""" + # Convert to the expected format: instance -> coin -> {address: balance} + report_data = {} + + for instance_name, instance_addresses in self.addresses.items(): + report_data[instance_name] = {} + for coin, coin_addresses in instance_addresses.items(): + report_data[instance_name][coin] = { + addr.address: addr.balance_display + for addr in coin_addresses.values() + } + + # Ensure output directory exists + output_file.parent.mkdir(parents=True, exist_ok=True) + + # Save with sorted keys + dump_sorted_json(report_data, output_file) + + # Log summary + total_instances = len(report_data) + total_coins = sum(len(instance_data) for instance_data in report_data.values()) + total_addresses = sum( + len(coin_data) for instance_data in report_data.values() + for coin_data in instance_data.values() + ) + + self.logger.info(f"๐Ÿฆ Test addresses saved to: {output_file.name}") + self.logger.info(f" Instances: {total_instances}, Coins: {total_coins}, Addresses: {total_addresses}") + + return { + "total_instances": total_instances, + "total_coins": total_coins, + "total_addresses": total_addresses, + "report_file": str(output_file), + "addresses_data": report_data + } + + def get_summary(self) -> Dict[str, Any]: + """Get comprehensive summary of collected addresses.""" + summary = { + "total_instances": len(self.addresses), + "instances": {} + } + + for instance_name in self.addresses: + summary["instances"][instance_name] = self.get_instance_summary(instance_name) + + summary["total_addresses"] = self.get_total_addresses_count() + summary["total_coins"] = len(set( + coin for instance_addresses in self.addresses.values() + for coin in instance_addresses.keys() + )) + + return summary diff --git a/utils/py/lib/models/kdf_method.py b/utils/py/lib/models/kdf_method.py new file mode 100644 index 000000000..8dc279dd7 --- /dev/null +++ b/utils/py/lib/models/kdf_method.py @@ -0,0 +1,531 @@ +#!/usr/bin/env python3 +""" +KDF Method Models - Object-oriented representation of KDF API methods and examples. + +This module provides structured classes for representing KDF methods, their examples, +prerequisites, and execution status. +""" + +from dataclasses import dataclass, field +from typing import Dict, List, Any, Optional, Set +from enum import Enum +import json +from pathlib import Path + + +class MethodStatus(Enum): + """Status of a method during processing.""" + PENDING = "pending" + PREREQUISITES_NEEDED = "prerequisites_needed" + IN_PROGRESS = "in_progress" + COMPLETED = "completed" + FAILED = "failed" + SKIPPED = "skipped" + + +@dataclass +class KdfExample: + """Represents a single example request/response for a KDF method.""" + name: str + description: str + request_data: Dict[str, Any] + response_data: Optional[Dict[str, Any]] = None + status_code: Optional[int] = None + error_data: Optional[Dict[str, Any]] = None + instance_responses: Dict[str, Any] = field(default_factory=dict) + collected: bool = False + + @property + def has_response(self) -> bool: + """Check if this example has response data.""" + return self.response_data is not None or bool(self.instance_responses) + + @property + def is_successful(self) -> bool: + """Check if this example completed successfully.""" + return self.collected and self.has_response and not self.error_data + + @staticmethod + def _contains_string_in_data(data: Any, search_string: str) -> bool: + """Recursively search for a string in any data structure.""" + if isinstance(data, str): + return search_string.lower() in data.lower() + elif isinstance(data, dict): + for key, value in data.items(): + if search_string.lower() in key.lower(): + return True + if KdfExample._contains_string_in_data(value, search_string): + return True + elif isinstance(data, list): + for item in data: + if KdfExample._contains_string_in_data(item, search_string): + return True + return False + + @property + def is_manual(self) -> bool: + """Detect if example likely requires manual interaction/hardware.""" + manual_terms = [ + "walletconnect", + "trezor", + "metamask", + "useraction", + "user_action", + ] + name_l = self.name.lower() + if any(t in name_l for t in manual_terms): + return True + desc_l = (self.description or "").lower() + if any(t in desc_l for t in manual_terms): + return True + for term in manual_terms: + if KdfExample._contains_string_in_data(self.request_data, term): + return True + return False + +@dataclass +class KdfMethod: + """Represents a KDF API method with its configuration and examples.""" + name: str + sequence: int + tags: List[str] = field(default_factory=list) + prerequisites: List[str] = field(default_factory=list) + request_table: str = "" + response_table: str = "" + errors_table: str = "" + requirements: Dict[str, Any] = field(default_factory=dict) + timeout: Optional[int] = None + deprecated: bool = False + examples: Dict[str, KdfExample] = field(default_factory=dict) + status: MethodStatus = MethodStatus.PENDING + prerequisite_methods_completed: Set[str] = field(default_factory=set) + + @classmethod + def from_json(cls, name: str, method_data: Dict[str, Any], request_examples: Dict[str, Dict[str, Any]]) -> 'KdfMethod': + """Create a KdfMethod instance from JSON configuration data.""" + # Extract examples and create KdfExample objects + examples = {} + example_configs = method_data.get("examples", {}) + + for example_name, example_description in example_configs.items(): + if example_name in request_examples: + request_data = request_examples[example_name] + examples[example_name] = KdfExample( + name=example_name, + description=example_description, + request_data=request_data + ) + + return cls( + name=name, + sequence=method_data.get("sequence", 100), + tags=method_data.get("tags", []), + prerequisites=method_data.get("prerequisites", []), + request_table=method_data.get("request_table", ""), + response_table=method_data.get("response_table", ""), + errors_table=method_data.get("errors_table", ""), + requirements=method_data.get("requirements", {}), + timeout=method_data.get("timeout"), + deprecated=method_data.get("deprecated", False), + examples=examples + ) + + @classmethod + def from_config(cls, name: str, method_data: Dict[str, Any]) -> 'KdfMethod': + """Create a KdfMethod from method config only (no request data binding).""" + # Build examples map with empty request_data to satisfy typing + examples: Dict[str, KdfExample] = {} + for example_name, example_description in (method_data.get("examples", {}) or {}).items(): + examples[example_name] = KdfExample( + name=example_name, + description=example_description, + request_data={} + ) + return cls( + name=name, + sequence=method_data.get("sequence", 100), + tags=method_data.get("tags", []), + prerequisites=method_data.get("prerequisites", []), + request_table=method_data.get("request_table", ""), + response_table=method_data.get("response_table", ""), + errors_table=method_data.get("errors_table", ""), + requirements=method_data.get("requirements", {}), + timeout=method_data.get("timeout"), + deprecated=method_data.get("deprecated", False), + examples=examples + ) + + # ===== Capability helpers (moved from EnvironmentManager) ===== + + @property + def supported_environments(self) -> List[str]: + reqs = self.requirements or {} + return reqs.get("environments", []) or [] + + def supports_environment(self, environment: str) -> bool: + return environment in self.supported_environments + + @property + def supported_wallet_types(self) -> List[str]: + reqs = self.requirements or {} + return reqs.get("wallet_types", []) or [] + + def supports_wallet_type(self, wallet_type: str) -> bool: + return wallet_type in self.supported_wallet_types + + @property + def required_hardware(self) -> List[str]: + reqs = self.requirements or {} + return reqs.get("hardware", []) or [] + + def requires_hardware(self, hardware_type: Optional[str] = None) -> bool: + hardware_list = self.required_hardware + if hardware_type is None: + return len(hardware_list) > 0 + return hardware_type in hardware_list + + def get_protocol_preferences(self, environment: str) -> Dict[str, List[str]]: + reqs = self.requirements or {} + protocols = reqs.get("protocols", {}) or {} + result: Dict[str, List[str]] = {} + for proto_type, env_map in protocols.items(): + if isinstance(env_map, dict) and environment in env_map: + result[proto_type] = env_map[environment] + return result + + @property + def is_manual_method(self) -> bool: + """Detect if method/examples require manual testing (WalletConnect, Trezor, Metamask, PIN, UserAction).""" + manual_terms = [ + "walletconnect", + "trezor", + "metamask", + "pin", + "useraction", + "user_action", + ] + name_l = self.name.lower() + if any(t in name_l for t in manual_terms): + return True + # Check examples by name/desc + for ex in self.examples.values(): + if ex.is_manual: + return True + # Check tags/requirements for hardware flags + req = self.requirements or {} + hardware = [h.lower() for h in req.get("hardware", []) if isinstance(h, str)] + if any(h in ["trezor", "ledger", "metamask", "walletconnect"] for h in hardware): + return True + return False + + def get_conditional_params_for_wallet(self, wallet_type: Optional[str] = None) -> List[str]: + reqs = self.requirements or {} + conditional_params = reqs.get("conditional_params", {}) or {} + if wallet_type == 'hd': + return conditional_params.get('hd_only', []) or [] + elif wallet_type == 'iguana': + return conditional_params.get('non_hd_only', []) or [] + # Return all conditional params if no specific type requested + all_params: List[str] = [] + all_params.extend(conditional_params.get('hd_only', []) or []) + all_params.extend(conditional_params.get('non_hd_only', []) or []) + return all_params + + def get_prerequisite_methods(self) -> List[str]: + # Prefer requirements.prerequisite_methods with fallback to top-level prerequisites + reqs = self.requirements or {} + prereq_methods = reqs.get('prerequisite_methods', []) or [] + if prereq_methods: + return prereq_methods + return self.prerequisites or [] + + @staticmethod + def _matches_example_pattern(example_key: str, environment: Optional[str] = None, + hardware: Optional[str] = None, + wallet_type: Optional[str] = None) -> bool: + example_lower = example_key.lower() + if 'trezor' in example_lower: + return hardware == 'trezor' or hardware is None + if 'native' in example_lower: + return environment == 'native' or environment is None + if 'wasm' in example_lower: + return environment == 'wasm' or environment is None + if 'hd' in example_lower and wallet_type is not None: + return wallet_type == 'hd' + if 'iguana' in example_lower and wallet_type is not None: + return wallet_type == 'iguana' + if any(pattern in example_lower for pattern in ['pin', 'passphrase']): + return hardware == 'trezor' or hardware is None + if any(pattern in example_lower for pattern in ['gap_limit', 'scan_policy', 'min_addresses', 'path_to_address']): + return wallet_type == 'hd' or wallet_type is None + return True + + def filter_examples(self, environment: Optional[str] = None, + hardware: Optional[str] = None, + wallet_type: Optional[str] = None) -> Dict[str, str]: + # If no filtering requested, return all example descriptions + all_examples = {ex.name: ex.description for ex in self.examples.values()} + if environment is None and hardware is None and wallet_type is None: + return all_examples + # Method-level requirements checks + method_requirements = self.requirements or {} + if environment is not None: + if environment not in (method_requirements.get('environments', []) or []): + return {} + if wallet_type is not None: + if wallet_type not in (method_requirements.get('wallet_types', []) or []): + return {} + if hardware is not None: + req_hw = method_requirements.get('hardware', []) or [] + if len(req_hw) > 0 and hardware not in req_hw: + return {} + # Example-specific requirements + example_requirements = method_requirements.get('example_requirements', {}) or {} + filtered: Dict[str, str] = {} + for example_key, description in all_examples.items(): + ex_reqs = example_requirements.get(example_key, {}) or {} + if hardware is not None: + ex_hw = ex_reqs.get('hardware', []) or [] + if len(ex_hw) > 0 and hardware not in ex_hw: + continue + if self._matches_example_pattern(example_key, environment, hardware, wallet_type): + filtered[example_key] = description + return filtered + + @property + def is_activation_method(self) -> bool: + """Check if this is an activation method.""" + activation_terms = ["enable", "activate", "init", "electrum"] + return any(term in self.name.lower() for term in activation_terms) + + @property + def is_wallet_method(self) -> bool: + """Check if this is a wallet-related method.""" + wallet_terms = ["withdraw", "fetch_utxos", "consolidate", "balance"] + return any(term in self.name.lower() for term in wallet_terms) + + @property + def prerequisites_satisfied(self) -> bool: + """Check if all prerequisites are satisfied.""" + return set(self.prerequisites).issubset(self.prerequisite_methods_completed) + + @property + def can_process(self) -> bool: + """Check if this method can be processed (prerequisites satisfied and not deprecated).""" + return self.prerequisites_satisfied and not self.deprecated and self.status in [MethodStatus.PENDING, MethodStatus.PREREQUISITES_NEEDED] + + @property + def has_examples(self) -> bool: + """Check if this method has examples to process.""" + return len(self.examples) > 0 + + @property + def collected_examples_count(self) -> int: + """Count of examples that have been collected.""" + return sum(1 for example in self.examples.values() if example.collected) + + @property + def successful_examples_count(self) -> int: + """Count of examples that completed successfully.""" + return sum(1 for example in self.examples.values() if example.is_successful) + + def mark_prerequisite_completed(self, prerequisite_method: str): + """Mark a prerequisite method as completed.""" + self.prerequisite_methods_completed.add(prerequisite_method) + + # Update status if all prerequisites are now satisfied + if self.prerequisites_satisfied and self.status == MethodStatus.PREREQUISITES_NEEDED: + self.status = MethodStatus.PENDING + + def get_example(self, example_name: str) -> Optional[KdfExample]: + """Get a specific example by name.""" + return self.examples.get(example_name) + + def add_example_response(self, example_name: str, response_data: Dict[str, Any], + status_code: int = 200, instance_responses: Optional[Dict[str, Any]] = None): + """Add response data to an example.""" + if example_name in self.examples: + example = self.examples[example_name] + example.response_data = response_data + example.status_code = status_code + if instance_responses: + example.instance_responses = instance_responses + example.collected = True + + def add_example_error(self, example_name: str, error_data: Dict[str, Any], + instance_responses: Optional[Dict[str, Any]] = None): + """Add error data to an example.""" + if example_name in self.examples: + example = self.examples[example_name] + example.error_data = error_data + if instance_responses: + example.instance_responses = instance_responses + example.collected = True + + def __lt__(self, other: 'KdfMethod') -> bool: + """Enable sorting by sequence, then alphabetically by name.""" + if self.sequence != other.sequence: + return self.sequence < other.sequence + return self.name < other.name + + +@dataclass +class MethodRequestQueue: + """Queue for managing method processing order and prerequisites.""" + methods: Dict[str, KdfMethod] = field(default_factory=dict) + completed_methods: Set[str] = field(default_factory=set) + failed_methods: Set[str] = field(default_factory=set) + + def add_method(self, method: KdfMethod): + """Add a method to the queue.""" + self.methods[method.name] = method + + def get_next_processable_method(self) -> Optional[KdfMethod]: + """Get the next method that can be processed (lowest sequence, prerequisites satisfied).""" + processable_methods = [ + method for method in self.methods.values() + if method.can_process and method.name not in self.completed_methods + ] + + if not processable_methods: + return None + + # Sort by sequence, then alphabetically + processable_methods.sort() + return processable_methods[0] + + def mark_method_completed(self, method_name: str): + """Mark a method as completed and update prerequisites for other methods.""" + if method_name in self.methods: + self.methods[method_name].status = MethodStatus.COMPLETED + + self.completed_methods.add(method_name) + + # Update prerequisite status for all methods + for method in self.methods.values(): + if method_name in method.prerequisites: + method.mark_prerequisite_completed(method_name) + + def mark_method_failed(self, method_name: str, reason: str = ""): + """Mark a method as failed.""" + if method_name in self.methods: + self.methods[method_name].status = MethodStatus.FAILED + + self.failed_methods.add(method_name) + + def get_methods_needing_prerequisites(self) -> List[KdfMethod]: + """Get methods that need prerequisites but haven't been marked as such.""" + return [ + method for method in self.methods.values() + if not method.prerequisites_satisfied and method.status == MethodStatus.PENDING + ] + + def update_prerequisite_status(self): + """Update the status of methods based on their prerequisites.""" + for method in self.methods.values(): + if not method.prerequisites_satisfied and method.status == MethodStatus.PENDING: + method.status = MethodStatus.PREREQUISITES_NEEDED + + @property + def pending_count(self) -> int: + """Count of methods still pending processing.""" + return len([m for m in self.methods.values() if m.status in [MethodStatus.PENDING, MethodStatus.PREREQUISITES_NEEDED]]) + + @property + def completed_count(self) -> int: + """Count of completed methods.""" + return len(self.completed_methods) + + @property + def failed_count(self) -> int: + """Count of failed methods.""" + return len(self.failed_methods) + + +class KdfMethodsLoader: + """Utility class for loading KDF methods from JSON files.""" + + @staticmethod + def load_from_files(workspace_root: Path) -> MethodRequestQueue: + """Load all KDF methods from configuration and request files.""" + # Load method configurations separately and combine for queue creation + data_dir = workspace_root / "src/data" + v2_file = data_dir / "kdf_methods_v2.json" + legacy_file = data_dir / "kdf_methods_legacy.json" + + methods_config = {} + try: + with open(legacy_file, 'r') as f: + legacy_cfg = json.load(f) + # Use unique method keys; if collisions exist, keep both by suffixing version for internal queue + for name, cfg in legacy_cfg.items(): + if name in methods_config: + methods_config[f"legacy::{name}"] = cfg + else: + methods_config[name] = cfg + except FileNotFoundError: + pass + try: + with open(v2_file, 'r') as f: + v2_cfg = json.load(f) + for name, cfg in v2_cfg.items(): + if name in methods_config: + methods_config[f"v2::{name}"] = cfg + else: + methods_config[name] = cfg + except FileNotFoundError: + pass + # Do not fallback to single file; expect split files present + + # Load request examples from all request files + all_request_examples = {} + request_dirs = [ + workspace_root / "src/data/requests/kdf/v2", + workspace_root / "src/data/requests/kdf/legacy" + ] + + for request_dir in request_dirs: + if request_dir.exists(): + for request_file in request_dir.glob("*.json"): + with open(request_file, 'r') as f: + request_data = json.load(f) + all_request_examples.update(request_data) + + # Create method queue + queue = MethodRequestQueue() + + # Create KdfMethod objects + for method_name, method_config in methods_config.items(): + method = KdfMethod.from_json(method_name, method_config, all_request_examples) + queue.add_method(method) + + # Update prerequisite status + queue.update_prerequisite_status() + + return queue + + +# -------- Generic request parsing helpers (centralized for reuse) -------- + +def extract_method_from_request(request_data: Dict[str, Any]) -> Optional[str]: + """Extract the method name from a request object.""" + if isinstance(request_data, dict) and 'method' in request_data: + return request_data['method'] + return None + +def extract_ticker_from_request(request_data: Dict[str, Any]) -> Optional[str]: + """Extract the ticker symbol from a request object.""" + if isinstance(request_data, dict): + # Look for ticker in params + params = request_data.get('params') + if isinstance(params, dict): + if 'ticker' in params: + return params['ticker'] + if 'coin' in params: + return params['coin'] + # Look for ticker in other common locations + if 'ticker' in request_data: + return request_data['ticker'] + if 'coin' in request_data: + return request_data['coin'] + return None diff --git a/utils/py/lib/utils/__init__.py b/utils/py/lib/utils/__init__.py new file mode 100644 index 000000000..dd7ee44cc --- /dev/null +++ b/utils/py/lib/utils/__init__.py @@ -0,0 +1 @@ +# Utils package diff --git a/utils/py/lib/utils/json_utils.py b/utils/py/lib/utils/json_utils.py new file mode 100644 index 000000000..cb8065f12 --- /dev/null +++ b/utils/py/lib/utils/json_utils.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +""" +JSON utilities for consistent sorting and formatting. + +This module provides utilities for deep sorting of JSON data structures, +ensuring consistent alphabetical ordering of all nested objects and lists. +""" + +import json +from typing import Any, Dict, List, Union +from pathlib import Path + + +def deep_sort_data(data: Any) -> Any: + """ + Recursively sort JSON data structures alphabetically. + + - Dictionaries are sorted by keys (case-insensitive) + - Lists are sorted alphabetically (when possible) + - Nested structures are recursively sorted + + Args: + data: The data structure to sort + + Returns: + The sorted data structure + """ + if isinstance(data, dict): + # Sort dictionary by keys (case-insensitive) + sorted_dict = {} + for key in sorted(data.keys(), key=str.lower): + sorted_dict[key] = deep_sort_data(data[key]) + return sorted_dict + + elif isinstance(data, list): + # Sort list elements recursively + sorted_list = [deep_sort_data(item) for item in data] + + # Try to sort the list if all elements are comparable + try: + # If all elements are strings, sort case-insensitive + if all(isinstance(item, str) for item in sorted_list): + return sorted(sorted_list, key=str.lower) + # If all elements are numbers, sort numerically + elif all(isinstance(item, (int, float)) for item in sorted_list): + return sorted(sorted_list) + # If all elements are dicts with same structure, try to sort by a common key + elif all(isinstance(item, dict) for item in sorted_list): + # Try to find a common string key to sort by + common_keys = None + for item in sorted_list: + if common_keys is None: + common_keys = set(item.keys()) + else: + common_keys &= set(item.keys()) + + if common_keys: + # Try to sort by the first string key that exists in all items + for key in sorted(common_keys, key=str.lower): + try: + if all(isinstance(item.get(key), str) for item in sorted_list): + return sorted(sorted_list, key=lambda x: x[key].lower()) + elif all(isinstance(item.get(key), (int, float)) for item in sorted_list): + return sorted(sorted_list, key=lambda x: x[key]) + except (KeyError, AttributeError, TypeError): + continue + + # If we can't sort meaningfully, return as-is but with sorted elements + return sorted_list + + except (TypeError, AttributeError): + # If sorting fails, return the list with recursively sorted elements + return sorted_list + + else: + # For primitive types, return as-is + return data + + +def dump_sorted_json(data: Any, file_path: Union[str, Path], **kwargs) -> None: + """ + Dump JSON data to file with consistent deep sorting. + + Args: + data: The data to dump + file_path: Path to output file + **kwargs: Additional arguments for json.dump (indent, ensure_ascii, etc.) + """ + # Set default formatting options + format_options = { + 'indent': 2, + 'ensure_ascii': False, + 'sort_keys': True, # This is redundant since we deep sort, but kept for safety + } + format_options.update(kwargs) + + # Deep sort the data + sorted_data = deep_sort_data(data) + + # Write to file + file_path = Path(file_path) + file_path.parent.mkdir(parents=True, exist_ok=True) + + with open(file_path, 'w', encoding='utf-8') as f: + json.dump(sorted_data, f, **format_options) + + +def dumps_sorted_json(data: Any, **kwargs) -> str: + """ + Dump JSON data to string with consistent deep sorting. + + Args: + data: The data to dump + **kwargs: Additional arguments for json.dumps + + Returns: + JSON string with sorted data + """ + # Set default formatting options + format_options = { + 'indent': 2, + 'ensure_ascii': False, + 'sort_keys': True, + } + format_options.update(kwargs) + + # Deep sort the data + sorted_data = deep_sort_data(data) + + return json.dumps(sorted_data, **format_options) + + +def load_and_sort_json_file(file_path: Union[str, Path]) -> Any: + """ + Load a JSON file and return its contents with deep sorting applied. + + Args: + file_path: Path to the JSON file + + Returns: + The loaded and sorted data + """ + with open(file_path, 'r', encoding='utf-8') as f: + data = json.load(f) + + return deep_sort_data(data) + + +def sort_json_file_inplace(file_path: Union[str, Path]) -> bool: + """ + Sort a JSON file in place. + + Args: + file_path: Path to the JSON file + + Returns: + True if the file was modified, False if it was already sorted + """ + file_path = Path(file_path) + + # Load original data + with open(file_path, 'r', encoding='utf-8') as f: + original_data = json.load(f) + + # Sort the data + sorted_data = deep_sort_data(original_data) + + # Check if data changed + if json.dumps(original_data, sort_keys=True) == json.dumps(sorted_data, sort_keys=True): + return False + + # Save sorted data + dump_sorted_json(sorted_data, file_path) + return True diff --git a/utils/py/manage_kdf_tags.py b/utils/py/manage_kdf_tags.py new file mode 100755 index 000000000..74a77fee4 --- /dev/null +++ b/utils/py/manage_kdf_tags.py @@ -0,0 +1,260 @@ +#!/usr/bin/env python3 +""" +CLI utility for managing KDF method tags using the TagManager. + +This script provides a convenient interface to analyze and apply automatic tags +to KDF methods based on their characteristics. +""" + +import argparse +import sys +import json +import logging +from pathlib import Path + +# Add lib path +sys.path.append(str(Path(__file__).parent / "lib")) + +from managers.tag_manager import TagManager + + +def setup_logging(verbose: bool = False) -> None: + """Setup logging configuration.""" + log_level = logging.INFO if verbose else logging.DEBUG + logging.basicConfig( + level=log_level, + format='%(levelname)s: %(message)s' + ) + + +def get_default_paths() -> tuple[Path, Path]: + """Get default paths for KDF methods and requests.""" + script_dir = Path(__file__).parent + project_root = script_dir.parent.parent + + # Default to v2 file; tool can still accept overrides via --kdf-methods + kdf_methods_path = project_root / "src" / "data" / "kdf_methods_v2.json" + requests_base_path = project_root / "src" / "data" / "requests" / "kdf" + + return kdf_methods_path, requests_base_path + + +def cmd_stats(args) -> None: + """Show tag statistics.""" + tag_manager = TagManager(args.kdf_methods, args.requests_base) + stats = tag_manager.get_tag_statistics() + print(json.dumps(stats, indent=2)) + + +def cmd_preview(args) -> None: + """Preview tag changes.""" + tag_manager = TagManager(args.kdf_methods, args.requests_base) + + if args.method: + try: + preview = tag_manager.preview_tag_changes(args.method) + print(json.dumps(preview, indent=2)) + except ValueError as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + else: + changes = tag_manager.apply_derived_tags(dry_run=True) + + print(f"Summary:") + print(f" Methods that would be modified: {changes['methods_modified']}") + print(f" Tags that would be added: {changes['tags_added']}") + print(f" Tags that would be removed: {changes['tags_removed']}") + + if args.detailed and changes['modifications']: + print(f"\nDetailed changes:") + for method_name, method_changes in changes['modifications'].items(): + print(f"\n{method_name}:") + print(f" Current tags: {method_changes['old_tags']}") + print(f" Would add: {method_changes['added_tags']}") + print(f" Would remove: {method_changes['removed_tags']}") + print(f" Final tags: {method_changes['new_tags']}") + + +def cmd_apply(args) -> None: + """Apply tag changes.""" + tag_manager = TagManager(args.kdf_methods, args.requests_base) + + if not args.confirm: + print("This will modify the KDF methods file. Use --confirm to proceed.") + sys.exit(1) + + print("Applying tag changes...") + changes = tag_manager.apply_derived_tags(dry_run=False) + + print(f"Completed!") + print(f" Modified methods: {changes['methods_modified']}") + print(f" Added tags: {changes['tags_added']}") + print(f" Removed tags: {changes['tags_removed']}") + + if changes['modifications']: + print(f"\nBackup created at: {tag_manager.kdf_methods_path}.backup") + + +def cmd_analyze(args) -> None: + """Analyze specific tagging rules.""" + tag_manager = TagManager(args.kdf_methods, args.requests_base) + + analysis = { + "total_methods": len(tag_manager.kdf_methods), + "rule_analysis": {} + } + + # Analyze each rule + rules = { + "v2": "Methods with mmrpc 2.0 requests", + "task-based": "Methods with names starting with 'task::'", + "single_wallet_type": "Methods with exactly one wallet type", + "single_environment": "Methods with exactly one environment", + "trezor": "Methods referencing Trezor", + "metamask": "Methods referencing MetaMask" + } + + derived_tags = tag_manager.derive_tags_for_all_methods() + + for rule_name, rule_desc in rules.items(): + methods_with_rule = [] + for method_name, tags in derived_tags.items(): + if rule_name in tags: + methods_with_rule.append(method_name) + elif rule_name == "single_wallet_type": + # Check for any wallet type tags + method_data = tag_manager.kdf_methods[method_name] + wallet_tag = tag_manager._get_single_wallet_type_tag(method_data) + if wallet_tag: + methods_with_rule.append(method_name) + elif rule_name == "single_environment": + # Check for any environment tags + method_data = tag_manager.kdf_methods[method_name] + env_tag = tag_manager._get_single_environment_tag(method_data) + if env_tag: + methods_with_rule.append(method_name) + + analysis["rule_analysis"][rule_name] = { + "description": rule_desc, + "count": len(methods_with_rule), + "methods": methods_with_rule if args.detailed else methods_with_rule[:5] + } + + print(json.dumps(analysis, indent=2)) + + +def main(): + """Main CLI entry point.""" + parser = argparse.ArgumentParser( + description="Manage KDF method tags automatically", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Show current tag statistics + %(prog)s stats + + # Preview what changes would be made + %(prog)s preview + + # Preview changes for a specific method + %(prog)s preview --method "task::enable_eth::init" + + # Show detailed analysis of tagging rules + %(prog)s analyze --detailed + + # Apply all derived tags (creates backup) + %(prog)s apply --confirm + """ + ) + + # Get default paths + default_kdf_methods, default_requests_base = get_default_paths() + + parser.add_argument( + "--kdf-methods", + default=default_kdf_methods, + type=Path, + help=f"Path to kdf methods directory or file (default: {default_kdf_methods})" + ) + parser.add_argument( + "--requests-base", + default=default_requests_base, + type=Path, + help=f"Path to requests base directory (default: {default_requests_base})" + ) + parser.add_argument( + "--verbose", "-v", + action="store_true", + help="Enable verbose logging" + ) + + subparsers = parser.add_subparsers(dest="command", help="Available commands") + + # Stats command + stats_parser = subparsers.add_parser("stats", help="Show tag statistics") + + # Preview command + preview_parser = subparsers.add_parser("preview", help="Preview tag changes") + preview_parser.add_argument( + "--method", + help="Preview changes for specific method only" + ) + preview_parser.add_argument( + "--detailed", + action="store_true", + help="Show detailed changes for all methods" + ) + + # Apply command + apply_parser = subparsers.add_parser("apply", help="Apply tag changes") + apply_parser.add_argument( + "--confirm", + action="store_true", + help="Confirm that you want to apply changes" + ) + + # Analyze command + analyze_parser = subparsers.add_parser("analyze", help="Analyze tagging rules") + analyze_parser.add_argument( + "--detailed", + action="store_true", + help="Show all methods for each rule" + ) + + args = parser.parse_args() + + if not args.command: + parser.print_help() + sys.exit(1) + + setup_logging(args.verbose) + + # Validate paths + if not args.kdf_methods.exists(): + print(f"Error: KDF methods file not found: {args.kdf_methods}", file=sys.stderr) + sys.exit(1) + + if not args.requests_base.exists(): + print(f"Error: Requests base directory not found: {args.requests_base}", file=sys.stderr) + sys.exit(1) + + # Execute command + commands = { + "stats": cmd_stats, + "preview": cmd_preview, + "apply": cmd_apply, + "analyze": cmd_analyze + } + + try: + commands[args.command](args) + except Exception as e: + logging.error(f"Command failed: {e}") + if args.verbose: + import traceback + traceback.print_exc() + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/utils/py/update_request_nodes.py b/utils/py/update_request_nodes.py index cf9bf68c1..8cf2c77d9 100755 --- a/utils/py/update_request_nodes.py +++ b/utils/py/update_request_nodes.py @@ -16,360 +16,55 @@ import sys import argparse import logging -import urllib.request -import random from pathlib import Path from typing import Dict, List, Any, Optional +# Add lib path for utilities +sys.path.append(str(Path(__file__).parent / "lib")) +from utils.json_utils import dump_sorted_json +sys.path.append(str(Path(__file__).parent / "lib" / "managers")) +from coins_config_manager import CoinsConfigManager, CoinProtocolInfo +from activation_manager import ActivationRequestBuilder +sys.path.append(str(Path(__file__).parent / "lib" / "models")) +from kdf_method import extract_method_from_request, extract_ticker_from_request + # Configure logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) -# URL to fetch the latest coins configuration -COINS_CONFIG_URL = "https://raw.githubusercontent.com/KomodoPlatform/coins/master/utils/coins_config.json" - def fetch_coins_config() -> Dict[str, Any]: - """Fetch the latest coins configuration from the coins repository""" + """Fetch coins configuration via CoinsConfigManager (with caching and normalization).""" try: - logger.info(f"Fetching coins configuration from {COINS_CONFIG_URL}") - with urllib.request.urlopen(COINS_CONFIG_URL) as response: - data = json.loads(response.read().decode('utf-8')) - logger.info(f"Successfully fetched configuration for {len(data)} coins") + workspace_root = Path(__file__).parent.parent.parent + manager = CoinsConfigManager(workspace_root) + data = manager.get_coins_config() + logger.info(f"Successfully loaded configuration for {len(data)} coins (via CoinsConfigManager)") return data except Exception as e: - logger.error(f"Failed to fetch coins configuration: {e}") + logger.error(f"Failed to load coins configuration via CoinsConfigManager: {e}") raise -def extract_method_from_request(request_data: Dict[str, Any]) -> Optional[str]: - """Extract the method name from a request object""" - if isinstance(request_data, dict) and 'method' in request_data: - return request_data['method'] - return None -def extract_ticker_from_request(request_data: Dict[str, Any]) -> Optional[str]: - """Extract the ticker symbol from a request object""" - # Look for ticker in params - if 'params' in request_data: - params = request_data['params'] - if isinstance(params, dict): - if 'ticker' in params: - return params['ticker'] - elif 'coin' in params: - return params['coin'] - - # Look for ticker in other common locations - elif 'ticker' in request_data: - return request_data['ticker'] - elif 'coin' in request_data: - return request_data['coin'] - - return None -def select_preferred_servers(servers: List[Dict[str, Any]], max_count: int = 3) -> List[Dict[str, Any]]: - """Select up to max_count servers, preferring cipig/komodo domains""" - if len(servers) <= max_count: - return servers - - # Separate servers into priority and non-priority - priority_servers = [] - regular_servers = [] - - for server in servers: - url = server.get('url', '') - if 'cipig' in url.lower() or 'komodo' in url.lower(): - priority_servers.append(server) - else: - regular_servers.append(server) - - selected_servers = [] - - # First, add priority servers (up to max_count) - if priority_servers: - if len(priority_servers) <= max_count: - selected_servers.extend(priority_servers) - else: - # Randomly select from priority servers - selected_servers.extend(random.sample(priority_servers, max_count)) - - # If we need more servers and have regular ones available - remaining_slots = max_count - len(selected_servers) - if remaining_slots > 0 and regular_servers: - if len(regular_servers) <= remaining_slots: - selected_servers.extend(regular_servers) - else: - # Randomly select from regular servers - selected_servers.extend(random.sample(regular_servers, remaining_slots)) - - logger.debug(f"Selected {len(selected_servers)} servers from {len(servers)} available ({len(priority_servers)} priority, {len(regular_servers)} regular)") - return selected_servers +def detect_coin_protocol_info(manager: CoinsConfigManager, ticker: str) -> CoinProtocolInfo: + """Use CoinsConfigManager to determine protocol info for a ticker.""" + return manager.get_protocol_info(ticker) -def select_preferred_urls(urls: List[str], max_count: int = 3) -> List[str]: - """Select up to max_count URLs, preferring cipig/komodo domains""" - if len(urls) <= max_count: - return urls - - # Separate URLs into priority and non-priority - priority_urls = [] - regular_urls = [] - - for url in urls: - if 'cipig' in url.lower() or 'komodo' in url.lower(): - priority_urls.append(url) - else: - regular_urls.append(url) - - selected_urls = [] - - # First, add priority URLs (up to max_count) - if priority_urls: - if len(priority_urls) <= max_count: - selected_urls.extend(priority_urls) - else: - # Randomly select from priority URLs - selected_urls.extend(random.sample(priority_urls, max_count)) - - # If we need more URLs and have regular ones available - remaining_slots = max_count - len(selected_urls) - if remaining_slots > 0 and regular_urls: - if len(regular_urls) <= remaining_slots: - selected_urls.extend(regular_urls) - else: - # Randomly select from regular URLs - selected_urls.extend(random.sample(regular_urls, remaining_slots)) - - logger.debug(f"Selected {len(selected_urls)} URLs from {len(urls)} available ({len(priority_urls)} priority, {len(regular_urls)} regular)") - return selected_urls - -def detect_coin_protocol(coin_config: Dict[str, Any]) -> str: - """Detect the coin protocol type from the coin configuration""" - if 'protocol' in coin_config: - protocol_type = coin_config['protocol'].get('type', '').upper() - if protocol_type in ['TENDERMINT', 'COSMOS']: - return 'TENDERMINT' - elif protocol_type in ['UTXO', 'QTUM', 'BCH']: - return 'UTXO' - elif protocol_type in ['ZHTLC', 'ZEC']: - return 'ZHTLC' - elif protocol_type in ['ETH', 'ERC20', 'MATIC', 'BNB', 'AVAX', 'FTM', 'ONE']: - return 'ETH' - - # Fallback: detect by available server types - if 'rpc_urls' in coin_config: - return 'TENDERMINT' - elif 'light_wallet_d_servers' in coin_config: - return 'ZHTLC' - elif 'electrum' in coin_config: - return 'UTXO' - elif 'nodes' in coin_config: - return 'ETH' - - return 'UNKNOWN' - -def update_tendermint_nodes(request_data: Dict[str, Any], coin_config: Dict[str, Any], ticker: str) -> bool: - """Update Tendermint coin nodes (rpc_urls โ†’ nodes)""" - if 'rpc_urls' not in coin_config: - logger.warning(f"No rpc_urls found for Tendermint ticker '{ticker}' in coins configuration") - return False - - # Select up to 3 preferred RPC URLs and convert to nodes format - selected_rpc_urls = select_preferred_servers(coin_config['rpc_urls'], max_count=3) - - # Convert selected rpc_urls to nodes format (preserve all fields) - new_nodes = [] - for rpc_url in selected_rpc_urls: - node = {"url": rpc_url["url"]} - # Preserve additional fields like api_url, grpc_url, ws_url, komodo_proxy - for field in ['api_url', 'grpc_url', 'ws_url', 'komodo_proxy']: - if field in rpc_url: - node[field] = rpc_url[field] - new_nodes.append(node) - - # Update nodes in params - if 'params' in request_data and isinstance(request_data['params'], dict): - params = request_data['params'] - if 'nodes' in params: - old_nodes = params['nodes'] - params['nodes'] = new_nodes - logger.info(f"Updated Tendermint nodes for ticker '{ticker}': {len(old_nodes)} -> {len(new_nodes)} nodes") - return True - - # Check root level for nodes - if 'nodes' in request_data: - old_nodes = request_data['nodes'] - request_data['nodes'] = new_nodes - logger.info(f"Updated Tendermint nodes for ticker '{ticker}': {len(old_nodes)} -> {len(new_nodes)} nodes") - return True - - return False +def update_tendermint_nodes(request_data: Dict[str, Any], arb: ActivationRequestBuilder, ticker: str) -> bool: + protocol_info = arb.coins_config.get_protocol_info(ticker) + return arb.update_tendermint_nodes_in_request(request_data, protocol_info, ticker) -def update_utxo_electrum_servers(request_data: Dict[str, Any], coin_config: Dict[str, Any], ticker: str) -> bool: - """Update UTXO coin electrum servers (electrum โ†’ servers)""" - if 'electrum' not in coin_config: - logger.warning(f"No electrum servers found for UTXO ticker '{ticker}' in coins configuration") - return False - - # Select up to 3 preferred electrum servers and convert to servers format - selected_electrum = select_preferred_servers(coin_config['electrum'], max_count=3) - - # Convert selected electrum to servers format - new_servers = [] - for electrum in selected_electrum: - server = {"url": electrum["url"]} - # Preserve protocol if specified - if 'protocol' in electrum: - server['protocol'] = electrum['protocol'] - # Add other optional fields - for field in ['ws_url', 'disable_cert_verification']: - if field in electrum: - server[field] = electrum[field] - new_servers.append(server) - - # Look for electrum servers nested in mode.rpc_data.servers (common pattern) - if 'params' in request_data and isinstance(request_data['params'], dict): - params = request_data['params'] - - # Handle nested activation_params.mode.rpc_data.servers - if 'activation_params' in params and 'mode' in params['activation_params']: - mode = params['activation_params']['mode'] - if 'rpc_data' in mode and 'servers' in mode['rpc_data']: - old_servers = mode['rpc_data']['servers'] - mode['rpc_data']['servers'] = new_servers - logger.info(f"Updated UTXO electrum servers for ticker '{ticker}': {len(old_servers)} -> {len(new_servers)} servers") - return True - - # Handle direct mode.rpc_data.servers - if 'mode' in params and 'rpc_data' in params['mode']: - rpc_data = params['mode']['rpc_data'] - if 'servers' in rpc_data: - old_servers = rpc_data['servers'] - rpc_data['servers'] = new_servers - logger.info(f"Updated UTXO electrum servers for ticker '{ticker}': {len(old_servers)} -> {len(new_servers)} servers") - return True - else: - # Legacy method - if request_data['method'] == 'electrum': - old_servers = request_data['servers'] - request_data['servers'] = new_servers - logger.info(f"Updated UTXO electrum servers for ticker '{ticker}': {len(old_servers)} -> {len(new_servers)} servers") - return True - elif request_data['method'] == 'enable': - if 'urls' in request_data: - old_servers = request_data['urls'] - request_data['urls'] = [ i['url'] for i in new_servers ] - logger.info(f"Updated UTXO electrum urls for ticker '{ticker}': {len(old_servers)} -> {len(new_servers)} servers") - return True - return False +def update_utxo_electrum_servers(request_data: Dict[str, Any], arb: ActivationRequestBuilder, ticker: str) -> bool: + protocol_info = arb.coins_config.get_protocol_info(ticker) + return arb.update_utxo_electrum_in_request(request_data, protocol_info, ticker) -def update_zhtlc_servers(request_data: Dict[str, Any], coin_config: Dict[str, Any], ticker: str) -> bool: - """Update ZHTLC coin servers (light_wallet_d_servers and electrum)""" - updated = False - - # Update light_wallet_d_servers (select up to 3) - if 'light_wallet_d_servers' in coin_config: - new_lwd_servers = select_preferred_urls(coin_config['light_wallet_d_servers'], max_count=3) - - # Look for light_wallet_d_servers in nested structure - if 'params' in request_data and isinstance(request_data['params'], dict): - params = request_data['params'] - - # Handle nested activation_params.mode.rpc_data.light_wallet_d_servers - if 'activation_params' in params and 'mode' in params['activation_params']: - mode = params['activation_params']['mode'] - if 'rpc_data' in mode and 'light_wallet_d_servers' in mode['rpc_data']: - old_lwd = mode['rpc_data']['light_wallet_d_servers'] - mode['rpc_data']['light_wallet_d_servers'] = new_lwd_servers - logger.info(f"Updated ZHTLC light_wallet_d_servers for ticker '{ticker}': {len(old_lwd)} -> {len(new_lwd_servers)} servers") - updated = True - - # Handle direct mode.rpc_data.light_wallet_d_servers - elif 'mode' in params and 'rpc_data' in params['mode']: - rpc_data = params['mode']['rpc_data'] - if 'light_wallet_d_servers' in rpc_data: - old_lwd = rpc_data['light_wallet_d_servers'] - rpc_data['light_wallet_d_servers'] = new_lwd_servers - logger.info(f"Updated ZHTLC light_wallet_d_servers for ticker '{ticker}': {len(old_lwd)} -> {len(new_lwd_servers)} servers") - updated = True - - # Update electrum_servers (from electrum field in coins_config, select up to 3) - if 'electrum' in coin_config: - # Select up to 3 preferred electrum servers - selected_electrum = select_preferred_servers(coin_config['electrum'], max_count=3) - - # Convert selected electrum to electrum_servers format (simpler than UTXO) - new_electrum_servers = [] - for electrum in selected_electrum: - server = {"url": electrum["url"]} - if 'protocol' in electrum: - server['protocol'] = electrum['protocol'] - if 'ws_url' in electrum: - server['ws_url'] = electrum['ws_url'] - new_electrum_servers.append(server) - - # Look for electrum_servers in nested structure - if 'params' in request_data and isinstance(request_data['params'], dict): - params = request_data['params'] - - # Handle nested activation_params.mode.rpc_data.electrum_servers - if 'activation_params' in params and 'mode' in params['activation_params']: - mode = params['activation_params']['mode'] - if 'rpc_data' in mode and 'electrum_servers' in mode['rpc_data']: - old_electrum = mode['rpc_data']['electrum_servers'] - mode['rpc_data']['electrum_servers'] = new_electrum_servers - logger.info(f"Updated ZHTLC electrum_servers for ticker '{ticker}': {len(old_electrum)} -> {len(new_electrum_servers)} servers") - updated = True - - # Handle direct mode.rpc_data.electrum_servers - elif 'mode' in params and 'rpc_data' in params['mode']: - rpc_data = params['mode']['rpc_data'] - if 'electrum_servers' in rpc_data: - old_electrum = rpc_data['electrum_servers'] - rpc_data['electrum_servers'] = new_electrum_servers - logger.info(f"Updated ZHTLC electrum_servers for ticker '{ticker}': {len(old_electrum)} -> {len(new_electrum_servers)} servers") - updated = True - - return updated +def update_zhtlc_servers(request_data: Dict[str, Any], arb: ActivationRequestBuilder, ticker: str) -> bool: + protocol_info = arb.coins_config.get_protocol_info(ticker) + return arb.update_zhtlc_in_request(request_data, protocol_info, ticker) -def update_eth_nodes(request_data: Dict[str, Any], coin_config: Dict[str, Any], ticker: str) -> bool: - """Update ETH-like coin nodes (nodes โ†’ nodes) - original functionality""" - if 'nodes' not in coin_config: - logger.warning(f"No nodes found for ETH ticker '{ticker}' in coins configuration") - return False - - # Select up to 3 preferred nodes and convert coins_config node format to request format - selected_nodes = select_preferred_servers(coin_config['nodes'], max_count=3) - - new_nodes = [] - for node in selected_nodes: - request_node = {"url": node["url"]} - # Preserve other fields that might be present - for field in ['ws_url', 'komodo_proxy']: - if field in node: - request_node[field] = node[field] - new_nodes.append(request_node) - - # Look for nodes in params first, then in the root of the request - if 'params' in request_data and isinstance(request_data['params'], dict): - params = request_data['params'] - if 'nodes' in params: - old_nodes = params['nodes'] - params['nodes'] = new_nodes - logger.info(f"Updated ETH nodes for ticker '{ticker}': {len(old_nodes)} -> {len(new_nodes)} nodes") - return True - - # Check root level for nodes - if 'nodes' in request_data: - old_nodes = request_data['nodes'] - request_data['nodes'] = new_nodes - logger.info(f"Updated ETH nodes for ticker '{ticker}': {len(old_nodes)} -> {len(new_nodes)} nodes") - return True - - elif request_data['method'] == 'enable': - if 'urls' in request_data: - old_urls = request_data['urls'] - request_data['urls'] = [ i['url'] for i in new_nodes ] - logger.info(f"Updated ETH nodes for ticker '{ticker}': {len(old_urls)} -> {len(new_nodes)} nodes") - return True - return False +def update_eth_nodes(request_data: Dict[str, Any], arb: ActivationRequestBuilder, ticker: str) -> bool: + protocol_info = arb.coins_config.get_protocol_info(ticker) + return arb.update_eth_nodes_in_request(request_data, protocol_info, ticker) def update_nodes_in_request(request_data: Dict[str, Any], coins_config: Dict[str, Any], request_name: str = "Unknown") -> bool: """ @@ -387,32 +82,32 @@ def update_nodes_in_request(request_data: Dict[str, Any], coins_config: Dict[str ticker = extract_ticker_from_request(request_data) if method: - logger.debug(f"Scanning method '{method}' in request '{request_name}'") + logger.info(f"Scanning method '{method}' in request '{request_name}'") else: - logger.debug(f"Scanning request '{request_name}' (no method field)") + logger.info(f"Scanning request '{request_name}' (no method field)") if not ticker: - logger.debug(f"No ticker found in request '{request_name}'") + logger.info(f"No ticker found in request '{request_name}'") return False if ticker not in coins_config: logger.warning(f"Ticker '{ticker}' not found in coins configuration") return False - coin_config = coins_config[ticker] - protocol = detect_coin_protocol(coin_config) - - logger.debug(f"Detected protocol '{protocol}' for ticker '{ticker}'") - - # Route to appropriate update function based on protocol + # Use ActivationRequestBuilder to detect and update + workspace_root = Path(__file__).parent.parent.parent + arb = ActivationRequestBuilder(CoinsConfigManager(workspace_root), "") + protocol_info = arb.coins_config.get_protocol_info(ticker) + protocol = protocol_info.protocol_type or 'UNKNOWN' + logger.info(f"Detected protocol '{protocol}' for ticker '{ticker}' via CoinsConfigManager") if protocol == 'TENDERMINT': - return update_tendermint_nodes(request_data, coin_config, ticker) + return update_tendermint_nodes(request_data, arb, ticker) elif protocol == 'UTXO': - return update_utxo_electrum_servers(request_data, coin_config, ticker) + return update_utxo_electrum_servers(request_data, arb, ticker) elif protocol == 'ZHTLC': - return update_zhtlc_servers(request_data, coin_config, ticker) + return update_zhtlc_servers(request_data, arb, ticker) elif protocol == 'ETH': - return update_eth_nodes(request_data, coin_config, ticker) + return update_eth_nodes(request_data, arb, ticker) else: logger.warning(f"Unknown or unsupported protocol '{protocol}' for ticker '{ticker}'") return False @@ -439,6 +134,11 @@ def process_request_file(input_file: Path, output_file: Optional[Path] = None) - if isinstance(request_data, dict): for key, request_obj in request_data.items(): if isinstance(request_obj, dict): + # Set transient __wasm flag based on request key naming + if isinstance(key, str) and "wasm" in key.lower(): + request_obj["__wasm"] = True + if isinstance(request_obj.get("params"), dict): + request_obj["params"]["__wasm"] = True if update_nodes_in_request(request_obj, coins_config, key): updates_made += 1 method = extract_method_from_request(request_obj) @@ -446,6 +146,10 @@ def process_request_file(input_file: Path, output_file: Optional[Path] = None) - logger.info(f"Updated request object '{key}' (method: {method})") else: logger.info(f"Updated request object: {key}") + # Remove transient __wasm flags before saving + request_obj.pop("__wasm", None) + if isinstance(request_obj.get("params"), dict): + request_obj["params"].pop("__wasm", None) elif isinstance(request_data, list): # Handle array of requests for i, request_obj in enumerate(request_data): @@ -474,8 +178,7 @@ def process_request_file(input_file: Path, output_file: Optional[Path] = None) - # Write the updated data try: - with open(output_file, 'w', encoding='utf-8') as f: - json.dump(request_data, f, indent=2, ensure_ascii=False) + dump_sorted_json(request_data, output_file, ensure_ascii=False) logger.info(f"Saved updated file: {output_file}") except Exception as e: logger.error(f"Failed to write output file {output_file}: {e}") @@ -498,7 +201,7 @@ def main(): args = parser.parse_args() if args.verbose: - logging.getLogger().setLevel(logging.DEBUG) + logging.getLogger().setLevel(logging.INFO) input_file = Path(args.input_file) output_file = Path(args.output_file) if args.output_file else None diff --git a/utils/py/validate_kdf_responses.py b/utils/py/validate_kdf_responses.py deleted file mode 100644 index 0135afcb2..000000000 --- a/utils/py/validate_kdf_responses.py +++ /dev/null @@ -1,448 +0,0 @@ -#!/usr/bin/env python3 -""" -KDF Responses Validation Script - -Validates the structure and content of KDF response JSON files to ensure -they follow the expected format for the KdfResponses component. - -Usage: - python validate_responses/kdf.py - -Features: -- Validates JSON structure and syntax -- Checks required fields and data types -- Validates response categories (success/error) -- Ensures consistent naming conventions -- Provides detailed error reporting -- Optional auto-fix for minor formatting issues -""" - -import json -import os -import sys -from pathlib import Path -from typing import Dict, List, Tuple, Any, Optional -import argparse -import re - - -class ValidationError: - def __init__(self, file_path: str, error_type: str, message: str, location: str = ""): - self.file_path = file_path - self.error_type = error_type - self.message = message - self.location = location - - def __str__(self): - location_str = f" [{self.location}]" if self.location else "" - return f"[{self.error_type}] {self.file_path}{location_str}: {self.message}" - - -class KdfResponseValidator: - def __init__(self): - self.errors: List[ValidationError] = [] - self.warnings: List[ValidationError] = [] - self.fixes_applied: List[str] = [] - - # Valid response types - self.valid_response_types = {'success', 'error'} - - # Valid request key pattern (alphanumeric, PascalCase with optional leading numeric) - self.request_key_pattern = re.compile(r'^[A-Z0-9][a-zA-Z0-9]*$') - - def validate_all(self) -> Tuple[bool, List[ValidationError], List[ValidationError]]: - """Validate all KDF response files.""" - base_path = Path('src/data/responses/kdf') - - if not base_path.exists(): - self.errors.append(ValidationError( - str(base_path), - "MISSING_DIRECTORY", - "KDF responses directory does not exist" - )) - return False, self.errors, self.warnings - - # Validate legacy and v2 directories - for version in ['legacy', 'v2']: - version_path = base_path / version - if version_path.exists(): - self._validate_directory(version_path, version) - else: - self.errors.append(ValidationError( - str(version_path), - "MISSING_DIRECTORY", - f"Missing {version} directory" - )) - - # Check request/response alignment - self._validate_request_response_alignment() - - return len(self.errors) == 0, self.errors, self.warnings - - def _validate_directory(self, dir_path: Path, version: str): - """Validate all JSON files in a directory.""" - json_files = list(dir_path.glob('*.json')) - - if not json_files: - self.warnings.append(ValidationError( - str(dir_path), - "EMPTY_DIRECTORY", - f"No JSON files found in {version} directory" - )) - return - - for json_file in json_files: - self._validate_file(json_file, version) - - def _validate_file(self, file_path: Path, version: str): - """Validate a single JSON file.""" - try: - with open(file_path, 'r', encoding='utf-8') as f: - content = f.read().strip() - - if not content: - self.errors.append(ValidationError( - str(file_path), - "EMPTY_FILE", - "File is empty" - )) - return - - # Parse JSON - try: - data = json.loads(content) - except json.JSONDecodeError as e: - self.errors.append(ValidationError( - str(file_path), - "INVALID_JSON", - f"JSON syntax error: {e.msg} at line {e.lineno}, column {e.colno}" - )) - return - - # Validate structure - self._validate_file_structure(file_path, data) - - except Exception as e: - self.errors.append(ValidationError( - str(file_path), - "FILE_ERROR", - f"Error reading file: {str(e)}" - )) - - def _validate_file_structure(self, file_path: Path, data: Dict): - """Validate the overall structure of a response file.""" - if not data: - self.warnings.append(ValidationError( - str(file_path), - "EMPTY_DATA", - "File contains no request definitions" - )) - return - - # Validate each request key and its responses - for request_key, responses in data.items(): - self._validate_request_key(file_path, request_key) - self._validate_response_structure(file_path, request_key, responses) - - def _validate_request_key(self, file_path: Path, request_key: str): - """Validate request key naming convention.""" - - if not self.request_key_pattern.match(request_key): - self.errors.append(ValidationError( - str(file_path), - "INVALID_KEY_FORMAT", - f"Request key '{request_key}' should follow PascalCase/camelCase pattern", - request_key - )) - - # Check for common issues - if request_key.lower() != request_key and request_key.upper() != request_key: - if '_' in request_key: - self.warnings.append(ValidationError( - str(file_path), - "KEY_STYLE_WARNING", - f"Request key '{request_key}' contains underscores, consider camelCase", - request_key - )) - - def _validate_response_structure(self, file_path: Path, request_key: str, responses: Any): - """Validate the structure of responses for a request key.""" - if not isinstance(responses, dict): - self.errors.append(ValidationError( - str(file_path), - "INVALID_RESPONSES_TYPE", - f"Responses must be an object, got {type(responses).__name__}", - request_key - )) - return - - # Check for required response types - has_success = 'success' in responses - has_error = 'error' in responses - - if not has_success and not has_error: - self.errors.append(ValidationError( - str(file_path), - "MISSING_RESPONSE_TYPES", - "Must have at least 'success' or 'error' responses", - request_key - )) - return - - # Validate each response type - for response_type, response_list in responses.items(): - if response_type not in self.valid_response_types: - self.errors.append(ValidationError( - str(file_path), - "INVALID_RESPONSE_TYPE", - f"Invalid response type '{response_type}', must be 'success' or 'error'", - f"{request_key}.{response_type}" - )) - continue - - self._validate_response_list(file_path, request_key, response_type, response_list) - - def _validate_response_list(self, file_path: Path, request_key: str, response_type: str, response_list: Any): - """Validate a list of responses.""" - if not isinstance(response_list, list): - self.errors.append(ValidationError( - str(file_path), - "INVALID_RESPONSE_LIST", - f"Response list must be an array, got {type(response_list).__name__}", - f"{request_key}.{response_type}" - )) - return - - if not response_list: - self.warnings.append(ValidationError( - str(file_path), - "EMPTY_RESPONSE_LIST", - f"Empty {response_type} response list", - f"{request_key}.{response_type}" - )) - return - - for idx, response in enumerate(response_list): - self._validate_response_item(file_path, request_key, response_type, idx, response) - - def _validate_response_item(self, file_path: Path, request_key: str, response_type: str, idx: int, response: Any): - """Validate a single response item.""" - location = f"{request_key}.{response_type}[{idx}]" - - if not isinstance(response, dict): - self.errors.append(ValidationError( - str(file_path), - "INVALID_RESPONSE_ITEM", - f"Response item must be an object, got {type(response).__name__}", - location - )) - return - - # Check required fields - required_fields = {'title', 'json'} - missing_fields = required_fields - set(response.keys()) - - if missing_fields: - self.errors.append(ValidationError( - str(file_path), - "MISSING_REQUIRED_FIELDS", - f"Missing required fields: {', '.join(missing_fields)}", - location - )) - - # Validate individual fields - if 'title' in response: - self._validate_title_field(file_path, location, response['title']) - - if 'notes' in response: - self._validate_notes_field(file_path, location, response['notes']) - - if 'json' in response: - self._validate_json_field(file_path, location, response['json']) - - def _validate_title_field(self, file_path: Path, location: str, title: Any): - """Validate the title field.""" - if not isinstance(title, str): - self.errors.append(ValidationError( - str(file_path), - "INVALID_TITLE_TYPE", - f"Title must be a string, got {type(title).__name__}", - f"{location}.title" - )) - return - - if not title.strip(): - self.errors.append(ValidationError( - str(file_path), - "EMPTY_TITLE", - "Title cannot be empty", - f"{location}.title" - )) - - def _validate_notes_field(self, file_path: Path, location: str, notes: Any): - """Validate the notes field.""" - if not isinstance(notes, str): - self.errors.append(ValidationError( - str(file_path), - "INVALID_NOTES_TYPE", - f"Notes must be a string, got {type(notes).__name__}", - f"{location}.notes" - )) - - def _validate_json_field(self, file_path: Path, location: str, json_data: Any): - """Validate the json field.""" - if json_data is None: - self.errors.append(ValidationError( - str(file_path), - "NULL_JSON_DATA", - "JSON field cannot be null", - f"{location}.json" - )) - return - - # JSON field should be a valid JSON structure (object, array, etc.) - if not isinstance(json_data, (dict, list, str, int, float, bool)): - self.errors.append(ValidationError( - str(file_path), - "INVALID_JSON_TYPE", - f"JSON field contains invalid type: {type(json_data).__name__}", - f"{location}.json" - )) - - # For API responses, usually expect objects - if isinstance(json_data, dict): - # Common validation for API response format - if 'mmrpc' in json_data: - # V2 API format validation - if json_data.get('mmrpc') != '2.0': - self.warnings.append(ValidationError( - str(file_path), - "UNEXPECTED_MMRPC_VERSION", - f"Expected mmrpc version '2.0', got '{json_data.get('mmrpc')}'", - f"{location}.json.mmrpc" - )) - - def _validate_request_response_alignment(self): - """Validate that requests have corresponding responses and vice versa.""" - # Load request data - requests_by_version = {} - for version in ['legacy', 'v2']: - requests_path = Path(f'src/data/requests/kdf/{version}') - if requests_path.exists(): - requests_by_version[version] = self._load_request_keys(requests_path) - - # Load response data - responses_by_version = {} - for version in ['legacy', 'v2']: - responses_path = Path(f'src/data/responses/kdf/{version}') - if responses_path.exists(): - responses_by_version[version] = self._load_response_keys(responses_path) - - # Compare and report mismatches - for version in ['legacy', 'v2']: - request_keys = requests_by_version.get(version, set()) - response_keys = responses_by_version.get(version, set()) - - # Requests without responses - missing_responses = request_keys - response_keys - for key in missing_responses: - self.warnings.append(ValidationError( - f"src/data/responses/kdf/{version}/", - "MISSING_RESPONSE", - f"Request '{key}' exists but has no corresponding response data", - f"{version}/{key}" - )) - - # Responses without requests - missing_requests = response_keys - request_keys - for key in missing_requests: - self.warnings.append(ValidationError( - f"src/data/requests/kdf/{version}/", - "MISSING_REQUEST", - f"Response '{key}' exists but has no corresponding request data", - f"{version}/{key}" - )) - - def _load_request_keys(self, requests_path: Path) -> set: - """Load all request keys from requests directory.""" - request_keys = set() - try: - for json_file in requests_path.glob('*.json'): - with open(json_file, 'r', encoding='utf-8') as f: - data = json.load(f) - if isinstance(data, dict): - request_keys.update(data.keys()) - except Exception as e: - self.warnings.append(ValidationError( - str(requests_path), - "REQUEST_LOAD_ERROR", - f"Error loading request keys: {str(e)}" - )) - return request_keys - - def _load_response_keys(self, responses_path: Path) -> set: - """Load all response keys from responses directory.""" - response_keys = set() - try: - for json_file in responses_path.glob('*.json'): - with open(json_file, 'r', encoding='utf-8') as f: - data = json.load(f) - if isinstance(data, dict): - response_keys.update(data.keys()) - except Exception as e: - self.warnings.append(ValidationError( - str(responses_path), - "RESPONSE_LOAD_ERROR", - f"Error loading response keys: {str(e)}" - )) - return response_keys - - -def main(): - """Main execution function.""" - parser = argparse.ArgumentParser(description='Validate KDF response JSON files') - parser.add_argument('--verbose', '-v', action='store_true', - help='Show detailed output including warnings') - - args = parser.parse_args() - - # Change to repo root directory - script_dir = Path(__file__).parent - repo_root = script_dir.parent.parent - os.chdir(repo_root) - - print("๐Ÿ” Validating KDF response files...") - print(f"๐Ÿ“‚ Working directory: {os.getcwd()}") - - validator = KdfResponseValidator() - success, errors, warnings = validator.validate_all() - - # Report results - if errors: - print(f"\nโŒ Validation failed with {len(errors)} error(s):") - for error in errors: - print(f" {error}") - - if warnings and args.verbose: - print(f"\nโš ๏ธ {len(warnings)} warning(s):") - for warning in warnings: - print(f" {warning}") - - if validator.fixes_applied: - print(f"\n๐Ÿ”ง Applied {len(validator.fixes_applied)} fix(es):") - for fix in validator.fixes_applied: - print(f" {fix}") - - if success: - if warnings: - print(f"\nโœ… Validation passed with {len(warnings)} warning(s)") - else: - print("\nโœ… All validations passed!") - return 0 - else: - print(f"\nโŒ Validation failed") - return 1 - - -if __name__ == '__main__': - sys.exit(main()) \ No newline at end of file diff --git a/utils/py/validate_request_metadata.py b/utils/py/validate_request_metadata.py new file mode 100644 index 000000000..70613017f --- /dev/null +++ b/utils/py/validate_request_metadata.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python3 +""" +KDF Methods Metadata Validator - Ensures kdf_methods.json has proper tags and prerequisites. + +This script validates and automatically fixes kdf_methods.json to ensure all methods have: +- 'tags' list field with correct version-specific tags (v2/legacy) and deprecation status +- 'prerequisites' list field (initially empty) + +Request files should contain only the request body data. +This can be run standalone or integrated into other validation workflows. +""" + +import json +import sys +from pathlib import Path +from typing import Dict, List, Any, Tuple + +# Add lib path for utilities +sys.path.append(str(Path(__file__).parent / "lib")) +from utils.json_utils import dump_sorted_json + + +class KdfMethodsMetadataValidator: + """Validator for kdf_methods.json metadata fields (tags and prerequisites).""" + + def __init__(self, workspace_root: Path = None): + """Initialize the validator.""" + self.workspace_root = workspace_root or Path(__file__).parent.parent.parent + # Support new split files; operate on both without merging on disk + self.kdf_methods_dir = self.workspace_root / "src/data" + self.v2_file = self.kdf_methods_dir / "kdf_methods_v2.json" + self.legacy_file = self.kdf_methods_dir / "kdf_methods_legacy.json" + self.kdf_methods = self._load_kdf_methods() + self.fixes_applied = [] + self.errors = [] + self.warnings = [] + + def _load_kdf_methods(self) -> Dict[str, Any]: + """Load KDF methods configuration from both v2 and legacy files.""" + methods: Dict[str, Any] = {} + try: + if self.legacy_file.exists(): + with open(self.legacy_file, 'r', encoding='utf-8') as f: + legacy_cfg = json.load(f) + for name, cfg in legacy_cfg.items(): + if name in methods: + methods[f"legacy::{name}"] = cfg + else: + methods[name] = cfg + if self.v2_file.exists(): + with open(self.v2_file, 'r', encoding='utf-8') as f: + v2_cfg = json.load(f) + for name, cfg in v2_cfg.items(): + if name in methods: + methods[f"v2::{name}"] = cfg + else: + methods[name] = cfg + if not methods: + self.warnings.append("No kdf_methods_v2.json or kdf_methods_legacy.json found; nothing to validate") + return methods + except Exception as e: + self.errors.append(f"Error loading KDF methods: {e}") + return {} + + def _determine_version_from_examples(self, examples: Dict[str, str]) -> str: + """Determine version based on example naming patterns.""" + if not examples: + return "v2" # Default to v2 + + # Check if method has v2 or legacy examples by looking at example names + has_v2_examples = any(not key.startswith("Legacy") for key in examples.keys()) + has_legacy_examples = any(key.startswith("Legacy") for key in examples.keys()) + + # Prefer v2 if both exist + if has_v2_examples: + return "v2" + elif has_legacy_examples: + return "legacy" + else: + return "v2" # Default + + def _determine_tags(self, method_name: str, method_config: Dict[str, Any]) -> List[str]: + """Determine the correct tags for a method.""" + tags = [] + + # Determine version from examples + examples = method_config.get("examples", {}) + version = self._determine_version_from_examples(examples) + tags.append(version) + + # Check if method is deprecated + if method_config.get("deprecated", False): + tags.append("deprecated") + + return sorted(tags) # Sort alphabetically + + def validate_and_fix_kdf_methods(self) -> bool: + """Validate and fix kdf_methods.json metadata. Returns True if modified.""" + if not self.kdf_methods: + self.errors.append("No KDF methods loaded") + return False + + methods_modified = False + + for method_name, method_config in self.kdf_methods.items(): + if not isinstance(method_config, dict): + self.errors.append(f"Method '{method_name}' configuration must be a JSON object") + continue + + method_modified = False + + # Validate tags field + expected_tags = self._determine_tags(method_name, method_config) + + if "tags" not in method_config: + method_config["tags"] = expected_tags + method_modified = True + self.fixes_applied.append(f"Added tags {expected_tags} to method {method_name}") + elif not isinstance(method_config["tags"], list): + self.errors.append(f"Method '{method_name}' tags field must be a list") + else: + current_tags = sorted(method_config["tags"]) + if current_tags != expected_tags: + method_config["tags"] = expected_tags + method_modified = True + self.fixes_applied.append(f"Updated tags from {current_tags} to {expected_tags} for method {method_name}") + + # Validate prerequisites field + if "prerequisites" not in method_config: + method_config["prerequisites"] = [] + method_modified = True + self.fixes_applied.append(f"Added empty prerequisites to method {method_name}") + elif not isinstance(method_config["prerequisites"], list): + self.errors.append(f"Method '{method_name}' prerequisites field must be a list") + + if method_modified: + methods_modified = True + + # Save the file if it was modified + if methods_modified: + # Split and save back to their respective files based on tags + v2_methods: Dict[str, Any] = {} + legacy_methods: Dict[str, Any] = {} + for name, cfg in self.kdf_methods.items(): + tags = (cfg or {}).get('tags', []) + if 'legacy' in tags and 'v2' not in tags: + legacy_methods[name] = cfg + else: + v2_methods[name] = cfg + dump_sorted_json(v2_methods, self.v2_file) + dump_sorted_json(legacy_methods, self.legacy_file) + print(f"โœ… Fixed {self.v2_file} and {self.legacy_file}") + + return methods_modified + + def validate_kdf_methods_metadata(self) -> Dict[str, Any]: + """Validate kdf_methods.json metadata and return summary.""" + methods_modified = self.validate_and_fix_kdf_methods() + return self._create_summary(methods_modified) + + def _create_summary(self, methods_modified: bool = False) -> Dict[str, Any]: + """Create validation summary.""" + return { + "methods_count": len(self.kdf_methods), + "methods_modified": methods_modified, + "fixes_applied": self.fixes_applied, + "fix_count": len(self.fixes_applied), + "errors": self.errors, + "error_count": len(self.errors), + "warnings": self.warnings, + "warning_count": len(self.warnings), + "success": len(self.errors) == 0 + } + + +def validate_kdf_methods_metadata(workspace_root: Path = None, silent: bool = False) -> Dict[str, Any]: + """ + Validate KDF methods metadata (for integration with other scripts). + + Args: + workspace_root: Path to workspace root (defaults to auto-detect) + silent: If True, don't print progress messages + + Returns: + Dictionary with validation summary + """ + validator = KdfMethodsMetadataValidator(workspace_root) + summary = validator.validate_kdf_methods_metadata() + + if not silent and summary['methods_modified']: + print(f"โœ… KDF methods metadata validation: applied {summary['fix_count']} fixes") + + return summary + +# Keep old function name for backwards compatibility +def validate_request_metadata(workspace_root: Path = None, silent: bool = False) -> Dict[str, Any]: + """Backwards compatibility wrapper.""" + return validate_kdf_methods_metadata(workspace_root, silent) + + +def main(): + """Main function for standalone execution.""" + print("๐Ÿ” Validating KDF methods metadata (tags and prerequisites)...") + + validator = KdfMethodsMetadataValidator() + summary = validator.validate_kdf_methods_metadata() + + print(f"\n๐Ÿ“Š Validation Summary:") + print(f" Methods processed: {summary['methods_count']}") + print(f" Methods modified: {summary['methods_modified']}") + print(f" Fixes applied: {summary['fix_count']}") + print(f" Errors: {summary['error_count']}") + print(f" Warnings: {summary['warning_count']}") + + if summary['fixes_applied']: + print(f"\nโœ… Applied fixes:") + for fix in summary['fixes_applied']: + print(f" - {fix}") + + if summary['errors']: + print(f"\nโŒ Errors:") + for error in summary['errors']: + print(f" - {error}") + + if summary['warnings']: + print(f"\nโš ๏ธ Warnings:") + for warning in summary['warnings']: + print(f" - {warning}") + + if summary['success']: + if summary['methods_modified']: + print(f"\n๐ŸŽ‰ Successfully validated and fixed KDF methods metadata!") + else: + print(f"\nโœจ All KDF methods metadata is already properly validated!") + else: + print(f"\n๐Ÿ’ฅ Validation completed with {summary['error_count']} errors.") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/utils/run_tests.sh b/utils/run_tests.sh index 616cc84b3..3cb889b01 100755 --- a/utils/run_tests.sh +++ b/utils/run_tests.sh @@ -5,10 +5,10 @@ cd js && npm ci cd ../../ #node utils/js/get_file_author_data.js -node utils/js/validate_update_internal_links_userpass.js || exit 1 -node utils/js/file_presence_structure_checker.js || exit 1 -node utils/js/h1_presence_format_checker.js || exit 1 -node utils/js/validate_compact_table_data.js || exit 1 -node utils/js/ensure_changelog_update.js || exit 1 +time node utils/js/validate_update_internal_links_userpass.js || exit 1 +time node utils/js/file_presence_structure_checker.js || exit 1 +time node utils/js/h1_presence_format_checker.js || exit 1 +time node utils/js/validate_compact_table_data.js || exit 1 +time node utils/js/ensure_changelog_update.js || exit 1 #node utils/js/create_data_for_gpts.js #node utils/js/create_search_index.js diff --git a/utils/scripts/process_responses.py b/utils/scripts/process_responses.py new file mode 100644 index 000000000..f9dc3fa78 --- /dev/null +++ b/utils/scripts/process_responses.py @@ -0,0 +1,273 @@ +#!/usr/bin/env python3 +""" +Response processor script for KDF Postman test results. +Processes Newman JSON reports and generates structured response reports +following the existing coin_activation.json format. +""" + +import argparse +import json +import os +import sys +from datetime import datetime +from pathlib import Path +from typing import Dict, List, Any, Optional + + +def load_newman_report(file_path: str) -> Optional[Dict]: + """Load Newman JSON report from file.""" + try: + with open(file_path, 'r') as f: + return json.load(f) + except (FileNotFoundError, json.JSONDecodeError) as e: + print(f"Error loading Newman report {file_path}: {e}") + return None + + +def extract_method_from_request(request: Dict) -> str: + """Extract the KDF method name from a request.""" + try: + if 'body' in request and 'raw' in request['body']: + body = json.loads(request['body']['raw']) + return body.get('method', 'unknown_method') + except (json.JSONDecodeError, KeyError): + pass + + # Fallback to request name + return request.get('name', 'unknown_method') + + +def format_response_entry(execution: Dict, environment: str, wallet_type: str, timestamp: str) -> Dict: + """Format a single execution into the expected response format.""" + request = execution.get('request', {}) + response = execution.get('response', {}) + + method = extract_method_from_request(request) + + # Determine success/error status + is_success = response.get('code', 0) in [200, 201] and not execution.get('assertions', []) + + # Parse response body + response_body = {} + if 'body' in response: + try: + response_body = json.loads(response['body']) + except json.JSONDecodeError: + response_body = {"raw_response": response['body']} + + # Build the formatted entry + entry = { + "title": execution.get('item', {}).get('name', method), + "notes": f"Environment: {environment}, Wallet: {wallet_type}", + "json": response_body, + "metadata": { + "environment": environment, + "wallet_type": wallet_type, + "timestamp": timestamp, + "method": method, + "status_code": response.get('code', 0), + "response_time": response.get('responseTime', 0), + "request_url": response.get('originalRequest', {}).get('url', {}).get('raw', ''), + "test_passed": is_success + } + } + + return entry + + +def process_newman_report(report_path: str, environment: str, wallet_type: str, timestamp: str) -> Dict[str, Dict]: + """Process a Newman report and return structured response data.""" + report = load_newman_report(report_path) + if not report: + return {} + + responses = {} + + # Process each execution in the report + for execution in report.get('run', {}).get('executions', []): + method = extract_method_from_request(execution.get('request', {})) + + if method not in responses: + responses[method] = { + "success": [], + "error": [] + } + + entry = format_response_entry(execution, environment, wallet_type, timestamp) + + # Categorize as success or error + if entry["metadata"]["test_passed"]: + responses[method]["success"].append(entry) + else: + responses[method]["error"].append(entry) + + return responses + + +def merge_responses(existing: Dict, new: Dict) -> Dict: + """Merge new responses into existing response structure.""" + for method, data in new.items(): + if method not in existing: + existing[method] = {"success": [], "error": []} + + existing[method]["success"].extend(data.get("success", [])) + existing[method]["error"].extend(data.get("error", [])) + + return existing + + +def load_existing_responses(template_dir: str) -> Dict: + """Load existing response templates.""" + responses = {} + + # Dynamically discover all template files + template_paths = [] + + # Add v2 templates + v2_template_dir = os.path.join(template_dir, "kdf", "v2") + if os.path.exists(v2_template_dir): + template_paths.extend([ + os.path.join(v2_template_dir, f) for f in os.listdir(v2_template_dir) + if f.endswith('.json') + ]) + + # Add legacy templates + legacy_template_dir = os.path.join(template_dir, "kdf", "legacy") + if os.path.exists(legacy_template_dir): + template_paths.extend([ + os.path.join(legacy_template_dir, f) for f in os.listdir(legacy_template_dir) + if f.endswith('.json') + ]) + + # Add common templates + common_template_file = os.path.join(template_dir, "kdf", "common.json") + if os.path.exists(common_template_file): + template_paths.append(common_template_file) + + for path in template_paths: + if os.path.exists(path): + try: + with open(path, 'r') as f: + template_data = json.load(f) + responses.update(template_data) + except (FileNotFoundError, json.JSONDecodeError) as e: + print(f"Warning: Could not load template {path}: {e}") + + return responses + + +def cleanup_old_reports(output_dir: Path) -> None: + """Remove old report files, keeping only the 2 most recent of each type.""" + import glob + import os + + if not output_dir.exists(): + return + + # Define the report patterns to clean up + patterns = [ + 'postman_test_results_*.json', + 'test_summary_*.json' + ] + + for pattern in patterns: + # Find all files matching this pattern + files = list(output_dir.glob(pattern)) + + if len(files) <= 2: + continue # Keep all if 2 or fewer + + # Sort by modification time (newest first) + files.sort(key=lambda f: f.stat().st_mtime, reverse=True) + + # Keep the 2 most recent, delete the rest + files_to_keep = files[:2] + files_to_delete = files[2:] + + for old_file in files_to_delete: + try: + old_file.unlink() + print(f"Removed old report: {old_file.name}") + except OSError as e: + print(f"Warning: Could not remove {old_file.name}: {e}") + + +def main(): + parser = argparse.ArgumentParser(description='Process Newman test results into KDF response format') + parser.add_argument('--input-dir', required=True, help='Directory containing Newman reports') + parser.add_argument('--output-dir', required=True, help='Directory to write processed reports') + parser.add_argument('--template-dir', required=True, help='Directory containing response templates') + parser.add_argument('--timestamp', help='Timestamp for this test run (ISO format)') + + args = parser.parse_args() + + # Use provided timestamp or generate current one + timestamp = args.timestamp or datetime.utcnow().isoformat() + 'Z' + + # Load existing response templates + all_responses = load_existing_responses(args.template_dir) + + # Process each environment's results + input_path = Path(args.input_dir) + + # Environment mappings based on directory structure + env_configs = [ + ('native-hd', 'native_hd', 'hd'), + ('native-nonhd', 'native_iguana', 'iguana'), + ] + + for dir_name, environment, wallet_type in env_configs: + results_file = input_path / dir_name / 'results.json' + + if results_file.exists(): + print(f"Processing {environment} results...") + new_responses = process_newman_report( + str(results_file), + environment, + wallet_type, + timestamp + ) + all_responses = merge_responses(all_responses, new_responses) + else: + print(f"Warning: Results file not found: {results_file}") + + # Write the consolidated report + output_path = Path(args.output_dir) + output_path.mkdir(parents=True, exist_ok=True) + + # Clean up old reports - keep only the 2 most recent of each type + cleanup_old_reports(output_path) + + report_filename = f"postman_test_results_{timestamp.replace(':', '-').replace('T', '_')}.json" + output_file = output_path / report_filename + + with open(output_file, 'w') as f: + json.dump(all_responses, f, indent=2) + + print(f"Consolidated report written to: {output_file}") + + # Also write a summary + summary = { + "generated_at": timestamp, + "environments_tested": len([env for env, _, _ in env_configs]), + "total_methods": len(all_responses), + "summary_by_method": {} + } + + for method, data in all_responses.items(): + summary["summary_by_method"][method] = { + "success_count": len(data.get("success", [])), + "error_count": len(data.get("error", [])) + } + + summary_file = output_path / f"test_summary_{timestamp.replace(':', '-').replace('T', '_')}.json" + with open(summary_file, 'w') as f: + json.dump(summary, f, indent=2) + + print(f"Test summary written to: {summary_file}") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/utils/scripts/validate_postman.py b/utils/scripts/validate_postman.py new file mode 100755 index 000000000..c27d0fa9d --- /dev/null +++ b/utils/scripts/validate_postman.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +""" +Postman collection validator script. +Validates that the generated Postman collections are properly formatted +and contain the expected structure for KDF API testing. +""" + +import json +import sys +from pathlib import Path +from typing import Dict, List, Optional + + +def validate_collection_structure(collection: Dict) -> List[str]: + """Validate basic Postman collection structure.""" + errors = [] + + # Check required top-level fields + required_fields = ['info', 'item'] + for field in required_fields: + if field not in collection: + errors.append(f"Missing required field: {field}") + + # Validate info section + if 'info' in collection: + info = collection['info'] + if 'name' not in info: + errors.append("Collection info missing 'name' field") + if 'schema' not in info: + errors.append("Collection info missing 'schema' field") + + # Validate items structure + if 'item' in collection: + if not isinstance(collection['item'], list): + errors.append("Collection 'item' should be a list") + elif len(collection['item']) == 0: + errors.append("Collection has no items") + + return errors + + +def validate_environment_structure(environment: Dict) -> List[str]: + """Validate Postman environment structure.""" + errors = [] + + # Check required fields + required_fields = ['info', 'variable'] + for field in required_fields: + if field not in environment: + errors.append(f"Missing required field: {field}") + + # Validate variables + if 'variable' in environment: + variables = environment['variable'] + if not isinstance(variables, list): + errors.append("Environment 'variable' should be a list") + else: + # Check for required variables + var_keys = [var.get('key') for var in variables] + required_vars = ['base_url', 'userpass'] + for req_var in required_vars: + if req_var not in var_keys: + errors.append(f"Missing required variable: {req_var}") + + return errors + + +def validate_kdf_methods(collection: Dict) -> List[str]: + """Validate that collection contains expected KDF methods.""" + errors = [] + + # Extract all method names from requests + methods = set() + + def extract_methods_recursive(items): + for item in items: + if 'request' in item: + # Try to extract method from request body + request = item['request'] + if 'body' in request and 'raw' in request['body']: + try: + body = json.loads(request['body']['raw']) + if 'method' in body: + methods.add(body['method']) + except json.JSONDecodeError: + pass + + # Recursively check nested items + if 'item' in item: + extract_methods_recursive(item['item']) + + if 'item' in collection: + extract_methods_recursive(collection['item']) + + # Check for some expected KDF methods + expected_methods = [ + 'task::enable_eth::init', + 'task::enable_eth::status', + 'task::enable_utxo::init' + ] + + for method in expected_methods: + if method not in methods: + errors.append(f"Expected KDF method not found: {method}") + + if len(methods) == 0: + errors.append("No KDF methods found in collection") + + return errors + + +def validate_file(file_path: Path) -> Dict[str, List[str]]: + """Validate a single JSON file.""" + result = { + 'file': str(file_path), + 'errors': [], + 'warnings': [] + } + + try: + with open(file_path, 'r') as f: + data = json.load(f) + except json.JSONDecodeError as e: + result['errors'].append(f"Invalid JSON: {e}") + return result + except Exception as e: + result['errors'].append(f"Error reading file: {e}") + return result + + # Determine file type and validate accordingly + if file_path.name.endswith('_collection.json') or 'collection' in file_path.name: + # Postman collection + result['errors'].extend(validate_collection_structure(data)) + result['errors'].extend(validate_kdf_methods(data)) + elif file_path.name.endswith('_environment.json') or 'environment' in file_path.name: + # Postman environment + result['errors'].extend(validate_environment_structure(data)) + else: + result['warnings'].append("Unknown file type, performing basic JSON validation only") + + return result + + +def main(): + """Main validation function.""" + if len(sys.argv) > 1: + # Validate specific files + files_to_check = [Path(arg) for arg in sys.argv[1:]] + else: + # Default: validate all generated Postman files + postman_dir = Path(__file__).parent.parent.parent / 'postman' / 'generated' + if not postman_dir.exists(): + print(f"Error: Postman generated directory not found: {postman_dir}") + return 1 + + files_to_check = list(postman_dir.glob('**/*.json')) + + if not files_to_check: + print("No JSON files found to validate") + return 1 + + total_errors = 0 + total_warnings = 0 + + print("๐Ÿงช Validating Postman Collections and Environments") + print("=" * 50) + + for file_path in files_to_check: + if not file_path.exists(): + print(f"โŒ File not found: {file_path}") + total_errors += 1 + continue + + result = validate_file(file_path) + + # Display results + status = "โœ…" if not result['errors'] else "โŒ" + print(f"{status} {result['file']}") + + if result['errors']: + total_errors += len(result['errors']) + for error in result['errors']: + print(f" โŒ {error}") + + if result['warnings']: + total_warnings += len(result['warnings']) + for warning in result['warnings']: + print(f" โš ๏ธ {warning}") + + if not result['errors'] and not result['warnings']: + print(" โœ… All validations passed") + + # Summary + print("\n" + "=" * 50) + print(f"๐Ÿ“Š Validation Summary:") + print(f" Files checked: {len(files_to_check)}") + print(f" Total errors: {total_errors}") + print(f" Total warnings: {total_warnings}") + + if total_errors > 0: + print("\nโŒ Validation failed with errors") + return 1 + else: + print("\nโœ… All validations passed!") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/utils/test_ui.sh b/utils/test_ui.sh new file mode 100755 index 000000000..ae149c23a --- /dev/null +++ b/utils/test_ui.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -e + +MDX_BRANCH=$(git branch --show-current) +UI_BRANCH=test-ui +echo "UI branch: $UI_BRANCH" +echo "MDX branch: $MDX_BRANCH" + +cd ../../komodo-docs-revamp-2023 +git checkout dev +git pull + +# Uncomment this to delete the branch +# Leave it uncommented to keep local changes to the branch +git branch -D $UI_BRANCH || true + +git checkout -b $UI_BRANCH || true +cd utils +./update_mdx_branch.sh $MDX_BRANCH +cd .. +./update-content.sh +yarn build + +