Showing preview only (9,442K chars total). Download the full file or copy to clipboard to get everything.
Repository: spesmilo/electrum
Branch: master
Commit: dceece1cda9b
Files: 776
Total size: 8.9 MB
Directory structure:
gitextract_3c6jsf9o/
├── .cirrus.yml
├── .editorconfig
├── .gitattributes
├── .github/
│ └── ISSUE_TEMPLATE/
│ ├── 01_issue.yml
│ └── config.yml
├── .gitignore
├── .gitmodules
├── AUTHORS
├── LICENCE
├── MANIFEST.in
├── README.md
├── RELEASE-NOTES
├── SECURITY.md
├── contrib/
│ ├── add_cosigner
│ ├── android/
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ ├── Readme.md
│ │ ├── apkdiff.py
│ │ ├── apt.preferences
│ │ ├── apt.sources.list
│ │ ├── bitcoin_intent.xml
│ │ ├── build.sh
│ │ ├── buildozer_qml.spec
│ │ ├── dl-ndk-ci.sh
│ │ ├── get_apk_versioncode.py
│ │ ├── make_apk.sh
│ │ ├── make_barcode_scanner.sh
│ │ └── p4a_recipes/
│ │ ├── README.md
│ │ ├── cffi/
│ │ │ └── __init__.py
│ │ ├── cryptography/
│ │ │ └── __init__.py
│ │ ├── hostpython3/
│ │ │ └── __init__.py
│ │ ├── libffi/
│ │ │ └── __init__.py
│ │ ├── libiconv/
│ │ │ └── __init__.py
│ │ ├── libsecp256k1/
│ │ │ └── __init__.py
│ │ ├── libzbar/
│ │ │ └── __init__.py
│ │ ├── openssl/
│ │ │ └── __init__.py
│ │ ├── packaging/
│ │ │ └── __init__.py
│ │ ├── ply/
│ │ │ └── __init__.py
│ │ ├── plyer/
│ │ │ └── __init__.py
│ │ ├── pycparser/
│ │ │ └── __init__.py
│ │ ├── pycryptodomex/
│ │ │ └── __init__.py
│ │ ├── pyjnius/
│ │ │ └── __init__.py
│ │ ├── pyparsing/
│ │ │ └── __init__.py
│ │ ├── pyqt6/
│ │ │ └── __init__.py
│ │ ├── pyqt6sip/
│ │ │ └── __init__.py
│ │ ├── pyqt_builder/
│ │ │ └── __init__.py
│ │ ├── python3/
│ │ │ └── __init__.py
│ │ ├── qt6/
│ │ │ └── __init__.py
│ │ ├── setuptools/
│ │ │ └── __init__.py
│ │ ├── sip/
│ │ │ └── __init__.py
│ │ ├── six/
│ │ │ └── __init__.py
│ │ ├── sqlite3/
│ │ │ └── __init__.py
│ │ ├── toml/
│ │ │ └── __init__.py
│ │ ├── tomli/
│ │ │ └── __init__.py
│ │ └── util.py
│ ├── apparmor/
│ │ ├── README.md
│ │ └── apparmor.d/
│ │ ├── abstractions/
│ │ │ └── electrum
│ │ ├── electrum.appimage
│ │ └── usr.local.bin.electrum
│ ├── ban_unicode.py
│ ├── build-linux/
│ │ ├── appimage/
│ │ │ ├── .dockerignore
│ │ │ ├── Dockerfile
│ │ │ ├── README.md
│ │ │ ├── apprun.sh
│ │ │ ├── apt.preferences
│ │ │ ├── apt.sources.list
│ │ │ ├── build.sh
│ │ │ ├── make_appimage.sh
│ │ │ ├── make_type2_runtime.sh
│ │ │ └── patches/
│ │ │ ├── python-3.11-reproducible-buildinfo.diff
│ │ │ └── type2-runtime-reproducible-build.patch
│ │ └── sdist/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── build.sh
│ │ └── make_sdist.sh
│ ├── build-wine/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── README_windows.md
│ │ ├── apt.preferences
│ │ ├── apt.sources.list
│ │ ├── build-electrum-git.sh
│ │ ├── build.sh
│ │ ├── electrum.nsi
│ │ ├── gpg_keys/
│ │ │ └── 7ED10B6531D7C8E1BC296021FC624643487034E5.asc
│ │ ├── make_win.sh
│ │ ├── patches/
│ │ │ └── libiconv-fix-pointer-buf.patch
│ │ ├── prepare-wine.sh
│ │ ├── pyinstaller.spec
│ │ ├── sign.sh
│ │ └── unsign.sh
│ ├── build_tools_util.sh
│ ├── deterministic-build/
│ │ ├── README.md
│ │ ├── check_submodules.sh
│ │ ├── find_restricted_dependencies.py
│ │ ├── requirements-binaries-mac.txt
│ │ ├── requirements-binaries.txt
│ │ ├── requirements-build-android.txt
│ │ ├── requirements-build-appimage.txt
│ │ ├── requirements-build-base.txt
│ │ ├── requirements-build-mac.txt
│ │ ├── requirements-build-wine.txt
│ │ ├── requirements-hw.txt
│ │ └── requirements.txt
│ ├── docker_notes.md
│ ├── freeze_containers_distro.sh
│ ├── freeze_packages.sh
│ ├── generate_payreqpb2.sh
│ ├── locale/
│ │ ├── build_cleanlocale.sh
│ │ ├── build_locale.sh
│ │ ├── push_locale.py
│ │ └── stats.py
│ ├── make_download
│ ├── make_libsecp256k1.sh
│ ├── make_libusb.sh
│ ├── make_packages.sh
│ ├── make_plugin
│ ├── make_zbar.sh
│ ├── osx/
│ │ ├── README.md
│ │ ├── README_macos.md
│ │ ├── apply_sigs.sh
│ │ ├── cdrkit-deterministic.patch
│ │ ├── compare_dmg
│ │ ├── entitlements.plist
│ │ ├── extract_sigs.sh
│ │ ├── make_osx.sh
│ │ ├── notarize_app.sh
│ │ ├── package.sh
│ │ ├── pyinstaller.spec
│ │ └── sign_osx.sh
│ ├── print_electrum_version.py
│ ├── release.sh
│ ├── release_www.sh
│ ├── requirements/
│ │ ├── requirements-binaries-mac.txt
│ │ ├── requirements-binaries.txt
│ │ ├── requirements-build-android.txt
│ │ ├── requirements-build-appimage.txt
│ │ ├── requirements-build-base.txt
│ │ ├── requirements-build-mac.txt
│ │ ├── requirements-build-wine.txt
│ │ ├── requirements-ci.txt
│ │ ├── requirements-hw.txt
│ │ └── requirements.txt
│ ├── sign_packages
│ ├── trigger_deploy.sh
│ ├── udev/
│ │ ├── 20-hw1.rules
│ │ ├── 51-coinkite.rules
│ │ ├── 51-hid-digitalbitbox.rules
│ │ ├── 51-safe-t.rules
│ │ ├── 51-trezor.rules
│ │ ├── 51-usb-keepkey.rules
│ │ ├── 52-hid-digitalbitbox.rules
│ │ ├── 53-hid-bitbox02.rules
│ │ ├── 54-hid-bitbox02.rules
│ │ ├── 55-usb-jade.rules
│ │ └── README.md
│ └── upload.sh
├── electrum/
│ ├── __init__.py
│ ├── _vendor/
│ │ ├── __init__.py
│ │ ├── distutils/
│ │ │ ├── LICENSE
│ │ │ ├── __init__.py
│ │ │ └── version.py
│ │ └── pyperclip/
│ │ ├── LICENSE.txt
│ │ ├── README.md
│ │ └── __init__.py
│ ├── address_synchronizer.py
│ ├── base_crash_reporter.py
│ ├── bip21.py
│ ├── bip32.py
│ ├── bip39_recovery.py
│ ├── bip39_wallet_formats.json
│ ├── bitcoin.py
│ ├── blockchain.py
│ ├── chains/
│ │ ├── mainnet/
│ │ │ ├── checkpoints.json
│ │ │ ├── fallback_lnnodes.json
│ │ │ └── servers.json
│ │ ├── mutinynet/
│ │ │ ├── fallback_lnnodes.json
│ │ │ └── servers.json
│ │ ├── regtest/
│ │ │ └── servers.json
│ │ ├── signet/
│ │ │ ├── checkpoints.json
│ │ │ ├── fallback_lnnodes.json
│ │ │ └── servers.json
│ │ ├── testnet/
│ │ │ ├── checkpoints.json
│ │ │ ├── fallback_lnnodes.json
│ │ │ └── servers.json
│ │ └── testnet4/
│ │ ├── checkpoints.json
│ │ └── servers.json
│ ├── channel_db.py
│ ├── coinchooser.py
│ ├── commands.py
│ ├── constants.py
│ ├── contacts.py
│ ├── crypto.py
│ ├── currencies.json
│ ├── daemon.py
│ ├── descriptor.py
│ ├── dns_hacks.py
│ ├── dnssec.py
│ ├── exchange_rate.py
│ ├── fee_policy.py
│ ├── gui/
│ │ ├── __init__.py
│ │ ├── common_qt/
│ │ │ ├── __init__.py
│ │ │ ├── i18n.py
│ │ │ ├── plugins.py
│ │ │ └── util.py
│ │ ├── default_lang.py
│ │ ├── fonts/
│ │ │ └── PTMono.LICENSE
│ │ ├── icons/
│ │ │ ├── clock5.pdn
│ │ │ └── electrum.icns
│ │ ├── messages.py
│ │ ├── qml/
│ │ │ ├── __init__.py
│ │ │ ├── android_res/
│ │ │ │ └── layout/
│ │ │ │ └── scanner_layout.xml
│ │ │ ├── auth.py
│ │ │ ├── components/
│ │ │ │ ├── About.qml
│ │ │ │ ├── AddressDetails.qml
│ │ │ │ ├── Addresses.qml
│ │ │ │ ├── BIP39RecoveryDialog.qml
│ │ │ │ ├── BalanceDetails.qml
│ │ │ │ ├── ChannelDetails.qml
│ │ │ │ ├── ChannelOpenProgressDialog.qml
│ │ │ │ ├── Channels.qml
│ │ │ │ ├── CloseChannelDialog.qml
│ │ │ │ ├── ConfirmTxDialog.qml
│ │ │ │ ├── Constants.qml
│ │ │ │ ├── CpfpBumpFeeDialog.qml
│ │ │ │ ├── ExceptionDialog.qml
│ │ │ │ ├── ExportTxDialog.qml
│ │ │ │ ├── GenericShareDialog.qml
│ │ │ │ ├── History.qml
│ │ │ │ ├── ImportAddressesKeysDialog.qml
│ │ │ │ ├── ImportChannelBackupDialog.qml
│ │ │ │ ├── InvoiceDialog.qml
│ │ │ │ ├── Invoices.qml
│ │ │ │ ├── LightningPaymentDetails.qml
│ │ │ │ ├── LnurlPayRequestDialog.qml
│ │ │ │ ├── LnurlWithdrawRequestDialog.qml
│ │ │ │ ├── LoadingWalletDialog.qml
│ │ │ │ ├── MessageDialog.qml
│ │ │ │ ├── NetworkOverview.qml
│ │ │ │ ├── NewWalletWizard.qml
│ │ │ │ ├── NostrConfigDialog.qml
│ │ │ │ ├── NostrSwapServersDialog.qml
│ │ │ │ ├── NotificationPopup.qml
│ │ │ │ ├── OpenChannelDialog.qml
│ │ │ │ ├── OpenWalletDialog.qml
│ │ │ │ ├── OtpDialog.qml
│ │ │ │ ├── PasswordDialog.qml
│ │ │ │ ├── Preferences.qml
│ │ │ │ ├── ProxyConfigDialog.qml
│ │ │ │ ├── RbfBumpFeeDialog.qml
│ │ │ │ ├── RbfCancelDialog.qml
│ │ │ │ ├── ReceiveDetailsDialog.qml
│ │ │ │ ├── ReceiveDialog.qml
│ │ │ │ ├── ReceiveRequests.qml
│ │ │ │ ├── ScanDialog.qml
│ │ │ │ ├── SendDialog.qml
│ │ │ │ ├── ServerConfigDialog.qml
│ │ │ │ ├── ServerConnectWizard.qml
│ │ │ │ ├── SignVerifyMessageDialog.qml
│ │ │ │ ├── SwapDialog.qml
│ │ │ │ ├── SweepDialog.qml
│ │ │ │ ├── TermsOfUseWizard.qml
│ │ │ │ ├── TxDetails.qml
│ │ │ │ ├── WalletDetails.qml
│ │ │ │ ├── WalletMainView.qml
│ │ │ │ ├── WalletSummary.qml
│ │ │ │ ├── Wallets.qml
│ │ │ │ ├── controls/
│ │ │ │ │ ├── AddressDelegate.qml
│ │ │ │ │ ├── BalanceSummary.qml
│ │ │ │ │ ├── BtcField.qml
│ │ │ │ │ ├── ButtonContainer.qml
│ │ │ │ │ ├── ChannelBar.qml
│ │ │ │ │ ├── ChannelDelegate.qml
│ │ │ │ │ ├── CoinDelegate.qml
│ │ │ │ │ ├── ElCheckBox.qml
│ │ │ │ │ ├── ElComboBox.qml
│ │ │ │ │ ├── ElDialog.qml
│ │ │ │ │ ├── ElListView.qml
│ │ │ │ │ ├── ElRadioButton.qml
│ │ │ │ │ ├── ElTextArea.qml
│ │ │ │ │ ├── FeeMethodComboBox.qml
│ │ │ │ │ ├── FeePicker.qml
│ │ │ │ │ ├── FiatField.qml
│ │ │ │ │ ├── FlatButton.qml
│ │ │ │ │ ├── FormattedAmount.qml
│ │ │ │ │ ├── Heading.qml
│ │ │ │ │ ├── HelpButton.qml
│ │ │ │ │ ├── HelpDialog.qml
│ │ │ │ │ ├── HistoryItemDelegate.qml
│ │ │ │ │ ├── InfoBanner.qml
│ │ │ │ │ ├── InfoTextArea.qml
│ │ │ │ │ ├── InvoiceDelegate.qml
│ │ │ │ │ ├── LightningNetworkStatusIndicator.qml
│ │ │ │ │ ├── OnchainNetworkStatusIndicator.qml
│ │ │ │ │ ├── PaneInsetBackground.qml
│ │ │ │ │ ├── PasswordField.qml
│ │ │ │ │ ├── PasswordStrengthIndicator.qml
│ │ │ │ │ ├── Piechart.qml
│ │ │ │ │ ├── PrefsHeading.qml
│ │ │ │ │ ├── ProxyConfig.qml
│ │ │ │ │ ├── QRImage.qml
│ │ │ │ │ ├── QRScan.qml
│ │ │ │ │ ├── RequestExpiryComboBox.qml
│ │ │ │ │ ├── SeedKeyboard.qml
│ │ │ │ │ ├── SeedKeyboardKey.qml
│ │ │ │ │ ├── SeedTextArea.qml
│ │ │ │ │ ├── ServerConfig.qml
│ │ │ │ │ ├── ServerConnectModeComboBox.qml
│ │ │ │ │ ├── ServerDelegate.qml
│ │ │ │ │ ├── Tag.qml
│ │ │ │ │ ├── TextHighlightPane.qml
│ │ │ │ │ ├── Toaster.qml
│ │ │ │ │ ├── ToggleLabel.qml
│ │ │ │ │ ├── TxInput.qml
│ │ │ │ │ └── TxOutput.qml
│ │ │ │ ├── main.qml
│ │ │ │ └── wizard/
│ │ │ │ ├── WCConfirmExt.qml
│ │ │ │ ├── WCConfirmSeed.qml
│ │ │ │ ├── WCCosignerKeystore.qml
│ │ │ │ ├── WCCreateSeed.qml
│ │ │ │ ├── WCEnterExt.qml
│ │ │ │ ├── WCHaveMasterKey.qml
│ │ │ │ ├── WCHaveSeed.qml
│ │ │ │ ├── WCImport.qml
│ │ │ │ ├── WCKeystoreType.qml
│ │ │ │ ├── WCMultisig.qml
│ │ │ │ ├── WCProxyConfig.qml
│ │ │ │ ├── WCScriptAndDerivation.qml
│ │ │ │ ├── WCServerConfig.qml
│ │ │ │ ├── WCShowMasterPubkey.qml
│ │ │ │ ├── WCTermsOfUseRequest.qml
│ │ │ │ ├── WCWalletName.qml
│ │ │ │ ├── WCWalletPassword.qml
│ │ │ │ ├── WCWalletType.qml
│ │ │ │ ├── WCWelcome.qml
│ │ │ │ ├── Wizard.qml
│ │ │ │ └── WizardComponent.qml
│ │ │ ├── java_classes/
│ │ │ │ └── org/
│ │ │ │ └── electrum/
│ │ │ │ ├── biometry/
│ │ │ │ │ ├── BiometricActivity.java
│ │ │ │ │ └── BiometricHelper.java
│ │ │ │ └── qr/
│ │ │ │ └── SimpleScannerActivity.java
│ │ │ ├── qeaddressdetails.py
│ │ │ ├── qeaddresslistmodel.py
│ │ │ ├── qeapp.py
│ │ │ ├── qebiometrics.py
│ │ │ ├── qebip39recovery.py
│ │ │ ├── qebitcoin.py
│ │ │ ├── qechanneldetails.py
│ │ │ ├── qechannellistmodel.py
│ │ │ ├── qechannelopener.py
│ │ │ ├── qeconfig.py
│ │ │ ├── qedaemon.py
│ │ │ ├── qefx.py
│ │ │ ├── qeinvoice.py
│ │ │ ├── qeinvoicelistmodel.py
│ │ │ ├── qelnpaymentdetails.py
│ │ │ ├── qemodelfilter.py
│ │ │ ├── qenetwork.py
│ │ │ ├── qepiresolver.py
│ │ │ ├── qeqr.py
│ │ │ ├── qeqrscanner.py
│ │ │ ├── qerequestdetails.py
│ │ │ ├── qeserverlistmodel.py
│ │ │ ├── qeswaphelper.py
│ │ │ ├── qetransactionlistmodel.py
│ │ │ ├── qetxdetails.py
│ │ │ ├── qetxfinalizer.py
│ │ │ ├── qetypes.py
│ │ │ ├── qewallet.py
│ │ │ ├── qewizard.py
│ │ │ └── util.py
│ │ ├── qt/
│ │ │ ├── __init__.py
│ │ │ ├── address_dialog.py
│ │ │ ├── address_list.py
│ │ │ ├── amountedit.py
│ │ │ ├── balance_dialog.py
│ │ │ ├── bip39_recovery_dialog.py
│ │ │ ├── channel_details.py
│ │ │ ├── channels_list.py
│ │ │ ├── completion_text_edit.py
│ │ │ ├── confirm_tx_dialog.py
│ │ │ ├── console.py
│ │ │ ├── contact_list.py
│ │ │ ├── custom_model.py
│ │ │ ├── exception_window.py
│ │ │ ├── fee_slider.py
│ │ │ ├── history_list.py
│ │ │ ├── invoice_list.py
│ │ │ ├── lightning_dialog.py
│ │ │ ├── lightning_tx_dialog.py
│ │ │ ├── locktimeedit.py
│ │ │ ├── main_window.py
│ │ │ ├── my_treeview.py
│ │ │ ├── network_dialog.py
│ │ │ ├── new_channel_dialog.py
│ │ │ ├── password_dialog.py
│ │ │ ├── paytoedit.py
│ │ │ ├── plugins_dialog.py
│ │ │ ├── qrcodewidget.py
│ │ │ ├── qrreader/
│ │ │ │ ├── __init__.py
│ │ │ │ └── qtmultimedia/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── camera_dialog.py
│ │ │ │ ├── crop_blur_effect.py
│ │ │ │ ├── validator.py
│ │ │ │ ├── video_overlay.py
│ │ │ │ ├── video_surface.py
│ │ │ │ └── video_widget.py
│ │ │ ├── qrtextedit.py
│ │ │ ├── qrwindow.py
│ │ │ ├── rate_limiter.py
│ │ │ ├── rbf_dialog.py
│ │ │ ├── rebalance_dialog.py
│ │ │ ├── receive_tab.py
│ │ │ ├── request_list.py
│ │ │ ├── seed_dialog.py
│ │ │ ├── send_tab.py
│ │ │ ├── settings_dialog.py
│ │ │ ├── stylesheet_patcher.py
│ │ │ ├── swap_dialog.py
│ │ │ ├── transaction_dialog.py
│ │ │ ├── update_checker.py
│ │ │ ├── util.py
│ │ │ ├── utxo_dialog.py
│ │ │ ├── utxo_list.py
│ │ │ ├── wallet_info_dialog.py
│ │ │ └── wizard/
│ │ │ ├── __init__.py
│ │ │ ├── server_connect.py
│ │ │ ├── terms_of_use.py
│ │ │ ├── wallet.py
│ │ │ └── wizard.py
│ │ ├── stdio.py
│ │ └── text.py
│ ├── harden_memory_linux.py
│ ├── hw_wallet/
│ │ ├── __init__.py
│ │ ├── cmdline.py
│ │ ├── plugin.py
│ │ ├── qt.py
│ │ └── trezor_qt_pinmatrix.py
│ ├── i18n.py
│ ├── interface.py
│ ├── invoices.py
│ ├── json_db.py
│ ├── keystore.py
│ ├── lnaddr.py
│ ├── lnchannel.py
│ ├── lnhtlc.py
│ ├── lnmsg.py
│ ├── lnonion.py
│ ├── lnpeer.py
│ ├── lnrater.py
│ ├── lnrouter.py
│ ├── lnsweep.py
│ ├── lntransport.py
│ ├── lnurl.py
│ ├── lnutil.py
│ ├── lnverifier.py
│ ├── lnwatcher.py
│ ├── lnwire/
│ │ ├── README.md
│ │ ├── onion_wire.csv
│ │ └── peer_wire.csv
│ ├── lnworker.py
│ ├── logging.py
│ ├── lrucache.py
│ ├── mnemonic.py
│ ├── mpp_split.py
│ ├── network.py
│ ├── old_mnemonic.py
│ ├── onion_message.py
│ ├── payment_identifier.py
│ ├── paymentrequest.proto
│ ├── paymentrequest.py
│ ├── paymentrequest_pb2.py
│ ├── pem.py
│ ├── plot.py
│ ├── plugin.py
│ ├── plugins/
│ │ ├── README
│ │ ├── __init__.py
│ │ ├── audio_modem/
│ │ │ ├── __init__.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── bitbox02/
│ │ │ ├── __init__.py
│ │ │ ├── bitbox02.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── coldcard/
│ │ │ ├── README.md
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── coldcard.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── digitalbitbox/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── digitalbitbox.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── jade/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── jade.py
│ │ │ ├── jadepy/
│ │ │ │ ├── README.md
│ │ │ │ ├── __init__.py
│ │ │ │ ├── jade.py
│ │ │ │ ├── jade_error.py
│ │ │ │ ├── jade_serial.py
│ │ │ │ └── jade_tcp.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── keepkey/
│ │ │ ├── __init__.py
│ │ │ ├── client.py
│ │ │ ├── clientbase.py
│ │ │ ├── cmdline.py
│ │ │ ├── keepkey.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── labels/
│ │ │ ├── Labels.qml
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── labels.py
│ │ │ ├── manifest.json
│ │ │ ├── qml.py
│ │ │ └── qt.py
│ │ ├── ledger/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── ledger.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── nwc/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── manifest.json
│ │ │ ├── nwcserver.py
│ │ │ └── qt.py
│ │ ├── psbt_nostr/
│ │ │ ├── __init__.py
│ │ │ ├── manifest.json
│ │ │ ├── psbt_nostr.py
│ │ │ ├── qml/
│ │ │ │ ├── PsbtReceiveDialog.qml
│ │ │ │ └── main.qml
│ │ │ ├── qml.py
│ │ │ └── qt.py
│ │ ├── revealer/
│ │ │ ├── LICENSE_DEJAVU.txt
│ │ │ ├── SIL Open Font License.txt
│ │ │ ├── SourceSans3-Bold.otf
│ │ │ ├── __init__.py
│ │ │ ├── hmac_drbg.py
│ │ │ ├── manifest.json
│ │ │ ├── qt.py
│ │ │ └── revealer.py
│ │ ├── safe_t/
│ │ │ ├── __init__.py
│ │ │ ├── client.py
│ │ │ ├── clientbase.py
│ │ │ ├── cmdline.py
│ │ │ ├── manifest.json
│ │ │ ├── qt.py
│ │ │ ├── safe_t.py
│ │ │ └── transport.py
│ │ ├── swapserver/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── manifest.json
│ │ │ ├── server.py
│ │ │ └── swapserver.py
│ │ ├── timelock_recovery/
│ │ │ ├── __init__.py
│ │ │ ├── intro.txt
│ │ │ ├── manifest.json
│ │ │ ├── qt.py
│ │ │ └── timelock_recovery.py
│ │ ├── trezor/
│ │ │ ├── __init__.py
│ │ │ ├── clientbase.py
│ │ │ ├── cmdline.py
│ │ │ ├── manifest.json
│ │ │ ├── qt.py
│ │ │ └── trezor.py
│ │ ├── trustedcoin/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── common_qt.py
│ │ │ ├── manifest.json
│ │ │ ├── qml/
│ │ │ │ ├── ChooseSeed.qml
│ │ │ │ ├── Disclaimer.qml
│ │ │ │ ├── KeepDisable.qml
│ │ │ │ ├── ShowConfirmOTP.qml
│ │ │ │ └── Terms.qml
│ │ │ ├── qml.py
│ │ │ ├── qt.py
│ │ │ └── trustedcoin.py
│ │ └── watchtower/
│ │ ├── __init__.py
│ │ ├── cmdline.py
│ │ ├── manifest.json
│ │ ├── server.py
│ │ └── watchtower.py
│ ├── qrreader/
│ │ ├── __init__.py
│ │ ├── abstract_base.py
│ │ └── zbar.py
│ ├── qrscanner.py
│ ├── ripemd.py
│ ├── rsakey.py
│ ├── scripts/
│ │ ├── README.md
│ │ ├── bip39_recovery.py
│ │ ├── block_headers.py
│ │ ├── bruteforce_pw.py
│ │ ├── estimate_fee.py
│ │ ├── get_history.py
│ │ ├── ln_features.py
│ │ ├── peers.py
│ │ ├── quick_start.py
│ │ ├── servers.py
│ │ ├── txbroadcast.py
│ │ ├── txradar.py
│ │ ├── update_default_servers.py
│ │ └── watch_address.py
│ ├── segwit_addr.py
│ ├── simple_config.py
│ ├── slip39.py
│ ├── sql_db.py
│ ├── storage.py
│ ├── submarine_swaps.py
│ ├── synchronizer.py
│ ├── trampoline.py
│ ├── transaction.py
│ ├── txbatcher.py
│ ├── util.py
│ ├── utils/
│ │ ├── __init__.py
│ │ ├── memory_leak.py
│ │ └── stacktracer.py
│ ├── verifier.py
│ ├── version.py
│ ├── wallet.py
│ ├── wallet_db.py
│ ├── wizard.py
│ ├── wordlist/
│ │ ├── chinese_simplified.txt
│ │ ├── english.txt
│ │ ├── japanese.txt
│ │ ├── portuguese.txt
│ │ ├── slip39.txt
│ │ └── spanish.txt
│ └── x509.py
├── electrum-env
├── electrum.desktop
├── fastlane/
│ └── metadata/
│ └── android/
│ └── en-US/
│ ├── full_description.txt
│ ├── short_description.txt
│ └── title.txt
├── org.electrum.electrum.metainfo.xml
├── pubkeys/
│ ├── Animazing.asc
│ ├── Emzy.asc
│ ├── ThomasV.asc
│ ├── bauerj.asc
│ ├── felixb_f321x.asc
│ ├── kyuupichan.asc
│ ├── sombernight.asc
│ ├── sombernight_releasekey.asc
│ └── wozz.asc
├── run_electrum
├── setup.cfg
├── setup.py
└── tests/
├── __init__.py
├── anchor-vectors.json
├── bip-0341/
│ └── wallet-test-vectors.json
├── blinded-onion-message-onion-test.json
├── cause_carbon_wallet.json
├── fiat_fx_data/
│ └── BitFinex_EUR
├── plugins/
│ ├── __init__.py
│ ├── test_revealer.py
│ ├── test_timelock_recovery/
│ │ └── default_wallet
│ └── test_timelock_recovery.py
├── qml/
│ ├── __init__.py
│ ├── qt_util.py
│ ├── test_qml_qeconfig.py
│ ├── test_qml_qetransactionlistmodel.py
│ └── test_qml_types.py
├── regtest/
│ ├── regtest.sh
│ ├── run_bitcoind.sh
│ └── run_electrumx.sh
├── regtest.py
├── slip39-vectors.json
├── test_bitcoin.py
├── test_blockchain.py
├── test_bolt11.py
├── test_callbackmgr.py
├── test_coinchooser.py
├── test_commands.py
├── test_contacts.py
├── test_daemon.py
├── test_descriptor.py
├── test_fee_policy.py
├── test_history_export/
│ ├── history_no_fx_client_4_5_2_9dk_with_ln.csv
│ ├── history_no_fx_client_4_5_2_9dk_with_ln.json
│ ├── history_with_fx_client_4_5_2_9dk_with_ln.csv
│ └── history_with_fx_client_4_5_2_9dk_with_ln.json
├── test_i18n.py
├── test_interface.py
├── test_invoices.py
├── test_jsondb.py
├── test_lnchannel.py
├── test_lnhtlc.py
├── test_lnmsg.py
├── test_lnpeer.py
├── test_lnpeermgr.py
├── test_lnrouter.py
├── test_lntransport.py
├── test_lnurl.py
├── test_lnutil.py
├── test_lnwallet.py
├── test_mnemonic.py
├── test_mpp_split.py
├── test_network.py
├── test_onion_message.py
├── test_payment_identifier.py
├── test_psbt.py
├── test_simple_config.py
├── test_storage_upgrade/
│ ├── client_1_9_8_seeded
│ ├── client_2_0_4_importedkeys
│ ├── client_2_0_4_multisig
│ ├── client_2_0_4_seeded
│ ├── client_2_0_4_trezor_multiacc
│ ├── client_2_0_4_trezor_singleacc
│ ├── client_2_0_4_watchaddresses
│ ├── client_2_1_1_importedkeys
│ ├── client_2_1_1_multisig
│ ├── client_2_1_1_seeded
│ ├── client_2_1_1_trezor_multiacc
│ ├── client_2_1_1_trezor_singleacc
│ ├── client_2_1_1_watchaddresses
│ ├── client_2_2_0_importedkeys
│ ├── client_2_2_0_multisig
│ ├── client_2_2_0_seeded
│ ├── client_2_2_0_trezor_multiacc
│ ├── client_2_2_0_trezor_singleacc
│ ├── client_2_2_0_watchaddresses
│ ├── client_2_3_2_importedkeys
│ ├── client_2_3_2_multisig
│ ├── client_2_3_2_seeded
│ ├── client_2_3_2_trezor_multiacc
│ ├── client_2_3_2_trezor_singleacc
│ ├── client_2_3_2_watchaddresses
│ ├── client_2_4_3_importedkeys
│ ├── client_2_4_3_multisig
│ ├── client_2_4_3_seeded
│ ├── client_2_4_3_trezor_multiacc
│ ├── client_2_4_3_trezor_singleacc
│ ├── client_2_4_3_watchaddresses
│ ├── client_2_5_4_importedkeys
│ ├── client_2_5_4_multisig
│ ├── client_2_5_4_seeded
│ ├── client_2_5_4_trezor_multiacc
│ ├── client_2_5_4_trezor_singleacc
│ ├── client_2_5_4_watchaddresses
│ ├── client_2_6_4_importedkeys
│ ├── client_2_6_4_multisig
│ ├── client_2_6_4_seeded
│ ├── client_2_6_4_watchaddresses
│ ├── client_2_7_18_importedkeys
│ ├── client_2_7_18_multisig
│ ├── client_2_7_18_seeded
│ ├── client_2_7_18_trezor_singleacc
│ ├── client_2_7_18_watchaddresses
│ ├── client_2_8_3_importedkeys
│ ├── client_2_8_3_importedkeys_flawed_previous_upgrade_from_2_7_18
│ ├── client_2_8_3_multisig
│ ├── client_2_8_3_seeded
│ ├── client_2_8_3_trezor_singleacc
│ ├── client_2_8_3_watchaddresses
│ ├── client_2_9_3_importedkeys
│ ├── client_2_9_3_importedkeys_keystore_changes
│ ├── client_2_9_3_multisig
│ ├── client_2_9_3_old_seeded_with_realistic_history
│ ├── client_2_9_3_seeded
│ ├── client_2_9_3_trezor_singleacc
│ ├── client_2_9_3_watchaddresses
│ ├── client_3_2_3_ledger_standard_keystore_changes
│ ├── client_3_3_8_xpub_with_realistic_history
│ └── client_4_5_2_9dk_with_ln
├── test_storage_upgrade.py
├── test_transaction.py
├── test_txbatcher.py
├── test_util.py
├── test_verifier.py
├── test_wallet.py
├── test_wallet_vertical.py
├── test_wizard.py
└── test_x509.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .cirrus.yml
================================================
# unittests using the 'latest' runtime python-dependencies
task:
container:
image: $ELECTRUM_IMAGE
cpu: 1
memory: 2G
matrix:
- name: "unittests: py$ELECTRUM_PYTHON_VERSION"
env:
ELECTRUM_IMAGE: python:$ELECTRUM_PYTHON_VERSION
matrix:
- env:
ELECTRUM_PYTHON_VERSION: 3.10
- env:
ELECTRUM_PYTHON_VERSION: 3.11
- env:
ELECTRUM_PYTHON_VERSION: 3.12
- env:
ELECTRUM_PYTHON_VERSION: 3.13
- env:
ELECTRUM_PYTHON_VERSION: 3.14
- name: "unittests: py3.14, debug-mode"
env:
ELECTRUM_PYTHON_VERSION: 3.14
# enable additional checks:
PYTHONASYNCIODEBUG: "1"
PYTHONDEVMODE: "1"
pip_cache:
folder: ~/.cache/pip
fingerprint_script: echo $ELECTRUM_IMAGE && cat $ELECTRUM_REQUIREMENTS_CI && cat $ELECTRUM_REQUIREMENTS
tag_script:
- git tag
libsecp_build_cache:
folder: contrib/_saved_secp256k1_build
fingerprint_script: sha256sum ./contrib/make_libsecp256k1.sh
populate_script:
- apt-get update
- apt-get -y install automake libtool
- ./contrib/make_libsecp256k1.sh
- mkdir contrib/_saved_secp256k1_build
- cp electrum/libsecp256k1.so.* contrib/_saved_secp256k1_build/
install_script:
- apt-get update
# qml test reqs:
- apt-get -y install libgl1 libegl1 libxkbcommon0 libdbus-1-3
- pip install -r $ELECTRUM_REQUIREMENTS_CI
# electrum itself:
- export ELECTRUM_ECC_DONT_COMPILE=1
- pip install ".[tests,qml_gui]"
version_script:
- python3 --version
- pip freeze --all
pytest_script:
- >
coverage run --source=electrum \
"--omit=electrum/gui/*,electrum/plugins/*,electrum/scripts/*" \
-m pytest tests -v
- coverage report
coveralls_script:
- if [ ! -z "$COVERALLS_REPO_TOKEN" ] && [ "$ELECTRUM_PYTHON_VERSION" = "3.10" ] ; then coveralls ; fi
env:
LD_LIBRARY_PATH: contrib/_saved_secp256k1_build/
ELECTRUM_REQUIREMENTS_CI: contrib/requirements/requirements-ci.txt
ELECTRUM_REQUIREMENTS: contrib/requirements/requirements.txt
# following CI_* env vars are set up for coveralls
CI_NAME: "CirrusCI"
CI_BUILD_NUMBER: $CIRRUS_BUILD_ID
CI_JOB_ID: $CIRRUS_TASK_ID
CI_BUILD_URL: "https://cirrus-ci.com/task/$CIRRUS_TASK_ID"
CI_BRANCH: $CIRRUS_BRANCH
CI_PULL_REQUEST: $CIRRUS_PR
# in addition, COVERALLS_REPO_TOKEN is set as an "override" in https://cirrus-ci.com/settings/...
depends_on:
- "linter: Flake8 Mandatory"
# unittests using the ~same frozen dependencies that are used in the released binaries
# note: not using pinned pyqt here, due to "qml_gui" extra
task:
container:
image: $ELECTRUM_IMAGE
cpu: 1
memory: 2G
name: "unittests: py3.10, frozen-deps"
pip_cache:
folder: ~/.cache/pip
fingerprint_script: echo $ELECTRUM_IMAGE && cat contrib/requirements/requirements*.txt && cat contrib/deterministic-build/requirements*.txt
tag_script:
- git tag
libsecp_build_cache:
folder: contrib/_saved_secp256k1_build
fingerprint_script: sha256sum ./contrib/make_libsecp256k1.sh
populate_script:
- apt-get update
- apt-get -y install automake libtool
- ./contrib/make_libsecp256k1.sh
- mkdir contrib/_saved_secp256k1_build
- cp electrum/libsecp256k1.so.* contrib/_saved_secp256k1_build/
install_script:
- apt-get update
# qml test reqs:
- apt-get -y install libgl1 libegl1 libxkbcommon0 libdbus-1-3
- pip install -r contrib/deterministic-build/requirements-build-base.txt
- pip install -r contrib/requirements/requirements-ci.txt
# electrum itself:
- export ELECTRUM_ECC_DONT_COMPILE=1
- pip install -r contrib/deterministic-build/requirements.txt -r contrib/deterministic-build/requirements-binaries.txt
- pip install ".[tests,qml_gui]"
version_script:
- python3 --version
- pip freeze --all
pytest_script:
- pytest tests -v
env:
ELECTRUM_IMAGE: python:3.10
LD_LIBRARY_PATH: contrib/_saved_secp256k1_build/
depends_on:
- "linter: Flake8 Mandatory"
task:
name: "locale: upload to crowdin"
container:
image: $ELECTRUM_IMAGE
cpu: 1
memory: 1G
pip_cache:
folder: ~/.cache/pip
fingerprint_script: echo Locale && echo $ELECTRUM_IMAGE && cat $ELECTRUM_REQUIREMENTS_CI
install_script:
- apt-get update
- apt-get -y install gettext qt6-l10n-tools
- pip install -r $ELECTRUM_REQUIREMENTS_CI
- pip install requests
submodules_script:
- git submodule update --init
locale_script:
- contrib/locale/push_locale.py
env:
ELECTRUM_IMAGE: python:3.10
ELECTRUM_REQUIREMENTS_CI: contrib/requirements/requirements-ci.txt
# in addition, crowdin_api_key is set as an "override" in https://cirrus-ci.com/settings/...
# - api key is for crowdin account: "SomberNight_CI_BOT"
# - see https://crowdin.com/settings#api-key
depends_on:
- "unittests: py3.10"
only_if: $CIRRUS_BRANCH == 'master'
task:
name: "Regtest functional tests"
compute_engine_instance:
image_project: cirrus-images
image: family/docker-builder
platform: linux
cpu: 1
memory: 1G
pip_cache:
folder: ~/.cache/pip
fingerprint_script: echo Regtest && echo docker_builder && cat $ELECTRUM_REQUIREMENTS
bitcoind_cache:
folder: /tmp/bitcoind
populate_script: mkdir -p /tmp/bitcoind
install_script:
- apt-get update
- apt-get -y install curl jq bc
- python3 -m pip install --user --upgrade pip
# install electrum
- export ELECTRUM_ECC_DONT_COMPILE=1 # we build manually to make caching it easier
- python3 -m pip install .[tests] --ignore-installed # ignore installed system installed attrs
# install e-x some commits after 1.18.0 tag
- python3 -m pip install git+https://github.com/spesmilo/electrumx.git@0b260d4345242cc41e316e97d7de10ae472fd172
- "BITCOIND_VERSION=$(curl https://bitcoincore.org/en/download/ | grep -E -i --only-matching 'Latest version: [0-9\\.]+' | grep -E --only-matching '[0-9\\.]+')"
- BITCOIND_FILENAME=bitcoin-$BITCOIND_VERSION-x86_64-linux-gnu.tar.gz
- BITCOIND_PATH=/tmp/bitcoind/$BITCOIND_FILENAME
- BITCOIND_URL=https://bitcoincore.org/bin/bitcoin-core-$BITCOIND_VERSION/$BITCOIND_FILENAME
- tar -xaf $BITCOIND_PATH || (rm -f /tmp/bitcoind/* && curl --output $BITCOIND_PATH $BITCOIND_URL && tar -xaf $BITCOIND_PATH)
- cp -a bitcoin-$BITCOIND_VERSION/* /usr/
libsecp_build_cache:
folder: contrib/_saved_secp256k1_build
fingerprint_script: sha256sum ./contrib/make_libsecp256k1.sh
populate_script:
- apt-get -y install automake libtool
- ./contrib/make_libsecp256k1.sh
- mkdir contrib/_saved_secp256k1_build
- cp electrum/libsecp256k1.so.* contrib/_saved_secp256k1_build/
bitcoind_service_background_script:
- tests/regtest/run_bitcoind.sh
electrumx_service_background_script:
- tests/regtest/run_electrumx.sh
# if any test fails, the test will get aborted (--failfast) and the wallet directories will be
# available for download in the Cirrus UI
regtest_script:
- sleep 10s
- python3 -m unittest tests/regtest.py --failfast || TEST_EXIT_CODE=$?
- tar -czf test_wallets.tar.gz /tmp/alice /tmp/bob /tmp/carol || true
- exit ${TEST_EXIT_CODE:-0}
on_failure:
wallet_artifacts:
path: "test_wallets.tar.gz"
env:
LD_LIBRARY_PATH: contrib/_saved_secp256k1_build/
ELECTRUM_REQUIREMENTS: contrib/requirements/requirements.txt
PIP_BREAK_SYSTEM_PACKAGES: 1
# ElectrumX exits with an error without this:
ALLOW_ROOT: 1
depends_on:
- "linter: Flake8 Mandatory"
task:
container:
image: $ELECTRUM_IMAGE
cpu: 1
memory: 1G
pip_cache:
folder: ~/.cache/pip
fingerprint_script: echo Flake8 && echo $ELECTRUM_IMAGE && cat $ELECTRUM_REQUIREMENTS
install_script:
- pip install "flake8==7.3.0" "flake8-bugbear==25.10.21"
flake8_script:
- flake8 . --count --select="$ELECTRUM_LINTERS" --ignore="$ELECTRUM_LINTERS_IGNORE" --show-source --statistics --exclude "*_pb2.py,electrum/_vendor/"
env:
ELECTRUM_IMAGE: python:3.10
ELECTRUM_REQUIREMENTS: contrib/requirements/requirements.txt
matrix:
- name: "linter: Flake8 Mandatory"
env:
# list of error codes:
# - https://flake8.pycqa.org/en/latest/user/error-codes.html
# - https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes
# - https://github.com/PyCQA/flake8-bugbear/tree/8c0e7eb04217494d48d0ab093bf5b31db0921989#list-of-warnings
ELECTRUM_LINTERS: E9,E101,E129,E273,E274,E703,E71,E722,F5,F6,F7,F8,W191,W29,B,B909
ELECTRUM_LINTERS_IGNORE: B007,B009,B010,B036,B042,F541,F841
- name: "linter: Flake8 Non-Mandatory"
env:
ELECTRUM_LINTERS: E,F,W,C90,B
ELECTRUM_LINTERS_IGNORE: ""
allow_failures: true
task:
name: "linter: ban unicode"
container:
image: python:3.10
cpu: 1
memory: 1G
main_script:
- contrib/ban_unicode.py
# Cron jobs configured in https://cirrus-ci.com/settings/...
# - job "nightly" on branch "master" at "0 30 2 * * ?" (every day at 02:30Z)
task:
name: "build: Windows"
matrix:
- trigger_type: manual
only_if: $CIRRUS_CRON == ""
- trigger_type: automatic
only_if: $CIRRUS_CRON == "nightly"
container:
dockerfile: contrib/build-wine/Dockerfile
cpu: 1
memory: 3G
pip_cache:
folders:
- contrib/build-wine/.cache/win*/wine_pip_cache
fingerprint_script:
- echo $CIRRUS_TASK_NAME
- git ls-files -s contrib/deterministic-build/*.txt
- git ls-files -s contrib/build-wine/
build2_cache:
folders:
- contrib/build-wine/.cache/win*/build
fingerprint_script:
- echo $CIRRUS_TASK_NAME
- cat contrib/make_libsecp256k1.sh | sha256sum
- cat contrib/make_libusb.sh | sha256sum
- cat contrib/make_zbar.sh | sha256sum
- git ls-files -s contrib/build-wine/
build_script:
- cd contrib/build-wine
- ./make_win.sh
binaries_artifacts:
path: "contrib/build-wine/dist/*"
env:
CIRRUS_WORKING_DIR: /opt/wine64/drive_c/electrum
CIRRUS_DOCKER_CONTEXT: contrib/build-wine
depends_on:
- "unittests: py3.10"
task:
name: "build: Android (QML $APK_ARCH)"
matrix:
- trigger_type: manual
only_if: $CIRRUS_CRON == ""
- trigger_type: automatic
only_if: $CIRRUS_CRON == "nightly"
timeout_in: 90m
container:
dockerfile: contrib/android/Dockerfile
cpu: 8
memory: 24G
env:
APK_ARCH: arm64-v8a
packages_tld_folder_cache:
folder: packages
fingerprint_script:
- echo $CIRRUS_TASK_NAME && cat contrib/deterministic-build/requirements.txt && cat contrib/make_packages.sh
- git ls-files -s contrib/android/
p4a_cache:
folders:
- ".buildozer/android/platform/build-$APK_ARCH/packages"
- ".buildozer/android/platform/build-$APK_ARCH/build"
fingerprint_script:
# note: should *at least* depend on Dockerfile and p4a_recipes/, but contrib/android/ is simplest
- git ls-files -s contrib/android/
- echo "qml $APK_ARCH"
build_script:
- ./contrib/android/make_apk.sh qml "$APK_ARCH" debug
binaries_artifacts:
path: "dist/*"
depends_on:
- "unittests: py3.10"
## mac build disabled, as Cirrus CI no longer supports Intel-based mac builds
#task:
# name: "build: macOS"
# macos_instance:
# image: catalina-xcode-11.3.1
# env:
# TARGET_OS: macOS
# pip_cache:
# folder: ~/Library/Caches/pip
# fingerprint_script:
# - echo $CIRRUS_TASK_NAME
# - git ls-files -s contrib/deterministic-build/*.txt
# - git ls-files -s contrib/osx/
# build2_cache:
# folder: contrib/osx/.cache
# fingerprint_script:
# - echo $CIRRUS_TASK_NAME
# - cat contrib/make_libsecp256k1.sh | shasum -a 256
# - cat contrib/make_libusb.sh | shasum -a 256
# - cat contrib/make_zbar.sh | shasum -a 256
# - git ls-files -s contrib/osx/
# install_script:
# - git fetch --all --tags
# build_script:
# - ./contrib/osx/make_osx.sh
# sum_script:
# - ls -lah dist
# - shasum -a 256 dist/*.dmg
# binaries_artifacts:
# path: "dist/*"
task:
name: "build: AppImage"
matrix:
- trigger_type: manual
only_if: $CIRRUS_CRON == ""
- trigger_type: automatic
only_if: $CIRRUS_CRON == "nightly"
compute_engine_instance:
image_project: cirrus-images
image: family/docker-builder
platform: linux
cpu: 2
memory: 2G
pip_cache:
folder: contrib/build-linux/appimage/.cache/pip_cache
fingerprint_script:
- echo $CIRRUS_TASK_NAME
- git ls-files -s contrib/deterministic-build/*.txt
- git ls-files -s contrib/build-linux/appimage/
build2_cache:
folder: contrib/build-linux/appimage/.cache/appimage
fingerprint_script:
- echo $CIRRUS_TASK_NAME
- cat contrib/make_libsecp256k1.sh | sha256sum
- git ls-files -s contrib/build-linux/appimage/
build_script:
- ./contrib/build-linux/appimage/build.sh
binaries_artifacts:
path: "dist/*"
depends_on:
- "unittests: py3.10"
task:
container:
dockerfile: contrib/build-linux/sdist/Dockerfile
cpu: 1
memory: 1G
pip_cache:
folder: ~/.cache/pip
fingerprint_script:
- echo $CIRRUS_TASK_NAME
- git ls-files -s contrib/deterministic-build/*.txt
- git ls-files -s contrib/build-linux/sdist/
build_script:
- ./contrib/build-linux/sdist/make_sdist.sh
binaries_artifacts:
path: "dist/*"
matrix:
- name: "build: tarball"
- name: "build: source-only tarball"
env:
OMIT_UNCLEAN_FILES: 1
depends_on:
- "unittests: py3.10"
task:
name: "check submodules"
container:
image: python:3.10
cpu: 1
memory: 1G
fetch_script:
- git fetch --all --tags
check_script:
- ./contrib/deterministic-build/check_submodules.sh
only_if: $CIRRUS_TAG != ''
================================================
FILE: .editorconfig
================================================
# see https://EditorConfig.org
root = true
[*]
indent_style = space
trim_trailing_whitespace = true
end_of_line = lf
charset = utf-8
[*.py]
indent_size = 4
insert_final_newline = true
[*.sh]
indent_size = 4
insert_final_newline = true
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform end-of-line normalization (to LF)
* text=auto
# These Windows files should have CRLF line endings in checkout
*.bat text eol=crlf
*.ps1 text eol=crlf
# Never perform LF normalization on these files
*.ico binary
*.jar binary
*.png binary
*.zip binary
================================================
FILE: .github/ISSUE_TEMPLATE/01_issue.yml
================================================
name: Issue
description: Submit a new issue.
#labels: [bug]
body:
- type: markdown
attributes:
value: |
## Read this first!
* This issue tracker is for bug reports and development, not general questions.
* There is no private support! Scammers will reply to you here and tell you to go to their external website or contact them privately in email/telegram/whatsapp/etc.
They will try to **steal** your coins!
Be extremely suspicious of anyone offering help in a non-public way. Scammers will want to chat with you in private as then other people will not get a chance to point out the scam.
* Do not post issues about non-**Bitcoin** versions of Electrum.
----
#- type: checkboxes
# attributes:
# label: Is there an existing issue for this already?
# #description: Please search to see if this issue is already being tracked.
# options:
# - label: I have searched the existing issues
# required: true
- type: textarea
id: main-text-body
attributes:
label: Description
#description: Tell us what went wrong
placeholder: Please search existing issues for duplicates.
validations:
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
# - name: Electrum Security Policy
# url: https://github.com/spesmilo/electrum/blob/master/SECURITY.md
# about: View security policy
- name: Community Forum
url: https://bitcointalk.org/index.php?board=98.0
about: Ask non-development-related questions here
================================================
FILE: .gitignore
================================================
.git/
####-*.patch
**/*.pyc
*.swp
build/
dist/
*.egg/
Electrum.egg-info/
.devlocaltmp/
*_trial_temp
packages
env/
/.venv*/
.buildozer
.buildozer_*/
bin/
.idea
.mypy_cache
.vscode
electrum_data
.DS_Store
contrib/trigger_website
contrib/trigger_binaries
# tests/tox
.tox/
.cache/
.coverage
.pytest_cache
# build workspaces
contrib/build-wine/tmp/
contrib/build-wine/build/
contrib/build-wine/.cache/
contrib/build-wine/dist/
contrib/build-wine/signed/
contrib/build-linux/appimage/build/
contrib/build-linux/appimage/.cache/
contrib/osx/.cache/
contrib/osx/build-venv/
contrib/android/android_debug.keystore
contrib/android/.cache/
contrib/secp256k1/
contrib/zbar/
contrib/libusb/
contrib/.venv_make_packages/
# shared objects
electrum/*.so
electrum/*.so.*
electrum/*.dll
electrum/*.dylib
contrib/osx/*.dylib
================================================
FILE: .gitmodules
================================================
[submodule "electrum/locale"]
path = electrum/locale
url = https://github.com/spesmilo/electrum-locale
ignore = dirty
[submodule "electrum/plugins/keepkey/keepkeylib"]
path = electrum/plugins/keepkey/keepkeylib
url = https://github.com/spesmilo/electrum-keepkeylib.git
================================================
FILE: AUTHORS
================================================
ThomasV - Creator and maintainer.
Animazing / Tachikoma - Styled the new GUI. Mac version.
Azelphur - GUI stuff.
Coblee - Alternate coin support and py2app support.
Deafboy - Ubuntu packages.
Soren Stoutner - Debian packages and some Qt GUI layout.
EagleTM - Bugfixes.
ErebusBat - Mac distribution.
Genjix - Porting pro-mode functionality to lite-gui and worked on server
Slush - Work on the server. Designed the original Stratum spec.
Julian Toash (Tuxavant) - Various fixes to the client.
rdymac - Website and translations.
kyuupichan - Miscellaneous.
================================================
FILE: LICENCE
================================================
The MIT License (MIT)
Copyright (c) 2011-2024 The Electrum developers
Copyright (c) 2011-2024 Thomas Voegtlin
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: MANIFEST.in
================================================
include LICENCE RELEASE-NOTES AUTHORS
include README.md
include electrum.desktop
include *.py
include run_electrum
include org.electrum.electrum.metainfo.xml
recursive-include packages *.py
recursive-include packages cacert.pem
include contrib/requirements/requirements*.txt
include contrib/deterministic-build/requirements*.txt
include contrib/*.sh
graft electrum
graft tests
graft contrib/udev
exclude electrum/*.so
exclude electrum/*.so.0
exclude electrum/*.dll
exclude electrum/*.dylib
global-exclude __pycache__
global-exclude *.py[co~]
global-exclude *.py.orig
global-exclude *.py.rej
global-exclude .git
# We include both source (.po) and compiled (.mo) locale files (if present).
# When building the "sourceonly" tar.gz, the build script explicitly deletes the compiled files.
# exclude electrum/locale/locale/*/LC_MESSAGES/electrum.mo
================================================
FILE: README.md
================================================
# Electrum - Lightweight Bitcoin client
```
Licence: MIT Licence
Author: Thomas Voegtlin
Language: Python (>= 3.10)
Homepage: https://electrum.org/
```
[](https://cirrus-ci.com/github/spesmilo/electrum)
[](https://coveralls.io/github/spesmilo/electrum?branch=master)
[](https://crowdin.com/project/electrum)
## Getting started
_(If you've come here looking to simply run Electrum,
[you may download it here](https://electrum.org/#download).)_
Electrum itself is pure Python, and so are most of the required dependencies,
but not everything. The following sections describe how to run from source, but here
is a TL;DR:
```
$ sudo apt-get install libsecp256k1-dev
$ ELECTRUM_ECC_DONT_COMPILE=1 python3 -m pip install --user ".[gui,crypto]"
```
### Not pure-python dependencies
#### Qt GUI
If you want to use the Qt interface, install the Qt dependencies:
```
$ sudo apt-get install python3-pyqt6
```
#### libsecp256k1
For elliptic curve operations,
[libsecp256k1](https://github.com/bitcoin-core/secp256k1)
is a required dependency.
If you "pip install" Electrum, by default libsecp will get compiled locally,
as part of the `electrum-ecc` dependency. This can be opted-out of,
by setting the `ELECTRUM_ECC_DONT_COMPILE=1` environment variable.
For the compilation to work, besides a C compiler, you need at least:
```
$ sudo apt-get install automake libtool
```
If you opt out of the compilation, you need to provide libsecp in another way, e.g.:
```
$ sudo apt-get install libsecp256k1-dev
```
#### cryptography
Due to the need for fast symmetric ciphers,
[cryptography](https://github.com/pyca/cryptography) is required.
Install from your package manager (or from pip):
```
$ sudo apt-get install python3-cryptography
```
#### hardware-wallet support
If you would like hardware wallet support,
[see this](https://github.com/spesmilo/electrum-docs/blob/master/hardware-linux.rst).
### Running from tar.gz
If you downloaded the official package (tar.gz), you can run
Electrum from its root directory without installing it on your
system; all the pure python dependencies are included in the 'packages'
directory. To run Electrum from its root directory, just do:
```
$ ./run_electrum
```
You can also install Electrum on your system, by running this command:
```
$ sudo apt-get install python3-setuptools python3-pip
$ python3 -m pip install --user .
```
This will download and install the Python dependencies used by
Electrum instead of using the 'packages' directory.
It will also place an executable named `electrum` in `~/.local/bin`,
so make sure that is on your `PATH` variable.
### Development version (git clone)
_(For OS-specific instructions, see [here for Windows](contrib/build-wine/README_windows.md),
and [for macOS](contrib/osx/README_macos.md))_
Check out the code from GitHub:
```
$ git clone https://github.com/spesmilo/electrum.git
$ cd electrum
$ git submodule update --init
```
Run install (this should install dependencies):
```
$ python3 -m pip install --user -e .
```
Create translations (optional):
```
$ sudo apt-get install gettext
$ ./contrib/locale/build_locale.sh electrum/locale/locale electrum/locale/locale
```
Finally, to start Electrum:
```
$ ./run_electrum
```
### Run tests
Run unit tests with `pytest`:
```
$ pytest tests -v
```
(can be parallelized with `-n auto` option, using [`pytest-xdist`](https://github.com/pytest-dev/pytest-xdist) plugin)
To run a single file, specify it directly like this:
```
$ pytest tests/test_bitcoin.py -v
```
## Creating Binaries
- [Linux (tarball)](contrib/build-linux/sdist/README.md)
- [Linux (AppImage)](contrib/build-linux/appimage/README.md)
- [macOS](contrib/osx/README.md)
- [Windows](contrib/build-wine/README.md)
- [Android](contrib/android/Readme.md)
## Contributing
Any help testing the software, reporting or fixing bugs, reviewing pull requests
and recent changes, writing tests, or helping with outstanding issues is very welcome.
Implementing new features, or improving/refactoring the codebase, is of course
also welcome, but to avoid wasted effort, especially for larger changes,
we encourage discussing these on the issue tracker or IRC first.
Besides [GitHub](https://github.com/spesmilo/electrum),
most communication about Electrum development happens on IRC, in the
`#electrum` channel on Libera Chat. The easiest way to participate on IRC is
with the web client, [web.libera.chat](https://web.libera.chat/#electrum).
Please improve translations on [Crowdin](https://crowdin.com/project/electrum).
================================================
FILE: RELEASE-NOTES
================================================
# Release 4.7.1 (Feb 26, 2026)
* Qt GUI (desktop):
- new: changelog website accessible from "Help" toolbar menu (#10433)
- new: show translation completion percentage in language names (#10479)
- new: allow changing font size in console (#10494)
- changed: validate Electrum server address input with UI feedback (#10441)
- changed: stop showing anchor icon for lightning channels with anchor outputs (3979d70)
- fix: broken addresses tab for imported watch-only wallets (#10436)
* QML GUI & Android:
- new: show translation completion percentage in language names (#10479)
- changed: validate Electrum server address input with UI feedback (#10441)
- fix: handle Java import error causing startup crash on Android 7 and 8 devices (#10484)
* Onchain / Wallet:
- fix: improved fee estimation for replacement transactions (#10453)
* Database:
- fix: handle upgrade failure for users with pending Lightning HTLCs (#10489)
* Lightning:
- changed: send channel_update alongside node_announcement gossip messages (#10475)
- fix: improved safety when revealing preimage on-chain (#10442)
- fix: don't attempt to fetch gossip from Tor peers without a proxy enabled (#10448)
- fix: handle peer sending back our own channel_update (#10493)
* Dependencies:
- changed: bump electrum-ecc (and libsecp256k1) from 0.7.0 to 0.7.1 (#10495)
* Builds/binaries:
- Android:
- changed: bump docker base image to Debian 13 (#10452)
* Contrib:
- changed: translation: stop sorting source strings (6c1e085)
- changed: freeze_packages.py: use stdlib "venv" instead of 3rd party virtualenv (4f7b6e8)
- fix: add_cosigner.py: compatibility with Python 3.13 (b495ee7)
* Plugins:
- new: hook 'qt_utxo_menu' for Qt GUI UTXO list (cfe2a57)
* Hardware wallets:
- new: support Ledger Nano Gen 5 (#10457)
* Translations: Call for Proofreaders and Translators.
- Localisation of the UI has always been a community effort.
Recently we found several examples of vandalism and malicious behaviour
among the translated strings, including multiple bitcoin addresses
injected into UI strings. One user sent funds to one such address
and hence lost money. (see spesmilo/electrum-locale#46)
- We added some automated safeguards to try and prevent this in the future,
including basic regexes and an LLM proofreader. We also made the ongoing
git diffs for updating the frozen translations much smaller to make it
realistic to ~review. (see spesmilo/electrum-locale#47, #49, #51)
- However, the best solution would be per-language human review.
If we had 1-3 proofreaders per language on Crowdin, we could restrict
the set of translated strings that gets included in the binaries to the
"proofreader-approved" strings. We ask interested people to start contributing
and apply to be proofreaders. To get proofreader permissions, send us an email
or come to irc, with your crowdin username and some proof of work (such as
activity on crowdin in our or another project, contributions to open-source,
having an established identity on github/bitcointalk/stackoverflow/..., etc
-- just prove being a human and being well-intentioned).
(see https://github.com/spesmilo/electrum-locale/issues/47#issuecomment-3914866337)
# Release 4.7.0 (Jan 22, 2026)
* Qt GUI (desktop):
- new: "Submarine Payments": support reverse swaps to external address (#10303)
Allows doing onchain payments from the wallet's lightning balance.
- changed: flag console usage in crash reports (#10219)
- changed: add "Tools" text to the tools button for increased visibility (#10277)
- changed: improved UI feedback for send change to lightning function (#10247)
- fix: improve Network Tab behavior when switching connection mode (#10280)
- fix: re-add fiat values to csv/json history export (#10209)
- fix: not proposing tx batching in some cases (#10204)
* QML GUI & Android:
- new: allow manual editing of fee/feerate (#10371)
This also allows sending sub-1 sat/b transactions on Android.
- new: support biometric authentication (#10340)
Allows using the Android system lockscreen (e.g. fingerprints)
to unlock the wallet and authorize payments.
The previous optional built-in PIN code authentication is removed.
- changed: make UI compatible with edge-to-edge layout (#10178)
- changed: fee histogram colors: extend color palette to cover sub-1 s/b (#10307)
- changed: enforce the usage of a single password for all wallet files (#10345)
- changed: allow tap-to-focus in the qr code scanner (#10385)
- fix: allow opening passwordless wallets (#10423)
- fix: also protect address private keys from screenshots (#10426)
* Lightning:
- new: support LNURL-withdraw/LUD-3 (#9993)
Allows scanning QR codes to receive funds on lightning (e.g. ATMs, vouchers).
- changed: refactor handling of incoming htlcs (#10230)
- changed: collect htlcs failed back to us before re-splitting (#10274)
- fix: allow spending channel reserve if anchor channels are closed but not redeemed (2d17252)
- fix: logic bug in liquidity hint calculation (#10305)
- fix: race resulting in "Not enough balance" error when doing concurrent payments (#10325)
- fix: self payments (and rebalance function) (#10271)
- fix: gossip exchange with Core Lightning nodes (#10347)
- fix: only wait for pending htlcs to get removed if peer is connected (1845143)
* Electrum protocol:
- new: add support for Electrum Protocol version 1.6 (#10295)
See https://electrum-protocol.readthedocs.io/en/latest/protocol-changes.html#version-1-6
Min required version is still 1.4.
- changed: prevent connecting to server with different genesis hash (#10281)
- changed: add warmup budget before batching server rpc calls for faster startup (#10281)
- changed: optimistically guess scripthash status on new blocks to reduce network traffic
and improve privacy (#10290)
- fix: flush network buffer before disconnecting from server (6423323)
* Onchain / Wallet:
- changed: non-SPV verified transactions now considered unconfirmed (#10216)
- changed: always enforce dnssec validation for Openalias (#10349)
* Submarine swaps:
- new: cli commands to get swap statistics for swapserver operators (#10198):
'swapserver_get_history' and 'swapserver_get_summary'
* CLI/RPC:
- new: add 'export_lightning_preimage' command (#10242)
- changed: return lightning preimage from 'check_hold_invoice' command (#10242)
- changed: 'add_peer' now blocks until the connection is established (#10283)
- changed: 'version_info' now shows OpenSSL version (828fc56)
- fix: print warnings to stderr so output is still valid json (7bfe2dd)
- fix: imply enabled proxy when starting with proxy cli option (#10326)
* Plugins:
- changed: plugins can now use existing cli command names without colliding with builtin commands (9c4c7f0)
- changed: Timelock Recovery: check if locking address is ours or script (#10272)
- removed: payserver plugin, now an external plugin, moved to spesmilo/electrum-payserver (d36b753)
* Hardware wallets:
- Coldcard: fix: compatibility with ckcc-protocol v1.5.0 (2172dad)
* Contrib:
- new: add README to scripts/ directory (5a14a58)
* Dependencies:
- changed: bump min required electrum-aionostr to 0.1.0 (e188102)
* Builds/binaries:
- Android:
- new: support 16kb page size (#10148)
- changed: bump Android target SDK version to 35 (#10178)
- changed: bump OpenSSL from 1.1.1w to 3.0.18 (#10332)
- changed: switch from cryptography to pycryptodomex (#10332)
- changed: bump python version from 3.10.18 to 3.11.14 (#10388)
- AppImage:
- changed: migrate AppImage build to use modern/maintained appimagetool (#10019)
# Release 4.6.2 (Aug 25, 2025)
* General:
- changed: minrelayfee clamps from [1, 50] to [0.1, 50] sat/vbyte (#10096)
- new: add support for "mutinynet" signet test network (#10134)
- new: network: don't request same tx from server that we just broadcast to it (#10111)
- new: logging: add config.LOGS_MAX_TOTAL_SIZE_BYTES: to limit size on disk (#10159)
* QML GUI (Android):
- fix: cannot open keystore-encryption-only wallets (#10171)
- fix: wizard: restoring from seed broken if already opened a wallet (#10117)
- fix: handle invoice validation errors on save (#10122)
- fix: sweep: handle network errors gracefully (#10108)
- fix: sweep: handle unexpected script_types (#10145)
* Qt GUI (desktop):
- fix: wizard: hardware device: handle missing xpub (#10109)
- fix: wizard: enable-keystore for bip39 seeds and hw devices (#10123)
* Lightning:
- fix: slow down peers sending too much gossip, and other rate-limits (#10153)
* Submarine swaps: several bug fixes and improved reliability.
* CLI/RPC:
- changed: onchain_history: add back from_height/to_height params (#10119)
- changed: reverse_swap: new mandatory parameter 'prepayment' (#10165)
- new: get_submarine_swap_providers: added command to fetch swap providers (#10158)
* Plugins:
- Nostr Cosigner: fix: don't allow saving tx without txid (#10128)
# Release 4.6.1 (Aug 5, 2025)
* QML GUI (Android):
- fix: QR scanner crashes due to null/orphaned View in hierarchy (#10071)
- fix: creating a tx with a pre-segwit watchonly wallet (#10042)
* CLI/RPC:
- fix several bugs related to new hold_invoice APIs. This required
minor breaking changes in the new APIs. (#10059, #10082)
- add max_cltv, max_fee_msat parameters to lnpay command (#10067)
* Hardware wallets:
- bitbox02: bump required and bundled library to 7.0.0 (#10040)
This should add support for the new BitBox02 "Nova" devices.
* General:
- rework crash reporter (#10052)
- show additional confirmation popup on clicking "Send"
- remove the "Never" button and the corresponding config option.
The crash reporter is now always shown on uncaught exceptions.
This unifies some code paths: the crash-reporter-disabled case
was untested and buggy.
- don't show reporter multiple times for the "same" exception
- new: network: parallelize block-header-chunks downloads (#10033)
* Lightning:
- wallet: don't spend reserve utxo to create new reserve utxo (#10091)
* various UI fixes (#10060, #10062, #10081, ...)
# Release 4.6.0 (July 16, 2025)
* A 'Terms of Use' screen was added to the install wizard. While the
licence remains unchanged, we ask users to agree with the fact that
we are not a custodial service or a money transmitter. The Terms of
Use screen also makes it clear that all issues are to be resolved
in public, and that there is no user support via private channels.
* Nostr support: (using new dependency: electrum-aionostr)
Electrum now uses Nostr in the context of submarine swaps,
and in several plugins. Electrum will not connect to Nostr
by default, only if required.
* Submarine swaps over Nostr: The Electrum client will connect to
Nostr in order to discover submarine swap providers, and to perform
related RPCs. This means that:
- Anyone can become a swap provider (you need to run an Electrum
daemon with the 'swapserver' plugin). Submarine swap providers
advertise their fees and their liquidity on Nostr.
See https://electrum.readthedocs.io/en/latest/swapserver.html
for set-up documentation.
- Submarine swap providers do not need to provide an HTTP
endpoint, since RPCs are performed via Nostr. They also do not
need to have public lightning channels.
- Because a decentralized service needs to be trustless, the
option to perform zero-confirmation swaps has been removed from
Electrum.
Note that Electrum connections to Nostr relays are only initiated
when the user uses the swap service, and the nostr public key used
by the client is ephemeral. In contrast, swap providers use a
persisted identity.
* Third-party plugins:
- Electrum supports the installation of plugins distributed by
third-parties as ZIP files. While it has long been possible to
install third-party plugins when running Electrum from python
sources, the same is now possible when using desktop binaries
(Windows, MacOS, Linux). Third-party plugins are installed as ZIP
files in the user's electrum data directory.
- In order to prevent plugin installation by malware, third-party
plugins can only be enabled if the user enters a plugin
authorization password (distinct from the wallet password).
Setting up that plugin authorization password requires
administrator permissions on the local machine; a
password-derived public key must be written in the system.
* Lightning:
- Anchor channels (#9264): Newly created channels use
anchor commitments by default. Since sweeping outputs from anchor
channels may require external UTXOs, lightning can no longer be
enabled in wallets that do not have a software keystore (hardware
wallets, watching-only wallets). Existing wallets that are in that
situation cannot create new channels.
- wallets with anchor channels must always have utxos available (#9536)
- support added for onion messages (only CLI for now) (#9039)
- lots of fixes and improvements (#8857, #8547, #9700, #9083, ...)
* Qt Desktop GUI:
- migrate from Qt5 to Qt6 (#9189)
- new: screenshot "protection" on Windows (#9898). Inspired by Windows
Recall, by default screenshots will contain black rectangles in
place of the Electrum windows, to try to avoid leaking secret keys.
This is opt-out using a config variable.
- exposed option to connect to only a single server (--oneserver)
- Wallet file encryption:
- Non-multisig hardware wallet files can now be encrypted with
either using the hardware device or (new) a password. (#5561)
- The option to have a password-protected wallet without file
encryption has been removed from the Qt GUI. It is still possible
to create such a wallet using the command line.
- Wallet unlocking:
- Wallets can be unlocked in the Qt GUI. When a password-protected
wallet is unlocked, its password is kept in memory, and signing
transactions will not require to enter the password. The unlocked
state is rendered by the 'open lock' icon in the status bar.
- If a wallet needs to sweep anchor channel outputs using extra
UTXOs, the operations will be performed without requiring the
user password if the wallet is unlocked. If the wallet is locked,
the status bar will show a 'password required' button.
- Transaction batching: When creating a new payment, if the
output can be added to an existing mempool transaction, the 'New
transaction' window will show a drop-down menu, proposing a list of
transactions that can be batched with the current payment. This
replaces the previous 'batch' option checkbox, and gives more
control to the user.
- Keystore enabling/disabling (Qt):
- It is now possible to add a seed
to an existing watching-only wallet, or to a keystore within a
multisig wallet. Similarly, it is possible to pair a watching-only
keystore with a hardware device. These operations are performed
from the 'Wallet Information' dialog.
- Lightning address contacts:
- It is now possible to create contacts with (lnurl type) lightning
addresses as payment identifier.
- show warnings on wallet close if there are sensitive pending operations,
e.g. when in the middle of doing a swap (#9715)
- some performance improvements for large wallets (#9958, #9967, #9968)
- qr-reader: macos: add runtime requesting of camera permission (#9955)
* Accounting rules: In order to properly handle on-chain transactions
created by lightning channel force closures, we consider that funds
successfully redeemed from a script with several possible
recipients have never left the final recipient's wallet. This
avoids having to write balance changes that are cancelled
later. The corresponding addresses are rendered in the GUI as
'accounting addresses' (in orange).
* New plugins:
- Nostr Wallet Connect: This plugin allows remote control of
Electrum lightning wallets via Nostr NIP-47. (#9675)
- Nostr Cosigner: This plugin facilitates the exchange of
PSBTs between cosigners of a multisig wallet. It replaces the
former 'Cosigner pool' plugin. Instead of relying on a central
server, it uses Nostr to send/receive PSBTs. (#9261)
- Timelock Recovery: A timelock based inheritance scheme.
See timelockrecovery.com (#9589)
* CLI:
- The command line help has been improved; parameters are
documented in the same docstring as the command they belong to.
- If the --wallet parameter passed to a command is a simple filename,
it is now interpreted as relative to the users wallets directory,
rather than to the current working directory.
- Plugins may add extra commands to the CLI. Plugin commands must
be prefixed with the plugin's internal name.
- Support for hold invoices.
- new commands:
- listconfig, helpconfig, unsetconfig
- onchain_capital_gains (was previously a field of onchain_history)
- {add,settle,cancel,check}_hold_invoice
- send_onion_message, get_blinded_path_via
- wait_for_sync
* General:
- Mitigate against dust attacks; Add option to avoid spending from
used addresses. (#9636)
- Restrict process memory access on Linux. (#9749)
- locale: syntax-check i18n translations at runtime. Malformed translation
strings are now less likely to cause errors: instead we fallback to the
original English string (#10011)
- fix: would sometimes hang on startup if system clock jumped backwards (#9802)
* QML GUI (Android):
- "Sweep key" feature ported to mobile
- Estimate amount when Max is checked
- exposed option to connect to only a single server (--oneserver)
* Android:
- replace QR code scanning library to make scanning fun again (#9983)
- properly ask for (notification) OS permission access. (#9682)
- add option to prevent the app touching the screen brightness (#9321)
* Electrum protocol: add padding and some noise to messages (#9875)
* Hardware wallets:
- Coldcard: add feature to upload multisig wallet configuration to Coldcard via USB.
- KeepKey: we now vendor our fork of keepkeylib,
instead of using the unmaintained upstream as an external dependency (#9650)
- Ledger:
- rm support for "HW.1" and "Nano" (non-S) devices (#9652)
- rm dependency: btchip-python (#9370)
* Builds/binaries:
- new minimum OS requirements:
- Windows: x86_64, Windows 10 (1809)
note: 32-bit Windows is no longer supported.
- macOS: 11 "Big Sur"
- Linux AppImage: x86_64, glibc 2.31 ("debian 11"-equivalent)
* Dependencies:
- the minimum required python version was increased: 3.8->3.10 (#9418)
- new first-party dep: electrum-aionostr
- forked the seemingly unmaintained davestgermain/aionostr library
- new first-party dep: electrum-ecc
- split out our existing libsecp256k1 python bindings into
this separate package
# Release 4.5.8 (Oct 23, 2024)
* Qt Desktop GUI:
- fix: regression: bump_fee and dscancel dialogs erroring (#9273)
# Release 4.5.7 (Oct 21, 2024)
* General:
- new: add new historical exchange rate providers: Bitfinex and Bitstamp
- fix: wizard regression: 2fa wallet setup erroring (#9253)
- fix: python 3.13 compat: could not connect to some self-signed electrum
servers with weird TLS certs. As workaround, set pre-3.13 behaviour (#9258)
* Lightning:
- fix: send update_fee right away after channel_reestablish (3a465593)
This fixes a race that can result in a force-closure if we try sending
a payment very soon after reestablishing the channel.
* Qt Desktop GUI:
- fix: show fee warnings also in the transaction dialog (c4fe2796)
# Release 4.5.6 (Oct 16, 2024)
* General:
- new: add support for testnet4 (#9197)
- fix: wizard: allow passphrase for some '2fa' seeds (#9088)
- fix: trustedcoin wallet wizard continuation if file has keystore-only encryption (#9237)
- fix: trustedcoin: sanitize error messages coming from 2fa server
- fix: new wizard did not set keystore password if storage was not encrypted (#9147)
- changed: set stricter UNIX permissions for log files (fa8595b1)
* QML GUI (Android):
- new: show seed passphrase in WalletDetails (#9204)
- new: set max screen brightness when displaying QR codes (79c08536)
- fix: crash due to ConcurrentModificationException (450b9a0)
- fix: issue deactivating PIN when no wallet loaded (#8366)
- fix: only allow Channel Backup import on Lightning-enabled wallets (8d9bcda)
* Qt Desktop GUI:
- fix: scanning multi (privkeys, addresses) from QR (4dc64e4)
* Hardware wallets:
- ColdCard: new: export multisig wallet to coldcard over USB (#7682)
- Trezor:
- new: add support for new device "Safe 5" (#9171)
- update: fix compat with and bump pinned library to 0.13.9 (#9141)
- Ledger:
- new: add support for new device "Flex" (#9179)
- update: bump pinned library to 0.3.0, raise max lib to <0.4 (719292f8)
- Jade: update: bump library to 1.0.31 (9a84bb32)
* CLI/RPC:
- changed: require wallet password for lnpay and similar commands (#9236)
(This is in addition to the wallet needing to be loaded,
and requiring read access to the config file)
* Builds/binaries:
- changed: include unit tests in tarballs (#9207)
- android:
- changed: set target_sdk_version to 34 (2917fde5)
- update: bump python version (3.8->3.10) (08127a60)
- work towards F-Droid inclusion:
- reproducible apks: strip file path prefix from .pyc files (6ebdbf04)
- add fastlane metadata for f-droid (#9211)
- change versionCode calculation (#9221)
- build.gradle: set android.dependenciesInfo.includeInApk=false (af18df10)
- contrib/release_www.sh: put android versionCode in "version" file (#9233)
# Release 4.5.5 (May 30, 2024)
* General:
- fix: timeout error shadowed by aiorpcx cancellation bug (#8954)
- changed: Fiat exchange rates: do not overwrite the locally saved historical
data. Instead, merge old and new data (a2fb70d6). This also ~fixes the
CoinGecko historical API by only asking for the last 365 days.
- update: support latest revision of SLIP-39 mnemonic spec (to restore) (#9059)
* Lightning:
- new: unify max fee bounds for payments, make it configurable (#9041)
- changed: trampoline fees: instead of hardcoded list, use
exponential search, capped by configurable budget (#9033)
- fix: opening new channels with peer that has .onion address (#9002)
* Dependencies:
- remove bitstring (#9020)
* QML GUI (Android):
- new: add tx options to ConfirmTxDialog, RbfBumpFeeDialog (#8909)
- various UI fixes (#9018, 472a65eb)
* Qt Desktop GUI:
- fix: save notes whenever modified (#8951)
- fix: offline 2fa wallet creation failing in some cases (#9037)
- various UI fixes (#8962, #8874, #9012, 1047200a, #9058)
* Hardware wallets:
- Bitbox02: fix: call pairing dialog when necessary (#8971)
- Jade: update: bump library to 1.0.29 (#9007)
* Binaries:
- new: add AppArmor profiles for tarball and AppImage (#9003)
# Release 4.5.4 (March 14, 2024)
* General:
- fix: failing WalletDB upgrade(58) in 4.5.3 (#8913), for wallets with
partial txs saved into the history as local txs
* Lightning:
- changed: use longer final_cltv_delta for client-normal-swap, to
give more time for user to come back online while doing the swap (#8940)
- changed: create trampoline onions even when directly paying
a trampoline forwarder node (777c2ffb)
* Hardware wallets:
- Trezor:
- fix: allow adding SLIP-19 ownership proofs to complete inputs (#8910)
* Plugins:
- fix: a race in swapserver when handling server-normal-swaps (#8825)
# Release 4.5.3 (February 23, 2024)
* General:
- changed: label tx sizes as "vbytes", and feerates as "sat/vbyte" (#8864)
- fix: wizard regression not able to use HWW as cosigner for new wallets (643fbec)
- fix: onchain invoice paid detection broken if jsonpatch enabled (#8842)
- fix: program not starting because of bad "proxy" config value (#8837)
- fix: wizard: don't log sensitive values: replace blacklist with whitelist (638fdf11)
* Qt Desktop GUI:
- new: basic "add server as bookmark" functionality (#8865)
- fix: potential race condition in wizard page construction (c78a90a)
- fix: don't use lightning invoice when user specifies MAX amount (#8900)
- various UI fixes (#8874, 2882c4b, #8889, 66af6e6)
* QML GUI (Android):
- fix potential concurrency issue loading wallet (#8355)
- fix: wizard: fails to restore from 2fa seed: KeyError: 'x1' (#8861)
- various UI fixes (50a53aa, 0a6b2d5, #8782, 6738e1e, c0b8927, 016e500, #8898)
* Hardware wallets:
- Trezor:
- new: support SLIP-19 ownership proofs, for trezor-based Standard_Wallets (#8871)
- fix: regression in sign_transaction for trezor one for multisig (#8813)
* CLI/RPC:
- changed: nicer error messages and error-passing (#8888)
* Lightning:
- fix: timing issue in lnpeer.reestablish_channel, for replaying unacked updates (79d88dcb)
# Release 4.5.2 (January 20, 2024)
* Qt Desktop GUI:
- fix crash during startup/wizard-open (#8833)
# Release 4.5.1 (January 19, 2024)
* Lightning:
- fix: MPP regression when using gossip that made paying small invoices fail (95c55c542)
- fix: better handle dataloss (#8814)
- allow manually requesting force-close in WE_ARE_TOXIC state
- fix some timing issues
* General:
- localization: never translate CLI/RPC (0e5a1380)
- localization: simplify how default language is chosen (0e5a1380)
* QML GUI (Android):
- bump min required android version from android 5.0 to 6.0 (#8761)
(older versions have not been working in practice since at least 4.4.0)
- properly refresh history if addresses are deleted from imported wallets (#8782)
- fix crash when LNURLp is scanned/pasted (#8822)
- fix crash for new wallets having cosigner using hww #8808)
- fix crash in finalizer when txid is undefined (#8807)
- various UI fixes (291f0ce, 3d9996a, ec81f00)
* Qt Desktop GUI:
- also support unfinished wallets when opened through File>Open (#8809)
- fix handler for OpenFileEventFilter (6a28ef5)
# Release 4.5.0 (January 12, 2024)
* General:
- remove SSL options from config (012ce1c)
- make number of logfiles to keep configurable (5e8b14f)
- refactored SimpleConfig and added ConfigVars (#8454)
- incremental writes of wallet file (#8493)
- add warnings and prompt users when signing txs with non-default sighashes (#8687)
- refactored bip21/bolt11/lnurl/etc-handling into PaymentIdentifiers (#8462)
- add option to merge duplicate outputs (#8474)
- fix: consider bip21 URIs as invalid if they contain unknown req-* param (#8781)
* Lightning:
- fix BOLT-04 "MUST set `short_channel_id` to the `short_channel_id` used by the incoming onion" (ca93af2)
- add support for hold invoices (1acf426)
- add support for bundled payments (c4eb7d8)
- various MPP improvements (#7987, ..)
- support large channels (40f2087)
- new flow for normal submarine swaps (fd10ae3)
- the client now uses hold invoices, just like the server
- the client waits until HTLCs are received before going on-chain
- the user may cancel the swaps during that waiting time
- don't create invoice with duplicate route hints (a3997f8)
- don't set channel OPEN before channel_ready has been both sent and received (#8641)
- if trampoline is enabled, do not add non-trampoline nodes to invoices (120faa4)
* QML GUI (Android):
- port to Qt6 (#8545)
- fix regression for lnurl-pay (#8585)
- fix invoice amount bounds check (#8582)
- fix places where text was rendered off-screen for certain translations (#8611)
- fix lnworker undefined when node alias requested (#8635)
- fix BIP39 cosigner script type must be same as primary (8cd95f1)
- fix: never use current fiat exchange rate for old historical amounts (#8788)
- better handle android back-gesture (#8464)
- new: show private key in address details (016b5eb)
- new: show tx inputs in TxDetails and other dialogs (#8772)
- new: label sync plugin toggle (b6863b4)
- fix: properly suggest paying BOLT11 invoice onchain if insufficient balance (0a80460)
- new: message sign & verify (e5e1e46)
- new: allow never expiring payment requests (#8631)
- new: add coins/UTXOs to addresses list, add filters (cf91d2e)
- new: delete addresses from imported wallet (#8675)
- new: add support for lightning address and openalias (03dd38b)
- new: add setting to allow screenshots everywhere (0dae1733)
- simplify welcome page for first-start network settings (#8737)
- various UI fixes (b846eab, #8634, 9ed5f7b, 941f425, b20a4b9, af61b9d, 0fb47c8, 2995bc8, ..)
* Qt Desktop GUI:
- port wizard to new implementation
- fix fiat balance sorting in address list window (#8469, #8478)
- remove thousands separator when copying numbers to clipboard (#8479)
- new: option to use extra trampoline for legacy payments (b2053c6)
- new: send change to lightning option for on-chain payments (649ce97)
- new: notes tab for saving text in the (encrypted) wallet file (d691aa07)
- simplify welcome page for first-start network settings (#8737)
- various UI fixes (#8587, #6526, ..)
* Hardware wallets:
- Trezor: allow multiple change outputs (#3920)
- Trezor: support external pre-signed inputs (#8324)
- Bitbox02: update to 6.2.0 (#8459)
* Plugins:
- new: swapserver plugin (#8489)
* Builds/binaries:
- update bundled zbar, for security fixes (#8805)
# Release 4.4.6 (August 18, 2023) (security update)
* Lightning:
- security fix: multiple lightning-related security issues have
been fixed. See disclosures:
- https://github.com/spesmilo/electrum/security/advisories/GHSA-9gpc-prj9-89x7
- https://github.com/spesmilo/electrum/security/advisories/GHSA-8r85-vp7r-hjxf
- fix: cannot sweep from channel after local-force-close, if using
imported channel backup (#8536). Fixing this required adding a
new field (local_payment_pubkey) to the channel backup
import/export format and bumping its version number
(v0->v1). Both v0 and v1 can be imported, and we only export v1
backups. When you force close a channel, the GUI will prompt you
to save a backup. In that case, you must export the backup using
the updated Electrum, and not rely on a backup made with an older
release of Electrum. Note that if you request a force close from
the remote node or co-op close, you do not need to save a channel
backup.
- fix: we would sometimes attempt sending MPP even if not supported
by the invoice (2cf6173c)
* QML GUI:
- fix lnurl-pay when config.BTC_AMOUNTS_ADD_THOUSANDS_SEP is True
(5b4df759)
* Hardware wallets:
- Trezor: support longer than 9 character PIN codes (#8526)
- Jade: support more custom-built DIY Jade devices (#8546)
* Builds/binaries:
- include AppStream metainfo.xml in tarballs (#8501)
* fix: exceptions in some callbacks got lost and not logged (3e6580b9)
# Release 4.4.5 (June 20, 2023)
* Hardware wallets:
- jade: fix regression in sign_transaction (#8463)
* Lightning:
- fix "rebalance_channels" function (#8468)
* enforce that we run with python asserts enabled,
regardless of platform (d1c88108)
# Release 4.4.4 (May 31, 2023)
* QML GUI:
- fix creating multisig wallets involving BIP39 seeds (#8432)
- fix "cannot scroll to open a lightning channel" (#8446)
- wizard: "confirm seed" screen to normalize whitespaces (#8442)
- fix assert on address details screen (#8420)
* Qt GUI:
- better handle some expected errors in SwapDialog (#8430)
* libsecp256k1: bump bundled version to 0.3.2 (10574bb1)
# Release 4.4.3 (May 11, 2023)
* Intentionally break multisig wallets that have heterogeneous master
keys. Versions 4.4.0 to 4.4.2 of Electrum for Android did not check
that master keys used the same script type. This may have resulted
in the creation of multisig wallets that cannot be spent from
with any existing version of Electrum. It is not sure whether any
users are affected by this; if there are any, we will publish
instructions on how to spend those coins (#8417, #8418).
* Qt GUI:
- handle expected errors in DSCancelDialog (#8390)
- persist addresses tab toolbar "show/hide" state (b40a608b)
* QML GUI:
- implement bip39 account detection (0e0c7980)
- add share toolbutton for outputs in TxDetails (#8410)
* Hardware wallets:
- Ledger:
- fix old bitcoin app support (<2.1): "no sig for ..." (#8365)
- bump req ledger-bitcoin (0.2.0+), adapt to API change (30204991)
* Lightning:
- limit max feature bit we accept to 10_000 (#8403)
- do not disconnect on "warning" messages (6fade55d)
* fix wallet.get_tx_parents for chain of unconf txs (#8391)
* locale: translate more strings when using "default" lang (a0c43573)
* wallet: persist frozen state of addresses to disk right away (#8389)
# Release 4.4.2 (May 4, 2023)
* Qt GUI:
- fix undefined var check in swap_dialog (#8341)
- really fix "recursion depth exceeded" for utxo privacy analysis (#8315)
* QML GUI:
- fix signing txs for 2fa wallets (#8368)
- fix for wallets with encrypted-keystore but unencrypted-storage (#8374)
- properly delete wizard components after use (#8357)
- avoid entering loadWallet if daemon is already busy loading (#8355)
- no auto capitalization on import and master key text fields (5600375d)
- remove Qt virtual keyboard and add Seedkeyboard for seed entry (#8371, #8352)
- add runtime toggling of android SECURE_FLAG, to allow screenshots (#8351)
- restrict cases where server is shown "lagging" (53d61c01)
* fix hardened char "h" vs "'" needed for some hw wallets (#8364, 499f5153)
* fix digitalbitbox(1) support (22b8c4e3)
* fix wrong type for "history_rates" config option (#8367)
* fix issues with wallet.get_tx_parents (a1bfea61, 56fa8325)
# Release 4.4.1 (April 27, 2023)
* Qt GUI:
- fix sweeping (#8340)
- fix send tab input_qr_from_camera (#8342)
- fix crash reporter showing if send fails on typical errors (#8312)
- bumpfee: disallow targeting an abs fee. only allow feerate (#8318)
* QML GUI:
- fix offline-signing or co-signing pre-segwit txs (#8319)
- add option to show onchain address in ReceiveDetailsDialog (#8331)
- fix strings unique to QML did not get localized/translated (#8323)
- allow paying bip21 uri onchain that has both onchain and bolt11
if we cannot pay on LN (#8334, 312e50e9)
- virtual keyboard: make buttons somewhat larger (75e65c5c)
- fix(?) Android crash with some OS-accessibility settings (#8344)
- fix channelopener.connectStr qr scan popping under (#8335)
- fix restoring from old mpk (watchonly for "old" seeds) (#8356)
* libsecp256k1: add runtime support for 0.3.x, bump bundled to 0.3.1
* forbid paying to "http:" lnurls (enforce https or .onion) (1b5c7d46)
* fix wallet.bump_fee "decrease payment" erroring on too high target
fee rate (#8316)
* fix performance regressions in tx logic (ee521545, 910832c1)
* fix "recursion depth exceeded" for utxo privacy analysis (#8315)
# Release 4.4.0 (April 18, 2023)
* New Android app, using QML instead of Kivy
- Using Qt 5.15.7, PyQt 5.15.9
- This release still on python3.8
- Feature parity with Kivy
- Android Back button used throughout, for cancel/close/back
- Note: two topbar menus; tap wallet name for wallet menu, tap
network orb for application menu
- Note: long-press Receive/Send for list of payment requests/invoices
* Qt GUI improvements
- New onchain transaction creation flow, with configurable preview
- Various options have been moved to toolbars, where their effect
can be more directly observed.
* Privacy features:
- lightning: support for option scid_alias.
- Qt GUI: UTXO privacy analysis: this dialog displays all the
wallet transactions that are either parent of a UTXO, or can be
related to it through address reuse (Note that in the case of
address reuse, it does not display children transactions.)
- Coins tab: New menu that lets users easily spend a selection
of UTXOs into a new channel, or into a submarine swap (Qt GUI).
* Internal:
- Lightning invoices are regenerated every time routing hints are
deprecated due to liquidity changes.
- Script descriptors are used internally to sign transactions.
# Release 4.3.4 - Copyright is Dubious (January 26, 2023)
* Lightning:
- make sending trampoline payments more reliable (5251e7f8)
- use different trampoline feature bits than eclair (#8141)
* invoice-handling: fix get_request_by_addr incorrectly mapping
addresses to request ids when an address was reused (#8113)
* fix a deadlock in wallet.py (52e2da3a)
* CLI: detect if daemon is already running (c7e2125f)
* add an AppStream metainfo.xml file for Linux packagers (#8149)
* payserver plugin:
-replaced vendored qrcode lib
-added tabs for on-chain and lightning invoices
-revamped html and javascript
# Release 4.3.3 - (January 3, 2023)
* Lightning:
- fix handling failed HTLCs in gossip-based routing (#7995)
- fix LN cooperative-chan-close to witness v1 addr (#8012)
* PSBTs:
- never put ypub/zpub in psbts, only plain xpubs (#8036)
- for witness v0 txins, put both UTXO and WIT_UTXO in psbt (#8039)
* Hardware wallets:
- Trezor: optimize signing speed by not serializing tx (#8058)
- Ledger:
- modify plugin to support new bitcoin app v2.1.0 (#8041),
- added a deprecation warning when using Ledger HW.1 devices.
Ledger itself stopped supporting HW.1 some years ago, and it is
becoming a maintenance burden for us to keep supporting it.
Please migrate away from these devices. Support will be removed
in a future release.
* Binaries:
- tighten build system to only use source pkgs in more places
(#7999, #8000)
- Windows:
- use debian makensis instead of upstream windows exe (#8057)
- stop using debian sid, build missing dep instead (98d29cba)
- AppImage: fix failing to run on certain systems (#8011)
* commands:
- getinfo() to show if running in testnet mode (#8044)
- add a "convert_currency" command (for fiat FX rate) (#8091)
* Qt wizard: fix QR code not shown during 2fa wallet creation (#8071)
* rework Tor-socks-proxy detection to reduce Tor-log-spam (#7317)
* Android: add setting to enable debug logs (#7409)
* fix payserver (merchant) js for electrum 4.3 invoice api (0fc90e07)
* bip21: more robust handling of URIs that include a "lightning" key
(ac1d53f0, 2fd762c3, #8047)
# Release 4.3.2 - (September 26, 2022)
* When creating new requests, reuse addresses of expired requests
(fixes #7927).
* Index requests by ID instead of receiving address. This affects the
following commands: get_request, get_invoice, list_requests,
list_invoices, delete_request, delete_invoice
* Trampoline routing: remember routes that have failed. Try other
routes instead of systematically raising tampoline fees.
* Fix sweep to_local output from channel backup (#7959)
* Harden build script for macOS binary: avoid using
precompiled wheels from PyPI for most packages (#7918)
* The Windows/AppImage/Android binaries are now built on debian using
the snapshot.debian.org archive instead of ubuntu. This should help
with historical reproducibility. (#7926)
# Release 4.3.1 - (August 17, 2022)
* build: we now also distribute a "source-only"
Linux-packager-friendly tarball (d0de44a7, #7594), in addition
to the current "normal" tarball. The "source-only" tarball excludes
compiled locale files, generated protobuf files, and does not
vendor our runtime python dependencies (the packages/ folder).
* fix os.chmod when running in tmpfs on Linux (#7681)
* (Qt GUI) some improvements for high-DPI monitors (38881129)
* bring kivy request dialog more in-line with Qt (#7929)
* rm support of "legacy" (without static_remotekey) LN channels.
Opening these channels were never supported in a release version,
only during development prior to the first lightning-capable
release. Wallets with such channels will have to close them.
(1f403d1c, 7b8e257e)
* Qt: fix duplication of some OS notifications on onchain txs (#7943)
* fix multiple recent regressions:
- handle NotEnoughFunds when trying to pay LN invoice (#7920)
- handle NotEnoughFunds when trying to open LN channel (#7921)
- labels of payment requests were not propagated to
history/addresses (#7919)
- better default labels of outgoing txs (#7942)
- kivy: dust-valued requests could not be created for LN (#7928)
- when closing LN channels, future (timelocked) txs were not
shown in history (#7930)
- kivy: fix deleting "local" tx from history (#7933)
- kivy: fix paying amountless LN invoice (#7935)
- Qt: better handle unparseable URIs (#7941)
# Release 4.3.0 - (August 5, 2022)
* This version introduces a set of UI modifications that simplify the
use of Lightning. The idea is to abstract payments from the payment
layer, and to suggest solutions when a lightning payment is hindered
by liquidity issues.
- Invoice unification: on-chain and lightning invoices have been
merged into a unique type of invoice, and the GUI has a single
'create request' button. Unified invoices contain both a
lightning invoice and an onchain fallback address.
- The receive tab of the GUI can display, for each payment
request, a lightning invoice, a BIP21 URI, or an onchain
address. If the request is paid off-chain, the associated
on-chain address will be recycled in subsequent requests.
- The receive tab displays whether a payment can be received using
Lightning, given the current channel liquidity. If a payment
cannot be received, but may be received after a channel
rebalance or a submarine swap, the GUI will propose such an
operation.
- Similarly, if channels do not have enough liquidity to pay a
lightning invoice, the GUI will suggest available alternatives:
rebalance existing channels, open a new channel, perform a
submarine swap, or pay to the provided onchain fallback address.
- A single balance is shown in the GUI. A pie chart reflects how
that balance is distributed (on-chain, lightning, unconfirmed,
frozen, etc).
- The semantics of the wallet balance has been modified: only
incoming transactions are considered in the 'unconfirmed' part
of the balance. Indeed, if an outgoing transaction does not get
mined, that is not going to decrease the wallet balance. Thus,
change outputs of outgoing transactions are not subtracted from
the confirmed balance. (Before this change, the arithmetic
values of both incoming and outgoing transactions were added to
the unconfirmed balance, and could potentially cancel
each other.)
* In addition, the following new features are worth noting:
- support for the Blockstream Jade hardware wallet (#7633)
- support for LNURL-pay (LUD-06) (#7839)
- updated trampoline feature bit in invoices (#7801)
- the claim transactions of reverse swaps are not broadcast until
the parent transaction is confirmed. This can be overridden by
manually broadcasting the local transaction.
- the fee of submarine swap transactions can be bumped (#7724)
- better error handling for trampoline payments, which should
improve payment success rate (#7844)
- channel backups are removed automatically when the corresponding
channel is redeemed (#7513)
# Release 4.2.2 - (May 27, 2022)
* Lightning:
- watching onchain outputs: significant perf. improvements (#7781)
- enforce relative order of some msgs during chan reestablishment,
lack of which can lead to unwanted force-closures (#7830)
- fix: in case of a force-close containing incoming HTLCs, we were
redeeming all HTLCs that we know the preimage for. This might
publish the preimage of an incomplete MPP. (1a5ef554, e74e9d8e)
* Hardware wallets:
- smarter pairing during sign_transaction (238619f1)
- keepkey: fix pairing with device using a workaround (#7779)
* fix AppImage failing to run on certain systems (#7784)
* fix "Automated BIP39 recovery" not scanning change paths (#7804)
* bypass network proxy for localhost electrum server (#3126)
* security fix: remove support of "file://" URIs from BIP70 payment
requests, which could be used to trigger "open()" on arbitrary files
(see https://github.com/spesmilo/electrum/security/advisories/GHSA-4fh4-hx35-r355)
# Release 4.2.1 - (March 26, 2022)
* Binaries:
- Windows: we are dropping support for Windows 7. (#7728)
Version 4.2.0 already unintentionally broke compatibility with
Win7 and there is no easy way to restore and maintain support.
Existing users can keep using version 4.1.5 for now, but should
consider upgrading or changing their OS.
Win8.1 still works but only Win10 is regularly tested.
- bump bundled Python version (win, mac, appimage) to 3.9.11,
(android) to 3.8.13 (1bb7ef92, #7721)
(note these include a fix to an openssl DOS-vector CVE-2022-0778)
- windows: bump pyinstaller to 4.10 and wine to 7.0 (#7721)
* Kivy GUI:
- fix "Child Pays For Parent" not working on Android (#7723)
- revert to defaulting the UI language to English (25fee6a6)
* Qt GUI:
- macOS: fix opening "Preferences" segfaulting for some (#7725)
- more resilient startup: better error-handling and fallback (#7447)
* Library:
- fix LN error/warning message-handling, and fix regression that
errors during channel-open were not properly shown in GUI (a92dede4)
- during LN chan open, do not backup wallet automatically (#7733)
- Imported wallets: fix delete_address rm-ing too many txs (#7587)
- fix potential deadlock in wallet.py (d3476b6b)
* Hardware wallets:
- ledger: add progress indicator to sign_transaction (#7516)
* fix the "--portable" flag for AppImage, and for pip installs (#7732)
# Release 4.2.0 - (March 16, 2022)
* The minimum python version was increased to 3.8 (#7661)
* Lightning:
- redesigned MPP splitting algorithm (#7202)
- trampoline: implement multi-trampoline MPP (#7623)
- implement option_shutdown_anysegwit, and allow dust limits
below 546 sat (#7542)
- implement option_channel_type (#7636)
- implement modern closing negotiation (#7586, #7680)
* improve support for "lightning:" URIs on all platforms (#7301)
* Qt GUI:
- add setting "show amounts with msat precision" (5891e039)
- add setting "add thousand separators to bitcoin amounts" (#7427)
* CLI/RPC:
- implement Unix sockets and make them the default (#7545, #7566)
- add "bumpfee" command (#7438)
* Kivy GUI:
- show network setup on first start before wallet creation (#7464)
- add "Child Pays For Parent" option (#7487)
- improved locale handling (22bb52d5, 7cb11ced, 4293d6ec)
* Hardware wallets:
- trezor: bump trezorlib to 0.13 (#7590)
- bitbox02: bump bitbox02 to 6.0, support send-to-taproot (#7693)
- ledger: support "Ledger Nano S Plus" (#7692)
* Library:
- added support for sighash types beside "ALL" (#7453)
- signmessage: also accept Trezor-type sigs for segwit addrs (#7668)
- network: make request timeout configurable (#7696)
- paytomany (onchain txout batching) now allows multiple max("!")
amounts with specified weights (#7492)
* Binary builds
- AppImage: changed base image from ubuntu 16.04 to 18.04 (5d0aa63a)
* migrated from Travis CI to Cirrus CI (#7431)
* Lots of other minor bugfixes and usability improvements.
# Release 4.1.5 - (July 19, 2021)
* Builds/binaries:
- macOS: the .dmg binary should now be reproducible
* Kivy/Android: fix paying bip70 invoices (regression) (90579ccf)
* fix: payment requests not saved if process is killed (6a049d99)
* Lightning: improve payment success when using trampoline (3a7f5373)
* add support for signet test network (#7282)
* Qt GUI:
- allow restoring from SLIP39 seeds (#6917)
- rework QR code scanning on Windows and macOS (#7365)
- support smaller window sizes, decrease minimums (#7385)
* GUIs: add "funded or unused" filter option to Addresses tab (#5823)
# Release 4.1.4 - (June 17, 2021)
* Kivy/Android: fix a regression where a non-LN wallet
could not open the settings (c49d6995)
* CLI/RPC: fix "close_wallet" command (#7348)
# Release 4.1.3 - (June 16, 2021)
* Builds/binaries:
- Android: the binaries (APKs) should now be reproducible (#7263)
- AppImage: fix some startup issues by including libxcb deps (#7198)
* Lightning:
- smarter LN pathfinding (if trampoline is disabled):
- estimate liquidity in channels using previous attempts (#7152)
- consider inflight HTLCs and try to route around them (#7292)
- bugfix: add more safety checks to avoid "batch RBF" feature
merging LN funding txs (#7298)
- remove HTLC value upper limit of ~42 mBTC (#7328)
- Kivy GUI: implement freezing LN channels (11bb39ee)
* imported wallets: when enabling the "Use change addresses" option,
change will now be sent to a random unused imported address. (#7330)
As before, by default, change is sent back to the "from address".
* seed generation: make sure newly created electrum seeds don't have
correct bip39 checksum by chance (#6001)
* other minor fixes
# Release 4.1.2 - (April 8, 2021)
* Qt GUI:
- fix some crashes when exiting (#6889)
- make sure pressing Ctrl-C always quits (c41cd4ae)
* Kivy GUI (Android):
- fix bug with scrollbar, again (#7155)
- 2fa wallets: fix making transactions (#7190)
- implement freezing addresses (#7178)
* Android: use more modern application launcher/icon (#7187)
# Release 4.1.1 - (April 2, 2021)
* fix Qt crash with the swap dialog
* fix Kivy bug with scrollbar (#7155)
* fix localization issues (#7158 #4621)
* fix python crash with swaps (#7160)
* other minor fixes
# Release 4.1.0 - Kangaroo (March 30, 2021)
This version is our second major release with support for the
Lightning Network. While our initial Lightning release was mostly
about implementing the protocol, this release brings features that are
specifically aimed at keeping Electrum lightweight and trustless,
while avoiding single points of failure. Most of the features listed
below are user-visible.
* The wallet creation wizard no longer asks for a seed type, and
creates segwit wallets with bech32 addresses. Older seed types can
still be created with the command line.
* Paid invoices (both incoming and outgoing) are automatically
removed from the send/receive lists of the GUI (one confirmation is
needed for onchain invoices). Once removed from the list, invoice
details can still be accessed from the transaction history. In Qt,
invoice lists have been renamed to 'Sending queue' and 'Receiving
queue'.
* Lightning:
- recoverable channels (see below)
- trampoline payments (see below)
- support multi-part-payment
- support upfront-shutdown-script
* Recoverable channels (option):
- Recovery data is added to the channel funding transaction using
an OP_RETURN. This makes it possible to recover a static backup
of the channel from the wallet seed. Please note that static
backups only allow users to request a force-close of the channel
with the remote node, so that funds not locked in HTLCs can be
recovered. This assumes that the remote node is still online, did
not lose its data, and accepts to force close the channel.
- This option is only available for standard wallets with an
Electrum seed. It is not available for hardware wallets, because
it requires a deterministic derivation of the nodeID. It is also
not available in watching-only wallets, for the same reason. If a
wallet can have recoverable channels but has an old nodeID, users
who want to use that feature need to close all their existing
channels, and to restore their wallet from seed.
- Channel recovery data uses 20 bytes (16 bytes of the remote
NodeID plus 4 magic bytes) and is encrypted so that only the
wallet that owns it can decrypt it. However, blockchain analysis
will be able to tell that the transaction was probably created by
Electrum.
- If the 'use recoverable channels' option is enabled, other nodes
cannot open a channel to Electrum.
- If a channel is force-closed, the information in the on-chain
backup is not sufficient to retrieve the funds in the to_local
output, in case the wallet is lost in a boating accident before
expiration of the CSV delay. For that reason, an additional
backup is presented to the user if they force-close a channel.
* Trampoline routing (option): Trampoline is a solution that allows
light clients to delegate path-finding on the Lightning Network, so
that they do not have to download the entire network
graph. Trampoline routing was originally proposed by Bastien
Teinturier and is used in the Phoenix wallet. Here is how
Trampoline works in Electrum:
- Trampoline is enabled by default, in order to prevent unwanted
download of the network gossip. If trampoline is disabled, the
gossip will be downloaded, regardless of the existence of
channels.
- Because there is no discovery mechanism for trampoline nodes, the
list of available trampolines is hardcoded in the client (it will
remain so until support for trampoline routing is announced in
gossip). 3 trampoline nodes are currently available on mainnet:
ACINQ, Electrum and Hodlister.
- If Trampoline is enabled:
- payments use trampoline routing.
- gossip is disabled.
- the wallet can only open channels with trampoline nodes.
- pre-existing channels with non-trampoline nodes are frozen for
sending.
- There are two types of trampoline payments: legacy and trampoline
end-to-end. Legacy payments are possible with any receiver, but
they offer less privacy than end-to-end trampoline
payments. Electrum decides whether to perform legacy or
end-to-end based on the features in the invoice:
- OPTION_TRAMPOLINE_ROUTING_OPT (bit 25) for Electrum
- OPTION_TRAMPOLINE_ROUTING_OPT_ECLAIR (bit 51) for Eclair/Phoenix
- When performing a legacy payment, Electrum will add a second
trampoline node to the route in order to protect the privacy of
the payer and payee. It will fall back to a single trampoline if
the two-trampoline strategy has failed for all trampolines.
(Note: two-trampoline payments are currently not possible if the
first trampoline is the ACINQ node, and is disabled for that
node.)
- Similar to Phoenix, the fee and CLTV delay are found by
trial-and-error. If there is a second trampoline in the route, we
use the same fee/CLTV for both. This trial-and-error is
temporary; the final specification should add fee information in
the failure messages, so that we will be able to better fine-tune
trampoline fees.
* Qt: The increase fee dialog now has advanced options, and offers
the choice between different RBF strategies.
* Watchtowers: The 'use_local_watchtower' feature is deprecated, and
it has been removed from the Qt GUI. The 'use_remote_watchtower'
setting has been renamed to 'use_watchtower'.
* Password unification (Android only): When the Android app is
started, the entered password is checked against all wallets in
the directory. If the test passes:
- all wallets are encrypted
- new wallets will use the unified password
- password updates are performed on all wallets
Whether the password is unified can be seen in the GUI: In the
'Settings' dialog, the description for the password setting is
'Change password for this wallet' if the password is not unified,
and becomes 'Change password' if password is unified.
* Submarine swaps are now available on kivy/android.
* Android PIN reset: If the password is unified, the PIN can be reset
by providing the password.
* Android: on-chain fees have been removed from the settings
dialog. Instead, the fee slider is shown to the user every time an
on-chain transaction will be performed (sending a payment, opening
a channel, initiating a submarine swap)
* BIP-0350: use bech32m for witness version 1+ addresses (4315fa43).
We have supported sending to any witness version since Electrum
3.0, using BIP-0173 (bech32) addresses. BIP-0350 makes a breaking
change in address encoding, and recommends using a new encoding
(bech32m) for sending to witness version 1 and later.
* Block explorer: allow setting a custom URL in Qt GUI (#6965)
# Release 4.0.9 - (Dec 18, 2020)
* fixes a regression introduced in 4.0.8, that prevents from
paying BIP70 invoices (#6859)
* reflect frozen channels and disconnected peers in the displayed
'can send/can receive' amounts.
# Release 4.0.8 - (Dec 17, 2020)
* fix decoding BIP21 URIs with uppercase schema (d40bedb2)
* psbt: put full derivation paths into PSBT by default (c8155129)
* invoices: allow address-reuse (#6609, #6852)
* A few other minor bugfixes.
# Release 4.0.7 - (Dec 9, 2020)
* kivy: fix open channel with 'max' amount
* kivy: fix regression introduced in last release (a9fc440)
* other minor GUI fixes
* Dependencies: as part of adapting to new dnspython (#6828),
- python-ecdsa is no longer needed at all,
- cryptography is now required (min 2.6), the user can no
longer choose between cryptography and pycryptodomex
# Release 4.0.6 - (Dec 4, 2020)
* Fix 'Max' button issue for submarine swaps button (#6770)
* Fix 'Max' button in kivy (#6169)
* Various fixes for Kivy/Android install wizard
* More robust account keypath for BitBox02 (#6766)
# Release 4.0.5 - (Nov 18, 2020)
* Fix .dmg binary hanging on recently released macOS 11 Big Sur (#6461)
* Lightning:
- bugfix: during LN channel opening, if the client crashed at the
wrong moment, the channel might not get fully persisted to disk,
and would need manual console-tinkering to recover (#6656)
- Lightning is enabled by default. Electrum will not connect to
the Lightning Network until the user opens a channel. (#6639)
- smarter node recommendation (to open channels with) (#6705)
* user interface: some minor changes that aim to improve usability
* Ledger:
- fix enumerating devices with new bitcoin app (1.5.1) (b78cbcff)
- fix compat with HW.1 (200f547a)
* A few other minor bugfixes.
# Release 4.0.4 - (Oct 15, 2020)
* PSBT: fix regression in 4.0.3 where UTXO data was not included in
QR codes (#6600)
* new feature: "Cancel tx" (#6641). The Qt/kivy GUI allows cancelling
an unconfirmed RBF tx by double-spending its inputs to self.
* Windows binary:
- fix some issues with QR scanning by building zbar ourselves (#6593)
- when using setup exe, also install a debug binary (#6603)
* Ledger: fix "The derivation path is unusual" warnings (#6512)
(needs Bitcoin app 1.4.8+ installed on device)
* A few other minor bugfixes and usability improvements.
# Release 4.0.3 - (Sep 11, 2020)
* PSBT: restore compatibility with Bitcoin Core following CVE-2020-14199:
we now allow a PSBT input to have both UTXO and WITNESS_UTXO (#6429).
(PSBTs created since 4.0.1 already contained UTXO for segwit inputs)
* Hardware wallets:
- bitbox02: better multisig UX: implement get_soft_device_id (#6386)
- coldcard: fix "show address" for multisig (#6517)
- all: run all device communication on a dedicated thread (#6561).
This should resolve some threading issues.
* new feature: "Automated BIP39 recovery" (#6219, #6155)
When restoring from a BIP39 seed, add option to scan many known
derivation paths for history, and show them to user to choose from.
* show derivation path of keystores in Qt GUI Wallet>Information (#4700)
* fix "signtransaction" RPC command (#6502)
* Dependencies: pyaes is no longer needed (#6563)
* The tar.gz source dist now bundles make_libsecp256k1.sh, to help
users getting libsecp256k1 (#6323).
* A few other minor bugfixes and usability improvements.
# Release 4.0.2 - (July 8, 2020)
- rm old corrupted non-bip70 invoices (#6345)
- other minor fixes
# Release 4.0.1 - (July 3, 2020)
* Lightning Network support (experimental)
- Our implementation of Lightning relies on Electrum servers to
query channel states. Since servers can lie about the state of a
channel, users should either use a server that they trust, or
setup a private watchtower (see below). A watchtower is also
recommended for lightning wallets that remain offline for
extended periods of time (the default CSV 'to_self_delay' is 1
week). Please note that Electrum Personal Server (EPS) cannot be
used with lightning wallets, because channels funding addresses
are arbitrary.
- Lightning funds cannot be restored from seed. Instead, users need
to create static backups of their channels. Static backups cannot
be used to perform lightning transactions, they can only be used
to trigger a remote-force-close of a channel.
- Lightning-enabled wallet files must not be copied. Instead, a
backup of the wallet can be created from the Qt menu, and it will
contain static backups of all its channels. Backups can also be
exported for each channel (e.g. via QR code), and imported in
another wallet. Since backups are encrypted with a key derived
from the wallet's xpub, they can only be imported into another
instance of the same wallet, or a watch-only version of it. The
force-close is not triggered automatically when the backup is
imported; imported backups can live inside a wallet file.
- Lightning can be enabled in the GUI (Wallet>Information) or from
the CLI (init_lightning). Lightning is currently restricted to HD
p2wpkh wallets (including watch-only and hardware wallets). The
Qt GUI, CLI/RPC, and the kivy GUI (Android) all have LN support,
with feature-richness in that order.
- LN protocol details: dataloss_protect and static_remotekey are
required; varonion and payment_secret are implemented, MPP not yet.
Channels are not announced ('private'), forwarding is disabled.
We do not serve gossip queries, only consume them.
- Submarine swaps: the GUI integrates a service that offers
atomically exchanging on-chain and lightning bitcoins for a fee.
Electrum Technologies runs a central server for this, powered by
the Boltz backend.
- Watchtowers: Electrum can run a local watchtower (GUI setting),
or it can connect to a remote watchtower. A watchtower contains
pre-signed transactions and does not need your private keys. A
local watchtower will watch your channels whenever an Electrum
instance is running, without needing access to your wallet file.
An Electrum daemon can be configured to be used as a remote
watchtower by setting 'watchtower_address', 'watchtower_user' and
'watchtower_password'.
* Partially Signed Bitcoin Transactions (PSBT, BIP-174) are supported
(#5721). The previous Electrum partial transaction format is no
longer supported, i.e. this is an incompatible change. Users should
make sure that all instances of Electrum they use to co-sign or
offline sign, are updated together.
* Hardware wallets: several fixes in general; notable changes:
- The BitBox02 is now supported (#5993)
- Multisig support for Coldcard (#5440)
- Compatibility with latest Trezor fw (#6064, #6198, #5692)
* Dependencies (see README for install instructions):
- libsecp256k1 is now required (previously optional). python-ecdsa
remains a dependency but it is now only used for DNSSEC.
- Added: either one of pycryptodomex or cryptography is now required,
mainly due to LN (previously pycryptodomex was optional, for fast AES)
- Removed: jsonrpclib-pelix, the JSON-RPC library used for CLI/daemon
* Qt GUI: several changes, notably:
- Separation between output selection and transaction finalization.
- Coin selection moved to the Coins tab, and it affects all txns,
e.g. RBF fee-bumping, LN channel opens, submarine swaps.
- Editable tx preview dialog that allows e.g. changing the locktime,
toggling RBF, and manual coinjoins.
* HTTP PayServer: The configuration of a bitcoin-accepting website
using Electrum has been simplified and requires fewer steps (see
documentation). The Payserver supports BIP70 and Lightning payments.
* Android:
- We now build two APKs, one for ARMv7 and one for ARMv8
- The kivy GUI now supports importing BIP39 seeds
- Each wallet on kivy now can have a separate generic password,
using which the wallet files are encrypted. An optional PIN,
shared among all wallets, can be added to get prompted for spends.
* The API of several CLI/RPC commands have changed, and several new
commands have been introduced (mainly for LN).
* Distributables:
- The .tar.gz source dist is now built reproducibly.
Relatedly, we no longer distribute a .zip sdist.
- The MacOS binary now conforms to macOS 10.15; it is notarized
by Apple. This required bumping the min macOS version to 10.13.
Startup times should now be faster on 10.15. (#6128, #6225)
* Transactions:
- we now grind low R for ECDSA signatures to match bitcoind (#5820)
* Lots and lots of other minor bugfixes and improvements.
# Release 3.3.8 - (July 11, 2019)
* fix some bugs with recent bump fee (RBF) improvements (#5483, #5502)
* fix #5491: watch-only wallets could not bump fee in some cases
* appimage: URLs could not be opened on some desktop environments (#5425)
* faster tx signing for segwit inputs for really large txns (#5494)
* A few other minor bugfixes and usability improvements.
# Release 3.3.7 - (July 3, 2019)
* The AppImage Linux x86_64 binary and the Windows setup.exe
(so now all Windows binaries) are now built reproducibly.
* Bump fee (RBF) improvements:
Implemented a new fee-bump strategy that can add new inputs,
so now any tx can be fee-bumped (d0a4366). The old strategy
was to decrease the value of outputs (starting with change).
We will now try the new strategy first, and only use the old
as a fallback (needed e.g. when spending "Max").
* CoinChooser improvements:
- more likely to construct txs without change (when possible)
- less likely to construct txs with really small change (e864fa5)
- will now only spend negative effective value coins when
beneficial for privacy (cb69aa8)
* fix long-standing bug that broke wallets with >65k addresses (#5366)
* Windows binaries: we now build the PyInstaller boot loader ourselves,
as this seems to reduce anti-virus false positives (1d0f679)
* Android: (fix) BIP70 payment requests could not be paid (#5376)
* Android: allow copy-pasting partial transactions from/to clipboard
* Fix a performance regression for large wallets (c6a54f0)
* Qt: fix some high DPI issues related to text fields (37809be)
* Trezor:
- allow bypassing "too old firmware" error (#5391)
- use only the Bridge to scan devices if it is available (#5420)
* hw wallets: (known issue) on Win10-1903, some hw devices
(that also have U2F functionality) can only be detected with
Administrator privileges. (see #5420 and #5437)
A workaround is to run as Admin, or for Trezor to install the Bridge.
* Several other minor bugfixes and usability improvements.
# Release 3.3.6 - (May 16, 2019)
* qt: fix crash during 2FA wallet creation (#5334)
* fix synchronizer not to keep resubscribing to addresses of
already closed wallets (e415c0d9)
* fix removing addresses/keys from imported wallets (#4481)
* kivy: fix crash when aborting 2FA wallet creation (#5333)
* kivy: fix rare crash when changing exchange rate settings (#5329)
* A few other minor bugfixes and usability improvements.
# Release 3.3.5 - (May 9, 2019)
* The logging system has been overhauled (#5296).
Logs can now also optionally be written to disk, disabled by default.
* Fix a bug in synchronizer (#5122) where client could get stuck.
Also, show the progress of history sync in the GUI. (#5319)
* fix Revealer in Windows and MacOS binaries (#5027)
* fiat rate providers:
- added CoinGecko.com and CoinCap.io
- BitcoinAverage now only provides historical exchange rates for
paying customers. Changed default provider to CoinGecko.com (#5188)
* hardware wallets:
- Ledger: Nano X is now recognized (#5140)
- KeepKey:
- device was not getting detected using Windows binary (#5165)
- support firmware 6.0.0+ (#5205)
- Trezor: implemented "seedless" mode (#5118)
* Coin Control in Qt: implemented freezing individual UTXOs
in addition to freezing addresses (#5152)
* TrustedCoin (2FA wallets):
- better error messages (#5184)
- longer signing timeout (#5221)
* Kivy:
- fix bug with local transactions (#5156)
- allow selecting fiat rate providers without historical data (#5162)
* fix CPFP: the fees already paid by the parent were not included in
the calculation, so it always overestimated (#5244)
* Testnet: there is now a warning when the client is started in
testnet mode as there were a number of reports of users getting
scammed through social engineering (#5295)
* CoinChooser: performance of creating transactions has been improved
significantly for large wallets. (d56917f4)
* Importing/sweeping WIF keys: stricter checks (#4638, #5290)
* Electrum protocol: the client's "user agent" has been changed from
"3.3.5" to "electrum/3.3.5". Other libraries connecting to servers
can consider not "spoofing" to be Electrum. (#5246)
* Several other minor bugfixes and usability improvements.
# Release 3.3.4 - (February 13, 2019)
* AppImage: we now also distribute self-contained binaries for x86_64
Linux in the form of an AppImage (#5042). The Python interpreter,
PyQt5, libsecp256k1, PyCryptodomex, zbar, hidapi/libusb (including
hardware wallet libraries) are all bundled. Note that users of
hw wallets still need to set udev rules themselves.
* hw wallets: fix a regression during transaction signing that prompts
the user too many times for confirmations (commit 2729909)
* transactions now set nVersion to 2, to mimic Bitcoin Core
* fix Qt bug that made all hw wallets unusable on Windows 8.1 (#4960)
* fix bugs in wallet creation wizard that resulted in corrupted
wallets being created in rare cases (#5082, #5057)
* fix compatibility with Qt 5.12 (#5109)
# Release 3.3.3 - (January 25, 2019)
* Do not expose users to server error messages (#4968)
* Notify users of new releases. Release announcements must be signed,
and they are verified byElectrum using a hardcoded Bitcoin address.
* Hardware wallet fixes (#4991, #4993, #5006)
* Display only QR code in QRcode Window
* Fixed code signing on MacOS
* Randomise locktime of transactions
# Release 3.3.2 - (December 21, 2018)
* Fix Qt history export bug
* Improve network timeouts
* Prepend server transaction_broadcast error messages with
explanatory message. Render error messages as plain text.
# Release 3.3.1 - (December 20, 2018)
* Qt: Fix invoices tab crash (#4941)
* Android: Minor GUI improvements
# Release 3.3.0 - Hodler's Edition (December 19, 2018)
* The network layer has been rewritten using asyncio and aiorpcx.
In addition to easier maintenance, this makes the client
more robust against misbehaving servers.
* The minimum python version was increased to 3.6
* The blockchain headers and fork handling logic has been generalized.
Clients by default now follow chain based on most work, not length.
* New wallet creation defaults to native segwit (bech32).
* Segwit 2FA: TrustedCoin now supports native segwit p2wsh
two-factor wallets.
* RBF batching (opt-in): If the wallet has an unconfirmed RBF
transaction, new payments will be added to that transaction,
instead of creating new transactions.
* MacOS: support QR code scanner in binaries.
* Android APK:
- build using Google NDK instead of Crystax NDK
- target API 28
- do not use external storage (previously for block headers)
* hardware wallets:
- Coldcard now supports spending from p2wpkh-p2sh,
fixed p2pkh signing for fw 1.1.0
- Archos Safe-T mini: fix #4726 signing issue
- KeepKey: full segwit support
- Trezor: refactoring and compat with python-trezor 0.11
- Digital BitBox: support firmware v5.0.0
* fix bitcoin URI handling when app already running (#4796)
* Qt listings rewritten:
the History tab now uses QAbstractItemModel, the other tabs use
QStandardItemModel. Performance should be better for large wallets.
* Several other minor bugfixes and usability improvements.
# Release 3.2.4 - (December 30, 2018)
* backport anti-phishing measures from master
# Release 3.2.3 - (September 3, 2018)
* hardware wallet: the Safe-T mini from Archos is now supported.
* hardware wallet: the Coldcard from Coinkite is now supported.
* BIP39 seeds: if a seed extension (aka passphrase) contained
multiple consecutive whitespaces or leading/trailing whitespaces
then the derived addresses were not following spec. This has been
fixed, and affected should move their coins. The wizard will show a
warning in this case. (#4566)
* Revealer: the PRNG used has been changed (#4649)
* fix Linux distributables: 'typing' was not bundled, needed for python 3.4
* fix #4626: fix spending from segwit multisig wallets involving a Trezor
cosigner when using a custom derivation path
* fix #4491: on Android, if user had set "uBTC" as base unit, app crashed
* fix #4497: on Android, paying bip70 invoices from cold start did not work
* Several other minor bugfixes and usability improvements.
# Release 3.2.2 - (July 2nd, 2018)
* Fix DNS resolution on Windows
* Fix websocket bug in daemon
# Release 3.2.1 - (July 1st, 2018)
* fix Windows binaries: due to build process changes, the locale files
were not included; the language could not be changed from English
* fix Linux distributables: wordlists were not included (#4475)
# Release 3.2.0 - Satoshi's Vision (June 30, 2018)
* If present, libsecp256k1 is used to speed up elliptic curve
operations. The library is bundled in the Windows, MacOS, and
Android binaries. On Linux, it needs to be installed separately.
* Two-factor authentication is available on Android. Note that this
will only provide additional security if one time passwords are
generated on a separate device.
* Semi-automated crash reporting is implemented for Android.
* Transactions that are dropped from the mempool are kept in the
wallet as 'local', and can be rebroadcast. Previously these
transactions were deleted from the wallet.
* The scriptSig and witness part of transaction inputs are no longer
parsed, unless actually needed. The wallet will no longer display
'from' addresses corresponding to transaction inputs, except for
its own inputs.
* The partial transaction format has been incompatibly changed. This
was needed as for partial transactions the scriptSig/witness has to
be parsed, but for signed transactions we did not want to do the
parsing. Users should make sure that all instances of Electrum
they use to co-sign or offline sign, are updated together.
* Signing of partial transactions created with online imported
addresses wallets now supports significantly more
setups. Previously only online p2pkh address + offline WIF was
supported. Now the following setups are all supported:
- online {p2pkh, p2wpkh-p2sh, p2wpkh} address + offline WIF,
- online {p2pkh, p2wpkh-p2sh, p2wpkh} address + offline seed/xprv,
- online {p2sh, p2wsh-p2sh, p2wsh}-multisig address + offline seeds/xprvs
(potentially distributed among several different machines)
Note that for the online address + offline HD secret case, you need
the offline wallet to recognize the address (i.e. within gap
limit). Having an xpub on the online machine is still the
recommended setup, as this allows the online machine to generate
new addresses on demand.
* Segwit multisig for bip39 and hardware wallets is now enabled.
(both p2wsh-p2sh and native p2wsh)
* Ledger: offline signing for segwit inputs (#3302) This has already
worked for Trezor and Digital Bitbox. Offline segwit signing can be
combined with online imported addresses wallets.
* Added Revealer plugin. ( https://revealer.cc ) Revealer is a seed
phrase back-up solution. It allows you to create a cold, analog,
multi-factor backup of your wallet seeds, or of any arbitrary
secret. The Revealer utilizes a transparent plastic visual one time
pad.
* Fractional fee rates: the Qt GUI now displays fee rates with 0.1
sat/byte precision, and also allows this same resolution in the
Send tab.
* Hardware wallets: a "show address" button is now displayed in the
Receive tab of the Qt GUI. (#4316)
* Trezor One: implemented advanced/matrix recovery (#4329)
* Qt/Kivy: added "sat" as optional base unit.
* Kivy GUI: significant performance improvements when displaying
history and address list of large wallets; and transaction dialog
of large transactions.
* Windows: use dnspython to resolve dns instead of socket.getaddrinfo
(#4422)
* Importing minikeys: use uncompressed pubkey instead of compressed
(#4384)
* SPV proofs: check inner nodes not to be valid transactions (#4436)
* Qt GUI: there is now an optional "dark" theme (#4461)
* Several other minor bugfixes and usability improvements.
# Release 3.1.3 - (April 16, 2018)
* Qt GUI: seed word auto-complete during restore
* Android: fix some crashes
* performance improvements (wallet, and Qt GUI)
* hardware wallets: show debug message during device scan
* Digital Bitbox: enabled BIP84 (p2wpkh) wallet creation
* add regtest support (via --regtest flag)
* other minor bugfixes and usability improvements
# Release 3.1.2 - (March 28, 2018)
* Kivy/android: request PIN on startup
* Improve OSX build process
* Fix various bugs with hardware wallets
* Other minor bugfixes
# Release 3.1.1 - (March 12, 2018)
* fix #4031: Trezor T support
* partial fix #4060: proxy and hardware wallet can't be used together
* fix #4039: can't set address labels
* fix crash related to coinbase transactions
* MacOS: use internal graphics card
* fix openalias related crashes
* speed-up capital gains calculations
* hw wallet encryption: re-prompt for passphrase if incorrect
* other minor fixes.
# Release 3.1.0 - (March 5, 2018)
* Memory-pool based fee estimation. Dynamic fees can target a desired
depth in the memory pool. This feature is optional, and ETA-based
estimates from Bitcoin Core are still available. Note that miners
could exploit this feature, if they conspired and filled the memory
pool with expensive transactions that never get mined. However,
since the Electrum client already trusts an Electrum server with
fee estimates, activating this feature does not introduce any new
vulnerability. In addition, the client uses a hard threshold to
protect itself from servers sending excessive fee estimates. In
practice, ETA-based estimates have resulted in sticky fees, and
caused many users to overpay for transactions. Advanced users tend
to visit (and trust) websites that display memory-pool data in
order to set their fees.
* Capital gains: For each outgoing transaction, the difference
between the acquisition and liquidation prices of outgoing coins is
displayed in the wallet history. By default, historical exchange
rates are used to compute acquisition and liquidation prices. These
values can also be entered manually, in order to match the actual
price realized by the user. The order of liquidation of coins is
the natural order defined by the blockchain; this results in
capital gain values that are invariant to changes in the set of
addresses that are in the wallet. Any other ordering strategy (such
as FIFO, LIFO) would result in capital gain values that depend on
the presence of other addresses in the wallet.
* Local transactions: Transactions can be saved in the wallet without
being broadcast. The inputs of local transactions are considered as
spent, and their change outputs can be re-used in subsequent
transactions. This can be combined with cold storage, in order to
create several transactions before broadcasting them. Outgoing
transactions that have been removed from the memory pool are also
saved in the wallet, and can be broadcast again.
* Checkpoints: The initial download of a headers file was replaced
with hardcoded checkpoints. The wallet uses one checkpoint per
retargeting period. The headers for a retargeting period are
downloaded only if transactions need to be verified in this period.
* The 'privacy' and 'priority' coin selection policies have been
merged into one. Previously, the 'privacy' policy has been unusable
because it was was not prioritizing confirmed coins. The new policy
is similar to 'privacy', except that it de-prioritizes addresses
that have unconfirmed coins.
* The 'Send' tab of the Qt GUI displays how transaction fees are
computed from transaction size.
* The wallet history can be filtered by time interval.
* Replace-by-fee is enabled by default. Note that this might cause
some issues with wallets that do not display RBF transactions until
they are confirmed.
* Watching-only wallets and hardware wallets can be encrypted.
* Semi-automated crash reporting
* The SSL checkbox option was removed from the GUI.
* The Trezor T hardware wallet is now supported.
* BIP84: native segwit p2wpkh scripts for bip39 seeds and hardware
wallets can now be created when specifying a BIP84 derivation
path. This is usable with Trezor and Ledger.
* Windows: the binaries now include ZBar, and QR code scanning should work.
* The Wallet Import Format (WIF) for private keys that was extended in 3.0
is changed. Keys in the previous format can be imported, compatibility
is maintained. Newly exported keys will be serialized as
"script_type:original_wif_format_key".
* BIP32 master keys for testnet once again have different version bytes than
on mainnet. For the mainnet prefixes {x,y,Y,z,Z}|{pub,prv}, the
corresponding testnet prefixes are {t,u,U,v,V}|{pub,prv}.
More details and exact version bytes are specified at:
https://github.com/spesmilo/electrum-docs/blob/master/xpub_version_bytes.rst
Note that due to this change, testnet wallet files created with previous
versions of Electrum must be considered broken, and they need to be
recreated from seed words.
* A new version of the Electrum protocol is required by the client
(version 1.2). Servers using older versions of the protocol will
not be displayed in the GUI.
# Release 3.0.6 :
* Fix transaction parsing bug #3788
# Release 3.0.5 : (Security update)
This is a follow-up to the 3.0.4 release, which did not completely fix
issue #3374. Users should upgrade to 3.0.5.
* The JSONRPC interface is password protected
* JSONRPC commands are disabled if the GUI is running, except 'ping',
which is used to determine if a GUI is already running
# Release 3.0.4 : (Security update)
* Fix a vulnerability caused by Cross-Origin Resource Sharing (CORS)
in the JSONRPC interface. Previous versions of Electrum are
vulnerable to port scanning and deanonimization attacks from
malicious websites. Wallets that are not password-protected are
vulnerable to theft.
* Bundle QR scanner with Android app
* Minor bug fixes
# Release 3.0.3
* Qt GUI: sweeping now uses the Send tab, allowing fees to be set
* Windows: if using the installer binary, there is now a separate shortcut
for "Electrum Testnet"
* Digital Bitbox: added support for p2sh-segwit
* OS notifications for incoming transactions
* better transaction size estimation:
- fees for segwit txns were somewhat underestimated (#3347)
- some multisig txns were underestimated
- handle uncompressed pubkeys
* fix #3321: testnet for Windows binaries
* fix #3264: Ledger/dbb signing on some platforms
* fix #3407: KeepKey sending to p2sh output
* other minor fixes and usability improvements
# Release 3.0.2
* Android: replace requests tab with address tab, with access to
private keys
* sweeping minikeys: search for both compressed and uncompressed
pubkeys
* fix wizard crash when attempting to reset Google Authenticator
* fix #3248: fix Ledger+segwit signing
* fix #3262: fix SSL payment request signing
* other minor fixes.
# Release 3.0.1
* minor bug and usability fixes
# Release 3.0 - Uncanny Valley (November 1st, 2017)
* The project was migrated to Python3 and Qt5. Python2 is no longer
supported. If you cloned the source repository, you will need to
run "python3 setup.py install" in order to install the new
dependencies.
* Segwit support:
- Native segwit scripts are supported using a new type of
seed. The version number for segwit seeds is 0x100. The install
wizard will not create segwit seeds by default; users must
opt-in with the segwit option.
- Native segwit scripts are represented using bech32 addresses,
following BIP173. Please note that BIP173 is still in draft
status, and that other wallets/websites may not support
it. Thus, you should keep a non-segwit wallet in order to be
able to receive bitcoins during the transition period. If BIP173
ends up being rejected or substantially modified, your wallet
may have to be restored from seed. This will not affect funds
sent to bech32 addresses, and it will not affect the capacity of
Electrum to spend these funds.
- Segwit scripts embedded in p2sh are supported with hardware
wallets or bip39 seeds. To create a segwit-in-p2sh wallet,
trezor/ledger users will need to enter a BIP49 derivation path.
- The BIP32 master keys of segwit wallets are serialized using new
version numbers. The new version numbers encode the script type,
and they result in the following prefixes:
* xpub/xprv : p2pkh or p2sh
* ypub/yprv : p2wpkh-in-p2sh
* Ypub/Yprv : p2wsh-in-p2sh
* zpub/zprv : p2wpkh
* Zpub/Zprv : p2wsh
These values are identical for mainnet and testnet; tpub/tprv
prefixes are no longer used in testnet wallets.
- The Wallet Import Format (WIF) is similarly extended for segwit
scripts. After a base58-encoded key is decoded to binary, its
first byte encodes the script type:
* 128 + 0: p2pkh
* 128 + 1: p2wpkh
* 128 + 2: p2wpkh-in-p2sh
* 128 + 5: p2sh
* 128 + 6: p2wsh
* 128 + 7: p2wsh-in-p2sh
The distinction between p2sh and p2pkh in private key means that
it is not possible to import a p2sh private key and associate it
to a p2pkh address.
* A new version of the Electrum protocol is required by the client
(version 1.1). Servers using older versions of the protocol will
not be displayed in the GUI.
* By default, transactions are time-locked to the height of the
current block. Other values of locktime may be passed using the
command line.
# Release 2.9.4 (security update)
* Backport security fixes from 3.0.5 after vulnerability was
discovered in JSONRPC interface.
# Release 2.9.3
* fix configuration file issue #2719
* fix ledger signing of non-RBF transactions
* disable 'spend confirmed only' option by default
# Release 2.9.2
* force headers download if headers file is corrupted
* add websocket to windows builds
# Release 2.9.1
* fix initial headers download
* validate contacts on import
* command-line option for locktime
# Release 2.9 - Independence (July 27th, 2017)
* Multiple Chain Validation: Electrum will download and validate
block headers sent by servers that may follow different branches
of a fork in the Bitcoin blockchain. Instead of a linear sequence,
block headers are organized in a tree structure. Branching points
are located efficiently using binary search. The purpose of MCV is
to detect and handle blockchain forks that are invisible to the
classical SPV model.
* The desired branch of a blockchain fork can be selected using the
network dialog. Branches are identified by the hash and height of
the diverging block. Coin splitting is possible using RBF
transaction (a tutorial will be added).
* Multibit support: If the user enters a BIP39 seed (or uses a
hardware wallet), the full derivation path is configurable in the
install wizard.
* Option to send only confirmed coins
* Qt GUI:
- Network dialog uses tabs and gets updated by network events.
- The gui tabs use icons
* Kivy GUI:
- separation between network dialog and wallet settings dialog.
- option for manual server entry
- proxy configuration
* Daemon: The wallet password can be passed as parameter to the
JSONRPC API.
* Various other bugfixes and improvements.
# Release 2.8.3
* Fix crash on reading older wallet formats.
* TrustedCoin: remove pay-per-tx option
# Release 2.8.2
* show paid invoices in history tab
* improve CPFP dialog
* fixes for trezor, keepkey
* other minor bugfixes
# Release 2.8.1
* fix Digital Bitbox plugin
* fix daemon jsonrpc
* fix trustedcoin wallet creation
* other minor bugfixes
# Release 2.8.0 (March 9, 2017)
* Wallet file encryption using ECIES: A keypair is derived from the
wallet password. Once the wallet is decrypted, only the public key
is retained in memory, in order to save the encrypted file.
* The daemon requires wallets to be explicitly loaded before
commands can use them. Wallets can be loaded using: 'electrum
daemon load_wallet [-w path]'. This command will require a
password if the wallet is encrypted.
* Invoices and contacts are stored in the wallet file and are no
longer shared between wallets. Previously created invoices and
contacts files may be imported from the menu.
* Fees improvements:
- Dynamic fees are enabled by default.
- Child Pays For Parent (CPFP) dialog in the GUI.
- RBF is automatically proposed for low fee transactions.
* Support for Segregated Witness (testnet only).
* Support for Digital Bitbox hardware wallet.
* The GUI shows a blue icon when connected using a proxy.
# Release 2.7.18
* enforce https on exchange rate APIs
* use hardcoded list of exchanges
* move 'Freeze' menu to Coins (utxo) tab
* various bugfixes
# Release 2.7.17
* fix a few minor regressions in the Qt GUI
# Release 2.7.16
* add Testnet support (fix #541)
* allow daemon to be launched in the foreground (fix #1873)
* Qt: use separate tabs for addresses and UTXOs
* Qt: update fee slider with a network callback
* Ledger: new ui and mobile 2fa validation (neocogent)
# Release 2.7.15
* Use fee slider for both static and dynamic fees.
* Add fee slider to RBF dialog (fix #2083).
* Simplify fee preferences.
* Critical: Fix password update issue (#2097). This bug prevents
password updates in multisig and 2FA wallets. It may also cause
wallet corruption if the wallet contains several master private
keys (such as 2FA wallets that have been restored from
seed). Affected wallets will need to be restored again.
# Release 2.7.14
* Merge exchange_rate plugin with main code
* Faster synchronization and transaction creation
* Fix bugs #2096, #2016
# Release 2.7.13
* fix message signing with imported keys
* add size to transaction details window
* move plot plugin to main code
* minor bugfixes
# Release 2.7.12
various bugfixes
# Release 2.7.11
* fix offline signing (issue #195)
* fix android crashes caused by threads
# Release 2.7.10
* various fixes for hardware wallets
* improve fee bumping
* separate sign and broadcast buttons in Qt tx dialog
* allow spaces in private keys
# Release 2.7.9
* Fix a bug with the ordering of pubkeys in recent multisig wallets.
Affected wallets will regenerate their public keys when opened for
the first time. This bug does not affect address generation.
* Fix hardware wallet issues #1975, #1976
# Release 2.7.8
* Fix a bug with fee bumping
* Fix crash when parsing request (issue #1969)
# Release 2.7.7
* Fix utf8 encoding bug with old wallet seeds (issue #1967)
* Fix delete request from menu (issue #1968)
# Release 2.7.6
* Fixes a critical bug with imported private keys (issue #1966). Keys
imported in Electrum 2.7.x were not encrypted, even if the wallet
had a password. If you imported private keys using Electrum 2.7.x,
you will need to import those keys again. If you imported keys in
2.6 and converted with 2.7.x, you don't need to do anything, but
you still need to upgrade in order to be able to spend.
* Wizard: Hide seed options in a popup dialog.
# Release 2.7.5
* Add number of confirmations to request status. (issue #1757)
* In the GUI, refer to passphrase as 'seed extension'.
* Fix bug with utf8 encoded passphrases.
* Kivy wizard: add a dialog for seed options.
* Kivy wizard: add current word to suggestions, because some users
don't see the space key.
# Release 2.7.4
* Fix private key import in wizard
* Fix Ledger display (issue #1961)
* Fix old watching-only wallets (issue #1959)
* Fix Android compatibility (issue #1947)
# Release 2.7.3
* fix Trezor and Keepkey support in Windows builds
* fix sweep private key dialog
* minor fixes: #1958, #1959
# Release 2.7.2
* fix bug in password update (issue #1954)
* fix fee slider (issue #1953)
# Release 2.7.1
* fix wizard crash with old seeds
* fix issue #1948: fee slider
# Release 2.7.0 (Oct 2 2016)
* The wallet file format has been upgraded. This upgrade is not
backward compatible, which means that a wallet upgraded to the 2.7
format will not be readable by earlier versions of
Electrum. Multiple accounts inside the same wallet are not
supported in the new format; the Qt GUI will propose to split any
wallet that has several accounts. Make sure that you have saved
your seed phrase before you upgrade Electrum.
* This version introduces a separation between wallets types and
keystores types. 'Wallet type' defines the type of Bitcoin contract
used in the wallet, while 'keystore type' refers to the method used
to store private keys. Therefore, so-called 'hardware wallets' will
be referred to as 'hardware keystores'.
* Hardware keystores:
- The Ledger Nano S is supported.
- Hardware keystores can be used as cosigners in multi-signature
wallets.
- Multiple hardware cosigners can be used in the same multisig
wallet. One icon per keystore is displayed in the satus bar. Each
connected device will co-sign the transaction.
* Replace-By-Fee: RBF transactions are supported in both Qt and
Android. A warning is displayed in the history for transactions
that are replaceable, have unconfirmed parents, or that have very
low fees.
* Dynamic fees: Dynamic fees are enabled by default. A slider allows
the user to select the expected confirmation time of their
transaction. The expected confirmation times of incoming
transactions is also displayed in the history.
* The install wizards of Qt and Kivy have been unified.
* Qt GUI (Desktop):
- A fee slider is visible in the in send tab
- The Address tab is hidden by default, can be shown with Ctrl-A
- UTXOs are displayed in the Address tab
* Kivy GUI (Android):
- The GUI displays the complete transaction history.
- Multisig wallets are supported.
- Wallets can be created and deleted in the GUI.
* Seed phrases can be extended with a user-chosen passphrase. The
length of seed phrases is standardized to 12 words, using 132 bits
of entropy (including 2FA seeds). In the wizard, the type of the
seed is displayed in the seed input dialog.
* TrustedCoin users can request a reset of their Google Authenticator
account, if they still have their seed.
# Release 2.6.4 (bugfixes)
* fix coinchooser bug (#1703)
* fix daemon JSONRPC (#1731)
* fix command-line broadcast (#1728)
* QT: add colors to labels
# Release 2.6.3 (bugfixes)
* fix command line parsing of transactions
* fix signtransaction --privkey (#1715)
# Release 2.6.2 (bugfixes)
* fix Trustedcoin restore from seed (bug #1704)
* small improvements to kivy GUI
# Release 2.6.1 (bugfixes)
* fix broadcast command (bug #1688)
* fix tx dialog (bug #1690)
* kivy: support old-type seed phrases in wizard
# Release 2.6
* The source code is relicensed under the MIT Licence
* First official release of the Kivy GUI, with android APK
* The old 'android' and 'gtk' GUIs are deprecated
* Separation between plugins and GUIs
* The command line uses jsonrpc to communicate with the daemon
* New command: 'notify <address> <url>'
* Alternative coin selection policy, designed to help preserve user
privacy. Enable it by setting the Coin Selection preference to
Privacy.
* The install wizard has been rewritten and improved
* Support minikeys as used in Casascius coins for private key import
and sweeping
* Much improved support for TREZOR and KeepKey devices:
- full device information display
- initialize a new or wiped device in 4 ways:
1) device generates a new wallet
2) you enter a seed
3) you enter a BIP39 mnemonic to generate the seed
4) you enter a master private key
- KeepKey secure seed recovery (KeepKey only)
- change / set / disable PIN
- set homescreen (TREZOR only)
- set a session timeout. Once a session has timed out, further use
of the device requires your PIN and passhphrase to be re-entered
- enable / disable passphrases
- device wipe
- multiple device support
# Release 2.5.4
* increase MIN_RELAY_TX_FEE to avoid dust transactions
# Release 2.5.3 (bugfixes)
* installwizard: do not allow direct copy-paste of the seed
* installwizard: fix bug #1531 (starting offline)
# Release 2.5.2 (bugfixes)
* fix bug #1513 (client tries to broadcast transaction while not connected)
* fix synchronization bug (#1520)
* fix command line bug (#1494)
* fixes for exchange rate plugin
# Release 2.5.1 (bugfixes)
* signatures in transactions were still using the old class
* make sure that setup.py uses python2
* fix wizard crash with trustedcoin plugin
* fix socket infinite loop
* fix history bug #1479
# Release 2.5
* Low-S values are used in signatures (BIP 62).
* The Kivy GUI has been merged into master.
* The Qt GUI supports multiple windows in the same process. When a
new Electrum instance is started, it checks for an already running
Electrum process, and connects to it.
* The network layer uses select(), so all server communication is
handled by a single thread. Moreover, the synchronizer, verifier,
and exchange rate plugin now run as separate jobs within the
networking thread instead of as their own threads.
* Plugins are revamped, particularly the exchange rate plugin.
# Release 2.4.4
* Fix bug with TrustedCoin plugin
# Release 2.4.3
* Support for KeepKey hardware wallet
* Simplified Chinese wordlist
* Minor bugfixes and GUI tweaks
# Release 2.4.2
* Command line can read arguments from stdin (pipe)
* Speedup fee computation for large transactions
* Various bugfixes
# Release 2.4.1
* Use ssl.PROTOCOL_TLSv1
* Fix DNSSEC issues with ECDSA signatures
* Replace TLSLite dependency with minimal RSA implementation
* Dynamic Fees: using estimatefee value returned by server
* Various GUI improvements
# Release 2.4
* Payment to DNS names storing a Bitcoin addresses (OpenAlias) is
supported directly, without activating a plugin. The verification
uses DNSSEC.
* The DNSSEC verification code was rewritten. The previous code,
which was part of the OpenAlias plugin, is vulnerable and should
not be trusted (Electrum 2.0 to 2.3).
* Payment requests can be signed using Bitcoin addresses stored
in DNS (OpenAlias). The identity of the requestor is verified using
DNSSEC.
* Payment requests signed with OpenAlias keys can be shared as
bitcoin: URIs, if they are simple (a single address-type
output). The BIP21 URI scheme is extended with 'name', 'sig',
'time', 'exp'.
* Arbitrary m-of-n multisig wallets are supported (n<=15).
* Multisig transactions can be signed with TREZOR. When you create
the multisig wallet, just enter the xpub of your existing TREZOR
wallet.
* Transaction fees set manually in the GUI are retained, including
when the user uses the '!' shortcut.
* New 'email' plugin, that enables sending and receiving payment
requests by email.
* The daemon supports Websocket notifications of payments.
# Release 2.3.3
* fix proxy settings (issue #1309)
* improvements to the transaction dialog:
- request password after showing transaction
- show change addresses in yellow color
# Release 2.3.2
* minor bugfixes
* updated ledger plugin
* sort inputs/outputs lexicographically (BIP-LI01)
# Release 2.3.1
* patch a bug with payment requests
# Release 2.3
* Improved logic for the network layer.
* More efficient coin selection. Spend oldest coins first, and
minimize the number of transaction inputs.
* Plugins are loaded independently of the GUI. As a result, Openalias,
TrustedCoin and TREZOR wallets can be used with the command
line. Example: 'electrum payto <openalias> <amount>'
* The command line has been refactored:
- Arguments are parsed with argparse.
- The inline help includes a description of options.
- Some commands have been renamed. Notably, 'mktx' and 'payto' have
been merged into a single command, with a --broadcast option.
Type 'electrum --help' for a complete overview.
* The command line accepts the '!' syntax to send the maximum
amount available. It can be combined with the '--from' option.
Example: 'payto <destination> ! --from <from_address>'
* The command line also accepts a '?' shortcut for private keys
arguments, that triggers a prompt.
* Payment requests can be managed with the command line, using the
following commands: 'addrequest', 'rmrequest', 'listrequests'.
Payment requests can be signed with a SSL certificate, and published
as bip70 files in a public web directory. To see the relevant
configuration variables, type 'electrum addrequest --help'
* Commands can be called with jsonrpc, using the 'jsonrpc' gui. The
jsonrpc interface may be called by php.
# Release 2.2
* Show amounts (thousands separators and decimal point)
according to locale in GUI
* Show unmatured coins in balance
* Fix exchange rates plugin
* Network layer: refactoring and fixes
# Release 2.1.1
* patch a bug that prevents new wallet creation.
* fix connection issue on osx binaries
# Release 2.1
* Faster startup, thanks to the following optimizations:
1. Transaction input/outputs are cached in the wallet file
2. Fast X509 certificate parser, not using pyasn1 anymore.
3. The Label Sync plugin only requests modified labels.
* The 'Invoices' and 'Send' tabs have been merged.
* Contacts are stored in a separate file, shared between wallets.
* A Search Box is available in the GUI (Ctrl-S)
* Payment requests have an expiration date and can be exported to
BIP70 files.
* file: scheme support in BIP72 URIs: "bitcoin:?r=file:///..."
* Own addresses are shown in green in the Transaction dialog.
* Address History dialog.
* The OpenAlias plugin was improved.
* Various bug fixes and GUI improvements.
* A new LabelSync backend is being used an import of the old
database was made but since the release came later it's
recommended that you do a full push when you upgrade.
# Release 2.0.4 - Minor GUI improvements
* The password dialog will ask for password again if the user enters
a wrong password
* The Master Public Key dialog displays which keys belong to the
wallet, and which are cosigners
* The transaction dialog will ask to save unsaved transaction
received from cosigner pool, when user clicks on 'Close'
* The multisig restore dialog accepts xprv keys.
* The network daemon must be started explicitly before using commands
that require a connection
Example:
electrum daemon start
electrum getaddressunspent <addr>
electrum daemon status
electrum daemon stop
If a daemon is running, the GUI will use it.
# Release 2.0.3 - bugfixes and minor GUI improvements
* Do not use daemon threads (fix #960)
* Add a zoom button to receive tab
* Add exchange rate conversion to receive tab
* Use Tor's default port number in default proxy config
# Release 2.0.2 - bugfixes
* Fix transaction sweep (#1066)
* Fix thread timing bug (#1054)
# Release 2.0.1 - bugfixes
* Fix critical bug in TREZOR address derivation: passphrases were not
NFKD normalized. TREZOR users who created a wallet protected by a
passphrase containing utf-8 characters with diacritics are
affected. These users will have to open their wallet with version
2.0 and to move their funds to a new wallet.
* Use a file socket for the daemon (fixes network dialog issues)
* Fix crash caused by QR scanner icon when zbar not installed.
* Fix CosignerPool plugin
* Label Sync plugin: Fix label sharing between multisig wallets
# Release 2.0
* Before you upgrade, make sure you have saved your wallet seed on
paper.
* Documentation is now hosted on a wiki: http://electrum.orain.org
* New seed derivation method (not compatible with BIP39). The seed
phrase includes a version number, that refers to the wallet
structure. The version number also serves as a checksum, and it
will prevent the import of seeds from incompatible wallets. Old
Electrum seeds are still supported.
* New address derivation (BIP32). Standard wallets are single account
and use a gap limit of 20.
* Support for Multisig wallets using parallel BIP32 derivations and
P2SH addresses ("2 of 2", "2 of 3").
* Compact serialization format for unsigned or partially signed
transactions, that includes the BIP32 master public key and
derivation needed to sign inputs. Serialized transactions can be
sent to cosigners or to cold storage using QR codes (using Andreas
Schildbach's base 43 idea).
* Support for BIP70 payment requests:
- Verification of the chain of signatures uses tlslite.
- In the GUI, payment requests are shown in the 'Invoices' tab.
* Support for hardware wallets: TREZOR (SatoshiLabs) and Btchip (Ledger).
* Two-factor authentication service by TrustedCoin. This service uses
"2 of 3" multisig wallets and Google Authenticator. Note that
wallets protected by this service can be deterministically restored
from seed, without Trustedcoin's server.
* Cosigner Pool plugin: encrypted communication channel for multisig
wallets, to send and receive partially signed transactions.
* Audio Modem plugin: send and receive transactions by sound.
* OpenAlias plugin: send bitcoins to aliases verified using DNSSEC.
* New 'Receive' tab in the GUI:
- create and manage payment requests, with QR Codes
- the former 'Receive' tab was renamed to 'Addresses'
- the former Point of Sale plugin is replaced by a resizable
window that pops up if you click on the QR code
* The 'Send' tab in the Qt GUI supports transactions with multiple
outputs, and raw hexadecimal scripts.
* The GUI can connect to the Electrum daemon: "electrum -d" will
start the daemon if it is not already running, and the GUI will
connect to it. The daemon can serve several clients. It times out
if no client uses if for more than 5 minutes.
* The install wizard can be used to import addresses or private
keys. A watching-only wallet is created by entering a list of
addresses in the wizard dialog.
* New file format: Wallets files are saved as JSON. Note that new
wallet files cannot be read by older versions of Electrum. Old
wallet files will be converted to the new format; this operation
may take some time, because public keys will be derived for each
address of your wallet.
* The client accepts servers with a CA-signed SSL certificate.
* ECIES encrypt/decrypt methods, available in the GUI and using
the command line:
encrypt <pubkey> <message>
decrypt <pubkey> <message>
* The Android GUI has received various updates and it is much more
stable. Another script was added to Android, called Authenticator,
that works completely offline: it reads an unsigned transaction
shown as QR code, signs it and shows the result as a QR code.
# Release 1.9.8
* Electrum servers were upgraded to version 0.9. The new server stores
a Patrica tree of all UTXOs, an idea proposed by Alan Reiner in the
bitcointalk forum. This property allows the client to directly
request the balance of any address. The new commands are:
1. getaddressbalance <address>
2. getaddressunspent <address>
3. getutxoaddress <txid> <pos>
* Command-line commands that require a connection to the network spawn
a daemon, that remains connected and handles subsequent
commands. The daemon terminates itself if it remains unused for more
than one minute. The purpose of this is to make scripting more
efficient. For example, a bash script using many electrum commands
will open only one connection.
# Release 1.9.7
* Fix for offline signing
* Various bugfixes
* GUI usability improvements
* Coinbase Buyback plugin
# Release 1.9.6
* During wallet creation, do not write seed to disk until it is encrypted.
* Confirmation dialog if the transaction fee is higher than 1mBTC.
* bugfixes
# Release 1.9.5
* Coin control: select addresses to send from
* Put addresses that have been used in a minimized section (Qt GUI)
* Allow non ascii chars in passwords
# Release 1.9.4
bugfixes: offline transactions
# Release 1.9.3
bugfixes: connection problems, transactions staying unverified
# Release 1.9.2
* fix a syntax error
# Release 1.9.1
* fix regression with --offline mode
* fix regression with --portable mode: use a dedicated directory
# Release 1.9
* The client connects to multiple servers in order to retrieve block headers and find the longest chain
* SSL certificate validation (to prevent MITM)
* Deterministic signatures (RFC 6979)
* Menu to create/restore/open wallets
* Create transactions with multiple outputs from CSV (comma separated values)
* New text gui: stdio
* Plugins are no longer tied to the qt GUI, they can reach all GUIs
* Proxy bugs have been fixed
# Release 1.8.1
* Notification option when receiving new transactions
* Confirm dialogue before sending large amounts
* Alternative datafile location for non-windows systems
* Fix offline wallet creation
* Remove enforced tx fee
* Tray icon improvements
* Various bugfixes
# Release 1.8
* Menubar in classic gui
* Updated the QR Code plugin to enable offline/online wallets to transmit unsigned/signed transactions via QR code.
* Fixed bug where never-confirmed transactions prevented further spending
# Release 1.7.4
* Increase default fee
* fix create and restore in command line
* fix verify message in the gui
# Release 1.7.3:
* Classic GUI can display amounts in mBTC
* Account selector in the classic GUI
* Changed the way the portable flag uses without supplying a -w argument
* Classic GUI asks users to enter their seed on wallet creation
# Release 1.7.2:
* Transactions that are in the same block are displayed in chronological order in the history.
* The client computes transaction priority and rejects zero-fee transactions that need a fee.
* The default fee was lowered to 200 uBTC per kb.
* Due to an internal format change, your history may be pruned when
you open your wallet for the first time after upgrading to 1.7.2. If
this is the case, please visit a full server to restore your full
history. You will only need to do that once.
# Release 1.7.1: bugfixes.
# Release 1.7
* The Classic GUI can be extended with plugins. Developers who want to
add new features or third-party services to Electrum are invited to
write plugins. Some previously existing and non-essential features of
Electrum (point-of-sale mode, qrcode scanner) were removed from the
core and are now available as plugins.
* The wallet waits for 2 confirmations before creating new
addresses. This makes recovery from seed more robust. Note that it
might create unwanted gaps if you use Electrum 1.7 together with older
versions of Electrum.
* An interactive Python console replaces the 'Wall' tab. The provided
python environment gives users access to the wallet and gui. Most
electrum commands are available as python function in the
console. Custom scripts an be loaded with a "run(filename)"
command. Tab-completions are available.
* The location of the Electrum folder in Windows changed from
LOCALAPPDATA to APPDATA. Discussion on this topic can be found here:
https://bitcointalk.org/index.php?topic=144575.0
* Private keys can be exported from within the classic GUI:
For a single address, use the address menu (right-click).
To export the keys of your entire wallet, use the settings dialog (import/export tab).
* It is possible to create, sign and redeem multisig transaction using the
command line interface. This is made possible by the following new commands:
dumpprivkey, listunspent, createmultisig, createrawtransaction, decoderawtransaction, signrawtransaction
The syntax of these commands is similar to their bitcoind counterpart.
For an example, see Gavin's tutorial: https://gist.github.com/gavinandresen/3966071
* Offline wallets now work in a way similar to Armory:
1. user creates an unsigned transaction using the online (watching-only) wallet.
2. unsigned transaction is copied to the offline computer, and signed by the offline wallet.
3. signed transaction is copied to the online computer, broadcasted by the online client.
4. All these steps can be done via the command line interface or the classic GUI.
* Many command line commands have been renamed in order to make the syntax consistent with bitcoind.
# Release 1.6.2
== Classic GUI
* Added new version notification
# Release 1.6.1 (11-01-2013)
== Core
* It is now possible to restore a wallet from MPK (this will create a watching-only wallet)
* A switch button allows to easily switch between Lite and Classic GUI.
== Classic GUI
* Seed and MPK help dialogs were rewritten
* Point of Sale: requested amounts can be expressed in other currencies and are converted to bitcoin.
== Lite GUI
* The receiving button was removed in favor of a menu item to keep it consistent with the history toggle.
# Release 1.6.0 (07-01-2013)
== Core
* (Feature) Add support for importing, signing and verifiying compressed keys
* (Feature) Auto reconnect to random server on disconnect
* (Feature) Ultimate fallback to HTTP port 80 if TCP doesn't work on any server
* (Bug) Under rare circumstances changing password with incorrect password could damage wallet
== Lite GUI
* (Chore) Use blockchain.info for exchange rate data
* (Feature) added currency conversion for BRL, CNY, RUB
* (Feature) Saraha theme
* (Feature) csv import/export for transactions including labels
== Classic GUI
* (Chore) pruning servers now called "p", full servers "f" to avoid confusion with terms
* (Feature) Debits in history shown in red
* (Feature) csv import/export for transactions including labels
# Release 1.5.8 (02-01-2013)
== Core
* (Bug) Fix pending address balance on received coins for pruning servers
* (Bug) Fix history command line option to show output again (regression by SPV)
* (Chore) Add timeout to blockchain headers file download by HTTP
* (Feature) new option: -L, --language: default language used in GUI.
== Lite GUI
* (Bug) Sending to auto-completed contacts works again
* (Chore) Added version number to title bar
== Classic GUI
* (Feature) Language selector in options.
# Release 1.5.7 (18-12-2012)
== Core
* The blockchain headers file is no longer included in the packages, it is downloaded on startup.
* New command line option: -P or --portable, for portable wallets. With this flag, all preferences are saved to the wallet file, and the blockchain headers file is in the same directory as the wallet
== Lite GUI
* (Feature) Added the ability to export your transactions to a CSV file.
* (Feature) Added a label dialog after sending a transaction.
* (Feature) Reworked receiving addresses; instead of a random selection from one of your receiving addresses a new widget will show listing unused addresses.
* (Chore) Removed server selection. With all the new server options a simple menu item does not suffice anymore.
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Reporting a Vulnerability
To report security issues, send an email to the addresses listed below.
(Not for support. Support requests will be *ignored*.)
Please send any report to *all* emails listed here.
The following GPG keys may be used to communicate sensitive information.
| Name | Email | GPG fingerprint |
|-------------|----------------------------------------|---------------------------------------------------|
| ThomasV | thomasv [AT] electrum [DOT] org | 6694 D8DE 7BE8 EE56 31BE D950 2BD5 824B 7F94 70E6 |
| SomberNight | somber.night [AT] protonmail [DOT] com | 4AD6 4339 DFA0 5E20 B3F6 AD51 E7B7 48CD AF5E 5ED9 |
#### Where to find GPG keys
You can import a key by running the following command with that
individual’s fingerprint: `gpg --recv-keys "<fingerprint>"`
These public keys can also be found in the Electrum git repository,
in the top-level `pubkeys` folder.
================================================
FILE: contrib/add_cosigner
================================================
#!/usr/bin/python3
#
# This script is part of the workflow for BUILDERs to reproduce and sign the
# release binaries. (for builders who do not have sftp access to "electrum-downloads-airlock")
#
# env vars:
# - SSHUSER
#
#
# - BUILDER builds all binaries and checks they match the official releases
# (using release.sh, and perhaps some manual steps)
# - BUILDER creates a PR against https://github.com/spesmilo/electrum-signatures/
# to add their sigs for a given release, which then gets merged
# - SFTPUSER runs `$ SSHUSER=$SFTPUSER electrum/contrib/add_cosigner $BUILDER`
# - SFTPUSER runs `$ electrum/contrib/make_download $WWW_DIR`
# - $ (cd $WWW_DIR; git commit -a -m "add_cosigner"; git push)
# - SFTPUSER runs `$ electrum-web/publish.sh $SFTPUSER`
# - (for the website to be updated, both ThomasV and SomberNight needs to run publish.sh)
import re
import os
import sys
import importlib
import importlib.util
import subprocess
if len(sys.argv) < 2:
print(f"usage: {os.path.basename(__file__)} <cosigner>", file=sys.stderr)
sys.exit(1)
# cd to project root
os.chdir(os.path.dirname(os.path.dirname(__file__)))
# load version.py; needlessly complicated alternative to "imp.load_source":
version_spec = importlib.util.spec_from_file_location('version', 'electrum/version.py')
version_module = importlib.util.module_from_spec(version_spec)
version_spec.loader.exec_module(version_module)
ELECTRUM_VERSION = version_module.ELECTRUM_VERSION
print("version", ELECTRUM_VERSION)
# GPG name of cosigner
cosigner = sys.argv[1]
version = version_win = version_mac = version_android = ELECTRUM_VERSION
files = {
"tgz": f"Electrum-{version}.tar.gz",
"tgz_srconly": f"Electrum-sourceonly-{version}.tar.gz",
"appimage": f"electrum-{version}-x86_64.AppImage",
"mac": f"electrum-{version_mac}.dmg",
"win": f"electrum-{version_win}.exe",
"win_setup": f"electrum-{version_win}-setup.exe",
"win_portable": f"electrum-{version_win}-portable.exe",
"apk_arm64": f"Electrum-{version_android}-arm64-v8a-release.apk",
"apk_armeabi": f"Electrum-{version_android}-armeabi-v7a-release.apk",
"apk_x86_64": f"Electrum-{version_android}-x86_64-release.apk",
}
for shortname, filename in files.items():
path = f"dist/{filename}"
link = f"https://download.electrum.org/{version}/{filename}"
if not os.path.exists(path):
os.system(f"wget -q {link} -O {path}")
if not os.path.getsize(path):
raise Exception(path)
sig_name = f"{filename}.{cosigner}.asc"
sig_url = f"https://raw.githubusercontent.com/spesmilo/electrum-signatures/master/{version}/{filename}/{sig_name}"
sig_path = f"dist/{sig_name}"
os.system(f"wget -nc {sig_url} -O {sig_path}")
if os.system(f"gpg --verify {sig_path} {path}") != 0:
raise Exception(sig_name)
print("Calling upload.sh now... This might take some time.")
subprocess.check_output(["./contrib/upload.sh", ])
================================================
FILE: contrib/android/Dockerfile
================================================
# based on https://github.com/kivy/python-for-android/blob/master/Dockerfile
FROM debian:trixie@sha256:a3b5f4f0286249a124bfe9845b3aec0f88de32ff31dd8d7e1b945f9f98d116b0
ENV DEBIAN_FRONTEND=noninteractive
ENV ANDROID_HOME="/opt/android"
# need ca-certificates before using snapshot packages
RUN apt update -qq > /dev/null && apt install -qq --yes --no-install-recommends \
ca-certificates
# pin the distro packages.
COPY contrib/android/apt.sources.list /etc/apt/sources.list
COPY contrib/android/apt.preferences /etc/apt/preferences.d/snapshot
# configure locale
RUN apt update -qq > /dev/null && apt install -qq --yes --no-install-recommends --allow-downgrades \
locales && \
locale-gen en_US.UTF-8
ENV LANG="en_US.UTF-8" \
LANGUAGE="en_US.UTF-8" \
LC_ALL="en_US.UTF-8"
RUN apt -y update -qq \
&& apt -y install -qq --no-install-recommends --allow-downgrades \
curl \
wget \
unzip \
ca-certificates \
python3 \
&& apt -y autoremove
ENV ANDROID_NDK_HOME="${ANDROID_HOME}/android-ndk"
#ENV ANDROID_NDK_VERSION="23b"
#ENV ANDROID_NDK_HASH="c6e97f9c8cfe5b7be0a9e6c15af8e7a179475b7ded23e2d1c1fa0945d6fb4382"
#ENV ANDROID_NDK_VERSION="27d"
#ENV ANDROID_NDK_HASH="601246087a682d1944e1e16dd85bc6e49560fe8b6d61255be2829178c8ed15d9"
ENV ANDROID_NDK_VERSION="23d-canary"
ENV ANDROID_NDK_HASH="6944ffc20ab018ff4ef6a403048d0a99d50a0630c3eae690c8f803c452f46f3e"
ENV ANDROID_NDK_HOME_V="${ANDROID_NDK_HOME}-r${ANDROID_NDK_VERSION}"
# get the latest version from https://developer.android.com/ndk/downloads/index.html
ENV ANDROID_NDK_ARCHIVE="android-ndk-r${ANDROID_NDK_VERSION}-linux.zip"
ENV ANDROID_NDK_DL_URL="https://dl.google.com/android/repository/${ANDROID_NDK_ARCHIVE}"
# below disabled in favor of CI build download
# download and install Android NDK
#RUN curl --location --progress-bar \
# "${ANDROID_NDK_DL_URL}" \
# --output "${ANDROID_NDK_ARCHIVE}" \
# && echo "${ANDROID_NDK_HASH} ${ANDROID_NDK_ARCHIVE}" | sha256sum -c - \
# && mkdir --parents "${ANDROID_NDK_HOME_V}" \
# && unzip -q "${ANDROID_NDK_ARCHIVE}" -d "${ANDROID_HOME}" \
# && ln -sfn "${ANDROID_NDK_HOME_V}" "${ANDROID_NDK_HOME}" \
# && rm -rf "${ANDROID_NDK_ARCHIVE}"
# temporary build using NDK from CI
ENV CI_REV="12186248"
ENV CI_NDK_FILE="android-ndk-${CI_REV}-linux-x86_64.zip"
COPY contrib/android/dl-ndk-ci.sh /tmp/
RUN /tmp/dl-ndk-ci.sh https://ci.android.com/builds/submitted/${CI_REV}/linux/latest/${CI_NDK_FILE} \
&& echo "${ANDROID_NDK_HASH} android-ndk-ci-linux-x86_64.zip" | sha256sum -c - \
&& mkdir --parents "${ANDROID_NDK_HOME_V}" \
&& unzip -q "android-ndk-ci-linux-x86_64.zip" -d "${ANDROID_HOME}" \
&& ln -sfn "${ANDROID_NDK_HOME_V}" "${ANDROID_NDK_HOME}" \
&& rm -rf "android-ndk-ci-linux-x86_64.zip"
ENV ANDROID_SDK_HOME="${ANDROID_HOME}/android-sdk"
# get the latest version from https://developer.android.com/studio/index.html
ENV ANDROID_SDK_TOOLS_VERSION="9477386"
ENV ANDROID_SDK_HASH="bd1aa17c7ef10066949c88dc6c9c8d536be27f992a1f3b5a584f9bd2ba5646a0"
ENV ANDROID_SDK_TOOLS_ARCHIVE="commandlinetools-linux-${ANDROID_SDK_TOOLS_VERSION}_latest.zip"
ENV ANDROID_SDK_TOOLS_DL_URL="https://dl.google.com/android/repository/${ANDROID_SDK_TOOLS_ARCHIVE}"
ENV ANDROID_SDK_MANAGER="${ANDROID_SDK_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=${ANDROID_SDK_HOME}"
# download and install Android SDK
RUN curl --location --progress-bar \
"${ANDROID_SDK_TOOLS_DL_URL}" \
--output "${ANDROID_SDK_TOOLS_ARCHIVE}" \
&& echo "${ANDROID_SDK_HASH} ${ANDROID_SDK_TOOLS_ARCHIVE}" | sha256sum -c - \
&& mkdir --parents "${ANDROID_SDK_HOME}" \
&& unzip -q "${ANDROID_SDK_TOOLS_ARCHIVE}" -d "${ANDROID_SDK_HOME}" \
&& rm -rf "${ANDROID_SDK_TOOLS_ARCHIVE}"
# update Android SDK, install Android API, Build Tools...
RUN mkdir --parents "${ANDROID_SDK_HOME}/.android/" \
&& echo '### User Sources for Android SDK Manager' \
> "${ANDROID_SDK_HOME}/.android/repositories.cfg"
# download Java-17 (debian 13 only packages Java-21 and Java-25)
# - we download the amd64 binaries from debian 12 repos
# - we should try to upgrade to Java-21...
# - the main blocker seems to be having to update Gradle (to a version compatible with Java-21)
# - make_barcode_scanner.sh: markusfisch/{zxing-cpp, ...} pins old Gradle
ENV JAVA_JRE_DL_URL="https://snapshot.debian.org/archive/debian/20260130T143028Z/pool/main/o/openjdk-17/openjdk-17-jre-headless_17.0.18+8-1~deb12u1_amd64.deb"
ENV JAVA_JRE_ARCHIVE="openjdk-17-jre-headless.deb"
ENV JAVA_JRE_HASH="5bc36cbb4e383dbea4168d57b5fd9b42375ec8837dd62a1d56677632c3c960e0"
ENV JAVA_JDK_DL_URL="https://snapshot.debian.org/archive/debian/20260130T143028Z/pool/main/o/openjdk-17/openjdk-17-jdk-headless_17.0.18+8-1~deb12u1_amd64.deb"
ENV JAVA_JDK_ARCHIVE="openjdk-17-jdk-headless.deb"
ENV JAVA_JDK_HASH="8841044caa66860a71039342fe3c02b7853b61c518e05970e501faa215b1788a"
RUN apt -y update -qq \
&& apt -y install -qq --no-install-recommends \
ca-certificates-java \
java-common \
libcups2 \
libfontconfig1 \
liblcms2-2 \
libjpeg62-turbo \
libnss3 \
libasound2 \
libfreetype6 \
libharfbuzz0b \
libpcsclite1 \
&& apt -y autoremove \
&& cd /opt \
&& curl --location --progress-bar "${JAVA_JRE_DL_URL}" --output "${JAVA_JRE_ARCHIVE}" \
&& echo "${JAVA_JRE_HASH} ${JAVA_JRE_ARCHIVE}" | sha256sum -c - \
&& dpkg -i "${JAVA_JRE_ARCHIVE}" \
&& rm "${JAVA_JRE_ARCHIVE}" \
&& curl --location --progress-bar "${JAVA_JDK_DL_URL}" --output "${JAVA_JDK_ARCHIVE}" \
&& echo "${JAVA_JDK_HASH} ${JAVA_JDK_ARCHIVE}" | sha256sum -c - \
&& dpkg -i "${JAVA_JDK_ARCHIVE}" \
&& rm "${JAVA_JDK_ARCHIVE}"
# accept Android licenses (JDK necessary!)
RUN yes | ${ANDROID_SDK_MANAGER} --licenses > /dev/null
ENV ANDROID_SDK_BUILD_TOOLS_MAJOR_V="31"
ENV ANDROID_SDK_BUILD_TOOLS_VERSION="31.0.0"
# download platforms, API, build tools
RUN ${ANDROID_SDK_MANAGER} "platforms;android-${ANDROID_SDK_BUILD_TOOLS_MAJOR_V}" > /dev/null && \
${ANDROID_SDK_MANAGER} "build-tools;${ANDROID_SDK_BUILD_TOOLS_VERSION}" > /dev/null && \
${ANDROID_SDK_MANAGER} "extras;android;m2repository" > /dev/null && \
chmod +x "${ANDROID_SDK_HOME}/cmdline-tools/bin/avdmanager"
# download ANT
ENV APACHE_ANT_VERSION="1.10.13"
ENV APACHE_ANT_HASH="776be4a5704158f00ef3f23c0327546e38159389bc8f39abbfe114913f88bab1"
ENV APACHE_ANT_ARCHIVE="apache-ant-${APACHE_ANT_VERSION}-bin.tar.gz"
ENV APACHE_ANT_DL_URL="https://archive.apache.org/dist/ant/binaries/${APACHE_ANT_ARCHIVE}"
ENV APACHE_ANT_HOME="${ANDROID_HOME}/apache-ant"
ENV APACHE_ANT_HOME_V="${APACHE_ANT_HOME}-${APACHE_ANT_VERSION}"
RUN curl --location --progress-bar \
"${APACHE_ANT_DL_URL}" \
--output "${APACHE_ANT_ARCHIVE}" \
&& echo "${APACHE_ANT_HASH} ${APACHE_ANT_ARCHIVE}" | sha256sum -c - \
&& tar -xf "${APACHE_ANT_ARCHIVE}" -C "${ANDROID_HOME}" \
&& ln -sfn "${APACHE_ANT_HOME_V}" "${APACHE_ANT_HOME}" \
&& rm -rf "${APACHE_ANT_ARCHIVE}"
# install system/build dependencies
# https://github.com/kivy/buildozer/blob/master/docs/source/installation.rst#android-on-ubuntu-2004-64bit
RUN apt -y update -q \
&& apt -y install -q --no-install-recommends --allow-downgrades \
wget \
lbzip2 \
patch \
sudo \
git \
zip \
unzip \
rsync \
build-essential \
ccache \
autoconf \
autopoint \
libtool \
pkg-config \
zlib1g-dev \
libncurses-dev \
cmake \
libffi-dev \
libssl-dev \
automake \
gettext \
libltdl-dev \
&& apt -y autoremove \
&& apt -y clean
# cross compile deps for Qt6
RUN apt -y update -qq \
&& apt -y install -qq --no-install-recommends --allow-downgrades \
libopengl-dev \
libegl-dev \
dos2unix \
&& apt -y autoremove \
&& apt -y clean
# create new user to avoid using root; but with sudo access and no password for convenience.
ARG UID=1000
RUN if [ "$UID" != "0" ] ; then useradd --uid $UID --create-home --shell /bin/bash "user" ; fi
RUN usermod -append --groups sudo $(id -nu $UID || echo "user")
RUN echo "%sudo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
RUN HOME_DIR=$(getent passwd $UID | cut -d: -f6)
ENV WORK_DIR="${HOME_DIR}/wspace" \
PATH="${HOME_DIR}/.local/bin:${PATH}"
WORKDIR ${WORK_DIR}
RUN chown --recursive ${UID} ${WORK_DIR} ${ANDROID_SDK_HOME}
RUN chown ${UID} /opt
USER ${UID}
# build cpython. FIXME we can't use the python3 from apt, as it is too new o.O
# - p4a and buildozer require cython<3 (see https://github.com/kivy/python-for-android/issues/2919)
# but the last such version, cython 0.29.37, can only be built by up to python 3.12
ENV VENV_PYTHON_VERSION="3.12.12"
ENV VENV_PY_VER_MAJOR="3.12"
ENV VENV_PYTHON_HASH="487c908ddf4097a1b9ba859f25fe46d22ccaabfb335880faac305ac62bffb79b"
RUN mkdir --parents "/opt/cpython/download" && cd "/opt/cpython/download" \
&& wget "https://www.python.org/ftp/python/${VENV_PYTHON_VERSION}/Python-${VENV_PYTHON_VERSION}.tgz" \
&& echo "${VENV_PYTHON_HASH} Python-${VENV_PYTHON_VERSION}.tgz" | sha256sum -c - \
&& tar xf "Python-${VENV_PYTHON_VERSION}.tgz" -C "/opt/cpython/download" \
&& cd "Python-${VENV_PYTHON_VERSION}" \
&& mkdir "/opt/cpython/install" \
&& ./configure \
--prefix="/opt/cpython/install" \
-q \
&& make "-j$(nproc)" -s \
&& make -s altinstall \
&& ln -s "/opt/cpython/install/bin/python${VENV_PY_VER_MAJOR}" "/opt/cpython/install/bin/python3"
RUN "/opt/cpython/install/bin/python3" -m ensurepip
# venv, VIRTUAL_ENV is used by buildozer to indicate a venv environment
ENV VIRTUAL_ENV=/opt/venv
RUN "/opt/cpython/install/bin/python3" -m venv ${VIRTUAL_ENV}
ENV PATH="${VIRTUAL_ENV}/bin:${PATH}"
COPY contrib/deterministic-build/requirements-build-base.txt /opt/deterministic-build/
COPY contrib/deterministic-build/requirements-build-android.txt /opt/deterministic-build/
RUN /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies \
-r /opt/deterministic-build/requirements-build-base.txt
RUN /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies --no-binary :all: \
-r /opt/deterministic-build/requirements-build-android.txt
# install buildozer
ENV BUILDOZER_CHECKOUT_COMMIT="4403ecf445f10b5fbf7c74f4621bf2b922ad35b5"
# ^ from branch electrum_20240930 (note: careful with force-pushing! see #8162)
RUN cd /opt \
&& git clone https://github.com/spesmilo/buildozer \
&& cd buildozer \
&& git checkout "${BUILDOZER_CHECKOUT_COMMIT}^{commit}" \
&& /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies -e .
# install python-for-android
ENV P4A_CHECKOUT_COMMIT="a01269f7799587ad74ee40e0b642d917b8db7d4e"
# ^ from branch electrum_20251211 (note: careful with force-pushing! see #8162)
RUN cd /opt \
&& git clone https://github.com/spesmilo/python-for-android \
&& cd python-for-android \
&& git checkout "${P4A_CHECKOUT_COMMIT}^{commit}" \
&& /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies -e .
# build env vars
ENV USE_SDK_WRAPPER=1
ENV GRADLE_OPTS="-Xmx1536M -Dorg.gradle.jvmargs='-Xmx1536M'"
#ENV P4A_FULL_DEBUG=1
================================================
FILE: contrib/android/Makefile
================================================
SHELL := /bin/bash
PYTHON = python3
# for reproducible builds
export LC_ALL := C
export TZ := UTC
ifndef ELEC_APK_USE_CURRENT_TIME
export SOURCE_DATE_EPOCH := $(shell git log -1 --pretty=%ct)
else
# p4a sets "private_version" based on SOURCE_DATE_EPOCH. "private_version" gets compiled into the apk,
# and is used at runtime to decide whether the already extracted project files in the app's datadir need updating.
# So, "private_version" needs to be reproducible, but it would be useful during development if it changed
# between subsequent builds (otherwise the new code won't be unpacked and used at runtime!).
# For this reason, for development purposes, we set SOURCE_DATE_EPOCH here to the current time.
# see https://github.com/kivy/python-for-android/blob/e8686e2104a553f05959cdaf7dd26867671fc8e6/pythonforandroid/bootstraps/common/build/build.py#L575-L587
export SOURCE_DATE_EPOCH := $(shell date +%s)
endif
export PYTHONHASHSEED := $(SOURCE_DATE_EPOCH)
export BUILD_DATE := $(shell LC_ALL=C TZ=UTC date +'%b %e %Y' -d @$(SOURCE_DATE_EPOCH))
export BUILD_TIME := $(shell LC_ALL=C TZ=UTC date +'%H:%M:%S' -d @$(SOURCE_DATE_EPOCH))
.PHONY: apk clean
prepare:
# running pre build setup
# copy electrum to main.py
@cp buildozer_$(ELEC_APK_GUI).spec ../../buildozer.spec
@cp ../../run_electrum ../../main.py
apk:
@make prepare
@-cd ../..; buildozer android debug
@make clean
release:
@make prepare
@-cd ../..; buildozer android release
@make clean
clean:
# Cleaning up
# rename main.py to electrum
@-rm ../../main.py
# remove buildozer.spec
@-rm ../../buildozer.spec
================================================
FILE: contrib/android/Readme.md
================================================
# Qml GUI
The Qml GUI is used with Electrum on Android devices, since Electrum 4.4.
To generate an APK file, follow these instructions.
(note: older versions of Electrum for Android used the "kivy" GUI)
## Android binary with Docker
✓ _These binaries should be reproducible, meaning you should be able to generate
binaries that match the official releases._
- _Minimum supported target system (i.e. what end-users need): Android 6.0 (API 23)_
This assumes an Ubuntu (x86_64) host, but it should not be too hard to adapt to another
similar system.
1. Install Docker
See [`contrib/docker_notes.md`](../docker_notes.md).
(worth reading even if you already have docker)
2. Build binaries
The build script takes a few arguments. To see syntax, run it without providing any:
```
$ ./build.sh
```
For development, consider e.g. `$ ./build.sh qml arm64-v8a debug`
If you want reproducibility, try instead e.g.:
```
$ ELECBUILD_COMMIT=HEAD ./build.sh qml all release-unsigned
```
3. The generated binary is in `./dist`.
## Verifying reproducibility and comparing against official binary
Every user can verify that the official binary was created from the source code in this
repository.
1. Build your own binary as described above.
Make sure you don't build in `debug` mode,
instead use either of `release` or `release-unsigned`.
If you build in `release` mode, the apk will be signed, which requires a keystore
that you need to create manually (see source of `make_apk.sh` for an example).
2. Note that the binaries are not going to be byte-for-byte identical, as the official
release is signed by a keystore that only the project maintainers have.
You can use the `apkdiff.py` python script (written by the Signal developers) to compare
the two binaries.
```
$ python3 contrib/android/apkdiff.py Electrum_apk_that_you_built.apk Electrum_apk_official_release.apk
```
This should output `APKs match!`.
## FAQ
### I changed something but I don't see any differences on the phone. What did I do wrong?
You probably need to clear the cache: `rm -rf .buildozer/android/platform/build-*/{build,dists}`
### How do I deploy on connected phone for quick testing?
Assuming `adb` is installed:
```
$ adb -d install -r dist/Electrum-*-arm64-v8a-debug.apk
$ adb shell monkey -p org.electrum.electrum 1
```
Note `adb install` can take a `--user {userId}` option to install the app for a specific profile.
Without that, the default is to install to *all* profiles.
### How do I get an interactive shell inside docker?
```
$ docker run -it --rm \
-v $PWD:/home/user/wspace/electrum \
-v $PWD/.buildozer/.gradle:/home/user/.gradle \
--workdir /home/user/wspace/electrum \
electrum-android-builder-img
```
### How do I get more verbose logs for the build?
See `log_level` in `buildozer.spec`
### How can I see logs at runtime?
This should work OK for most scenarios:
```
adb logcat | grep python
```
Better `grep` but fragile because of `cut`:
```
adb logcat | grep -F "`adb shell ps | grep org.electrum.electrum | cut -c14-19`"
```
### The Qml GUI can be run directly on Linux Desktop. How?
Install requirements:
```
python3 -m pip install ".[qml_gui]"
```
Run electrum with the `-g` switch: `electrum -g qml`
Notes:
- pyqt ~6.4 would work best, as the gui has not yet been adapted to styling changes in 6.5
- However, pyqt6 as distributed on PyPI does not include a required module (PyQt6.QtQml) until 6.5
- Installing these deps from your OS package manager should also work,
except many don't distribute pyqt6 yet.
For pyqt5 on debian-based distros, this used to look like this:
```
sudo apt-get install python3-pyqt5 python3-pyqt5.qtquick python3-pyqt5.qtmultimedia
sudo apt-get install python3-pil
sudo apt-get install qml-module-qtquick-controls2 qml-module-qtquick-layouts \
qml-module-qtquick-window2 qml-module-qtmultimedia \
libqt5multimedia5-plugins qml-module-qt-labs-folderlistmodel
```
### debug vs release build
If you just follow the instructions above, you will build the apk
in debug mode. The most notable difference is that the apk will be
signed using a debug keystore. If you are planning to upload
what you build to e.g. the Play Store, you should create your own
keystore, back it up safely, and run `./build.sh` in `release` mode.
See e.g. [kivy wiki](https://github.com/kivy/kivy/wiki/Creating-a-Release-APK)
and [android dev docs](https://developer.android.com/studio/build/building-cmdline#sign_cmdline).
### Access datadir on Android from desktop (e.g. to copy wallet file)
Note that this only works for debug builds! Otherwise the security model
of Android does not let you access the internal storage of an app without root.
(See [this](https://stackoverflow.com/q/9017073))
To pull a file:
```
$ adb shell
adb$ run-as org.electrum.electrum ls /data/data/org.electrum.electrum/files/data
adb$ exit
$ adb exec-out run-as org.electrum.electrum cat /data/data/org.electrum.electrum/files/data/wallets/my_wallet > my_wallet
```
To push a file:
```
$ adb push ~/wspace/tmp/my_wallet /data/local/tmp
$ adb shell
adb$ ls -la /data/local/tmp
adb$ run-as org.electrum.testnet.electrum cp /data/local/tmp/my_wallet /data/data/org.electrum.testnet.electrum/files/data/testnet/wallets/
adb$ run-as org.electrum.testnet.electrum chmod -R 700 /data/data/org.electrum.testnet.electrum/files/data/testnet/wallets
adb$ run-as org.electrum.testnet.electrum chmod -R u-x,u+X /data/data/org.electrum.testnet.electrum/files/data/testnet/wallets
adb$ rm /data/local/tmp/my_wallet
```
Or use Android Studio: "Device File Explorer", which can download/upload data directly from device (via adb).
#### Device with multiple user profiles
There are further complications if using an Android device
[with multiple user profiles](https://source.android.com/docs/devices/admin/multi-user-testing)
(typical for GrapheneOS/etc).
Run `$ adb shell pm list users` to get a list of all existing users, and take note of the user ids.
Instead of `/data/data/{app.path}`, private app data is stored at `/data/user/{userId}/{app.path}`.
Further, instead of `adb$ run-as org.electrum.electrum`,
you need `adb$ run-as org.electrum.electrum --user {userId}`.
### How to investigate diff between binaries if reproducibility fails?
```
cd dist/
unzip Electrum-*.apk1 -d apk1
mkdir apk1/assets/private_mp3/
tar -xzvf apk1/assets/private.tar --directory apk1/assets/private_mp3/
mkdir apk1/lib/_libpybundle/
tar -xzvf apk1/lib/*/libpybundle.so --directory apk1/lib/_libpybundle/
unzip Electrum-*.apk2 -d apk2
mkdir apk2/assets/private_mp3/
tar -xzvf apk2/assets/private.tar --directory apk2/assets/private_mp3/
mkdir apk2/lib/_libpybundle/
tar -xzvf apk2/lib/*/libpybundle.so --directory apk2/lib/_libpybundle/
sudo chown --recursive "$(id -u -n)":"$(id -u -n)" apk1/ apk2/
chmod -R +Xr apk1/ apk2/
unzip apk1/lib/_libpybundle/_python_bundle/stdlib.zip -d apk1/lib/_libpybundle/_python_bundle/stdlib
unzip apk2/lib/_libpybundle/_python_bundle/stdlib.zip -d apk2/lib/_libpybundle/_python_bundle/stdlib
sudo chown --recursive "$(id -u -n)":"$(id -u -n)" apk1/ apk2/
chmod -R +Xr apk1/ apk2/
$(cd apk1; find -type f -exec sha256sum '{}' \; > ./../sha256sum1)
$(cd apk2; find -type f -exec sha256sum '{}' \; > ./../sha256sum2)
diff sha256sum1 sha256sum2 > d
cat d
```
### How to install apks built by the CI on my phone?
The CI (Cirrus) builds apks on most git commits.
See e.g. [here](https://github.com/spesmilo/electrum/runs/9272252577).
The task name should start with "Android build".
Click "View more details on Cirrus CI" to get to cirrus' website, and search for "Artifacts".
The apk is built in `debug` mode, and is signed using an ephemeral RSA key.
For tech demo purposes, you can directly install this apk on your phone.
However, if you already have electrum installed on your phone, Android's TOFU signing model
will not let you upgrade that to the CI apk due to mismatching signing keys. As the CI key
is ephemeral, it is not even possible to upgrade from an older CI apk to a newer CI apk.
However, it is possible to resign the apk manually with one's own key, using
e.g. [`apksigner`](https://developer.android.com/studio/command-line/apksigner),
mutating the apk in place, after which it should be possible to upgrade:
```
apksigner sign --ks ~/wspace/electrum/contrib/android/android_debug.keystore Electrum-*-arm64-v8a-debug.apk
```
================================================
FILE: contrib/android/apkdiff.py
================================================
#! /usr/bin/env python3
# from https://github.com/signalapp/Signal-Android/blob/2029ea378f249a70983c1fc3d55b9a63588bc06c/reproducible-builds/apkdiff/apkdiff.py
import sys
from zipfile import ZipFile
# FIXME it is possible to hide data in the apk signing block - and then the application
# can introspect itself at runtime and access that, even execute it as code... :/
# see https://source.android.com/docs/security/features/apksigning/v2#apk-signing-block
# https://android.izzysoft.de/articles/named/iod-scan-apkchecks
# https://github.com/obfusk/sigblock-code-poc
# I think if the app did this kind of introspection, that should be caught by code review,
# but still, note that with this current diff script it is possible to smuggle data in the apk.
class ApkDiff:
IGNORE_FILES = ["META-INF/MANIFEST.MF", "META-INF/CERT.RSA", "META-INF/CERT.SF"]
def compare(self, sourceApk, destinationApk) -> bool:
sourceZip = ZipFile(sourceApk, 'r')
destinationZip = ZipFile(destinationApk, 'r')
if self.compareManifests(sourceZip, destinationZip) and self.compareEntries(sourceZip, destinationZip):
print("APKs match!")
return True
else:
print("APKs don't match!")
return False
def compareManifests(self, sourceZip, destinationZip):
sourceEntrySortedList = sorted(sourceZip.namelist())
destinationEntrySortedList = sorted(destinationZip.namelist())
for ignoreFile in self.IGNORE_FILES:
while ignoreFile in sourceEntrySortedList: sourceEntrySortedList.remove(ignoreFile)
while ignoreFile in destinationEntrySortedList: destinationEntrySortedList.remove(ignoreFile)
if len(sourceEntrySortedList) != len(destinationEntrySortedList):
print("Manifest lengths differ!")
for (sourceEntryName, destinationEntryName) in zip(sourceEntrySortedList, destinationEntrySortedList):
if sourceEntryName != destinationEntryName:
print("Sorted manifests don't match, %s vs %s" % (sourceEntryName, destinationEntryName))
return False
return True
def compareEntries(self, sourceZip, destinationZip):
sourceInfoList = list(filter(lambda sourceInfo: sourceInfo.filename not in self.IGNORE_FILES, sourceZip.infolist()))
destinationInfoList = list(filter(lambda destinationInfo: destinationInfo.filename not in self.IGNORE_FILES, destinationZip.infolist()))
if len(sourceInfoList) != len(destinationInfoList):
print("APK info lists of different length!")
return False
for sourceEntryInfo in sourceInfoList:
for destinationEntryInfo in list(destinationInfoList):
if sourceEntryInfo.filename == destinationEntryInfo.filename:
sourceEntry = sourceZip.open(sourceEntryInfo, 'r')
destinationEntry = destinationZip.open(destinationEntryInfo, 'r')
if not self.compareFiles(sourceEntry, destinationEntry):
print("APK entry %s does not match %s!" % (sourceEntryInfo.filename, destinationEntryInfo.filename))
return False
destinationInfoList.remove(destinationEntryInfo)
break
return True
def compareFiles(self, sourceFile, destinationFile):
sourceChunk = sourceFile.read(1024)
destinationChunk = destinationFile.read(1024)
while sourceChunk != b"" or destinationChunk != b"":
if sourceChunk != destinationChunk:
return False
sourceChunk = sourceFile.read(1024)
destinationChunk = destinationFile.read(1024)
return True
if __name__ == '__main__':
if len(sys.argv) != 3:
print("Usage: apkdiff <pathToFirstApk> <pathToSecondApk>")
sys.exit(1)
match = ApkDiff().compare(sys.argv[1], sys.argv[2])
if match:
sys.exit(0)
else:
sys.exit(1)
================================================
FILE: contrib/android/apt.preferences
================================================
Package: *
Pin: origin "snapshot.debian.org"
Pin-Priority: 1001
================================================
FILE: contrib/android/apt.sources.list
================================================
deb https://snapshot.debian.org/archive/debian/20260129T082333Z/ trixie main
deb-src https://snapshot.debian.org/archive/debian/20260129T082333Z/ trixie main
================================================
FILE: contrib/android/bitcoin_intent.xml
================================================
<intent-filter >
<action android:name="android.intent.action.VIEW" />
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="bitcoin" />
<data android:scheme="lightning" />
</intent-filter>
================================================
FILE: contrib/android/build.sh
================================================
#!/bin/bash
#
# env vars:
# - ELECBUILD_NOCACHE: if set, forces rebuild of docker image
# - ELECBUILD_COMMIT: if set, do a fresh clone and git checkout
set -e
PROJECT_ROOT="$(dirname "$(readlink -e "$0")")/../.."
PROJECT_ROOT_OR_FRESHCLONE_ROOT="$PROJECT_ROOT"
CONTRIB="$PROJECT_ROOT/contrib"
CONTRIB_ANDROID="$CONTRIB/android"
DISTDIR="$PROJECT_ROOT/dist"
BUILD_UID=$(/usr/bin/stat -c %u "$PROJECT_ROOT")
. "$CONTRIB"/build_tools_util.sh
# check arguments
if [[ -n "$3" \
&& ( "$1" == "qml" ) \
&& ( "$2" == "all" || "$2" == "armeabi-v7a" || "$2" == "arm64-v8a" || "$2" == "x86" || "$2" == "x86_64" ) \
&& ( "$3" == "debug" || "$3" == "release" || "$3" == "release-unsigned" ) ]] ; then
info "arguments $1 $2 $3"
else
fail "usage: build.sh <qml|...> <arm64-v8a|armeabi-v7a|x86|x86_64|all> <debug|release|release-unsigned>"
exit 1
fi
# create symlink
rm -f ${PROJECT_ROOT}/.buildozer
mkdir -p "${PROJECT_ROOT}/.buildozer_$1"
ln -s ".buildozer_$1" ${PROJECT_ROOT}/.buildozer
DOCKER_BUILD_FLAGS=""
if [ ! -z "$ELECBUILD_NOCACHE" ] ; then
info "ELECBUILD_NOCACHE is set. forcing rebuild of docker image."
DOCKER_BUILD_FLAGS="--pull --no-cache"
fi
if [ -z "$ELECBUILD_COMMIT" ] ; then # local dev build
DOCKER_BUILD_FLAGS="$DOCKER_BUILD_FLAGS --build-arg UID=$BUILD_UID"
fi
info "building docker image."
docker build \
$DOCKER_BUILD_FLAGS \
-t electrum-android-builder-img \
--file "$CONTRIB_ANDROID/Dockerfile" \
"$PROJECT_ROOT"
# maybe do fresh clone
if [ ! -z "$ELECBUILD_COMMIT" ] ; then
info "ELECBUILD_COMMIT=$ELECBUILD_COMMIT. doing fresh clone and git checkout."
FRESH_CLONE=${FRESH_CLONE:-"/tmp/electrum_build/android/fresh_clone/electrum"}
rm -rf "$FRESH_CLONE" 2>/dev/null || ( info "we need sudo to rm prev FRESH_CLONE." && sudo rm -rf "$FRESH_CLONE" )
umask 0022
git clone "$PROJECT_ROOT" "$FRESH_CLONE"
cd "$FRESH_CLONE"
git checkout "$ELECBUILD_COMMIT"
PROJECT_ROOT_OR_FRESHCLONE_ROOT="$FRESH_CLONE"
else
info "not doing fresh clone."
fi
DOCKER_RUN_FLAGS=""
if [[ "$3" == "release" ]] ; then
info "'release' mode selected. mounting ~/.keystore inside container."
DOCKER_RUN_FLAGS="-v $HOME/.keystore:/home/user/.keystore"
fi
if sh -c ": >/dev/tty" >/dev/null 2>/dev/null; then
info "/dev/tty is available and usable"
DOCKER_RUN_FLAGS="$DOCKER_RUN_FLAGS -it"
fi
info "building binary..."
mkdir --parents "$PROJECT_ROOT_OR_FRESHCLONE_ROOT"/.buildozer/.gradle
# check uid and maybe chown. see #8261
if [ ! -z "$ELECBUILD_COMMIT" ] ; then # fresh clone (reproducible build)
if [ $(id -u) != "1000" ] || [ $(id -g) != "1000" ] ; then
info "need to chown -R FRESH_CLONE dir. prompting for sudo."
sudo chown -R 1000:1000 "$FRESH_CLONE"
fi
fi
docker run --rm \
--name electrum-android-builder-cont \
-v "$PROJECT_ROOT_OR_FRESHCLONE_ROOT":/home/user/wspace/electrum \
-v "$PROJECT_ROOT_OR_FRESHCLONE_ROOT"/.buildozer/.gradle:/home/user/.gradle \
$DOCKER_RUN_FLAGS \
--workdir /home/user/wspace/electrum \
electrum-android-builder-img \
./contrib/android/make_apk.sh "$@"
# make sure resulting binary location is independent of fresh_clone
if [ ! -z "$ELECBUILD_COMMIT" ] ; then
mkdir --parents "$DISTDIR/"
cp -f "$FRESH_CLONE/dist"/* "$DISTDIR/"
fi
================================================
FILE: contrib/android/buildozer_qml.spec
================================================
[app]
# (str) Title of your application
title = Electrum
# (str) Package name
package.name = Electrum
# (str) Package domain (needed for android/ios packaging)
package.domain = org.electrum
# (str) Source code where the main.py live
source.dir = .
# (list) Source files to include (let empty to include all the files)
source.include_exts = py,png,jpg,qml,qmltypes,ttf,txt,gif,pem,mo,json,csv,so,svg
# (list) Source files to exclude (let empty to not exclude anything)
source.exclude_exts = spec
# (list) List of directory to exclude (let empty to not exclude anything)
source.exclude_dirs =
bin,
build,
dist,
contrib,
env,
tests,
fastlane,
electrum/www,
electrum/scripts,
electrum/utils,
electrum/gui/qt,
electrum/plugins/audio_modem,
electrum/plugins/bitbox02,
electrum/plugins/coldcard,
electrum/plugins/digitalbitbox,
electrum/plugins/jade,
electrum/plugins/keepkey,
electrum/plugins/ledger,
electrum/plugins/nwc,
electrum/plugins/payserver,
electrum/plugins/revealer,
electrum/plugins/safe_t,
electrum/plugins/swapserver,
electrum/plugins/timelock_recovery,
electrum/plugins/trezor,
electrum/plugins/watchtower,
packages/qdarkstyle,
packages/qtpy,
packages/bin,
packages/share,
packages/pkg_resources,
packages/setuptools
# (list) List of exclusions using pattern matching
source.exclude_patterns = Makefile,setup*,
# not reproducible:
packages/aiohttp-*.dist-info/*,
packages/frozenlist-*.dist-info/*
# (str) Application versioning (method 1)
version.regex = ELECTRUM_VERSION = '(.*)'
version.filename = %(source.dir)s/electrum/version.py
# (str) Application versioning (method 2)
#version = 1.9.8
# (list) Application requirements
# note: versions and hashes are pinned in ./p4a_recipes/*
requirements =
hostpython3,
python3,
android,
openssl,
plyer,
libffi,
libsecp256k1,
pycryptodomex,
pyqt6sip,
pyqt6,
libzbar
# (str) Presplash of the application
presplash.filename = %(source.dir)s/electrum/gui/icons/electrum_presplash.png
# (str) Icon of the application
icon.filename = %(source.dir)s/electrum/gui/icons/android_electrum_icon_legacy.png
icon.adaptive_foreground.filename = %(source.dir)s/electrum/gui/icons/android_electrum_icon_foreground.png
icon.adaptive_background.filename = %(source.dir)s/electrum/gui/icons/android_electrum_icon_background.png
# (str) Supported orientation (one of landscape, portrait or all)
orientation = portrait
# (bool) Indicate if the application should be fullscreen or not
fullscreen = False
#
# Android specific
#
# (list) Permissions
android.permissions = INTERNET, CAMERA, WRITE_EXTERNAL_STORAGE, POST_NOTIFICATIONS, USE_BIOMETRIC
# (int) Android API to use (compileSdkVersion)
# note: when changing, Dockerfile also needs to be changed to install corresponding build tools
android.api = 31
# (int) Android targetSdkVersion
android.target_sdk_version = 35
# (int) Minimum API required. You will need to set the android.ndk_api to be as low as this value.
android.minapi = 23
# (str) Android NDK version to use
android.ndk = 23b
# (int) Android NDK API to use (optional). This is the minimum API your app will support.
android.ndk_api = 23
# (bool) Use --private data storage (True) or --dir public storage (False)
#android.private_storage = True
# (str) Android NDK directory (if empty, it will be automatically downloaded.)
android.ndk_path = /opt/android/android-ndk
# (str) Android SDK directory (if empty, it will be automatically downloaded.)
android.sdk_path = /opt/android/android-sdk
# (str) ANT directory (if empty, it will be automatically downloaded.)
android.ant_path = /opt/android/apache-ant
# (bool) If True, then skip trying to update the Android sdk
# This can be useful to avoid excess Internet downloads or save time
# when an update is due and you just want to test/build your package
# note(ghost43): probably needed for reproducibility. versions pinned in Dockerfile.
android.skip_update = True
# (bool) If True, then automatically accept SDK license
# agreements. This is intended for automation only. If set to False,
# the default, you will be shown the license when first running
# buildozer.
android.accept_sdk_license = True
# (str) Android entry point, default is ok for Kivy-based app
#android.entrypoint = org.renpy.android.PythonActivity
# (list) List of Java .jar files to add to the libs so that pyjnius can access
# their classes. Don't add jars that you do not need, since extra jars can slow
# down the build process. Allows wildcards matching, for example:
# OUYA-ODK/libs/*.jar
#android.add_jars = foo.jar,bar.jar,path/to/more/*.jar
#android.add_jars = lib/android/zbar.jar
android.add_jars = .buildozer/android/platform/*/build/libs_collections/Electrum/jar/*.jar
android.add_aars =
contrib/android/.cache/aars/BarcodeScannerView.aar,
contrib/android/.cache/aars/CameraView.aar,
contrib/android/.cache/aars/zxing-cpp.aar
# (list) List of Java files to add to the android project (can be java or a
# directory containing the files)
android.add_src = electrum/gui/qml/java_classes/
# kotlin-stdlib is required for zxing-cpp (BarcodeScannerView)
android.gradle_dependencies =
com.android.support:support-compat:28.0.0,
org.jetbrains.kotlin:kotlin-stdlib:1.8.22
android.add_activities = org.electrum.qr.SimpleScannerActivity, org.electrum.biometry.BiometricActivity
# (list) Put these files or directories in the apk res directory.
# The option may be used in three ways, the value may contain one or zero ':'
# Some examples:
# 1) A file to add to resources, legal resource names contain ['a-z','0-9','_']
# android.add_resources = my_icons/all-inclusive.png:drawable/all_inclusive.png
# 2) A directory, here 'legal_icons' must contain resources of one kind
# android.add_resources = legal_icons:drawable
# 3) A directory, here 'legal_resources' must contain one or more directories,
# each of a resource kind: drawable, xml, etc...
# android.add_resources = legal_resources
android.add_resources = electrum/gui/qml/android_res/layout:layout
# (str) python-for-android branch to use, if not master, useful to try
# not yet merged features.
#android.branch = master
# (str) OUYA Console category. Should be one of GAME or APP
# If you leave this blank, OUYA support will not be enabled
#android.ouya.category = GAME
# (str) Filename of OUYA Console icon. It must be a 732x412 png image.
#android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png
# (str) XML file to include as an intent filters in <activity> tag
android.manifest.intent_filters = contrib/android/bitcoin_intent.xml
# (str) launchMode to set for the main activity
android.manifest.launch_mode = singleTask
# (list) Android additional libraries to copy into libs/armeabi
#android.add_libs_armeabi = lib/android/*.so
# (bool) Indicate whether the screen should stay on
# Don't forget to add the WAKE_LOCK permission if you set this to True
#android.wakelock = False
# (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64
# note: can be overwritten by APP_ANDROID_ARCH env var
#android.arch = armeabi-v7a
# (int) overrides automatic versionCode computation (used in build.gradle)
# this is not the same as app version and should only be edited if you know what you're doing
# android.numeric_version = 1
# (list) Android application meta-data to set (key=value format)
#android.meta_data =
# (list) Android library project to add (will be added in the
# project.properties automatically.)
#android.library_references =
android.whitelist = lib-dynload/_csv.so
# (bool) enables Android auto backup feature (Android API >=23)
android.allow_backup = False
# (str) The format used to package the app for release mode (aab or apk or aar).
android.release_artifact = apk
# (str) The format used to package the app for debug mode (apk or aar).
android.debug_artifact = apk
#
# Python for android (p4a) specific
#
# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
p4a.source_dir = /opt/python-for-android
# (str) The directory in which python-for-android should look for your own build recipes (if any)
p4a.local_recipes = %(source.dir)s/contrib/android/p4a_recipes/
# (str) Filename to the hook for p4a
#p4a.hook =
# (str) Bootstrap to use for android builds
p4a.bootstrap = qt6
# (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask)
#p4a.port =
#
# iOS specific
#
# (str) Name of the certificate to use for signing the debug version
# Get a list of available identities: buildozer ios list_identities
#ios.codesign.debug = "iPhone Developer: <lastname> <firstname> (<hexstring>)"
# (str) Name of the certificate to use for signing the release version
#ios.codesign.release = %(ios.codesign.debug)s
[buildozer]
# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
log_level = 2
# (str) Path to build output (i.e. .apk, .ipa) storage
bin_dir = ./dist
# -----------------------------------------------------------------------------
# List as sections
#
# You can define all the "list" as [section:key].
# Each line will be considered as a option to the list.
# Let's take [app] / source.exclude_patterns.
# Instead of doing:
#
# [app]
# source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
#
# This can be translated into:
#
# [app:source.exclude_patterns]
# license
# data/audio/*.wav
# data/images/original/*
#
# -----------------------------------------------------------------------------
# Profiles
#
# You can extend section / key with a profile
# For example, you want to deploy a demo version of your application without
# HD content. You could first change the title to add "(demo)" in the name
# and extend the excluded directories to remove the HD content.
#
# [app@demo]
# title = My Application (demo)
#
# [app:source.exclude_patterns@demo]
# images/hd/*
#
# Then, invoke the command line with the "demo" profile:
#
# buildozer --profile demo android debug
================================================
FILE: contrib/android/dl-ndk-ci.sh
================================================
#!/bin/sh
if [ -z "$1" ]; then
echo "missing url"
exit 1
fi
echo $1
curl $1 | grep "var JSVariables" | python3 -c "import sys; line=sys.stdin.read(); line=line[line.find('{'):-2]; import json; j=json.loads(line); print(j['artifactUrl'])" | wget -i - -O android-ndk-ci-linux-x86_64.zip
================================================
FILE: contrib/android/get_apk_versioncode.py
================================================
#!/usr/bin/python3
import importlib.util
import os
import sys
ARCH_DICT = {
"x86_64": "4",
"arm64-v8a": "3",
"armeabi-v7a": "2",
"x86": "1",
"null": "0",
}
def get_electrum_version() -> str:
project_root = os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
version_file_path = os.path.join(project_root, "electrum", "version.py")
# load version.py; needlessly complicated alternative to "imp.load_source":
version_spec = importlib.util.spec_from_file_location('version', version_file_path)
version_module = version = importlib.util.module_from_spec(version_spec)
version_spec.loader.exec_module(version_module)
return version.ELECTRUM_VERSION
def get_android_versioncode(*, arch_name: str) -> int:
version_code = 0
# add ELECTRUM_VERSION
app_version = get_electrum_version()
# if alpha/beta, and not stable: strip out alpha/beta part from last component.
# NOTE: we REUSE the version_code int between alphas/betas and the final stable.
# This is not allowed on Google Play or F-Droid.
# This means we MUST NOT upload alphas/betas there.
if any(c in app_version for c in ("a", "b")):
c_pos = app_version.find("a")
if c_pos == -1:
c_pos = app_version.find("b")
app_version = app_version[:c_pos]
# now the app_version str must contain exactly three dot-delimited components
app_version_components = app_version.split('.')
assert len(app_version_components) == 3, f"version str expected to have 3 components, but got {app_version!r}"
# convert to int
for i in app_version_components:
version_code *= 100
version_code += int(i)
# add arch
arch_code = ARCH_DICT[arch_name]
assert len(arch_code) == 1
version_code *= 10
version_code += int(arch_code)
# compensate for legacy scheme
# note: up until version 4.5.5, we used a different scheme for version_code.
# 4_______________4_05_05_00
# ^ android arch, ^ app_version (4.5.5.0)
# This offset ensures that all new-scheme version codes are larger than the old-scheme version codes.
offset_due_to_legacy_scheme = 45_000_000
version_code += offset_due_to_legacy_scheme
return version_code
if __name__ == '__main__':
try:
android_arch = sys.argv[1]
except Exception:
print(f"usage: {os.path.basename(__file__)} <android_arch>", file=sys.stderr)
sys.exit(1)
if android_arch not in ARCH_DICT:
print(f"usage: {os.path.basename(__file__)} <android_arch>", file=sys.stderr)
print(f"error: unknown {android_arch=}", file=sys.stderr)
print(f" should be one of: {list(ARCH_DICT.keys())}", file=sys.stderr)
sys.exit(1)
version_code = get_android_versioncode(arch_name=android_arch)
assert isinstance(version_code, int), f"{version_code=!r} must be an int."
print(version_code, file=sys.stdout)
================================================
FILE: contrib/android/make_apk.sh
================================================
#!/bin/bash
set -e
CONTRIB_ANDROID="$(dirname "$(readlink -e "$0")")"
CONTRIB="$CONTRIB_ANDROID"/..
PROJECT_ROOT="$CONTRIB"/..
PACKAGES="$PROJECT_ROOT"/packages/
. "$CONTRIB"/build_tools_util.sh
git -C "$PROJECT_ROOT" rev-parse 2>/dev/null || fail "Building outside a git clone is not supported."
# arguments have been checked in build.sh
export ELEC_APK_GUI=$1
if [ ! -d "$PACKAGES" ]; then
"$CONTRIB"/make_packages.sh || fail "make_packages failed"
fi
# update locale
info "preparing electrum-locale."
(
"$CONTRIB/locale/build_cleanlocale.sh"
# we want the binary to have only compiled (.mo) locale files; not source (.po) files
rm -r "$PROJECT_ROOT/electrum/locale/locale"/*/electrum.po
)
pushd "$CONTRIB_ANDROID"
info "apk building phase starts."
# Uncomment and change below to set a custom android package id,
# e.g. to allow simultaneous mainnet and testnet installs of the apk.
# defaults:
# export APP_PACKAGE_NAME=Electrum
# export APP_PACKAGE_DOMAIN=org.electrum
# FIXME: changing "APP_PACKAGE_NAME" seems to require a clean rebuild of ".buildozer/",
# to avoid that, maybe change "APP_PACKAGE_DOMAIN" instead.
# So, in particular, to build a testnet apk, simply uncomment:
#export APP_PACKAGE_DOMAIN=org.electrum.testnet
if [ $CI ]; then
# override log level specified in buildozer.spec to "debug":
export BUILDOZER_LOG_LEVEL=2
fi
if [[ "$3" == "release" ]] ; then
# do release build, and sign the APKs.
TARGET="release"
export P4A_RELEASE_KEYSTORE_PASSWD="$4"
export P4A_RELEASE_KEYALIAS_PASSWD="$4"
export P4A_RELEASE_KEYSTORE=~/.keystore
export P4A_RELEASE_KEYALIAS=electrum
if [ -z "$P4A_RELEASE_KEYSTORE_PASSWD" ] || [ -z "$P4A_RELEASE_KEYALIAS_PASSWD" ]; then
echo "p4a password not defined"
exit 1
fi
elif [[ "$3" == "release-unsigned" ]] ; then
# do release build, but do not sign the APKs.
TARGET="release"
elif [[ "$3" == "debug" ]] ; then
# do debug build.
TARGET="apk"
export P4A_DEBUG_KEYSTORE="$CONTRIB_ANDROID"/android_debug.keystore
export P4A_DEBUG_KEYSTORE_PASSWD=unsafepassword
export P4A_DEBUG_KEYALIAS_PASSWD=unsafepassword
export P4A_DEBUG_KEYALIAS=electrum
# create keystore if needed
if [ ! -f "$P4A_DEBUG_KEYSTORE" ]; then
keytool -genkey -v -keystore "$CONTRIB_ANDROID"/android_debug.keystore \
-alias "$P4A_DEBUG_KEYALIAS" -keyalg RSA -keysize 2048 -validity 10000 \
-dname "CN=mqttserver.ibm.com, OU=ID, O=IBM, L=Hursley, S=Hants, C=GB" \
-storepass "$P4A_DEBUG_KEYSTORE_PASSWD" \
-keypass "$P4A_DEBUG_KEYALIAS_PASSWD"
fi
export ELEC_APK_USE_CURRENT_TIME=1
else
fail "unknown build type"
fi
if [[ "$2" == "all" ]] ; then
# build all apks
# FIXME failures are not propagated out: we should fail the script if any arch build fails
export APP_ANDROID_ARCHS=armeabi-v7a
export APP_ANDROID_NUMERIC_VERSION=$("$CONTRIB_ANDROID"/get_apk_versioncode.py "$APP_ANDROID_ARCHS")
"$CONTRIB_ANDROID"/make_barcode_scanner.sh "$APP_ANDROID_ARCHS" || fail "make_barcode_scanner.sh failed"
make $TARGET
export APP_ANDROID_ARCHS=arm64-v8a
export APP_ANDROID_NUMERIC_VERSION=$("$CONTRIB_ANDROID"/get_apk_versioncode.py "$APP_ANDROID_ARCHS")
"$CONTRIB_ANDROID"/make_barcode_scanner.sh "$APP_ANDROID_ARCHS" || fail "make_barcode_scanner.sh failed"
make $TARGET
export APP_ANDROID_ARCHS=x86_64
export APP_ANDROID_NUMERIC_VERSION=$("$CONTRIB_ANDROID"/get_apk_versioncode.py "$APP_ANDROID_ARCHS")
"$CONTRIB_ANDROID"/make_barcode_scanner.sh "$APP_ANDROID_ARCHS" || fail "make_barcode_scanner.sh failed"
make $TARGET
else
export APP_ANDROID_ARCHS=$2
export APP_ANDROID_NUMERIC_VERSION=$("$CONTRIB_ANDROID"/get_apk_versioncode.py "$APP_ANDROID_ARCHS")
"$CONTRIB_ANDROID"/make_barcode_scanner.sh "$APP_ANDROID_ARCHS" || fail "make_barcode_scanner.sh failed"
make $TARGET
fi
popd
info "done."
ls -la "$PROJECT_ROOT/dist"
sha256sum "$PROJECT_ROOT/dist"/*
================================================
FILE: contrib/android/make_barcode_scanner.sh
================================================
#!/bin/bash
# script to clone and build https://github.com/markusfisch/BarcodeScannerView and its dependencies,
# https://github.com/markusfisch/CameraView/ and https://github.com/markusfisch/zxing-cpp
# which are being used as barcode scanner in the Android app.
# To bump the version of BarcodeScannerView, get the newest version tag from the github repo,
# then get the required dependencies from
# https://github.com/markusfisch/BarcodeScannerView/blob/**VERSION_TAG**/barcodescannerview/build.gradle
# then update the commit hashes below. Also update kotlin-stdlib in buildozer_qml.spec to the
# "kotlin-version" specified in the used zxing-cpp commit:
# https://github.com/markusfisch/zxing-cpp/blob/master/wrappers/aar/build.gradle
BARCODE_SCANNER_VIEW_COMMIT_HASH="0bdb69269c252bb6daef2f871b76403c8b051945" # 1.6.5
BARCODE_SCANNER_VIEW_REPO="https://github.com/markusfisch/BarcodeScannerView.git"
CAMERA_VIEW_COMMIT_HASH="745597d05bc6abfdb3637a09a8ecaf30fdce7b6e" # 1.10.0
CAMERA_VIEW_REPO="https://github.com/markusfisch/CameraView.git"
ZXING_CPP_COMMIT_HASH="79f5adc6250e90de0bd635eb9181c5f8a18affda" # v2.3.0.4 using kotlin-stdlib 1.8.22
ZXING_CPP_REPO="https://github.com/markusfisch/zxing-cpp.git"
########################################################################################################
set -e
CONTRIB_ANDROID="$(dirname "$(readlink -e "$0")")"
CONTRIB="$CONTRIB_ANDROID"/..
CACHEDIR="$CONTRIB_ANDROID/.cache"
BUILDDIR="$CACHEDIR/builds"
. "$CONTRIB"/build_tools_util.sh
# target architecture passed as argument by`make_apk.sh`
TARGET_ARCH="$1"
# check if TARGET_ARCH is set and supported
if [[ "$TARGET_ARCH" != "armeabi-v7a" \
&& "$TARGET_ARCH" != "arm64-v8a" \
&& "$TARGET_ARCH" != "x86_64" ]]; then
fail "make_barcode_scanner.sh invalid target architecture argument: $TARGET_ARCH"
fi
info "Building BarcodeScannerView and deps for architecture: $TARGET_ARCH"
# check if directories exist, create them if not
if [ ! -d "$CACHEDIR/aars" ]; then
mkdir -p "$CACHEDIR/aars"
fi
if [ ! -d "$BUILDDIR" ]; then
mkdir -p "$BUILDDIR"
fi
####### zxing-cpp ########
# check if zxing-cpp aar is already in cachedir, else build it
ZXING_CPP_BUILD_ID="$TARGET_ARCH-$ZXING_CPP_COMMIT_HASH"
if [ -f "$CACHEDIR/aars/zxing-cpp-$ZXING_CPP_BUILD_ID.aar" ]; then
info "zxing-cpp for $ZXING_CPP_BUILD_ID already exists in cache, skipping build."
cp "$CACHEDIR/aars/zxing-cpp-$ZXING_CPP_BUILD_ID.aar" "$CACHEDIR/aars/zxing-cpp.aar"
else
info "Building zxing-cpp for $ZXING_CPP_BUILD_ID..."
ZXING_CPP_DIR="$BUILDDIR/zxing-cpp"
clone_or_update_repo "$ZXING_CPP_REPO" "$ZXING_CPP_COMMIT_HASH" "$ZXING_CPP_DIR"
cd "$ZXING_CPP_DIR/wrappers/aar"
gitextract_3c6jsf9o/
├── .cirrus.yml
├── .editorconfig
├── .gitattributes
├── .github/
│ └── ISSUE_TEMPLATE/
│ ├── 01_issue.yml
│ └── config.yml
├── .gitignore
├── .gitmodules
├── AUTHORS
├── LICENCE
├── MANIFEST.in
├── README.md
├── RELEASE-NOTES
├── SECURITY.md
├── contrib/
│ ├── add_cosigner
│ ├── android/
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ ├── Readme.md
│ │ ├── apkdiff.py
│ │ ├── apt.preferences
│ │ ├── apt.sources.list
│ │ ├── bitcoin_intent.xml
│ │ ├── build.sh
│ │ ├── buildozer_qml.spec
│ │ ├── dl-ndk-ci.sh
│ │ ├── get_apk_versioncode.py
│ │ ├── make_apk.sh
│ │ ├── make_barcode_scanner.sh
│ │ └── p4a_recipes/
│ │ ├── README.md
│ │ ├── cffi/
│ │ │ └── __init__.py
│ │ ├── cryptography/
│ │ │ └── __init__.py
│ │ ├── hostpython3/
│ │ │ └── __init__.py
│ │ ├── libffi/
│ │ │ └── __init__.py
│ │ ├── libiconv/
│ │ │ └── __init__.py
│ │ ├── libsecp256k1/
│ │ │ └── __init__.py
│ │ ├── libzbar/
│ │ │ └── __init__.py
│ │ ├── openssl/
│ │ │ └── __init__.py
│ │ ├── packaging/
│ │ │ └── __init__.py
│ │ ├── ply/
│ │ │ └── __init__.py
│ │ ├── plyer/
│ │ │ └── __init__.py
│ │ ├── pycparser/
│ │ │ └── __init__.py
│ │ ├── pycryptodomex/
│ │ │ └── __init__.py
│ │ ├── pyjnius/
│ │ │ └── __init__.py
│ │ ├── pyparsing/
│ │ │ └── __init__.py
│ │ ├── pyqt6/
│ │ │ └── __init__.py
│ │ ├── pyqt6sip/
│ │ │ └── __init__.py
│ │ ├── pyqt_builder/
│ │ │ └── __init__.py
│ │ ├── python3/
│ │ │ └── __init__.py
│ │ ├── qt6/
│ │ │ └── __init__.py
│ │ ├── setuptools/
│ │ │ └── __init__.py
│ │ ├── sip/
│ │ │ └── __init__.py
│ │ ├── six/
│ │ │ └── __init__.py
│ │ ├── sqlite3/
│ │ │ └── __init__.py
│ │ ├── toml/
│ │ │ └── __init__.py
│ │ ├── tomli/
│ │ │ └── __init__.py
│ │ └── util.py
│ ├── apparmor/
│ │ ├── README.md
│ │ └── apparmor.d/
│ │ ├── abstractions/
│ │ │ └── electrum
│ │ ├── electrum.appimage
│ │ └── usr.local.bin.electrum
│ ├── ban_unicode.py
│ ├── build-linux/
│ │ ├── appimage/
│ │ │ ├── .dockerignore
│ │ │ ├── Dockerfile
│ │ │ ├── README.md
│ │ │ ├── apprun.sh
│ │ │ ├── apt.preferences
│ │ │ ├── apt.sources.list
│ │ │ ├── build.sh
│ │ │ ├── make_appimage.sh
│ │ │ ├── make_type2_runtime.sh
│ │ │ └── patches/
│ │ │ ├── python-3.11-reproducible-buildinfo.diff
│ │ │ └── type2-runtime-reproducible-build.patch
│ │ └── sdist/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── build.sh
│ │ └── make_sdist.sh
│ ├── build-wine/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── README_windows.md
│ │ ├── apt.preferences
│ │ ├── apt.sources.list
│ │ ├── build-electrum-git.sh
│ │ ├── build.sh
│ │ ├── electrum.nsi
│ │ ├── gpg_keys/
│ │ │ └── 7ED10B6531D7C8E1BC296021FC624643487034E5.asc
│ │ ├── make_win.sh
│ │ ├── patches/
│ │ │ └── libiconv-fix-pointer-buf.patch
│ │ ├── prepare-wine.sh
│ │ ├── pyinstaller.spec
│ │ ├── sign.sh
│ │ └── unsign.sh
│ ├── build_tools_util.sh
│ ├── deterministic-build/
│ │ ├── README.md
│ │ ├── check_submodules.sh
│ │ ├── find_restricted_dependencies.py
│ │ ├── requirements-binaries-mac.txt
│ │ ├── requirements-binaries.txt
│ │ ├── requirements-build-android.txt
│ │ ├── requirements-build-appimage.txt
│ │ ├── requirements-build-base.txt
│ │ ├── requirements-build-mac.txt
│ │ ├── requirements-build-wine.txt
│ │ ├── requirements-hw.txt
│ │ └── requirements.txt
│ ├── docker_notes.md
│ ├── freeze_containers_distro.sh
│ ├── freeze_packages.sh
│ ├── generate_payreqpb2.sh
│ ├── locale/
│ │ ├── build_cleanlocale.sh
│ │ ├── build_locale.sh
│ │ ├── push_locale.py
│ │ └── stats.py
│ ├── make_download
│ ├── make_libsecp256k1.sh
│ ├── make_libusb.sh
│ ├── make_packages.sh
│ ├── make_plugin
│ ├── make_zbar.sh
│ ├── osx/
│ │ ├── README.md
│ │ ├── README_macos.md
│ │ ├── apply_sigs.sh
│ │ ├── cdrkit-deterministic.patch
│ │ ├── compare_dmg
│ │ ├── entitlements.plist
│ │ ├── extract_sigs.sh
│ │ ├── make_osx.sh
│ │ ├── notarize_app.sh
│ │ ├── package.sh
│ │ ├── pyinstaller.spec
│ │ └── sign_osx.sh
│ ├── print_electrum_version.py
│ ├── release.sh
│ ├── release_www.sh
│ ├── requirements/
│ │ ├── requirements-binaries-mac.txt
│ │ ├── requirements-binaries.txt
│ │ ├── requirements-build-android.txt
│ │ ├── requirements-build-appimage.txt
│ │ ├── requirements-build-base.txt
│ │ ├── requirements-build-mac.txt
│ │ ├── requirements-build-wine.txt
│ │ ├── requirements-ci.txt
│ │ ├── requirements-hw.txt
│ │ └── requirements.txt
│ ├── sign_packages
│ ├── trigger_deploy.sh
│ ├── udev/
│ │ ├── 20-hw1.rules
│ │ ├── 51-coinkite.rules
│ │ ├── 51-hid-digitalbitbox.rules
│ │ ├── 51-safe-t.rules
│ │ ├── 51-trezor.rules
│ │ ├── 51-usb-keepkey.rules
│ │ ├── 52-hid-digitalbitbox.rules
│ │ ├── 53-hid-bitbox02.rules
│ │ ├── 54-hid-bitbox02.rules
│ │ ├── 55-usb-jade.rules
│ │ └── README.md
│ └── upload.sh
├── electrum/
│ ├── __init__.py
│ ├── _vendor/
│ │ ├── __init__.py
│ │ ├── distutils/
│ │ │ ├── LICENSE
│ │ │ ├── __init__.py
│ │ │ └── version.py
│ │ └── pyperclip/
│ │ ├── LICENSE.txt
│ │ ├── README.md
│ │ └── __init__.py
│ ├── address_synchronizer.py
│ ├── base_crash_reporter.py
│ ├── bip21.py
│ ├── bip32.py
│ ├── bip39_recovery.py
│ ├── bip39_wallet_formats.json
│ ├── bitcoin.py
│ ├── blockchain.py
│ ├── chains/
│ │ ├── mainnet/
│ │ │ ├── checkpoints.json
│ │ │ ├── fallback_lnnodes.json
│ │ │ └── servers.json
│ │ ├── mutinynet/
│ │ │ ├── fallback_lnnodes.json
│ │ │ └── servers.json
│ │ ├── regtest/
│ │ │ └── servers.json
│ │ ├── signet/
│ │ │ ├── checkpoints.json
│ │ │ ├── fallback_lnnodes.json
│ │ │ └── servers.json
│ │ ├── testnet/
│ │ │ ├── checkpoints.json
│ │ │ ├── fallback_lnnodes.json
│ │ │ └── servers.json
│ │ └── testnet4/
│ │ ├── checkpoints.json
│ │ └── servers.json
│ ├── channel_db.py
│ ├── coinchooser.py
│ ├── commands.py
│ ├── constants.py
│ ├── contacts.py
│ ├── crypto.py
│ ├── currencies.json
│ ├── daemon.py
│ ├── descriptor.py
│ ├── dns_hacks.py
│ ├── dnssec.py
│ ├── exchange_rate.py
│ ├── fee_policy.py
│ ├── gui/
│ │ ├── __init__.py
│ │ ├── common_qt/
│ │ │ ├── __init__.py
│ │ │ ├── i18n.py
│ │ │ ├── plugins.py
│ │ │ └── util.py
│ │ ├── default_lang.py
│ │ ├── fonts/
│ │ │ └── PTMono.LICENSE
│ │ ├── icons/
│ │ │ ├── clock5.pdn
│ │ │ └── electrum.icns
│ │ ├── messages.py
│ │ ├── qml/
│ │ │ ├── __init__.py
│ │ │ ├── android_res/
│ │ │ │ └── layout/
│ │ │ │ └── scanner_layout.xml
│ │ │ ├── auth.py
│ │ │ ├── components/
│ │ │ │ ├── About.qml
│ │ │ │ ├── AddressDetails.qml
│ │ │ │ ├── Addresses.qml
│ │ │ │ ├── BIP39RecoveryDialog.qml
│ │ │ │ ├── BalanceDetails.qml
│ │ │ │ ├── ChannelDetails.qml
│ │ │ │ ├── ChannelOpenProgressDialog.qml
│ │ │ │ ├── Channels.qml
│ │ │ │ ├── CloseChannelDialog.qml
│ │ │ │ ├── ConfirmTxDialog.qml
│ │ │ │ ├── Constants.qml
│ │ │ │ ├── CpfpBumpFeeDialog.qml
│ │ │ │ ├── ExceptionDialog.qml
│ │ │ │ ├── ExportTxDialog.qml
│ │ │ │ ├── GenericShareDialog.qml
│ │ │ │ ├── History.qml
│ │ │ │ ├── ImportAddressesKeysDialog.qml
│ │ │ │ ├── ImportChannelBackupDialog.qml
│ │ │ │ ├── InvoiceDialog.qml
│ │ │ │ ├── Invoices.qml
│ │ │ │ ├── LightningPaymentDetails.qml
│ │ │ │ ├── LnurlPayRequestDialog.qml
│ │ │ │ ├── LnurlWithdrawRequestDialog.qml
│ │ │ │ ├── LoadingWalletDialog.qml
│ │ │ │ ├── MessageDialog.qml
│ │ │ │ ├── NetworkOverview.qml
│ │ │ │ ├── NewWalletWizard.qml
│ │ │ │ ├── NostrConfigDialog.qml
│ │ │ │ ├── NostrSwapServersDialog.qml
│ │ │ │ ├── NotificationPopup.qml
│ │ │ │ ├── OpenChannelDialog.qml
│ │ │ │ ├── OpenWalletDialog.qml
│ │ │ │ ├── OtpDialog.qml
│ │ │ │ ├── PasswordDialog.qml
│ │ │ │ ├── Preferences.qml
│ │ │ │ ├── ProxyConfigDialog.qml
│ │ │ │ ├── RbfBumpFeeDialog.qml
│ │ │ │ ├── RbfCancelDialog.qml
│ │ │ │ ├── ReceiveDetailsDialog.qml
│ │ │ │ ├── ReceiveDialog.qml
│ │ │ │ ├── ReceiveRequests.qml
│ │ │ │ ├── ScanDialog.qml
│ │ │ │ ├── SendDialog.qml
│ │ │ │ ├── ServerConfigDialog.qml
│ │ │ │ ├── ServerConnectWizard.qml
│ │ │ │ ├── SignVerifyMessageDialog.qml
│ │ │ │ ├── SwapDialog.qml
│ │ │ │ ├── SweepDialog.qml
│ │ │ │ ├── TermsOfUseWizard.qml
│ │ │ │ ├── TxDetails.qml
│ │ │ │ ├── WalletDetails.qml
│ │ │ │ ├── WalletMainView.qml
│ │ │ │ ├── WalletSummary.qml
│ │ │ │ ├── Wallets.qml
│ │ │ │ ├── controls/
│ │ │ │ │ ├── AddressDelegate.qml
│ │ │ │ │ ├── BalanceSummary.qml
│ │ │ │ │ ├── BtcField.qml
│ │ │ │ │ ├── ButtonContainer.qml
│ │ │ │ │ ├── ChannelBar.qml
│ │ │ │ │ ├── ChannelDelegate.qml
│ │ │ │ │ ├── CoinDelegate.qml
│ │ │ │ │ ├── ElCheckBox.qml
│ │ │ │ │ ├── ElComboBox.qml
│ │ │ │ │ ├── ElDialog.qml
│ │ │ │ │ ├── ElListView.qml
│ │ │ │ │ ├── ElRadioButton.qml
│ │ │ │ │ ├── ElTextArea.qml
│ │ │ │ │ ├── FeeMethodComboBox.qml
│ │ │ │ │ ├── FeePicker.qml
│ │ │ │ │ ├── FiatField.qml
│ │ │ │ │ ├── FlatButton.qml
│ │ │ │ │ ├── FormattedAmount.qml
│ │ │ │ │ ├── Heading.qml
│ │ │ │ │ ├── HelpButton.qml
│ │ │ │ │ ├── HelpDialog.qml
│ │ │ │ │ ├── HistoryItemDelegate.qml
│ │ │ │ │ ├── InfoBanner.qml
│ │ │ │ │ ├── InfoTextArea.qml
│ │ │ │ │ ├── InvoiceDelegate.qml
│ │ │ │ │ ├── LightningNetworkStatusIndicator.qml
│ │ │ │ │ ├── OnchainNetworkStatusIndicator.qml
│ │ │ │ │ ├── PaneInsetBackground.qml
│ │ │ │ │ ├── PasswordField.qml
│ │ │ │ │ ├── PasswordStrengthIndicator.qml
│ │ │ │ │ ├── Piechart.qml
│ │ │ │ │ ├── PrefsHeading.qml
│ │ │ │ │ ├── ProxyConfig.qml
│ │ │ │ │ ├── QRImage.qml
│ │ │ │ │ ├── QRScan.qml
│ │ │ │ │ ├── RequestExpiryComboBox.qml
│ │ │ │ │ ├── SeedKeyboard.qml
│ │ │ │ │ ├── SeedKeyboardKey.qml
│ │ │ │ │ ├── SeedTextArea.qml
│ │ │ │ │ ├── ServerConfig.qml
│ │ │ │ │ ├── ServerConnectModeComboBox.qml
│ │ │ │ │ ├── ServerDelegate.qml
│ │ │ │ │ ├── Tag.qml
│ │ │ │ │ ├── TextHighlightPane.qml
│ │ │ │ │ ├── Toaster.qml
│ │ │ │ │ ├── ToggleLabel.qml
│ │ │ │ │ ├── TxInput.qml
│ │ │ │ │ └── TxOutput.qml
│ │ │ │ ├── main.qml
│ │ │ │ └── wizard/
│ │ │ │ ├── WCConfirmExt.qml
│ │ │ │ ├── WCConfirmSeed.qml
│ │ │ │ ├── WCCosignerKeystore.qml
│ │ │ │ ├── WCCreateSeed.qml
│ │ │ │ ├── WCEnterExt.qml
│ │ │ │ ├── WCHaveMasterKey.qml
│ │ │ │ ├── WCHaveSeed.qml
│ │ │ │ ├── WCImport.qml
│ │ │ │ ├── WCKeystoreType.qml
│ │ │ │ ├── WCMultisig.qml
│ │ │ │ ├── WCProxyConfig.qml
│ │ │ │ ├── WCScriptAndDerivation.qml
│ │ │ │ ├── WCServerConfig.qml
│ │ │ │ ├── WCShowMasterPubkey.qml
│ │ │ │ ├── WCTermsOfUseRequest.qml
│ │ │ │ ├── WCWalletName.qml
│ │ │ │ ├── WCWalletPassword.qml
│ │ │ │ ├── WCWalletType.qml
│ │ │ │ ├── WCWelcome.qml
│ │ │ │ ├── Wizard.qml
│ │ │ │ └── WizardComponent.qml
│ │ │ ├── java_classes/
│ │ │ │ └── org/
│ │ │ │ └── electrum/
│ │ │ │ ├── biometry/
│ │ │ │ │ ├── BiometricActivity.java
│ │ │ │ │ └── BiometricHelper.java
│ │ │ │ └── qr/
│ │ │ │ └── SimpleScannerActivity.java
│ │ │ ├── qeaddressdetails.py
│ │ │ ├── qeaddresslistmodel.py
│ │ │ ├── qeapp.py
│ │ │ ├── qebiometrics.py
│ │ │ ├── qebip39recovery.py
│ │ │ ├── qebitcoin.py
│ │ │ ├── qechanneldetails.py
│ │ │ ├── qechannellistmodel.py
│ │ │ ├── qechannelopener.py
│ │ │ ├── qeconfig.py
│ │ │ ├── qedaemon.py
│ │ │ ├── qefx.py
│ │ │ ├── qeinvoice.py
│ │ │ ├── qeinvoicelistmodel.py
│ │ │ ├── qelnpaymentdetails.py
│ │ │ ├── qemodelfilter.py
│ │ │ ├── qenetwork.py
│ │ │ ├── qepiresolver.py
│ │ │ ├── qeqr.py
│ │ │ ├── qeqrscanner.py
│ │ │ ├── qerequestdetails.py
│ │ │ ├── qeserverlistmodel.py
│ │ │ ├── qeswaphelper.py
│ │ │ ├── qetransactionlistmodel.py
│ │ │ ├── qetxdetails.py
│ │ │ ├── qetxfinalizer.py
│ │ │ ├── qetypes.py
│ │ │ ├── qewallet.py
│ │ │ ├── qewizard.py
│ │ │ └── util.py
│ │ ├── qt/
│ │ │ ├── __init__.py
│ │ │ ├── address_dialog.py
│ │ │ ├── address_list.py
│ │ │ ├── amountedit.py
│ │ │ ├── balance_dialog.py
│ │ │ ├── bip39_recovery_dialog.py
│ │ │ ├── channel_details.py
│ │ │ ├── channels_list.py
│ │ │ ├── completion_text_edit.py
│ │ │ ├── confirm_tx_dialog.py
│ │ │ ├── console.py
│ │ │ ├── contact_list.py
│ │ │ ├── custom_model.py
│ │ │ ├── exception_window.py
│ │ │ ├── fee_slider.py
│ │ │ ├── history_list.py
│ │ │ ├── invoice_list.py
│ │ │ ├── lightning_dialog.py
│ │ │ ├── lightning_tx_dialog.py
│ │ │ ├── locktimeedit.py
│ │ │ ├── main_window.py
│ │ │ ├── my_treeview.py
│ │ │ ├── network_dialog.py
│ │ │ ├── new_channel_dialog.py
│ │ │ ├── password_dialog.py
│ │ │ ├── paytoedit.py
│ │ │ ├── plugins_dialog.py
│ │ │ ├── qrcodewidget.py
│ │ │ ├── qrreader/
│ │ │ │ ├── __init__.py
│ │ │ │ └── qtmultimedia/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── camera_dialog.py
│ │ │ │ ├── crop_blur_effect.py
│ │ │ │ ├── validator.py
│ │ │ │ ├── video_overlay.py
│ │ │ │ ├── video_surface.py
│ │ │ │ └── video_widget.py
│ │ │ ├── qrtextedit.py
│ │ │ ├── qrwindow.py
│ │ │ ├── rate_limiter.py
│ │ │ ├── rbf_dialog.py
│ │ │ ├── rebalance_dialog.py
│ │ │ ├── receive_tab.py
│ │ │ ├── request_list.py
│ │ │ ├── seed_dialog.py
│ │ │ ├── send_tab.py
│ │ │ ├── settings_dialog.py
│ │ │ ├── stylesheet_patcher.py
│ │ │ ├── swap_dialog.py
│ │ │ ├── transaction_dialog.py
│ │ │ ├── update_checker.py
│ │ │ ├── util.py
│ │ │ ├── utxo_dialog.py
│ │ │ ├── utxo_list.py
│ │ │ ├── wallet_info_dialog.py
│ │ │ └── wizard/
│ │ │ ├── __init__.py
│ │ │ ├── server_connect.py
│ │ │ ├── terms_of_use.py
│ │ │ ├── wallet.py
│ │ │ └── wizard.py
│ │ ├── stdio.py
│ │ └── text.py
│ ├── harden_memory_linux.py
│ ├── hw_wallet/
│ │ ├── __init__.py
│ │ ├── cmdline.py
│ │ ├── plugin.py
│ │ ├── qt.py
│ │ └── trezor_qt_pinmatrix.py
│ ├── i18n.py
│ ├── interface.py
│ ├── invoices.py
│ ├── json_db.py
│ ├── keystore.py
│ ├── lnaddr.py
│ ├── lnchannel.py
│ ├── lnhtlc.py
│ ├── lnmsg.py
│ ├── lnonion.py
│ ├── lnpeer.py
│ ├── lnrater.py
│ ├── lnrouter.py
│ ├── lnsweep.py
│ ├── lntransport.py
│ ├── lnurl.py
│ ├── lnutil.py
│ ├── lnverifier.py
│ ├── lnwatcher.py
│ ├── lnwire/
│ │ ├── README.md
│ │ ├── onion_wire.csv
│ │ └── peer_wire.csv
│ ├── lnworker.py
│ ├── logging.py
│ ├── lrucache.py
│ ├── mnemonic.py
│ ├── mpp_split.py
│ ├── network.py
│ ├── old_mnemonic.py
│ ├── onion_message.py
│ ├── payment_identifier.py
│ ├── paymentrequest.proto
│ ├── paymentrequest.py
│ ├── paymentrequest_pb2.py
│ ├── pem.py
│ ├── plot.py
│ ├── plugin.py
│ ├── plugins/
│ │ ├── README
│ │ ├── __init__.py
│ │ ├── audio_modem/
│ │ │ ├── __init__.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── bitbox02/
│ │ │ ├── __init__.py
│ │ │ ├── bitbox02.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── coldcard/
│ │ │ ├── README.md
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── coldcard.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── digitalbitbox/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── digitalbitbox.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── jade/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── jade.py
│ │ │ ├── jadepy/
│ │ │ │ ├── README.md
│ │ │ │ ├── __init__.py
│ │ │ │ ├── jade.py
│ │ │ │ ├── jade_error.py
│ │ │ │ ├── jade_serial.py
│ │ │ │ └── jade_tcp.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── keepkey/
│ │ │ ├── __init__.py
│ │ │ ├── client.py
│ │ │ ├── clientbase.py
│ │ │ ├── cmdline.py
│ │ │ ├── keepkey.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── labels/
│ │ │ ├── Labels.qml
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── labels.py
│ │ │ ├── manifest.json
│ │ │ ├── qml.py
│ │ │ └── qt.py
│ │ ├── ledger/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── ledger.py
│ │ │ ├── manifest.json
│ │ │ └── qt.py
│ │ ├── nwc/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── manifest.json
│ │ │ ├── nwcserver.py
│ │ │ └── qt.py
│ │ ├── psbt_nostr/
│ │ │ ├── __init__.py
│ │ │ ├── manifest.json
│ │ │ ├── psbt_nostr.py
│ │ │ ├── qml/
│ │ │ │ ├── PsbtReceiveDialog.qml
│ │ │ │ └── main.qml
│ │ │ ├── qml.py
│ │ │ └── qt.py
│ │ ├── revealer/
│ │ │ ├── LICENSE_DEJAVU.txt
│ │ │ ├── SIL Open Font License.txt
│ │ │ ├── SourceSans3-Bold.otf
│ │ │ ├── __init__.py
│ │ │ ├── hmac_drbg.py
│ │ │ ├── manifest.json
│ │ │ ├── qt.py
│ │ │ └── revealer.py
│ │ ├── safe_t/
│ │ │ ├── __init__.py
│ │ │ ├── client.py
│ │ │ ├── clientbase.py
│ │ │ ├── cmdline.py
│ │ │ ├── manifest.json
│ │ │ ├── qt.py
│ │ │ ├── safe_t.py
│ │ │ └── transport.py
│ │ ├── swapserver/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── manifest.json
│ │ │ ├── server.py
│ │ │ └── swapserver.py
│ │ ├── timelock_recovery/
│ │ │ ├── __init__.py
│ │ │ ├── intro.txt
│ │ │ ├── manifest.json
│ │ │ ├── qt.py
│ │ │ └── timelock_recovery.py
│ │ ├── trezor/
│ │ │ ├── __init__.py
│ │ │ ├── clientbase.py
│ │ │ ├── cmdline.py
│ │ │ ├── manifest.json
│ │ │ ├── qt.py
│ │ │ └── trezor.py
│ │ ├── trustedcoin/
│ │ │ ├── __init__.py
│ │ │ ├── cmdline.py
│ │ │ ├── common_qt.py
│ │ │ ├── manifest.json
│ │ │ ├── qml/
│ │ │ │ ├── ChooseSeed.qml
│ │ │ │ ├── Disclaimer.qml
│ │ │ │ ├── KeepDisable.qml
│ │ │ │ ├── ShowConfirmOTP.qml
│ │ │ │ └── Terms.qml
│ │ │ ├── qml.py
│ │ │ ├── qt.py
│ │ │ └── trustedcoin.py
│ │ └── watchtower/
│ │ ├── __init__.py
│ │ ├── cmdline.py
│ │ ├── manifest.json
│ │ ├── server.py
│ │ └── watchtower.py
│ ├── qrreader/
│ │ ├── __init__.py
│ │ ├── abstract_base.py
│ │ └── zbar.py
│ ├── qrscanner.py
│ ├── ripemd.py
│ ├── rsakey.py
│ ├── scripts/
│ │ ├── README.md
│ │ ├── bip39_recovery.py
│ │ ├── block_headers.py
│ │ ├── bruteforce_pw.py
│ │ ├── estimate_fee.py
│ │ ├── get_history.py
│ │ ├── ln_features.py
│ │ ├── peers.py
│ │ ├── quick_start.py
│ │ ├── servers.py
│ │ ├── txbroadcast.py
│ │ ├── txradar.py
│ │ ├── update_default_servers.py
│ │ └── watch_address.py
│ ├── segwit_addr.py
│ ├── simple_config.py
│ ├── slip39.py
│ ├── sql_db.py
│ ├── storage.py
│ ├── submarine_swaps.py
│ ├── synchronizer.py
│ ├── trampoline.py
│ ├── transaction.py
│ ├── txbatcher.py
│ ├── util.py
│ ├── utils/
│ │ ├── __init__.py
│ │ ├── memory_leak.py
│ │ └── stacktracer.py
│ ├── verifier.py
│ ├── version.py
│ ├── wallet.py
│ ├── wallet_db.py
│ ├── wizard.py
│ ├── wordlist/
│ │ ├── chinese_simplified.txt
│ │ ├── english.txt
│ │ ├── japanese.txt
│ │ ├── portuguese.txt
│ │ ├── slip39.txt
│ │ └── spanish.txt
│ └── x509.py
├── electrum-env
├── electrum.desktop
├── fastlane/
│ └── metadata/
│ └── android/
│ └── en-US/
│ ├── full_description.txt
│ ├── short_description.txt
│ └── title.txt
├── org.electrum.electrum.metainfo.xml
├── pubkeys/
│ ├── Animazing.asc
│ ├── Emzy.asc
│ ├── ThomasV.asc
│ ├── bauerj.asc
│ ├── felixb_f321x.asc
│ ├── kyuupichan.asc
│ ├── sombernight.asc
│ ├── sombernight_releasekey.asc
│ └── wozz.asc
├── run_electrum
├── setup.cfg
├── setup.py
└── tests/
├── __init__.py
├── anchor-vectors.json
├── bip-0341/
│ └── wallet-test-vectors.json
├── blinded-onion-message-onion-test.json
├── cause_carbon_wallet.json
├── fiat_fx_data/
│ └── BitFinex_EUR
├── plugins/
│ ├── __init__.py
│ ├── test_revealer.py
│ ├── test_timelock_recovery/
│ │ └── default_wallet
│ └── test_timelock_recovery.py
├── qml/
│ ├── __init__.py
│ ├── qt_util.py
│ ├── test_qml_qeconfig.py
│ ├── test_qml_qetransactionlistmodel.py
│ └── test_qml_types.py
├── regtest/
│ ├── regtest.sh
│ ├── run_bitcoind.sh
│ └── run_electrumx.sh
├── regtest.py
├── slip39-vectors.json
├── test_bitcoin.py
├── test_blockchain.py
├── test_bolt11.py
├── test_callbackmgr.py
├── test_coinchooser.py
├── test_commands.py
├── test_contacts.py
├── test_daemon.py
├── test_descriptor.py
├── test_fee_policy.py
├── test_history_export/
│ ├── history_no_fx_client_4_5_2_9dk_with_ln.csv
│ ├── history_no_fx_client_4_5_2_9dk_with_ln.json
│ ├── history_with_fx_client_4_5_2_9dk_with_ln.csv
│ └── history_with_fx_client_4_5_2_9dk_with_ln.json
├── test_i18n.py
├── test_interface.py
├── test_invoices.py
├── test_jsondb.py
├── test_lnchannel.py
├── test_lnhtlc.py
├── test_lnmsg.py
├── test_lnpeer.py
├── test_lnpeermgr.py
├── test_lnrouter.py
├── test_lntransport.py
├── test_lnurl.py
├── test_lnutil.py
├── test_lnwallet.py
├── test_mnemonic.py
├── test_mpp_split.py
├── test_network.py
├── test_onion_message.py
├── test_payment_identifier.py
├── test_psbt.py
├── test_simple_config.py
├── test_storage_upgrade/
│ ├── client_1_9_8_seeded
│ ├── client_2_0_4_importedkeys
│ ├── client_2_0_4_multisig
│ ├── client_2_0_4_seeded
│ ├── client_2_0_4_trezor_multiacc
│ ├── client_2_0_4_trezor_singleacc
│ ├── client_2_0_4_watchaddresses
│ ├── client_2_1_1_importedkeys
│ ├── client_2_1_1_multisig
│ ├── client_2_1_1_seeded
│ ├── client_2_1_1_trezor_multiacc
│ ├── client_2_1_1_trezor_singleacc
│ ├── client_2_1_1_watchaddresses
│ ├── client_2_2_0_importedkeys
│ ├── client_2_2_0_multisig
│ ├── client_2_2_0_seeded
│ ├── client_2_2_0_trezor_multiacc
│ ├── client_2_2_0_trezor_singleacc
│ ├── client_2_2_0_watchaddresses
│ ├── client_2_3_2_importedkeys
│ ├── client_2_3_2_multisig
│ ├── client_2_3_2_seeded
│ ├── client_2_3_2_trezor_multiacc
│ ├── client_2_3_2_trezor_singleacc
│ ├── client_2_3_2_watchaddresses
│ ├── client_2_4_3_importedkeys
│ ├── client_2_4_3_multisig
│ ├── client_2_4_3_seeded
│ ├── client_2_4_3_trezor_multiacc
│ ├── client_2_4_3_trezor_singleacc
│ ├── client_2_4_3_watchaddresses
│ ├── client_2_5_4_importedkeys
│ ├── client_2_5_4_multisig
│ ├── client_2_5_4_seeded
│ ├── client_2_5_4_trezor_multiacc
│ ├── client_2_5_4_trezor_singleacc
│ ├── client_2_5_4_watchaddresses
│ ├── client_2_6_4_importedkeys
│ ├── client_2_6_4_multisig
│ ├── client_2_6_4_seeded
│ ├── client_2_6_4_watchaddresses
│ ├── client_2_7_18_importedkeys
│ ├── client_2_7_18_multisig
│ ├── client_2_7_18_seeded
│ ├── client_2_7_18_trezor_singleacc
│ ├── client_2_7_18_watchaddresses
│ ├── client_2_8_3_importedkeys
│ ├── client_2_8_3_importedkeys_flawed_previous_upgrade_from_2_7_18
│ ├── client_2_8_3_multisig
│ ├── client_2_8_3_seeded
│ ├── client_2_8_3_trezor_singleacc
│ ├── client_2_8_3_watchaddresses
│ ├── client_2_9_3_importedkeys
│ ├── client_2_9_3_importedkeys_keystore_changes
│ ├── client_2_9_3_multisig
│ ├── client_2_9_3_old_seeded_with_realistic_history
│ ├── client_2_9_3_seeded
│ ├── client_2_9_3_trezor_singleacc
│ ├── client_2_9_3_watchaddresses
│ ├── client_3_2_3_ledger_standard_keystore_changes
│ ├── client_3_3_8_xpub_with_realistic_history
│ └── client_4_5_2_9dk_with_ln
├── test_storage_upgrade.py
├── test_transaction.py
├── test_txbatcher.py
├── test_util.py
├── test_verifier.py
├── test_wallet.py
├── test_wallet_vertical.py
├── test_wizard.py
└── test_x509.py
Showing preview only (815K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (9653 symbols across 338 files)
FILE: contrib/android/apkdiff.py
class ApkDiff (line 15) | class ApkDiff:
method compare (line 18) | def compare(self, sourceApk, destinationApk) -> bool:
method compareManifests (line 29) | def compareManifests(self, sourceZip, destinationZip):
method compareEntries (line 47) | def compareEntries(self, sourceZip, destinationZip):
method compareFiles (line 70) | def compareFiles(self, sourceFile, destinationFile):
FILE: contrib/android/get_apk_versioncode.py
function get_electrum_version (line 16) | def get_electrum_version() -> str:
function get_android_versioncode (line 26) | def get_android_versioncode(*, arch_name: str) -> int:
FILE: contrib/android/p4a_recipes/cffi/__init__.py
class CffiRecipePinned (line 14) | class CffiRecipePinned(util.InheritedRecipeMixin, CffiRecipe):
FILE: contrib/android/p4a_recipes/cryptography/__init__.py
class CryptographyRecipePinned (line 9) | class CryptographyRecipePinned(CryptographyRecipe):
FILE: contrib/android/p4a_recipes/hostpython3/__init__.py
class HostPython3RecipePinned (line 13) | class HostPython3RecipePinned(util.InheritedRecipeMixin, HostPython3Reci...
FILE: contrib/android/p4a_recipes/libffi/__init__.py
class LibffiRecipePinned (line 14) | class LibffiRecipePinned(util.InheritedRecipeMixin, LibffiRecipe):
FILE: contrib/android/p4a_recipes/libiconv/__init__.py
class LibIconvRecipePinned (line 14) | class LibIconvRecipePinned(util.InheritedRecipeMixin, LibIconvRecipe):
FILE: contrib/android/p4a_recipes/libsecp256k1/__init__.py
class LibSecp256k1RecipePinned (line 8) | class LibSecp256k1RecipePinned(LibSecp256k1Recipe):
FILE: contrib/android/p4a_recipes/libzbar/__init__.py
class LibZBarRecipePinned (line 13) | class LibZBarRecipePinned(util.InheritedRecipeMixin, LibZBarRecipe):
FILE: contrib/android/p4a_recipes/openssl/__init__.py
class OpenSSLRecipePinned (line 14) | class OpenSSLRecipePinned(util.InheritedRecipeMixin, OpenSSLRecipe):
FILE: contrib/android/p4a_recipes/packaging/__init__.py
class PackagingRecipePinned (line 9) | class PackagingRecipePinned(PackagingRecipe):
FILE: contrib/android/p4a_recipes/ply/__init__.py
class PlyRecipePinned (line 14) | class PlyRecipePinned(util.InheritedRecipeMixin, PlyRecipe):
FILE: contrib/android/p4a_recipes/plyer/__init__.py
class PlyerRecipePinned (line 8) | class PlyerRecipePinned(PythonRecipe):
FILE: contrib/android/p4a_recipes/pycparser/__init__.py
class PycparserRecipePinned (line 9) | class PycparserRecipePinned(PycparserRecipe):
FILE: contrib/android/p4a_recipes/pycryptodomex/__init__.py
class PycryptodomexRecipe (line 8) | class PycryptodomexRecipe(PythonRecipe):
FILE: contrib/android/p4a_recipes/pyjnius/__init__.py
class PyjniusRecipePinned (line 14) | class PyjniusRecipePinned(util.InheritedRecipeMixin, PyjniusRecipe):
FILE: contrib/android/p4a_recipes/pyparsing/__init__.py
class PyparsingRecipePinned (line 9) | class PyparsingRecipePinned(PyparsingRecipe):
FILE: contrib/android/p4a_recipes/pyqt6/__init__.py
class PyQt6RecipePinned (line 14) | class PyQt6RecipePinned(util.InheritedRecipeMixin, PyQt6Recipe):
FILE: contrib/android/p4a_recipes/pyqt6sip/__init__.py
class PyQt6SipRecipePinned (line 14) | class PyQt6SipRecipePinned(util.InheritedRecipeMixin, PyQt6SipRecipe):
FILE: contrib/android/p4a_recipes/pyqt_builder/__init__.py
class PyQtBuilderRecipePinned (line 9) | class PyQtBuilderRecipePinned(PyQtBuilderRecipe):
FILE: contrib/android/p4a_recipes/python3/__init__.py
class Python3RecipePinned (line 13) | class Python3RecipePinned(util.InheritedRecipeMixin, Python3Recipe):
FILE: contrib/android/p4a_recipes/qt6/__init__.py
class Qt6RecipePinned (line 14) | class Qt6RecipePinned(util.InheritedRecipeMixin, Qt6Recipe):
FILE: contrib/android/p4a_recipes/setuptools/__init__.py
class SetuptoolsRecipePinned (line 9) | class SetuptoolsRecipePinned(SetuptoolsRecipe):
FILE: contrib/android/p4a_recipes/sip/__init__.py
class SipRecipePinned (line 9) | class SipRecipePinned(SipRecipe):
FILE: contrib/android/p4a_recipes/six/__init__.py
class SixRecipePinned (line 9) | class SixRecipePinned(SixRecipe):
FILE: contrib/android/p4a_recipes/sqlite3/__init__.py
class Sqlite3RecipePinned (line 14) | class Sqlite3RecipePinned(util.InheritedRecipeMixin, Sqlite3Recipe):
FILE: contrib/android/p4a_recipes/toml/__init__.py
class TomlRecipePinned (line 9) | class TomlRecipePinned(TomlRecipe):
FILE: contrib/android/p4a_recipes/tomli/__init__.py
class TomliRecipePinned (line 9) | class TomliRecipePinned(TomliRecipe):
FILE: contrib/android/p4a_recipes/util.py
class InheritedRecipeMixin (line 4) | class InheritedRecipeMixin:
method get_recipe_dir (line 6) | def get_recipe_dir(self):
FILE: contrib/deterministic-build/find_restricted_dependencies.py
function is_dependency_edge_blacklisted (line 9) | def is_dependency_edge_blacklisted(*, parent_pkg: str, dep: str) -> bool:
function check_restriction (line 22) | def check_restriction(*, dep: str, restricted: str, parent_pkg: str):
function main (line 35) | def main():
FILE: electrum/__init__.py
class GuiImportError (line 13) | class GuiImportError(ImportError):
FILE: electrum/_vendor/distutils/version.py
class Version (line 31) | class Version:
method __init__ (line 38) | def __init__ (self, vstring=None):
method __repr__ (line 42) | def __repr__ (self):
method __eq__ (line 45) | def __eq__(self, other):
method __lt__ (line 51) | def __lt__(self, other):
method __le__ (line 57) | def __le__(self, other):
method __gt__ (line 63) | def __gt__(self, other):
method __ge__ (line 69) | def __ge__(self, other):
class StrictVersion (line 93) | class StrictVersion (Version):
method parse (line 134) | def parse (self, vstring):
method __str__ (line 153) | def __str__ (self):
method _cmp (line 166) | def _cmp (self, other):
class LooseVersion (line 269) | class LooseVersion (Version):
method __init__ (line 304) | def __init__ (self, vstring=None):
method parse (line 309) | def parse (self, vstring):
method __str__ (line 325) | def __str__ (self):
method __repr__ (line 329) | def __repr__ (self):
method _cmp (line 333) | def _cmp (self, other):
FILE: electrum/_vendor/pyperclip/__init__.py
function _executable_exists (line 87) | def _executable_exists(name):
class PyperclipException (line 94) | class PyperclipException(RuntimeError):
class PyperclipWindowsException (line 97) | class PyperclipWindowsException(PyperclipException):
method __init__ (line 98) | def __init__(self, message):
class PyperclipTimeoutException (line 102) | class PyperclipTimeoutException(PyperclipException):
function _stringifyText (line 105) | def _stringifyText(text):
function init_osx_pbcopy_clipboard (line 115) | def init_osx_pbcopy_clipboard():
function init_osx_pyobjc_clipboard (line 132) | def init_osx_pyobjc_clipboard():
function init_gtk_clipboard (line 151) | def init_gtk_clipboard():
function init_qt_clipboard (line 173) | def init_qt_clipboard():
function init_xclip_clipboard (line 205) | def init_xclip_clipboard():
function init_xsel_clipboard (line 233) | def init_xsel_clipboard():
function init_wl_clipboard (line 258) | def init_wl_clipboard():
function init_klipper_clipboard (line 285) | def init_klipper_clipboard():
function init_dev_clipboard_clipboard (line 314) | def init_dev_clipboard_clipboard():
function init_no_clipboard (line 335) | def init_no_clipboard():
class CheckedCall (line 354) | class CheckedCall(object):
method __init__ (line 355) | def __init__(self, f):
method __call__ (line 358) | def __call__(self, *args):
method __setattr__ (line 364) | def __setattr__(self, key, value):
function init_windows_clipboard (line 368) | def init_windows_clipboard():
function init_wsl_clipboard (line 509) | def init_wsl_clipboard():
function determine_clipboard (line 530) | def determine_clipboard():
function set_clipboard (line 615) | def set_clipboard(clipboard):
function lazy_load_stub_copy (line 652) | def lazy_load_stub_copy(text):
function lazy_load_stub_paste (line 674) | def lazy_load_stub_paste():
function is_available (line 696) | def is_available():
function waitForPaste (line 707) | def waitForPaste(timeout=None):
function waitForNewPaste (line 725) | def waitForNewPaste(timeout=None):
FILE: electrum/address_synchronizer.py
class TxMinedDepth (line 61) | class TxMinedDepth(IntEnum):
class HistoryItem (line 69) | class HistoryItem(NamedTuple):
class AddressSynchronizer (line 77) | class AddressSynchronizer(Logger, EventListener):
method __init__ (line 85) | def __init__(self, db: 'WalletDB', config: 'SimpleConfig', *, name: st...
method invalidate_cache (line 109) | def invalidate_cache(self):
method diagnostic_name (line 113) | def diagnostic_name(self):
method load_and_cleanup (line 117) | def load_and_cleanup(self):
method is_mine (line 123) | def is_mine(self, address: Optional[str]) -> bool:
method get_addresses (line 136) | def get_addresses(self):
method get_address_history (line 140) | def get_address_history(self, addr: str) -> Dict[str, int]:
method get_address_history_len (line 155) | def get_address_history_len(self, addr: str) -> int:
method get_txin_address (line 160) | def get_txin_address(self, txin: TxInput) -> Optional[str]:
method get_txin_value (line 175) | def get_txin_value(self, txin: TxInput, *, address: str = None) -> Opt...
method load_unverified_transactions (line 195) | def load_unverified_transactions(self):
method start_network (line 203) | def start_network(self, network: Optional['Network']) -> None:
method on_event_blockchain_updated (line 215) | def on_event_blockchain_updated(self, *args):
method stop (line 219) | async def stop(self):
method add_address (line 233) | def add_address(self, address: str) -> None:
method get_conflicting_transactions (line 241) | def get_conflicting_transactions(self, tx: Transaction, *, include_sel...
method get_transaction (line 272) | def get_transaction(self, txid: str) -> Optional[Transaction]:
method add_transaction (line 282) | def add_transaction(self, tx: Transaction, *, allow_unrelated=False, i...
method remove_transaction (line 382) | def remove_transaction(self, tx_hash: str) -> None:
method _remove_transaction (line 391) | def _remove_transaction(self, tx_hash: str) -> None:
method get_depending_transactions (line 432) | def get_depending_transactions(self, tx_hash: str) -> Set[str]:
method receive_tx_callback (line 442) | def receive_tx_callback(self, tx: Transaction, *, tx_height: Optional[...
method receive_history_callback (line 451) | def receive_history_callback(self, addr: str, hist, tx_fees: Dict[str,...
method load_local_history (line 482) | def load_local_history(self):
method check_history (line 490) | def check_history(self):
method remove_local_transactions_we_dont_have (line 505) | def remove_local_transactions_we_dont_have(self):
method clear_history (line 512) | def clear_history(self):
method _get_tx_sort_key (line 518) | def _get_tx_sort_key(self, tx_hash: str) -> Tuple[int, int]:
method tx_height_to_sort_height (line 526) | def tx_height_to_sort_height(cls, height: int = None):
method with_local_height_cached (line 541) | def with_local_height_cached(func):
method get_history (line 555) | def get_history(self, domain) -> Sequence[HistoryItem]:
method _add_tx_to_local_history (line 591) | def _add_tx_to_local_history(self, txid):
method _remove_tx_from_local_history (line 599) | def _remove_tx_from_local_history(self, txid):
method _mark_address_history_changed (line 610) | def _mark_address_history_changed(self, addr: str) -> None:
method wait_for_address_history_to_change (line 620) | async def wait_for_address_history_to_change(self, addr: str) -> None:
method add_unverified_or_unconfirmed_tx (line 630) | def add_unverified_or_unconfirmed_tx(self, tx_hash: str, tx_height: in...
method remove_unverified_tx (line 646) | def remove_unverified_tx(self, tx_hash: str, tx_height: int) -> None:
method add_verified_tx (line 651) | def add_verified_tx(self, tx_hash: str, info: TxMinedInfo):
method get_unverified_txs (line 660) | def get_unverified_txs(self) -> Dict[str, int]:
method undo_verifications (line 664) | def undo_verifications(self, blockchain: Blockchain, above_height: int...
method get_local_height (line 691) | def get_local_height(self) -> int:
method _update_stored_local_height (line 698) | def _update_stored_local_height(self) -> None:
method set_future_tx (line 701) | def set_future_tx(self, txid: str, *, wanted_height: int):
method get_tx_height (line 713) | def get_tx_height(
method up_to_date_changed (line 751) | def up_to_date_changed(self) -> None:
method is_up_to_date (line 755) | def is_up_to_date(self):
method reset_netrequest_counters (line 760) | def reset_netrequest_counters(self) -> None:
method get_history_sync_state_details (line 766) | def get_history_sync_state_details(self) -> Tuple[int, int]:
method get_tx_delta (line 779) | def get_tx_delta(self, tx_hash: str, address: str) -> int:
method get_tx_fee (line 793) | def get_tx_fee(self, txid: str) -> Optional[int]:
method get_addr_io (line 847) | def get_addr_io(self, address: str):
method get_addr_outputs (line 862) | def get_addr_outputs(self, address: str) -> Dict[TxOutpoint, PartialTx...
method get_addr_utxo (line 883) | def get_addr_utxo(self, address: str) -> Dict[TxOutpoint, PartialTxInp...
method get_addr_received (line 891) | def get_addr_received(self, address):
method get_balance (line 897) | def get_balance(self, domain, *, excluded_addresses: Set[str] = None,
method get_utxos (line 963) | def get_utxos(
method is_used (line 1013) | def is_used(self, address: str) -> bool:
method is_used_as_from_address (line 1017) | def is_used_as_from_address(self, address: str) -> bool:
method is_empty (line 1022) | def is_empty(self, address: str) -> bool:
method address_is_old (line 1028) | def address_is_old(self, address: str, *, req_conf: int = 3) -> bool:
method get_spender (line 1047) | def get_spender(self, outpoint: str) -> Optional[str]:
method get_tx_mined_depth (line 1068) | def get_tx_mined_depth(self, txid: str):
method is_deeply_mined (line 1087) | def is_deeply_mined(self, txid):
FILE: electrum/base_crash_reporter.py
function taint_reports_by_console_usage (line 43) | def taint_reports_by_console_usage():
class CrashReportResponse (line 48) | class CrashReportResponse(NamedTuple):
class BaseCrashReporter (line 54) | class BaseCrashReporter(Logger):
method __init__ (line 81) | def __init__(
method send_report (line 90) | def send_report(self, asyncio_loop, proxy: 'ProxySettings', *, timeout...
method do_post (line 124) | async def do_post(self, proxy: 'ProxySettings', url, data) -> str:
method get_traceback_info (line 130) | def get_traceback_info(
method get_traceback_groupid_hash (line 151) | def get_traceback_groupid_hash(
method get_additional_info (line 161) | def get_additional_info(self):
method _get_traceback_str_to_send (line 181) | def _get_traceback_str_to_send(
method _get_traceback_str_to_display (line 192) | def _get_traceback_str_to_display(self) -> str:
method get_report_string (line 196) | def get_report_string(self):
method get_user_description (line 201) | def get_user_description(self):
method get_wallet_type (line 204) | def get_wallet_type(self) -> str:
class EarlyExceptionsQueue (line 208) | class EarlyExceptionsQueue:
method set_hook_as_ready (line 221) | def set_hook_as_ready(cls):
method send_exception_to_crash_reporter (line 231) | def send_exception_to_crash_reporter(cls, e: BaseException):
method _send_exception_to_crash_reporter (line 238) | def _send_exception_to_crash_reporter(e: BaseException):
function trigger_crash (line 246) | def trigger_crash():
FILE: electrum/bip21.py
class InvalidBitcoinURI (line 17) | class InvalidBitcoinURI(Exception):
function parse_bip21_URI (line 21) | def parse_bip21_URI(uri: str) -> dict:
function create_bip21_uri (line 107) | def create_bip21_uri(addr, amount_sat: Optional[int], message: Optional[...
FILE: electrum/bip32.py
function protect_against_invalid_ecpoint (line 26) | def protect_against_invalid_ecpoint(func):
function CKD_priv (line 42) | def CKD_priv(parent_privkey: bytes, parent_chaincode: bytes, child_index...
function _CKD_priv (line 57) | def _CKD_priv(parent_privkey: bytes, parent_chaincode: bytes,
function CKD_pub (line 80) | def CKD_pub(parent_pubkey: bytes, parent_chaincode: bytes, child_index: ...
function _CKD_pub (line 94) | def _CKD_pub(parent_pubkey: bytes, parent_chaincode: bytes, child_index:...
function xprv_header (line 104) | def xprv_header(xtype: str, *, net=None) -> bytes:
function xpub_header (line 110) | def xpub_header(xtype: str, *, net=None) -> bytes:
class InvalidMasterKeyVersionBytes (line 116) | class InvalidMasterKeyVersionBytes(BitcoinException): pass
class BIP32Node (line 119) | class BIP32Node(NamedTuple):
method from_xkey (line 128) | def from_xkey(
method from_rootseed (line 169) | def from_rootseed(cls, seed: bytes, *, xtype: str) -> 'BIP32Node':
method from_bytes (line 178) | def from_bytes(cls, b: bytes) -> 'BIP32Node':
method to_xprv (line 184) | def to_xprv(self, *, net=None) -> str:
method to_xprv_bytes (line 188) | def to_xprv_bytes(self, *, net=None) -> bytes:
method to_xpub (line 201) | def to_xpub(self, *, net=None) -> str:
method to_xpub_bytes (line 205) | def to_xpub_bytes(self, *, net=None) -> bytes:
method to_xkey (line 215) | def to_xkey(self, *, net=None) -> str:
method to_bytes (line 221) | def to_bytes(self, *, net=None) -> bytes:
method convert_to_public (line 227) | def convert_to_public(self) -> 'BIP32Node':
method is_private (line 233) | def is_private(self) -> bool:
method subkey_at_private_derivation (line 236) | def subkey_at_private_derivation(self, path: Union[str, Iterable[int]]...
method subkey_at_public_derivation (line 262) | def subkey_at_public_derivation(self, path: Union[str, Iterable[int]])...
method calc_fingerprint_of_this_node (line 285) | def calc_fingerprint_of_this_node(self) -> bytes:
function xpub_type (line 293) | def xpub_type(x: str) -> str:
function is_xpub (line 298) | def is_xpub(text: str) -> bool:
function is_xprv (line 306) | def is_xprv(text: str) -> bool:
function xpub_from_xprv (line 314) | def xpub_from_xprv(xprv: str) -> str:
function convert_bip32_strpath_to_intpath (line 318) | def convert_bip32_strpath_to_intpath(n: str) -> List[int]:
function convert_bip32_intpath_to_strpath (line 357) | def convert_bip32_intpath_to_strpath(path: Sequence[int], *, hardened_ch...
function is_bip32_derivation (line 376) | def is_bip32_derivation(s: str) -> bool:
function normalize_bip32_derivation (line 387) | def normalize_bip32_derivation(s: Optional[str], *, hardened_char=BIP32_...
function is_all_public_derivation (line 396) | def is_all_public_derivation(path: Union[str, Iterable[int]]) -> bool:
function root_fp_and_der_prefix_from_xkey (line 408) | def root_fp_and_der_prefix_from_xkey(xkey: str) -> Tuple[Optional[str], ...
function is_xkey_consistent_with_key_origin_info (line 426) | def is_xkey_consistent_with_key_origin_info(xkey: str, *,
class KeyOriginInfo (line 449) | class KeyOriginInfo:
method __init__ (line 457) | def __init__(self, fingerprint: bytes, path: Sequence[int]) -> None:
method deserialize (line 466) | def deserialize(cls, s: bytes) -> 'KeyOriginInfo':
method serialize (line 476) | def serialize(self) -> bytes:
method _path_string (line 484) | def _path_string(self) -> str:
method to_string (line 490) | def to_string(self) -> str:
method from_string (line 500) | def from_string(cls, s: str) -> 'KeyOriginInfo':
method get_derivation_path (line 513) | def get_derivation_path(self) -> str:
method get_full_int_list (line 519) | def get_full_int_list(self) -> List[int]:
method __eq__ (line 528) | def __eq__(self, other) -> bool:
method __repr__ (line 533) | def __repr__(self) -> str:
FILE: electrum/bip39_recovery.py
function account_discovery (line 19) | async def account_discovery(network: Optional['Network'], get_account_xp...
function scan_for_active_accounts (line 33) | async def scan_for_active_accounts(network: 'Network', get_account_xpub,...
function account_has_history (line 49) | async def account_has_history(network: 'Network', account_node: BIP32Nod...
function format_account (line 72) | def format_account(wallet_format, account_path):
FILE: electrum/bitcoin.py
class opcodes (line 60) | class opcodes(IntEnum):
method hex (line 197) | def hex(self) -> str:
function script_num_to_bytes (line 201) | def script_num_to_bytes(i: int) -> bytes:
function var_int (line 225) | def var_int(i: int) -> bytes:
function witness_push (line 240) | def witness_push(item: bytes) -> bytes:
function _op_push (line 245) | def _op_push(i: int) -> bytes:
function push_script (line 256) | def push_script(data: bytes) -> bytes:
function make_op_return (line 275) | def make_op_return(x: bytes) -> bytes:
function add_number_to_script (line 279) | def add_number_to_script(i: int) -> bytes:
function construct_witness (line 283) | def construct_witness(items: Sequence[Union[str, int, bytes]]) -> bytes:
function construct_script (line 299) | def construct_script(
function relayfee (line 326) | def relayfee(network: 'Network' = None) -> int:
function dust_threshold (line 348) | def dust_threshold(network: 'Network' = None) -> int:
function hash_encode (line 353) | def hash_encode(x: bytes) -> str:
function hash_decode (line 357) | def hash_decode(x: str) -> bytes:
function hash160_to_b58_address (line 363) | def hash160_to_b58_address(h160: bytes, addrtype: int) -> str:
function b58_address_to_hash160 (line 369) | def b58_address_to_hash160(addr: str) -> Tuple[int, bytes]:
function hash160_to_p2pkh (line 377) | def hash160_to_p2pkh(h160: bytes, *, net=None) -> str:
function hash160_to_p2sh (line 382) | def hash160_to_p2sh(h160: bytes, *, net=None) -> str:
function public_key_to_p2pkh (line 387) | def public_key_to_p2pkh(public_key: bytes, *, net=None) -> str:
function hash_to_segwit_addr (line 391) | def hash_to_segwit_addr(h: bytes, witver: int, *, net=None) -> str:
function public_key_to_p2wpkh (line 398) | def public_key_to_p2wpkh(public_key: bytes, *, net=None) -> str:
function script_to_p2wsh (line 402) | def script_to_p2wsh(script: bytes, *, net=None) -> str:
function p2wsh_nested_script (line 406) | def p2wsh_nested_script(witness_script: bytes) -> bytes:
function pubkey_to_address (line 411) | def pubkey_to_address(txin_type: str, pubkey: str, *, net=None) -> str:
function redeem_script_to_address (line 418) | def redeem_script_to_address(txin_type: str, scriptcode: bytes, *, net=N...
function script_to_address (line 434) | def script_to_address(script: bytes, *, net=None) -> Optional[str]:
function address_to_script (line 439) | def address_to_script(addr: str, *, net=None) -> bytes:
class OnchainOutputType (line 458) | class OnchainOutputType(Enum):
function address_to_payload (line 469) | def address_to_payload(addr: str, *, net=None) -> Tuple[OnchainOutputTyp...
function address_to_scripthash (line 498) | def address_to_scripthash(addr: str, *, net=None) -> str:
function script_to_scripthash (line 503) | def script_to_scripthash(script: bytes) -> str:
function pubkeyhash_to_p2pkh_script (line 508) | def pubkeyhash_to_p2pkh_script(pubkey_hash160: bytes) -> bytes:
class BaseDecodeError (line 527) | class BaseDecodeError(BitcoinException): pass
function base_encode (line 530) | def base_encode(v: bytes, *, base: int) -> str:
function base_decode (line 553) | def base_decode(v: Union[bytes, str], *, base: int) -> Optional[bytes]:
class InvalidChecksum (line 582) | class InvalidChecksum(BaseDecodeError):
function EncodeBase58Check (line 586) | def EncodeBase58Check(vchIn: bytes) -> str:
function DecodeBase58Check (line 591) | def DecodeBase58Check(psz: Union[bytes, str]) -> bytes:
function is_segwit_script_type (line 616) | def is_segwit_script_type(txin_type: str) -> bool:
function serialize_privkey (line 620) | def serialize_privkey(secret: bytes, compressed: bool, txin_type: str, *,
function deserialize_privkey (line 637) | def deserialize_privkey(key: str) -> Tuple[str, bytes, bool]:
function is_compressed_privkey (line 683) | def is_compressed_privkey(sec: str) -> bool:
function address_from_private_key (line 687) | def address_from_private_key(sec: str) -> str:
function is_segwit_address (line 693) | def is_segwit_address(addr: str, *, net=None) -> bool:
function is_taproot_address (line 702) | def is_taproot_address(addr: str, *, net=None) -> bool:
function is_b58_address (line 711) | def is_b58_address(addr: str, *, net=None) -> bool:
function is_address (line 723) | def is_address(addr: str, *, net=None) -> bool:
function is_private_key (line 728) | def is_private_key(key: str, *, raise_on_error=False) -> bool:
function is_minikey (line 740) | def is_minikey(text: str) -> bool:
function minikey_to_private_key (line 751) | def minikey_to_private_key(text: str) -> bytes:
function _get_dummy_address (line 755) | def _get_dummy_address(purpose: str) -> str:
class DummyAddress (line 762) | class DummyAddress:
method purpose (line 766) | def purpose(func):
method CHANNEL (line 771) | def CHANNEL(self) -> str:
method SWAP (line 774) | def SWAP(self) -> str:
method is_dummy_address (line 778) | def is_dummy_address(cls, addr: str) -> bool:
class DummyAddressUsedInTxException (line 782) | class DummyAddressUsedInTxException(Exception): pass
function taproot_tweak_pubkey (line 785) | def taproot_tweak_pubkey(pubkey32: bytes, h: bytes) -> Tuple[int, bytes]:
function taproot_tweak_seckey (line 799) | def taproot_tweak_seckey(seckey0: bytes, h: bytes) -> bytes:
function taproot_tree_helper (line 821) | def taproot_tree_helper(script_tree: TapTree):
function taproot_output_script (line 834) | def taproot_output_script(internal_pubkey: bytes, *, script_tree: Option...
function control_block_for_taproot_script_spend (line 846) | def control_block_for_taproot_script_spend(
function usermessage_magic (line 863) | def usermessage_magic(message: bytes) -> bytes:
function ecdsa_sign_usermessage (line 868) | def ecdsa_sign_usermessage(ec_privkey, message: Union[bytes, str], *, is...
function verify_usermessage_with_address (line 874) | def verify_usermessage_with_address(address: str, sig65: bytes, message:...
FILE: electrum/blockchain.py
class MissingHeader (line 47) | class MissingHeader(Exception):
class InvalidHeader (line 51) | class InvalidHeader(Exception):
function serialize_header (line 55) | def serialize_header(header_dict: dict) -> bytes:
function deserialize_header (line 66) | def deserialize_header(s: bytes, height: int) -> dict:
function hash_header (line 82) | def hash_header(header: dict) -> str:
function hash_raw_header (line 90) | def hash_raw_header(header: bytes) -> str:
function read_blockchains (line 104) | def read_blockchains(config: 'SimpleConfig'):
function get_best_chain (line 166) | def get_best_chain() -> 'Blockchain':
function init_headers_file_for_best_chain (line 176) | def init_headers_file_for_best_chain():
class Blockchain (line 190) | class Blockchain(Logger):
method __init__ (line 195) | def __init__(self, config: 'SimpleConfig', forkpoint: int, parent: Opt...
method checkpoints (line 212) | def checkpoints(self):
method get_max_child (line 215) | def get_max_child(self) -> Optional[int]:
method get_max_forkpoint (line 219) | def get_max_forkpoint(self) -> int:
method get_direct_children (line 226) | def get_direct_children(self) -> Sequence['Blockchain']:
method get_parent_heights (line 230) | def get_parent_heights(self) -> Mapping['Blockchain', int]:
method get_height_of_last_common_block_with_chain (line 242) | def get_height_of_last_common_block_with_chain(self, other_chain: 'Blo...
method get_branch_size (line 253) | def get_branch_size(self) -> int:
method get_name (line 256) | def get_name(self) -> str:
method check_header (line 259) | def check_header(self, header: dict) -> bool:
method check_hash (line 264) | def check_hash(self, height: int, header_hash: str) -> bool:
method fork (line 274) | def fork(parent, header: dict) -> 'Blockchain':
method height (line 294) | def height(self) -> int:
method size (line 298) | def size(self) -> int:
method update_size (line 302) | def update_size(self) -> None:
method verify_header (line 307) | def verify_header(cls, header: dict, prev_hash: str, target: int, expe...
method verify_chunk (line 323) | def verify_chunk(self, index: int, data: bytes) -> None:
method path (line 340) | def path(self):
method save_chunk (line 353) | def save_chunk(self, index: int, chunk: bytes):
method swap_with_parent (line 373) | def swap_with_parent(self) -> None:
method _swap_with_parent (line 390) | def _swap_with_parent(self) -> bool:
method get_id (line 436) | def get_id(self) -> str:
method assert_headers_file_available (line 439) | def assert_headers_file_available(self, path):
method write (line 448) | def write(self, data: bytes, offset: int, truncate: bool = True, *, fs...
method save_header (line 463) | def save_header(self, header: dict) -> None:
method read_header (line 474) | def read_header(self, height: int) -> Optional[dict]:
method header_at_tip (line 493) | def header_at_tip(self) -> Optional[dict]:
method is_tip_stale (line 498) | def is_tip_stale(self) -> bool:
method get_hash (line 512) | def get_hash(self, height: int) -> str:
method get_target (line 532) | def get_target(self, index: int) -> int:
method bits_to_target (line 558) | def bits_to_target(cls, bits: int) -> int:
method target_to_bits (line 579) | def target_to_bits(cls, target: int) -> int:
method chainwork_of_header_at_height (line 595) | def chainwork_of_header_at_height(self, height: int) -> int:
method get_chainwork (line 603) | def get_chainwork(self, height=None) -> int:
method can_connect (line 629) | def can_connect(self, header: dict, *, check_height: bool = True) -> b...
method connect_chunk (line 653) | def connect_chunk(self, idx: int, data: bytes) -> bool:
method get_checkpoints (line 663) | def get_checkpoints(self):
function check_header (line 674) | def check_header(header: dict) -> Optional[Blockchain]:
function can_connect (line 685) | def can_connect(header: dict) -> Optional[Blockchain]:
function get_chains_that_contain_header (line 696) | def get_chains_that_contain_header(height: int, header_hash: str) -> Seq...
FILE: electrum/channel_db.py
class ChannelDBNotLoaded (line 64) | class ChannelDBNotLoaded(UserFacingException): pass
class ChannelInfo (line 67) | class ChannelInfo(NamedTuple):
method from_msg (line 75) | def from_msg(payload: dict) -> 'ChannelInfo':
method from_raw_msg (line 92) | def from_raw_msg(raw: bytes) -> 'ChannelInfo':
method from_route_edge (line 98) | def from_route_edge(route_edge: 'RouteEdge') -> 'ChannelInfo':
class Policy (line 108) | class Policy(NamedTuple):
method from_msg (line 121) | def from_msg(payload: dict) -> 'Policy':
method from_raw_msg (line 136) | def from_raw_msg(key: bytes, raw: bytes) -> 'Policy':
method from_route_edge (line 143) | def from_route_edge(route_edge: 'RouteEdge') -> 'Policy':
method is_disabled (line 156) | def is_disabled(self):
method short_channel_id (line 160) | def short_channel_id(self) -> ShortChannelID:
method start_node (line 164) | def start_node(self) -> bytes:
class NodeInfo (line 168) | class NodeInfo(NamedTuple):
method from_msg (line 176) | def from_msg(payload) -> Tuple['NodeInfo', Sequence['LNPeerAddr']]:
method from_raw_msg (line 202) | def from_raw_msg(raw: bytes) -> Tuple['NodeInfo', Sequence['LNPeerAddr...
method to_addresses_field (line 208) | def to_addresses_field(hostname: str, port: int) -> bytes:
method invalid_announcement_hostname (line 238) | def invalid_announcement_hostname(hostname: Optional[str]) -> bool:
method parse_addresses_field (line 251) | def parse_addresses_field(addresses_field):
class UpdateStatus (line 296) | class UpdateStatus(IntEnum):
class CategorizedChannelUpdates (line 304) | class CategorizedChannelUpdates(NamedTuple):
function get_mychannel_info (line 312) | def get_mychannel_info(short_channel_id: ShortChannelID,
function get_mychannel_policy (line 322) | def get_mychannel_policy(short_channel_id: bytes, node_id: bytes,
class _LoadDataAborted (line 342) | class _LoadDataAborted(Exception): pass
class ChannelDB (line 376) | class ChannelDB(SqlDB):
method __init__ (line 382) | def __init__(self, network: 'Network'):
method get_file_path (line 418) | def get_file_path(cls, config: 'SimpleConfig') -> str:
method update_counts (line 421) | def update_counts(self):
method get_channel_ids (line 428) | def get_channel_ids(self):
method add_recent_peer (line 432) | def add_recent_peer(self, peer: LNPeerAddr):
method get_200_randomly_sorted_nodes_not_in (line 444) | def get_200_randomly_sorted_nodes_not_in(self, node_ids):
method get_last_good_address (line 449) | def get_last_good_address(self, node_id: bytes) -> Optional[LNPeerAddr]:
method get_recent_peers (line 460) | def get_recent_peers(self):
method add_channel_announcements (line 473) | def add_channel_announcements(self, msg_payloads, *, trusted=True):
method add_verified_channel_info (line 498) | def add_verified_channel_info(self, msg: dict, *, capacity_sat: int = ...
method policy_changed (line 515) | def policy_changed(self, old_policy: Policy, new_policy: Policy, verbo...
method add_channel_update (line 549) | def add_channel_update(
method add_channel_updates (line 588) | def add_channel_updates(self, payloads, max_age=None) -> CategorizedCh...
method create_database (line 614) | def create_database(self):
method _db_save_policy (line 623) | def _db_save_policy(self, key: bytes, msg: bytes):
method _db_delete_policy (line 629) | def _db_delete_policy(self, node_id: bytes, short_channel_id: ShortCha...
method _db_save_channel (line 635) | def _db_save_channel(self, short_channel_id: ShortChannelID, msg: bytes):
method _db_delete_channel (line 641) | def _db_delete_channel(self, short_channel_id: ShortChannelID):
method _db_save_node_info (line 646) | def _db_save_node_info(self, node_id: bytes, msg: bytes):
method _db_save_node_address (line 652) | def _db_save_node_address(self, peer: LNPeerAddr, timestamp: int):
method _db_save_node_addresses (line 658) | def _db_save_node_addresses(self, node_addresses: Sequence[LNPeerAddr]):
method verify_channel_update (line 667) | def verify_channel_update(cls, payload, *, start_node: bytes = None) -...
method verify_channel_announcement (line 678) | def verify_channel_announcement(cls, payload) -> None:
method verify_node_announcement (line 687) | def verify_node_announcement(cls, payload) -> None:
method add_node_announcements (line 694) | def add_node_announcements(self, msg_payloads):
method get_old_policies (line 729) | def get_old_policies(self, delta) -> Sequence[Tuple[bytes, ShortChanne...
method prune_old_policies (line 735) | def prune_old_policies(self, delta):
method prune_orphaned_channels (line 747) | def prune_orphaned_channels(self):
method _get_channel_update_for_private_channel (line 756) | def _get_channel_update_for_private_channel(
method add_channel_update_for_private_channel (line 772) | def add_channel_update_for_private_channel(
method remove_channel (line 798) | def remove_channel(self, short_channel_id: ShortChannelID):
method get_node_addresses (line 809) | def get_node_addresses(self, node_id: bytes) -> Sequence[Tuple[str, in...
method handle_abort (line 817) | def handle_abort(func):
method load_data (line 829) | def load_data(self):
method _update_num_policies_for_chan (line 898) | def _update_num_policies_for_chan(self, short_channel_id: ShortChannel...
method get_num_channels_partitioned_by_policy_count (line 919) | def get_num_channels_partitioned_by_policy_count(self) -> Tuple[int, i...
method get_policy_for_node (line 925) | def get_policy_for_node(
method get_channel_info (line 951) | def get_channel_info(
method get_channels_for_node (line 971) | def get_channels_for_node(
method get_endnodes_for_chan (line 995) | def get_endnodes_for_chan(self, short_channel_id: ShortChannelID, *,
method get_node_info_for_node_id (line 1008) | def get_node_info_for_node_id(self, node_id: bytes) -> Optional['NodeI...
method get_node_infos (line 1011) | def get_node_infos(self) -> Dict[bytes, NodeInfo]:
method get_node_policies (line 1015) | def get_node_policies(self) -> Dict[Tuple[bytes, ShortChannelID], Poli...
method get_node_by_prefix (line 1019) | def get_node_by_prefix(self, prefix):
method clear_forwarding_gossip (line 1026) | def clear_forwarding_gossip(self) -> None:
method filter_orphan_channel_anns (line 1032) | def filter_orphan_channel_anns(
method set_fwd_channel_anns_ts (line 1048) | def set_fwd_channel_anns_ts(self, channel_anns: List[GossipForwardingM...
method get_forwarding_gossip_batch (line 1077) | def get_forwarding_gossip_batch(self) -> List[GossipForwardingMessage]:
method get_gossip_in_timespan (line 1088) | def get_gossip_in_timespan(self, timespan: GossipTimestampFilter) \
method get_channels_in_range (line 1121) | def get_channels_in_range(self, first_blocknum: int, number_of_blocks:...
method get_gossip_for_scid_request (line 1131) | def get_gossip_for_scid_request(self, scid: ShortChannelID) -> List[by...
method to_dict (line 1147) | def to_dict(self) -> dict:
FILE: electrum/coinchooser.py
class PRNG (line 45) | class PRNG:
method __init__ (line 46) | def __init__(self, seed):
method get_bytes (line 50) | def get_bytes(self, n: int) -> bytes:
method randint (line 57) | def randint(self, start, end):
method choice (line 67) | def choice(self, seq):
method shuffle (line 70) | def shuffle(self, x):
class Bucket (line 77) | class Bucket(NamedTuple):
class ScoredCandidate (line 87) | class ScoredCandidate(NamedTuple):
function strip_unneeded (line 93) | def strip_unneeded(bkts: List[Bucket], sufficient_funds: Callable) -> Li...
class CoinChooserBase (line 107) | class CoinChooserBase(Logger):
method __init__ (line 109) | def __init__(self, *, enable_output_value_rounding: bool):
method keys (line 113) | def keys(self, coins: Sequence[PartialTxInput]) -> Sequence[str]:
method bucketize_coins (line 116) | def bucketize_coins(
method penalty_func (line 159) | def penalty_func(
method _change_amounts (line 167) | def _change_amounts(self, tx: PartialTransaction, count: int, fee_esti...
method _change_outputs (line 224) | def _change_outputs(self, tx: PartialTransaction, change_addrs, fee_es...
method _construct_tx_from_selected_buckets (line 239) | def _construct_tx_from_selected_buckets(
method _get_tx_weight (line 267) | def _get_tx_weight(self, buckets: Sequence[Bucket], *, base_weight: in...
method make_tx (line 287) | def make_tx(
method choose_buckets (line 376) | def choose_buckets(self, buckets: List[Bucket],
class CoinChooserRandom (line 382) | class CoinChooserRandom(CoinChooserBase):
method bucket_candidates_any (line 384) | def bucket_candidates_any(
method bucket_candidates_prefer_confirmed (line 426) | def bucket_candidates_prefer_confirmed(
method choose_buckets (line 472) | def choose_buckets(self, buckets, sufficient_funds, penalty_func):
class CoinChooserPrivacy (line 482) | class CoinChooserPrivacy(CoinChooserRandom):
method keys (line 493) | def keys(self, coins):
method penalty_func (line 496) | def penalty_func(self, base_tx, *, tx_from_buckets):
function get_name (line 531) | def get_name(config: 'SimpleConfig') -> str:
function get_coin_chooser (line 538) | def get_coin_chooser(config: 'SimpleConfig') -> CoinChooserBase:
FILE: electrum/commands.py
class NotSynchronizedException (line 93) | class NotSynchronizedException(UserFacingException):
function satoshis_or_max (line 97) | def satoshis_or_max(amount):
function satoshis (line 101) | def satoshis(amount):
function format_satoshis (line 106) | def format_satoshis(x: Union[float, int, Decimal, None]) -> Optional[str]:
class Command (line 116) | class Command:
method __init__ (line 117) | def __init__(self, func, name, s):
method parse_docstring (line 145) | def parse_docstring(self, docstring):
function command (line 158) | def command(s):
class Commands (line 209) | class Commands(Logger):
method __init__ (line 211) | def __init__(self, *, config: 'SimpleConfig',
method _run (line 220) | def _run(self, method, args, password_getter=None, **kwargs):
method getinfo (line 249) | async def getinfo(self):
method stop (line 267) | async def stop(self):
method list_wallets (line 273) | async def list_wallets(self):
method load_wallet (line 285) | async def load_wallet(self, wallet_path=None, password=None):
method close_wallet (line 296) | async def close_wallet(self, wallet_path=None):
method create (line 301) | async def create(self, passphrase=None, password=None, encrypt_file=Tr...
method restore (line 323) | async def restore(self, text, passphrase=None, password=None, encrypt_...
method password (line 347) | async def password(self, password=None, new_password=None, encrypt_fil...
method get (line 367) | async def get(self, key, wallet: Abstract_Wallet = None):
method getconfig (line 376) | async def getconfig(self, key):
method _setconfig_normalize_value (line 388) | def _setconfig_normalize_value(cls, key, value):
method _setconfig (line 398) | def _setconfig(self, key, value):
method setconfig (line 411) | async def setconfig(self, key, value):
method unsetconfig (line 421) | async def unsetconfig(self, key):
method listconfig (line 431) | async def listconfig(self):
method helpconfig (line 436) | async def helpconfig(self, key):
method make_seed (line 452) | async def make_seed(self, nbits=None, language=None, seed_type=None):
method getaddresshistory (line 464) | async def getaddresshistory(self, address):
method unlock (line 475) | async def unlock(self, wallet: Abstract_Wallet = None, password=None):
method listunspent (line 480) | async def listunspent(self, wallet: Abstract_Wallet = None):
method getaddressunspent (line 492) | async def getaddressunspent(self, address):
method serialize (line 503) | async def serialize(self, jsontx):
method signtransaction_with_privkey (line 562) | async def signtransaction_with_privkey(self, tx, privkey):
method signtransaction (line 590) | async def signtransaction(self, tx, password=None, wallet: Abstract_Wa...
method deserialize (line 602) | async def deserialize(self, tx):
method broadcast (line 612) | async def broadcast(self, tx):
method createmultisig (line 623) | async def createmultisig(self, num, pubkeys):
method freeze (line 636) | async def freeze(self, address: str, wallet: Abstract_Wallet = None):
method unfreeze (line 645) | async def unfreeze(self, address: str, wallet: Abstract_Wallet = None):
method freeze_utxo (line 654) | async def freeze_utxo(self, coin: str, wallet: Abstract_Wallet = None):
method unfreeze_utxo (line 664) | async def unfreeze_utxo(self, coin: str, wallet: Abstract_Wallet = None):
method getprivatekeys (line 673) | async def getprivatekeys(self, address, password=None, wallet: Abstrac...
method getprivatekeyforpath (line 687) | async def getprivatekeyforpath(self, path, password=None, wallet: Abst...
method ismine (line 695) | async def ismine(self, address, wallet: Abstract_Wallet = None):
method dumpprivkeys (line 704) | async def dumpprivkeys(self):
method validateaddress (line 709) | async def validateaddress(self, address):
method getpubkeys (line 717) | async def getpubkeys(self, address, wallet: Abstract_Wallet = None):
method getbalance (line 726) | async def getbalance(self, wallet: Abstract_Wallet = None):
method getaddressbalance (line 740) | async def getaddressbalance(self, address):
method getmerkle (line 754) | async def getmerkle(self, txid, height):
method getservers (line 764) | async def getservers(self):
method version (line 769) | async def version(self):
method version_info (line 774) | async def version_info(self):
method getmpk (line 815) | async def getmpk(self, wallet: Abstract_Wallet = None):
method getmasterprivate (line 820) | async def getmasterprivate(self, password=None, wallet: Abstract_Walle...
method convert_xkey (line 825) | async def convert_xkey(self, xkey, xtype):
method getseed (line 838) | async def getseed(self, password=None, wallet: Abstract_Wallet = None):
method importprivkey (line 844) | async def importprivkey(self, privkey, password=None, wallet: Abstract...
method _resolver (line 869) | async def _resolver(self, x, wallet: Abstract_Wallet):
method sweep (line 876) | async def sweep(self, privkey, destination, fee=None, feerate=None, im...
method signmessage (line 901) | async def signmessage(self, address, message, password=None, wallet: A...
method verifymessage (line 912) | async def verifymessage(self, address, signature, message):
method _get_fee_policy (line 926) | def _get_fee_policy(self, fee: str, feerate: str):
method payto (line 940) | async def payto(self, destination, amount, fee=None, feerate=None, fro...
method paytomany (line 972) | async def paytomany(self, outputs, fee=None, feerate=None, from_addr=N...
method get_year_timestamps (line 1017) | def get_year_timestamps(self, year: int) -> dict[str, Any]:
method onchain_capital_gains (line 1027) | async def onchain_capital_gains(self, year=None, wallet: Abstract_Wall...
method bumpfee (line 1040) | async def bumpfee(self, tx, new_fee_rate, from_coins=None, decrease_pa...
method onchain_history (line 1077) | async def onchain_history(
method lightning_history (line 1116) | async def lightning_history(self, wallet: Abstract_Wallet = None):
method setlabel (line 1123) | async def setlabel(self, key, label, wallet: Abstract_Wallet = None):
method listcontacts (line 1134) | async def listcontacts(self, wallet: Abstract_Wallet = None):
method getopenalias (line 1139) | async def getopenalias(self, key, wallet: Abstract_Wallet = None):
method searchcontacts (line 1152) | async def searchcontacts(self, query, wallet: Abstract_Wallet = None):
method listaddresses (line 1165) | async def listaddresses(self, receiving=False, change=False, labels=Fa...
method gettransaction (line 1199) | async def gettransaction(self, txid, wallet: Abstract_Wallet = None):
method encrypt (line 1218) | async def encrypt(self, pubkey, message) -> str:
method decrypt (line 1236) | async def decrypt(self, pubkey, encrypted, password=None, wallet: Abst...
method get_request (line 1250) | async def get_request(self, request_id, wallet: Abstract_Wallet = None):
method get_invoice (line 1261) | async def get_invoice(self, invoice_id, wallet: Abstract_Wallet = None):
method _filter_invoices (line 1272) | def _filter_invoices(self, _list, wallet, pending, expired, paid):
method list_requests (line 1286) | async def list_requests(self, pending=False, expired=False, paid=False...
method list_invoices (line 1298) | async def list_invoices(self, pending=False, expired=False, paid=False...
method createnewaddress (line 1310) | async def createnewaddress(self, wallet: Abstract_Wallet = None):
method changegaplimit (line 1315) | async def changegaplimit(self, new_limit, iknowwhatimdoing=False, wall...
method getminacceptablegap (line 1334) | async def getminacceptablegap(self, wallet: Abstract_Wallet = None):
method getunusedaddress (line 1345) | async def getunusedaddress(self, wallet: Abstract_Wallet = None):
method add_request (line 1351) | async def add_request(self, amount, memo='', expiry=3600, lightning=Fa...
method add_hold_invoice (line 1379) | async def add_hold_invoice(
method settle_hold_invoice (line 1432) | async def settle_hold_invoice(self, preimage: str, wallet: Abstract_Wa...
method cancel_hold_invoice (line 1456) | async def cancel_hold_invoice(self, payment_hash: str, wallet: Abstrac...
method check_hold_invoice (line 1480) | async def check_hold_invoice(self, payment_hash: str, wallet: Abstract...
method export_lightning_preimage (line 1524) | async def export_lightning_preimage(self, payment_hash: str, wallet: '...
method addtransaction (line 1535) | async def addtransaction(self, tx, wallet: Abstract_Wallet = None):
method delete_request (line 1548) | async def delete_request(self, request_id, wallet: Abstract_Wallet = N...
method delete_invoice (line 1556) | async def delete_invoice(self, invoice_id, wallet: Abstract_Wallet = N...
method clear_requests (line 1564) | async def clear_requests(self, wallet: Abstract_Wallet = None):
method clear_invoices (line 1570) | async def clear_invoices(self, wallet: Abstract_Wallet = None):
method notify (line 1576) | async def notify(self, address: str, URL: Optional[str]):
method is_synchronized (line 1593) | async def is_synchronized(self, wallet: Abstract_Wallet = None):
method wait_for_sync (line 1598) | async def wait_for_sync(self, wallet: Abstract_Wallet = None):
method getfeerate (line 1606) | async def getfeerate(self):
method test_inject_fee_etas (line 1623) | async def test_inject_fee_etas(self, fee_est):
method removelocaltx (line 1646) | async def removelocaltx(self, txid, wallet: Abstract_Wallet = None):
method get_tx_status (line 1661) | async def get_tx_status(self, txid, wallet: Abstract_Wallet = None):
method help (line 1674) | async def help(self):
method add_peer (line 1681) | async def add_peer(self, connection_string, timeout=20, gossip=False, ...
method gossip_info (line 1699) | async def gossip_info(self, wallet: Abstract_Wallet = None):
method list_peers (line 1721) | async def list_peers(self, gossip=False, wallet: Abstract_Wallet = None):
method open_channel (line 1737) | async def open_channel(self, connection_string, amount, push_amount=0,...
method decode_invoice (line 1761) | async def decode_invoice(self, invoice: str):
method lnpay (line 1771) | async def lnpay(
method nodeid (line 1826) | async def nodeid(self, wallet: Abstract_Wallet = None):
method list_channels (line 1832) | async def list_channels(self, public: bool = False, private: bool = Fa...
method list_channel_backups (line 1875) | async def list_channel_backups(self, wallet: Abstract_Wallet = None):
method enable_htlc_settle (line 1890) | async def enable_htlc_settle(self, b: bool, wallet: Abstract_Wallet = ...
method clear_ln_blacklist (line 1899) | async def clear_ln_blacklist(self):
method reset_liquidity_hints (line 1904) | async def reset_liquidity_hints(self):
method close_channel (line 1910) | async def close_channel(self, channel_point, force=False, password=Non...
method request_force_close (line 1926) | async def request_force_close(self, channel_point, connection_string=N...
method export_channel_backup (line 1942) | async def export_channel_backup(self, channel_point, password=None, wa...
method import_channel_backup (line 1955) | async def import_channel_backup(self, encrypted, wallet: Abstract_Wall...
method get_channel_ctx (line 1962) | async def get_channel_ctx(self, channel_point, password=None, iknowwha...
method get_watchtower_ctn (line 1982) | async def get_watchtower_ctn(self, channel_point, wallet: Abstract_Wal...
method rebalance_channels (line 1991) | async def rebalance_channels(self, from_scid, dest_scid, amount, passw...
method get_submarine_swap_providers (line 2018) | async def get_submarine_swap_providers(self, query_time=15, wallet: Ab...
method normal_swap (line 2044) | async def normal_swap(self, onchain_amount, lightning_amount, password...
method reverse_swap (line 2084) | async def reverse_swap(
method convert_currency (line 2134) | async def convert_currency(self, from_amount=1, from_ccy='', to_ccy=''):
method send_onion_message (line 2176) | async def send_onion_message(self, node_id_or_blinded_path_hex: str, m...
method get_blinded_path_via (line 2207) | async def get_blinded_path_via(self, node_id: str, dummy_hops: int = 0...
function plugin_command (line 2239) | def plugin_command(s, plugin_name):
function eval_bool (line 2267) | def eval_bool(x: str) -> bool:
function check_txid (line 2280) | def check_txid(txid):
function set_default_subparser (line 2310) | def set_default_subparser(self, name, args=None):
function subparser_call (line 2338) | def subparser_call(self, parser, namespace, values, option_string=None):
function add_network_options (line 2364) | def add_network_options(parser):
function add_global_options (line 2393) | def add_global_options(parser, suppress=False):
function get_simple_parser (line 2425) | def get_simple_parser():
function get_parser (line 2446) | def get_parser():
FILE: electrum/constants.py
function read_json (line 35) | def read_json(filename, default=None):
function create_fallback_node_list (line 49) | def create_fallback_node_list(fallback_nodes_dict: dict[str, dict]) -> L...
class AbstractNet (line 64) | class AbstractNet:
method max_checkpoint (line 85) | def max_checkpoint(cls) -> int:
method rev_genesis_bytes (line 89) | def rev_genesis_bytes(cls) -> bytes:
method set_as_network (line 93) | def set_as_network(cls) -> None:
method DEFAULT_SERVERS (line 99) | def DEFAULT_SERVERS(cls) -> Mapping[str, Mapping[str, str]]:
method FALLBACK_LN_NODES (line 107) | def FALLBACK_LN_NODES(cls) -> Sequence[LNPeerAddr]:
method CHECKPOINTS (line 116) | def CHECKPOINTS(cls) -> Sequence[Tuple[str, int]]:
method datadir_subdir (line 123) | def datadir_subdir(cls) -> Optional[str]:
method cli_flag (line 130) | def cli_flag(cls) -> str:
method config_key (line 135) | def config_key(cls) -> str:
class BitcoinMainnet (line 140) | class BitcoinMainnet(AbstractNet):
method datadir_subdir (line 178) | def datadir_subdir(cls):
class BitcoinTestnet (line 182) | class BitcoinTestnet(AbstractNet):
class BitcoinTestnet4 (line 218) | class BitcoinTestnet4(BitcoinTestnet):
class BitcoinRegtest (line 225) | class BitcoinRegtest(BitcoinTestnet):
class BitcoinSimnet (line 234) | class BitcoinSimnet(BitcoinTestnet):
class BitcoinSignet (line 246) | class BitcoinSignet(BitcoinTestnet):
class BitcoinMutinynet (line 254) | class BitcoinMutinynet(BitcoinTestnet):
FILE: electrum/contacts.py
class AliasNotFoundException (line 43) | class AliasNotFoundException(Exception):
class Contacts (line 47) | class Contacts(dict, Logger):
method __init__ (line 49) | def __init__(self, db: 'WalletDB'):
method save (line 64) | def save(self):
method import_file (line 68) | def import_file(self, path):
method export_file (line 74) | def export_file(self, path):
method __setitem__ (line 77) | def __setitem__(self, key, value):
method pop (line 81) | def pop(self, key):
method resolve (line 88) | async def resolve(self, k) -> dict:
method resolve_openalias (line 107) | async def resolve_openalias(cls, url: str) -> Dict[str, Any]:
method by_name (line 118) | def by_name(self, name):
method fetch_openalias (line 129) | def fetch_openalias(self, config: 'SimpleConfig'):
method _resolve_openalias (line 140) | async def _resolve_openalias(cls, url: str) -> Optional[Tuple[str, str]]:
method find_regex (line 167) | def find_regex(haystack, needle):
method _validate (line 174) | def _validate(self, data):
FILE: electrum/crypto.py
function version_info (line 89) | def version_info() -> Mapping[str, Optional[str]]:
class InvalidPadding (line 110) | class InvalidPadding(Exception):
class CiphertextFormatError (line 114) | class CiphertextFormatError(Exception):
function append_PKCS7_padding (line 118) | def append_PKCS7_padding(data: bytes) -> bytes:
function strip_PKCS7_padding (line 124) | def strip_PKCS7_padding(data: bytes) -> bytes:
function aes_encrypt_with_iv (line 137) | def aes_encrypt_with_iv(key: bytes, iv: bytes, data: bytes) -> bytes:
function aes_decrypt_with_iv (line 155) | def aes_decrypt_with_iv(key: bytes, iv: bytes, data: bytes) -> bytes:
function EncodeAES_bytes (line 176) | def EncodeAES_bytes(secret: bytes, msg: bytes) -> bytes:
function DecodeAES_bytes (line 183) | def DecodeAES_bytes(secret: bytes, ciphertext: bytes) -> bytes:
class UnexpectedPasswordHashVersion (line 197) | class UnexpectedPasswordHashVersion(InvalidPassword, WalletFileException):
method __init__ (line 198) | def __init__(self, version):
method __str__ (line 203) | def __str__(self):
class UnsupportedPasswordHashVersion (line 210) | class UnsupportedPasswordHashVersion(InvalidPassword, WalletFileException):
method __init__ (line 211) | def __init__(self, version):
method __str__ (line 216) | def __str__(self):
function _hash_password (line 224) | def _hash_password(password: Union[bytes, str], *, version: int) -> bytes:
function _pw_encode_raw (line 235) | def _pw_encode_raw(data: bytes, password: Union[bytes, str], *, version:...
function _pw_decode_raw (line 245) | def _pw_decode_raw(data_bytes: bytes, password: Union[bytes, str], *, ve...
function pw_encode_bytes (line 258) | def pw_encode_bytes(data: bytes, password: Union[bytes, str], *, version...
function pw_decode_bytes (line 265) | def pw_decode_bytes(data: str, password: Union[bytes, str], *, version:i...
function pw_encode_with_version_and_mac (line 276) | def pw_encode_with_version_and_mac(data: bytes, password: Union[bytes, s...
function pw_decode_with_version_and_mac (line 287) | def pw_decode_with_version_and_mac(data: str, password: Union[bytes, str...
function pw_encode (line 304) | def pw_encode(data: str, password: Union[bytes, str, None], *, version: ...
function pw_decode (line 312) | def pw_decode(data: str, password: Union[bytes, str, None], *, version: ...
function sha256 (line 324) | def sha256(x: Union[bytes, str]) -> bytes:
function sha256d (line 329) | def sha256d(x: Union[bytes, str]) -> bytes:
function hash_160 (line 335) | def hash_160(x: bytes) -> bytes:
function ripemd (line 338) | def ripemd(x: bytes) -> bytes:
function hmac_oneshot (line 353) | def hmac_oneshot(key: bytes, msg: bytes, digest) -> bytes:
function chacha20_poly1305_encrypt (line 357) | def chacha20_poly1305_encrypt(
function chacha20_poly1305_decrypt (line 382) | def chacha20_poly1305_decrypt(
function chacha20_encrypt (line 410) | def chacha20_encrypt(*, key: bytes, nonce: bytes, data: bytes) -> bytes:
function chacha20_decrypt (line 431) | def chacha20_decrypt(*, key: bytes, nonce: bytes, data: bytes) -> bytes:
function ecies_encrypt_message (line 449) | def ecies_encrypt_message(
function ecies_decrypt_message (line 470) | def ecies_decrypt_message(
function get_ecdh (line 497) | def get_ecdh(priv: bytes, pub: bytes) -> bytes:
function privkey_to_pubkey (line 501) | def privkey_to_pubkey(priv: bytes) -> bytes:
FILE: electrum/daemon.py
class DaemonNotRunning (line 65) | class DaemonNotRunning(Exception):
function get_rpcsock_defaultpath (line 69) | def get_rpcsock_defaultpath(config: SimpleConfig):
function get_rpcsock_default_type (line 73) | def get_rpcsock_default_type(config: SimpleConfig):
function get_lockfile (line 84) | def get_lockfile(config: SimpleConfig):
function remove_lockfile (line 88) | def remove_lockfile(lockfile):
function get_file_descriptor (line 92) | def get_file_descriptor(config: SimpleConfig):
function request (line 112) | def request(config: SimpleConfig, endpoint, args=(), timeout: Union[floa...
function wait_until_daemon_becomes_ready (line 167) | def wait_until_daemon_becomes_ready(*, config: SimpleConfig, timeout=5) ...
function get_rpc_credentials (line 180) | def get_rpc_credentials(config: SimpleConfig) -> Tuple[str, str]:
class AuthenticationError (line 196) | class AuthenticationError(Exception):
class AuthenticationInvalidOrMissing (line 200) | class AuthenticationInvalidOrMissing(AuthenticationError):
class AuthenticationCredentialsInvalid (line 204) | class AuthenticationCredentialsInvalid(AuthenticationError):
class AuthenticatedServer (line 208) | class AuthenticatedServer(Logger):
method __init__ (line 210) | def __init__(self, rpc_user, rpc_password):
method register_method (line 217) | def register_method(self, name: str, f):
method authenticate (line 221) | async def authenticate(self, headers):
method handle (line 239) | async def handle(self, request):
class CommandsServer (line 287) | class CommandsServer(AuthenticatedServer):
method __init__ (line 289) | def __init__(self, daemon: 'Daemon', fd):
method _socket_config_str (line 309) | def _socket_config_str(self) -> str:
method run (line 317) | async def run(self):
method ping (line 341) | async def ping(self):
method gui (line 344) | async def gui(self, config_options):
method run_cmdline (line 361) | async def run_cmdline(self, config_options):
class Daemon (line 385) | class Daemon(Logger):
method __init__ (line 391) | def __init__(
method _run (line 430) | async def _run(self):
method start_network (line 444) | def start_network(self):
method _wallet_key_from_path (line 454) | def _wallet_key_from_path(path) -> str:
method with_wallet_lock (line 476) | def with_wallet_lock(func):
method load_wallet (line 483) | def load_wallet(
method _load_wallet (line 522) | def _load_wallet(
method add_wallet (line 548) | def add_wallet(self, wallet: Abstract_Wallet) -> None:
method get_wallet (line 554) | def get_wallet(self, path: str) -> Optional[Abstract_Wallet]:
method get_wallets (line 559) | def get_wallets(self) -> Dict[str, Abstract_Wallet]:
method delete_wallet (line 562) | def delete_wallet(self, path: str) -> bool:
method stop_wallet (line 572) | def stop_wallet(self, path: str) -> bool:
method _stop_wallet (line 579) | async def _stop_wallet(self, path: str) -> bool:
method run_daemon (line 594) | def run_daemon(self):
method stop (line 612) | async def stop(self):
method run_gui (line 643) | def run_gui(self) -> None:
method check_password_for_directory (line 670) | def check_password_for_directory(self, *, old_password, new_password=N...
method update_password_for_directory (line 721) | def update_password_for_directory(
method update_recently_opened_wallets (line 744) | def update_recently_opened_wallets(self, wallet_path, *, remove: bool ...
FILE: electrum/descriptor.py
class ExpandedScripts (line 52) | class ExpandedScripts:
method __init__ (line 54) | def __init__(
method scriptcode_for_sighash (line 68) | def scriptcode_for_sighash(self) -> Optional[bytes]:
method scriptcode_for_sighash (line 74) | def scriptcode_for_sighash(self, value: Optional[bytes]):
method address (line 77) | def address(self, *, net=None) -> Optional[str]:
class ScriptSolutionInner (line 81) | class ScriptSolutionInner(NamedTuple):
class ScriptSolutionTop (line 85) | class ScriptSolutionTop(NamedTuple):
class MissingSolutionPiece (line 90) | class MissingSolutionPiece(Exception): pass
function PolyMod (line 93) | def PolyMod(c: int, val: int) -> int:
function DescriptorChecksum (line 118) | def DescriptorChecksum(desc: str) -> str:
function AddChecksum (line 151) | def AddChecksum(desc: str) -> str:
class PubkeyProvider (line 161) | class PubkeyProvider(object):
method __init__ (line 167) | def __init__(
method parse (line 202) | def parse(cls, s: str) -> 'PubkeyProvider':
method to_string (line 225) | def to_string(self) -> str:
method get_pubkey_bytes (line 239) | def get_pubkey_bytes(self, *, pos: Optional[int] = None) -> bytes:
method get_full_derivation_path (line 260) | def get_full_derivation_path(self, *, pos: Optional[int] = None) -> str:
method get_full_derivation_int_list (line 272) | def get_full_derivation_int_list(self, *, pos: Optional[int] = None) -...
method get_der_suffix_int_list (line 283) | def get_der_suffix_int_list(self, *, pos: Optional[int] = None) -> Lis...
method __lt__ (line 291) | def __lt__(self, other: 'PubkeyProvider') -> bool:
method is_range (line 294) | def is_range(self) -> bool:
method has_uncompressed_pubkey (line 301) | def has_uncompressed_pubkey(self) -> bool:
class Descriptor (line 307) | class Descriptor(object):
method __init__ (line 317) | def __init__(
method to_string_no_checksum (line 332) | def to_string_no_checksum(self) -> str:
method to_string (line 344) | def to_string(self) -> str:
method expand (line 352) | def expand(self, *, pos: Optional[int] = None) -> "ExpandedScripts":
method _satisfy_inner (line 358) | def _satisfy_inner(
method satisfy (line 366) | def satisfy(
method get_satisfaction_progress (line 390) | def get_satisfaction_progress(
method is_range (line 406) | def is_range(self) -> bool:
method is_segwit (line 415) | def is_segwit(self) -> bool:
method is_taproot (line 418) | def is_taproot(self) -> bool:
method get_all_pubkeys (line 421) | def get_all_pubkeys(self) -> Set[bytes]:
method get_simple_singlesig (line 429) | def get_simple_singlesig(self) -> Optional['Descriptor']:
method get_simple_multisig (line 438) | def get_simple_multisig(self) -> Optional['MultisigDescriptor']:
method to_legacy_electrum_script_type (line 444) | def to_legacy_electrum_script_type(self) -> str:
class PKDescriptor (line 463) | class PKDescriptor(Descriptor):
method __init__ (line 467) | def __init__(
method expand (line 476) | def expand(self, *, pos: Optional[int] = None) -> "ExpandedScripts":
method _satisfy_inner (line 481) | def _satisfy_inner(self, *, sigdata=None, allow_dummy=False) -> Script...
method get_satisfaction_progress (line 495) | def get_satisfaction_progress(self, *, sigdata=None) -> Tuple[int, int]:
method get_simple_singlesig (line 500) | def get_simple_singlesig(self) -> Optional['Descriptor']:
class PKHDescriptor (line 504) | class PKHDescriptor(Descriptor):
method __init__ (line 508) | def __init__(
method expand (line 517) | def expand(self, *, pos: Optional[int] = None) -> "ExpandedScripts":
method _satisfy_inner (line 523) | def _satisfy_inner(self, *, sigdata=None, allow_dummy=False) -> Script...
method get_satisfaction_progress (line 537) | def get_satisfaction_progress(self, *, sigdata=None) -> Tuple[int, int]:
method get_simple_singlesig (line 542) | def get_simple_singlesig(self) -> Optional['Descriptor']:
class WPKHDescriptor (line 546) | class WPKHDescriptor(Descriptor):
method __init__ (line 550) | def __init__(
method expand (line 559) | def expand(self, *, pos: Optional[int] = None) -> "ExpandedScripts":
method _satisfy_inner (line 568) | def _satisfy_inner(self, *, sigdata=None, allow_dummy=False) -> Script...
method get_satisfaction_progress (line 582) | def get_satisfaction_progress(self, *, sigdata=None) -> Tuple[int, int]:
method is_segwit (line 587) | def is_segwit(self) -> bool:
method get_simple_singlesig (line 590) | def get_simple_singlesig(self) -> Optional['Descriptor']:
class MultisigDescriptor (line 594) | class MultisigDescriptor(Descriptor):
method __init__ (line 598) | def __init__(
method to_string_no_checksum (line 624) | def to_string_no_checksum(self) -> str:
method expand (line 627) | def expand(self, *, pos: Optional[int] = None) -> "ExpandedScripts":
method _satisfy_inner (line 634) | def _satisfy_inner(self, *, sigdata=None, allow_dummy=False) -> Script...
method get_satisfaction_progress (line 657) | def get_satisfaction_progress(self, *, sigdata=None) -> Tuple[int, int]:
method get_simple_multisig (line 662) | def get_simple_multisig(self) -> Optional['MultisigDescriptor']:
class SHDescriptor (line 666) | class SHDescriptor(Descriptor):
method __init__ (line 670) | def __init__(
method expand (line 679) | def expand(self, *, pos: Optional[int] = None) -> "ExpandedScripts":
method _satisfy_inner (line 692) | def _satisfy_inner(self, *, sigdata=None, allow_dummy=False) -> Script...
method satisfy (line 695) | def satisfy(self, *, sigdata=None, allow_dummy=False) -> ScriptSolutio...
class WSHDescriptor (line 713) | class WSHDescriptor(Descriptor):
method __init__ (line 717) | def __init__(
method expand (line 726) | def expand(self, *, pos: Optional[int] = None) -> "ExpandedScripts":
method _satisfy_inner (line 736) | def _satisfy_inner(self, *, sigdata=None, allow_dummy=False) -> Script...
method satisfy (line 739) | def satisfy(self, *, sigdata=None, allow_dummy=False) -> ScriptSolutio...
method is_segwit (line 749) | def is_segwit(self) -> bool:
class TRDescriptor (line 753) | class TRDescriptor(Descriptor):
method __init__ (line 757) | def __init__(
method to_string_no_checksum (line 785) | def to_string_no_checksum(self) -> str:
method is_segwit (line 798) | def is_segwit(self) -> bool:
method is_taproot (line 801) | def is_taproot(self) -> bool:
method expand (line 805) | def expand(self, *, pos: Optional[int] = None) -> "ExpandedScripts":
method get_max_tree_depth (line 822) | def get_max_tree_depth(self) -> Optional[int]:
function _get_func_expr (line 833) | def _get_func_expr(s: str) -> Tuple[str, str]:
function _get_const (line 849) | def _get_const(s: str, const: str) -> str:
function _get_expr (line 864) | def _get_expr(s: str) -> Tuple[str, str]:
function parse_pubkey (line 886) | def parse_pubkey(expr: str, *, ctx: '_ParseDescriptorContext') -> Tuple[...
class _ParseDescriptorContext (line 906) | class _ParseDescriptorContext(Enum):
function _parse_descriptor (line 921) | def _parse_descriptor(desc: str, *, ctx: '_ParseDescriptorContext') -> '...
function parse_descriptor (line 1012) | def parse_descriptor(desc: str) -> 'Descriptor':
class NotLegacySinglesigScriptType (line 1034) | class NotLegacySinglesigScriptType(Exception): pass
function get_singlesig_descriptor_from_legacy_leaf (line 1037) | def get_singlesig_descriptor_from_legacy_leaf(*, pubkey: str, script_typ...
function create_dummy_descriptor_from_address (line 1052) | def create_dummy_descriptor_from_address(addr: Optional[str]) -> 'Descri...
FILE: electrum/dns_hacks.py
function configure_dns_resolver (line 22) | def configure_dns_resolver() -> None:
function _prepare_windows_dns_hack (line 38) | def _prepare_windows_dns_hack():
function _is_force_system_dns_for_host (line 47) | def _is_force_system_dns_for_host(host: str) -> bool:
function _fast_getaddrinfo (line 51) | def _fast_getaddrinfo(host, *args, **kwargs):
FILE: electrum/dnssec.py
function _check_query (line 72) | async def _check_query(ns, sub, _type, keys) -> dns.rrset.RRset:
function _get_and_validate (line 91) | async def _get_and_validate(ns, url, _type) -> dns.rrset.RRset:
function query (line 141) | async def query(url: str, rtype: dns.rdatatype.RdataType) -> Tuple[dns.r...
FILE: electrum/exchange_rate.py
class ExchangeBase (line 45) | class ExchangeBase(Logger):
method __init__ (line 47) | def __init__(self, on_quotes, on_history):
method get_raw (line 55) | async def get_raw(self, site, get_string):
method get_json (line 65) | async def get_json(self, site, get_string):
method get_csv (line 76) | async def get_csv(self, site, get_string):
method name (line 81) | def name(self):
method update_safe (line 84) | async def update_safe(self, ccy: str) -> None:
method _read_historical_rates_from_file (line 102) | def _read_historical_rates_from_file(
method read_historical_rates (line 120) | def read_historical_rates(self, ccy: str, cache_dir: str) -> Optional[...
method _write_historical_rates_to_file (line 135) | def _write_historical_rates_to_file(
method get_historical_rates_safe (line 149) | async def get_historical_rates_safe(self, ccy: str, cache_dir: str) ->...
method get_historical_rates (line 176) | def get_historical_rates(self, ccy: str, cache_dir: str) -> None:
method history_ccys (line 185) | def history_ccys(self) -> Sequence[str]:
method historical_rate (line 188) | def historical_rate(self, ccy: str, d_t: datetime) -> Decimal:
method request_history (line 197) | async def request_history(self, ccy: str) -> Dict[str, Union[str, floa...
method get_rates (line 200) | async def get_rates(self, ccy: str) -> Mapping[str, Optional[Decimal]]:
method get_currencies (line 203) | async def get_currencies(self) -> Sequence[str]:
method get_cached_spot_quote (line 207) | def get_cached_spot_quote(self, ccy: str) -> Decimal:
class Yadio (line 220) | class Yadio(ExchangeBase):
method get_currencies (line 222) | async def get_currencies(self):
method get_rates (line 226) | async def get_rates(self, ccy: str) -> Mapping[str, Optional[Decimal]]:
class BitcoinAverage (line 231) | class BitcoinAverage(ExchangeBase):
method get_rates (line 235) | async def get_rates(self, ccy):
class Bitcointoyou (line 241) | class Bitcointoyou(ExchangeBase):
method get_rates (line 243) | async def get_rates(self, ccy):
class BitcoinVenezuela (line 248) | class BitcoinVenezuela(ExchangeBase):
method get_rates (line 250) | async def get_rates(self, ccy):
method history_ccys (line 256) | def history_ccys(self):
method request_history (line 259) | async def request_history(self, ccy):
class Bitbank (line 264) | class Bitbank(ExchangeBase):
method get_rates (line 266) | async def get_rates(self, ccy):
class BitFinex (line 271) | class BitFinex(ExchangeBase):
method get_currencies (line 273) | async def get_currencies(self):
method history_ccys (line 281) | def history_ccys(self):
method get_rates (line 284) | async def get_rates(self, ccy):
method request_history (line 291) | async def request_history(self, ccy):
class BitFlyer (line 300) | class BitFlyer(ExchangeBase):
method get_rates (line 302) | async def get_rates(self, ccy):
class BitPay (line 307) | class BitPay(ExchangeBase):
method get_rates (line 309) | async def get_rates(self, ccy):
class Bitso (line 314) | class Bitso(ExchangeBase):
method get_rates (line 316) | async def get_rates(self, ccy):
class BitStamp (line 321) | class BitStamp(ExchangeBase):
method get_currencies (line 323) | async def get_currencies(self):
method get_rates (line 333) | async def get_rates(self, ccy):
method history_ccys (line 340) | def history_ccys(self):
method request_history (line 343) | async def request_history(self, ccy):
class Bitvalor (line 369) | class Bitvalor(ExchangeBase):
method get_rates (line 371) | async def get_rates(self,ccy):
class BlockchainInfo (line 376) | class BlockchainInfo(ExchangeBase):
method get_rates (line 378) | async def get_rates(self, ccy):
class Bylls (line 383) | class Bylls(ExchangeBase):
method get_rates (line 385) | async def get_rates(self, ccy):
class Coinbase (line 390) | class Coinbase(ExchangeBase):
method get_rates (line 392) | async def get_rates(self, ccy):
class CoinCap (line 398) | class CoinCap(ExchangeBase):
method get_rates (line 400) | async def get_rates(self, ccy):
method history_ccys (line 404) | def history_ccys(self):
method request_history (line 407) | async def request_history(self, ccy):
class CoinDesk (line 416) | class CoinDesk(ExchangeBase):
method get_currencies (line 418) | async def get_currencies(self):
method get_rates (line 423) | async def get_rates(self, ccy):
method history_starts (line 429) | def history_starts(self):
method history_ccys (line 432) | def history_ccys(self):
method request_history (line 435) | async def request_history(self, ccy):
class CoinGecko (line 445) | class CoinGecko(ExchangeBase):
method get_rates (line 447) | async def get_rates(self, ccy):
method history_ccys (line 452) | def history_ccys(self):
method request_history (line 456) | async def request_history(self, ccy):
class Bit2C (line 469) | class Bit2C(ExchangeBase):
method get_rates (line 471) | async def get_rates(self, ccy):
method history_ccys (line 475) | def history_ccys(self):
method request_history (line 478) | async def request_history(self, ccy):
class CointraderMonitor (line 486) | class CointraderMonitor(ExchangeBase):
method get_rates (line 488) | async def get_rates(self, ccy):
class itBit (line 493) | class itBit(ExchangeBase):
method get_rates (line 495) | async def get_rates(self, ccy):
class Kraken (line 504) | class Kraken(ExchangeBase):
method get_rates (line 506) | async def get_rates(self, ccy):
class MercadoBitcoin (line 520) | class MercadoBitcoin(ExchangeBase):
method get_rates (line 522) | async def get_rates(self, ccy):
class Winkdex (line 527) | class Winkdex(ExchangeBase):
method get_rates (line 529) | async def get_rates(self, ccy):
method history_ccys (line 533) | def history_ccys(self):
method request_history (line 536) | async def request_history(self, ccy):
class Zaif (line 544) | class Zaif(ExchangeBase):
method get_rates (line 545) | async def get_rates(self, ccy):
class Bitragem (line 550) | class Bitragem(ExchangeBase):
method get_rates (line 552) | async def get_rates(self,ccy):
class Biscoint (line 557) | class Biscoint(ExchangeBase):
method get_rates (line 559) | async def get_rates(self,ccy):
class Walltime (line 564) | class Walltime(ExchangeBase):
method get_rates (line 566) | async def get_rates(self, ccy):
function dictinvert (line 572) | def dictinvert(d):
function get_exchanges_and_currencies (line 580) | def get_exchanges_and_currencies():
function get_exchanges_by_ccy (line 625) | def get_exchanges_by_ccy(history=True):
class FxThread (line 637) | class FxThread(ThreadJob, EventListener, NetworkRetryManager[str]):
method __init__ (line 639) | def __init__(self, *, config: SimpleConfig):
method on_event_proxy_set (line 661) | def on_event_proxy_set(self, *args):
method get_currencies (line 666) | def get_currencies(history: bool) -> Sequence[str]:
method get_exchanges_by_ccy (line 671) | def get_exchanges_by_ccy(ccy: str, history: bool) -> Sequence[str]:
method remove_thousands_separator (line 676) | def remove_thousands_separator(text: str) -> str:
method ccy_amount_str (line 679) | def ccy_amount_str(self, amount, *, add_thousands_sep: bool = False, c...
method ccy_precision (line 695) | def ccy_precision(self, ccy=None) -> int:
method run (line 698) | async def run(self):
method is_enabled (line 724) | def is_enabled(self) -> bool:
method set_enabled (line 727) | def set_enabled(self, b: bool) -> None:
method can_have_history (line 731) | def can_have_history(self):
method has_history (line 734) | def has_history(self) -> bool:
method get_currency (line 737) | def get_currency(self) -> str:
method config_exchange (line 741) | def config_exchange(self):
method set_currency (line 744) | def set_currency(self, ccy: str):
method trigger_update (line 750) | def trigger_update(self):
method set_exchange (line 755) | def set_exchange(self, name):
method on_quotes (line 767) | def on_quotes(self, *, received_new_data: bool = False):
method on_history (line 772) | def on_history(self):
method exchange_rate (line 775) | def exchange_rate(self) -> Decimal:
method format_amount (line 781) | def format_amount(self, btc_balance, *, timestamp: int = None) -> str:
method format_amount_and_units (line 788) | def format_amount_and_units(self, btc_balance, *, timestamp: int = Non...
method get_fiat_status_text (line 795) | def get_fiat_status_text(self, btc_balance, base_unit, decimal_point):
method fiat_value (line 803) | def fiat_value(self, satoshis, rate) -> Decimal:
method value_str (line 806) | def value_str(self, satoshis, rate, *, add_thousands_sep: bool = None)...
method format_fiat (line 810) | def format_fiat(self, value: Decimal, *, add_thousands_sep: bool = Non...
method history_rate (line 817) | def history_rate(self, d_t: Optional[datetime]) -> Decimal:
method historical_value_str (line 830) | def historical_value_str(self, satoshis, d_t: Optional[datetime]) -> str:
method historical_value (line 833) | def historical_value(self, satoshis, d_t: Optional[datetime]) -> Decimal:
method timestamp_rate (line 836) | def timestamp_rate(self, timestamp: Optional[int]) -> Decimal:
FILE: electrum/fee_policy.py
function closest_index (line 49) | def closest_index(value, array) -> int:
class FeeMethod (line 54) | class FeeMethod(IntEnum):
method slider_values (line 62) | def slider_values(cls):
method name_for_GUI (line 65) | def name_for_GUI(self):
method slider_index_of_method (line 75) | def slider_index_of_method(cls, method):
class FeePolicy (line 83) | class FeePolicy(Logger):
method __init__ (line 86) | def __init__(self, descriptor: str):
method __repr__ (line 97) | def __repr__(self):
method get_descriptor (line 100) | def get_descriptor(self) -> str:
method set_method (line 103) | def set_method(self, method: FeeMethod):
method _get_array (line 116) | def _get_array(self) -> Sequence[int]:
method set_value_from_slider_pos (line 126) | def set_value_from_slider_pos(self, slider_pos: int):
method get_slider_pos (line 131) | def get_slider_pos(self) -> int:
method get_slider_max (line 135) | def get_slider_max(self) -> int:
method use_dynamic_estimates (line 141) | def use_dynamic_estimates(self):
method depth_target (line 145) | def depth_target(cls, slider_pos: int) -> int:
method eta_target (line 151) | def eta_target(self, slider_pos: int) -> int:
method eta_tooltip (line 156) | def eta_tooltip(cls, x):
method get_target_text (line 168) | def get_target_text(self):
method get_estimate_text (line 180) | def get_estimate_text(self, network: 'Network') -> str:
method get_tooltip (line 201) | def get_tooltip(self, network: 'Network'):
method depth_tooltip (line 210) | def depth_tooltip(cls, depth: Optional[int]) -> str:
method get_depth_mb_str (line 218) | def get_depth_mb_str(cls, depth: int) -> str:
method fee_per_kb (line 223) | def fee_per_kb(self, network: 'Network') -> Optional[int]:
method fee_per_byte (line 247) | def fee_per_byte(self, network: 'Network') -> Optional[int]:
method estimate_fee (line 254) | def estimate_fee(
method estimate_fee_for_feerate (line 271) | def estimate_fee_for_feerate(
class FixedFeePolicy (line 287) | class FixedFeePolicy(FeePolicy):
method __init__ (line 288) | def __init__(self, fee):
function impose_hard_limits_on_fee (line 292) | def impose_hard_limits_on_fee(func):
class FeeHistogram (line 305) | class FeeHistogram:
method __init__ (line 307) | def __init__(self):
method has_data (line 310) | def has_data(self) -> bool:
method set_data (line 313) | def set_data(self, data):
method fee_to_depth (line 316) | def fee_to_depth(self, target_fee: Real) -> Optional[int]:
method depth_target_to_fee (line 331) | def depth_target_to_fee(self, target: int) -> Optional[int]:
method depth_to_fee (line 353) | def depth_to_fee(self, slider_pos) -> Optional[int]:
method get_capped_data (line 358) | def get_capped_data(self):
class FeeTimeEstimates (line 380) | class FeeTimeEstimates:
method __init__ (line 382) | def __init__(self):
method get_data (line 385) | def get_data(self):
method has_data (line 388) | def has_data(self) -> bool:
method set_data (line 398) | def set_data(self, nblock_target: int, fee_per_kb: int):
method fee_to_eta (line 403) | def fee_to_eta(self, fee_per_kb: Optional[int]) -> int:
method eta_to_fee (line 420) | def eta_to_fee(self, slider_pos) -> Optional[int]:
method eta_target_to_fee (line 432) | def eta_target_to_fee(self, num_blocks: int) -> Optional[int]:
FILE: electrum/gui/__init__.py
class BaseElectrumGui (line 16) | class BaseElectrumGui:
method __init__ (line 17) | def __init__(self, *, config: 'SimpleConfig', daemon: 'Daemon', plugin...
method main (line 22) | def main(self) -> None:
method stop (line 25) | def stop(self) -> None:
method version_info (line 32) | def version_info(cls) -> Mapping[str, Optional[str]]:
FILE: electrum/gui/common_qt/i18n.py
class ElectrumTranslator (line 6) | class ElectrumTranslator(QTranslator):
method __init__ (line 8) | def __init__(self, parent=None):
method translate (line 16) | def translate(self, context, source_text: str, disambiguation, n):
FILE: electrum/gui/common_qt/plugins.py
class PluginQObject (line 13) | class PluginQObject(QObject):
method __init__ (line 20) | def __init__(self, plugin: 'BasePlugin', parent: Optional['ElectrumQml...
method name (line 29) | def name(self): return self._name
method busy (line 32) | def busy(self): return self._busy
method pluginEnabled (line 37) | def pluginEnabled(self): return self.plugin.is_enabled()
method pluginEnabled (line 40) | def pluginEnabled(self, enabled):
FILE: electrum/gui/common_qt/util.py
function get_font_id (line 19) | def get_font_id(filename: str) -> int:
function draw_qr (line 31) | def draw_qr(
function paintQR (line 97) | def paintQR(data) -> Optional[QImage]:
class TaskThread (line 125) | class TaskThread(QThread, Logger):
class Task (line 129) | class Task(NamedTuple):
method __init__ (line 138) | def __init__(self, parent, on_error=None):
method add (line 148) | def add(self, task, on_success=None, on_done=None, on_error=None, *, c...
method run (line 156) | def run(self):
method on_done (line 170) | def on_done(self, result, cb_done, cb_result):
method stop (line 177) | def stop(self):
class QtEventListener (line 197) | class QtEventListener(EventListener):
method register_callbacks (line 200) | def register_callbacks(self):
method unregister_callbacks (line 204) | def unregister_callbacks(self):
method on_qt_callback_signal (line 212) | def on_qt_callback_signal(self, args):
function qt_event_listener (line 218) | def qt_event_listener(func):
FILE: electrum/gui/default_lang.py
function get_default_language (line 21) | def get_default_language(*, gui_name: Optional[str] = None) -> str:
FILE: electrum/gui/messages.py
function to_rtf (line 5) | def to_rtf(msg):
FILE: electrum/gui/qml/__init__.py
class ElectrumGui (line 41) | class ElectrumGui(BaseElectrumGui, Logger):
method __init__ (line 43) | def __init__(self, config: 'SimpleConfig', daemon: 'Daemon', plugins: ...
method close (line 91) | def close(self):
method main (line 94) | def main(self):
method _handle_sigint (line 104) | def _handle_sigint(self):
method stop (line 108) | def stop(self):
FILE: electrum/gui/qml/auth.py
function auth_protect (line 8) | def auth_protect(func=None, reject=None, method='payment_auth', message=...
class AuthMixin (line 36) | class AuthMixin:
method authProceed (line 41) | def authProceed(self):
method authCancel (line 55) | def authCancel(self):
FILE: electrum/gui/qml/java_classes/org/electrum/biometry/BiometricActivity.java
class BiometricActivity (line 27) | public class BiometricActivity extends Activity {
method onCreate (line 34) | @Override
method handleIntent (line 48) | private void handleIntent() {
method handleAuthenticationSuccess (line 120) | private void handleAuthenticationSuccess(BiometricPrompt.Authenticatio...
method getSecretKey (line 148) | private SecretKey getSecretKey() throws Exception {
method genSecretKey (line 154) | private SecretKey genSecretKey() throws Exception {
method getCipher (line 170) | private Cipher getCipher() throws Exception {
FILE: electrum/gui/qml/java_classes/org/electrum/biometry/BiometricHelper.java
class BiometricHelper (line 9) | public class BiometricHelper {
method isAvailable (line 10) | public static boolean isAvailable(Context context) {
FILE: electrum/gui/qml/java_classes/org/electrum/qr/SimpleScannerActivity.java
class SimpleScannerActivity (line 32) | public class SimpleScannerActivity extends Activity {
method onCreate (line 40) | @Override
method onResume (line 76) | @Override
method onPause (line 87) | @Override
method startCamera (line 95) | private void startCamera() {
method setResultAndClose (line 115) | private void setResultAndClose(Result scanResult, String textOnly) {
method hasPermission (line 135) | private boolean hasPermission() {
method requestPermission (line 141) | private void requestPermission() {
method onRequestPermissionsResult (line 147) | @Override
method enforcesEdgeToEdge (line 165) | private boolean enforcesEdgeToEdge() {
method setupEdgeToEdge (line 170) | private void setupEdgeToEdge() {
FILE: electrum/gui/qml/qeaddressdetails.py
class QEAddressDetails (line 12) | class QEAddressDetails(AuthMixin, QObject):
method __init__ (line 18) | def __init__(self, parent=None):
method wallet (line 39) | def wallet(self):
method wallet (line 43) | def wallet(self, wallet: QEWallet):
method address (line 50) | def address(self):
method address (line 54) | def address(self, address: str):
method scriptType (line 62) | def scriptType(self):
method balance (line 66) | def balance(self):
method pubkeys (line 70) | def pubkeys(self):
method privkey (line 74) | def privkey(self):
method derivationPath (line 78) | def derivationPath(self):
method numTx (line 82) | def numTx(self):
method canDelete (line 86) | def canDelete(self):
method isFrozen (line 91) | def isFrozen(self):
method label (line 96) | def label(self):
method freeze (line 100) | def freeze(self, freeze: bool):
method setLabel (line 108) | def setLabel(self, label: str):
method historyModel (line 116) | def historyModel(self):
method requestShowPrivateKey (line 123) | def requestShowPrivateKey(self):
method retrieve_private_key (line 127) | def retrieve_private_key(self):
method deleteAddress (line 137) | def deleteAddress(self):
method update (line 147) | def update(self):
FILE: electrum/gui/qml/qeaddresslistmodel.py
class QEAddressCoinFilterProxyModel (line 20) | class QEAddressCoinFilterProxyModel(QSortFilterProxyModel):
method __init__ (line 23) | def __init__(self, parent_model, parent=None):
method count (line 34) | def count(self):
method filterAcceptsRow (line 37) | def filterAcceptsRow(self, s_row, s_parent):
method showAddressesCoins (line 65) | def showAddressesCoins(self) -> int:
method showAddressesCoins (line 74) | def showAddressesCoins(self, show_addresses_coins: int):
method showUsed (line 86) | def showUsed(self) -> bool:
method showUsed (line 90) | def showUsed(self, show_used: bool):
method filterText (line 98) | def filterText(self) -> str:
method filterText (line 102) | def filterText(self, filter_text: str):
class QEAddressCoinListModel (line 109) | class QEAddressCoinListModel(QAbstractListModel, QtEventListener):
method __init__ (line 119) | def __init__(self, wallet: 'Abstract_Wallet', parent=None):
method on_destroy (line 133) | def on_destroy(self):
method on_event_labels_received (line 137) | def on_event_labels_received(self, wallet, labels):
method rowCount (line 141) | def rowCount(self, index):
method roleNames (line 144) | def roleNames(self):
method data (line 147) | def data(self, index, role):
method clear (line 160) | def clear(self):
method addr_to_model (line 165) | def addr_to_model(self, addrtype: str, addridx: int, address: str):
method coin_to_model (line 178) | def coin_to_model(self, addrtype: str, coin: 'PartialTxInput'):
method setDirty (line 200) | def setDirty(self):
method initModel (line 206) | def initModel(self, force: bool = False):
method updateAddress (line 241) | def updateAddress(self, address):
method deleteAddress (line 248) | def deleteAddress(self, address):
method updateCoin (line 262) | def updateCoin(self, outpoint):
method do_update (line 268) | def do_update(self, modelindex, modelitem):
method filterModel (line 280) | def filterModel(self):
method setFrozenForItems (line 286) | def setFrozenForItems(self, freeze: bool, items: List[str]):
FILE: electrum/gui/qml/qeapp.py
class QEAppController (line 71) | class QEAppController(BaseCrashReporter, QObject):
method __init__ (line 84) | def __init__(self, qeapp: 'ElectrumQmlApplication', plugins: 'Plugins'):
method on_wallet_loaded (line 118) | def on_wallet_loaded(self):
method on_wallet_usernotify (line 134) | def on_wallet_usernotify(self, wallet, message):
method on_notification_timer (line 142) | def on_notification_timer(self):
method doNotify (line 166) | def doNotify(self, wallet_name, message):
method bindIntent (line 185) | def bindIntent(self):
method hasPermission (line 195) | def hasPermission(self, permissionFqcn: str) -> bool:
method request_permission (line 201) | def request_permission(self, permissionFqcn: str, permission_result_cb...
method on_request_permissions_result (line 210) | def on_request_permissions_result(
method on_new_intent (line 230) | def on_new_intent(self, intent):
method startup_finished (line 241) | def startup_finished(self):
method wantClose (line 250) | def wantClose(self):
method wantClose (line 254) | def wantClose(self, want_close):
method doShare (line 260) | def doShare(self, data, title):
method isMaxBrightnessOnQrDisplayEnabled (line 272) | def isMaxBrightnessOnQrDisplayEnabled(self):
method setMaxScreenBrightness (line 276) | def setMaxScreenBrightness(self):
method resetScreenBrightness (line 280) | def resetScreenBrightness(self):
method _set_screen_brightness (line 283) | def _set_screen_brightness(self, br: float) -> None:
method textToClipboard (line 300) | def textToClipboard(self, text):
method clipboardToText (line 304) | def clipboardToText(self):
method plugin (line 309) | def plugin(self, plugin_name):
method plugins (line 320) | def plugins(self):
method setPluginEnabled (line 332) | def setPluginEnabled(self, plugin: str, enabled: bool):
method isPluginEnabled (line 341) | def isPluginEnabled(self, plugin: str):
method isAndroid (line 345) | def isAndroid(self):
method crashData (line 349) | def crashData(self):
method crash (line 357) | def crash(self, e, text, tb):
method sendReport (line 362) | def sendReport(self, user_text: str):
method _get_traceback_str_to_display (line 386) | def _get_traceback_str_to_display(self) -> str:
method get_user_description (line 393) | def get_user_description(self):
method get_wallet_type (line 396) | def get_wallet_type(self):
method haptic (line 401) | def haptic(self):
method secureWindow (line 407) | def secureWindow(self):
method secureWindow (line 411) | def secureWindow(self, secure):
method enforcesEdgeToEdge (line 422) | def enforcesEdgeToEdge(self) -> bool:
method _getSystemBarHeight (line 428) | def _getSystemBarHeight(self, bar_type: str) -> int:
method getStatusBarHeight (line 462) | def getStatusBarHeight(self) -> int:
method getNavigationBarHeight (line 466) | def getNavigationBarHeight(self) -> int:
class ElectrumQmlApplication (line 470) | class ElectrumQmlApplication(QGuiApplication):
method __init__ (line 474) | def __init__(self, args, *, config: 'SimpleConfig', daemon: 'Daemon', ...
method objectCreated (line 573) | def objectCreated(self, object, url):
method message_handler (line 580) | def message_handler(self, line, funct, file):
class Exception_Hook (line 587) | class Exception_Hook(QObject, Logger):
method __init__ (line 592) | def __init__(self, *, slot):
method maybe_setup (line 607) | def maybe_setup(cls, *, wallet: 'Abstract_Wallet' = None, slot=None) -...
method handler (line 613) | def handler(self, *exc_info):
FILE: electrum/gui/qml/qebiometrics.py
class BiometricAction (line 41) | class BiometricAction(str, Enum):
class QEBiometrics (line 46) | class QEBiometrics(AuthMixin, QObject):
method __init__ (line 55) | def __init__(self, *, config: 'SimpleConfig', parent=None):
method isAvailable (line 61) | def isAvailable(self) -> bool:
method isEnabled (line 72) | def isEnabled(self) -> bool:
method enable (line 76) | def enable(self, unified_wallet_password: str):
method disable (line 95) | def disable(self):
method disableProtected (line 104) | def disableProtected(self):
method _disable_protected_failed (line 114) | def _disable_protected_failed(self):
method unlock (line 119) | def unlock(self, auth_message: str = None):
method _start_activity (line 130) | def _start_activity(self, action: BiometricAction, data: str, auth_mes...
method _on_activity_result (line 150) | def _on_activity_result(self, requestCode: int, resultCode: int, intent):
method _on_wrap_key_decrypted (line 190) | def _on_wrap_key_decrypted(self, *, wrap_key: str):
method _on_wrap_key_encrypted (line 201) | def _on_wrap_key_encrypted(self, *, encrypted_bundle: str):
FILE: electrum/gui/qml/qebip39recovery.py
class QEBip39RecoveryListModel (line 17) | class QEBip39RecoveryListModel(QAbstractListModel):
class State (line 21) | class State(IntEnum):
method __init__ (line 36) | def __init__(self, config, parent=None):
method rowCount (line 43) | def rowCount(self, index):
method roleNames (line 46) | def roleNames(self):
method data (line 49) | def data(self, index, role):
method clear (line 57) | def clear(self):
method state (line 63) | def state(self):
method state (line 67) | def state(self, state: State):
method startScan (line 74) | def startScan(self, wallet_type: str, seed: str, seed_extra_words: str...
method addAccount (line 96) | def addAccount(self, account):
method on_recovery_success (line 102) | def on_recovery_success(self, accounts):
method on_recovery_error (line 110) | def on_recovery_error(self, exc_info):
method get_account_xpub (line 119) | def get_account_xpub(self, account_path):
FILE: electrum/gui/qml/qebitcoin.py
class QEBitcoin (line 17) | class QEBitcoin(QObject):
method __init__ (line 24) | def __init__(self, config, parent=None):
method generatedSeed (line 33) | def generatedSeed(self):
method seedType (line 37) | def seedType(self):
method validationMessage (line 41) | def validationMessage(self):
method validationMessage (line 45) | def validationMessage(self, msg):
method generateSeed (line 53) | def generateSeed(self, seed_type='segwit', language='en'):
method verifyMasterKey (line 64) | def verifyMasterKey(self, key, wallet_type='standard'):
method verifyDerivationPath (line 98) | def verifyDerivationPath(self, path):
method isRawTx (line 102) | def isRawTx(self, rawtx):
method isAddress (line 110) | def isAddress(self, addr: str):
method isAddressList (line 114) | def isAddressList(self, csv: str):
method isPrivateKeyList (line 118) | def isPrivateKeyList(self, csv: str):
method mnemonicsFor (line 122) | def mnemonicsFor(self, fragment):
FILE: electrum/gui/qml/qechanneldetails.py
class QEChannelDetails (line 24) | class QEChannelDetails(AuthMixin, QObject, QtEventListener):
class State (line 28) | class State(IntEnum): # subset, only ones we currently need in UI
method __init__ (line 38) | def __init__(self, parent=None):
method on_event_channel (line 56) | def on_event_channel(self, wallet: 'Abstract_Wallet', channel: 'Abstra...
method on_destroy (line 60) | def on_destroy(self):
method wallet (line 65) | def wallet(self) -> QEWallet:
method wallet (line 69) | def wallet(self, wallet: QEWallet):
method channelid (line 76) | def channelid(self) -> str:
method channelid (line 80) | def channelid(self, channelid: str):
method load (line 87) | def load(self):
method name (line 95) | def name(self) -> str:
method pubkey (line 101) | def pubkey(self) -> str:
method shortCid (line 105) | def shortCid(self) -> str:
method localScidAlias (line 109) | def localScidAlias(self) -> str:
method remoteScidAlias (line 114) | def remoteScidAlias(self) -> str:
method currentFeerate (line 119) | def currentFeerate(self) -> str:
method state (line 126) | def state(self) -> str:
method stateCode (line 130) | def stateCode(self) -> ChannelState:
method initiator (line 134) | def initiator(self) -> str:
method fundingOutpoint (line 141) | def fundingOutpoint(self) -> dict:
method closingTxid (line 149) | def closingTxid(self) -> str:
method capacity (line 160) | def capacity(self) -> QEAmount:
method localCapacity (line 165) | def localCapacity(self) -> QEAmount:
method remoteCapacity (line 171) | def remoteCapacity(self) -> QEAmount:
method canSend (line 177) | def canSend(self) -> QEAmount:
method canReceive (line 183) | def canReceive(self) -> QEAmount:
method frozenForSending (line 189) | def frozenForSending(self) -> bool:
method frozenForReceiving (line 193) | def frozenForReceiving(self) -> bool:
method channelType (line 197) | def channelType(self) -> str:
method isOpen (line 201) | def isOpen(self) -> bool:
method canClose (line 205) | def canClose(self) -> bool:
method canCoopClose (line 209) | def canCoopClose(self) -> bool:
method canLocalForceClose (line 213) | def canLocalForceClose(self) -> bool:
method canRequestForceClose (line 217) | def canRequestForceClose(self) -> bool:
method canDelete (line 221) | def canDelete(self) -> bool:
method messageForceClose (line 225) | def messageForceClose(self) -> str:
method messageForceCloseBackup (line 229) | def messageForceCloseBackup(self):
method isBackup (line 238) | def isBackup(self):
method backupType (line 242) | def backupType(self):
method toSelfDelay (line 249) | def toSelfDelay(self):
method isClosing (line 253) | def isClosing(self):
method freezeForSending (line 259) | def freezeForSending(self):
method freezeForReceiving (line 270) | def freezeForReceiving(self):
method closeChannel (line 280) | def closeChannel(self, closetype):
method do_close_channel (line 284) | def do_close_channel(self, closetype: str):
method deleteChannel (line 318) | def deleteChannel(self):
method channelBackup (line 325) | def channelBackup(self):
method channelBackupHelpText (line 329) | def channelBackupHelpText(self):
FILE: electrum/gui/qml/qechannellistmodel.py
class QEChannelListModel (line 16) | class QEChannelListModel(QAbstractListModel, QtEventListener):
method __init__ (line 30) | def __init__(self, wallet, parent=None):
method on_event_channel (line 48) | def on_event_channel(self, wallet, channel):
method on_event_channels_updated (line 53) | def on_event_channels_updated(self, wallet):
method on_destroy (line 57) | def on_destroy(self):
method rowCount (line 60) | def rowCount(self, index):
method count (line 66) | def count(self):
method roleNames (line 69) | def roleNames(self):
method data (line 72) | def data(self, index, role):
method clear (line 82) | def clear(self):
method channel_to_model (line 87) | def channel_to_model(self, lnc):
method numOpenChannels (line 120) | def numOpenChannels(self):
method initModel (line 124) | def initModel(self):
method on_channel_updated (line 149) | def on_channel_updated(self, channel):
method do_update (line 155) | def do_update(self, modelindex, channel):
method newChannel (line 165) | def newChannel(self, cid):
method removeChannel (line 179) | def removeChannel(self, cid):
method filterModel (line 190) | def filterModel(self, role, match):
method filterModelBackups (line 198) | def filterModelBackups(self):
method filterModelNoBackups (line 203) | def filterModelNoBackups(self):
method lightningWarningMessage (line 208) | def lightningWarningMessage(self):
FILE: electrum/gui/qml/qechannelopener.py
class QEChannelOpener (line 27) | class QEChannelOpener(QObject, AuthMixin):
method __init__ (line 39) | def __init__(self, parent=None):
method wallet (line 59) | def wallet(self):
method wallet (line 63) | def wallet(self, wallet: QEWallet):
method connectStr (line 70) | def connectStr(self):
method connectStr (line 74) | def connectStr(self, connect_str: str):
method amount (line 83) | def amount(self):
method amount (line 87) | def amount(self, amount: QEAmount):
method valid (line 95) | def valid(self):
method setValid (line 98) | def setValid(self, is_valid):
method warning (line 105) | def warning(self):
method setWarning (line 108) | def setWarning(self, warning):
method finalizer (line 115) | def finalizer(self):
method txDetails (line 120) | def txDetails(self):
method trampolineNodeNames (line 124) | def trampolineNodeNames(self):
method validate (line 128) | def validate(self):
method validateConnectString (line 181) | def validateConnectString(self, connect_str):
method openChannel (line 192) | def openChannel(self, confirm_backup_conflict=False):
method do_open_channel (line 223) | def do_open_channel(self, funding_tx: PartialTransaction, conn_str, pa...
method channelBackup (line 268) | def channelBackup(self, cid):
method updateMaxAmount (line 272) | def updateMaxAmount(self):
FILE: electrum/gui/qml/qeconfig.py
class QEConfig (line 20) | class QEConfig(AuthMixin, QObject):
method __init__ (line 24) | def __init__(self, config: 'SimpleConfig', parent=None):
method shortDescFor (line 32) | def shortDescFor(self, key) -> str:
method longDescFor (line 37) | def longDescFor(self, key) -> str:
method getTranslatedMessage (line 45) | def getTranslatedMessage(self, key) -> str:
method language (line 50) | def language(self):
method language (line 54) | def language(self, language):
method languagesAvailable (line 64) | def languagesAvailable(self):
method termsOfUseAccepted (line 71) | def termsOfUseAccepted(self) -> bool:
method termsOfUseAccepted (line 75) | def termsOfUseAccepted(self, accepted: bool) -> None:
method baseUnit (line 84) | def baseUnit(self):
method baseUnit (line 88) | def baseUnit(self, unit):
method btcAmountRegex (line 93) | def btcAmountRegex(self):
method btcAmountRegexMsat (line 97) | def btcAmountRegexMsat(self):
method _btcAmountRegex (line 100) | def _btcAmountRegex(self, extra_precision: int = 0):
method thousandsSeparator (line 114) | def thousandsSeparator(self):
method thousandsSeparator (line 118) | def thousandsSeparator(self, checked):
method spendUnconfirmed (line 125) | def spendUnconfirmed(self):
method spendUnconfirmed (line 129) | def spendUnconfirmed(self, checked):
method freezeReusedAddressUtxos (line 135) | def freezeReusedAddressUtxos(self):
method freezeReusedAddressUtxos (line 139) | def freezeReusedAddressUtxos(self, checked):
method requestExpiry (line 145) | def requestExpiry(self):
method requestExpiry (line 149) | def requestExpiry(self, expiry):
method paymentAuthentication (line 155) | def paymentAuthentication(self):
method paymentAuthentication (line 159) | def paymentAuthentication(self, enabled: bool):
method _disable_payment_authentication (line 167) | def _disable_payment_authentication(self):
method _payment_auth_reject (line 171) | def _payment_auth_reject(self):
method useGossip (line 176) | def useGossip(self):
method useGossip (line 180) | def useGossip(self, gossip):
method enableDebugLogs (line 186) | def enableDebugLogs(self):
method canToggleDebugLogs (line 191) | def canToggleDebugLogs(self):
method enableDebugLogs (line 196) | def enableDebugLogs(self, enable):
method alwaysAllowScreenshots (line 202) | def alwaysAllowScreenshots(self):
method alwaysAllowScreenshots (line 206) | def alwaysAllowScreenshots(self, enable):
method setMaxBrightnessOnQrDisplay (line 212) | def setMaxBrightnessOnQrDisplay(self):
method setMaxBrightnessOnQrDisplay (line 216) | def setMaxBrightnessOnQrDisplay(self, enable):
method useRecoverableChannels (line 221) | def useRecoverableChannels(self):
method useRecoverableChannels (line 225) | def useRecoverableChannels(self, useRecoverableChannels):
method trustedcoinPrepay (line 231) | def trustedcoinPrepay(self):
method trustedcoinPrepay (line 235) | def trustedcoinPrepay(self, num_prepay):
method preferredRequestType (line 242) | def preferredRequestType(self):
method preferredRequestType (line 246) | def preferredRequestType(self, preferred_request_type):
method userKnowsPressAndHold (line 253) | def userKnowsPressAndHold(self):
method userKnowsPressAndHold (line 257) | def userKnowsPressAndHold(self, userKnowsPressAndHold):
method addresslistShowType (line 264) | def addresslistShowType(self):
method addresslistShowType (line 268) | def addresslistShowType(self, addresslistShowType):
method addresslistShowUsed (line 275) | def addresslistShowUsed(self):
method addresslistShowUsed (line 279) | def addresslistShowUsed(self, addresslistShowUsed):
method outputValueRounding (line 286) | def outputValueRounding(self):
method outputValueRounding (line 290) | def outputValueRounding(self, outputValueRounding):
method lightningPaymentFeeMaxMillionths (line 297) | def lightningPaymentFeeMaxMillionths(self):
method lightningPaymentFeeMaxMillionths (line 301) | def lightningPaymentFeeMaxMillionths(self, lightningPaymentFeeMaxMilli...
method nostrRelays (line 308) | def nostrRelays(self):
method nostrRelays (line 312) | def nostrRelays(self, nostr_relays):
method swapServerNPub (line 319) | def swapServerNPub(self):
method swapServerNPub (line 323) | def swapServerNPub(self, swapserver_npub):
method lnUtxoReserve (line 330) | def lnUtxoReserve(self):
method walletShouldUseSinglePassword (line 336) | def walletShouldUseSinglePassword(self):
method walletDidUseSinglePassword (line 345) | def walletDidUseSinglePassword(self):
method formatSatsForEditing (line 355) | def formatSatsForEditing(self, satoshis):
method formatSats (line 367) | def formatSats(self, satoshis, with_unit=False):
method formatMilliSats (line 377) | def formatMilliSats(self, amount, with_unit=False):
method unitsToSats (line 387) | def unitsToSats(self, unitAmount):
method satsToUnits (line 402) | def satsToUnits(self, satoshis):
FILE: electrum/gui/qml/qedaemon.py
class QEWalletListModel (line 33) | class QEWalletListModel(QAbstractListModel):
method __init__ (line 41) | def __init__(self, daemon: 'Daemon', parent=None):
method rowCount (line 47) | def rowCount(self, index):
method roleNames (line 50) | def roleNames(self):
method data (line 53) | def data(self, index, role):
method reload (line 65) | def reload(self):
method add_wallet (line 81) | def add_wallet(self, wallet_path):
method remove_wallet (line 89) | def remove_wallet(self, path):
method wallet_name_exists (line 106) | def wallet_name_exists(self, name):
method updateWallet (line 113) | def updateWallet(self, path):
class QEDaemon (line 123) | class QEDaemon(AuthMixin, QObject):
method __init__ (line 154) | def __init__(self, daemon: 'Daemon', plugins: 'Plugins', parent=None):
method passwordValidityCheck (line 166) | def passwordValidityCheck(self):
method loadWallet (line 173) | def loadWallet(self, path=None, password=None):
method _on_backend_wallet_loaded (line 265) | def _on_backend_wallet_loaded(self, password=None):
method checkThenDeleteWallet (line 280) | def checkThenDeleteWallet(self, wallet, confirm_requests=False, confir...
method delete_wallet (line 300) | def delete_wallet(self, wallet):
method loading (line 314) | def loading(self):
method currentWallet (line 318) | def currentWallet(self):
method availableWallets (line 322) | def availableWallets(self):
method fx (line 329) | def fx(self):
method getWalletsUnlockableWithPassword (line 333) | def getWalletsUnlockableWithPassword(self, password: str) -> list[str]:
method numWalletsWithPassword (line 351) | def numWalletsWithPassword(self, password: str) -> int:
method singlePasswordEnabled (line 358) | def singlePasswordEnabled(self):
method singlePassword (line 369) | def singlePassword(self):
method singlePassword (line 378) | def singlePassword(self, password: str):
method suggestWalletName (line 386) | def suggestWalletName(self):
method startChangePassword (line 395) | def startChangePassword(self):
method setPassword (line 402) | def setPassword(self, password):
method _update_password_for_directory_and_unlock_wallets (line 410) | def _update_password_for_directory_and_unlock_wallets(self, *, old_pas...
method newWalletWizard (line 424) | def newWalletWizard(self):
method serverConnectWizard (line 431) | def serverConnectWizard(self):
method termsOfUseWizard (line 438) | def termsOfUseWizard(self):
method startNetwork (line 444) | def startNetwork(self):
method verifyMessage (line 448) | def verifyMessage(self, address, message, signature):
method passwordStrength (line 462) | def passwordStrength(self, password):
FILE: electrum/gui/qml/qefx.py
class QEFX (line 17) | class QEFX(QObject, QtEventListener):
method __init__ (line 22) | def __init__(self, fxthread: FxThread, config: SimpleConfig, parent=No...
method on_destroy (line 29) | def on_destroy(self):
method on_event_on_quotes (line 33) | def on_event_on_quotes(self, *args):
method on_event_on_history (line 39) | def on_event_on_history(self, *args):
method currencies (line 45) | def currencies(self):
method rateSources (line 50) | def rateSources(self):
method fiatCurrency (line 55) | def fiatCurrency(self):
method fiatCurrency (line 59) | def fiatCurrency(self, currency):
method fiatAmountRegex (line 67) | def fiatAmountRegex(self):
method historicRates (line 77) | def historicRates(self):
method historicRates (line 83) | def historicRates(self, checked):
method rateSource (line 91) | def rateSource(self):
method rateSource (line 95) | def rateSource(self, source):
method enabled (line 102) | def enabled(self):
method enabled (line 106) | def enabled(self, enable):
method fiatValue (line 115) | def fiatValue(self, satoshis, plain=True):
method fiatValueHistoric (line 133) | def fiatValueHistoric(self, satoshis, timestamp, plain=True):
method satoshiValue (line 156) | def satoshiValue(self, fiat, plain=True):
method isRecent (line 171) | def isRecent(self, timestamp):
FILE: electrum/gui/qml/qeinvoice.py
class QEInvoice (line 32) | class QEInvoice(QObject, QtEventListener):
class Type (line 34) | class Type(IntEnum):
class Status (line 41) | class Status(IntEnum):
method __init__ (line 58) | def __init__(self, parent=None):
method on_destroy (line 84) | def on_destroy(self):
method on_event_payment_succeeded (line 88) | def on_event_payment_succeeded(self, wallet, key):
method on_event_payment_failed (line 95) | def on_event_payment_failed(self, wallet, key, reason):
method on_event_invoice_status (line 102) | def on_event_invoice_status(self, wallet, key, status):
method on_event_channel (line 109) | def on_event_channel(self, wallet, channel):
method wallet (line 116) | def wallet(self):
method wallet (line 120) | def wallet(self, wallet: QEWallet):
method invoiceType (line 126) | def invoiceType(self):
method setInvoiceType (line 130) | def setInvoiceType(self, invoiceType: Type):
method message (line 134) | def message(self):
method time (line 138) | def time(self):
method expiration (line 142) | def expiration(self):
method address (line 146) | def address(self):
method amount (line 150) | def amount(self):
method amountOverride (line 158) | def amountOverride(self):
method amountOverride (line 162) | def amountOverride(self, new_amount: QEAmount):
method _on_amountoverride_value_changed (line 168) | def _on_amountoverride_value_changed(self):
method status (line 174) | def status(self):
method statusString (line 183) | def statusString(self):
method isSaved (line 191) | def isSaved(self):
method canSave (line 196) | def canSave(self):
method canSave (line 200) | def canSave(self, canSave):
method canPay (line 207) | def canPay(self):
method canPay (line 211) | def canPay(self, canPay):
method key (line 218) | def key(self):
method key (line 222) | def key(self, key):
method userinfo (line 231) | def userinfo(self):
method userinfo (line 235) | def userinfo(self, userinfo):
method lnprops (line 241) | def lnprops(self):
method set_lnprops (line 244) | def set_lnprops(self):
method name_for_node_id (line 262) | def name_for_node_id(self, node_id):
method set_effective_invoice (line 266) | def set_effective_invoice(self, invoice: Invoice):
method set_status_timer (line 289) | def set_status_timer(self):
method updateStatusString (line 301) | def updateStatusString(self):
method update_userinfo (line 305) | def update_userinfo(self):
method determine_can_pay (line 338) | def determine_can_pay(self):
method check_can_pay_amount (line 360) | def check_can_pay_amount(self, amount: QEAmount) -> Tuple[bool, Option...
method payLightningInvoice (line 378) | def payLightningInvoice(self):
method get_max_spendable_onchain (line 393) | def get_max_spendable_onchain(self):
method get_max_spendable_lightning (line 396) | def get_max_spendable_lightning(self):
method updateMaxAmount (line 400) | def updateMaxAmount(self):
class QEInvoiceParser (line 432) | class QEInvoiceParser(QEInvoice):
method __init__ (line 446) | def __init__(self, parent=None):
method fromResolvedPaymentIdentifier (line 456) | def fromResolvedPaymentIdentifier(self, resolved_pi: PaymentIdentifier...
method lnurlData (line 464) | def lnurlData(self):
method isLnurlPay (line 468) | def isLnurlPay(self):
method busy (line 472) | def busy(self):
method clear (line 476) | def clear(self):
method setValidOnchainInvoice (line 484) | def setValidOnchainInvoice(self, invoice: Invoice):
method setValidLightningInvoice (line 490) | def setValidLightningInvoice(self, invoice: Invoice):
method setValidLNURLPayRequest (line 497) | def setValidLNURLPayRequest(self):
method create_onchain_invoice (line 503) | def create_onchain_invoice(self, outputs, message, payment_request, uri):
method _bip70_payment_request_resolved (line 511) | def _bip70_payment_request_resolved(self, pr: 'PaymentRequest'):
method validateRecipient (line 525) | def validateRecipient(self, pi: PaymentIdentifier):
method _update_from_payment_identifier (line 549) | def _update_from_payment_identifier(self):
method _validateRecipient_bip21_onchain (line 590) | def _validateRecipient_bip21_onchain(self, bip21: Dict[str, Any]) -> N...
method on_lnurl_pay (line 605) | def on_lnurl_pay(self, lnurldata: LNURL6Data):
method lnurlGetInvoice (line 623) | def lnurlGetInvoice(self, comment=None):
method on_lnurl_invoice (line 651) | def on_lnurl_invoice(self, orig_amount, invoice):
method saveInvoice (line 665) | def saveInvoice(self) -> bool:
FILE: electrum/gui/qml/qeinvoicelistmodel.py
class QEAbstractInvoiceListModel (line 20) | class QEAbstractInvoiceListModel(QAbstractListModel):
method __init__ (line 31) | def __init__(self, wallet: 'Abstract_Wallet', parent=None):
method rowCount (line 46) | def rowCount(self, index):
method roleNames (line 49) | def roleNames(self):
method data (line 52) | def data(self, index, role):
method clear (line 63) | def clear(self):
method initModel (line 69) | def initModel(self):
method add_invoice (line 82) | def add_invoice(self, invoice: BaseInvoice):
method addInvoice (line 99) | def addInvoice(self, key):
method delete_invoice (line 102) | def delete_invoice(self, key: str):
method get_model_invoice (line 111) | def get_model_invoice(self, key: str):
method updateInvoice (line 118) | def updateInvoice(self, key, status):
method invoice_to_model (line 129) | def invoice_to_model(self, invoice: BaseInvoice):
method set_status_timer (line 141) | def set_status_timer(self):
method updateStatusStrings (line 155) | def updateStatusStrings(self):
method get_invoice_for_key (line 169) | def get_invoice_for_key(self, key: str):
method get_invoice_list (line 173) | def get_invoice_list(self) -> List[BaseInvoice]:
method get_invoice_as_dict (line 177) | def get_invoice_as_dict(self, invoice: BaseInvoice) -> Dict[str, Any]:
class QEInvoiceListModel (line 181) | class QEInvoiceListModel(QEAbstractInvoiceListModel, QtEventListener):
method __init__ (line 182) | def __init__(self, wallet, parent=None):
method on_destroy (line 189) | def on_destroy(self):
method on_event_invoice_status (line 193) | def on_event_invoice_status(self, wallet, key, status):
method invoice_to_model (line 198) | def invoice_to_model(self, invoice: BaseInvoice):
method get_invoice_list (line 204) | def get_invoice_list(self):
method get_invoice_for_key (line 209) | def get_invoice_for_key(self, key: str):
method get_invoice_as_dict (line 212) | def get_invoice_as_dict(self, invoice: Invoice):
class QERequestListModel (line 216) | class QERequestListModel(QEAbstractInvoiceListModel, QtEventListener):
method __init__ (line 217) | def __init__(self, wallet, parent=None):
method on_destroy (line 224) | def on_destroy(self):
method on_event_request_status (line 228) | def on_event_request_status(self, wallet, key, status):
method invoice_to_model (line 233) | def invoice_to_model(self, invoice: BaseInvoice):
method get_invoice_list (line 239) | def get_invoice_list(self):
method get_invoice_for_key (line 244) | def get_invoice_for_key(self, key: str):
method get_invoice_as_dict (line 247) | def get_invoice_as_dict(self, invoice: Request):
method updateRequest (line 251) | def updateRequest(self, key, status):
FILE: electrum/gui/qml/qelnpaymentdetails.py
class QELnPaymentDetails (line 10) | class QELnPaymentDetails(QObject):
method __init__ (line 15) | def __init__(self, parent=None):
method wallet (line 31) | def wallet(self):
method wallet (line 35) | def wallet(self, wallet: QEWallet):
method key (line 42) | def key(self):
method key (line 46) | def key(self, key: str):
method label (line 55) | def label(self):
method setLabel (line 59) | def setLabel(self, label: str):
method status (line 66) | def status(self):
method date (line 70) | def date(self):
method timestamp (line 74) | def timestamp(self):
method paymentHash (line 78) | def paymentHash(self):
method preimage (line 82) | def preimage(self):
method amount (line 86) | def amount(self):
method fee (line 90) | def fee(self):
method update (line 93) | def update(self):
FILE: electrum/gui/qml/qemodelfilter.py
class QEFilterProxyModel (line 6) | class QEFilterProxyModel(QSortFilterProxyModel):
method __init__ (line 9) | def __init__(self, parent_model, parent=None):
method count (line 16) | def count(self):
method isCustomFilter (line 19) | def isCustomFilter(self):
method setFilterValue (line 23) | def setFilterValue(self, filter_value):
method filterAcceptsRow (line 27) | def filterAcceptsRow(self, s_row, s_parent):
FILE: electrum/gui/qml/qenetwork.py
class QENetwork (line 21) | class QENetwork(QObject, QtEventListener):
method __init__ (line 54) | def __init__(self, network: 'Network', parent=None):
method on_destroy (line 66) | def on_destroy(self):
method on_event_network_updated (line 70) | def on_event_network_updated(self, *args):
method on_event_blockchain_updated (line 75) | def on_event_blockchain_updated(self):
method on_event_default_server_changed (line 83) | def on_event_default_server_changed(self, *args):
method on_event_proxy_set (line 87) | def on_event_proxy_set(self, *args):
method on_event_tor_probed (line 93) | def on_event_tor_probed(self, *args):
method _update_status (line 96) | def _update_status(self):
method on_event_status (line 132) | def on_event_status(self, *args):
method on_event_fee_histogram (line 136) | def on_event_fee_histogram(self, histogram):
method update_histogram (line 140) | def update_histogram(self, histogram):
method on_event_channel_db (line 152) | def on_event_channel_db(self, num_nodes, num_channels, num_policies):
method on_event_gossip_peers (line 168) | def on_event_gossip_peers(self, num_peers):
method on_event_unknown_channels (line 174) | def on_event_unknown_channels(self, unknown):
method on_gossip_setting_changed (line 181) | def on_gossip_setting_changed(self):
method height (line 190) | def height(self): # local blockchain height
method serverHeight (line 194) | def serverHeight(self):
method autoConnect (line 199) | def autoConnect(self):
method autoConnectDefined (line 204) | def autoConnectDefined(self):
method server (line 208) | def server(self):
method isValidServerAddress (line 212) | def isValidServerAddress(self, server: str) -> bool:
method setServerParameters (line 216) | def setServerParameters(self, server_str: str, auto_connect: bool, one...
method serverWithStatus (line 234) | def serverWithStatus(self):
method status (line 241) | def status(self):
method serverStatus (line 245) | def serverStatus(self):
method isConnected (line 249) | def isConnected(self):
method chaintips (line 253) | def chaintips(self):
method isLagging (line 257) | def isLagging(self):
method isTestNet (line 261) | def isTestNet(self):
method networkName (line 265) | def networkName(self):
method proxy (line 269) | def proxy(self):
method proxy (line 275) | def proxy(self, proxy_dict):
method isProxyTor (line 284) | def isProxyTor(self):
method oneServer (line 288) | def oneServer(self):
method feeHistogram (line 292) | def feeHistogram(self):
method gossipInfo (line 296) | def gossipInfo(self):
method serverListModel (line 307) | def serverListModel(self):
method probeTor (line 313) | def probeTor(self):
FILE: electrum/gui/qml/qepiresolver.py
class QEPIResolver (line 13) | class QEPIResolver(QObject):
method __init__ (line 23) | def __init__(self, parent=None):
method recipient (line 35) | def recipient(self) -> Optional[str]:
method recipient (line 39) | def recipient(self, recipient: str) -> None:
method wallet (line 55) | def wallet(self) -> Optional[QEWallet]:
method wallet (line 59) | def wallet(self, wallet: QEWallet) -> None:
method busy (line 63) | def busy(self):
method resolve_pi (line 66) | def resolve_pi(self) -> None:
method clear (line 95) | def clear(self) -> None:
FILE: electrum/gui/qml/qeqr.py
class QEQRParser (line 26) | class QEQRParser(QObject):
method __init__ (line 34) | def __init__(self, text=None, parent=None):
method videoSink (line 47) | def videoSink(self):
method videoSink (line 51) | def videoSink(self, sink: QVideoSink):
method onVideoFrame (line 56) | def onVideoFrame(self, videoframe):
method _parseQR (line 73) | def _parseQR(self, image: QImage):
method _get_crop (line 100) | def _get_crop(self, image: QImage, scan_size: int) -> QRect:
method busy (line 107) | def busy(self):
method size (line 111) | def size(self):
method data (line 115) | def data(self):
method reset (line 121) | def reset(self):
class QEQRImageProvider (line 126) | class QEQRImageProvider(QQuickImageProvider):
method __init__ (line 132) | def __init__(self, max_size, parent=None):
method requestImage (line 140) | def requestImage(self, qstr, size):
class QEQRImageProviderHelper (line 177) | class QEQRImageProviderHelper(QObject):
method __init__ (line 178) | def __init__(self, max_size, parent=None):
method getDimensions (line 183) | def getDimensions(self, qstr):
FILE: electrum/gui/qml/qeqrscanner.py
class QEQRScanner (line 21) | class QEQRScanner(QObject):
method __init__ (line 31) | def __init__(self, parent=None):
method on_destroy (line 38) | def on_destroy(self):
method hint (line 42) | def hint(self):
method hint (line 46) | def hint(self, v: str):
method open (line 50) | def open(self):
method close (line 62) | def close(self):
method on_qr_activity_result (line 66) | def on_qr_activity_result(self, requestCode, resultCode, intent):
method _unbind (line 83) | def _unbind(self):
method _scan_qr_non_android (line 87) | def _scan_qr_non_android(self):
FILE: electrum/gui/qml/qerequestdetails.py
class QERequestDetails (line 24) | class QERequestDetails(QObject, QtEventListener):
class Status (line 27) | class Status(IntEnum):
method __init__ (line 45) | def __init__(self, parent=None):
method on_destroy (line 64) | def on_destroy(self):
method on_event_request_status (line 71) | def on_event_request_status(self, wallet, key, status):
method wallet (line 78) | def wallet(self):
method wallet (line 82) | def wallet(self, wallet: QEWallet):
method key (line 90) | def key(self):
method key (line 94) | def key(self, key):
method status (line 102) | def status(self):
method status_str (line 106) | def status_str(self):
method isLightning (line 110) | def isLightning(self):
method address (line 114) | def address(self):
method message (line 119) | def message(self):
method amount (line 123) | def amount(self):
method timestamp (line 127) | def timestamp(self):
method expiration (line 131) | def expiration(self):
method paidTxid (line 135) | def paidTxid(self):
method bolt11 (line 145) | def bolt11(self):
method bip21 (line 163) | def bip21(self):
method lnurlData (line 167) | def lnurlData(self) -> Optional[dict]:
method busy (line 171) | def busy(self):
method initRequest (line 174) | def initRequest(self):
method set_status_timer (line 190) | def set_status_timer(self):
method updateStatusString (line 201) | def updateStatusString(self):
method fromResolvedPaymentIdentifier (line 206) | def fromResolvedPaymentIdentifier(self, resolved_pi: PaymentIdentifier...
method lnurlRequestWithdrawal (line 230) | def lnurlRequestWithdrawal(self, amount_sat: int) -> None:
FILE: electrum/gui/qml/qeserverlistmodel.py
class QEServerListModel (line 12) | class QEServerListModel(QAbstractListModel, QtEventListener):
method __init__ (line 21) | def __init__(self, network, parent=None):
method on_event_network_updated (line 33) | def on_event_network_updated(self):
method on_event_blockchain_updated (line 38) | def on_event_blockchain_updated(self):
method on_event_default_server_changed (line 43) | def on_event_default_server_changed(self):
method rowCount (line 47) | def rowCount(self, index):
method roleNames (line 50) | def roleNames(self):
method data (line 53) | def data(self, index, role):
method clear (line 64) | def clear(self):
method chaintips (line 71) | def chaintips(self):
method get_chains (line 74) | def get_chains(self):
method initModel (line 83) | def initModel(self):
FILE: electrum/gui/qml/qeswaphelper.py
class InvalidSwapParameters (line 32) | class InvalidSwapParameters(Exception): pass
class QESwapServerNPubListModel (line 35) | class QESwapServerNPubListModel(QAbstractListModel):
method __init__ (line 44) | def __init__(self, config, parent=None):
method rowCount (line 49) | def rowCount(self, index):
method count (line 55) | def count(self):
method roleNames (line 58) | def roleNames(self):
method data (line 61) | def data(self, index, role):
method clear (line 69) | def clear(self):
method offer_to_model (line 74) | def offer_to_model(self, x: 'SwapOffer'):
method updateModel (line 88) | def updateModel(self, items: Sequence['SwapOffer']):
method indexFor (line 127) | def indexFor(self, npub: str):
class QESwapHelper (line 134) | class QESwapHelper(AuthMixin, QObject, QtEventListener):
class State (line 143) | class State(IntEnum):
method __init__ (line 159) | def __init__(self, parent=None):
method on_destroy (line 202) | def on_destroy(self):
method wallet (line 209) | def wallet(self):
method wallet (line 213) | def wallet(self, wallet: QEWallet):
method sliderPos (line 221) | def sliderPos(self):
method sliderPos (line 225) | def sliderPos(self, sliderPos):
method rangeMin (line 233) | def rangeMin(self):
method rangeMin (line 237) | def rangeMin(self, rangeMin):
method rangeMax (line 244) | def rangeMax(self):
method rangeMax (line 248) | def rangeMax(self, rangeMax):
method leftVoid (line 255) | def leftVoid(self):
method rightVoid (line 260) | def rightVoid(self):
method valid (line 265) | def valid(self):
method valid (line 269) | def valid(self, valid):
method state (line 276) | def state(self):
method state (line 280) | def state(self, state):
method userinfo (line 287) | def userinfo(self):
method userinfo (line 291) | def userinfo(self, userinfo):
method tosend (line 298) | def tosend(self):
method tosend (line 302) | def tosend(self, tosend):
method toreceive (line 309) | def toreceive(self):
method toreceive (line 313) | def toreceive(self, toreceive):
method serverMiningfee (line 320) | def serverMiningfee(self):
method serverMiningfee (line 324) | def serverMiningfee(self, server_miningfee):
method serverfeeperc (line 331) | def serverfeeperc(self):
method serverfeeperc (line 335) | def serverfeeperc(self, serverfeeperc):
method miningfee (line 342) | def miningfee(self):
method miningfee (line 346) | def miningfee(self, miningfee):
method isReverse (line 353) | def isReverse(self):
method isReverse (line 357) | def isReverse(self, isReverse):
method canCancel (line 364) | def canCancel(self):
method canCancel (line 368) | def canCancel(self, canCancel):
method availableSwapServers (line 375) | def availableSwapServers(self):
method on_offers_updated (line 381) | def on_offers_updated(self):
method isNostr (line 385) | def isNostr(self):
method run_swap_manager (line 388) | def run_swap_manager(self):
method npubSelectionCancelled (line 476) | def npubSelectionCancelled(self):
method setReadyState (line 487) | def setReadyState(self):
method update_swap_manager_pair (line 494) | def update_swap_manager_pair(self):
method initSwapSliderRange (line 503) | def initSwapSliderRange(self):
method update_tx (line 553) | def update_tx(self, onchain_amount: Union[int, str]):
method on_event_fee_histogram (line 572) | def on_event_fee_histogram(self, *args):
method on_event_fee (line 576) | def on_event_fee(self, *args):
method swap_slider_moved (line 579) | def swap_slider_moved(self):
method tx_update_pushback_timer (line 607) | def tx_update_pushback_timer(self):
method check_valid (line 610) | def check_valid(self, send_amount, receive_amount):
method fwd_swap_updatetx (line 617) | def fwd_swap_updatetx(self):
method do_normal_swap (line 627) | def do_normal_swap(self, lightning_amount, onchain_amount):
method _create_tx (line 681) | def _create_tx(self, onchain_amount: Union[int, str, None]) -> Partial...
method do_reverse_swap (line 708) | def do_reverse_swap(self, lightning_amount, onchain_amount):
method executeSwap (line 746) | def executeSwap(self):
method _do_execute_swap (line 753) | def _do_execute_swap(self):
method cancelNormalSwap (line 764) | def cancelNormalSwap(self):
FILE: electrum/gui/qml/qetransactionlistmodel.py
class QETransactionListModel (line 19) | class QETransactionListModel(QAbstractListModel, QtEventListener):
method __init__ (line 32) | def __init__(self, wallet: 'Abstract_Wallet', parent=None, *, onchain_...
method on_destroy (line 47) | def on_destroy(self):
method on_event_verified (line 51) | def on_event_verified(self, wallet, txid, info):
method on_event_adb_set_future_tx (line 57) | def on_event_adb_set_future_tx(self, adb, txid):
method on_event_fee_histogram (line 67) | def on_event_fee_histogram(self, histogram):
method on_event_labels_received (line 86) | def on_event_labels_received(self, wallet, labels):
method rowCount (line 90) | def rowCount(self, index):
method count (line 96) | def count(self):
method roleNames (line 99) | def roleNames(self):
method data (line 102) | def data(self, index, role):
method setDirty (line 119) | def setDirty(self):
method clear (line 122) | def clear(self):
method tx_to_model (line 127) | def tx_to_model(self, tx_item):
method get_section_by_timestamp (line 167) | def get_section_by_timestamp(timestamp):
method format_date_by_section (line 183) | def format_date_by_section(section: str, date: datetime):
method _tx_mined_info_from_tx_item (line 197) | def _tx_mined_info_from_tx_item(tx_item: Dict[str, Any]) -> TxMinedInfo:
method initModel (line 209) | def initModel(self, force: bool = False):
method on_tx_verified (line 233) | def on_tx_verified(self, txid: str, info: TxMinedInfo):
method _update_future_txitem (line 246) | def _update_future_txitem(self, tx_item_idx: int):
method updateTxLabel (line 265) | def updateTxLabel(self, key, label):
method updateBlockchainHeight (line 274) | def updateBlockchainHeight(self, height):
FILE: electrum/gui/qml/qetxdetails.py
class QETxDetails (line 21) | class QETxDetails(QObject, QtEventListener):
method __init__ (line 31) | def __init__(self, parent=None):
method on_destroy (line 76) | def on_destroy(self):
method on_event_verified (line 80) | def on_event_verified(self, wallet, txid, info):
method on_event_new_transaction (line 86) | def on_event_new_transaction(self, wallet, tx):
method on_event_removed_transaction (line 92) | def on_event_removed_transaction(self, wallet, tx):
method on_event_fee_histogram (line 100) | def on_event_fee_histogram(self, histogram):
method wallet (line 107) | def wallet(self):
method wallet (line 111) | def wallet(self, wallet: QEWallet):
method txid (line 118) | def txid(self):
method txid (line 122) | def txid(self, txid: str):
method rawtx (line 130) | def rawtx(self):
method rawtx (line 134) | def rawtx(self, rawtx: str):
method label (line 151) | def label(self):
method setLabel (line 155) | def setLabel(self, label: str):
method status (line 162) | def status(self):
method warning (line 166) | def warning(self):
method amount (line 170) | def amount(self):
method lnAmount (line 174) | def lnAmount(self):
method fee (line 178) | def fee(self):
method feeRateStr (line 182) | def feeRateStr(self):
method inputs (line 186) | def inputs(self):
method outputs (line 190) | def outputs(self):
method isMined (line 194) | def isMined(self):
method isRemoved (line 198) | def isRemoved(self):
method mempoolDepth (line 202) | def mempoolDepth(self):
method inMempool (line 206) | def inMempool(self):
method date (line 210) | def date(self):
method timestamp (line 214) | def timestamp(self):
method confirmations (line 218) | def confirmations(self):
method shortId (line 222) | def shortId(self):
method headerHash (line 226) | def headerHash(self):
method isLightningFundingTx (line 230) | def isLightningFundingTx(self):
method canBump (line 234) | def canBump(self):
method canCancel (line 238) | def canCancel(self):
method canBroadcast (line 242) | def canBroadcast(self):
method canCpfp (line 246) | def canCpfp(self):
method canSaveAsLocal (line 250) | def canSaveAsLocal(self):
method canRemove (line 254) | def canRemove(self):
method canSign (line 258) | def canSign(self):
method isUnrelated (line 262) | def isUnrelated(self):
method isComplete (line 266) | def isComplete(self):
method isRbfEnabled (line 270) | def isRbfEnabled(self):
method lockDelay (line 274) | def lockDelay(self):
method shouldConfirm (line 278) | def shouldConfirm(self):
method update (line 281) | def update(self, from_txid: bool = False):
method update_mined_status (line 401) | def update_mined_status(self, tx_mined_info: TxMinedInfo):
method signAndBroadcast (line 410) | def signAndBroadcast(self):
method sign (line 414) | def sign(self):
method _sign (line 417) | def _sign(self, broadcast):
method on_signed_tx (line 436) | def on_signed_tx(self, tx: Transaction):
method broadcast (line 441) | def broadcast(self):
method onBroadcastSucceeded (line 456) | def onBroadcastSucceeded(self, txid):
method onBroadcastFailed (line 470) | def onBroadcastFailed(self, txid, code, reason):
method removeLocalTx (line 484) | def removeLocalTx(self, confirm=False):
method save (line 507) | def save(self):
method getSerializedTx (line 517) | def getSerializedTx(self):
FILE: electrum/gui/qml/qetxfinalizer.py
class FeeSlider (line 33) | class FeeSlider(QObject):
class FSMethod (line 36) | class FSMethod(IntEnum):
method to_fee_method (line 42) | def to_fee_method(self) -> 'FeeMethod':
method from_fee_method (line 51) | def from_fee_method(cls, fm: FeeMethod) -> 'FeeSlider.FSMethod':
method __init__ (line 59) | def __init__(self, parent=None):
method wallet (line 72) | def wallet(self):
method wallet (line 76) | def wallet(self, wallet: QEWallet):
method sliderSteps (line 85) | def sliderSteps(self):
method sliderPos (line 90) | def sliderPos(self):
method sliderPos (line 94) | def sliderPos(self, sliderPos):
method method (line 102) | def method(self) -> int:
method method (line 107) | def method(self, method: int):
method target (line 117) | def target(self):
method target (line 121) | def target(self, target):
method update_slider (line 126) | def update_slider(self):
method update_target (line 134) | def update_target(self):
method read_config (line 137) | def read_config(self):
method save_config (line 144) | def save_config(self):
method update (line 151) | def update(self):
class TxFeeSlider (line 155) | class TxFeeSlider(FeeSlider):
method __init__ (line 156) | def __init__(self, parent=None):
method fee (line 174) | def fee(self):
method fee (line 178) | def fee(self, fee):
method feeRate (line 185) | def feeRate(self):
method feeRate (line 189) | def feeRate(self, feeRate):
method userFee (line 196) | def userFee(self):
method userFee (line 200) | def userFee(self, userFee):
method userFeerate (line 212) | def userFeerate(self):
method userFeerate (line 216) | def userFeerate(self, userFeerate):
method isUserFeerateLast (line 229) | def isUserFeerateLast(self):
method isUserFeerateLast (line 233) | def isUserFeerateLast(self, isUserFeerateLast):
method rbf (line 240) | def rbf(self):
method rbf (line 244) | def rbf(self, rbf):
method inputs (line 252) | def inputs(self):
method inputs (line 256) | def inputs(self, inputs):
method outputs (line 263) | def outputs(self):
method outputs (line 267) | def outputs(self, outputs):
method finalizedTxid (line 274) | def finalizedTxid(self):
method finalizedTxid (line 278) | def finalizedTxid(self, finalized_txid):
method warning (line 285) | def warning(self):
method warning (line 289) | def warning(self, warning):
method valid (line 296) | def valid(self):
method doUpdate (line 300) | def doUpdate(self):
method update_from_tx (line 303) | def update_from_tx(self, tx: PartialTransaction):
method update_manual_fields (line 317) | def update_manual_fields(self):
method update_inputs_from_tx (line 326) | def update_inputs_from_tx(self, tx: Transaction):
method update_outputs_from_tx (line 347) | def update_outputs_from_tx(self, tx: PartialTransaction):
method update_fee_warning_from_tx (line 365) | def update_fee_warning_from_tx(self, *, tx: PartialTransaction, invoic...
method save_config (line 378) | def save_config(self):
class QETxFinalizer (line 387) | class QETxFinalizer(TxFeeSlider):
method __init__ (line 393) | def __init__(
method address (line 412) | def address(self):
method address (line 416) | def address(self, address):
method amount (line 423) | def amount(self):
method amount (line 427) | def amount(self, amount):
method effectiveAmount (line 435) | def effectiveAmount(self):
method extraFee (line 440) | def extraFee(self):
method extraFee (line 444) | def extraFee(self, extrafee):
method canRbf (line 451) | def canRbf(self):
method canRbf (line 455) | def canRbf(self, canRbf):
method make_tx (line 462) | def make_tx(self, amount):
method update (line 481) | def update(self):
method saveOrShow (line 539) | def saveOrShow(self):
method signAndSend (line 552) | def signAndSend(self):
method sign (line 564) | def sign(self):
method on_signed_tx (line 571) | def on_signed_tx(self, save: bool, tx: Transaction):
method on_sign_failed (line 581) | def on_sign_failed(self, msg: str = None):
method getSerializedTx (line 586) | def getSerializedTx(self):
class TxMonMixin (line 594) | class TxMonMixin(QtEventListener):
method __init__ (line 605) | def __init__(self, parent=None):
method on_destroy (line 613) | def on_destroy(self):
method on_event_verified (line 617) | def on_event_verified(self, wallet, txid, info):
method on_event_removed_transaction (line 624) | def on_event_removed_transaction(self, wallet, tx):
method txid (line 632) | def txid(self):
method txid (line 636) | def txid(self, txid):
method get_tx (line 643) | def get_tx(self) -> None:
method tx_verified (line 647) | def tx_verified(self) -> None:
method tx_removed (line 651) | def tx_removed(self) -> None:
class QETxRbfFeeBumper (line 655) | class QETxRbfFeeBumper(TxFeeSlider, TxMonMixin):
method __init__ (line 658) | def __init__(self, parent=None):
method oldfee (line 670) | def oldfee(self):
method oldfee (line 674) | def oldfee(self, oldfee):
method oldfeeRate (line 681) | def oldfeeRate(self):
method oldfeeRate (line 685) | def oldfeeRate(self, oldfeerate):
method bumpMethod (line 692) | def bumpMethod(self):
method bumpMethod (line 696) | def bumpMethod(self, bumpmethod: str) -> None:
method bumpMethodsAvailable (line 704) | def bumpMethodsAvailable(self):
method get_tx (line 707) | def get_tx(self):
method tx_verified (line 729) | def tx_verified(self):
method tx_removed (line 734) | def tx_removed(self):
method update (line 739) | def update(self):
method getNewTx (line 792) | def getNewTx(self):
class QETxCanceller (line 796) | class QETxCanceller(TxFeeSlider, TxMonMixin):
method __init__ (line 799) | def __init__(self, parent=None):
method oldfee (line 810) | def oldfee(self):
method oldfee (line 814) | def oldfee(self, oldfee):
method oldfeeRate (line 821) | def oldfeeRate(self):
method oldfeeRate (line 825) | def oldfeeRate(self, oldfeerate):
method get_tx (line 830) | def get_tx(self):
method tx_verified (line 847) | def tx_verified(self):
method tx_removed (line 852) | def tx_removed(self):
method update (line 857) | def update(self):
method getNewTx (line 916) | def getNewTx(self):
class QETxCpfpFeeBumper (line 920) | class QETxCpfpFeeBumper(TxFeeSlider, TxMonMixin):
method __init__ (line 923) | def __init__(self, parent=None):
method totalFee (line 942) | def totalFee(self):
method totalFee (line 946) | def totalFee(self, totalfee):
method totalFeeRate (line 953) | def totalFeeRate(self):
method totalFeeRate (line 957) | def totalFeeRate(self, totalfeerate):
method inputAmount (line 964) | def inputAmount(self):
method outputAmount (line 969) | def outputAmount(self):
method totalSize (line 974) | def totalSize(self):
method get_tx (line 977) | def get_tx(self):
method get_child_fee_from_total_feerate (line 1002) | def get_child_fee_from_total_feerate(self, fee_per_kb: Optional[int]) ...
method get_child_fee_from_total_fee (line 1008) | def get_child_fee_from_total_fee(self, fee: int) -> int:
method tx_verified (line 1013) | def tx_verified(self):
method tx_removed (line 1018) | def tx_removed(self):
method update (line 1023) | def update(self):
method update_manual_fields (line 1096) | def update_manual_fields(self):
method getNewTx (line 1106) | def getNewTx(self):
class QETxSweepFinalizer (line 1110) | class QETxSweepFinalizer(QETxFinalizer):
method __init__ (line 1115) | def __init__(self, parent=None):
method privateKeys (line 1126) | def privateKeys(self):
method privateKeys (line 1130) | def privateKeys(self, private_keys):
method make_sweep_tx (line 1136) | def make_sweep_tx(self):
method update_privkeys (line 1151) | def update_privkeys(self):
method update (line 1168) | def update(self):
method send (line 1209) | def send(self):
FILE: electrum/gui/qml/qetypes.py
class QEAmount (line 7) | class QEAmount(QObject):
method __init__ (line 23) | def __init__(self, *, amount_sat: int = 0, amount_msat: int = 0, is_ma...
method satsInt (line 39) | def satsInt(self):
method satsInt (line 46) | def satsInt(self, sats):
method msatsInt (line 52) | def msatsInt(self):
method msatsInt (line 59) | def msatsInt(self, msats):
method satsStr (line 65) | def satsStr(self):
method msatsStr (line 69) | def msatsStr(self):
method isMax (line 73) | def isMax(self):
method isMax (line 77) | def isMax(self, ismax):
method isEmpty (line 83) | def isEmpty(self):
method clear (line 87) | def clear(self):
method copyFrom (line 94) | def copyFrom(self, amount):
method __eq__ (line 102) | def __eq__(self, other):
method __str__ (line 112) | def __str__(self):
method __repr__ (line 118) | def __repr__(self):
class QEBytes (line 122) | class QEBytes(QObject):
method __init__ (line 123) | def __init__(self, data: bytes = None, *, parent=None):
method data (line 128) | def data(self):
method data (line 132) | def data(self, _data):
method isEmpty (line 136) | def isEmpty(self):
method __str__ (line 139) | def __str__(self):
method __repr__ (line 142) | def __repr__(self):
FILE: electrum/gui/qml/qewallet.py
class QEWallet (line 39) | class QEWallet(AuthMixin, QObject, QtEventListener):
method getInstanceFor (line 45) | def getInstanceFor(cls, wallet):
method __init__ (line 87) | def __init__(self, wallet: 'Abstract_Wallet', parent=None):
method synchronizing (line 142) | def synchronizing(self):
method synchronizing (line 146) | def synchronizing(self, synchronizing):
method synchronizingProgress (line 160) | def synchronizingProgress(self):
method synchronizingProgress (line 164) | def synchronizingProgress(self, progress):
method multipleChange (line 172) | def multipleChange(self):
method multipleChange (line 176) | def multipleChange(self, multiple_change):
method on_event_request_status (line 183) | def on_event_request_status(self, wallet, key, status):
method on_event_invoice_status (line 195) | def on_event_invoice_status(self, wallet, key, status):
method on_event_new_transaction (line 201) | def on_event_new_transaction(self, wallet: 'Abstract_Wallet', tx: Tran...
method on_event_adb_tx_height_changed (line 210) | def on_event_adb_tx_height_changed(self, adb, txid, old_height, new_he...
method on_event_removed_transaction (line 216) | def on_event_removed_transaction(self, wallet, tx):
method on_event_wallet_updated (line 226) | def on_event_wallet_updated(self, wallet):
method on_event_channel (line 236) | def on_event_channel(self, wallet, channel):
method on_event_channels_updated (line 242) | def on_event_channels_updated(self, wallet):
method on_event_payment_succeeded (line 248) | def on_event_payment_succeeded(self, wallet, key):
method on_event_payment_failed (line 254) | def on_event_payment_failed(self, wallet, key, reason):
method on_destroy (line 258) | def on_destroy(self):
method add_tx_notification (line 261) | def add_tx_notification(self, tx: Transaction):
method notify_transactions (line 268) | def notify_transactions(self):
method update_sync_progress (line 291) | def update_sync_progress(self):
method historyModel (line 299) | def historyModel(self):
method addressCoinModel (line 306) | def addressCoinModel(self):
method requestModel (line 313) | def requestModel(self):
method invoiceModel (line 320) | def invoiceModel(self):
method channelModel (line 327) | def channelModel(self):
method name (line 334) | def name(self):
method isLightning (line 339) | def isLightning(self):
method billingInfo (line 344) | def billingInfo(self):
method canHaveLightning (line 350) | def canHaveLightning(self):
method walletType (line 354) | def walletType(self):
method isMultisig (line 358) | def isMultisig(self):
method hasSeed (line 362) | def hasSeed(self):
method seed (line 366) | def seed(self):
method seedPassphrase (line 370) | def seedPassphrase(self):
method txinType (line 374) | def txinType(self):
method seedType (line 380) | def seedType(self):
method isWatchOnly (line 384) | def isWatchOnly(self):
method isDeterministic (line 388) | def isDeterministic(self):
method isEncrypted (line 392) | def isEncrypted(self):
method isHardware (line 396) | def isHardware(self):
method keystores (line 400) | def keystores(self):
method lightningNodePubkey (line 414) | def lightningNodePubkey(self):
method lightningHasDeterministicNodeId (line 418) | def lightningHasDeterministicNodeId(self):
method derivationPrefix (line 422) | def derivationPrefix(self):
method masterPubkey (line 434) | def masterPubkey(self):
method canSignWithoutServer (line 438) | def canSignWithoutServer(self):
method canSignWithoutCosigner (line 442) | def canSignWithoutCosigner(self):
method canSignMessage (line 450) | def canSignMessage(self):
method canGetZeroconfChannel (line 455) | def canGetZeroconfChannel(self) -> bool:
method frozenBalance (line 459) | def frozenBalance(self):
method unconfirmedBalance (line 465) | def unconfirmedBalance(self):
method confirmedBalance (line 470) | def confirmedBalance(self):
method lightningBalance (line 476) | def lightningBalance(self):
method lightningBalanceFrozen (line 482) | def lightningBalanceFrozen(self):
method totalBalance (line 488) | def totalBalance(self):
method lightningCanSend (line 494) | def lightningCanSend(self):
method lightningCanReceive (line 500) | def lightningCanReceive(self):
method isLowReserve (line 506) | def isLowReserve(self):
method minChannelFunding (line 510) | def minChannelFunding(self):
method lightningNumPeers (line 514) | def lightningNumPeers(self):
method enableLightning (line 520) | def enableLightning(self):
method sign_and_broadcast (line 526) | def sign_and_broadcast(self, tx, *,
method sign (line 532) | def sign(self, tx, *,
method do_sign (line 537) | def do_sign(self, tx, broadcast, on_success: Callable[[Transaction], N...
method on_sign_complete (line 579) | def on_sign_complete(self, broadcast, cb: Callable[[Transaction], None...
method on_sign_failed (line 587) | def on_sign_failed(self, cb: Callable[[], None] = None, error: str = N...
method request_otp (line 592) | def request_otp(self, on_submit):
method submitOtp (line 597) | def submitOtp(self, otp):
method broadcast (line 602) | def broadcast(self, tx):
method save_tx (line 628) | def save_tx(self, tx: 'PartialTransaction') -> bool:
method ln_auth_rejected (line 644) | def ln_auth_rejected(self):
method pay_lightning_invoice (line 648) | def pay_lightning_invoice(self, invoice: 'Invoice', amount_msat: int =...
method deleteExpiredRequests (line 678) | def deleteExpiredRequests(self):
method createRequest (line 687) | def createRequest(self, amount: QEAmount, message: str, expiration: in...
method deleteRequest (line 719) | def deleteRequest(self, key: str):
method deleteInvoice (line 725) | def deleteInvoice(self, key: str):
method verifyPassword (line 731) | def verifyPassword(self, password):
method setPassword (line 741) | def setPassword(self, password):
method password (line 764) | def password(self):
method importAddresses (line 768) | def importAddresses(self, addresslist):
method importPrivateKeys (line 775) | def importPrivateKeys(self, keyslist):
method importChannelBackup (line 782) | def importChannelBackup(self, backup_str):
method isValidChannelBackup (line 790) | def isValidChannelBackup(self, backup_str):
method requestShowSeed (line 801) | def requestShowSeed(self):
method retrieve_seed (line 805) | def retrieve_seed(self):
method getSerializedTx (line 817) | def getSerializedTx(self, txid):
method getBalancesForPiechart (line 823) | def getBalancesForPiechart(self):
method isAddressMine (line 836) | def isAddressMine(self, addr):
method signMessage (line 841) | def signMessage(self, address, message):
method determine_max (line 846) | def determine_max(self, *, mktx: Callable[[FeePolicy], PartialTransact...
FILE: electrum/gui/qml/qewizard.py
class QEAbstractWizard (line 19) | class QEAbstractWizard(QObject):
method __init__ (line 26) | def __init__(self, parent=None):
method startWizard (line 30) | def startWizard(self):
method viewToComponent (line 35) | def viewToComponent(self, view):
method submit (line 39) | def submit(self, wizard_data):
method prev (line 45) | def prev(self):
method isLast (line 50) | def isLast(self, wizard_data):
class QENewWalletWizard (line 55) | class QENewWalletWizard(NewWalletWizard, QEAbstractWizard):
method __init__ (line 59) | def __init__(self, daemon: 'QEDaemon', plugins: 'Plugins', parent=None):
method path (line 91) | def path(self):
method path (line 95) | def path(self, path):
method is_single_password (line 99) | def is_single_password(self):
method hasDuplicateMasterKeys (line 103) | def hasDuplicateMasterKeys(self, js_data):
method hasHeterogeneousMasterKeys (line 109) | def hasHeterogeneousMasterKeys(self, js_data):
method isMatchingSeed (line 115) | def isMatchingSeed(self, seed, seed_again):
method verifySeed (line 119) | def verifySeed(self, seed, seed_variant, wallet_type='standard'):
method _wallet_path_from_wallet_name (line 128) | def _wallet_path_from_wallet_name(self, wallet_name: str) -> str:
method isValidNewWalletName (line 132) | def isValidNewWalletName(self, wallet_name: str) -> bool:
method createStorage (line 158) | def createStorage(self, js_data, single_password_enabled, single_passw...
class QEServerConnectWizard (line 184) | class QEServerConnectWizard(ServerConnectWizard, QEAbstractWizard):
method __init__ (line 185) | def __init__(self, daemon: 'QEDaemon', parent=None):
class QETermsOfUseWizard (line 197) | class QETermsOfUseWizard(TermsOfUseWizard, QEAbstractWizard):
method __init__ (line 198) | def __init__(self, daemon: 'QEDaemon', parent=None):
method termsOfUseText (line 209) | def termsOfUseText(self):
FILE: electrum/gui/qml/util.py
function status_update_timer_interval (line 12) | def status_update_timer_interval(exp):
function check_password_strength (line 31) | def check_password_strength(password: str) -> Tuple[int, str]:
FILE: electrum/gui/qt/__init__.py
class OpenFileEventFilter (line 101) | class OpenFileEventFilter(QObject):
method __init__ (line 102) | def __init__(self, windows: Sequence[ElectrumWindow]):
method eventFilter (line 106) | def eventFilter(self, obj, event):
class ScreenshotProtectionEventFilter (line 114) | class ScreenshotProtectionEventFilter(QObject):
method __init__ (line 115) | def __init__(self):
method eventFilter (line 118) | def eventFilter(self, obj, event):
class QElectrumApplication (line 128) | class QElectrumApplication(QApplication):
class ElectrumGui (line 138) | class ElectrumGui(BaseElectrumGui, Logger):
method __init__ (line 144) | def __init__(self, *, config: 'SimpleConfig', daemon: 'Daemon', plugin...
method _init_tray (line 184) | def _init_tray(self):
method reload_app_stylesheet (line 191) | def reload_app_stylesheet(self):
method build_tray_menu (line 218) | def build_tray_menu(self):
method tray_icon (line 243) | def tray_icon(self):
method toggle_tray_icon (line 249) | def toggle_tray_icon(self):
method tray_activated (line 256) | def tray_activated(self, reason):
method _cleanup_before_exit (line 265) | def _cleanup_before_exit(self):
method _maybe_quit_if_no_windows_open (line 293) | def _maybe_quit_if_no_windows_open(self) -> None:
method new_window (line 304) | def new_window(self, path, uri=None):
method show_lightning_dialog (line 308) | def show_lightning_dialog(self):
method show_plugins_dialog (line 315) | def show_plugins_dialog(self):
method show_network_dialog (line 320) | def show_network_dialog(self, proxy_tab=False):
method _create_window_for_wallet (line 328) | def _create_window_for_wallet(self, wallet):
method count_wizards_in_progress (line 336) | def count_wizards_in_progress(func):
method get_window_for_wallet (line 348) | def get_window_for_wallet(self, wallet):
method start_new_window (line 354) | def start_new_window(
method _start_wizard_to_select_or_create_wallet (line 446) | def _start_wizard_to_select_or_create_wallet(self, path) -> Optional[A...
method close_window (line 512) | def close_window(self, window: ElectrumWindow):
method reload_window (line 520) | def reload_window(self, window):
method reload_windows (line 529) | def reload_windows(self):
method has_accepted_terms_of_use (line 533) | def has_accepted_terms_of_use(self) -> bool:
method ask_terms_of_use (line 539) | def ask_terms_of_use(self):
method init_network (line 552) | def init_network(self):
method main (line 566) | def main(self):
method stop (line 598) | def stop(self):
method version_info (line 603) | def version_info(cls):
method do_copy (line 612) | def do_copy(self, text: str, *, title: str = None) -> None:
function standalone_exception_dialog (line 619) | def standalone_exception_dialog(exception: Union[str, BaseException]) ->...
FILE: electrum/gui/qt/address_dialog.py
class AddressHistoryModel (line 40) | class AddressHistoryModel(HistoryModel):
method __init__ (line 41) | def __init__(self, window: 'ElectrumWindow', address):
method get_domain (line 45) | def get_domain(self):
method should_include_lightning_payments (line 48) | def should_include_lightning_payments(self) -> bool:
class AddressDialog (line 52) | class AddressDialog(WindowModalDialog):
method __init__ (line 54) | def __init__(self, window: 'ElectrumWindow', address: str, *, parent=N...
method show_qr (line 116) | def show_qr(self):
FILE: electrum/gui/qt/address_list.py
class AddressUsageStateFilter (line 50) | class AddressUsageStateFilter(IntEnum):
method ui_text (line 57) | def ui_text(self) -> str:
class AddressTypeFilter (line 67) | class AddressTypeFilter(IntEnum):
method ui_text (line 72) | def ui_text(self) -> str:
class AddressList (line 80) | class AddressList(MyTreeView):
class Columns (line 82) | class Columns(MyTreeView.BaseColumnsEnum):
method __init__ (line 96) | def __init__(self, main_window: 'ElectrumWindow'):
method on_double_click (line 125) | def on_double_click(self, idx):
method create_toolbar (line 129) | def create_toolbar(self, config: 'SimpleConfig'):
method should_show_fiat (line 138) | def should_show_fiat(self):
method get_toolbar_buttons (line 141) | def get_toolbar_buttons(self):
method on_hide_toolbar (line 144) | def on_hide_toolbar(self):
method refresh_headers (line 149) | def refresh_headers(self):
method toggle_change (line 164) | def toggle_change(self, state: int):
method toggle_used (line 170) | def toggle_used(self, state: int):
method update (line 177) | def update(self):
method address_index_as_sortable_key (line 253) | def address_index_as_sortable_key(address_index: Optional['AddressInde...
method refresh_row (line 261) | def refresh_row(self, key, row):
method create_menu (line 293) | def create_menu(self, position):
method place_text_on_clipboard (line 353) | def place_text_on_clipboard(self, text: str, *, title: str = None) -> ...
method get_edit_key_from_coordinate (line 362) | def get_edit_key_from_coordinate(self, row, col):
method on_edited (line 367) | def on_edited(self, idx, edit_key, *, text):
FILE: electrum/gui/qt/amountedit.py
class FreezableLineEdit (line 19) | class FreezableLineEdit(QLineEdit):
method setFrozen (line 22) | def setFrozen(self, b):
method isFrozen (line 27) | def isFrozen(self):
class SizedFreezableLineEdit (line 31) | class SizedFreezableLineEdit(FreezableLineEdit):
method __init__ (line 33) | def __init__(self, *, width: int, parent=None):
method sizeHint (line 39) | def sizeHint(self) -> QSize:
class AmountEdit (line 44) | class AmountEdit(SizedFreezableLineEdit):
method __init__ (line 47) | def __init__(self, base_unit, is_int=False, parent=None, *, max_amount...
method decimal_point (line 58) | def decimal_point(self):
method max_precision (line 61) | def max_precision(self):
method numbify (line 64) | def numbify(self):
method paintEvent (line 87) | def paintEvent(self, event):
method _get_amount_from_text (line 98) | def _get_amount_from_text(self, text: str) -> Union[None, Decimal, int]:
method get_amount (line 105) | def get_amount(self) -> Union[None, Decimal, int]:
method _get_text_from_amount (line 111) | def _get_text_from_amount(self, amount) -> str:
method setAmount (line 114) | def setAmount(self, amount):
class BTCAmountEdit (line 119) | class BTCAmountEdit(AmountEdit):
method __init__ (line 121) | def __init__(self, decimal_point, is_int=False, parent=None, *, max_am...
method _base_unit (line 127) | def _base_unit(self):
method _get_amount_from_text (line 130) | def _get_amount_from_text(self, text):
method _get_text_from_amount (line 147) | def _get_text_from_amount(self, amount_sat):
method setAmount (line 152) | def setAmount(self, amount_sat):
class FeerateEdit (line 162) | class FeerateEdit(BTCAmountEdit):
method __init__ (line 164) | def __init__(self, decimal_point, is_int=False, parent=None, *, max_am...
method _base_unit (line 168) | def _base_unit(self):
method _get_amount_from_text (line 171) | def _get_amount_from_text(self, text):
method _get_text_from_amount (line 175) | def _get_text_from_amount(self, amount):
FILE: electrum/gui/qt/balance_dialog.py
class PieChartObject (line 54) | class PieChartObject:
method paintEvent (line 56) | def paintEvent(self, event):
class PieChartWidget (line 81) | class PieChartWidget(QWidget, PieChartObject):
method __init__ (line 83) | def __init__(self, size, l):
method update_list (line 95) | def update_list(self, l):
class BalanceToolButton (line 100) | class BalanceToolButton(QToolButton, PieChartObject):
method __init__ (line 102) | def __init__(self):
method has_warning (line 109) | def has_warning(self) -> bool:
method update_list (line 112) | def update_list(self, l, warning: bool):
method setText (line 117) | def setText(self, text):
method paintEvent (line 121) | def paintEvent(self, event):
method resizeEvent (line 132) | def resizeEvent(self, e):
method _update_size (line 136) | def _update_size(self):
class LegendWidget (line 141) | class LegendWidget(QWidget):
method __init__ (line 144) | def __init__(self, color):
method paintEvent (line 154) | def paintEvent(self, event):
class BalanceDialog (line 165) | class BalanceDialog(WindowModalDialog):
method __init__ (line 167) | def __init__(self, parent: 'ElectrumWindow', *, wallet: 'Abstract_Wall...
method run (line 274) | def run(self):
FILE: electrum/gui/qt/bip39_recovery_dialog.py
class Bip39RecoveryDialog (line 24) | class Bip39RecoveryDialog(WindowModalDialog):
method __init__ (line 28) | def __init__(self, parent: QWidget, get_account_xpub, on_account_select):
method on_finished (line 59) | def on_finished(self):
method on_ok_button_click (line 62) | def on_ok_button_click(self):
method on_recovery_success (line 67) | def on_recovery_success(self, accounts):
method on_recovery_error (line 81) | def on_recovery_error(self, exc_info):
method clear_content (line 93) | def clear_content(self):
FILE: electrum/gui/qt/channel_details.py
class HTLCItem (line 24) | class HTLCItem(QtGui.QStandardItem):
method __init__ (line 25) | def __init__(self, *args, **kwargs):
class SelectableLabel (line 30) | class SelectableLabel(QtWidgets.QLabel):
method __init__ (line 31) | def __init__(self, text=''):
class LinkedLabel (line 36) | class LinkedLabel(QtWidgets.QLabel):
method __init__ (line 37) | def __init__(self, text, on_clicked):
class ChannelDetailsDialog (line 42) | class ChannelDetailsDialog(QtWidgets.QDialog, MessageBoxMixin, QtEventLi...
method __init__ (line 44) | def __init__(self, window: 'ElectrumWindow', chan: AbstractChannel):
method make_htlc_item (line 88) | def make_htlc_item(self, i: UpdateAddHtlc, direction: Direction) -> HT...
method make_model (line 95) | def make_model(self, htlcs: Sequence[HTLCWithStatus]) -> QtGui.QStanda...
method move (line 127) | def move(self, fro: str, to: str, payment_hash: bytes):
method on_event_channel (line 136) | def on_event_channel(self, wallet, chan):
method on_event_htlc_added (line 141) | def on_event_htlc_added(self, chan, htlc, direction):
method on_event_htlc_fulfilled (line 149) | def on_event_htlc_fulfilled(self, payment_hash, chan, htlc_id):
method on_event_htlc_failed (line 156) | def on_event_htlc_failed(self, payment_hash, chan, htlc_id):
method update (line 162) | def update(self):
method show_tx (line 175) | def show_tx(self, link_text: str):
method get_common_form (line 182) | def get_common_form(self, chan: AbstractChannel):
method get_hbox_stats (line 217) | def get_hbox_stats(self, chan: Channel):
method create_htlc_list (line 271) | def create_htlc_list(self, chan):
method closeEvent (line 282) | def closeEvent(self, event):
FILE: electrum/gui/qt/channels_list.py
class ChannelsList (line 30) | class ChannelsList(MyTreeView):
class Columns (line 35) | class Columns(MyTreeView.BaseColumnsEnum):
method __init__ (line 65) | def __init__(self, main_window: 'ElectrumWindow'):
method lnworker (line 81) | def lnworker(self):
method format_fields (line 84) | def format_fields(self, chan: AbstractChannel) -> Dict['ChannelsList.C...
method on_channel_closed (line 114) | def on_channel_closed(self, txid):
method on_failure (line 117) | def on_failure(self, exc_info):
method close_channel (line 122) | def close_channel(self, channel_id):
method force_close (line 136) | def force_close(self, channel_id):
method remove_channel (line 164) | def remove_channel(self, channel_id):
method remove_channel_backup (line 168) | def remove_channel_backup(self, channel_id):
method export_channel_backup (line 172) | def export_channel_backup(self, channel_id):
method request_force_close (line 178) | def request_force_close(self, channel_id):
method set_frozen (line 193) | def set_frozen(self, chan, *, for_sending, value):
method get_rebalance_pair (line 203) | def get_rebalance_pair(self):
method on_rebalance (line 216) | def on_rebalance(self):
method on_double_click (line 223) | def on_double_click(self, idx):
method create_menu (line 228) | def create_menu(self, position):
method do_update_single_row (line 287) | def do_update_single_row(self, wallet: Abstract_Wallet, chan: Abstract...
method on_gossip_db (line 302) | def on_gossip_db(self):
method do_update_rows (line 306) | def do_update_rows(self, wallet):
method _update_chan_frozen_bg (line 334) | def _update_chan_frozen_bg(self, *, chan: AbstractChannel, items: Sequ...
method update_can_send (line 353) | def update_can_send(self, lnworker: LNWallet):
method create_toolbar (line 360) | def create_toolbar(self, config):
method statistics_dialog (line 379) | def statistics_dialog(self):
method set_visibility_of_columns (line 396) | def set_visibility_of_columns(self):
class ChannelFeature (line 402) | class ChannelFeature(ABC):
method __init__ (line 403) | def __init__(self):
method tooltip (line 407) | def tooltip(self) -> str:
method icon (line 411) | def icon(self) -> QIcon:
class ChanFeatChannel (line 415) | class ChanFeatChannel(ChannelFeature):
method tooltip (line 416) | def tooltip(self) -> str:
method icon (line 418) | def icon(self) -> QIcon:
class ChanFeatBackup (line 422) | class ChanFeatBackup(ChannelFeature):
method tooltip (line 423) | def tooltip(self) -> str:
method icon (line 425) | def icon(self) -> QIcon:
class ChanFeatTrampoline (line 429) | class ChanFeatTrampoline(ChannelFeature):
method tooltip (line 430) | def tooltip(self) -> str:
method icon (line 432) | def icon(self) -> QIcon:
class ChanFeatNoOnchainBackup (line 436) | class ChanFeatNoOnchainBackup(ChannelFeature):
method tooltip (line 437) | def tooltip(self) -> str:
method icon (line 439) | def icon(self) -> QIcon:
class ChannelFeatureIcons (line 444) | class ChannelFeatureIcons:
method __init__ (line 446) | def __init__(self, features: Sequence['ChannelFeature']):
method from_channel (line 452) | def from_channel(cls, chan: AbstractChannel) -> 'ChannelFeatureIcons':
method paint (line 466) | def paint(self, painter: QPainter, rect: QRect) -> None:
method sizeHint (line 477) | def sizeHint(self, default_size: QSize) -> QSize:
method show_tooltip (line 483) | def show_tooltip(self, evt: QHelpEvent) -> bool:
FILE: electrum/gui/qt/completion_text_edit.py
class CompletionTextEdit (line 33) | class CompletionTextEdit(ButtonsTextEdit):
method __init__ (line 35) | def __init__(self):
method set_completer (line 41) | def set_completer(self, completer):
method initialize_completer (line 45) | def initialize_completer(self):
method insert_completion (line 51) | def insert_completion(self, completion):
method text_under_cursor (line 64) | def text_under_cursor(self):
method enable_suggestions (line 69) | def enable_suggestions(self):
method disable_suggestions (line 72) | def disable_suggestions(self):
method keyPressEvent (line 75) | def keyPressEvent(self, e):
method is_special_key (line 111) | def is_special_key(self, e):
FILE: electrum/gui/qt/confirm_tx_dialog.py
class TxEditorContext (line 65) | class TxEditorContext(Enum):
class TxEditor (line 74) | class TxEditor(WindowModalDialog, QtEventListener, Logger):
method __init__ (line 78) | def __init__(
method accept (line 171) | def accept(self):
method reject (line 175) | def reject(self):
method closeEvent (line 179) | def closeEvent(self, event):
method _cleanup (line 183) | def _cleanup(self):
method on_tab_changed (line 191) | def on_tab_changed(self, index):
method is_batching (line 198) | def is_batching(self) -> bool:
method timer_actions (line 201) | def timer_actions(self):
method update (line 206) | def update(self):
method stop_editor_updates (line 211) | def stop_editor_updates(self):
method update_tx (line 214) | def update_tx(self, *, fallback_to_zero_fee: bool = False):
method create_grid (line 218) | def create_grid(self) -> QGridLayout:
method help_text (line 222) | def help_text(self) -> str:
method update_fee_target (line 225) | def update_fee_target(self):
method update_feerate_label (line 232) | def update_feerate_label(self):
method create_fee_controls (line 235) | def create_fee_controls(self):
method update_tab_visibility (line 315) | def update_tab_visibility(self):
method trigger_update (line 341) | def trigger_update(self):
method fee_slider_callback (line 349) | def fee_slider_callback(self, fee_rate):
method on_fee_or_feerate (line 361) | def on_fee_or_feerate(self, edit_changed, editing_finished):
method is_send_fee_frozen (line 377) | def is_send_fee_frozen(self) -> bool:
method is_send_feerate_frozen (line 381) | def is_send_feerate_frozen(self) -> bool:
method feerounding_text (line 385) | def feerounding_text(self):
method set_feerounding_visibility (line 388) | def set_feerounding_visibility(self, b:bool):
method get_fee_policy (line 393) | def get_fee_policy(self):
method entry_changed (line 405) | def entry_changed(self):
method update_fee_fields (line 424) | def update_fee_fields(self):
method create_buttons_bar (line 485) | def create_buttons_bar(self):
method create_top_bar (line 506) | def create_top_bar(self, text):
method resize_to_fit_content (line 573) | def resize_to_fit_content(self):
method toggle_use_change (line 579) | def toggle_use_change(self):
method toggle_multiple_change (line 585) | def toggle_multiple_change(self):
method set_io_visible (line 590) | def set_io_visible(self):
method set_fee_edit_visible (line 593) | def set_fee_edit_visible(self):
method set_locktime_visible (line 603) | def set_locktime_visible(self):
method run (line 610) | def run(self):
method on_send (line 619) | def on_send(self):
method on_preview (line 625) | def on_preview(self):
method _update_widgets (line 630) | def _update_widgets(self):
method get_messages (line 669) | def get_messages(self):
method set_locktime (line 742) | def set_locktime(self):
method _update_amount_label (line 749) | def _update_amount_label(self):
method _update_extra_fees (line 752) | def _update_extra_fees(self):
method _update_message (line 755) | def _update_message(self):
method _update_send_button (line 761) | def _update_send_button(self):
method can_pay_assuming_zero_fees (line 770) | def can_pay_assuming_zero_fees(self, confirmed_only: bool) -> bool:
method prepare_swap_transport (line 774) | def prepare_swap_transport(self):
method wait_for_swap_transport (line 816) | async def wait_for_swap_transport(self, new_swap_transport: Union[Http...
method on_event_swap_provider_changed (line 847) | def on_event_swap_provider_changed(self):
method on_event_channel (line 851) | def on_event_channel(self, wallet, _channel):
method on_event_swap_offers_changed (line 857) | def on_event_swap_offers_changed(self, _):
method on_swap_availability_changed (line 865) | def on_swap_availability_changed(self):
method create_submarine_payment_tab (line 873) | def create_submarine_payment_tab(self) -> QWidget:
method show_swap_transport_connection_message (line 937) | def show_swap_transport_connection_message(self):
method start_submarine_payment (line 942) | def start_submarine_payment(self):
method update_submarine_payment_tab (line 972) | def update_submarine_payment_tab(self):
method get_swap_warning (line 1040) | def get_swap_warning(self) -> Optional[str]:
method set_submarine_payment_tab_warning (line 1089) | def set_submarine_payment_tab_warning(self, warning: str):
method request_forward_swap (line 1096) | def request_forward_swap(self):
class ConfirmTxDialog (line 1116) | class ConfirmTxDialog(TxEditor):
method __init__ (line 1119) | def __init__(
method _update_amount_label (line 1141) | def _update_amount_label(self):
method update_tx (line 1154) | def update_tx(self, *, fallback_to_zero_fee: bool = False):
method can_pay_assuming_zero_fees (line 1191) | def can_pay_assuming_zero_fees(self, confirmed_only: bool) -> bool:
method create_grid (line 1200) | def create_grid(self):
method _update_extra_fees (line 1237) | def _update_extra_fees(self):
FILE: electrum/gui/qt/console.py
class OverlayLabel (line 22) | class OverlayLabel(QtWidgets.QLabel):
method __init__ (line 32) | def __init__(self, text, parent):
method mousePressEvent (line 41) | def mousePressEvent(self, e):
method on_resize (line 44) | def on_resize(self, w):
class Console (line 49) | class Console(QtWidgets.QPlainTextEdit):
method __init__ (line 54) | def __init__(self, parent=None):
method set_font_size (line 79) | def set_font_size(self, size: int):
method resizeEvent (line 84) | def resizeEvent(self, e):
method set_json (line 89) | def set_json(self, b):
method run_script (line 92) | def run_script(self, filename):
method updateNamespace (line 98) | def updateNamespace(self, namespace):
method showMessage (line 101) | def showMessage(self, message):
method clear (line 106) | def clear(self):
method keyboard_interrupt (line 111) | def keyboard_interrupt(self):
method newPrompt (line 116) | def newPrompt(self, curr_line):
method getCommand (line 128) | def getCommand(self, *, strip=True):
method setCommand (line 136) | def setCommand(self, command):
method show_completions (line 150) | def show_completions(self, completions):
method hide_completions (line 167) | def hide_completions(self):
method getConstruct (line 178) | def getConstruct(self, command):
method addToHistory (line 194) | def addToHistory(self, command):
method getPrevHistoryEntry (line 204) | def getPrevHistoryEntry(self):
method getNextHistoryEntry (line 210) | def getNextHistoryEntry(self):
method getCursorPosition (line 218) | def getCursorPosition(self):
method setCursorPosition (line 222) | def setCursorPosition(self, position):
method run_command (line 227) | def run_command(self):
method _exec_command (line 238) | def _exec_command(self, command):
method keyPressEvent (line 291) | def keyPressEvent(self, event):
method completions (line 329) | def completions(self):
FILE: electrum/gui/qt/contact_list.py
class ContactList (line 46) | class ContactList(MyTreeView):
class Columns (line 48) | class Columns(MyTreeView.BaseColumnsEnum):
method __init__ (line 61) | def __init__(self, main_window: 'ElectrumWindow'):
method on_edited (line 73) | def on_edited(self, idx, edit_key, *, text):
method create_menu (line 78) | def create_menu(self, position):
method update (line 106) | def update(self):
method refresh_row (line 136) | def refresh_row(self, key, row):
method get_edit_key_from_coordinate (line 140) | def get_edit_key_from_coordinate(self, row, col):
method create_toolbar (line 145) | def create_toolbar(self, config):
FILE: electrum/gui/qt/custom_model.py
class CustomNode (line 7) | class CustomNode:
method __init__ (line 9) | def __init__(self, model: 'CustomModel', data):
method get_data (line 16) | def get_data(self):
method get_data_for_role (line 19) | def get_data_for_role(self, index, role):
method childCount (line 23) | def childCount(self):
method child (line 26) | def child(self, row):
method parent (line 30) | def parent(self):
method row (line 33) | def row(self):
method addChild (line 36) | def addChild(self, child):
class CustomModel (line 42) | class CustomModel(QtCore.QAbstractItemModel):
method __init__ (line 44) | def __init__(self, parent, columncount):
method rowCount (line 49) | def rowCount(self, index):
method columnCount (line 54) | def columnCount(self, index):
method addChild (line 57) | def addChild(self, node, _parent):
method index (line 64) | def index(self, row, column, _parent=None):
method parent (line 85) | def parent(self, index):
method data (line 96) | def data(self, index, role):
FILE: electrum/gui/qt/exception_window.py
class Exception_Window (line 46) | class Exception_Window(BaseCrashReporter, QWidget, MessageBoxMixin, Logg...
method __init__ (line 49) | def __init__(self, config: 'SimpleConfig', exctype, value, tb):
method _ask_for_confirm_to_send_report (line 102) | def _ask_for_confirm_to_send_report(self):
method send_report (line 106) | def send_report(self):
method on_close (line 132) | def on_close(self):
method closeEvent (line 136) | def closeEvent(self, event):
method get_user_description (line 140) | def get_user_description(self):
method get_wallet_type (line 143) | def get_wallet_type(self):
method _get_traceback_str_to_display (line 147) | def _get_traceback_str_to_display(self) -> str:
method show_report_contents_dlg (line 154) | def show_report_contents_dlg(self):
function _show_window (line 164) | def _show_window(*args):
class Exception_Hook (line 169) | class Exception_Hook(QObject, Logger):
method __init__ (line 174) | def __init__(self, *, config: 'SimpleConfig'):
method maybe_setup (line 187) | def maybe_setup(cls, *, config: 'SimpleConfig', wallet: 'Abstract_Wall...
method handler (line 193) | def handler(self, *exc_info):
class ReportContentsDialog (line 202) | class ReportContentsDialog(QDialog):
method __init__ (line 204) | def __init__(self, *, parent: QWidget, text: str):
FILE: electrum/gui/qt/fee_slider.py
class FeeComboBox (line 13) | class FeeComboBox(QComboBox):
method __init__ (line 15) | def __init__(self, fee_slider: 'FeeSlider'):
method on_fee_type (line 29) | def on_fee_type(self, x):
class FeeSlider (line 35) | class FeeSlider(QSlider):
method __init__ (line 37) | def __init__(
method dyn (line 55) | def dyn(self) -> bool:
method get_policy (line 58) | def get_policy(self) -> FeePolicy:
method moved (line 61) | def moved(self, pos):
method update (line 72) | def update(self, *, is_initialized: bool = True):
method activate (line 83) | def activate(self):
method deactivate (line 87) | def deactivate(self):
method is_active (line 110) | def is_active(self):
FILE: electrum/gui/qt/history_list.py
class HistorySortModel (line 78) | class HistorySortModel(QSortFilterProxyModel):
method data_for (line 80) | def data_for(self, index: QModelIndex):
method lessThan (line 89) | def lessThan(self, source_left: QModelIndex, source_right: QModelIndex):
function get_item_key (line 93) | def get_item_key(tx_item):
function flatten_sort_key (line 96) | def flatten_sort_key(v):
class HistoryNode (line 103) | class HistoryNode(CustomNode):
method __init__ (line 107) | def __init__(self, model: 'CustomModel', tx_item):
method set_balance (line 137) | def set_balance(self, balance):
method get_data_for_role (line 141) | def get_data_for_role(self, index: QModelIndex, role: Qt.ItemDataRole)...
class HistoryModel (line 241) | class HistoryModel(CustomModel, Logger):
method __init__ (line 243) | def __init__(self, window: 'ElectrumWindow'):
method set_view (line 251) | def set_view(self, history_list: 'HistoryList'):
method update_label (line 257) | def update_label(self, index):
method get_domain (line 265) | def get_domain(self):
method should_include_lightning_payments (line 269) | def should_include_lightning_payments(self) -> bool:
method should_show_fiat (line 273) | def should_show_fiat(self):
method should_show_capital_gains (line 281) | def should_show_capital_gains(self):
method refresh (line 285) | def refresh(self, reason: str):
method set_visibility_of_columns (line 357) | def set_visibility_of_columns(self):
method update_fiat (line 371) | def update_fiat(self, idx):
method update_tx_mined_status (line 381) | def update_tx_mined_status(self, tx_hash: str, tx_mined_info: TxMinedI...
method on_fee_histogram (line 398) | def on_fee_histogram(self):
method headerData (line 408) | def headerData(self, section: int, orientation: Qt.Orientation, role: ...
method flags (line 432) | def flags(self, idx: QModelIndex) -> Qt.ItemFlag:
method _tx_mined_info_from_tx_item (line 439) | def _tx_mined_info_from_tx_item(tx_item: Dict[str, Any]) -> TxMinedInfo:
class HistoryList (line 450) | class HistoryList(MyTreeView, AcceptFileDragDrop):
class Columns (line 452) | class Columns(MyTreeView.BaseColumnsEnum):
method tx_item_from_proxy_row (line 471) | def tx_item_from_proxy_row(self, proxy_row):
method should_hide (line 475) | def should_hide(self, proxy_row):
method __init__ (line 485) | def __init__(self, main_window: 'ElectrumWindow', model: HistoryModel):
method update (line 519) | def update(self):
method format_date (line 522) | def format_date(self, d):
method on_combo (line 525) | def on_combo(self, x):
method create_toolbar (line 546) | def create_toolbar(self, config: 'SimpleConfig'):
method update_toolbar_menu (line 560) | def update_toolbar_menu(self):
method get_toolbar_buttons (line 568) | def get_toolbar_buttons(self):
method on_hide_toolbar (line 571) | def on_hide_toolbar(self):
method select_start_date (line 576) | def select_start_date(self):
method select_end_date (line 580) | def select_end_date(self):
method select_date (line 584) | def select_date(self, button):
method show_summary (line 606) | def show_summary(self):
method plot_history_dialog (line 678) | def plot_history_dialog(self):
method on_edited (line 697) | def on_edited(self, idx, edit_key, *, text):
method on_double_click (line 714) | def on_double_click(self, idx):
method add_copy_menu (line 726) | def add_copy_menu(self, menu, idx):
method create_menu (line 742) | def create_menu(self, position: QPoint):
method remove_local_tx (line 804) | def remove_local_tx(self, tx_hash: str):
method onFileAdded (line 817) | def onFileAdded(self, fn):
method export_history_dialog (line 828) | def export_history_dialog(self):
method get_text_from_coordinate (line 858) | def get_text_from_coordinate(self, row, col):
method get_role_data_from_coordinate (line 861) | def get_role_data_from_coordinate(self, row, col, *, role):
FILE: electrum/gui/qt/invoice_list.py
class InvoiceList (line 54) | class InvoiceList(MyTreeView):
class Columns (line 57) | class Columns(MyTreeView.BaseColumnsEnum):
method __init__ (line 71) | def __init__(self, send_tab: 'SendTab'):
method on_double_click (line 86) | def on_double_click(self, idx):
method refresh_row (line 90) | def refresh_row(self, key, row):
method update (line 106) | def update(self):
method show_invoice (line 144) | def show_invoice(self, key):
method hide_if_empty (line 154) | def hide_if_empty(self):
method create_menu (line 159) | def create_menu(self, position):
method show_log (line 200) | def show_log(self, key, log: Sequence[HtlcLog]):
method delete_invoices (line 216) | def delete_invoices(self, keys):
FILE: electrum/gui/qt/lightning_dialog.py
class LightningDialog (line 40) | class LightningDialog(QDialog, QtEventListener):
method __init__ (line 42) | def __init__(self, gui_object: 'ElectrumGui'):
method on_event_channel_db (line 72) | def on_event_channel_db(self, num_nodes, num_channels, num_policies):
method on_event_gossip_peers (line 77) | def on_event_gossip_peers(self, num_peers):
method on_event_unknown_channels (line 81) | def on_event_unknown_channels(self, unknown):
method is_hidden (line 84) | def is_hidden(self):
method show_or_hide (line 87) | def show_or_hide(self):
method bring_to_top (line 93) | def bring_to_top(self):
method closeEvent (line 97) | def closeEvent(self, event):
FILE: electrum/gui/qt/lightning_tx_dialog.py
class LightningTxDialog (line 42) | class LightningTxDialog(WindowModalDialog):
method __init__ (line 44) | def __init__(self, parent: 'ElectrumWindow', tx_item: dict):
FILE: electrum/gui/qt/locktimeedit.py
class LockTimeEdit (line 20) | class LockTimeEdit(QWidget):
method __init__ (line 24) | def __init__(self, parent=None):
method get_locktime (line 73) | def get_locktime(self) -> Optional[int]:
method set_locktime (line 76) | def set_locktime(self, x: Any) -> None:
class _LockTimeEditor (line 80) | class _LockTimeEditor:
method get_locktime (line 84) | def get_locktime(self) -> Optional[int]:
method set_locktime (line 87) | def set_locktime(self, x: Any) -> None:
method is_acceptable_locktime (line 91) | def is_acceptable_locktime(cls, x: Any) -> bool:
class LockTimeRawEdit (line 101) | class LockTimeRawEdit(QLineEdit, _LockTimeEditor):
method __init__ (line 103) | def __init__(self, parent=None):
method numbify (line 108) | def numbify(self):
method get_locktime (line 120) | def get_locktime(self) -> Optional[int]:
method set_locktime (line 126) | def set_locktime(self, x: Any) -> None:
class LockTimeHeightEdit (line 137) | class LockTimeHeightEdit(LockTimeRawEdit):
method __init__ (line 140) | def __init__(self, parent=None):
method paintEvent (line 144) | def paintEvent(self, event):
function get_max_allowed_timestamp (line 155) | def get_max_allowed_timestamp() -> int:
class LockTimeDateEdit (line 167) | class LockTimeDateEdit(QDateTimeEdit, _LockTimeEditor):
method __init__ (line 171) | def __init__(self, parent=None):
method get_locktime (line 177) | def get_locktime(self) -> Optional[int]:
method set_locktime (line 182) | def set_locktime(self, x: Any) -> None:
FILE: electrum/gui/qt/main_window.py
class StatusBarButton (line 113) | class StatusBarButton(QToolButton):
method __init__ (line 115) | def __init__(self, icon, tooltip, func, sb_height):
method onPress (line 129) | def onPress(self, checked=False):
method keyPressEvent (line 133) | def keyPressEvent(self, e):
function protected (line 138) | def protected(func):
class ElectrumWindow (line 164) | class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListen...
method __init__ (line 172) | def __init__(self, gui_object: 'ElectrumGui', wallet: Abstract_Wallet):
method run_coroutine_dialog (line 319) | def run_coroutine_dialog(self, coro, text):
method run_coroutine_from_thread (line 325) | def run_coroutine_from_thread(self, coro, name, on_result=None):
method toggle_lock (line 348) | def toggle_lock(self):
method update_lock_menu (line 359) | def update_lock_menu(self):
method unlock_wallet (line 365) | def unlock_wallet(self, password, message=None):
method lock_wallet (line 377) | def lock_wallet(self):
method on_fx_history (line 388) | def on_fx_history(self):
method on_fx_quotes (line 392) | def on_fx_quotes(self):
method toggle_tab (line 404) | def toggle_tab(self, tab):
method push_top_level_window (line 422) | def push_top_level_window(self, window):
method pop_top_level_window (line 428) | def pop_top_level_window(self, window):
method top_level_window (line 431) | def top_level_window(self, test_func=None):
method diagnostic_name (line 438) | def diagnostic_name(self):
method is_hidden (line 442) | def is_hidden(self):
method show_or_hide (line 445) | def show_or_hide(self):
method bring_to_top (line 451) | def bring_to_top(self):
method on_error (line 455) | def on_error(self, exc_info):
method on_event_wallet_updated (line 472) | def on_event_wallet_updated(self, wallet):
method on_event_new_transaction (line 477) | def on_event_new_transaction(self, wallet: Abstract_Wallet, tx: Transa...
method on_event_password_required (line 483) | def on_event_password_required(self, wallet):
method on_event_password_not_required (line 488) | def on_event_password_not_required(self, wallet):
method on_password_required_button_clicked (line 492) | def on_password_required_button_clicked(self):
method on_event_status (line 503) | def on_event_status(self):
method on_event_network_updated (line 507) | def on_event_network_updated(self, *args):
method on_event_blockchain_updated (line 511) | def on_event_blockchain_updated(self, *args):
method on_event_on_quotes (line 516) | def on_event_on_quotes(self, *args):
method on_event_on_history (line 520) | def on_event_on_history(self, *args):
method on_event_gossip_db_loaded (line 524) | def on_event_gossip_db_loaded(self, *args):
method on_event_channels_updated (line 528) | def on_event_channels_updated(self, *args):
method on_event_channel (line 534) | def on_event_channel(self, *args):
method on_event_banner (line 541) | def on_event_banner(self, *args):
method on_event_adb_set_future_tx (line 545) | def on_event_adb_set_future_tx(self, adb, txid):
method on_event_verified (line 552) | def on_event_verified(self, *args):
method on_event_fee_histogram (line 558) | def on_event_fee_histogram(self, *args):
method on_event_ln_gossip_sync_progress (line 562) | def on_event_ln_gossip_sync_progress(self, *args):
method on_event_cert_mismatch (line 566) | def on_event_cert_mismatch(self, *args):
method on_event_tor_probed (line 570) | def on_event_tor_probed(self, is_tor):
method on_event_proxy_set (line 574) | def on_event_proxy_set(self, *args):
method on_event_recently_opened_wallets_update (line 578) | def on_event_recently_opened_wallets_update(self
Condensed preview — 776 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (9,669K chars).
[
{
"path": ".cirrus.yml",
"chars": 14015,
"preview": "# unittests using the 'latest' runtime python-dependencies\ntask:\n container:\n image: $ELECTRUM_IMAGE\n cpu: 1\n "
},
{
"path": ".editorconfig",
"chars": 239,
"preview": "# see https://EditorConfig.org\n\nroot = true\n\n[*]\nindent_style = space\ntrim_trailing_whitespace = true\nend_of_line = lf\nc"
},
{
"path": ".gitattributes",
"chars": 314,
"preview": "# Auto detect text files and perform end-of-line normalization (to LF)\n* text=auto\n\n# These Windows files should "
},
{
"path": ".github/ISSUE_TEMPLATE/01_issue.yml",
"chars": 1237,
"preview": "name: Issue\ndescription: Submit a new issue.\n#labels: [bug]\nbody:\n - type: markdown\n attributes:\n value: |\n "
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 317,
"preview": "blank_issues_enabled: false\ncontact_links:\n# - name: Electrum Security Policy\n# url: https://github.com/spesmilo/ele"
},
{
"path": ".gitignore",
"chars": 810,
"preview": ".git/\n####-*.patch\n**/*.pyc\n*.swp\nbuild/\ndist/\n*.egg/\nElectrum.egg-info/\n.devlocaltmp/\n*_trial_temp\npackages\nenv/\n/.venv"
},
{
"path": ".gitmodules",
"chars": 289,
"preview": "[submodule \"electrum/locale\"]\n path = electrum/locale\n url = https://github.com/spesmilo/electrum-locale\n ignor"
},
{
"path": "AUTHORS",
"chars": 554,
"preview": "ThomasV - Creator and maintainer.\nAnimazing / Tachikoma - Styled the new GUI. Mac version.\nAzelphur - GUI stuff.\nCoblee "
},
{
"path": "LICENCE",
"chars": 1135,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2011-2024 The Electrum developers\nCopyright (c) 2011-2024 Thomas Voegtlin\n\nPermissi"
},
{
"path": "MANIFEST.in",
"chars": 849,
"preview": "include LICENCE RELEASE-NOTES AUTHORS\ninclude README.md\ninclude electrum.desktop\ninclude *.py\ninclude run_electrum\ninclu"
},
{
"path": "README.md",
"chars": 4814,
"preview": "# Electrum - Lightweight Bitcoin client\n\n```\nLicence: MIT Licence\nAuthor: Thomas Voegtlin\nLanguage: Python (>= 3.10)\nHom"
},
{
"path": "RELEASE-NOTES",
"chars": 118270,
"preview": "# Release 4.7.1 (Feb 26, 2026)\n * Qt GUI (desktop):\n - new: changelog website accessible from \"Help\" toolbar menu (#10"
},
{
"path": "SECURITY.md",
"chars": 1000,
"preview": "# Security Policy\n\n## Reporting a Vulnerability\n\nTo report security issues, send an email to the addresses listed below."
},
{
"path": "contrib/add_cosigner",
"chars": 2936,
"preview": "#!/usr/bin/python3\n#\n# This script is part of the workflow for BUILDERs to reproduce and sign the\n# release binaries. (f"
},
{
"path": "contrib/android/Dockerfile",
"chars": 11367,
"preview": "# based on https://github.com/kivy/python-for-android/blob/master/Dockerfile\n\nFROM debian:trixie@sha256:a3b5f4f0286249a1"
},
{
"path": "contrib/android/Makefile",
"chars": 1672,
"preview": "SHELL := /bin/bash\nPYTHON = python3\n\n# for reproducible builds\nexport LC_ALL := C\nexport TZ "
},
{
"path": "contrib/android/Readme.md",
"chars": 8486,
"preview": "# Qml GUI\n\nThe Qml GUI is used with Electrum on Android devices, since Electrum 4.4.\nTo generate an APK file, follow the"
},
{
"path": "contrib/android/apkdiff.py",
"chars": 4085,
"preview": "#! /usr/bin/env python3\n# from https://github.com/signalapp/Signal-Android/blob/2029ea378f249a70983c1fc3d55b9a63588bc06c"
},
{
"path": "contrib/android/apt.preferences",
"chars": 64,
"preview": "Package: *\nPin: origin \"snapshot.debian.org\"\nPin-Priority: 1001\n"
},
{
"path": "contrib/android/apt.sources.list",
"chars": 158,
"preview": "deb https://snapshot.debian.org/archive/debian/20260129T082333Z/ trixie main\ndeb-src https://snapshot.debian.org/archive"
},
{
"path": "contrib/android/bitcoin_intent.xml",
"chars": 351,
"preview": "<intent-filter >\n <action android:name=\"android.intent.action.VIEW\" />\n <action android:name=\"android.nfc.action.NDEF_"
},
{
"path": "contrib/android/build.sh",
"chars": 3328,
"preview": "#!/bin/bash\n#\n# env vars:\n# - ELECBUILD_NOCACHE: if set, forces rebuild of docker image\n# - ELECBUILD_COMMIT: if set, do"
},
{
"path": "contrib/android/buildozer_qml.spec",
"chars": 10196,
"preview": "[app]\n\n# (str) Title of your application\ntitle = Electrum\n\n# (str) Package name\npackage.name = Electrum\n\n# (str) Package"
},
{
"path": "contrib/android/dl-ndk-ci.sh",
"chars": 290,
"preview": "#!/bin/sh\nif [ -z \"$1\" ]; then\n echo \"missing url\"\n exit 1\nfi\necho $1\n\ncurl $1 | grep \"var JSVariables\" | python3 -c \""
},
{
"path": "contrib/android/get_apk_versioncode.py",
"chars": 2973,
"preview": "#!/usr/bin/python3\n\nimport importlib.util\nimport os\nimport sys\n\nARCH_DICT = {\n \"x86_64\": \"4\",\n \"arm64-v8a\": \"3\",\n "
},
{
"path": "contrib/android/make_apk.sh",
"chars": 4047,
"preview": "#!/bin/bash\n\nset -e\n\nCONTRIB_ANDROID=\"$(dirname \"$(readlink -e \"$0\")\")\"\nCONTRIB=\"$CONTRIB_ANDROID\"/..\nPROJECT_ROOT=\"$CON"
},
{
"path": "contrib/android/make_barcode_scanner.sh",
"chars": 6293,
"preview": "#!/bin/bash\n\n# script to clone and build https://github.com/markusfisch/BarcodeScannerView and its dependencies,\n# https"
},
{
"path": "contrib/android/p4a_recipes/README.md",
"chars": 503,
"preview": "python-for-android local recipes\n--------------------------------\n\nThese folders are recipes (build scripts) for most of"
},
{
"path": "contrib/android/p4a_recipes/cffi/__init__.py",
"chars": 630,
"preview": "import os\n\nfrom pythonforandroid.recipes.cffi import CffiRecipe\nfrom pythonforandroid.util import load_source\n\nutil = lo"
},
{
"path": "contrib/android/p4a_recipes/cryptography/__init__.py",
"chars": 490,
"preview": "from pythonforandroid.recipes.cryptography import CryptographyRecipe\n\n\nassert CryptographyRecipe._version == \"2.8\"\nasser"
},
{
"path": "contrib/android/p4a_recipes/hostpython3/__init__.py",
"chars": 684,
"preview": "import os\n\nfrom pythonforandroid.recipes.hostpython3 import HostPython3Recipe\nfrom pythonforandroid.util import load_sou"
},
{
"path": "contrib/android/p4a_recipes/libffi/__init__.py",
"chars": 600,
"preview": "import os\n\nfrom pythonforandroid.recipes.libffi import LibffiRecipe\nfrom pythonforandroid.util import load_source\n\nutil "
},
{
"path": "contrib/android/p4a_recipes/libiconv/__init__.py",
"chars": 612,
"preview": "import os\n\nfrom pythonforandroid.recipes.libiconv import LibIconvRecipe\nfrom pythonforandroid.util import load_source\n\nu"
},
{
"path": "contrib/android/p4a_recipes/libsecp256k1/__init__.py",
"chars": 530,
"preview": "from pythonforandroid.recipes.libsecp256k1 import LibSecp256k1Recipe\n\n\nassert LibSecp256k1Recipe.depends == []\nassert Li"
},
{
"path": "contrib/android/p4a_recipes/libzbar/__init__.py",
"chars": 736,
"preview": "import os\n\nfrom pythonforandroid.recipes.libzbar import LibZBarRecipe\nfrom pythonforandroid.util import load_source\n\nuti"
},
{
"path": "contrib/android/p4a_recipes/openssl/__init__.py",
"chars": 608,
"preview": "import os\n\nfrom pythonforandroid.recipes.openssl import OpenSSLRecipe\nfrom pythonforandroid.util import load_source\n\nuti"
},
{
"path": "contrib/android/p4a_recipes/packaging/__init__.py",
"chars": 598,
"preview": "from pythonforandroid.recipes.packaging import PackagingRecipe\n\n\nassert PackagingRecipe._version == \"21.3\"\nassert Packag"
},
{
"path": "contrib/android/p4a_recipes/ply/__init__.py",
"chars": 573,
"preview": "import os\n\nfrom pythonforandroid.recipes.ply import PlyRecipe\nfrom pythonforandroid.util import load_source\n\nutil = load"
},
{
"path": "contrib/android/p4a_recipes/plyer/__init__.py",
"chars": 346,
"preview": "from pythonforandroid.recipe import PythonRecipe\n\n\nassert PythonRecipe.depends == ['python3']\nassert PythonRecipe.python"
},
{
"path": "contrib/android/p4a_recipes/pycparser/__init__.py",
"chars": 462,
"preview": "from pythonforandroid.recipes.pycparser import PycparserRecipe\n\n\nassert PycparserRecipe._version == \"2.14\"\nassert Pycpar"
},
{
"path": "contrib/android/p4a_recipes/pycryptodomex/__init__.py",
"chars": 499,
"preview": "from pythonforandroid.recipe import PythonRecipe\n\n\nassert PythonRecipe.depends == ['python3']\nassert PythonRecipe.python"
},
{
"path": "contrib/android/p4a_recipes/pyjnius/__init__.py",
"chars": 658,
"preview": "import os\n\nfrom pythonforandroid.recipes.pyjnius import PyjniusRecipe\nfrom pythonforandroid.util import load_source\n\nuti"
},
{
"path": "contrib/android/p4a_recipes/pyparsing/__init__.py",
"chars": 962,
"preview": "from pythonforandroid.recipes.pyparsing import PyparsingRecipe\n\n\nassert PyparsingRecipe._version == \"3.0.7\"\nassert Pypar"
},
{
"path": "contrib/android/p4a_recipes/pyqt6/__init__.py",
"chars": 641,
"preview": "import os\n\nfrom pythonforandroid.recipes.pyqt6 import PyQt6Recipe\nfrom pythonforandroid.util import load_source\n\nutil = "
},
{
"path": "contrib/android/p4a_recipes/pyqt6sip/__init__.py",
"chars": 616,
"preview": "import os\n\nfrom pythonforandroid.recipes.pyqt6sip import PyQt6SipRecipe\nfrom pythonforandroid.util import load_source\n\nu"
},
{
"path": "contrib/android/p4a_recipes/pyqt_builder/__init__.py",
"chars": 466,
"preview": "from pythonforandroid.recipes.pyqt_builder import PyQtBuilderRecipe\n\n\nassert PyQtBuilderRecipe._version == \"1.15.1\"\nasse"
},
{
"path": "contrib/android/p4a_recipes/python3/__init__.py",
"chars": 701,
"preview": "import os\n\nfrom pythonforandroid.recipes.python3 import Python3Recipe\nfrom pythonforandroid.util import load_source\n\nuti"
},
{
"path": "contrib/android/p4a_recipes/qt6/__init__.py",
"chars": 759,
"preview": "import os\n\nfrom pythonforandroid.recipes.qt6 import Qt6Recipe\n\nfrom pythonforandroid.util import load_source\n\nutil = loa"
},
{
"path": "contrib/android/p4a_recipes/setuptools/__init__.py",
"chars": 437,
"preview": "from pythonforandroid.recipes.setuptools import SetuptoolsRecipe\n\n\nassert SetuptoolsRecipe._version == \"51.3.3\"\nassert S"
},
{
"path": "contrib/android/p4a_recipes/sip/__init__.py",
"chars": 442,
"preview": "from pythonforandroid.recipes.sip import SipRecipe\n\n\nassert SipRecipe._version == \"6.7.9\"\nassert SipRecipe.depends == [\""
},
{
"path": "contrib/android/p4a_recipes/six/__init__.py",
"chars": 418,
"preview": "from pythonforandroid.recipes.six import SixRecipe\n\n\nassert SixRecipe._version == \"1.15.0\"\nassert SixRecipe.depends == ["
},
{
"path": "contrib/android/p4a_recipes/sqlite3/__init__.py",
"chars": 680,
"preview": "import os\n\nfrom pythonforandroid.recipes.sqlite3 import Sqlite3Recipe\nfrom pythonforandroid.util import load_source\n\nuti"
},
{
"path": "contrib/android/p4a_recipes/toml/__init__.py",
"chars": 403,
"preview": "from pythonforandroid.recipes.toml import TomlRecipe\n\n\nassert TomlRecipe._version == \"0.10.2\"\nassert TomlRecipe.depends "
},
{
"path": "contrib/android/p4a_recipes/tomli/__init__.py",
"chars": 545,
"preview": "from pythonforandroid.recipes.tomli import TomliRecipe\n\n\nassert TomliRecipe._version == \"2.0.1\"\nassert TomliRecipe.depen"
},
{
"path": "contrib/android/p4a_recipes/util.py",
"chars": 461,
"preview": "import os\n\n\nclass InheritedRecipeMixin:\n\n def get_recipe_dir(self):\n \"\"\"This is used to replace pythonforandro"
},
{
"path": "contrib/apparmor/README.md",
"chars": 941,
"preview": "# Electrum AppArmor Profiles\nAppArmor is a Mandatory Access Control (MAC) system which confines programs to a limited se"
},
{
"path": "contrib/apparmor/apparmor.d/abstractions/electrum",
"chars": 1269,
"preview": "include <abstractions/base>\ninclude <abstractions/fonts>\ninclude <abstractions/user-tmp>\ninclude <abstractions/X>\ninclud"
},
{
"path": "contrib/apparmor/apparmor.d/electrum.appimage",
"chars": 698,
"preview": "# Credits : Mikhail Morfikov\nabi <abi/3.0>,\n\ninclude <tunables/global>\n\n@{exec_path} = /{usr/,}bin/fusermount{,3}\nprofil"
},
{
"path": "contrib/apparmor/apparmor.d/usr.local.bin.electrum",
"chars": 314,
"preview": "#Credits: Anton Nesterov\nabi <abi/3.0>,\n\ninclude <tunables/global>\n\n@{electrum_exec_path} = /{usr/,usr/local/,*/*/.local"
},
{
"path": "contrib/ban_unicode.py",
"chars": 2047,
"preview": "#!/usr/bin/env python3\n#\n# Copyright (C) 2025 The Electrum developers\n# Distributed under the MIT software license, see "
},
{
"path": "contrib/build-linux/appimage/.dockerignore",
"chars": 15,
"preview": "build/\n.cache/\n"
},
{
"path": "contrib/build-linux/appimage/Dockerfile",
"chars": 2512,
"preview": "# Note: we deliberately use an old Debian stable as base image.\n# from https://docs.appimage.org/introduction/concepts.h"
},
{
"path": "contrib/build-linux/appimage/README.md",
"chars": 1701,
"preview": "AppImage binary for Electrum\n============================\n\n✓ _This binary should be reproducible, meaning you should be "
},
{
"path": "contrib/build-linux/appimage/apprun.sh",
"chars": 364,
"preview": "#!/bin/bash\n\nset -e\n\nAPPDIR=\"$(dirname \"$(readlink -e \"$0\")\")\"\n\nexport LD_LIBRARY_PATH=\"${APPDIR}/usr/lib/:${APPDIR}/usr"
},
{
"path": "contrib/build-linux/appimage/apt.preferences",
"chars": 64,
"preview": "Package: *\nPin: origin \"snapshot.debian.org\"\nPin-Priority: 1001\n"
},
{
"path": "contrib/build-linux/appimage/apt.sources.list",
"chars": 162,
"preview": "deb https://snapshot.debian.org/archive/debian/20250530T143637Z/ bullseye main\ndeb-src https://snapshot.debian.org/archi"
},
{
"path": "contrib/build-linux/appimage/build.sh",
"chars": 2677,
"preview": "#!/bin/bash\n#\n# env vars:\n# - ELECBUILD_NOCACHE: if set, forces rebuild of docker image\n# - ELECBUILD_COMMIT: if set, do"
},
{
"path": "contrib/build-linux/appimage/make_appimage.sh",
"chars": 12174,
"preview": "#!/bin/bash\n\nset -e\n\nPROJECT_ROOT=\"$(dirname \"$(readlink -e \"$0\")\")/../../..\"\nCONTRIB=\"$PROJECT_ROOT/contrib\"\nCONTRIB_AP"
},
{
"path": "contrib/build-linux/appimage/make_type2_runtime.sh",
"chars": 1362,
"preview": "#!/bin/bash\n\nset -e\n\nPROJECT_ROOT=\"$(dirname \"$(readlink -e \"$0\")\")/../../..\"\nCONTRIB=\"$PROJECT_ROOT/contrib\"\nCONTRIB_AP"
},
{
"path": "contrib/build-linux/appimage/patches/python-3.11-reproducible-buildinfo.diff",
"chars": 705,
"preview": "Description: Build reproduceable date and time into build info\n Build information is encoded into getbuildinfo.o at buil"
},
{
"path": "contrib/build-linux/appimage/patches/type2-runtime-reproducible-build.patch",
"chars": 5458,
"preview": "From 0c54d91dd1d33235ae97566600e692edfb613642 Mon Sep 17 00:00:00 2001\nFrom: f321x <f@f321x.com>\nDate: Thu, 10 Jul 2025 "
},
{
"path": "contrib/build-linux/sdist/.dockerignore",
"chars": 0,
"preview": ""
},
{
"path": "contrib/build-linux/sdist/Dockerfile",
"chars": 961,
"preview": "FROM debian:bookworm@sha256:b877a1a3fdf02469440f1768cf69c9771338a875b7add5e80c45b756c92ac20a\n\nENV LC_ALL=C.UTF-8 LANG=C."
},
{
"path": "contrib/build-linux/sdist/README.md",
"chars": 2231,
"preview": "# Source tarballs\n\n✓ _These tarballs should be reproducible, meaning you should be able to generate\n distributables th"
},
{
"path": "contrib/build-linux/sdist/build.sh",
"chars": 2381,
"preview": "#!/bin/bash\n#\n# env vars:\n# - ELECBUILD_NOCACHE: if set, forces rebuild of docker image\n# - ELECBUILD_COMMIT: if set, do"
},
{
"path": "contrib/build-linux/sdist/make_sdist.sh",
"chars": 2684,
"preview": "#!/bin/bash\n\nset -e\n\nPROJECT_ROOT=\"$(dirname \"$(readlink -e \"$0\")\")/../../..\"\nCONTRIB=\"$PROJECT_ROOT/contrib\"\nCONTRIB_SD"
},
{
"path": "contrib/build-wine/.dockerignore",
"chars": 34,
"preview": "tmp/\nbuild/\n.cache/\ndist/\nsigned/\n"
},
{
"path": "contrib/build-wine/Dockerfile",
"chars": 2512,
"preview": "FROM debian:trixie@sha256:13f29b6806e531c3ff3b565bb6eed73f2132506c8c9d41bb996065ca20fb27f2\n\n# need ca-certificates befor"
},
{
"path": "contrib/build-wine/README.md",
"chars": 3454,
"preview": "# Windows binaries\n\n✓ _These binaries should be reproducible, meaning you should be able to generate\n binaries that ma"
},
{
"path": "contrib/build-wine/README_windows.md",
"chars": 2001,
"preview": "# Running Electrum from source on Windows (development version)\n\n## Prerequisites\n\n- [python3](https://www.python.org/)\n"
},
{
"path": "contrib/build-wine/apt.preferences",
"chars": 64,
"preview": "Package: *\nPin: origin \"snapshot.debian.org\"\nPin-Priority: 1001\n"
},
{
"path": "contrib/build-wine/apt.sources.list",
"chars": 158,
"preview": "deb https://snapshot.debian.org/archive/debian/20260227T144551Z/ trixie main\ndeb-src https://snapshot.debian.org/archive"
},
{
"path": "contrib/build-wine/build-electrum-git.sh",
"chars": 4428,
"preview": "#!/bin/bash\n\nNAME_ROOT=electrum\nPROJECT_ROOT=\"$WINEPREFIX/drive_c/electrum\"\n\nexport PYTHONDONTWRITEBYTECODE=1 # don't c"
},
{
"path": "contrib/build-wine/build.sh",
"chars": 2479,
"preview": "#!/bin/bash\n#\n# env vars:\n# - ELECBUILD_NOCACHE: if set, forces rebuild of docker image\n# - ELECBUILD_COMMIT: if set, do"
},
{
"path": "contrib/build-wine/electrum.nsi",
"chars": 9380,
"preview": ";--------------------------------\n;Include Modern UI\n !include \"TextFunc.nsh\" ;Needed for the $GetSize function. I know"
},
{
"path": "contrib/build-wine/gpg_keys/7ED10B6531D7C8E1BC296021FC624643487034E5.asc",
"chars": 6712,
"preview": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nComment: User-ID:\tSteve Dower (Python Release Signing) <steve.dower@microsoft.com>\n"
},
{
"path": "contrib/build-wine/make_win.sh",
"chars": 3953,
"preview": "#!/bin/bash\n\nset -e\n\nhere=\"$(dirname \"$(readlink -e \"$0\")\")\"\ntest -n \"$here\" -a -d \"$here\" || exit\n\nif [ -z \"$WIN_ARCH\" "
},
{
"path": "contrib/build-wine/patches/libiconv-fix-pointer-buf.patch",
"chars": 1664,
"preview": "--- a/lib/iconv.c\t2018-05-03 23:18:55.997221700 -0400\n+++ b/lib/iconv.c\t2018-05-03 23:26:47.611682700 -0400\n@@ -170,12 +"
},
{
"path": "contrib/build-wine/prepare-wine.sh",
"chars": 3912,
"preview": "#!/bin/bash\n\nPYINSTALLER_REPO=\"https://github.com/pyinstaller/pyinstaller.git\"\nPYINSTALLER_COMMIT=\"306d4d92580fea7be7ff2"
},
{
"path": "contrib/build-wine/pyinstaller.spec",
"chars": 5387,
"preview": "# -*- mode: python -*-\nimport sys\nimport os\nfrom typing import TYPE_CHECKING\n\nfrom PyInstaller.utils.hooks import collec"
},
{
"path": "contrib/build-wine/sign.sh",
"chars": 951,
"preview": "#!/bin/bash\n\nset -e\n\nhere=\"$(dirname \"$0\")\"\nif [ -z \"$WIN_SIGNING_PASSWORD\" ]; then\n echo \"password missing\"\n exit"
},
{
"path": "contrib/build-wine/unsign.sh",
"chars": 1174,
"preview": "#!/bin/bash\n\n# exit if command fails\nset -e\n\nPROJECT_ROOT=\"$(dirname \"$(readlink -e \"$0\")\")/../..\"\nCONTRIB=\"$PROJECT_ROO"
},
{
"path": "contrib/build_tools_util.sh",
"chars": 5882,
"preview": "#!/usr/bin/env bash\n\nset -e\n\n# Set a fixed umask as this leaks into docker containers\numask 0022\n\nRED='\\033[0;31m'\nBLUE="
},
{
"path": "contrib/deterministic-build/README.md",
"chars": 474,
"preview": "# Notes\n\nThe frozen dependency lists in this folder are *generated* files.\n\n- Starting from `contrib/requirements/requir"
},
{
"path": "contrib/deterministic-build/check_submodules.sh",
"chars": 592,
"preview": "#!/usr/bin/env bash\n\nset -e\n\nPROJECT_ROOT=\"$(dirname \"$(readlink -e \"$0\")\")/../..\"\nLOCALE=\"$PROJECT_ROOT/electrum/locale"
},
{
"path": "contrib/deterministic-build/find_restricted_dependencies.py",
"chars": 2561,
"preview": "#!/usr/bin/env python3\nimport sys\n\ntry:\n import requests\nexcept ImportError as e:\n sys.exit(f\"Error: {str(e)}. Try"
},
{
"path": "contrib/deterministic-build/requirements-binaries-mac.txt",
"chars": 12383,
"preview": "cffi==1.17.1 \\\n --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \\\n --hash=sha256:09"
},
{
"path": "contrib/deterministic-build/requirements-binaries.txt",
"chars": 12723,
"preview": "cffi==1.17.1 \\\n --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \\\n --hash=sha256:09"
},
{
"path": "contrib/deterministic-build/requirements-build-android.txt",
"chars": 1508,
"preview": "appdirs==1.4.4 \\\n --hash=sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41\ncolorama==0.4.5 \\\n "
},
{
"path": "contrib/deterministic-build/requirements-build-appimage.txt",
"chars": 398,
"preview": "Cython==3.1.1 \\\n --hash=sha256:505ccd413669d5132a53834d792c707974248088c4f60c497deb1b416e366397\npip==25.1.1 \\\n --h"
},
{
"path": "contrib/deterministic-build/requirements-build-base.txt",
"chars": 1680,
"preview": "expandvars==1.0.0 \\\n --hash=sha256:f04070b8260264185f81142cd85e5df9ceef7229e836c5844302c4ccfa00c30d \\\n --hash=sha2"
},
{
"path": "contrib/deterministic-build/requirements-build-mac.txt",
"chars": 822,
"preview": "altgraph==0.17.4 \\\n --hash=sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406\nCython==3.1.1 \\\n "
},
{
"path": "contrib/deterministic-build/requirements-build-wine.txt",
"chars": 830,
"preview": "altgraph==0.17.4 \\\n --hash=sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406\npackaging==25.0 \\\n"
},
{
"path": "contrib/deterministic-build/requirements-hw.txt",
"chars": 34779,
"preview": "base58==2.1.1 \\\n --hash=sha256:11a36f4d3ce51dfc1043f3218591ac4eb1ceb172919cebe05b52a5bcc8d245c2 \\\n --hash=sha256:c"
},
{
"path": "contrib/deterministic-build/requirements.txt",
"chars": 2867,
"preview": "aiohappyeyeballs==2.6.1 \\\n --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558\naiohttp==3."
},
{
"path": "contrib/docker_notes.md",
"chars": 2835,
"preview": "# Using the build scripts\n\nMost of our build scripts are docker-based.\n(All, except the macOS build, which is a separate"
},
{
"path": "contrib/freeze_containers_distro.sh",
"chars": 1665,
"preview": "#!/bin/sh\n\n# Run this after a new release to update pin for build container distro packages\n\nset -e\n\nDEBIAN_SNAPSHOT_BAS"
},
{
"path": "contrib/freeze_packages.sh",
"chars": 2480,
"preview": "#!/bin/bash\n# Run this after a new release to update dependencies\n\nset -e\n\nvenv_dir=~/.electrum-venv\ncontrib=\"$(dirname "
},
{
"path": "contrib/generate_payreqpb2.sh",
"chars": 371,
"preview": "#!/bin/bash\n# Generates the file paymentrequest_pb2.py\n\nset -e\n\nCONTRIB=\"$(dirname \"$(readlink -e \"$0\")\")\"\nEL=\"$CONTRIB\""
},
{
"path": "contrib/locale/build_cleanlocale.sh",
"chars": 381,
"preview": "#!/bin/bash\n\nset -e\n\nCONTRIB_LOCALE=\"$(dirname \"$(realpath \"$0\" 2> /dev/null || grealpath \"$0\")\")\"\nCONTRIB=\"$CONTRIB_LOC"
},
{
"path": "contrib/locale/build_locale.sh",
"chars": 888,
"preview": "#!/bin/bash\n#\n# This script converts human-readable (.po) locale files to compiled (.mo) locale files.\n\nset -e\n\nCONTRIB_"
},
{
"path": "contrib/locale/push_locale.py",
"chars": 7279,
"preview": "#!/usr/bin/env python3\n#\n# This script extracts \"raw\" strings from the codebase,\n# and uploads them to crowdin, for the "
},
{
"path": "contrib/locale/stats.py",
"chars": 2684,
"preview": "#!/usr/bin/env python3\n#\n# Copyright (C) 2026 The Electrum developers\n# Distributed under the MIT software license, see "
},
{
"path": "contrib/make_download",
"chars": 3640,
"preview": "#!/usr/bin/python3\nimport re\nimport os\nimport sys\nimport importlib\nfrom collections import defaultdict\n\n\nif len(sys.argv"
},
{
"path": "contrib/make_libsecp256k1.sh",
"chars": 2997,
"preview": "#!/bin/bash\n\n# This script was tested on Linux and MacOS hosts, where it can be used\n# to build native libsecp256k1 bina"
},
{
"path": "contrib/make_libusb.sh",
"chars": 2237,
"preview": "#!/bin/bash\n\nLIBUSB_VERSION=\"d52e355daa09f17ce64819122cb067b8a2ee0d4b\"\n# ^ tag v1.0.27\n\nset -e\n\n. \"$(dirname \"$0\")/build"
},
{
"path": "contrib/make_packages.sh",
"chars": 2476,
"preview": "#!/bin/bash\n# This script installs our pure python dependencies into the 'packages' folder.\n\nset -e\n\nCONTRIB=\"$(dirname "
},
{
"path": "contrib/make_plugin",
"chars": 1602,
"preview": "#!/usr/bin/python3\nimport os\nimport sys\nimport hashlib\nimport json\nimport zipfile\nimport zipimport\n\n# todo: use version "
},
{
"path": "contrib/make_zbar.sh",
"chars": 3532,
"preview": "#!/bin/bash\n\n# This script can be used on Linux hosts to build native libzbar binaries.\n# sudo apt-get install pkg-confi"
},
{
"path": "contrib/osx/README.md",
"chars": 9545,
"preview": "Building macOS binaries\n=======================\n\n✓ _This binary should be reproducible, meaning you should be able to ge"
},
{
"path": "contrib/osx/README_macos.md",
"chars": 704,
"preview": "# Running Electrum from source on macOS (development version)\n\n## Prerequisites\n\n- [brew](https://brew.sh/)\n- python3\n- "
},
{
"path": "contrib/osx/apply_sigs.sh",
"chars": 1654,
"preview": "#!/bin/sh\n# Copyright (c) 2014-2019 The Bitcoin Core developers\n# Distributed under the MIT software license, see the ac"
},
{
"path": "contrib/osx/cdrkit-deterministic.patch",
"chars": 2090,
"preview": "--- cdrkit-1.1.11.old/genisoimage/tree.c\t2008-10-21 19:57:47.000000000 -0400\n+++ cdrkit-1.1.11/genisoimage/tree.c\t2013-1"
},
{
"path": "contrib/osx/compare_dmg",
"chars": 1706,
"preview": "#!/usr/bin/env bash\nset -e\n\nif [ $(uname) != \"Darwin\" ]; then\n echo \"This script needs to be run on macOS.\"\n exit "
},
{
"path": "contrib/osx/entitlements.plist",
"chars": 883,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "contrib/osx/extract_sigs.sh",
"chars": 2304,
"preview": "#!/bin/sh\n# Copyright (c) 2014-2019 The Bitcoin Core developers\n# Distributed under the MIT software license, see the ac"
},
{
"path": "contrib/osx/make_osx.sh",
"chars": 9675,
"preview": "#!/usr/bin/env bash\n\nset -e\n\n# Parameterize\nPYTHON_VERSION=3.12.10\nPY_VER_MAJOR=\"3.12\" # as it appears in fs paths\nPACK"
},
{
"path": "contrib/osx/notarize_app.sh",
"chars": 1489,
"preview": "#!/usr/bin/env bash\n# from https://github.com/metabrainz/picard/blob/e1354632d2db305b7a7624282701d34d73afa225/scripts/pa"
},
{
"path": "contrib/osx/package.sh",
"chars": 2515,
"preview": "#!/usr/bin/env bash\n\nset -ex\n\nPROJECT_ROOT=\"$(dirname \"$(readlink -e \"$0\")\")/../..\"\nCONTRIB=\"$PROJECT_ROOT/contrib\"\n. \"$"
},
{
"path": "contrib/osx/pyinstaller.spec",
"chars": 4577,
"preview": "# -*- mode: python -*-\nimport sys\nimport os\nfrom typing import TYPE_CHECKING\n\nfrom PyInstaller.utils.hooks import collec"
},
{
"path": "contrib/osx/sign_osx.sh",
"chars": 2374,
"preview": "#!/usr/bin/env bash\n\nset -e\n\nsecurity -v unlock-keychain login.keychain\n\n\nPACKAGE=Electrum\n\n\n. \"$(dirname \"$0\")/../build"
},
{
"path": "contrib/print_electrum_version.py",
"chars": 1046,
"preview": "#!/usr/bin/python3\n# For usage in shell, to get the version of electrum, without needing electrum installed.\n# usage: ./"
},
{
"path": "contrib/release.sh",
"chars": 11944,
"preview": "#!/bin/bash\n#\n# This script is used for stage 1 of the release process. It operates exclusively on the airlock.\n# This s"
},
{
"path": "contrib/release_www.sh",
"chars": 1964,
"preview": "#!/bin/bash\n#\n# env vars:\n# - WWW_DIR: path to \"electrum-web\" git clone\n# - for signing the version announcement file:\n#"
},
{
"path": "contrib/requirements/requirements-binaries-mac.txt",
"chars": 260,
"preview": "# Qt 6.8 would require macOS 12+, 6.7 still supports macOS 11\n# Qt 6.7 has issue \"No QtMultimedia backends found.\" (i.e"
},
{
"path": "contrib/requirements/requirements-binaries.txt",
"chars": 138,
"preview": "PyQt6\n\n# we need at least cryptography>=2.1 for electrum.crypto,\n# and at least cryptography>=2.6 for dnspython[DNSSEC]\n"
},
{
"path": "contrib/requirements/requirements-build-android.txt",
"chars": 335,
"preview": "pip\nsetuptools\nwheel\n\n# needed by buildozer:\npexpect\nsh\n# some p4a recipes don't work with cython 3+\ncython<3.0\n\n# neede"
},
{
"path": "contrib/requirements/requirements-build-appimage.txt",
"chars": 365,
"preview": "pip\nsetuptools\nwheel\n\n# Note: hidapi requires Cython at build-time (not needed at runtime).\n# For reproducible builds, t"
},
{
"path": "contrib/requirements/requirements-build-base.txt",
"chars": 1447,
"preview": "# This file contains build-time dependencies needed to build other higher level build-time dependencies\n# and runtime de"
},
{
"path": "contrib/requirements/requirements-build-mac.txt",
"chars": 524,
"preview": "pip\nsetuptools\nwheel\n\n# needed by pyinstaller:\n# fixme: ugly to have to duplicate this here from upstream\nmacholib>=1.8\n"
},
{
"path": "contrib/requirements/requirements-build-wine.txt",
"chars": 217,
"preview": "pip\nsetuptools\nwheel\n\n# needed by pyinstaller:\n# fixme: ugly to have to duplicate this here from upstream\npefile>=2022.5"
},
{
"path": "contrib/requirements/requirements-ci.txt",
"chars": 26,
"preview": "pytest\ncoverage\ncoveralls\n"
},
{
"path": "contrib/requirements/requirements-hw.txt",
"chars": 525,
"preview": "hidapi\n\n# device plugin: trezor\ntrezor[hidapi]>=0.13.0,<0.14\n\n# device plugin: safe_t\nsafet>=0.1.5\n\n# device plugin: kee"
},
{
"path": "contrib/requirements/requirements.txt",
"chars": 590,
"preview": "qrcode\nprotobuf>=3.20\nqdarkstyle>=3.2\naiorpcx>=0.25.0,<0.26\naiohttp>=3.11.0,<4.0.0\naiohttp_socks>=0.9.2\ncertifi\njsonpatc"
},
{
"path": "contrib/sign_packages",
"chars": 351,
"preview": "#!/usr/bin/env python3\nimport os, sys\n\nif __name__ == '__main__':\n username = sys.argv[1]\n os.chdir(\"dist\")\n fo"
},
{
"path": "contrib/trigger_deploy.sh",
"chars": 915,
"preview": "#!/bin/bash\n# Triggers deploy.sh to maybe update the website or move binaries.\n# uploadserver needs to be defined in /et"
},
{
"path": "contrib/udev/20-hw1.rules",
"chars": 386,
"preview": "# HW.1, Nano\nSUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"2581\", ATTRS{idProduct}==\"1b7c|2b7c|3b7c|4b7c\", TAG+=\"uaccess\", TAG+=\""
},
{
"path": "contrib/udev/51-coinkite.rules",
"chars": 618,
"preview": "# Linux udev support file.\n#\n# This is a example udev file for HIDAPI devices which changes the permissions\n# to 0666 (w"
},
{
"path": "contrib/udev/51-hid-digitalbitbox.rules",
"chars": 119,
"preview": "SUBSYSTEM==\"usb\", TAG+=\"uaccess\", TAG+=\"udev-acl\", SYMLINK+=\"dbb%n\", ATTRS{idVendor}==\"03eb\", ATTRS{idProduct}==\"2402\"\n"
},
{
"path": "contrib/udev/51-safe-t.rules",
"chars": 687,
"preview": "# Put this file into /usr/lib/udev/rules.d or /etc/udev/rules.d\n\n# Archos Safe-T mini\nSUBSYSTEM==\"usb\", ATTR{idVendor}=="
},
{
"path": "contrib/udev/51-trezor.rules",
"chars": 978,
"preview": "# Trezor: The Original Hardware Wallet\n# https://trezor.io/\n#\n# Put this file into /etc/udev/rules.d\n#\n# If you are crea"
},
{
"path": "contrib/udev/51-usb-keepkey.rules",
"chars": 769,
"preview": "# KeepKey: Your Private Bitcoin Vault\n# http://www.keepkey.com/\n# Put this file into /usr/lib/udev/rules.d or /etc/udev/"
},
{
"path": "contrib/udev/52-hid-digitalbitbox.rules",
"chars": 142,
"preview": "KERNEL==\"hidraw*\", SUBSYSTEM==\"hidraw\", ATTRS{idVendor}==\"03eb\", ATTRS{idProduct}==\"2402\", TAG+=\"uaccess\", TAG+=\"udev-ac"
},
{
"path": "contrib/udev/53-hid-bitbox02.rules",
"chars": 125,
"preview": "SUBSYSTEM==\"usb\", TAG+=\"uaccess\", TAG+=\"udev-acl\", SYMLINK+=\"bitbox02_%n\", ATTRS{idVendor}==\"03eb\", ATTRS{idProduct}==\"2"
},
{
"path": "contrib/udev/54-hid-bitbox02.rules",
"chars": 147,
"preview": "KERNEL==\"hidraw*\", SUBSYSTEM==\"hidraw\", ATTRS{idVendor}==\"03eb\", ATTRS{idProduct}==\"2403\", TAG+=\"uaccess\", TAG+=\"udev-ac"
},
{
"path": "contrib/udev/55-usb-jade.rules",
"chars": 340,
"preview": "KERNEL==\"ttyUSB*\", SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"10c4\", ATTRS{idProduct}==\"ea60\", MODE=\"0660\", GROUP=\"plugdev\", T"
},
{
"path": "contrib/udev/README.md",
"chars": 1555,
"preview": "# udev rules\n\nThis directory contains all of the udev rules for the supported devices\nas retrieved from vendor websites "
},
{
"path": "contrib/upload.sh",
"chars": 873,
"preview": "#!/bin/bash\n# uploadserver is set in /etc/hosts\n#\n# env vars:\n# - ELECBUILD_UPLOADFROM\n# - SSHUSER\n\nset -ex\n\nPROJECT_ROO"
},
{
"path": "electrum/__init__.py",
"chars": 1703,
"preview": "import sys\nimport os\n\n# these are ~duplicated from run_electrum:\nis_bundle = getattr(sys, 'frozen', False)\nis_local = no"
},
{
"path": "electrum/_vendor/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "electrum/_vendor/distutils/LICENSE",
"chars": 13931,
"preview": "A. HISTORY OF THE SOFTWARE\n==========================\n\nPython was created in the early 1990s by Guido van Rossum at Stic"
},
{
"path": "electrum/_vendor/distutils/__init__.py",
"chars": 173,
"preview": "\"\"\"(part of) distutils, taken from the cpython standard library\n\nat commit https://github.com/python/cpython/tree/9d3812"
},
{
"path": "electrum/_vendor/distutils/version.py",
"chars": 12514,
"preview": "#\n# distutils/version.py\n#\n# Implements multiple version numbering conventions for the\n# Python Module Distribution Util"
},
{
"path": "electrum/_vendor/pyperclip/LICENSE.txt",
"chars": 1487,
"preview": "Copyright (c) 2014, Al Sweigart\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without"
},
{
"path": "electrum/_vendor/pyperclip/README.md",
"chars": 303,
"preview": "\nThis is a stripped-down copy of the 3rd-party `pyperclip` package.\n\nIt is used by the \"text\" GUI.\n\nAt revision https://"
},
{
"path": "electrum/_vendor/pyperclip/__init__.py",
"chars": 25819,
"preview": "\"\"\"\nPyperclip\n\nA cross-platform clipboard module for Python, with copy & paste functions for plain text.\nBy Al Sweigart "
},
{
"path": "electrum/address_synchronizer.py",
"chars": 47764,
"preview": "# Electrum - lightweight Bitcoin client\n# Copyright (C) 2018 The Electrum Developers\n#\n# Permission is hereby granted, f"
},
{
"path": "electrum/base_crash_reporter.py",
"chars": 9625,
"preview": "# Electrum - lightweight Bitcoin client\n#\n# Permission is hereby granted, free of charge, to any person\n# obtaining a co"
},
{
"path": "electrum/bip21.py",
"chars": 4775,
"preview": "import urllib\nimport urllib.parse\nimport re\nfrom decimal import Decimal\nfrom typing import Optional\n\nfrom . import bitco"
},
{
"path": "electrum/bip32.py",
"chars": 20218,
"preview": "# Copyright (C) 2018 The Electrum developers\n# Distributed under the MIT software license, see the accompanying\n# file L"
},
{
"path": "electrum/bip39_recovery.py",
"chars": 3382,
"preview": "# Copyright (C) 2020 The Electrum developers\n# Distributed under the MIT software license, see the accompanying\n# file L"
},
{
"path": "electrum/bip39_wallet_formats.json",
"chars": 3308,
"preview": "[\n {\n \"description\": \"Standard BIP44 legacy\",\n \"derivation_path\": \"m/44'/0'/0'\",\n \"script_type\":"
},
{
"path": "electrum/bitcoin.py",
"chars": 29095,
"preview": "# -*- coding: utf-8 -*-\n#\n# Electrum - lightweight Bitcoin client\n# Copyright (C) 2011 thomasv@gitorious\n#\n# Permission "
},
{
"path": "electrum/blockchain.py",
"chars": 28890,
"preview": "# Electrum - lightweight Bitcoin client\n# Copyright (C) 2012 thomasv@ecdsa.org\n#\n# Permission is hereby granted, free of"
},
{
"path": "electrum/chains/mainnet/checkpoints.json",
"chars": 72250,
"preview": "[\n [\n \"00000000693067b0e6b440bc51450b9f3850561b07f6d3c021c54fbd6abb9763\",\n 2695953529101130949315647634"
},
{
"path": "electrum/chains/mainnet/fallback_lnnodes.json",
"chars": 3250,
"preview": "{\n \"0294ac3e099def03c12a37e30fe5364b1223fd60069869142ef96580c8439c2e0a\": {\n \"host\": \"8.210.134.135\",\n \"port\": 266"
},
{
"path": "electrum/chains/mainnet/servers.json",
"chars": 10705,
"preview": "{\n \"5.9.83.108\": {\n \"pruning\": \"-\",\n \"s\": \"50002\",\n \"version\": \"1.6.0\"\n },\n \"104.248.139.211\": {"
},
{
"path": "electrum/chains/mutinynet/fallback_lnnodes.json",
"chars": 500,
"preview": "{\n \"02465ed5be53d04fde66c9418ff14a5f2267723810176c9212b722e542dc1afb1b\": {\n \"host\": \"45.79.52.207\",\n \"port\": 9735"
},
{
"path": "electrum/chains/mutinynet/servers.json",
"chars": 100,
"preview": "{\n \"5.9.83.108\": {\n \"pruning\": \"-\",\n \"s\": \"51234\",\n \"version\": \"1.4\"\n }\n}"
},
{
"path": "electrum/chains/regtest/servers.json",
"chars": 122,
"preview": "{\n \"127.0.0.1\": {\n \"pruning\": \"-\",\n \"s\": \"51002\",\n \"t\": \"51001\",\n \"version\": \"1.4\"\n }\n"
},
{
"path": "electrum/chains/signet/checkpoints.json",
"chars": 14258,
"preview": "[\n [\n \"000000c0a3841a6ae64c45864ae25314b40fd522bfb299a4b6bd5ef288cae74d\",\n 0\n ],\n [\n \"0000"
},
{
"path": "electrum/chains/signet/fallback_lnnodes.json",
"chars": 1518,
"preview": "{\n \"02357a375a846279fc1e8413f5e182652a125e5f6a4f4653bffabebb8177a6d8aa\": {\n \"host\": \"34.68.95.152\",\n \"port\": 9735"
},
{
"path": "electrum/chains/signet/servers.json",
"chars": 348,
"preview": "{\n \"signet-electrumx.wakiyamap.dev\": {\n \"pruning\": \"-\",\n \"s\": \"50002\",\n \"t\": \"50001\",\n \"v"
},
{
"path": "electrum/chains/testnet/checkpoints.json",
"chars": 237602,
"preview": "[\n [\n \"00000000864b744c5025331036aa4a16e9ed1cbb362908c625272150fa059b29\",\n 0\n ],\n [\n \"0000"
},
{
"path": "electrum/chains/testnet/fallback_lnnodes.json",
"chars": 1639,
"preview": "{\n \"038863cf8ab91046230f561cd5b386cbff8309fa02e3f0c3ed161a3aeb64a643b9\": {\n \"host\": \"203.132.95.10\",\n \"port\": 973"
},
{
"path": "electrum/chains/testnet/servers.json",
"chars": 1031,
"preview": "{\n \"blackie.c3-soft.com\": {\n \"pruning\": \"-\",\n \"s\": \"57006\",\n \"t\": \"57005\",\n \"version\": \"1"
},
{
"path": "electrum/chains/testnet4/checkpoints.json",
"chars": 5942,
"preview": "[\n [\n \"00000000962a7fc2ef639196051fe181ed53ac6aa4cdfead14dca90f58aa36bc\",\n 0\n ],\n [\n \"0000"
},
{
"path": "electrum/chains/testnet4/servers.json",
"chars": 375,
"preview": "{\n \"testnet4-electrumx.wakiyamap.dev\": {\n \"pruning\": \"-\",\n \"s\": \"51002\",\n \"t\": \"51001\",\n "
},
{
"path": "electrum/channel_db.py",
"chars": 50288,
"preview": "# -*- coding: utf-8 -*-\n#\n# Electrum - lightweight Bitcoin client\n# Copyright (C) 2018 The Electrum developers\n#\n# Permi"
},
{
"path": "electrum/coinchooser.py",
"chars": 24434,
"preview": "#!/usr/bin/env python\n#\n# Electrum - lightweight Bitcoin client\n# Copyright (C) 2015 kyuupichan@gmail\n#\n# Permission is "
},
{
"path": "electrum/commands.py",
"chars": 109025,
"preview": "#!/usr/bin/env python\n#\n# Electrum - lightweight Bitcoin client\n# Copyright (C) 2011 thomasv@gitorious\n#\n# Permission is"
},
{
"path": "electrum/constants.py",
"chars": 9417,
"preview": "# -*- coding: utf-8 -*-\n#\n# Electrum - lightweight Bitcoin client\n# Copyright (C) 2018 The Electrum developers\n#\n# Permi"
},
{
"path": "electrum/contacts.py",
"chars": 6251,
"preview": "# Electrum - Lightweight Bitcoin Client\n# Copyright (c) 2015 Thomas Voegtlin\n#\n# Permission is hereby granted, free of c"
},
{
"path": "electrum/crypto.py",
"chars": 18808,
"preview": "# -*- coding: utf-8 -*-\n#\n# Electrum - lightweight Bitcoin client\n# Copyright (C) 2018 The Electrum developers\n#\n# Permi"
},
{
"path": "electrum/currencies.json",
"chars": 13457,
"preview": "{\n \"Bit2C\": [\n \"ILS\"\n ],\n \"BitFinex\": [\n \"EUR\",\n \"GBP\",\n \"JPY\",\n \"TRY\",\n "
},
{
"path": "electrum/daemon.py",
"chars": 31292,
"preview": "#!/usr/bin/env python\n#\n# Electrum - lightweight Bitcoin client\n# Copyright (C) 2015 Thomas Voegtlin\n#\n# Permission is h"
},
{
"path": "electrum/descriptor.py",
"chars": 41254,
"preview": "# Copyright (c) 2017 Andrew Chow\n# Copyright (c) 2023 The Electrum developers\n# Distributed under the MIT software licen"
},
{
"path": "electrum/dns_hacks.py",
"chars": 3941,
"preview": "# Copyright (C) 2020 The Electrum developers\n# Distributed under the MIT software license, see the accompanying\n# file L"
},
{
"path": "electrum/dnssec.py",
"chars": 6613,
"preview": "#!/usr/bin/env python\n#\n# Electrum - lightweight Bitcoin client\n# Copyright (C) 2015 Thomas Voegtlin\n#\n# Permission is h"
},
{
"path": "electrum/exchange_rate.py",
"chars": 32509,
"preview": "import asyncio\nfrom datetime import datetime\nimport inspect\nimport sys\nimport os\nimport json\nimport time\nimport csv\nimpo"
}
]
// ... and 576 more files (download for full content)
About this extraction
This page contains the full source code of the spesmilo/electrum GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 776 files (8.9 MB), approximately 2.4M tokens, and a symbol index with 9653 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.