Rename from SignerProviderType.EthSign to SignerType.Default

This commit is contained in:
Jacob Evans
2018-08-09 12:24:52 +10:00
parent 5d4dd406f2
commit ca4905c343
9 changed files with 116 additions and 115 deletions

View File

@@ -19,14 +19,7 @@ import {
// 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 { import { AssetProxyId, ERC20AssetData, ERC721AssetData, Order, SignedOrder, SignerType } from '@0xproject/types';
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';
@@ -244,19 +237,21 @@ 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 SignerProviderType The type of Signer Provider which implements `eth_sign`. E.g Metamask, Ledger, Trezor or EthSign. * @param signerType the type signer that will perform the `eth_sign` operation. E.g Default, Metamask, Ledger or Trezor.
* Some implementations exhibit different behaviour. Default will assume a spec compliant eth_sign implementation.
* This parameter is defaulted to `SignerType.Default`.
* @return A hex encoded string of the Elliptic curve signature parameters generated by signing the orderHash and signature type. * @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,
signerProviderType: SignerProviderType, signerType: SignerType = SignerType.Default,
): Promise<string> { ): Promise<string> {
const signature = await ecSignOrderHashAsync( const signature = await ecSignOrderHashAsync(
this._contractWrappers.getProvider(), this._contractWrappers.getProvider(),
orderHash, orderHash,
signerAddress, signerAddress,
signerProviderType, signerType,
); );
return signature; return signature;
} }

View File

@@ -6,7 +6,7 @@ export {
ExchangeContractErrs, ExchangeContractErrs,
Order, Order,
SignedOrder, SignedOrder,
SignerProviderType, SignerType,
ECSignature, ECSignature,
OrderStateValid, OrderStateValid,
OrderStateInvalid, OrderStateInvalid,

View File

@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { addSignedMessagePrefix, assetDataUtils, orderHashUtils } from '@0xproject/order-utils'; import { addSignedMessagePrefix, assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { RevertReason, SignatureType, SignedOrder, SignerProviderType } from '@0xproject/types'; import { RevertReason, SignatureType, SignedOrder, SignerType } 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, SignerProviderType.EthSign); const orderHashWithEthSignPrefixHex = addSignedMessagePrefix(orderHashHex, SignerType.Default);
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, SignerProviderType.EthSign); const orderHashWithEthSignPrefixHex = addSignedMessagePrefix(orderHashHex, SignerType.Default);
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, SignerProviderType.Trezor); const orderHashWithTrezorPrefixHex = addSignedMessagePrefix(orderHashHex, SignerType.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, SignerProviderType.Trezor); const orderHashWithTrezorPrefixHex = addSignedMessagePrefix(orderHashHex, SignerType.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

View File

@@ -1,4 +1,4 @@
import { Order, SignedOrder, SignerProviderType } from '@0xproject/types'; import { Order, SignedOrder, SignerType } 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 _ from 'lodash'; import * as _ from 'lodash';
@@ -58,12 +58,11 @@ export const orderFactory = {
createOrderOpts, createOrderOpts,
); );
const orderHash = orderHashUtils.getOrderHashHex(order); const orderHash = orderHashUtils.getOrderHashHex(order);
const signature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, SignerProviderType.EthSign); const signature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, SignerType.Default);
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;
@@ -84,18 +83,3 @@ function generateDefaultCreateOrderOpts(): {
expirationTimeSeconds: constants.INFINITE_TIMESTAMP_SEC, expirationTimeSeconds: constants.INFINITE_TIMESTAMP_SEC,
}; };
} }
function getVRSHexString(ecSignature: ECSignature): string {
const ETH_SIGN_SIGNATURE_TYPE = '03';
const vrs = `${intToHex(ecSignature.v)}${ethUtil.stripHexPrefix(ecSignature.r)}${ethUtil.stripHexPrefix(
ecSignature.s,
)}${ETH_SIGN_SIGNATURE_TYPE}`;
return vrs;
}
function intToHex(i: number): string {
const hex = ethUtil.bufferToHex(ethUtil.toBuffer(i));
return hex;
}
=======
>>>>>>> Introduce SignerProviderType

