Address review comments and regenerate contract-wrappers

This commit is contained in:
Lawrence Forman 2020-02-07 23:03:16 -05:00
parent 1a9ed4d4fe
commit 8635849977
17 changed files with 1458 additions and 127 deletions

View File

@ -130,12 +130,9 @@ export class {{contractName}}Contract extends BaseContract {
txDefaults
);
const bytecode = linkLibrariesInBytecode(
artifact.compilerOutput.evm.bytecode,
artifact,
libraryAddresses,
);
if (!hexUtils.isHex(bytecode)) {
throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`);
}
return {{contractName}}Contract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly, {{> params inputs=ctor.inputs}});
}
@ -236,12 +233,9 @@ export class {{contractName}}Contract extends BaseContract {
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(
libraryArtifact.compilerOutput.evm.bytecode,
libraryArtifact,
libraryAddresses,
);
if (!hexUtils.isHex(linkedLibraryBytecode)) {
throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`);
}
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,

View File

@ -119,10 +119,7 @@ export class AbiGenDummyContract extends BaseContract {
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses);
if (!hexUtils.isHex(bytecode)) {
throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`);
}
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return AbiGenDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
@ -933,13 +930,7 @@ export class AbiGenDummyContract extends BaseContract {
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(
libraryArtifact.compilerOutput.evm.bytecode,
libraryAddresses,
);
if (!hexUtils.isHex(linkedLibraryBytecode)) {
throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`);
}
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,

View File

@ -98,10 +98,7 @@ export class LibDummyContract extends BaseContract {
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses);
if (!hexUtils.isHex(bytecode)) {
throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`);
}
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return LibDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
@ -180,13 +177,7 @@ export class LibDummyContract extends BaseContract {
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(
libraryArtifact.compilerOutput.evm.bytecode,
libraryAddresses,
);
if (!hexUtils.isHex(linkedLibraryBytecode)) {
throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`);
}
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,

View File

@ -99,10 +99,7 @@ export class TestLibDummyContract extends BaseContract {
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses);
if (!hexUtils.isHex(bytecode)) {
throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`);
}
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return TestLibDummyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
@ -220,13 +217,7 @@ export class TestLibDummyContract extends BaseContract {
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(
libraryArtifact.compilerOutput.evm.bytecode,
libraryAddresses,
);
if (!hexUtils.isHex(linkedLibraryBytecode)) {
throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`);
}
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,

View File

