Add ApprovalFactory class
This commit is contained in:
@@ -16,5 +16,5 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"contracts": ["src/MixinSignatureValidator.sol", "src/TEC.sol", "test/TestLibs.sol"]
|
"contracts": ["src/TEC.sol", "test/TestLibs.sol", "test/TestMixins.sol"]
|
||||||
}
|
}
|
||||||
|
29
contracts/tec/contracts/test/TestMixins.sol
Normal file
29
contracts/tec/contracts/test/TestMixins.sol
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2018 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity 0.5.3;
|
||||||
|
pragma experimental "ABIEncoderV2";
|
||||||
|
|
||||||
|
import "../src/MixinSignatureValidator.sol";
|
||||||
|
import "../src/MixinTECApprovalVerifier.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestMixins is
|
||||||
|
MixinSignatureValidator,
|
||||||
|
MixinTECApprovalVerifier
|
||||||
|
{}
|
@@ -33,7 +33,7 @@
|
|||||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis": "./generated-artifacts/@(MixinSignatureValidator|TEC|TestLibs).json",
|
"abis": "./generated-artifacts/@(IExchange|TEC|TestLibs|TestMixins).json",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@@ -5,11 +5,11 @@
|
|||||||
*/
|
*/
|
||||||
import { ContractArtifact } from 'ethereum-types';
|
import { ContractArtifact } from 'ethereum-types';
|
||||||
|
|
||||||
import * as MixinSignatureValidator from '../generated-artifacts/MixinSignatureValidator.json';
|
|
||||||
import * as TEC from '../generated-artifacts/TEC.json';
|
import * as TEC from '../generated-artifacts/TEC.json';
|
||||||
import * as TestLibs from '../generated-artifacts/TestLibs.json';
|
import * as TestLibs from '../generated-artifacts/TestLibs.json';
|
||||||
|
import * as TestMixins from '../generated-artifacts/TestMixins.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
|
TestMixins: TestMixins as ContractArtifact,
|
||||||
TEC: TEC as ContractArtifact,
|
TEC: TEC as ContractArtifact,
|
||||||
TestLibs: TestLibs as ContractArtifact,
|
TestLibs: TestLibs as ContractArtifact,
|
||||||
MixinSignatureValidator: MixinSignatureValidator as ContractArtifact,
|
|
||||||
};
|
};
|
||||||
|
@@ -3,6 +3,6 @@
|
|||||||
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
export * from '../generated-wrappers/mixin_signature_validator';
|
|
||||||
export * from '../generated-wrappers/tec';
|
export * from '../generated-wrappers/tec';
|
||||||
export * from '../generated-wrappers/test_libs';
|
export * from '../generated-wrappers/test_libs';
|
||||||
|
export * from '../generated-wrappers/test_mixins';
|
||||||
|
@@ -3,7 +3,7 @@ import { BlockchainLifecycle } from '@0x/dev-utils';
|
|||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
|
|
||||||
import { approvalHashUtils, artifacts, TestLibsContract } from '../src';
|
import { artifacts, hashUtils, TestLibsContract } from '../src';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -36,7 +36,7 @@ describe('Libs tests', () => {
|
|||||||
signerAddress: constants.NULL_ADDRESS,
|
signerAddress: constants.NULL_ADDRESS,
|
||||||
data: '0x1234',
|
data: '0x1234',
|
||||||
};
|
};
|
||||||
const expectedTxHash = approvalHashUtils._getTransactionHashHex(tx);
|
const expectedTxHash = hashUtils.getTransactionHashHex(tx);
|
||||||
const txHash = await testLibs.publicGetTransactionHash.callAsync(tx);
|
const txHash = await testLibs.publicGetTransactionHash.callAsync(tx);
|
||||||
expect(expectedTxHash).to.eq(txHash);
|
expect(expectedTxHash).to.eq(txHash);
|
||||||
});
|
});
|
||||||
@@ -53,11 +53,11 @@ describe('Libs tests', () => {
|
|||||||
};
|
};
|
||||||
const approvalExpirationTimeSeconds = new BigNumber(0);
|
const approvalExpirationTimeSeconds = new BigNumber(0);
|
||||||
const approval = {
|
const approval = {
|
||||||
transactionHash: approvalHashUtils._getTransactionHashHex(signedTx),
|
transactionHash: hashUtils.getTransactionHashHex(signedTx),
|
||||||
transactionSignature: signedTx.signature,
|
transactionSignature: signedTx.signature,
|
||||||
approvalExpirationTimeSeconds,
|
approvalExpirationTimeSeconds,
|
||||||
};
|
};
|
||||||
const expectedApprovalHash = approvalHashUtils.getApprovalHashHex(signedTx, approvalExpirationTimeSeconds);
|
const expectedApprovalHash = hashUtils.getApprovalHashHex(signedTx, approvalExpirationTimeSeconds);
|
||||||
const approvalHash = await testLibs.publicGetTECApprovalHash.callAsync(approval);
|
const approvalHash = await testLibs.publicGetTECApprovalHash.callAsync(approval);
|
||||||
expect(expectedApprovalHash).to.eq(approvalHash);
|
expect(expectedApprovalHash).to.eq(approvalHash);
|
||||||
});
|
});
|
||||||
|
@@ -7,13 +7,19 @@ import {
|
|||||||
web3Wrapper,
|
web3Wrapper,
|
||||||
} from '@0x/contracts-test-utils';
|
} from '@0x/contracts-test-utils';
|
||||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||||
import { transactionHashUtils } from '@0x/order-utils';
|
import { RevertReason, SignedOrder } from '@0x/types';
|
||||||
import { RevertReason } from '@0x/types';
|
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
|
|
||||||
import { artifacts, MixinSignatureValidatorContract, TECSignatureType, TECTransactionFactory } from '../src';
|
import {
|
||||||
|
ApprovalFactory,
|
||||||
|
artifacts,
|
||||||
|
hashUtils,
|
||||||
|
TECSignatureType,
|
||||||
|
TECTransactionFactory,
|
||||||
|
TestMixinsContract,
|
||||||
|
} from '../src';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -22,8 +28,10 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
|||||||
describe('Mixins tests', () => {
|
describe('Mixins tests', () => {
|
||||||
let transactionSignerAddress: string;
|
let transactionSignerAddress: string;
|
||||||
let approvalSignerAddress: string;
|
let approvalSignerAddress: string;
|
||||||
let signatureValidator: MixinSignatureValidatorContract;
|
let mixins: TestMixinsContract;
|
||||||
let transactionFactory: TECTransactionFactory;
|
let transactionFactory: TECTransactionFactory;
|
||||||
|
let approvalFactory: ApprovalFactory;
|
||||||
|
let defaultOrder: SignedOrder;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await blockchainLifecycle.startAsync();
|
await blockchainLifecycle.startAsync();
|
||||||
@@ -32,16 +40,29 @@ describe('Mixins tests', () => {
|
|||||||
await blockchainLifecycle.revertAsync();
|
await blockchainLifecycle.revertAsync();
|
||||||
});
|
});
|
||||||
before(async () => {
|
before(async () => {
|
||||||
signatureValidator = await MixinSignatureValidatorContract.deployFrom0xArtifactAsync(
|
mixins = await TestMixinsContract.deployFrom0xArtifactAsync(artifacts.TestMixins, provider, txDefaults);
|
||||||
artifacts.MixinSignatureValidator,
|
|
||||||
provider,
|
|
||||||
txDefaults,
|
|
||||||
);
|
|
||||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
[transactionSignerAddress, approvalSignerAddress] = accounts.slice(0, 2);
|
[transactionSignerAddress, approvalSignerAddress] = accounts.slice(0, 2);
|
||||||
|
defaultOrder = {
|
||||||
|
exchangeAddress: constants.NULL_ADDRESS,
|
||||||
|
makerAddress: constants.NULL_ADDRESS,
|
||||||
|
takerAddress: constants.NULL_ADDRESS,
|
||||||
|
senderAddress: mixins.address,
|
||||||
|
feeRecipientAddress: approvalSignerAddress,
|
||||||
|
makerAssetData: constants.NULL_BYTES,
|
||||||
|
takerAssetData: constants.NULL_BYTES,
|
||||||
|
makerAssetAmount: constants.ZERO_AMOUNT,
|
||||||
|
takerAssetAmount: constants.ZERO_AMOUNT,
|
||||||
|
makerFee: constants.ZERO_AMOUNT,
|
||||||
|
takerFee: constants.ZERO_AMOUNT,
|
||||||
|
expirationTimeSeconds: constants.ZERO_AMOUNT,
|
||||||
|
salt: constants.ZERO_AMOUNT,
|
||||||
|
signature: constants.NULL_BYTES,
|
||||||
|
};
|
||||||
const transactionSignerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[0];
|
const transactionSignerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[0];
|
||||||
const approvalSignerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[1];
|
const approvalSignerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[1];
|
||||||
transactionFactory = new TECTransactionFactory(transactionSignerPrivateKey, signatureValidator.address);
|
transactionFactory = new TECTransactionFactory(transactionSignerPrivateKey, mixins.address);
|
||||||
|
approvalFactory = new ApprovalFactory(approvalSignerPrivateKey);
|
||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await blockchainLifecycle.startAsync();
|
await blockchainLifecycle.startAsync();
|
||||||
@@ -54,21 +75,15 @@ describe('Mixins tests', () => {
|
|||||||
it('should return the correct address using the EthSign signature type', async () => {
|
it('should return the correct address using the EthSign signature type', async () => {
|
||||||
const data = constants.NULL_BYTES;
|
const data = constants.NULL_BYTES;
|
||||||
const transaction = transactionFactory.newSignedTECTransaction(data, TECSignatureType.EthSign);
|
const transaction = transactionFactory.newSignedTECTransaction(data, TECSignatureType.EthSign);
|
||||||
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
const transactionHash = hashUtils.getTransactionHashHex(transaction);
|
||||||
const signerAddress = await signatureValidator.getSignerAddress.callAsync(
|
const signerAddress = await mixins.getSignerAddress.callAsync(transactionHash, transaction.signature);
|
||||||
transactionHash,
|
|
||||||
transaction.signature,
|
|
||||||
);
|
|
||||||
expect(transaction.signerAddress).to.eq(signerAddress);
|
expect(transaction.signerAddress).to.eq(signerAddress);
|
||||||
});
|
});
|
||||||
it('should return the correct address using the EIP712 signature type', async () => {
|
it('should return the correct address using the EIP712 signature type', async () => {
|
||||||
const data = constants.NULL_BYTES;
|
const data = constants.NULL_BYTES;
|
||||||
const transaction = transactionFactory.newSignedTECTransaction(data, TECSignatureType.EIP712);
|
const transaction = transactionFactory.newSignedTECTransaction(data, TECSignatureType.EIP712);
|
||||||
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
const transactionHash = hashUtils.getTransactionHashHex(transaction);
|
||||||
const signerAddress = await signatureValidator.getSignerAddress.callAsync(
|
const signerAddress = await mixins.getSignerAddress.callAsync(transactionHash, transaction.signature);
|
||||||
transactionHash,
|
|
||||||
transaction.signature,
|
|
||||||
);
|
|
||||||
expect(transaction.signerAddress).to.eq(signerAddress);
|
expect(transaction.signerAddress).to.eq(signerAddress);
|
||||||
});
|
});
|
||||||
it('should revert with with the Illegal signature type', async () => {
|
it('should revert with with the Illegal signature type', async () => {
|
||||||
@@ -79,9 +94,9 @@ describe('Mixins tests', () => {
|
|||||||
0,
|
0,
|
||||||
transaction.signature.length - 2,
|
transaction.signature.length - 2,
|
||||||
)}${illegalSignatureByte}`;
|
)}${illegalSignatureByte}`;
|
||||||
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
const transactionHash = hashUtils.getTransactionHashHex(transaction);
|
||||||
expectContractCallFailedAsync(
|
expectContractCallFailedAsync(
|
||||||
signatureValidator.getSignerAddress.callAsync(transactionHash, transaction.signature),
|
mixins.getSignerAddress.callAsync(transactionHash, transaction.signature),
|
||||||
RevertReason.SignatureIllegal,
|
RevertReason.SignatureIllegal,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -93,11 +108,15 @@ describe('Mixins tests', () => {
|
|||||||
0,
|
0,
|
||||||
transaction.signature.length - 2,
|
transaction.signature.length - 2,
|
||||||
)}${invalidSignatureByte}`;
|
)}${invalidSignatureByte}`;
|
||||||
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
const transactionHash = hashUtils.getTransactionHashHex(transaction);
|
||||||
expectContractCallFailedAsync(
|
expectContractCallFailedAsync(
|
||||||
signatureValidator.getSignerAddress.callAsync(transactionHash, transaction.signature),
|
mixins.getSignerAddress.callAsync(transactionHash, transaction.signature),
|
||||||
RevertReason.SignatureUnsupported,
|
RevertReason.SignatureUnsupported,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('assertValidSingleOrderApproval', () => {});
|
||||||
|
describe('assertValidBatchOrderApproval', () => {});
|
||||||
|
describe('assertValidTECApproval', () => {});
|
||||||
});
|
});
|
||||||
|
@@ -0,0 +1,28 @@
|
|||||||
|
import { SignedZeroExTransaction } from '@0x/types';
|
||||||
|
import { BigNumber } from '@0x/utils';
|
||||||
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
|
|
||||||
|
import { hashUtils, SignedTECApproval, signingUtils, TECSignatureType } from './index';
|
||||||
|
|
||||||
|
export class ApprovalFactory {
|
||||||
|
private readonly _privateKey: Buffer;
|
||||||
|
constructor(privateKey: Buffer) {
|
||||||
|
this._privateKey = privateKey;
|
||||||
|
}
|
||||||
|
public newSignedApproval(
|
||||||
|
transaction: SignedZeroExTransaction,
|
||||||
|
approvalExpirationTimeSeconds: BigNumber,
|
||||||
|
signatureType: TECSignatureType = TECSignatureType.EthSign,
|
||||||
|
): SignedTECApproval {
|
||||||
|
const approvalHashBuff = hashUtils.getApprovalHashBuffer(transaction, approvalExpirationTimeSeconds);
|
||||||
|
const signatureBuff = signingUtils.signMessage(approvalHashBuff, this._privateKey, signatureType);
|
||||||
|
const transactionHash = hashUtils.getTransactionHashHex(transaction);
|
||||||
|
const signedApproval = {
|
||||||
|
transactionHash,
|
||||||
|
approvalExpirationTimeSeconds,
|
||||||
|
transactionSignature: transaction.signature,
|
||||||
|
approvalSignature: ethUtil.addHexPrefix(signatureBuff.toString('hex')),
|
||||||
|
};
|
||||||
|
return signedApproval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -4,16 +4,16 @@ import { SignedZeroExTransaction, ZeroExTransaction } from '@0x/types';
|
|||||||
import { BigNumber, signTypedDataUtils } from '@0x/utils';
|
import { BigNumber, signTypedDataUtils } from '@0x/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { constants } from './constants';
|
import { constants } from './index';
|
||||||
|
|
||||||
export const approvalHashUtils = {
|
export const hashUtils = {
|
||||||
getApprovalHashBuffer(transaction: SignedZeroExTransaction, approvalExpirationTimeSeconds: BigNumber): Buffer {
|
getApprovalHashBuffer(transaction: SignedZeroExTransaction, approvalExpirationTimeSeconds: BigNumber): Buffer {
|
||||||
const domain = {
|
const domain = {
|
||||||
name: constants.TEC_DOMAIN_NAME,
|
name: constants.TEC_DOMAIN_NAME,
|
||||||
version: constants.TEC_DOMAIN_VERSION,
|
version: constants.TEC_DOMAIN_VERSION,
|
||||||
verifyingContractAddress: transaction.verifyingContractAddress,
|
verifyingContractAddress: transaction.verifyingContractAddress,
|
||||||
};
|
};
|
||||||
const transactionHash = approvalHashUtils._getTransactionHashHex(transaction);
|
const transactionHash = hashUtils.getTransactionHashHex(transaction);
|
||||||
const approval = {
|
const approval = {
|
||||||
transactionHash,
|
transactionHash,
|
||||||
transactionSignature: transaction.signature,
|
transactionSignature: transaction.signature,
|
||||||
@@ -31,12 +31,12 @@ export const approvalHashUtils = {
|
|||||||
return hashBuffer;
|
return hashBuffer;
|
||||||
},
|
},
|
||||||
getApprovalHashHex(transaction: SignedZeroExTransaction, approvalExpirationTimeSeconds: BigNumber): string {
|
getApprovalHashHex(transaction: SignedZeroExTransaction, approvalExpirationTimeSeconds: BigNumber): string {
|
||||||
const hashHex = `0x${approvalHashUtils
|
const hashHex = `0x${hashUtils
|
||||||
.getApprovalHashBuffer(transaction, approvalExpirationTimeSeconds)
|
.getApprovalHashBuffer(transaction, approvalExpirationTimeSeconds)
|
||||||
.toString('hex')}`;
|
.toString('hex')}`;
|
||||||
return hashHex;
|
return hashHex;
|
||||||
},
|
},
|
||||||
_getTransactionHashBuffer(transaction: ZeroExTransaction | SignedZeroExTransaction): Buffer {
|
getTransactionHashBuffer(transaction: ZeroExTransaction | SignedZeroExTransaction): Buffer {
|
||||||
const domain = {
|
const domain = {
|
||||||
name: constants.TEC_DOMAIN_NAME,
|
name: constants.TEC_DOMAIN_NAME,
|
||||||
version: constants.TEC_DOMAIN_VERSION,
|
version: constants.TEC_DOMAIN_VERSION,
|
||||||
@@ -54,8 +54,8 @@ export const approvalHashUtils = {
|
|||||||
const hashBuffer = signTypedDataUtils.generateTypedDataHash(typedData);
|
const hashBuffer = signTypedDataUtils.generateTypedDataHash(typedData);
|
||||||
return hashBuffer;
|
return hashBuffer;
|
||||||
},
|
},
|
||||||
_getTransactionHashHex(transaction: ZeroExTransaction | SignedZeroExTransaction): string {
|
getTransactionHashHex(transaction: ZeroExTransaction | SignedZeroExTransaction): string {
|
||||||
const hashHex = `0x${approvalHashUtils._getTransactionHashBuffer(transaction).toString('hex')}`;
|
const hashHex = `0x${hashUtils.getTransactionHashBuffer(transaction).toString('hex')}`;
|
||||||
return hashHex;
|
return hashHex;
|
||||||
},
|
},
|
||||||
};
|
};
|
@@ -1,3 +1,6 @@
|
|||||||
export { approvalHashUtils } from './approval_hash';
|
export { hashUtils } from './hash_utils';
|
||||||
|
export { signingUtils } from './signing_utils';
|
||||||
export { TECTransactionFactory } from './tec_transaction_factory';
|
export { TECTransactionFactory } from './tec_transaction_factory';
|
||||||
|
export { ApprovalFactory } from './approval_factory';
|
||||||
|
export { constants } from './constants';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
30
contracts/tec/test/utils/signing_utils.ts
Normal file
30
contracts/tec/test/utils/signing_utils.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
|
|
||||||
|
import { TECSignatureType } from './types';
|
||||||
|
|
||||||
|
export const signingUtils = {
|
||||||
|
signMessage(message: Buffer, privateKey: Buffer, signatureType: TECSignatureType): Buffer {
|
||||||
|
if (signatureType === TECSignatureType.EthSign) {
|
||||||
|
const prefixedMessage = ethUtil.hashPersonalMessage(message);
|
||||||
|
const ecSignature = ethUtil.ecsign(prefixedMessage, privateKey);
|
||||||
|
const signature = Buffer.concat([
|
||||||
|
ethUtil.toBuffer(ecSignature.v),
|
||||||
|
ecSignature.r,
|
||||||
|
ecSignature.s,
|
||||||
|
ethUtil.toBuffer(signatureType),
|
||||||
|
]);
|
||||||
|
return signature;
|
||||||
|
} else if (signatureType === TECSignatureType.EIP712) {
|
||||||
|
const ecSignature = ethUtil.ecsign(message, privateKey);
|
||||||
|
const signature = Buffer.concat([
|
||||||
|
ethUtil.toBuffer(ecSignature.v),
|
||||||
|
ecSignature.r,
|
||||||
|
ecSignature.s,
|
||||||
|
ethUtil.toBuffer(signatureType),
|
||||||
|
]);
|
||||||
|
return signature;
|
||||||
|
} else {
|
||||||
|
throw new Error(`${signatureType} is not a valid signature type`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
@@ -1,31 +1,34 @@
|
|||||||
import { TransactionFactory } from '@0x/contracts-test-utils';
|
import { generatePseudoRandomSalt } from '@0x/order-utils';
|
||||||
import { SignatureType, SignedZeroExTransaction } from '@0x/types';
|
import { SignedZeroExTransaction } from '@0x/types';
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
|
|
||||||
import { TECSignatureType } from './types';
|
import { hashUtils, signingUtils, TECSignatureType } from './index';
|
||||||
|
|
||||||
export class TECTransactionFactory extends TransactionFactory {
|
export class TECTransactionFactory {
|
||||||
constructor(privateKey: Buffer, exchangeAddress: string) {
|
private readonly _signerBuff: Buffer;
|
||||||
super(privateKey, exchangeAddress);
|
private readonly _verifyingContractAddress: string;
|
||||||
|
private readonly _privateKey: Buffer;
|
||||||
|
constructor(privateKey: Buffer, verifyingContractAddress: string) {
|
||||||
|
this._privateKey = privateKey;
|
||||||
|
this._verifyingContractAddress = verifyingContractAddress;
|
||||||
|
this._signerBuff = ethUtil.privateToAddress(this._privateKey);
|
||||||
}
|
}
|
||||||
public newSignedTECTransaction(
|
public newSignedTECTransaction(
|
||||||
data: string,
|
data: string,
|
||||||
signatureType: TECSignatureType = TECSignatureType.EthSign,
|
signatureType: TECSignatureType = TECSignatureType.EthSign,
|
||||||
): SignedZeroExTransaction {
|
): SignedZeroExTransaction {
|
||||||
let exchangeSignatureType;
|
const transaction = {
|
||||||
if (signatureType === TECSignatureType.EthSign) {
|
verifyingContractAddress: this._verifyingContractAddress,
|
||||||
exchangeSignatureType = SignatureType.EthSign;
|
signerAddress: ethUtil.addHexPrefix(this._signerBuff.toString('hex')),
|
||||||
} else if (signatureType === TECSignatureType.EIP712) {
|
salt: generatePseudoRandomSalt(),
|
||||||
exchangeSignatureType = SignatureType.EIP712;
|
data,
|
||||||
} else {
|
};
|
||||||
throw new Error(`Error: ${signatureType} not a valid signature type`);
|
const transactionHashBuff = hashUtils.getTransactionHashBuffer(transaction);
|
||||||
}
|
const signatureBuff = signingUtils.signMessage(transactionHashBuff, this._privateKey, signatureType);
|
||||||
const signedTransaction = super.newSignedTransaction(data, exchangeSignatureType);
|
const signedTransaction = {
|
||||||
const tecSignatureTypeByte = ethUtil.toBuffer(signatureType).toString('hex');
|
...transaction,
|
||||||
signedTransaction.signature = `${signedTransaction.signature.slice(
|
signature: ethUtil.addHexPrefix(signatureBuff.toString('hex')),
|
||||||
0,
|
};
|
||||||
signedTransaction.signature.length - 2,
|
|
||||||
)}${tecSignatureTypeByte}`;
|
|
||||||
return signedTransaction;
|
return signedTransaction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,10 @@ export interface TECApproval {
|
|||||||
approvalExpirationTimeSeconds: BigNumber;
|
approvalExpirationTimeSeconds: BigNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SignedTECApproval extends TECApproval {
|
||||||
|
approvalSignature: string;
|
||||||
|
}
|
||||||
|
|
||||||
export enum TECSignatureType {
|
export enum TECSignatureType {
|
||||||
Illegal,
|
Illegal,
|
||||||
EIP712,
|
EIP712,
|
||||||
|
@@ -3,9 +3,9 @@
|
|||||||
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
|
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
|
||||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||||
"files": [
|
"files": [
|
||||||
"generated-artifacts/MixinSignatureValidator.json",
|
|
||||||
"generated-artifacts/TEC.json",
|
"generated-artifacts/TEC.json",
|
||||||
"generated-artifacts/TestLibs.json"
|
"generated-artifacts/TestLibs.json",
|
||||||
|
"generated-artifacts/TestMixins.json"
|
||||||
],
|
],
|
||||||
"exclude": ["./deploy/solc/solc_bin"]
|
"exclude": ["./deploy/solc/solc_bin"]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user