Giter Club home page Giter Club logo

ledgerjs's Introduction

⛔️ DEPRECATED

This repository is now deprecated. We moved to a new mono repository architecture containing all of Ledger Live JavaScript Ecosystem that you can find here. You can follow the migration guide to help you make the transition.

We are hiring, join us! 👨‍💻👩‍💻

Ledger Devs Slack License

Welcome to Ledger's JavaScript libraries.

See also:

@ledgerhq/hw-transport-*

To communicate with a Ledger device, you first need to identify which transport(s) to use.

The hw-transport libraries implement communication protocol for our hardware wallet devices (Ledger Nano / Ledger Nano S / Ledger Nano X / Ledger Blue) in many platforms: Web, Node, Electron, React Native,... and using many different communication channels: U2F, HID, WebUSB, Bluetooth,...

Channels U2F/WebAuthn HID WebUSB Bluetooth
Blue DEPRECATED1 YES NO NO
Nano S DEPRECATED1 YES YES NO
Nano X DEPRECATED1 YES YES YES
  1. U2F is deprecated. See https://github.com/LedgerHQ/ledgerjs/blob/master/docs/migrate_webusb.md

Summary of implementations available per platform

Platforms U2F/WebAuthn HID WebUSB Bluetooth
Web @ledgerhq/hw-transport-u2f @ledgerhq/hw-transport-webhid @ledgerhq/hw-transport-webusb @ledgerhq/hw-transport-web-ble
Electron/Node.js NO @ledgerhq/hw-transport-node-hid1 NO @ledgerhq/hw-transport-node-ble
iOS NO NO NO @ledgerhq/react-native-hw-transport-ble
Android @ledgerhq/hw-transport-u2f2 @ledgerhq/react-native-hid @ledgerhq/hw-transport-webusb2 @ledgerhq/react-native-hw-transport-ble
  1. 3 implementations available
  2. via Android Chrome

Beware the current web support:

Channels U2F WebHID. WebUSB WebBluetooth
Windows DEPRECATED1 YES OK BUT2 YES
Mac DEPRECATED1 YES YES YES
Linux DEPRECATED1 YES YES YES
Chrome DEPRECATED1 YES3 YES YES
Safari DEPRECATED1 NO NO NO
Firefox DEPRECATED1 NO NO NO
IE. DEPRECATED1 NO NO NO
  1. U2F is deprecated. See https://github.com/LedgerHQ/ledgerjs/blob/master/docs/migrate_webusb.md
  2. instabilities has been reported
  3. WebHID supported under Chrome experimental flags

Please find respective documentation for each transport:

An unified Transport interface

All these transports implement a generic interface exposed by @ledgerhq/hw-transport. There are specifics for each transport which are explained in each package.

A Transport is essentially:

  • Transport.listen: (observer)=>Subscription
  • Transport.open: (descriptor)=>Promise<Transport>
  • transport.exchange(apdu: Buffer): Promise<Buffer>
  • transport.close()

and some derivates:

  • transport.create(): Promise<Transport>: make use of listen and open for the most simple scenario.
  • transport.send(cla, ins, p1, p2, data): Promise<Buffer>: a small abstraction of exchange

NB: APDU is the encoding primitive for all binary exchange with the devices. (it comes from smart card industry)

@ledgerhq/hw-app-*

As soon as your Transport is created, you can already communicate by implementing the apps protocol (refer to application documentations, for instance BTC app and ETH app ones).

We also provide libraries that help implementing the low level exchanges. These higher level APIs are split per app:

Community packages:

Other packages

Published Packages

Package Version Description
create-dapp npm Ledger DApp Ethereum starter kit
@ledgerhq/web3-subprovider npm web3 subprovider implementation for web3-provider-engine
Development Tools
@ledgerhq/hw-transport-mocker npm Tool used for test to record and replay APDU calls.

Basic gist

import Transport from "@ledgerhq/hw-transport-node-hid";
// import Transport from "@ledgerhq/hw-transport-webusb";
// import Transport from "@ledgerhq/react-native-hw-transport-ble";
import AppBtc from "@ledgerhq/hw-app-btc";
const getBtcAddress = async () => {
  const transport = await Transport.create();
  const btc = new AppBtc(transport);
  const result = await btc.getWalletPublicKey("44'/0'/0'/0/0");
  return result.bitcoinAddress;
};
getBtcAddress().then(a => console.log(a));

Contributing

Please read our contribution guidelines before getting started.

You need to have a recent Node.js and Yarn installed.

Install dependencies

yarn

Build

Build all packages

yarn build

Watch

Watch all packages change. Very useful during development to build only file that changes.

yarn watch

Lint

Lint all packages

yarn lint

Run Tests

First of all, this ensure the libraries are correctly building, and passing lint and flow:

yarn test

then to test on a real device...

Plug a device like the Nano S and open Bitcoin app.

Then run the test and accept the commands on the devices for the tests to continue.

yarn test-node

You can also test on the web:

yarn test-browser

make sure to configure your device app with "Browser support" set to "YES".

Deploy

Checklist before deploying a new release:

  • you have the right in the LedgerHQ org on NPM
  • you have run npm login once (check npm whoami)
  • Go to master branch
    • your master point on LedgerHQ repository (check with git config remote.$(git config branch.master.remote).url and fix it with git branch --set-upstream master origin/master)
    • you are in sync (git pull) and there is no changes in git status
  • Run yarn once, there is still no changes in git status

deploy a new release

 yarn run publish

then, go to /releases and create a release with change logs.

alternatively:

deploy a canary release (beta, etc)

 yarn run publish -c

NB: if there is a new package, AFAIK you need to manually npm publish it once on NPM.

VSCode settings

Here is a example config for a workspace file to handle the monorepo setup.
Just add project.code-workspace to your .vscode folder

{
  "folders": [
    {
      "name": "root",
      "path": "../"
    },
    {
      "name": "cryptoassets",
      "path": "../packages/cryptoassets"
    },
    {
      "name": "devices",
      "path": "../packages/devices"
    },
    {
      "name": "errors",
      "path": "../packages/errors"
    },
    {
      "name": "hw-app-algorand",
      "path": "../packages/hw-app-algorand"
    },
    {
      "name": "hw-app-btc",
      "path": "../packages/hw-app-btc"
    },
    {
      "name": "hw-app-cosmos",
      "path": "../packages/hw-app-cosmos"
    },
    {
      "name": "hw-app-eth",
      "path": "../packages/hw-app-eth"
    },
    {
      "name": "hw-app-polkadot",
      "path": "../packages/hw-app-polkadot"
    },
    {
      "name": "hw-app-str",
      "path": "../packages/hw-app-str"
    },
    {
      "name": "hw-app-tezos",
      "path": "../packages/hw-app-tezos"
    },
    {
      "name": "hw-app-trx",
      "path": "../packages/hw-app-trx"
    },
    {
      "name": "hw-app-xrp",
      "path": "../packages/hw-app-xrp"
    },
    {
      "name": "hw-transport",
      "path": "../packages/hw-transport"
    },
    {
      "name": "hw-transport-http",
      "path": "../packages/hw-transport-http"
    },
    {
      "name": "hw-transport-mocker",
      "path": "../packages/hw-transport-mocker"
    },
    {
      "name": "hw-transport-node-ble",
      "path": "../packages/hw-transport-node-ble"
    },
    {
      "name": "hw-transport-node-hid",
      "path": "../packages/hw-transport-node-hid"
    },
    {
      "name": "hw-transport-node-hid-noevents",
      "path": "../packages/hw-transport-node-hid-noevents"
    },
    {
      "name": "hw-transport-node-hid-singleton",
      "path": "../packages/hw-transport-node-hid-singleton"
    },
    {
      "name": "hw-transport-node-speculos",
      "path": "../packages/hw-transport-node-speculos"
    },
    {
      "name": "hw-transport-web-ble",
      "path": "../packages/hw-transport-web-ble"
    },
    {
      "name": "hw-transport-webhid",
      "path": "../packages/hw-transport-webhid"
    },
    {
      "name": "hw-transport-webusb",
      "path": "../packages/hw-transport-webusb"
    },
    {
      "name": "logs",
      "path": "../packages/logs"
    },
    {
      "name": "react-native-hid",
      "path": "../packages/react-native-hid"
    },
    {
      "name": "react-native-hw-transport-ble",
      "path": "../packages/react-native-hw-transport-ble"
    }
  ],
}

