178 lines
8.6 KiB
TypeScript
178 lines
8.6 KiB
TypeScript
import { ContractAddresses, ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers';
|
|
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
|
|
import { assetDataUtils } from '@0x/order-utils';
|
|
import { MarketOperation, SignedOrder } from '@0x/types';
|
|
import { BigNumber } from '@0x/utils';
|
|
import * as chai from 'chai';
|
|
import 'mocha';
|
|
|
|
import { SwapQuote, SwapQuoteConsumer } from '../src';
|
|
import { ExtensionContractType } from '../src/types';
|
|
|
|
import { chaiSetup } from './utils/chai_setup';
|
|
import { migrateOnceAsync } from './utils/migrate';
|
|
import { getFullyFillableSwapQuoteWithNoFees, getSignedOrdersWithNoFeesAsync } from './utils/swap_quote';
|
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
|
|
|
chaiSetup.configure();
|
|
const expect = chai.expect;
|
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
|
|
|
const ONE_ETH_IN_WEI = new BigNumber(1000000000000000000);
|
|
const TESTRPC_NETWORK_ID = 50;
|
|
const FILLABLE_AMOUNTS = [new BigNumber(3), new BigNumber(2), new BigNumber(5)].map(value =>
|
|
value.multipliedBy(ONE_ETH_IN_WEI),
|
|
);
|
|
|
|
const UNLIMITED_ALLOWANCE_IN_BASE_UNITS = new BigNumber(2).pow(256).minus(1); // tslint:disable-line:custom-no-magic-numbers
|
|
|
|
describe('SwapQuoteConsumer', () => {
|
|
let contractWrappers: ContractWrappers;
|
|
let erc20Token: ERC20TokenContract;
|
|
let userAddresses: string[];
|
|
let coinbaseAddress: string;
|
|
let makerAddress: string;
|
|
let takerAddress: string;
|
|
let feeRecipient: string;
|
|
let makerTokenAddress: string;
|
|
let takerTokenAddress: string;
|
|
let makerAssetData: string;
|
|
let takerAssetData: string;
|
|
let wethAssetData: string;
|
|
let contractAddresses: ContractAddresses;
|
|
|
|
const networkId = TESTRPC_NETWORK_ID;
|
|
|
|
let orders: SignedOrder[];
|
|
let marketSellSwapQuote: SwapQuote;
|
|
let swapQuoteConsumer: SwapQuoteConsumer;
|
|
let erc20ProxyAddress: string;
|
|
|
|
before(async () => {
|
|
contractAddresses = await migrateOnceAsync();
|
|
await blockchainLifecycle.startAsync();
|
|
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
|
const config = {
|
|
networkId,
|
|
contractAddresses,
|
|
};
|
|
contractWrappers = new ContractWrappers(provider, config);
|
|
[coinbaseAddress, takerAddress, makerAddress, feeRecipient] = userAddresses;
|
|
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
|
erc20Token = new ERC20TokenContract(makerTokenAddress, provider);
|
|
[makerAssetData, takerAssetData, wethAssetData] = [
|
|
assetDataUtils.encodeERC20AssetData(makerTokenAddress),
|
|
assetDataUtils.encodeERC20AssetData(takerTokenAddress),
|
|
assetDataUtils.encodeERC20AssetData(contractAddresses.etherToken),
|
|
];
|
|
});
|
|
after(async () => {
|
|
await blockchainLifecycle.revertAsync();
|
|
});
|
|
beforeEach(async () => {
|
|
await blockchainLifecycle.startAsync();
|
|
const UNLIMITED_ALLOWANCE = UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
|
erc20ProxyAddress = contractWrappers.erc20Proxy.address;
|
|
|
|
const totalFillableAmount = FILLABLE_AMOUNTS.reduce(
|
|
(a: BigNumber, c: BigNumber) => a.plus(c),
|
|
new BigNumber(0),
|
|
);
|
|
|
|
await erc20Token.transfer.sendTransactionAsync(makerAddress, totalFillableAmount, {
|
|
from: coinbaseAddress,
|
|
});
|
|
|
|
await erc20Token.approve.sendTransactionAsync(erc20ProxyAddress, UNLIMITED_ALLOWANCE, {
|
|
from: makerAddress,
|
|
});
|
|
orders = await getSignedOrdersWithNoFeesAsync(
|
|
provider,
|
|
makerAssetData,
|
|
wethAssetData,
|
|
makerAddress,
|
|
takerAddress,
|
|
FILLABLE_AMOUNTS,
|
|
contractAddresses.exchange,
|
|
);
|
|
|
|
marketSellSwapQuote = getFullyFillableSwapQuoteWithNoFees(
|
|
makerAssetData,
|
|
wethAssetData,
|
|
orders,
|
|
MarketOperation.Sell,
|
|
);
|
|
|
|
swapQuoteConsumer = new SwapQuoteConsumer(provider, {
|
|
networkId,
|
|
});
|
|
});
|
|
afterEach(async () => {
|
|
await blockchainLifecycle.revertAsync();
|
|
});
|
|
// TODO(david): write tests to ensure options work for executeSwapQuote
|
|
// describe('executeSwapQuoteOrThrowAsync', () => {
|
|
// /*
|
|
// * Testing that SwapQuoteConsumer logic correctly performs a execution (doesn't throw or revert)
|
|
// * Does not test the validity of the state change performed by the forwarder smart contract
|
|
// */
|
|
// it('should perform an asset swap with Forwarder contract when provided corresponding useExtensionContract option', async () => {
|
|
// let makerBalance = await erc20TokenContract.balanceOf.callAsync(makerAddress);
|
|
// let takerBalance = await erc20TokenContract.balanceOf.callAsync(takerAddress);
|
|
// expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
|
|
// expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
|
// await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketSellSwapQuote, { takerAddress, useExtensionContract: ConsumerType.Forwarder });
|
|
// makerBalance = await erc20TokenContract.balanceOf.callAsync(makerAddress);
|
|
// takerBalance = await erc20TokenContract.balanceOf.callAsync(takerAddress);
|
|
// expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
|
|
// expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
|
// });
|
|
// it('should perform an asset swap with Exchange contract when provided corresponding useExtensionContract option', async () => {
|
|
// let makerBalance = await erc20TokenContract.balanceOf.callAsync(makerAddress);
|
|
// let takerBalance = await erc20TokenContract.balanceOf.callAsync(takerAddress);
|
|
// expect(makerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
|
|
// expect(takerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
|
// await swapQuoteConsumer.executeSwapQuoteOrThrowAsync(marketBuySwapQuote, { takerAddress });
|
|
// makerBalance = await erc20TokenContract.balanceOf.callAsync(makerAddress);
|
|
// takerBalance = await erc20TokenContract.balanceOf.callAsync(takerAddress);
|
|
// expect(takerBalance).to.bignumber.equal(new BigNumber(10).multipliedBy(ONE_ETH_IN_WEI));
|
|
// expect(makerBalance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
|
// });
|
|
// });
|
|
|
|
describe('getSmartContractParamsOrThrow', () => {
|
|
describe('valid swap quote', async () => {
|
|
// TODO(david) Check for valid MethodAbi
|
|
it('should provide correct and optimized smart contract params for Forwarder contract when provided corresponding useExtensionContract option', async () => {
|
|
const { toAddress } = await swapQuoteConsumer.getSmartContractParamsOrThrowAsync(marketSellSwapQuote, {
|
|
useExtensionContract: ExtensionContractType.Forwarder,
|
|
});
|
|
expect(toAddress).to.deep.equal(contractWrappers.forwarder.address);
|
|
});
|
|
it('should provide correct and optimized smart contract params for Exchange contract when provided corresponding useExtensionContract option', async () => {
|
|
const { toAddress } = await swapQuoteConsumer.getSmartContractParamsOrThrowAsync(marketSellSwapQuote, {
|
|
useExtensionContract: ExtensionContractType.None,
|
|
});
|
|
expect(toAddress).to.deep.equal(contractWrappers.exchange.address);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('getCalldataOrThrow', () => {
|
|
describe('valid swap quote', async () => {
|
|
it('should provide correct and optimized calldata options for Forwarder contract when provided corresponding useExtensionContract option', async () => {
|
|
const { toAddress } = await swapQuoteConsumer.getCalldataOrThrowAsync(marketSellSwapQuote, {
|
|
useExtensionContract: ExtensionContractType.Forwarder,
|
|
});
|
|
expect(toAddress).to.deep.equal(contractWrappers.forwarder.address);
|
|
});
|
|
it('should provide correct and optimized smart contract params for Exchange contract when provided corresponding useExtensionContract option', async () => {
|
|
const { toAddress } = await swapQuoteConsumer.getCalldataOrThrowAsync(marketSellSwapQuote, {
|
|
useExtensionContract: ExtensionContractType.None,
|
|
});
|
|
expect(toAddress).to.deep.equal(contractWrappers.exchange.address);
|
|
});
|
|
});
|
|
});
|
|
});
|