diff --git a/packages/subproviders/CHANGELOG.json b/packages/subproviders/CHANGELOG.json index f635219dde..ef29019143 100644 --- a/packages/subproviders/CHANGELOG.json +++ b/packages/subproviders/CHANGELOG.json @@ -1,4 +1,12 @@ [ + { + "version": "5.0.0", + "changes": [ + { + "note": "Remove eth-lightwallet subprovider" + } + ] + }, { "version": "4.1.2", "changes": [ diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index eceb633c62..d4d36184b7 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -37,12 +37,10 @@ "@0x/web3-wrapper": "^6.0.8", "@ledgerhq/hw-app-eth": "^4.3.0", "@ledgerhq/hw-transport-u2f": "4.24.0", - "@types/eth-lightwallet": "^3.0.0", "@types/hdkey": "^0.7.0", "@types/web3-provider-engine": "^14.0.0", "bip39": "^2.5.0", "bn.js": "^4.11.8", - "eth-lightwallet": "^3.0.1", "ethereum-types": "^2.1.4", "ethereumjs-tx": "^1.3.5", "ethereumjs-util": "^5.1.1", diff --git a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts b/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts deleted file mode 100644 index 15cd713af3..0000000000 --- a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { EIP712TypedData } from '@0x/types'; -import * as lightwallet from 'eth-lightwallet'; - -import { PartialTxParams } from '../types'; - -import { BaseWalletSubprovider } from './base_wallet_subprovider'; -import { PrivateKeyWalletSubprovider } from './private_key_wallet'; - -/* - * This class implements the web3-provider-engine subprovider interface and forwards - * requests involving user accounts and signing operations to eth-lightwallet - * - * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js - */ -export class EthLightwalletSubprovider extends BaseWalletSubprovider { - private readonly _keystore: lightwallet.keystore; - private readonly _pwDerivedKey: Uint8Array; - /** - * Instantiate an EthLightwalletSubprovider - * @param keystore The EthLightWallet keystore you wish to use - * @param pwDerivedKey The password derived key to use - * @return EthLightwalletSubprovider instance - */ - constructor(keystore: lightwallet.keystore, pwDerivedKey: Uint8Array) { - super(); - this._keystore = keystore; - this._pwDerivedKey = pwDerivedKey; - } - /** - * Retrieve the accounts associated with the eth-lightwallet instance. - * This method is implicitly called when issuing a `eth_accounts` JSON RPC request - * via your providerEngine instance. - * - * @return An array of accounts - */ - public async getAccountsAsync(): Promise { - const accounts = this._keystore.getAddresses(); - return accounts; - } - /** - * Signs a transaction with the account specificed by the `from` field in txParams. - * If you've added this Subprovider to your app's provider, you can simply send - * an `eth_sendTransaction` JSON RPC request, and this method will be called auto-magically. - * If you are not using this via a ProviderEngine instance, you can call it directly. - * @param txParams Parameters of the transaction to sign - * @return Signed transaction hex string - */ - public async signTransactionAsync(txParams: PartialTxParams): Promise { - // Lightwallet loses the chain id information when hex encoding the transaction - // this results in a different signature on certain networks. PrivateKeyWallet - // respects this as it uses the parameters passed in - let privateKey = this._keystore.exportPrivateKey(txParams.from, this._pwDerivedKey); - const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey); - privateKey = ''; - const privateKeySignature = await privateKeyWallet.signTransactionAsync(txParams); - return privateKeySignature; - } - /** - * Sign a personal Ethereum signed message. The signing account will be the account - * associated with the provided address. - * If you've added this Subprovider to your app's provider, you can simply send an `eth_sign` - * or `personal_sign` JSON RPC request, and this method will be called auto-magically. - * If you are not using this via a ProviderEngine instance, you can call it directly. - * @param data Hex string message to sign - * @param address Address of the account to sign with - * @return Signature hex string (order: rsv) - */ - public async signPersonalMessageAsync(data: string, address: string): Promise { - let privateKey = this._keystore.exportPrivateKey(address, this._pwDerivedKey); - const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey); - privateKey = ''; - const result = privateKeyWallet.signPersonalMessageAsync(data, address); - return result; - } - /** - * Sign an EIP712 Typed Data message. The signing address will associated with the provided address. - * If you've added this Subprovider to your app's provider, you can simply send an `eth_signTypedData` - * JSON RPC request, and this method will be called auto-magically. - * If you are not using this via a ProviderEngine instance, you can call it directly. - * @param address Address of the account to sign with - * @param data the typed data object - * @return Signature hex string (order: rsv) - */ - public async signTypedDataAsync(address: string, typedData: EIP712TypedData): Promise { - let privateKey = this._keystore.exportPrivateKey(address, this._pwDerivedKey); - const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey); - privateKey = ''; - const result = privateKeyWallet.signTypedDataAsync(address, typedData); - return result; - } -} diff --git a/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts b/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts deleted file mode 100644 index 468a9725f4..0000000000 --- a/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { providerUtils } from '@0x/utils'; -import * as chai from 'chai'; -import * as lightwallet from 'eth-lightwallet'; -import { JSONRPCResponsePayload } from 'ethereum-types'; -import * as ethUtils from 'ethereumjs-util'; - -import { EthLightwalletSubprovider, Web3ProviderEngine } from '../../src'; -import { DoneCallback } from '../../src/types'; -import { chaiSetup } from '../chai_setup'; -import { fixtureData } from '../utils/fixture_data'; -import { ganacheSubprovider } from '../utils/ganache_subprovider'; -import { reportCallbackErrors } from '../utils/report_callback_errors'; - -chaiSetup.configure(); -const expect = chai.expect; - -const DEFAULT_NUM_ACCOUNTS = 10; -const PASSWORD = 'supersecretpassword99'; -const SALT = 'kvODghzs7Ff1uqHyI0P3wI4Hso4w4iWT2e9qmrWz0y4'; - -describe('EthLightwalletSubprovider', () => { - let ethLightwalletSubprovider: EthLightwalletSubprovider; - before(async () => { - const options = { - password: PASSWORD, - seedPhrase: fixtureData.TEST_RPC_MNEMONIC, - salt: SALT, - hdPathString: fixtureData.TESTRPC_BASE_DERIVATION_PATH, - }; - const createVaultAsync = async (vaultOptions: lightwallet.VaultOptions) => { - return new Promise(resolve => { - lightwallet.keystore.createVault(vaultOptions, (err: Error, vaultKeystore) => { - if (err) { - throw new Error(`Failed to createVault: ${err}`); - } - resolve(vaultKeystore); - }); - }); - }; - const deriveKeyFromPasswordAsync = async (vaultKeystore: lightwallet.keystore) => { - return new Promise(resolve => { - vaultKeystore.keyFromPassword(PASSWORD, (err: Error, passwordDerivedKey: Uint8Array) => { - if (err) { - throw new Error(`Failed to get key from password: ${err}`); - } - resolve(passwordDerivedKey); - }); - }); - }; - const keystore: lightwallet.keystore = await createVaultAsync(options); - const pwDerivedKey: Uint8Array = await deriveKeyFromPasswordAsync(keystore); - - // Generate 10 addresses - keystore.generateNewAddress(pwDerivedKey, DEFAULT_NUM_ACCOUNTS); - - ethLightwalletSubprovider = new EthLightwalletSubprovider(keystore, pwDerivedKey); - }); - describe('direct method calls', () => { - describe('success cases', () => { - it('returns a list of accounts', async () => { - const accounts = await ethLightwalletSubprovider.getAccountsAsync(); - expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0); - expect(accounts[1]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_1); - expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); - }); - it('signs a personal message hash', async () => { - const accounts = await ethLightwalletSubprovider.getAccountsAsync(); - const signingAccount = accounts[0]; - const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); - const ecSignatureHex = await ethLightwalletSubprovider.signPersonalMessageAsync(data, signingAccount); - expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT); - }); - it('signs a transaction', async () => { - const txHex = await ethLightwalletSubprovider.signTransactionAsync(fixtureData.TX_DATA); - expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT); - }); - it('signs an EIP712 sign typed data message', async () => { - const signature = await ethLightwalletSubprovider.signTypedDataAsync( - fixtureData.TEST_RPC_ACCOUNT_0, - fixtureData.EIP712_TEST_TYPED_DATA, - ); - expect(signature).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT); - }); - }); - }); - describe('calls through a provider', () => { - let provider: Web3ProviderEngine; - before(() => { - provider = new Web3ProviderEngine(); - provider.addProvider(ethLightwalletSubprovider); - provider.addProvider(ganacheSubprovider); - providerUtils.startProviderEngine(provider); - }); - describe('success cases', () => { - it('returns a list of accounts', (done: DoneCallback) => { - const payload = { - jsonrpc: '2.0', - method: 'eth_accounts', - params: [], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { - expect(err).to.be.a('null'); - expect(response.result[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0); - expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); - done(); - }); - provider.sendAsync(payload, callback); - }); - it('signs a personal message hash with eth_sign', (done: DoneCallback) => { - const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); - const account = fixtureData.TEST_RPC_ACCOUNT_0; - const payload = { - jsonrpc: '2.0', - method: 'eth_sign', - params: [account, data], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { - expect(err).to.be.a('null'); - expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT); - done(); - }); - provider.sendAsync(payload, callback); - }); - it('signs a transaction', (done: DoneCallback) => { - const payload = { - jsonrpc: '2.0', - method: 'eth_signTransaction', - params: [fixtureData.TX_DATA], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { - expect(err).to.be.a('null'); - expect(response.result.raw).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT); - done(); - }); - provider.sendAsync(payload, callback); - }); - it('signs an EIP712 sign typed data message with eth_signTypedData', (done: DoneCallback) => { - const payload = { - jsonrpc: '2.0', - method: 'eth_signTypedData', - params: [fixtureData.TEST_RPC_ACCOUNT_0, fixtureData.EIP712_TEST_TYPED_DATA], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { - expect(err).to.be.a('null'); - expect(response.result).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT); - done(); - }); - provider.sendAsync(payload, callback); - }); - }); - describe('failure cases', () => { - it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => { - const nonHexMessage = 'hello world'; - const payload = { - jsonrpc: '2.0', - method: 'eth_sign', - params: [fixtureData.TEST_RPC_ACCOUNT_0, nonHexMessage], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { - expect(err).to.not.be.a('null'); - expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world'); - done(); - }); - provider.sendAsync(payload, callback); - }); - it('should throw if `data` param not hex when calling personal_sign', (done: DoneCallback) => { - const nonHexMessage = 'hello world'; - const payload = { - jsonrpc: '2.0', - method: 'personal_sign', - params: [nonHexMessage, fixtureData.TEST_RPC_ACCOUNT_0], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { - expect(err).to.not.be.a('null'); - expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world'); - done(); - }); - provider.sendAsync(payload, callback); - }); - }); - }); -});