Coder Social home page Coder Social logo

trezor / python-trezor Goto Github PK

View Code? Open in Web Editor NEW
203.0 37.0 193.0 3.15 MB

:snake: Don't use this repo, use the new monorepo instead:

Home Page: https://github.com/trezor/trezor-firmware

License: GNU Lesser General Public License v3.0

Shell 0.25% Python 99.56% Makefile 0.16% Nix 0.04%
trezor python cli library bitcoin

python-trezor's Introduction

python-trezor

image repology image

Python library and commandline client for communicating with TREZOR Hardware Wallet

See https://trezor.io for more information

Install

Python-trezor requires Python 3.5 or higher, and libusb 1.0. The easiest way to install it is with pip. The rest of this guide assumes you have a working pip; if not, you can refer to this guide.

Quick installation

On a typical Linux / Mac / BSD system, you already have all you need. Install trezor with:

pip3 install --upgrade setuptools
pip3 install trezor

On Windows, you also need to install libusb and the appropriate drivers. This is, unfortunately, a topic bigger than this README.

Older Trezor One support

If your Trezor One is on firmware 1.6.3 or older, you will need HIDAPI support for it to be recognized. That requires additional packages.

Debian / Ubuntu

On a Debian or Ubuntu based system, you can install these:

sudo apt-get install python3-dev python3-pip cython3 libusb-1.0-0-dev libudev-dev

Windows

On a Windows based system, you can install these (for more info on choco, refer to this):

choco install vcbuildtools python3 protoc
refreshenv
pip3 install protobuf

When installing the trezor library, you need to specify that you want hidapi:

pip3 install --upgrade setuptools
pip3 install trezor[hidapi]

Ethereum support

Ethereum requires additional python packages. Instead of pip3 install trezor, specify pip3 install trezor[ethereum].

You can combine it with the above, to get both HIDAPI and Ethereum support:

pip3 install trezor[ethereum,hidapi]

FreeBSD

On FreeBSD you can install the packages:

pkg install security/py-trezor

or build via ports:

cd /usr/ports/security/py-trezor
make install clean

Building from source

Sometimes you might need to install the latest-and-greatest unreleased version straight from GitHub. You will need some prerequisites first:

sudo apt-get install protobuf-compiler protobuf-dev
pip3 install protobuf

If you just need to install the package, you can use pip again:

pip3 install git+https://github.com/trezor/python-trezor

If you want to work on the sources, make a local clone:

git clone https://github.com/trezor/python-trezor
cd python-trezor
python3 setup.py prebuild
python3 setup.py develop

Command line client (trezorctl)

The included trezorctl python script can perform various tasks such as changing setting in the Trezor, signing transactions, retrieving account info and addresses. See the docs/ sub folder for detailed examples and options.

NOTE: An older version of the trezorctl command is available for Debian Stretch (and comes pre-installed on Tails OS).

Python Library

You can use this python library to interact with a Bitcoin Trezor and use its capabilities in your application. See examples here in the tools/ sub folder.

PIN Entering

When you are asked for PIN, you have to enter scrambled PIN. Follow the numbers shown on TREZOR display and enter the their positions using the numeric keyboard mapping:

7 8 9
4 5 6
1 2 3

Example: your PIN is 1234 and TREZOR is displaying the following:

2 8 3
5 4 6
7 9 1

You have to enter: 3795

Contributing

Python-trezor pulls coins info and protobuf messages from trezor-common repository. If you are developing new features for Trezor, you will want to start there. Once your changes are accepted to trezor-common, you can make a PR against this repository. Don't forget to update the submodule with:

git submodule update --init --remote

Then, rebuild the protobuf messages and get coins.json by running:

python3 setup.py prebuild

To get support for BTC-like coins, these steps are enough and no further changes to the library are necessary.

python-trezor's People

Contributors

admin-slush avatar alepop avatar antonkolesnyk avatar arachnid avatar brianddk avatar dekoza avatar hackmod avatar jhoenicke avatar jonathancross avatar jpochyla avatar karelbilek avatar matejcik avatar matheusd avatar mdance avatar mrmebelman avatar mruddy avatar nelisky avatar peterzen avatar ph4r05 avatar prusnak avatar refi93 avatar romanz avatar saleemrashid avatar slush0 avatar strmci avatar tarpas avatar teknico avatar timthelion avatar tsusanka avatar zulucrypto avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-trezor's Issues

Include the git commit from what protobuf code is generated from

There are no information what commit the protobuf messages are compiled from, this makes it hard to rebuild the the correct protobuf messages from source.