ledgerjs's People

Contributors

adrienlacombe avatar akuukis avatar alexandrupislariu avatar allenan avatar amougel avatar dcrichards avatar dependabot[bot] avatar emmanuelm41 avatar frederikbolding avatar gre avatar henri-ly avatar hyperbolist avatar hzheng-ledger avatar iammorrow avatar juan-cortes avatar junichisugiura avatar kallerosenbaum avatar khalilbellakrid avatar konoart avatar lambertkevin avatar loeck avatar max-lt avatar meriadec avatar micahzoltu avatar mortalkastor avatar phra avatar pscott avatar schnogz avatar scmilee avatar valpinkman 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  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

ledgerjs's Issues

Get invalid channel when using ledger with node-hid

Hello,
I'm trying to use the node library to get the ledger accounts but I'm getting an error "Invalid channel" why do I get this? and how can I make it work?

I used the following code:

ledger.comm_node.create_async().then(function(comm) { 
   eth = new ledger.eth(comm); 
   eth.getAddress_async("44'/60'/0'/0'/0").then(console.log, console.log);
});
{ state: 'pending' }
> Invalid channel;

add a hw-dashboard

this will contain all api calls we can do on the "dashboard" (not in an app)

Error: Can't resolve 'fs'

using this:
"@ledgerhq/hw-transport-node-hid": "^4.0.0",
"@ledgerhq/hw-transport-u2f": "^4.0.0",
"@ledgerhq/hw-app-str": "^4.0.0"

ERROR in ./node_modules/bindings/bindings.js
Module not found: Error: Can't resolve 'fs' in 'f:\Github\stellar-client-web\node_modules\bindings'
@ ./node_modules/bindings/bindings.js 6:9-22
@ ./node_modules/node-hid/nodehid.js
@ ./node_modules/@ledgerhq/hw-transport-node-hid/lib/TransportNodeHid.js
@ ./node_modules/stellar-js-utils/dist/build.js
@ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/pages/CreateToken.vue
@ ./src/pages/CreateToken.vue
@ ./src/libEntry.js
@ ./src/entry.js
@ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/entry.js

WARNING in ./node_modules/bindings/bindings.js
81:22-40 Critical dependency: the request of a dependency is an expression
@ ./node_modules/bindings/bindings.js
@ ./node_modules/node-hid/nodehid.js
@ ./node_modules/@ledgerhq/hw-transport-node-hid/lib/TransportNodeHid.js
@ ./node_modules/stellar-js-utils/dist/build.js
@ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/pages/CreateToken.vue
@ ./src/pages/CreateToken.vue
@ ./src/libEntry.js
@ ./src/entry.js
@ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/entry.js

WARNING in ./node_modules/bindings/bindings.js
81:43-53 Critical dependency: the request of a dependency is an expression
@ ./node_modules/bindings/bindings.js
@ ./node_modules/node-hid/nodehid.js
@ ./node_modules/@ledgerhq/hw-transport-node-hid/lib/TransportNodeHid.js
@ ./node_modules/stellar-js-utils/dist/build.js
@ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/pages/CreateToken.vue
@ ./src/pages/CreateToken.vue
@ ./src/libEntry.js
@ ./src/entry.js
@ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/entry.js

"Cannot write to HID device" after reopening Bitcoin app

I'm able to get the public key, however, it no longer works if I quit the Bitcoin app and reopen it.

  1. Plug in Ledger Nano S
  2. Enter PIN
  3. Select "Bitcoin" app
  4. Get the public key
    btc.getWalletPublicKey_async('0')
    // { publicKey, chainCode, bitcoinAddress }
  5. Quit the Bitcoin app
  6. Reopen the Bitcoin app
  7. Get the public key again
    btc.getWalletPublicKey_async('0')
    // Error: Cannot write to HID device (ledger-comm-node.js:171)

Any help to get me pointed in the right direction is much appreciated. Thanks!

generate a doc website

netlify might be great for this. we can use documentation to generate us a nice HTML page + having more general written documentation

Installation does not work

I'm trying to run the tests but I'm unable to install the dependencies.
I've tried both with node 0.12.5 and node v5.0.0

$ npm install
npm WARN package.json [email protected] license should be a valid SPDX license expression

[email protected] preinstall /Work/Bitcoin/ledger-node-js-api/node_modules/node-hid
sh get-hidapi.sh

Cloning into 'hidapi'...
remote: Counting objects: 1965, done.
remote: Total 1965 (delta 0), reused 0 (delta 0), pack-reused 1965
Receiving objects: 100% (1965/1965), 2.80 MiB | 1.94 MiB/s, done.
Resolving deltas: 100% (1086/1086), done.
Checking connectivity... done.

[email protected] install /Work/Bitcoin/ledger-node-js-api/node_modules/node-hid
sh install.sh

make: Entering directory '/Work/Bitcoin/ledger-node-js-api/node_modules/node-hid/build'
CC(target) Release/obj.target/hidapi/hidapi/libusb/hid.o
../hidapi/libusb/hid.c: In function ‘hid_read_timeout’:
../hidapi/libusb/hid.c:1078:6: warning: variable ‘bytes_read’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Wclobbered]
int bytes_read = -1;
^
AR(target) Release/obj.target/hidapi.a
COPY Release/hidapi.a
CXX(target) Release/obj.target/HID/src/HID.o
../src/HID.cc: In member function ‘virtual v8::Handlev8::Value JSException::asV8Exception() const’:
../src/HID.cc:50:71: error: ‘New’ is not a member of ‘v8::String’
virtual Handle asV8Exception() const { return ThrowException(String::New(message().c_str())); }
}}}

Invalid Status 6e 00, when signing an ethereum transaction using an electron app.

I am developing an electron app, with ledgerco node module, using it for ethereum transactions.
Able to generate a raw transaction and send it to device for signing.
As it displays the transaction details on the device, i get "Invalid status 6e 00" error and device freezes.
On debug, I noticed I get an response of length 64 with 6e 00, whereas other 64 length responses are undefined.

debug logs

To Device:
=>01010500000041e00400003c048000002c8000003c8000000000000002ea028504e3b2920082520894ebab7dce1e99aaa5422a1e13cb9bba5c1073c7d4865af3
=>0101050001107a400080018080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

From device:
<=010105000000026e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

RECEIVED:  <Buffer 01 01 05 00 00 00 02 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >
RECEIVED LEN:  64
RESPONSE:  <Buffer 6e 00>

If I confirm the transaction immediately once it flashes on ledger device, I do get proper signed response back.
debug log of a successful transaction, by confirming the transaction immediately on device.


To device:
=>01010500000041e00400003c048000002c8000003c8000000000000002ea028504e3b2920082520894ebab7dce1e99aaa5422a1e13cb9bba5c1073c7d4865af3
=>0101050001107a400080018080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

