Refactor contracts-* exports so none in test dir so npmignore works as intended

This commit is contained in:
fabioberger
2019-11-11 21:49:29 +00:00
parent 67e7b5c124
commit 6324a92ec5
64 changed files with 72 additions and 294 deletions

View File

@@ -23,10 +23,10 @@ import { LogWithDecodedArgs } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { ERC1155ProxyWrapper } from '../src/erc1155_proxy_wrapper';
import { ERC1155ProxyContract, IAssetDataContract } from '../src/wrappers';
import { artifacts } from './artifacts';
import { ERC1155ProxyWrapper } from './utils/erc1155_proxy_wrapper';
chaiSetup.configure();
const expect = chai.expect;

View File

@@ -29,12 +29,12 @@ import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import { ERC1155ProxyWrapper } from '../src/erc1155_proxy_wrapper';
import { ERC20Wrapper } from '../src/erc20_wrapper';
import { ERC721Wrapper } from '../src/erc721_wrapper';
import { ERC1155ProxyContract, ERC20ProxyContract, ERC721ProxyContract } from '../src/wrappers';
import { artifacts } from './artifacts';
import { ERC1155ProxyWrapper } from './utils/erc1155_proxy_wrapper';
import { ERC20Wrapper } from './utils/erc20_wrapper';
import { ERC721Wrapper } from './utils/erc721_wrapper';
import { IAssetDataContract, IAssetProxyContract, MultiAssetProxyContract } from './wrappers';
chaiSetup.configure();

View File