Sugestion, include something like this in build_pb.sh
git rev-parse HEAD > $CURDIR/.trezor-protob-version.txt

protobuf version fallback

When using python-trezor 0.6.10 on trisquel belenos, I get the following error:

File "/usr/lib/python2.7/dist-packages/trezorlib/client.py", line 7, in
import mapping
File "/usr/lib/python2.7/dist-packages/trezorlib/mapping.py", line 1, in
import messages_pb2 as proto
File "/usr/lib/python2.7/dist-packages/trezorlib/messages_pb2.py", line 10, in
from google.protobuf import symbol_database as _symbol_database
ImportError: cannot import name symbol_database

The packaged version of protobuf is: 2.5.0-9ubuntu1

Is there a possible fallback other than installing protobuf from pip?
I prefer to have as much as possible from apt.
That would mean I would have to maintain a newer version of protobuf in my ppa.

If the symbol_database functionality is not always needed, would graceful degradation be an option?

python-trezor can't detect a device in bootloader mode for macOS

The macOS successfully detected the device(as a composite device):

Composite Device:

  Product ID:	0x0001
  Vendor ID:	0x534c
  Version:	1.00
  Serial Number:	SatoshiLabs
  Manufacturer:	TREZOR
  Location ID:	0x14200000

The device successfully entered the bootloader mode, which there is a screen shows the Serial No. and the loader version(1.3.0)

However, the trezorctl's get_transport function can't get the device. The len of HidTransport.enumerate() is 0, and the get_transport raised a "Device not found" error.

The device can be detected when is not in bootloader mode.

/trezorlib/qt/pinmatrix.py#L20 broken on OSX

After successfully installing cython and python-trezor under OSX, all ./cmdtr.py change_pin does not work

https://github.com/trezor/python-trezor/blob/master/trezorlib/qt/pinmatrix.py#L20

The trezor's screen displays "Do you really want to change the current PIN?" Confirm
then on Trezor "Please then the current PIN:" pin matrix

However the command line defaults to "Please enter old PIN:" (which does not work even if the correct PIN in typed in). There is no QT window to enter the PIN.

I don't know if it has something to do this the commented out code here
https://github.com/trezor/python-trezor/blob/master/cmdtr.py#L314

I believe this is a bug as my QT seems to work fine, I can use electrum+trezor plugin, and can enter my passphrase and PIN into electrum successfully.

encfs_aes_getpass.py generates short passwords sometimes with a new lines

I made a small change to the os.environment for testing

  rootdir = os.environ['HOME']

I don't know if passw is supposed to be 32 bytes every time

        #32 bytes, good for AES
    trezor_entropy = client.get_entropy(32)
    urandom_entropy = os.urandom(32)
    passw = hashlib.sha256(trezor_entropy + urandom_entropy).digest()

    if len(passw) != 32:
        raise Exception("32 bytes password expected")

But the output of print passw from the script regenerating the password.dat

Please confirm action on your device.
???z?L???r???X?|?S??uJ???

Please confirm action on your device.
?:hh?9!?a??]N?Rb