From device:
<=0101050000004325353eb234509ccb9206c2354f824b46416f738cad677d0e3ce8f48acdaff91f962b4cafdcf5ca9e49d8b117575d55d8b20ae892cd00ad0924

RECEIVED:  <Buffer 01 01 05 00 00 00 43 25 35 3e b2 34 50 9c cb 92 06 c2 35 4f 82 4b 46 41 6f 73 8c ad 67 7d 0e 3c e8 f4 8a cd af f9 1f 96 2b 4c af dc f5 ca 9e 49 d8 b1 ... >
RECEIVED LEN:  64
RESPONSE:  undefined

From device:
<=010105000184d3cdec9c863428900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

RECEIVED:  <Buffer 01 01 05 00 00 00 43 25 35 3e b2 34 50 9c cb 92 06 c2 35 4f 82 4b 46 41 6f 73 8c ad 67 7d 0e 3c e8 f4 8a cd af f9 1f 96 2b 4c af dc f5 ca 9e 49 d8 b1 ... >
RECEIVED LEN:  128
RESPONSE:  <Buffer 25 35 3e b2 34 50 9c cb 92 06 c2 35 4f 82 4b 46 41 6f 73 8c ad 67 7d 0e 3c e8 f4 8a cd af f9 1f 96 2b 4c af dc f5 ca 9e 49 d8 b1 17 57 5d 55 d8 b2 0a ... >

It seems like the device does not wait for the confirm input and times out immediately sending invalid status 6e 00.

Could someone help me out how to make it wait for a confirm input.

Ethereum message signing mismatch

Hi all,
I'm getting a weird signature issue.

This is without the ledger:

var ledger = require('ledgerco')
var EthereumBip44 = require('ethereum-bip44')
var ethutil = require('ethereumjs-util')

var wallet2 = EthereumBip44.fromPrivateSeed('xprvA14DWX6xDyqUrwpfJRm7awb51r6ZXA8b9bJ2oqLvZ1CPmPHXX8gCuz2xtYxF7jy6YsWLzN9h1oTkb2a6TCpeZifaGR65pwzRn82SHQdND4E')

console.log('Private key', wallet2.getPrivateKey(0))

var sig = ethutil.ecsign(msgHash, wallet2.getPrivateKey(0))
console.log('SIGNED via ecsign', sig)
console.log('recovered address', ethutil.ecrecover(msgHash, sig.v, sig.r, sig.s).toString('hex'))

Recovering a signed message, I can find the following address to my account:

63a55fc5428648b9e527e48e099a43cafc8997a7032dd6bd2f62b4132cc47915e25ab472c0bc2ac764d5b757edf169863f32aeb46acaeebbfac352429c54f65f

This is the same address that I can recover using my ledger at path m/44'/60'/0'/0'/0

When I try to sign the same message using the node api on my ledger, I get a different signature and a different signed message.

ledger.comm_node.create_async().then(function (comm) {
  var eth = new ledger.eth(comm)
  var path = "m/44'/60'/0'/0'/0"  // The public address on this path is the same as above
  eth.signPersonalMessage_async(path, msgHash).then(function (result) {
      var v = result['v'] - 27
      v = v.toString(16)
      if (v.length < 2) {
        v = '0' + v
      }
      console.log('recovered address', ethutil.ecrecover(msgHash, result['v'], new Buffer(result.r, 'hex'), new Buffer(result.s, 'hex')).toString('hex'))
    
  })
})

The returned signature here is not the same as the ethereumjs-util ecsign

refactor the exchange Comm method to be Buffer=>Buffer

the fact it's currently a hexString => hexString make code more complex and with unecessary successive conversion. we can just make it accept buffer and return promise of buffer. this will be a breaking change and therefore a future major release.

Feedback and ideas for future

assuming #26 gets in, here is next step feedback & ideas

JS code

  • The library have a lot of async. I think it would be interesting to migrate
    the promise codebase to async/await (babel compiles it down to Promise
    code) This is especially interesting for code that need to chain promises in
    sequence (eachSeries) (you can basically do a for loop with a await in
    it!).
  • Apparently new Buffer is deprecated so need to port the remaining usage of
    that (and use Buffer.from / Buffer.alloc)
  • codebase currently have some repetition. Need to think what we could factorize
    and if there is a higher level library that could help us on dealing with data
    format? (e.g; maybe we should directly manipulate the buffer, but define some
    "schema" and inject all data to "serialize" something) – just a thought.

Documentation

  • https://www.npmjs.com/package/documentation could be interesting to use. We
    could generate a API.md that is always in sync with the source code. What we
    need to do is to add some "Javadoc" in all public objects/classes/methods. To
    have used it before, I'm pretty sure this is compatible with Flow too. (need
    to check this works ok with async/await tho)
  • README should start by telling more what the library is, and how to install
    and use it. The part about developing on the project is documented in
    CONTRIBUTING.md (and we can have a link to there).
  • README is a good place to have a simple example so people instantly get the
    "gist" of the library. I'm not sure if the whole documentation should stick in
    there and maybe we would delegate to this API.md? (we have have links to that
    API doc)
  • Contributing needs doc on how to deploy a new version on npm.

API

These are breaking API changes suggestions (only to be in a major release)

  • I think it would be better to directly export the classes (LedgerBtc /
    LedgerEth / ..) under these names.
  • Maybe we should have LedgerComm exported as either LedgerCommU2F or
    LedgerCommNode. So we can just write the exact same code on Node or on
    Browser (and it also simplify documenting this).
  • I don't think we should suffix any method with _async. It is common to have
    promise returned in JS libs. Just need users to know everything is async
    (RTFM!), but also if they use Flowtype, you won't have surprises ;)

More general question & thoughts

  • This is unclear to me what is the lifecycle of a comm and with a
    LedgerBtc/LedgerEth instance. E.g. nor the API, nor any runtime check,
    prevents me from using comm on 2 instances of these (which I guess is an
    issue, especially that instanciating a LedgerBtc will set a state on comm
    (setScrambleKey)). Which led me to the question: can we afford creating one
    comm at a time & per LedgerBtc/Eth usage? If so, shouldn't this be hidden for
    the user? (aka you would do: LedgerBtc.create().then(btc => ...) without
    having to worry about comm ?). If we still want comm to have a bigger
    lifecycle (like you instanciate it only once for the all app lifecycle), I
    think we will need a "context" concept that we bind again that context
    when we enter a new call (e.g. like OpenGL programs) and maybe we even need
    some ways to throw if user is calling something and we're in the middle of
    something else (to avoid concurrent access).

Tests

I suggest we could use Jest engine for tests.

  • We could use test coverage to determine which things remain to be tested.
    (jest provides this)
  • to test LedgerCommU2F, we could mock implementation of U2F and back it by
    node-hid. (jest have nice ways to .mock things). (we still would have browser
    example/test for a end-to-end check, but if the mock implementation is
    correct, we shouldn't worry much as it would just mean testing the actual
    browser U2F)
  • tests can use async/await too (I think Jest works with async test too)
  • This would still requires the user to plug a device and manually check&accept
    the things on the display. This is nice to have but I think we should also
    have a headless version (device simulator) that eventually runs on Travis. I
    imagine there will be some addition testing code for the simulator too, like
    you want to test both side (the client side and the "device" side) e.g; that
    it display something / a given string / ...

CI

  • as said above, if we can have a headless version (device simulator) we can
    eventually run tests on Travis!
  • but also, we should already setup Travis check that will call the lint and
    flow commands (and obviously we connect it to incoming PRs).

