diff options
author | Fabio Berger <me@fabioberger.com> | 2018-04-09 13:34:36 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-04-09 13:34:36 +0800 |
commit | e05b55d4a5698d3e936e7164ed69d9417d12cd12 (patch) | |
tree | 1f9be2d21d21cc915687f3606b2dad9e8a4add8e /packages/subproviders/src/subproviders/base_wallet_subprovider.ts | |
parent | 6f24337a5309bc4b06d0a91eac3af7566bde5754 (diff) | |
parent | 073bf738ddb271b6b4158798baf4cac3cb0608e9 (diff) | |
download | dexon-sol-tools-e05b55d4a5698d3e936e7164ed69d9417d12cd12.tar dexon-sol-tools-e05b55d4a5698d3e936e7164ed69d9417d12cd12.tar.gz dexon-sol-tools-e05b55d4a5698d3e936e7164ed69d9417d12cd12.tar.bz2 dexon-sol-tools-e05b55d4a5698d3e936e7164ed69d9417d12cd12.tar.lz dexon-sol-tools-e05b55d4a5698d3e936e7164ed69d9417d12cd12.tar.xz dexon-sol-tools-e05b55d4a5698d3e936e7164ed69d9417d12cd12.tar.zst dexon-sol-tools-e05b55d4a5698d3e936e7164ed69d9417d12cd12.zip |
merge development
Diffstat (limited to 'packages/subproviders/src/subproviders/base_wallet_subprovider.ts')
-rw-r--r-- | packages/subproviders/src/subproviders/base_wallet_subprovider.ts | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/packages/subproviders/src/subproviders/base_wallet_subprovider.ts b/packages/subproviders/src/subproviders/base_wallet_subprovider.ts new file mode 100644 index 000000000..034f83e7f --- /dev/null +++ b/packages/subproviders/src/subproviders/base_wallet_subprovider.ts @@ -0,0 +1,137 @@ +import { assert } from '@0xproject/assert'; +import { JSONRPCRequestPayload, JSONRPCResponsePayload } from '@0xproject/types'; +import { addressUtils } from '@0xproject/utils'; +import * as _ from 'lodash'; + +import { Callback, ErrorCallback, PartialTxParams, ResponseWithTxParams, WalletSubproviderErrors } from '../types'; + +import { Subprovider } from './subprovider'; + +export abstract class BaseWalletSubprovider extends Subprovider { + protected static _validateTxParams(txParams: PartialTxParams) { + assert.isETHAddressHex('to', txParams.to); + assert.isHexString('nonce', txParams.nonce); + assert.isHexString('gas', txParams.gas); + } + private static _validateSender(sender: string) { + if (_.isUndefined(sender) || !addressUtils.isAddress(sender)) { + throw new Error(WalletSubproviderErrors.SenderInvalidOrNotSupplied); + } + } + + public abstract async getAccountsAsync(): Promise<string[]>; + public abstract async signTransactionAsync(txParams: PartialTxParams): Promise<string>; + public abstract async signPersonalMessageAsync(data: string): Promise<string>; + + /** + * This method conforms to the web3-provider-engine interface. + * It is called internally by the ProviderEngine when it is this subproviders + * turn to handle a JSON RPC request. + * @param payload JSON RPC payload + * @param next Callback to call if this subprovider decides not to handle the request + * @param end Callback to call if subprovider handled the request and wants to pass back the request. + */ + // tslint:disable-next-line:async-suffix + public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback) { + let accounts; + let txParams; + switch (payload.method) { + case 'eth_coinbase': + try { + accounts = await this.getAccountsAsync(); + end(null, accounts[0]); + } catch (err) { + end(err); + } + return; + + case 'eth_accounts': + try { + accounts = await this.getAccountsAsync(); + end(null, accounts); + } catch (err) { + end(err); + } + return; + + case 'eth_sendTransaction': + txParams = payload.params[0]; + try { + BaseWalletSubprovider._validateSender(txParams.from); + const filledParams = await this._populateMissingTxParamsAsync(txParams); + const signedTx = await this.signTransactionAsync(filledParams); + const response = await this._emitSendTransactionAsync(signedTx); + end(null, response.result); + } catch (err) { + end(err); + } + return; + + case 'eth_signTransaction': + txParams = payload.params[0]; + try { + const filledParams = await this._populateMissingTxParamsAsync(txParams); + const signedTx = await this.signTransactionAsync(filledParams); + const result = { + raw: signedTx, + tx: txParams, + }; + end(null, result); + } catch (err) { + end(err); + } + return; + + case 'eth_sign': + case 'personal_sign': + const data = payload.method === 'eth_sign' ? payload.params[1] : payload.params[0]; + try { + const ecSignatureHex = await this.signPersonalMessageAsync(data); + end(null, ecSignatureHex); + } catch (err) { + end(err); + } + return; + + default: + next(); + return; + } + } + private async _emitSendTransactionAsync(signedTx: string): Promise<JSONRPCResponsePayload> { + const payload = { + method: 'eth_sendRawTransaction', + params: [signedTx], + }; + const result = await this.emitPayloadAsync(payload); + return result; + } + private async _populateMissingTxParamsAsync(partialTxParams: PartialTxParams): Promise<PartialTxParams> { + let txParams = partialTxParams; + if (_.isUndefined(partialTxParams.gasPrice)) { + const gasPriceResult = await this.emitPayloadAsync({ + method: 'eth_gasPrice', + params: [], + }); + const gasPrice = gasPriceResult.result.toString(); + txParams = { ...txParams, gasPrice }; + } + if (_.isUndefined(partialTxParams.nonce)) { + const nonceResult = await this.emitPayloadAsync({ + method: 'eth_getTransactionCount', + params: [partialTxParams.from, 'pending'], + }); + const nonce = nonceResult.result; + txParams = { ...txParams, nonce }; + } + if (_.isUndefined(partialTxParams.gas)) { + const gasResult = await this.emitPayloadAsync({ + method: 'eth_estimateGas', + params: [partialTxParams], + }); + const gas = gasResult.result.toString(); + txParams = { ...txParams, gas }; + } + return txParams; + } +} |