Please confirm action on your device.
IC5 ^???4k?c
            ?`?j?????I???bPI

Please confirm action on your device.
??<?2??\A?6???1??ห‚????#t6??M

Please confirm action on your device.
??
  0
??????R@4??ืผ??i?1??9[?Y?

Please confirm action on your device.
?
 ??c??pNu>Kn??XB?t??~???+_?F?

Please confirm action on your device.
Jv?_????ฯŽ??/?qiX?O]?
?>                  ??(?

Please confirm action on your device.
S?????g?+d??Tฬ“?
              ?1?Y?P?I?

Please confirm action on your device.
01'=1%?[~W?ฬด?z}TC?A$??&O
                       Q?A

Please confirm action on your device.
???F?f?zl?8<?2??I??E??%???

Please confirm action on your device.
???6^8??@????g?l?b??h??xu?Co

Should the length of passw vary ?
Should it contain special characters such as ืผ ?ฬด Tฬ“ ฯŽ ?
Should it have carriage returns and spaces (3rd example has both), and if so will that break it's use as an encfs --extpass input ?
Why is the string so short with so many repeats of "?"

v.0.6.10 problems connecting

Just updated my python-trezor library from 0.6.6 to 0.6.10 - then started to have communication problem using Electrum (version 2.5.4).

File "/Library/Python/2.7/site-packages/trezor-0.6.10-py2.7.egg/trezorlib/transport_hid.py", line 54, in enumerate
raise Exception("Unknown USB interface number: %d" % interface_number)
Exception: Unknown USB interface number: -1

Same error comes up when using the example code in the repository Readme file. Therefore, problem is not with Electrum.

Reverted back to v.0.6.6 and it worked again.

python-trezor-0.7.13 crashes electrum-2.8.2

0.7.12 did not trigger this issue, I am surprised since there was only a bump in the patch number.

$ electrum 
"sni-qt/15815" WARN  23:53:25.727 void StatusNotifierItemFactory::connectToSnw() Invalid interface to SNW_SERVICE 
Traceback (most recent call last):
  File "/usr/bin/electrum", line 379, in <module>
    d.init_gui(config, plugins)
  File "/usr/lib/python2.7/site-packages/electrum/daemon.py", line 282, in init_gui
    self.gui.main()
  File "/usr/lib/python2.7/site-packages/electrum_gui/qt/__init__.py", line 199, in main
    if not self.start_new_window(path, self.config.get('url')):
  File "/usr/lib/python2.7/site-packages/electrum_gui/qt/__init__.py", line 156, in start_new_window
    wallet = self.daemon.load_wallet(path, None)
  File "/usr/lib/python2.7/site-packages/electrum/daemon.py", line 219, in load_wallet
    wallet = Wallet(storage)
  File "/usr/lib/python2.7/site-packages/electrum/wallet.py", line 1756, in __new__
    wallet = WalletClass(storage)
  File "/usr/lib/python2.7/site-packages/electrum/wallet.py", line 1563, in __init__
    Deterministic_Wallet.__init__(self, storage)
  File "/usr/lib/python2.7/site-packages/electrum/wallet.py", line 1408, in __init__
    Abstract_Wallet.__init__(self, storage)
  File "/usr/lib/python2.7/site-packages/electrum/wallet.py", line 103, in __init__
    self.load_keystore()
  File "/usr/lib/python2.7/site-packages/electrum/wallet.py", line 1530, in load_keystore
    self.keystore = load_keystore(self.storage, 'keystore')
  File "/usr/lib/python2.7/site-packages/electrum/keystore.py", line 617, in load_keystore
    k = hardware_keystore(d)
  File "/usr/lib/python2.7/site-packages/electrum/keystore.py", line 601, in hardware_keystore
    return constructor(d)
  File "/usr/lib/python2.7/site-packages/electrum/plugins.py", line 169, in dynamic_constructor
    return self.get_plugin(name).keystore_class(d)
  File "/usr/lib/python2.7/site-packages/electrum/plugins.py", line 177, in get_plugin
    self.load_plugin(name)
  File "/usr/lib/python2.7/site-packages/electrum/plugins.py", line 102, in load_plugin
    plugin = p.Plugin(self, self.config, name)
  File "/usr/lib/python2.7/site-packages/electrum_plugins/trezor/trezor.py", line 16, in __init__
    import client
  File "/usr/lib/python2.7/site-packages/electrum_plugins/trezor/client.py", line 1, in <module>
    from trezorlib.client import proto, BaseClient, ProtocolMixin
  File "/usr/lib/python2.7/site-packages/trezorlib/client.py", line 34, in <module>
    from . import mapping
  File "/usr/lib/python2.7/site-packages/trezorlib/mapping.py", line 19, in <module>
    from . import messages_pb2 as proto
  File "/usr/lib/python2.7/site-packages/trezorlib/messages_pb2.py", line 17, in <module>
    from . import types_pb2 as types__pb2
  File "/usr/lib/python2.7/site-packages/trezorlib/types_pb2.py", line 26, in <module>
    dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,])
TypeError: __init__() got an unexpected keyword argument 'syntax'

allow core entropy entry through pin pad

Rather than trust host computer for source of entropy, allow user to generate entropy via alternative means (eg diceware, flipping coins, or however).

The entropy would be entered via the scrambled pin mechanism. If we just use digits 1-8, 256 bits would be 32 entries, or 128 bits would be 16. A bit of a pain, but not too bad. The entropy entry could be repeated to ensure no mistakes.

(For stylepoints, trezor could add a "hexadecimal pin pad" to slyly hint that only 3l1te experts should be using this feature.)

After the entropy entry the 3*x word passphrase would be calculated and displayed to user as usual. The user could can now either

-- throw away the entropy seed, and do future restores with current mechanism
-- or keep the entropy seed, and do future restores with extra secure mechanism of re-entering same entropy via keypad, so even if host computer is compromised the original entropy is maintained, and we don't leak down to 24 factorial, or however many if an attacker gains a scrambled word list.

As a side note on naming, I would refer to "core entropy seed" described above, versus "stretched entropy seed" which is encoded by the pass phrase that is usually referred to as the seed.

For everyone who has ever wondered if /dev/random is back doored on their system, the trezor now presents an irresistible value proposition.

Replace hidapi dependency with libusb1

hidapi development has stalled and we don't really need HID features.

The following example script works:

#!/usr/bin/python

import usb1

VENDOR_ID=0x534c
PRODUCT_ID=0x0001
IFACE=0

with usb1.USBContext() as context:

    device = None
    for d in context.getDeviceIterator(skip_on_error=True):
        if d.getVendorID() == VENDOR_ID and d.getProductID() == PRODUCT_ID:
            device = d
            break

    if device is None:
        raise Exception('Device not found')
    print(device)

    handle = device.open()
    if handle is None:
        raise Exception('Cannot open device')
    print(handle)

    if handle.kernelDriverActive(IFACE):
        handle.detachKernelDriver(IFACE)

    handle.claimInterface(IFACE)

    written = handle.interruptWrite(0x01, b'?##' + b'\x00' * 61)
    print(written)

    read = handle.interruptRead(0x81, 64)
    print(read)

    handle.releaseInterface(IFACE)
    handle.close()

Not able to run the tests

I am getting this error when I try to run the tests on master on Fedora 25:

$ python2 setup.py test
running test
running egg_info
writing requirements to trezor.egg-info/requires.txt
writing trezor.egg-info/PKG-INFO
writing top-level names to trezor.egg-info/top_level.txt
writing dependency_links to trezor.egg-info/dependency_links.txt
reading manifest file 'trezor.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'trezor.egg-info/SOURCES.txt'
running build_ext
Traceback (most recent call last):
  File "setup.py", line 45, in <module>
    'Operating System :: MacOS :: MacOS X',
  File "/usr/lib64/python2.7/distutils/core.py", line 151, in setup
    dist.run_commands()
  File "/usr/lib64/python2.7/distutils/dist.py", line 953, in run_commands
    self.run_command(cmd)
  File "/usr/lib64/python2.7/distutils/dist.py", line 972, in run_command
    cmd_obj.run()
  File "/usr/lib/python2.7/site-packages/setuptools/command/test.py", line 172, in run
    self.run_tests()
  File "/usr/lib/python2.7/site-packages/setuptools/command/test.py", line 193, in run_tests
    testRunner=self._resolve_as_ep(self.test_runner),
  File "/usr/lib64/python2.7/unittest/main.py", line 94, in __init__
    self.parseArgs(argv)
  File "/usr/lib64/python2.7/unittest/main.py", line 149, in parseArgs
    self.createTests()
  File "/usr/lib64/python2.7/unittest/main.py", line 158, in createTests
    self.module)
  File "/usr/lib64/python2.7/unittest/loader.py", line 130, in loadTestsFromNames
    suites = [self.loadTestsFromName(name, module) for name in names]
  File "/usr/lib64/python2.7/unittest/loader.py", line 91, in loadTestsFromName
    module = __import__('.'.join(parts_copy))
ImportError: No module named tests

Bug on mac

With the new firmware, python-trezor is not usable on mac, because we are using unpatched hidapi

see

signal11/hidapi#288

so neither can users use electrum (and electrum dash, etc).

Once the hidapi is patched everything should work again

Multisig examples?

It will be great to have some examples or a guide on how to 'be part' of a multisig address and how to sign a multisig transaction with this lib

Thanks

Share account between trezor and hw1

Is it possible to share a trezor account with hw1?
Say I have a trezor with account#1 and account#2 and I want to share the account#2 with HW1.
How would I get the seed that I need to initialize the HW1?
I know pycoin has some key derivation functions exposed, but I don't know how much format conversion is needed at different steps.

master public key

How do I get the master public key (xpub) from my accounts? When I use get_public_node(bip32_path) I get the public_key and and the cain_code I know I have to combine them somehow. Or is there an easier way?
Thanks

Thanks

Thanks for writing and having this tool open-sourced.

Using MyEtherWallet as a client to TREZOR to manage Ethereum is a pretty poor experience for several reasons. First of all, it requires to have a Chrome extension. Then, wallet.trezor.io must be functioning properly, as well as myetherwallet.com (except if you want to run a TLS server for an HTML page). And finally, the UX is not great/confusing.

I do not really want to deal with trezor-chrome-extension, connect.js, trezor.js, any similar JS-based application, or run a daemon such as trezord to simply be able to manage an USB device and sign transactions either. It seems overkill. Additionally, it does not seem like the repositories are too active..

At least, this Python client is pretty clear, fairly low-level, is quite contained and dependency free!
I feel like there is a strong need for a solid CLI client for TREZOR AND Ethereum.

OSX Yosemite protobuf issue

After installing with 'sudo python setup.py install' and running helloworld.py with Trezor attached:

Traceback (most recent call last):
File "./helloworld.py", line 3, in
from trezorlib.client import TrezorClient
File "/Users/user/src/python-trezor/trezorlib/client.py", line 7, in
import mapping
File "/Users/user/src/python-trezor/trezorlib/mapping.py", line 1, in
import messages_pb2 as proto
File "/Users/user/src/python-trezor/trezorlib/messages_pb2.py", line 4, in
from google.protobuf.internal import enum_type_wrapper
ImportError: No module named google.protobuf.internal

Install log is here, seems to pick the right protobuf version (2.5.0):
http://pastebin.com/qqw4tyGh

Exception: Unexpected magic characters

latest git trezorlib. Works sometime but later complain about magic characters. firmware 1.4.0, Mac OS X 10.10.5, Python 2.7.12 (homebrew)

$ trezor-agent [email protected]
Traceback (most recent call last):
  File "/usr/local/bin/trezor-agent", line 11, in <module>
    sys.exit(run_agent())
  File "/usr/local/lib/python2.7/site-packages/trezor_agent/__main__.py", line 124, in wrapper
    return func(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/trezor_agent/__main__.py", line 137, in run_agent
    with client_factory(curve=args.ecdsa_curve_name) as conn:
  File "/usr/local/lib/python2.7/site-packages/trezor_agent/client.py", line 20, in __init__
    client_wrapper = loader()
  File "/usr/local/lib/python2.7/site-packages/trezor_agent/factory.py", line 243, in load
    device_list.extend(device)
  File "/usr/local/lib/python2.7/site-packages/trezor_agent/factory.py", line 27, in _load_client
    connection = client_type(hid_transport(d))
  File "/usr/local/lib/python2.7/site-packages/trezorlib/client.py", line 361, in __init__
    self.init_device()
  File "/usr/local/lib/python2.7/site-packages/trezorlib/client.py", line 368, in init_device
    self.features = expect(proto.Features)(self.call)(proto.Initialize())
  File "/usr/local/lib/python2.7/site-packages/trezorlib/client.py", line 85, in wrapped_f
    ret = f(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/trezorlib/client.py", line 98, in wrapped_f
    return f(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/trezorlib/client.py", line 134, in call
    resp = self.call_raw(msg)
  File "/usr/local/lib/python2.7/site-packages/trezorlib/client.py", line 98, in wrapped_f
    return f(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/trezorlib/client.py", line 130, in call_raw
    return self.transport.read_blocking()
  File "/usr/local/lib/python2.7/site-packages/trezorlib/transport.py", line 68, in read_blocking
    data = self._read()
  File "/usr/local/lib/python2.7/site-packages/trezorlib/transport.py", line 128, in _read
    (msg_type, datalen, data) = self.parse_first(chunk)
  File "/usr/local/lib/python2.7/site-packages/trezorlib/transport.py", line 140, in parse_first
    raise Exception("Unexpected magic characters")
Exception: Unexpected magic characters

ideas?

Add some documentnation, please? :)

Hello,

I like the ideas behind Trezor and I want to explore the code,

but I don't really understand which github repo does what, and how are they related, and how is the code related to anything.

Karel

how should change_pin behave?

change_pin and reset_device -p are not accepting my pins. I tried pin1=1234 pin2=1234 and pin1=screenpos_1234 pin2=new_screenpos_1234. Also tried with the assumption of offset by 0. No luck. any advice?

python: xcb_io.c:179: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.

When I plug in the Trezor device, running Electrum, it crashes with the output given below.

I'm using it with Electrum 2.0.3, but I guess it is an issue with python-trezor. Electrum in watch-only mode works fine, I set up the Trezor account in there some time ago with an earlier release. Please let me know if you need more information.

I'm running OpenSuse 13.2, KDE 4.14.6. Installation of python-trezor and Electrum from Source went flawless.

QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap::scaleWidth: Pixmap is a null pixmap
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject::installEventFilter(): Cannot filter events for objects in a different thread.
QObject::installEventFilter(): Cannot filter events for objects in a different thread.
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::LabelEngine(0x1882260), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::LabelEngine(0x1882260), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::LabelEngine(0x1882260), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x1803710), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x1803710), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::LineEditEngine(0x1882380), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::LabelEngine(0x1882260), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x1803710), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x1803710), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::LineEditEngine(0x1882380), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::LabelEngine(0x1882260), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x189a070), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x189a070), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x182e060), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x189a070), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Oxygen::WidgetStateEngine(0x189a070), parent's thread is QThread(0x1272cb0), current thread is QThread(0x7fd85c0147e0)
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python: xcb_io.c:179: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Aborted

Invalid Pin when using encfs_aes_getpass.py

When I try to run encfs_aes_getpass.py, I get past it asking for a label for the new drive, and prompting the trezor device for entropy. It then asks me to "Please enter old PIN: " while the Trezor screen says "Please enter current PIN:". It is here that I am confused about how to enter my pin. If my password is 1234 and the trezor is displaying:

2 8 3
5 4 6
7 9 1

Which of these options would I enter?

  1. 9135
  2. 2835

I have tried both of the above methods, and both give me an Invalid PIN exception.

Add Python3 support

There's WIP in branch named "python3". Unfortunately I was unable to compile messages_pb2.py and types_pb2.py with python3 syntax yet, which looks like the last obstacle to get it running.

Is it possible to force trezor to watch specific path?

Might wrong place to ask, but can't find one anyway.
Let's say I want my trezor to watch path "44'/0'/0'/0/9999", when all previous addresses not used?
Is it possible with this api? How can I then send money from this address?

package / release

are there plans for a debian package of python-trezor?
If not, I might give it a try. But it would be best to have a released version to base it on.

electrum trezor plugin related:

e8f76eb introduces a problem in my electrum wallet (problem does not occur with previous commit b0e39b5):

To reproduce.

  • start electrum (using -w to open a trezor based wallet)
  • observe popup saying "could not connect to your TREZOR. Verify the calbe is connected and that no other application is iusing it. Try connect again?"

stdout says:

[DeviceMgr] scanning devices...

in later versions (tag v0.7.0) the behaviour in the gui is the same, but there seems to be an exception

[trezor] cannot connect at 0003:004b:00 'Plugin' object does not support indexing

finding the place in the code (trezor/plugin.py) and commenting out the catch to actually see the stacktrace reveals:

Traceback (most recent call last):
  File "/mnt/maui/home/nick/bitcoin/electrum/gui/qt/util.py", line 550, in run
    result = task.task()
  File "/mnt/maui/home/nick/bitcoin/electrum/plugins/trezor/plugin.py", line 138, in get_client
    client = devmgr.client_for_wallet(self, wallet, force_pair)
  File "/mnt/maui/home/nick/bitcoin/electrum/lib/plugins.py", line 399, in client_for_wallet
    return self.force_pair_wallet(plugin, wallet, devices)
  File "/mnt/maui/home/nick/bitcoin/electrum/lib/plugins.py", line 409, in force_pair_wallet
    info = self.select_device(wallet, plugin, devices)
  File "/mnt/maui/home/nick/bitcoin/electrum/lib/plugins.py", line 460, in select_device
    infos = self.unpaired_device_infos(wallet.handler, plugin, devices)
  File "/mnt/maui/home/nick/bitcoin/electrum/lib/plugins.py", line 446, in unpaired_device_infos
    client = self.create_client(device, handler, plugin)
  File "/mnt/maui/home/nick/bitcoin/electrum/lib/plugins.py", line 327, in create_client
    client = plugin.create_client(device, handler)
  File "/mnt/maui/home/nick/bitcoin/electrum/plugins/trezor/plugin.py", line 108, in create_client
    transport = self.HidTransport(pair)
  File "/usr/lib64/python2.7/site-packages/trezor-0.7.0-py2.7.egg/trezorlib/transport_hid.py", line 140, in HidTransport
    transport = path_to_transport(device[0])
TypeError: 'Plugin' object does not support indexing

not sure if this is electrum or python-trezor problem. Stopped digging at this point, will use v0.6.13 for now...

String overflow error when running helloword.py

The following error occurs when I enter in my PIN after running python helloworld.py
Traceback (most recent call last):
File "helloworld.py", line 33, in
main()
File "helloworld.py", line 27, in main
address = client.get_address('Bitcoin', bip32_path)
File "/home/chris/dev/python-trezor/trezorlib/client.py", line 70, in wrapped_f
ret = f(_args, *_kwargs)
File "/home/chris/dev/python-trezor/trezorlib/client.py", line 84, in wrapped_f
ret = f(_args, *_kwargs)
File "/home/chris/dev/python-trezor/trezorlib/client.py", line 405, in get_address
return self.call(proto.GetAddress(address_n=n, coin_name=coin_name, show_display=show_display))
File "/home/chris/dev/python-trezor/trezorlib/client.py", line 131, in call
resp = self.call(msg)
File "/home/chris/dev/python-trezor/trezorlib/client.py", line 127, in call
msg = handler(resp)
File "/home/chris/dev/python-trezor/trezorlib/client.py", line 143, in callback_Failure
raise CallException(msg.code, msg.message)
trezorlib.client.CallException: (3, u'string overflow')

Ability to enable / disable passphrase for connected device

Trezor has a security issue where it advertises the use of a 25th seed as documented here: https://www.reddit.com/r/TREZOR/comments/5vln7d/security_issue_with_25th_seed_word_passsphrase/

The only known workaround is to disable / enable the advertising of the 25th seed use manually. The only way to do this is via mytrezor.com, which is yet another security issue as mytrezor could be logging access requests to the server.

As such, until this bug is resolved, there should be an option in trezorctrl to easily disable / enable the passphrase advertising feature so users are not forced to compromise security by going to mytrezor.

Include a proper license header in source files

It would make it easier to redistribute python-trezor in Fedora[1] if each source file contains a license header. The only file that have license header is trezor-0.7.7/trezorlib/protobuf_json.py, which is licensed BSD. Can you confirm that the rest of the files are licensed LGPLv3?

Check https://bugzilla.redhat.com/show_bug.cgi?id=1398340#c3 and for details.

[1] https://fedoraproject.org/wiki/Packaging:LicensingGuidelines?rd=Packaging/LicensingGuidelines#License_Clarification

python-trezor plus electrum problem with protobuf

In Electrum, opening the new hardware wallet screen results in the following error, which hides the option to create a new Trezor-backed wallet. Installing a new version of protobuf (protobuf-2.6.1) appears to fix the problem. However python-trezor requires 2.5.0 exactly.

Error: cannot initialize plugin trezor
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/electrum/plugins.py", line 68, in load_plugin
    p = __import__(full_name, fromlist=['electrum_plugins'])
  File "/usr/local/lib/python2.7/dist-packages/electrum_plugins/trezor.py", line 39, in <module>
    import trezorlib.ckd_public as ckd_public
  File "/usr/local/lib/python2.7/dist-packages/trezorlib/ckd_public.py", line 11, in <module>
    import types_pb2 as proto_types
  File "/usr/local/lib/python2.7/dist-packages/trezorlib/types_pb2.py", line 10, in <module>
    from google.protobuf import symbol_database as _symbol_database
ImportError: cannot import name symbol_database

I've just started playing with this combination, so I'm not sure if the issue is with Electrum or with python-trezor. Apologies if this is mis-filed.

python-trezor was installed directly from the github version. I'm using Electrum 2.5.4.

Exception: Got <class 'trezorlib.messages_pb2.Success'>, expected (<class 'trezorlib.messages_pb2.CipheredKeyValue'>,)

john@ubuntu:~$ sudo encfs --standard --extpass=~/python-trezor/tools/encfs_aes_getpass.py ~/.trezor ~/trezor
/usr/local/lib/python2.7/dist-packages/hidapi-0.7.99_5-py2.7-linux-x86_64.egg/hid.py:3: UserWarning: Module trezorlib was already imported from /usr/local/lib/python2.7/dist-packages/trezor-0.6.3-py2.7.egg/trezorlib/__init__.pyc, but /usr/local/lib/python2.7/dist-packages/python_trezor-0.5.0-py2.7.egg is being added to sys.path
Please provide label for new drive: trezor
Computer asked Trezor for new strong password.
Please confirm action on your device.
Traceback (most recent call last):
  File "/home/david/python-trezor/tools/encfs_aes_getpass.py", line 113, in <module>
    main()
  File "/home/david/python-trezor/tools/encfs_aes_getpass.py", line 93, in main
    passw_encrypted = client.encrypt_keyvalue(bip32_path, label, passw, False, True)
  File "/usr/local/lib/python2.7/dist-packages/trezor-0.6.3-py2.7.egg/trezorlib/client.py", line 68, in wrapped_f
    ret = f(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/trezor-0.6.3-py2.7.egg/trezorlib/client.py", line 84, in wrapped_f
    raise Exception("Got %s, expected %s" % (ret.__class__, self.expected))
Exception: Got <class 'trezorlib.messages_pb2.Success'>, expected (<class 'trezorlib.messages_pb2.CipheredKeyValue'>,)

Does anyone know why this is happening?

License

What license is this software distributed under?

./cmdtr.py get_address -n does not generate valid addresses for non m/44'/0' coin types

using the command

./cmdtr.py get_address -n "44'/0'/0'/0/0" 

gives equivalent results to mytrezor.com and electrum+trezor plugin, for all m/44'/0'/[A]'/[C]/[K] addresses

However using non-bitcoin cointypes from here does not work. http://doc.satoshilabs.com/slips/slip-0044.html

./cmdtr.py get_address -n "44'/1'/0'/0/0"

gives different addresses to test.mytrezor.com, and

./cmdtr.py get_address -n "44'/2'/0'/0/0"

should give a Litecoin address starting with "L" but instead gives an address starting with "1"

I've also tried the non-bitcoin numbers from get_features which also do not produce the desired results

$ ./cmdtr.py get_features

coins {
  coin_name: "Bitcoin"
  coin_shortcut: "BTC"
  address_type: 0
  maxfee_kb: 10000
}
coins {
  coin_name: "Testnet"
  coin_shortcut: "TEST"
  address_type: 111
  maxfee_kb: 10000000
}
coins {
  coin_name: "Namecoin"
  coin_shortcut: "NMC"
  address_type: 52
  maxfee_kb: 10000000
}
coins {
  coin_name: "Litecoin"
  coin_shortcut: "LTC"
  address_type: 48
  maxfee_kb: 10000000
}

Issues with library testing

Environment OS X, x64, 10.9.4 (not relevant probably)
Python version 2.7.8

  1. Missing documentation on how to run tests. Should we use run.sh or run-separate.sh ?
  2. python setup.py test doesn't react, should execute given tests after in-place build
  3. Running ./run-separate.sh gives no output on tests success/failure, example output:
> ./run-separate.sh 
Starting: test_basic.py
Starting: test_bip32_speed.py
Starting: test_debuglink.py
Starting: test_msg_applysettings.py
Starting: test_msg_changepin.py
Starting: test_msg_cipherkeyvalue.py
Starting: test_msg_clearsession.py
Starting: test_msg_decryptmessage.py
Starting: test_msg_encryptmessage.py
Starting: test_msg_estimatetxsize.py
Starting: test_msg_getaddress.py
Starting: test_msg_getentropy.py
Starting: test_msg_getpublickey.py
Starting: test_msg_loaddevice.py
Starting: test_msg_ping.py
Starting: test_msg_recoverydevice.py
Starting: test_msg_resetdevice.py
Starting: test_msg_signmessage.py
Starting: test_msg_signtx.py
Starting: test_msg_simplesigntx.py
Starting: test_msg_verifymessage.py
Starting: test_msg_wipedevice.py
Starting: test_protect_call.py
Starting: test_protection_levels.py
Starting: test_zerosig.py
  1. Running ./run.sh in tests folder, gives 99 errors like this:
======================================================================
ERROR: test_two_zero_signature (test_zerosig.TestZeroSig)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/{REPOSITORY_PATH}/python-trezor/tests/common.py", line 9, in setUp
    self.debug_transport = config.DEBUG_TRANSPORT(*config.DEBUG_TRANSPORT_ARGS, **config.DEBUG_TRANSPORT_KWARGS)
  File "../trezorlib/transport_socket.py", line 16, in __init__
    super(SocketTransportClient, self).__init__(device, *args, **kwargs)
  File "../trezorlib/transport.py", line 14, in __init__
    self._open()
  File "../trezorlib/transport_socket.py", line 20, in _open
    self.socket.connect(self.device)
  File "/usr/local/Cellar/python/2.7.8/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
gaierror: [Errno 8] nodename nor servname provided, or not known

----------------------------------------------------------------------

python setup.by install error on osx mavericks

Installed /Library/Python/2.7/site-packages/trezor-0.6.5-py2.7.egg
Processing dependencies for trezor==0.6.5
Searching for hidapi>=0.7.99
Reading http://pypi.python.org/simple/hidapi/
Download error: [Errno 8] nodename nor servname provided, or not known -- Some packages may not be found!
Couldn't find index page for 'hidapi' (maybe misspelled?)

I did brew install hidapi and

brew install hidapi
Warning: hidapi-0.8.0-rc1 already installed

but that didn't fix the problem.

Missing example usage/implementation

Library should provide either within repository itself or within github wiki, example implementation and documentation.

Example implementation should show life-cycle of trezor usage and resolve questions about multi-threading issues.

support lock_time

does the API allow to pass a lock_time?
I did not find it in the code

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.