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:
parent
53713188fe
commit
45e9fbe8f9
@ -21,6 +21,9 @@
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
},
|
||||
{
|
||||
"note": "Update ecSignOrderHashAsync to return the signature as a string for immediate use in contracts"
|
||||
}
|
||||
],
|
||||
"timestamp": 1532605697
|
||||
|
@ -14,13 +14,19 @@ import {
|
||||
ecSignOrderHashAsync,
|
||||
generatePseudoRandomSalt,
|
||||
isValidSignatureAsync,
|
||||
MessagePrefixOpts,
|
||||
orderHashUtils,
|
||||
} from '@0xproject/order-utils';
|
||||
// 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.
|
||||
// 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 { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||
@ -238,19 +244,19 @@ export class ZeroEx {
|
||||
* @param orderHash Hex encoded orderHash to sign.
|
||||
* @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.
|
||||
* @param MessagePrefixOpts Options regarding the desired prefix and whether to add it before calling `eth_sign`
|
||||
* @return An object containing the Elliptic curve signature parameters generated by signing the orderHash.
|
||||
* @param SignerProviderType The type of Signer Provider which implements `eth_sign`. E.g Metamask, Ledger, Trezor or EthSign.
|
||||
* @return A hex encoded string of the Elliptic curve signature parameters generated by signing the orderHash and signature type.
|
||||
*/
|
||||
public async ecSignOrderHashAsync(
|
||||
orderHash: string,
|
||||
signerAddress: string,
|
||||
messagePrefixOpts: MessagePrefixOpts,
|
||||
): Promise<ECSignature> {
|
||||
signerProviderType: SignerProviderType,
|
||||
): Promise<string> {
|
||||
const signature = await ecSignOrderHashAsync(
|
||||
this._contractWrappers.getProvider(),
|
||||
orderHash,
|
||||
signerAddress,
|
||||
messagePrefixOpts,
|
||||
signerProviderType,
|
||||
);
|
||||
return signature;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
export { ZeroEx } from './0x';
|
||||
|
||||
export { MessagePrefixType, MessagePrefixOpts } from '@0xproject/order-utils';
|
||||
export { Web3ProviderEngine, RPCSubprovider } from '@0xproject/subproviders';
|
||||
|
||||
export {
|
||||
ExchangeContractErrs,
|
||||
Order,
|
||||
SignedOrder,
|
||||
SignerProviderType,
|
||||
ECSignature,
|
||||
OrderStateValid,
|
||||
OrderStateInvalid,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
||||
import { addSignedMessagePrefix, assetDataUtils, MessagePrefixType, orderHashUtils } from '@0xproject/order-utils';
|
||||
import { RevertReason, SignatureType, SignedOrder } from '@0xproject/types';
|
||||
import { addSignedMessagePrefix, assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
|
||||
import { RevertReason, SignatureType, SignedOrder, SignerProviderType } from '@0xproject/types';
|
||||
import * as chai from 'chai';
|
||||
import { LogWithDecodedArgs } from 'ethereum-types';
|
||||
import ethUtil = require('ethereumjs-util');
|
||||
@ -213,7 +213,7 @@ describe('MixinSignatureValidator', () => {
|
||||
it('should return true when SignatureType=EthSign and signature is valid', async () => {
|
||||
// Create EthSign signature
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const orderHashWithEthSignPrefixHex = addSignedMessagePrefix(orderHashHex, MessagePrefixType.EthSign);
|
||||
const orderHashWithEthSignPrefixHex = addSignedMessagePrefix(orderHashHex, SignerProviderType.EthSign);
|
||||
const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex);
|
||||
const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey);
|
||||
// Create 0x signature from EthSign signature
|
||||
@ -236,7 +236,7 @@ describe('MixinSignatureValidator', () => {
|
||||
it('should return false when SignatureType=EthSign and signature is invalid', async () => {
|
||||
// Create EthSign signature
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const orderHashWithEthSignPrefixHex = addSignedMessagePrefix(orderHashHex, MessagePrefixType.EthSign);
|
||||
const orderHashWithEthSignPrefixHex = addSignedMessagePrefix(orderHashHex, SignerProviderType.EthSign);
|
||||
const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex);
|
||||
const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey);
|
||||
// Create 0x signature from EthSign signature
|
||||
@ -385,7 +385,7 @@ describe('MixinSignatureValidator', () => {
|
||||
it('should return true when SignatureType=Trezor and signature is valid', async () => {
|
||||
// Create Trezor signature
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const orderHashWithTrezorPrefixHex = addSignedMessagePrefix(orderHashHex, MessagePrefixType.Trezor);
|
||||
const orderHashWithTrezorPrefixHex = addSignedMessagePrefix(orderHashHex, SignerProviderType.Trezor);
|
||||
const orderHashWithTrezorPrefixBuffer = ethUtil.toBuffer(orderHashWithTrezorPrefixHex);
|
||||
const ecSignature = ethUtil.ecsign(orderHashWithTrezorPrefixBuffer, signerPrivateKey);
|
||||
// Create 0x signature from Trezor signature
|
||||
@ -408,7 +408,7 @@ describe('MixinSignatureValidator', () => {
|
||||
it('should return false when SignatureType=Trezor and signature is invalid', async () => {
|
||||
// Create Trezor signature
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const orderHashWithTrezorPrefixHex = addSignedMessagePrefix(orderHashHex, MessagePrefixType.Trezor);
|
||||
const orderHashWithTrezorPrefixHex = addSignedMessagePrefix(orderHashHex, SignerProviderType.Trezor);
|
||||
const orderHashWithTrezorPrefixBuffer = ethUtil.toBuffer(orderHashWithTrezorPrefixHex);
|
||||
const ecSignature = ethUtil.ecsign(orderHashWithTrezorPrefixBuffer, signerPrivateKey);
|
||||
// Create 0x signature from Trezor signature
|
||||
|
@ -30,6 +30,9 @@
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
},
|
||||
{
|
||||
"note": "Update ecSignOrderHashAsync to return signature string with signature type byte"
|
||||
}
|
||||
],
|
||||
"timestamp": 1532605697
|
||||
|
@ -13,15 +13,7 @@ export { orderFactory } from './order_factory';
|
||||
export { constants } from './constants';
|
||||
export { crypto } from './crypto';
|
||||
export { generatePseudoRandomSalt } from './salt';
|
||||
export {
|
||||
CreateOrderOpts,
|
||||
OrderError,
|
||||
MessagePrefixType,
|
||||
MessagePrefixOpts,
|
||||
EIP712Parameter,
|
||||
EIP712Schema,
|
||||
EIP712Types,
|
||||
} from './types';
|
||||
export { CreateOrderOpts, OrderError, EIP712Parameter, EIP712Schema, EIP712Types } from './types';
|
||||
export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
|
||||
export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
|
||||
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 { Provider } from 'ethereum-types';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { constants } from './constants';
|
||||
import { orderHashUtils } from './order_hash';
|
||||
import { generatePseudoRandomSalt } from './salt';
|
||||
import { ecSignOrderHashAsync } from './signature_utils';
|
||||
import { CreateOrderOpts, MessagePrefixType } from './types';
|
||||
import { CreateOrderOpts } from './types';
|
||||
|
||||
export const orderFactory = {
|
||||
createOrder(
|
||||
@ -59,16 +58,12 @@ export const orderFactory = {
|
||||
createOrderOpts,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(order);
|
||||
const messagePrefixOpts = {
|
||||
prefixType: MessagePrefixType.EthSign,
|
||||
shouldAddPrefixBeforeCallingEthSign: false,
|
||||
};
|
||||
const ecSignature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, messagePrefixOpts);
|
||||
const signature = getVRSHexString(ecSignature);
|
||||
const signature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, SignerProviderType.EthSign);
|
||||
const signedOrder: SignedOrder = _.assign(order, { signature });
|
||||
return signedOrder;
|
||||
},
|
||||
};
|
||||
<<<<<<< HEAD
|
||||
|
||||
function generateDefaultCreateOrderOpts(): {
|
||||
takerAddress: string;
|
||||
@ -102,3 +97,5 @@ function intToHex(i: number): string {
|
||||
const hex = ethUtil.bufferToHex(ethUtil.toBuffer(i));
|
||||
return hex;
|
||||
}
|
||||
=======
|
||||
>>>>>>> Introduce SignerProviderType
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { Provider } from 'ethereum-types';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
@ -10,7 +10,7 @@ import { assert } from './assert';
|
||||
import { ExchangeContract } from './generated_contract_wrappers/exchange';
|
||||
import { IValidatorContract } from './generated_contract_wrappers/i_validator';
|
||||
import { IWalletContract } from './generated_contract_wrappers/i_wallet';
|
||||
import { MessagePrefixOpts, MessagePrefixType, OrderError } from './types';
|
||||
import { OrderError } from './types';
|
||||
import { utils } from './utils';
|
||||
|
||||
/**
|
||||
@ -48,7 +48,7 @@ export async function isValidSignatureAsync(
|
||||
|
||||
case SignatureType.EthSign: {
|
||||
const ecSignature = parseECSignature(signature);
|
||||
const prefixedMessageHex = addSignedMessagePrefix(data, MessagePrefixType.EthSign);
|
||||
const prefixedMessageHex = addSignedMessagePrefix(data, SignerProviderType.EthSign);
|
||||
return isValidECSignature(prefixedMessageHex, ecSignature, signerAddress);
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ export async function isValidSignatureAsync(
|
||||
}
|
||||
|
||||
case SignatureType.Trezor: {
|
||||
const prefixedMessageHex = addSignedMessagePrefix(data, MessagePrefixType.Trezor);
|
||||
const prefixedMessageHex = addSignedMessagePrefix(data, SignerProviderType.Trezor);
|
||||
const ecSignature = parseECSignature(signature);
|
||||
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
|
||||
* @param orderHash Hex encoded orderHash to sign.
|
||||
* @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.
|
||||
* @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
|
||||
* 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(
|
||||
provider: Provider,
|
||||
orderHash: string,
|
||||
signerAddress: string,
|
||||
messagePrefixOpts: MessagePrefixOpts,
|
||||
): Promise<ECSignature> {
|
||||
signerProviderType: SignerProviderType,
|
||||
): Promise<string> {
|
||||
assert.isWeb3Provider('provider', provider);
|
||||
assert.isHexString('orderHash', orderHash);
|
||||
assert.isETHAddressHex('signerAddress', signerAddress);
|
||||
@ -215,8 +215,9 @@ export async function ecSignOrderHashAsync(
|
||||
const normalizedSignerAddress = signerAddress.toLowerCase();
|
||||
|
||||
let msgHashHex = orderHash;
|
||||
const prefixedMsgHashHex = addSignedMessagePrefix(orderHash, messagePrefixOpts.prefixType);
|
||||
if (messagePrefixOpts.shouldAddPrefixBeforeCallingEthSign) {
|
||||
const prefixedMsgHashHex = addSignedMessagePrefix(orderHash, signerProviderType);
|
||||
// Metamask incorrectly implements eth_sign and does not prefix the message as per the spec
|
||||
if (signerProviderType === SignerProviderType.Metamask) {
|
||||
msgHashHex = prefixedMsgHashHex;
|
||||
}
|
||||
const signature = await web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex);
|
||||
@ -231,7 +232,8 @@ export async function ecSignOrderHashAsync(
|
||||
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
|
||||
const isValidVRSSignature = isValidECSignature(prefixedMsgHashHex, ecSignatureVRS, normalizedSignerAddress);
|
||||
if (isValidVRSSignature) {
|
||||
return ecSignatureVRS;
|
||||
const convertedSignatureHex = convertECSignatureToSignatureHex(ecSignatureVRS, signerProviderType);
|
||||
return convertedSignatureHex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,13 +241,45 @@ export async function ecSignOrderHashAsync(
|
||||
if (_.includes(validVParamValues, ecSignatureRSV.v)) {
|
||||
const isValidRSVSignature = isValidECSignature(prefixedMsgHashHex, ecSignatureRSV, normalizedSignerAddress);
|
||||
if (isValidRSVSignature) {
|
||||
return ecSignatureRSV;
|
||||
const convertedSignatureHex = convertECSignatureToSignatureHex(ecSignatureRSV, signerProviderType);
|
||||
return convertedSignatureHex;
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
* @param message Message to sign
|
||||
@ -253,29 +287,25 @@ export async function ecSignOrderHashAsync(
|
||||
* specific message prefixes.
|
||||
* @return Prefixed message
|
||||
*/
|
||||
export function addSignedMessagePrefix(message: string, messagePrefixType: MessagePrefixType): string {
|
||||
export function addSignedMessagePrefix(message: string, signerProviderType: SignerProviderType): string {
|
||||
assert.isString('message', message);
|
||||
assert.doesBelongToStringEnum('messagePrefixType', messagePrefixType, MessagePrefixType);
|
||||
switch (messagePrefixType) {
|
||||
case MessagePrefixType.None:
|
||||
return message;
|
||||
|
||||
case MessagePrefixType.EthSign: {
|
||||
assert.doesBelongToStringEnum('signerProviderType', signerProviderType, SignerProviderType);
|
||||
switch (signerProviderType) {
|
||||
case SignerProviderType.Metamask:
|
||||
case SignerProviderType.EthSign: {
|
||||
const msgBuff = ethUtil.toBuffer(message);
|
||||
const prefixedMsgBuff = ethUtil.hashPersonalMessage(msgBuff);
|
||||
const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
|
||||
return prefixedMsgHex;
|
||||
}
|
||||
|
||||
case MessagePrefixType.Trezor: {
|
||||
case SignerProviderType.Trezor: {
|
||||
const msgBuff = ethUtil.toBuffer(message);
|
||||
const prefixedMsgBuff = hashTrezorPersonalMessage(msgBuff);
|
||||
const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
|
||||
return prefixedMsgHex;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error(`Unrecognized MessagePrefixType: ${messagePrefixType}`);
|
||||
throw new Error(`Unrecognized SignerProviderType: ${signerProviderType}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,28 +4,6 @@ export enum OrderError {
|
||||
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 {
|
||||
Maker = 'maker',
|
||||
Taker = 'taker',
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { SignerProviderType } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as chai from 'chai';
|
||||
import { JSONRPCErrorCallback, JSONRPCRequestPayload } from 'ethereum-types';
|
||||
@ -5,7 +6,7 @@ import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
|
||||
import { ecSignOrderHashAsync, generatePseudoRandomSalt, MessagePrefixType } from '../src';
|
||||
import { ecSignOrderHashAsync, generatePseudoRandomSalt } from '../src';
|
||||
import { isValidECSignature, isValidSignatureAsync } from '../src/signature_utils';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
@ -119,32 +120,28 @@ describe('Signature utils', () => {
|
||||
_.each(stubs, s => s.restore());
|
||||
stubs = [];
|
||||
});
|
||||
it('Should return the correct ECSignature', async () => {
|
||||
it('Should return the correct Signature', async () => {
|
||||
const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
||||
};
|
||||
const messagePrefixOpts = {
|
||||
prefixType: MessagePrefixType.EthSign,
|
||||
shouldAddPrefixBeforeCallingEthSign: false,
|
||||
};
|
||||
const ecSignature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, messagePrefixOpts);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
const expectedSignature =
|
||||
'0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
|
||||
const ecSignature = await ecSignOrderHashAsync(
|
||||
provider,
|
||||
orderHash,
|
||||
makerAddress,
|
||||
SignerProviderType.EthSign,
|
||||
);
|
||||
expect(ecSignature).to.equal(expectedSignature);
|
||||
});
|
||||
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 expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d87287113',
|
||||
s: '0x7feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b',
|
||||
};
|
||||
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(orderHash);
|
||||
const signature = await web3Wrapper.signMessageAsync(address, message);
|
||||
// tslint:disable-next-line:custom-no-magic-numbers
|
||||
const rsvHex = `0x${signature.substr(130)}${signature.substr(2, 128)}`;
|
||||
@ -158,21 +155,18 @@ describe('Signature utils', () => {
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const messagePrefixOpts = {
|
||||
prefixType: MessagePrefixType.EthSign,
|
||||
shouldAddPrefixBeforeCallingEthSign: false,
|
||||
};
|
||||
const ecSignature = await ecSignOrderHashAsync(fakeProvider, orderHash, makerAddress, messagePrefixOpts);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
const ecSignature = await ecSignOrderHashAsync(
|
||||
fakeProvider,
|
||||
orderHash,
|
||||
makerAddress,
|
||||
SignerProviderType.EthSign,
|
||||
);
|
||||
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 expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d87287113',
|
||||
s: '0x7feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b',
|
||||
};
|
||||
const expectedSignature =
|
||||
'0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03';
|
||||
const fakeProvider = {
|
||||
async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
|
||||
if (payload.method === 'eth_sign') {
|
||||
@ -189,12 +183,57 @@ describe('Signature utils', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const messagePrefixOpts = {
|
||||
prefixType: MessagePrefixType.EthSign,
|
||||
shouldAddPrefixBeforeCallingEthSign: false,
|
||||
const ecSignature = await ecSignOrderHashAsync(
|
||||
fakeProvider,
|
||||
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,
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user