@@ -1,423 +0,0 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc1155Artifacts, ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
import {
constants,
ERC1155FungibleHoldingsByOwner,
ERC1155HoldingsByOwner,
ERC1155NonFungibleHoldingsByOwner,
LogDecoder,
txDefaults,
} from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../../src/artifacts';
import { ERC1155ProxyContract, IAssetProxyContract } from '../../src/wrappers';
export class ERC1155ProxyWrapper {
private readonly _tokenOwnerAddresses: string[];
private readonly _fungibleTokenIds: string[];
private readonly _nonFungibleTokenIds: string[];
private readonly _nfts: Array<{ id: BigNumber; tokenId: BigNumber }>;
private readonly _contractOwnerAddress: string;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _provider: Provider;
private readonly _logDecoder: LogDecoder;
private readonly _dummyTokenWrappers: Erc1155Wrapper[];
private readonly _assetProxyInterface: IAssetProxyContract;
private readonly _devUtils: DevUtilsContract;
private _proxyContract?: ERC1155ProxyContract;
private _proxyIdIfExists?: string;
private _initialTokenIdsByOwner: ERC1155HoldingsByOwner = { fungible: {}, nonFungible: {} };
constructor(provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._web3Wrapper = new Web3Wrapper(provider);
this._provider = provider;
const allArtifacts = _.merge(artifacts, erc1155Artifacts);
this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts);
this._dummyTokenWrappers = [];
this._assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
this._fungibleTokenIds = [];
this._nonFungibleTokenIds = [];
this._nfts = [];
}
/**
* @dev Deploys dummy ERC1155 contracts
* @return An array of ERC1155 wrappers; one for each deployed contract.
*/
public async deployDummyContractsAsync(): Promise<Erc1155Wrapper[]> {
// tslint:disable-next-line:no-unused-variable
for (const i of _.times(constants.NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY)) {
const erc1155Contract = await ERC1155MintableContract.deployFrom0xArtifactAsync(
erc1155Artifacts.ERC1155Mintable,
this._provider,
txDefaults,
artifacts,
);
const erc1155Wrapper = new Erc1155Wrapper(erc1155Contract, this._provider, this._contractOwnerAddress);
this._dummyTokenWrappers.push(erc1155Wrapper);
}
return this._dummyTokenWrappers;
}
/**
* @dev Deploys the ERC1155 proxy
* @return Deployed ERC1155 proxy contract instance
*/
public async deployProxyAsync(): Promise<ERC1155ProxyContract> {
this._proxyContract = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
artifacts.ERC1155Proxy,
this._provider,
txDefaults,
artifacts,
);
this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
return this._proxyContract;
}
/**
* @dev Gets the ERC1155 proxy id
*/
public getProxyId(): string {
this._validateProxyContractExistsOrThrow();
return this._proxyIdIfExists as string;
}
/**
* @dev generates abi-encoded tx data for transferring erc1155 fungible/non-fungible tokens.
* @param from source address
* @param to destination address
* @param contractAddress address of erc155 contract
* @param tokensToTransfer array of erc1155 tokens to transfer
* @param valuesToTransfer array of corresponding values for each erc1155 token to transfer
* @param valueMultiplier each value in `valuesToTransfer` is multiplied by this
* @param receiverCallbackData callback data if `to` is a contract
* @param authorizedSender sender of `transferFrom` transaction
* @param extraData extra data to append to `transferFrom` transaction. Optional.
* @return abi encoded tx data.
*/
public async getTransferFromAbiEncodedTxDataAsync(
from: string,
to: string,
contractAddress: string,
tokensToTransfer: BigNumber[],
valuesToTransfer: BigNumber[],
valueMultiplier: BigNumber,
receiverCallbackData: string,
authorizedSender: string,
assetData_?: string,
): Promise<string> {
this._validateProxyContractExistsOrThrow();
const assetData =
assetData_ === undefined
? await this._devUtils.encodeERC1155AssetData.callAsync(
contractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
: assetData_;
const data = this._assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData,
from,
to,
valueMultiplier,
);
return data;
}
/**
* @dev transfers erc1155 fungible/non-fungible tokens.
* @param txData: abi-encoded tx data
* @param authorizedSender sender of `transferFrom` transaction
*/
public async transferFromRawAsync(
txData: string,
authorizedSender: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const txHash = await this._web3Wrapper.sendTransactionAsync({
to: (this._proxyContract as ERC1155ProxyContract).address,
data: txData,
from: authorizedSender,
gas: 300000,
});
const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return txReceipt;
}
/**
* @dev transfers erc1155 fungible/non-fungible tokens.
* @param from source address
* @param to destination address
* @param contractAddress address of erc155 contract
* @param tokensToTransfer array of erc1155 tokens to transfer
* @param valuesToTransfer array of corresponding values for each erc1155 token to transfer
* @param valueMultiplier each value in `valuesToTransfer` is multiplied by this
* @param receiverCallbackData callback data if `to` is a contract
* @param authorizedSender sender of `transferFrom` transaction
* @param extraData extra data to append to `transferFrom` transaction. Optional.
* @return tranasction hash.
*/
public async transferFromAsync(
from: string,
to: string,
contractAddress: string,
tokensToTransfer: BigNumber[],
valuesToTransfer: BigNumber[],
valueMultiplier: BigNumber,
receiverCallbackData: string,
authorizedSender: string,
assetData_?: string,
): Promise<TransactionReceiptWithDecodedLogs> {
this._validateProxyContractExistsOrThrow();
const assetData =
assetData_ === undefined
? await this._devUtils.encodeERC1155AssetData.callAsync(
contractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
: assetData_;
const data = this._assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData,
from,
to,
valueMultiplier,
);
const txHash = await this._web3Wrapper.sendTransactionAsync({
to: (this._proxyContract as ERC1155ProxyContract).address,
data,
from: authorizedSender,
gas: 300000,
});
const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return txReceipt;
}
/**
* @dev For each deployed ERC1155 contract, this function mints a set of fungible/non-fungible
* tokens for each token owner address (`_tokenOwnerAddresses`).
* @return Balances of each token owner, across all ERC1155 contracts and tokens.
*/
public async setBalancesAndAllowancesAsync(): Promise<ERC1155HoldingsByOwner> {
this._validateDummyTokenContractsExistOrThrow();
this._validateProxyContractExistsOrThrow();
this._initialTokenIdsByOwner = {
fungible: {},
nonFungible: {},
};
const fungibleHoldingsByOwner: ERC1155FungibleHoldingsByOwner = {};
const nonFungibleHoldingsByOwner: ERC1155NonFungibleHoldingsByOwner = {};
// Set balances accordingly
for (const dummyWrapper of this._dummyTokenWrappers) {
const dummyAddress = dummyWrapper.getContract().address;
// tslint:disable-next-line:no-unused-variable
for (const i of _.times(constants.NUM_ERC1155_FUNGIBLE_TOKENS_MINT)) {
// Create a fungible token
const tokenId = await dummyWrapper.mintFungibleTokensAsync(
this._tokenOwnerAddresses,
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
);
const tokenIdAsString = tokenId.toString();
this._fungibleTokenIds.push(tokenIdAsString);
// Mint tokens for each owner for this token
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
// tslint:disable-next-line:no-unused-variable
if (fungibleHoldingsByOwner[tokenOwnerAddress] === undefined) {
fungibleHoldingsByOwner[tokenOwnerAddress] = {};
}
if (fungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress] === undefined) {
fungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress] = {};
}
fungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString] =
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE;
await dummyWrapper.setApprovalForAllAsync(
tokenOwnerAddress,
(this._proxyContract as ERC1155ProxyContract).address,
true,
);
}
}
// Non-fungible tokens
// tslint:disable-next-line:no-unused-variable
for (const j of _.times(constants.NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT)) {
const [tokenId, nftIds] = await dummyWrapper.mintNonFungibleTokensAsync(this._tokenOwnerAddresses);
const tokenIdAsString = tokenId.toString();
this._nonFungibleTokenIds.push(tokenIdAsString);
_.each(this._tokenOwnerAddresses, async (tokenOwnerAddress: string, i: number) => {
if (nonFungibleHoldingsByOwner[tokenOwnerAddress] === undefined) {
nonFungibleHoldingsByOwner[tokenOwnerAddress] = {};
}
if (nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress] === undefined) {
nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress] = {};
}
if (nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString] === undefined) {
nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString] = [];
}
this._nfts.push({ id: nftIds[i], tokenId });
nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString].push(nftIds[i]);
await dummyWrapper.setApprovalForAllAsync(
tokenOwnerAddress,
(this._proxyContract as ERC1155ProxyContract).address,
true,
);
});
}
}
this._initialTokenIdsByOwner = {
fungible: fungibleHoldingsByOwner,
nonFungible: nonFungibleHoldingsByOwner,
};
return this._initialTokenIdsByOwner;
}
/**
* @dev For each deployed ERC1155 contract, this function quieries the set of fungible/non-fungible
* tokens for each token owner address (`_tokenOwnerAddresses`).
* @return Balances of each token owner, across all ERC1155 contracts and tokens.
*/
public async getBalancesAsync(): Promise<ERC1155HoldingsByOwner> {
this._validateDummyTokenContractsExistOrThrow();
this._validateBalancesAndAllowancesSetOrThrow();
const tokenHoldingsByOwner: ERC1155FungibleHoldingsByOwner = {};
const nonFungibleHoldingsByOwner: ERC1155NonFungibleHoldingsByOwner = {};
for (const dummyTokenWrapper of this._dummyTokenWrappers) {
const tokenContract = dummyTokenWrapper.getContract();
const tokenAddress = tokenContract.address;
// Construct batch balance call
const tokenOwners: string[] = [];
const tokenIds: BigNumber[] = [];
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
for (const tokenId of this._fungibleTokenIds) {
tokenOwners.push(tokenOwnerAddress);
tokenIds.push(new BigNumber(tokenId));
}
for (const nft of this._nfts) {
tokenOwners.push(tokenOwnerAddress);
tokenIds.push(nft.id);
}
}
const balances = await dummyTokenWrapper.getBalancesAsync(tokenOwners, tokenIds);
// Parse out balances into fungible / non-fungible token holdings
let i = 0;
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
// Fungible tokens
for (const tokenId of this._fungibleTokenIds) {
if (tokenHoldingsByOwner[tokenOwnerAddress] === undefined) {
tokenHoldingsByOwner[tokenOwnerAddress] = {};
}
if (tokenHoldingsByOwner[tokenOwnerAddress][tokenAddress] === undefined) {
tokenHoldingsByOwner[tokenOwnerAddress][tokenAddress] = {};
}
tokenHoldingsByOwner[tokenOwnerAddress][tokenAddress][tokenId] = balances[i++];
}
// Non-fungible tokens
for (const nft of this._nfts) {
if (nonFungibleHoldingsByOwner[tokenOwnerAddress] === undefined) {
nonFungibleHoldingsByOwner[tokenOwnerAddress] = {};
}
if (nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress] === undefined) {
nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress] = {};
}
if (
nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress][nft.tokenId.toString()] ===
undefined
) {
nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress][nft.tokenId.toString()] = [];
}
const isOwner = balances[i++];
if (isOwner.isEqualTo(1)) {
nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress][nft.tokenId.toString()].push(
nft.id,
);
}
}
}
}
const holdingsByOwner = {
fungible: tokenHoldingsByOwner,
nonFungible: nonFungibleHoldingsByOwner,
};
return holdingsByOwner;
}
/**
* @dev Set the approval for the proxy on behalf of `userAddress` .
* @param userAddress owner of ERC1155 tokens.
* @param contractAddress address of ERC1155 contract.
* @param isApproved Whether to approve the proxy for all or not.
*/
public async setProxyAllowanceForAllAsync(
userAddress: string,
contractAddress: string,
isApproved: boolean,
): Promise<void> {
this._validateProxyContractExistsOrThrow();
const tokenWrapper = this.getContractWrapper(contractAddress);
const operator = (this._proxyContract as ERC1155ProxyContract).address;
await tokenWrapper.setApprovalForAllAsync(userAddress, operator, isApproved);
}
/**
* @dev Checks if proxy is approved to transfer tokens on behalf of `userAddress`.
* @param userAddress owner of ERC1155 tokens.
* @param contractAddress address of ERC1155 contract.
* @return True iff the proxy is approved for all. False otherwise.
*/
public async isProxyApprovedForAllAsync(userAddress: string, contractAddress: string): Promise<boolean> {
this._validateProxyContractExistsOrThrow();
const tokenContract = this._getContractFromAddress(contractAddress);
const operator = (this._proxyContract as ERC1155ProxyContract).address;
const didApproveAll = await tokenContract.isApprovedForAll.callAsync(userAddress, operator);
return didApproveAll;
}
public getFungibleTokenIds(): BigNumber[] {
const fungibleTokenIds = _.map(this._fungibleTokenIds, (tokenIdAsString: string) => {
return new BigNumber(tokenIdAsString);
});
return fungibleTokenIds;
}
public getNonFungibleTokenIds(): BigNumber[] {
const nonFungibleTokenIds = _.map(this._nonFungibleTokenIds, (tokenIdAsString: string) => {
return new BigNumber(tokenIdAsString);
});
return nonFungibleTokenIds;
}
public getTokenOwnerAddresses(): string[] {
return this._tokenOwnerAddresses;
}
public getContractWrapper(contractAddress: string): Erc1155Wrapper {
const tokenWrapper = _.find(this._dummyTokenWrappers, (wrapper: Erc1155Wrapper) => {
return wrapper.getContract().address === contractAddress;
});
if (tokenWrapper === undefined) {
throw new Error(`Contract: ${contractAddress} was not deployed through ERC1155ProxyWrapper`);
}
return tokenWrapper;
}
private _getContractFromAddress(tokenAddress: string): ERC1155MintableContract {
const tokenContractIfExists = _.find(this._dummyTokenWrappers, c => c.getContract().address === tokenAddress);
if (tokenContractIfExists === undefined) {
throw new Error(`Token: ${tokenAddress} was not deployed through ERC1155ProxyWrapper`);
}
return tokenContractIfExists.getContract();
}
private _validateDummyTokenContractsExistOrThrow(): void {
if (this._dummyTokenWrappers === undefined) {
throw new Error('Dummy ERC1155 tokens not yet deployed, please call "deployDummyTokensAsync"');
}
}
private _validateProxyContractExistsOrThrow(): void {
if (this._proxyContract === undefined) {
throw new Error('ERC1155 proxy contract not yet deployed, please call "deployProxyAsync"');
}
}
private _validateBalancesAndAllowancesSetOrThrow(): void {
if (
_.keys(this._initialTokenIdsByOwner.fungible).length === 0 ||
_.keys(this._initialTokenIdsByOwner.nonFungible).length === 0
) {
throw new Error(
'Dummy ERC1155 balances and allowances not yet set, please call "setBalancesAndAllowancesAsync"',
);
}
}
}