@ -1,5 +1,5 @@
import { AbiEncoder } from '@0x/utils';
import { DataItem, EvmBytecodeOutput, MethodAbi } from 'ethereum-types';
import { ContractArtifact, DataItem, MethodAbi } from 'ethereum-types';
// tslint:disable-next-line:completed-docs
export function formatABIDataItem(abi: DataItem, value: any, formatter: (type: string, value: any) => any): any {
@ -40,19 +40,24 @@ export function methodAbiToFunctionSignature(methodAbi: MethodAbi): string {
}
/**
* Replaces unliked library references in bytecode with real addresses
* and returns the bytecode.
* Replaces unliked library references in the bytecode of a contract artifact
* with real addresses and returns the bytecode.
*/
export function linkLibrariesInBytecode(
bytecodeArtifact: EvmBytecodeOutput,
artifact: ContractArtifact,
libraryAddresses: { [libraryName: string]: string },
): string {
const bytecodeArtifact = artifact.compilerOutput.evm.bytecode;
let bytecode = bytecodeArtifact.object.substr(2);
for (const link of Object.values(bytecodeArtifact.linkReferences)) {
for (const [libraryName, libraryRefs] of Object.entries(link)) {
const libraryAddress = libraryAddresses[libraryName];
if (!libraryAddress) {
continue;
throw new Error(
`${
artifact.contractName
} has an unlinked reference library ${libraryName} but no addresses was provided'.`,
);
}
for (const ref of libraryRefs) {
bytecode = [

View File

@ -9,6 +9,7 @@ import {
BaseContract,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -25,7 +26,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -78,6 +79,50 @@ export class CoordinatorContract extends BaseContract {
chainId,
);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
exchange: string,
chainId: BigNumber,
): Promise<CoordinatorContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await CoordinatorContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return CoordinatorContract.deployAsync(
bytecode,
abi,
provider,
txDefaults,
logDecodeDependenciesAbiOnly,
exchange,
chainId,
);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -456,12 +501,58 @@ export class CoordinatorContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await CoordinatorContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = CoordinatorContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as CoordinatorContract;
@ -469,6 +560,7 @@ export class CoordinatorContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as CoordinatorContract;
@ -476,6 +568,7 @@ export class CoordinatorContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as CoordinatorContract;
@ -688,7 +781,15 @@ export class CoordinatorContract extends BaseContract {
}>
> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<
@ -840,7 +941,15 @@ export class CoordinatorContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);

View File

@ -9,6 +9,7 @@ import {
BaseContract,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -25,7 +26,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -78,6 +79,50 @@ export class DevUtilsContract extends BaseContract {
_chaiBridge,
);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
_exchange: string,
_chaiBridge: string,
): Promise<DevUtilsContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await DevUtilsContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return DevUtilsContract.deployAsync(
bytecode,
abi,
provider,
txDefaults,
logDecodeDependenciesAbiOnly,
_exchange,
_chaiBridge,
);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -1666,12 +1711,58 @@ export class DevUtilsContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await DevUtilsContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = DevUtilsContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as DevUtilsContract;
@ -1679,6 +1770,7 @@ export class DevUtilsContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as DevUtilsContract;
@ -1686,6 +1778,7 @@ export class DevUtilsContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as DevUtilsContract;
@ -1729,7 +1822,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[number, string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[number, string, string]>(rawCallResult);
@ -1752,7 +1853,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<[string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string]>(rawCallResult);
@ -1776,7 +1885,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
@ -1802,7 +1919,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[string, string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string, string]>(rawCallResult);
@ -1828,7 +1953,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[string, string, string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string, string, string]>(rawCallResult);
@ -1857,7 +1990,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[string, string, BigNumber[], BigNumber[], string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string, BigNumber[], BigNumber[], string]>(
@ -1882,7 +2023,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<[string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string]>(rawCallResult);
@ -1909,7 +2058,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[string, string, string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string, string, string]>(rawCallResult);
@ -1936,7 +2093,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[string, string, BigNumber]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string, BigNumber]>(rawCallResult);
@ -1962,7 +2127,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[number, string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[number, string, string]>(rawCallResult);
@ -1985,7 +2158,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<[number, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[number, string]>(rawCallResult);
@ -2011,7 +2192,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[number, BigNumber, BigNumber]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[number, BigNumber, BigNumber]>(rawCallResult);
@ -2037,7 +2226,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[string, BigNumber[], string[]]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, BigNumber[], string[]]>(rawCallResult);
@ -2060,7 +2257,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<[string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string]>(rawCallResult);
@ -2086,7 +2291,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[string, string, BigNumber]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string, BigNumber]>(rawCallResult);
@ -2109,7 +2322,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<[string, number]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, number]>(rawCallResult);
@ -2135,7 +2356,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[number, string, string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[number, string, string, string]>(rawCallResult);
@ -2158,7 +2387,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<[string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string]>(rawCallResult);
@ -2184,7 +2421,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[string, string, string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string, string, string]>(rawCallResult);
@ -2211,7 +2456,15 @@ export class DevUtilsContract extends BaseContract {
defaultBlock?: BlockParam,
): Promise<[string, string, string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string, string, string]>(rawCallResult);
@ -2234,7 +2487,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<[number, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[number, string]>(rawCallResult);
@ -2257,7 +2518,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<[string, string]> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<[string, string]>(rawCallResult);
@ -2293,7 +2562,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
@ -2322,7 +2599,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
@ -2348,7 +2633,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
@ -2374,7 +2667,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
@ -2407,7 +2708,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
@ -2819,7 +3128,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
@ -3273,7 +3590,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
@ -3350,7 +3675,15 @@ export class DevUtilsContract extends BaseContract {
return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);

View File

@ -10,6 +10,7 @@ import {
SubscriptionManager,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -27,7 +28,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -89,6 +90,40 @@ export class ERC20TokenContract extends BaseContract {
}
return ERC20TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
): Promise<ERC20TokenContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await ERC20TokenContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return ERC20TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -314,12 +349,58 @@ export class ERC20TokenContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await ERC20TokenContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = ERC20TokenContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ERC20TokenContract;
@ -327,6 +408,7 @@ export class ERC20TokenContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ERC20TokenContract;
@ -334,6 +416,7 @@ export class ERC20TokenContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ERC20TokenContract;
@ -608,6 +691,7 @@ export class ERC20TokenContract extends BaseContract {
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
@ -615,12 +699,14 @@ export class ERC20TokenContract extends BaseContract {
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The ERC20Token contract event you would like to subscribe to.
@ -646,6 +732,7 @@ export class ERC20TokenContract extends BaseContract {
);
return logs;
}
constructor(
address: string,
supportedProvider: SupportedProvider,

View File

@ -10,6 +10,7 @@ import {
SubscriptionManager,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -27,7 +28,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -99,6 +100,40 @@ export class ERC721TokenContract extends BaseContract {
}
return ERC721TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
): Promise<ERC721TokenContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await ERC721TokenContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return ERC721TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -404,12 +439,58 @@ export class ERC721TokenContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await ERC721TokenContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = ERC721TokenContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ERC721TokenContract;
@ -417,6 +498,7 @@ export class ERC721TokenContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ERC721TokenContract;
@ -424,6 +506,7 @@ export class ERC721TokenContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ERC721TokenContract;
@ -868,6 +951,7 @@ export class ERC721TokenContract extends BaseContract {
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
@ -875,12 +959,14 @@ export class ERC721TokenContract extends BaseContract {
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The ERC721Token contract event you would like to subscribe to.
@ -906,6 +992,7 @@ export class ERC721TokenContract extends BaseContract {
);
return logs;
}
constructor(
address: string,
supportedProvider: SupportedProvider,

View File

@ -10,6 +10,7 @@ import {
SubscriptionManager,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -27,7 +28,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -156,6 +157,41 @@ export class ExchangeContract extends BaseContract {
}
return ExchangeContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly, chainId);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
chainId: BigNumber,
): Promise<ExchangeContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await ExchangeContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return ExchangeContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly, chainId);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -3113,12 +3149,58 @@ export class ExchangeContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await ExchangeContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = ExchangeContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ExchangeContract;
@ -3126,6 +3208,7 @@ export class ExchangeContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ExchangeContract;
@ -3133,6 +3216,7 @@ export class ExchangeContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ExchangeContract;
@ -5879,6 +5963,7 @@ export class ExchangeContract extends BaseContract {
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
@ -5886,12 +5971,14 @@ export class ExchangeContract extends BaseContract {
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The Exchange contract event you would like to subscribe to.
@ -5917,6 +6004,7 @@ export class ExchangeContract extends BaseContract {
);
return logs;
}
constructor(
address: string,
supportedProvider: SupportedProvider,

View File

@ -10,6 +10,7 @@ import {
SubscriptionManager,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -27,7 +28,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -93,6 +94,52 @@ export class ForwarderContract extends BaseContract {
_weth,
);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
_exchange: string,
_exchangeV2: string,
_weth: string,
): Promise<ForwarderContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await ForwarderContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return ForwarderContract.deployAsync(
bytecode,
abi,
provider,
txDefaults,
logDecodeDependenciesAbiOnly,
_exchange,
_exchangeV2,
_weth,
);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -459,12 +506,58 @@ export class ForwarderContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await ForwarderContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = ForwarderContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ForwarderContract;
@ -472,6 +565,7 @@ export class ForwarderContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ForwarderContract;
@ -479,6 +573,7 @@ export class ForwarderContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as ForwarderContract;
@ -903,6 +998,7 @@ export class ForwarderContract extends BaseContract {
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
@ -910,12 +1006,14 @@ export class ForwarderContract extends BaseContract {
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The Forwarder contract event you would like to subscribe to.
@ -941,6 +1039,7 @@ export class ForwarderContract extends BaseContract {
);
return logs;
}
constructor(
address: string,
supportedProvider: SupportedProvider,

View File

@ -9,6 +9,7 @@ import {
BaseContract,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -25,7 +26,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -67,6 +68,40 @@ export class IAssetDataContract extends BaseContract {
}
return IAssetDataContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
): Promise<IAssetDataContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await IAssetDataContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return IAssetDataContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -237,12 +272,58 @@ export class IAssetDataContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await IAssetDataContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = IAssetDataContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as IAssetDataContract;
@ -250,6 +331,7 @@ export class IAssetDataContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as IAssetDataContract;
@ -257,6 +339,7 @@ export class IAssetDataContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as IAssetDataContract;

View File

@ -9,6 +9,7 @@ import {
BaseContract,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -25,7 +26,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -73,6 +74,46 @@ export class IERC20BridgeSamplerContract extends BaseContract {
logDecodeDependenciesAbiOnly,
);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
): Promise<IERC20BridgeSamplerContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await IERC20BridgeSamplerContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return IERC20BridgeSamplerContract.deployAsync(
bytecode,
abi,
provider,
txDefaults,
logDecodeDependenciesAbiOnly,
);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -731,12 +772,58 @@ export class IERC20BridgeSamplerContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await IERC20BridgeSamplerContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = IERC20BridgeSamplerContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as IERC20BridgeSamplerContract;
@ -744,6 +831,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as IERC20BridgeSamplerContract;
@ -751,6 +839,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as IERC20BridgeSamplerContract;
@ -852,9 +941,18 @@ export class IERC20BridgeSamplerContract extends BaseContract {
},
};
}
/**
* Query batches of native orders and sample buy quotes on multiple DEXes at once.
* @param orders Batches of Native orders to query.
* @param orderSignatures Batches of Signatures for each respective order in
* `orders`.
* @param sources Address of each DEX. Passing in an unsupported DEX will
* throw.
* @param makerTokenAmounts Batches of Maker token sell amount for each sample.
* @returns ordersAndSamples How much taker asset can be filled by each order in &#x60;orders&#x60;. Taker amounts sold for each source at each maker token amount. First indexed by source index, then sample index
*/
public queryBatchOrdersAndSampleBuys(
orders: Array<
Array<{
orders: Array<Array<{
makerAddress: string;
takerAddress: string;
feeRecipientAddress: string;
@ -869,8 +967,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
takerAssetData: string;
makerFeeAssetData: string;
takerFeeAssetData: string;
}>
>,
}>>,
orderSignatures: string[][],
sources: string[],
makerTokenAmounts: BigNumber[][],
@ -894,6 +991,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
defaultBlock,
);
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<
Array<{ orderFillableAssetAmounts: BigNumber[]; tokenAmountsBySource: BigNumber[][] }>
>(rawCallResult);
@ -908,9 +1006,18 @@ export class IERC20BridgeSamplerContract extends BaseContract {
},
};
}
/**
* Query batches of native orders and sample sell quotes on multiple DEXes at once.
* @param orders Batches of Native orders to query.
* @param orderSignatures Batches of Signatures for each respective order in
* `orders`.
* @param sources Address of each DEX. Passing in an unsupported DEX will
* throw.
* @param takerTokenAmounts Batches of Taker token sell amount for each sample.
* @returns ordersAndSamples How much taker asset can be filled by each order in &#x60;orders&#x60;. Maker amounts bought for each source at each taker token amount. First indexed by source index, then sample index.
*/
public queryBatchOrdersAndSampleSells(
orders: Array<
Array<{
orders: Array<Array<{
makerAddress: string;
takerAddress: string;
feeRecipientAddress: string;
@ -925,8 +1032,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
takerAssetData: string;
makerFeeAssetData: string;
takerFeeAssetData: string;
}>
>,
}>>,
orderSignatures: string[][],
sources: string[],
takerTokenAmounts: BigNumber[][],
@ -950,6 +1056,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
defaultBlock,
);
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<
Array<{ orderFillableAssetAmounts: BigNumber[]; tokenAmountsBySource: BigNumber[][] }>
>(rawCallResult);

View File

@ -9,6 +9,7 @@ import {
BaseContract,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -25,7 +26,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -74,6 +75,46 @@ export class LibTransactionDecoderContract extends BaseContract {
logDecodeDependenciesAbiOnly,
);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
): Promise<LibTransactionDecoderContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await LibTransactionDecoderContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return LibTransactionDecoderContract.deployAsync(
bytecode,
abi,
provider,
txDefaults,
logDecodeDependenciesAbiOnly,
);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -213,12 +254,58 @@ export class LibTransactionDecoderContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await LibTransactionDecoderContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = LibTransactionDecoderContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as LibTransactionDecoderContract;
@ -226,6 +313,7 @@ export class LibTransactionDecoderContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as LibTransactionDecoderContract;
@ -233,6 +321,7 @@ export class LibTransactionDecoderContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as LibTransactionDecoderContract;
@ -303,7 +392,15 @@ export class LibTransactionDecoderContract extends BaseContract {
]
> {
BaseContract._assertCallParams(callData, defaultBlock);
const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
let rawCallResult;
if (self._deployedBytecodeIfExists) {
rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData());
} else {
rawCallResult = await self._performCallAsync(
{ ...callData, data: this.getABIEncodedTransactionData() },
defaultBlock,
);
}
const abiEncoder = self._lookupAbiEncoder(functionSignature);
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
return abiEncoder.strictDecodeReturnValue<

View File

@ -10,6 +10,7 @@ import {
SubscriptionManager,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -27,7 +28,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -200,6 +201,40 @@ export class StakingContract extends BaseContract {
}
return StakingContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
): Promise<StakingContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await StakingContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return StakingContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -1583,12 +1618,58 @@ export class StakingContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await StakingContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = StakingContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as StakingContract;
@ -1596,6 +1677,7 @@ export class StakingContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as StakingContract;
@ -1603,6 +1685,7 @@ export class StakingContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as StakingContract;
@ -3430,6 +3513,7 @@ export class StakingContract extends BaseContract {
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
@ -3437,12 +3521,14 @@ export class StakingContract extends BaseContract {
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The Staking contract event you would like to subscribe to.
@ -3468,6 +3554,7 @@ export class StakingContract extends BaseContract {
);
return logs;
}
constructor(
address: string,
supportedProvider: SupportedProvider,

View File

@ -10,6 +10,7 @@ import {
SubscriptionManager,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -27,7 +28,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -114,6 +115,48 @@ export class StakingProxyContract extends BaseContract {
_stakingContract,
);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
_stakingContract: string,
): Promise<StakingProxyContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await StakingProxyContract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return StakingProxyContract.deployAsync(
bytecode,
abi,
provider,
txDefaults,
logDecodeDependenciesAbiOnly,
_stakingContract,
);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -702,12 +745,58 @@ export class StakingProxyContract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await StakingProxyContract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = StakingProxyContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as StakingProxyContract;
@ -715,6 +804,7 @@ export class StakingProxyContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as StakingProxyContract;
@ -722,6 +812,7 @@ export class StakingProxyContract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as StakingProxyContract;
@ -1546,6 +1637,7 @@ export class StakingProxyContract extends BaseContract {
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
@ -1553,12 +1645,14 @@ export class StakingProxyContract extends BaseContract {
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The StakingProxy contract event you would like to subscribe to.
@ -1584,6 +1678,7 @@ export class StakingProxyContract extends BaseContract {
);
return logs;
}
constructor(
address: string,
supportedProvider: SupportedProvider,

View File

@ -10,6 +10,7 @@ import {
SubscriptionManager,
PromiseWithTransactionHash,
methodAbiToFunctionSignature,
linkLibrariesInBytecode,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
@ -27,7 +28,7 @@ import {
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
@ -105,6 +106,40 @@ export class WETH9Contract extends BaseContract {
}
return WETH9Contract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployWithLibrariesFrom0xArtifactAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
): Promise<WETH9Contract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (artifact.compilerOutput === undefined) {
throw new Error('Compiler output not found in the artifact file');
}
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const abi = artifact.compilerOutput.abi;
const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
if (Object.keys(logDecodeDependencies) !== undefined) {
for (const key of Object.keys(logDecodeDependencies)) {
logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
}
}
const libraryAddresses = await WETH9Contract._deployLibrariesAsync(
artifact,
libraryArtifacts,
new Web3Wrapper(provider),
txDefaults,
);
const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses);
return WETH9Contract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
@ -438,12 +473,58 @@ export class WETH9Contract extends BaseContract {
return abi;
}
protected static async _deployLibrariesAsync(
artifact: ContractArtifact,
libraryArtifacts: { [libraryName: string]: ContractArtifact },
web3Wrapper: Web3Wrapper,
txDefaults: Partial<TxData>,
libraryAddresses: { [libraryName: string]: string } = {},
): Promise<{ [libraryName: string]: string }> {
const links = artifact.compilerOutput.evm.bytecode.linkReferences;
// Go through all linked libraries, recursively deploying them if necessary.
for (const link of Object.values(links)) {
for (const libraryName of Object.keys(link)) {
if (!libraryAddresses[libraryName]) {
// Library not yet deployed.
const libraryArtifact = libraryArtifacts[libraryName];
if (!libraryArtifact) {
throw new Error(`Missing artifact for linked library "${libraryName}"`);
}
// Deploy any dependent libraries used by this library.
await WETH9Contract._deployLibrariesAsync(
libraryArtifact,
libraryArtifacts,
web3Wrapper,
txDefaults,
libraryAddresses,
);
// Deploy this library.
const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
data: linkedLibraryBytecode,
...txDefaults,
},
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
);
const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
logUtils.log(`transactionHash: ${txHash}`);
const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`);
libraryAddresses[libraryArtifact.contractName] = contractAddress as string;
}
}
}
return libraryAddresses;
}
public getFunctionSignature(methodName: string): string {
const index = this._methodABIIndex[methodName];
const methodAbi = WETH9Contract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
const functionSignature = methodAbiToFunctionSignature(methodAbi);
return functionSignature;
}
public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as WETH9Contract;
@ -451,6 +532,7 @@ export class WETH9Contract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
return abiDecodedCallData;
}
public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as WETH9Contract;
@ -458,6 +540,7 @@ export class WETH9Contract extends BaseContract {
const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
return abiDecodedCallData;
}
public getSelector(methodName: string): string {
const functionSignature = this.getFunctionSignature(methodName);
const self = (this as any) as WETH9Contract;
@ -857,6 +940,7 @@ export class WETH9Contract extends BaseContract {
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
@ -864,12 +948,14 @@ export class WETH9Contract extends BaseContract {
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The WETH9 contract event you would like to subscribe to.
@ -895,6 +981,7 @@ export class WETH9Contract extends BaseContract {
);
return logs;
}
constructor(
address: string,
supportedProvider: SupportedProvider,