├── gui ├── kivy │ ├── uix │ │ ├── __init__.py │ │ ├── dialogs │ │ │ ├── nfc_transaction.py │ │ │ ├── qr_scanner.py │ │ │ ├── qr_dialog.py │ │ │ ├── question.py │ │ │ ├── checkbox_dialog.py │ │ │ ├── label_dialog.py │ │ │ ├── wallets.py │ │ │ ├── choice_dialog.py │ │ │ └── password_dialog.py │ │ ├── context_menu.py │ │ ├── ui_screens │ │ │ ├── requests.kv │ │ │ ├── invoices.kv │ │ │ ├── about.kv │ │ │ ├── network.kv │ │ │ ├── history.kv │ │ │ ├── invoice.kv │ │ │ └── status.kv │ │ ├── combobox.py │ │ └── menus.py │ ├── data │ │ ├── background.png │ │ ├── fonts │ │ │ ├── Roboto.ttf │ │ │ ├── tron │ │ │ │ ├── Tr2n.ttf │ │ │ │ ├── License.txt │ │ │ │ └── Readme.txt │ │ │ ├── Roboto-Bold.ttf │ │ │ ├── Roboto-Medium.ttf │ │ │ └── Roboto-Condensed.ttf │ │ ├── glsl │ │ │ ├── default.png │ │ │ ├── default.fs │ │ │ ├── default.vs │ │ │ ├── header.fs │ │ │ └── header.vs │ │ ├── logo │ │ │ └── kivy-icon-32.png │ │ └── images │ │ │ ├── defaulttheme-0.png │ │ │ └── defaulttheme.atlas │ ├── theming │ │ └── light │ │ │ ├── card.png │ │ │ ├── gear.png │ │ │ ├── info.png │ │ │ ├── logo.png │ │ │ ├── nfc.png │ │ │ ├── pen.png │ │ │ ├── save.png │ │ │ ├── tab.png │ │ │ ├── btn_nfc.png │ │ │ ├── camera.png │ │ │ ├── clock1.png │ │ │ ├── clock2.png │ │ │ ├── clock3.png │ │ │ ├── clock4.png │ │ │ ├── clock5.png │ │ │ ├── close.png │ │ │ ├── contact.png │ │ │ ├── dialog.png │ │ │ ├── error.png │ │ │ ├── globe.png │ │ │ ├── network.png │ │ │ ├── qrcode.png │ │ │ ├── shadow.png │ │ │ ├── tab_btn.png │ │ │ ├── wallet.png │ │ │ ├── wallets.png │ │ │ ├── bit_logo.png │ │ │ ├── card_btn.png │ │ │ ├── card_top.png │ │ │ ├── confirmed.png │ │ │ ├── important.png │ │ │ ├── mail_icon.png │ │ │ ├── nfc_clock.png │ │ │ ├── nfc_phone.png │ │ │ ├── settings.png │ │ │ ├── tab_strip.png │ │ │ ├── action_bar.png │ │ │ ├── add_contact.png │ │ │ ├── arrow_back.png │ │ │ ├── btn_send_nfc.png │ │ │ ├── calculator.png │ │ │ ├── card_bottom.png │ │ │ ├── closebutton.png │ │ │ ├── icon_border.png │ │ │ ├── manualentry.png │ │ │ ├── paste_icon.png │ │ │ ├── shadow_right.png │ │ │ ├── stepper_full.png │ │ │ ├── stepper_left.png │ │ │ ├── tab_disabled.png │ │ │ ├── unconfirmed.png │ │ │ ├── logo_atom_dull.png │ │ │ ├── nfc_stage_one.png │ │ │ ├── action_group_dark.png │ │ │ ├── blue_bg_round_rb.png │ │ │ ├── btn_send_address.png │ │ │ ├── carousel_selected.png │ │ │ ├── contact_overlay.png │ │ │ ├── create_act_text.png │ │ │ ├── electrum_icon640.png │ │ │ ├── overflow_btn_dn.png │ │ │ ├── star_big_inactive.png │ │ │ ├── tab_btn_disabled.png │ │ │ ├── tab_btn_pressed.png │ │ │ ├── textinput_active.png │ │ │ ├── action_button_group.png │ │ │ ├── action_group_light.png │ │ │ ├── btn_create_account.png │ │ │ ├── carousel_deselected.png │ │ │ ├── dropdown_background.png │ │ │ ├── overflow_background.png │ │ │ ├── white_bg_round_top.png │ │ │ ├── create_act_text_active.png │ │ │ ├── lightblue_bg_round_lb.png │ │ │ ├── stepper_restore_seed.png │ │ │ ├── btn_create_act_disabled.png │ │ │ └── stepper_restore_password.png │ ├── tools │ │ ├── bitcoin_intent.xml │ │ └── blacklist.txt │ ├── Readme.rst │ ├── Makefile │ ├── i18n.py │ ├── nfc_scanner │ │ ├── __init__.py │ │ └── scanner_dummy.py │ └── __init__.py ├── __init__.py └── qt │ ├── address_dialog.py │ └── qrwindow.py ├── plugins ├── hw_wallet │ ├── __init__.py │ └── plugin.py ├── email_requests │ └── __init__.py ├── exchange_rate │ ├── __init__.py │ └── kivy.py ├── plot │ └── __init__.py ├── greenaddress_instant │ └── __init__.py ├── audio_modem │ └── __init__.py ├── virtualkeyboard │ ├── __init__.py │ └── qt.py ├── ledger │ ├── __init__.py │ ├── cmdline.py │ └── qt.py ├── keepkey │ ├── __init__.py │ ├── qt.py │ ├── client.py │ ├── cmdline.py │ └── keepkey.py ├── trezor │ ├── __init__.py │ ├── qt.py │ ├── client.py │ ├── cmdline.py │ └── trezor.py ├── labels │ ├── __init__.py │ ├── kivy.py │ └── qt.py ├── cosigner_pool │ └── __init__.py ├── trustedcoin │ └── __init__.py ├── __init__.py └── README ├── Uwallet.ico ├── uwallet.ico ├── icons ├── copy.png ├── file.png ├── key.png ├── left.png ├── lock.png ├── page.png ├── seal.png ├── seed.png ├── zoom.png ├── Slider.png ├── caveat.png ├── clock1.png ├── clock2.png ├── clock3.png ├── clock4.png ├── clock5.png ├── ic_spa.png ├── ic_up.png ├── ledger.png ├── prompt.png ├── qrcode.png ├── right.png ├── trezor.png ├── unlock.png ├── unpaid.png ├── warn1.png ├── warn2.png ├── confirmed.png ├── drop_down.png ├── electrum.ico ├── electrum.png ├── expired.png ├── ic_clear.png ├── ic_down.png ├── ic_folder.png ├── ic_remove.png ├── ic_search.png ├── keepkey.png ├── last_page.png ├── network.png ├── next_page.png ├── options.png ├── speaker.png ├── warning.png ├── first_page.png ├── ic_crop_5_4.png ├── ic_qr_code.png ├── ic_query_0.png ├── ic_settings.png ├── ic_spa_pre.png ├── microphone.png ├── network_red.png ├── options_box.png ├── options_pre.png ├── preferences.png ├── trustedcoin.png ├── unconfirmed.png ├── first_page_pre.png ├── ic_clear_pre.png ├── ic_folder_pre.png ├── ic_lock_colse.png ├── ic_lock_open.png ├── ic_qr_code_pre.png ├── ic_remove_pre.png ├── last_page_pre.png ├── network_green.png ├── network_yellow.png ├── next_page_pre.png ├── previous_page.png ├── small_window.png ├── status_lagging.png ├── status_waiting.png ├── ic_crop_5_4_pre.png ├── ic_library_books.png ├── ic_lock_open_pre.png ├── ic_settings_pre.png ├── keepkey_unpaired.png ├── ledger_unpaired.png ├── options_box_pre.png ├── small_window_pre.png ├── status_connected.png ├── trezor_unpaired.png ├── electrum_dark_icon.png ├── electrum_launcher.png ├── electrum_light_icon.png ├── ic_clear_copy_pre.png ├── ic_lock_colse_pre.png ├── previous_page_pre.png ├── status_disconnected.png ├── electrum_light_icon1.png ├── ic_library_books_pre.png └── electrum_android_launcher_icon.png ├── uwallet.icns ├── lib ├── cryptohello_hash.so ├── locale │ └── zh_CN │ │ ├── ulord.mo │ │ └── LC_MESSAGES │ │ └── ulord.mo ├── www │ └── example.php ├── version.py ├── __init__.py ├── i18n.py ├── signmessage.py ├── paymentrequest.proto ├── msqr.py ├── qrscanner.py └── contacts.py ├── .gitignore ├── .travis.yml ├── tox.ini ├── scripts ├── estimate_fee ├── get_history ├── txradar ├── servers ├── block_headers ├── watch_address ├── bip70 ├── peers └── util.py ├── contrib ├── make_apk ├── sign_packages ├── build-wine │ ├── portable.patch │ ├── README.rst │ ├── prepare-hw.sh │ ├── prepare-wine.sh │ ├── build-electrum-git.sh │ └── deterministic.spec ├── make_download ├── make_packages └── make_locale ├── MANIFEST.in ├── uwallet.conf.sample ├── uwallet.desktop ├── AUTHORS ├── Info.plist ├── uwallet-env ├── UpdateAppClient_install.py ├── progressbar_pyinstaller.py ├── app.fil ├── uwallet_pyinstaller.py ├── process.dat ├── c.spec ├── progressbarWindow.spec ├── UpdateAppClient.spec ├── LICENCE ├── uwallet.spec ├── version ├── README.rst ├── pubkeys ├── Animazing.asc └── kyuupichan.asc ├── setup.py ├── setup-release.py └── deterministic.spec /gui/kivy/uix/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /plugins/hw_wallet/__init__.py: -------------------------------------------------------------------------------- 1 | from plugin import HW_PluginBase 2 | -------------------------------------------------------------------------------- /Uwallet.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/Uwallet.ico -------------------------------------------------------------------------------- /uwallet.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/uwallet.ico -------------------------------------------------------------------------------- /icons/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/copy.png -------------------------------------------------------------------------------- /icons/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/file.png -------------------------------------------------------------------------------- /icons/key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/key.png -------------------------------------------------------------------------------- /icons/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/left.png -------------------------------------------------------------------------------- /icons/lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/lock.png -------------------------------------------------------------------------------- /icons/page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/page.png -------------------------------------------------------------------------------- /icons/seal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/seal.png -------------------------------------------------------------------------------- /icons/seed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/seed.png -------------------------------------------------------------------------------- /icons/zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/zoom.png -------------------------------------------------------------------------------- /uwallet.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/uwallet.icns -------------------------------------------------------------------------------- /icons/Slider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/Slider.png -------------------------------------------------------------------------------- /icons/caveat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/caveat.png -------------------------------------------------------------------------------- /icons/clock1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/clock1.png -------------------------------------------------------------------------------- /icons/clock2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/clock2.png -------------------------------------------------------------------------------- /icons/clock3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/clock3.png -------------------------------------------------------------------------------- /icons/clock4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/clock4.png -------------------------------------------------------------------------------- /icons/clock5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/clock5.png -------------------------------------------------------------------------------- /icons/ic_spa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_spa.png -------------------------------------------------------------------------------- /icons/ic_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_up.png -------------------------------------------------------------------------------- /icons/ledger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ledger.png -------------------------------------------------------------------------------- /icons/prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/prompt.png -------------------------------------------------------------------------------- /icons/qrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/qrcode.png -------------------------------------------------------------------------------- /icons/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/right.png -------------------------------------------------------------------------------- /icons/trezor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/trezor.png -------------------------------------------------------------------------------- /icons/unlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/unlock.png -------------------------------------------------------------------------------- /icons/unpaid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/unpaid.png -------------------------------------------------------------------------------- /icons/warn1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/warn1.png -------------------------------------------------------------------------------- /icons/warn2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/warn2.png -------------------------------------------------------------------------------- /icons/confirmed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/confirmed.png -------------------------------------------------------------------------------- /icons/drop_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/drop_down.png -------------------------------------------------------------------------------- /icons/electrum.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/electrum.ico -------------------------------------------------------------------------------- /icons/electrum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/electrum.png -------------------------------------------------------------------------------- /icons/expired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/expired.png -------------------------------------------------------------------------------- /icons/ic_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_clear.png -------------------------------------------------------------------------------- /icons/ic_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_down.png -------------------------------------------------------------------------------- /icons/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_folder.png -------------------------------------------------------------------------------- /icons/ic_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_remove.png -------------------------------------------------------------------------------- /icons/ic_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_search.png -------------------------------------------------------------------------------- /icons/keepkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/keepkey.png -------------------------------------------------------------------------------- /icons/last_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/last_page.png -------------------------------------------------------------------------------- /icons/network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/network.png -------------------------------------------------------------------------------- /icons/next_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/next_page.png -------------------------------------------------------------------------------- /icons/options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/options.png -------------------------------------------------------------------------------- /icons/speaker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/speaker.png -------------------------------------------------------------------------------- /icons/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/warning.png -------------------------------------------------------------------------------- /icons/first_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/first_page.png -------------------------------------------------------------------------------- /icons/ic_crop_5_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_crop_5_4.png -------------------------------------------------------------------------------- /icons/ic_qr_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_qr_code.png -------------------------------------------------------------------------------- /icons/ic_query_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_query_0.png -------------------------------------------------------------------------------- /icons/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_settings.png -------------------------------------------------------------------------------- /icons/ic_spa_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_spa_pre.png -------------------------------------------------------------------------------- /icons/microphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/microphone.png -------------------------------------------------------------------------------- /icons/network_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/network_red.png -------------------------------------------------------------------------------- /icons/options_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/options_box.png -------------------------------------------------------------------------------- /icons/options_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/options_pre.png -------------------------------------------------------------------------------- /icons/preferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/preferences.png -------------------------------------------------------------------------------- /icons/trustedcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/trustedcoin.png -------------------------------------------------------------------------------- /icons/unconfirmed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/unconfirmed.png -------------------------------------------------------------------------------- /icons/first_page_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/first_page_pre.png -------------------------------------------------------------------------------- /icons/ic_clear_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_clear_pre.png -------------------------------------------------------------------------------- /icons/ic_folder_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_folder_pre.png -------------------------------------------------------------------------------- /icons/ic_lock_colse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_lock_colse.png -------------------------------------------------------------------------------- /icons/ic_lock_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_lock_open.png -------------------------------------------------------------------------------- /icons/ic_qr_code_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_qr_code_pre.png -------------------------------------------------------------------------------- /icons/ic_remove_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_remove_pre.png -------------------------------------------------------------------------------- /icons/last_page_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/last_page_pre.png -------------------------------------------------------------------------------- /icons/network_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/network_green.png -------------------------------------------------------------------------------- /icons/network_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/network_yellow.png -------------------------------------------------------------------------------- /icons/next_page_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/next_page_pre.png -------------------------------------------------------------------------------- /icons/previous_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/previous_page.png -------------------------------------------------------------------------------- /icons/small_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/small_window.png -------------------------------------------------------------------------------- /icons/status_lagging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/status_lagging.png -------------------------------------------------------------------------------- /icons/status_waiting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/status_waiting.png -------------------------------------------------------------------------------- /lib/cryptohello_hash.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/lib/cryptohello_hash.so -------------------------------------------------------------------------------- /icons/ic_crop_5_4_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_crop_5_4_pre.png -------------------------------------------------------------------------------- /icons/ic_library_books.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_library_books.png -------------------------------------------------------------------------------- /icons/ic_lock_open_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_lock_open_pre.png -------------------------------------------------------------------------------- /icons/ic_settings_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_settings_pre.png -------------------------------------------------------------------------------- /icons/keepkey_unpaired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/keepkey_unpaired.png -------------------------------------------------------------------------------- /icons/ledger_unpaired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ledger_unpaired.png -------------------------------------------------------------------------------- /icons/options_box_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/options_box_pre.png -------------------------------------------------------------------------------- /icons/small_window_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/small_window_pre.png -------------------------------------------------------------------------------- /icons/status_connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/status_connected.png -------------------------------------------------------------------------------- /icons/trezor_unpaired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/trezor_unpaired.png -------------------------------------------------------------------------------- /lib/locale/zh_CN/ulord.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/lib/locale/zh_CN/ulord.mo -------------------------------------------------------------------------------- /gui/kivy/data/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/data/background.png -------------------------------------------------------------------------------- /icons/electrum_dark_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/electrum_dark_icon.png -------------------------------------------------------------------------------- /icons/electrum_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/electrum_launcher.png -------------------------------------------------------------------------------- /icons/electrum_light_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/electrum_light_icon.png -------------------------------------------------------------------------------- /icons/ic_clear_copy_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_clear_copy_pre.png -------------------------------------------------------------------------------- /icons/ic_lock_colse_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_lock_colse_pre.png -------------------------------------------------------------------------------- /icons/previous_page_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/previous_page_pre.png -------------------------------------------------------------------------------- /icons/status_disconnected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/status_disconnected.png -------------------------------------------------------------------------------- /gui/kivy/data/fonts/Roboto.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/data/fonts/Roboto.ttf -------------------------------------------------------------------------------- /gui/kivy/data/glsl/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/data/glsl/default.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/card.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/gear.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/info.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/logo.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/nfc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/nfc.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/pen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/pen.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/save.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/tab.png -------------------------------------------------------------------------------- /icons/electrum_light_icon1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/electrum_light_icon1.png -------------------------------------------------------------------------------- /icons/ic_library_books_pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/ic_library_books_pre.png -------------------------------------------------------------------------------- /gui/kivy/data/fonts/tron/Tr2n.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/data/fonts/tron/Tr2n.ttf -------------------------------------------------------------------------------- /gui/kivy/theming/light/btn_nfc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/btn_nfc.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/camera.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/clock1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/clock1.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/clock2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/clock2.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/clock3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/clock3.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/clock4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/clock4.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/clock5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/clock5.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/close.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/contact.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/dialog.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/error.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/globe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/globe.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/network.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/qrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/qrcode.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/shadow.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/tab_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/tab_btn.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/wallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/wallet.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/wallets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/wallets.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | build 3 | *.egg 4 | *.xml 5 | .idea/workspace.xml 6 | 7 | *.pyd 8 | *.pyc 9 | /dist 10 | /UWallet.egg-info -------------------------------------------------------------------------------- /gui/kivy/data/fonts/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/data/fonts/Roboto-Bold.ttf -------------------------------------------------------------------------------- /gui/kivy/data/logo/kivy-icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/data/logo/kivy-icon-32.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/bit_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/bit_logo.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/card_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/card_btn.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/card_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/card_top.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/confirmed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/confirmed.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/important.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/important.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/mail_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/mail_icon.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/nfc_clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/nfc_clock.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/nfc_phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/nfc_phone.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/settings.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/tab_strip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/tab_strip.png -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: python 3 | python: 4 | - "2.7" 5 | install: 6 | - pip install tox 7 | script: 8 | - tox 9 | -------------------------------------------------------------------------------- /gui/kivy/data/fonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/data/fonts/Roboto-Medium.ttf -------------------------------------------------------------------------------- /gui/kivy/data/glsl/default.fs: -------------------------------------------------------------------------------- 1 | $HEADER$ 2 | void main (void){ 3 | gl_FragColor = frag_color * texture2D(texture0, tex_coord0); 4 | } 5 | -------------------------------------------------------------------------------- /gui/kivy/data/images/defaulttheme-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/data/images/defaulttheme-0.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/action_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/action_bar.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/add_contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/add_contact.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/arrow_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/arrow_back.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/btn_send_nfc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/btn_send_nfc.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/calculator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/calculator.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/card_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/card_bottom.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/closebutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/closebutton.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/icon_border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/icon_border.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/manualentry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/manualentry.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/paste_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/paste_icon.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/shadow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/shadow_right.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/stepper_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/stepper_full.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/stepper_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/stepper_left.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/tab_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/tab_disabled.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/unconfirmed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/unconfirmed.png -------------------------------------------------------------------------------- /lib/locale/zh_CN/LC_MESSAGES/ulord.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/lib/locale/zh_CN/LC_MESSAGES/ulord.mo -------------------------------------------------------------------------------- /gui/kivy/data/fonts/Roboto-Condensed.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/data/fonts/Roboto-Condensed.ttf -------------------------------------------------------------------------------- /gui/kivy/theming/light/logo_atom_dull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/logo_atom_dull.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/nfc_stage_one.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/nfc_stage_one.png -------------------------------------------------------------------------------- /icons/electrum_android_launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/icons/electrum_android_launcher_icon.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/action_group_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/action_group_dark.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/blue_bg_round_rb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/blue_bg_round_rb.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/btn_send_address.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/btn_send_address.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/carousel_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/carousel_selected.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/contact_overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/contact_overlay.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/create_act_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/create_act_text.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/electrum_icon640.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/electrum_icon640.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/overflow_btn_dn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/overflow_btn_dn.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/star_big_inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/star_big_inactive.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/tab_btn_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/tab_btn_disabled.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/tab_btn_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/tab_btn_pressed.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/textinput_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/textinput_active.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/action_button_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/action_button_group.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/action_group_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/action_group_light.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/btn_create_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/btn_create_account.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/carousel_deselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/carousel_deselected.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/dropdown_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/dropdown_background.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/overflow_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/overflow_background.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/white_bg_round_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/white_bg_round_top.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/create_act_text_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/create_act_text_active.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/lightblue_bg_round_lb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/lightblue_bg_round_lb.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/stepper_restore_seed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/stepper_restore_seed.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/btn_create_act_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/btn_create_act_disabled.png -------------------------------------------------------------------------------- /gui/kivy/theming/light/stepper_restore_password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/uwallet-client-pro/HEAD/gui/kivy/theming/light/stepper_restore_password.png -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py27 3 | 4 | [testenv] 5 | deps= 6 | pytest 7 | coverage 8 | commands= 9 | coverage run --source=lib -m py.test -v 10 | coverage report 11 | -------------------------------------------------------------------------------- /plugins/email_requests/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = _('Email') 4 | description = _("Send and receive payment request with an email account") 5 | available_for = ['qt'] 6 | -------------------------------------------------------------------------------- /plugins/exchange_rate/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = _("Exchange rates") 4 | description = _("Exchange rates and currency conversion tools.") 5 | available_for = ['qt','kivy'] 6 | -------------------------------------------------------------------------------- /scripts/estimate_fee: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import util, json 3 | peers = util.get_peers() 4 | results = util.send_request(peers, 'blockchain.estimatefee', [2]) 5 | print json.dumps(results, indent=4) 6 | -------------------------------------------------------------------------------- /contrib/make_apk: -------------------------------------------------------------------------------- 1 | pushd contrib 2 | VERSION=$(python -c "import versions; print versions.version_apk") 3 | popd 4 | echo $VERSION 5 | echo $VERSION > contrib/apk_version 6 | pushd ./gui/kivy/; make apk; popd 7 | -------------------------------------------------------------------------------- /gui/kivy/data/glsl/default.vs: -------------------------------------------------------------------------------- 1 | $HEADER$ 2 | void main (void) { 3 | frag_color = color * vec4(1.0, 1.0, 1.0, opacity); 4 | tex_coord0 = vTexCoords0; 5 | gl_Position = projection_mat * modelview_mat * vec4(vPosition.xy, 0.0, 1.0); 6 | } 7 | -------------------------------------------------------------------------------- /plugins/plot/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = 'Plot History' 4 | description = _("Ability to plot transaction history in graphical mode.") 5 | requires = [('matplotlib', 'matplotlib')] 6 | available_for = ['qt'] 7 | -------------------------------------------------------------------------------- /plugins/greenaddress_instant/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = 'GreenAddress instant' 4 | description = _("Allows validating if your transactions have instant confirmations by GreenAddress") 5 | available_for = ['qt'] 6 | -------------------------------------------------------------------------------- /plugins/audio_modem/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = _('Audio MODEM') 4 | description = _('Provides support for air-gapped transaction signing.') 5 | requires = [('amodem', 'http://github.com/romanz/amodem/')] 6 | available_for = ['qt'] 7 | 8 | -------------------------------------------------------------------------------- /gui/kivy/data/glsl/header.fs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | /* Outputs from the vertex shader */ 6 | varying vec4 frag_color; 7 | varying vec2 tex_coord0; 8 | 9 | /* uniform texture samplers */ 10 | uniform sampler2D texture0; 11 | -------------------------------------------------------------------------------- /plugins/virtualkeyboard/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = 'Virtual Keyboard' 4 | description = '%s\n%s' % (_("Add an optional virtual keyboard to the password dialog."), _("Warning: do not use this if it makes you pick a weaker password.")) 5 | available_for = ['qt'] 6 | -------------------------------------------------------------------------------- /gui/__init__.py: -------------------------------------------------------------------------------- 1 | # To create a new GUI, please add its code to this directory. 2 | # Three objects are passed to the ElectrumGui: config, daemon and plugins 3 | # The Wallet object is instanciated by the GUI 4 | 5 | # Notifications about network events are sent to the GUI by using network.register_callback() 6 | -------------------------------------------------------------------------------- /plugins/ledger/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = 'Ledger Wallet' 4 | description = 'Provides support for Ledger hardware wallet' 5 | requires = [('btchip', 'github.com/ledgerhq/btchip-python')] 6 | registers_keystore = ('hardware', 'ledger', _("Ledger wallet")) 7 | available_for = ['qt', 'cmdline'] 8 | -------------------------------------------------------------------------------- /plugins/keepkey/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = 'KeepKey' 4 | description = _('Provides support for KeepKey hardware wallet') 5 | requires = [('keepkeylib','github.com/keepkey/python-keepkey')] 6 | registers_keystore = ('hardware', 'keepkey', _("KeepKey wallet")) 7 | available_for = ['qt', 'cmdline'] 8 | -------------------------------------------------------------------------------- /plugins/trezor/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = 'TREZOR Wallet' 4 | description = _('Provides support for TREZOR hardware wallet') 5 | requires = [('trezorlib','github.com/trezor/python-trezor')] 6 | registers_keystore = ('hardware', 'trezor', _("TREZOR wallet")) 7 | available_for = ['qt', 'cmdline'] 8 | 9 | -------------------------------------------------------------------------------- /gui/kivy/tools/bitcoin_intent.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /gui/kivy/data/fonts/tron/License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2011, Jeff Bell [www.randombell.com] | [jeffbell@randombell.com]. 2 | This font may be distributed freely however must retain this document as well as the Readme.txt file. 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is available with a FAQ at: http://scripts.sil.org/OFL -------------------------------------------------------------------------------- /plugins/labels/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = _('LabelSync') 4 | description = ' '.join([ 5 | _("Save your wallet labels on a remote server, and synchronize them across multiple devices where you use uwallet."), 6 | _("Labels, transactions IDs and addresses are encrypted before they are sent to the remote server.") 7 | ]) 8 | available_for = ['qt', 'kivy'] 9 | 10 | -------------------------------------------------------------------------------- /plugins/labels/kivy.py: -------------------------------------------------------------------------------- 1 | from labels import LabelsPlugin 2 | from uwallet.plugins import hook 3 | 4 | class Plugin(LabelsPlugin): 5 | 6 | @hook 7 | def load_wallet(self, wallet, window): 8 | self.window = window 9 | self.start_wallet(wallet) 10 | 11 | def on_pulled(self, wallet): 12 | self.print_error('on pulled') 13 | self.window.update_tab('history') 14 | 15 | -------------------------------------------------------------------------------- /plugins/trezor/qt.py: -------------------------------------------------------------------------------- 1 | from ..trezor.qt_generic import QtPlugin 2 | from trezor import TrezorPlugin 3 | 4 | 5 | class Plugin(TrezorPlugin, QtPlugin): 6 | icon_unpaired = ":icons/trezor_unpaired.png" 7 | icon_paired = ":icons/trezor.png" 8 | 9 | @classmethod 10 | def pin_matrix_widget_class(self): 11 | from trezorlib.qt.pinmatrix import PinMatrixWidget 12 | return PinMatrixWidget 13 | -------------------------------------------------------------------------------- /plugins/keepkey/qt.py: -------------------------------------------------------------------------------- 1 | from ..trezor.qt_generic import QtPlugin 2 | from keepkey import KeepKeyPlugin 3 | 4 | 5 | class Plugin(KeepKeyPlugin, QtPlugin): 6 | icon_paired = ":icons/keepkey.png" 7 | icon_unpaired = ":icons/keepkey_unpaired.png" 8 | 9 | @classmethod 10 | def pin_matrix_widget_class(self): 11 | from keepkeylib.qt.pinmatrix import PinMatrixWidget 12 | return PinMatrixWidget 13 | -------------------------------------------------------------------------------- /scripts/get_history: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from uwallet import Network 5 | from uwallet.util import json_encode, print_msg 6 | 7 | try: 8 | addr = sys.argv[1] 9 | except Exception: 10 | print "usage: get_history " 11 | sys.exit(1) 12 | 13 | n = Network() 14 | n.start() 15 | h = n.synchronous_get(('blockchain.address.get_history',[addr])) 16 | print_msg(json_encode(h)) 17 | -------------------------------------------------------------------------------- /plugins/cosigner_pool/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | fullname = _('Cosigner Pool') 3 | description = ' '.join([ 4 | _("This plugin facilitates the use of multi-signatures wallets."), 5 | _("It sends and receives partially signed transactions from/to your cosigner wallet."), 6 | _("Transactions are encrypted and stored on a remote server.") 7 | ]) 8 | #requires_wallet_type = ['2of2', '2of3'] 9 | available_for = ['qt'] 10 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENCE RELEASE-NOTES AUTHORS 2 | include README.rst 3 | include uwallet.conf.sample 4 | include uwallet.desktop 5 | include *.py 6 | include uwallet 7 | recursive-include lib *.py 8 | recursive-include gui *.py 9 | recursive-include plugins *.py 10 | recursive-include packages *.py 11 | recursive-include packages cacert.pem 12 | include app.fil 13 | include icons.qrc 14 | recursive-include icons * 15 | recursive-include scripts * 16 | 17 | -------------------------------------------------------------------------------- /contrib/sign_packages: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | 3 | import sys, re, shutil, os, hashlib 4 | import imp 5 | import getpass 6 | 7 | if __name__ == '__main__': 8 | 9 | os.chdir("dist") 10 | password = getpass.getpass("Password:") 11 | for f in os.listdir('.'): 12 | if f.endswith('asc'): 13 | continue 14 | os.system( "gpg --sign --armor --detach --passphrase \"%s\" %s"%(password, f) ) 15 | 16 | os.chdir("..") 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /gui/kivy/data/glsl/header.vs: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | /* Outputs to the fragment shader */ 6 | varying vec4 frag_color; 7 | varying vec2 tex_coord0; 8 | 9 | /* vertex attributes */ 10 | attribute vec2 vPosition; 11 | attribute vec2 vTexCoords0; 12 | 13 | /* uniform variables */ 14 | uniform mat4 modelview_mat; 15 | uniform mat4 projection_mat; 16 | uniform vec4 color; 17 | uniform float opacity; 18 | -------------------------------------------------------------------------------- /plugins/trustedcoin/__init__.py: -------------------------------------------------------------------------------- 1 | from uwallet.i18n import _ 2 | 3 | fullname = _('Two Factor Authentication') 4 | description = ''.join([ 5 | _("This plugin adds two-factor authentication to your wallet."), '
', 6 | _("For more information, visit"), 7 | " https://api.trustedcoin.com/#/uwallet-help" 8 | ]) 9 | requires_wallet_type = ['2fa'] 10 | registers_wallet_type = '2fa' 11 | available_for = ['qt'] 12 | -------------------------------------------------------------------------------- /uwallet.conf.sample: -------------------------------------------------------------------------------- 1 | # Configuration file for the electrum client 2 | # Settings defined here are shared across wallets 3 | # 4 | # copy this file to /etc/electrum.conf if you want read-only settings 5 | 6 | [client] 7 | server = electrum.novit.ro:50001:t 8 | proxy = None 9 | gap_limit = 5 10 | # booleans use python syntax 11 | use_change = True 12 | gui = qt 13 | num_zeros = 2 14 | # default transaction fee is in Satoshis 15 | fee = 10000 16 | winpos-qt = [799, 226, 877, 435] 17 | -------------------------------------------------------------------------------- /plugins/trezor/client.py: -------------------------------------------------------------------------------- 1 | from trezorlib.client import proto, BaseClient, ProtocolMixin 2 | from clientbase import TrezorClientBase 3 | 4 | class TrezorClient(TrezorClientBase, ProtocolMixin, BaseClient): 5 | def __init__(self, transport, handler, plugin): 6 | BaseClient.__init__(self, transport) 7 | ProtocolMixin.__init__(self, transport) 8 | TrezorClientBase.__init__(self, handler, plugin, proto) 9 | 10 | 11 | TrezorClientBase.wrap_methods(TrezorClient) 12 | -------------------------------------------------------------------------------- /lib/www/example.php: -------------------------------------------------------------------------------- 1 | Wallet balance
'."\n"; 7 | try { 8 | 9 | $balance = $electrum->getbalance(); 10 | echo 'confirmed: '.$balance['confirmed'].'
'."\n"; 11 | echo 'unconfirmed: '.$balance['unconfirmed'].'
'."\n"; 12 | 13 | } catch (Exception $e) { 14 | echo nl2br($e->getMessage()).'
'."\n"; 15 | } 16 | 17 | ?> 18 | -------------------------------------------------------------------------------- /scripts/txradar: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import util, sys 3 | try: 4 | tx = sys.argv[1] 5 | except: 6 | print "usage: txradar txid" 7 | sys.exit(1) 8 | 9 | peers = util.get_peers() 10 | results = util.send_request(peers, 'blockchain.transaction.get', [tx]) 11 | 12 | r1 = [] 13 | r2 = [] 14 | 15 | for k, v in results.items(): 16 | (r1 if v else r2).append(k) 17 | 18 | print "Received %d answers"%len(results) 19 | print "Propagation rate: %.1f percent" % (len(r1) *100./(len(r1)+ len(r2))) 20 | -------------------------------------------------------------------------------- /contrib/build-wine/portable.patch: -------------------------------------------------------------------------------- 1 | diff --git a/electrum b/electrum 2 | index 8c972c6..46903b7 100755 3 | --- a/electrum 4 | +++ b/electrum 5 | @@ -454,6 +454,8 @@ if __name__ == '__main__': 6 | if config_options.get('server'): 7 | config_options['auto_connect'] = False 8 | 9 | + config_options['portable'] = True 10 | + 11 | if config_options.get('portable'): 12 | config_options['electrum_path'] = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'electrum_data') 13 | 14 | -------------------------------------------------------------------------------- /uwallet.desktop: -------------------------------------------------------------------------------- 1 | # If you want electrum to appear in a linux app launcher ("start menu"), install this by doing: 2 | # sudo desktop-file-install electrum.desktop 3 | 4 | [Desktop Entry] 5 | Comment=Lightweight Bitcoin Client 6 | Exec=electrum %u 7 | GenericName[en_US]=Electrum 8 | GenericName=Electrum 9 | Icon=electrum 10 | Name[en_US]=Electrum Bitcoin Wallet 11 | Name=Electrum Bitcoin Wallet 12 | Categories=Network; 13 | StartupNotify=false 14 | Terminal=false 15 | Type=Application 16 | MimeType=x-scheme-handler/bitcoin; 17 | 18 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | ThomasV - Creator and maintainer. 2 | Animazing / Tachikoma - Styled the new GUI. Mac version. 3 | Azelphur - GUI stuff. 4 | Coblee - Alternate coin support and py2app support. 5 | Deafboy - Ubuntu packages. 6 | EagleTM - Bugfixes. 7 | ErebusBat - Mac distribution. 8 | Genjix - Porting pro-mode functionality to lite-gui and worked on server 9 | Slush - Work on the server. Designed the original Stratum spec. 10 | Julian Toash (Tuxavant) - Various fixes to the client. 11 | rdymac - Website and translations. 12 | kyuupichan - Miscellaneous. -------------------------------------------------------------------------------- /plugins/ledger/cmdline.py: -------------------------------------------------------------------------------- 1 | from legder import LedgerPlugin 2 | from uwallet.util import print_msg 3 | 4 | class BTChipCmdLineHandler: 5 | def stop(self): 6 | pass 7 | 8 | def show_message(self, msg): 9 | print_msg(msg) 10 | 11 | def prompt_auth(self, msg): 12 | import getpass 13 | print_msg(msg) 14 | response = getpass.getpass('') 15 | if len(response) == 0: 16 | return None 17 | return response 18 | 19 | class Plugin(LedgerPlugin): 20 | handler = BTChipCmdLineHandler() 21 | -------------------------------------------------------------------------------- /plugins/keepkey/client.py: -------------------------------------------------------------------------------- 1 | from keepkeylib.client import proto, BaseClient, ProtocolMixin 2 | from ..trezor.clientbase import TrezorClientBase 3 | 4 | class KeepKeyClient(TrezorClientBase, ProtocolMixin, BaseClient): 5 | def __init__(self, transport, handler, plugin): 6 | BaseClient.__init__(self, transport) 7 | ProtocolMixin.__init__(self, transport) 8 | TrezorClientBase.__init__(self, handler, plugin, proto) 9 | 10 | def recovery_device(self, *args): 11 | ProtocolMixin.recovery_device(self, False, *args) 12 | 13 | 14 | TrezorClientBase.wrap_methods(KeepKeyClient) 15 | -------------------------------------------------------------------------------- /lib/version.py: -------------------------------------------------------------------------------- 1 | UWallet_VERSION = '1.0.6' # version of the client package 2 | PROTOCOL_VERSION = '0.10' # protocol version requested 3 | 4 | OLD_SEED_VERSION = 4 # electrum versions < 2.0 5 | NEW_SEED_VERSION = 11 # electrum versions >= 2.0 6 | FINAL_SEED_VERSION = 12 # electrum >= 2.7 will set this to prevent 7 | # old versions from overwriting new format 8 | 9 | 10 | # The hash of the mnemonic seed must begin with this 11 | SEED_PREFIX = '01' # Electrum standard wallet 12 | SEED_PREFIX_2FA = '101' # extended seed for two-factor authentication 13 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleURLTypes 6 | 7 | 8 | CFBundleURLName 9 | bitcoin 10 | CFBundleURLSchemes 11 | 12 | bitcoin 13 | 14 | 15 | 16 | LSArchitecturePriority 17 | 18 | x86_64 19 | i386 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /gui/kivy/Readme.rst: -------------------------------------------------------------------------------- 1 | Getting start 2 | =============== 3 | Before compiling, create packages: `contrib/make_packages` 4 | 5 | Commands:: 6 | 7 | `make theming` to make a atlas out of a list of pngs 8 | 9 | `make apk` to make a apk 10 | 11 | 12 | If modules included by the project are changed, like kivy or any other modules, rebuilding is needed: 13 | 14 | rm -rf .buildozer/android/platform/python-for-android/dist 15 | 16 | 17 | Notes: 18 | 19 | 20 | To use internal storage, python-for-android must be patched with: 21 | 22 | git pull git@github.com:denys-duchier/python-for-android.git fix-recursive-delete 23 | -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- 1 | from version import UWallet_VERSION 2 | from util import format_satoshis, print_msg, print_error, set_verbosity 3 | from wallet import Synchronizer, WalletStorage, Wallet, Imported_Wallet 4 | from coinchooser import COIN_CHOOSERS 5 | from network import Network, DEFAULT_SERVERS, DEFAULT_PORTS, pick_random_server 6 | from interface import Connection, Interface 7 | from simple_config import SimpleConfig, get_config, set_config 8 | import bitcoin 9 | import transaction 10 | from transaction import Transaction 11 | from plugins import BasePlugin 12 | from commands import Commands, known_commands 13 | from serialize import * 14 | from privatekey import BitcoinPrivateKey -------------------------------------------------------------------------------- /scripts/servers: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from uwallet import SimpleConfig, set_verbosity 4 | from uwallet.network import filter_protocol 5 | import time, Queue 6 | from collections import defaultdict 7 | 8 | import util, json 9 | set_verbosity(False) 10 | 11 | config = SimpleConfig() 12 | servers = filter_protocol(protocol = 't') 13 | results = util.send_request(servers, 'blockchain.headers.subscribe', []) 14 | 15 | d = defaultdict(int) 16 | 17 | for k, r in results.items(): 18 | blocks = r.get('block_height') 19 | d[blocks] += 1 20 | 21 | 22 | 23 | for k, v in results.items(): 24 | print k, v.get('block_height') 25 | 26 | v = d.values() 27 | numblocks = d.keys()[v.index(max(v))] 28 | print "blocks:",numblocks 29 | -------------------------------------------------------------------------------- /plugins/keepkey/cmdline.py: -------------------------------------------------------------------------------- 1 | from keepkey import KeepKeyPlugin 2 | from uwallet.util import print_msg 3 | 4 | class KeepKeyCmdLineHandler: 5 | 6 | def get_passphrase(self, msg, confirm): 7 | import getpass 8 | print_msg(msg) 9 | return getpass.getpass('') 10 | 11 | def get_pin(self, msg): 12 | t = { 'a':'7', 'b':'8', 'c':'9', 'd':'4', 'e':'5', 'f':'6', 'g':'1', 'h':'2', 'i':'3'} 13 | print_msg(msg) 14 | print_msg("a b c\nd e f\ng h i\n-----") 15 | o = raw_input() 16 | return ''.join(map(lambda x: t[x], o)) 17 | 18 | def stop(self): 19 | pass 20 | 21 | def show_message(self, msg): 22 | print_msg(msg) 23 | 24 | class Plugin(KeepKeyPlugin): 25 | handler = KeepKeyCmdLineHandler() 26 | -------------------------------------------------------------------------------- /plugins/trezor/cmdline.py: -------------------------------------------------------------------------------- 1 | from trezor import TrezorPlugin 2 | from uwallet.util import print_msg 3 | 4 | class TrezorCmdLineHandler: 5 | 6 | def get_passphrase(self, msg, confirm): 7 | import getpass 8 | print_msg(msg) 9 | return getpass.getpass('') 10 | 11 | def get_pin(self, msg): 12 | t = { 'a':'7', 'b':'8', 'c':'9', 'd':'4', 'e':'5', 'f':'6', 'g':'1', 'h':'2', 'i':'3'} 13 | print_msg(msg) 14 | print_msg("a b c\nd e f\ng h i\n-----") 15 | o = raw_input() 16 | return ''.join(map(lambda x: t[x], o)) 17 | 18 | def stop(self): 19 | pass 20 | 21 | def show_message(self, msg): 22 | print_msg(msg) 23 | 24 | 25 | class Plugin(TrezorPlugin): 26 | handler = TrezorCmdLineHandler() 27 | -------------------------------------------------------------------------------- /uwallet-env: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script creates a virtualenv named 'env' and installs all 4 | # python dependencies before activating the env and running Electrum. 5 | # If 'env' already exists, it is activated and Electrum is started 6 | # without any installations. Additionally, the PYTHONPATH environment 7 | # variable is set properly before running Electrum. 8 | # 9 | # python-qt and its dependencies will still need to be installed with 10 | # your package manager. 11 | 12 | if [ -e ./env/bin/activate ]; then 13 | source ./env/bin/activate 14 | else 15 | virtualenv env 16 | source ./env/bin/activate 17 | python setup.py install 18 | fi 19 | 20 | export PYTHONPATH="/usr/local/lib/python2.7/site-packages:$PYTHONPATH" 21 | 22 | ./electrum "$@" 23 | 24 | deactivate 25 | -------------------------------------------------------------------------------- /scripts/block_headers: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # A simple script that connects to a server and displays block headers 4 | 5 | import time 6 | from uwallet import SimpleConfig, Network 7 | from uwallet.util import print_msg, json_encode 8 | 9 | # start network 10 | c = SimpleConfig() 11 | network = Network(c) 12 | network.start() 13 | 14 | # wait until connected 15 | while network.is_connecting(): 16 | time.sleep(0.1) 17 | 18 | if not network.is_connected(): 19 | print_msg("daemon is not connected") 20 | sys.exit(1) 21 | 22 | # 2. send the subscription 23 | callback = lambda response: print_msg(json_encode(response.get('result'))) 24 | network.send([('blockchain.headers.subscribe',[])], callback) 25 | 26 | # 3. wait for results 27 | while network.is_connected(): 28 | time.sleep(1) 29 | -------------------------------------------------------------------------------- /UpdateAppClient_install.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Author : Shu 3 | # @Email : httpservlet@yeah.net 4 | # @Date : 2017/12/27 5 | # @Description : 打包python项目为exe 6 | 7 | # coding=utf-8 8 | 9 | 10 | # http://www.cnblogs.com/dcb3688/p/4211390.html 11 | if __name__ == '__main__': 12 | from PyInstaller.__main__ import run 13 | 14 | # -w 纯窗口程序, 不带命令窗口 15 | # --icon 可执行文件图标 16 | # --version-file 可执行文件的文件信息 17 | # --upx-dir upx加壳压缩(需要单独下载upx), 放到此文件同目录下会自动找到upx.exe(都不需要专门注明此参数) 18 | # -y 打包生成的文件直接覆盖上一次生成 19 | # --add-data: 添加数据文件. 格式为 源;目标 20 | #params = ['-y', '-n=UlordWallet', 'deterministic.spec'] 21 | #run(params) 22 | 23 | #params = ['-y', '-n=uwallet', 'deterministic.spec'] 24 | params = ['UpdateAppClient.py','--icon=uwallet.ico','--hidden-import=queue','-w','-y'] 25 | run(params) 26 | #qt5.11 -------------------------------------------------------------------------------- /progressbar_pyinstaller.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Author : Shu 3 | # @Email : httpservlet@yeah.net 4 | # @Date : 2017/12/27 5 | # @Description : 打包python项目为exe 6 | 7 | # coding=utf-8 8 | 9 | 10 | # http://www.cnblogs.com/dcb3688/p/4211390.html 11 | if __name__ == '__main__': 12 | from PyInstaller.__main__ import run 13 | 14 | # -w 纯窗口程序, 不带命令窗口 15 | # --icon 可执行文件图标 16 | # --version-file 可执行文件的文件信息 17 | # --upx-dir upx加壳压缩(需要单独下载upx), 放到此文件同目录下会自动找到upx.exe(都不需要专门注明此参数) 18 | # -y 打包生成的文件直接覆盖上一次生成 19 | # --add-data: 添加数据文件. 格式为 源;目标 20 | #params = ['-y', '-n=UlordWallet', 'deterministic.spec'] 21 | #run(params) 22 | 23 | #params = ['-y', '-n=uwallet', 'deterministic.spec'] 24 | params = ['progressbarWindow.py','--icon=uwallet.ico','--hidden-import=queue','-w','-y'] 25 | run(params) 26 | #qt5.11 -------------------------------------------------------------------------------- /app.fil: -------------------------------------------------------------------------------- 1 | gui/qt/__init__.py 2 | gui/qt/main_window.py 3 | gui/qt/history_list.py 4 | gui/qt/contact_list.py 5 | gui/qt/invoice_list.py 6 | gui/qt/request_list.py 7 | gui/qt/installwizard.py 8 | gui/qt/network_dialog.py 9 | gui/qt/password_dialog.py 10 | gui/qt/util.py 11 | gui/qt/seed_dialog.py 12 | gui/qt/transaction_dialog.py 13 | gui/qt/address_dialog.py 14 | gui/qt/qrcodewidget.py 15 | gui/qt/qrtextedit.py 16 | gui/qt/qrwindow.py 17 | gui/kivy/main.kv 18 | gui/kivy/main_window.py 19 | gui/kivy/uix/dialogs/__init__.py 20 | gui/kivy/uix/dialogs/fee_dialog.py 21 | gui/kivy/uix/dialogs/installwizard.py 22 | gui/kivy/uix/dialogs/settings.py 23 | gui/kivy/uix/dialogs/wallets.py 24 | gui/kivy/uix/ui_screens/history.kv 25 | gui/kivy/uix/ui_screens/receive.kv 26 | gui/kivy/uix/ui_screens/send.kv 27 | plugins/labels/qt.py 28 | plugins/trezor/qt.py 29 | plugins/virtualkeyboard/qt.py 30 | -------------------------------------------------------------------------------- /uwallet_pyinstaller.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Author : Shu 3 | # @Email : httpservlet@yeah.net 4 | # @Date : 2017/12/27 5 | # @Description : 打包python项目为exe 6 | 7 | # coding=utf-8 8 | 9 | 10 | # http://www.cnblogs.com/dcb3688/p/4211390.html 11 | if __name__ == '__main__': 12 | from PyInstaller.__main__ import run 13 | 14 | # -w 纯窗口程序, 不带命令窗口 15 | # --icon 可执行文件图标 16 | # --version-file 可执行文件的文件信息 17 | # --upx-dir upx加壳压缩(需要单独下载upx), 放到此文件同目录下会自动找到upx.exe(都不需要专门注明此参数) 18 | # -y 打包生成的文件直接覆盖上一次生成 19 | # --add-data: 添加数据文件. 格式为 源;目标 20 | #params = ['-y', '-n=UlordWallet', 'deterministic.spec'] 21 | #run(params) 22 | 23 | #params = ['-y', '-n=uwallet', 'deterministic.spec'] 24 | params = ['uwallet','--icon=uwallet.ico','--hidden-import=queue','-w','--version-file=version','-y'] 25 | run(params) 26 | #qt5.11 -------------------------------------------------------------------------------- /scripts/watch_address: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import time 5 | from uwallet import SimpleConfig, Network 6 | from uwallet.util import print_msg, json_encode 7 | 8 | try: 9 | addr = sys.argv[1] 10 | except Exception: 11 | print "usage: watch_address " 12 | sys.exit(1) 13 | 14 | # start network 15 | c = SimpleConfig() 16 | network = Network(c) 17 | network.start() 18 | 19 | # wait until connected 20 | while network.is_connecting(): 21 | time.sleep(0.1) 22 | 23 | if not network.is_connected(): 24 | print_msg("daemon is not connected") 25 | sys.exit(1) 26 | 27 | # 2. send the subscription 28 | callback = lambda response: print_msg(json_encode(response.get('result'))) 29 | network.send([('blockchain.address.subscribe',[addr])], callback) 30 | 31 | # 3. wait for results 32 | while network.is_connected(): 33 | time.sleep(1) 34 | -------------------------------------------------------------------------------- /contrib/build-wine/README.rst: -------------------------------------------------------------------------------- 1 | Getting start 2 | =============== 3 | These scripts can be used for cross-compilation of Windows Electrum executables from Linux/Wine. 4 | 5 | Usage: 6 | 7 | :: 8 | 9 | 1. Install Wine (tested with wine-1.7.18) 10 | 11 | 2. Run "./prepare-wine.sh", it will download all dependencies. When you'll be asked, always leave default settings and press "Next >". 12 | 13 | 3. Run "./prepare-hw.sh" to build support for hardware wallets (TREZOR) 14 | 15 | 4. Run "./build-electrum-git.sh". Sources will be packed into three separate versions to dist/ directory: 16 | * Standalone compressed executable is "dist/electrum.exe" 17 | * Uncompressed binaries are in "dist/electrum". They're useful for comparsion with other builds. 18 | * NSIS-based installer of Electrum is "electrum-setup.exe" 19 | 20 | 5. Everytime you want to rebuild new version of Electrum just change the path to ZIP file in "build-electrum.sh" and re-run the script. 21 | -------------------------------------------------------------------------------- /gui/kivy/Makefile: -------------------------------------------------------------------------------- 1 | PYTHON = python 2 | 3 | # needs kivy installed or in PYTHONPATH 4 | 5 | .PHONY: theming apk clean 6 | 7 | theming: 8 | $(PYTHON) -m kivy.atlas theming/light 1024 theming/light/*.png 9 | prepare: 10 | # running pre build setup 11 | @cp tools/buildozer.spec ../../buildozer.spec 12 | # copy electrum to main.py 13 | @cp ../../electrum ../../main.py 14 | @-if [ ! -d "../../.buildozer" ];then \ 15 | cd ../..; buildozer android debug;\ 16 | cp -f gui/kivy/tools/blacklist.txt .buildozer/android/platform/python-for-android/src/blacklist.txt;\ 17 | rm -rf ./.buildozer/android/platform/python-for-android/dist;\ 18 | fi 19 | apk: 20 | @make prepare 21 | @-cd ../..; buildozer android_new debug deploy run 22 | @make clean 23 | release: 24 | @make prepare 25 | @-cd ../..; buildozer android_new release 26 | @make clean 27 | clean: 28 | # Cleaning up 29 | # rename main.py to electrum 30 | @-rm ../../main.py 31 | # remove buildozer.spec 32 | @-rm ../../buildozer.spec 33 | -------------------------------------------------------------------------------- /process.dat: -------------------------------------------------------------------------------- 1 | 1/1 -------------------------------------------------------------------------------- /c.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['c', 'uwallet'], 7 | pathex=['F:\\MyProject\\Ulord\\uwallet-client-pro'], 8 | binaries=[], 9 | datas=[], 10 | hiddenimports=['queue'], 11 | hookspath=[], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher) 17 | pyz = PYZ(a.pure, a.zipped_data, 18 | cipher=block_cipher) 19 | exe = EXE(pyz, 20 | a.scripts, 21 | exclude_binaries=True, 22 | name='c', 23 | debug=True, 24 | strip=False, 25 | upx=False, 26 | console=True , icon='Uwallet.ico') 27 | coll = COLLECT(exe, 28 | a.binaries, 29 | a.zipfiles, 30 | a.datas, 31 | strip=False, 32 | upx=False, 33 | name='c') 34 | -------------------------------------------------------------------------------- /progressbarWindow.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['progressbarWindow.py'], 7 | pathex=['C:\\Work\\uwallet-client-pro'], 8 | binaries=[], 9 | datas=[], 10 | hiddenimports=['queue'], 11 | hookspath=[], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher) 17 | pyz = PYZ(a.pure, a.zipped_data, 18 | cipher=block_cipher) 19 | exe = EXE(pyz, 20 | a.scripts, 21 | exclude_binaries=True, 22 | name='progressbarWindow', 23 | debug=False, 24 | strip=False, 25 | upx=True, 26 | console=False , icon='uwallet.ico') 27 | coll = COLLECT(exe, 28 | a.binaries, 29 | a.zipfiles, 30 | a.datas, 31 | strip=False, 32 | upx=True, 33 | name='progressbarWindow') 34 | -------------------------------------------------------------------------------- /UpdateAppClient.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['UpdateAppClient.py'], 7 | pathex=['F:\\MyProject\\Ulord\\uwallet-client-pro'], 8 | binaries=[], 9 | datas=[], 10 | hiddenimports=['queue'], 11 | hookspath=[], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher) 17 | pyz = PYZ(a.pure, a.zipped_data, 18 | cipher=block_cipher) 19 | exe = EXE(pyz, 20 | a.scripts, 21 | exclude_binaries=True, 22 | name='UpdateAppClient', 23 | debug=False, 24 | strip=False, 25 | upx=True, 26 | console=False , icon='uwallet.ico') 27 | coll = COLLECT(exe, 28 | a.binaries, 29 | a.zipfiles, 30 | a.datas, 31 | strip=False, 32 | upx=True, 33 | name='UpdateAppClient') 34 | -------------------------------------------------------------------------------- /plugins/ledger/qt.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from PyQt4.Qt import (QDialog, QInputDialog, QLineEdit, 4 | QVBoxLayout, QLabel, SIGNAL) 5 | import PyQt4.QtCore as QtCore 6 | 7 | from uwallet.i18n import _ 8 | from .ledger import LedgerPlugin 9 | from ..hw_wallet.qt import QtHandlerBase, QtPluginBase 10 | from uwallet_gui.qt.util import * 11 | 12 | 13 | class Plugin(LedgerPlugin, QtPluginBase): 14 | icon_unpaired = ":icons/ledger_unpaired.png" 15 | icon_paired = ":icons/ledger.png" 16 | 17 | def create_handler(self, window): 18 | return Ledger_Handler(window) 19 | 20 | 21 | class Ledger_Handler(QtHandlerBase): 22 | 23 | def __init__(self, win): 24 | super(Ledger_Handler, self).__init__(win, 'Ledger') 25 | 26 | def word_dialog(self, msg): 27 | response = QInputDialog.getText(self.top_level_window(), "Ledger Wallet Authentication", msg, QLineEdit.Password) 28 | if not response[1]: 29 | self.word = None 30 | else: 31 | self.word = str(response[0]) 32 | self.done.set() 33 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /uwallet.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['uwallet'], 7 | pathex=['D:\\Work\\uwallet-client-pro'], 8 | binaries=[], 9 | datas=[], 10 | hiddenimports=['queue'], 11 | hookspath=[], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher, 17 | noarchive=False) 18 | pyz = PYZ(a.pure, a.zipped_data, 19 | cipher=block_cipher) 20 | exe = EXE(pyz, 21 | a.scripts, 22 | [], 23 | exclude_binaries=True, 24 | name='uwallet', 25 | debug=False, 26 | bootloader_ignore_signals=False, 27 | strip=False, 28 | upx=True, 29 | console=False , version='version', icon='uwallet.ico') 30 | coll = COLLECT(exe, 31 | a.binaries, 32 | a.zipfiles, 33 | a.datas, 34 | strip=False, 35 | upx=True, 36 | name='uwallet') 37 | -------------------------------------------------------------------------------- /gui/kivy/uix/dialogs/nfc_transaction.py: -------------------------------------------------------------------------------- 1 | class NFCTransactionDialog(AnimatedPopup): 2 | 3 | mode = OptionProperty('send', options=('send','receive')) 4 | 5 | scanner = ObjectProperty(None) 6 | 7 | def __init__(self, **kwargs): 8 | # Delayed Init 9 | global NFCSCanner 10 | if NFCSCanner is None: 11 | from uwallet_gui.kivy.nfc_scanner import NFCScanner 12 | self.scanner = NFCSCanner 13 | 14 | super(NFCTransactionDialog, self).__init__(**kwargs) 15 | self.scanner.nfc_init() 16 | self.scanner.bind() 17 | 18 | def on_parent(self, instance, value): 19 | sctr = self.ids.sctr 20 | if value: 21 | def _cmp(*l): 22 | anim = Animation(rotation=2, scale=1, opacity=1) 23 | anim.start(sctr) 24 | anim.bind(on_complete=_start) 25 | 26 | def _start(*l): 27 | anim = Animation(rotation=350, scale=2, opacity=0) 28 | anim.start(sctr) 29 | anim.bind(on_complete=_cmp) 30 | _start() 31 | return 32 | Animation.cancel_all(sctr) -------------------------------------------------------------------------------- /gui/kivy/data/fonts/tron/Readme.txt: -------------------------------------------------------------------------------- 1 | TR2N v1.3 2 | 3 | ABOUT THE FONT: 4 | A font based upon the poster text for TRON LEGACY. 5 | 6 | The font is different from the pre-existing TRON font currently on the web. Similar in minor aspects but different in most. Style based upon text from different region posters. 7 | 8 | UPDATE HISTORY: 9 | 3/7/11 - Adjusted the letter B (both lowercase and uppercase), capped off the ends of T, P and R, added a few more punctuation marks, as well as added the TR and TP ligature to allow for the solid bar connect as in the poster art. 10 | 11 | 1/22/11 - Made minor corrections to all previous letters and punctuation. Corrected issue with number 8's top filling in. 12 | 13 | ABOUT THE AUTHOR: 14 | Jeff Bell has produced fonts before, but this is the first one in over 10 years. His original 3 fonts were under the name DJ-JOHNNYRKA and include "CASPER", "BEVERLY HILLS COP", "THE GODFATHER" and "FIDDUMS FAMILY". 15 | 16 | For more information on Jeff Bell and his work can be found online: 17 | 18 | www.randombell.com 19 | www.damovieman.deviantart.com 20 | http://www.imdb.com/name/nm3983081/ 21 | http://www.vimeo.com/user4004969/videos -------------------------------------------------------------------------------- /scripts/bip70: -------------------------------------------------------------------------------- 1 | # create a BIP70 payment request signed with a certificate 2 | 3 | import tlslite 4 | import time 5 | import hashlib 6 | 7 | from uwallet.transaction import Transaction 8 | from uwallet import bitcoin 9 | from uwallet import x509 10 | from uwallet import paymentrequest 11 | from uwallet import paymentrequest_pb2 as pb2 12 | 13 | chain_file = 'mychain.pem' 14 | cert_file = 'mycert.pem' 15 | amount = 1000000 16 | address = "18U5kpCAU4s8weFF8Ps5n8HAfpdUjDVF64" 17 | memo = "blah" 18 | out_file = "payreq" 19 | 20 | 21 | with open(chain_file, 'r') as f: 22 | chain = tlslite.X509CertChain() 23 | chain.parsePemList(f.read()) 24 | 25 | certificates = pb2.X509Certificates() 26 | certificates.certificate.extend(map(lambda x: str(x.bytes), chain.x509List)) 27 | 28 | with open(cert_file, 'r') as f: 29 | rsakey = tlslite.utils.python_rsakey.Python_RSAKey.parsePEM(f.read()) 30 | 31 | script = Transaction.pay_script('address', address).decode('hex') 32 | 33 | pr_string = paymentrequest.make_payment_request(amount, script, memo, rsakey) 34 | 35 | with open(out_file,'wb') as f: 36 | f.write(pr_string) 37 | 38 | print "Payment request was written to file '%s'"%out_file 39 | -------------------------------------------------------------------------------- /scripts/peers: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import util, json 4 | from collections import defaultdict 5 | 6 | 7 | def analyze(results): 8 | out = {} 9 | dd = {} 10 | for k, v in results.items(): 11 | height = v.get('block_height') 12 | merkle = v.get('merkle_root') 13 | utxo = v.get('utxo_root') 14 | d = dd.get(merkle, defaultdict(int)) 15 | d[utxo] += 1 16 | dd[merkle] = d 17 | refs = {} 18 | for merkle, d in dd.items(): 19 | v = d.values() 20 | m = max(v) 21 | ref = d.keys()[v.index(m)] 22 | refs[merkle] = ref, m 23 | for k, v in results.items(): 24 | height = v.get('block_height') 25 | merkle = v.get('merkle_root') 26 | utxo = v.get('utxo_root') 27 | ref_utxo, num = refs.get(merkle) 28 | if ref_utxo != utxo and num > 1: 29 | out[k] = height, merkle, utxo 30 | return out 31 | 32 | 33 | peers = util.get_peers() 34 | results = util.send_request(peers, 'blockchain.headers.subscribe', []) 35 | 36 | errors = analyze(results).keys() 37 | 38 | for n,v in sorted(results.items(), key=lambda x:x[1].get('block_height')): 39 | print "%40s"%n, v.get('block_height'), v.get('utxo_root'), "error" if n in errors else "ok" 40 | -------------------------------------------------------------------------------- /plugins/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Electrum - lightweight Bitcoin client 4 | # Copyright (C) 2015 Thomas Voegtlin 5 | # 6 | # Permission is hereby granted, free of charge, to any person 7 | # obtaining a copy of this software and associated documentation files 8 | # (the "Software"), to deal in the Software without restriction, 9 | # including without limitation the rights to use, copy, modify, merge, 10 | # publish, distribute, sublicense, and/or sell copies of the Software, 11 | # and to permit persons to whom the Software is furnished to do so, 12 | # subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be 15 | # included in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | 26 | 27 | -------------------------------------------------------------------------------- /plugins/keepkey/keepkey.py: -------------------------------------------------------------------------------- 1 | from ..trezor.plugin import TrezorCompatiblePlugin, TrezorCompatibleKeyStore 2 | 3 | 4 | class KeepKey_KeyStore(TrezorCompatibleKeyStore): 5 | hw_type = 'keepkey' 6 | device = 'KeepKey' 7 | 8 | 9 | class KeepKeyPlugin(TrezorCompatiblePlugin): 10 | firmware_URL = 'https://www.keepkey.com' 11 | libraries_URL = 'https://github.com/keepkey/python-keepkey' 12 | minimum_firmware = (1, 0, 0) 13 | keystore_class = KeepKey_KeyStore 14 | 15 | def __init__(self, *args): 16 | try: 17 | import client 18 | import keepkeylib 19 | import keepkeylib.ckd_public 20 | import keepkeylib.transport_hid 21 | self.client_class = client.KeepKeyClient 22 | self.ckd_public = keepkeylib.ckd_public 23 | self.types = keepkeylib.client.types 24 | self.DEVICE_IDS = keepkeylib.transport_hid.DEVICE_IDS 25 | self.libraries_available = True 26 | except ImportError: 27 | self.libraries_available = False 28 | TrezorCompatiblePlugin.__init__(self, *args) 29 | 30 | def hid_transport(self, pair): 31 | from keepkeylib.transport_hid import HidTransport 32 | return HidTransport(pair) 33 | 34 | def bridge_transport(self, d): 35 | raise NotImplementedError('') 36 | -------------------------------------------------------------------------------- /gui/kivy/i18n.py: -------------------------------------------------------------------------------- 1 | import gettext 2 | 3 | class _(str): 4 | 5 | observers = set() 6 | lang = None 7 | 8 | def __new__(cls, s, *args, **kwargs): 9 | if _.lang is None: 10 | _.switch_lang('en') 11 | t = _.translate(s, *args, **kwargs) 12 | o = super(_, cls).__new__(cls, t) 13 | o.source_text = s 14 | return o 15 | 16 | @staticmethod 17 | def translate(s, *args, **kwargs): 18 | return _.lang(s).format(args, kwargs) 19 | 20 | @staticmethod 21 | def bind(label): 22 | try: 23 | _.observers.add(label) 24 | except: 25 | pass 26 | # garbage collection 27 | new = set() 28 | for label in _.observers: 29 | try: 30 | new.add(label) 31 | except: 32 | pass 33 | _.observers = new 34 | 35 | @staticmethod 36 | def switch_lang(lang): 37 | # get the right locales directory, and instanciate a gettext 38 | from uwallet.i18n import LOCALE_DIR 39 | locales = gettext.translation('uwallet', LOCALE_DIR, languages=[lang], fallback=True) 40 | _.lang = locales.gettext 41 | for label in _.observers: 42 | try: 43 | label.text = _(label.text.source_text) 44 | except: 45 | pass 46 | -------------------------------------------------------------------------------- /gui/kivy/uix/dialogs/qr_scanner.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.factory import Factory 3 | from kivy.lang import Builder 4 | 5 | Factory.register('QRScanner', module='uwallet_gui.kivy.qr_scanner') 6 | 7 | class QrScannerDialog(Factory.AnimatedPopup): 8 | 9 | __events__ = ('on_complete', ) 10 | 11 | def on_symbols(self, instance, value): 12 | instance.stop() 13 | self.dismiss() 14 | data = value[0].data 15 | self.dispatch('on_complete', data) 16 | 17 | def on_complete(self, x): 18 | ''' Default Handler for on_complete event. 19 | ''' 20 | print x 21 | 22 | 23 | Builder.load_string(''' 24 | 25 | title: 26 | _(\ 27 | '[size=18dp]Hold your QRCode up to the camera[/size][size=7dp]\\n[/size]') 28 | title_size: '24sp' 29 | border: 7, 7, 7, 7 30 | size_hint: None, None 31 | size: '340dp', '290dp' 32 | pos_hint: {'center_y': .53} 33 | #separator_color: .89, .89, .89, 1 34 | #separator_height: '1.2dp' 35 | #title_color: .437, .437, .437, 1 36 | #background: 'atlas://gui/kivy/theming/light/dialog' 37 | on_activate: 38 | qrscr.start() 39 | qrscr.size = self.size 40 | on_deactivate: qrscr.stop() 41 | QRScanner: 42 | id: qrscr 43 | on_symbols: root.on_symbols(*args) 44 | ''') 45 | -------------------------------------------------------------------------------- /plugins/trezor/trezor.py: -------------------------------------------------------------------------------- 1 | from .plugin import TrezorCompatiblePlugin, TrezorCompatibleKeyStore 2 | 3 | 4 | class TrezorKeyStore(TrezorCompatibleKeyStore): 5 | hw_type = 'trezor' 6 | device = 'TREZOR' 7 | 8 | class TrezorPlugin(TrezorCompatiblePlugin): 9 | firmware_URL = 'https://www.mytrezor.com' 10 | libraries_URL = 'https://github.com/trezor/python-trezor' 11 | minimum_firmware = (1, 3, 3) 12 | keystore_class = TrezorKeyStore 13 | 14 | def __init__(self, *args): 15 | try: 16 | import client 17 | import trezorlib 18 | import trezorlib.ckd_public 19 | import trezorlib.transport_hid 20 | self.client_class = client.TrezorClient 21 | self.ckd_public = trezorlib.ckd_public 22 | self.types = trezorlib.client.types 23 | self.DEVICE_IDS = trezorlib.transport_hid.DEVICE_IDS 24 | self.libraries_available = True 25 | except ImportError: 26 | self.libraries_available = False 27 | TrezorCompatiblePlugin.__init__(self, *args) 28 | 29 | def hid_transport(self, pair): 30 | from trezorlib.transport_hid import HidTransport 31 | return HidTransport(pair) 32 | 33 | def bridge_transport(self, d): 34 | from trezorlib.transport_bridge import BridgeTransport 35 | return BridgeTransport(d) 36 | -------------------------------------------------------------------------------- /gui/kivy/nfc_scanner/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ('NFCBase', 'NFCScanner') 2 | 3 | class NFCBase(Widget): 4 | ''' This is the base Abstract definition class that the actual hardware dependent 5 | implementations would be based on. If you want to define a feature that is 6 | accissible and implemented by every platform implementation then define that 7 | method in this class. 8 | ''' 9 | 10 | payload = ObjectProperty(None) 11 | '''This is the data gotten from the tag. 12 | ''' 13 | 14 | def nfc_init(self): 15 | ''' Initialize the adapter. 16 | ''' 17 | pass 18 | 19 | def nfc_disable(self): 20 | ''' Disable scanning 21 | ''' 22 | pass 23 | 24 | def nfc_enable(self): 25 | ''' Enable Scanning 26 | ''' 27 | pass 28 | 29 | def nfc_enable_exchange(self, data): 30 | ''' Enable P2P Ndef exchange 31 | ''' 32 | pass 33 | 34 | def nfc_disable_exchange(self): 35 | ''' Disable/Stop P2P Ndef exchange 36 | ''' 37 | pass 38 | 39 | # load NFCScanner implementation 40 | 41 | NFCScanner = core_select_lib('nfc_manager', ( 42 | # keep the dummy implementtation as the last one to make it the fallback provider.NFCScanner = core_select_lib('nfc_scanner', ( 43 | ('android', 'scanner_android', 'ScannerAndroid'), 44 | ('dummy', 'scanner_dummy', 'ScannerDummy')), True, 'uwallet_gui.kivy') 45 | -------------------------------------------------------------------------------- /gui/kivy/uix/dialogs/qr_dialog.py: -------------------------------------------------------------------------------- 1 | from kivy.factory import Factory 2 | from kivy.lang import Builder 3 | 4 | Builder.load_string(''' 5 | 6 | id: popup 7 | title: '' 8 | data: '' 9 | shaded: False 10 | show_text: False 11 | AnchorLayout: 12 | anchor_x: 'center' 13 | BoxLayout: 14 | orientation: 'vertical' 15 | size_hint: 1, 1 16 | padding: '10dp' 17 | spacing: '10dp' 18 | QRCodeWidget: 19 | id: qr 20 | TopLabel: 21 | text: root.data if root.show_text else '' 22 | Widget: 23 | size_hint: 1, 0.2 24 | BoxLayout: 25 | size_hint: 1, None 26 | height: '48dp' 27 | Widget: 28 | size_hint: 1, None 29 | height: '48dp' 30 | Button: 31 | size_hint: 1, None 32 | height: '48dp' 33 | text: _('Close') 34 | on_release: 35 | popup.dismiss() 36 | ''') 37 | 38 | class QRDialog(Factory.Popup): 39 | def __init__(self, title, data, show_text): 40 | Factory.Popup.__init__(self) 41 | self.title = title 42 | self.data = data 43 | self.show_text = show_text 44 | 45 | def on_open(self): 46 | self.ids.qr.set_data(self.data) 47 | -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | # UTF-8 2 | # 3 | VSVersionInfo( 4 | ffi=FixedFileInfo( 5 | # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) 6 | # Set not needed items to zero 0. 7 | filevers=(1, 0, 2,0), 8 | prodvers=(1, 0, 2,0), 9 | # Contains a bitmask that specifies the valid bits 'flags'r 10 | mask=0x3f, 11 | # Contains a bitmask that specifies the Boolean attributes of the file. 12 | flags=0x0, 13 | # The operating system for which this file was designed. 14 | # 0x4 - NT and there is no need to change it. 15 | OS=0x40004, 16 | # The general type of file. 17 | # 0x1 - the file is an application. 18 | fileType=0x1, 19 | # The function of the file. 20 | # 0x0 - the function is not defined for this fileType 21 | subtype=0x0, 22 | # Creation date and time stamp. 23 | date=(0, 0) 24 | ), 25 | kids=[ 26 | StringFileInfo( 27 | [ 28 | StringTable( 29 | u'040904B0', 30 | [StringStruct(u'CompanyName', u'Ulord Foundation Ltd.'), 31 | StringStruct(u'FileDescription', u'UWalletLite Client'), 32 | StringStruct(u'FileVersion', u'1.0.2'), 33 | StringStruct(u'InternalName', u'uwallet'), 34 | StringStruct(u'LegalCopyright', u'Ulord Foundation Ltd.'), 35 | StringStruct(u'OriginalFilename', u'uwallet.exe'), 36 | StringStruct(u'ProductName', u'UWalletLite'), 37 | StringStruct(u'ProductVersion', u'1.0.2')]) 38 | ]), 39 | VarFileInfo([VarStruct(u'Translation', [1033, 1200])]) 40 | ] 41 | ) -------------------------------------------------------------------------------- /gui/kivy/uix/dialogs/question.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.factory import Factory 3 | from kivy.properties import ObjectProperty 4 | from kivy.lang import Builder 5 | from kivy.uix.checkbox import CheckBox 6 | from kivy.uix.label import Label 7 | from kivy.uix.widget import Widget 8 | 9 | from uwallet_gui.kivy.i18n import _ 10 | 11 | Builder.load_string(''' 12 | 13 | id: popup 14 | title: '' 15 | message: '' 16 | size_hint: 0.8, 0.5 17 | pos_hint: {'top':0.9} 18 | BoxLayout: 19 | orientation: 'vertical' 20 | Label: 21 | id: label 22 | text: root.message 23 | text_size: self.width, None 24 | Widget: 25 | size_hint: 1, 0.1 26 | BoxLayout: 27 | orientation: 'horizontal' 28 | size_hint: 1, 0.2 29 | Button: 30 | text: _('No') 31 | size_hint: 0.5, None 32 | height: '48dp' 33 | on_release: 34 | root.callback(False) 35 | popup.dismiss() 36 | Button: 37 | text: _('Yes') 38 | size_hint: 0.5, None 39 | height: '48dp' 40 | on_release: 41 | root.callback(True) 42 | popup.dismiss() 43 | ''') 44 | 45 | 46 | 47 | class Question(Factory.Popup): 48 | 49 | def __init__(self, msg, callback): 50 | Factory.Popup.__init__(self) 51 | self.title = _('Question') 52 | self.message = msg 53 | self.callback = callback 54 | -------------------------------------------------------------------------------- /gui/kivy/uix/context_menu.py: -------------------------------------------------------------------------------- 1 | #!python 2 | #!/usr/bin/env python 3 | from kivy.app import App 4 | from kivy.uix.bubble import Bubble 5 | from kivy.animation import Animation 6 | from kivy.uix.floatlayout import FloatLayout 7 | from kivy.lang import Builder 8 | from kivy.factory import Factory 9 | from kivy.clock import Clock 10 | 11 | from uwallet_gui.kivy.i18n import _ 12 | 13 | Builder.load_string(''' 14 | 15 | background_normal: '' 16 | background_color: (0.192, .498, 0.745, 1) 17 | height: '48dp' 18 | size_hint: 1, None 19 | 20 | 21 | size_hint: 1, None 22 | height: '48dp' 23 | pos: (0, 0) 24 | show_arrow: False 25 | arrow_pos: 'top_mid' 26 | padding: 0 27 | orientation: 'horizontal' 28 | BoxLayout: 29 | size_hint: 1, 1 30 | height: '48dp' 31 | padding: '12dp', '0dp' 32 | spacing: '3dp' 33 | orientation: 'horizontal' 34 | id: buttons 35 | ''') 36 | 37 | 38 | class MenuItem(Factory.Button): 39 | pass 40 | 41 | class ContextMenu(Bubble): 42 | 43 | def __init__(self, obj, action_list): 44 | Bubble.__init__(self) 45 | self.obj = obj 46 | for k, v in action_list: 47 | l = MenuItem() 48 | l.text = _(k) 49 | def func(f=v): 50 | Clock.schedule_once(lambda dt: self.hide(), 0.1) 51 | Clock.schedule_once(lambda dt: f(obj), 0.15) 52 | l.on_release = func 53 | self.ids.buttons.add_widget(l) 54 | 55 | def hide(self): 56 | if self.parent: 57 | self.parent.hide_menu() 58 | -------------------------------------------------------------------------------- /plugins/README: -------------------------------------------------------------------------------- 1 | Plugin rules: 2 | 3 | * The plugin system of Electrum is designed to allow the development 4 | of new features without increasing the core code of Electrum. 5 | 6 | * Electrum is written in pure python. if you want to add a feature 7 | that requires non-python libraries, then it must be submitted as a 8 | plugin. If the feature you want to add requires communication with 9 | a remote server (not an Electrum server), then it should be a 10 | plugin as well. If the feature you want to add introduces new 11 | dependencies in the code, then it should probably be a plugin. 12 | 13 | * We expect plugin developers to maintain their plugin code. However, 14 | once a plugin is merged in Electrum, we will have to maintain it 15 | too, because changes in the Electrum code often require updates in 16 | the plugin code. Therefore, plugins have to be easy to maintain. If 17 | we believe that a plugin will create too much maintenance work in 18 | the future, it will be rejected. 19 | 20 | * Plugins should be compatible with Electrum's conventions. If your 21 | plugin does not fit with Electrum's architecture, or if we believe 22 | that it will create too much maintenance work, it will not be 23 | accepted. In particular, do not duplicate existing Electrum code in 24 | your plugin. 25 | 26 | * We may decide to remove a plugin after it has been merged in 27 | Electrum. For this reason, a plugin must be easily removable, 28 | without putting at risk the user's bitcoins. If we feel that a 29 | plugin cannot be removed without threatening users who rely on it, 30 | we will not merge it. 31 | 32 | -------------------------------------------------------------------------------- /gui/kivy/uix/dialogs/checkbox_dialog.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.factory import Factory 3 | from kivy.properties import ObjectProperty 4 | from kivy.lang import Builder 5 | 6 | Builder.load_string(''' 7 | 8 | id: popup 9 | title: '' 10 | size_hint: 0.8, 0.8 11 | pos_hint: {'top':0.9} 12 | BoxLayout: 13 | orientation: 'vertical' 14 | Label: 15 | id: description 16 | text: '' 17 | halign: 'left' 18 | text_size: self.width, None 19 | size: self.texture_size 20 | BoxLayout: 21 | orientation: 'horizontal' 22 | size_hint: 1, 0.2 23 | Label: 24 | text: _('Enable') 25 | CheckBox: 26 | id:cb 27 | Widget: 28 | size_hint: 1, 0.1 29 | BoxLayout: 30 | orientation: 'horizontal' 31 | size_hint: 1, 0.2 32 | Button: 33 | text: 'Cancel' 34 | size_hint: 0.5, None 35 | height: '48dp' 36 | on_release: popup.dismiss() 37 | Button: 38 | text: 'OK' 39 | size_hint: 0.5, None 40 | height: '48dp' 41 | on_release: 42 | root.callback(cb.active) 43 | popup.dismiss() 44 | ''') 45 | 46 | class CheckBoxDialog(Factory.Popup): 47 | def __init__(self, title, text, status, callback): 48 | Factory.Popup.__init__(self) 49 | self.ids.cb.active = status 50 | self.ids.description.text = text 51 | self.callback = callback 52 | self.title = title 53 | -------------------------------------------------------------------------------- /plugins/exchange_rate/kivy.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .exchange_rate import FxPlugin 4 | from uwallet.plugins import hook 5 | 6 | 7 | from kivy.event import EventDispatcher 8 | 9 | class MyEventDispatcher(EventDispatcher): 10 | 11 | def __init__(self, **kwargs): 12 | self.register_event_type('on_quotes') 13 | self.register_event_type('on_history') 14 | super(MyEventDispatcher, self).__init__(**kwargs) 15 | 16 | def on_quotes(self, *args): 17 | pass 18 | 19 | def on_history(self, *args): 20 | pass 21 | 22 | 23 | class Plugin(FxPlugin): 24 | 25 | def __init__(self, parent, config, name): 26 | FxPlugin.__init__(self, parent, config, name) 27 | self.dispatcher = MyEventDispatcher() 28 | 29 | def on_quotes(self): 30 | self.print_error("on_quotes", self.ccy) 31 | self.dispatcher.dispatch('on_quotes') 32 | 33 | def on_history(self): 34 | self.print_error("on_history", self.ccy) 35 | self.dispatcher.dispatch('on_history') 36 | 37 | def on_close(self): 38 | self.print_error("on close") 39 | self.window.fiat_unit = '' 40 | self.window.history_screen.update() 41 | 42 | @hook 43 | def init_kivy(self, window): 44 | self.print_error("init_kivy") 45 | self.window = window 46 | self.dispatcher.bind(on_quotes=window.on_quotes) 47 | self.dispatcher.bind(on_history=window.on_history) 48 | self.window.fiat_unit = self.ccy 49 | self.dispatcher.dispatch('on_history') 50 | 51 | @hook 52 | def load_wallet(self, wallet, window): 53 | self.window = window 54 | self.window.fiat_unit = self.ccy 55 | -------------------------------------------------------------------------------- /gui/kivy/nfc_scanner/scanner_dummy.py: -------------------------------------------------------------------------------- 1 | ''' Dummy NFC Provider to be used on desktops in case no other provider is found 2 | ''' 3 | from uwallet_gui.kivy.nfc_scanner import NFCBase 4 | from kivy.clock import Clock 5 | from kivy.logger import Logger 6 | 7 | class ScannerDummy(NFCBase): 8 | '''This is the dummy interface that gets selected in case any other 9 | hardware interface to NFC is not available. 10 | ''' 11 | 12 | _initialised = False 13 | 14 | name = 'NFCDummy' 15 | 16 | def nfc_init(self): 17 | # print 'nfc_init()' 18 | 19 | Logger.debug('NFC: configure nfc') 20 | self._initialised = True 21 | self.nfc_enable() 22 | return True 23 | 24 | def on_new_intent(self, dt): 25 | tag_info = {'type': 'dymmy', 26 | 'message': 'dummy', 27 | 'extra details': None} 28 | 29 | # let Main app know that a tag has been detected 30 | app = App.get_running_app() 31 | app.tag_discovered(tag_info) 32 | app.show_info('New tag detected.', duration=2) 33 | Logger.debug('NFC: got new dummy tag') 34 | 35 | def nfc_enable(self): 36 | Logger.debug('NFC: enable') 37 | if self._initialised: 38 | Clock.schedule_interval(self.on_new_intent, 22) 39 | 40 | def nfc_disable(self): 41 | # print 'nfc_enable()' 42 | Clock.unschedule(self.on_new_intent) 43 | 44 | def nfc_enable_exchange(self, data): 45 | ''' Start sending data 46 | ''' 47 | Logger.debug('NFC: sending data {}'.format(data)) 48 | 49 | def nfc_disable_exchange(self): 50 | ''' Disable/Stop ndef exchange 51 | ''' 52 | Logger.debug('NFC: disable nfc exchange') 53 | -------------------------------------------------------------------------------- /lib/i18n.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Electrum - lightweight Bitcoin client 4 | # Copyright (C) 2012 thomasv@gitorious 5 | # 6 | # Permission is hereby granted, free of charge, to any person 7 | # obtaining a copy of this software and associated documentation files 8 | # (the "Software"), to deal in the Software without restriction, 9 | # including without limitation the rights to use, copy, modify, merge, 10 | # publish, distribute, sublicense, and/or sell copies of the Software, 11 | # and to permit persons to whom the Software is furnished to do so, 12 | # subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be 15 | # included in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | 26 | import gettext, os 27 | 28 | LOCALE_DIR = os.path.join(os.path.dirname(__file__), 'locale') 29 | language = gettext.translation('ulord', LOCALE_DIR, fallback = True) 30 | 31 | 32 | def _(x): 33 | global language 34 | return language.ugettext(x) 35 | 36 | def set_language(x): 37 | global language 38 | if x: language = gettext.translation('ulord', LOCALE_DIR, fallback = True, languages=[x]) 39 | 40 | 41 | languages = { 42 | '':_('Default'), 43 | 'zh_CN':_('Chinese'), 44 | 'en_UK':_('English'), 45 | } 46 | -------------------------------------------------------------------------------- /gui/kivy/uix/ui_screens/requests.kv: -------------------------------------------------------------------------------- 1 | 2 | #color: .305, .309, .309, 1 3 | text_size: self.width, None 4 | halign: 'left' 5 | valign: 'top' 6 | 7 | 8 | address: '' 9 | memo: '' 10 | amount: '' 11 | status: '' 12 | date: '' 13 | icon: 'atlas://gui/kivy/theming/light/important' 14 | Image: 15 | id: icon 16 | source: root.icon 17 | size_hint: None, 1 18 | width: self.height *.54 19 | mipmap: True 20 | BoxLayout: 21 | spacing: '8dp' 22 | height: '32dp' 23 | orientation: 'vertical' 24 | Widget 25 | RequestLabel: 26 | text: root.address 27 | shorten: True 28 | Widget 29 | RequestLabel: 30 | text: root.memo 31 | color: .699, .699, .699, 1 32 | font_size: '13sp' 33 | shorten: True 34 | Widget 35 | BoxLayout: 36 | spacing: '8dp' 37 | height: '32dp' 38 | orientation: 'vertical' 39 | Widget 40 | RequestLabel: 41 | text: root.amount 42 | halign: 'right' 43 | font_size: '15sp' 44 | Widget 45 | RequestLabel: 46 | text: root.status 47 | halign: 'right' 48 | font_size: '13sp' 49 | color: .699, .699, .699, 1 50 | Widget 51 | 52 | 53 | 54 | RequestsScreen: 55 | name: 'requests' 56 | BoxLayout: 57 | orientation: 'vertical' 58 | spacing: '1dp' 59 | ScrollView: 60 | GridLayout: 61 | cols: 1 62 | id: requests_container 63 | size_hint_y: None 64 | height: self.minimum_height 65 | spacing: '2dp' 66 | padding: '12dp' 67 | -------------------------------------------------------------------------------- /contrib/make_download: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | import sys 3 | import re 4 | import hashlib 5 | import os 6 | 7 | from versions import version, version_win, version_mac, version_apk 8 | from versions import download_template, download_page 9 | 10 | with open(download_template) as f: 11 | string = f.read() 12 | 13 | string = string.replace("##VERSION##", version) 14 | string = string.replace("##VERSION_WIN##", version_win) 15 | string = string.replace("##VERSION_MAC##", version_mac) 16 | string = string.replace("##VERSION_APK##", version_apk) 17 | 18 | files = { 19 | 'tgz': "UWallet-%s.tar.gz" % version, 20 | 'zip': "UWallet-%s.zip" % version, 21 | 'mac': "uwallet-%s.dmg" % version_mac, 22 | 'win': "uwallet-%s.exe" % version_win, 23 | 'win_setup': "uwallet-%s-setup.exe" % version_win, 24 | 'win_portable': "uwallet-%s-portable.exe" % version_win, 25 | } 26 | 27 | for k, n in files.items(): 28 | path = "dist/%s"%n 29 | link = "" 30 | if not os.path.exists(path): 31 | os.system("wget -q %s -O %s" % (link, path)) 32 | if not os.path.getsize(path): 33 | os.unlink(path) 34 | string = re.sub("
(.*?)
"%k, '', string, flags=re.DOTALL + re.MULTILINE) 35 | continue 36 | sigpath = path + '.asc' 37 | siglink = link + '.asc' 38 | if not os.path.exists(sigpath): 39 | os.system("wget -q %s -O %s" % (siglink, sigpath)) 40 | if not os.path.getsize(sigpath): 41 | os.unlink(sigpath) 42 | string = re.sub("
(.*?)
"%k, '', string, flags=re.DOTALL + re.MULTILINE) 43 | continue 44 | if os.system("gpg --verify %s"%sigpath) != 0: 45 | raise BaseException(sigpath) 46 | string = string.replace("##link_%s##"%k, link) 47 | 48 | 49 | with open(download_page,'w') as f: 50 | f.write(string) 51 | 52 | 53 | -------------------------------------------------------------------------------- /gui/kivy/uix/dialogs/label_dialog.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.factory import Factory 3 | from kivy.properties import ObjectProperty 4 | from kivy.lang import Builder 5 | 6 | Builder.load_string(''' 7 | 8 | id: popup 9 | title: '' 10 | size_hint: 0.8, 0.3 11 | pos_hint: {'top':0.9} 12 | BoxLayout: 13 | orientation: 'vertical' 14 | Widget: 15 | size_hint: 1, 0.2 16 | TextInput: 17 | id:input 18 | padding: '5dp' 19 | size_hint: 1, None 20 | height: '27dp' 21 | pos_hint: {'center_y':.5} 22 | text:'' 23 | multiline: False 24 | background_normal: 'atlas://gui/kivy/theming/light/tab_btn' 25 | background_active: 'atlas://gui/kivy/theming/light/textinput_active' 26 | hint_text_color: self.foreground_color 27 | foreground_color: 1, 1, 1, 1 28 | font_size: '16dp' 29 | focus: True 30 | Widget: 31 | size_hint: 1, 0.2 32 | BoxLayout: 33 | orientation: 'horizontal' 34 | size_hint: 1, 0.5 35 | Button: 36 | text: 'Cancel' 37 | size_hint: 0.5, None 38 | height: '48dp' 39 | on_release: popup.dismiss() 40 | Button: 41 | text: 'OK' 42 | size_hint: 0.5, None 43 | height: '48dp' 44 | on_release: 45 | root.callback(input.text) 46 | popup.dismiss() 47 | ''') 48 | 49 | class LabelDialog(Factory.Popup): 50 | 51 | def __init__(self, title, text, callback): 52 | Factory.Popup.__init__(self) 53 | self.ids.input.text = text 54 | self.callback = callback 55 | self.title = title 56 | -------------------------------------------------------------------------------- /gui/kivy/uix/ui_screens/invoices.kv: -------------------------------------------------------------------------------- 1 | 2 | #color: .305, .309, .309, 1 3 | text_size: self.width, None 4 | halign: 'left' 5 | valign: 'top' 6 | 7 | 8 | requestor: '' 9 | memo: '' 10 | amount: '' 11 | status: '' 12 | date: '' 13 | icon: 'atlas://gui/kivy/theming/light/important' 14 | Image: 15 | id: icon 16 | source: root.icon 17 | size_hint: None, 1 18 | width: self.height *.54 19 | mipmap: True 20 | BoxLayout: 21 | spacing: '8dp' 22 | height: '32dp' 23 | orientation: 'vertical' 24 | Widget 25 | InvoicesLabel: 26 | text: root.requestor 27 | shorten: True 28 | Widget 29 | InvoicesLabel: 30 | text: root.memo 31 | color: .699, .699, .699, 1 32 | font_size: '13sp' 33 | shorten: True 34 | Widget 35 | BoxLayout: 36 | spacing: '8dp' 37 | height: '32dp' 38 | orientation: 'vertical' 39 | Widget 40 | InvoicesLabel: 41 | text: root.amount 42 | font_size: '15sp' 43 | halign: 'right' 44 | width: '110sp' 45 | Widget 46 | InvoicesLabel: 47 | text: root.status 48 | font_size: '13sp' 49 | halign: 'right' 50 | color: .699, .699, .699, 1 51 | Widget 52 | 53 | 54 | InvoicesScreen: 55 | name: 'invoices' 56 | BoxLayout: 57 | orientation: 'vertical' 58 | spacing: '1dp' 59 | ScrollView: 60 | GridLayout: 61 | cols: 1 62 | id: invoices_container 63 | size_hint: 1, None 64 | height: self.minimum_height 65 | spacing: '2dp' 66 | padding: '12dp' 67 | -------------------------------------------------------------------------------- /plugins/virtualkeyboard/qt.py: -------------------------------------------------------------------------------- 1 | from PyQt4.QtGui import * 2 | from uwallet.plugins import BasePlugin, hook 3 | from uwallet.i18n import _ 4 | import random 5 | 6 | class Plugin(BasePlugin): 7 | 8 | vkb = None 9 | vkb_index = 0 10 | 11 | @hook 12 | def password_dialog(self, pw, grid, pos): 13 | vkb_button = QPushButton(_("+")) 14 | vkb_button.setFixedWidth(20) 15 | vkb_button.clicked.connect(lambda: self.toggle_vkb(grid, pw)) 16 | grid.addWidget(vkb_button, pos, 2) 17 | self.kb_pos = 2 18 | self.vkb = None 19 | 20 | def toggle_vkb(self, grid, pw): 21 | if self.vkb: 22 | grid.removeItem(self.vkb) 23 | self.vkb = self.virtual_keyboard(self.vkb_index, pw) 24 | grid.addLayout(self.vkb, self.kb_pos, 0, 1, 3) 25 | self.vkb_index += 1 26 | 27 | def virtual_keyboard(self, i, pw): 28 | i = i%3 29 | if i == 0: 30 | chars = 'abcdefghijklmnopqrstuvwxyz ' 31 | elif i == 1: 32 | chars = 'ABCDEFGHIJKLMNOPQRTSUVWXYZ ' 33 | elif i == 2: 34 | chars = '1234567890!?.,;:/%&()[]{}+-' 35 | 36 | n = len(chars) 37 | s = [] 38 | for i in xrange(n): 39 | while True: 40 | k = random.randint(0,n-1) 41 | if k not in s: 42 | s.append(k) 43 | break 44 | 45 | def add_target(t): 46 | return lambda: pw.setText(str(pw.text()) + t) 47 | 48 | vbox = QVBoxLayout() 49 | grid = QGridLayout() 50 | grid.setSpacing(2) 51 | for i in range(n): 52 | l_button = QPushButton(chars[s[i]]) 53 | l_button.setFixedWidth(25) 54 | l_button.setFixedHeight(25) 55 | l_button.clicked.connect(add_target(chars[s[i]])) 56 | grid.addWidget(l_button, i/6, i%6) 57 | 58 | vbox.addLayout(grid) 59 | 60 | return vbox 61 | -------------------------------------------------------------------------------- /gui/kivy/uix/ui_screens/about.kv: -------------------------------------------------------------------------------- 1 | #:import VERSION electrum.version.ELECTRUM_VERSION 2 | 3 | Popup: 4 | title: _("About Electrum") 5 | BoxLayout: 6 | orientation: 'vertical' 7 | spacing: '10dp' 8 | padding: '10dp' 9 | GridLayout: 10 | cols: 2 11 | spacing: '10dp' 12 | TopLabel: 13 | text: _('Version') 14 | size_hint_x: 0.4 15 | TopLabel: 16 | text: VERSION 17 | size_hint_x: 0.6 18 | TopLabel: 19 | text: _('Licence') 20 | size_hint_x: 0.4 21 | TopLabel: 22 | text: "MIT Licence" 23 | size_hint_x: 0.6 24 | TopLabel: 25 | text: _('Homepage') 26 | size_hint_x: 0.4 27 | TopLabel: 28 | markup: True 29 | text: '[color=6666ff][ref=x]https://electrum.org[/ref][/color]' 30 | on_ref_press: 31 | import webbrowser 32 | webbrowser.open("https://electrum.org") 33 | size_hint_x: 0.6 34 | TopLabel: 35 | text: _('Developers') 36 | size_hint_x: 0.4 37 | TopLabel: 38 | text: '\n'.join(['Thomas Voegtlin', 'Neil Booth', 'Akshay Arora']) 39 | size_hint_x: 0.6 40 | TopLabel: 41 | text: _('Distributed by Electrum Technologies GmbH') 42 | padding: '0dp', '20dp' 43 | Widget: 44 | size_hint: None, 0.5 45 | BoxLayout: 46 | size_hint: 1, None 47 | height: '48dp' 48 | Widget: 49 | size_hint: 0.5, None 50 | height: '48dp' 51 | Button: 52 | size_hint: 0.5, None 53 | height: '48dp' 54 | text: _('Close') 55 | on_release: root.dismiss() 56 | -------------------------------------------------------------------------------- /contrib/make_packages: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | 3 | import sys, re, shutil, os, hashlib 4 | import imp 5 | import getpass 6 | 7 | if __name__ == '__main__': 8 | 9 | d = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir)) 10 | os.chdir(d) 11 | v = imp.load_source('version', 'lib/version.py') 12 | version = v.UWallet_VERSION 13 | print "version", version 14 | 15 | # copy dependencies into 'packages' directory 16 | deps = [ 17 | 'aes', 18 | 'ecdsa', 19 | 'pbkdf2', 20 | 'requests', # note: requests-2.5.1 is needed to build with pyinstaller 21 | 'qrcode', 22 | 'google/protobuf', 23 | 'dns', 24 | 'six', 25 | 'jsonrpclib', 26 | ] 27 | for module in deps: 28 | f, pathname, descr = imp.find_module(module) 29 | target = 'packages/' + module + descr[0] 30 | if os.path.exists(target): 31 | continue 32 | d = os.path.dirname(target) 33 | if d and not (os.path.exists(d)): 34 | os.makedirs(d) 35 | if descr[0]: 36 | shutil.copy(pathname, target) 37 | else: 38 | shutil.copytree(pathname, target, ignore=shutil.ignore_patterns('*.pyc')) 39 | 40 | # fix google/__init__.py needed by pyinstaller 41 | n = 'packages/google/__init__.py' 42 | if not os.path.exists(n): 43 | os.system("echo \# do not remove>%s"%n) 44 | 45 | # patch requests and add cacert.pem 46 | import requests 47 | crt = requests.certs.where() 48 | n = 'packages/requests/certs.py' 49 | with open(n, 'r') as f: 50 | s = f.read() 51 | s = s.replace("'%s'"%crt, "os.path.join(os.path.dirname(__file__), 'cacert.pem')") 52 | with open(n, 'w') as f: 53 | f.write(s) 54 | shutil.copy(crt, 'packages/requests/cacert.pem') 55 | 56 | os.system("pyrcc4 icons.qrc -o gui/qt/icons_rc.py") 57 | os.system("python setup.py sdist --format=zip,gztar") 58 | 59 | print "Packages are ready in dist" 60 | 61 | 62 | -------------------------------------------------------------------------------- /gui/kivy/uix/dialogs/wallets.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.factory import Factory 3 | from kivy.properties import ObjectProperty 4 | from kivy.lang import Builder 5 | 6 | from uwallet_gui.kivy.i18n import _ 7 | from uwallet.util import base_units 8 | 9 | import os 10 | from label_dialog import LabelDialog 11 | 12 | Builder.load_string(''' 13 | #:import os os 14 | : 15 | title: _('Wallets') 16 | id: popup 17 | path: os.path.dirname(app.get_wallet_path()) 18 | BoxLayout: 19 | orientation: 'vertical' 20 | padding: '10dp' 21 | FileChooserListView: 22 | id: wallet_selector 23 | dirselect: False 24 | filter_dirs: True 25 | filter: '*.*' 26 | path: root.path 27 | rootpath: root.path 28 | size_hint_y: 0.6 29 | Widget 30 | size_hint_y: 0.1 31 | GridLayout: 32 | cols: 3 33 | size_hint_y: 0.1 34 | Button: 35 | id: open_button 36 | size_hint: 0.1, None 37 | height: '48dp' 38 | text: _('New') 39 | on_release: 40 | popup.dismiss() 41 | root.new_wallet(app, wallet_selector.path) 42 | Button: 43 | id: open_button 44 | size_hint: 0.1, None 45 | height: '48dp' 46 | text: _('Open') 47 | disabled: not wallet_selector.selection 48 | on_release: 49 | popup.dismiss() 50 | root.open_wallet(app) 51 | ''') 52 | 53 | class WalletDialog(Factory.Popup): 54 | 55 | def new_wallet(self, app, dirname): 56 | def cb(text): 57 | if text: 58 | app.load_wallet_by_name(os.path.join(dirname, text)) 59 | d = LabelDialog(_('Enter wallet name'), '', cb) 60 | d.open() 61 | 62 | def open_wallet(self, app): 63 | app.load_wallet_by_name(self.ids.wallet_selector.selection[0]) 64 | 65 | -------------------------------------------------------------------------------- /contrib/build-wine/prepare-hw.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TREZOR_GIT_URL=git://github.com/trezor/python-trezor.git 4 | KEEPKEY_GIT_URL=git://github.com/keepkey/python-keepkey.git 5 | BTCHIP_GIT_URL=git://github.com/LedgerHQ/btchip-python.git 6 | 7 | BRANCH=master 8 | 9 | # These settings probably don't need any change 10 | export WINEPREFIX=/opt/wine64 11 | 12 | PYHOME=c:/python27 13 | PYTHON="wine $PYHOME/python.exe " 14 | 15 | # Let's begin! 16 | cd `dirname $0` 17 | set -e 18 | 19 | cd tmp 20 | 21 | # downoad mingw-get-setup.exe 22 | #wget http://downloads.sourceforge.net/project/mingw/Installer/mingw-get-setup.exe 23 | #wine mingw-get-setup.exe 24 | 25 | #echo "add c:\MinGW\bin to PATH using regedit" 26 | #regedit 27 | #exit 28 | 29 | #wine mingw-get install gcc 30 | #wine mingw-get install mingw-utils 31 | #wine mingw-get install mingw32-libz 32 | 33 | #create cfg file 34 | #printf "[build]\ncompiler=mingw32\n" > /opt/me/wine64/drive_c/Python27/Lib/distutils/distutils.cfg 35 | 36 | # Install Cython 37 | #wine "$PYHOME\\Scripts\\easy_install.exe" cython 38 | 39 | 40 | # not working 41 | ##wine "$PYHOME\\Scripts\\easy_install.exe" hidapi 42 | 43 | #git clone https://github.com/trezor/cython-hidapi.git 44 | 45 | #replace: from distutils.core import setup, Extenstion 46 | 47 | #cd cython-hidapi 48 | #git submodule init 49 | #git submodule update 50 | #$PYTHON setup.py install 51 | #cd .. 52 | 53 | 54 | 55 | if [ -d "trezor-git" ]; then 56 | cd trezor-git 57 | git pull 58 | cd .. 59 | else 60 | git clone -b $BRANCH $TREZOR_GIT_URL trezor-git 61 | fi 62 | cd trezor-git 63 | $PYTHON setup.py install 64 | cd .. 65 | 66 | #keepkey 67 | if [ -d "keepkey-git" ]; then 68 | cd keepkey-git 69 | git pull 70 | git checkout v0.7.3 71 | cd .. 72 | else 73 | git clone -b $BRANCH $KEEPKEY_GIT_URL keepkey-git 74 | fi 75 | cd keepkey-git 76 | # fails $PYTHON setup.py install 77 | cd .. 78 | 79 | #btchip 80 | if [ -d "btchip-git" ]; then 81 | cd btchip-git 82 | git pull 83 | cd .. 84 | else 85 | git clone -b $BRANCH $BTCHIP_GIT_URL btchip-git 86 | fi 87 | cd btchip-git 88 | $PYTHON setup.py install 89 | cd .. 90 | 91 | -------------------------------------------------------------------------------- /gui/kivy/uix/ui_screens/network.kv: -------------------------------------------------------------------------------- 1 | Popup: 2 | id: nd 3 | title: _('Network') 4 | n_nodes: len(app.network.get_interfaces()) 5 | blockchain_height: app.network.get_local_height() 6 | is_connected: app.network.is_connected() 7 | 8 | BoxLayout: 9 | orientation: 'vertical' 10 | padding: '10dp' 11 | spacing: '10dp' 12 | TopLabel: 13 | s1: _("Connected to %d nodes.")%root.n_nodes if root.n_nodes else _("Not connected?") 14 | s2: _("Blockchain length") + ": %d "%root.blockchain_height + _("blocks") 15 | text: self.s1 + '\n' + self.s2 16 | Widget: 17 | size_hint: 1, 0.1 18 | GridLayout: 19 | cols: 2 20 | Label: 21 | text: _('Server') 22 | Spinner: 23 | id: host 24 | height: '48dp' 25 | size_hint_y: None 26 | text: '' 27 | values: sorted(app.network.get_servers()) 28 | disabled: auto_connect.active 29 | Label: 30 | text: _('Auto-connect') 31 | CheckBox: 32 | id: auto_connect 33 | size_hint_y: None 34 | Widget: 35 | size_hint: 1, 0.1 36 | TopLabel: 37 | text: _("Electrum retrieves your wallet information from a single node (address server). In addition, it connects to a number of extra nodes, in order to fetch block headers. Block headers are used to verify the information sent by the address server, using Simple Payment Verification (SPV).") 38 | font_size: '6pt' 39 | Widget: 40 | size_hint: 1, 0.1 41 | TopLabel: 42 | text: _("If auto-connect is checked, the address server will be selected automatically.") 43 | font_size: '6pt' 44 | Widget: 45 | size_hint: 1, 0.1 46 | 47 | BoxLayout: 48 | Widget: 49 | size_hint: 0.5, None 50 | Button: 51 | size_hint: 0.5, None 52 | height: '48dp' 53 | text: _('OK') 54 | on_release: 55 | nd.dismiss() 56 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Lightweight ulord client 2 | ===================================== 3 | 4 | :: 5 | 6 | Licence: MIT Licence 7 | Language: Python 8 | 9 | 10 | 11 | Getting started 12 | =============== 13 | 14 | uwallet is a pure python application. However, if you want to use the 15 | Qt interface, then you need to install the Qt dependencies:: 16 | 17 | sudo apt-get install python-qt4 18 | 19 | If you download the official package (tar.gz), you can run 20 | uwallet from its root directory directly; all the python dependencies are included in the 'packages' 21 | directory. To run uwallet from its root directory, just do:: 22 | 23 | ./uwallet 24 | 25 | If you cloned the git repository, then you need to compile extra files 26 | before you can run uwallet. Please refer to "Development Version". 27 | 28 | 29 | 30 | Development version 31 | =================== 32 | 33 | Run install (python dependencies needed):: 34 | 35 | python setup.py install 36 | 37 | Compile the icons file for Qt:: 38 | 39 | sudo apt-get install pyqt4-dev-tools 40 | pyrcc4 icons.qrc -o gui/qt/icons_rc.py 41 | 42 | Compile the protobuf description file:: 43 | 44 | sudo apt-get install protobuf-compiler 45 | protoc --proto_path=lib/ --python_out=lib/ lib/paymentrequest.proto 46 | 47 | Create translations:: 48 | 49 | sudo apt-get install python-pycurl gettext 50 | ./contrib/make_locale 51 | 52 | 53 | 54 | Installing on Linux system 55 | ======================== 56 | 57 | If you install uwallet on your system, you can run it from any 58 | directory. 59 | 60 | 61 | 62 | If you don't have pip, install with:: 63 | 64 | python setup.py sdist 65 | sudo python setup.py install 66 | 67 | 68 | 69 | Creating Binaries 70 | ================= 71 | 72 | 73 | In order to create binaries, you must create the 'packages' directory:: 74 | 75 | ./contrib/make_packages 76 | 77 | This directory contains the python dependencies used by uwallet. 78 | 79 | 80 | Windows 81 | ------- 82 | 83 | See `Windows README `_ file. 84 | 85 | 86 | Android 87 | ------- 88 | 89 | See `Android README `_ file. 90 | -------------------------------------------------------------------------------- /plugins/labels/qt.py: -------------------------------------------------------------------------------- 1 | from functools import partial 2 | 3 | from PyQt4.QtGui import * 4 | from PyQt4.QtCore import * 5 | 6 | from uwallet.plugins import hook 7 | from uwallet.i18n import _ 8 | from uwallet_gui.qt import EnterButton 9 | from uwallet_gui.qt.util import ThreadedButton, Buttons 10 | from uwallet_gui.qt.util import WindowModalDialog, OkButton 11 | 12 | from labels import LabelsPlugin 13 | 14 | 15 | class Plugin(LabelsPlugin): 16 | 17 | def __init__(self, *args): 18 | LabelsPlugin.__init__(self, *args) 19 | self.obj = QObject() 20 | 21 | def requires_settings(self): 22 | return True 23 | 24 | def settings_widget(self, window): 25 | return EnterButton(_('Settings'), 26 | partial(self.settings_dialog, window)) 27 | 28 | def settings_dialog(self, window): 29 | wallet = window.parent().wallet 30 | d = WindowModalDialog(window, _("Label Settings")) 31 | hbox = QHBoxLayout() 32 | hbox.addWidget(QLabel("Label sync options:")) 33 | upload = ThreadedButton("Force upload", 34 | partial(self.push_thread, wallet), 35 | partial(self.done_processing, d)) 36 | download = ThreadedButton("Force download", 37 | partial(self.pull_thread, wallet, True), 38 | partial(self.done_processing, d)) 39 | vbox = QVBoxLayout() 40 | vbox.addWidget(upload) 41 | vbox.addWidget(download) 42 | hbox.addLayout(vbox) 43 | vbox = QVBoxLayout(d) 44 | vbox.addLayout(hbox) 45 | vbox.addSpacing(20) 46 | vbox.addLayout(Buttons(OkButton(d))) 47 | return bool(d.exec_()) 48 | 49 | def on_pulled(self, wallet): 50 | self.obj.emit(SIGNAL('labels_changed'), wallet) 51 | 52 | def done_processing(self, dialog, result): 53 | dialog.show_message(_("Your labels have been synchronised.")) 54 | 55 | @hook 56 | def on_new_window(self, window): 57 | window.connect(window.app, SIGNAL('labels_changed'), window.update_tabs) 58 | self.start_wallet(window.wallet) 59 | 60 | @hook 61 | def on_close_window(self, window): 62 | self.stop_wallet(window.wallet) 63 | -------------------------------------------------------------------------------- /gui/kivy/uix/ui_screens/history.kv: -------------------------------------------------------------------------------- 1 | #:import _ electrum_gui.kivy.i18n._ 2 | #:import Factory kivy.factory.Factory 3 | #:set font_light 'gui/kivy/data/fonts/Roboto-Condensed.ttf' 4 | #:set btc_symbol unichr(171) 5 | #:set mbtc_symbol unichr(187) 6 | 7 | 8 | 9 | 10 | color: 0.95, 0.95, 0.95, 1 11 | size_hint: 1, None 12 | text: '' 13 | text_size: self.width, None 14 | height: self.texture_size[1] 15 | halign: 'left' 16 | valign: 'top' 17 | 18 | 19 | 20 | icon: 'atlas://gui/kivy/theming/light/important' 21 | message: '' 22 | value: 0 23 | value_known: True 24 | amount: app.format_amount(self.value, True) if self.value_known else '--' 25 | amount_color: '#FF6657' if self.value < 0 else '#2EA442' 26 | confirmations: 0 27 | date: '' 28 | quote_text: '' 29 | spacing: '9dp' 30 | Image: 31 | id: icon 32 | source: root.icon 33 | size_hint: None, 1 34 | width: self.height *.54 35 | mipmap: True 36 | BoxLayout: 37 | orientation: 'vertical' 38 | Widget 39 | CardLabel: 40 | text: root.date 41 | font_size: '14sp' 42 | CardLabel: 43 | color: .699, .699, .699, 1 44 | font_size: '13sp' 45 | shorten: True 46 | text: root.message 47 | Widget 48 | CardLabel: 49 | halign: 'right' 50 | font_size: '15sp' 51 | size_hint: None, 1 52 | width: '110sp' 53 | markup: True 54 | font_name: font_light 55 | text: 56 | u'[color={amount_color}]{sign}{amount} {unit}[/color]\n'\ 57 | u'[color=#B2B3B3][size=13sp]{qt}[/size]'\ 58 | u'[/color]'.format(amount_color=root.amount_color,\ 59 | amount=root.amount[1:], qt=root.quote_text, sign=root.amount[0],\ 60 | unit=app.base_unit) 61 | 62 | 63 | HistoryScreen: 64 | name: 'history' 65 | content: content 66 | ScrollView: 67 | id: content 68 | do_scroll_x: False 69 | GridLayout 70 | id: history_container 71 | cols: 1 72 | size_hint: 1, None 73 | height: self.minimum_height 74 | padding: '12dp' 75 | spacing: '2dp' 76 | -------------------------------------------------------------------------------- /lib/signmessage.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (C) 2013-2015 The python-bitcoinlib developers 3 | # 4 | # This file is part of python-bitcoinlib. 5 | # 6 | # It is subject to the license terms in the LICENSE file found in the top-level 7 | # directory of this distribution. 8 | # 9 | # No part of python-bitcoinlib, including this file, may be copied, modified, 10 | # propagated, or distributed except according to the terms contained in the 11 | # LICENSE file. 12 | 13 | from __future__ import absolute_import, division, print_function, unicode_literals 14 | 15 | # from bitcoin.core.key import CPubKey 16 | from lib.serialize import * 17 | # from bitcoin.wallet import P2PKHBitcoinAddress 18 | # import bitcoin 19 | import base64 20 | import sys 21 | 22 | _bchr = chr 23 | _bord = ord 24 | if sys.version > '3': 25 | long = int 26 | _bchr = lambda x: bytes([x]) 27 | _bord = lambda x: x 28 | 29 | 30 | # def VerifyMessage(address, message, sig): 31 | # sig = base64.b64decode(sig) 32 | # hash = message.GetHash() 33 | # 34 | # pubkey = CPubKey.recover_compact(hash, sig) 35 | # 36 | # return str(P2PKHBitcoinAddress.from_pubkey(pubkey)) == str(address) 37 | 38 | 39 | def SignMessage(key, message): 40 | sig, i = key.sign_compact(message.GetHash()) 41 | 42 | meta = 27 + i 43 | if key.is_compressed: 44 | meta += 4 45 | 46 | return base64.b64encode(_bchr(meta) + sig) 47 | 48 | 49 | class BitcoinMessage(ImmutableSerializable): 50 | __slots__ = ['magic', 'message'] 51 | 52 | def __init__(self, message="", magic="Ulord Signed Message:\n"): 53 | object.__setattr__(self, 'message', message.encode("utf-8")) 54 | object.__setattr__(self, 'magic', magic.encode("utf-8")) 55 | 56 | @classmethod 57 | def stream_deserialize(cls, f): 58 | magic = BytesSerializer.stream_deserialize(f) 59 | message = BytesSerializer.stream_deserialize(f) 60 | return cls(message, magic) 61 | 62 | def stream_serialize(self, f): 63 | BytesSerializer.stream_serialize(self.magic, f) 64 | BytesSerializer.stream_serialize(self.message, f) 65 | 66 | def __str__(self): 67 | return self.message.decode('ascii') 68 | 69 | 70 | def __repr__(self): 71 | return 'BitcoinMessage(%s, %s)' % (self.magic, self.message) -------------------------------------------------------------------------------- /contrib/build-wine/prepare-wine.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Please update these links carefully, some versions won't work under Wine 4 | PYTHON_URL=http://www.python.org/ftp/python/2.7.8/python-2.7.8.msi 5 | PYQT4_URL=http://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-4.11.1/PyQt4-4.11.1-gpl-Py2.7-Qt4.8.6-x32.exe 6 | PYWIN32_URL=http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/pywin32-219.win32-py2.7.exe/download 7 | PYINSTALLER_URL=https://pypi.python.org/packages/source/P/PyInstaller/PyInstaller-2.1.zip 8 | NSIS_URL=http://prdownloads.sourceforge.net/nsis/nsis-2.46-setup.exe?download 9 | SETUPTOOLS_URL=https://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11.win32-py2.7.exe 10 | 11 | 12 | ## These settings probably don't need change 13 | export WINEPREFIX=/opt/wine64 14 | #export WINEARCH='win32' 15 | 16 | PYHOME=c:/python27 17 | PYTHON="wine $PYHOME/python.exe -OO -B" 18 | 19 | # Let's begin! 20 | cd `dirname $0` 21 | set -e 22 | 23 | # Clean up Wine environment 24 | echo "Cleaning $WINEPREFIX" 25 | rm -rf $WINEPREFIX 26 | echo "done" 27 | 28 | wine 'wineboot' 29 | 30 | echo "Cleaning tmp" 31 | rm -rf tmp 32 | mkdir -p tmp 33 | echo "done" 34 | 35 | cd tmp 36 | 37 | # Install Python 38 | wget -O python.msi "$PYTHON_URL" 39 | wine msiexec /q /i python.msi 40 | 41 | # Install PyWin32 42 | wget -O pywin32.exe "$PYWIN32_URL" 43 | wine pywin32.exe 44 | 45 | # Install PyQt4 46 | wget -O PyQt.exe "$PYQT4_URL" 47 | wine PyQt.exe 48 | 49 | # Install pyinstaller 50 | wget -O pyinstaller.zip "$PYINSTALLER_URL" 51 | unzip pyinstaller.zip 52 | mv PyInstaller-2.1 $WINEPREFIX/drive_c/pyinstaller 53 | 54 | # Install ZBar 55 | #wget -q -O zbar.exe "http://sourceforge.net/projects/zbar/files/zbar/0.10/zbar-0.10-setup.exe/download" 56 | #wine zbar.exe 57 | 58 | # Install setuptools 59 | wget -O setuptools.exe "$SETUPTOOLS_URL" 60 | wine setuptools.exe 61 | 62 | # Install NSIS installer 63 | wget -q -O nsis.exe "$NSIS_URL" 64 | wine nsis.exe 65 | 66 | # Install UPX 67 | #wget -O upx.zip "http://upx.sourceforge.net/download/upx308w.zip" 68 | #unzip -o upx.zip 69 | #cp upx*/upx.exe . 70 | 71 | # add dlls needed for pyinstaller: 72 | cp $WINEPREFIX/drive_c/windows/system32/msvcp90.dll $WINEPREFIX/drive_c/Python27/ 73 | cp $WINEPREFIX/drive_c/windows/system32/msvcm90.dll $WINEPREFIX/drive_c/Python27/ 74 | -------------------------------------------------------------------------------- /plugins/hw_wallet/plugin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- mode: python -*- 3 | # 4 | # Electrum - lightweight Bitcoin client 5 | # Copyright (C) 2016 The Electrum developers 6 | # 7 | # Permission is hereby granted, free of charge, to any person 8 | # obtaining a copy of this software and associated documentation files 9 | # (the "Software"), to deal in the Software without restriction, 10 | # including without limitation the rights to use, copy, modify, merge, 11 | # publish, distribute, sublicense, and/or sell copies of the Software, 12 | # and to permit persons to whom the Software is furnished to do so, 13 | # subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be 16 | # included in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 22 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | # SOFTWARE. 26 | 27 | from uwallet.plugins import BasePlugin, hook 28 | from uwallet.i18n import _ 29 | 30 | 31 | class HW_PluginBase(BasePlugin): 32 | # Derived classes provide: 33 | # 34 | # class-static variables: client_class, firmware_URL, handler_class, 35 | # libraries_available, libraries_URL, minimum_firmware, 36 | # wallet_class, ckd_public, types, HidTransport 37 | 38 | def __init__(self, parent, config, name): 39 | BasePlugin.__init__(self, parent, config, name) 40 | self.device = self.keystore_class.device 41 | self.keystore_class.plugin = self 42 | 43 | def is_enabled(self): 44 | return self.libraries_available 45 | 46 | def device_manager(self): 47 | return self.parent.device_manager 48 | 49 | @hook 50 | def close_wallet(self, wallet): 51 | for keystore in wallet.get_keystores(): 52 | if isinstance(keystore, self.keystore_class): 53 | self.device_manager().unpair_xpub(keystore.xpub) 54 | -------------------------------------------------------------------------------- /gui/kivy/uix/dialogs/choice_dialog.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.factory import Factory 3 | from kivy.properties import ObjectProperty 4 | from kivy.lang import Builder 5 | from kivy.uix.checkbox import CheckBox 6 | from kivy.uix.label import Label 7 | from kivy.uix.widget import Widget 8 | 9 | Builder.load_string(''' 10 | 11 | id: popup 12 | title: '' 13 | size_hint: 0.8, 0.8 14 | pos_hint: {'top':0.9} 15 | BoxLayout: 16 | orientation: 'vertical' 17 | Widget: 18 | size_hint: 1, 0.1 19 | ScrollView: 20 | orientation: 'vertical' 21 | size_hint: 1, 0.8 22 | GridLayout: 23 | row_default_height: '48dp' 24 | orientation: 'vertical' 25 | id: choices 26 | cols: 2 27 | size_hint: 1, None 28 | BoxLayout: 29 | orientation: 'horizontal' 30 | size_hint: 1, 0.2 31 | Button: 32 | text: 'Cancel' 33 | size_hint: 0.5, None 34 | height: '48dp' 35 | on_release: popup.dismiss() 36 | Button: 37 | text: 'OK' 38 | size_hint: 0.5, None 39 | height: '48dp' 40 | on_release: 41 | root.callback(popup.value) 42 | popup.dismiss() 43 | ''') 44 | 45 | class ChoiceDialog(Factory.Popup): 46 | 47 | def __init__(self, title, choices, key, callback): 48 | Factory.Popup.__init__(self) 49 | if type(choices) is list: 50 | choices = dict(map(lambda x: (x,x), choices)) 51 | layout = self.ids.choices 52 | layout.bind(minimum_height=layout.setter('height')) 53 | for k, v in sorted(choices.items()): 54 | l = Label(text=v) 55 | l.height = '48dp' 56 | cb = CheckBox(group='choices') 57 | cb.value = k 58 | cb.height = '48dp' 59 | def f(cb, x): 60 | if x: self.value = cb.value 61 | cb.bind(active=f) 62 | if k == key: 63 | cb.active = True 64 | layout.add_widget(l) 65 | layout.add_widget(cb) 66 | layout.add_widget(Widget(size_hint_y=1)) 67 | self.callback = callback 68 | self.title = title 69 | self.value = key 70 | -------------------------------------------------------------------------------- /gui/kivy/tools/blacklist.txt: -------------------------------------------------------------------------------- 1 | # eggs 2 | *.egg-info 3 | 4 | # unit test 5 | unittest/* 6 | 7 | # python config 8 | config/makesetup 9 | 10 | # unused pygame files 11 | pygame/_camera_* 12 | pygame/camera.pyo 13 | pygame/*.html 14 | pygame/*.bmp 15 | pygame/*.svg 16 | pygame/cdrom.so 17 | pygame/pygame_icon.icns 18 | pygame/LGPL 19 | pygame/threads/Py25Queue.pyo 20 | pygame/*.ttf 21 | pygame/mac* 22 | pygame/_numpy* 23 | pygame/sndarray.pyo 24 | pygame/surfarray.pyo 25 | pygame/_arraysurfarray.pyo 26 | 27 | # unused kivy files (platform specific) 28 | kivy/input/providers/wm_* 29 | kivy/input/providers/mactouch* 30 | kivy/input/providers/probesysfs* 31 | kivy/input/providers/mtdev* 32 | kivy/input/providers/hidinput* 33 | kivy/core/camera/camera_videocapture* 34 | kivy/core/spelling/*osx* 35 | kivy/core/video/video_pyglet* 36 | 37 | kivy/adapters 38 | kivy/modules 39 | kivy/uix/sandbox 40 | kivy/uix/pagelayout 41 | kivy/uix/video 42 | kivy/uix/vkeyboard 43 | kivy/uix/videoplayer 44 | 45 | # unused encodings 46 | lib-dynload/*codec* 47 | encodings/cp*.pyo 48 | encodings/tis* 49 | encodings/shift* 50 | encodings/bz2* 51 | encodings/iso* 52 | encodings/undefined* 53 | encodings/johab* 54 | encodings/p* 55 | encodings/m* 56 | encodings/euc* 57 | encodings/k* 58 | encodings/unicode_internal* 59 | encodings/quo* 60 | encodings/gb* 61 | encodings/big5* 62 | encodings/hp* 63 | encodings/hz* 64 | 65 | # unused python modules 66 | bsddb/* 67 | wsgiref/* 68 | hotshot/* 69 | pydoc_data/* 70 | tty.pyo 71 | #anydbm.pyo 72 | nturl2path.pyo 73 | LICENCE.txt 74 | macurl2path.pyo 75 | dummy_threading.pyo 76 | audiodev.pyo 77 | antigravity.pyo 78 | #dumbdbm.pyo 79 | sndhdr.pyo 80 | __phello__.foo.pyo 81 | sunaudio.pyo 82 | os2emxpath.pyo 83 | multiprocessing/dummy* 84 | 85 | # unused binaries python modules 86 | lib-dynload/termios.so 87 | lib-dynload/_lsprof.so 88 | lib-dynload/*audioop.so 89 | #lib-dynload/mmap.so 90 | lib-dynload/_hotshot.so 91 | #lib-dynload/_csv.so 92 | lib-dynload/future_builtins.so 93 | lib-dynload/_heapq.so 94 | lib-dynload/_json.so 95 | lib-dynload/grp.so 96 | lib-dynload/resource.so 97 | lib-dynload/pyexpat.so 98 | 99 | # odd files 100 | plat-linux3/regen 101 | 102 | #>sqlite3 103 | # conditionnal include depending if some recipes are included or not. 104 | #sqlite3/* 105 | #lib-dynload/_sqlite3.so 106 | # device 68 | if os.path.exists(device_root): 69 | for device in os.listdir(device_root): 70 | name = open(os.path.join(device_root, device, 'name')).read() 71 | name = name.strip('\n') 72 | devices[name] = os.path.join("/dev",device) 73 | return devices 74 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | # python setup.py sdist --format=zip,gztar 4 | 5 | from setuptools import setup 6 | import os 7 | import sys 8 | import platform 9 | import imp 10 | import argparse 11 | 12 | version = imp.load_source('version', 'lib/version.py') 13 | 14 | if sys.version_info[:3] < (2, 7, 0): 15 | sys.exit("Error: UWallet requires Python version >= 2.7.0...") 16 | 17 | data_files = [] 18 | 19 | if platform.system() in ['Linux', 'FreeBSD', 'DragonFly']: 20 | parser = argparse.ArgumentParser() 21 | parser.add_argument('--root=', dest='root_path', metavar='dir', default='/') 22 | opts, _ = parser.parse_known_args(sys.argv[1:]) 23 | usr_share = os.path.join(sys.prefix, "share") 24 | if not os.access(opts.root_path + usr_share, os.W_OK) and \ 25 | not os.access(opts.root_path, os.W_OK): 26 | if 'XDG_DATA_HOME' in os.environ.keys(): 27 | usr_share = os.environ['XDG_DATA_HOME'] 28 | else: 29 | usr_share = os.path.expanduser('~/.local/share') 30 | data_files += [ 31 | (os.path.join(usr_share, 'applications/'), ['uwallet.desktop']), 32 | (os.path.join(usr_share, 'pixmaps/'), ['icons/uwallet.png']) 33 | ] 34 | 35 | setup( 36 | name="UWallet", 37 | version=version.UWallet_VERSION, 38 | install_requires=[ 39 | 'slowaes>=0.1a1', 40 | 'ecdsa>=0.9', 41 | 'pbkdf2', 42 | 'requests', 43 | 'qrcode', 44 | 'protobuf', 45 | 'dnspython', 46 | 'jsonrpclib', 47 | ], 48 | packages=[ 49 | 'uwallet', 50 | 'uwallet_gui', 51 | 'uwallet_gui.qt', 52 | 'uwallet_plugins', 53 | 'uwallet_plugins.audio_modem', 54 | 'uwallet_plugins.cosigner_pool', 55 | 'uwallet_plugins.email_requests', 56 | 'uwallet_plugins.exchange_rate', 57 | 'uwallet_plugins.greenaddress_instant', 58 | 'uwallet_plugins.hw_wallet', 59 | 'uwallet_plugins.keepkey', 60 | 'uwallet_plugins.labels', 61 | 'uwallet_plugins.ledger', 62 | 'uwallet_plugins.plot', 63 | 'uwallet_plugins.trezor', 64 | 'uwallet_plugins.trustedcoin', 65 | 'uwallet_plugins.virtualkeyboard', 66 | ], 67 | package_dir={ 68 | 'uwallet': 'lib', 69 | 'uwallet_gui': 'gui', 70 | 'uwallet_plugins': 'plugins', 71 | }, 72 | package_data={ 73 | 'uwallet': [ 74 | 'www/index.html', 75 | 'wordlist/*.txt', 76 | 'locale/*/LC_MESSAGES/ulord.mo', 77 | ] 78 | }, 79 | scripts=['uwallet'], 80 | data_files=data_files, 81 | description="Lightweight Bitcoin Wallet", 82 | author="Thomas Voegtlin", 83 | author_email="", 84 | license="MIT Licence", 85 | url="http://www.ulord.one/", 86 | long_description="""Lightweight Bitcoin Wallet""" 87 | ) 88 | -------------------------------------------------------------------------------- /gui/kivy/uix/combobox.py: -------------------------------------------------------------------------------- 1 | ''' 2 | ComboBox 3 | ======= 4 | 5 | Based on Spinner 6 | ''' 7 | 8 | __all__ = ('ComboBox', 'ComboBoxOption') 9 | 10 | from kivy.properties import ListProperty, ObjectProperty, BooleanProperty 11 | from kivy.uix.button import Button 12 | from kivy.uix.dropdown import DropDown 13 | from kivy.lang import Builder 14 | 15 | 16 | Builder.load_string(''' 17 | : 18 | size_hint_y: None 19 | height: 44 20 | 21 | : 22 | background_normal: 'atlas://data/images/defaulttheme/spinner' 23 | background_down: 'atlas://data/images/defaulttheme/spinner_pressed' 24 | on_key: 25 | if self.items: x, y = zip(*self.items); self.text = y[x.index(args[1])] 26 | ''') 27 | 28 | 29 | class ComboBoxOption(Button): 30 | pass 31 | 32 | 33 | class ComboBox(Button): 34 | items = ListProperty() 35 | key = ObjectProperty() 36 | 37 | option_cls = ObjectProperty(ComboBoxOption) 38 | 39 | dropdown_cls = ObjectProperty(DropDown) 40 | 41 | is_open = BooleanProperty(False) 42 | 43 | def __init__(self, **kwargs): 44 | self._dropdown = None 45 | super(ComboBox, self).__init__(**kwargs) 46 | self.items_dict = dict(self.items) 47 | self.bind( 48 | on_release=self._toggle_dropdown, 49 | dropdown_cls=self._build_dropdown, 50 | option_cls=self._build_dropdown, 51 | items=self._update_dropdown, 52 | key=self._update_text) 53 | self._build_dropdown() 54 | self._update_text() 55 | 56 | def _update_text(self, *largs): 57 | try: 58 | self.text = self.items_dict[self.key] 59 | except KeyError: 60 | pass 61 | 62 | def _build_dropdown(self, *largs): 63 | if self._dropdown: 64 | self._dropdown.unbind(on_select=self._on_dropdown_select) 65 | self._dropdown.dismiss() 66 | self._dropdown = None 67 | self._dropdown = self.dropdown_cls() 68 | self._dropdown.bind(on_select=self._on_dropdown_select) 69 | self._update_dropdown() 70 | 71 | def _update_dropdown(self, *largs): 72 | dp = self._dropdown 73 | cls = self.option_cls 74 | dp.clear_widgets() 75 | for key, value in self.items: 76 | item = cls(text=value) 77 | # extra attribute 78 | item.key = key 79 | item.bind(on_release=lambda option: dp.select(option.key)) 80 | dp.add_widget(item) 81 | 82 | def _toggle_dropdown(self, *largs): 83 | self.is_open = not self.is_open 84 | 85 | def _on_dropdown_select(self, instance, data, *largs): 86 | self.key = data 87 | self.is_open = False 88 | 89 | def on_is_open(self, instance, value): 90 | if value: 91 | self._dropdown.open(self) 92 | else: 93 | self._dropdown.dismiss() 94 | -------------------------------------------------------------------------------- /gui/qt/address_dialog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Electrum - lightweight Bitcoin client 4 | # Copyright (C) 2012 thomasv@gitorious 5 | # 6 | # Permission is hereby granted, free of charge, to any person 7 | # obtaining a copy of this software and associated documentation files 8 | # (the "Software"), to deal in the Software without restriction, 9 | # including without limitation the rights to use, copy, modify, merge, 10 | # publish, distribute, sublicense, and/or sell copies of the Software, 11 | # and to permit persons to whom the Software is furnished to do so, 12 | # subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be 15 | # included in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | 26 | from uwallet.i18n import _ 27 | 28 | import PyQt4 29 | from PyQt4.QtGui import * 30 | from PyQt4.QtCore import * 31 | 32 | from util import * 33 | from history_list import HistoryList 34 | 35 | class AddressDialog(WindowModalDialog): 36 | 37 | def __init__(self, parent, address): 38 | WindowModalDialog.__init__(self, parent, _("Address")) 39 | self.address = address 40 | self.parent = parent 41 | self.config = parent.config 42 | self.wallet = parent.wallet 43 | self.app = parent.app 44 | self.saved = True 45 | 46 | self.setMinimumWidth(700) 47 | vbox = QVBoxLayout() 48 | self.setLayout(vbox) 49 | self.setTitleBar(vbox) 50 | vbox.addWidget(QLabel(_("Address:"))) 51 | self.addr_e = ButtonsLineEdit(self.address) 52 | self.addr_e.addCopyButton(self.app) 53 | # self.addr_e.addButton(":icons/qrcode.png", self.show_qr, _("Show QR Code")) 54 | self.addr_e.setReadOnly(True) 55 | vbox.addWidget(self.addr_e) 56 | 57 | vbox.addWidget(QLabel(_("History"))) 58 | self.hw = HistoryList(self.parent) 59 | self.hw.get_domain = self.get_domain 60 | vbox.addWidget(self.hw) 61 | 62 | vbox.addStretch(1) 63 | vbox.addLayout(Buttons(CloseButton(self))) 64 | self.format_amount = self.parent.format_amount 65 | self.hw.update() 66 | 67 | def get_domain(self): 68 | return [self.address] 69 | 70 | def show_qr(self): 71 | text = self.address 72 | try: 73 | self.parent.show_qrcode(text, 'Address') 74 | except Exception as e: 75 | self.show_message(str(e)) 76 | -------------------------------------------------------------------------------- /contrib/build-wine/deterministic.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | home = 'C:\\electrum\\' 4 | 5 | # We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports 6 | a = Analysis([home+'electrum', 7 | home+'gui/qt/main_window.py', 8 | home+'gui/text.py', 9 | home+'lib/util.py', 10 | home+'lib/wallet.py', 11 | home+'lib/simple_config.py', 12 | home+'lib/bitcoin.py', 13 | home+'lib/dnssec.py', 14 | home+'lib/commands.py', 15 | home+'plugins/cosigner_pool/qt.py', 16 | home+'plugins/email_requests/qt.py', 17 | home+'plugins/trezor/qt.py', 18 | home+'plugins/keepkey/qt.py', 19 | home+'plugins/ledger/qt.py', 20 | home+'packages/requests/utils.py' 21 | ], 22 | pathex=[home+'lib', home+'gui', home+'plugins', home+'packages'], 23 | hiddenimports=['lib', 'gui'], 24 | hookspath=[]) 25 | 26 | ##### include folder in distribution ####### 27 | def extra_datas(mydir): 28 | def rec_glob(p, files): 29 | import os 30 | import glob 31 | for d in glob.glob(p): 32 | if os.path.isfile(d): 33 | files.append(d) 34 | rec_glob("%s/*" % d, files) 35 | files = [] 36 | rec_glob("%s/*" % mydir, files) 37 | extra_datas = [] 38 | for f in files: 39 | d = f.split('\\') 40 | t = '' 41 | for a in d[2:]: 42 | if len(t)==0: 43 | t = a 44 | else: 45 | t = t+'\\'+a 46 | extra_datas.append((t, f, 'DATA')) 47 | 48 | return extra_datas 49 | ########################################### 50 | 51 | # append dirs 52 | 53 | # cacert.pem 54 | a.datas += [ ('requests/cacert.pem', home+'packages/requests/cacert.pem', 'DATA') ] 55 | 56 | # Py folders that are needed because of the magic import finding 57 | a.datas += extra_datas(home+'gui') 58 | a.datas += extra_datas(home+'lib') 59 | a.datas += extra_datas(home+'plugins') 60 | a.datas += extra_datas(home+'packages') 61 | 62 | pyz = PYZ(a.pure) 63 | exe = EXE(pyz, 64 | a.scripts, 65 | a.binaries, 66 | a.datas, 67 | name=os.path.join('build\\pyi.win32\\electrum', 'electrum.exe'), 68 | debug=False, 69 | strip=None, 70 | upx=False, 71 | icon=home+'icons/electrum.ico', 72 | console=False) 73 | # The console True makes an annoying black box pop up, but it does make Electrum output command line commands, with this turned off no output will be given but commands can still be used 74 | 75 | coll = COLLECT(exe, 76 | a.binaries, 77 | a.zipfiles, 78 | a.datas, 79 | strip=None, 80 | upx=True, 81 | debug=False, 82 | icon=home+'icons/electrum.ico', 83 | console=False, 84 | name=os.path.join('dist', 'electrum')) 85 | -------------------------------------------------------------------------------- /gui/kivy/uix/dialogs/password_dialog.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.factory import Factory 3 | from kivy.properties import ObjectProperty 4 | from kivy.lang import Builder 5 | from decimal import Decimal 6 | from kivy.clock import Clock 7 | 8 | Builder.load_string(''' 9 | 10 | 11 | id: popup 12 | title: _('PIN Code') 13 | message: '' 14 | size_hint: 0.9, 0.9 15 | BoxLayout: 16 | orientation: 'vertical' 17 | Widget: 18 | size_hint: 1, 1 19 | Label: 20 | text: root.message 21 | text_size: self.width, None 22 | size: self.texture_size 23 | Widget: 24 | size_hint: 1, 1 25 | Label: 26 | id: a 27 | text: ' * '*len(kb.password) + ' o '*(6-len(kb.password)) 28 | Widget: 29 | size_hint: 1, 1 30 | GridLayout: 31 | id: kb 32 | update_amount: popup.update_password 33 | password: '' 34 | on_password: popup.on_password(self.password) 35 | size_hint: 1, None 36 | height: '200dp' 37 | cols: 3 38 | KButton: 39 | text: '1' 40 | KButton: 41 | text: '2' 42 | KButton: 43 | text: '3' 44 | KButton: 45 | text: '4' 46 | KButton: 47 | text: '5' 48 | KButton: 49 | text: '6' 50 | KButton: 51 | text: '7' 52 | KButton: 53 | text: '8' 54 | KButton: 55 | text: '9' 56 | KButton: 57 | text: 'Clear' 58 | KButton: 59 | text: '0' 60 | KButton: 61 | text: '<' 62 | BoxLayout: 63 | size_hint: 1, None 64 | height: '48dp' 65 | Widget: 66 | size_hint: 0.5, None 67 | Button: 68 | size_hint: 0.5, None 69 | height: '48dp' 70 | text: _('Cancel') 71 | on_release: 72 | popup.dismiss() 73 | ''') 74 | 75 | 76 | class PasswordDialog(Factory.Popup): 77 | 78 | #def __init__(self, message, callback): 79 | # Factory.Popup.__init__(self) 80 | 81 | def init(self, message, callback): 82 | self.pw = None 83 | self.message = message 84 | self.callback = callback 85 | self.ids.kb.password = '' 86 | 87 | def update_password(self, c): 88 | kb = self.ids.kb 89 | text = kb.password 90 | if c == '<': 91 | text = text[:-1] 92 | elif c == 'Clear': 93 | text = '' 94 | else: 95 | text += c 96 | kb.password = text 97 | 98 | def on_password(self, pw): 99 | if len(pw) == 6: 100 | self.pw = pw 101 | self.dismiss() 102 | 103 | def on_dismiss(self): 104 | Clock.schedule_once(lambda dt: self.callback(self.pw), 0.1) 105 | -------------------------------------------------------------------------------- /gui/kivy/uix/menus.py: -------------------------------------------------------------------------------- 1 | from functools import partial 2 | 3 | from kivy.animation import Animation 4 | from kivy.core.window import Window 5 | from kivy.clock import Clock 6 | from kivy.uix.bubble import Bubble, BubbleButton 7 | from kivy.properties import ListProperty 8 | from kivy.uix.widget import Widget 9 | 10 | from uwallet_gui.i18n import _ 11 | 12 | class ContextMenuItem(Widget): 13 | '''abstract class 14 | ''' 15 | 16 | class ContextButton(ContextMenuItem, BubbleButton): 17 | pass 18 | 19 | class ContextMenu(Bubble): 20 | 21 | buttons = ListProperty([_('ok'), _('cancel')]) 22 | '''List of Buttons to be displayed at the bottom''' 23 | 24 | __events__ = ('on_press', 'on_release') 25 | 26 | def __init__(self, **kwargs): 27 | self._old_buttons = self.buttons 28 | super(ContextMenu, self).__init__(**kwargs) 29 | self.on_buttons(self, self.buttons) 30 | 31 | def on_touch_down(self, touch): 32 | if not self.collide_point(*touch.pos): 33 | self.hide() 34 | return 35 | return super(ContextMenu, self).on_touch_down(touch) 36 | 37 | def on_buttons(self, _menu, value): 38 | if 'menu_content' not in self.ids.keys(): 39 | return 40 | if value == self._old_buttons: 41 | return 42 | blayout = self.ids.menu_content 43 | blayout.clear_widgets() 44 | for btn in value: 45 | ib = ContextButton(text=btn) 46 | ib.bind(on_press=partial(self.dispatch, 'on_press')) 47 | ib.bind(on_release=partial(self.dispatch, 'on_release')) 48 | blayout.add_widget(ib) 49 | self._old_buttons = value 50 | 51 | def on_press(self, instance): 52 | pass 53 | 54 | def on_release(self, instance): 55 | pass 56 | 57 | def show(self, pos, duration=0): 58 | Window.add_widget(self) 59 | # wait for the bubble to adjust it's size according to text then animate 60 | Clock.schedule_once(lambda dt: self._show(pos, duration)) 61 | 62 | def _show(self, pos, duration): 63 | def on_stop(*l): 64 | if duration: 65 | Clock.schedule_once(self.hide, duration + .5) 66 | 67 | self.opacity = 0 68 | arrow_pos = self.arrow_pos 69 | if arrow_pos[0] in ('l', 'r'): 70 | pos = pos[0], pos[1] - (self.height/2) 71 | else: 72 | pos = pos[0] - (self.width/2), pos[1] 73 | 74 | self.limit_to = Window 75 | 76 | anim = Animation(opacity=1, pos=pos, d=.32) 77 | anim.bind(on_complete=on_stop) 78 | anim.cancel_all(self) 79 | anim.start(self) 80 | 81 | 82 | def hide(self, *dt): 83 | 84 | def on_stop(*l): 85 | Window.remove_widget(self) 86 | anim = Animation(opacity=0, d=.25) 87 | anim.bind(on_complete=on_stop) 88 | anim.cancel_all(self) 89 | anim.start(self) 90 | 91 | def add_widget(self, widget, index=0): 92 | if not isinstance(widget, ContextMenuItem): 93 | super(ContextMenu, self).add_widget(widget, index) 94 | return 95 | menu_content.add_widget(widget, index) 96 | -------------------------------------------------------------------------------- /setup-release.py: -------------------------------------------------------------------------------- 1 | """ 2 | py2app/py2exe build script for Electrum 3 | 4 | Usage (Mac OS X): 5 | python setup.py py2app 6 | 7 | Usage (Windows): 8 | python setup.py py2exe 9 | """ 10 | 11 | from setuptools import setup 12 | import os 13 | import re 14 | import shutil 15 | import sys 16 | 17 | from lib.util import print_error 18 | from lib.version import UWallet_VERSION as version 19 | 20 | 21 | name = "UWallet" 22 | mainscript = 'uwallet' 23 | 24 | if sys.version_info[:3] < (2, 6, 0): 25 | print_error("Error: " + name + " requires Python version >= 2.6.0...") 26 | sys.exit(1) 27 | 28 | if sys.platform == 'darwin': 29 | from plistlib import Plist 30 | plist = Plist.fromFile('Info.plist') 31 | plist.update(dict(CFBundleIconFile='electrum.icns')) 32 | 33 | shutil.copy(mainscript, mainscript + '.py') 34 | mainscript += '.py' 35 | extra_options = dict( 36 | setup_requires=['py2app'], 37 | app=[mainscript], 38 | options=dict(py2app=dict(argv_emulation=False, 39 | includes=['PyQt4.QtCore', 'PyQt4.QtGui', 'PyQt4.QtWebKit', 'PyQt4.QtNetwork', 'sip'], 40 | packages=['lib', 'gui', 'plugins', 'packages'], 41 | iconfile='electrum.icns', 42 | plist=plist, 43 | resources=["icons"])), 44 | ) 45 | elif sys.platform == 'win32': 46 | extra_options = dict( 47 | setup_requires=['py2exe'], 48 | app=[mainscript], 49 | ) 50 | else: 51 | extra_options = dict( 52 | # Normally unix-like platforms will use "setup.py install" 53 | # and install the main script as such 54 | scripts=[mainscript], 55 | ) 56 | 57 | setup( 58 | name=name, 59 | version=version, 60 | **extra_options 61 | ) 62 | from distutils import dir_util 63 | 64 | if sys.platform == 'darwin': 65 | # Remove the copied py file 66 | os.remove(mainscript) 67 | resource = "dist/" + name + ".app/Contents/Resources/" 68 | 69 | # Try to locate qt_menu 70 | # Let's try the port version first! 71 | if os.path.isfile("/opt/local/lib/Resources/qt_menu.nib"): 72 | qt_menu_location = "/opt/local/lib/Resources/qt_menu.nib" 73 | else: 74 | # No dice? Then let's try the brew version 75 | if os.path.exists("/usr/local/Cellar"): 76 | qt_menu_location = os.popen("find /usr/local/Cellar -name qt_menu.nib | tail -n 1").read() 77 | # no brew, check /opt/local 78 | else: 79 | qt_menu_location = os.popen("find /opt/local -name qt_menu.nib | tail -n 1").read() 80 | qt_menu_location = re.sub('\n', '', qt_menu_location) 81 | 82 | if (len(qt_menu_location) == 0): 83 | print "Sorry couldn't find your qt_menu.nib this probably won't work" 84 | else: 85 | print "Found your qib: " + qt_menu_location 86 | 87 | # Need to include a copy of qt_menu.nib 88 | shutil.copytree(qt_menu_location, resource + "qt_menu.nib") 89 | # Need to touch qt.conf to avoid loading 2 sets of Qt libraries 90 | fname = resource + "qt.conf" 91 | with file(fname, 'a'): 92 | os.utime(fname, None) 93 | -------------------------------------------------------------------------------- /gui/kivy/uix/ui_screens/status.kv: -------------------------------------------------------------------------------- 1 | Popup: 2 | title: "Electrum" 3 | confirmed: 0 4 | unconfirmed: 0 5 | unmatured: 0 6 | watching_only: app.wallet.is_watching_only() 7 | on_parent: 8 | self.confirmed, self.unconfirmed, self.unmatured = app.wallet.get_balance() 9 | BoxLayout: 10 | orientation: 'vertical' 11 | ScrollView: 12 | GridLayout: 13 | cols: 1 14 | height: self.minimum_height 15 | size_hint_y: None 16 | padding: '10dp' 17 | spacing: '10dp' 18 | padding: '10dp' 19 | spacing: '10dp' 20 | GridLayout: 21 | cols: 1 22 | size_hint_y: None 23 | height: self.minimum_height 24 | spacing: '10dp' 25 | BoxLabel: 26 | text: _('Wallet Name') 27 | value: app.wallet_name() 28 | BoxLabel: 29 | text: _("Wallet type:") 30 | value: app.wallet.wallet_type 31 | BoxLabel: 32 | text: _("Balance") + ':' 33 | value: app.format_amount_and_units(root.confirmed + root.unconfirmed + root.unmatured) 34 | BoxLabel: 35 | text: _("Confirmed") + ':' 36 | opacity: 1 if root.confirmed else 0 37 | value: app.format_amount_and_units(root.confirmed) 38 | opacity: 1 if root.confirmed else 0 39 | BoxLabel: 40 | text: _("Unconfirmed") + ':' 41 | opacity: 1 if root.unconfirmed else 0 42 | value: app.format_amount_and_units(root.unconfirmed) 43 | BoxLabel: 44 | text: _("Unmatured") + ':' 45 | opacity: 1 if root.unmatured else 0 46 | value: app.format_amount_and_units(root.unmatured) 47 | opacity: 1 if root.unmatured else 0 48 | 49 | TopLabel: 50 | text: _('Master Public Key') 51 | RefLabel: 52 | data: app.wallet.get_master_public_key() or 'None' 53 | name: _('Master Public Key') 54 | TopLabel: 55 | id: seed_label 56 | text: _('This wallet is watching-only') if root.watching_only else '' 57 | 58 | BoxLayout: 59 | size_hint: 1, None 60 | height: '48dp' 61 | Button: 62 | size_hint: 0.5, None 63 | height: '48dp' 64 | text: '' if root.watching_only else (_('Hide seed') if seed_label.text else _('Show seed')) 65 | disabled: root.watching_only 66 | on_release: 67 | setattr(seed_label, 'text', '') if seed_label.text else app.show_seed(seed_label) 68 | Button: 69 | size_hint: 0.5, None 70 | height: '48dp' 71 | text: _('Delete') 72 | on_release: 73 | root.dismiss() 74 | app.delete_wallet() 75 | -------------------------------------------------------------------------------- /scripts/util.py: -------------------------------------------------------------------------------- 1 | import select, time, uwallet, Queue 2 | from uwallet import Connection, Interface, SimpleConfig 3 | from uwallet.network import filter_protocol, parse_servers 4 | from collections import defaultdict 5 | 6 | # electrum.util.set_verbosity(1) 7 | def get_interfaces(servers, timeout=10): 8 | '''Returns a map of servers to connected interfaces. If any 9 | connections fail or timeout, they will be missing from the map. 10 | ''' 11 | socket_queue = Queue.Queue() 12 | config = SimpleConfig() 13 | connecting = {} 14 | for server in servers: 15 | if server not in connecting: 16 | connecting[server] = Connection(server, socket_queue, config.path) 17 | interfaces = {} 18 | timeout = time.time() + timeout 19 | count = 0 20 | while time.time() < timeout and count < len(servers): 21 | try: 22 | server, socket = socket_queue.get(True, 0.3) 23 | except Queue.Empty: 24 | continue 25 | if socket: 26 | interfaces[server] = Interface(server, socket) 27 | count += 1 28 | return interfaces 29 | 30 | def wait_on_interfaces(interfaces, timeout=10): 31 | '''Return a map of servers to a list of (request, response) tuples. 32 | Waits timeout seconds, or until each interface has a response''' 33 | result = defaultdict(list) 34 | timeout = time.time() + timeout 35 | while len(result) < len(interfaces) and time.time() < timeout: 36 | rin = [i for i in interfaces.values()] 37 | win = [i for i in interfaces.values() if i.unsent_requests] 38 | rout, wout, xout = select.select(rin, win, [], 1) 39 | for interface in wout: 40 | interface.send_requests() 41 | for interface in rout: 42 | responses = interface.get_responses() 43 | if responses: 44 | result[interface.server].extend(responses) 45 | return result 46 | 47 | def get_peers(): 48 | peers = [] 49 | # 1. get connected interfaces 50 | server = 'ecdsa.net:110:s' 51 | interfaces = get_interfaces([server]) 52 | if not interfaces: 53 | print "No connection to", server 54 | return [] 55 | # 2. get list of peers 56 | interface = interfaces[server] 57 | interface.queue_request('server.peers.subscribe', [], 0) 58 | responses = wait_on_interfaces(interfaces).get(server) 59 | if responses: 60 | response = responses[0][1] # One response, (req, response) tuple 61 | peers = parse_servers(response.get('result')) 62 | peers = filter_protocol(peers,'s') 63 | return peers 64 | 65 | def send_request(peers, method, params): 66 | print "Contacting %d servers"%len(peers) 67 | interfaces = get_interfaces(peers) 68 | print "%d servers could be reached" % len(interfaces) 69 | for peer in peers: 70 | if not peer in interfaces: 71 | print "Connection failed:", peer 72 | for msg_id, i in enumerate(interfaces.values()): 73 | i.queue_request(method, params, msg_id) 74 | responses = wait_on_interfaces(interfaces) 75 | for peer in interfaces: 76 | if not peer in responses: 77 | print peer, "did not answer" 78 | results = dict(zip(responses.keys(), [t[0][1].get('result') for t in responses.values()])) 79 | print "%d answers"%len(results) 80 | return results 81 | -------------------------------------------------------------------------------- /gui/kivy/data/images/defaulttheme.atlas: -------------------------------------------------------------------------------- 1 | {"defaulttheme-0.png": {"progressbar_background": [391, 227, 24, 24], "tab_btn_disabled": [264, 137, 32, 32], "tab_btn_pressed": [366, 137, 32, 32], "image-missing": [152, 171, 48, 48], "splitter_h": [174, 123, 32, 7], "splitter_down": [501, 253, 7, 32], "splitter_disabled_down": [503, 291, 7, 32], "vkeyboard_key_down": [468, 137, 32, 32], "vkeyboard_disabled_key_down": [400, 137, 32, 32], "selector_right": [248, 223, 55, 62], "player-background": [2, 287, 103, 103], "selector_middle": [191, 223, 55, 62], "spinner": [235, 82, 29, 37], "tab_btn_disabled_pressed": [298, 137, 32, 32], "switch-button_disabled": [277, 291, 43, 32], "textinput_disabled_active": [372, 326, 64, 64], "splitter_grip": [36, 50, 12, 26], "vkeyboard_key_normal": [2, 44, 32, 32], "button_disabled": [80, 82, 29, 37], "media-playback-stop": [302, 171, 48, 48], "splitter": [501, 87, 7, 32], "splitter_down_h": [140, 123, 32, 7], "sliderh_background_disabled": [72, 132, 41, 37], "modalview-background": [464, 456, 45, 54], "button": [142, 82, 29, 37], "splitter_disabled": [502, 137, 7, 32], "checkbox_radio_disabled_on": [433, 87, 32, 32], "slider_cursor": [402, 171, 48, 48], "vkeyboard_disabled_background": [68, 221, 64, 64], "checkbox_disabled_on": [297, 87, 32, 32], "sliderv_background_disabled": [2, 78, 37, 41], "button_disabled_pressed": [111, 82, 29, 37], "audio-volume-muted": [102, 171, 48, 48], "close": [417, 231, 20, 20], "action_group_disabled": [452, 171, 33, 48], "vkeyboard_background": [2, 221, 64, 64], "checkbox_off": [331, 87, 32, 32], "tab_disabled": [305, 253, 96, 32], "sliderh_background": [115, 132, 41, 37], "switch-button": [322, 291, 43, 32], "tree_closed": [439, 231, 20, 20], "bubble_btn_pressed": [435, 291, 32, 32], "selector_left": [134, 223, 55, 62], "filechooser_file": [174, 326, 64, 64], "checkbox_radio_disabled_off": [399, 87, 32, 32], "checkbox_radio_on": [196, 137, 32, 32], "checkbox_on": [365, 87, 32, 32], "button_pressed": [173, 82, 29, 37], "audio-volume-high": [464, 406, 48, 48], "audio-volume-low": [2, 171, 48, 48], "progressbar": [305, 227, 32, 24], "previous_normal": [487, 187, 19, 32], "separator": [504, 342, 5, 48], "filechooser_folder": [240, 326, 64, 64], "checkbox_radio_off": [467, 87, 32, 32], "textinput_active": [306, 326, 64, 64], "textinput": [438, 326, 64, 64], "player-play-overlay": [122, 395, 117, 115], "media-playback-pause": [202, 171, 48, 48], "sliderv_background": [41, 78, 37, 41], "ring": [354, 402, 108, 108], "bubble_arrow": [487, 175, 16, 10], "slider_cursor_disabled": [352, 171, 48, 48], "checkbox_disabled_off": [469, 291, 32, 32], "action_group_down": [2, 121, 33, 48], "spinner_disabled": [204, 82, 29, 37], "splitter_disabled_h": [106, 123, 32, 7], "bubble": [107, 325, 65, 65], "media-playback-start": [252, 171, 48, 48], "vkeyboard_disabled_key_normal": [434, 137, 32, 32], "overflow": [230, 137, 32, 32], "tree_opened": [461, 231, 20, 20], "action_item": [339, 227, 24, 24], "bubble_btn": [401, 291, 32, 32], "audio-volume-medium": [52, 171, 48, 48], "action_group": [37, 121, 33, 48], "spinner_pressed": [266, 82, 29, 37], "filechooser_selected": [2, 392, 118, 118], "tab": [403, 253, 96, 32], "action_bar": [158, 133, 36, 36], "action_view": [365, 227, 24, 24], "tab_btn": [332, 137, 32, 32], "switch-background": [192, 291, 83, 32], "splitter_disabled_down_h": [72, 123, 32, 7], "action_item_down": [367, 291, 32, 32], "switch-background_disabled": [107, 291, 83, 32], "textinput_disabled": [241, 399, 111, 111], "splitter_grip_h": [483, 239, 26, 12]}} -------------------------------------------------------------------------------- /deterministic.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | from PyInstaller.utils.hooks import collect_data_files, collect_submodules 4 | 5 | 6 | # see https://github.com/pyinstaller/pyinstaller/issues/2005 7 | hiddenimports = [] 8 | #hiddenimports += collect_submodules('trezorlib') 9 | #hiddenimports += collect_submodules('btchip') 10 | #hiddenimports += collect_submodules('keepkeylib') 11 | 12 | datas = [ 13 | ('lib/wordlist/english.txt', 'uwallet/wordlist'), 14 | ('plugins', 'uwallet_plugins'), 15 | ] 16 | #datas += collect_data_files('trezorlib') 17 | #datas += collect_data_files('btchip') 18 | #datas += collect_data_files('keepkeylib') 19 | 20 | # We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports 21 | a = Analysis(['uwallet', 22 | 'gui/qt/main_window.py', 23 | 'gui/text.py', 24 | 'lib/util.py', 25 | 'lib/wallet.py', 26 | 'lib/simple_config.py', 27 | 'lib/bitcoin.py', 28 | 'lib/dnssec.py', 29 | 'lib/commands.py', 30 | 'plugins/cosigner_pool/qt.py', 31 | 'plugins/email_requests/qt.py', 32 | 'plugins/trezor/client.py', 33 | 'plugins/trezor/qt.py', 34 | 'plugins/keepkey/qt.py', 35 | 'plugins/ledger/qt.py', 36 | #'packages/requests/utils.py' 37 | ], 38 | datas=datas, 39 | #pathex=['lib', 'gui', 'plugins'], 40 | hiddenimports=hiddenimports, 41 | hookspath=[]) 42 | 43 | 44 | # http://stackoverflow.com/questions/19055089/pyinstaller-onefile-warning-pyconfig-h-when-importing-scipy-or-scipy-signal 45 | for d in a.datas: 46 | if 'pyconfig' in d[0]: 47 | a.datas.remove(d) 48 | break 49 | 50 | # hotfix for #3171 (pre-Win10 binaries) 51 | a.binaries = [x for x in a.binaries if not x[1].lower().startswith(r'c:\windows')] 52 | 53 | pyz = PYZ(a.pure) 54 | 55 | 56 | ##### 57 | # "standalone" exe with all dependencies packed into it 58 | 59 | #options = [ ('v', None, 'OPTION')] - put this in the following exe list to debug and turn console=true 60 | 61 | exe_standalone = EXE( 62 | pyz, 63 | a.scripts, 64 | a.binaries, 65 | a.datas, 66 | name="uwallet", 67 | debug=False, 68 | strip=None, 69 | upx=False, 70 | icon='uwallet.ico', 71 | console=False) 72 | # console=True makes an annoying black box pop up, but it does make Electrum output command line commands, with this turned off no output will be given but commands can still be used 73 | 74 | exe_portable = EXE( 75 | pyz, 76 | a.scripts, 77 | a.binaries, 78 | a.datas, 79 | name="uwallet-portable.exe", 80 | debug=False, 81 | strip=None, 82 | upx=False, 83 | icon='uwallet.ico', 84 | console=False) 85 | 86 | ##### 87 | # exe and separate files that NSIS uses to build installer "setup" exe 88 | 89 | exe_dependent = EXE( 90 | pyz, 91 | a.scripts, 92 | exclude_binaries=True, 93 | name="uwallet", 94 | debug=False, 95 | strip=None, 96 | upx=False, 97 | icon='uwallet.ico', 98 | console=False) 99 | 100 | coll = COLLECT( 101 | exe_dependent, 102 | a.binaries, 103 | a.zipfiles, 104 | a.datas, 105 | strip=None, 106 | upx=True, 107 | debug=False, 108 | icon='uwallet.ico', 109 | console=False, 110 | name='uwallet') 111 | -------------------------------------------------------------------------------- /lib/contacts.py: -------------------------------------------------------------------------------- 1 | # Electrum - Lightweight Bitcoin Client 2 | # Copyright (c) 2015 Thomas Voegtlin 3 | # -*- coding: utf-8 -*- 4 | # Permission is hereby granted, free of charge, to any person 5 | # obtaining a copy of this software and associated documentation files 6 | # (the "Software"), to deal in the Software without restriction, 7 | # including without limitation the rights to use, copy, modify, merge, 8 | # publish, distribute, sublicense, and/or sell copies of the Software, 9 | # and to permit persons to whom the Software is furnished to do so, 10 | # subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be 13 | # included in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | 24 | import sys 25 | import re 26 | import dns 27 | import bitcoin 28 | import dnssec 29 | from util import StoreDict, print_error 30 | from i18n import _ 31 | 32 | 33 | class Contacts(StoreDict): 34 | 35 | def __init__(self, config): 36 | StoreDict.__init__(self, config, 'contacts') 37 | # backward compatibility 38 | for k, v in self.items(): 39 | _type, n = v 40 | if _type == 'address' and bitcoin.is_address(n): 41 | self.pop(k) 42 | self[n] = ('address', k) 43 | 44 | 45 | def resolve(self, k): 46 | if bitcoin.is_address(k): 47 | return { 48 | 'address': k, 49 | 'type': 'address' 50 | } 51 | if k in self.keys(): 52 | _type, addr = self[k] 53 | if _type == 'address': 54 | return { 55 | 'address': addr, 56 | 'type': 'contact' 57 | } 58 | out = self.resolve_openalias(k) 59 | if out: 60 | address, name, validated = out 61 | return { 62 | 'address': address, 63 | 'name': name, 64 | 'type': 'openalias', 65 | 'validated': validated 66 | } 67 | raise Exception("Invalid Bitcoin address or alias", k) 68 | 69 | def resolve_openalias(self, url): 70 | # support email-style addresses, per the OA standard 71 | url = url.replace('@', '.') 72 | records, validated = dnssec.query(url, dns.rdatatype.TXT) 73 | prefix = 'btc' 74 | for record in records: 75 | string = record.strings[0] 76 | if string.startswith('oa1:' + prefix): 77 | address = self.find_regex(string, r'recipient_address=([A-Za-z0-9]+)') 78 | name = self.find_regex(string, r'recipient_name=([^;]+)') 79 | if not name: 80 | name = address 81 | if not address: 82 | continue 83 | return address, name, validated 84 | 85 | def find_regex(self, haystack, needle): 86 | regex = re.compile(needle) 87 | try: 88 | return regex.search(haystack).groups()[0] 89 | except AttributeError: 90 | return None 91 | 92 | -------------------------------------------------------------------------------- /gui/qt/qrwindow.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Electrum - lightweight Bitcoin client 4 | # Copyright (C) 2014 Thomas Voegtlin 5 | # 6 | # Permission is hereby granted, free of charge, to any person 7 | # obtaining a copy of this software and associated documentation files 8 | # (the "Software"), to deal in the Software without restriction, 9 | # including without limitation the rights to use, copy, modify, merge, 10 | # publish, distribute, sublicense, and/or sell copies of the Software, 11 | # and to permit persons to whom the Software is furnished to do so, 12 | # subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be 15 | # included in all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | 26 | import re 27 | import platform 28 | from decimal import Decimal 29 | from urllib import quote 30 | 31 | from PyQt4.QtGui import * 32 | from PyQt4.QtCore import * 33 | import PyQt4.QtCore as QtCore 34 | import PyQt4.QtGui as QtGui 35 | 36 | from uwallet_gui.qt.qrcodewidget import QRCodeWidget 37 | from uwallet.i18n import _ 38 | 39 | if platform.system() == 'Windows': 40 | MONOSPACE_FONT = 'Lucida Console' 41 | elif platform.system() == 'Darwin': 42 | MONOSPACE_FONT = 'Monaco' 43 | else: 44 | MONOSPACE_FONT = 'monospace' 45 | 46 | column_index = 4 47 | 48 | class QR_Window(QWidget): 49 | 50 | def __init__(self, win): 51 | QWidget.__init__(self) 52 | self.win = win 53 | self.setWindowTitle('UWalletLite - '+_('Payment Request')) 54 | self.setMinimumSize(800, 250) 55 | self.address = '' 56 | self.label = '' 57 | self.amount = 0 58 | self.setFocusPolicy(QtCore.Qt.NoFocus) 59 | self.setStyleSheet("background-color:white;") 60 | main_box = QHBoxLayout() 61 | 62 | self.qrw = QRCodeWidget() 63 | main_box.addWidget(self.qrw, 1) 64 | 65 | vbox = QVBoxLayout() 66 | main_box.addLayout(vbox) 67 | 68 | self.address_label = QLabel("") 69 | #self.address_label.setFont(QFont(MONOSPACE_FONT)) 70 | vbox.addWidget(self.address_label) 71 | 72 | self.label_label = QLabel("") 73 | vbox.addWidget(self.label_label) 74 | 75 | self.amount_label = QLabel("") 76 | vbox.addWidget(self.amount_label) 77 | 78 | vbox.addStretch(1) 79 | self.setLayout(main_box) 80 | 81 | 82 | def set_content(self, address, amount, message, url): 83 | address_text = "%s" % address if address else "" 84 | self.address_label.setText(address_text) 85 | if amount: 86 | amount = self.win.format_amount(amount) 87 | amount_text = "%s %s " % (amount, self.win.base_unit()) 88 | else: 89 | amount_text = '' 90 | self.amount_label.setText(amount_text) 91 | label_text = "%s" % message if message else "" 92 | self.label_label.setText(label_text) 93 | self.qrw.setData(url) 94 | -------------------------------------------------------------------------------- /pubkeys/kyuupichan.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v1 3 | 4 | mQGiBD7CrZkRBADjXAk5ONxSGO01JMqUjwQFZAwGynWcEVF093g6SezPXsMN/HEP 5 | PoxndqVhtOOI5M7ZezusYzUEH4RJNEDc/JmrQh9d6Q+CanaLuOn3c84XvgKVAmID 6 | ogMrxeQ7biCn9NyZf6EjqP4QGBwWQdsrb2CvK+NO8h2oLo2Aycv+hciDlwCgoLPl 7 | scZLBvfwNRdcajG45g5NfmMEANqZLvax6e5Wr9lHpfZFQch3ai5hP5dDetA0jeR4 8 | nzeWdbwD4Aph3AXrZt4c64qwkSi3ElS5UKzNRsO6APF3+COR1VXJHyN5ve6jxpuY 9 | 69zq9ZM3KwYHztoKfHlXJqTtOx9U0DSK/xwphI+Q1neMBr3RyL8muKQvlESNuN+3 10 | n47+A/9+5pWs8m060jRcs7W1zAYOBCv5fb3Zeot6TgkprDrrRFitcyXbB6k1zyMh 11 | iqUMce5Ht785AWYZuCTjvbxJ2yuT37s26OswyXDoBGwwcPgaFyEO3SBRGaoxvTrW 12 | NQ+gpiW8ILjXCBoJdgPcOlxjj+mhRp3OQ1TJZojMBgio56IWbbQtTmVpbCBCb290 13 | aCAoYWtpaGFiYXJhKSA8bmVpbEBkYWlrb2t1eWEuY28udWs+iFkEExECABkFAj7C 14 | rZkECwcDAgMVAgMDFgIBAh4BAheAAAoJEHV+VfRE0xInLkgAn0c/8n77dUl71F7q 15 | aMolNZ8KmxZcAJ93ESJQ6UWhnyUxHm8l4OFdXXu4RohGBBMRAgAGBQI+0it6AAoJ 16 | EMXAxcchjRjXF7MAoM88e9oNMPdUpeu/hUMmZw6AL+AqAKCPgRmICbdH2fQYR99E 17 | Lyw1wGwii4hGBBMRAgAGBQI+0jp/AAoJEDiaVjzCcqEmYpoAn1kwGm12ovyG4PwS 18 | 5rN+Z46FE5wUAJ9tQkDrxF4yhTkCU6KVOje/tufBdohGBBMRAgAGBQI+0la2AAoJ 19 | ELfOmxk3oYfG1yoAoIhyQvVnzA3AUPmpJZP/sfCqzRrNAJ9LmVN+b63BfgyXkJbu 20 | K0w792EDS4hGBBIRAgAGBQI+0pzOAAoJECIYyB6OfAP/1G0An0XtPhXIf+Z8VHrb 21 | u9d+e7tJodQ1AJ4v1rH9v/NopQtHdcnxFvI9alEPH4hGBBMRAgAGBQI+06DGAAoJ 22 | EC4s9nt3lqYLLuoAnRm+RnRj3RJJxE42yTzLP7GslzazAKDO3CHEtgPbj8DseXKS 23 | 2jiwi8g9RYhGBBMRAgAGBQI+1BTBAAoJEElFpTfXe0P7LQcAn23wIm2Pg6nO+dBO 24 | 8oBrmARV0+ImAKCcO5k/5ByeqUMHy7lKx3HVzOET8YhGBBIRAgAGBQI+1K4rAAoJ 25 | ENGVGa1MfyvuLTIAoITJh0RbLqqsoyKMIPA3DWWs8iUOAJ4g4HO/rL4foavPOyzn 26 | BDaHoDBJ1IhGBBIRAgAGBQI+1Y1MAAoJEFC7KXQtWafSrP8An17bXzC3iyywvnC1 27 | W7RfvjohMzzQAJ9v6BJn9xRORSIHY4ifqfU6BPtVUIhGBBMRAgAGBQI+1M8FAAoJ 28 | EEXlkGj5G7efrxoAoIKXAOjFCrxhlNSIFUpDkgtxaPfyAJ9LYM88b7Jpz/octbEH 29 | 6o6lx8B5lIhGBBMRAgAGBQI+1lmrAAoJEFI0hF3yuSD1WDgAn0CjIP3eHGFoNTMF 30 | BTefl5KQWFjlAJ0bt40eHF2hp46HKS6Bbl2p09FFyohGBBMRAgAGBQI+1mfTAAoJ 31 | EG4Dj17go4N34MMAn0GSwAMasmCfBUhFLRxy4uYSy2mhAKDZ2uklcaBauLQyjFoL 32 | M1NMhMCJ/ohGBBMRAgAGBQI+1r14AAoJECTxPj/mjACSpH8AoIxJsUJr3iUoYCzZ 33 | 0220/CbBO9kyAJ49dc3iiBArycmnGjbkSLnktpiqwYhGBBIRAgAGBQI+1itWAAoJ 34 | ECn45GVniJZfNQoAoIfjMXEsjsnaHI83sNdrBmN4knQDAJ9NAsEIxzaGFfQmc33E 35 | MhxRpo2cE4hGBBMRAgAGBQI+2BXeAAoJEFlRJ0yBj+NA09QAoLN99g2hp7h7onqW 36 | MIc4T9WYWKgiAKCD/4r1f7vrqR/sSYKHrahI5PbysYhGBBARAgAGBQI+3GFvAAoJ 37 | EGcvIifCwHAobfQAn01wzHEdfIeWy1X44PF3EDA1izBAAJ9oLQ3ES3Tv7R1rPPlo 38 | rSCPocO324hGBBARAgAGBQI+4mQfAAoJEHFzfab4xNFPBgUAoOk8J3Xe3ko2SPjM 39 | d84JfXbIijW+AKD5b7NfeVAkz9mNhYePqU53SpQvQYhGBBMRAgAGBQI+2U6qAAoJ 40 | EFHGMyB5fcdf47MAnAprssI6tke7MQuiqf+xOPO2XxS7AKDOn8YOQDEJtlm8qRW/ 41 | SGG0DJ5MBIhGBBMRAgAGBQI+44T5AAoJEN5HUcxjjSIaSpcAn0pWC2xioUmTdjnJ 42 | OVJPV6m3h7TYAKCm3tIRQ/n1e3+SjrZ6B6u9arKRiYhGBBMRAgAGBQI/ASS3AAoJ 43 | EDC3rnBH3fqFUAoAnA5k7w/Y6FCkgSBDqjC8Mz9e+DQ7AJ4npy3wXIW6gk9UD484 44 | 6CFTk7rwHIhGBBMRAgAGBQI/ATFzAAoJEF1s/WZ+hdAzbf4AoMjm6YMw4TfxTASb 45 | 85EfShS6LdH5AJ4zDq7QAvGkPjTY2JLlwHph3afyHIhGBBMRAgAGBQI/K8oEAAoJ 46 | EHx6uUUZG8DsJYQAn0VwLcYxa3f7Ovk6m+xJUzcpcMMIAJ9F0JRKAS2w//tkMPab 47 | 8YZ+sYECv7QhTmVpbCBCb290aCA8a3l1dXBpY2hhbkBnbWFpbC5jb20+iGIEExEC 48 | ACIFAk/485MCGyMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEHV+VfRE0xIn 49 | mTYAnid43IhUSJp4f35yw7V48uWI/PHiAJ9O0+8kcnVukXQOLpKgQekH8GIevbkB 50 | DQQ+wq2lEAQAlZjNXxfrUYxJ8ewd0LIGmig3HSKjREHc7vuN76P56KzH7pdEENaa 51 | rhY7XggGQ826MyFgkpRp7LLNR8LNJb6JR4tPeeUFpS6Xyz2tj3UHIkLTbLeub3em 52 | W3/oinoO3bbzuZ2hVx2GyR2yVlM5hbjUFayne0D5KfSHzCEJ5SLMn0cABAsD/i6c 53 | 62u9tAkMRsrWAjcd8z5PLf+Gp5MuviE396gP0CCdcwo3K7RAYcUyiJRObv/zktbN 54 | cE+ZwYclB5zJT7kiJlaDmMfwyHBDYond4bV5VKeveGcr8Xy/cEh+cN7CceWoPC8P 55 | wjcnylxM5UZHMrTBlaoLqKvNq/JZk1sDAau/9g9kiEYEGBECAAYFAj7CraUACgkQ 56 | dX5V9ETTEidutgCdERuNxOlRNFORwpSVJcvOgeItgMsAn3RblJxgwKC8S+z1NpV/ 57 | q9K8C944 58 | =MRTd 59 | -----END PGP PUBLIC KEY BLOCK----- 60 | --------------------------------------------------------------------------------