View File

@@ -1,169 +0,0 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
import { constants, ERC20BalancesByOwner, txDefaults } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { ZeroExProvider } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../../src/artifacts';
import { ERC20ProxyContract } from '../../src/wrappers';
export class ERC20Wrapper {
private readonly _tokenOwnerAddresses: string[];
private readonly _contractOwnerAddress: string;
private readonly _provider: ZeroExProvider;
private readonly _dummyTokenContracts: DummyERC20TokenContract[];
private readonly _devUtils: DevUtilsContract;
private _proxyContract?: ERC20ProxyContract;
private _proxyIdIfExists?: string;
/**
* Instanitates an ERC20Wrapper
* @param provider Web3 provider to use for all JSON RPC requests
* @param tokenOwnerAddresses Addresses that we want to endow as owners for dummy ERC20 tokens
* @param contractOwnerAddress Desired owner of the contract
* Instance of ERC20Wrapper
*/
constructor(provider: ZeroExProvider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._dummyTokenContracts = [];
this._provider = provider;
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
}
public async deployDummyTokensAsync(
numberToDeploy: number,
decimals: BigNumber,
): Promise<DummyERC20TokenContract[]> {
for (let i = 0; i < numberToDeploy; i++) {
this._dummyTokenContracts.push(
await DummyERC20TokenContract.deployFrom0xArtifactAsync(
erc20Artifacts.DummyERC20Token,
this._provider,
txDefaults,
artifacts,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
decimals,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
);
}
return this._dummyTokenContracts;
}
public async deployProxyAsync(): Promise<ERC20ProxyContract> {
this._proxyContract = await ERC20ProxyContract.deployFrom0xArtifactAsync(
artifacts.ERC20Proxy,
this._provider,
txDefaults,
artifacts,
);
this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
return this._proxyContract;
}
public getProxyId(): string {
this._validateProxyContractExistsOrThrow();
return this._proxyIdIfExists as string;
}
public async setBalancesAndAllowancesAsync(): Promise<void> {
this._validateDummyTokenContractsExistOrThrow();
this._validateProxyContractExistsOrThrow();
for (const dummyTokenContract of this._dummyTokenContracts) {
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
await dummyTokenContract.setBalance.awaitTransactionSuccessAsync(
tokenOwnerAddress,
constants.INITIAL_ERC20_BALANCE,
{ from: this._contractOwnerAddress },
);
await dummyTokenContract.approve.awaitTransactionSuccessAsync(
(this._proxyContract as ERC20ProxyContract).address,
constants.INITIAL_ERC20_ALLOWANCE,
{ from: tokenOwnerAddress },
);
}
}
}
public async getBalanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
const balance = new BigNumber(await tokenContract.balanceOf.callAsync(userAddress));
return balance;
}
public async setBalanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> {
const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
await tokenContract.setBalance.awaitTransactionSuccessAsync(
userAddress,
amount,
{ from: this._contractOwnerAddress },
{ pollingIntervalMs: constants.AWAIT_TRANSACTION_MINED_MS },
);
}
public async getProxyAllowanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
const proxyAddress = (this._proxyContract as ERC20ProxyContract).address;
const allowance = new BigNumber(await tokenContract.allowance.callAsync(userAddress, proxyAddress));
return allowance;
}
public async setAllowanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> {
const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
const proxyAddress = (this._proxyContract as ERC20ProxyContract).address;
await tokenContract.approve.awaitTransactionSuccessAsync(proxyAddress, amount, { from: userAddress });
}
public async getBalancesAsync(): Promise<ERC20BalancesByOwner> {
this._validateDummyTokenContractsExistOrThrow();
const balancesByOwner: ERC20BalancesByOwner = {};
const balances: BigNumber[] = [];
const balanceInfo: Array<{ tokenOwnerAddress: string; tokenAddress: string }> = [];
for (const dummyTokenContract of this._dummyTokenContracts) {
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
balances.push(await dummyTokenContract.balanceOf.callAsync(tokenOwnerAddress));
balanceInfo.push({
tokenOwnerAddress,
tokenAddress: dummyTokenContract.address,
});
}
}
_.forEach(balances, (balance, balanceIndex) => {
const tokenAddress = balanceInfo[balanceIndex].tokenAddress;
const tokenOwnerAddress = balanceInfo[balanceIndex].tokenOwnerAddress;
if (balancesByOwner[tokenOwnerAddress] === undefined) {
balancesByOwner[tokenOwnerAddress] = {};
}
const wrappedBalance = new BigNumber(balance);
balancesByOwner[tokenOwnerAddress][tokenAddress] = wrappedBalance;
});
return balancesByOwner;
}
public addDummyTokenContract(dummy: DummyERC20TokenContract): void {
if (this._dummyTokenContracts !== undefined) {
this._dummyTokenContracts.push(dummy);
}
}
public addTokenOwnerAddress(address: string): void {
this._tokenOwnerAddresses.push(address);
}
public getTokenOwnerAddresses(): string[] {
return this._tokenOwnerAddresses;
}
public getTokenAddresses(): string[] {
const tokenAddresses = _.map(this._dummyTokenContracts, dummyTokenContract => dummyTokenContract.address);
return tokenAddresses;
}
private async _getTokenContractFromAssetDataAsync(assetData: string): Promise<DummyERC20TokenContract> {
const [proxyId, tokenAddress] = await this._devUtils.decodeERC20AssetData.callAsync(assetData); // tslint:disable-line:no-unused-variable
const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress);
if (tokenContractIfExists === undefined) {
throw new Error(`Token: ${tokenAddress} was not deployed through ERC20Wrapper`);
}
return tokenContractIfExists;
}
private _validateDummyTokenContractsExistOrThrow(): void {
if (this._dummyTokenContracts === undefined) {
throw new Error('Dummy ERC20 tokens not yet deployed, please call "deployDummyTokensAsync"');
}
}
private _validateProxyContractExistsOrThrow(): void {
if (this._proxyContract === undefined) {
throw new Error('ERC20 proxy contract not yet deployed, please call "deployProxyAsync"');
}
}
}

