Add ERC721 wrapper

This commit is contained in:
Amir Bandeali
2018-04-22 15:17:55 -07:00
parent 1f968fa4fd
commit 48b44342ab
2 changed files with 161 additions and 20 deletions

View File

@@ -0,0 +1,154 @@
import { ZeroEx } from '0x.js';
import { Deployer } from '@0xproject/deployer';
import { Provider } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { DummyERC721TokenContract } from '../contract_wrappers/generated/dummy_e_r_c721_token';
import { ERC721ProxyContract } from '../contract_wrappers/generated/e_r_c721_proxy';
import { constants } from './constants';
import { ContractName, ERC721BalancesByOwner } from './types';
export class ERC721Wrapper {
private _tokenOwnerAddresses: string[];
private _contractOwnerAddress: string;
private _deployer: Deployer;
private _provider: Provider;
private _dummyERC721TokenContracts?: DummyERC721TokenContract[];
private _erc721ProxyContract?: ERC721ProxyContract;
private _initialERC721BalancesByOwner?: ERC721BalancesByOwner;
constructor(deployer: Deployer, provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._deployer = deployer;
this._provider = provider;
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
}
public async deployDummyERC721TokensAsync(): Promise<DummyERC721TokenContract[]> {
const tokenContractInstances = await Promise.all(
_.map(this._tokenOwnerAddresses, tokenOwnerAddress =>
this._deployer.deployAsync(ContractName.DummyERC721Token, constants.DUMMY_ERC721_TOKEN_ARGS),
),
);
this._dummyERC721TokenContracts = _.map(
tokenContractInstances,
tokenContractInstance =>
new DummyERC721TokenContract(tokenContractInstance.abi, tokenContractInstance.address, this._provider),
);
return this._dummyERC721TokenContracts;
}
public async deployERC721ProxyAsync(): Promise<ERC721ProxyContract> {
const proxyContractInstance = await this._deployer.deployAsync(ContractName.ERC721Proxy);
this._erc721ProxyContract = new ERC721ProxyContract(
proxyContractInstance.abi,
proxyContractInstance.address,
this._provider,
);
return this._erc721ProxyContract;
}
public async setBalancesAndAllowancesAsync() {
if (_.isUndefined(this._dummyERC721TokenContracts)) {
throw new Error('Dummy ERC721 tokens not yet deployed, please call "deployDummyERC721TokensAsync"');
}
if (_.isUndefined(this._erc721ProxyContract)) {
throw new Error('ERC721 proxy contract not yet deployed, please call "deployERC721ProxyAsync"');
}
const setBalancePromises: any[] = [];
const setAllowancePromises: any[] = [];
this._initialERC721BalancesByOwner = {};
_.forEach(this._dummyERC721TokenContracts, dummyERC721TokenContract => {
_.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => {
_.forEach(_.range(constants.NUM_ERC721_TOKENS_TO_MINT), () => {
const tokenId = ZeroEx.generatePseudoRandomSalt();
setBalancePromises.push(
dummyERC721TokenContract.mint.sendTransactionAsync(tokenOwnerAddress, tokenId, {
from: this._contractOwnerAddress,
}),
);
if (
_.isUndefined((this._initialERC721BalancesByOwner as ERC721BalancesByOwner)[tokenOwnerAddress])
) {
(this._initialERC721BalancesByOwner as ERC721BalancesByOwner)[tokenOwnerAddress] = {
[dummyERC721TokenContract.address]: [],
};
}
if (
_.isUndefined(
(this._initialERC721BalancesByOwner as ERC721BalancesByOwner)[tokenOwnerAddress][
dummyERC721TokenContract.address
],
)
) {
(this._initialERC721BalancesByOwner as ERC721BalancesByOwner)[tokenOwnerAddress][
dummyERC721TokenContract.address
] = [];
}
(this._initialERC721BalancesByOwner as ERC721BalancesByOwner)[tokenOwnerAddress][
dummyERC721TokenContract.address
].push(tokenId);
});
const approval = true;
setAllowancePromises.push(
dummyERC721TokenContract.setApprovalForAll.sendTransactionAsync(
(this._erc721ProxyContract as ERC721ProxyContract).address,
approval,
{ from: tokenOwnerAddress },
),
);
});
});
await Promise.all([...setBalancePromises, ...setAllowancePromises]);
}
public async getBalancesAsync(): Promise<ERC721BalancesByOwner> {
if (_.isUndefined(this._dummyERC721TokenContracts)) {
throw new Error('Dummy ERC721 tokens not yet deployed, please call "deployDummyERC721TokensAsync"');
}
if (_.isUndefined(this._initialERC721BalancesByOwner)) {
throw new Error(
'Dummy ERC721 balances and allowances not yet set, please call "setBalancesAndAllowancesAsync"',
);
}
const balancesByOwner: ERC721BalancesByOwner = {};
const tokenOwnerPromises: any[] = [];
const tokenInfo: Array<{ tokenId: BigNumber; tokenAddress: string }> = [];
_.forEach(this._dummyERC721TokenContracts, dummyERC721TokenContract => {
_.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => {
const initialTokenOwnerIds = (this._initialERC721BalancesByOwner as ERC721BalancesByOwner)[
tokenOwnerAddress
][dummyERC721TokenContract.address];
_.forEach(initialTokenOwnerIds, tokenId => {
tokenOwnerPromises.push(dummyERC721TokenContract.ownerOf.callAsync(tokenId));
tokenInfo.push({
tokenId,
tokenAddress: dummyERC721TokenContract.address,
});
});
});
});
const tokenOwnerAddresses = await Promise.all(tokenOwnerPromises);
_.forEach(tokenOwnerAddresses, (tokenOwnerAddress, ownerIndex) => {
const tokenAddress = tokenInfo[ownerIndex].tokenAddress;
const tokenId = tokenInfo[ownerIndex].tokenId;
if (_.isUndefined(balancesByOwner[tokenOwnerAddress])) {
balancesByOwner[tokenOwnerAddress] = {
[tokenAddress]: [],
};
}
if (_.isUndefined(balancesByOwner[tokenOwnerAddress][tokenAddress])) {
balancesByOwner[tokenOwnerAddress][tokenAddress] = [];
}
balancesByOwner[tokenOwnerAddress][tokenAddress].push(tokenId);
});
return balancesByOwner;
}
public getTokenOwnerAddresses(): string[] {
return this._tokenOwnerAddresses;
}
public getTokenAddresses(): string[] {
const tokenAddresses = _.map(
this._dummyERC721TokenContracts,
dummyERC721TokenContract => dummyERC721TokenContract.address,
);
return tokenAddresses;
}
}

