-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial code drop of new hardware wallet package.
- Loading branch information
Showing
9 changed files
with
244 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
lib/bin/*.d.ts | ||
lib.esm/bin/*.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
tsconfig.json | ||
src.ts/ | ||
tsconfig.tsbuildinfo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
Hardware Wallets | ||
================ | ||
|
||
Thid is still very experimental. | ||
|
||
I only have 1 ledger nano, and testing is done locally (CirlceCI doesn't have | ||
ledgers plugged in ;)). | ||
|
||
API | ||
=== | ||
|
||
``` | ||
import { LedgerSigner } from "@ethersproject/hardware-wallets"; | ||
const signer = new LedgerSigner(provider, type, path); | ||
// By default: | ||
// - in node, type = "usb" | ||
// - path is the default Ethereum path (i.e. `m/44'/60'/0'/0/0`) | ||
``` | ||
|
||
License | ||
======= | ||
|
||
All ethers code is MIT License. | ||
|
||
Each hardware wallet manufacturer may impose additional license | ||
requirements so please check the related abstraction libraries | ||
they provide. | ||
|
||
All Firefly abstraction is also MIT Licensed. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"author": "Richard Moore <[email protected]>", | ||
"dependencies": { | ||
"@ethersproject/abstract-provider": ">=5.0.0-beta.136", | ||
"@ethersproject/abstract-signer": ">=5.0.0-beta.137", | ||
"@ethersproject/address": ">=5.0.0-beta.134", | ||
"@ethersproject/bytes": ">=5.0.0-beta.134", | ||
"@ethersproject/properties": ">=5.0.0-beta.136", | ||
"@ethersproject/strings": ">=5.0.0-beta.135", | ||
"@ethersproject/transactions": ">=5.0.0-beta.133", | ||
"@ledgerhq/hw-app-eth": "5.3.0", | ||
"@ledgerhq/hw-transport": "5.3.0", | ||
"@ledgerhq/hw-transport-node-hid": "5.3.0", | ||
"@ledgerhq/hw-transport-u2f": "5.3.0" | ||
}, | ||
"description": "Hardware Wallet support for ethers.", | ||
"devDependencies": { | ||
"@types/node": "^12.7.4" | ||
}, | ||
"ethereum": "donations.ethers.eth", | ||
"keywords": [ | ||
"Ethereum", | ||
"ethers", | ||
"cli" | ||
], | ||
"license": "MIT", | ||
"main": "./lib/index.js", | ||
"module": "./lib.esm/index.js", | ||
"name": "@ethersproject/hardware-wallets", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/ethers-io/ethers.js.git" | ||
}, | ||
"scripts": { | ||
"test": "exit 1" | ||
}, | ||
"types": "./lib/index.d.ts", | ||
"version": "5.0.0-beta.1" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
"use strict"; | ||
|
||
import { LedgerSigner } from "./ledger"; | ||
|
||
export { | ||
LedgerSigner | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
"use strict"; | ||
|
||
import hid from "@ledgerhq/hw-transport-node-hid"; | ||
|
||
export type TransportCreator = { | ||
create: () => Promise<Transport>; | ||
}; | ||
|
||
export const transports: { [ name: string ]: TransportCreator } = { | ||
"hid": hid, | ||
"default": hid | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
"use strict"; | ||
|
||
import { getAddress } from "@ethersproject/address"; | ||
import { Bytes, hexlify, joinSignature } from "@ethersproject/bytes"; | ||
import { Signer } from "@ethersproject/abstract-signer"; | ||
import { Provider, TransactionRequest } from "@ethersproject/abstract-provider"; | ||
import { defineReadOnly, resolveProperties } from "@ethersproject/properties"; | ||
import { toUtf8Bytes } from "@ethersproject/strings"; | ||
import { serialize as serializeTransaction } from "@ethersproject/transactions"; | ||
|
||
import Eth from "@ledgerhq/hw-app-eth"; | ||
|
||
// We store these in a separated import so it is easier to swap them out | ||
// at bundle time; browsers do not get HID, for example. This maps a string | ||
// "type" to a Transport with create. | ||
import { transports } from "./ledger-transport"; | ||
|
||
const defaultPath = "m/44'/60'/0'/0/0"; | ||
|
||
export class LedgerSigner extends Signer { | ||
readonly type: string; | ||
readonly path: string | ||
|
||
readonly _eth: Promise<Eth>; | ||
|
||
constructor(provider?: Provider, type?: string, path?: string) { | ||
super(); | ||
if (path == null) { path = defaultPath; } | ||
if (type == null) { type = "default"; } | ||
|
||
defineReadOnly(this, "path", path); | ||
defineReadOnly(this, "type", type); | ||
defineReadOnly(this, "provider", provider || null); | ||
|
||
const transport = transports[type]; | ||
if (!transport) { throw new Error("unknown or unsupport type"); } | ||
|
||
defineReadOnly(this, "_eth", transport.create().then((transport) => { | ||
const eth = new Eth(transport); | ||
return eth.getAppConfiguration().then((config) => { | ||
return eth; | ||
}, (error) => { | ||
return Promise.reject(error); | ||
}); | ||
}, (error) => { | ||
return Promise.reject(error); | ||
})); | ||
} | ||
|
||
async getAddress(): Promise<string> { | ||
const eth = await this._eth; | ||
if (eth == null) { throw new Error("failed to connect"); } | ||
const o = await eth.getAddress(this.path); | ||
return getAddress(o.address); | ||
} | ||
|
||
async signMessage(message: Bytes | string): Promise<string> { | ||
if (typeof(message) === 'string') { | ||
message = toUtf8Bytes(message); | ||
} | ||
|
||
const messageHex = hexlify(message).substring(2); | ||
|
||
const eth = await this._eth; | ||
const sig = await eth.signPersonalMessage(this.path, messageHex); | ||
sig.r = '0x' + sig.r; | ||
sig.s = '0x' + sig.s; | ||
return joinSignature(sig); | ||
} | ||
|
||
async signTransaction(transaction: TransactionRequest): Promise<string> { | ||
const eth = await this._eth; | ||
return resolveProperties(transaction).then((tx) => { | ||
const unsignedTx = serializeTransaction(tx).substring(2); | ||
return eth.signTransaction(this.path, unsignedTx).then((sig) => { | ||
return serializeTransaction(tx, { | ||
v: sig.v, | ||
r: ("0x" + sig.r), | ||
s: ("0x" + sig.s), | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
connect(provider: Provider): Signer { | ||
return new LedgerSigner(provider, this.type, this.path); | ||
} | ||
} | ||
|
||
(async function() { | ||
const signer = new LedgerSigner(); | ||
console.log(signer); | ||
try { | ||
const sig = await signer.signMessage("Hello World"); | ||
console.log(sig); | ||
} catch (error) { | ||
console.log("ERR", error); | ||
} | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
declare module "@ledgerhq/hw-app-eth" { | ||
export type PublicAccount = { | ||
publicKey: string; | ||
address: string; | ||
chainCode: string; | ||
}; | ||
|
||
export type Config = { | ||
arbitraryDataEnabled: number, | ||
version: string | ||
}; | ||
|
||
export type Signature = { | ||
r: string, | ||
s: string, | ||
v: number | ||
}; | ||
|
||
export class Transport { } | ||
|
||
export class Eth { | ||
constructor(transport: Transport); | ||
getAppConfiguration(): Promise<Config>; | ||
getAddress(path: string): Promise<PublicAccount>; | ||
signPersonalMessage(path: string, message: string): Promise<Signature>; | ||
signTransaction(path: string, unsignedTx: string): Promise<Signature>; | ||
} | ||
|
||
export default Eth; | ||
} | ||
|
||
declare module "@ledgerhq/hw-transport-node-hid" { | ||
export function create(): Promise<Transport>; | ||
} | ||
|
||
declare module "@ledgerhq/hw-transport-u2f" { | ||
export function create(): Promise<Transport>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"extends": "../../tsconfig.package.json", | ||
"compilerOptions": { | ||
"rootDir": "./src.ts", | ||
"outDir": "./lib/" | ||
}, | ||
"include": [ | ||
"./thirdparty.d.ts", | ||
"./src.ts/*" | ||
], | ||
"exclude": [] | ||
} |