View File

@@ -1,5 +1,5 @@
import { schemas } from '@0xproject/json-schemas'; import { schemas } from '@0xproject/json-schemas';
import { ECSignature, SignatureType, SignerProviderType, ValidatorSignature } from '@0xproject/types'; import { ECSignature, SignatureType, SignerType, 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';
@@ -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, SignerProviderType.EthSign); const prefixedMessageHex = addSignedMessagePrefix(data, SignerType.Default);
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, SignerProviderType.Trezor); const prefixedMessageHex = addSignedMessagePrefix(data, SignerType.Trezor);
const ecSignature = parseECSignature(signature); const ecSignature = parseECSignature(signature);
return isValidECSignature(prefixedMessageHex, ecSignature, signerAddress); return isValidECSignature(prefixedMessageHex, ecSignature, signerAddress);
} }
@@ -196,15 +196,15 @@ export function isValidECSignature(data: string, signature: ECSignature, signerA
* @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 signerProviderType Different signers add/require different prefixes to be prepended to the message being signed. * @param signerType Different signers add/require different prefixes to be prepended to the message being signed.
* Since we cannot know ahead of time which signer you are using, you must supply a SignerProviderType. * Since we cannot know ahead of time which signer you are using, you must supply a SignerType.
* @return A hex encoded string containing the Elliptic curve signature generated by signing the orderHash and the Signature Type. * @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,
signerProviderType: SignerProviderType, signerType: SignerType,
): Promise<string> { ): Promise<string> {
assert.isWeb3Provider('provider', provider); assert.isWeb3Provider('provider', provider);
assert.isHexString('orderHash', orderHash); assert.isHexString('orderHash', orderHash);
@@ -214,9 +214,9 @@ export async function ecSignOrderHashAsync(
const normalizedSignerAddress = signerAddress.toLowerCase(); const normalizedSignerAddress = signerAddress.toLowerCase();
let msgHashHex = orderHash; let msgHashHex = orderHash;
const prefixedMsgHashHex = addSignedMessagePrefix(orderHash, signerProviderType); const prefixedMsgHashHex = addSignedMessagePrefix(orderHash, signerType);
// Metamask incorrectly implements eth_sign and does not prefix the message as per the spec // Metamask incorrectly implements eth_sign and does not prefix the message as per the spec
if (signerProviderType === SignerProviderType.Metamask) { if (signerType === SignerType.Metamask) {
msgHashHex = prefixedMsgHashHex; msgHashHex = prefixedMsgHashHex;
} }
const signature = await web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex); const signature = await web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex);
@@ -225,22 +225,22 @@ export async function ecSignOrderHashAsync(
// v + r + s OR r + s + v, and different clients (even different versions of the same client) // v + r + s OR r + s + v, and different clients (even different versions of the same client)
// return the signature params in different orders. In order to support all client implementations, // return the signature params in different orders. In order to support all client implementations,
// we parse the signature in both ways, and evaluate if either one is a valid signature. // we parse the signature in both ways, and evaluate if either one is a valid signature.
// r + s + v is the most prevalent format from eth_sign, so we attempt this first.
// tslint:disable-next-line:custom-no-magic-numbers // tslint:disable-next-line:custom-no-magic-numbers
const validVParamValues = [27, 28]; const validVParamValues = [27, 28];
const ecSignatureVRS = parseSignatureHexAsVRS(signature);
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
const isValidVRSSignature = isValidECSignature(prefixedMsgHashHex, ecSignatureVRS, normalizedSignerAddress);
if (isValidVRSSignature) {
const convertedSignatureHex = convertECSignatureToSignatureHex(ecSignatureVRS, signerProviderType);
return convertedSignatureHex;
}
}
const ecSignatureRSV = parseSignatureHexAsRSV(signature); const ecSignatureRSV = parseSignatureHexAsRSV(signature);
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) {
const convertedSignatureHex = convertECSignatureToSignatureHex(ecSignatureRSV, signerProviderType); const convertedSignatureHex = convertECSignatureToSignatureHex(ecSignatureRSV, signerType);
return convertedSignatureHex;
}
}
const ecSignatureVRS = parseSignatureHexAsVRS(signature);
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
const isValidVRSSignature = isValidECSignature(prefixedMsgHashHex, ecSignatureVRS, normalizedSignerAddress);
if (isValidVRSSignature) {
const convertedSignatureHex = convertECSignatureToSignatureHex(ecSignatureVRS, signerType);
return convertedSignatureHex; return convertedSignatureHex;
} }
} }
@@ -250,23 +250,32 @@ export async function ecSignOrderHashAsync(
/** /**
* Combines ECSignature with V,R,S and the relevant signature type for use in 0x protocol * 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 ecSignature The ECSignature of the signed data
* @param signerProviderType The SignerProviderType of the signed data * @param signerType The SignerType of the signed data
* @return Hex encoded string of signature with Signature Type * @return Hex encoded string of signature (v,r,s) with Signature Type
*/ */
export function convertECSignatureToSignatureHex( export function convertECSignatureToSignatureHex(ecSignature: ECSignature, signerType: SignerType): string {
ecSignature: ECSignature,
signerProviderType: SignerProviderType,
): string {
const signatureBuffer = Buffer.concat([ const signatureBuffer = Buffer.concat([
ethUtil.toBuffer(ecSignature.v), ethUtil.toBuffer(ecSignature.v),
ethUtil.toBuffer(ecSignature.r), ethUtil.toBuffer(ecSignature.r),
ethUtil.toBuffer(ecSignature.s), ethUtil.toBuffer(ecSignature.s),
]); ]);
const signatureHex = `0x${signatureBuffer.toString('hex')}`; const signatureHex = `0x${signatureBuffer.toString('hex')}`;
const signatureType = switch (signerType) {
signerProviderType === SignerProviderType.Trezor ? SignatureType.Trezor : SignatureType.EthSign; case SignerType.Metamask:
case SignerType.Ledger:
case SignerType.Default: {
const signatureType = SignatureType.EthSign;
const signatureWithType = convertToSignatureWithType(signatureHex, signatureType); const signatureWithType = convertToSignatureWithType(signatureHex, signatureType);
return signatureWithType; return signatureWithType;
}
case SignerType.Trezor: {
const signatureType = SignatureType.Trezor;
const signatureWithType = convertToSignatureWithType(signatureHex, signatureType);
return signatureWithType;
}
default:
throw new Error(`Unrecognized SignerType: ${signerType}`);
}
} }
/** /**
* Combines the signature proof and the Signature Type. * Combines the signature proof and the Signature Type.
@@ -282,30 +291,30 @@ export function convertToSignatureWithType(signature: string, signatureType: Sig
/** /**
* 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
* @param signerProviderType The type of message prefix to add for a given SignerProviderType. Different signers expect * @param signerType The type of message prefix to add for a given SignerType. Different signers expect
* specific message prefixes. * specific message prefixes.
* @return Prefixed message * @return Prefixed message
*/ */
export function addSignedMessagePrefix(message: string, signerProviderType: SignerProviderType): string { export function addSignedMessagePrefix(message: string, signerType: SignerType = SignerType.Default): string {
assert.isString('message', message); assert.isString('message', message);
assert.doesBelongToStringEnum('signerProviderType', signerProviderType, SignerProviderType); assert.doesBelongToStringEnum('signerType', signerType, SignerType);
switch (signerProviderType) { switch (signerType) {
case SignerProviderType.Metamask: case SignerType.Metamask:
case SignerProviderType.Ledger: case SignerType.Ledger:
case SignerProviderType.EthSign: { case SignerType.Default: {
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 SignerType.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 SignerProviderType: ${signerProviderType}`); throw new Error(`Unrecognized SignerType: ${signerType}`);
} }
} }

View File

@@ -1,4 +1,4 @@
import { SignerProviderType } from '@0xproject/types'; import { SignerType } 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';
@@ -7,7 +7,7 @@ import 'mocha';
import * as Sinon from 'sinon'; import * as Sinon from 'sinon';
import { ecSignOrderHashAsync, generatePseudoRandomSalt } from '../src'; import { ecSignOrderHashAsync, generatePseudoRandomSalt } from '../src';
import { isValidECSignature, isValidSignatureAsync } from '../src/signature_utils'; import { convertECSignatureToSignatureHex, isValidECSignature, isValidSignatureAsync } from '../src/signature_utils';
import { chaiSetup } from './utils/chai_setup'; import { chaiSetup } from './utils/chai_setup';
import { provider, web3Wrapper } from './utils/web3_wrapper'; import { provider, web3Wrapper } from './utils/web3_wrapper';
@@ -124,12 +124,7 @@ describe('Signature utils', () => {
const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0'; const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
const expectedSignature = const expectedSignature =
'0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403'; '0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
const ecSignature = await ecSignOrderHashAsync( const ecSignature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, SignerType.Default);
provider,
orderHash,
makerAddress,
SignerProviderType.EthSign,
);
expect(ecSignature).to.equal(expectedSignature); expect(ecSignature).to.equal(expectedSignature);
}); });
it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => { it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => {
@@ -155,12 +150,7 @@ describe('Signature utils', () => {
} }
}, },
}; };
const ecSignature = await ecSignOrderHashAsync( const ecSignature = await ecSignOrderHashAsync(fakeProvider, orderHash, makerAddress, SignerType.Default);
fakeProvider,
orderHash,
makerAddress,
SignerProviderType.EthSign,
);
expect(ecSignature).to.equal(expectedSignature); expect(ecSignature).to.equal(expectedSignature);
}); });
it('should return the correct Signature for signatureHex concatenated as V + R + S', async () => { it('should return the correct Signature for signatureHex concatenated as V + R + S', async () => {
@@ -183,32 +173,28 @@ describe('Signature utils', () => {
}, },
}; };
const ecSignature = await ecSignOrderHashAsync( const ecSignature = await ecSignOrderHashAsync(fakeProvider, orderHash, makerAddress, SignerType.Default);
fakeProvider,
orderHash,
makerAddress,
SignerProviderType.EthSign,
);
expect(ecSignature).to.equal(expectedSignature); 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 // 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
// Source: https://github.com/MetaMask/metamask-extension/commit/a9d36860bec424dcee8db043d3e7da6a5ff5672e // Source: https://github.com/MetaMask/metamask-extension/commit/a9d36860bec424dcee8db043d3e7da6a5ff5672e
it('should receive a payload modified with a prefix when Metamask is SignerProviderType', async () => { it('should receive a payload modified with a prefix when Metamask is SignerType', async () => {
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004'; const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
const orderHashPrefixed = '0xae70f31d26096291aa681b26cb7574563956221d0b4213631e1ef9df675d4cba'; const orderHashPrefixed = '0xae70f31d26096291aa681b26cb7574563956221d0b4213631e1ef9df675d4cba';
const expectedSignature = const expectedSignature =
'0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03'; '0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03';
// Generated from a MM eth_sign request from 0x5409ed021d9299bf6814279a6a1411a7e866a631 signing 0xae70f31d26096291aa681b26cb7574563956221d0b4213631e1ef9df675d4cba
const metamaskSignature =
'0x117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b1b';
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 [, message] = payload.params;
expect(message).to.equal(orderHashPrefixed); expect(message).to.equal(orderHashPrefixed);
const signature =
'0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b';
callback(null, { callback(null, {
id: 42, id: 42,
jsonrpc: '2.0', jsonrpc: '2.0',
result: signature, result: metamaskSignature,
}); });
} else { } else {
callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] }); callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] });
@@ -216,25 +202,52 @@ describe('Signature utils', () => {
}, },
}; };
const ecSignature = await ecSignOrderHashAsync( const ecSignature = await ecSignOrderHashAsync(fakeProvider, orderHash, makerAddress, SignerType.Metamask);
fakeProvider,
orderHash,
makerAddress,
SignerProviderType.Metamask,
);
expect(ecSignature).to.equal(expectedSignature); expect(ecSignature).to.equal(expectedSignature);
}); });
it('should return a valid signature', async () => { it('should return a valid signature', async () => {
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004'; const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
const ecSignature = await ecSignOrderHashAsync( const ecSignature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, SignerType.Default);
provider,
orderHash,
makerAddress,
SignerProviderType.EthSign,
);
const isValidSignature = await isValidSignatureAsync(provider, orderHash, ecSignature, makerAddress); const isValidSignature = await isValidSignatureAsync(provider, orderHash, ecSignature, makerAddress);
expect(isValidSignature).to.be.true(); expect(isValidSignature).to.be.true();
}); });
}); });
describe('#convertECSignatureToSignatureHex', () => {
const ecSignature: ECSignature = {
v: 27,
r: '0xaca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d64393',
s: '0x46b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf2',
};
it('should concatenate v,r,s and append the Trezor signature type', async () => {
const expectedSignatureWithSignatureType =
'0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf208';
const signatureWithSignatureType = convertECSignatureToSignatureHex(ecSignature, SignerType.Trezor);
expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
});
it('should concatenate v,r,s and append the EthSign signature type when SignerType is Default', async () => {
const expectedSignatureWithSignatureType =
'0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf203';
const signatureWithSignatureType = convertECSignatureToSignatureHex(ecSignature, SignerType.Default);
expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
});
it('should concatenate v,r,s and append the EthSign signature type when SignerType is Ledger', async () => {
const expectedSignatureWithSignatureType =
'0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf203';
const signatureWithSignatureType = convertECSignatureToSignatureHex(ecSignature, SignerType.Ledger);
expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
});
it('should concatenate v,r,s and append the EthSign signature type when SignerType is Metamask', async () => {
const expectedSignatureWithSignatureType =
'0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf203';
const signatureWithSignatureType = convertECSignatureToSignatureHex(ecSignature, SignerType.Metamask);
expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
});
it('should throw if the SignerType is invalid', async () => {
const expectedMessage = 'Unrecognized SignerType: INVALID_SIGNER';
expect(() => convertECSignatureToSignatureHex(ecSignature, 'INVALID_SIGNER' as SignerType)).to.throw(
expectedMessage,
);
});
});
}); });

View File

@@ -25,7 +25,7 @@ export const fixtureData = {
chainId: networkId, chainId: networkId,
from: TEST_RPC_ACCOUNT_0, from: TEST_RPC_ACCOUNT_0,
}, },
// This is the signed result of the abouve Transaction Data // This is the signed result of the above Transaction Data
TX_DATA_SIGNED_RESULT: TX_DATA_SIGNED_RESULT:
'0xf85f8080822710940000000000000000000000000000000000000000808078a0712854c73c69445cc1b22a7c3d7312ff9a97fe4ffba35fd636e8236b211b6e7ca0647cee031615e52d916c7c707025bc64ad525d8f1b9876c3435a863b42743178', '0xf85f8080822710940000000000000000000000000000000000000000808078a0712854c73c69445cc1b22a7c3d7312ff9a97fe4ffba35fd636e8236b211b6e7ca0647cee031615e52d916c7c707025bc64ad525d8f1b9876c3435a863b42743178',
TX_DATA_ACCOUNT_1_SIGNED_RESULT: TX_DATA_ACCOUNT_1_SIGNED_RESULT:

View File

@@ -4,7 +4,7 @@
"changes": [ "changes": [
{ {
"pr": 914, "pr": 914,
"note": "Added SignerProviderType" "note": "Added SignerType to handle different signing prefix scenarios"
} }
] ]
}, },

View File

@@ -143,11 +143,11 @@ export enum SignatureType {
} }
/** /**
* The Signer Provider Type. Some Signer provider implementations use different message prefixes or implement different * The type of the Signer implementation. Some signer implementations use different message prefixes (e.g Trezor) or implement different
* eth_sign behaviour. * eth_sign behaviour (e.g Metamask). Default assumes a spec compliant `eth_sign`.
*/ */
export enum SignerProviderType { export enum SignerType {
EthSign = 'ETH_SIGN', Default = 'DEFAULT',
Ledger = 'LEDGER', Ledger = 'LEDGER',
Metamask = 'METAMASK', Metamask = 'METAMASK',
Trezor = 'TREZOR', Trezor = 'TREZOR',