"Invalid channel" while using blue eth app

Hello,
I came accross the following errors maybe related to #4

Note : i'm using linux

result with browser support disabled

> var ledger = require("ledgerco")
undefined
> ledger.comm_node.create_async(0,true).then(x=>_comm=x).catch(e=>console.log(e))
{ state: 'pending' }
> eth.getAddress_async("44'/0'/0'/0", true, true).then(console.log).catch(console.log)
=>01010500000016e002010111048000002c8000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000
{ state: 'pending' }
> <=01010500000002680400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Invalid status 6804

I get a different error with browser support enabled

> eth.getAddress_async("44'/0'/0'/0", true, true).then(console.log).catch(console.log)
=>01010500000016e002010111048000002c8000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000
{ state: 'pending' }
> <=bf00018d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Invalid channel;

As a side note bitcoin app seems to work fine .I didn't go further than call getWalletPublicKey_async but it didn't raised any error.

"Invalid channel" error on Windows

I can't seem to get this to work on Windows (Node). The device is detected, but when I attempt to get the BTC public key I get an error "Invalid channel".

The code out of test/testBTC.js:

var ledger = require('ledgerco');

ledger.comm_node.create_async(0, true).then(function(comm) {

  var btc = new ledger.btc(comm);
  btc.getWalletPublicKey_async("44'/0'/0'/0").then(function(result) {
    console.log(result);
  }).fail(function(ex) {console.log(ex);});

}).fail(function(ex) {console.log(ex);});

The console shows:

=>01010500000016e040000011048000002c80000000800000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
<=0105000000000040000011048000002c8000000080000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
Invalid channel

The same snippet works on Ubuntu. What am I missing?

intermittent stack traces when interacting with the UI

I was toying around with the API and noticed that on my Ledger Nano S (just updated the firmware to 1.3), I see miscellaneous memory errors:

$ node examples/node-device-info.js 
{ manufacturer: 'Ledger',
  product: 'Nano S',
  serialNumber: '0001' }
