Introduce SignerProviderType
This allows the developer to indicate the nuanced signer provider. Some have different implementations (trezor, ledger) and others have different implementations (metamask). Breaking the abstraction of eth_sign. EthSign assumes a spec compliant implementation and can be used as a default
This commit is contained in:
		@@ -21,6 +21,9 @@
 | 
				
			|||||||
        "changes": [
 | 
					        "changes": [
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                "note": "Dependencies updated"
 | 
					                "note": "Dependencies updated"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "note": "Update ecSignOrderHashAsync to return the signature as a string for immediate use in contracts"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        "timestamp": 1532605697
 | 
					        "timestamp": 1532605697
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,13 +14,19 @@ import {
 | 
				
			|||||||
    ecSignOrderHashAsync,
 | 
					    ecSignOrderHashAsync,
 | 
				
			||||||
    generatePseudoRandomSalt,
 | 
					    generatePseudoRandomSalt,
 | 
				
			||||||
    isValidSignatureAsync,
 | 
					    isValidSignatureAsync,
 | 
				
			||||||
    MessagePrefixOpts,
 | 
					 | 
				
			||||||
    orderHashUtils,
 | 
					    orderHashUtils,
 | 
				
			||||||
} from '@0xproject/order-utils';
 | 
					} from '@0xproject/order-utils';
 | 
				
			||||||
// HACK: Since we export assetDataUtils from ZeroEx and it has AssetProxyId, ERC20AssetData and ERC721AssetData
 | 
					// HACK: Since we export assetDataUtils from ZeroEx and it has AssetProxyId, ERC20AssetData and ERC721AssetData
 | 
				
			||||||
// in it's public interface, we need to import these types here.
 | 
					// in it's public interface, we need to import these types here.
 | 
				
			||||||
// tslint:disable-next-line:no-unused-variable
 | 
					// tslint:disable-next-line:no-unused-variable
 | 
				
			||||||
import { AssetProxyId, ECSignature, ERC20AssetData, ERC721AssetData, Order, SignedOrder } from '@0xproject/types';
 | 
					import {
 | 
				
			||||||
 | 
					    AssetProxyId,
 | 
				
			||||||
 | 
					    ERC20AssetData,
 | 
				
			||||||
 | 
					    ERC721AssetData,
 | 
				
			||||||
 | 
					    Order,
 | 
				
			||||||
 | 
					    SignedOrder,
 | 
				
			||||||
 | 
					    SignerProviderType,
 | 
				
			||||||
 | 
					} from '@0xproject/types';
 | 
				
			||||||
import { BigNumber } from '@0xproject/utils';
 | 
					import { BigNumber } from '@0xproject/utils';
 | 
				
			||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
 | 
					import { Web3Wrapper } from '@0xproject/web3-wrapper';
 | 
				
			||||||
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
 | 
					import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
 | 
				
			||||||
@@ -238,19 +244,19 @@ export class ZeroEx {
 | 
				
			|||||||
     * @param   orderHash       Hex encoded orderHash to sign.
 | 
					     * @param   orderHash       Hex encoded orderHash to sign.
 | 
				
			||||||
     * @param   signerAddress   The hex encoded Ethereum address you wish to sign it with. This address
 | 
					     * @param   signerAddress   The hex encoded Ethereum address you wish to sign it with. This address
 | 
				
			||||||
     *          must be available via the Provider supplied to 0x.js.
 | 
					     *          must be available via the Provider supplied to 0x.js.
 | 
				
			||||||
     * @param   MessagePrefixOpts  Options regarding the desired prefix and whether to add it before calling `eth_sign`
 | 
					     * @param   SignerProviderType  The type of Signer Provider which implements `eth_sign`. E.g Metamask, Ledger, Trezor or EthSign.
 | 
				
			||||||
     * @return  An object containing the Elliptic curve signature parameters generated by signing the orderHash.
 | 
					     * @return  A hex encoded string of the Elliptic curve signature parameters generated by signing the orderHash and signature type.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public async ecSignOrderHashAsync(
 | 
					    public async ecSignOrderHashAsync(
 | 
				
			||||||
        orderHash: string,
 | 
					        orderHash: string,
 | 
				
			||||||
        signerAddress: string,
 | 
					        signerAddress: string,
 | 
				
			||||||
        messagePrefixOpts: MessagePrefixOpts,
 | 
					        signerProviderType: SignerProviderType,
 | 
				
			||||||
    ): Promise<ECSignature> {
 | 
					    ): Promise<string> {
 | 
				
			||||||
        const signature = await ecSignOrderHashAsync(
 | 
					        const signature = await ecSignOrderHashAsync(
 | 
				
			||||||
            this._contractWrappers.getProvider(),
 | 
					            this._contractWrappers.getProvider(),
 | 
				
			||||||
            orderHash,
 | 
					            orderHash,
 | 
				
			||||||
            signerAddress,
 | 
					            signerAddress,
 | 
				
			||||||
            messagePrefixOpts,
 | 
					            signerProviderType,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        return signature;
 | 
					        return signature;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,12 @@
 | 
				
			|||||||
export { ZeroEx } from './0x';
 | 
					export { ZeroEx } from './0x';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export { MessagePrefixType, MessagePrefixOpts } from '@0xproject/order-utils';
 | 
					 | 
				
			||||||
export { Web3ProviderEngine, RPCSubprovider } from '@0xproject/subproviders';
 | 
					export { Web3ProviderEngine, RPCSubprovider } from '@0xproject/subproviders';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export {
 | 
					export {
 | 
				
			||||||
    ExchangeContractErrs,
 | 
					    ExchangeContractErrs,
 | 
				
			||||||
    Order,
 | 
					    Order,
 | 
				
			||||||
    SignedOrder,
 | 
					    SignedOrder,
 | 
				
			||||||
 | 
					    SignerProviderType,
 | 
				
			||||||
    ECSignature,
 | 
					    ECSignature,
 | 
				
			||||||
    OrderStateValid,
 | 
					    OrderStateValid,
 | 
				
			||||||
    OrderStateInvalid,
 | 
					    OrderStateInvalid,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
 | 
					import { BlockchainLifecycle } from '@0xproject/dev-utils';
 | 
				
			||||||
import { addSignedMessagePrefix, assetDataUtils, MessagePrefixType, orderHashUtils } from '@0xproject/order-utils';
 | 
					import { addSignedMessagePrefix, assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
 | 
				
			||||||
import { RevertReason, SignatureType, SignedOrder } from '@0xproject/types';
 | 
					import { RevertReason, SignatureType, SignedOrder, SignerProviderType } from '@0xproject/types';
 | 
				
			||||||
import * as chai from 'chai';
 | 
					import * as chai from 'chai';
 | 
				
			||||||
import { LogWithDecodedArgs } from 'ethereum-types';
 | 
					import { LogWithDecodedArgs } from 'ethereum-types';
 | 
				
			||||||
import ethUtil = require('ethereumjs-util');
 | 
					import ethUtil = require('ethereumjs-util');
 | 
				
			||||||
@@ -213,7 +213,7 @@ describe('MixinSignatureValidator', () => {
 | 
				
			|||||||
        it('should return true when SignatureType=EthSign and signature is valid', async () => {
 | 
					        it('should return true when SignatureType=EthSign and signature is valid', async () => {
 | 
				
			||||||
            // Create EthSign signature
 | 
					            // Create EthSign signature
 | 
				
			||||||
            const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
 | 
					            const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
 | 
				
			||||||
            const orderHashWithEthSignPrefixHex = addSignedMessagePrefix(orderHashHex, MessagePrefixType.EthSign);
 | 
					            const orderHashWithEthSignPrefixHex = addSignedMessagePrefix(orderHashHex, SignerProviderType.EthSign);
 | 
				
			||||||
            const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex);
 | 
					            const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex);
 | 
				
			||||||
            const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey);
 | 
					            const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey);
 | 
				
			||||||
            // Create 0x signature from EthSign signature
 | 
					            // Create 0x signature from EthSign signature
 | 
				
			||||||
@@ -236,7 +236,7 @@ describe('MixinSignatureValidator', () => {
 | 
				
			|||||||
        it('should return false when SignatureType=EthSign and signature is invalid', async () => {
 | 
					        it('should return false when SignatureType=EthSign and signature is invalid', async () => {
 | 
				
			||||||
            // Create EthSign signature
 | 
					            // Create EthSign signature
 | 
				
			||||||
            const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
 | 
					            const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
 | 
				
			||||||
            const orderHashWithEthSignPrefixHex = addSignedMessagePrefix(orderHashHex, MessagePrefixType.EthSign);
 | 
					            const orderHashWithEthSignPrefixHex = addSignedMessagePrefix(orderHashHex, SignerProviderType.EthSign);
 | 
				
			||||||
            const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex);
 | 
					            const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex);
 | 
				
			||||||
            const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey);
 | 
					            const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey);
 | 
				
			||||||
            // Create 0x signature from EthSign signature
 | 
					            // Create 0x signature from EthSign signature
 | 
				
			||||||
@@ -385,7 +385,7 @@ describe('MixinSignatureValidator', () => {
 | 
				
			|||||||
        it('should return true when SignatureType=Trezor and signature is valid', async () => {
 | 
					        it('should return true when SignatureType=Trezor and signature is valid', async () => {
 | 
				
			||||||
            // Create Trezor signature
 | 
					            // Create Trezor signature
 | 
				
			||||||
            const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
 | 
					            const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
 | 
				
			||||||
            const orderHashWithTrezorPrefixHex = addSignedMessagePrefix(orderHashHex, MessagePrefixType.Trezor);
 | 
					            const orderHashWithTrezorPrefixHex = addSignedMessagePrefix(orderHashHex, SignerProviderType.Trezor);
 | 
				
			||||||
            const orderHashWithTrezorPrefixBuffer = ethUtil.toBuffer(orderHashWithTrezorPrefixHex);
 | 
					            const orderHashWithTrezorPrefixBuffer = ethUtil.toBuffer(orderHashWithTrezorPrefixHex);
 | 
				
			||||||
            const ecSignature = ethUtil.ecsign(orderHashWithTrezorPrefixBuffer, signerPrivateKey);
 | 
					            const ecSignature = ethUtil.ecsign(orderHashWithTrezorPrefixBuffer, signerPrivateKey);
 | 
				
			||||||
            // Create 0x signature from Trezor signature
 | 
					            // Create 0x signature from Trezor signature
 | 
				
			||||||
@@ -408,7 +408,7 @@ describe('MixinSignatureValidator', () => {
 | 
				
			|||||||
        it('should return false when SignatureType=Trezor and signature is invalid', async () => {
 | 
					        it('should return false when SignatureType=Trezor and signature is invalid', async () => {
 | 
				
			||||||
            // Create Trezor signature
 | 
					            // Create Trezor signature
 | 
				
			||||||
            const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
 | 
					            const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
 | 
				
			||||||
            const orderHashWithTrezorPrefixHex = addSignedMessagePrefix(orderHashHex, MessagePrefixType.Trezor);
 | 
					            const orderHashWithTrezorPrefixHex = addSignedMessagePrefix(orderHashHex, SignerProviderType.Trezor);
 | 
				
			||||||
            const orderHashWithTrezorPrefixBuffer = ethUtil.toBuffer(orderHashWithTrezorPrefixHex);
 | 
					            const orderHashWithTrezorPrefixBuffer = ethUtil.toBuffer(orderHashWithTrezorPrefixHex);
 | 
				
			||||||
            const ecSignature = ethUtil.ecsign(orderHashWithTrezorPrefixBuffer, signerPrivateKey);
 | 
					            const ecSignature = ethUtil.ecsign(orderHashWithTrezorPrefixBuffer, signerPrivateKey);
 | 
				
			||||||
            // Create 0x signature from Trezor signature
 | 
					            // Create 0x signature from Trezor signature
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,6 +30,9 @@
 | 
				
			|||||||
        "changes": [
 | 
					        "changes": [
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                "note": "Dependencies updated"
 | 
					                "note": "Dependencies updated"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "note": "Update ecSignOrderHashAsync to return signature string with signature type byte"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        "timestamp": 1532605697
 | 
					        "timestamp": 1532605697
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,15 +13,7 @@ export { orderFactory } from './order_factory';
 | 
				
			|||||||
export { constants } from './constants';
 | 
					export { constants } from './constants';
 | 
				
			||||||
export { crypto } from './crypto';
 | 
					export { crypto } from './crypto';
 | 
				
			||||||
export { generatePseudoRandomSalt } from './salt';
 | 
					export { generatePseudoRandomSalt } from './salt';
 | 
				
			||||||
export {
 | 
					export { CreateOrderOpts, OrderError, EIP712Parameter, EIP712Schema, EIP712Types } from './types';
 | 
				
			||||||
    CreateOrderOpts,
 | 
					 | 
				
			||||||
    OrderError,
 | 
					 | 
				
			||||||
    MessagePrefixType,
 | 
					 | 
				
			||||||
    MessagePrefixOpts,
 | 
					 | 
				
			||||||
    EIP712Parameter,
 | 
					 | 
				
			||||||
    EIP712Schema,
 | 
					 | 
				
			||||||
    EIP712Types,
 | 
					 | 
				
			||||||
} from './types';
 | 
					 | 
				
			||||||
export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
 | 
					export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
 | 
				
			||||||
export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
 | 
					export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
 | 
				
			||||||
export { BalanceAndProxyAllowanceLazyStore } from './store/balance_and_proxy_allowance_lazy_store';
 | 
					export { BalanceAndProxyAllowanceLazyStore } from './store/balance_and_proxy_allowance_lazy_store';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +1,13 @@
 | 
				
			|||||||
import { ECSignature, Order, SignedOrder } from '@0xproject/types';
 | 
					import { Order, SignedOrder, SignerProviderType } from '@0xproject/types';
 | 
				
			||||||
import { BigNumber } from '@0xproject/utils';
 | 
					import { BigNumber } from '@0xproject/utils';
 | 
				
			||||||
import { Provider } from 'ethereum-types';
 | 
					import { Provider } from 'ethereum-types';
 | 
				
			||||||
import * as ethUtil from 'ethereumjs-util';
 | 
					 | 
				
			||||||
import * as _ from 'lodash';
 | 
					import * as _ from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { constants } from './constants';
 | 
					import { constants } from './constants';
 | 
				
			||||||
import { orderHashUtils } from './order_hash';
 | 
					import { orderHashUtils } from './order_hash';
 | 
				
			||||||
import { generatePseudoRandomSalt } from './salt';
 | 
					import { generatePseudoRandomSalt } from './salt';
 | 
				
			||||||
import { ecSignOrderHashAsync } from './signature_utils';
 | 
					import { ecSignOrderHashAsync } from './signature_utils';
 | 
				
			||||||
import { CreateOrderOpts, MessagePrefixType } from './types';
 | 
					import { CreateOrderOpts } from './types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const orderFactory = {
 | 
					export const orderFactory = {
 | 
				
			||||||
    createOrder(
 | 
					    createOrder(
 | 
				
			||||||
@@ -59,16 +58,12 @@ export const orderFactory = {
 | 
				
			|||||||
            createOrderOpts,
 | 
					            createOrderOpts,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        const orderHash = orderHashUtils.getOrderHashHex(order);
 | 
					        const orderHash = orderHashUtils.getOrderHashHex(order);
 | 
				
			||||||
        const messagePrefixOpts = {
 | 
					        const signature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, SignerProviderType.EthSign);
 | 
				
			||||||
            prefixType: MessagePrefixType.EthSign,
 | 
					 | 
				
			||||||
            shouldAddPrefixBeforeCallingEthSign: false,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        const ecSignature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, messagePrefixOpts);
 | 
					 | 
				
			||||||
        const signature = getVRSHexString(ecSignature);
 | 
					 | 
				
			||||||
        const signedOrder: SignedOrder = _.assign(order, { signature });
 | 
					        const signedOrder: SignedOrder = _.assign(order, { signature });
 | 
				
			||||||
        return signedOrder;
 | 
					        return signedOrder;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function generateDefaultCreateOrderOpts(): {
 | 
					function generateDefaultCreateOrderOpts(): {
 | 
				
			||||||
    takerAddress: string;
 | 
					    takerAddress: string;
 | 
				
			||||||
@@ -102,3 +97,5 @@ function intToHex(i: number): string {
 | 
				
			|||||||
    const hex = ethUtil.bufferToHex(ethUtil.toBuffer(i));
 | 
					    const hex = ethUtil.bufferToHex(ethUtil.toBuffer(i));
 | 
				
			||||||
    return hex;
 | 
					    return hex;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					>>>>>>> Introduce SignerProviderType
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
import { schemas } from '@0xproject/json-schemas';
 | 
					import { schemas } from '@0xproject/json-schemas';
 | 
				
			||||||
import { ECSignature, SignatureType, ValidatorSignature } from '@0xproject/types';
 | 
					import { ECSignature, SignatureType, SignerProviderType, ValidatorSignature } from '@0xproject/types';
 | 
				
			||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
 | 
					import { Web3Wrapper } from '@0xproject/web3-wrapper';
 | 
				
			||||||
import { Provider } from 'ethereum-types';
 | 
					import { Provider } from 'ethereum-types';
 | 
				
			||||||
import * as ethUtil from 'ethereumjs-util';
 | 
					import * as ethUtil from 'ethereumjs-util';
 | 
				
			||||||
@@ -10,7 +10,7 @@ import { assert } from './assert';
 | 
				
			|||||||
import { ExchangeContract } from './generated_contract_wrappers/exchange';
 | 
					import { ExchangeContract } from './generated_contract_wrappers/exchange';
 | 
				
			||||||
import { IValidatorContract } from './generated_contract_wrappers/i_validator';
 | 
					import { IValidatorContract } from './generated_contract_wrappers/i_validator';
 | 
				
			||||||
import { IWalletContract } from './generated_contract_wrappers/i_wallet';
 | 
					import { IWalletContract } from './generated_contract_wrappers/i_wallet';
 | 
				
			||||||
import { MessagePrefixOpts, MessagePrefixType, OrderError } from './types';
 | 
					import { OrderError } from './types';
 | 
				
			||||||
import { utils } from './utils';
 | 
					import { utils } from './utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -48,7 +48,7 @@ export async function isValidSignatureAsync(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        case SignatureType.EthSign: {
 | 
					        case SignatureType.EthSign: {
 | 
				
			||||||
            const ecSignature = parseECSignature(signature);
 | 
					            const ecSignature = parseECSignature(signature);
 | 
				
			||||||
            const prefixedMessageHex = addSignedMessagePrefix(data, MessagePrefixType.EthSign);
 | 
					            const prefixedMessageHex = addSignedMessagePrefix(data, SignerProviderType.EthSign);
 | 
				
			||||||
            return isValidECSignature(prefixedMessageHex, ecSignature, signerAddress);
 | 
					            return isValidECSignature(prefixedMessageHex, ecSignature, signerAddress);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -72,7 +72,7 @@ export async function isValidSignatureAsync(
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case SignatureType.Trezor: {
 | 
					        case SignatureType.Trezor: {
 | 
				
			||||||
            const prefixedMessageHex = addSignedMessagePrefix(data, MessagePrefixType.Trezor);
 | 
					            const prefixedMessageHex = addSignedMessagePrefix(data, SignerProviderType.Trezor);
 | 
				
			||||||
            const ecSignature = parseECSignature(signature);
 | 
					            const ecSignature = parseECSignature(signature);
 | 
				
			||||||
            return isValidECSignature(prefixedMessageHex, ecSignature, signerAddress);
 | 
					            return isValidECSignature(prefixedMessageHex, ecSignature, signerAddress);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -191,22 +191,22 @@ export function isValidECSignature(data: string, signature: ECSignature, signerA
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Signs an orderHash and returns it's elliptic curve signature.
 | 
					 * Signs an orderHash and returns it's elliptic curve signature and signature type.
 | 
				
			||||||
 * This method currently supports TestRPC, Geth and Parity above and below V1.6.6
 | 
					 * This method currently supports TestRPC, Geth and Parity above and below V1.6.6
 | 
				
			||||||
 * @param   orderHash       Hex encoded orderHash to sign.
 | 
					 * @param   orderHash       Hex encoded orderHash to sign.
 | 
				
			||||||
 * @param   signerAddress   The hex encoded Ethereum address you wish to sign it with. This address
 | 
					 * @param   signerAddress   The hex encoded Ethereum address you wish to sign it with. This address
 | 
				
			||||||
 *          must be available via the Provider supplied to 0x.js.
 | 
					 *          must be available via the Provider supplied to 0x.js.
 | 
				
			||||||
 * @param   hashPrefixOpts Different signers add/require different prefixes be appended to the message being signed.
 | 
					 * @param   messagePrefixOpts Different signers add/require different prefixes be prepended to the message being signed.
 | 
				
			||||||
 *          Since we cannot know ahead of time which signer you are using, you must supply both a prefixType and
 | 
					 *          Since we cannot know ahead of time which signer you are using, you must supply both a prefixType and
 | 
				
			||||||
 *          whether it must be added before calling `eth_sign` (some signers add it themselves)
 | 
					 *          whether it must be added before calling `eth_sign` (some signers add it themselves)
 | 
				
			||||||
 * @return  An object containing the Elliptic curve signature parameters generated by signing the orderHash.
 | 
					 * @return  A hex encoded string containing the Elliptic curve signature generated by signing the orderHash and the Signature Type.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export async function ecSignOrderHashAsync(
 | 
					export async function ecSignOrderHashAsync(
 | 
				
			||||||
    provider: Provider,
 | 
					    provider: Provider,
 | 
				
			||||||
    orderHash: string,
 | 
					    orderHash: string,
 | 
				
			||||||
    signerAddress: string,
 | 
					    signerAddress: string,
 | 
				
			||||||
    messagePrefixOpts: MessagePrefixOpts,
 | 
					    signerProviderType: SignerProviderType,
 | 
				
			||||||
): Promise<ECSignature> {
 | 
					): Promise<string> {
 | 
				
			||||||
    assert.isWeb3Provider('provider', provider);
 | 
					    assert.isWeb3Provider('provider', provider);
 | 
				
			||||||
    assert.isHexString('orderHash', orderHash);
 | 
					    assert.isHexString('orderHash', orderHash);
 | 
				
			||||||
    assert.isETHAddressHex('signerAddress', signerAddress);
 | 
					    assert.isETHAddressHex('signerAddress', signerAddress);
 | 
				
			||||||
@@ -215,8 +215,9 @@ export async function ecSignOrderHashAsync(
 | 
				
			|||||||
    const normalizedSignerAddress = signerAddress.toLowerCase();
 | 
					    const normalizedSignerAddress = signerAddress.toLowerCase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let msgHashHex = orderHash;
 | 
					    let msgHashHex = orderHash;
 | 
				
			||||||
    const prefixedMsgHashHex = addSignedMessagePrefix(orderHash, messagePrefixOpts.prefixType);
 | 
					    const prefixedMsgHashHex = addSignedMessagePrefix(orderHash, signerProviderType);
 | 
				
			||||||
    if (messagePrefixOpts.shouldAddPrefixBeforeCallingEthSign) {
 | 
					    // Metamask incorrectly implements eth_sign and does not prefix the message as per the spec
 | 
				
			||||||
 | 
					    if (signerProviderType === SignerProviderType.Metamask) {
 | 
				
			||||||
        msgHashHex = prefixedMsgHashHex;
 | 
					        msgHashHex = prefixedMsgHashHex;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const signature = await web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex);
 | 
					    const signature = await web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex);
 | 
				
			||||||
@@ -231,7 +232,8 @@ export async function ecSignOrderHashAsync(
 | 
				
			|||||||
    if (_.includes(validVParamValues, ecSignatureVRS.v)) {
 | 
					    if (_.includes(validVParamValues, ecSignatureVRS.v)) {
 | 
				
			||||||
        const isValidVRSSignature = isValidECSignature(prefixedMsgHashHex, ecSignatureVRS, normalizedSignerAddress);
 | 
					        const isValidVRSSignature = isValidECSignature(prefixedMsgHashHex, ecSignatureVRS, normalizedSignerAddress);
 | 
				
			||||||
        if (isValidVRSSignature) {
 | 
					        if (isValidVRSSignature) {
 | 
				
			||||||
            return ecSignatureVRS;
 | 
					            const convertedSignatureHex = convertECSignatureToSignatureHex(ecSignatureVRS, signerProviderType);
 | 
				
			||||||
 | 
					            return convertedSignatureHex;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -239,13 +241,45 @@ export async function ecSignOrderHashAsync(
 | 
				
			|||||||
    if (_.includes(validVParamValues, ecSignatureRSV.v)) {
 | 
					    if (_.includes(validVParamValues, ecSignatureRSV.v)) {
 | 
				
			||||||
        const isValidRSVSignature = isValidECSignature(prefixedMsgHashHex, ecSignatureRSV, normalizedSignerAddress);
 | 
					        const isValidRSVSignature = isValidECSignature(prefixedMsgHashHex, ecSignatureRSV, normalizedSignerAddress);
 | 
				
			||||||
        if (isValidRSVSignature) {
 | 
					        if (isValidRSVSignature) {
 | 
				
			||||||
            return ecSignatureRSV;
 | 
					            const convertedSignatureHex = convertECSignatureToSignatureHex(ecSignatureRSV, signerProviderType);
 | 
				
			||||||
 | 
					            return convertedSignatureHex;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    throw new Error(OrderError.InvalidSignature);
 | 
					    throw new Error(OrderError.InvalidSignature);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Combines ECSignature with V,R,S and the relevant signature type for use in 0x protocol
 | 
				
			||||||
 | 
					 * @param ecSignature The ECSignature of the signed data
 | 
				
			||||||
 | 
					 * @param messagePrefixType The MessagePrefixType of the signed data
 | 
				
			||||||
 | 
					 * @return Hex encoded string of signature with Signature Type
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function convertECSignatureToSignatureHex(
 | 
				
			||||||
 | 
					    ecSignature: ECSignature,
 | 
				
			||||||
 | 
					    signerProviderType: SignerProviderType,
 | 
				
			||||||
 | 
					): string {
 | 
				
			||||||
 | 
					    const signatureBuffer = Buffer.concat([
 | 
				
			||||||
 | 
					        ethUtil.toBuffer(ecSignature.v),
 | 
				
			||||||
 | 
					        ethUtil.toBuffer(ecSignature.r),
 | 
				
			||||||
 | 
					        ethUtil.toBuffer(ecSignature.s),
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    const signatureHex = `0x${signatureBuffer.toString('hex')}`;
 | 
				
			||||||
 | 
					    const signatureType =
 | 
				
			||||||
 | 
					        signerProviderType === SignerProviderType.Trezor ? SignatureType.Trezor : SignatureType.EthSign;
 | 
				
			||||||
 | 
					    const signatureWithType = convertToSignatureWithType(signatureHex, signatureType);
 | 
				
			||||||
 | 
					    return signatureWithType;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Combines the signature proof and the Signature Type.
 | 
				
			||||||
 | 
					 * @param signature The hex encoded signature proof
 | 
				
			||||||
 | 
					 * @param type The signature type, i.e EthSign, Trezor, Wallet etc.
 | 
				
			||||||
 | 
					 * @return Hex encoded string of signature proof with Signature Type
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function convertToSignatureWithType(signature: string, type: SignatureType): string {
 | 
				
			||||||
 | 
					    const signatureBuffer = Buffer.concat([ethUtil.toBuffer(signature), ethUtil.toBuffer(type)]);
 | 
				
			||||||
 | 
					    const signatureHex = `0x${signatureBuffer.toString('hex')}`;
 | 
				
			||||||
 | 
					    return signatureHex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Adds the relevant prefix to the message being signed.
 | 
					 * Adds the relevant prefix to the message being signed.
 | 
				
			||||||
 * @param message Message to sign
 | 
					 * @param message Message to sign
 | 
				
			||||||
@@ -253,29 +287,25 @@ export async function ecSignOrderHashAsync(
 | 
				
			|||||||
 *                          specific message prefixes.
 | 
					 *                          specific message prefixes.
 | 
				
			||||||
 * @return Prefixed message
 | 
					 * @return Prefixed message
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function addSignedMessagePrefix(message: string, messagePrefixType: MessagePrefixType): string {
 | 
					export function addSignedMessagePrefix(message: string, signerProviderType: SignerProviderType): string {
 | 
				
			||||||
    assert.isString('message', message);
 | 
					    assert.isString('message', message);
 | 
				
			||||||
    assert.doesBelongToStringEnum('messagePrefixType', messagePrefixType, MessagePrefixType);
 | 
					    assert.doesBelongToStringEnum('signerProviderType', signerProviderType, SignerProviderType);
 | 
				
			||||||
    switch (messagePrefixType) {
 | 
					    switch (signerProviderType) {
 | 
				
			||||||
        case MessagePrefixType.None:
 | 
					        case SignerProviderType.Metamask:
 | 
				
			||||||
            return message;
 | 
					        case SignerProviderType.EthSign: {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        case MessagePrefixType.EthSign: {
 | 
					 | 
				
			||||||
            const msgBuff = ethUtil.toBuffer(message);
 | 
					            const msgBuff = ethUtil.toBuffer(message);
 | 
				
			||||||
            const prefixedMsgBuff = ethUtil.hashPersonalMessage(msgBuff);
 | 
					            const prefixedMsgBuff = ethUtil.hashPersonalMessage(msgBuff);
 | 
				
			||||||
            const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
 | 
					            const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
 | 
				
			||||||
            return prefixedMsgHex;
 | 
					            return prefixedMsgHex;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        case SignerProviderType.Trezor: {
 | 
				
			||||||
        case MessagePrefixType.Trezor: {
 | 
					 | 
				
			||||||
            const msgBuff = ethUtil.toBuffer(message);
 | 
					            const msgBuff = ethUtil.toBuffer(message);
 | 
				
			||||||
            const prefixedMsgBuff = hashTrezorPersonalMessage(msgBuff);
 | 
					            const prefixedMsgBuff = hashTrezorPersonalMessage(msgBuff);
 | 
				
			||||||
            const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
 | 
					            const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
 | 
				
			||||||
            return prefixedMsgHex;
 | 
					            return prefixedMsgHex;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            throw new Error(`Unrecognized MessagePrefixType: ${messagePrefixType}`);
 | 
					            throw new Error(`Unrecognized SignerProviderType: ${signerProviderType}`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,28 +4,6 @@ export enum OrderError {
 | 
				
			|||||||
    InvalidSignature = 'INVALID_SIGNATURE',
 | 
					    InvalidSignature = 'INVALID_SIGNATURE',
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * The requisite message prefix (is any) to add to an `eth_sign` request.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export enum MessagePrefixType {
 | 
					 | 
				
			||||||
    None = 'NONE',
 | 
					 | 
				
			||||||
    EthSign = 'ETH_SIGN',
 | 
					 | 
				
			||||||
    Trezor = 'TREZOR',
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Options related to message prefixing of messages sent to `eth_sign`
 | 
					 | 
				
			||||||
 * Some signers prepend a message prefix (e.g Parity Signer, Ledger, TestRPC), while
 | 
					 | 
				
			||||||
 * others require it already be prepended (e.g Metamask). In addition, different signers
 | 
					 | 
				
			||||||
 * expect slightly different prefixes (See: https://github.com/ethereum/go-ethereum/issues/14794).
 | 
					 | 
				
			||||||
 * Depending on the signer that will receive your signing request, you must specify the
 | 
					 | 
				
			||||||
 * desired prefix and whether it should be added before making the `eth_sign` request.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export interface MessagePrefixOpts {
 | 
					 | 
				
			||||||
    prefixType: MessagePrefixType;
 | 
					 | 
				
			||||||
    shouldAddPrefixBeforeCallingEthSign: boolean;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export enum TradeSide {
 | 
					export enum TradeSide {
 | 
				
			||||||
    Maker = 'maker',
 | 
					    Maker = 'maker',
 | 
				
			||||||
    Taker = 'taker',
 | 
					    Taker = 'taker',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import { SignerProviderType } from '@0xproject/types';
 | 
				
			||||||
import { BigNumber } from '@0xproject/utils';
 | 
					import { BigNumber } from '@0xproject/utils';
 | 
				
			||||||
import * as chai from 'chai';
 | 
					import * as chai from 'chai';
 | 
				
			||||||
import { JSONRPCErrorCallback, JSONRPCRequestPayload } from 'ethereum-types';
 | 
					import { JSONRPCErrorCallback, JSONRPCRequestPayload } from 'ethereum-types';
 | 
				
			||||||
@@ -5,7 +6,7 @@ import * as _ from 'lodash';
 | 
				
			|||||||
import 'mocha';
 | 
					import 'mocha';
 | 
				
			||||||
import * as Sinon from 'sinon';
 | 
					import * as Sinon from 'sinon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { ecSignOrderHashAsync, generatePseudoRandomSalt, MessagePrefixType } from '../src';
 | 
					import { ecSignOrderHashAsync, generatePseudoRandomSalt } from '../src';
 | 
				
			||||||
import { isValidECSignature, isValidSignatureAsync } from '../src/signature_utils';
 | 
					import { isValidECSignature, isValidSignatureAsync } from '../src/signature_utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { chaiSetup } from './utils/chai_setup';
 | 
					import { chaiSetup } from './utils/chai_setup';
 | 
				
			||||||
@@ -119,32 +120,28 @@ describe('Signature utils', () => {
 | 
				
			|||||||
            _.each(stubs, s => s.restore());
 | 
					            _.each(stubs, s => s.restore());
 | 
				
			||||||
            stubs = [];
 | 
					            stubs = [];
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        it('Should return the correct ECSignature', async () => {
 | 
					        it('Should return the correct Signature', async () => {
 | 
				
			||||||
            const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
 | 
					            const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
 | 
				
			||||||
            const expectedECSignature = {
 | 
					            const expectedSignature =
 | 
				
			||||||
                v: 27,
 | 
					                '0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
 | 
				
			||||||
                r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
 | 
					            const ecSignature = await ecSignOrderHashAsync(
 | 
				
			||||||
                s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
 | 
					                provider,
 | 
				
			||||||
            };
 | 
					                orderHash,
 | 
				
			||||||
            const messagePrefixOpts = {
 | 
					                makerAddress,
 | 
				
			||||||
                prefixType: MessagePrefixType.EthSign,
 | 
					                SignerProviderType.EthSign,
 | 
				
			||||||
                shouldAddPrefixBeforeCallingEthSign: false,
 | 
					            );
 | 
				
			||||||
            };
 | 
					            expect(ecSignature).to.equal(expectedSignature);
 | 
				
			||||||
            const ecSignature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, messagePrefixOpts);
 | 
					 | 
				
			||||||
            expect(ecSignature).to.deep.equal(expectedECSignature);
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => {
 | 
					        it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => {
 | 
				
			||||||
            const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
 | 
					            const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
 | 
				
			||||||
            const expectedECSignature = {
 | 
					            const expectedSignature =
 | 
				
			||||||
                v: 27,
 | 
					                '0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03';
 | 
				
			||||||
                r: '0x117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d87287113',
 | 
					 | 
				
			||||||
                s: '0x7feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b',
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const fakeProvider = {
 | 
					            const fakeProvider = {
 | 
				
			||||||
                async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
 | 
					                async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
 | 
				
			||||||
                    if (payload.method === 'eth_sign') {
 | 
					                    if (payload.method === 'eth_sign') {
 | 
				
			||||||
                        const [address, message] = payload.params;
 | 
					                        const [address, message] = payload.params;
 | 
				
			||||||
 | 
					                        expect(message).to.equal(orderHash);
 | 
				
			||||||
                        const signature = await web3Wrapper.signMessageAsync(address, message);
 | 
					                        const signature = await web3Wrapper.signMessageAsync(address, message);
 | 
				
			||||||
                        // tslint:disable-next-line:custom-no-magic-numbers
 | 
					                        // tslint:disable-next-line:custom-no-magic-numbers
 | 
				
			||||||
                        const rsvHex = `0x${signature.substr(130)}${signature.substr(2, 128)}`;
 | 
					                        const rsvHex = `0x${signature.substr(130)}${signature.substr(2, 128)}`;
 | 
				
			||||||
@@ -158,21 +155,18 @@ describe('Signature utils', () => {
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					            const ecSignature = await ecSignOrderHashAsync(
 | 
				
			||||||
            const messagePrefixOpts = {
 | 
					                fakeProvider,
 | 
				
			||||||
                prefixType: MessagePrefixType.EthSign,
 | 
					                orderHash,
 | 
				
			||||||
                shouldAddPrefixBeforeCallingEthSign: false,
 | 
					                makerAddress,
 | 
				
			||||||
            };
 | 
					                SignerProviderType.EthSign,
 | 
				
			||||||
            const ecSignature = await ecSignOrderHashAsync(fakeProvider, orderHash, makerAddress, messagePrefixOpts);
 | 
					            );
 | 
				
			||||||
            expect(ecSignature).to.deep.equal(expectedECSignature);
 | 
					            expect(ecSignature).to.equal(expectedSignature);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => {
 | 
					        it('should return the correct Signature for signatureHex concatenated as V + R + S', async () => {
 | 
				
			||||||
            const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
 | 
					            const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
 | 
				
			||||||
            const expectedECSignature = {
 | 
					            const expectedSignature =
 | 
				
			||||||
                v: 27,
 | 
					                '0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03';
 | 
				
			||||||
                r: '0x117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d87287113',
 | 
					 | 
				
			||||||
                s: '0x7feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b',
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
            const fakeProvider = {
 | 
					            const fakeProvider = {
 | 
				
			||||||
                async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
 | 
					                async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
 | 
				
			||||||
                    if (payload.method === 'eth_sign') {
 | 
					                    if (payload.method === 'eth_sign') {
 | 
				
			||||||
@@ -189,12 +183,57 @@ describe('Signature utils', () => {
 | 
				
			|||||||
                },
 | 
					                },
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const messagePrefixOpts = {
 | 
					            const ecSignature = await ecSignOrderHashAsync(
 | 
				
			||||||
                prefixType: MessagePrefixType.EthSign,
 | 
					                fakeProvider,
 | 
				
			||||||
                shouldAddPrefixBeforeCallingEthSign: false,
 | 
					                orderHash,
 | 
				
			||||||
 | 
					                makerAddress,
 | 
				
			||||||
 | 
					                SignerProviderType.EthSign,
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            expect(ecSignature).to.equal(expectedSignature);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        // Note this is due to a bug in Metamask where it does not prefix before signing, this is a known issue and is to be fixed in the future
 | 
				
			||||||
 | 
					        it('should receive a payload modified with a prefix when Metamask is SignerProviderType', async () => {
 | 
				
			||||||
 | 
					            const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
 | 
				
			||||||
 | 
					            const orderHashPrefixed = '0xae70f31d26096291aa681b26cb7574563956221d0b4213631e1ef9df675d4cba';
 | 
				
			||||||
 | 
					            const expectedSignature =
 | 
				
			||||||
 | 
					                '0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03';
 | 
				
			||||||
 | 
					            const fakeProvider = {
 | 
				
			||||||
 | 
					                async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
 | 
				
			||||||
 | 
					                    if (payload.method === 'eth_sign') {
 | 
				
			||||||
 | 
					                        const [address, message] = payload.params;
 | 
				
			||||||
 | 
					                        expect(message).to.equal(orderHashPrefixed);
 | 
				
			||||||
 | 
					                        const signature =
 | 
				
			||||||
 | 
					                            '0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b';
 | 
				
			||||||
 | 
					                        callback(null, {
 | 
				
			||||||
 | 
					                            id: 42,
 | 
				
			||||||
 | 
					                            jsonrpc: '2.0',
 | 
				
			||||||
 | 
					                            result: signature,
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] });
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            const ecSignature = await ecSignOrderHashAsync(fakeProvider, orderHash, makerAddress, messagePrefixOpts);
 | 
					
 | 
				
			||||||
            expect(ecSignature).to.deep.equal(expectedECSignature);
 | 
					            const ecSignature = await ecSignOrderHashAsync(
 | 
				
			||||||
 | 
					                fakeProvider,
 | 
				
			||||||
 | 
					                orderHash,
 | 
				
			||||||
 | 
					                makerAddress,
 | 
				
			||||||
 | 
					                SignerProviderType.Metamask,
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            expect(ecSignature).to.equal(expectedSignature);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        it('should return a valid signature', async () => {
 | 
				
			||||||
 | 
					            const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
 | 
				
			||||||
 | 
					            const ecSignature = await ecSignOrderHashAsync(
 | 
				
			||||||
 | 
					                provider,
 | 
				
			||||||
 | 
					                orderHash,
 | 
				
			||||||
 | 
					                makerAddress,
 | 
				
			||||||
 | 
					                SignerProviderType.EthSign,
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const isValidSignature = await isValidSignatureAsync(provider, orderHash, ecSignature, makerAddress);
 | 
				
			||||||
 | 
					            expect(isValidSignature).to.be.true();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -142,6 +142,16 @@ export enum SignatureType {
 | 
				
			|||||||
    NSignatureTypes,
 | 
					    NSignatureTypes,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The Signer Provider Type. Some Signer implementations use different message prefixes or implement different
 | 
				
			||||||
 | 
					 * eth_sign behaviour. Note EthSign is compatible with the Ledger device.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export enum SignerProviderType {
 | 
				
			||||||
 | 
					    EthSign = 'ETH_SIGN',
 | 
				
			||||||
 | 
					    Metamask = 'METAMASK',
 | 
				
			||||||
 | 
					    Trezor = 'TREZOR',
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Elliptic Curve signature
 | 
					 * Elliptic Curve signature
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user