@ethersproject/contracts
Advanced tools
Comparing version 5.0.0-beta.153 to 5.0.0-beta.154
@@ -1,1 +0,1 @@ | ||
export declare const version = "contracts/5.0.0-beta.153"; | ||
export declare const version = "contracts/5.0.0-beta.154"; |
@@ -1,1 +0,1 @@ | ||
export const version = "contracts/5.0.0-beta.153"; | ||
export const version = "contracts/5.0.0-beta.154"; |
@@ -19,7 +19,7 @@ import { Fragment, Indexed, Interface, JsonFragment, Result } from "@ethersproject/abi"; | ||
} | ||
export declare type ContractFunction = (...params: Array<any>) => Promise<any>; | ||
export declare type EventFilter = { | ||
address?: string; | ||
topics?: Array<string>; | ||
topics?: Array<string | Array<string>>; | ||
}; | ||
export declare type ContractFunction<T = any> = (...args: Array<any>) => Promise<T>; | ||
export interface Event extends Log { | ||
@@ -42,5 +42,2 @@ event?: string; | ||
} | ||
interface Bucket<T> { | ||
[name: string]: T; | ||
} | ||
declare class RunningEvent { | ||
@@ -66,13 +63,27 @@ readonly tag: string; | ||
readonly provider: Provider; | ||
readonly functions: Bucket<ContractFunction>; | ||
readonly callStatic: Bucket<ContractFunction>; | ||
readonly estimateGas: Bucket<(...params: Array<any>) => Promise<BigNumber>>; | ||
readonly populateTransaction: Bucket<(...params: Array<any>) => Promise<UnsignedTransaction>>; | ||
readonly filters: Bucket<(...params: Array<any>) => EventFilter>; | ||
readonly [name: string]: ContractFunction | any; | ||
readonly functions: { | ||
[name: string]: ContractFunction; | ||
}; | ||
readonly callStatic: { | ||
[name: string]: ContractFunction; | ||
}; | ||
readonly estimateGas: { | ||
[name: string]: ContractFunction<BigNumber>; | ||
}; | ||
readonly populateTransaction: { | ||
[name: string]: ContractFunction<UnsignedTransaction>; | ||
}; | ||
readonly filters: { | ||
[name: string]: (...args: Array<any>) => EventFilter; | ||
}; | ||
readonly [key: string]: ContractFunction | any; | ||
readonly resolvedAddress: Promise<string>; | ||
readonly deployTransaction: TransactionResponse; | ||
private _deployedPromise; | ||
private _runningEvents; | ||
private _wrappedEmits; | ||
_deployedPromise: Promise<Contract>; | ||
_runningEvents: { | ||
[eventTag: string]: RunningEvent; | ||
}; | ||
_wrappedEmits: { | ||
[eventTag: string]: (...args: Array<any>) => void; | ||
}; | ||
constructor(addressOrName: string, contractInterface: ContractInterface, signerOrProvider: Signer | Provider); | ||
@@ -79,0 +90,0 @@ static getContractAddress(transaction: { |
@@ -17,3 +17,2 @@ "use strict"; | ||
import { concat, hexlify, isBytes, isHexString } from "@ethersproject/bytes"; | ||
import { Zero } from "@ethersproject/constants"; | ||
import { defineReadOnly, deepCopy, getStatic, resolveProperties, shallowCopy } from "@ethersproject/properties"; | ||
@@ -48,141 +47,224 @@ import { Logger } from "@ethersproject/logger"; | ||
} | ||
/* | ||
export function _populateTransaction(func: FunctionFragment, args: Array<any>, overrides?: any): Promise<Transaction> { | ||
return null; | ||
function _populateTransaction(contract, fragment, args, overrides) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
overrides = shallowCopy(overrides); | ||
// Wait for all dependency addresses to be resolved (prefer the signer over the provider) | ||
const resolved = yield resolveProperties({ | ||
args: resolveAddresses(contract.signer || contract.provider, args, fragment.inputs), | ||
address: contract.resolvedAddress, | ||
overrides: (resolveProperties(overrides) || {}) | ||
}); | ||
// The ABI coded transaction | ||
const tx = { | ||
data: contract.interface.encodeFunctionData(fragment, resolved.args), | ||
to: resolved.address | ||
}; | ||
// Resolved Overrides | ||
const ro = resolved.overrides; | ||
if (ro.nonce != null) { | ||
tx.nonce = BigNumber.from(ro.nonce).toNumber(); | ||
} | ||
if (ro.gasLimit != null) { | ||
tx.gasLimit = BigNumber.from(ro.gasLimit); | ||
} | ||
if (ro.gasPrice != null) { | ||
tx.gasPrice = BigNumber.from(ro.gasPrice); | ||
} | ||
// If there was no gasLimit override, but the ABI specifies one use it | ||
if (tx.gasLimit == null && fragment.gas != null) { | ||
tx.gasLimit = BigNumber.from(fragment.gas).add(21000); | ||
} | ||
// Remvoe the overrides | ||
delete overrides.nonce; | ||
delete overrides.gasLimit; | ||
delete overrides.gasPrice; | ||
// @TODO: Maybe move all tx property validation to the Signer and Provider? | ||
// Make sure there are no stray overrides, which may indicate a | ||
// typo or using an unsupported key. | ||
const leftovers = Object.keys(overrides); | ||
if (leftovers.length) { | ||
logger.throwError(`cannot override ${leftovers.map((l) => JSON.stringify(l)).join(",")}`, Logger.errors.UNSUPPORTED_OPERATION, { | ||
operation: "overrides", | ||
keys: leftovers | ||
}); | ||
} | ||
return tx; | ||
}); | ||
} | ||
export function _sendTransaction(func: FunctionFragment, args: Array<any>, overrides?: any): Promise<Transaction> { | ||
return null; | ||
} | ||
*/ | ||
function runMethod(contract, functionName, options) { | ||
const method = contract.interface.functions[functionName]; | ||
return function (...params) { | ||
let tx = {}; | ||
let blockTag = null; | ||
// If 1 extra parameter was passed in, it contains overrides | ||
if (params.length === method.inputs.length + 1 && typeof (params[params.length - 1]) === "object") { | ||
tx = shallowCopy(params.pop()); | ||
if (tx.blockTag != null) { | ||
blockTag = tx.blockTag; | ||
function populateTransaction(contract, fragment, args, overrides) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
overrides = shallowCopy(overrides); | ||
// If the contract was just deployed, wait until it is minded | ||
if (contract.deployTransaction != null) { | ||
yield contract._deployed(); | ||
} | ||
// Resolved Overrides (keep value for errors) | ||
const ro = yield resolveProperties(overrides); | ||
const value = overrides.value; | ||
delete overrides.value; | ||
const tx = yield _populateTransaction(contract, fragment, args, overrides); | ||
if (ro.value) { | ||
const roValue = BigNumber.from(ro.value); | ||
if (!roValue.isZero() && !fragment.payable) { | ||
logger.throwError("non-payable method cannot override value", Logger.errors.UNSUPPORTED_OPERATION, { | ||
operation: "overrides.value", | ||
value: value | ||
}); | ||
} | ||
delete tx.blockTag; | ||
// Check for unexpected keys (e.g. using "gas" instead of "gasLimit") | ||
for (let key in tx) { | ||
if (!allowedTransactionKeys[key]) { | ||
logger.throwArgumentError(("unknown transaction override - " + key), "overrides", tx); | ||
} | ||
} | ||
tx.value = roValue; | ||
} | ||
logger.checkArgumentCount(params.length, method.inputs.length, "passed to contract"); | ||
// Check overrides make sense | ||
["data", "to"].forEach(function (key) { | ||
if (tx[key] != null) { | ||
logger.throwError("cannot override " + key, Logger.errors.UNSUPPORTED_OPERATION, { operation: key }); | ||
} | ||
}); | ||
return tx; | ||
}); | ||
} | ||
function populateCallTransaction(contract, fragment, args, overrides) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
overrides = shallowCopy(overrides); | ||
// If the contract was just deployed, wait until it is minded | ||
if (contract.deployTransaction != null) { | ||
tx.to = contract._deployed(blockTag).then(() => { | ||
return contract.resolvedAddress; | ||
}); | ||
let blockTag = undefined; | ||
if (overrides.blockTag) { | ||
blockTag = yield overrides.blockTag; | ||
} | ||
yield contract._deployed(blockTag); | ||
} | ||
else { | ||
tx.to = contract.resolvedAddress; | ||
// Resolved Overrides | ||
delete overrides.blockTag; | ||
const ro = yield resolveProperties(overrides); | ||
delete overrides.from; | ||
const tx = yield populateTransaction(contract, fragment, args, overrides); | ||
if (ro.from) { | ||
tx.from = this.interface.constructor.getAddress(ro.from); | ||
} | ||
return resolveAddresses(contract.signer || contract.provider, params, method.inputs).then((params) => { | ||
tx.data = contract.interface.encodeFunctionData(method, params); | ||
if (method.constant || options.callStatic) { | ||
// Call (constant functions) always cost 0 ether | ||
if (options.estimate) { | ||
return Promise.resolve(Zero); | ||
return tx; | ||
}); | ||
} | ||
function buildPopulate(contract, fragment) { | ||
const populate = (fragment.constant) ? populateCallTransaction : populateTransaction; | ||
return function (...args) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let overrides = null; | ||
if (args.length === fragment.inputs.length + 1 && typeof (args[args.length - 1]) === "object") { | ||
overrides = args.pop(); | ||
} | ||
logger.checkArgumentCount(args.length, fragment.inputs.length, "passed to contract"); | ||
return populate(contract, fragment, args, overrides); | ||
}); | ||
}; | ||
} | ||
function buildEstimate(contract, fragment) { | ||
const signerOrProvider = (contract.signer || contract.provider); | ||
const populate = (fragment.constant) ? populateCallTransaction : populateTransaction; | ||
return function (...args) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let overrides = null; | ||
if (args.length === fragment.inputs.length + 1 && typeof (args[args.length - 1]) === "object") { | ||
overrides = args.pop(); | ||
} | ||
logger.checkArgumentCount(args.length, fragment.inputs.length, "passed to contract"); | ||
if (!signerOrProvider) { | ||
logger.throwError("estimate require a provider or signer", Logger.errors.UNSUPPORTED_OPERATION, { operation: "estimateGas" }); | ||
} | ||
const tx = yield populate(contract, fragment, args, overrides); | ||
return yield signerOrProvider.estimateGas(tx); | ||
}); | ||
}; | ||
} | ||
function buildCall(contract, fragment, collapseSimple) { | ||
const signerOrProvider = (contract.signer || contract.provider); | ||
const populate = (fragment.constant) ? populateCallTransaction : populateTransaction; | ||
return function (...args) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let overrides = null; | ||
let blockTag = undefined; | ||
if (args.length === fragment.inputs.length + 1 && typeof (args[args.length - 1]) === "object") { | ||
overrides = shallowCopy(args.pop()); | ||
if (overrides.blockTag) { | ||
blockTag = yield overrides.blockTag; | ||
delete overrides.blockTag; | ||
} | ||
if (!contract.provider && !contract.signer) { | ||
logger.throwError("call (constant functions) require a provider or signer", Logger.errors.UNSUPPORTED_OPERATION, { operation: "call" }); | ||
} | ||
logger.checkArgumentCount(args.length, fragment.inputs.length, "passed to contract"); | ||
const tx = yield populate(contract, fragment, args, overrides); | ||
const value = yield signerOrProvider.call(tx, blockTag); | ||
try { | ||
let result = contract.interface.decodeFunctionResult(fragment, value); | ||
if (collapseSimple && fragment.outputs.length === 1) { | ||
result = result[0]; | ||
} | ||
// Check overrides make sense | ||
["gasLimit", "gasPrice", "value"].forEach(function (key) { | ||
if (tx[key] != null) { | ||
throw new Error("call cannot override " + key); | ||
} | ||
}); | ||
if (options.transaction) { | ||
return resolveProperties(tx); | ||
} | ||
return (contract.signer || contract.provider).call(tx, blockTag).then((value) => { | ||
try { | ||
let result = contract.interface.decodeFunctionResult(method, value); | ||
if (method.outputs.length === 1) { | ||
result = result[0]; | ||
} | ||
return result; | ||
} | ||
catch (error) { | ||
if (error.code === Logger.errors.CALL_EXCEPTION) { | ||
error.address = contract.address; | ||
error.args = params; | ||
error.transaction = tx; | ||
} | ||
throw error; | ||
} | ||
}); | ||
return result; | ||
} | ||
// Only computing the transaction estimate | ||
if (options.estimate) { | ||
if (!contract.provider && !contract.signer) { | ||
logger.throwError("estimate require a provider or signer", Logger.errors.UNSUPPORTED_OPERATION, { operation: "estimateGas" }); | ||
catch (error) { | ||
if (error.code === Logger.errors.CALL_EXCEPTION) { | ||
error.address = contract.address; | ||
error.args = args; | ||
error.transaction = tx; | ||
} | ||
return (contract.signer || contract.provider).estimateGas(tx); | ||
throw error; | ||
} | ||
if (tx.gasLimit == null && method.gas != null) { | ||
tx.gasLimit = BigNumber.from(method.gas).add(21000); | ||
} | ||
if (tx.value != null && !method.payable) { | ||
logger.throwArgumentError("contract method is not payable", "sendTransaction:" + method.format(), tx); | ||
} | ||
if (options.transaction) { | ||
return resolveProperties(tx); | ||
} | ||
}); | ||
}; | ||
} | ||
function buildSend(contract, fragment) { | ||
return function (...args) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!contract.signer) { | ||
logger.throwError("sending a transaction requires a signer", Logger.errors.UNSUPPORTED_OPERATION, { operation: "sendTransaction" }); | ||
} | ||
return contract.signer.sendTransaction(tx).then((tx) => { | ||
const wait = tx.wait.bind(tx); | ||
tx.wait = (confirmations) => { | ||
return wait(confirmations).then((receipt) => { | ||
receipt.events = receipt.logs.map((log) => { | ||
let event = deepCopy(log); | ||
let parsed = null; | ||
try { | ||
parsed = contract.interface.parseLog(log); | ||
} | ||
catch (e) { } | ||
if (parsed) { | ||
event.args = parsed.args; | ||
event.decode = (data, topics) => { | ||
return this.interface.decodeEventLog(parsed.eventFragment, data, topics); | ||
}; | ||
event.event = parsed.name; | ||
event.eventSignature = parsed.signature; | ||
} | ||
event.removeListener = () => { return contract.provider; }; | ||
event.getBlock = () => { | ||
return contract.provider.getBlock(receipt.blockHash); | ||
// We allow CallOverrides, since the Signer can accept from | ||
let overrides = null; | ||
if (args.length === fragment.inputs.length + 1 && typeof (args[args.length - 1]) === "object") { | ||
overrides = shallowCopy(args.pop()); | ||
if (overrides.blockTag != null) { | ||
logger.throwArgumentError(`cannot override "blockTag" in transaction`, "overrides", overrides); | ||
} | ||
} | ||
logger.checkArgumentCount(args.length, fragment.inputs.length, "passed to contract"); | ||
const txRequest = yield populateCallTransaction(contract, fragment, args, overrides); | ||
const tx = yield contract.signer.sendTransaction(txRequest); | ||
// Tweak the tw.wait so the receipt has extra properties | ||
const wait = tx.wait.bind(tx); | ||
tx.wait = (confirmations) => { | ||
return wait(confirmations).then((receipt) => { | ||
receipt.events = receipt.logs.map((log) => { | ||
let event = deepCopy(log); | ||
let parsed = null; | ||
try { | ||
parsed = contract.interface.parseLog(log); | ||
} | ||
catch (e) { } | ||
// Successfully parsed the event log; include it | ||
if (parsed) { | ||
event.args = parsed.args; | ||
event.decode = (data, topics) => { | ||
return this.interface.decodeEventLog(parsed.eventFragment, data, topics); | ||
}; | ||
event.getTransaction = () => { | ||
return contract.provider.getTransaction(receipt.transactionHash); | ||
}; | ||
event.getTransactionReceipt = () => { | ||
return Promise.resolve(receipt); | ||
}; | ||
return event; | ||
}); | ||
return receipt; | ||
event.event = parsed.name; | ||
event.eventSignature = parsed.signature; | ||
} | ||
// Useful operations | ||
event.removeListener = () => { return contract.provider; }; | ||
event.getBlock = () => { | ||
return contract.provider.getBlock(receipt.blockHash); | ||
}; | ||
event.getTransaction = () => { | ||
return contract.provider.getTransaction(receipt.transactionHash); | ||
}; | ||
event.getTransactionReceipt = () => { | ||
return Promise.resolve(receipt); | ||
}; | ||
return event; | ||
}); | ||
}; | ||
return tx; | ||
}); | ||
return receipt; | ||
}); | ||
}; | ||
return tx; | ||
}); | ||
}; | ||
} | ||
function buildDefault(contract, fragment, collapseSimple) { | ||
if (fragment.constant) { | ||
return buildCall(contract, fragment, collapseSimple); | ||
} | ||
return buildSend(contract, fragment); | ||
} | ||
function getEventTag(filter) { | ||
@@ -192,3 +274,8 @@ if (filter.address && (filter.topics == null || filter.topics.length === 0)) { | ||
} | ||
return (filter.address || "*") + "@" + (filter.topics ? filter.topics.join(":") : ""); | ||
return (filter.address || "*") + "@" + (filter.topics ? filter.topics.map((topic) => { | ||
if (Array.isArray(topic)) { | ||
return topic.join("|"); | ||
} | ||
return topic; | ||
}).join(":") : ""); | ||
} | ||
@@ -415,18 +502,19 @@ class RunningEvent { | ||
} | ||
// @TODO: This should take in fragment | ||
const run = runMethod(this, signature, {}); | ||
if (this[signature] == null) { | ||
defineReadOnly(this, signature, run); | ||
defineReadOnly(this, signature, buildDefault(this, fragment, true)); | ||
} | ||
// We do not collapse simple calls on this bucket, which allows | ||
// frameworks to safely use this without introspection as well as | ||
// allows decoding error recovery. | ||
if (this.functions[signature] == null) { | ||
defineReadOnly(this.functions, signature, run); | ||
defineReadOnly(this.functions, signature, buildDefault(this, fragment, false)); | ||
} | ||
if (this.callStatic[signature] == null) { | ||
defineReadOnly(this.callStatic, signature, runMethod(this, signature, { callStatic: true })); | ||
defineReadOnly(this.callStatic, signature, buildCall(this, fragment, true)); | ||
} | ||
if (this.populateTransaction[signature] == null) { | ||
defineReadOnly(this.populateTransaction, signature, runMethod(this, signature, { transaction: true })); | ||
defineReadOnly(this.populateTransaction, signature, buildPopulate(this, fragment)); | ||
} | ||
if (this.estimateGas[signature] == null) { | ||
defineReadOnly(this.estimateGas, signature, runMethod(this, signature, { estimate: true })); | ||
defineReadOnly(this.estimateGas, signature, buildEstimate(this, fragment)); | ||
} | ||
@@ -564,3 +652,7 @@ }); | ||
try { | ||
const fragment = this.interface.getEvent(eventName.topics[0]); | ||
const topic = eventName.topics[0]; | ||
if (typeof (topic) !== "string") { | ||
throw new Error("invalid topic"); // @TODO: May happen for anonymous events | ||
} | ||
const fragment = this.interface.getEvent(topic); | ||
return this._normalizeRunningEvent(new FragmentRunningEvent(this.address, this.interface, fragment, eventName.topics)); | ||
@@ -764,2 +856,3 @@ } | ||
} | ||
// @TODO: Future; rename to populteTransaction? | ||
getDeployTransaction(...args) { | ||
@@ -766,0 +859,0 @@ let tx = {}; |
@@ -1,1 +0,1 @@ | ||
export declare const version = "contracts/5.0.0-beta.153"; | ||
export declare const version = "contracts/5.0.0-beta.154"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.version = "contracts/5.0.0-beta.153"; | ||
exports.version = "contracts/5.0.0-beta.154"; |
@@ -19,7 +19,7 @@ import { Fragment, Indexed, Interface, JsonFragment, Result } from "@ethersproject/abi"; | ||
} | ||
export declare type ContractFunction = (...params: Array<any>) => Promise<any>; | ||
export declare type EventFilter = { | ||
address?: string; | ||
topics?: Array<string>; | ||
topics?: Array<string | Array<string>>; | ||
}; | ||
export declare type ContractFunction<T = any> = (...args: Array<any>) => Promise<T>; | ||
export interface Event extends Log { | ||
@@ -42,5 +42,2 @@ event?: string; | ||
} | ||
interface Bucket<T> { | ||
[name: string]: T; | ||
} | ||
declare class RunningEvent { | ||
@@ -66,13 +63,27 @@ readonly tag: string; | ||
readonly provider: Provider; | ||
readonly functions: Bucket<ContractFunction>; | ||
readonly callStatic: Bucket<ContractFunction>; | ||
readonly estimateGas: Bucket<(...params: Array<any>) => Promise<BigNumber>>; | ||
readonly populateTransaction: Bucket<(...params: Array<any>) => Promise<UnsignedTransaction>>; | ||
readonly filters: Bucket<(...params: Array<any>) => EventFilter>; | ||
readonly [name: string]: ContractFunction | any; | ||
readonly functions: { | ||
[name: string]: ContractFunction; | ||
}; | ||
readonly callStatic: { | ||
[name: string]: ContractFunction; | ||
}; | ||
readonly estimateGas: { | ||
[name: string]: ContractFunction<BigNumber>; | ||
}; | ||
readonly populateTransaction: { | ||
[name: string]: ContractFunction<UnsignedTransaction>; | ||
}; | ||
readonly filters: { | ||
[name: string]: (...args: Array<any>) => EventFilter; | ||
}; | ||
readonly [key: string]: ContractFunction | any; | ||
readonly resolvedAddress: Promise<string>; | ||
readonly deployTransaction: TransactionResponse; | ||
private _deployedPromise; | ||
private _runningEvents; | ||
private _wrappedEmits; | ||
_deployedPromise: Promise<Contract>; | ||
_runningEvents: { | ||
[eventTag: string]: RunningEvent; | ||
}; | ||
_wrappedEmits: { | ||
[eventTag: string]: (...args: Array<any>) => void; | ||
}; | ||
constructor(addressOrName: string, contractInterface: ContractInterface, signerOrProvider: Signer | Provider); | ||
@@ -79,0 +90,0 @@ static getContractAddress(transaction: { |
438
lib/index.js
@@ -65,3 +65,2 @@ "use strict"; | ||
var bytes_1 = require("@ethersproject/bytes"); | ||
var constants_1 = require("@ethersproject/constants"); | ||
var properties_1 = require("@ethersproject/properties"); | ||
@@ -96,142 +95,220 @@ var logger_1 = require("@ethersproject/logger"); | ||
} | ||
/* | ||
export function _populateTransaction(func: FunctionFragment, args: Array<any>, overrides?: any): Promise<Transaction> { | ||
return null; | ||
function _populateTransaction(contract, fragment, args, overrides) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var resolved, tx, ro, leftovers; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
overrides = properties_1.shallowCopy(overrides); | ||
return [4 /*yield*/, properties_1.resolveProperties({ | ||
args: resolveAddresses(contract.signer || contract.provider, args, fragment.inputs), | ||
address: contract.resolvedAddress, | ||
overrides: (properties_1.resolveProperties(overrides) || {}) | ||
})]; | ||
case 1: | ||
resolved = _a.sent(); | ||
tx = { | ||
data: contract.interface.encodeFunctionData(fragment, resolved.args), | ||
to: resolved.address | ||
}; | ||
ro = resolved.overrides; | ||
if (ro.nonce != null) { | ||
tx.nonce = bignumber_1.BigNumber.from(ro.nonce).toNumber(); | ||
} | ||
if (ro.gasLimit != null) { | ||
tx.gasLimit = bignumber_1.BigNumber.from(ro.gasLimit); | ||
} | ||
if (ro.gasPrice != null) { | ||
tx.gasPrice = bignumber_1.BigNumber.from(ro.gasPrice); | ||
} | ||
// If there was no gasLimit override, but the ABI specifies one use it | ||
if (tx.gasLimit == null && fragment.gas != null) { | ||
tx.gasLimit = bignumber_1.BigNumber.from(fragment.gas).add(21000); | ||
} | ||
// Remvoe the overrides | ||
delete overrides.nonce; | ||
delete overrides.gasLimit; | ||
delete overrides.gasPrice; | ||
leftovers = Object.keys(overrides); | ||
if (leftovers.length) { | ||
logger.throwError("cannot override " + leftovers.map(function (l) { return JSON.stringify(l); }).join(","), logger_1.Logger.errors.UNSUPPORTED_OPERATION, { | ||
operation: "overrides", | ||
keys: leftovers | ||
}); | ||
} | ||
return [2 /*return*/, tx]; | ||
} | ||
}); | ||
}); | ||
} | ||
export function _sendTransaction(func: FunctionFragment, args: Array<any>, overrides?: any): Promise<Transaction> { | ||
return null; | ||
function populateTransaction(contract, fragment, args, overrides) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var ro, value, tx, roValue; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
overrides = properties_1.shallowCopy(overrides); | ||
if (!(contract.deployTransaction != null)) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, contract._deployed()]; | ||
case 1: | ||
_a.sent(); | ||
_a.label = 2; | ||
case 2: return [4 /*yield*/, properties_1.resolveProperties(overrides)]; | ||
case 3: | ||
ro = _a.sent(); | ||
value = overrides.value; | ||
delete overrides.value; | ||
return [4 /*yield*/, _populateTransaction(contract, fragment, args, overrides)]; | ||
case 4: | ||
tx = _a.sent(); | ||
if (ro.value) { | ||
roValue = bignumber_1.BigNumber.from(ro.value); | ||
if (!roValue.isZero() && !fragment.payable) { | ||
logger.throwError("non-payable method cannot override value", logger_1.Logger.errors.UNSUPPORTED_OPERATION, { | ||
operation: "overrides.value", | ||
value: value | ||
}); | ||
} | ||
tx.value = roValue; | ||
} | ||
return [2 /*return*/, tx]; | ||
} | ||
}); | ||
}); | ||
} | ||
*/ | ||
function runMethod(contract, functionName, options) { | ||
var method = contract.interface.functions[functionName]; | ||
function populateCallTransaction(contract, fragment, args, overrides) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var blockTag, ro, tx; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
overrides = properties_1.shallowCopy(overrides); | ||
if (!(contract.deployTransaction != null)) return [3 /*break*/, 4]; | ||
blockTag = undefined; | ||
if (!overrides.blockTag) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, overrides.blockTag]; | ||
case 1: | ||
blockTag = _a.sent(); | ||
_a.label = 2; | ||
case 2: return [4 /*yield*/, contract._deployed(blockTag)]; | ||
case 3: | ||
_a.sent(); | ||
_a.label = 4; | ||
case 4: | ||
// Resolved Overrides | ||
delete overrides.blockTag; | ||
return [4 /*yield*/, properties_1.resolveProperties(overrides)]; | ||
case 5: | ||
ro = _a.sent(); | ||
delete overrides.from; | ||
return [4 /*yield*/, populateTransaction(contract, fragment, args, overrides)]; | ||
case 6: | ||
tx = _a.sent(); | ||
if (ro.from) { | ||
tx.from = this.interface.constructor.getAddress(ro.from); | ||
} | ||
return [2 /*return*/, tx]; | ||
} | ||
}); | ||
}); | ||
} | ||
function buildPopulate(contract, fragment) { | ||
var populate = (fragment.constant) ? populateCallTransaction : populateTransaction; | ||
return function () { | ||
var _this = this; | ||
var params = []; | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
params[_i] = arguments[_i]; | ||
args[_i] = arguments[_i]; | ||
} | ||
var tx = {}; | ||
var blockTag = null; | ||
// If 1 extra parameter was passed in, it contains overrides | ||
if (params.length === method.inputs.length + 1 && typeof (params[params.length - 1]) === "object") { | ||
tx = properties_1.shallowCopy(params.pop()); | ||
if (tx.blockTag != null) { | ||
blockTag = tx.blockTag; | ||
} | ||
delete tx.blockTag; | ||
// Check for unexpected keys (e.g. using "gas" instead of "gasLimit") | ||
for (var key in tx) { | ||
if (!allowedTransactionKeys[key]) { | ||
logger.throwArgumentError(("unknown transaction override - " + key), "overrides", tx); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var overrides; | ||
return __generator(this, function (_a) { | ||
overrides = null; | ||
if (args.length === fragment.inputs.length + 1 && typeof (args[args.length - 1]) === "object") { | ||
overrides = args.pop(); | ||
} | ||
} | ||
} | ||
logger.checkArgumentCount(params.length, method.inputs.length, "passed to contract"); | ||
// Check overrides make sense | ||
["data", "to"].forEach(function (key) { | ||
if (tx[key] != null) { | ||
logger.throwError("cannot override " + key, logger_1.Logger.errors.UNSUPPORTED_OPERATION, { operation: key }); | ||
} | ||
logger.checkArgumentCount(args.length, fragment.inputs.length, "passed to contract"); | ||
return [2 /*return*/, populate(contract, fragment, args, overrides)]; | ||
}); | ||
}); | ||
// If the contract was just deployed, wait until it is minded | ||
if (contract.deployTransaction != null) { | ||
tx.to = contract._deployed(blockTag).then(function () { | ||
return contract.resolvedAddress; | ||
}); | ||
}; | ||
} | ||
function buildEstimate(contract, fragment) { | ||
var signerOrProvider = (contract.signer || contract.provider); | ||
var populate = (fragment.constant) ? populateCallTransaction : populateTransaction; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
else { | ||
tx.to = contract.resolvedAddress; | ||
} | ||
return resolveAddresses(contract.signer || contract.provider, params, method.inputs).then(function (params) { | ||
tx.data = contract.interface.encodeFunctionData(method, params); | ||
if (method.constant || options.callStatic) { | ||
// Call (constant functions) always cost 0 ether | ||
if (options.estimate) { | ||
return Promise.resolve(constants_1.Zero); | ||
} | ||
if (!contract.provider && !contract.signer) { | ||
logger.throwError("call (constant functions) require a provider or signer", logger_1.Logger.errors.UNSUPPORTED_OPERATION, { operation: "call" }); | ||
} | ||
// Check overrides make sense | ||
["gasLimit", "gasPrice", "value"].forEach(function (key) { | ||
if (tx[key] != null) { | ||
throw new Error("call cannot override " + key); | ||
} | ||
}); | ||
if (options.transaction) { | ||
return properties_1.resolveProperties(tx); | ||
} | ||
return (contract.signer || contract.provider).call(tx, blockTag).then(function (value) { | ||
try { | ||
var result = contract.interface.decodeFunctionResult(method, value); | ||
if (method.outputs.length === 1) { | ||
result = result[0]; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var overrides, tx; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
overrides = null; | ||
if (args.length === fragment.inputs.length + 1 && typeof (args[args.length - 1]) === "object") { | ||
overrides = args.pop(); | ||
} | ||
return result; | ||
} | ||
catch (error) { | ||
if (error.code === logger_1.Logger.errors.CALL_EXCEPTION) { | ||
error.address = contract.address; | ||
error.args = params; | ||
error.transaction = tx; | ||
logger.checkArgumentCount(args.length, fragment.inputs.length, "passed to contract"); | ||
if (!signerOrProvider) { | ||
logger.throwError("estimate require a provider or signer", logger_1.Logger.errors.UNSUPPORTED_OPERATION, { operation: "estimateGas" }); | ||
} | ||
throw error; | ||
} | ||
}); | ||
} | ||
// Only computing the transaction estimate | ||
if (options.estimate) { | ||
if (!contract.provider && !contract.signer) { | ||
logger.throwError("estimate require a provider or signer", logger_1.Logger.errors.UNSUPPORTED_OPERATION, { operation: "estimateGas" }); | ||
return [4 /*yield*/, populate(contract, fragment, args, overrides)]; | ||
case 1: | ||
tx = _a.sent(); | ||
return [4 /*yield*/, signerOrProvider.estimateGas(tx)]; | ||
case 2: return [2 /*return*/, _a.sent()]; | ||
} | ||
return (contract.signer || contract.provider).estimateGas(tx); | ||
} | ||
if (tx.gasLimit == null && method.gas != null) { | ||
tx.gasLimit = bignumber_1.BigNumber.from(method.gas).add(21000); | ||
} | ||
if (tx.value != null && !method.payable) { | ||
logger.throwArgumentError("contract method is not payable", "sendTransaction:" + method.format(), tx); | ||
} | ||
if (options.transaction) { | ||
return properties_1.resolveProperties(tx); | ||
} | ||
if (!contract.signer) { | ||
logger.throwError("sending a transaction requires a signer", logger_1.Logger.errors.UNSUPPORTED_OPERATION, { operation: "sendTransaction" }); | ||
} | ||
return contract.signer.sendTransaction(tx).then(function (tx) { | ||
var wait = tx.wait.bind(tx); | ||
tx.wait = function (confirmations) { | ||
return wait(confirmations).then(function (receipt) { | ||
receipt.events = receipt.logs.map(function (log) { | ||
var event = properties_1.deepCopy(log); | ||
var parsed = null; | ||
try { | ||
parsed = contract.interface.parseLog(log); | ||
}); | ||
}); | ||
}; | ||
} | ||
function buildCall(contract, fragment, collapseSimple) { | ||
var signerOrProvider = (contract.signer || contract.provider); | ||
var populate = (fragment.constant) ? populateCallTransaction : populateTransaction; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
return __awaiter(this, void 0, void 0, function () { | ||
var overrides, blockTag, tx, value, result; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
overrides = null; | ||
blockTag = undefined; | ||
if (!(args.length === fragment.inputs.length + 1 && typeof (args[args.length - 1]) === "object")) return [3 /*break*/, 2]; | ||
overrides = properties_1.shallowCopy(args.pop()); | ||
if (!overrides.blockTag) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, overrides.blockTag]; | ||
case 1: | ||
blockTag = _a.sent(); | ||
delete overrides.blockTag; | ||
_a.label = 2; | ||
case 2: | ||
logger.checkArgumentCount(args.length, fragment.inputs.length, "passed to contract"); | ||
return [4 /*yield*/, populate(contract, fragment, args, overrides)]; | ||
case 3: | ||
tx = _a.sent(); | ||
return [4 /*yield*/, signerOrProvider.call(tx, blockTag)]; | ||
case 4: | ||
value = _a.sent(); | ||
try { | ||
result = contract.interface.decodeFunctionResult(fragment, value); | ||
if (collapseSimple && fragment.outputs.length === 1) { | ||
result = result[0]; | ||
} | ||
catch (e) { } | ||
if (parsed) { | ||
event.args = parsed.args; | ||
event.decode = function (data, topics) { | ||
return _this.interface.decodeEventLog(parsed.eventFragment, data, topics); | ||
}; | ||
event.event = parsed.name; | ||
event.eventSignature = parsed.signature; | ||
return [2 /*return*/, result]; | ||
} | ||
catch (error) { | ||
if (error.code === logger_1.Logger.errors.CALL_EXCEPTION) { | ||
error.address = contract.address; | ||
error.args = args; | ||
error.transaction = tx; | ||
} | ||
event.removeListener = function () { return contract.provider; }; | ||
event.getBlock = function () { | ||
return contract.provider.getBlock(receipt.blockHash); | ||
}; | ||
event.getTransaction = function () { | ||
return contract.provider.getTransaction(receipt.transactionHash); | ||
}; | ||
event.getTransactionReceipt = function () { | ||
return Promise.resolve(receipt); | ||
}; | ||
return event; | ||
}); | ||
return receipt; | ||
}); | ||
}; | ||
return tx; | ||
throw error; | ||
} | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
@@ -241,2 +318,78 @@ }); | ||
} | ||
function buildSend(contract, fragment) { | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
return __awaiter(this, void 0, void 0, function () { | ||
var overrides, txRequest, tx, wait; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!contract.signer) { | ||
logger.throwError("sending a transaction requires a signer", logger_1.Logger.errors.UNSUPPORTED_OPERATION, { operation: "sendTransaction" }); | ||
} | ||
overrides = null; | ||
if (args.length === fragment.inputs.length + 1 && typeof (args[args.length - 1]) === "object") { | ||
overrides = properties_1.shallowCopy(args.pop()); | ||
if (overrides.blockTag != null) { | ||
logger.throwArgumentError("cannot override \"blockTag\" in transaction", "overrides", overrides); | ||
} | ||
} | ||
logger.checkArgumentCount(args.length, fragment.inputs.length, "passed to contract"); | ||
return [4 /*yield*/, populateCallTransaction(contract, fragment, args, overrides)]; | ||
case 1: | ||
txRequest = _a.sent(); | ||
return [4 /*yield*/, contract.signer.sendTransaction(txRequest)]; | ||
case 2: | ||
tx = _a.sent(); | ||
wait = tx.wait.bind(tx); | ||
tx.wait = function (confirmations) { | ||
return wait(confirmations).then(function (receipt) { | ||
receipt.events = receipt.logs.map(function (log) { | ||
var event = properties_1.deepCopy(log); | ||
var parsed = null; | ||
try { | ||
parsed = contract.interface.parseLog(log); | ||
} | ||
catch (e) { } | ||
// Successfully parsed the event log; include it | ||
if (parsed) { | ||
event.args = parsed.args; | ||
event.decode = function (data, topics) { | ||
return _this.interface.decodeEventLog(parsed.eventFragment, data, topics); | ||
}; | ||
event.event = parsed.name; | ||
event.eventSignature = parsed.signature; | ||
} | ||
// Useful operations | ||
event.removeListener = function () { return contract.provider; }; | ||
event.getBlock = function () { | ||
return contract.provider.getBlock(receipt.blockHash); | ||
}; | ||
event.getTransaction = function () { | ||
return contract.provider.getTransaction(receipt.transactionHash); | ||
}; | ||
event.getTransactionReceipt = function () { | ||
return Promise.resolve(receipt); | ||
}; | ||
return event; | ||
}); | ||
return receipt; | ||
}); | ||
}; | ||
return [2 /*return*/, tx]; | ||
} | ||
}); | ||
}); | ||
}; | ||
} | ||
function buildDefault(contract, fragment, collapseSimple) { | ||
if (fragment.constant) { | ||
return buildCall(contract, fragment, collapseSimple); | ||
} | ||
return buildSend(contract, fragment); | ||
} | ||
function getEventTag(filter) { | ||
@@ -246,3 +399,8 @@ if (filter.address && (filter.topics == null || filter.topics.length === 0)) { | ||
} | ||
return (filter.address || "*") + "@" + (filter.topics ? filter.topics.join(":") : ""); | ||
return (filter.address || "*") + "@" + (filter.topics ? filter.topics.map(function (topic) { | ||
if (Array.isArray(topic)) { | ||
return topic.join("|"); | ||
} | ||
return topic; | ||
}).join(":") : ""); | ||
} | ||
@@ -488,18 +646,19 @@ var RunningEvent = /** @class */ (function () { | ||
} | ||
// @TODO: This should take in fragment | ||
var run = runMethod(_this, signature, {}); | ||
if (_this[signature] == null) { | ||
properties_1.defineReadOnly(_this, signature, run); | ||
properties_1.defineReadOnly(_this, signature, buildDefault(_this, fragment, true)); | ||
} | ||
// We do not collapse simple calls on this bucket, which allows | ||
// frameworks to safely use this without introspection as well as | ||
// allows decoding error recovery. | ||
if (_this.functions[signature] == null) { | ||
properties_1.defineReadOnly(_this.functions, signature, run); | ||
properties_1.defineReadOnly(_this.functions, signature, buildDefault(_this, fragment, false)); | ||
} | ||
if (_this.callStatic[signature] == null) { | ||
properties_1.defineReadOnly(_this.callStatic, signature, runMethod(_this, signature, { callStatic: true })); | ||
properties_1.defineReadOnly(_this.callStatic, signature, buildCall(_this, fragment, true)); | ||
} | ||
if (_this.populateTransaction[signature] == null) { | ||
properties_1.defineReadOnly(_this.populateTransaction, signature, runMethod(_this, signature, { transaction: true })); | ||
properties_1.defineReadOnly(_this.populateTransaction, signature, buildPopulate(_this, fragment)); | ||
} | ||
if (_this.estimateGas[signature] == null) { | ||
properties_1.defineReadOnly(_this.estimateGas, signature, runMethod(_this, signature, { estimate: true })); | ||
properties_1.defineReadOnly(_this.estimateGas, signature, buildEstimate(_this, fragment)); | ||
} | ||
@@ -639,3 +798,7 @@ }); | ||
try { | ||
var fragment = this.interface.getEvent(eventName.topics[0]); | ||
var topic = eventName.topics[0]; | ||
if (typeof (topic) !== "string") { | ||
throw new Error("invalid topic"); // @TODO: May happen for anonymous events | ||
} | ||
var fragment = this.interface.getEvent(topic); | ||
return this._normalizeRunningEvent(new FragmentRunningEvent(this.address, this.interface, fragment, eventName.topics)); | ||
@@ -849,2 +1012,3 @@ } | ||
} | ||
// @TODO: Future; rename to populteTransaction? | ||
ContractFactory.prototype.getDeployTransaction = function () { | ||
@@ -851,0 +1015,0 @@ var args = []; |
@@ -35,5 +35,5 @@ { | ||
}, | ||
"tarballHash": "0xcfc82f0eb8ef40414848c63115b2f09acfa075423f101b56237b9f0f7b277bbe", | ||
"tarballHash": "0xc7210dbd8a387e8ee1b090ba36f5393ab7167a7a5fbb2dea34fc938b2e5c67e6", | ||
"types": "./lib/index.d.ts", | ||
"version": "5.0.0-beta.153" | ||
"version": "5.0.0-beta.154" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
106016
2308