*** Error in `node': double free or corruption (fasttop): 0x00007fd630000a30 ***
======= Backtrace: =========
/usr/lib/libc.so.6(+0x7254c)[0x7fd647a8454c]
/usr/lib/libc.so.6(+0x78bfb)[0x7fd647a8abfb]
/usr/lib/libc.so.6(+0x79fd1)[0x7fd647a8bfd1]
/usr/lib/libusb-1.0.so.0(+0x968d)[0x7fd6438bf68d]
/usr/lib/libusb-1.0.so.0(libusb_handle_events_timeout_completed+0xf0)[0x7fd6438c0770]
/usr/lib/libusb-1.0.so.0(libusb_handle_events+0x2f)[0x7fd6438c086f]
//ledger-node-js-api/node_modules/node-hid/build/Release/HID.node(+0xd5ce)[0x7fd643adc5ce]
/usr/lib/libpthread.so.0(+0x7297)[0x7fd647dbe297]
/usr/lib/libc.so.6(clone+0x3f)[0x7fd647aff25f]
======= Memory map: ========
00400000-015f3000 r-xp 00000000 fe:02 79444715                           /usr/bin/node
017f2000-017f3000 r--p 011f2000 fe:02 79444715                           /usr/bin/node
017f3000-017fc000 rw-p 011f3000 fe:02 79444715                           /usr/bin/node
017fc000-0180d000 rw-p 00000000 00:00 0 
01983000-01b08000 rw-p 00000000 00:00 0                                  [heap]
1264e800000-1264e880000 rw-p 00000000 00:00 0 
6bc02080000-6bc02100000 rw-p 00000000 00:00 0 
c5f03f00000-c5f03f80000 rw-p 00000000 00:00 0 
dbb71b80000-dbb71c00000 rw-p 00000000 00:00 0 
173431480000-173431500000 ---p 00000000 00:00 0 
1e8b6ee00000-1e8b6ee80000 ---p 00000000 00:00 0 
1ff5f0821000-1ff5f0a00000 ---p 00000000 00:00 0 
1ff5f0a00000-1ff5f0a03000 rw-p 00000000 00:00 0 
1ff5f0a03000-1ff5f0a04000 ---p 00000000 00:00 0 
1ff5f0a04000-1ff5f0a7f000 rwxp 00000000 00:00 0 
1ff5f0a7f000-1ff5f0a80000 ---p 00000000 00:00 0 
1ff5f0a80000-1ff5f0a83000 rw-p 00000000 00:00 0 
1ff5f0a83000-1ff5f0a84000 ---p 00000000 00:00 0 
1ff5f0a84000-1ff5f0a8d000 rwxp 00000000 00:00 0 
1ff5f0a8d000-1ff5f0b00000 ---p 00000000 00:00 0 
1ff5f0b00000-1ff5f0b03000 rw-p 00000000 00:00 0 
1ff5f0b03000-1ff5f0b04000 ---p 00000000 00:00 0 
1ff5f0b04000-1ff5f0b7f000 rwxp 00000000 00:00 0 
1ff5f0b7f000-1ff5f0b80000 ---p 00000000 00:00 0 
1ff5f0b80000-1ff5f0b83000 rw-p 00000000 00:00 0 
1ff5f0b83000-1ff5f0b84000 ---p 00000000 00:00 0 
1ff5f0b84000-1ff5f0bff000 rwxp 00000000 00:00 0 
1ff5f0bff000-1ff610821000 ---p 00000000 00:00 0 
203638980000-203638a00000 ---p 00000000 00:00 0 
237c4b800000-237c4b880000 ---p 00000000 00:00 0 
29f4beabd000-29f4beac0000 ---p 00000000 00:00 0 
29f4beac0000-29f4beae0000 rw-p 00000000 00:00 0 
29f4beae0000-29f4beafd000 ---p 00000000 00:00 0 
316849800000-316849880000 ---p 00000000 00:00 0 
365d25880000-365d25885000 rw-p 00000000 00:00 0 
365d25885000-365d25900000 ---p 00000000 00:00 0 
3b22cec80000-3b22ced00000 rw-p 00000000 00:00 0 
3cca44780000-3cca44800000 ---p 00000000 00:00 0 
3d74b6300000-3d74b6380000 ---p 00000000 00:00 0 
3f74d6080000-3f74d6100000 ---p 00000000 00:00 0 
7fd624000000-7fd624021000 rw-p 00000000 00:00 0 
7fd624021000-7fd628000000 ---p 00000000 00:00 0 
7fd62c000000-7fd62c034000 rw-p 00000000 00:00 0 
7fd62c034000-7fd630000000 ---p 00000000 00:00 0 
7fd630000000-7fd630021000 rw-p 00000000 00:00 0 
7fd630021000-7fd634000000 ---p 00000000 00:00 0 
7fd634000000-7fd634022000 rw-p 00000000 00:00 0 
7fd634022000-7fd638000000 ---p 00000000 00:00 0 
7fd638000000-7fd638057000 rw-p 00000000 00:00 0 
7fd638057000-7fd63c000000 ---p 00000000 00:00 0 
7fd63c000000-7fd63c058000 rw-p 00000000 00:00 0 
7fd63c058000-7fd640000000 ---p 00000000 00:00 0 
7fd642296000-7fd642297000 ---p 00000000 00:00 0 
7fd642297000-7fd642a97000 rw-p 00000000 00:00 0 
7fd642a97000-7fd642a9a000 r-xp 00000000 fe:02 79575139                   /usr/lib/gconv/UTF-16.so
7fd642a9a000-7fd642c99000 ---p 00003000 fe:02 79575139                   /usr/lib/gconv/UTF-16.so
7fd642c99000-7fd642c9a000 r--p 00002000 fe:02 79575139                   /usr/lib/gconv/UTF-16.so
7fd642c9a000-7fd642c9b000 rw-p 00003000 fe:02 79575139                   /usr/lib/gconv/UTF-16.so
7fd642c9b000-7fd642c9c000 ---p 00000000 00:00 0 
7fd642c9c000-7fd64349c000 rw-p 00000000 00:00 0 
7fd64349c000-7fd6434a0000 r-xp 00000000 fe:02 79445693                   /usr/lib/libcap.so.2.25
7fd6434a0000-7fd64369f000 ---p 00004000 fe:02 79445693                   /usr/lib/libcap.so.2.25
7fd64369f000-7fd6436a0000 rw-p 00003000 fe:02 79445693                   /usr/lib/libcap.so.2.25
7fd6436a0000-7fd6436b3000 r-xp 00000000 fe:02 79448058                   /usr/lib/libresolv-2.25.so
7fd6436b3000-7fd6438b2000 ---p 00013000 fe:02 79448058                   /usr/lib/libresolv-2.25.so
7fd6438b2000-7fd6438b3000 r--p 00012000 fe:02 79448058                   /usr/lib/libresolv-2.25.so
7fd6438b3000-7fd6438b4000 rw-p 00013000 fe:02 79448058                   /usr/lib/libresolv-2.25.so
7fd6438b4000-7fd6438b6000 rw-p 00000000 00:00 0 
7fd6438b6000-7fd6438cd000 r-xp 00000000 fe:02 79446294                   /usr/lib/libusb-1.0.so.0.1.0
7fd6438cd000-7fd643acd000 ---p 00017000 fe:02 79446294                   /usr/lib/libusb-1.0.so.0.1.0
7fd643acd000-7fd643ace000 r--p 00017000 fe:02 79446294                   /usr/lib/libusb-1.0.so.0.1.0
7fd643ace000-7fd643acf000 rw-p 00018000 fe:02 79446294                   /usr/lib/libusb-1.0.so.0.1.0
7fd643acf000-7fd643ae1000 r-xp 00000000 fe:02 73007544                   //ledger-node-js-api/node_modules/node-hid/build/Release/HID.node
7fd643ae1000-7fd643ce0000 ---p 00012000 fe:02 73007544                   //ledger-node-js-api/node_modules/node-hid/build/Release/HID.node
7fd643ce0000-7fd643ce1000 r--p 00011000 fe:02 73007544                   //ledger-node-js-api/node_modules/node-hid/build/Release/HID.node
7fd643ce1000-7fd643ce3000 rw-p 00012000 fe:02 73007544                   //ledger-node-js-api/node_modules/node-hid/build/Release/HID.node
7fd643ce3000-7fd643ce4000 ---p 00000000 00:00 0 
7fd643ce4000-7fd6444e4000 rw-p 00000000 00:00 0 
7fd6444e4000-7fd6444e5000 ---p 00000000 00:00 0 
7fd6444e5000-7fd644ce5000 rw-p 00000000 00:00 0 
7fd644ce5000-7fd644ce6000 ---p 00000000 00:00 0 
7fd644ce6000-7fd6454e6000 rw-p 00000000 00:00 0 
7fd6454e6000-7fd6454e7000 ---p 00000000 00:00 0 
7fd6454e7000-7fd645ce7000 rw-p 00000000 00:00 0 
7fd645ce7000-7fd6475fa000 r--p 00000000 fe:02 79444524                   /usr/lib/libicudata.so.59.1
7fd6475fa000-7fd6477f9000 ---p 01913000 fe:02 79444524                   /usr/lib/libicudata.so.59.1
7fd6477f9000-7fd6477fa000 r--p 01912000 fe:02 79444524                   /usr/lib/libicudata.so.59.1
7fd6477fa000-7fd64780f000 r-xp 00000000 fe:02 79448057                   /usr/lib/libnsl-2.25.so
7fd64780f000-7fd647a0e000 ---p 00015000 fe:02 79448057                   /usr/lib/libnsl-2.25.so
7fd647a0e000-7fd647a0f000 r--p 00014000 fe:02 79448057                   /usr/lib/libnsl-2.25.so
7fd647a0f000-7fd647a10000 rw-p 00015000 fe:02 79448057                   /usr/lib/libnsl-2.25.so
7fd647a10000-7fd647a12000 rw-p 00000000 00:00 0 
7fd647a12000-7fd647bae000 r-xp 00000000 fe:02 79445596                   /usr/lib/libc-2.25.so
7fd647bae000-7fd647dad000 ---p 0019c000 fe:02 79445596                   /usr/lib/libc-2.25.so
7fd647dad000-7fd647db1000 r--p 0019b000 fe:02 79445596                   /usr/lib/libc-2.25.so
7fd647db1000-7fd647db3000 rw-p 0019f000 fe:02 79445596                   /usr/lib/libc-2.25.so
7fd647db3000-7fd647db7000 rw-p 00000000 00:00 0 
7fd647db7000-7fd647dd0000 r-xp 00000000 fe:02 79444940                   /usr/lib/libpthread-2.25.so
7fd647dd0000-7fd647fcf000 ---p 00019000 fe:02 79444940                   /usr/lib/libpthread-2.25.so
7fd647fcf000-7fd647fd0000 r--p 00018000 fe:02 79444940                   /usr/lib/libpthread-2.25.so
7fd647fd0000-7fd647fd1000 rw-p 00019000 fe:02 79444940                   /usr/lib/libpthread-2.25.so
7fd647fd1000-7fd647fd5000 rw-p 00000000 00:00 0 
7fd647fd5000-7fd647feb000 r-xp 00000000 fe:02 79448639                   /usr/lib/libgcc_s.so.1
7fd647feb000-7fd6481ea000 ---p 00016000 fe:02 79448639                   /usr/lib/libgcc_s.so.1
7fd6481ea000-7fd6481eb000 r--p 00015000 fe:02 79448639                   /usr/lib/libgcc_s.so.1
7fd6481eb000-7fd6481ec000 rw-p 00016000 fe:02 79448639                   /usr/lib/libgcc_s.so.1
7fd6481ec000-7fd6482fc000 r-xp 00000000 fe:02 79448056                   /usr/lib/libm-2.25.so
7fd6482fc000-7fd6484fc000 ---p 00110000 fe:02 79448056                   /usr/lib/libm-2.25.so
7fd6484fc000-7fd6484fd000 r--p 00110000 fe:02 79448056                   /usr/lib/libm-2.25.so
7fd6484fd000-7fd6484fe000 rw-p 00111000 fe:02 79448056                   /usr/lib/libm-2.25.so
7fd6484fe000-7fd648678000 r-xp 00000000 fe:02 79444622                   /usr/lib/libstdc++.so.6.0.23
7fd648678000-7fd648878000 ---p 0017a000 fe:02 79444622                   /usr/lib/libstdc++.so.6.0.23
7fd648878000-7fd648882000 r--p 0017a000 fe:02 79444622                   /usr/lib/libstdc++.so.6.0.23
7fd648882000-7fd648884000 rw-p 00184000 fe:02 79444622                   /usr/lib/libstdc++.so.6.0.23
7fd648884000-7fd648887000 rw-p 00000000 00:00 0 
7fd648887000-7fd64888e000 r-xp 00000000 fe:02 79448059                   /usr/lib/librt-2.25.so
7fd64888e000-7fd648a8d000 ---p 00007000 fe:02 79448059                   /usr/lib/librt-2.25.so
7fd648a8d000-7fd648a8e000 r--p 00006000 fe:02 79448059                   /usr/lib/librt-2.25.so
7fd648a8e000-7fd648a8f000 rw-p 00007000 fe:02 79448059                   /usr/lib/librt-2.25.so
7fd648a8f000-7fd648a92000 r-xp 00000000 fe:02 79448055                   /usr/lib/libdl-2.25.so
7fd648a92000-7fd648c91000 ---p 00003000 fe:02 79448055                   /usr/lib/libdl-2.25.so
7fd648c91000-7fd648c92000 r--p 00002000 fe:02 79448055                   /usr/lib/libdl-2.25.so
7fd648c92000-7fd648c93000 rw-p 00003000 fe:02 79448055                   /usr/lib/libdl-2.25.so
7fd648c93000-7fd648e31000 r-xp 00000000 fe:02 79444515                   /usr/lib/libicuuc.so.59.1
7fd648e31000-7fd649030000 ---p 0019e000 fe:02 79444515                   /usr/lib/libicuuc.so.59.1
7fd649030000-7fd649042000 r--p 0019d000 fe:02 79444515                   /usr/lib/libicuuc.so.59.1
7fd649042000-7fd649043000 rw-p 001af000 fe:02 79444515                   /usr/lib/libicuuc.so.59.1
7fd649043000-7fd649044000 rw-p 00000000 00:00 0 
7fd649044000-7fd6492b3000 r-xp 00000000 fe:02 79444516                   /usr/lib/libicui18n.so.59.1
7fd6492b3000-7fd6494b2000 ---p 0026f000 fe:02 79444516                   /usr/lib/libicui18n.so.59.1
7fd6494b2000-7fd6494bf000 r--p 0026e000 fe:02 79444516                   /usr/lib/libicui18n.so.59.1
7fd6494bf000-7fd6494c1000 rw-p 0027b000 fe:02 79444516                   /usr/lib/libicui18n.so.59.1
7fd6494c1000-7fd6494c2000 rw-p 00000000 00:00 0 
7fd6494c2000-7fd649525000 r-xp 00000000 fe:02 79447467                   /usr/lib/libssl.so.1.0.0
7fd649525000-7fd649724000 ---p 00063000 fe:02 79447467                   /usr/lib/libssl.so.1.0.0
7fd649724000-7fd649728000 r--p 00062000 fe:02 79447467                   /usr/lib/libssl.so.1.0.0
7fd649728000-7fd64972f000 rw-p 00066000 fe:02 79447467                   /usr/lib/libssl.so.1.0.0
7fd64972f000-7fd64997a000 r-xp 00000000 fe:02 79447468                   /usr/lib/libcrypto.so.1.0.0
7fd64997a000-7fd649b79000 ---p 0024b000 fe:02 79447468                   /usr/lib/libcrypto.so.1.0.0
7fd649b79000-7fd649b95000 r--p 0024a000 fe:02 79447468                   /usr/lib/libcrypto.so.1.0.0
7fd649b95000-7fd649ba1000 rw-p 00266000 fe:02 79447468                   /usr/lib/libcrypto.so.1.0.0
7fd649ba1000-7fd649ba4000 rw-p 00000000 00:00 0 
7fd649ba4000-7fd649bb5000 r-xp 00000000 fe:02 79445694                   /usr/lib/libcares.so.2.2.0
7fd649bb5000-7fd649db4000 ---p 00011000 fe:02 79445694                   /usr/lib/libcares.so.2.2.0
7fd649db4000-7fd649db5000 r--p 00010000 fe:02 79445694                   /usr/lib/libcares.so.2.2.0
7fd649db5000-7fd649db6000 rw-p 00011000 fe:02 79445694                   /usr/lib/libcares.so.2.2.0
7fd649db6000-7fd649ddb000 r-xp 00000000 fe:02 79433155                   /usr/lib/libuv.so.1.0.0
7fd649ddb000-7fd649fdb000 ---p 00025000 fe:02 79433155                   /usr/lib/libuv.so.1.0.0
7fd649fdb000-7fd649fdc000 r--p 00025000 fe:02 79433155                   /usr/lib/libuv.so.1.0.0
7fd649fdc000-7fd649fdd000 rw-p 00026000 fe:02 79433155                   /usr/lib/libuv.so.1.0.0
7fd649fdd000-7fd649fde000 rw-p 00000000 00:00 0 
7fd649fde000-7fd649fe5000 r-xp 00000000 fe:02 79444152                   /usr/lib/libhttp_parser.so.2.7.1
7fd649fe5000-7fd64a1e4000 ---p 00007000 fe:02 79444152                   /usr/lib/libhttp_parser.so.2.7.1
7fd64a1e4000-7fd64a1e5000 r--p 00006000 fe:02 79444152                   /usr/lib/libhttp_parser.so.2.7.1
7fd64a1e5000-7fd64a1e6000 rw-p 00007000 fe:02 79444152                   /usr/lib/libhttp_parser.so.2.7.1
7fd64a1e6000-7fd64a1fc000 r-xp 00000000 fe:02 79433197                   /usr/lib/libz.so.1.2.11
7fd64a1fc000-7fd64a3fb000 ---p 00016000 fe:02 79433197                   /usr/lib/libz.so.1.2.11
7fd64a3fb000-7fd64a3fc000 r--p 000

Running node 7.10.0 on Linux. I am using the example script from a PR I opened: https://github.com/LedgerHQ/ledger-node-js-api/pull/14/files

eth.getAddress_async return {errorCode: 2} in browser

What I am doing

  • ledger unlocked
  • ethereum app is open
  • Contract data: yes
  • Browser support: yes
ledgerco.comm_u2f.create_async().then(function(x) {
  eth = new ledgerco.eth(x)
  eth.getAddress_async("44'/60'/0'/0'/0").then(
     function(result) { console.log(result);}).catch(
     function(error) { console.log(error); });
})

What I got

{errorCode: 2}

Needs error when issuing two commands concurrently on accident

I had a very annoying bug where I was accidentally getting the public key and issuing a sign transaction before the getpublickey call returned. It would succeed or fail randomly and it took forever to track down. It would be great if the ledger would have returned an error alerting me to the fact that I was trying to sign before the getpublickey returned. It also worked fine for u2f, but put my ledger in weird state for node-hid.

Switch to standard ES6 promises.

Putting this in mainly for tracking purposes as I know that this is a pretty significant (semver major) change. Now that ES2015 officially supports promises and they are available in most browsers, it would be nice if this library used them rather than the legacy non-standard promises available via the q library. Details about A+ promises can be found at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

If you would be open to a Pull Request, let me know. No promises I'll carve out the time to do it, but if I get annoyed enough with dealing with q I may.

Error with node-hid on Node v8.7.0

Got error trying to use ledgerco module
It works fine with node 6 and 7

/home/emerald-wallet/node_modules/electron/dist/electron[13371]: ../../vendor/node/src/node.cc:4451:void node::AtExit(node::Environment *, void (*)(void *), void *): Assertion `(env) != (nullptr)' failed.
 1: node::Abort() [/home/emerald-wallet/node_modules/electron/dist/libnode.so]
 2: 0x7f97233ac2f4 [/home/emerald-wallet/node_modules/electron/dist/libnode.so]
 3: 0x7f97233b59bc [/home/emerald-wallet/node_modules/electron/dist/libnode.so]
 4: HID::Initialize(v8::Local<v8::Object>) [/home/emerald-wallet/node_modules/ledgerco/node_modules/node-hid/build/Release/HID.node]
 5: 0x7f971049f459 [/home/emerald-wallet/node_modules/ledgerco/node_modules/node-hid/build/Release/HID.node]
 6: 0x7f97233b330d [/home/emerald-wallet/node_modules/electron/dist/libnode.so]
 7: 0x7f9722cbaaa0 [/home/emerald-wallet/node_modules/electron/dist/libnode.so]
 8: 0x7f9723104d08 [/home/emerald-wallet/node_modules/electron/dist/libnode.so]
 9: 0x7f972310427e [/home/emerald-wallet/node_modules/electron/dist/libnode.so]
