aboutsummaryrefslogtreecommitdiffstats
path: root/packages/subproviders/src/subproviders/base_wallet_subprovider.ts
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2018-04-09 13:34:36 +0800
committerFabio Berger <me@fabioberger.com>2018-04-09 13:34:36 +0800
commite05b55d4a5698d3e936e7164ed69d9417d12cd12 (patch)
tree1f9be2d21d21cc915687f3606b2dad9e8a4add8e /packages/subproviders/src/subproviders/base_wallet_subprovider.ts
parent6f24337a5309bc4b06d0a91eac3af7566bde5754 (diff)
parent073bf738ddb271b6b4158798baf4cac3cb0608e9 (diff)
downloaddexon-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.ts137
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;
+ }
+}