Refactor TS tooling

This commit is contained in:
Michael Zhu
2022-01-12 22:06:08 -08:00
parent 9047abbc9b
commit 3a3e447dc1
5 changed files with 242 additions and 230 deletions

View File

@@ -7,7 +7,7 @@ import {
randomAddress,
verifyEventsFromLogs,
} from '@0x/contracts-test-utils';
import { ERC721Order, RevertErrors, SIGNATURE_ABI, SignatureType } from '@0x/protocol-utils';
import { ERC721Order, NFTOrder, RevertErrors, SIGNATURE_ABI, SignatureType } from '@0x/protocol-utils';
import { AbiEncoder, BigNumber, hexUtils, NULL_BYTES, StringRevertError } from '@0x/utils';
import {
@@ -150,7 +150,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
_taker: string = taker,
): Promise<void> {
const totalFeeAmount = order.fees.length > 0 ? BigNumber.sum(...order.fees.map(fee => fee.amount)) : ZERO;
if (order.direction === ERC721Order.TradeDirection.Sell721) {
if (order.direction === NFTOrder.TradeDirection.SellNFT) {
await erc721Token.mint(order.maker, tokenId).awaitTransactionSuccessAsync();
if (order.erc20Token !== ETH_TOKEN_ADDRESS) {
await erc20Token
@@ -178,7 +178,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
_taker: string = taker,
): Promise<void> {
const token = order.erc20Token === weth.address ? weth : erc20Token;
if (order.direction === ERC721Order.TradeDirection.Sell721) {
if (order.direction === NFTOrder.TradeDirection.SellNFT) {
const makerBalance = await token.balanceOf(order.maker).callAsync();
expect(makerBalance).to.bignumber.equal(order.erc20TokenAmount);
const erc721Owner = await erc721Token.ownerOf(tokenId).callAsync();
@@ -333,7 +333,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
verifyEventsFromLogs(tx.logs, [{ maker, nonce: order.nonce }], IZeroExEvents.ERC721OrderCancelled);
const orderStatus = await zeroEx.getERC721OrderStatus(order).callAsync();
expect(orderStatus).to.equal(ERC721Order.OrderStatus.Unfillable);
expect(orderStatus).to.equal(NFTOrder.OrderStatus.Unfillable);
const bitVector = await zeroEx
.getERC721OrderStatusBitVector(maker, order.nonce.dividedToIntegerBy(256))
.callAsync();
@@ -350,7 +350,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
verifyEventsFromLogs(tx.logs, [{ maker, nonce: order.nonce }], IZeroExEvents.ERC721OrderCancelled);
const orderStatus = await zeroEx.getERC721OrderStatus(order).callAsync();
expect(orderStatus).to.equal(ERC721Order.OrderStatus.Unfillable);
expect(orderStatus).to.equal(NFTOrder.OrderStatus.Unfillable);
const bitVector = await zeroEx
.getERC721OrderStatusBitVector(maker, order.nonce.dividedToIntegerBy(256))
.callAsync();
@@ -362,7 +362,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
describe('sellERC721', () => {
it('can fill a ERC721 buy order', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -381,7 +381,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('cannot fill the same order twice', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -396,16 +396,12 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
from: taker,
});
return expect(tx).to.revertWith(
new RevertErrors.NFTOrders.OrderNotFillableError(
maker,
order.nonce,
ERC721Order.OrderStatus.Unfillable,
),
new RevertErrors.NFTOrders.OrderNotFillableError(maker, order.nonce, NFTOrder.OrderStatus.Unfillable),
);
});
it('can fill two orders from the same maker with different nonces', async () => {
const order1 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
nonce: ZERO,
});
const signature1 = await order1.getSignatureWithProviderAsync(env.provider);
@@ -416,7 +412,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
from: taker,
});
const order2 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
nonce: new BigNumber(1),
});
const signature2 = await order2.getSignatureWithProviderAsync(env.provider);
@@ -431,7 +427,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('cannot fill a cancelled order', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -444,16 +440,12 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
from: taker,
});
return expect(tx).to.revertWith(
new RevertErrors.NFTOrders.OrderNotFillableError(
maker,
order.nonce,
ERC721Order.OrderStatus.Unfillable,
),
new RevertErrors.NFTOrders.OrderNotFillableError(maker, order.nonce, NFTOrder.OrderStatus.Unfillable),
);
});
it('cannot fill an invalid order (erc20Token == ETH)', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc20Token: ETH_TOKEN_ADDRESS,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
@@ -467,7 +459,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('cannot fill an expired order', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
expiry: new BigNumber(Math.floor(Date.now() / 1000 - 1)),
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
@@ -478,12 +470,12 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
from: taker,
});
return expect(tx).to.revertWith(
new RevertErrors.NFTOrders.OrderNotFillableError(maker, order.nonce, ERC721Order.OrderStatus.Expired),
new RevertErrors.NFTOrders.OrderNotFillableError(maker, order.nonce, NFTOrder.OrderStatus.Expired),
);
});
it('reverts if a sell order is provided', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -496,7 +488,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('reverts if the taker is not the taker address specified in the order', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
taker,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
@@ -510,7 +502,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('succeeds if the taker is the taker address specified in the order', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
taker,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
@@ -524,7 +516,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('reverts if an invalid signature is provided', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider, SignatureType.EIP712, otherMaker);
await mintAssetsAsync(order);
@@ -537,7 +529,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('reverts if `unwrapNativeToken` is true and `erc20Token` is not WETH', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -552,7 +544,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('sends ETH to taker if `unwrapNativeToken` is true and `erc20Token` is WETH', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc20Token: weth.address,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
@@ -571,7 +563,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
describe('fees', () => {
it('single fee to EOA', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
fees: [
{
recipient: otherMaker,
@@ -591,7 +583,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('single fee, successful callback', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
fees: [
{
recipient: feeRecipient.address,
@@ -611,7 +603,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('single fee, callback reverts', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
fees: [
{
recipient: feeRecipient.address,
@@ -631,7 +623,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('single fee, callback returns invalid value', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
fees: [
{
recipient: feeRecipient.address,
@@ -651,7 +643,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('multiple fees to EOAs', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
fees: [
{
recipient: otherMaker,
@@ -688,7 +680,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('Checks tokenId if no properties are provided', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order, order.erc721TokenId.plus(1));
@@ -703,7 +695,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('Null property', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc721TokenId: ZERO,
erc721TokenProperties: [
{
@@ -722,7 +714,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('Reverts if property validation fails', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc721TokenId: ZERO,
erc721TokenProperties: [
{
@@ -751,7 +743,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('Successful property validation', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc721TokenId: ZERO,
erc721TokenProperties: [
{
@@ -811,7 +803,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('throws if data is not encoded correctly', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
await mintAssetsAsync(order);
const tx = erc721Token
@@ -823,7 +815,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('reverts if msg.sender != order.erc721Token', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -847,7 +839,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('reverts if transferred tokenId does not match order.erc721TokenId', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order, order.erc721TokenId.plus(1));
@@ -872,7 +864,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('can sell ERC721 without approval', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -901,7 +893,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
describe('buyERC721', () => {
it('can fill a ERC721 sell order', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -918,7 +910,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('cannot fill the same order twice', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -929,16 +921,12 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
from: taker,
});
return expect(tx).to.revertWith(
new RevertErrors.NFTOrders.OrderNotFillableError(
maker,
order.nonce,
ERC721Order.OrderStatus.Unfillable,
),
new RevertErrors.NFTOrders.OrderNotFillableError(maker, order.nonce, NFTOrder.OrderStatus.Unfillable),
);
});
it('cannot fill a cancelled order', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -949,16 +937,12 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
from: taker,
});
return expect(tx).to.revertWith(
new RevertErrors.NFTOrders.OrderNotFillableError(
maker,
order.nonce,
ERC721Order.OrderStatus.Unfillable,
),
new RevertErrors.NFTOrders.OrderNotFillableError(maker, order.nonce, NFTOrder.OrderStatus.Unfillable),
);
});
it('cannot fill an expired order', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
expiry: new BigNumber(Math.floor(Date.now() / 1000 - 1)),
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
@@ -967,12 +951,12 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
from: taker,
});
return expect(tx).to.revertWith(
new RevertErrors.NFTOrders.OrderNotFillableError(maker, order.nonce, ERC721Order.OrderStatus.Expired),
new RevertErrors.NFTOrders.OrderNotFillableError(maker, order.nonce, NFTOrder.OrderStatus.Expired),
);
});
it('reverts if a buy order is provided', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -983,7 +967,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('reverts if the taker is not the taker address specified in the order', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
taker,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
@@ -995,7 +979,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('succeeds if the taker is the taker address specified in the order', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
taker,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
@@ -1007,7 +991,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('reverts if an invalid signature is provided', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider, SignatureType.EIP712, otherMaker);
await mintAssetsAsync(order);
@@ -1020,7 +1004,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
it('can fill an order with ETH (and refunds excess ETH)', async () => {
const order = getTestERC721Order({
erc20Token: ETH_TOKEN_ADDRESS,
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -1049,7 +1033,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
it('can fill a WETH order with ETH', async () => {
const order = getTestERC721Order({
erc20Token: weth.address,
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await erc721Token.mint(maker, order.erc721TokenId).awaitTransactionSuccessAsync();
@@ -1065,7 +1049,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
it('uses WETH if not enough ETH to fill WETH order', async () => {
const order = getTestERC721Order({
erc20Token: weth.address,
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await weth.deposit().awaitTransactionSuccessAsync({
@@ -1086,7 +1070,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
describe('fees', () => {
it('single fee to EOA', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
fees: [
{
recipient: otherMaker,
@@ -1104,7 +1088,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('pays fees in ETH if erc20Token == ETH', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: ETH_TOKEN_ADDRESS,
fees: [
{
@@ -1138,7 +1122,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('pays fees in ETH if erc20Token == WETH but taker uses ETH', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: weth.address,
fees: [
{
@@ -1184,7 +1168,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('pays fees in WETH if taker uses WETH', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: weth.address,
fees: [
{
@@ -1207,7 +1191,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('reverts if overspent ETH', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: ETH_TOKEN_ADDRESS,
fees: [
{
@@ -1236,7 +1220,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
describe('batchBuyERC721s', () => {
it('reverts if arrays are different lengths', async () => {
const order = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature = await order.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order);
@@ -1247,12 +1231,12 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('successfully fills multiple orders', async () => {
const order1 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature1 = await order1.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order1);
const order2 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: weth.address,
});
const signature2 = await order2.getSignatureWithProviderAsync(env.provider);
@@ -1271,12 +1255,12 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('catches revert if one order fails', async () => {
const order1 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature1 = await order1.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order1);
const order2 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: weth.address,
});
// invalid signature
@@ -1306,12 +1290,12 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('bubbles up revert if one order fails and `revertIfIncomplete == true`', async () => {
const order1 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature1 = await order1.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order1);
const order2 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: weth.address,
});
// invalid signature
@@ -1334,13 +1318,13 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('can fill multiple orders with ETH, refund excess ETH', async () => {
const order1 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: ETH_TOKEN_ADDRESS,
});
const signature1 = await order1.getSignatureWithProviderAsync(env.provider);
await mintAssetsAsync(order1);
const order2 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: weth.address,
});
const signature2 = await order2.getSignatureWithProviderAsync(env.provider);
@@ -1384,7 +1368,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
it('can fill order that has been presigned by the maker', async () => {
const order = getTestERC721Order({
maker: contractMaker.address,
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
await mintAssetsAsync(order);
await contractMaker.preSignOrder(order).awaitTransactionSuccessAsync();
@@ -1398,7 +1382,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
it('cannot fill order that has not been presigned by the maker', async () => {
const order = getTestERC721Order({
maker: contractMaker.address,
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
await mintAssetsAsync(order);
const tx = zeroEx
@@ -1413,7 +1397,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
it('cannot fill order that was presigned then cancelled', async () => {
const order = getTestERC721Order({
maker: contractMaker.address,
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
await mintAssetsAsync(order);
await contractMaker.preSignOrder(order).awaitTransactionSuccessAsync();
@@ -1427,7 +1411,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
new RevertErrors.NFTOrders.OrderNotFillableError(
contractMaker.address,
order.nonce,
ERC721Order.OrderStatus.Unfillable,
NFTOrder.OrderStatus.Unfillable,
),
);
});
@@ -1435,11 +1419,11 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
describe('matchERC721Orders', () => {
it('cannot match two sell orders', async () => {
const order1 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature1 = await order1.getSignatureWithProviderAsync(env.provider);
const order2 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const signature2 = await order2.getSignatureWithProviderAsync(env.provider);
const tx = zeroEx.matchERC721Orders(order1, order2, signature1, signature2).awaitTransactionSuccessAsync({
@@ -1449,11 +1433,11 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('cannot match two buy orders', async () => {
const order1 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature1 = await order1.getSignatureWithProviderAsync(env.provider);
const order2 = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const signature2 = await order2.getSignatureWithProviderAsync(env.provider);
const tx = zeroEx.matchERC721Orders(order1, order2, signature1, signature2).awaitTransactionSuccessAsync({
@@ -1463,11 +1447,11 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('erc721TokenId must match', async () => {
const sellOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const sellSignature = await sellOrder.getSignatureWithProviderAsync(env.provider);
const buyOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
});
const buySignature = await buyOrder.getSignatureWithProviderAsync(env.provider);
const tx = zeroEx
@@ -1481,11 +1465,11 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('erc721Token must match', async () => {
const sellOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const sellSignature = await sellOrder.getSignatureWithProviderAsync(env.provider);
const buyOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc721Token: erc20Token.address,
erc721TokenId: sellOrder.erc721TokenId,
});
@@ -1501,11 +1485,11 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('erc20Token must match', async () => {
const sellOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const sellSignature = await sellOrder.getSignatureWithProviderAsync(env.provider);
const buyOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc20Token: weth.address,
erc721TokenId: sellOrder.erc721TokenId,
});
@@ -1521,11 +1505,11 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('reverts if spread is negative', async () => {
const sellOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const sellSignature = await sellOrder.getSignatureWithProviderAsync(env.provider);
const buyOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc721TokenId: sellOrder.erc721TokenId,
erc20TokenAmount: sellOrder.erc20TokenAmount.minus(1),
});
@@ -1541,13 +1525,13 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('matches two orders and sends profit to matcher', async () => {
const sellOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
});
const sellSignature = await sellOrder.getSignatureWithProviderAsync(env.provider);
const spread = getRandomInteger(1, '1e18');
const buyOrder = getTestERC721Order({
maker: otherMaker,
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc721TokenId: sellOrder.erc721TokenId,
erc20TokenAmount: sellOrder.erc20TokenAmount.plus(spread),
});
@@ -1564,14 +1548,14 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
});
it('matches two ETH/WETH orders and sends profit to matcher', async () => {
const sellOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: ETH_TOKEN_ADDRESS,
});
const sellSignature = await sellOrder.getSignatureWithProviderAsync(env.provider);
const spread = getRandomInteger(1, '1e18');
const buyOrder = getTestERC721Order({
maker: otherMaker,
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc20Token: weth.address,
erc721TokenId: sellOrder.erc721TokenId,
erc20TokenAmount: sellOrder.erc20TokenAmount.plus(spread),
@@ -1595,7 +1579,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
it('matches two orders (with fees) and sends profit to matcher', async () => {
const spread = getRandomInteger(1, '1e18');
const sellOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
fees: [
{
recipient: otherTaker,
@@ -1607,7 +1591,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
const sellSignature = await sellOrder.getSignatureWithProviderAsync(env.provider);
const buyOrder = getTestERC721Order({
maker: otherMaker,
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc721TokenId: sellOrder.erc721TokenId,
erc20TokenAmount: sellOrder.erc20TokenAmount.plus(spread),
});
@@ -1626,7 +1610,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
it('matches two ETH/WETH (with fees) orders and sends profit to matcher', async () => {
const spread = getRandomInteger(1, '1e18');
const sellOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: ETH_TOKEN_ADDRESS,
fees: [
{
@@ -1639,7 +1623,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
const sellSignature = await sellOrder.getSignatureWithProviderAsync(env.provider);
const buyOrder = getTestERC721Order({
maker: otherMaker,
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc20Token: weth.address,
erc721TokenId: sellOrder.erc721TokenId,
erc20TokenAmount: sellOrder.erc20TokenAmount.plus(spread),
@@ -1668,7 +1652,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
it('reverts if sell order fees exceed spread', async () => {
const spread = getRandomInteger(1, '1e18');
const sellOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
fees: [
{
recipient: otherTaker,
@@ -1680,7 +1664,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
const sellSignature = await sellOrder.getSignatureWithProviderAsync(env.provider);
const buyOrder = getTestERC721Order({
maker: otherMaker,
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc721TokenId: sellOrder.erc721TokenId,
erc20TokenAmount: sellOrder.erc20TokenAmount.plus(spread),
});
@@ -1699,7 +1683,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
it('reverts if sell order fees exceed spread (ETH/WETH)', async () => {
const spread = getRandomInteger(1, '1e18');
const sellOrder = getTestERC721Order({
direction: ERC721Order.TradeDirection.Sell721,
direction: NFTOrder.TradeDirection.SellNFT,
erc20Token: ETH_TOKEN_ADDRESS,
fees: [
{
@@ -1713,7 +1697,7 @@ blockchainTests.resets.only('ERC721OrdersFeature', env => {
const sellSignature = await sellOrder.getSignatureWithProviderAsync(env.provider);
const buyOrder = getTestERC721Order({
maker: otherMaker,
direction: ERC721Order.TradeDirection.Buy721,
direction: NFTOrder.TradeDirection.BuyNFT,
erc20Token: weth.address,
erc721TokenId: sellOrder.erc721TokenId,
erc20TokenAmount: sellOrder.erc20TokenAmount.plus(spread),

View File

@@ -2,6 +2,13 @@ import * as _RevertErrors from './revert-errors';
export const RevertErrors = _RevertErrors;
export const RevertError = _RevertErrors.RevertError;
import { ERC721Order, OrderStatus, TradeDirection } from './nft_orders';
export { ERC721Order };
export const NFTOrder = {
OrderStatus,
TradeDirection,
};
export * from './eip712_utils';
export * from './orders';
export * from './meta_transactions';
@@ -10,4 +17,3 @@ export * from './transformer_utils';
export * from './constants';
export * from './vip_utils';
export * from './treasury_votes';
export * from './erc721_orders';

View File

@@ -19,7 +19,140 @@ import {
SignatureType,
} from './signature_utils';
export class ERC721Order {
export enum TradeDirection {
SellNFT = 0,
BuyNFT = 1,
}
export enum OrderStatus {
Invalid = 0,
Fillable = 1,
Unfillable = 2,
Expired = 3,
}
export interface Fee {
recipient: string;
amount: BigNumber;
feeData: string;
}
export interface Property {
propertyValidator: string;
propertyData: string;
}
const NFT_ORDER_DEFAULT_VALUES = {
direction: TradeDirection.SellNFT,
maker: NULL_ADDRESS,
taker: NULL_ADDRESS,
expiry: ZERO,
nonce: ZERO,
erc20Token: NULL_ADDRESS,
erc20TokenAmount: ZERO,
fees: [] as Fee[],
chainId: 1,
verifyingContract: getContractAddressesForChainOrThrow(1).exchangeProxy,
};
const ERC721_ORDER_DEFAULT_VALUES = {
direction: TradeDirection.SellNFT,
maker: NULL_ADDRESS,
taker: NULL_ADDRESS,
expiry: ZERO,
nonce: ZERO,
erc20Token: NULL_ADDRESS,
erc20TokenAmount: ZERO,
fees: [] as Fee[],
erc721Token: NULL_ADDRESS,
erc721TokenId: ZERO,
erc721TokenProperties: [] as Property[],
chainId: 1,
verifyingContract: getContractAddressesForChainOrThrow(1).exchangeProxy,
};
export type CommonNFTOrderFields = typeof NFT_ORDER_DEFAULT_VALUES;
export type ERC721OrderFields = typeof ERC721_ORDER_DEFAULT_VALUES;
export abstract class NFTOrder {
public static readonly FEE_ABI = [
{ type: 'address', name: 'recipient' },
{ type: 'uint256', name: 'amount' },
{ type: 'bytes', name: 'feeData' },
];
public static readonly PROPERTY_ABI = [
{ type: 'address', name: 'propertyValidator' },
{ type: 'bytes', name: 'propertyData' },
];
public static readonly FEE_TYPE_HASH = getTypeHash('Fee', NFTOrder.FEE_ABI);
public static readonly PROPERTY_TYPE_HASH = getTypeHash('Property', NFTOrder.PROPERTY_ABI);
public direction: TradeDirection;
public maker: string;
public taker: string;
public expiry: BigNumber;
public nonce: BigNumber;
public erc20Token: string;
public erc20TokenAmount: BigNumber;
public fees: Fee[];
public chainId: number;
public verifyingContract: string;
protected constructor(fields: Partial<CommonNFTOrderFields> = {}) {
const _fields = { ...NFT_ORDER_DEFAULT_VALUES, ...fields };
this.direction = _fields.direction;
this.maker = _fields.maker;
this.taker = _fields.taker;
this.expiry = _fields.expiry;
this.nonce = _fields.nonce;
this.erc20Token = _fields.erc20Token;
this.erc20TokenAmount = _fields.erc20TokenAmount;
this.fees = _fields.fees;
this.chainId = _fields.chainId;
this.verifyingContract = _fields.verifyingContract;
}
public abstract getStructHash(): string;
public abstract getEIP712TypedData(): EIP712TypedData;
public willExpire(secondsFromNow: number = 0): boolean {
const millisecondsInSecond = 1000;
const currentUnixTimestampSec = new BigNumber(Date.now() / millisecondsInSecond).integerValue();
return this.expiry.isLessThan(currentUnixTimestampSec.plus(secondsFromNow));
}
public getHash(): string {
return getExchangeProxyEIP712Hash(this.getStructHash(), this.chainId, this.verifyingContract);
}
public async getSignatureWithProviderAsync(
provider: SupportedProvider,
type: SignatureType = SignatureType.EthSign,
signer: string = this.maker,
): Promise<Signature> {
switch (type) {
case SignatureType.EIP712:
return eip712SignTypedDataWithProviderAsync(this.getEIP712TypedData(), signer, provider);
case SignatureType.EthSign:
return ethSignHashWithProviderAsync(this.getHash(), signer, provider);
default:
throw new Error(`Cannot sign with signature type: ${type}`);
}
}
public getSignatureWithKey(key: string, type: SignatureType = SignatureType.EthSign): Signature {
switch (type) {
case SignatureType.EIP712:
return eip712SignHashWithKey(this.getHash(), key);
case SignatureType.EthSign:
return ethSignHashWithKey(this.getHash(), key);
default:
throw new Error(`Cannot sign with signature type: ${type}`);
}
}
}
export class ERC721Order extends NFTOrder {
public static readonly STRUCT_NAME = 'ERC721Order';
public static readonly STRUCT_ABI = [
{ type: 'uint8', name: 'direction' },
@@ -34,55 +167,22 @@ export class ERC721Order {
{ type: 'uint256', name: 'erc721TokenId' },
{ type: 'Property[]', name: 'erc721TokenProperties' },
];
public static readonly REFERENCED_STRUCT_ABIS = {
['Fee']: [
{ type: 'address', name: 'recipient' },
{ type: 'uint256', name: 'amount' },
{ type: 'bytes', name: 'feeData' },
],
['Property']: [
{ type: 'address', name: 'propertyValidator' },
{ type: 'bytes', name: 'propertyData' },
],
};
public static readonly TYPE_HASH = getTypeHash(
ERC721Order.STRUCT_NAME,
ERC721Order.STRUCT_ABI,
ERC721Order.REFERENCED_STRUCT_ABIS,
);
public static readonly FEE_TYPE_HASH = getTypeHash('Fee', ERC721Order.REFERENCED_STRUCT_ABIS.Fee);
public static readonly PROPERTY_TYPE_HASH = getTypeHash('Property', ERC721Order.REFERENCED_STRUCT_ABIS.Property);
public static readonly TYPE_HASH = getTypeHash(ERC721Order.STRUCT_NAME, ERC721Order.STRUCT_ABI, {
['Fee']: NFTOrder.FEE_ABI,
['Property']: NFTOrder.PROPERTY_ABI,
});
public direction: ERC721Order.TradeDirection;
public maker: string;
public taker: string;
public expiry: BigNumber;
public nonce: BigNumber;
public erc20Token: string;
public erc20TokenAmount: BigNumber;
public fees: ERC721Order.Fee[];
public erc721Token: string;
public erc721TokenId: BigNumber;
public erc721TokenProperties: ERC721Order.Property[];
public chainId: number;
public verifyingContract: string;
public erc721TokenProperties: Property[];
constructor(fields: Partial<ERC721OrderFields> = {}) {
const _fields = { ...ERC721_ORDER_DEFAULT_VALUES, ...fields };
this.direction = _fields.direction;
this.maker = _fields.maker;
this.taker = _fields.taker;
this.expiry = _fields.expiry;
this.nonce = _fields.nonce;
this.erc20Token = _fields.erc20Token;
this.erc20TokenAmount = _fields.erc20TokenAmount;
this.fees = _fields.fees;
super(_fields);
this.erc721Token = _fields.erc721Token;
this.erc721TokenId = _fields.erc721TokenId;
this.erc721TokenProperties = _fields.erc721TokenProperties;
this.chainId = _fields.chainId;
this.verifyingContract = _fields.verifyingContract;
}
public clone(fields: Partial<ERC721OrderFields> = {}): ERC721Order {
@@ -155,7 +255,8 @@ export class ERC721Order {
types: {
EIP712Domain: EIP712_DOMAIN_PARAMETERS,
[ERC721Order.STRUCT_NAME]: ERC721Order.STRUCT_ABI,
...ERC721Order.REFERENCED_STRUCT_ABIS,
['Fee']: NFTOrder.FEE_ABI,
['Property']: NFTOrder.PROPERTY_ABI,
},
domain: createExchangeProxyEIP712Domain(this.chainId, this.verifyingContract) as any,
primaryType: ERC721Order.STRUCT_NAME,
@@ -178,83 +279,4 @@ export class ERC721Order {
},
};
}
public willExpire(secondsFromNow: number = 0): boolean {
const millisecondsInSecond = 1000;
const currentUnixTimestampSec = new BigNumber(Date.now() / millisecondsInSecond).integerValue();
return this.expiry.isLessThan(currentUnixTimestampSec.plus(secondsFromNow));
}
public getHash(): string {
return getExchangeProxyEIP712Hash(this.getStructHash(), this.chainId, this.verifyingContract);
}
public async getSignatureWithProviderAsync(
provider: SupportedProvider,
type: SignatureType = SignatureType.EthSign,
signer: string = this.maker,
): Promise<Signature> {
switch (type) {
case SignatureType.EIP712:
return eip712SignTypedDataWithProviderAsync(this.getEIP712TypedData(), signer, provider);
case SignatureType.EthSign:
return ethSignHashWithProviderAsync(this.getHash(), signer, provider);
default:
throw new Error(`Cannot sign with signature type: ${type}`);
}
}
public getSignatureWithKey(key: string, type: SignatureType = SignatureType.EthSign): Signature {
switch (type) {
case SignatureType.EIP712:
return eip712SignHashWithKey(this.getHash(), key);
case SignatureType.EthSign:
return ethSignHashWithKey(this.getHash(), key);
default:
throw new Error(`Cannot sign with signature type: ${type}`);
}
}
}
export namespace ERC721Order {
export interface Property {
propertyValidator: string;
propertyData: string;
}
export interface Fee {
recipient: string;
amount: BigNumber;
feeData: string;
}
export enum TradeDirection {
Sell721 = 0,
Buy721 = 1,
}
export enum OrderStatus {
Invalid = 0,
Fillable = 1,
Unfillable = 2,
Expired = 3,
}
}
const ERC721_ORDER_DEFAULT_VALUES = {
direction: ERC721Order.TradeDirection.Sell721,
maker: NULL_ADDRESS,
taker: NULL_ADDRESS,
expiry: ZERO,
nonce: ZERO,
erc20Token: NULL_ADDRESS,
erc20TokenAmount: ZERO,
fees: [] as ERC721Order.Fee[],
erc721Token: NULL_ADDRESS,
erc721TokenId: ZERO,
erc721TokenProperties: [] as ERC721Order.Property[],
chainId: 1,
verifyingContract: getContractAddressesForChainOrThrow(1).exchangeProxy,
};
export type ERC721OrderFields = typeof ERC721_ORDER_DEFAULT_VALUES;

View File

@@ -13,8 +13,8 @@ import {
Wallet,
} from './inherited';
import * as NativeOrders from './native_orders';
import * as Signatures from './signatures';
import * as NFTOrders from './nft_orders';
import * as Signatures from './signatures';
export {
Common,

View File

@@ -1,7 +1,7 @@
// tslint:disable: max-classes-per-file
import { Numberish, RevertError } from '@0x/utils';
import { ERC721Order } from '../erc721_orders';
import { OrderStatus } from '../nft_orders';
export class OverspentEthError extends RevertError {
constructor(ethSpent?: Numberish, msgValue?: Numberish) {
@@ -73,7 +73,7 @@ export class OnlyTakerError extends RevertError {
export { InvalidSignerError } from './native_orders';
export class OrderNotFillableError extends RevertError {
constructor(maker?: string, nonce?: Numberish, orderStatus?: ERC721Order.OrderStatus) {
constructor(maker?: string, nonce?: Numberish, orderStatus?: OrderStatus) {
super('OrderNotFillableError', 'OrderNotFillableError(address maker, uint256 nonce, uint8 orderStatus)', {
maker,
nonce,