10: 0x1a3829d843fd

more U2F Transport feature: listen/list/open & "disconnect" event

Summary: currently, a TransportU2F is optimistically created. This is a problem because there is no guarantee the ledger device is actually plugged, we will only know at the first time we do a call (like getAddress, etc..). in Transport, listen/list/open are here to solve this lifecycle.

The solution: To workaround this problem, we should have a way to detect at a more "early" phase, if the device is actually here. one way to do this is to trigger a first light APDU call. there is no noop call at the moment but we can just use a fake APDU call, that will fails, but at least we know if device answers something. if the timeout of this APDU call is reached, we can makes the open fail. that timeout is defined by openTimeout

Thoughts Now the real question is which of (listen/list) or (open) should implement that. Ideally a listen will only emit when the device is plugged, so it is probably the place (same for list). if we do that, then open would still directly returns. Alternatively, we could yield a result out of list/listen IF u2f is supported, and actively do the APDU call in the open. The second solution is probably preferable because open() should contain the "intensive" work as last step of creating a transport, moreover the first approach requires to be able "interrupt" a search (listen) which is not really possible with u2f (only can be timeouted).
so that's basically it for the open() part. once open() yield a transport, you will have a better guarantee that the device is here, but exchangeTimeout will still be important in case device don't open the correct app / is unplugged / in sleep mode.
as soon as an exchange will yield a bad u2f error (identify which? probably the timeout case) we should emit a "disconnect" event as specified in Transport.