View File

@@ -1,12 +1,18 @@
import { AbiDefinition, ContractAbi } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
export interface BalancesByOwner {
export interface ERC20BalancesByOwner {
[ownerAddress: string]: {
[tokenAddress: string]: BigNumber;
};
}
export interface ERC721BalancesByOwner {
[ownerAddress: string]: {
[tokenAddress: string]: BigNumber[];
};
}
export interface SubmissionContractEventArgs {
transactionId: BigNumber;
}
@@ -43,20 +49,6 @@ export enum AssetProxyId {
ERC721,
}
export interface DefaultOrderParams {
exchangeAddress: string;
makerAddress: string;
feeRecipientAddress: string;
makerAssetAddress: string;
takerAssetAddress: string;
makerAssetAmount: BigNumber;
takerAssetAmount: BigNumber;
makerFee: BigNumber;
takerFee: BigNumber;
makerAssetData: string;
takerAssetData: string;
}
export interface TransactionDataParams {
name: string;
abi: AbiDefinition[];
@@ -82,11 +74,6 @@ export interface Token {
swarmHash: string;
}
export interface TokenInfoByNetwork {
development: Token[];
live: Token[];
}
export enum ExchangeContractErrs {
ERROR_ORDER_EXPIRED,
ERROR_ORDER_FULLY_FILLED,