cryptoadvance-specter 2.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cryptoadvance/specter/__init__.py +0 -0
- cryptoadvance/specter/__main__.py +7 -0
- cryptoadvance/specter/_version.py +34 -0
- cryptoadvance/specter/api/__init__.py +18 -0
- cryptoadvance/specter/api/rest/__init__.py +0 -0
- cryptoadvance/specter/api/rest/api.py +83 -0
- cryptoadvance/specter/api/rest/base.py +92 -0
- cryptoadvance/specter/api/rest/resource_healthz.py +42 -0
- cryptoadvance/specter/api/rest/resource_jwt.py +135 -0
- cryptoadvance/specter/api/rest/resource_psbt.py +53 -0
- cryptoadvance/specter/api/rest/resource_specter.py +46 -0
- cryptoadvance/specter/api/rest/resource_txlist.py +34 -0
- cryptoadvance/specter/api/security.py +73 -0
- cryptoadvance/specter/api/templates/api.html +18 -0
- cryptoadvance/specter/api/views.py +11 -0
- cryptoadvance/specter/cli/__init__.py +36 -0
- cryptoadvance/specter/cli/cli_ext.py +193 -0
- cryptoadvance/specter/cli/cli_gunicorn.py +61 -0
- cryptoadvance/specter/cli/cli_noded.py +425 -0
- cryptoadvance/specter/cli/cli_server.py +279 -0
- cryptoadvance/specter/cli/utils.py +65 -0
- cryptoadvance/specter/commands/psbt_creator.py +360 -0
- cryptoadvance/specter/commands/utxo_scanner.py +250 -0
- cryptoadvance/specter/config.py +298 -0
- cryptoadvance/specter/device.py +208 -0
- cryptoadvance/specter/devices/__init__.py +34 -0
- cryptoadvance/specter/devices/bitbox02.py +20 -0
- cryptoadvance/specter/devices/bitcoin_core.py +314 -0
- cryptoadvance/specter/devices/cobo.py +68 -0
- cryptoadvance/specter/devices/coldcard.py +63 -0
- cryptoadvance/specter/devices/elements_core.py +59 -0
- cryptoadvance/specter/devices/generic.py +19 -0
- cryptoadvance/specter/devices/hwi/__init__.py +4 -0
- cryptoadvance/specter/devices/hwi/jade.py +766 -0
- cryptoadvance/specter/devices/hwi/jadepy/__init__.py +4 -0
- cryptoadvance/specter/devices/hwi/jadepy/jade.py +2195 -0
- cryptoadvance/specter/devices/hwi/jadepy/jade_error.py +31 -0
- cryptoadvance/specter/devices/hwi/jadepy/jade_serial.py +85 -0
- cryptoadvance/specter/devices/hwi/jadepy/jade_tcp.py +65 -0
- cryptoadvance/specter/devices/hwi/keepkey.py +219 -0
- cryptoadvance/specter/devices/hwi/specter_diy.py +416 -0
- cryptoadvance/specter/devices/hwi_device.py +21 -0
- cryptoadvance/specter/devices/jade.py +100 -0
- cryptoadvance/specter/devices/keepkey.py +15 -0
- cryptoadvance/specter/devices/keystone.py +54 -0
- cryptoadvance/specter/devices/ledger.py +10 -0
- cryptoadvance/specter/devices/passport.py +7 -0
- cryptoadvance/specter/devices/sd_card_device.py +12 -0
- cryptoadvance/specter/devices/seedsigner.py +22 -0
- cryptoadvance/specter/devices/specter.py +172 -0
- cryptoadvance/specter/devices/trezor.py +15 -0
- cryptoadvance/specter/gunicorn.py +33 -0
- cryptoadvance/specter/helpers.py +350 -0
- cryptoadvance/specter/htmlsafebabel.py +34 -0
- cryptoadvance/specter/hwi_rpc.py +596 -0
- cryptoadvance/specter/hwi_server.py +117 -0
- cryptoadvance/specter/internal_node.py +268 -0
- cryptoadvance/specter/key.py +209 -0
- cryptoadvance/specter/liquid/__init__.py +0 -0
- cryptoadvance/specter/liquid/addresslist.py +63 -0
- cryptoadvance/specter/liquid/rpc.py +519 -0
- cryptoadvance/specter/liquid/txlist.py +219 -0
- cryptoadvance/specter/liquid/util/__init__.py +0 -0
- cryptoadvance/specter/liquid/util/pset.py +200 -0
- cryptoadvance/specter/liquid/wallet.py +305 -0
- cryptoadvance/specter/managers/config_manager.py +341 -0
- cryptoadvance/specter/managers/device_manager.py +143 -0
- cryptoadvance/specter/managers/genericdata_manager.py +88 -0
- cryptoadvance/specter/managers/node_manager.py +288 -0
- cryptoadvance/specter/managers/otp_manager.py +49 -0
- cryptoadvance/specter/managers/service_manager/__init__.py +5 -0
- cryptoadvance/specter/managers/service_manager/callback_executor.py +160 -0
- cryptoadvance/specter/managers/service_manager/service_manager.py +606 -0
- cryptoadvance/specter/managers/user_manager.py +108 -0
- cryptoadvance/specter/managers/wallet_manager.py +527 -0
- cryptoadvance/specter/node.py +783 -0
- cryptoadvance/specter/persistence.py +305 -0
- cryptoadvance/specter/process_controller/__init__.py +0 -0
- cryptoadvance/specter/process_controller/bitcoind_controller.py +87 -0
- cryptoadvance/specter/process_controller/elementsd_controller.py +93 -0
- cryptoadvance/specter/process_controller/node_controller.py +593 -0
- cryptoadvance/specter/rpc.py +543 -0
- cryptoadvance/specter/server.py +375 -0
- cryptoadvance/specter/server_endpoints/__init__.py +18 -0
- cryptoadvance/specter/server_endpoints/auth.py +272 -0
- cryptoadvance/specter/server_endpoints/controller.py +307 -0
- cryptoadvance/specter/server_endpoints/devices.py +541 -0
- cryptoadvance/specter/server_endpoints/filters.py +160 -0
- cryptoadvance/specter/server_endpoints/nodes.py +576 -0
- cryptoadvance/specter/server_endpoints/price.py +51 -0
- cryptoadvance/specter/server_endpoints/settings.py +756 -0
- cryptoadvance/specter/server_endpoints/setup.py +216 -0
- cryptoadvance/specter/server_endpoints/wallets/__init__.py +1 -0
- cryptoadvance/specter/server_endpoints/wallets/wallets.py +987 -0
- cryptoadvance/specter/server_endpoints/wallets/wallets_api.py +1163 -0
- cryptoadvance/specter/server_endpoints/wallets/wallets_vm.py +16 -0
- cryptoadvance/specter/server_endpoints/welcome/__init__.py +1 -0
- cryptoadvance/specter/server_endpoints/welcome/welcome.py +129 -0
- cryptoadvance/specter/server_endpoints/welcome/welcome_vm.py +17 -0
- cryptoadvance/specter/services/__init__.py +5 -0
- cryptoadvance/specter/services/callbacks.py +126 -0
- cryptoadvance/specter/services/controller.py +91 -0
- cryptoadvance/specter/services/extension_gen.py +239 -0
- cryptoadvance/specter/services/service.py +255 -0
- cryptoadvance/specter/services/service_annotations_storage.py +72 -0
- cryptoadvance/specter/services/service_encrypted_storage.py +217 -0
- cryptoadvance/specter/services/templates/components/menu_item.jinja +19 -0
- cryptoadvance/specter/services/templates/includes/services-data.html +15 -0
- cryptoadvance/specter/services/templates/services/associate_addr.jinja +20 -0
- cryptoadvance/specter/specter.py +817 -0
- cryptoadvance/specter/specter_error.py +65 -0
- cryptoadvance/specter/static/bcur/base58.min.js +1 -0
- cryptoadvance/specter/static/bcur/buffer.min.js +1 -0
- cryptoadvance/specter/static/bcur/urlib.min.js +23 -0
- cryptoadvance/specter/static/bitcoin-release-pubkey.asc +784 -0
- cryptoadvance/specter/static/favicon.js +22 -0
- cryptoadvance/specter/static/fonts/RobotoMono-Bold.ttf +0 -0
- cryptoadvance/specter/static/fonts/RobotoMono-Regular.ttf +0 -0
- cryptoadvance/specter/static/fonts/Social-Bold.otf +0 -0
- cryptoadvance/specter/static/fonts/Social-Medium.otf +0 -0
- cryptoadvance/specter/static/fonts/Social-Regular.otf +0 -0
- cryptoadvance/specter/static/helpers.js +214 -0
- cryptoadvance/specter/static/hwi.js +205 -0
- cryptoadvance/specter/static/img/add-person.svg +1 -0
- cryptoadvance/specter/static/img/alert.svg +3 -0
- cryptoadvance/specter/static/img/arrow-right.svg +4 -0
- cryptoadvance/specter/static/img/backspace.svg +1 -0
- cryptoadvance/specter/static/img/bitcoin-logo.svg +6 -0
- cryptoadvance/specter/static/img/broken-connection.svg +55 -0
- cryptoadvance/specter/static/img/caret-down.svg +3 -0
- cryptoadvance/specter/static/img/caret-up.svg +3 -0
- cryptoadvance/specter/static/img/check.svg +3 -0
- cryptoadvance/specter/static/img/check_thick.svg +3 -0
- cryptoadvance/specter/static/img/checkbox-tick.svg +1 -0
- cryptoadvance/specter/static/img/checkbox-untick.svg +1 -0
- cryptoadvance/specter/static/img/clear-character.svg +3 -0
- cryptoadvance/specter/static/img/clock.svg +3 -0
- cryptoadvance/specter/static/img/close.svg +1 -0
- cryptoadvance/specter/static/img/copy-color.svg +61 -0
- cryptoadvance/specter/static/img/copy.svg +4 -0
- cryptoadvance/specter/static/img/cross.svg +4 -0
- cryptoadvance/specter/static/img/cross_thick.svg +4 -0
- cryptoadvance/specter/static/img/devices/bitbox02_icon.svg +11 -0
- cryptoadvance/specter/static/img/devices/bitcoincore_icon.svg +11 -0
- cryptoadvance/specter/static/img/devices/cobo_icon.svg +11 -0
- cryptoadvance/specter/static/img/devices/coldcard_icon.svg +26 -0
- cryptoadvance/specter/static/img/devices/elementscore_icon.svg +49 -0
- cryptoadvance/specter/static/img/devices/hwi_icon.svg +15 -0
- cryptoadvance/specter/static/img/devices/jade_icon.svg +14 -0
- cryptoadvance/specter/static/img/devices/keepkey_icon.svg +13 -0
- cryptoadvance/specter/static/img/devices/keystone_icon.svg +14 -0
- cryptoadvance/specter/static/img/devices/ledger_icon.svg +14 -0
- cryptoadvance/specter/static/img/devices/other_icon.svg +15 -0
- cryptoadvance/specter/static/img/devices/passport_icon.svg +66 -0
- cryptoadvance/specter/static/img/devices/seedsigner_icon.svg +9 -0
- cryptoadvance/specter/static/img/devices/specter_icon.svg +16 -0
- cryptoadvance/specter/static/img/devices/trezor_icon.svg +11 -0
- cryptoadvance/specter/static/img/disconnected.svg +1 -0
- cryptoadvance/specter/static/img/down-arrow.svg +39 -0
- cryptoadvance/specter/static/img/edit.svg +3 -0
- cryptoadvance/specter/static/img/exit.svg +5 -0
- cryptoadvance/specter/static/img/expand-less.svg +1 -0
- cryptoadvance/specter/static/img/expand-more.svg +1 -0
- cryptoadvance/specter/static/img/failed.svg +63 -0
- cryptoadvance/specter/static/img/favicon-dark-mode.png +0 -0
- cryptoadvance/specter/static/img/favicon-light-mode.png +0 -0
- cryptoadvance/specter/static/img/file.svg +3 -0
- cryptoadvance/specter/static/img/flip-horizontal.svg +6 -0
- cryptoadvance/specter/static/img/gear.svg +3 -0
- cryptoadvance/specter/static/img/generate_icon.svg +14 -0
- cryptoadvance/specter/static/img/ghost.png +0 -0
- cryptoadvance/specter/static/img/ghost_3d.png +0 -0
- cryptoadvance/specter/static/img/ghost_3d_transparent.png +0 -0
- cryptoadvance/specter/static/img/github.svg +2 -0
- cryptoadvance/specter/static/img/hidden.svg +4 -0
- cryptoadvance/specter/static/img/icon.icns +0 -0
- cryptoadvance/specter/static/img/icon.ico +0 -0
- cryptoadvance/specter/static/img/icon.png +0 -0
- cryptoadvance/specter/static/img/info_sign.svg +4 -0
- cryptoadvance/specter/static/img/key.svg +3 -0
- cryptoadvance/specter/static/img/light-bulb.svg +48 -0
- cryptoadvance/specter/static/img/liquid-logo.svg +121 -0
- cryptoadvance/specter/static/img/loader.gif +0 -0
- cryptoadvance/specter/static/img/loader_boxes.svg +17 -0
- cryptoadvance/specter/static/img/love.png +0 -0
- cryptoadvance/specter/static/img/menu.svg +5 -0
- cryptoadvance/specter/static/img/mixed-clock.svg +79 -0
- cryptoadvance/specter/static/img/mixed.svg +9 -0
- cryptoadvance/specter/static/img/no-dollars.svg +3 -0
- cryptoadvance/specter/static/img/not-supported.svg +52 -0
- cryptoadvance/specter/static/img/note.svg +85 -0
- cryptoadvance/specter/static/img/other.svg +15 -0
- cryptoadvance/specter/static/img/party.png +0 -0
- cryptoadvance/specter/static/img/plus.svg +4 -0
- cryptoadvance/specter/static/img/preferences_tab_screenshot.png +0 -0
- cryptoadvance/specter/static/img/qr-code.svg +27 -0
- cryptoadvance/specter/static/img/radio-button-running-node.svg +1 -0
- cryptoadvance/specter/static/img/radio-button-selected-node.svg +1 -0
- cryptoadvance/specter/static/img/receive-clock.svg +57 -0
- cryptoadvance/specter/static/img/receive.svg +4 -0
- cryptoadvance/specter/static/img/refresh.svg +1 -0
- cryptoadvance/specter/static/img/sd-card.svg +3 -0
- cryptoadvance/specter/static/img/send-clock.svg +57 -0
- cryptoadvance/specter/static/img/send.svg +4 -0
- cryptoadvance/specter/static/img/snowflake.svg +8 -0
- cryptoadvance/specter/static/img/specter.svg +247 -0
- cryptoadvance/specter/static/img/tag.svg +1 -0
- cryptoadvance/specter/static/img/tor.svg +31 -0
- cryptoadvance/specter/static/img/transfer-clock.svg +82 -0
- cryptoadvance/specter/static/img/transfer.svg +5 -0
- cryptoadvance/specter/static/img/twitter.svg +1 -0
- cryptoadvance/specter/static/img/two-keys.svg +4 -0
- cryptoadvance/specter/static/img/usb.svg +4 -0
- cryptoadvance/specter/static/img/v1-icons/icon.icns +0 -0
- cryptoadvance/specter/static/img/v1-icons/icon.ico +0 -0
- cryptoadvance/specter/static/img/v1-icons/icon.png +0 -0
- cryptoadvance/specter/static/img/visible.svg +3 -0
- cryptoadvance/specter/static/img/warning_sign.svg +4 -0
- cryptoadvance/specter/static/output.css +2462 -0
- cryptoadvance/specter/static/pdf/jspdf.es.js +36077 -0
- cryptoadvance/specter/static/pdf/jspdf.es.js.map +1 -0
- cryptoadvance/specter/static/pdf/jspdf.es.min.js +507 -0
- cryptoadvance/specter/static/pdf/jspdf.es.min.js.map +1 -0
- cryptoadvance/specter/static/pdf/polyfills.es.js +62 -0
- cryptoadvance/specter/static/progress-wizard.min.css +1 -0
- cryptoadvance/specter/static/pruned-node-today-release-pubkey.asc +12 -0
- cryptoadvance/specter/static/qr/qr-scanner-worker.min.js +86 -0
- cryptoadvance/specter/static/qr/qr-scanner.min.js +12 -0
- cryptoadvance/specter/static/qr/qr-scanner.min.js.map +1 -0
- cryptoadvance/specter/static/qr/qrcode.min.js +1 -0
- cryptoadvance/specter/static/style.css +244 -0
- cryptoadvance/specter/static/styles.css +1585 -0
- cryptoadvance/specter/static/torbrowser-release-pubkey.asc +332 -0
- cryptoadvance/specter/static/typography.css +20 -0
- cryptoadvance/specter/templates/500.jinja +35 -0
- cryptoadvance/specter/templates/500_timeout.jinja +35 -0
- cryptoadvance/specter/templates/base.jinja +168 -0
- cryptoadvance/specter/templates/components/editable_title.jinja +42 -0
- cryptoadvance/specter/templates/components/explorer_select.jinja +28 -0
- cryptoadvance/specter/templates/components/network_label.jinja +17 -0
- cryptoadvance/specter/templates/components/price_bar.jinja +246 -0
- cryptoadvance/specter/templates/device/components/add_keys.js +25 -0
- cryptoadvance/specter/templates/device/components/device_type.jinja +13 -0
- cryptoadvance/specter/templates/device/device.jinja +259 -0
- cryptoadvance/specter/templates/device/device_blinding_key.jinja +101 -0
- cryptoadvance/specter/templates/device/new_device/new_device_keys.jinja +545 -0
- cryptoadvance/specter/templates/device/new_device/new_device_mnemonic.jinja +188 -0
- cryptoadvance/specter/templates/device/new_device/new_device_type.jinja +63 -0
- cryptoadvance/specter/templates/device/new_device_manual.jinja +458 -0
- cryptoadvance/specter/templates/hwi_bridge.jinja +34 -0
- cryptoadvance/specter/templates/includes/address-data.html +151 -0
- cryptoadvance/specter/templates/includes/address-label.html +311 -0
- cryptoadvance/specter/templates/includes/address-row.html +174 -0
- cryptoadvance/specter/templates/includes/addresses-table.html +512 -0
- cryptoadvance/specter/templates/includes/asset-label.html +248 -0
- cryptoadvance/specter/templates/includes/coin_selection.html +187 -0
- cryptoadvance/specter/templates/includes/dnd-textarea.html +153 -0
- cryptoadvance/specter/templates/includes/explorer-link.html +38 -0
- cryptoadvance/specter/templates/includes/fee-selection.html +418 -0
- cryptoadvance/specter/templates/includes/file-uploader.html +79 -0
- cryptoadvance/specter/templates/includes/helpers.jinja +81 -0
- cryptoadvance/specter/templates/includes/hwi/components/passphrase.jinja +29 -0
- cryptoadvance/specter/templates/includes/hwi/components/pin.jinja +101 -0
- cryptoadvance/specter/templates/includes/hwi/components/select_device.jinja +155 -0
- cryptoadvance/specter/templates/includes/hwi/components/wallet.jinja +131 -0
- cryptoadvance/specter/templates/includes/hwi/hwi.jinja +230 -0
- cryptoadvance/specter/templates/includes/language/language_js.jinja +33 -0
- cryptoadvance/specter/templates/includes/language/language_select.jinja +11 -0
- cryptoadvance/specter/templates/includes/merkletooltip.html +12 -0
- cryptoadvance/specter/templates/includes/message-box.html +100 -0
- cryptoadvance/specter/templates/includes/message-events.js +9 -0
- cryptoadvance/specter/templates/includes/overlay/broadcast_tx.jinja +17 -0
- cryptoadvance/specter/templates/includes/overlay/key_export_qr.jinja +74 -0
- cryptoadvance/specter/templates/includes/overlay/liquid_assets_registry.html +135 -0
- cryptoadvance/specter/templates/includes/overlay/overlay.html +107 -0
- cryptoadvance/specter/templates/includes/overlay/qr_code_sign.jinja +38 -0
- cryptoadvance/specter/templates/includes/overlay/qr_code_sign_message.jinja +38 -0
- cryptoadvance/specter/templates/includes/overlay/sd_card_sign.jinja +27 -0
- cryptoadvance/specter/templates/includes/overlay/sign_tx_method.jinja +125 -0
- cryptoadvance/specter/templates/includes/page-limit-select.html +10 -0
- cryptoadvance/specter/templates/includes/qr-code.html +436 -0
- cryptoadvance/specter/templates/includes/qr-scanner.html +235 -0
- cryptoadvance/specter/templates/includes/recipient-box.html +506 -0
- cryptoadvance/specter/templates/includes/sidebar/components/node_connection.jinja +51 -0
- cryptoadvance/specter/templates/includes/sidebar/components/node_select_popup.jinja +102 -0
- cryptoadvance/specter/templates/includes/sidebar/components/sidebar_btn.jinja +15 -0
- cryptoadvance/specter/templates/includes/sidebar/components/sidebar_device_list_item.jinja +17 -0
- cryptoadvance/specter/templates/includes/sidebar/components/sidebar_services_list.jinja +10 -0
- cryptoadvance/specter/templates/includes/sidebar/components/sidebar_wallet_list_item.jinja +93 -0
- cryptoadvance/specter/templates/includes/sidebar/components/wallet_type_svg.jinja +11 -0
- cryptoadvance/specter/templates/includes/sidebar/sidebar.jinja +361 -0
- cryptoadvance/specter/templates/includes/text-explainer.html +72 -0
- cryptoadvance/specter/templates/includes/tool-tip.html +179 -0
- cryptoadvance/specter/templates/includes/tx-data.html +279 -0
- cryptoadvance/specter/templates/includes/tx-row.html +471 -0
- cryptoadvance/specter/templates/includes/tx-table.html +1187 -0
- cryptoadvance/specter/templates/login.jinja +21 -0
- cryptoadvance/specter/templates/node/components/bitcoin_core_info.jinja +202 -0
- cryptoadvance/specter/templates/node/components/no_tx_hint.jinja +8 -0
- cryptoadvance/specter/templates/node/components/node_logo.jinja +7 -0
- cryptoadvance/specter/templates/node/internal_node_logs.jinja +21 -0
- cryptoadvance/specter/templates/node/internal_node_settings.jinja +54 -0
- cryptoadvance/specter/templates/node/node_settings.jinja +249 -0
- cryptoadvance/specter/templates/register.jinja +43 -0
- cryptoadvance/specter/templates/services/choose.jinja +238 -0
- cryptoadvance/specter/templates/services/components/plugin_card.jinja +16 -0
- cryptoadvance/specter/templates/services/components/wishlist.jinja +6 -0
- cryptoadvance/specter/templates/services/inject_in_basejinja_body_bottom.jinja +8 -0
- cryptoadvance/specter/templates/services/inject_in_basejinja_body_top.jinja +8 -0
- cryptoadvance/specter/templates/services/inject_in_basejinja_head.jinja +8 -0
- cryptoadvance/specter/templates/settings/auth_settings.jinja +161 -0
- cryptoadvance/specter/templates/settings/components/settings_menu.jinja +32 -0
- cryptoadvance/specter/templates/settings/components/settings_menu_item.jinja +15 -0
- cryptoadvance/specter/templates/settings/general_settings.jinja +266 -0
- cryptoadvance/specter/templates/settings/hwi_settings.jinja +86 -0
- cryptoadvance/specter/templates/settings/tor_settings.jinja +212 -0
- cryptoadvance/specter/templates/setup/bitcoind.jinja +45 -0
- cryptoadvance/specter/templates/setup/bitcoind_datadir.jinja +188 -0
- cryptoadvance/specter/templates/setup/end.jinja +8 -0
- cryptoadvance/specter/templates/setup/node_type.jinja +17 -0
- cryptoadvance/specter/templates/setup/setup_page.jinja +78 -0
- cryptoadvance/specter/templates/setup/start.jinja +17 -0
- cryptoadvance/specter/templates/setup/tor.jinja +52 -0
- cryptoadvance/specter/templates/wallet/addresses/wallet_addresses.jinja +25 -0
- cryptoadvance/specter/templates/wallet/components/editable_label.jinja +41 -0
- cryptoadvance/specter/templates/wallet/components/explorer_link.jinja +15 -0
- cryptoadvance/specter/templates/wallet/components/wallet_menu.jinja +32 -0
- cryptoadvance/specter/templates/wallet/components/wallet_menu_item.jinja +21 -0
- cryptoadvance/specter/templates/wallet/components/wallet_pdf.jinja +259 -0
- cryptoadvance/specter/templates/wallet/components/wallet_tab.jinja +14 -0
- cryptoadvance/specter/templates/wallet/history/components/total_wallet_balances.jinja +153 -0
- cryptoadvance/specter/templates/wallet/history/wallet_history.jinja +37 -0
- cryptoadvance/specter/templates/wallet/new_wallet/components/import_wallet_account_map.jinja +117 -0
- cryptoadvance/specter/templates/wallet/new_wallet/import_wallet.jinja +70 -0
- cryptoadvance/specter/templates/wallet/new_wallet/new_wallet.jinja +76 -0
- cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja +309 -0
- cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_type.jinja +60 -0
- cryptoadvance/specter/templates/wallet/overview/balance_overview.jinja +17 -0
- cryptoadvance/specter/templates/wallet/overview/header_and_summary.jinja +1 -0
- cryptoadvance/specter/templates/wallet/overview/tx_table.jinja +18 -0
- cryptoadvance/specter/templates/wallet/overview/wallets_overview.jinja +26 -0
- cryptoadvance/specter/templates/wallet/receive/wallet_receive.jinja +193 -0
- cryptoadvance/specter/templates/wallet/send/components/send_nav.jinja +20 -0
- cryptoadvance/specter/templates/wallet/send/import/wallet_importpsbt.jinja +63 -0
- cryptoadvance/specter/templates/wallet/send/new/wallet_send.jinja +653 -0
- cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_item.jinja +53 -0
- cryptoadvance/specter/templates/wallet/send/pending/components/pending_psbt_table.jinja +35 -0
- cryptoadvance/specter/templates/wallet/send/pending/wallet_sendpending.jinja +12 -0
- cryptoadvance/specter/templates/wallet/send/sign/wallet_send_sign_psbt.jinja +493 -0
- cryptoadvance/specter/templates/wallet/settings/components/export_wallet_account_map.jinja +34 -0
- cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja +486 -0
- cryptoadvance/specter/templates/welcome/components/get_started.jinja +26 -0
- cryptoadvance/specter/templates/welcome/components/remaining_remarks.jinja +16 -0
- cryptoadvance/specter/templates/welcome/components/specter_remote.jinja +12 -0
- cryptoadvance/specter/templates/welcome/components/tick_checkboxes.jinja +102 -0
- cryptoadvance/specter/templates/welcome/welcome.jinja +21 -0
- cryptoadvance/specter/tor_daemon.py +108 -0
- cryptoadvance/specter/translations/bg/LC_MESSAGES/messages.po +4374 -0
- cryptoadvance/specter/translations/de/LC_MESSAGES/messages.po +4438 -0
- cryptoadvance/specter/translations/el/LC_MESSAGES/messages.po +4376 -0
- cryptoadvance/specter/translations/es/LC_MESSAGES/messages.po +4396 -0
- cryptoadvance/specter/translations/fi/LC_MESSAGES/messages.po +4358 -0
- cryptoadvance/specter/translations/fr/LC_MESSAGES/messages.po +4414 -0
- cryptoadvance/specter/translations/he/LC_MESSAGES/messages.po +4361 -0
- cryptoadvance/specter/translations/hi/LC_MESSAGES/messages.po +4366 -0
- cryptoadvance/specter/translations/hr/LC_MESSAGES/messages.po +4361 -0
- cryptoadvance/specter/translations/is/LC_MESSAGES/messages.po +4361 -0
- cryptoadvance/specter/translations/it/LC_MESSAGES/messages.po +4361 -0
- cryptoadvance/specter/translations/ko/LC_MESSAGES/messages.po +4361 -0
- cryptoadvance/specter/translations/mal/LC_MESSAGES/messages.po +4358 -0
- cryptoadvance/specter/translations/nl/LC_MESSAGES/messages.po +4381 -0
- cryptoadvance/specter/translations/pl/LC_MESSAGES/messages.po +4376 -0
- cryptoadvance/specter/translations/pt/LC_MESSAGES/messages.po +4371 -0
- cryptoadvance/specter/translations/ru/LC_MESSAGES/messages.po +4373 -0
- cryptoadvance/specter/translations/sr/LC_MESSAGES/messages.po +4361 -0
- cryptoadvance/specter/translations/sv/LC_MESSAGES/messages.po +4377 -0
- cryptoadvance/specter/translations/ta/LC_MESSAGES/messages.po +4358 -0
- cryptoadvance/specter/translations/tr/LC_MESSAGES/messages.po +4361 -0
- cryptoadvance/specter/translations/zh_Hans_CN/LC_MESSAGES/messages.po +4379 -0
- cryptoadvance/specter/translations/zh_Hant_TW/LC_MESSAGES/messages.po +4380 -0
- cryptoadvance/specter/user.py +559 -0
- cryptoadvance/specter/util/__init__.py +0 -0
- cryptoadvance/specter/util/base43.py +58 -0
- cryptoadvance/specter/util/base58.py +52 -0
- cryptoadvance/specter/util/bcur.py +199 -0
- cryptoadvance/specter/util/bitcoind_setup_tasks.py +199 -0
- cryptoadvance/specter/util/checker.py +92 -0
- cryptoadvance/specter/util/common.py +139 -0
- cryptoadvance/specter/util/descriptor.py +504 -0
- cryptoadvance/specter/util/fee_estimation.py +188 -0
- cryptoadvance/specter/util/file_download.py +22 -0
- cryptoadvance/specter/util/flask.py +35 -0
- cryptoadvance/specter/util/json_rpc.py +41 -0
- cryptoadvance/specter/util/merkleblock.py +448 -0
- cryptoadvance/specter/util/migrations/__init__.py +0 -0
- cryptoadvance/specter/util/migrations/migration_0000.py +28 -0
- cryptoadvance/specter/util/migrations/migration_0001.py +129 -0
- cryptoadvance/specter/util/migrations/migration_0002.py +111 -0
- cryptoadvance/specter/util/mnemonic.py +89 -0
- cryptoadvance/specter/util/price_providers.py +195 -0
- cryptoadvance/specter/util/psbt.py +492 -0
- cryptoadvance/specter/util/reflection.py +268 -0
- cryptoadvance/specter/util/reflection_fs.py +70 -0
- cryptoadvance/specter/util/requests_tools.py +43 -0
- cryptoadvance/specter/util/rpcauth.py +55 -0
- cryptoadvance/specter/util/setup_states.py +18 -0
- cryptoadvance/specter/util/sha256sum.py +11 -0
- cryptoadvance/specter/util/shell.py +73 -0
- cryptoadvance/specter/util/specter_migrator.py +274 -0
- cryptoadvance/specter/util/tor.py +95 -0
- cryptoadvance/specter/util/tor_setup_tasks.py +68 -0
- cryptoadvance/specter/util/tx.py +103 -0
- cryptoadvance/specter/util/version.py +259 -0
- cryptoadvance/specter/util/wallet_importer.py +551 -0
- cryptoadvance/specter/util/xpub.py +18 -0
- cryptoadvance/specter/wallet/__init__.py +3 -0
- cryptoadvance/specter/wallet/abstract_wallet.py +25 -0
- cryptoadvance/specter/wallet/addresslist.py +282 -0
- cryptoadvance/specter/wallet/tx_fetcher.py +275 -0
- cryptoadvance/specter/wallet/txlist.py +685 -0
- cryptoadvance/specter/wallet/wallet.py +1940 -0
- cryptoadvance/specterext/devhelp/__init__.py +0 -0
- cryptoadvance/specterext/devhelp/config.py +13 -0
- cryptoadvance/specterext/devhelp/console.py +58 -0
- cryptoadvance/specterext/devhelp/controller.py +116 -0
- cryptoadvance/specterext/devhelp/devices/devhelpdevice.py +11 -0
- cryptoadvance/specterext/devhelp/service.py +63 -0
- cryptoadvance/specterext/devhelp/static/devhelp/css/styles.css +5 -0
- cryptoadvance/specterext/devhelp/static/devhelp/img/mydevice-logo.svg +80 -0
- cryptoadvance/specterext/devhelp/static/devhelp/img/orange-wrench.png +0 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/base.jinja +5 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/components/devhelp_menu.jinja +16 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/components/devhelp_tab.jinja +8 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/dev-console.jinja +114 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/html/address-data.jinja +73 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/html/address-label.jinja +52 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/html/address-row.jinja +51 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/html/fee-selection.jinja +43 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/html/macro_total_wallet_balances.jinja +88 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/html/notification-system.jinja +136 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/html/tx-table.jinja +127 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/html_inject_in_basejinja.jinja +17 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/includes/set-address.html +20 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/includes/set-wallet.html +11 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/index.jinja +29 -0
- cryptoadvance/specterext/devhelp/templates/devhelp/settings.jinja +24 -0
- cryptoadvance/specterext/electrum/__init__.py +0 -0
- cryptoadvance/specterext/electrum/controller.py +33 -0
- cryptoadvance/specterext/electrum/devices/__init__.py +0 -0
- cryptoadvance/specterext/electrum/devices/electrum.py +21 -0
- cryptoadvance/specterext/electrum/service.py +28 -0
- cryptoadvance/specterext/electrum/static/electrum/img/devices/electrum_icon.svg +15 -0
- cryptoadvance/specterext/electrum/static/electrum/img/electrum_lightblue.svg +193 -0
- cryptoadvance/specterext/electrum/static/electrum/img/electrum_manual/1.png +0 -0
- cryptoadvance/specterext/electrum/static/electrum/img/electrum_manual/2.png +0 -0
- cryptoadvance/specterext/electrum/templates/electrum/device/new_device_keys_electrum.jinja +41 -0
- cryptoadvance/specterext/electrum/templates/electrum/index.jinja +17 -0
- cryptoadvance/specterext/notifications/__init__.py +0 -0
- cryptoadvance/specterext/notifications/config.py +25 -0
- cryptoadvance/specterext/notifications/controller.py +90 -0
- cryptoadvance/specterext/notifications/notification_manager.py +485 -0
- cryptoadvance/specterext/notifications/notifications.py +166 -0
- cryptoadvance/specterext/notifications/service.py +88 -0
- cryptoadvance/specterext/notifications/static/notifications/css/styles.css +105 -0
- cryptoadvance/specterext/notifications/static/notifications/img/notification.png +0 -0
- cryptoadvance/specterext/notifications/templates/notifications/base.jinja +4 -0
- cryptoadvance/specterext/notifications/templates/notifications/components/notifications_menu.jinja +16 -0
- cryptoadvance/specterext/notifications/templates/notifications/components/notifications_tab.jinja +8 -0
- cryptoadvance/specterext/notifications/templates/notifications/html_inject_in_basejinja.jinja +13 -0
- cryptoadvance/specterext/notifications/templates/notifications/index.jinja +88 -0
- cryptoadvance/specterext/notifications/templates/notifications/message_box.js +161 -0
- cryptoadvance/specterext/notifications/templates/notifications/notifications.js +396 -0
- cryptoadvance/specterext/notifications/templates/notifications/settings.jinja +98 -0
- cryptoadvance/specterext/notifications/ui_notifications.py +234 -0
- cryptoadvance/specterext/notifications/websockets_server_client.py +444 -0
- cryptoadvance/specterext/spectrum/__init__.py +0 -0
- cryptoadvance/specterext/spectrum/bridge_rpc.py +122 -0
- cryptoadvance/specterext/spectrum/config.py +99 -0
- cryptoadvance/specterext/spectrum/controller.py +192 -0
- cryptoadvance/specterext/spectrum/controller_helpers.py +83 -0
- cryptoadvance/specterext/spectrum/service.py +167 -0
- cryptoadvance/specterext/spectrum/spectrum_node.py +235 -0
- cryptoadvance/specterext/spectrum/static/spectrum/css/styles.css +1 -0
- cryptoadvance/specterext/spectrum/static/spectrum/img/electrum_lightblue.svg +193 -0
- cryptoadvance/specterext/spectrum/static/spectrum/img/ghost.png +0 -0
- cryptoadvance/specterext/spectrum/static/spectrum/img/logo.jpeg +0 -0
- cryptoadvance/specterext/spectrum/static/spectrum/img/logo.svg +20 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/base.jinja +7 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/components/spectrum_info.jinja +63 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/components/spectrum_menu.jinja +15 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/components/spectrum_no_tx_hint.jinja +7 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/components/spectrum_node_connection.jinja +46 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/components/spectrum_node_logo.jinja +1 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/components/spectrum_tab.jinja +8 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/index.jinja +123 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/settings.jinja +19 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/spectrum_setup.jinja +61 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/spectrum_setup_beta.jinja +27 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/spectrum_wallets.jinja +63 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/welcome/components/get_started.jinja +15 -0
- cryptoadvance/specterext/spectrum/templates/spectrum/welcome/components/tick_checkboxes.jinja +89 -0
- cryptoadvance/specterext/swan/__init__.py +0 -0
- cryptoadvance/specterext/swan/client.py +478 -0
- cryptoadvance/specterext/swan/config.py +28 -0
- cryptoadvance/specterext/swan/controller.py +262 -0
- cryptoadvance/specterext/swan/service.py +465 -0
- cryptoadvance/specterext/swan/static/swan/img/swan_icon.svg +1 -0
- cryptoadvance/specterext/swan/static/swan/img/swan_logo.svg +2 -0
- cryptoadvance/specterext/swan/templates/swan/api_error.jinja +16 -0
- cryptoadvance/specterext/swan/templates/swan/components/base.jinja +1 -0
- cryptoadvance/specterext/swan/templates/swan/components/swan_menu.jinja +15 -0
- cryptoadvance/specterext/swan/templates/swan/components/swan_tab.jinja +8 -0
- cryptoadvance/specterext/swan/templates/swan/index.jinja +64 -0
- cryptoadvance/specterext/swan/templates/swan/oauth2_start.jinja +62 -0
- cryptoadvance/specterext/swan/templates/swan/oauth2_success.jinja +20 -0
- cryptoadvance/specterext/swan/templates/swan/settings.jinja +48 -0
- cryptoadvance/specterext/swan/templates/swan/withdrawals.jinja +46 -0
- cryptoadvance_specter-2.1.2.dist-info/LICENSE +21 -0
- cryptoadvance_specter-2.1.2.dist-info/METADATA +287 -0
- cryptoadvance_specter-2.1.2.dist-info/RECORD +523 -0
- cryptoadvance_specter-2.1.2.dist-info/WHEEL +5 -0
- cryptoadvance_specter-2.1.2.dist-info/entry_points.txt +2 -0
- cryptoadvance_specter-2.1.2.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
17
|
+
|
|
18
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
20
|
+
else:
|
|
21
|
+
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
23
|
+
|
|
24
|
+
version: str
|
|
25
|
+
__version__: str
|
|
26
|
+
__version_tuple__: VERSION_TUPLE
|
|
27
|
+
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
30
|
+
|
|
31
|
+
__version__ = version = '2.1.2'
|
|
32
|
+
__version_tuple__ = version_tuple = (2, 1, 2)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
""" API Blueprint Application """
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from flask import Flask, Blueprint, session
|
|
5
|
+
from flask_restful import Api
|
|
6
|
+
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth
|
|
7
|
+
from flask import current_app as app
|
|
8
|
+
|
|
9
|
+
api_bp = Blueprint("api_bp", __name__, template_folder="templates", url_prefix="/api")
|
|
10
|
+
|
|
11
|
+
api_rest = Api(api_bp, decorators=[app.csrf.exempt])
|
|
12
|
+
|
|
13
|
+
auth = HTTPBasicAuth()
|
|
14
|
+
|
|
15
|
+
token_auth = HTTPTokenAuth()
|
|
16
|
+
|
|
17
|
+
from . import views
|
|
18
|
+
from .rest import api
|
|
File without changes
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
import cryptoadvance.specter as specter
|
|
5
|
+
from ...wallet import Wallet
|
|
6
|
+
from .base import (
|
|
7
|
+
SecureResource,
|
|
8
|
+
rest_resource,
|
|
9
|
+
)
|
|
10
|
+
from ..security import require_admin, verify_password
|
|
11
|
+
from flask_restful import abort
|
|
12
|
+
from flask import current_app as app
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from ...specter_error import SpecterError
|
|
15
|
+
|
|
16
|
+
from ...util.fee_estimation import get_fees
|
|
17
|
+
|
|
18
|
+
from .. import token_auth
|
|
19
|
+
from .resource_jwt import JWTResource, JWTResourceById
|
|
20
|
+
from .resource_healthz import ResourceLiveness, ResourceReadyness
|
|
21
|
+
from .resource_psbt import ResourcePsbt
|
|
22
|
+
from .resource_specter import ResourceSpecter
|
|
23
|
+
from .resource_txlist import ResourceTXlist
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@rest_resource
|
|
29
|
+
class ResourceWallet(SecureResource):
|
|
30
|
+
|
|
31
|
+
endpoints = ["/v1alpha/wallets/<wallet_alias>/"]
|
|
32
|
+
|
|
33
|
+
def get(self, wallet_alias):
|
|
34
|
+
user = token_auth.current_user()
|
|
35
|
+
try:
|
|
36
|
+
wallet: Wallet = app.specter.user_manager.get_user(
|
|
37
|
+
user
|
|
38
|
+
).wallet_manager.get_by_alias(wallet_alias)
|
|
39
|
+
except SpecterError as se:
|
|
40
|
+
logger.error(se)
|
|
41
|
+
if str(se).startswith(f"Wallet {wallet_alias} does not exist!"):
|
|
42
|
+
return abort(403, message=f"Wallet {wallet_alias} does not exist")
|
|
43
|
+
logger.error(se)
|
|
44
|
+
return abort(500)
|
|
45
|
+
|
|
46
|
+
wallet.update_balance()
|
|
47
|
+
wallet.check_utxo()
|
|
48
|
+
wallet.check_unused()
|
|
49
|
+
|
|
50
|
+
return_dict = {}
|
|
51
|
+
address_index = wallet.address_index
|
|
52
|
+
validate_merkle_proofs = app.specter.config.get("validate_merkle_proofs")
|
|
53
|
+
tx_list = []
|
|
54
|
+
idx = 0
|
|
55
|
+
tx_len = 1
|
|
56
|
+
transactions = app.specter.wallet_manager.full_txlist(
|
|
57
|
+
fetch_transactions=False, validate_merkle_proofs=validate_merkle_proofs
|
|
58
|
+
)
|
|
59
|
+
tx_list.append(transactions)
|
|
60
|
+
|
|
61
|
+
# Flatten the list
|
|
62
|
+
flat_list = []
|
|
63
|
+
for element in tx_list:
|
|
64
|
+
for dic_item in element:
|
|
65
|
+
flat_list.append(dic_item)
|
|
66
|
+
|
|
67
|
+
# Check if scanning
|
|
68
|
+
scan = wallet.rescan_progress
|
|
69
|
+
return_dict[wallet_alias] = wallet.__dict__
|
|
70
|
+
return_dict["txlist"] = flat_list
|
|
71
|
+
return_dict["scan"] = scan
|
|
72
|
+
return_dict["address_index"] = address_index
|
|
73
|
+
return_dict["utxo"] = wallet.utxo
|
|
74
|
+
|
|
75
|
+
# Serialize only objects that are json compatible
|
|
76
|
+
# This will exclude classes and methods
|
|
77
|
+
def safe_serialize(obj):
|
|
78
|
+
def default(o):
|
|
79
|
+
return f"{type(o).__qualname__}"
|
|
80
|
+
|
|
81
|
+
return json.dumps(obj, default=default)
|
|
82
|
+
|
|
83
|
+
return json.loads(safe_serialize(return_dict))
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
""" API Backend - Base Resource Models """
|
|
2
|
+
|
|
3
|
+
from functools import wraps
|
|
4
|
+
import logging
|
|
5
|
+
import re
|
|
6
|
+
from flask_restful import Resource, abort
|
|
7
|
+
|
|
8
|
+
from cryptoadvance.specter.api import api_rest
|
|
9
|
+
from cryptoadvance.specter.api.security import require_admin
|
|
10
|
+
from cryptoadvance.specter.api import auth, token_auth
|
|
11
|
+
from cryptoadvance.specter.specter_error import SpecterError
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def error_handling(func):
|
|
17
|
+
"""User needs Admin-rights method decorator"""
|
|
18
|
+
|
|
19
|
+
@wraps(func)
|
|
20
|
+
def wrapper(*args, **kwargs):
|
|
21
|
+
"""wrapping the whole error-handling around methods"""
|
|
22
|
+
try:
|
|
23
|
+
return func(*args, **kwargs)
|
|
24
|
+
except SpecterError as se:
|
|
25
|
+
logger.error(se)
|
|
26
|
+
# Not that elegant as this function is accumulating all the error-handling for different
|
|
27
|
+
# endpoints. On the other hand, this is probabyl more tied to different SpecterErrors
|
|
28
|
+
# rather than the implementation of a rest-endpoint.
|
|
29
|
+
match = re.match("Wallet (.+) does not exist!", str(se))
|
|
30
|
+
if match:
|
|
31
|
+
return abort(403, message=f"Wallet {match.group(1)} does not exist")
|
|
32
|
+
if str(se).endswith(
|
|
33
|
+
"does not have sufficient funds to make the transaction."
|
|
34
|
+
):
|
|
35
|
+
return abort(
|
|
36
|
+
412,
|
|
37
|
+
message=f"Wallet does not have sufficient funds to make the transaction.",
|
|
38
|
+
)
|
|
39
|
+
return abort(500)
|
|
40
|
+
except Exception as e:
|
|
41
|
+
logger.error("Unexpected Exception in Rest-Request:")
|
|
42
|
+
logger.exception(e)
|
|
43
|
+
return abort(
|
|
44
|
+
500,
|
|
45
|
+
message="Can't tell you the reason of the issue. Please check the logs",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return wrapper
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class BaseResource(Resource):
|
|
52
|
+
"""A baseClass for rsources which returns Method not allowed by default"""
|
|
53
|
+
|
|
54
|
+
method_decorators = [error_handling]
|
|
55
|
+
|
|
56
|
+
def get(self, *args, **kwargs):
|
|
57
|
+
abort(405)
|
|
58
|
+
|
|
59
|
+
def post(self, *args, **kwargs):
|
|
60
|
+
abort(405)
|
|
61
|
+
|
|
62
|
+
def put(self, *args, **kwargs):
|
|
63
|
+
abort(405)
|
|
64
|
+
|
|
65
|
+
def patch(self, *args, **kwargs):
|
|
66
|
+
abort(405)
|
|
67
|
+
|
|
68
|
+
def delete(self, *args, **kwargs):
|
|
69
|
+
abort(405)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class SecureResource(BaseResource):
|
|
73
|
+
"""A REST-resource which makes sure that the user is Authenticated"""
|
|
74
|
+
|
|
75
|
+
method_decorators = [error_handling, token_auth.login_required]
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class BasicAuthResource(BaseResource):
|
|
79
|
+
"""A REST-resource which makes sure that the user is Authenticated"""
|
|
80
|
+
|
|
81
|
+
method_decorators = [error_handling, auth.login_required]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class AdminResource(BaseResource):
|
|
85
|
+
"""A REST-resource which makes sure that the user is an admin"""
|
|
86
|
+
|
|
87
|
+
method_decorators = [error_handling, require_admin, token_auth.login_required]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def rest_resource(resource_cls):
|
|
91
|
+
"""Decorator for adding resources to Api App"""
|
|
92
|
+
api_rest.add_resource(resource_cls, *resource_cls.endpoints)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
liveness and readiness probes are a semi-standard way of health-checking.
|
|
3
|
+
See e.g. here:
|
|
4
|
+
https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
|
|
5
|
+
"""
|
|
6
|
+
import json
|
|
7
|
+
import logging
|
|
8
|
+
from os import abort
|
|
9
|
+
|
|
10
|
+
from cryptoadvance.specter.api.rest.base import BaseResource, rest_resource
|
|
11
|
+
from flask import current_app as app
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@rest_resource
|
|
17
|
+
class ResourceLiveness(BaseResource):
|
|
18
|
+
"""/api/healthz/liveness
|
|
19
|
+
Whether the app is up and running although it might not have connection to DB/nodes etc.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
endpoints = ["/healthz/liveness"]
|
|
23
|
+
|
|
24
|
+
def get(self):
|
|
25
|
+
return {"message": "i am alive"}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@rest_resource
|
|
29
|
+
class ResourceReadyness(BaseResource):
|
|
30
|
+
"""/api/healthz/readyness
|
|
31
|
+
Whether the app is up and running AND ALL its dependent services (in our case nodes) are properly functioning as well.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
endpoints = ["/healthz/readyness"]
|
|
35
|
+
|
|
36
|
+
def get(self):
|
|
37
|
+
try:
|
|
38
|
+
# Not sure whether that's enough. Probably improvable:
|
|
39
|
+
app.specter.check()
|
|
40
|
+
except Exception as e:
|
|
41
|
+
abort(500, message="Readyness probe failed")
|
|
42
|
+
return {"message": "i am ready"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import jwt
|
|
2
|
+
from flask import current_app as app
|
|
3
|
+
from flask_restful import Api, abort, reqparse
|
|
4
|
+
from cryptoadvance.specter.api.rest.base import (
|
|
5
|
+
BaseResource,
|
|
6
|
+
BasicAuthResource,
|
|
7
|
+
SecureResource,
|
|
8
|
+
rest_resource,
|
|
9
|
+
AdminResource,
|
|
10
|
+
)
|
|
11
|
+
import uuid
|
|
12
|
+
import datetime
|
|
13
|
+
import logging
|
|
14
|
+
from ...user import *
|
|
15
|
+
from .base import *
|
|
16
|
+
from pytimeparse import parse
|
|
17
|
+
|
|
18
|
+
from .. import auth
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
# Initialize the parser
|
|
23
|
+
parser = reqparse.RequestParser()
|
|
24
|
+
parser.add_argument(
|
|
25
|
+
"jwt_token_description", type=str, help="JWT token description", required=True
|
|
26
|
+
)
|
|
27
|
+
parser.add_argument("jwt_token_life", type=str, help="JWT token life", required=True)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@rest_resource
|
|
31
|
+
class JWTResource(BasicAuthResource):
|
|
32
|
+
"""
|
|
33
|
+
A Resource to manage JWT tokens in order to authenticate against the REST-API
|
|
34
|
+
Other then the other Resources, this endpoint uses BasicAuth to avoid the chicken egg problem
|
|
35
|
+
This one is only to create a token. The other Resource for getting and deleting.
|
|
36
|
+
This violates the REST principles but only on the implementation-side. Happy for improvements here.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
endpoints = ["/v1alpha/token/"]
|
|
40
|
+
|
|
41
|
+
def get(self):
|
|
42
|
+
# An endpoint to get all JWT tokens' information created by the user
|
|
43
|
+
user = auth.current_user()
|
|
44
|
+
user_details = app.specter.user_manager.get_user(user)
|
|
45
|
+
jwt_tokens = user_details.get_all_jwt_tokens_info()
|
|
46
|
+
if len(jwt_tokens) == 0:
|
|
47
|
+
return {"message": "Tokens does not exist"}, 404
|
|
48
|
+
return {"message": "Tokens exist", "jwt_tokens": jwt_tokens}, 200
|
|
49
|
+
|
|
50
|
+
def post(self):
|
|
51
|
+
# An endpoint to create a JWT token
|
|
52
|
+
user = auth.current_user()
|
|
53
|
+
data = parser.parse_args()
|
|
54
|
+
user_details = app.specter.user_manager.get_user(user)
|
|
55
|
+
jwt_token_id = user_details.generate_token_id()
|
|
56
|
+
jwt_token_description = data["jwt_token_description"]
|
|
57
|
+
|
|
58
|
+
# pytimeparse has been used to parse different time units to seconds
|
|
59
|
+
# For eg: "jwt_token_life_unit": "1 hour" will be parsed to 3600 seconds
|
|
60
|
+
# For more information visit: https://pypi.org/project/pytimeparse/
|
|
61
|
+
jwt_token_life = parse(data["jwt_token_life"])
|
|
62
|
+
jwt_token = user_details.generate_jwt_token(
|
|
63
|
+
user_details.username,
|
|
64
|
+
jwt_token_id,
|
|
65
|
+
jwt_token_description,
|
|
66
|
+
jwt_token_life,
|
|
67
|
+
)
|
|
68
|
+
if user_details.validate_jwt_token_description(jwt_token_description):
|
|
69
|
+
user_details.add_jwt_token(
|
|
70
|
+
jwt_token_id,
|
|
71
|
+
jwt_token,
|
|
72
|
+
jwt_token_description,
|
|
73
|
+
jwt_token_life,
|
|
74
|
+
)
|
|
75
|
+
return {
|
|
76
|
+
"message": "Token generated",
|
|
77
|
+
"jwt_token_id": jwt_token_id,
|
|
78
|
+
"jwt_token": jwt_token,
|
|
79
|
+
"jwt_token_description": jwt_token_description,
|
|
80
|
+
"jwt_token_life": jwt_token_life,
|
|
81
|
+
}, 201
|
|
82
|
+
else:
|
|
83
|
+
return {"message": "Token description already exists or is blank"}, 400
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@rest_resource
|
|
87
|
+
class JWTResourceById(BasicAuthResource):
|
|
88
|
+
"""
|
|
89
|
+
A Resource to manage individual JWT token
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
endpoints = ["/v1alpha/token/<jwt_token_id>/"]
|
|
93
|
+
|
|
94
|
+
def get(self, jwt_token_id):
|
|
95
|
+
# An endpoint to get a JWT token by id
|
|
96
|
+
user = auth.current_user()
|
|
97
|
+
user_details = app.specter.user_manager.get_user(user)
|
|
98
|
+
jwt_tokens = user_details.jwt_tokens
|
|
99
|
+
jwt_token = user_details.get_jwt_token(jwt_token_id)
|
|
100
|
+
jwt_token_life_remaining = user_details.jwt_token_life_remaining(jwt_token_id)
|
|
101
|
+
expiry_status = f"Valid"
|
|
102
|
+
if jwt_token_life_remaining == 0:
|
|
103
|
+
expiry_status = f"Expired"
|
|
104
|
+
if (
|
|
105
|
+
not user_details.verify_jwt_token_id_and_jwt_token(jwt_token_id, jwt_token)
|
|
106
|
+
and jwt_tokens[jwt_token_id] is None
|
|
107
|
+
):
|
|
108
|
+
return {
|
|
109
|
+
"message": "Token does not exist, make sure to enter correct token id"
|
|
110
|
+
}, 404
|
|
111
|
+
return {
|
|
112
|
+
"message": "Token exists",
|
|
113
|
+
"jwt_token_description": jwt_token["jwt_token_description"],
|
|
114
|
+
"jwt_token_life": jwt_token["jwt_token_life"],
|
|
115
|
+
"jwt_token_life_remaining": jwt_token_life_remaining,
|
|
116
|
+
"expiry_status": expiry_status,
|
|
117
|
+
}, 200
|
|
118
|
+
|
|
119
|
+
def delete(self, jwt_token_id):
|
|
120
|
+
# An endpoint to delete a JWT token by id
|
|
121
|
+
user = auth.current_user()
|
|
122
|
+
user_details = app.specter.user_manager.get_user(user)
|
|
123
|
+
jwt_tokens = user_details.jwt_tokens
|
|
124
|
+
jwt_token = user_details.get_jwt_token(jwt_token_id)
|
|
125
|
+
|
|
126
|
+
if (
|
|
127
|
+
not user_details.verify_jwt_token_id_and_jwt_token(jwt_token_id, jwt_token)
|
|
128
|
+
and jwt_tokens[jwt_token_id] is None
|
|
129
|
+
):
|
|
130
|
+
return {
|
|
131
|
+
"message": "Token does not exist, make sure to enter correct token id"
|
|
132
|
+
}, 404
|
|
133
|
+
|
|
134
|
+
user_details.delete_jwt_token(jwt_token_id)
|
|
135
|
+
return {"message": "Token deleted"}, 200
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import base64
|
|
3
|
+
from json import dumps
|
|
4
|
+
|
|
5
|
+
from .base import (
|
|
6
|
+
SecureResource,
|
|
7
|
+
rest_resource,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from flask import current_app as app, request, Response
|
|
11
|
+
from ...wallet import Wallet
|
|
12
|
+
from ...commands.psbt_creator import PsbtCreator
|
|
13
|
+
from ...specter_error import SpecterError
|
|
14
|
+
from .. import token_auth
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@rest_resource
|
|
20
|
+
class ResourcePsbt(SecureResource):
|
|
21
|
+
"""/api/v1alpha/specter"""
|
|
22
|
+
|
|
23
|
+
endpoints = ["/v1alpha/wallets/<wallet_alias>/psbt"]
|
|
24
|
+
|
|
25
|
+
def get(self, wallet_alias):
|
|
26
|
+
user = token_auth.current_user()
|
|
27
|
+
wallet_manager = app.specter.user_manager.get_user(user).wallet_manager
|
|
28
|
+
# Check that the wallet belongs to the user from Basic Auth
|
|
29
|
+
try:
|
|
30
|
+
wallet = wallet_manager.get_by_alias(wallet_alias)
|
|
31
|
+
except SpecterError as se:
|
|
32
|
+
# ToDo: Be more specific here. How do we know that this SpecterError is a fit to that message?
|
|
33
|
+
logger.warning(
|
|
34
|
+
f"User user {user} denied access to {wallet_alias} because of {se}"
|
|
35
|
+
)
|
|
36
|
+
error_message = dumps(
|
|
37
|
+
{"message": "The wallet does not belong to the user in the request."}
|
|
38
|
+
)
|
|
39
|
+
return Response(error_message, 403)
|
|
40
|
+
pending_psbts = wallet.pending_psbts_dict()
|
|
41
|
+
return {"result": pending_psbts or {}}
|
|
42
|
+
|
|
43
|
+
def post(self, wallet_alias):
|
|
44
|
+
user = token_auth.current_user()
|
|
45
|
+
wallet: Wallet = app.specter.user_manager.get_user(
|
|
46
|
+
user
|
|
47
|
+
).wallet_manager.get_by_alias(wallet_alias)
|
|
48
|
+
logger.debug(f"Got a post request for creating a psbt: {request.json}")
|
|
49
|
+
psbt_creator = PsbtCreator(
|
|
50
|
+
app.specter, wallet, "json", request_json=request.json
|
|
51
|
+
)
|
|
52
|
+
psbt = psbt_creator.create_psbt(wallet)
|
|
53
|
+
return {"result": psbt}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from cryptoadvance.specter.api.rest.base import (
|
|
4
|
+
AdminResource,
|
|
5
|
+
rest_resource,
|
|
6
|
+
)
|
|
7
|
+
from flask import current_app as app
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@rest_resource
|
|
14
|
+
class ResourceSpecter(AdminResource):
|
|
15
|
+
"""/api/v1alpha/specter"""
|
|
16
|
+
|
|
17
|
+
endpoints = ["/v1alpha/specter"]
|
|
18
|
+
|
|
19
|
+
def get(self):
|
|
20
|
+
specter_data = app.specter
|
|
21
|
+
|
|
22
|
+
return_dict = {
|
|
23
|
+
"data_folder": specter_data.data_folder,
|
|
24
|
+
"config": specter_data.config,
|
|
25
|
+
"info": specter_data.info,
|
|
26
|
+
"network_info": specter_data.network_info,
|
|
27
|
+
"device_manager_datafolder": specter_data.device_manager.data_folder,
|
|
28
|
+
"devices_names": specter_data.device_manager.devices_names,
|
|
29
|
+
"wallets_names": specter_data.wallet_manager.wallets_names,
|
|
30
|
+
"last_update": datetime.now().strftime("%m/%d/%Y, %H:%M:%S"),
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Include alias list for easy lookup between names and alias
|
|
34
|
+
# Maybe there's a better way to create this
|
|
35
|
+
wallets_alias = []
|
|
36
|
+
alias_name = {}
|
|
37
|
+
name_alias = {}
|
|
38
|
+
for wallet in return_dict["wallets_names"]:
|
|
39
|
+
alias = specter_data.wallet_manager.wallets[wallet].alias
|
|
40
|
+
wallets_alias.append(alias)
|
|
41
|
+
alias_name[alias] = wallet
|
|
42
|
+
name_alias[wallet] = alias
|
|
43
|
+
return_dict["alias_name"] = alias_name
|
|
44
|
+
return_dict["name_alias"] = name_alias
|
|
45
|
+
return_dict["wallets_alias"] = wallets_alias
|
|
46
|
+
return return_dict
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from cryptoadvance.specter.api.rest.base import AdminResource, rest_resource
|
|
5
|
+
from flask import current_app as app
|
|
6
|
+
|
|
7
|
+
from .. import token_auth
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@rest_resource
|
|
13
|
+
class ResourceTXlist(AdminResource):
|
|
14
|
+
"""/api/v1alpha/full_txlist"""
|
|
15
|
+
|
|
16
|
+
endpoints = ["/v1alpha/specter/full_txlist/"]
|
|
17
|
+
|
|
18
|
+
def get(self):
|
|
19
|
+
user = token_auth.current_user()
|
|
20
|
+
wallet_manager = app.specter.user_manager.get_user(user).wallet_manager
|
|
21
|
+
validate_merkle_proofs = app.specter.config.get("validate_merkle_proofs")
|
|
22
|
+
idx = 0
|
|
23
|
+
tx_len = 1
|
|
24
|
+
tx_list = []
|
|
25
|
+
transactions = wallet_manager.full_txlist(
|
|
26
|
+
fetch_transactions=False, validate_merkle_proofs=validate_merkle_proofs
|
|
27
|
+
)
|
|
28
|
+
tx_list.append(transactions)
|
|
29
|
+
# Flatten the list
|
|
30
|
+
flat_list = []
|
|
31
|
+
for element in tx_list:
|
|
32
|
+
for dic_item in element:
|
|
33
|
+
flat_list.append(dic_item)
|
|
34
|
+
return flat_list
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
""" Security Related things for the REST-API """
|
|
2
|
+
import logging, jwt
|
|
3
|
+
from functools import wraps
|
|
4
|
+
|
|
5
|
+
from cryptoadvance.specter.user import User, verify_password as user_verify_password
|
|
6
|
+
from flask import current_app as app
|
|
7
|
+
from flask import g
|
|
8
|
+
from flask_restful import abort
|
|
9
|
+
from . import auth, token_auth
|
|
10
|
+
from ..user import *
|
|
11
|
+
from . import auth
|
|
12
|
+
from flask import current_app as app
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@auth.verify_password
|
|
18
|
+
def verify_password(username, password):
|
|
19
|
+
"""Validate user passwords and store user in the 'g' object"""
|
|
20
|
+
if not username or not password:
|
|
21
|
+
return abort(401)
|
|
22
|
+
the_user = app.specter.user_manager.get_user_by_username(username)
|
|
23
|
+
if not the_user:
|
|
24
|
+
return abort(401)
|
|
25
|
+
g.user = app.specter.user_manager.get_user_by_username(username)
|
|
26
|
+
if user_verify_password(g.user.password_hash, password):
|
|
27
|
+
logger.info(f"Rest-Request for user {username} PASSED password-test")
|
|
28
|
+
return username
|
|
29
|
+
else:
|
|
30
|
+
logger.info(f"Rest-Request for user {username} FAILED password-test")
|
|
31
|
+
return abort(401)
|
|
32
|
+
|
|
33
|
+
return g.user is not None and verify_password(g.user.password_hash, password)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@token_auth.verify_token
|
|
37
|
+
def verify_token(jwt_token):
|
|
38
|
+
"""Validate JWT token and store user in the 'g' object"""
|
|
39
|
+
if not jwt_token:
|
|
40
|
+
return abort(401)
|
|
41
|
+
try:
|
|
42
|
+
payload = jwt.decode(jwt_token, app.config["SECRET_KEY"], algorithms=["HS256"])
|
|
43
|
+
username = payload["username"]
|
|
44
|
+
the_user = app.specter.user_manager.get_user_by_username(username)
|
|
45
|
+
if not the_user:
|
|
46
|
+
return abort(401)
|
|
47
|
+
g.user = app.specter.user_manager.get_user_by_username(username)
|
|
48
|
+
logger.info({"payload": payload})
|
|
49
|
+
logger.info(f"Rest-Request for user {username} PASSED JWT-test")
|
|
50
|
+
return username
|
|
51
|
+
except jwt.ExpiredSignatureError:
|
|
52
|
+
logger.info(f"Token expired. Please create a new one")
|
|
53
|
+
return abort(401)
|
|
54
|
+
except jwt.InvalidTokenError:
|
|
55
|
+
logger.info(f"Invalid token. Please create a new one")
|
|
56
|
+
return abort(401)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def require_admin(func):
|
|
60
|
+
"""User needs Admin-rights method decorator"""
|
|
61
|
+
|
|
62
|
+
@wraps(func)
|
|
63
|
+
def wrapper(*args, **kwargs):
|
|
64
|
+
"""this needs to get implemented properly"""
|
|
65
|
+
# Verify if User is Admin
|
|
66
|
+
if g.user == None:
|
|
67
|
+
return abort(401)
|
|
68
|
+
if g.user.is_admin:
|
|
69
|
+
return func(*args, **kwargs)
|
|
70
|
+
else:
|
|
71
|
+
return abort(401)
|
|
72
|
+
|
|
73
|
+
return wrapper
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
|
|
3
|
+
<body>
|
|
4
|
+
The documentation for the API FOR THE MASTER BRANCH can be found here:
|
|
5
|
+
<a href="https://github.com/cryptoadvance/specter-desktop/blob/master/docs/api/README.md">https://github.com/cryptoadvance/specter-desktop/blob/master/docs/api/api.md</a>
|
|
6
|
+
|
|
7
|
+
<br><br>
|
|
8
|
+
Make sure to choose the right version for the version you're currently using: {{version}}
|
|
9
|
+
|
|
10
|
+
<br><br>
|
|
11
|
+
{% if version != "custom" %}
|
|
12
|
+
So assuming that, please use this url:
|
|
13
|
+
<a href="https://github.com/cryptoadvance/specter-desktop/blob/v{{version}}/docs/api/README.md">https://github.com/cryptoadvance/specter-desktop/blob/v{{version}}/docs/api/api.md</a>
|
|
14
|
+
{% endif %}
|
|
15
|
+
|
|
16
|
+
</body>
|
|
17
|
+
|
|
18
|
+
</html>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from flask import render_template
|
|
2
|
+
from cryptoadvance.specter.api import api_bp
|
|
3
|
+
from flask import current_app as app
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@api_bp.route("/")
|
|
7
|
+
def api():
|
|
8
|
+
"""rendering the documentation for the api"""
|
|
9
|
+
return render_template(
|
|
10
|
+
"api.html", version=app.specter.version._get_current_version()
|
|
11
|
+
)
|