U2F exchange hangs after more than 30 seconds

If you set the exchange timeout on the u2f transport to more than 30 seconds (the default) and wait more than 30 seconds (but less than the custom timeout) before approving the transaction, the exchange will hang. In debug mode it shows no packets are received anymore.

Steps to reproduce:

First set the exchange timeout on the transport to more than 30 seconds. For instance 45:

===================================================================
--- packages/test/src/runTests.js	(revision eb96fd57f3e8504741a750a1f5e324c8b07d84bd)
+++ packages/test/src/runTests.js	(revision )
@@ -120,6 +120,7 @@
     ][i % 3];
     let transport = await createTransport(Transport);
     transport.setDebugMode(true);
+    transport.setExchangeTimeout(45 * 1000);
 
     if (step.name) {
       console.info("Running test " + step.name);

Then build and run the browser tests. When the device asks for confirmation during the testBtc2 test wait for more than thirty seconds but less than 45 seconds.

Expected: the test passes and the script continues to the next test.

Actual: Nothing happens. No response is logged on the javascript console. After 45 seconds however a TransportError is logged: U2F TIMEOUT.

How to create broadcastable ETH transaction ?

Hi guys,
I'd like to integrate the ledger on my website in order to sign transactions; but I'm stuck on a little detail.

For this purpose, I'm using this ledger library to sign the transaction; and I also use ethereumjs/ethereumjs-tx to create the raw transactions in hex.
However, the transactions I'm creating do not seem to be properly formatted, I get the following error when broadcasting using etherscan:

Error! Unable to broadcast Tx : {"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"invalid sender"}}

Here is how I use the libs :

var raw = {
  "nonce": "0x1",
  "gasPrice": "0x2cb417800",
  "gasLimit": "0x5208",
  "to": "0x6ef71ca9cd708883e129559f5edbfb9d9d5c6148",
  "value": "0x5af3107a4000",
  "chainId": 1
};

var txToSign = new ethereumjs.Tx(raw).serialize().toString('hex');

new ledger.eth(comm).signTransaction_async('44\'/60\'/0\'/0', txToSign).then(function(result) {
  raw.r = '0x' + result.r; // "0xf4611d559d1db7c034236ef3989b43304b2e8ffd5855cead12da8f8f10c1db4f"
  raw.s = '0x' + result.s; // "0x68acbc380b551cd883db4b995f50df01533efef09f2529d85d205a6dd83e8f43"
  raw.v = '0x' + result.v; // "0x5b"

  var txSigned = new ethereumjs.Tx(raw);

  console.log('tx raw', raw);
  console.log('tx signed', txSigned.serialize().toString('hex')); // 0xf86a018502cb417800825208946ef71ca9cd708883e129559f5edbfb9d9d5c6148865af3107a4000805ba0f4611d559d1db7c034236ef3989b43304b2e8ffd5855cead12da8f8f10c1db4fa068acbc380b551cd883db4b995f50df01533efef09f2529d85d205a6dd83e8f43
}).catch(function() {});

The message prompts correctly on the ledger, and I can sign the transaction using the embedded ethereum app.

I'm not sure this issue is related to the ledger-node-js-api (could be how I use ethereumjs-tx) but in any case I think my use-case is pretty much representative of what we'd like to do with it in a browser so maybe it will help you guys provide a more complete example.

I'd be interested in a bitcoin example too.

make the error cases more programmatically usable

throw "invalid status "+status is not usable from outside. we need to use our own Error class to provide some fields in it so you can do logic based on if it's a specific status, or if it's a com error, logic error, etc..

improve error messages

this is a general task but basically instead of Invalid Status 9f5a we should have something like Invalid Status 9f5a: Please check you are running on the correct app (trying to have the most precise error message, yet visually printable)

Cannot seem to communicate with device

I enabled browser mode on my ledger nano s and am running in the browser

`if (typeof ledger == "undefined") {
ledger = require('ledgerco');
comm = ledger.comm_node;
browser = false;
}
else {
browser = true;
comm = ledger.comm_u2f;
}

function runTest() {

ledger.comm_u2f.create_async(0, true).then(function(comm) {

var btc = new ledger.btc(comm);
var tx1 = btc.splitTransaction("01000000014ea60aeac5252c14291d428915bd7ccd1bfc4af009f4d4dc57ae597ed0420b71010000008a47304402201f36a12c240dbf9e566bc04321050b1984cd6eaf6caee8f02bb0bfec08e3354b022012ee2aeadcbbfd1e92959f57c15c1c6debb757b798451b104665aa3010569b49014104090b15bde569386734abf2a2b99f9ca6a50656627e77de663ca7325702769986cf26cc9dd7fdea0af432c8e2becc867c932e1b9dd742f2a108997c2252e2bdebffffffff0281b72e00000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88aca0860100000000001976a9144533f5fb9b4817f713c48f0bfe96b9f50c476c9b88ac00000000");
btc.createPaymentTransactionNew_async([ [tx1, 1] ], ["0'/0/0"], undefined, "01905f0100000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88ac").then(function(result) {
	console.log(result);
}).fail(function(ex) {console.log(ex);});

}).fail(function(ex) {console.log(ex);});

}

if (!browser) {
runTest();
}
`

however I get an error in the javascript console

screen shot 2017-02-21 at 2 19 08 pm

Support Firefox Quantum v58+

Firefox Quantum now has U2F support built in. However it seems the current Ledger U2F transport is incompatible.

The browser test shows the following error on the Firefox web console:

Object { name: "TransportError", message: "Failed to sign with Ledger device: U2F BAD_REQUEST", stack: "TransportError@https://192.168.178.17:9966/index-browser.js:21822:16\nwrapU2FTransportError@https://192.168.178.17:9966/index-browser.js:21471:13\n_callee2$@https://192.168.178.17:9966/index-browser.js:21655:23\ntryCatch@https://192.168.178.17:9966/index-browser.js:14276:37\ninvoke@https://192.168.178.17:9966/index-browser.js:14510:22\ndefineIteratorMethods/</prototype[method]@https://192.168.178.17:9966/index-browser.js:14328:16\nstep@https://192.168.178.17:9966/index-browser.js:809:22\nstep/<@https://192.168.178.17:9966/index-browser.js:822:13\nrun@https://192.168.178.17:9966/index-browser.js:4980:22\nnotify/<@https://192.168.178.17:9966/index-browser.js:4993:30\nflush@https://192.168.178.17:9966/index-browser.js:4219:9\n", id: "U2F_2", originalError: Error }```

Transaction signing issue u2f

I get this error {errorCode: 1, errorMessage: "device status code: -3"} when trying to sign an ark transaction with a Nano S.

const ledgerArk = new LedgerArk(this.$store.getters.app.ledgerComm)
const amount = 1 * Math.pow(8, 10)

let tx = arkjs.transaction.createTransaction(
  'Valid address',
  amount,
  null,
  '',
  null
)
delete tx.signature
tx.senderId = this.$store.getters.wallet.address
tx.senderPublicKey = this.$store.getters.wallet.publicKey

const slip44 = this.$store.getters.networkType.slip44
const rawTx = arkjs.crypto.getBytes(tx, true, true).toString('hex')

ledgerArk.signTransaction_async(`44'/${slip44}'/0'/0/0`, rawTx)
  .then((result) => {
    console.log(result)
  })
  .fail((error) => {
    console.log('Ledger error : ', error)
  })
// console.log(tx)
{
  "type": 0,
  "amount": 1073741824,
  "fee": 10000000,
  "recipientId": "Valid recipient address",
  "timestamp": 21264018,
  "asset": {},
  "senderPublicKey": "Valid sender public key",
  "id": "b664b25cfec17dd88a9d9a0c90c1cccdaa071a4e8d59ed01e4e2633c838c957e",
  "senderId": "Valid sender address"
}

Browser support is on. LedgerArk is available here. I get ledgerComm from ledger.comm_u2f.create_async(), I have no trouble to get addresses, just signing.

Project Naming

@btchip can we get some consistency on the project naming?

  • Git Repo - ledgerjs
  • Repo Title - ledger-node-js-api
  • NPM Name - ledgerco

I'm concerned that someone malicious could squat on those package names since they are available and not registered. This could lead to some serious and malicious issues with developers using the wrong packages in their Ledger integrations.

errorCode: 1, errorMessage: "device status code: -3

Hi, I am using this LedgerHQ API to develop our platform.

Similar to Ethereum, which enables users to exchange tokens from one another,

we are working on coins that have similar platform.

Right now, I have been testing Qtum for weeks to make token transaction.

However, I believe there is a bug when signing a transaction (the source code below shows where triggers an error).

When we tested to create and sign token transaction for the first time, it was sent well, but the second time using the same Qtum address it triggers this specific error. (We waited until the transaction has enough confirmations, so it shouldn't be about confirmations)

{errorCode: 1, errorMessage: "device status code: -3"}

u2f.responseHandler_ = function(message) {
 console.log("u2f.responseHandler_", message);
 var response = message.data;
 var reqId = response['requestId'];
 if (!reqId || !u2f.callbackMap_[reqId]) {
   console.error('Unknown or missing requestId in response.');
   return;
 }
 var cb = u2f.callbackMap_[reqId];
 delete u2f.callbackMap_[reqId];
 cb(null, response['responseData']);
};

The specific test-case as explained above, it works well in my local computer using node commands. However, like I attached the source code that test-case does not work in browser (u2f). It is really odd.

Do you think this is a bug?

or

Do you think there is something I am missing?

Versions we have tried are as below

v1.1.3

v2.1.3

Ethereum getAddress_async Failure

I'm trying to grab an Ethereum address.

new ledger.eth(comm).getAddress_async("m/0'", true, true).then(function (result) {
    // ...
}).fail(function (error) {
    // ...
});

But I keep getting Invalid status 6804. I modified the ledgerUnwrap function in ledger-comm-node.js to print what it's unwrapping:

	var ledgerUnwrap = function(channel, data, packetSize) {
	    console.log("Unwrapping " + JSON.stringify([channel, data, packetSize]));
            // ...

Retrying the call every second, my log output is

Unwrapping [257,{"type":"Buffer","data":[1,1,5,0,0,0,2,104,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},64]
"Invalid status 6804"
Unwrapping [257,{"type":"Buffer","data":[1,1,5,0,0,0,2,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},64]
"Invalid status 6700"
Unwrapping [257,{"type":"Buffer","data":[1,1,5,0,0,0,2,104,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},64]
"Invalid status 6804"
Unwrapping [257,{"type":"Buffer","data":[1,1,5,0,0,0,2,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},64]
"Invalid status 6700"

The 6700s are when the ledger is unlocked but not in the Ethereum app, the 6804s are when it's unlocked and the app is open. Browser & contract support are off, I'm running this from node locally, and when I use the same comm to query bitcoin public keys I have no problem.

Any ideas?

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TransportError: Invalid channel

This might be a noob question to ask as I don't have much knowledge about JavaScript.

Below are the steps how I installed this project .
(I basically followed the instructions on README.md)

I installed a recent Node.js[v8.9.4] and Yarn [1.3.2].

$ git clone https://github.com/LedgerHQ/ledgerjs.git
$ yarn
$ yarn run build
$ yarn run lint
$ yarn test

Done with no errors!

Now, I am trying to run index.js, and it triggers the below error.
[I plugged my Ledger with 'no' browser support]

$ cd packages/example-node/lib/
$ node index.js

(node:87045) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TransportError: Invalid channel
(node:87045) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Is there something that I am missing?
Anything I need to take a look at?

Any references or directions will be helpful.

Thanks

refactor the hw-app-* libs to be pure functions

const btc = new AppBtc(transport)
should be
const btc = createAppBtc(transport)

because it's just fundamentally a function that creates an API to communicate with a device using a transport. really should be just a function, there is no need to have a class because there is no lifecycle (unlike transport).
This will make the implementation life easier for all the apps. also we shouldn't return the private methods.. we especially want to protect the API with a lock ( #87 ) but the way that PR was doing inside class paradigm is unecessary complex where we could just do

function AppFoo (transport) {
  function doSomething() {
  }
  return {
    // public API
    doSomething: transport.globalLock("doSomething", doSomething)
  }
}

migration plan

i'm pretty sure this is not a breaking change after further tests but people should still migrate so we'll do a warn

if (this instanceof AppFoo) {
  console.warn("do not use `new` in `new AppFoo`: it is now a simple function call")
}

yarn install failing

Trying to verify that #15 is fixed, I cannot build the project:

$ yarn install
yarn install v1.3.2
$ node -e "if (process.env.npm_execpath.indexOf('yarn') === -1) { console.log('Please use yarn'); process.exit(1); }"
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
error [email protected]: The engine "node" is incompatible with this module. Expected version ">=8.8.0".
error Found incompatible module
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

versions:

yarn --version
1.3.2
node --version
v9.4.0

On a Linux distribution.

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.