View File

@@ -1,220 +0,0 @@
import { artifacts as erc721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721';
import { constants, ERC721TokenIdsByOwner, txDefaults } from '@0x/contracts-test-utils';
import { generatePseudoRandomSalt } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import { ZeroExProvider } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../../src/artifacts';
import { ERC721ProxyContract } from '../../src/wrappers';
export class ERC721Wrapper {
private readonly _tokenOwnerAddresses: string[];
private readonly _contractOwnerAddress: string;
private readonly _provider: ZeroExProvider;
private readonly _dummyTokenContracts: DummyERC721TokenContract[];
private _proxyContract?: ERC721ProxyContract;
private _proxyIdIfExists?: string;
private _initialTokenIdsByOwner: ERC721TokenIdsByOwner = {};
constructor(provider: ZeroExProvider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._provider = provider;
this._dummyTokenContracts = [];
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
}
public async deployDummyTokensAsync(): Promise<DummyERC721TokenContract[]> {
// tslint:disable-next-line:no-unused-variable
for (const i of _.times(constants.NUM_DUMMY_ERC721_TO_DEPLOY)) {
this._dummyTokenContracts.push(
await DummyERC721TokenContract.deployFrom0xArtifactAsync(
erc721Artifacts.DummyERC721Token,
this._provider,
txDefaults,
artifacts,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
),
);
}
return this._dummyTokenContracts;
}
public async deployProxyAsync(): Promise<ERC721ProxyContract> {
this._proxyContract = await ERC721ProxyContract.deployFrom0xArtifactAsync(
artifacts.ERC721Proxy,
this._provider,
txDefaults,
artifacts,
);
this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
return this._proxyContract;
}
public getProxyId(): string {
this._validateProxyContractExistsOrThrow();
return this._proxyIdIfExists as string;
}
public async setBalancesAndAllowancesAsync(): Promise<void> {
this._validateDummyTokenContractsExistOrThrow();
this._validateProxyContractExistsOrThrow();
this._initialTokenIdsByOwner = {};
for (const dummyTokenContract of this._dummyTokenContracts) {
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
// tslint:disable-next-line:no-unused-variable
for (const i of _.times(constants.NUM_ERC721_TOKENS_TO_MINT)) {
const tokenId = generatePseudoRandomSalt();
await this.mintAsync(dummyTokenContract.address, tokenId, tokenOwnerAddress);
if (this._initialTokenIdsByOwner[tokenOwnerAddress] === undefined) {
this._initialTokenIdsByOwner[tokenOwnerAddress] = {
[dummyTokenContract.address]: [],
};
}
if (this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address] === undefined) {
this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address] = [];
}
this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address].push(tokenId);
await this.approveProxyForAllAsync(dummyTokenContract.address, tokenOwnerAddress, true);
}
}
}
}
public async doesTokenExistAsync(tokenAddress: string, tokenId: BigNumber): Promise<boolean> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
const owner = await tokenContract.ownerOf.callAsync(tokenId);
const doesExist = owner !== constants.NULL_ADDRESS;
return doesExist;
}
public async approveProxyAsync(tokenAddress: string, tokenId: BigNumber): Promise<void> {
const proxyAddress = (this._proxyContract as ERC721ProxyContract).address;
await this.approveAsync(proxyAddress, tokenAddress, tokenId);
}
public async approveProxyForAllAsync(
tokenAddress: string,
ownerAddress: string,
isApproved: boolean,
): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
const proxyAddress = (this._proxyContract as ERC721ProxyContract).address;
await tokenContract.setApprovalForAll.awaitTransactionSuccessAsync(proxyAddress, isApproved, {
from: ownerAddress,
});
}
public async approveAsync(to: string, tokenAddress: string, tokenId: BigNumber): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
const tokenOwner = await this.ownerOfAsync(tokenAddress, tokenId);
await tokenContract.approve.awaitTransactionSuccessAsync(to, tokenId, { from: tokenOwner });
}
public async transferFromAsync(
tokenAddress: string,
tokenId: BigNumber,
currentOwner: string,
userAddress: string,
): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
await tokenContract.transferFrom.awaitTransactionSuccessAsync(currentOwner, userAddress, tokenId, {
from: currentOwner,
});
}
public async mintAsync(tokenAddress: string, tokenId: BigNumber, userAddress: string): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
await tokenContract.mint.awaitTransactionSuccessAsync(userAddress, tokenId, {
from: this._contractOwnerAddress,
});
}
public async burnAsync(tokenAddress: string, tokenId: BigNumber, owner: string): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
await tokenContract.burn.awaitTransactionSuccessAsync(owner, tokenId, { from: this._contractOwnerAddress });
}
public async ownerOfAsync(tokenAddress: string, tokenId: BigNumber): Promise<string> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
const owner = await tokenContract.ownerOf.callAsync(tokenId);
return owner;
}
public async isOwnerAsync(userAddress: string, tokenAddress: string, tokenId: BigNumber): Promise<boolean> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
const tokenOwner = await tokenContract.ownerOf.callAsync(tokenId);
const isOwner = tokenOwner === userAddress;
return isOwner;
}
public async isProxyApprovedForAllAsync(userAddress: string, tokenAddress: string): Promise<boolean> {
this._validateProxyContractExistsOrThrow();
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
const operator = (this._proxyContract as ERC721ProxyContract).address;
const didApproveAll = await tokenContract.isApprovedForAll.callAsync(userAddress, operator);
return didApproveAll;
}
public async isProxyApprovedAsync(tokenAddress: string, tokenId: BigNumber): Promise<boolean> {
this._validateProxyContractExistsOrThrow();
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
const approvedAddress = await tokenContract.getApproved.callAsync(tokenId);
const proxyAddress = (this._proxyContract as ERC721ProxyContract).address;
const isProxyAnApprovedOperator = approvedAddress === proxyAddress;
return isProxyAnApprovedOperator;
}
public async getBalancesAsync(): Promise<ERC721TokenIdsByOwner> {
this._validateDummyTokenContractsExistOrThrow();
this._validateBalancesAndAllowancesSetOrThrow();
const tokenIdsByOwner: ERC721TokenIdsByOwner = {};
const tokenOwnerAddresses: string[] = [];
const tokenInfo: Array<{ tokenId: BigNumber; tokenAddress: string }> = [];
for (const dummyTokenContract of this._dummyTokenContracts) {
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
const initialTokenOwnerIds = this._initialTokenIdsByOwner[tokenOwnerAddress][
dummyTokenContract.address
];
for (const tokenId of initialTokenOwnerIds) {
tokenOwnerAddresses.push(await dummyTokenContract.ownerOf.callAsync(tokenId));
tokenInfo.push({
tokenId,
tokenAddress: dummyTokenContract.address,
});
}
}
}
_.forEach(tokenOwnerAddresses, (tokenOwnerAddress, ownerIndex) => {
const tokenAddress = tokenInfo[ownerIndex].tokenAddress;
const tokenId = tokenInfo[ownerIndex].tokenId;
if (tokenIdsByOwner[tokenOwnerAddress] === undefined) {
tokenIdsByOwner[tokenOwnerAddress] = {
[tokenAddress]: [],
};
}
if (tokenIdsByOwner[tokenOwnerAddress][tokenAddress] === undefined) {
tokenIdsByOwner[tokenOwnerAddress][tokenAddress] = [];
}
tokenIdsByOwner[tokenOwnerAddress][tokenAddress].push(tokenId);
});
return tokenIdsByOwner;
}
public getTokenOwnerAddresses(): string[] {
return this._tokenOwnerAddresses;
}
public getTokenAddresses(): string[] {
const tokenAddresses = _.map(this._dummyTokenContracts, dummyTokenContract => dummyTokenContract.address);
return tokenAddresses;
}
private _getTokenContractFromAssetData(tokenAddress: string): DummyERC721TokenContract {
const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress);
if (tokenContractIfExists === undefined) {
throw new Error(`Token: ${tokenAddress} was not deployed through ERC20Wrapper`);
}
return tokenContractIfExists;
}
private _validateDummyTokenContractsExistOrThrow(): void {
if (this._dummyTokenContracts === undefined) {
throw new Error('Dummy ERC721 tokens not yet deployed, please call "deployDummyTokensAsync"');
}
}
private _validateProxyContractExistsOrThrow(): void {
if (this._proxyContract === undefined) {
throw new Error('ERC721 proxy contract not yet deployed, please call "deployProxyAsync"');
}
}
private _validateBalancesAndAllowancesSetOrThrow(): void {
if (_.keys(this._initialTokenIdsByOwner).length === 0) {
throw new Error(
'Dummy ERC721 balances and allowances not yet set, please call "setBalancesAndAllowancesAsync"',
);
}
}
}

View File

@@ -1,3 +0,0 @@
export * from './erc20_wrapper';
export * from './erc721_wrapper';
export * from './erc1155_proxy_wrapper';