docs: added jsdocs and general documentation
This commit is contained in:
parent
c785c1e515
commit
bbcfb5f6b8
@ -1,26 +1,97 @@
|
|||||||
_section: ABI
|
_section: Application Binary Interfaces @<docs-abi>
|
||||||
|
|
||||||
Explain about ABI here, what it does and does not do
|
When interacting with any application, whether it is on Ethereum,
|
||||||
|
over the internet or within a compiled application on a computer
|
||||||
|
all information is stored and sent as binary data which is just a
|
||||||
|
sequence of bytes.
|
||||||
|
|
||||||
- encodes arbitrary (but defined) data structures to raw bytes
|
So every application must agree on how to encode and decode their
|
||||||
|
information as a sequence of bytes.
|
||||||
|
|
||||||
_subsection: Call
|
An **Application Binary Interface** (ABI) provides a way to describe
|
||||||
|
the encoding and decoding process, in a generic way so that a variety
|
||||||
|
of types and structures of types can be defined.
|
||||||
|
|
||||||
About encoding
|
For example, a string is often encoded as a UTF-8 sequence of bytes,
|
||||||
|
which uses specific bits within sub-sequences to indicate emoji and
|
||||||
|
other special characters. Every implementation of UTF-8 must understand
|
||||||
|
and operate under the same rules so that strings work universally. In
|
||||||
|
this way, UTF-8 standard is itself an ABI.
|
||||||
|
|
||||||
_heading: selector or signature hash (sighash)
|
When interacting with Ethereum, a contract received a sequence of bytes
|
||||||
|
as input (provided by sending a transaction or through a call) and
|
||||||
|
returns a result as a sequence of bytes. So, each Contract has its own
|
||||||
|
ABI that helps specify how to encode the input and how to decode the output.
|
||||||
|
|
||||||
_heading: Results
|
It is up to the contract developer to make this ABI available. Many
|
||||||
|
Contracts implement a standard (such as ERC-20), in which case the
|
||||||
|
ABI for that standard can be used. Many developers choose to verify their
|
||||||
|
source code on Etherscan, in which case Etherscan computes the ABI and
|
||||||
|
provides it through their website (which can be fetched using the ``getContract``
|
||||||
|
method). Otherwise, beyond reverse engineering the Contract there is
|
||||||
|
not a meaningful way to extract the contract ABI.
|
||||||
|
|
||||||
_subsection: Events
|
_subsection: Call Data Representation
|
||||||
|
|
||||||
|
When calling a Contract on Ethereum, the input data must be encoded
|
||||||
|
according to the ABI.
|
||||||
|
|
||||||
|
The first 4 bytes of the data are the **method selector**, which is
|
||||||
|
the keccak256 hash of the normalized method signature.
|
||||||
|
|
||||||
|
Then the method parameters are encoded and concatenated to the selector.
|
||||||
|
|
||||||
|
All encoded data is made up of components padded to 32 bytes, so the length
|
||||||
|
of input data will always be congruent to ``4 mod 32``.
|
||||||
|
|
||||||
|
The result of a successful call will be encoded values, whose components
|
||||||
|
are padded to 32 bytes each as well, so the length of a result will always
|
||||||
|
be congruent to ``0 mod 32``, on success.
|
||||||
|
|
||||||
|
The result of a reverted call will contain the **error selector** as the
|
||||||
|
first 4 bytes, which is the keccak256 of the normalized error signature,
|
||||||
|
followed by the encoded values, whose components are padded to 32 bytes
|
||||||
|
each, so the length of a revert will be congruent to ``4 mod 32``.
|
||||||
|
|
||||||
|
The one exception to all this is that ``revert(false)`` will return a
|
||||||
|
result or ``0x``.
|
||||||
|
|
||||||
|
|
||||||
|
_subsection: Event Data Representation
|
||||||
|
|
||||||
|
When an Event is emitted from a contract, there are two places data is
|
||||||
|
logged in a Log: the **topics** and the **data**.
|
||||||
|
|
||||||
|
An additonal fee is paid for each **topic**, but this affords a topic
|
||||||
|
to be indexed in a bloom filter within the block, which allows efficient
|
||||||
|
filtering.
|
||||||
|
|
||||||
|
The **topic hash** is always the first topic in a Log, which is the
|
||||||
|
keccak256 of the normalized event signature. This allows a specific
|
||||||
|
event to be efficiently filtered, finding the matching events in a block.
|
||||||
|
|
||||||
|
Each additional **indexed** parameter (i.e. parameters marked with
|
||||||
|
``indexed`` in the signautre) are placed in the topics as well, but may be
|
||||||
|
filtered to find matching values.
|
||||||
|
|
||||||
|
All non-indexed parameters are encoded and placed in the **data**. This
|
||||||
|
is cheaper and more compact, but does not allow filtering on these values.
|
||||||
|
|
||||||
|
For example, the event ``Transfer(address indexed from, address indexed to, uint value)``
|
||||||
|
would require 3 topics, which are the topic hash, the ``from`` address
|
||||||
|
and the ``to`` address and the data would contain 32 bytes, which is
|
||||||
|
the padded big-endian representation of ``value``. This allows for
|
||||||
|
efficient filtering by the event (i.e. ``Transfer``) as well as the ``from``
|
||||||
|
address and ``to`` address.
|
||||||
|
|
||||||
|
|
||||||
_subsection: Deployment
|
_subsection: Deployment
|
||||||
|
|
||||||
About initcode
|
When deploying a transaction, the data provided is treated as **initcode**,
|
||||||
|
which executes the data as normal EVM bytecode, which returns a sequence
|
||||||
|
of bytes, but instead of that sequence of bytes being treated as data that
|
||||||
|
result is instead the bytecode to install as the bytecode of the contract.
|
||||||
|
|
||||||
Another paragraph [[link-bip-39]].
|
The bytecode produced by Solidity is designed to have all constructor
|
||||||
|
parameters encoded normally and concatenated to the bytecode and provided
|
||||||
_heading: Foo?
|
as the ``data`` to a transaction with no ``to`` address.
|
||||||
|
|
||||||
Bar?
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
_section: Ethereum Basics @priority<99>
|
_section: Ethereum Basics @<docs-basics> @priority<99>
|
||||||
|
|
||||||
Prelude here...
|
This section aims to cover some of the basics for those interested
|
||||||
|
in a deeper understanding of the inner-workings of Ethereum.
|
||||||
|
|
||||||
_subsection: About stuff?
|
_subsection: Topics
|
||||||
|
|
||||||
Some info
|
- [Application Binary Interface](docs-abi)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
link-js-array [link-js-array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
|
link-js-array [link-js-array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
|
||||||
link-js-bigint [link-js-bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
|
link-js-bigint [link-js-bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
|
||||||
link-js-date [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)
|
link-js-date [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)
|
||||||
|
link-js-fetch [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
|
||||||
link-js-normalize [String.normalize](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize)
|
link-js-normalize [String.normalize](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize)
|
||||||
link-js-maxsafe [link-js-maxsafe](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER#Description)
|
link-js-maxsafe [link-js-maxsafe](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER#Description)
|
||||||
link-js-proxy [link-js-proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)
|
link-js-proxy [link-js-proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)
|
||||||
|
@ -12,6 +12,7 @@ link-infura [INFURA](https://infura.io)
|
|||||||
link-javascriptcore [JavaScriptCore](https://developer.apple.com/documentation/javascriptcore?language=objc)
|
link-javascriptcore [JavaScriptCore](https://developer.apple.com/documentation/javascriptcore?language=objc)
|
||||||
link-ledger [Ledger](https://www.ledger.com)
|
link-ledger [Ledger](https://www.ledger.com)
|
||||||
link-metamask [MetaMask](https://metamask.io/)
|
link-metamask [MetaMask](https://metamask.io/)
|
||||||
|
link-node [Node.js](https://nodejs.org/)
|
||||||
link-otto [Otto](https://github.com/robertkrimen/otto)
|
link-otto [Otto](https://github.com/robertkrimen/otto)
|
||||||
link-parity [Parity](https://www.parity.io)
|
link-parity [Parity](https://www.parity.io)
|
||||||
link-pocket [Pocket Network](https://pokt.network)
|
link-pocket [Pocket Network](https://pokt.network)
|
||||||
|
@ -43,6 +43,7 @@ link-namehash [namehash](https://docs.ens.domains/contract-api-reference/name-pr
|
|||||||
link-rlp [Recursive-Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/)
|
link-rlp [Recursive-Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/)
|
||||||
link-pbkdf2 [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2)
|
link-pbkdf2 [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2)
|
||||||
link-solc-abi [ABI Specification](https://docs.soliditylang.org/en/v0.8.19/abi-spec.html#formal-specification-of-the-encoding)
|
link-solc-abi [ABI Specification](https://docs.soliditylang.org/en/v0.8.19/abi-spec.html#formal-specification-of-the-encoding)
|
||||||
|
link-solc-jsonabi [ABI JSON Specification](https://docs.soliditylang.org/en/v0.8.19/abi-spec.html#json)
|
||||||
link-solc-errors [Solidity Custom Errors](https://docs.soliditylang.org/en/v0.8.4/abi-spec.html#errors)
|
link-solc-errors [Solidity Custom Errors](https://docs.soliditylang.org/en/v0.8.4/abi-spec.html#errors)
|
||||||
link-solc-events [Solidity Events](https://docs.soliditylang.org/en/v0.8.4/abi-spec.html#events)
|
link-solc-events [Solidity Events](https://docs.soliditylang.org/en/v0.8.4/abi-spec.html#events)
|
||||||
link-solc-output [solc standard output](https://solidity.readthedocs.io/en/v0.6.0/using-the-compiler.html#output-description)
|
link-solc-output [solc standard output](https://solidity.readthedocs.io/en/v0.6.0/using-the-compiler.html#output-description)
|
||||||
|
@ -121,8 +121,9 @@ function getBuiltinCallException(action: CallExceptionAction, tx: { to?: null |
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* About AbiCoder
|
* The **AbiCoder** is a low-level class responsible for encoding JavaScript
|
||||||
*/
|
* values into binary data and decoding binary data into JavaScript values.
|
||||||
|
*/
|
||||||
export class AbiCoder {
|
export class AbiCoder {
|
||||||
|
|
||||||
#getCoder(param: ParamType): Coder {
|
#getCoder(param: ParamType): Coder {
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* About frgaments...
|
* A fragment is a single item from an ABI, which may represent any of:
|
||||||
|
*
|
||||||
|
* - [Functions](FunctionFragment)
|
||||||
|
* - [Events](EventFragment)
|
||||||
|
* - [Constructors](ConstructorFragment)
|
||||||
|
* - Custom [Errors](ErrorFragment)
|
||||||
|
* - [Fallback or Receive](FallbackFragment) functions
|
||||||
*
|
*
|
||||||
* @_subsection api/abi/abi-coder:Fragments [about-fragments]
|
* @_subsection api/abi/abi-coder:Fragments [about-fragments]
|
||||||
*/
|
*/
|
||||||
@ -11,7 +17,7 @@ import {
|
|||||||
import { id } from "../hash/index.js";
|
import { id } from "../hash/index.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type description in a JSON API.
|
* A Type description in a [JSON ABI format](link-solc-jsonabi).
|
||||||
*/
|
*/
|
||||||
export interface JsonFragmentType {
|
export interface JsonFragmentType {
|
||||||
/**
|
/**
|
||||||
@ -41,7 +47,7 @@ export interface JsonFragmentType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fragment for a method, event or error in a JSON API.
|
* A fragment for a method, event or error in a [JSON ABI format](link-solc-jsonabi).
|
||||||
*/
|
*/
|
||||||
export interface JsonFragment {
|
export interface JsonFragment {
|
||||||
/**
|
/**
|
||||||
@ -92,19 +98,21 @@ export interface JsonFragment {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The format to serialize the output as.
|
* The format to serialize the output as.
|
||||||
|
*
|
||||||
|
* **``"sighash"``** - the bare formatting, used to compute the selector
|
||||||
|
* or topic hash; this format cannot be reversed (as it discards ``indexed``)
|
||||||
|
* so cannot by used to export an [[Interface]].
|
||||||
|
*
|
||||||
|
* **``"minimal"``** - Human-Readable ABI with minimal spacing and without
|
||||||
|
* names, so it is compact, but will result in Result objects that cannot
|
||||||
|
* be accessed by name.
|
||||||
|
*
|
||||||
|
* **``"full"``** - Full Human-Readable ABI, with readable spacing and names
|
||||||
|
* intact; this is generally the recommended format.
|
||||||
|
*
|
||||||
|
* **``"json"``** - The [JSON ABI format](link-solc-jsonabi).
|
||||||
*/
|
*/
|
||||||
export type FormatType =
|
export type FormatType = "sighash" | "minimal" | "full" | "json";
|
||||||
// Bare formatting, as is needed for computing a sighash of an event or function
|
|
||||||
"sighash" |
|
|
||||||
|
|
||||||
// Human-Readable with Minimal spacing and without names (compact human-readable)
|
|
||||||
"minimal" |
|
|
||||||
|
|
||||||
// Human-Readable with nice spacing, including all names
|
|
||||||
"full" |
|
|
||||||
|
|
||||||
// JSON-format a la Solidity
|
|
||||||
"json";
|
|
||||||
|
|
||||||
// [ "a", "b" ] => { "a": 1, "b": 1 }
|
// [ "a", "b" ] => { "a": 1, "b": 1 }
|
||||||
function setify(items: Array<string>): ReadonlySet<string> {
|
function setify(items: Array<string>): ReadonlySet<string> {
|
||||||
@ -513,7 +521,7 @@ const FunctionFragmentInternal = "_FunctionInternal";
|
|||||||
const StructFragmentInternal = "_StructInternal";
|
const StructFragmentInternal = "_StructInternal";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each input and output of a [[Fragment]] is an Array of **PAramType**.
|
* Each input and output of a [[Fragment]] is an Array of **ParamType**.
|
||||||
*/
|
*/
|
||||||
export class ParamType {
|
export class ParamType {
|
||||||
|
|
||||||
@ -642,16 +650,6 @@ export class ParamType {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns true if %%value%% is an Array type.
|
|
||||||
*
|
|
||||||
* This provides a type gaurd ensuring that the
|
|
||||||
* [[arrayChildren]] and [[arrayLength]] are non-null.
|
|
||||||
*/
|
|
||||||
//static isArray(value: any): value is { arrayChildren: ParamType, arrayLength: number } {
|
|
||||||
// return value && (value.baseType === "array")
|
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if %%this%% is an Array type.
|
* Returns true if %%this%% is an Array type.
|
||||||
*
|
*
|
||||||
@ -913,7 +911,7 @@ export abstract class Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string representation of this fragment.
|
* Returns a string representation of this fragment as %%format%%.
|
||||||
*/
|
*/
|
||||||
abstract format(format?: FormatType): string;
|
abstract format(format?: FormatType): string;
|
||||||
|
|
||||||
@ -1050,6 +1048,9 @@ export class ErrorFragment extends NamedFragment {
|
|||||||
return id(this.format("sighash")).substring(0, 10);
|
return id(this.format("sighash")).substring(0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this fragment as %%format%%.
|
||||||
|
*/
|
||||||
format(format?: FormatType): string {
|
format(format?: FormatType): string {
|
||||||
if (format == null) { format = "sighash"; }
|
if (format == null) { format = "sighash"; }
|
||||||
if (format === "json") {
|
if (format === "json") {
|
||||||
@ -1066,6 +1067,9 @@ export class ErrorFragment extends NamedFragment {
|
|||||||
return result.join(" ");
|
return result.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new **ErrorFragment** for %%obj%%.
|
||||||
|
*/
|
||||||
static from(obj: any): ErrorFragment {
|
static from(obj: any): ErrorFragment {
|
||||||
if (ErrorFragment.isFragment(obj)) { return obj; }
|
if (ErrorFragment.isFragment(obj)) { return obj; }
|
||||||
|
|
||||||
@ -1084,6 +1088,10 @@ export class ErrorFragment extends NamedFragment {
|
|||||||
obj.inputs ? obj.inputs.map(ParamType.from): [ ]);
|
obj.inputs ? obj.inputs.map(ParamType.from): [ ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``true`` and provides a type guard if %%value%% is an
|
||||||
|
* **ErrorFragment**.
|
||||||
|
*/
|
||||||
static isFragment(value: any): value is ErrorFragment {
|
static isFragment(value: any): value is ErrorFragment {
|
||||||
return (value && value[internal] === ErrorFragmentInternal);
|
return (value && value[internal] === ErrorFragmentInternal);
|
||||||
}
|
}
|
||||||
@ -1093,6 +1101,9 @@ export class ErrorFragment extends NamedFragment {
|
|||||||
* A Fragment which represents an Event.
|
* A Fragment which represents an Event.
|
||||||
*/
|
*/
|
||||||
export class EventFragment extends NamedFragment {
|
export class EventFragment extends NamedFragment {
|
||||||
|
/**
|
||||||
|
* Whether this event is anonymous.
|
||||||
|
*/
|
||||||
readonly anonymous!: boolean;
|
readonly anonymous!: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1111,6 +1122,9 @@ export class EventFragment extends NamedFragment {
|
|||||||
return id(this.format("sighash"));
|
return id(this.format("sighash"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this event as %%format%%.
|
||||||
|
*/
|
||||||
format(format?: FormatType): string {
|
format(format?: FormatType): string {
|
||||||
if (format == null) { format = "sighash"; }
|
if (format == null) { format = "sighash"; }
|
||||||
if (format === "json") {
|
if (format === "json") {
|
||||||
@ -1129,12 +1143,18 @@ export class EventFragment extends NamedFragment {
|
|||||||
return result.join(" ");
|
return result.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the topic hash for an event with %%name%% and %%params%%.
|
||||||
|
*/
|
||||||
static getTopicHash(name: string, params?: Array<any>): string {
|
static getTopicHash(name: string, params?: Array<any>): string {
|
||||||
params = (params || []).map((p) => ParamType.from(p));
|
params = (params || []).map((p) => ParamType.from(p));
|
||||||
const fragment = new EventFragment(_guard, name, params, false);
|
const fragment = new EventFragment(_guard, name, params, false);
|
||||||
return fragment.topicHash;
|
return fragment.topicHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new **EventFragment** for %%obj%%.
|
||||||
|
*/
|
||||||
static from(obj: any): EventFragment {
|
static from(obj: any): EventFragment {
|
||||||
if (EventFragment.isFragment(obj)) { return obj; }
|
if (EventFragment.isFragment(obj)) { return obj; }
|
||||||
|
|
||||||
@ -1154,6 +1174,10 @@ export class EventFragment extends NamedFragment {
|
|||||||
obj.inputs ? obj.inputs.map((p: any) => ParamType.from(p, true)): [ ], !!obj.anonymous);
|
obj.inputs ? obj.inputs.map((p: any) => ParamType.from(p, true)): [ ], !!obj.anonymous);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``true`` and provides a type guard if %%value%% is an
|
||||||
|
* **EventFragment**.
|
||||||
|
*/
|
||||||
static isFragment(value: any): value is EventFragment {
|
static isFragment(value: any): value is EventFragment {
|
||||||
return (value && value[internal] === EventFragmentInternal);
|
return (value && value[internal] === EventFragmentInternal);
|
||||||
}
|
}
|
||||||
@ -1163,7 +1187,15 @@ export class EventFragment extends NamedFragment {
|
|||||||
* A Fragment which represents a constructor.
|
* A Fragment which represents a constructor.
|
||||||
*/
|
*/
|
||||||
export class ConstructorFragment extends Fragment {
|
export class ConstructorFragment extends Fragment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the constructor can receive an endowment.
|
||||||
|
*/
|
||||||
readonly payable!: boolean;
|
readonly payable!: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The recommended gas limit for deployment or ``null``.
|
||||||
|
*/
|
||||||
readonly gas!: null | bigint;
|
readonly gas!: null | bigint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1175,6 +1207,9 @@ export class ConstructorFragment extends Fragment {
|
|||||||
defineProperties<ConstructorFragment>(this, { payable, gas });
|
defineProperties<ConstructorFragment>(this, { payable, gas });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this constructor as %%format%%.
|
||||||
|
*/
|
||||||
format(format?: FormatType): string {
|
format(format?: FormatType): string {
|
||||||
assert(format != null && format !== "sighash", "cannot format a constructor for sighash",
|
assert(format != null && format !== "sighash", "cannot format a constructor for sighash",
|
||||||
"UNSUPPORTED_OPERATION", { operation: "format(sighash)" });
|
"UNSUPPORTED_OPERATION", { operation: "format(sighash)" });
|
||||||
@ -1195,6 +1230,9 @@ export class ConstructorFragment extends Fragment {
|
|||||||
return result.join(" ");
|
return result.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new **ConstructorFragment** for %%obj%%.
|
||||||
|
*/
|
||||||
static from(obj: any): ConstructorFragment {
|
static from(obj: any): ConstructorFragment {
|
||||||
if (ConstructorFragment.isFragment(obj)) { return obj; }
|
if (ConstructorFragment.isFragment(obj)) { return obj; }
|
||||||
|
|
||||||
@ -1216,6 +1254,10 @@ export class ConstructorFragment extends Fragment {
|
|||||||
!!obj.payable, (obj.gas != null) ? obj.gas: null);
|
!!obj.payable, (obj.gas != null) ? obj.gas: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``true`` and provides a type guard if %%value%% is a
|
||||||
|
* **ConstructorFragment**.
|
||||||
|
*/
|
||||||
static isFragment(value: any): value is ConstructorFragment {
|
static isFragment(value: any): value is ConstructorFragment {
|
||||||
return (value && value[internal] === ConstructorFragmentInternal);
|
return (value && value[internal] === ConstructorFragmentInternal);
|
||||||
}
|
}
|
||||||
@ -1237,6 +1279,9 @@ export class FallbackFragment extends Fragment {
|
|||||||
defineProperties<FallbackFragment>(this, { payable });
|
defineProperties<FallbackFragment>(this, { payable });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this fallback as %%format%%.
|
||||||
|
*/
|
||||||
format(format?: FormatType): string {
|
format(format?: FormatType): string {
|
||||||
const type = ((this.inputs.length === 0) ? "receive": "fallback");
|
const type = ((this.inputs.length === 0) ? "receive": "fallback");
|
||||||
|
|
||||||
@ -1248,6 +1293,9 @@ export class FallbackFragment extends Fragment {
|
|||||||
return `${ type }()${ this.payable ? " payable": "" }`;
|
return `${ type }()${ this.payable ? " payable": "" }`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new **FallbackFragment** for %%obj%%.
|
||||||
|
*/
|
||||||
static from(obj: any): FallbackFragment {
|
static from(obj: any): FallbackFragment {
|
||||||
if (FallbackFragment.isFragment(obj)) { return obj; }
|
if (FallbackFragment.isFragment(obj)) { return obj; }
|
||||||
|
|
||||||
@ -1310,6 +1358,10 @@ export class FallbackFragment extends Fragment {
|
|||||||
assertArgument(false, "invalid fallback description", "obj", obj);
|
assertArgument(false, "invalid fallback description", "obj", obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``true`` and provides a type guard if %%value%% is a
|
||||||
|
* **FallbackFragment**.
|
||||||
|
*/
|
||||||
static isFragment(value: any): value is FallbackFragment {
|
static isFragment(value: any): value is FallbackFragment {
|
||||||
return (value && value[internal] === FallbackFragmentInternal);
|
return (value && value[internal] === FallbackFragmentInternal);
|
||||||
}
|
}
|
||||||
@ -1342,7 +1394,7 @@ export class FunctionFragment extends NamedFragment {
|
|||||||
readonly payable!: boolean;
|
readonly payable!: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount of gas to send when calling this function
|
* The recommended gas limit to send when calling this function.
|
||||||
*/
|
*/
|
||||||
readonly gas!: null | bigint;
|
readonly gas!: null | bigint;
|
||||||
|
|
||||||
@ -1365,6 +1417,9 @@ export class FunctionFragment extends NamedFragment {
|
|||||||
return id(this.format("sighash")).substring(0, 10);
|
return id(this.format("sighash")).substring(0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this function as %%format%%.
|
||||||
|
*/
|
||||||
format(format?: FormatType): string {
|
format(format?: FormatType): string {
|
||||||
if (format == null) { format = "sighash"; }
|
if (format == null) { format = "sighash"; }
|
||||||
if (format === "json") {
|
if (format === "json") {
|
||||||
@ -1401,12 +1456,18 @@ export class FunctionFragment extends NamedFragment {
|
|||||||
return result.join(" ");
|
return result.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the selector for a function with %%name%% and %%params%%.
|
||||||
|
*/
|
||||||
static getSelector(name: string, params?: Array<any>): string {
|
static getSelector(name: string, params?: Array<any>): string {
|
||||||
params = (params || []).map((p) => ParamType.from(p));
|
params = (params || []).map((p) => ParamType.from(p));
|
||||||
const fragment = new FunctionFragment(_guard, name, "view", params, [ ], null);
|
const fragment = new FunctionFragment(_guard, name, "view", params, [ ], null);
|
||||||
return fragment.selector;
|
return fragment.selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new **FunctionFragment** for %%obj%%.
|
||||||
|
*/
|
||||||
static from(obj: any): FunctionFragment {
|
static from(obj: any): FunctionFragment {
|
||||||
if (FunctionFragment.isFragment(obj)) { return obj; }
|
if (FunctionFragment.isFragment(obj)) { return obj; }
|
||||||
|
|
||||||
@ -1458,6 +1519,10 @@ export class FunctionFragment extends NamedFragment {
|
|||||||
(obj.gas != null) ? obj.gas: null);
|
(obj.gas != null) ? obj.gas: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``true`` and provides a type guard if %%value%% is a
|
||||||
|
* **FunctionFragment**.
|
||||||
|
*/
|
||||||
static isFragment(value: any): value is FunctionFragment {
|
static isFragment(value: any): value is FunctionFragment {
|
||||||
return (value && value[internal] === FunctionFragmentInternal);
|
return (value && value[internal] === FunctionFragmentInternal);
|
||||||
}
|
}
|
||||||
@ -1476,10 +1541,16 @@ export class StructFragment extends NamedFragment {
|
|||||||
Object.defineProperty(this, internal, { value: StructFragmentInternal });
|
Object.defineProperty(this, internal, { value: StructFragmentInternal });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this struct as %%format%%.
|
||||||
|
*/
|
||||||
format(): string {
|
format(): string {
|
||||||
throw new Error("@TODO");
|
throw new Error("@TODO");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new **StructFragment** for %%obj%%.
|
||||||
|
*/
|
||||||
static from(obj: any): StructFragment {
|
static from(obj: any): StructFragment {
|
||||||
if (typeof(obj) === "string") {
|
if (typeof(obj) === "string") {
|
||||||
return StructFragment.from(lex(obj));
|
return StructFragment.from(lex(obj));
|
||||||
@ -1494,6 +1565,11 @@ export class StructFragment extends NamedFragment {
|
|||||||
return new StructFragment(_guard, obj.name, obj.inputs ? obj.inputs.map(ParamType.from): [ ]);
|
return new StructFragment(_guard, obj.name, obj.inputs ? obj.inputs.map(ParamType.from): [ ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @TODO: fix this return type
|
||||||
|
/**
|
||||||
|
* Returns ``true`` and provides a type guard if %%value%% is a
|
||||||
|
* **StructFragment**.
|
||||||
|
*/
|
||||||
static isFragment(value: any): value is FunctionFragment {
|
static isFragment(value: any): value is FunctionFragment {
|
||||||
return (value && value[internal] === StructFragmentInternal);
|
return (value && value[internal] === StructFragmentInternal);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* Explain about ABI here...
|
* The Application Binary Interface (ABI) describes how method input
|
||||||
|
* parameters should be encoded, their results decoded, and how to
|
||||||
|
* decode events and errors.
|
||||||
|
*
|
||||||
|
* See [About ABIs](docs-abi) for more details how they are used.
|
||||||
*
|
*
|
||||||
* @_section api/abi:Application Binary Interface [about-abi]
|
* @_section api/abi:Application Binary Interface [about-abi]
|
||||||
* @_navTitle: ABI
|
* @_navTitle: ABI
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* About Interface
|
* The Interface class is a low-level class that accepts an
|
||||||
|
* ABI and provides all the necessary functionality to encode
|
||||||
|
* and decode paramaters to and results from methods, events
|
||||||
|
* and errors.
|
||||||
|
*
|
||||||
|
* It also provides several convenience methods to automatically
|
||||||
|
* search and find matching transactions and events to parse them.
|
||||||
*
|
*
|
||||||
* @_subsection api/abi:Interfaces [interfaces]
|
* @_subsection api/abi:Interfaces [interfaces]
|
||||||
*/
|
*/
|
||||||
@ -27,13 +33,39 @@ import type { JsonFragment } from "./fragments.js";
|
|||||||
|
|
||||||
export { checkResultErrors, Result };
|
export { checkResultErrors, Result };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When using the [[Interface-parseLog]] to automatically match a Log to its event
|
||||||
|
* for parsing, a **LogDescription** is returned.
|
||||||
|
*/
|
||||||
export class LogDescription {
|
export class LogDescription {
|
||||||
|
/**
|
||||||
|
* The matching fragment for the ``topic0``.
|
||||||
|
*/
|
||||||
readonly fragment!: EventFragment;
|
readonly fragment!: EventFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the Event.
|
||||||
|
*/
|
||||||
readonly name!: string;
|
readonly name!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The full Event signature.
|
||||||
|
*/
|
||||||
readonly signature!: string;
|
readonly signature!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The topic hash for the Event.
|
||||||
|
*/
|
||||||
readonly topic!: string;
|
readonly topic!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arguments passed into the Event with ``emit``.
|
||||||
|
*/
|
||||||
readonly args!: Result
|
readonly args!: Result
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(fragment: EventFragment, topic: string, args: Result) {
|
constructor(fragment: EventFragment, topic: string, args: Result) {
|
||||||
const name = fragment.name, signature = fragment.format();
|
const name = fragment.name, signature = fragment.format();
|
||||||
defineProperties<LogDescription>(this, {
|
defineProperties<LogDescription>(this, {
|
||||||
@ -42,14 +74,45 @@ export class LogDescription {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When using the [[Interface-parseTransaction]] to automatically match
|
||||||
|
* a transaction data to its function for parsing,
|
||||||
|
* a **TransactionDescription** is returned.
|
||||||
|
*/
|
||||||
export class TransactionDescription {
|
export class TransactionDescription {
|
||||||
|
/**
|
||||||
|
* The matching fragment from the transaction ``data``.
|
||||||
|
*/
|
||||||
readonly fragment!: FunctionFragment;
|
readonly fragment!: FunctionFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the Function from the transaction ``data``.
|
||||||
|
*/
|
||||||
readonly name!: string;
|
readonly name!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arguments passed to the Function from the transaction ``data``.
|
||||||
|
*/
|
||||||
readonly args!: Result;
|
readonly args!: Result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The full Function signature from the transaction ``data``.
|
||||||
|
*/
|
||||||
readonly signature!: string;
|
readonly signature!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The selector for the Function from the transaction ``data``.
|
||||||
|
*/
|
||||||
readonly selector!: string;
|
readonly selector!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ``value`` (in wei) from the transaction.
|
||||||
|
*/
|
||||||
readonly value!: bigint;
|
readonly value!: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(fragment: FunctionFragment, selector: string, args: Result, value: bigint) {
|
constructor(fragment: FunctionFragment, selector: string, args: Result, value: bigint) {
|
||||||
const name = fragment.name, signature = fragment.format();
|
const name = fragment.name, signature = fragment.format();
|
||||||
defineProperties<TransactionDescription>(this, {
|
defineProperties<TransactionDescription>(this, {
|
||||||
@ -58,13 +121,39 @@ export class TransactionDescription {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When using the [[Interface-parseError]] to automatically match an
|
||||||
|
* error for a call result for parsing, an **ErrorDescription** is returned.
|
||||||
|
*/
|
||||||
export class ErrorDescription {
|
export class ErrorDescription {
|
||||||
|
/**
|
||||||
|
* The matching fragment.
|
||||||
|
*/
|
||||||
readonly fragment!: ErrorFragment;
|
readonly fragment!: ErrorFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the Error.
|
||||||
|
*/
|
||||||
readonly name!: string;
|
readonly name!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arguments passed to the Error with ``revert``.
|
||||||
|
*/
|
||||||
readonly args!: Result;
|
readonly args!: Result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The full Error signature.
|
||||||
|
*/
|
||||||
readonly signature!: string;
|
readonly signature!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The selector for the Error.
|
||||||
|
*/
|
||||||
readonly selector!: string;
|
readonly selector!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(fragment: ErrorFragment, selector: string, args: Result) {
|
constructor(fragment: ErrorFragment, selector: string, args: Result) {
|
||||||
const name = fragment.name, signature = fragment.format();
|
const name = fragment.name, signature = fragment.format();
|
||||||
defineProperties<ErrorDescription>(this, {
|
defineProperties<ErrorDescription>(this, {
|
||||||
@ -73,14 +162,35 @@ export class ErrorDescription {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An **Indexed** is used as a value when a value that does not
|
||||||
|
* fit within a topic (i.e. not a fixed-length, 32-byte type). It
|
||||||
|
* is the ``keccak256`` of the value, and used for types such as
|
||||||
|
* arrays, tuples, bytes and strings.
|
||||||
|
*/
|
||||||
export class Indexed {
|
export class Indexed {
|
||||||
|
/**
|
||||||
|
* The ``keccak256`` of the value logged.
|
||||||
|
*/
|
||||||
readonly hash!: null | string;
|
readonly hash!: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
readonly _isIndexed!: boolean;
|
readonly _isIndexed!: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``true`` if %%value%% is an **Indexed**.
|
||||||
|
*
|
||||||
|
* This provides a Type Guard for property access.
|
||||||
|
*/
|
||||||
static isIndexed(value: any): value is Indexed {
|
static isIndexed(value: any): value is Indexed {
|
||||||
return !!(value && value._isIndexed);
|
return !!(value && value._isIndexed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(hash: null | string) {
|
constructor(hash: null | string) {
|
||||||
defineProperties<Indexed>(this, { hash, _isIndexed: true })
|
defineProperties<Indexed>(this, { hash, _isIndexed: true })
|
||||||
}
|
}
|
||||||
@ -152,7 +262,23 @@ function checkNames(fragment: Fragment, type: "input" | "output", params: Array<
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @TODO
|
* An **InterfaceAbi** may be any supported ABI format.
|
||||||
|
*
|
||||||
|
* A string is expected to be a JSON string, which will be parsed
|
||||||
|
* using ``JSON.parse``. This means that the value **must** be a valid
|
||||||
|
* JSON string, with no stray commas, etc.
|
||||||
|
*
|
||||||
|
* An array may contain any combination of:
|
||||||
|
* - Human-Readable fragments
|
||||||
|
* - Parsed JSON fragment
|
||||||
|
* - [[Fragment]] instances
|
||||||
|
*
|
||||||
|
* A **Human-Readable Fragment** is a string which resembles a Solidity
|
||||||
|
* signature and is introduced in [this blog entry](link-ricmoo-humanreadableabi).
|
||||||
|
* For example, ``function balanceOf(address) view returns (uint)``.
|
||||||
|
*
|
||||||
|
* A **Parsed JSON Fragment** is a JavaScript Object desribed in the
|
||||||
|
* [Solidity documentation](link-solc-jsonabi).
|
||||||
*/
|
*/
|
||||||
export type InterfaceAbi = string | ReadonlyArray<Fragment | JsonFragment | string>;
|
export type InterfaceAbi = string | ReadonlyArray<Fragment | JsonFragment | string>;
|
||||||
|
|
||||||
|
@ -38,6 +38,10 @@ function b(value: BytesLike, size?: number): Typed {
|
|||||||
return new Typed(_gaurd, `bytes${ (size) ? size: "" }`, value, { size });
|
return new Typed(_gaurd, `bytes${ (size) ? size: "" }`, value, { size });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @TODO: Remove this in v7, it was replaced by TypedBigInt
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
export interface TypedNumber extends Typed {
|
export interface TypedNumber extends Typed {
|
||||||
value: number;
|
value: number;
|
||||||
defaultValue(): number;
|
defaultValue(): number;
|
||||||
@ -45,33 +49,88 @@ export interface TypedNumber extends Typed {
|
|||||||
maxValue(): number;
|
maxValue(): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **Typed** that represents a numeric value.
|
||||||
|
*/
|
||||||
export interface TypedBigInt extends Typed {
|
export interface TypedBigInt extends Typed {
|
||||||
|
/**
|
||||||
|
* The value.
|
||||||
|
*/
|
||||||
value: bigint;
|
value: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default value for all numeric types is ``0``.
|
||||||
|
*/
|
||||||
defaultValue(): bigint;
|
defaultValue(): bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum value for this type, accounting for bit-width and signed-ness.
|
||||||
|
*/
|
||||||
minValue(): bigint;
|
minValue(): bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum value for this type, accounting for bit-width.
|
||||||
|
*/
|
||||||
maxValue(): bigint;
|
maxValue(): bigint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **Typed** that represents a binary sequence of data as bytes.
|
||||||
|
*/
|
||||||
export interface TypedData extends Typed {
|
export interface TypedData extends Typed {
|
||||||
|
/**
|
||||||
|
* The value.
|
||||||
|
*/
|
||||||
value: string;
|
value: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default value for this type.
|
||||||
|
*/
|
||||||
defaultValue(): string;
|
defaultValue(): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **Typed** that represents a UTF-8 sequence of bytes.
|
||||||
|
*/
|
||||||
export interface TypedString extends Typed {
|
export interface TypedString extends Typed {
|
||||||
|
/**
|
||||||
|
* The value.
|
||||||
|
*/
|
||||||
value: string;
|
value: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default value for the string type is the empty string (i.e. ``""``).
|
||||||
|
*/
|
||||||
defaultValue(): string;
|
defaultValue(): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _typedSymbol = Symbol.for("_ethers_typed");
|
const _typedSymbol = Symbol.for("_ethers_typed");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The **Typed** class to wrap values providing explicit type information.
|
||||||
|
*/
|
||||||
export class Typed {
|
export class Typed {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type, as a Solidity-compatible type.
|
||||||
|
*/
|
||||||
readonly type!: string;
|
readonly type!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual value.
|
||||||
|
*/
|
||||||
readonly value!: any;
|
readonly value!: any;
|
||||||
|
|
||||||
readonly #options: any;
|
readonly #options: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
readonly _typedSymbol!: Symbol;
|
readonly _typedSymbol!: Symbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(gaurd: any, type: string, value: any, options?: any) {
|
constructor(gaurd: any, type: string, value: any, options?: any) {
|
||||||
if (options == null) { options = null; }
|
if (options == null) { options = null; }
|
||||||
assertPrivate(_gaurd, gaurd, "Typed");
|
assertPrivate(_gaurd, gaurd, "Typed");
|
||||||
@ -82,6 +141,9 @@ export class Typed {
|
|||||||
this.format();
|
this.format();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the type as a Human-Readable type.
|
||||||
|
*/
|
||||||
format(): string {
|
format(): string {
|
||||||
if (this.type === "array") {
|
if (this.type === "array") {
|
||||||
throw new Error("");
|
throw new Error("");
|
||||||
@ -94,30 +156,51 @@ export class Typed {
|
|||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default value returned by this type.
|
||||||
|
*/
|
||||||
defaultValue(): string | number | bigint | Result {
|
defaultValue(): string | number | bigint | Result {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum value for numeric types.
|
||||||
|
*/
|
||||||
minValue(): string | number | bigint {
|
minValue(): string | number | bigint {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum value for numeric types.
|
||||||
|
*/
|
||||||
maxValue(): string | number | bigint {
|
maxValue(): string | number | bigint {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``true`` and provides a type guard is this is a [[TypedBigInt]].
|
||||||
|
*/
|
||||||
isBigInt(): this is TypedBigInt {
|
isBigInt(): this is TypedBigInt {
|
||||||
return !!(this.type.match(/^u?int[0-9]+$/));
|
return !!(this.type.match(/^u?int[0-9]+$/));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``true`` and provides a type guard is this is a [[TypedData]].
|
||||||
|
*/
|
||||||
isData(): this is TypedData {
|
isData(): this is TypedData {
|
||||||
return this.type.startsWith("bytes");
|
return this.type.startsWith("bytes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``true`` and provides a type guard is this is a [[TypedString]].
|
||||||
|
*/
|
||||||
isString(): this is TypedString {
|
isString(): this is TypedString {
|
||||||
return (this.type === "string");
|
return (this.type === "string");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tuple name, if this is a tuple. Throws otherwise.
|
||||||
|
*/
|
||||||
get tupleName(): null | string {
|
get tupleName(): null | string {
|
||||||
if (this.type !== "tuple") { throw TypeError("not a tuple"); }
|
if (this.type !== "tuple") { throw TypeError("not a tuple"); }
|
||||||
return this.#options;
|
return this.#options;
|
||||||
@ -127,6 +210,12 @@ export class Typed {
|
|||||||
// - `null` indicates the length is unforced, it could be dynamic
|
// - `null` indicates the length is unforced, it could be dynamic
|
||||||
// - `-1` indicates the length is dynamic
|
// - `-1` indicates the length is dynamic
|
||||||
// - any other value indicates it is a static array and is its length
|
// - any other value indicates it is a static array and is its length
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the length of the array type or ``-1`` if it is dynamic.
|
||||||
|
*
|
||||||
|
* Throws if the type is not an array.
|
||||||
|
*/
|
||||||
get arrayLength(): null | number {
|
get arrayLength(): null | number {
|
||||||
if (this.type !== "array") { throw TypeError("not an array"); }
|
if (this.type !== "array") { throw TypeError("not an array"); }
|
||||||
if (this.#options === true) { return -1; }
|
if (this.#options === true) { return -1; }
|
||||||
@ -134,126 +223,546 @@ export class Typed {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new **Typed** of %%type%% with the %%value%%.
|
||||||
|
*/
|
||||||
static from(type: string, value: any): Typed {
|
static from(type: string, value: any): Typed {
|
||||||
return new Typed(_gaurd, type, value);
|
return new Typed(_gaurd, type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint8`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint8(v: BigNumberish): Typed { return n(v, 8); }
|
static uint8(v: BigNumberish): Typed { return n(v, 8); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint16`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint16(v: BigNumberish): Typed { return n(v, 16); }
|
static uint16(v: BigNumberish): Typed { return n(v, 16); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint24`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint24(v: BigNumberish): Typed { return n(v, 24); }
|
static uint24(v: BigNumberish): Typed { return n(v, 24); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint32`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint32(v: BigNumberish): Typed { return n(v, 32); }
|
static uint32(v: BigNumberish): Typed { return n(v, 32); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint40`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint40(v: BigNumberish): Typed { return n(v, 40); }
|
static uint40(v: BigNumberish): Typed { return n(v, 40); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint48`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint48(v: BigNumberish): Typed { return n(v, 48); }
|
static uint48(v: BigNumberish): Typed { return n(v, 48); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint56`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint56(v: BigNumberish): Typed { return n(v, 56); }
|
static uint56(v: BigNumberish): Typed { return n(v, 56); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint64`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint64(v: BigNumberish): Typed { return n(v, 64); }
|
static uint64(v: BigNumberish): Typed { return n(v, 64); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint72`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint72(v: BigNumberish): Typed { return n(v, 72); }
|
static uint72(v: BigNumberish): Typed { return n(v, 72); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint80`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint80(v: BigNumberish): Typed { return n(v, 80); }
|
static uint80(v: BigNumberish): Typed { return n(v, 80); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint88`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint88(v: BigNumberish): Typed { return n(v, 88); }
|
static uint88(v: BigNumberish): Typed { return n(v, 88); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint96`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint96(v: BigNumberish): Typed { return n(v, 96); }
|
static uint96(v: BigNumberish): Typed { return n(v, 96); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint104`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint104(v: BigNumberish): Typed { return n(v, 104); }
|
static uint104(v: BigNumberish): Typed { return n(v, 104); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint112`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint112(v: BigNumberish): Typed { return n(v, 112); }
|
static uint112(v: BigNumberish): Typed { return n(v, 112); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint120`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint120(v: BigNumberish): Typed { return n(v, 120); }
|
static uint120(v: BigNumberish): Typed { return n(v, 120); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint128`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint128(v: BigNumberish): Typed { return n(v, 128); }
|
static uint128(v: BigNumberish): Typed { return n(v, 128); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint136`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint136(v: BigNumberish): Typed { return n(v, 136); }
|
static uint136(v: BigNumberish): Typed { return n(v, 136); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint144`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint144(v: BigNumberish): Typed { return n(v, 144); }
|
static uint144(v: BigNumberish): Typed { return n(v, 144); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint152`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint152(v: BigNumberish): Typed { return n(v, 152); }
|
static uint152(v: BigNumberish): Typed { return n(v, 152); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint160`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint160(v: BigNumberish): Typed { return n(v, 160); }
|
static uint160(v: BigNumberish): Typed { return n(v, 160); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint168`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint168(v: BigNumberish): Typed { return n(v, 168); }
|
static uint168(v: BigNumberish): Typed { return n(v, 168); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint176`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint176(v: BigNumberish): Typed { return n(v, 176); }
|
static uint176(v: BigNumberish): Typed { return n(v, 176); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint184`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint184(v: BigNumberish): Typed { return n(v, 184); }
|
static uint184(v: BigNumberish): Typed { return n(v, 184); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint192`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint192(v: BigNumberish): Typed { return n(v, 192); }
|
static uint192(v: BigNumberish): Typed { return n(v, 192); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint200`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint200(v: BigNumberish): Typed { return n(v, 200); }
|
static uint200(v: BigNumberish): Typed { return n(v, 200); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint208`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint208(v: BigNumberish): Typed { return n(v, 208); }
|
static uint208(v: BigNumberish): Typed { return n(v, 208); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint216`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint216(v: BigNumberish): Typed { return n(v, 216); }
|
static uint216(v: BigNumberish): Typed { return n(v, 216); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint224`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint224(v: BigNumberish): Typed { return n(v, 224); }
|
static uint224(v: BigNumberish): Typed { return n(v, 224); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint232`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint232(v: BigNumberish): Typed { return n(v, 232); }
|
static uint232(v: BigNumberish): Typed { return n(v, 232); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint240`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint240(v: BigNumberish): Typed { return n(v, 240); }
|
static uint240(v: BigNumberish): Typed { return n(v, 240); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint248`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint248(v: BigNumberish): Typed { return n(v, 248); }
|
static uint248(v: BigNumberish): Typed { return n(v, 248); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint256`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint256(v: BigNumberish): Typed { return n(v, 256); }
|
static uint256(v: BigNumberish): Typed { return n(v, 256); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint256`` type for %%v%%.
|
||||||
|
*/
|
||||||
static uint(v: BigNumberish): Typed { return n(v, 256); }
|
static uint(v: BigNumberish): Typed { return n(v, 256); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int8`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int8(v: BigNumberish): Typed { return n(v, -8); }
|
static int8(v: BigNumberish): Typed { return n(v, -8); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int16`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int16(v: BigNumberish): Typed { return n(v, -16); }
|
static int16(v: BigNumberish): Typed { return n(v, -16); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int24`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int24(v: BigNumberish): Typed { return n(v, -24); }
|
static int24(v: BigNumberish): Typed { return n(v, -24); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int32`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int32(v: BigNumberish): Typed { return n(v, -32); }
|
static int32(v: BigNumberish): Typed { return n(v, -32); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int40`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int40(v: BigNumberish): Typed { return n(v, -40); }
|
static int40(v: BigNumberish): Typed { return n(v, -40); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int48`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int48(v: BigNumberish): Typed { return n(v, -48); }
|
static int48(v: BigNumberish): Typed { return n(v, -48); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int56`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int56(v: BigNumberish): Typed { return n(v, -56); }
|
static int56(v: BigNumberish): Typed { return n(v, -56); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int64`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int64(v: BigNumberish): Typed { return n(v, -64); }
|
static int64(v: BigNumberish): Typed { return n(v, -64); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int72`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int72(v: BigNumberish): Typed { return n(v, -72); }
|
static int72(v: BigNumberish): Typed { return n(v, -72); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int80`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int80(v: BigNumberish): Typed { return n(v, -80); }
|
static int80(v: BigNumberish): Typed { return n(v, -80); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int88`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int88(v: BigNumberish): Typed { return n(v, -88); }
|
static int88(v: BigNumberish): Typed { return n(v, -88); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int96`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int96(v: BigNumberish): Typed { return n(v, -96); }
|
static int96(v: BigNumberish): Typed { return n(v, -96); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int104`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int104(v: BigNumberish): Typed { return n(v, -104); }
|
static int104(v: BigNumberish): Typed { return n(v, -104); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int112`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int112(v: BigNumberish): Typed { return n(v, -112); }
|
static int112(v: BigNumberish): Typed { return n(v, -112); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int120`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int120(v: BigNumberish): Typed { return n(v, -120); }
|
static int120(v: BigNumberish): Typed { return n(v, -120); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int128`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int128(v: BigNumberish): Typed { return n(v, -128); }
|
static int128(v: BigNumberish): Typed { return n(v, -128); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int136`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int136(v: BigNumberish): Typed { return n(v, -136); }
|
static int136(v: BigNumberish): Typed { return n(v, -136); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int144`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int144(v: BigNumberish): Typed { return n(v, -144); }
|
static int144(v: BigNumberish): Typed { return n(v, -144); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int52`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int152(v: BigNumberish): Typed { return n(v, -152); }
|
static int152(v: BigNumberish): Typed { return n(v, -152); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int160`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int160(v: BigNumberish): Typed { return n(v, -160); }
|
static int160(v: BigNumberish): Typed { return n(v, -160); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int168`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int168(v: BigNumberish): Typed { return n(v, -168); }
|
static int168(v: BigNumberish): Typed { return n(v, -168); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int176`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int176(v: BigNumberish): Typed { return n(v, -176); }
|
static int176(v: BigNumberish): Typed { return n(v, -176); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int184`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int184(v: BigNumberish): Typed { return n(v, -184); }
|
static int184(v: BigNumberish): Typed { return n(v, -184); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int92`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int192(v: BigNumberish): Typed { return n(v, -192); }
|
static int192(v: BigNumberish): Typed { return n(v, -192); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int200`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int200(v: BigNumberish): Typed { return n(v, -200); }
|
static int200(v: BigNumberish): Typed { return n(v, -200); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int208`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int208(v: BigNumberish): Typed { return n(v, -208); }
|
static int208(v: BigNumberish): Typed { return n(v, -208); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int216`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int216(v: BigNumberish): Typed { return n(v, -216); }
|
static int216(v: BigNumberish): Typed { return n(v, -216); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int224`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int224(v: BigNumberish): Typed { return n(v, -224); }
|
static int224(v: BigNumberish): Typed { return n(v, -224); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int232`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int232(v: BigNumberish): Typed { return n(v, -232); }
|
static int232(v: BigNumberish): Typed { return n(v, -232); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int240`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int240(v: BigNumberish): Typed { return n(v, -240); }
|
static int240(v: BigNumberish): Typed { return n(v, -240); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int248`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int248(v: BigNumberish): Typed { return n(v, -248); }
|
static int248(v: BigNumberish): Typed { return n(v, -248); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int256`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int256(v: BigNumberish): Typed { return n(v, -256); }
|
static int256(v: BigNumberish): Typed { return n(v, -256); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``int256`` type for %%v%%.
|
||||||
|
*/
|
||||||
static int(v: BigNumberish): Typed { return n(v, -256); }
|
static int(v: BigNumberish): Typed { return n(v, -256); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes1`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes1(v: BytesLike): Typed { return b(v, 1); }
|
static bytes1(v: BytesLike): Typed { return b(v, 1); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes2`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes2(v: BytesLike): Typed { return b(v, 2); }
|
static bytes2(v: BytesLike): Typed { return b(v, 2); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes3`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes3(v: BytesLike): Typed { return b(v, 3); }
|
static bytes3(v: BytesLike): Typed { return b(v, 3); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes4`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes4(v: BytesLike): Typed { return b(v, 4); }
|
static bytes4(v: BytesLike): Typed { return b(v, 4); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes5`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes5(v: BytesLike): Typed { return b(v, 5); }
|
static bytes5(v: BytesLike): Typed { return b(v, 5); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes6`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes6(v: BytesLike): Typed { return b(v, 6); }
|
static bytes6(v: BytesLike): Typed { return b(v, 6); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes7`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes7(v: BytesLike): Typed { return b(v, 7); }
|
static bytes7(v: BytesLike): Typed { return b(v, 7); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes8`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes8(v: BytesLike): Typed { return b(v, 8); }
|
static bytes8(v: BytesLike): Typed { return b(v, 8); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes9`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes9(v: BytesLike): Typed { return b(v, 9); }
|
static bytes9(v: BytesLike): Typed { return b(v, 9); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes10`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes10(v: BytesLike): Typed { return b(v, 10); }
|
static bytes10(v: BytesLike): Typed { return b(v, 10); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes11`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes11(v: BytesLike): Typed { return b(v, 11); }
|
static bytes11(v: BytesLike): Typed { return b(v, 11); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes12`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes12(v: BytesLike): Typed { return b(v, 12); }
|
static bytes12(v: BytesLike): Typed { return b(v, 12); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes13`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes13(v: BytesLike): Typed { return b(v, 13); }
|
static bytes13(v: BytesLike): Typed { return b(v, 13); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes14`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes14(v: BytesLike): Typed { return b(v, 14); }
|
static bytes14(v: BytesLike): Typed { return b(v, 14); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes15`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes15(v: BytesLike): Typed { return b(v, 15); }
|
static bytes15(v: BytesLike): Typed { return b(v, 15); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes16`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes16(v: BytesLike): Typed { return b(v, 16); }
|
static bytes16(v: BytesLike): Typed { return b(v, 16); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes17`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes17(v: BytesLike): Typed { return b(v, 17); }
|
static bytes17(v: BytesLike): Typed { return b(v, 17); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes18`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes18(v: BytesLike): Typed { return b(v, 18); }
|
static bytes18(v: BytesLike): Typed { return b(v, 18); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes19`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes19(v: BytesLike): Typed { return b(v, 19); }
|
static bytes19(v: BytesLike): Typed { return b(v, 19); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes20`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes20(v: BytesLike): Typed { return b(v, 20); }
|
static bytes20(v: BytesLike): Typed { return b(v, 20); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes21`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes21(v: BytesLike): Typed { return b(v, 21); }
|
static bytes21(v: BytesLike): Typed { return b(v, 21); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes22`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes22(v: BytesLike): Typed { return b(v, 22); }
|
static bytes22(v: BytesLike): Typed { return b(v, 22); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes23`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes23(v: BytesLike): Typed { return b(v, 23); }
|
static bytes23(v: BytesLike): Typed { return b(v, 23); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes24`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes24(v: BytesLike): Typed { return b(v, 24); }
|
static bytes24(v: BytesLike): Typed { return b(v, 24); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes25`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes25(v: BytesLike): Typed { return b(v, 25); }
|
static bytes25(v: BytesLike): Typed { return b(v, 25); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes26`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes26(v: BytesLike): Typed { return b(v, 26); }
|
static bytes26(v: BytesLike): Typed { return b(v, 26); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes27`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes27(v: BytesLike): Typed { return b(v, 27); }
|
static bytes27(v: BytesLike): Typed { return b(v, 27); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes28`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes28(v: BytesLike): Typed { return b(v, 28); }
|
static bytes28(v: BytesLike): Typed { return b(v, 28); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes29`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes29(v: BytesLike): Typed { return b(v, 29); }
|
static bytes29(v: BytesLike): Typed { return b(v, 29); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes30`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes30(v: BytesLike): Typed { return b(v, 30); }
|
static bytes30(v: BytesLike): Typed { return b(v, 30); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes31`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes31(v: BytesLike): Typed { return b(v, 31); }
|
static bytes31(v: BytesLike): Typed { return b(v, 31); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes32`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes32(v: BytesLike): Typed { return b(v, 32); }
|
static bytes32(v: BytesLike): Typed { return b(v, 32); }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``address`` type for %%v%%.
|
||||||
|
*/
|
||||||
static address(v: string | Addressable): Typed { return new Typed(_gaurd, "address", v); }
|
static address(v: string | Addressable): Typed { return new Typed(_gaurd, "address", v); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bool`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bool(v: any): Typed { return new Typed(_gaurd, "bool", !!v); }
|
static bool(v: any): Typed { return new Typed(_gaurd, "bool", !!v); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``bytes`` type for %%v%%.
|
||||||
|
*/
|
||||||
static bytes(v: BytesLike): Typed { return new Typed(_gaurd, "bytes", v); }
|
static bytes(v: BytesLike): Typed { return new Typed(_gaurd, "bytes", v); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``string`` type for %%v%%.
|
||||||
|
*/
|
||||||
static string(v: string): Typed { return new Typed(_gaurd, "string", v); }
|
static string(v: string): Typed { return new Typed(_gaurd, "string", v); }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``array`` type for %%v%%, allowing %%dynamic%% length.
|
||||||
|
*/
|
||||||
static array(v: Array<any | Typed>, dynamic?: null | boolean): Typed {
|
static array(v: Array<any | Typed>, dynamic?: null | boolean): Typed {
|
||||||
throw new Error("not implemented yet");
|
throw new Error("not implemented yet");
|
||||||
return new Typed(_gaurd, "array", v, dynamic);
|
return new Typed(_gaurd, "array", v, dynamic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``tuple`` type for %%v%%, with the optional %%name%%.
|
||||||
|
*/
|
||||||
static tuple(v: Array<any | Typed> | Record<string, any | Typed>, name?: string): Typed {
|
static tuple(v: Array<any | Typed> | Record<string, any | Typed>, name?: string): Typed {
|
||||||
throw new Error("not implemented yet");
|
throw new Error("not implemented yet");
|
||||||
return new Typed(_gaurd, "tuple", v, name);
|
return new Typed(_gaurd, "tuple", v, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new ``uint8`` type for %%v%%.
|
||||||
|
*/
|
||||||
static overrides(v: Record<string, any>): Typed {
|
static overrides(v: Record<string, any>): Typed {
|
||||||
return new Typed(_gaurd, "overrides", Object.assign({ }, v));
|
return new Typed(_gaurd, "overrides", Object.assign({ }, v));
|
||||||
}
|
}
|
||||||
|
@ -608,16 +608,49 @@ async function emit(contract: BaseContract, event: ContractEventName, args: Arra
|
|||||||
|
|
||||||
const passProperties = [ "then" ];
|
const passProperties = [ "then" ];
|
||||||
export class BaseContract implements Addressable, EventEmitterable<ContractEventName> {
|
export class BaseContract implements Addressable, EventEmitterable<ContractEventName> {
|
||||||
|
/**
|
||||||
|
* The target to connect to.
|
||||||
|
*
|
||||||
|
* This can be an address, ENS name or any [[Addressable]], such as
|
||||||
|
* another contract. To get the resovled address, use the ``getAddress``
|
||||||
|
* method.
|
||||||
|
*/
|
||||||
readonly target!: string | Addressable;
|
readonly target!: string | Addressable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The contract Interface.
|
||||||
|
*/
|
||||||
readonly interface!: Interface;
|
readonly interface!: Interface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connected runner. This is generally a [[Provider]] or a
|
||||||
|
* [[Signer]], which dictates what operations are supported.
|
||||||
|
*
|
||||||
|
* For example, a **Contract** connected to a [[Provider]] may
|
||||||
|
* only execute read-only operations.
|
||||||
|
*/
|
||||||
readonly runner!: null | ContractRunner;
|
readonly runner!: null | ContractRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All the Events available on this contract.
|
||||||
|
*/
|
||||||
readonly filters!: Record<string, ContractEvent>;
|
readonly filters!: Record<string, ContractEvent>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
readonly [internal]: any;
|
readonly [internal]: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fallback or receive function if any.
|
||||||
|
*/
|
||||||
readonly fallback!: null | WrappedFallback;
|
readonly fallback!: null | WrappedFallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new contract connected to %%target%% with the %%abi%% and
|
||||||
|
* optionally connected to a %%runner%% to perform operations on behalf
|
||||||
|
* of.
|
||||||
|
*/
|
||||||
constructor(target: string | Addressable, abi: Interface | InterfaceAbi, runner?: null | ContractRunner, _deployTx?: null | TransactionResponse) {
|
constructor(target: string | Addressable, abi: Interface | InterfaceAbi, runner?: null | ContractRunner, _deployTx?: null | TransactionResponse) {
|
||||||
assertArgument(typeof(target) === "string" || isAddressable(target),
|
assertArgument(typeof(target) === "string" || isAddressable(target),
|
||||||
"invalid value for Contract target", "target", target);
|
"invalid value for Contract target", "target", target);
|
||||||
@ -727,12 +760,22 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new Contract instance with the same target and ABI, but
|
||||||
|
* a different %%runner%%.
|
||||||
|
*/
|
||||||
connect(runner: null | ContractRunner): BaseContract {
|
connect(runner: null | ContractRunner): BaseContract {
|
||||||
return new BaseContract(this.target, this.interface, runner);
|
return new BaseContract(this.target, this.interface, runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the resolved address of this Contract.
|
||||||
|
*/
|
||||||
async getAddress(): Promise<string> { return await getInternal(this).addrPromise; }
|
async getAddress(): Promise<string> { return await getInternal(this).addrPromise; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the dedployed bytecode or null if no bytecode is found.
|
||||||
|
*/
|
||||||
async getDeployedCode(): Promise<null | string> {
|
async getDeployedCode(): Promise<null | string> {
|
||||||
const provider = getProvider(this.runner);
|
const provider = getProvider(this.runner);
|
||||||
assert(provider, "runner does not support .provider",
|
assert(provider, "runner does not support .provider",
|
||||||
@ -743,6 +786,10 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve to this Contract once the bytecode has been deployed, or
|
||||||
|
* resolve immediately if already deployed.
|
||||||
|
*/
|
||||||
async waitForDeployment(): Promise<this> {
|
async waitForDeployment(): Promise<this> {
|
||||||
// We have the deployement transaction; just use that (throws if deployement fails)
|
// We have the deployement transaction; just use that (throws if deployement fails)
|
||||||
const deployTx = this.deploymentTransaction();
|
const deployTx = this.deploymentTransaction();
|
||||||
@ -774,26 +821,50 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the transaction used to deploy this contract.
|
||||||
|
*
|
||||||
|
* This is only available if this instance was returned from a
|
||||||
|
* [[ContractFactory]].
|
||||||
|
*/
|
||||||
deploymentTransaction(): null | ContractTransactionResponse {
|
deploymentTransaction(): null | ContractTransactionResponse {
|
||||||
return getInternal(this).deployTx;
|
return getInternal(this).deployTx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the function for a given name. This is useful when a contract
|
||||||
|
* method name conflicts with a JavaScript name such as ``prototype`` or
|
||||||
|
* when using a Contract programatically.
|
||||||
|
*/
|
||||||
getFunction<T extends ContractMethod = ContractMethod>(key: string | FunctionFragment): T {
|
getFunction<T extends ContractMethod = ContractMethod>(key: string | FunctionFragment): T {
|
||||||
if (typeof(key) !== "string") { key = key.format(); }
|
if (typeof(key) !== "string") { key = key.format(); }
|
||||||
const func = buildWrappedMethod(this, key);
|
const func = buildWrappedMethod(this, key);
|
||||||
return <T>func;
|
return <T>func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the event for a given name. This is useful when a contract
|
||||||
|
* event name conflicts with a JavaScript name such as ``prototype`` or
|
||||||
|
* when using a Contract programatically.
|
||||||
|
*/
|
||||||
getEvent(key: string | EventFragment): ContractEvent {
|
getEvent(key: string | EventFragment): ContractEvent {
|
||||||
if (typeof(key) !== "string") { key = key.format(); }
|
if (typeof(key) !== "string") { key = key.format(); }
|
||||||
return buildWrappedEvent(this, key);
|
return buildWrappedEvent(this, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
async queryTransaction(hash: string): Promise<Array<EventLog>> {
|
async queryTransaction(hash: string): Promise<Array<EventLog>> {
|
||||||
// Is this useful?
|
// Is this useful?
|
||||||
throw new Error("@TODO");
|
throw new Error("@TODO");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide historic access to event data for %%event%% in the range
|
||||||
|
* %%fromBlock%% (default: ``0``) to %%toBlock%% (default: ``"latest"``)
|
||||||
|
* inclusive.
|
||||||
|
*/
|
||||||
async queryFilter(event: ContractEventName, fromBlock?: BlockTag, toBlock?: BlockTag): Promise<Array<EventLog | Log>> {
|
async queryFilter(event: ContractEventName, fromBlock?: BlockTag, toBlock?: BlockTag): Promise<Array<EventLog | Log>> {
|
||||||
if (fromBlock == null) { fromBlock = 0; }
|
if (fromBlock == null) { fromBlock = 0; }
|
||||||
if (toBlock == null) { toBlock = "latest"; }
|
if (toBlock == null) { toBlock = "latest"; }
|
||||||
@ -822,6 +893,9 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an event %%listener%% for the %%event%%.
|
||||||
|
*/
|
||||||
async on(event: ContractEventName, listener: Listener): Promise<this> {
|
async on(event: ContractEventName, listener: Listener): Promise<this> {
|
||||||
const sub = await getSub(this, "on", event);
|
const sub = await getSub(this, "on", event);
|
||||||
sub.listeners.push({ listener, once: false });
|
sub.listeners.push({ listener, once: false });
|
||||||
@ -829,6 +903,10 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an event %%listener%% for the %%event%%, but remove the listener
|
||||||
|
* after it is fired once.
|
||||||
|
*/
|
||||||
async once(event: ContractEventName, listener: Listener): Promise<this> {
|
async once(event: ContractEventName, listener: Listener): Promise<this> {
|
||||||
const sub = await getSub(this, "once", event);
|
const sub = await getSub(this, "once", event);
|
||||||
sub.listeners.push({ listener, once: true });
|
sub.listeners.push({ listener, once: true });
|
||||||
@ -836,10 +914,19 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emit an %%event%% calling all listeners with %%args%%.
|
||||||
|
*
|
||||||
|
* Resolves to ``true`` if any listeners were called.
|
||||||
|
*/
|
||||||
async emit(event: ContractEventName, ...args: Array<any>): Promise<boolean> {
|
async emit(event: ContractEventName, ...args: Array<any>): Promise<boolean> {
|
||||||
return await emit(this, event, args, null);
|
return await emit(this, event, args, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the number of listeners of %%event%% or the total number
|
||||||
|
* of listeners if unspecified.
|
||||||
|
*/
|
||||||
async listenerCount(event?: ContractEventName): Promise<number> {
|
async listenerCount(event?: ContractEventName): Promise<number> {
|
||||||
if (event) {
|
if (event) {
|
||||||
const sub = await hasSub(this, event);
|
const sub = await hasSub(this, event);
|
||||||
@ -856,6 +943,10 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the listeners subscribed to %%event%% or all listeners
|
||||||
|
* if unspecified.
|
||||||
|
*/
|
||||||
async listeners(event?: ContractEventName): Promise<Array<Listener>> {
|
async listeners(event?: ContractEventName): Promise<Array<Listener>> {
|
||||||
if (event) {
|
if (event) {
|
||||||
const sub = await hasSub(this, event);
|
const sub = await hasSub(this, event);
|
||||||
@ -872,6 +963,10 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the %%listener%% from the listeners for %%event%% or remove
|
||||||
|
* all listeners if unspecified.
|
||||||
|
*/
|
||||||
async off(event: ContractEventName, listener?: Listener): Promise<this> {
|
async off(event: ContractEventName, listener?: Listener): Promise<this> {
|
||||||
const sub = await hasSub(this, event);
|
const sub = await hasSub(this, event);
|
||||||
if (!sub) { return this; }
|
if (!sub) { return this; }
|
||||||
@ -889,6 +984,10 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all the listeners for %%event%% or remove all listeners if
|
||||||
|
* unspecified.
|
||||||
|
*/
|
||||||
async removeAllListeners(event?: ContractEventName): Promise<this> {
|
async removeAllListeners(event?: ContractEventName): Promise<this> {
|
||||||
if (event) {
|
if (event) {
|
||||||
const sub = await hasSub(this, event);
|
const sub = await hasSub(this, event);
|
||||||
@ -906,16 +1005,23 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alias for "on"
|
/**
|
||||||
|
* Alias for [on].
|
||||||
|
*/
|
||||||
async addListener(event: ContractEventName, listener: Listener): Promise<this> {
|
async addListener(event: ContractEventName, listener: Listener): Promise<this> {
|
||||||
return await this.on(event, listener);
|
return await this.on(event, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alias for "off"
|
/**
|
||||||
|
* Alias for [off].
|
||||||
|
*/
|
||||||
async removeListener(event: ContractEventName, listener: Listener): Promise<this> {
|
async removeListener(event: ContractEventName, listener: Listener): Promise<this> {
|
||||||
return await this.off(event, listener);
|
return await this.off(event, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Class for the %%abi%%.
|
||||||
|
*/
|
||||||
static buildClass<T = ContractInterface>(abi: InterfaceAbi): new (target: string, runner?: null | ContractRunner) => BaseContract & Omit<T, keyof BaseContract> {
|
static buildClass<T = ContractInterface>(abi: InterfaceAbi): new (target: string, runner?: null | ContractRunner) => BaseContract & Omit<T, keyof BaseContract> {
|
||||||
class CustomContract extends BaseContract {
|
class CustomContract extends BaseContract {
|
||||||
constructor(address: string, runner: null | ContractRunner = null) {
|
constructor(address: string, runner: null | ContractRunner = null) {
|
||||||
@ -925,6 +1031,9 @@ export class BaseContract implements Addressable, EventEmitterable<ContractEvent
|
|||||||
return CustomContract as any;
|
return CustomContract as any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new BaseContract with a specified Interface.
|
||||||
|
*/
|
||||||
static from<T = ContractInterface>(target: string, abi: InterfaceAbi, runner?: null | ContractRunner): BaseContract & Omit<T, keyof BaseContract> {
|
static from<T = ContractInterface>(target: string, abi: InterfaceAbi, runner?: null | ContractRunner): BaseContract & Omit<T, keyof BaseContract> {
|
||||||
if (runner == null) { runner = null; }
|
if (runner == null) { runner = null; }
|
||||||
const contract = new this(target, abi, runner );
|
const contract = new this(target, abi, runner );
|
||||||
@ -936,4 +1045,7 @@ function _ContractBase(): new (target: string, abi: InterfaceAbi, runner?: null
|
|||||||
return BaseContract as any;
|
return BaseContract as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A [[BaseContract]] with no type guards on its methods or events.
|
||||||
|
*/
|
||||||
export class Contract extends _ContractBase() { }
|
export class Contract extends _ContractBase() { }
|
||||||
|
@ -20,11 +20,34 @@ import type { ContractTransactionResponse } from "./wrappers.js";
|
|||||||
|
|
||||||
// A = Arguments to the constructor
|
// A = Arguments to the constructor
|
||||||
// I = Interface of deployed contracts
|
// I = Interface of deployed contracts
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **ContractFactory** is used to deploy a Contract to the blockchain.
|
||||||
|
*/
|
||||||
export class ContractFactory<A extends Array<any> = Array<any>, I = BaseContract> {
|
export class ContractFactory<A extends Array<any> = Array<any>, I = BaseContract> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Contract Interface.
|
||||||
|
*/
|
||||||
readonly interface!: Interface;
|
readonly interface!: Interface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Contract deployment bytecode. Often called the initcode.
|
||||||
|
*/
|
||||||
readonly bytecode!: string;
|
readonly bytecode!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ContractRunner to deploy the Contract as.
|
||||||
|
*/
|
||||||
readonly runner!: null | ContractRunner;
|
readonly runner!: null | ContractRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new **ContractFactory** with %%abi%% and %%bytecode%%,
|
||||||
|
* optionally connected to %%runner%%.
|
||||||
|
*
|
||||||
|
* The %%bytecode%% may be the ``bytecode`` property within the
|
||||||
|
* standard Solidity JSON output.
|
||||||
|
*/
|
||||||
constructor(abi: Interface | InterfaceAbi, bytecode: BytesLike | { object: string }, runner?: null | ContractRunner) {
|
constructor(abi: Interface | InterfaceAbi, bytecode: BytesLike | { object: string }, runner?: null | ContractRunner) {
|
||||||
const iface = Interface.from(abi);
|
const iface = Interface.from(abi);
|
||||||
|
|
||||||
@ -42,6 +65,10 @@ export class ContractFactory<A extends Array<any> = Array<any>, I = BaseContract
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the transaction to deploy the contract, passing %%args%%
|
||||||
|
* into the constructor.
|
||||||
|
*/
|
||||||
async getDeployTransaction(...args: ContractMethodArgs<A>): Promise<ContractDeployTransaction> {
|
async getDeployTransaction(...args: ContractMethodArgs<A>): Promise<ContractDeployTransaction> {
|
||||||
let overrides: Omit<ContractDeployTransaction, "data"> = { };
|
let overrides: Omit<ContractDeployTransaction, "data"> = { };
|
||||||
|
|
||||||
@ -61,6 +88,14 @@ export class ContractFactory<A extends Array<any> = Array<any>, I = BaseContract
|
|||||||
return Object.assign({ }, overrides, { data });
|
return Object.assign({ }, overrides, { data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the Contract deployed by passing %%args%% into the
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* This will resovle to the Contract before it has been deployed to the
|
||||||
|
* network, so the [[BaseContract-waitForDeployment]] should be used before
|
||||||
|
* sending any transactions to it.
|
||||||
|
*/
|
||||||
async deploy(...args: ContractMethodArgs<A>): Promise<BaseContract & { deploymentTransaction(): ContractTransactionResponse } & Omit<I, keyof BaseContract>> {
|
async deploy(...args: ContractMethodArgs<A>): Promise<BaseContract & { deploymentTransaction(): ContractTransactionResponse } & Omit<I, keyof BaseContract>> {
|
||||||
const tx = await this.getDeployTransaction(...args);
|
const tx = await this.getDeployTransaction(...args);
|
||||||
|
|
||||||
@ -73,10 +108,17 @@ export class ContractFactory<A extends Array<any> = Array<any>, I = BaseContract
|
|||||||
return new (<any>BaseContract)(address, this.interface, this.runner, sentTx);
|
return new (<any>BaseContract)(address, this.interface, this.runner, sentTx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new **ContractFactory** with the same ABI and bytecode,
|
||||||
|
* but connected to %%runner%%.
|
||||||
|
*/
|
||||||
connect(runner: null | ContractRunner): ContractFactory<A, I> {
|
connect(runner: null | ContractRunner): ContractFactory<A, I> {
|
||||||
return new ContractFactory(this.interface, this.bytecode, runner);
|
return new ContractFactory(this.interface, this.bytecode, runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new **ContractFactory** from the standard Solidity JSON output.
|
||||||
|
*/
|
||||||
static fromSolidity<A extends Array<any> = Array<any>, I = ContractInterface>(output: any, runner?: ContractRunner): ContractFactory<A, I> {
|
static fromSolidity<A extends Array<any> = Array<any>, I = ContractInterface>(output: any, runner?: ContractRunner): ContractFactory<A, I> {
|
||||||
assertArgument(output != null, "bad compiler output", "output", output);
|
assertArgument(output != null, "bad compiler output", "output", output);
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* About contracts...
|
* A **Contract** object is a meta-class (a class whose definition is
|
||||||
|
* defined at runtime), which communicates with a deployed smart contract
|
||||||
|
* on the blockchain and provides a simple JavaScript interface to call
|
||||||
|
* methods, send transaction, query historic logs and listen for its events.
|
||||||
*
|
*
|
||||||
* @_section: api/contract:Contracts [about-contracts]
|
* @_section: api/contract:Contracts [about-contracts]
|
||||||
*/
|
*/
|
||||||
|
@ -8,36 +8,89 @@ import type {
|
|||||||
import type { ContractTransactionResponse } from "./wrappers.js";
|
import type { ContractTransactionResponse } from "./wrappers.js";
|
||||||
|
|
||||||
|
|
||||||
// The types of events a Contract can listen for
|
/**
|
||||||
|
* The name for an event used for subscribing to Contract events.
|
||||||
|
*
|
||||||
|
* **``string``** - An event by name. The event must be non-ambiguous.
|
||||||
|
* The parameters will be dereferenced when passed into the listener.
|
||||||
|
*
|
||||||
|
* [[ContractEvent]] - A filter from the ``contract.filters``, which will
|
||||||
|
* pass only the EventPayload as a single parameter, which includes a
|
||||||
|
* ``.signature`` property that can be used to further filter the event.
|
||||||
|
*
|
||||||
|
* [[TopicFilter]] - A filter defined using the standard Ethereum API
|
||||||
|
* which provides the specific topic hash or topic hashes to watch for along
|
||||||
|
* with any additional values to filter by. This will only pass a single
|
||||||
|
* parameter to the listener, the EventPayload which will include additional
|
||||||
|
* details to refine by, such as the event name and signature.
|
||||||
|
*
|
||||||
|
* [[DeferredTopicFilter]] - A filter created by calling a [[ContractEvent]]
|
||||||
|
* with parameters, which will create a filter for a specific event
|
||||||
|
* signautre and dereference each parameter when calling the listener.
|
||||||
|
*/
|
||||||
export type ContractEventName = string | ContractEvent | TopicFilter | DeferredTopicFilter;
|
export type ContractEventName = string | ContractEvent | TopicFilter | DeferredTopicFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Contract with no method constraints.
|
||||||
|
*/
|
||||||
export interface ContractInterface {
|
export interface ContractInterface {
|
||||||
[ name: string ]: BaseContractMethod;
|
[ name: string ]: BaseContractMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When creating a filter using the ``contract.filters``, this is returned.
|
||||||
|
*/
|
||||||
export interface DeferredTopicFilter {
|
export interface DeferredTopicFilter {
|
||||||
getTopicFilter(): Promise<TopicFilter>;
|
getTopicFilter(): Promise<TopicFilter>;
|
||||||
fragment: EventFragment;
|
fragment: EventFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When populating a transaction this type is returned.
|
||||||
|
*/
|
||||||
export interface ContractTransaction extends PreparedTransactionRequest {
|
export interface ContractTransaction extends PreparedTransactionRequest {
|
||||||
// These are populated by contract methods and cannot bu null
|
/**
|
||||||
|
* The target address.
|
||||||
|
*/
|
||||||
to: string;
|
to: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction data.
|
||||||
|
*/
|
||||||
data: string;
|
data: string;
|
||||||
|
|
||||||
// These are resolved
|
/**
|
||||||
|
* The from address, if any.
|
||||||
|
*/
|
||||||
from?: string;
|
from?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deployment Transactions have no `to`
|
/**
|
||||||
|
* A deployment transaction for a contract.
|
||||||
|
*/
|
||||||
export interface ContractDeployTransaction extends Omit<ContractTransaction, "to"> { }
|
export interface ContractDeployTransaction extends Omit<ContractTransaction, "to"> { }
|
||||||
|
|
||||||
// Overrides; cannot override `to` or `data` as Contract populates these
|
/**
|
||||||
|
* The overrides for a contract transaction.
|
||||||
|
*/
|
||||||
export interface Overrides extends Omit<TransactionRequest, "to" | "data"> { };
|
export interface Overrides extends Omit<TransactionRequest, "to" | "data"> { };
|
||||||
|
|
||||||
|
|
||||||
// Arguments for methods; with an optional (n+1)th Override
|
/**
|
||||||
|
* Arguments to a Contract method can always include an additional and
|
||||||
|
* optional overrides parameter.
|
||||||
|
*
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
export type PostfixOverrides<A extends Array<any>> = A | [ ...A, Overrides ];
|
export type PostfixOverrides<A extends Array<any>> = A | [ ...A, Overrides ];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arguments to a Contract method can always include an additional and
|
||||||
|
* optional overrides parameter, and each parameter can optionally be
|
||||||
|
* [[Typed]].
|
||||||
|
*
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
export type ContractMethodArgs<A extends Array<any>> = PostfixOverrides<{ [ I in keyof A ]-?: A[I] | Typed }>;
|
export type ContractMethodArgs<A extends Array<any>> = PostfixOverrides<{ [ I in keyof A ]-?: A[I] | Typed }>;
|
||||||
|
|
||||||
// A = Arguments passed in as a tuple
|
// A = Arguments passed in as a tuple
|
||||||
@ -45,51 +98,139 @@ export type ContractMethodArgs<A extends Array<any>> = PostfixOverrides<{ [ I in
|
|||||||
// the qualified type, otherwise Result)
|
// the qualified type, otherwise Result)
|
||||||
// D = The type the default call will return (i.e. R for view/pure,
|
// D = The type the default call will return (i.e. R for view/pure,
|
||||||
// TransactionResponse otherwise)
|
// TransactionResponse otherwise)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Contract method can be called directly, or used in various ways.
|
||||||
|
*/
|
||||||
export interface BaseContractMethod<A extends Array<any> = Array<any>, R = any, D extends R | ContractTransactionResponse = R | ContractTransactionResponse> {
|
export interface BaseContractMethod<A extends Array<any> = Array<any>, R = any, D extends R | ContractTransactionResponse = R | ContractTransactionResponse> {
|
||||||
(...args: ContractMethodArgs<A>): Promise<D>;
|
(...args: ContractMethodArgs<A>): Promise<D>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the Contract method.
|
||||||
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fragment of the Contract method. This will throw on ambiguous
|
||||||
|
* method names.
|
||||||
|
*/
|
||||||
fragment: FunctionFragment;
|
fragment: FunctionFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fragment constrained by %%args%%. This can be used to
|
||||||
|
* resolve ambiguous method names.
|
||||||
|
*/
|
||||||
getFragment(...args: ContractMethodArgs<A>): FunctionFragment;
|
getFragment(...args: ContractMethodArgs<A>): FunctionFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a populated transaction that can be used to perform the
|
||||||
|
* contract method with %%args%%.
|
||||||
|
*/
|
||||||
populateTransaction(...args: ContractMethodArgs<A>): Promise<ContractTransaction>;
|
populateTransaction(...args: ContractMethodArgs<A>): Promise<ContractTransaction>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the contract method with %%args%% and return the value.
|
||||||
|
*
|
||||||
|
* If the return value is a single type, it will be dereferenced and
|
||||||
|
* returned directly, otherwise the full Result will be returned.
|
||||||
|
*/
|
||||||
staticCall(...args: ContractMethodArgs<A>): Promise<R>;
|
staticCall(...args: ContractMethodArgs<A>): Promise<R>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a transaction for the contract method with %%args%%.
|
||||||
|
*/
|
||||||
send(...args: ContractMethodArgs<A>): Promise<ContractTransactionResponse>;
|
send(...args: ContractMethodArgs<A>): Promise<ContractTransactionResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estimate the gas to send the contract method with %%args%%.
|
||||||
|
*/
|
||||||
estimateGas(...args: ContractMethodArgs<A>): Promise<bigint>;
|
estimateGas(...args: ContractMethodArgs<A>): Promise<bigint>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the contract method with %%args%% and return the Result
|
||||||
|
* without any dereferencing.
|
||||||
|
*/
|
||||||
staticCallResult(...args: ContractMethodArgs<A>): Promise<Result>;
|
staticCallResult(...args: ContractMethodArgs<A>): Promise<Result>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A contract method on a Contract.
|
||||||
|
*/
|
||||||
export interface ContractMethod<
|
export interface ContractMethod<
|
||||||
A extends Array<any> = Array<any>,
|
A extends Array<any> = Array<any>,
|
||||||
R = any,
|
R = any,
|
||||||
D extends R | ContractTransactionResponse = R | ContractTransactionResponse
|
D extends R | ContractTransactionResponse = R | ContractTransactionResponse
|
||||||
> extends BaseContractMethod<A, R, D> { }
|
> extends BaseContractMethod<A, R, D> { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pure of view method on a Contract.
|
||||||
|
*/
|
||||||
export interface ConstantContractMethod<
|
export interface ConstantContractMethod<
|
||||||
A extends Array<any>,
|
A extends Array<any>,
|
||||||
R = any
|
R = any
|
||||||
> extends ContractMethod<A, R, R> { }
|
> extends ContractMethod<A, R, R> { }
|
||||||
|
|
||||||
|
|
||||||
// Arguments for events; with each element optional and/or nullable
|
/**
|
||||||
|
* Each argument of an event is nullable (to indicate matching //any//.
|
||||||
|
*
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
export type ContractEventArgs<A extends Array<any>> = { [ I in keyof A ]?: A[I] | Typed | null };
|
export type ContractEventArgs<A extends Array<any>> = { [ I in keyof A ]?: A[I] | Typed | null };
|
||||||
|
|
||||||
export interface ContractEvent<A extends Array<any> = Array<any>> {
|
export interface ContractEvent<A extends Array<any> = Array<any>> {
|
||||||
(...args: ContractEventArgs<A>): DeferredTopicFilter;
|
(...args: ContractEventArgs<A>): DeferredTopicFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the Contract event.
|
||||||
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fragment of the Contract event. This will throw on ambiguous
|
||||||
|
* method names.
|
||||||
|
*/
|
||||||
fragment: EventFragment;
|
fragment: EventFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fragment constrained by %%args%%. This can be used to
|
||||||
|
* resolve ambiguous event names.
|
||||||
|
*/
|
||||||
getFragment(...args: ContractEventArgs<A>): EventFragment;
|
getFragment(...args: ContractEventArgs<A>): EventFragment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Fallback or Receive function on a Contract.
|
||||||
|
*/
|
||||||
export interface WrappedFallback {
|
export interface WrappedFallback {
|
||||||
(overrides?: Omit<TransactionRequest, "to">): Promise<ContractTransactionResponse>;
|
(overrides?: Omit<TransactionRequest, "to">): Promise<ContractTransactionResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a populated transaction that can be used to perform the
|
||||||
|
* fallback method.
|
||||||
|
*
|
||||||
|
* For non-receive fallback, ``data`` may be overridden.
|
||||||
|
*/
|
||||||
populateTransaction(overrides?: Omit<TransactionRequest, "to">): Promise<ContractTransaction>;
|
populateTransaction(overrides?: Omit<TransactionRequest, "to">): Promise<ContractTransaction>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the contract fallback and return the result.
|
||||||
|
*
|
||||||
|
* For non-receive fallback, ``data`` may be overridden.
|
||||||
|
*/
|
||||||
staticCall(overrides?: Omit<TransactionRequest, "to">): Promise<string>;
|
staticCall(overrides?: Omit<TransactionRequest, "to">): Promise<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a transaction to the contract fallback.
|
||||||
|
*
|
||||||
|
* For non-receive fallback, ``data`` may be overridden.
|
||||||
|
*/
|
||||||
send(overrides?: Omit<TransactionRequest, "to">): Promise<ContractTransactionResponse>;
|
send(overrides?: Omit<TransactionRequest, "to">): Promise<ContractTransactionResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estimate the gas to send a transaction to the contract fallback.
|
||||||
|
*
|
||||||
|
* For non-receive fallback, ``data`` may be overridden.
|
||||||
|
*/
|
||||||
estimateGas(overrides?: Omit<TransactionRequest, "to">): Promise<bigint>;
|
estimateGas(overrides?: Omit<TransactionRequest, "to">): Promise<bigint>;
|
||||||
}
|
}
|
||||||
|
@ -14,30 +14,64 @@ import type {
|
|||||||
import type { BaseContract } from "./contract.js";
|
import type { BaseContract } from "./contract.js";
|
||||||
import type { ContractEventName } from "./types.js";
|
import type { ContractEventName } from "./types.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An **EventLog** contains additional properties parsed from the [[Log]].
|
||||||
|
*/
|
||||||
export class EventLog extends Log {
|
export class EventLog extends Log {
|
||||||
|
/**
|
||||||
|
* The Contract Interface.
|
||||||
|
*/
|
||||||
readonly interface!: Interface;
|
readonly interface!: Interface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The matching event.
|
||||||
|
*/
|
||||||
readonly fragment!: EventFragment;
|
readonly fragment!: EventFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parsed arguments passed to the event by ``emit``.
|
||||||
|
*/
|
||||||
readonly args!: Result;
|
readonly args!: Result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(log: Log, iface: Interface, fragment: EventFragment) {
|
constructor(log: Log, iface: Interface, fragment: EventFragment) {
|
||||||
super(log, log.provider);
|
super(log, log.provider);
|
||||||
const args = iface.decodeEventLog(fragment, log.data, log.topics);
|
const args = iface.decodeEventLog(fragment, log.data, log.topics);
|
||||||
defineProperties<EventLog>(this, { args, fragment, interface: iface });
|
defineProperties<EventLog>(this, { args, fragment, interface: iface });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the event.
|
||||||
|
*/
|
||||||
get eventName(): string { return this.fragment.name; }
|
get eventName(): string { return this.fragment.name; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signature of the event.
|
||||||
|
*/
|
||||||
get eventSignature(): string { return this.fragment.format(); }
|
get eventSignature(): string { return this.fragment.format(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **ContractTransactionReceipt** includes the parsed logs from a
|
||||||
|
* [[TransactionReceipt]].
|
||||||
|
*/
|
||||||
export class ContractTransactionReceipt extends TransactionReceipt {
|
export class ContractTransactionReceipt extends TransactionReceipt {
|
||||||
readonly #iface: Interface;
|
readonly #iface: Interface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(iface: Interface, provider: Provider, tx: TransactionReceipt) {
|
constructor(iface: Interface, provider: Provider, tx: TransactionReceipt) {
|
||||||
super(tx, provider);
|
super(tx, provider);
|
||||||
this.#iface = iface;
|
this.#iface = iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parsed logs for any [[Log]] which has a matching event in the
|
||||||
|
* Contract ABI.
|
||||||
|
*/
|
||||||
get logs(): Array<EventLog | Log> {
|
get logs(): Array<EventLog | Log> {
|
||||||
return super.logs.map((log) => {
|
return super.logs.map((log) => {
|
||||||
const fragment = log.topics.length ? this.#iface.getEvent(log.topics[0]): null;
|
const fragment = log.topics.length ? this.#iface.getEvent(log.topics[0]): null;
|
||||||
@ -51,14 +85,30 @@ export class ContractTransactionReceipt extends TransactionReceipt {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **ContractTransactionResponse** will return a
|
||||||
|
* [[ContractTransactionReceipt]] when waited on.
|
||||||
|
*/
|
||||||
export class ContractTransactionResponse extends TransactionResponse {
|
export class ContractTransactionResponse extends TransactionResponse {
|
||||||
readonly #iface: Interface;
|
readonly #iface: Interface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(iface: Interface, provider: Provider, tx: TransactionResponse) {
|
constructor(iface: Interface, provider: Provider, tx: TransactionResponse) {
|
||||||
super(tx, provider);
|
super(tx, provider);
|
||||||
this.#iface = iface;
|
this.#iface = iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves once this transaction has been mined and has
|
||||||
|
* %%confirms%% blocks including it (default: ``1``) with an
|
||||||
|
* optional %%timeout%%.
|
||||||
|
*
|
||||||
|
* This can resolve to ``null`` only if %%confirms%% is ``0``
|
||||||
|
* and the transaction has not been mined, otherwise this will
|
||||||
|
* wait until enough confirmations have completed.
|
||||||
|
*/
|
||||||
async wait(confirms?: number): Promise<null | ContractTransactionReceipt> {
|
async wait(confirms?: number): Promise<null | ContractTransactionReceipt> {
|
||||||
const receipt = await super.wait();
|
const receipt = await super.wait();
|
||||||
if (receipt == null) { return null; }
|
if (receipt == null) { return null; }
|
||||||
@ -66,43 +116,86 @@ export class ContractTransactionResponse extends TransactionResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **ContractUnknownEventPayload** is included as the last parameter to
|
||||||
|
* Contract Events when the event does not match any events in the ABI.
|
||||||
|
*/
|
||||||
export class ContractUnknownEventPayload extends EventPayload<ContractEventName> {
|
export class ContractUnknownEventPayload extends EventPayload<ContractEventName> {
|
||||||
|
/**
|
||||||
|
* The log with no matching events.
|
||||||
|
*/
|
||||||
readonly log!: Log;
|
readonly log!: Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_event:
|
||||||
|
*/
|
||||||
constructor(contract: BaseContract, listener: null | Listener, filter: ContractEventName, log: Log) {
|
constructor(contract: BaseContract, listener: null | Listener, filter: ContractEventName, log: Log) {
|
||||||
super(contract, listener, filter);
|
super(contract, listener, filter);
|
||||||
defineProperties<ContractUnknownEventPayload>(this, { log });
|
defineProperties<ContractUnknownEventPayload>(this, { log });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the block the event occured in.
|
||||||
|
*/
|
||||||
async getBlock(): Promise<Block> {
|
async getBlock(): Promise<Block> {
|
||||||
return await this.log.getBlock();
|
return await this.log.getBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the transaction the event occured in.
|
||||||
|
*/
|
||||||
async getTransaction(): Promise<TransactionResponse> {
|
async getTransaction(): Promise<TransactionResponse> {
|
||||||
return await this.log.getTransaction();
|
return await this.log.getTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the transaction receipt the event occured in.
|
||||||
|
*/
|
||||||
async getTransactionReceipt(): Promise<TransactionReceipt> {
|
async getTransactionReceipt(): Promise<TransactionReceipt> {
|
||||||
return await this.log.getTransactionReceipt();
|
return await this.log.getTransactionReceipt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **ContractEventPayload** is included as the last parameter to
|
||||||
|
* Contract Events when the event is known.
|
||||||
|
*/
|
||||||
export class ContractEventPayload extends ContractUnknownEventPayload {
|
export class ContractEventPayload extends ContractUnknownEventPayload {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The matching event.
|
||||||
|
*/
|
||||||
declare readonly fragment: EventFragment;
|
declare readonly fragment: EventFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The log, with parsed properties.
|
||||||
|
*/
|
||||||
declare readonly log: EventLog;
|
declare readonly log: EventLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parsed arguments passed to the event by ``emit``.
|
||||||
|
*/
|
||||||
declare readonly args: Result;
|
declare readonly args: Result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(contract: BaseContract, listener: null | Listener, filter: ContractEventName, fragment: EventFragment, _log: Log) {
|
constructor(contract: BaseContract, listener: null | Listener, filter: ContractEventName, fragment: EventFragment, _log: Log) {
|
||||||
super(contract, listener, filter, new EventLog(_log, contract.interface, fragment));
|
super(contract, listener, filter, new EventLog(_log, contract.interface, fragment));
|
||||||
const args = contract.interface.decodeEventLog(fragment, this.log.data, this.log.topics);
|
const args = contract.interface.decodeEventLog(fragment, this.log.data, this.log.topics);
|
||||||
defineProperties<ContractEventPayload>(this, { args, fragment });
|
defineProperties<ContractEventPayload>(this, { args, fragment });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The event name.
|
||||||
|
*/
|
||||||
get eventName(): string {
|
get eventName(): string {
|
||||||
return this.fragment.name;
|
return this.fragment.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The event signature.
|
||||||
|
*/
|
||||||
get eventSignature(): string {
|
get eventSignature(): string {
|
||||||
return this.fragment.format();
|
return this.fragment.format();
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,10 @@ export {
|
|||||||
export { SigningKey } from "./signing-key.js";
|
export { SigningKey } from "./signing-key.js";
|
||||||
export { Signature } from "./signature.js";
|
export { Signature } from "./signature.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Once called, prevents any future change to the underlying cryptographic
|
||||||
|
* primitives using the ``.register`` feature for hooks.
|
||||||
|
*/
|
||||||
function lock(): void {
|
function lock(): void {
|
||||||
computeHmac.lock();
|
computeHmac.lock();
|
||||||
keccak256.lock();
|
keccak256.lock();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* About hashing here...
|
* Utilities for common tasks involving hashing. Also see
|
||||||
|
* [cryptographic hashing](about-crypto-hashing).
|
||||||
*
|
*
|
||||||
* @_section: api/hashing:Hashing Utilities [about-hashing]
|
* @_section: api/hashing:Hashing Utilities [about-hashing]
|
||||||
*/
|
*/
|
||||||
|
@ -21,16 +21,50 @@ const BN_0 = BigInt(0);
|
|||||||
const BN_1 = BigInt(1);
|
const BN_1 = BigInt(1);
|
||||||
const BN_MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
const BN_MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||||
|
|
||||||
|
// @TODO: in v7, verifyingContract should be an AddressLike and use resolveAddress
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The domain for an [[link-eip-712]] payload.
|
||||||
|
*/
|
||||||
export interface TypedDataDomain {
|
export interface TypedDataDomain {
|
||||||
|
/**
|
||||||
|
* The human-readable name of the signing domain.
|
||||||
|
*/
|
||||||
name?: null | string;
|
name?: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The major version of the signing domain.
|
||||||
|
*/
|
||||||
version?: null | string;
|
version?: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The chain ID of the signing domain.
|
||||||
|
*/
|
||||||
chainId?: null | BigNumberish;
|
chainId?: null | BigNumberish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The the address of the contract that will verify the signature.
|
||||||
|
*/
|
||||||
verifyingContract?: null | string;
|
verifyingContract?: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A salt used for purposes decided by the specific domain.
|
||||||
|
*/
|
||||||
salt?: null | BytesLike;
|
salt?: null | BytesLike;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A specific field of a structured [[link-eip-712]] type.
|
||||||
|
*/
|
||||||
export interface TypedDataField {
|
export interface TypedDataField {
|
||||||
|
/**
|
||||||
|
* The field name.
|
||||||
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the field.
|
||||||
|
*/
|
||||||
type: string;
|
type: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -147,10 +181,30 @@ function encodeType(name: string, fields: Array<TypedDataField>): string {
|
|||||||
return `${ name }(${ fields.map(({ name, type }) => (type + " " + name)).join(",") })`;
|
return `${ name }(${ fields.map(({ name, type }) => (type + " " + name)).join(",") })`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **TypedDataEncode** prepares and encodes [[link-eip-712]] payloads
|
||||||
|
* for signed typed data.
|
||||||
|
*
|
||||||
|
* This is useful for those that wish to compute various components of a
|
||||||
|
* typed data hash, primary types, or sub-components, but generally the
|
||||||
|
* higher level [[Signer-signTypedData]] is more useful.
|
||||||
|
*/
|
||||||
export class TypedDataEncoder {
|
export class TypedDataEncoder {
|
||||||
|
/**
|
||||||
|
* The primary type for the structured [[types]].
|
||||||
|
*
|
||||||
|
* This is derived automatically from the [[types]], since no
|
||||||
|
* recursion is possible, once the DAG for the types is consturcted
|
||||||
|
* internally, the primary type must be the only remaining type with
|
||||||
|
* no parent nodes.
|
||||||
|
*/
|
||||||
readonly primaryType!: string;
|
readonly primaryType!: string;
|
||||||
|
|
||||||
readonly #types: string;
|
readonly #types: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types.
|
||||||
|
*/
|
||||||
get types(): Record<string, Array<TypedDataField>> {
|
get types(): Record<string, Array<TypedDataField>> {
|
||||||
return JSON.parse(this.#types);
|
return JSON.parse(this.#types);
|
||||||
}
|
}
|
||||||
@ -159,6 +213,13 @@ export class TypedDataEncoder {
|
|||||||
|
|
||||||
readonly #encoderCache: Map<string, (value: any) => string>;
|
readonly #encoderCache: Map<string, (value: any) => string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new **TypedDataEncoder** for %%types%%.
|
||||||
|
*
|
||||||
|
* This performs all necessary checking that types are valid and
|
||||||
|
* do not violate the [[link-eip-712]] structural constraints as
|
||||||
|
* well as computes the [[primaryType]].
|
||||||
|
*/
|
||||||
constructor(types: Record<string, Array<TypedDataField>>) {
|
constructor(types: Record<string, Array<TypedDataField>>) {
|
||||||
this.#types = JSON.stringify(types);
|
this.#types = JSON.stringify(types);
|
||||||
this.#fullTypes = new Map();
|
this.#fullTypes = new Map();
|
||||||
@ -241,6 +302,9 @@ export class TypedDataEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returnthe encoder for the specific %%type%%.
|
||||||
|
*/
|
||||||
getEncoder(type: string): (value: any) => string {
|
getEncoder(type: string): (value: any) => string {
|
||||||
let encoder = this.#encoderCache.get(type);
|
let encoder = this.#encoderCache.get(type);
|
||||||
if (!encoder) {
|
if (!encoder) {
|
||||||
@ -293,28 +357,46 @@ export class TypedDataEncoder {
|
|||||||
assertArgument(false, `unknown type: ${ type }`, "type", type);
|
assertArgument(false, `unknown type: ${ type }`, "type", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the full type for %%name%%.
|
||||||
|
*/
|
||||||
encodeType(name: string): string {
|
encodeType(name: string): string {
|
||||||
const result = this.#fullTypes.get(name);
|
const result = this.#fullTypes.get(name);
|
||||||
assertArgument(result, `unknown type: ${ JSON.stringify(name) }`, "name", name);
|
assertArgument(result, `unknown type: ${ JSON.stringify(name) }`, "name", name);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the encoded %%value%% for the %%type%%.
|
||||||
|
*/
|
||||||
encodeData(type: string, value: any): string {
|
encodeData(type: string, value: any): string {
|
||||||
return this.getEncoder(type)(value);
|
return this.getEncoder(type)(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hash of %%value%% for the type of %%name%%.
|
||||||
|
*/
|
||||||
hashStruct(name: string, value: Record<string, any>): string {
|
hashStruct(name: string, value: Record<string, any>): string {
|
||||||
return keccak256(this.encodeData(name, value));
|
return keccak256(this.encodeData(name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the fulled encoded %%value%% for the [[types]].
|
||||||
|
*/
|
||||||
encode(value: Record<string, any>): string {
|
encode(value: Record<string, any>): string {
|
||||||
return this.encodeData(this.primaryType, value);
|
return this.encodeData(this.primaryType, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the hash of the fully encoded %%value%% for the [[types]].
|
||||||
|
*/
|
||||||
hash(value: Record<string, any>): string {
|
hash(value: Record<string, any>): string {
|
||||||
return this.hashStruct(this.primaryType, value);
|
return this.hashStruct(this.primaryType, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
_visit(type: string, value: any, callback: (type: string, data: any) => any): any {
|
_visit(type: string, value: any, callback: (type: string, data: any) => any): any {
|
||||||
// Basic encoder type (address, bool, uint256, etc)
|
// Basic encoder type (address, bool, uint256, etc)
|
||||||
{
|
{
|
||||||
@ -341,22 +423,41 @@ export class TypedDataEncoder {
|
|||||||
assertArgument(false, `unknown type: ${ type }`, "type", type);
|
assertArgument(false, `unknown type: ${ type }`, "type", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call %%calback%% for each value in %%value%%, passing the type and
|
||||||
|
* component within %%value%%.
|
||||||
|
*
|
||||||
|
* This is useful for replacing addresses or other transformation that
|
||||||
|
* may be desired on each component, based on its type.
|
||||||
|
*/
|
||||||
visit(value: Record<string, any>, callback: (type: string, data: any) => any): any {
|
visit(value: Record<string, any>, callback: (type: string, data: any) => any): any {
|
||||||
return this._visit(this.primaryType, value, callback);
|
return this._visit(this.primaryType, value, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new **TypedDataEncoder** for %%types%%.
|
||||||
|
*/
|
||||||
static from(types: Record<string, Array<TypedDataField>>): TypedDataEncoder {
|
static from(types: Record<string, Array<TypedDataField>>): TypedDataEncoder {
|
||||||
return new TypedDataEncoder(types);
|
return new TypedDataEncoder(types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the primary type for %%types%%.
|
||||||
|
*/
|
||||||
static getPrimaryType(types: Record<string, Array<TypedDataField>>): string {
|
static getPrimaryType(types: Record<string, Array<TypedDataField>>): string {
|
||||||
return TypedDataEncoder.from(types).primaryType;
|
return TypedDataEncoder.from(types).primaryType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the hashed struct for %%value%% using %%types%% and %%name%%.
|
||||||
|
*/
|
||||||
static hashStruct(name: string, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
|
static hashStruct(name: string, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
|
||||||
return TypedDataEncoder.from(types).hashStruct(name, value);
|
return TypedDataEncoder.from(types).hashStruct(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the domain hash for %%domain%%.
|
||||||
|
*/
|
||||||
static hashDomain(domain: TypedDataDomain): string {
|
static hashDomain(domain: TypedDataDomain): string {
|
||||||
const domainFields: Array<TypedDataField> = [ ];
|
const domainFields: Array<TypedDataField> = [ ];
|
||||||
for (const name in domain) {
|
for (const name in domain) {
|
||||||
@ -373,6 +474,9 @@ export class TypedDataEncoder {
|
|||||||
return TypedDataEncoder.hashStruct("EIP712Domain", { EIP712Domain: domainFields }, domain);
|
return TypedDataEncoder.hashStruct("EIP712Domain", { EIP712Domain: domainFields }, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the fully encoded [[link-eip-712]] %%value%% for %%types%% with %%domain%%.
|
||||||
|
*/
|
||||||
static encode(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
|
static encode(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
|
||||||
return concat([
|
return concat([
|
||||||
"0x1901",
|
"0x1901",
|
||||||
@ -381,11 +485,18 @@ export class TypedDataEncoder {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the hash of the fully encoded [[link-eip-712]] %%value%% for %%types%% with %%domain%%.
|
||||||
|
*/
|
||||||
static hash(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
|
static hash(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
|
||||||
return keccak256(TypedDataEncoder.encode(domain, types, value));
|
return keccak256(TypedDataEncoder.encode(domain, types, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces all address types with ENS names with their looked up address
|
// Replaces all address types with ENS names with their looked up address
|
||||||
|
/**
|
||||||
|
* Resolves to the value from resolving all addresses in %%value%% for
|
||||||
|
* %%types%% and the %%domain%%.
|
||||||
|
*/
|
||||||
static async resolveNames(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>, resolveName: (name: string) => Promise<string>): Promise<{ domain: TypedDataDomain, value: any }> {
|
static async resolveNames(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>, resolveName: (name: string) => Promise<string>): Promise<{ domain: TypedDataDomain, value: any }> {
|
||||||
// Make a copy to isolate it from the object passed in
|
// Make a copy to isolate it from the object passed in
|
||||||
domain = Object.assign({ }, domain);
|
domain = Object.assign({ }, domain);
|
||||||
@ -435,6 +546,10 @@ export class TypedDataEncoder {
|
|||||||
return { domain, value };
|
return { domain, value };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the JSON-encoded payload expected by nodes which implement
|
||||||
|
* the JSON-RPC [[link-eip-712]] method.
|
||||||
|
*/
|
||||||
static getPayload(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): any {
|
static getPayload(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): any {
|
||||||
// Validate the domain fields
|
// Validate the domain fields
|
||||||
TypedDataEncoder.hashDomain(domain);
|
TypedDataEncoder.hashDomain(domain);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* About Subclassing the Provider...
|
* The available providers should suffice for most developers purposes,
|
||||||
|
* but the [[AbstractProvider]] class has many features which enable
|
||||||
|
* sub-classing it for specific purposes.
|
||||||
*
|
*
|
||||||
* @_section: api/providers/abstract-provider: Subclassing Provider [abstract-provider]
|
* @_section: api/providers/abstract-provider: Subclassing Provider [abstract-provider]
|
||||||
*/
|
*/
|
||||||
@ -86,6 +88,10 @@ function getTag(prefix: string, value: any): string {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of additional event values that can be emitted for the
|
||||||
|
* ``"debug"`` event.
|
||||||
|
*/
|
||||||
export type DebugEventAbstractProvider = {
|
export type DebugEventAbstractProvider = {
|
||||||
action: "sendCcipReadFetchRequest",
|
action: "sendCcipReadFetchRequest",
|
||||||
request: FetchRequest
|
request: FetchRequest
|
||||||
@ -113,7 +119,12 @@ export type DebugEventAbstractProvider = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Only sub-classes overriding the _getSubscription method will care about this
|
/**
|
||||||
|
* The value passed to the [[AbstractProvider-_getSubscriber]] method.
|
||||||
|
*
|
||||||
|
* Only developers sub-classing [[AbstractProvider[[ will care about this,
|
||||||
|
* if they are modifying a low-level feature of how subscriptions operate.
|
||||||
|
*/
|
||||||
export type Subscription = {
|
export type Subscription = {
|
||||||
type: "block" | "close" | "debug" | "error" | "network" | "pending",
|
type: "block" | "close" | "debug" | "error" | "network" | "pending",
|
||||||
tag: string
|
tag: string
|
||||||
@ -131,22 +142,59 @@ export type Subscription = {
|
|||||||
filter: OrphanFilter
|
filter: OrphanFilter
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **Subscriber** manages a subscription.
|
||||||
|
*
|
||||||
|
* Only developers sub-classing [[AbstractProvider[[ will care about this,
|
||||||
|
* if they are modifying a low-level feature of how subscriptions operate.
|
||||||
|
*/
|
||||||
export interface Subscriber {
|
export interface Subscriber {
|
||||||
|
/**
|
||||||
|
* Called initially when a subscriber is added the first time.
|
||||||
|
*/
|
||||||
start(): void;
|
start(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when there are no more subscribers to the event.
|
||||||
|
*/
|
||||||
stop(): void;
|
stop(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the subscription should pause.
|
||||||
|
*
|
||||||
|
* If %%dropWhilePaused%%, events that occur while paused should not
|
||||||
|
* be emitted [[resume]].
|
||||||
|
*/
|
||||||
pause(dropWhilePaused?: boolean): void;
|
pause(dropWhilePaused?: boolean): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resume a paused subscriber.
|
||||||
|
*/
|
||||||
resume(): void;
|
resume(): void;
|
||||||
|
|
||||||
// Subscribers which use polling should implement this to allow
|
/**
|
||||||
// Providers the ability to update underlying polling intervals
|
* The frequency (in ms) to poll for events, if polling is used by
|
||||||
// If not supported, accessing this property should return undefined
|
* the subscriber.
|
||||||
|
*
|
||||||
|
* For non-polling subscribers, this must return ``undefined``.
|
||||||
|
*/
|
||||||
pollingInterval?: number;
|
pollingInterval?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An **UnmanagedSubscriber** is useful for events which do not require
|
||||||
|
* any additional management, such as ``"debug"`` which only requires
|
||||||
|
* emit in synchronous event loop triggered calls.
|
||||||
|
*/
|
||||||
export class UnmanagedSubscriber implements Subscriber {
|
export class UnmanagedSubscriber implements Subscriber {
|
||||||
|
/**
|
||||||
|
* The name fof the event.
|
||||||
|
*/
|
||||||
name!: string;
|
name!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new UnmanagedSubscriber with %%name%%.
|
||||||
|
*/
|
||||||
constructor(name: string) { defineProperties<UnmanagedSubscriber>(this, { name }); }
|
constructor(name: string) { defineProperties<UnmanagedSubscriber>(this, { name }); }
|
||||||
|
|
||||||
start(): void { }
|
start(): void { }
|
||||||
@ -247,11 +295,26 @@ async function getSubscription(_event: ProviderEvent, provider: AbstractProvider
|
|||||||
|
|
||||||
function getTime(): number { return (new Date()).getTime(); }
|
function getTime(): number { return (new Date()).getTime(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An **AbstractPlugin** is used to provide additional internal services
|
||||||
|
* to an [[AbstractProvider]] without adding backwards-incompatible changes
|
||||||
|
* to method signatures or other internal and complex logic.
|
||||||
|
*/
|
||||||
export interface AbstractProviderPlugin {
|
export interface AbstractProviderPlugin {
|
||||||
|
/**
|
||||||
|
* The reverse domain notation of the plugin.
|
||||||
|
*/
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of the plugin, connected to %%provider%%.
|
||||||
|
*/
|
||||||
connect(provider: AbstractProvider): AbstractProviderPlugin;
|
connect(provider: AbstractProvider): AbstractProviderPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A normalized filter used for [[PerformActionRequest]] objects.
|
||||||
|
*/
|
||||||
export type PerformActionFilter = {
|
export type PerformActionFilter = {
|
||||||
address?: string | Array<string>;
|
address?: string | Array<string>;
|
||||||
topics?: Array<null | string | Array<string>>;
|
topics?: Array<null | string | Array<string>>;
|
||||||
@ -263,11 +326,25 @@ export type PerformActionFilter = {
|
|||||||
blockHash?: string;
|
blockHash?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A normalized transactions used for [[PerformActionRequest]] objects.
|
||||||
|
*/
|
||||||
export interface PerformActionTransaction extends PreparedTransactionRequest {
|
export interface PerformActionTransaction extends PreparedTransactionRequest {
|
||||||
|
/**
|
||||||
|
* The ``to`` address of the transaction.
|
||||||
|
*/
|
||||||
to?: string;
|
to?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sender of the transaction.
|
||||||
|
*/
|
||||||
from?: string;
|
from?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[AbstractProvider]] methods will normalize all values and pass this
|
||||||
|
* type to [[AbstractProvider-_perform]].
|
||||||
|
*/
|
||||||
export type PerformActionRequest = {
|
export type PerformActionRequest = {
|
||||||
method: "broadcastTransaction",
|
method: "broadcastTransaction",
|
||||||
signedTransaction: string
|
signedTransaction: string
|
||||||
@ -330,7 +407,12 @@ type CcipArgs = {
|
|||||||
errorArgs: Array<any>
|
errorArgs: Array<any>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An **AbstractProvider** provides a base class for other sub-classes to
|
||||||
|
* implement the [[Provider]] API by normalizing input arguments and
|
||||||
|
* formatting output results as well as tracking events for consistent
|
||||||
|
* behaviour on an eventually-consistent network.
|
||||||
|
*/
|
||||||
export class AbstractProvider implements Provider {
|
export class AbstractProvider implements Provider {
|
||||||
|
|
||||||
#subs: Map<string, Sub>;
|
#subs: Map<string, Sub>;
|
||||||
@ -352,8 +434,11 @@ export class AbstractProvider implements Provider {
|
|||||||
|
|
||||||
#disableCcipRead: boolean;
|
#disableCcipRead: boolean;
|
||||||
|
|
||||||
// @TODO: This should be a () => Promise<Network> so network can be
|
/**
|
||||||
// done when needed; or rely entirely on _detectNetwork?
|
* Create a new **AbstractProvider** connected to %%network%%, or
|
||||||
|
* use the various network detection capabilities to discover the
|
||||||
|
* [[Network]] if necessary.
|
||||||
|
*/
|
||||||
constructor(_network?: "any" | Networkish) {
|
constructor(_network?: "any" | Networkish) {
|
||||||
|
|
||||||
if (_network === "any") {
|
if (_network === "any") {
|
||||||
@ -383,12 +468,22 @@ export class AbstractProvider implements Provider {
|
|||||||
this.#disableCcipRead = false;
|
this.#disableCcipRead = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``this``, to allow an **AbstractProvider** to implement
|
||||||
|
* the [[ContractRunner]] interface.
|
||||||
|
*/
|
||||||
get provider(): this { return this; }
|
get provider(): this { return this; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the registered plug-ins.
|
||||||
|
*/
|
||||||
get plugins(): Array<AbstractProviderPlugin> {
|
get plugins(): Array<AbstractProviderPlugin> {
|
||||||
return Array.from(this.#plugins.values());
|
return Array.from(this.#plugins.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach a new plug-in.
|
||||||
|
*/
|
||||||
attachPlugin(plugin: AbstractProviderPlugin): this {
|
attachPlugin(plugin: AbstractProviderPlugin): this {
|
||||||
if (this.#plugins.get(plugin.name)) {
|
if (this.#plugins.get(plugin.name)) {
|
||||||
throw new Error(`cannot replace existing plugin: ${ plugin.name } `);
|
throw new Error(`cannot replace existing plugin: ${ plugin.name } `);
|
||||||
@ -397,10 +492,17 @@ export class AbstractProvider implements Provider {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a plugin by name.
|
||||||
|
*/
|
||||||
getPlugin<T extends AbstractProviderPlugin = AbstractProviderPlugin>(name: string): null | T {
|
getPlugin<T extends AbstractProviderPlugin = AbstractProviderPlugin>(name: string): null | T {
|
||||||
return <T>(this.#plugins.get(name)) || null;
|
return <T>(this.#plugins.get(name)) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent any CCIP-read operation, regardless of whether requested
|
||||||
|
* in a [[call]] using ``enableCcipRead``.
|
||||||
|
*/
|
||||||
get disableCcipRead(): boolean { return this.#disableCcipRead; }
|
get disableCcipRead(): boolean { return this.#disableCcipRead; }
|
||||||
set disableCcipRead(value: boolean) { this.#disableCcipRead = !!value; }
|
set disableCcipRead(value: boolean) { this.#disableCcipRead = !!value; }
|
||||||
|
|
||||||
@ -424,6 +526,9 @@ export class AbstractProvider implements Provider {
|
|||||||
return await perform;
|
return await perform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the data for executing the CCIP-read operations.
|
||||||
|
*/
|
||||||
async ccipReadFetch(tx: PerformActionTransaction, calldata: string, urls: Array<string>): Promise<null | string> {
|
async ccipReadFetch(tx: PerformActionTransaction, calldata: string, urls: Array<string>): Promise<null | string> {
|
||||||
if (this.disableCcipRead || urls.length === 0 || tx.to == null) { return null; }
|
if (this.disableCcipRead || urls.length === 0 || tx.to == null) { return null; }
|
||||||
|
|
||||||
@ -479,30 +584,60 @@ export class AbstractProvider implements Provider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the opportunity for a sub-class to wrap a block before
|
||||||
|
* returning it, to add additional properties or an alternate
|
||||||
|
* sub-class of [[Block]].
|
||||||
|
*/
|
||||||
_wrapBlock(value: BlockParams, network: Network): Block {
|
_wrapBlock(value: BlockParams, network: Network): Block {
|
||||||
return new Block(formatBlock(value), this);
|
return new Block(formatBlock(value), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the opportunity for a sub-class to wrap a log before
|
||||||
|
* returning it, to add additional properties or an alternate
|
||||||
|
* sub-class of [[Log]].
|
||||||
|
*/
|
||||||
_wrapLog(value: LogParams, network: Network): Log {
|
_wrapLog(value: LogParams, network: Network): Log {
|
||||||
return new Log(formatLog(value), this);
|
return new Log(formatLog(value), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the opportunity for a sub-class to wrap a transaction
|
||||||
|
* receipt before returning it, to add additional properties or an
|
||||||
|
* alternate sub-class of [[TransactionReceipt]].
|
||||||
|
*/
|
||||||
_wrapTransactionReceipt(value: TransactionReceiptParams, network: Network): TransactionReceipt {
|
_wrapTransactionReceipt(value: TransactionReceiptParams, network: Network): TransactionReceipt {
|
||||||
return new TransactionReceipt(formatTransactionReceipt(value), this);
|
return new TransactionReceipt(formatTransactionReceipt(value), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the opportunity for a sub-class to wrap a transaction
|
||||||
|
* response before returning it, to add additional properties or an
|
||||||
|
* alternate sub-class of [[TransactionResponse]].
|
||||||
|
*/
|
||||||
_wrapTransactionResponse(tx: TransactionResponseParams, network: Network): TransactionResponse {
|
_wrapTransactionResponse(tx: TransactionResponseParams, network: Network): TransactionResponse {
|
||||||
return new TransactionResponse(formatTransactionResponse(tx), this);
|
return new TransactionResponse(formatTransactionResponse(tx), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the Network, forcing a network detection using whatever
|
||||||
|
* technique the sub-class requires.
|
||||||
|
*
|
||||||
|
* Sub-classes **must** override this.
|
||||||
|
*/
|
||||||
_detectNetwork(): Promise<Network> {
|
_detectNetwork(): Promise<Network> {
|
||||||
assert(false, "sub-classes must implement this", "UNSUPPORTED_OPERATION", {
|
assert(false, "sub-classes must implement this", "UNSUPPORTED_OPERATION", {
|
||||||
operation: "_detectNetwork"
|
operation: "_detectNetwork"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub-classes should override this and handle PerformActionRequest requests, calling
|
/**
|
||||||
// the super for any unhandled actions.
|
* Sub-classes should use this to perform all built-in operations. All
|
||||||
|
* methods sanitizes and normalizes the values passed into this.
|
||||||
|
*
|
||||||
|
* Sub-classes **must** override this.
|
||||||
|
*/
|
||||||
async _perform<T = any>(req: PerformActionRequest): Promise<T> {
|
async _perform<T = any>(req: PerformActionRequest): Promise<T> {
|
||||||
assert(false, `unsupported method: ${ req.method }`, "UNSUPPORTED_OPERATION", {
|
assert(false, `unsupported method: ${ req.method }`, "UNSUPPORTED_OPERATION", {
|
||||||
operation: req.method,
|
operation: req.method,
|
||||||
@ -511,16 +646,26 @@ export class AbstractProvider implements Provider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
async getBlockNumber(): Promise<number> {
|
async getBlockNumber(): Promise<number> {
|
||||||
const blockNumber = getNumber(await this.#perform({ method: "getBlockNumber" }), "%response");
|
const blockNumber = getNumber(await this.#perform({ method: "getBlockNumber" }), "%response");
|
||||||
if (this.#lastBlockNumber >= 0) { this.#lastBlockNumber = blockNumber; }
|
if (this.#lastBlockNumber >= 0) { this.#lastBlockNumber = blockNumber; }
|
||||||
return blockNumber;
|
return blockNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns or resolves to the address for %%address%%, resolving ENS
|
||||||
|
* names and [[Addressable]] objects and returning if already an
|
||||||
|
* address.
|
||||||
|
*/
|
||||||
_getAddress(address: AddressLike): string | Promise<string> {
|
_getAddress(address: AddressLike): string | Promise<string> {
|
||||||
return resolveAddress(address, this);
|
return resolveAddress(address, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns or resolves to a valid block tag for %%blockTag%%, resolving
|
||||||
|
* negative values and returning if already a valid block tag.
|
||||||
|
*/
|
||||||
_getBlockTag(blockTag?: BlockTag): string | Promise<string> {
|
_getBlockTag(blockTag?: BlockTag): string | Promise<string> {
|
||||||
if (blockTag == null) { return "latest"; }
|
if (blockTag == null) { return "latest"; }
|
||||||
|
|
||||||
@ -550,6 +695,11 @@ export class AbstractProvider implements Provider {
|
|||||||
assertArgument(false, "invalid blockTag", "blockTag", blockTag);
|
assertArgument(false, "invalid blockTag", "blockTag", blockTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns or resolves to a filter for %%filter%%, resolving any ENS
|
||||||
|
* names or [[Addressable]] object and returning if already a valid
|
||||||
|
* filter.
|
||||||
|
*/
|
||||||
_getFilter(filter: Filter | FilterByBlockHash): PerformActionFilter | Promise<PerformActionFilter> {
|
_getFilter(filter: Filter | FilterByBlockHash): PerformActionFilter | Promise<PerformActionFilter> {
|
||||||
|
|
||||||
// Create a canonical representation of the topics
|
// Create a canonical representation of the topics
|
||||||
@ -619,6 +769,11 @@ export class AbstractProvider implements Provider {
|
|||||||
return resolve(<Array<string>>address, fromBlock, toBlock);
|
return resolve(<Array<string>>address, fromBlock, toBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns or resovles to a transaction for %%request%%, resolving
|
||||||
|
* any ENS names or [[Addressable]] and returning if already a valid
|
||||||
|
* transaction.
|
||||||
|
*/
|
||||||
_getTransactionRequest(_request: TransactionRequest): PerformActionTransaction | Promise<PerformActionTransaction> {
|
_getTransactionRequest(_request: TransactionRequest): PerformActionTransaction | Promise<PerformActionTransaction> {
|
||||||
const request = <PerformActionTransaction>copyRequest(_request);
|
const request = <PerformActionTransaction>copyRequest(_request);
|
||||||
|
|
||||||
@ -1059,6 +1214,9 @@ export class AbstractProvider implements Provider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear a timer created using the [[_setTimeout]] method.
|
||||||
|
*/
|
||||||
_clearTimeout(timerId: number): void {
|
_clearTimeout(timerId: number): void {
|
||||||
const timer = this.#timers.get(timerId);
|
const timer = this.#timers.get(timerId);
|
||||||
if (!timer) { return; }
|
if (!timer) { return; }
|
||||||
@ -1066,6 +1224,14 @@ export class AbstractProvider implements Provider {
|
|||||||
this.#timers.delete(timerId);
|
this.#timers.delete(timerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a timer that will execute %%func%% after at least %%timeout%%
|
||||||
|
* (in ms). If %%timeout%% is unspecified, then %%func%% will execute
|
||||||
|
* in the next event loop.
|
||||||
|
*
|
||||||
|
* [Pausing](AbstractProvider-paused) the provider will pause any
|
||||||
|
* associated timers.
|
||||||
|
*/
|
||||||
_setTimeout(_func: () => void, timeout?: number): number {
|
_setTimeout(_func: () => void, timeout?: number): number {
|
||||||
if (timeout == null) { timeout = 0; }
|
if (timeout == null) { timeout = 0; }
|
||||||
const timerId = this.#nextTimer++;
|
const timerId = this.#nextTimer++;
|
||||||
@ -1084,14 +1250,19 @@ export class AbstractProvider implements Provider {
|
|||||||
return timerId;
|
return timerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform %%func%% on each subscriber.
|
||||||
|
*/
|
||||||
_forEachSubscriber(func: (s: Subscriber) => void): void {
|
_forEachSubscriber(func: (s: Subscriber) => void): void {
|
||||||
for (const sub of this.#subs.values()) {
|
for (const sub of this.#subs.values()) {
|
||||||
func(sub.subscriber);
|
func(sub.subscriber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event API; sub-classes should override this; any supported
|
/**
|
||||||
// event filter will have been munged into an EventFilter
|
* Sub-classes may override this to customize subscription
|
||||||
|
* implementations.
|
||||||
|
*/
|
||||||
_getSubscriber(sub: Subscription): Subscriber {
|
_getSubscriber(sub: Subscription): Subscriber {
|
||||||
switch (sub.type) {
|
switch (sub.type) {
|
||||||
case "debug":
|
case "debug":
|
||||||
@ -1111,6 +1282,15 @@ export class AbstractProvider implements Provider {
|
|||||||
throw new Error(`unsupported event: ${ sub.type }`);
|
throw new Error(`unsupported event: ${ sub.type }`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a [[Subscriber]] fails and needs to replace itself, this
|
||||||
|
* method may be used.
|
||||||
|
*
|
||||||
|
* For example, this is used for providers when using the
|
||||||
|
* ``eth_getFilterChanges`` method, which can return null if state
|
||||||
|
* filters are not supported by the backend, allowing the Subscriber
|
||||||
|
* to swap in a [[PollingEventSubscriber]].
|
||||||
|
*/
|
||||||
_recoverSubscriber(oldSub: Subscriber, newSub: Subscriber): void {
|
_recoverSubscriber(oldSub: Subscriber, newSub: Subscriber): void {
|
||||||
for (const sub of this.#subs.values()) {
|
for (const sub of this.#subs.values()) {
|
||||||
if (sub.subscriber === oldSub) {
|
if (sub.subscriber === oldSub) {
|
||||||
@ -1265,8 +1445,12 @@ export class AbstractProvider implements Provider {
|
|||||||
return this.off(event, listener);
|
return this.off(event, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub-classes should override this to shutdown any sockets, etc.
|
/**
|
||||||
// but MUST call this super.shutdown.
|
* Sub-classes may use this to shutdown any sockets or release their
|
||||||
|
* resources.
|
||||||
|
*
|
||||||
|
* Sub-classes **must** call ``super.destroy()``.
|
||||||
|
*/
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
// Stop all listeners
|
// Stop all listeners
|
||||||
this.removeAllListeners();
|
this.removeAllListeners();
|
||||||
@ -1277,6 +1461,17 @@ export class AbstractProvider implements Provider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the provider is currently paused.
|
||||||
|
*
|
||||||
|
* A paused provider will not emit any events, and generally should
|
||||||
|
* not make any requests to the network, but that is up to sub-classes
|
||||||
|
* to manage.
|
||||||
|
*
|
||||||
|
* Setting ``paused = true`` is identical to calling ``.pause(false)``,
|
||||||
|
* which will buffer any events that occur while paused until the
|
||||||
|
* provider is unpaused.
|
||||||
|
*/
|
||||||
get paused(): boolean { return (this.#pausedState != null); }
|
get paused(): boolean { return (this.#pausedState != null); }
|
||||||
set paused(pause: boolean) {
|
set paused(pause: boolean) {
|
||||||
if (!!pause === this.paused) { return; }
|
if (!!pause === this.paused) { return; }
|
||||||
@ -1288,6 +1483,11 @@ export class AbstractProvider implements Provider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause the provider. If %%dropWhilePaused%%, any events that occur
|
||||||
|
* while paused are dropped, otherwise all events will be emitted once
|
||||||
|
* the provider is unpaused.
|
||||||
|
*/
|
||||||
pause(dropWhilePaused?: boolean): void {
|
pause(dropWhilePaused?: boolean): void {
|
||||||
this.#lastBlockNumber = -1;
|
this.#lastBlockNumber = -1;
|
||||||
|
|
||||||
@ -1310,6 +1510,9 @@ export class AbstractProvider implements Provider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resume the provider.
|
||||||
|
*/
|
||||||
resume(): void {
|
resume(): void {
|
||||||
if (this.#pausedState == null) { return; }
|
if (this.#pausedState == null) { return; }
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* About Abstract Signer and subclassing
|
* Generally the [[Wallet]] and [[JsonRpcSigner]] and their sub-classes
|
||||||
|
* are sufficent for most developers, but this is provided to
|
||||||
|
* fascilitate more complex Signers.
|
||||||
*
|
*
|
||||||
* @_section: api/providers/abstract-signer: Subclassing Signer [abstract-signer]
|
* @_section: api/providers/abstract-signer: Subclassing Signer [abstract-signer]
|
||||||
*/
|
*/
|
||||||
@ -49,14 +51,36 @@ async function populate(signer: AbstractSigner, tx: TransactionRequest): Promise
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An **AbstractSigner** includes most of teh functionality required
|
||||||
|
* to get a [[Signer]] working as expected, but requires a few
|
||||||
|
* Signer-specific methods be overridden.
|
||||||
|
*
|
||||||
|
*/
|
||||||
export abstract class AbstractSigner<P extends null | Provider = null | Provider> implements Signer {
|
export abstract class AbstractSigner<P extends null | Provider = null | Provider> implements Signer {
|
||||||
|
/**
|
||||||
|
* The provider this signer is connected to.
|
||||||
|
*/
|
||||||
readonly provider!: P;
|
readonly provider!: P;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Signer connected to %%provider%%.
|
||||||
|
*/
|
||||||
constructor(provider?: P) {
|
constructor(provider?: P) {
|
||||||
defineProperties<AbstractSigner>(this, { provider: (provider || null) });
|
defineProperties<AbstractSigner>(this, { provider: (provider || null) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the Signer address.
|
||||||
|
*/
|
||||||
abstract getAddress(): Promise<string>;
|
abstract getAddress(): Promise<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the signer connected to %%provider%%.
|
||||||
|
*
|
||||||
|
* This may throw, for example, a Signer connected over a Socket or
|
||||||
|
* to a specific instance of a node may not be transferrable.
|
||||||
|
*/
|
||||||
abstract connect(provider: null | Provider): Signer;
|
abstract connect(provider: null | Provider): Signer;
|
||||||
|
|
||||||
async getNonce(blockTag?: BlockTag): Promise<number> {
|
async getNonce(blockTag?: BlockTag): Promise<number> {
|
||||||
@ -216,9 +240,24 @@ export abstract class AbstractSigner<P extends null | Provider = null | Provider
|
|||||||
abstract signTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): Promise<string>;
|
abstract signTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): Promise<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **VoidSigner** is a class deisgned to allow an address to be used
|
||||||
|
* in any API which accepts a Signer, but for which there are no
|
||||||
|
* credentials available to perform any actual signing.
|
||||||
|
*
|
||||||
|
* This for example allow impersonating an account for the purpose of
|
||||||
|
* static calls or estimating gas, but does not allow sending transactions.
|
||||||
|
*/
|
||||||
export class VoidSigner extends AbstractSigner {
|
export class VoidSigner extends AbstractSigner {
|
||||||
|
/**
|
||||||
|
* The signer address.
|
||||||
|
*/
|
||||||
readonly address!: string;
|
readonly address!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **VoidSigner** with %%address%% attached to
|
||||||
|
* %%provider%%.
|
||||||
|
*/
|
||||||
constructor(address: string, provider?: null | Provider) {
|
constructor(address: string, provider?: null | Provider) {
|
||||||
super(provider);
|
super(provider);
|
||||||
defineProperties<VoidSigner>(this, { address });
|
defineProperties<VoidSigner>(this, { address });
|
||||||
|
@ -2,20 +2,41 @@ import type {
|
|||||||
Provider, TransactionRequest, TransactionResponse
|
Provider, TransactionRequest, TransactionResponse
|
||||||
} from "./provider.js";
|
} from "./provider.js";
|
||||||
|
|
||||||
// The object that will be used to run Contracts. The Signer and Provider
|
/**
|
||||||
// both adhere to this, but other types of objects may wish to as well.
|
* A **ContractRunner** is a generic interface which defines an object
|
||||||
|
* capable of interacting with a Contract on the network.
|
||||||
|
*
|
||||||
|
* The more operations supported, the more utility it is capable of.
|
||||||
|
*
|
||||||
|
* The most common ContractRunners are [Providers](Provider) which enable
|
||||||
|
* read-only access and [Signers](Signer) which enable write-access.
|
||||||
|
*/
|
||||||
export interface ContractRunner {
|
export interface ContractRunner {
|
||||||
|
/**
|
||||||
|
* The provider used for necessary state querying operations.
|
||||||
|
*
|
||||||
|
* This can also point to the **ContractRunner** itself, in the
|
||||||
|
* case of an [[AbstractProvider]].
|
||||||
|
*/
|
||||||
provider: null | Provider;
|
provider: null | Provider;
|
||||||
|
|
||||||
// Required to estimate gas; usually a Signer or Provider
|
/**
|
||||||
|
* Required to estimate gas.
|
||||||
|
*/
|
||||||
estimateGas?: (tx: TransactionRequest) => Promise<bigint>;
|
estimateGas?: (tx: TransactionRequest) => Promise<bigint>;
|
||||||
|
|
||||||
// Required for pure, view or static calls to contracts; usually a Signer or Provider
|
/**
|
||||||
|
* Required for pure, view or static calls to contracts.
|
||||||
|
*/
|
||||||
call?: (tx: TransactionRequest) => Promise<string>;
|
call?: (tx: TransactionRequest) => Promise<string>;
|
||||||
|
|
||||||
// Required to support ENS names; usually a Signer or Provider
|
/**
|
||||||
|
* Required to support ENS names
|
||||||
|
*/
|
||||||
resolveName?: (name: string) => Promise<null | string>;
|
resolveName?: (name: string) => Promise<null | string>;
|
||||||
|
|
||||||
// Required for mutating calls; usually a Signer
|
/**
|
||||||
|
* Required for state mutating calls
|
||||||
|
*/
|
||||||
sendTransaction?: (tx: TransactionRequest) => Promise<TransactionResponse>;
|
sendTransaction?: (tx: TransactionRequest) => Promise<TransactionResponse>;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* About ENS Resolver
|
* ENS is a service which allows easy-to-remember names to map to
|
||||||
|
* network addresses.
|
||||||
*
|
*
|
||||||
* @_section: api/providers/ens-resolver:ENS Resolver [about-ens-rsolver]
|
* @_section: api/providers/ens-resolver:ENS Resolver [about-ens-rsolver]
|
||||||
*/
|
*/
|
||||||
@ -50,7 +51,14 @@ export type AvatarLinkageType = "name" | "avatar" | "!avatar" | "url" | "data" |
|
|||||||
* An individual record for each step during avatar resolution.
|
* An individual record for each step during avatar resolution.
|
||||||
*/
|
*/
|
||||||
export interface AvatarLinkage {
|
export interface AvatarLinkage {
|
||||||
|
/**
|
||||||
|
* The type of linkage.
|
||||||
|
*/
|
||||||
type: AvatarLinkageType;
|
type: AvatarLinkageType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The linkage value.
|
||||||
|
*/
|
||||||
value: string;
|
value: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,7 +71,17 @@ export interface AvatarLinkage {
|
|||||||
* each completed step during avatar resolution.
|
* each completed step during avatar resolution.
|
||||||
*/
|
*/
|
||||||
export interface AvatarResult {
|
export interface AvatarResult {
|
||||||
|
/**
|
||||||
|
* How the [[url]] was arrived at, resolving the many steps required
|
||||||
|
* for an avatar URL.
|
||||||
|
*/
|
||||||
linkage: Array<AvatarLinkage>;
|
linkage: Array<AvatarLinkage>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The avatar URL or null if the avatar was not set, or there was
|
||||||
|
* an issue during validation (such as the address not owning the
|
||||||
|
* avatar or a metadata error).
|
||||||
|
*/
|
||||||
url: null | string;
|
url: null | string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -71,8 +89,14 @@ export interface AvatarResult {
|
|||||||
* A provider plugin super-class for processing multicoin address types.
|
* A provider plugin super-class for processing multicoin address types.
|
||||||
*/
|
*/
|
||||||
export abstract class MulticoinProviderPlugin implements AbstractProviderPlugin {
|
export abstract class MulticoinProviderPlugin implements AbstractProviderPlugin {
|
||||||
|
/**
|
||||||
|
* The name.
|
||||||
|
*/
|
||||||
readonly name!: string;
|
readonly name!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **MulticoinProviderPluing** for %%name%%.
|
||||||
|
*/
|
||||||
constructor(name: string) {
|
constructor(name: string) {
|
||||||
defineProperties<MulticoinProviderPlugin>(this, { name });
|
defineProperties<MulticoinProviderPlugin>(this, { name });
|
||||||
}
|
}
|
||||||
@ -81,14 +105,23 @@ export abstract class MulticoinProviderPlugin implements AbstractProviderPlugin
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ``true`` if %%coinType%% is supported by this plugin.
|
||||||
|
*/
|
||||||
supportsCoinType(coinType: number): boolean {
|
supportsCoinType(coinType: number): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resovles to the encoded %%address%% for %%coinType%%.
|
||||||
|
*/
|
||||||
async encodeAddress(coinType: number, address: string): Promise<string> {
|
async encodeAddress(coinType: number, address: string): Promise<string> {
|
||||||
throw new Error("unsupported coin");
|
throw new Error("unsupported coin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resovles to the decoded %%data%% for %%coinType%%.
|
||||||
|
*/
|
||||||
async decodeAddress(coinType: number, data: BytesLike): Promise<string> {
|
async decodeAddress(coinType: number, data: BytesLike): Promise<string> {
|
||||||
throw new Error("unsupported coin");
|
throw new Error("unsupported coin");
|
||||||
}
|
}
|
||||||
@ -97,9 +130,14 @@ export abstract class MulticoinProviderPlugin implements AbstractProviderPlugin
|
|||||||
const BasicMulticoinPluginId = "org.ethers.plugins.provider.BasicMulticoin";
|
const BasicMulticoinPluginId = "org.ethers.plugins.provider.BasicMulticoin";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic multicoin provider plugin.
|
* A **BasicMulticoinProviderPlugin** provides service for common
|
||||||
|
* coin types, which do not require additional libraries to encode or
|
||||||
|
* decode.
|
||||||
*/
|
*/
|
||||||
export class BasicMulticoinProviderPlugin extends MulticoinProviderPlugin {
|
export class BasicMulticoinProviderPlugin extends MulticoinProviderPlugin {
|
||||||
|
/**
|
||||||
|
* Creates a new **BasicMulticoinProviderPlugin**.
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
super(BasicMulticoinPluginId);
|
super(BasicMulticoinPluginId);
|
||||||
}
|
}
|
||||||
|
@ -7,86 +7,78 @@
|
|||||||
import type { Signature } from "../crypto/index.js";
|
import type { Signature } from "../crypto/index.js";
|
||||||
import type { AccessList } from "../transaction/index.js";
|
import type { AccessList } from "../transaction/index.js";
|
||||||
|
|
||||||
/*
|
|
||||||
export interface TransactionRequest {
|
|
||||||
type?: null | number;
|
|
||||||
|
|
||||||
to?: null | AddressLike;
|
|
||||||
from?: null | AddressLike;
|
|
||||||
|
|
||||||
nonce?: null | number;
|
|
||||||
|
|
||||||
gasLimit?: null | BigNumberish;
|
|
||||||
gasPrice?: null | BigNumberish;
|
|
||||||
|
|
||||||
maxPriorityFeePerGas?: null | BigNumberish;
|
|
||||||
maxFeePerGas?: null | BigNumberish;
|
|
||||||
|
|
||||||
data?: null | string;
|
|
||||||
value?: null | BigNumberish;
|
|
||||||
chainId?: null | BigNumberish;
|
|
||||||
|
|
||||||
accessList?: null | AccessListish;
|
|
||||||
|
|
||||||
customData?: any;
|
|
||||||
|
|
||||||
// Only meaningful when used for call
|
|
||||||
blockTag?: BlockTag;
|
|
||||||
enableCcipRead?: boolean;
|
|
||||||
|
|
||||||
// Todo?
|
|
||||||
//gasMultiplier?: number;
|
|
||||||
};
|
|
||||||
export interface PreparedTransactionRequest {
|
|
||||||
type?: number;
|
|
||||||
|
|
||||||
to?: AddressLike;
|
|
||||||
from?: AddressLike;
|
|
||||||
|
|
||||||
nonce?: number;
|
|
||||||
|
|
||||||
gasLimit?: bigint;
|
|
||||||
gasPrice?: bigint;
|
|
||||||
|
|
||||||
maxPriorityFeePerGas?: bigint;
|
|
||||||
maxFeePerGas?: bigint;
|
|
||||||
|
|
||||||
data?: string;
|
|
||||||
value?: bigint;
|
|
||||||
chainId?: bigint;
|
|
||||||
|
|
||||||
accessList?: AccessList;
|
|
||||||
|
|
||||||
customData?: any;
|
|
||||||
|
|
||||||
blockTag?: BlockTag;
|
|
||||||
enableCcipRead?: boolean;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
// Block
|
// Block
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a **BlockParams** encodes the minimal required properties for a
|
||||||
|
* formatted block.
|
||||||
|
*/
|
||||||
export interface BlockParams {
|
export interface BlockParams {
|
||||||
|
/**
|
||||||
|
* The block hash.
|
||||||
|
*/
|
||||||
hash?: null | string;
|
hash?: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block number.
|
||||||
|
*/
|
||||||
number: number;
|
number: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The timestamp for this block, which is the number of seconds
|
||||||
|
* since epoch that this block was included.
|
||||||
|
*/
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hash of the previous block in the blockchain. The genesis block
|
||||||
|
* has the parentHash of the [[ZeroHash]].
|
||||||
|
*/
|
||||||
parentHash: string;
|
parentHash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A random sequence provided during the mining process for
|
||||||
|
* proof-of-work networks.
|
||||||
|
*/
|
||||||
nonce: string;
|
nonce: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For proof-of-work networks, the difficulty target is used to
|
||||||
|
* adjust the difficulty in mining to ensure a expected block rate.
|
||||||
|
*/
|
||||||
difficulty: bigint;
|
difficulty: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum amount of gas a block can consume.
|
||||||
|
*/
|
||||||
gasLimit: bigint;
|
gasLimit: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of gas a block consumed.
|
||||||
|
*/
|
||||||
gasUsed: bigint;
|
gasUsed: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The miner (or author) of a block.
|
||||||
|
*/
|
||||||
miner: string;
|
miner: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional data the miner choose to include.
|
||||||
|
*/
|
||||||
extraData: string;
|
extraData: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The protocol-defined base fee per gas in an [[link-eip-1559]]
|
||||||
|
* block.
|
||||||
|
*/
|
||||||
baseFeePerGas: null | bigint;
|
baseFeePerGas: null | bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of transactions in the block.
|
||||||
|
*/
|
||||||
transactions: ReadonlyArray<string | TransactionResponseParams>;
|
transactions: ReadonlyArray<string | TransactionResponseParams>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -94,19 +86,57 @@ export interface BlockParams {
|
|||||||
//////////////////////
|
//////////////////////
|
||||||
// Log
|
// Log
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a **LogParams** encodes the minimal required properties for a
|
||||||
|
* formatted log.
|
||||||
|
*/
|
||||||
export interface LogParams {
|
export interface LogParams {
|
||||||
|
/**
|
||||||
|
* The transaction hash for the transaxction the log occurred in.
|
||||||
|
*/
|
||||||
transactionHash: string;
|
transactionHash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block hash of the block that included the transaction for this
|
||||||
|
* log.
|
||||||
|
*/
|
||||||
blockHash: string;
|
blockHash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block number of the block that included the transaction for this
|
||||||
|
* log.
|
||||||
|
*/
|
||||||
blockNumber: number;
|
blockNumber: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this log was removed due to the transaction it was included
|
||||||
|
* in being removed dur to an orphaned block.
|
||||||
|
*/
|
||||||
removed: boolean;
|
removed: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The address of the contract that emitted this log.
|
||||||
|
*/
|
||||||
address: string;
|
address: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data emitted with this log.
|
||||||
|
*/
|
||||||
data: string;
|
data: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The topics emitted with this log.
|
||||||
|
*/
|
||||||
topics: ReadonlyArray<string>;
|
topics: ReadonlyArray<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index of this log.
|
||||||
|
*/
|
||||||
index: number;
|
index: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction index of this log.
|
||||||
|
*/
|
||||||
transactionIndex: number;
|
transactionIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,28 +144,99 @@ export interface LogParams {
|
|||||||
//////////////////////
|
//////////////////////
|
||||||
// Transaction Receipt
|
// Transaction Receipt
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a **TransactionReceiptParams** encodes the minimal required properties
|
||||||
|
* for a formatted transaction receipt.
|
||||||
|
*/
|
||||||
export interface TransactionReceiptParams {
|
export interface TransactionReceiptParams {
|
||||||
|
/**
|
||||||
|
* The target of the transaction. If null, the transaction was trying
|
||||||
|
* to deploy a transaction with the ``data`` as the initi=code.
|
||||||
|
*/
|
||||||
to: null | string;
|
to: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sender of the transaction.
|
||||||
|
*/
|
||||||
from: string;
|
from: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the transaction was directly deploying a contract, the [[to]]
|
||||||
|
* will be null, the ``data`` will be initcode and if successful, this
|
||||||
|
* will be the address of the contract deployed.
|
||||||
|
*/
|
||||||
contractAddress: null | string;
|
contractAddress: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction hash.
|
||||||
|
*/
|
||||||
hash: string;
|
hash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction index.
|
||||||
|
*/
|
||||||
index: number;
|
index: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block hash of the block that included this transaction.
|
||||||
|
*/
|
||||||
blockHash: string;
|
blockHash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block number of the block that included this transaction.
|
||||||
|
*/
|
||||||
blockNumber: number;
|
blockNumber: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bloom filter for the logs emitted during execution of this
|
||||||
|
* transaction.
|
||||||
|
*/
|
||||||
logsBloom: string;
|
logsBloom: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logs emitted during the execution of this transaction.
|
||||||
|
*/
|
||||||
logs: ReadonlyArray<LogParams>;
|
logs: ReadonlyArray<LogParams>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of gas consumed executing this transaciton.
|
||||||
|
*/
|
||||||
gasUsed: bigint;
|
gasUsed: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total amount of gas consumed during the entire block up to
|
||||||
|
* and including this transaction.
|
||||||
|
*/
|
||||||
cumulativeGasUsed: bigint;
|
cumulativeGasUsed: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual gas price per gas charged for this transaction.
|
||||||
|
*/
|
||||||
gasPrice?: null | bigint;
|
gasPrice?: null | bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual gas price per gas charged for this transaction.
|
||||||
|
*/
|
||||||
effectiveGasPrice?: null | bigint;
|
effectiveGasPrice?: null | bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[link-eip-2718]] envelope type.
|
||||||
|
*/
|
||||||
type: number;
|
type: number;
|
||||||
//byzantium: boolean;
|
//byzantium: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status of the transaction execution. If ``1`` then the
|
||||||
|
* the transaction returned success, if ``0`` then the transaction
|
||||||
|
* was reverted. For pre-byzantium blocks, this is usually null, but
|
||||||
|
* some nodes may have backfilled this data.
|
||||||
|
*/
|
||||||
status: null | number;
|
status: null | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root of this transaction in a pre-bazatium block. In
|
||||||
|
* post-byzantium blocks this is null.
|
||||||
|
*/
|
||||||
root: null | string;
|
root: null | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,33 +259,97 @@ export interface ByzantiumTransactionReceipt {
|
|||||||
//////////////////////
|
//////////////////////
|
||||||
// Transaction Response
|
// Transaction Response
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a **TransactionResponseParams** encodes the minimal required properties
|
||||||
|
* for a formatted transaction response.
|
||||||
|
*/
|
||||||
export interface TransactionResponseParams {
|
export interface TransactionResponseParams {
|
||||||
|
/**
|
||||||
|
* The block number of the block that included this transaction.
|
||||||
|
*/
|
||||||
blockNumber: null | number;
|
blockNumber: null | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block hash of the block that included this transaction.
|
||||||
|
*/
|
||||||
blockHash: null | string;
|
blockHash: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction hash.
|
||||||
|
*/
|
||||||
hash: string;
|
hash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction index.
|
||||||
|
*/
|
||||||
index: number;
|
index: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[link-eip-2718]] transaction type.
|
||||||
|
*/
|
||||||
type: number;
|
type: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The target of the transaction. If ``null``, the ``data`` is initcode
|
||||||
|
* and this transaction is a deployment transaction.
|
||||||
|
*/
|
||||||
to: null | string;
|
to: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sender of the transaction.
|
||||||
|
*/
|
||||||
from: string;
|
from: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The nonce of the transaction, used for replay protection.
|
||||||
|
*/
|
||||||
nonce: number;
|
nonce: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum amount of gas this transaction is authorized to consume.
|
||||||
|
*/
|
||||||
gasLimit: bigint;
|
gasLimit: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For legacy transactions, this is the gas price per gas to pay.
|
||||||
|
*/
|
||||||
gasPrice: bigint;
|
gasPrice: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For [[link-eip-1559]] transactions, this is the maximum priority
|
||||||
|
* fee to allow a producer to claim.
|
||||||
|
*/
|
||||||
maxPriorityFeePerGas: null | bigint;
|
maxPriorityFeePerGas: null | bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For [[link-eip-1559]] transactions, this is the maximum fee that
|
||||||
|
* will be paid.
|
||||||
|
*/
|
||||||
maxFeePerGas: null | bigint;
|
maxFeePerGas: null | bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction data.
|
||||||
|
*/
|
||||||
data: string;
|
data: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction value (in wei).
|
||||||
|
*/
|
||||||
value: bigint;
|
value: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The chain ID this transaction is valid on.
|
||||||
|
*/
|
||||||
chainId: bigint;
|
chainId: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signature of the transaction.
|
||||||
|
*/
|
||||||
signature: Signature;
|
signature: Signature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction access list.
|
||||||
|
*/
|
||||||
accessList: null | AccessList;
|
accessList: null | AccessList;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
/**
|
/**
|
||||||
* About providers.
|
* A **Provider** provides a connection to the blockchain, whch can be
|
||||||
|
* used to query its current state, simulate execution and send transactions
|
||||||
|
* to update the state.
|
||||||
|
*
|
||||||
|
* It is one of the most fundamental components of interacting with a
|
||||||
|
* blockchain application, and there are many ways to connect, such as over
|
||||||
|
* HTTP, WebSockets or injected providers such as [MetaMask](link-metamask).
|
||||||
*
|
*
|
||||||
* @_section: api/providers:Providers [about-providers]
|
* @_section: api/providers:Providers [about-providers]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
AbstractProvider, UnmanagedSubscriber
|
AbstractProvider, UnmanagedSubscriber
|
||||||
} from "./abstract-provider.js";
|
} from "./abstract-provider.js";
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* About networks
|
* A **Network** encapsulates the various properties required to
|
||||||
|
* interact with a specific chain.
|
||||||
*
|
*
|
||||||
* @_subsection: api/providers:Networks [networks]
|
* @_subsection: api/providers:Networks [networks]
|
||||||
*/
|
*/
|
||||||
@ -91,18 +92,28 @@ const Networks: Map<string | bigint, () => Network> = new Map();
|
|||||||
|
|
||||||
// @TODO: Add a _ethersNetworkObj variable to better detect network ovjects
|
// @TODO: Add a _ethersNetworkObj variable to better detect network ovjects
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **Network** provides access to a chain's properties and allows
|
||||||
|
* for plug-ins to extend functionality.
|
||||||
|
*/
|
||||||
export class Network {
|
export class Network {
|
||||||
#name: string;
|
#name: string;
|
||||||
#chainId: bigint;
|
#chainId: bigint;
|
||||||
|
|
||||||
#plugins: Map<string, NetworkPlugin>;
|
#plugins: Map<string, NetworkPlugin>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **Network** for %%name%% and %%chainId%%.
|
||||||
|
*/
|
||||||
constructor(name: string, chainId: BigNumberish) {
|
constructor(name: string, chainId: BigNumberish) {
|
||||||
this.#name = name;
|
this.#name = name;
|
||||||
this.#chainId = getBigInt(chainId);
|
this.#chainId = getBigInt(chainId);
|
||||||
this.#plugins = new Map();
|
this.#plugins = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a JSON-compatible representation of a Network.
|
||||||
|
*/
|
||||||
toJSON(): any {
|
toJSON(): any {
|
||||||
return { name: this.name, chainId: String(this.chainId) };
|
return { name: this.name, chainId: String(this.chainId) };
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,28 @@ import type {
|
|||||||
|
|
||||||
const EnsAddress = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
|
const EnsAddress = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **NetworkPlugin** provides additional functionality on a [[Network]].
|
||||||
|
*/
|
||||||
export class NetworkPlugin {
|
export class NetworkPlugin {
|
||||||
|
/**
|
||||||
|
* The name of the plugin.
|
||||||
|
*
|
||||||
|
* It is recommended to use reverse-domain-notation, which permits
|
||||||
|
* unique names with a known authority as well as hierarchal entries.
|
||||||
|
*/
|
||||||
readonly name!: string;
|
readonly name!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **NetworkPlugin**.
|
||||||
|
*/
|
||||||
constructor(name: string) {
|
constructor(name: string) {
|
||||||
defineProperties<NetworkPlugin>(this, { name });
|
defineProperties<NetworkPlugin>(this, { name });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of this plugin.
|
||||||
|
*/
|
||||||
clone(): NetworkPlugin {
|
clone(): NetworkPlugin {
|
||||||
return new NetworkPlugin(this.name);
|
return new NetworkPlugin(this.name);
|
||||||
}
|
}
|
||||||
@ -26,28 +41,91 @@ export class NetworkPlugin {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Networks can use this plugin to override calculations for the
|
|
||||||
// intrinsic gas cost of a transaction for networks that differ
|
/**
|
||||||
// from the latest hardfork on Ethereum mainnet.
|
* The gas cost parameters for a [[GasCostPlugin]].
|
||||||
|
*/
|
||||||
export type GasCostParameters = {
|
export type GasCostParameters = {
|
||||||
|
/**
|
||||||
|
* The transactions base fee.
|
||||||
|
*/
|
||||||
txBase?: number;
|
txBase?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee for creating a new account.
|
||||||
|
*/
|
||||||
txCreate?: number;
|
txCreate?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee per zero-byte in the data.
|
||||||
|
*/
|
||||||
txDataZero?: number;
|
txDataZero?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee per non-zero-byte in the data.
|
||||||
|
*/
|
||||||
txDataNonzero?: number;
|
txDataNonzero?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee per storage key in the [[link-eip-2930]] access list.
|
||||||
|
*/
|
||||||
txAccessListStorageKey?: number;
|
txAccessListStorageKey?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee per address in the [[link-eip-2930]] access list.
|
||||||
|
*/
|
||||||
txAccessListAddress?: number;
|
txAccessListAddress?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **GasCostPlugin** allows a network to provide alternative values when
|
||||||
|
* computing the intrinsic gas required for a transaction.
|
||||||
|
*/
|
||||||
export class GasCostPlugin extends NetworkPlugin implements GasCostParameters {
|
export class GasCostPlugin extends NetworkPlugin implements GasCostParameters {
|
||||||
|
/**
|
||||||
|
* The block number to treat these values as valid from.
|
||||||
|
*
|
||||||
|
* This allows a hardfork to have updated values included as well as
|
||||||
|
* mulutiple hardforks to be supported.
|
||||||
|
*/
|
||||||
readonly effectiveBlock!: number;
|
readonly effectiveBlock!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transactions base fee.
|
||||||
|
*/
|
||||||
readonly txBase!: number;
|
readonly txBase!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee for creating a new account.
|
||||||
|
*/
|
||||||
readonly txCreate!: number;
|
readonly txCreate!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee per zero-byte in the data.
|
||||||
|
*/
|
||||||
readonly txDataZero!: number;
|
readonly txDataZero!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee per non-zero-byte in the data.
|
||||||
|
*/
|
||||||
readonly txDataNonzero!: number;
|
readonly txDataNonzero!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee per storage key in the [[link-eip-2930]] access list.
|
||||||
|
*/
|
||||||
readonly txAccessListStorageKey!: number;
|
readonly txAccessListStorageKey!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee per address in the [[link-eip-2930]] access list.
|
||||||
|
*/
|
||||||
readonly txAccessListAddress!: number;
|
readonly txAccessListAddress!: number;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new GasCostPlugin from %%effectiveBlock%% until the
|
||||||
|
* latest block or another GasCostPlugin supercedes that block number,
|
||||||
|
* with the associated %%costs%%.
|
||||||
|
*/
|
||||||
constructor(effectiveBlock?: number, costs?: GasCostParameters) {
|
constructor(effectiveBlock?: number, costs?: GasCostParameters) {
|
||||||
if (effectiveBlock == null) { effectiveBlock = 0; }
|
if (effectiveBlock == null) { effectiveBlock = 0; }
|
||||||
super(`org.ethers.network.plugins.GasCost#${ (effectiveBlock || 0) }`);
|
super(`org.ethers.network.plugins.GasCost#${ (effectiveBlock || 0) }`);
|
||||||
@ -75,16 +153,32 @@ export class GasCostPlugin extends NetworkPlugin implements GasCostParameters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Networks shoudl use this plugin to specify the contract address
|
/**
|
||||||
// and network necessary to resolve ENS names.
|
* An **EnsPlugin** allows a [[Network]] to specify the ENS Registry
|
||||||
|
* Contract address and the target network to use when using that
|
||||||
|
* contract.
|
||||||
|
*
|
||||||
|
* Various testnets have their own instance of the contract to use, but
|
||||||
|
* in general, the mainnet instance supports multi-chain addresses and
|
||||||
|
* should be used.
|
||||||
|
*/
|
||||||
export class EnsPlugin extends NetworkPlugin {
|
export class EnsPlugin extends NetworkPlugin {
|
||||||
|
|
||||||
// The ENS contract address
|
/**
|
||||||
|
* The ENS Registrty Contract address.
|
||||||
|
*/
|
||||||
readonly address!: string;
|
readonly address!: string;
|
||||||
|
|
||||||
// The network ID that the ENS contract lives on
|
/**
|
||||||
|
* The chain ID that the ENS contract lives on.
|
||||||
|
*/
|
||||||
readonly targetNetwork!: number;
|
readonly targetNetwork!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **EnsPlugin** connected to %%address%% on the
|
||||||
|
* %%targetNetwork%%. The default ENS address and mainnet is used
|
||||||
|
* if unspecified.
|
||||||
|
*/
|
||||||
constructor(address?: null | string, targetNetwork?: null | number) {
|
constructor(address?: null | string, targetNetwork?: null | number) {
|
||||||
super("org.ethers.plugins.network.Ens");
|
super("org.ethers.plugins.network.Ens");
|
||||||
defineProperties<EnsPlugin>(this, {
|
defineProperties<EnsPlugin>(this, {
|
||||||
@ -98,18 +192,34 @@ export class EnsPlugin extends NetworkPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **FeeDataNetworkPlugin** allows a network to provide and alternate
|
||||||
|
* means to specify its fee data.
|
||||||
|
*
|
||||||
|
* For example, a network which does not support [[link-eip-1559]] may
|
||||||
|
* choose to use a Gas Station site to approximate the gas price.
|
||||||
|
*/
|
||||||
export class FeeDataNetworkPlugin extends NetworkPlugin {
|
export class FeeDataNetworkPlugin extends NetworkPlugin {
|
||||||
readonly #feeDataFunc: (provider: Provider) => Promise<FeeData>;
|
readonly #feeDataFunc: (provider: Provider) => Promise<FeeData>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fee data function provided to the constructor.
|
||||||
|
*/
|
||||||
get feeDataFunc(): (provider: Provider) => Promise<FeeData> {
|
get feeDataFunc(): (provider: Provider) => Promise<FeeData> {
|
||||||
return this.#feeDataFunc;
|
return this.#feeDataFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **FeeDataNetworkPlugin**.
|
||||||
|
*/
|
||||||
constructor(feeDataFunc: (provider: Provider) => Promise<FeeData>) {
|
constructor(feeDataFunc: (provider: Provider) => Promise<FeeData>) {
|
||||||
super("org.ethers.plugins.network.FeeData");
|
super("org.ethers.plugins.network.FeeData");
|
||||||
this.#feeDataFunc = feeDataFunc;
|
this.#feeDataFunc = feeDataFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the fee data.
|
||||||
|
*/
|
||||||
async getFeeData(provider: Provider): Promise<FeeData> {
|
async getFeeData(provider: Provider): Promise<FeeData> {
|
||||||
return await this.#feeDataFunc(provider);
|
return await this.#feeDataFunc(provider);
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,22 @@ import type {
|
|||||||
} from "./provider-jsonrpc.js";
|
} from "./provider-jsonrpc.js";
|
||||||
import type { Networkish } from "./network.js";
|
import type { Networkish } from "./network.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface to an [[link-eip-1193]] provider, which is a standard
|
||||||
|
* used by most injected providers, which the [[BrowserProvider]] accepts
|
||||||
|
* and exposes the API of.
|
||||||
|
*/
|
||||||
export interface Eip1193Provider {
|
export interface Eip1193Provider {
|
||||||
|
/**
|
||||||
|
* See [[link-eip-1193]] for details on this method.
|
||||||
|
*/
|
||||||
request(request: { method: string, params?: Array<any> | Record<string, any> }): Promise<any>;
|
request(request: { method: string, params?: Array<any> | Record<string, any> }): Promise<any>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The possible additional events dispatched when using the ``"debug"``
|
||||||
|
* event on a [[BrowserProvider]].
|
||||||
|
*/
|
||||||
export type DebugEventBrowserProvider = {
|
export type DebugEventBrowserProvider = {
|
||||||
action: "sendEip1193Payload",
|
action: "sendEip1193Payload",
|
||||||
payload: { method: string, params: Array<any> }
|
payload: { method: string, params: Array<any> }
|
||||||
@ -25,10 +36,18 @@ export type DebugEventBrowserProvider = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **BrowserProvider** is intended to wrap an injected provider which
|
||||||
|
* adheres to the [[link-eip-1193]] standard, which most (if not all)
|
||||||
|
* currently do.
|
||||||
|
*/
|
||||||
export class BrowserProvider extends JsonRpcApiPollingProvider {
|
export class BrowserProvider extends JsonRpcApiPollingProvider {
|
||||||
#request: (method: string, params: Array<any> | Record<string, any>) => Promise<any>;
|
#request: (method: string, params: Array<any> | Record<string, any>) => Promise<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connnect to the %%ethereum%% provider, optionally forcing the
|
||||||
|
* %%network%%.
|
||||||
|
*/
|
||||||
constructor(ethereum: Eip1193Provider, network?: Networkish) {
|
constructor(ethereum: Eip1193Provider, network?: Networkish) {
|
||||||
super(network, { batchMaxCount: 1 });
|
super(network, { batchMaxCount: 1 });
|
||||||
|
|
||||||
@ -88,6 +107,9 @@ export class BrowserProvider extends JsonRpcApiPollingProvider {
|
|||||||
return super.getRpcError(payload, error);
|
return super.getRpcError(payload, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to ``true`` if the provider manages the %%address%%.
|
||||||
|
*/
|
||||||
async hasSigner(address: number | string): Promise<boolean> {
|
async hasSigner(address: number | string): Promise<boolean> {
|
||||||
if (address == null) { address = 0; }
|
if (address == null) { address = 0; }
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Explain all the nitty-gritty about the **FallbackProvider**.
|
* A **FallbackProvider** providers resiliance, security and performatnce
|
||||||
|
* in a way that is customizable and configurable.
|
||||||
*
|
*
|
||||||
* @_section: api/providers/fallback-provider:Fallback Provider [about-fallback-provider]
|
* @_section: api/providers/fallback-provider:Fallback Provider [about-fallback-provider]
|
||||||
*/
|
*/
|
||||||
@ -45,17 +46,27 @@ function stringify(value: any): string {
|
|||||||
*/
|
*/
|
||||||
export interface FallbackProviderConfig {
|
export interface FallbackProviderConfig {
|
||||||
|
|
||||||
// The provider
|
/**
|
||||||
|
* The provider.
|
||||||
|
*/
|
||||||
provider: AbstractProvider;
|
provider: AbstractProvider;
|
||||||
|
|
||||||
// How long to wait for a response before getting impatient
|
/**
|
||||||
// and ispatching the next provider
|
* The amount of time to wait before kicking off the next provider.
|
||||||
|
*
|
||||||
|
* Any providers that have not responded can still respond and be
|
||||||
|
* counted, but this ensures new providers start.
|
||||||
|
*/
|
||||||
stallTimeout?: number;
|
stallTimeout?: number;
|
||||||
|
|
||||||
// Lower values are dispatched first
|
/**
|
||||||
|
* The priority. Lower priority providers are dispatched first.
|
||||||
|
*/
|
||||||
priority?: number;
|
priority?: number;
|
||||||
|
|
||||||
// How much this provider contributes to the quorum
|
/**
|
||||||
|
* The amount of weight a provider is given against the quorum.
|
||||||
|
*/
|
||||||
weight?: number;
|
weight?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -68,28 +79,44 @@ const defaultConfig = { stallTimeout: 400, priority: 1, weight: 1 };
|
|||||||
*/
|
*/
|
||||||
export interface FallbackProviderState extends Required<FallbackProviderConfig> {
|
export interface FallbackProviderState extends Required<FallbackProviderConfig> {
|
||||||
|
|
||||||
// The most recent blockNumber this provider has reported (-2 if none)
|
/**
|
||||||
|
* The most recent blockNumber this provider has reported (-2 if none).
|
||||||
|
*/
|
||||||
blockNumber: number;
|
blockNumber: number;
|
||||||
|
|
||||||
// The number of total requests ever sent to this provider
|
/**
|
||||||
|
* The number of total requests ever sent to this provider.
|
||||||
|
*/
|
||||||
requests: number;
|
requests: number;
|
||||||
|
|
||||||
// The number of responses that errored
|
/**
|
||||||
|
* The number of responses that errored.
|
||||||
|
*/
|
||||||
errorResponses: number;
|
errorResponses: number;
|
||||||
|
|
||||||
// The number of responses that occured after the result resolved
|
/**
|
||||||
|
* The number of responses that occured after the result resolved.
|
||||||
|
*/
|
||||||
lateResponses: number;
|
lateResponses: number;
|
||||||
|
|
||||||
// How many times syncing was required to catch up the expected block
|
/**
|
||||||
|
* How many times syncing was required to catch up the expected block.
|
||||||
|
*/
|
||||||
outOfSync: number;
|
outOfSync: number;
|
||||||
|
|
||||||
// The number of requests which reported unsupported operation
|
/**
|
||||||
|
* The number of requests which reported unsupported operation.
|
||||||
|
*/
|
||||||
unsupportedEvents: number;
|
unsupportedEvents: number;
|
||||||
|
|
||||||
// A rolling average (5% current duration) for response time
|
/**
|
||||||
|
* A rolling average (5% current duration) for response time.
|
||||||
|
*/
|
||||||
rollingDuration: number;
|
rollingDuration: number;
|
||||||
|
|
||||||
// The ratio of quorum-agreed results to total
|
/**
|
||||||
|
* The ratio of quorum-agreed results to total.
|
||||||
|
*/
|
||||||
score: number;
|
score: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,13 +344,28 @@ function getFuzzyMode(quorum: number, results: Array<TallyResult>): undefined |
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Fallback Provider.
|
* A **FallbackProvider** manages several [[Providers]] providing
|
||||||
|
* resiliance by switching between slow or misbehaving nodes, security
|
||||||
|
* by requiring multiple backends to aggree and performance by allowing
|
||||||
|
* faster backends to respond earlier.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export class FallbackProvider extends AbstractProvider {
|
export class FallbackProvider extends AbstractProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of backends that must agree on a value before it is
|
||||||
|
* accpeted.
|
||||||
|
*/
|
||||||
readonly quorum: number;
|
readonly quorum: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
readonly eventQuorum: number;
|
readonly eventQuorum: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
readonly eventWorkers: number;
|
readonly eventWorkers: number;
|
||||||
|
|
||||||
readonly #configs: Array<Config>;
|
readonly #configs: Array<Config>;
|
||||||
@ -331,6 +373,13 @@ export class FallbackProvider extends AbstractProvider {
|
|||||||
#height: number;
|
#height: number;
|
||||||
#initialSyncPromise: null | Promise<void>;
|
#initialSyncPromise: null | Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **FallbackProvider** with %%providers%% connected to
|
||||||
|
* %%network%%.
|
||||||
|
*
|
||||||
|
* If a [[Provider]] is included in %%providers%%, defaults are used
|
||||||
|
* for the configuration.
|
||||||
|
*/
|
||||||
constructor(providers: Array<AbstractProvider | FallbackProviderConfig>, network?: Networkish) {
|
constructor(providers: Array<AbstractProvider | FallbackProviderConfig>, network?: Networkish) {
|
||||||
super(network);
|
super(network);
|
||||||
this.#configs = providers.map((p) => {
|
this.#configs = providers.map((p) => {
|
||||||
@ -371,6 +420,9 @@ export class FallbackProvider extends AbstractProvider {
|
|||||||
// throw new Error("@TODO");
|
// throw new Error("@TODO");
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms a %%req%% into the correct method call on %%provider%%.
|
||||||
|
*/
|
||||||
async _translatePerform(provider: AbstractProvider, req: PerformActionRequest): Promise<any> {
|
async _translatePerform(provider: AbstractProvider, req: PerformActionRequest): Promise<any> {
|
||||||
switch (req.method) {
|
switch (req.method) {
|
||||||
case "broadcastTransaction":
|
case "broadcastTransaction":
|
||||||
|
@ -22,8 +22,17 @@ function splitBuffer(data: Buffer): { messages: Array<string>, remaining: Buffer
|
|||||||
return { messages, remaining: data.subarray(lastStart) };
|
return { messages, remaining: data.subarray(lastStart) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An **IpcSocketProvider** connects over an IPC socket on the host
|
||||||
|
* which provides fast access to the node, but requires the node and
|
||||||
|
* the script run on the same machine.
|
||||||
|
*/
|
||||||
export class IpcSocketProvider extends SocketProvider {
|
export class IpcSocketProvider extends SocketProvider {
|
||||||
#socket: Socket;
|
#socket: Socket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connected socket.
|
||||||
|
*/
|
||||||
get socket(): Socket { return this.#socket; }
|
get socket(): Socket { return this.#socket; }
|
||||||
|
|
||||||
constructor(path: string, network?: Networkish) {
|
constructor(path: string, network?: Networkish) {
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* About JSON-RPC...
|
* One of the most common ways to interact with the blockchain is
|
||||||
|
* by a node running a JSON-RPC interface which can be connected to,
|
||||||
|
* based on the transport, using:
|
||||||
|
*
|
||||||
|
* - HTTP or HTTPS - [[JsonRpcProvider]]
|
||||||
|
* - WebSocket - [[WebSocketProvider]]
|
||||||
|
* - IPC - [[IpcSocketProvider]]
|
||||||
*
|
*
|
||||||
* @_section: api/providers/jsonrpc:JSON-RPC Provider [about-jsonrpcProvider]
|
* @_section: api/providers/jsonrpc:JSON-RPC Provider [about-jsonrpcProvider]
|
||||||
*/
|
*/
|
||||||
@ -81,9 +87,24 @@ function isPollable(value: any): value is Pollable {
|
|||||||
* A JSON-RPC payload, which are sent to a JSON-RPC server.
|
* A JSON-RPC payload, which are sent to a JSON-RPC server.
|
||||||
*/
|
*/
|
||||||
export type JsonRpcPayload = {
|
export type JsonRpcPayload = {
|
||||||
|
/**
|
||||||
|
* The JSON-RPC request ID.
|
||||||
|
*/
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The JSON-RPC request method.
|
||||||
|
*/
|
||||||
method: string;
|
method: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The JSON-RPC request parameters.
|
||||||
|
*/
|
||||||
params: Array<any> | Record<string, any>;
|
params: Array<any> | Record<string, any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A required constant in the JSON-RPC specification.
|
||||||
|
*/
|
||||||
jsonrpc: "2.0";
|
jsonrpc: "2.0";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -91,7 +112,14 @@ export type JsonRpcPayload = {
|
|||||||
* A JSON-RPC result, which are returned on success from a JSON-RPC server.
|
* A JSON-RPC result, which are returned on success from a JSON-RPC server.
|
||||||
*/
|
*/
|
||||||
export type JsonRpcResult = {
|
export type JsonRpcResult = {
|
||||||
|
/**
|
||||||
|
* The response ID to match it to the relevant request.
|
||||||
|
*/
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The response result.
|
||||||
|
*/
|
||||||
result: any;
|
result: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,7 +127,14 @@ export type JsonRpcResult = {
|
|||||||
* A JSON-RPC error, which are returned on failure from a JSON-RPC server.
|
* A JSON-RPC error, which are returned on failure from a JSON-RPC server.
|
||||||
*/
|
*/
|
||||||
export type JsonRpcError = {
|
export type JsonRpcError = {
|
||||||
|
/**
|
||||||
|
* The response ID to match it to the relevant request.
|
||||||
|
*/
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The response error.
|
||||||
|
*/
|
||||||
error: {
|
error: {
|
||||||
code: number;
|
code: number;
|
||||||
message?: string;
|
message?: string;
|
||||||
@ -168,22 +203,72 @@ const defaultOptions = {
|
|||||||
batchMaxCount: 100 // 100 requests
|
batchMaxCount: 100 // 100 requests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **JsonRpcTransactionRequest** is formatted as needed by the JSON-RPC
|
||||||
|
* Ethereum API specification.
|
||||||
|
*/
|
||||||
export interface JsonRpcTransactionRequest {
|
export interface JsonRpcTransactionRequest {
|
||||||
|
/**
|
||||||
|
* The sender address to use when signing.
|
||||||
|
*/
|
||||||
from?: string;
|
from?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The target address.
|
||||||
|
*/
|
||||||
to?: string;
|
to?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction data.
|
||||||
|
*/
|
||||||
data?: string;
|
data?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The chain ID the transaction is valid on.
|
||||||
|
*/
|
||||||
chainId?: string;
|
chainId?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[link-eip-2718]] transaction type.
|
||||||
|
*/
|
||||||
type?: string;
|
type?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum amount of gas to allow a transaction to consume.
|
||||||
|
*
|
||||||
|
* In most other places in ethers, this is called ``gasLimit`` which
|
||||||
|
* differs from the JSON-RPC Ethereum API specification.
|
||||||
|
*/
|
||||||
gas?: string;
|
gas?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The gas price per wei for transactions prior to [[link-eip-1559]].
|
||||||
|
*/
|
||||||
gasPrice?: string;
|
gasPrice?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum fee per gas for [[link-eip-1559]] transactions.
|
||||||
|
*/
|
||||||
maxFeePerGas?: string;
|
maxFeePerGas?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum priority fee per gas for [[link-eip-1559]] transactions.
|
||||||
|
*/
|
||||||
maxPriorityFeePerGas?: string;
|
maxPriorityFeePerGas?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The nonce for the transaction.
|
||||||
|
*/
|
||||||
nonce?: string;
|
nonce?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction value (in wei).
|
||||||
|
*/
|
||||||
value?: string;
|
value?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction access list.
|
||||||
|
*/
|
||||||
accessList?: Array<{ address: string, storageKeys: Array<string> }>;
|
accessList?: Array<{ address: string, storageKeys: Array<string> }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,10 +27,18 @@ type JsonRpcSubscription = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **SocketSubscriber** uses a socket transport to handle events and
|
||||||
|
* should use [[_emit]] to manage the events.
|
||||||
|
*/
|
||||||
export class SocketSubscriber implements Subscriber {
|
export class SocketSubscriber implements Subscriber {
|
||||||
#provider: SocketProvider;
|
#provider: SocketProvider;
|
||||||
|
|
||||||
#filter: string;
|
#filter: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The filter.
|
||||||
|
*/
|
||||||
get filter(): Array<any> { return JSON.parse(this.#filter); }
|
get filter(): Array<any> { return JSON.parse(this.#filter); }
|
||||||
|
|
||||||
#filterId: null | Promise<string |number>;
|
#filterId: null | Promise<string |number>;
|
||||||
@ -38,6 +46,10 @@ export class SocketSubscriber implements Subscriber {
|
|||||||
|
|
||||||
#emitPromise: null | Promise<void>;
|
#emitPromise: null | Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **SocketSubscriber** attached to %%provider%% listening
|
||||||
|
* to %%filter%%.
|
||||||
|
*/
|
||||||
constructor(provider: SocketProvider, filter: Array<any>) {
|
constructor(provider: SocketProvider, filter: Array<any>) {
|
||||||
this.#provider = provider;
|
this.#provider = provider;
|
||||||
this.#filter = JSON.stringify(filter);
|
this.#filter = JSON.stringify(filter);
|
||||||
@ -72,6 +84,9 @@ export class SocketSubscriber implements Subscriber {
|
|||||||
this.#paused = null;
|
this.#paused = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
_handleMessage(message: any): void {
|
_handleMessage(message: any): void {
|
||||||
if (this.#filterId == null) { return; }
|
if (this.#filterId == null) { return; }
|
||||||
if (this.#paused === null) {
|
if (this.#paused === null) {
|
||||||
@ -91,12 +106,23 @@ export class SocketSubscriber implements Subscriber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub-classes **must** override this to emit the events on the
|
||||||
|
* provider.
|
||||||
|
*/
|
||||||
async _emit(provider: SocketProvider, message: any): Promise<void> {
|
async _emit(provider: SocketProvider, message: any): Promise<void> {
|
||||||
throw new Error("sub-classes must implemente this; _emit");
|
throw new Error("sub-classes must implemente this; _emit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **SocketBlockSubscriber** listens for ``newHeads`` events and emits
|
||||||
|
* ``"block"`` events.
|
||||||
|
*/
|
||||||
export class SocketBlockSubscriber extends SocketSubscriber {
|
export class SocketBlockSubscriber extends SocketSubscriber {
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(provider: SocketProvider) {
|
constructor(provider: SocketProvider) {
|
||||||
super(provider, [ "newHeads" ]);
|
super(provider, [ "newHeads" ]);
|
||||||
}
|
}
|
||||||
@ -106,7 +132,15 @@ export class SocketBlockSubscriber extends SocketSubscriber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **SocketPendingSubscriber** listens for pending transacitons and emits
|
||||||
|
* ``"pending"`` events.
|
||||||
|
*/
|
||||||
export class SocketPendingSubscriber extends SocketSubscriber {
|
export class SocketPendingSubscriber extends SocketSubscriber {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(provider: SocketProvider) {
|
constructor(provider: SocketProvider) {
|
||||||
super(provider, [ "newPendingTransactions" ]);
|
super(provider, [ "newPendingTransactions" ]);
|
||||||
}
|
}
|
||||||
@ -116,10 +150,20 @@ export class SocketPendingSubscriber extends SocketSubscriber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **SocketEventSubscriber** listens for event logs.
|
||||||
|
*/
|
||||||
export class SocketEventSubscriber extends SocketSubscriber {
|
export class SocketEventSubscriber extends SocketSubscriber {
|
||||||
#logFilter: string;
|
#logFilter: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The filter.
|
||||||
|
*/
|
||||||
get logFilter(): EventFilter { return JSON.parse(this.#logFilter); }
|
get logFilter(): EventFilter { return JSON.parse(this.#logFilter); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(provider: SocketProvider, filter: EventFilter) {
|
constructor(provider: SocketProvider, filter: EventFilter) {
|
||||||
super(provider, [ "logs", filter ]);
|
super(provider, [ "logs", filter ]);
|
||||||
this.#logFilter = JSON.stringify(filter);
|
this.#logFilter = JSON.stringify(filter);
|
||||||
@ -131,8 +175,9 @@ export class SocketEventSubscriber extends SocketSubscriber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SocketProvider...
|
* A **SocketProvider** is backed by a long-lived connection over a
|
||||||
*
|
* socket, which can subscribe and receive real-time messages over
|
||||||
|
* its communication channel.
|
||||||
*/
|
*/
|
||||||
export class SocketProvider extends JsonRpcApiProvider {
|
export class SocketProvider extends JsonRpcApiProvider {
|
||||||
#callbacks: Map<number, { payload: JsonRpcPayload, resolve: (r: any) => void, reject: (e: Error) => void }>;
|
#callbacks: Map<number, { payload: JsonRpcPayload, resolve: (r: any) => void, reject: (e: Error) => void }>;
|
||||||
@ -144,6 +189,11 @@ export class SocketProvider extends JsonRpcApiProvider {
|
|||||||
// registering, queue them
|
// registering, queue them
|
||||||
#pending: Map<number | string, Array<any>>;
|
#pending: Map<number | string, Array<any>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **SocketProvider** connected to %%network%%.
|
||||||
|
*
|
||||||
|
* If unspecified, the network will be discovered.
|
||||||
|
*/
|
||||||
constructor(network?: Networkish) {
|
constructor(network?: Networkish) {
|
||||||
super(network, { batchMaxCount: 1 });
|
super(network, { batchMaxCount: 1 });
|
||||||
this.#callbacks = new Map();
|
this.#callbacks = new Map();
|
||||||
@ -181,6 +231,10 @@ export class SocketProvider extends JsonRpcApiProvider {
|
|||||||
return super._getSubscriber(sub);
|
return super._getSubscriber(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new subscriber. This is used internalled by Subscribers
|
||||||
|
* and generally is unecessary unless extending capabilities.
|
||||||
|
*/
|
||||||
_register(filterId: number | string, subscriber: SocketSubscriber): void {
|
_register(filterId: number | string, subscriber: SocketSubscriber): void {
|
||||||
this.#subs.set(filterId, subscriber);
|
this.#subs.set(filterId, subscriber);
|
||||||
const pending = this.#pending.get(filterId);
|
const pending = this.#pending.get(filterId);
|
||||||
@ -227,7 +281,10 @@ export class SocketProvider extends JsonRpcApiProvider {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Sub-classes must call this for each message
|
/**
|
||||||
|
* Sub-classes **must** call this with messages received over their
|
||||||
|
* transport to be processed and dispatched.
|
||||||
|
*/
|
||||||
async _processMessage(message: string): Promise<void> {
|
async _processMessage(message: string): Promise<void> {
|
||||||
const result = <JsonRpcResult | JsonRpcError | JsonRpcSubscription>(JSON.parse(message));
|
const result = <JsonRpcResult | JsonRpcError | JsonRpcSubscription>(JSON.parse(message));
|
||||||
|
|
||||||
@ -267,6 +324,10 @@ export class SocketProvider extends JsonRpcApiProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub-classes **must** override this to send %%message%% over their
|
||||||
|
* transport.
|
||||||
|
*/
|
||||||
async _write(message: string): Promise<void> {
|
async _write(message: string): Promise<void> {
|
||||||
throw new Error("sub-classes must override this");
|
throw new Error("sub-classes must override this");
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@ import { SocketProvider } from "./provider-socket.js";
|
|||||||
|
|
||||||
import type { Networkish } from "./network.js";
|
import type { Networkish } from "./network.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic interface to a Websocket-like object.
|
||||||
|
*/
|
||||||
export interface WebSocketLike {
|
export interface WebSocketLike {
|
||||||
onopen: null | ((...args: Array<any>) => any);
|
onopen: null | ((...args: Array<any>) => any);
|
||||||
onmessage: null | ((...args: Array<any>) => any);
|
onmessage: null | ((...args: Array<any>) => any);
|
||||||
@ -17,8 +20,22 @@ export interface WebSocketLike {
|
|||||||
close(code?: number, reason?: string): void;
|
close(code?: number, reason?: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function which can be used to re-create a WebSocket connection
|
||||||
|
* on disconnect.
|
||||||
|
*/
|
||||||
export type WebSocketCreator = () => WebSocketLike;
|
export type WebSocketCreator = () => WebSocketLike;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JSON-RPC provider which is backed by a WebSocket.
|
||||||
|
*
|
||||||
|
* WebSockets are often preferred because they retain a live connection
|
||||||
|
* to a server, which permits more instant access to events.
|
||||||
|
*
|
||||||
|
* However, this incurs higher server infrasturture costs, so additional
|
||||||
|
* resources may be required to host your own WebSocket nodes and many
|
||||||
|
* third-party services charge additional fees for WebSocket endpoints.
|
||||||
|
*/
|
||||||
export class WebSocketProvider extends SocketProvider {
|
export class WebSocketProvider extends SocketProvider {
|
||||||
#connect: null | WebSocketCreator;
|
#connect: null | WebSocketCreator;
|
||||||
|
|
||||||
|
@ -16,6 +16,19 @@ import type { Network } from "./network.js";
|
|||||||
|
|
||||||
const BN_0 = BigInt(0);
|
const BN_0 = BigInt(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **BlockTag** specifies a specific block.
|
||||||
|
*
|
||||||
|
* **numeric value** - specifies the block height, where
|
||||||
|
* the genesis block is block 0; many operations accept a negative
|
||||||
|
* value which indicates the block number should be deducted from
|
||||||
|
* the most recent block. A numeric value may be a ``number``, ``bigint``,
|
||||||
|
* or a decimal of hex string.
|
||||||
|
*
|
||||||
|
* **blockhash** - specifies a specific block by its blockhash; this allows
|
||||||
|
* potentially orphaned blocks to be specifed, without ambiguity, but many
|
||||||
|
* backends do not support this for some operations.
|
||||||
|
*/
|
||||||
export type BlockTag = BigNumberish | string;
|
export type BlockTag = BigNumberish | string;
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -101,62 +114,215 @@ export class FeeData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **TransactionRequest** is a transactions with potentially various
|
||||||
|
* properties not defined, or with less strict types for its values.
|
||||||
|
*
|
||||||
|
* This is used to pass to various operations, which will internally
|
||||||
|
* coerce any types and populate any necessary values.
|
||||||
|
*/
|
||||||
export interface TransactionRequest {
|
export interface TransactionRequest {
|
||||||
|
/**
|
||||||
|
* The transaction type.
|
||||||
|
*/
|
||||||
type?: null | number;
|
type?: null | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The target of the transaction.
|
||||||
|
*/
|
||||||
to?: null | AddressLike;
|
to?: null | AddressLike;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sender of the transaction.
|
||||||
|
*/
|
||||||
from?: null | AddressLike;
|
from?: null | AddressLike;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The nonce of the transaction, used to prevent replay attacks.
|
||||||
|
*/
|
||||||
nonce?: null | number;
|
nonce?: null | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum amount of gas to allow this transaction to consime.
|
||||||
|
*/
|
||||||
gasLimit?: null | BigNumberish;
|
gasLimit?: null | BigNumberish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The gas price to use for legacy transactions or transactions on
|
||||||
|
* legacy networks.
|
||||||
|
*
|
||||||
|
* Most of the time the ``max*FeePerGas`` is preferred.
|
||||||
|
*/
|
||||||
gasPrice?: null | BigNumberish;
|
gasPrice?: null | BigNumberish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[link-eip-1559]] maximum priority fee to pay per gas.
|
||||||
|
*/
|
||||||
maxPriorityFeePerGas?: null | BigNumberish;
|
maxPriorityFeePerGas?: null | BigNumberish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[link-eip-1559]] maximum total fee to pay per gas. The actual
|
||||||
|
* value used is protocol enforced to be the block's base fee.
|
||||||
|
*/
|
||||||
maxFeePerGas?: null | BigNumberish;
|
maxFeePerGas?: null | BigNumberish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction data.
|
||||||
|
*/
|
||||||
data?: null | string;
|
data?: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction value (in wei).
|
||||||
|
*/
|
||||||
value?: null | BigNumberish;
|
value?: null | BigNumberish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The chain ID for the network this transaction is valid on.
|
||||||
|
*/
|
||||||
chainId?: null | BigNumberish;
|
chainId?: null | BigNumberish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[link-eip-2930]] access list. Storage slots included in the access
|
||||||
|
* list are //warmed// by pre-loading them, so their initial cost to
|
||||||
|
* fetch is guaranteed, but then each additional access is cheaper.
|
||||||
|
*/
|
||||||
accessList?: null | AccessListish;
|
accessList?: null | AccessListish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom object, which can be passed along for network-specific
|
||||||
|
* values.
|
||||||
|
*/
|
||||||
customData?: any;
|
customData?: any;
|
||||||
|
|
||||||
// Only meaningful when used for call
|
// Only meaningful when used for call
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When using ``call`` or ``estimateGas``, this allows a specific
|
||||||
|
* block to be queried. Many backends do not support this and when
|
||||||
|
* unsupported errors are silently squelched and ``"latest"`` is used.
|
||||||
|
*/
|
||||||
blockTag?: BlockTag;
|
blockTag?: BlockTag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When using ``call``, this enables CCIP-read, which permits the
|
||||||
|
* provider to be redirected to web-based content during execution,
|
||||||
|
* which is then further validated by the contract.
|
||||||
|
*
|
||||||
|
* There are potential security implications allowing CCIP-read, as
|
||||||
|
* it could be used to expose the IP address or user activity during
|
||||||
|
* the fetch to unexpected parties.
|
||||||
|
*/
|
||||||
enableCcipRead?: boolean;
|
enableCcipRead?: boolean;
|
||||||
|
|
||||||
// Todo?
|
// Todo?
|
||||||
//gasMultiplier?: number;
|
//gasMultiplier?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **PreparedTransactionRequest** is identical to a [[TransactionRequest]]
|
||||||
|
* except all the property types are strictly enforced.
|
||||||
|
*/
|
||||||
export interface PreparedTransactionRequest {
|
export interface PreparedTransactionRequest {
|
||||||
|
/**
|
||||||
|
* The transaction type.
|
||||||
|
*/
|
||||||
type?: number;
|
type?: number;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The target of the transaction.
|
||||||
|
*/
|
||||||
to?: AddressLike;
|
to?: AddressLike;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sender of the transaction.
|
||||||
|
*/
|
||||||
from?: AddressLike;
|
from?: AddressLike;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The nonce of the transaction, used to prevent replay attacks.
|
||||||
|
*/
|
||||||
|
|
||||||
nonce?: number;
|
nonce?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum amount of gas to allow this transaction to consime.
|
||||||
|
*/
|
||||||
gasLimit?: bigint;
|
gasLimit?: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The gas price to use for legacy transactions or transactions on
|
||||||
|
* legacy networks.
|
||||||
|
*
|
||||||
|
* Most of the time the ``max*FeePerGas`` is preferred.
|
||||||
|
*/
|
||||||
gasPrice?: bigint;
|
gasPrice?: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[link-eip-1559]] maximum priority fee to pay per gas.
|
||||||
|
*/
|
||||||
maxPriorityFeePerGas?: bigint;
|
maxPriorityFeePerGas?: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[link-eip-1559]] maximum total fee to pay per gas. The actual
|
||||||
|
* value used is protocol enforced to be the block's base fee.
|
||||||
|
*/
|
||||||
maxFeePerGas?: bigint;
|
maxFeePerGas?: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction data.
|
||||||
|
*/
|
||||||
data?: string;
|
data?: string;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction value (in wei).
|
||||||
|
*/
|
||||||
value?: bigint;
|
value?: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The chain ID for the network this transaction is valid on.
|
||||||
|
*/
|
||||||
chainId?: bigint;
|
chainId?: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[link-eip-2930]] access list. Storage slots included in the access
|
||||||
|
* list are //warmed// by pre-loading them, so their initial cost to
|
||||||
|
* fetch is guaranteed, but then each additional access is cheaper.
|
||||||
|
*/
|
||||||
accessList?: AccessList;
|
accessList?: AccessList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom object, which can be passed along for network-specific
|
||||||
|
* values.
|
||||||
|
*/
|
||||||
customData?: any;
|
customData?: any;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When using ``call`` or ``estimateGas``, this allows a specific
|
||||||
|
* block to be queried. Many backends do not support this and when
|
||||||
|
* unsupported errors are silently squelched and ``"latest"`` is used.
|
||||||
|
*/
|
||||||
blockTag?: BlockTag;
|
blockTag?: BlockTag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When using ``call``, this enables CCIP-read, which permits the
|
||||||
|
* provider to be redirected to web-based content during execution,
|
||||||
|
* which is then further validated by the contract.
|
||||||
|
*
|
||||||
|
* There are potential security implications allowing CCIP-read, as
|
||||||
|
* it could be used to expose the IP address or user activity during
|
||||||
|
* the fetch to unexpected parties.
|
||||||
|
*/
|
||||||
enableCcipRead?: boolean;
|
enableCcipRead?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a copy of %%req%% with all properties coerced to their strict
|
||||||
|
* types.
|
||||||
|
*/
|
||||||
export function copyRequest(req: TransactionRequest): PreparedTransactionRequest {
|
export function copyRequest(req: TransactionRequest): PreparedTransactionRequest {
|
||||||
const result: any = { };
|
const result: any = { };
|
||||||
|
|
||||||
@ -206,10 +372,30 @@ export function copyRequest(req: TransactionRequest): PreparedTransactionRequest
|
|||||||
* Before a block is included, it is a //pending// block.
|
* Before a block is included, it is a //pending// block.
|
||||||
*/
|
*/
|
||||||
export interface MinedBlock extends Block {
|
export interface MinedBlock extends Block {
|
||||||
|
/**
|
||||||
|
* The block number also known as the block height.
|
||||||
|
*/
|
||||||
readonly number: number;
|
readonly number: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block hash.
|
||||||
|
*/
|
||||||
readonly hash: string;
|
readonly hash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block timestamp, in seconds from epoch.
|
||||||
|
*/
|
||||||
readonly timestamp: number;
|
readonly timestamp: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block date, created from the [[timestamp]].
|
||||||
|
*/
|
||||||
readonly date: Date;
|
readonly date: Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The miner of the block, also known as the ``author`` or
|
||||||
|
* block ``producer``.
|
||||||
|
*/
|
||||||
readonly miner: string;
|
readonly miner: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,6 +404,7 @@ export interface MinedBlock extends Block {
|
|||||||
* Ethereum.
|
* Ethereum.
|
||||||
*/
|
*/
|
||||||
export class Block implements BlockParams, Iterable<string> {
|
export class Block implements BlockParams, Iterable<string> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The provider connected to the block used to fetch additional details
|
* The provider connected to the block used to fetch additional details
|
||||||
* if necessary.
|
* if necessary.
|
||||||
@ -232,6 +419,9 @@ export class Block implements BlockParams, Iterable<string> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The block hash.
|
* The block hash.
|
||||||
|
*
|
||||||
|
* This hash includes all properties, so can be safely used to identify
|
||||||
|
* an exact set of block properties.
|
||||||
*/
|
*/
|
||||||
readonly hash!: null | string;
|
readonly hash!: null | string;
|
||||||
|
|
||||||
@ -348,7 +538,7 @@ export class Block implements BlockParams, Iterable<string> {
|
|||||||
/**
|
/**
|
||||||
* Returns the complete transactions for blocks which
|
* Returns the complete transactions for blocks which
|
||||||
* prefetched them, by passing ``true`` to %%prefetchTxs%%
|
* prefetched them, by passing ``true`` to %%prefetchTxs%%
|
||||||
* into [[provider_getBlock]].
|
* into [[Provider-getBlock]].
|
||||||
*/
|
*/
|
||||||
get prefetchedTransactions(): Array<TransactionResponse> {
|
get prefetchedTransactions(): Array<TransactionResponse> {
|
||||||
const txs = this.#transactions.slice();
|
const txs = this.#transactions.slice();
|
||||||
@ -445,6 +635,12 @@ export class Block implements BlockParams, Iterable<string> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a **Block** was fetched with a request to include the transactions
|
||||||
|
* this will allow synchronous access to those transactions.
|
||||||
|
*
|
||||||
|
* If the transactions were not prefetched, this will throw.
|
||||||
|
*/
|
||||||
getPrefetchedTransaction(indexOrHash: number | string): TransactionResponse {
|
getPrefetchedTransaction(indexOrHash: number | string): TransactionResponse {
|
||||||
const txs = this.prefetchedTransactions;
|
const txs = this.prefetchedTransactions;
|
||||||
if (typeof(indexOrHash) === "number") {
|
if (typeof(indexOrHash) === "number") {
|
||||||
@ -460,20 +656,21 @@ export class Block implements BlockParams, Iterable<string> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Has this block been mined.
|
* Returns true if this block been mined. This provides a type guard
|
||||||
*
|
* for all properties on a [[MinedBlock]].
|
||||||
* If true, the block has been typed-gaurded that all mined
|
|
||||||
* properties are non-null.
|
|
||||||
*/
|
*/
|
||||||
isMined(): this is MinedBlock { return !!this.hash; }
|
isMined(): this is MinedBlock { return !!this.hash; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Returns true if this block is an [[link-eip-2930]] block.
|
||||||
*/
|
*/
|
||||||
isLondon(): this is (Block & { baseFeePerGas: bigint }) {
|
isLondon(): this is (Block & { baseFeePerGas: bigint }) {
|
||||||
return !!this.baseFeePerGas;
|
return !!this.baseFeePerGas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
orphanedEvent(): OrphanFilter {
|
orphanedEvent(): OrphanFilter {
|
||||||
if (!this.isMined()) { throw new Error(""); }
|
if (!this.isMined()) { throw new Error(""); }
|
||||||
return createOrphanedBlockFilter(this);
|
return createOrphanedBlockFilter(this);
|
||||||
@ -483,24 +680,80 @@ export class Block implements BlockParams, Iterable<string> {
|
|||||||
//////////////////////
|
//////////////////////
|
||||||
// Log
|
// Log
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **Log** in Ethereum represents an event that has been included in a
|
||||||
|
* transaction using the ``LOG*`` opcodes, which are most commonly used by
|
||||||
|
* Solidity's emit for announcing events.
|
||||||
|
*/
|
||||||
export class Log implements LogParams {
|
export class Log implements LogParams {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The provider connected to the log used to fetch additional details
|
||||||
|
* if necessary.
|
||||||
|
*/
|
||||||
readonly provider: Provider;
|
readonly provider: Provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction hash of the transaction this log occurred in. Use the
|
||||||
|
* [[Log-getTransaction]] to get the [[TransactionResponse]].
|
||||||
|
*/
|
||||||
readonly transactionHash!: string;
|
readonly transactionHash!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block hash of the block this log occurred in. Use the
|
||||||
|
* [[Log-getBlock]] to get the [[Block]].
|
||||||
|
*/
|
||||||
readonly blockHash!: string;
|
readonly blockHash!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block number of the block this log occurred in. It is preferred
|
||||||
|
* to use the [[Block-hash]] when fetching the related [[Block]],
|
||||||
|
* since in the case of an orphaned block, the block at that height may
|
||||||
|
* have changed.
|
||||||
|
*/
|
||||||
readonly blockNumber!: number;
|
readonly blockNumber!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the **Log** represents a block that was removed due to an orphaned
|
||||||
|
* block, this will be true.
|
||||||
|
*
|
||||||
|
* This can only happen within an orphan event listener.
|
||||||
|
*/
|
||||||
readonly removed!: boolean;
|
readonly removed!: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The address of the contract that emitted this log.
|
||||||
|
*/
|
||||||
readonly address!: string;
|
readonly address!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data included in this log when it was emitted.
|
||||||
|
*/
|
||||||
readonly data!: string;
|
readonly data!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The indexed topics included in this log when it was emitted.
|
||||||
|
*
|
||||||
|
* All topics are included in the bloom filters, so they can be
|
||||||
|
* efficiently filtered using the [[Provider-getLogs]] method.
|
||||||
|
*/
|
||||||
readonly topics!: ReadonlyArray<string>;
|
readonly topics!: ReadonlyArray<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index within the block this log occurred at. This is generally
|
||||||
|
* not useful to developers, but can be used with the various roots
|
||||||
|
* to proof inclusion within a block.
|
||||||
|
*/
|
||||||
readonly index!: number;
|
readonly index!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index within the transaction of this log.
|
||||||
|
*/
|
||||||
readonly transactionIndex!: number;
|
readonly transactionIndex!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(log: LogParams, provider: Provider) {
|
constructor(log: LogParams, provider: Provider) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
|
|
||||||
@ -522,6 +775,9 @@ export class Log implements LogParams {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a JSON-compatible object.
|
||||||
|
*/
|
||||||
toJSON(): any {
|
toJSON(): any {
|
||||||
const {
|
const {
|
||||||
address, blockHash, blockNumber, data, index,
|
address, blockHash, blockNumber, data, index,
|
||||||
@ -535,24 +791,37 @@ export class Log implements LogParams {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the block that this log occurred in.
|
||||||
|
*/
|
||||||
async getBlock(): Promise<Block> {
|
async getBlock(): Promise<Block> {
|
||||||
const block = await this.provider.getBlock(this.blockHash);
|
const block = await this.provider.getBlock(this.blockHash);
|
||||||
assert(!!block, "failed to find transaction", "UNKNOWN_ERROR", { });
|
assert(!!block, "failed to find transaction", "UNKNOWN_ERROR", { });
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the transaction that this log occurred in.
|
||||||
|
*/
|
||||||
async getTransaction(): Promise<TransactionResponse> {
|
async getTransaction(): Promise<TransactionResponse> {
|
||||||
const tx = await this.provider.getTransaction(this.transactionHash);
|
const tx = await this.provider.getTransaction(this.transactionHash);
|
||||||
assert(!!tx, "failed to find transaction", "UNKNOWN_ERROR", { });
|
assert(!!tx, "failed to find transaction", "UNKNOWN_ERROR", { });
|
||||||
return tx;
|
return tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the transaction receipt fot the transaction that this
|
||||||
|
* log occurred in.
|
||||||
|
*/
|
||||||
async getTransactionReceipt(): Promise<TransactionReceipt> {
|
async getTransactionReceipt(): Promise<TransactionReceipt> {
|
||||||
const receipt = await this.provider.getTransactionReceipt(this.transactionHash);
|
const receipt = await this.provider.getTransactionReceipt(this.transactionHash);
|
||||||
assert(!!receipt, "failed to find transaction receipt", "UNKNOWN_ERROR", { });
|
assert(!!receipt, "failed to find transaction receipt", "UNKNOWN_ERROR", { });
|
||||||
return receipt;
|
return receipt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
removedEvent(): OrphanFilter {
|
removedEvent(): OrphanFilter {
|
||||||
return createRemovedLogFilter(this);
|
return createRemovedLogFilter(this);
|
||||||
}
|
}
|
||||||
@ -575,32 +844,118 @@ export interface ByzantiumTransactionReceipt {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **TransactionReceipt** includes additional information about a
|
||||||
|
* transaction that is only available after it has been mined.
|
||||||
|
*/
|
||||||
export class TransactionReceipt implements TransactionReceiptParams, Iterable<Log> {
|
export class TransactionReceipt implements TransactionReceiptParams, Iterable<Log> {
|
||||||
|
/**
|
||||||
|
* The provider connected to the log used to fetch additional details
|
||||||
|
* if necessary.
|
||||||
|
*/
|
||||||
readonly provider!: Provider;
|
readonly provider!: Provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The address the transaction was send to.
|
||||||
|
*/
|
||||||
readonly to!: null | string;
|
readonly to!: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sender of the transaction.
|
||||||
|
*/
|
||||||
readonly from!: string;
|
readonly from!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The address of the contract if the transaction was directly
|
||||||
|
* responsible for deploying one.
|
||||||
|
*
|
||||||
|
* This is non-null **only** if the ``to`` is empty and the ``data``
|
||||||
|
* was successfully executed as initcode.
|
||||||
|
*/
|
||||||
readonly contractAddress!: null | string;
|
readonly contractAddress!: null | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction hash.
|
||||||
|
*/
|
||||||
readonly hash!: string;
|
readonly hash!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index of this transaction within the block transactions.
|
||||||
|
*/
|
||||||
readonly index!: number;
|
readonly index!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block hash of the [[Block]] this transaction was included in.
|
||||||
|
*/
|
||||||
readonly blockHash!: string;
|
readonly blockHash!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block number of the [[Block]] this transaction was included in.
|
||||||
|
*/
|
||||||
readonly blockNumber!: number;
|
readonly blockNumber!: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bloom filter bytes that represent all logs that occurred within
|
||||||
|
* this transaction. This is generally not useful for most developers,
|
||||||
|
* but can be used to validate the included logs.
|
||||||
|
*/
|
||||||
readonly logsBloom!: string;
|
readonly logsBloom!: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual amount of gas used by this transaction.
|
||||||
|
*
|
||||||
|
* When creating a transaction, the amount of gas that will be used can
|
||||||
|
* only be approximated, but the sender must pay the gas fee for the
|
||||||
|
* entire gas limit. After the transaction, the difference is refunded.
|
||||||
|
*/
|
||||||
readonly gasUsed!: bigint;
|
readonly gasUsed!: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of gas used by all transactions within the block for this
|
||||||
|
* and all transactions with a lower ``index``.
|
||||||
|
*
|
||||||
|
* This is generally not useful for developers but can be used to
|
||||||
|
* validate certain aspects of execution.
|
||||||
|
*/
|
||||||
readonly cumulativeGasUsed!: bigint;
|
readonly cumulativeGasUsed!: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual gas price used during execution.
|
||||||
|
*
|
||||||
|
* Due to the complexity of [[link-eip-1559]] this value can only
|
||||||
|
* be caluclated after the transaction has been mined, snce the base
|
||||||
|
* fee is protocol-enforced.
|
||||||
|
*/
|
||||||
readonly gasPrice!: bigint;
|
readonly gasPrice!: bigint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [[link-eip-2718]] transaction type.
|
||||||
|
*/
|
||||||
readonly type!: number;
|
readonly type!: number;
|
||||||
//readonly byzantium!: boolean;
|
//readonly byzantium!: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status of this transaction, indicating success (i.e. ``1``) or
|
||||||
|
* a revert (i.e. ``0``).
|
||||||
|
*
|
||||||
|
* This is available in post-byzantium blocks, but some backends may
|
||||||
|
* backfill this value.
|
||||||
|
*/
|
||||||
readonly status!: null | number;
|
readonly status!: null | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root hash of this transaction.
|
||||||
|
*
|
||||||
|
* This is no present and was only included in pre-byzantium blocks, but
|
||||||
|
* could be used to validate certain parts of the receipt.
|
||||||
|
*/
|
||||||
readonly root!: null | string;
|
readonly root!: null | string;
|
||||||
|
|
||||||
readonly #logs: ReadonlyArray<Log>;
|
readonly #logs: ReadonlyArray<Log>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
constructor(tx: TransactionReceiptParams, provider: Provider) {
|
constructor(tx: TransactionReceiptParams, provider: Provider) {
|
||||||
this.#logs = Object.freeze(tx.logs.map((log) => {
|
this.#logs = Object.freeze(tx.logs.map((log) => {
|
||||||
return new Log(log, provider);
|
return new Log(log, provider);
|
||||||
@ -639,8 +994,14 @@ export class TransactionReceipt implements TransactionReceiptParams, Iterable<Lo
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logs for this transaction.
|
||||||
|
*/
|
||||||
get logs(): ReadonlyArray<Log> { return this.#logs; }
|
get logs(): ReadonlyArray<Log> { return this.#logs; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a JSON-compatible representation.
|
||||||
|
*/
|
||||||
toJSON(): any {
|
toJSON(): any {
|
||||||
const {
|
const {
|
||||||
to, from, contractAddress, hash, index, blockHash, blockNumber, logsBloom,
|
to, from, contractAddress, hash, index, blockHash, blockNumber, logsBloom,
|
||||||
@ -661,6 +1022,9 @@ export class TransactionReceipt implements TransactionReceiptParams, Iterable<Lo
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
get length(): number { return this.logs.length; }
|
get length(): number { return this.logs.length; }
|
||||||
|
|
||||||
[Symbol.iterator](): Iterator<Log> {
|
[Symbol.iterator](): Iterator<Log> {
|
||||||
@ -675,34 +1039,58 @@ export class TransactionReceipt implements TransactionReceiptParams, Iterable<Lo
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total fee for this transaction, in wei.
|
||||||
|
*/
|
||||||
get fee(): bigint {
|
get fee(): bigint {
|
||||||
return this.gasUsed * this.gasPrice;
|
return this.gasUsed * this.gasPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the block this transaction occurred in.
|
||||||
|
*/
|
||||||
async getBlock(): Promise<Block> {
|
async getBlock(): Promise<Block> {
|
||||||
const block = await this.provider.getBlock(this.blockHash);
|
const block = await this.provider.getBlock(this.blockHash);
|
||||||
if (block == null) { throw new Error("TODO"); }
|
if (block == null) { throw new Error("TODO"); }
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the transaction this transaction occurred in.
|
||||||
|
*/
|
||||||
async getTransaction(): Promise<TransactionResponse> {
|
async getTransaction(): Promise<TransactionResponse> {
|
||||||
const tx = await this.provider.getTransaction(this.hash);
|
const tx = await this.provider.getTransaction(this.hash);
|
||||||
if (tx == null) { throw new Error("TODO"); }
|
if (tx == null) { throw new Error("TODO"); }
|
||||||
return tx;
|
return tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the return value of the execution of this transaction.
|
||||||
|
*
|
||||||
|
* Support for this feature is limited, as it requires an archive node
|
||||||
|
* with the ``debug_`` or ``trace_`` API enabled.
|
||||||
|
*/
|
||||||
async getResult(): Promise<string> {
|
async getResult(): Promise<string> {
|
||||||
return <string>(await this.provider.getTransactionResult(this.hash));
|
return <string>(await this.provider.getTransactionResult(this.hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves to the number of confirmations this transaction has.
|
||||||
|
*/
|
||||||
async confirmations(): Promise<number> {
|
async confirmations(): Promise<number> {
|
||||||
return (await this.provider.getBlockNumber()) - this.blockNumber + 1;
|
return (await this.provider.getBlockNumber()) - this.blockNumber + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
removedEvent(): OrphanFilter {
|
removedEvent(): OrphanFilter {
|
||||||
return createRemovedTransactionFilter(this);
|
return createRemovedTransactionFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @_ignore:
|
||||||
|
*/
|
||||||
reorderedEvent(other?: TransactionResponse): OrphanFilter {
|
reorderedEvent(other?: TransactionResponse): OrphanFilter {
|
||||||
assert(!other || other.isMined(), "unmined 'other' transction cannot be orphaned",
|
assert(!other || other.isMined(), "unmined 'other' transction cannot be orphaned",
|
||||||
"UNSUPPORTED_OPERATION", { operation: "reorderedEvent(other)" });
|
"UNSUPPORTED_OPERATION", { operation: "reorderedEvent(other)" });
|
||||||
@ -714,22 +1102,38 @@ export class TransactionReceipt implements TransactionReceiptParams, Iterable<Lo
|
|||||||
//////////////////////
|
//////////////////////
|
||||||
// Transaction Response
|
// Transaction Response
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **MinedTransactionResponse** is an interface representing a
|
||||||
|
* transaction which has been mined and allows for a type guard for its
|
||||||
|
* property values being defined.
|
||||||
|
*/
|
||||||
export interface MinedTransactionResponse extends TransactionResponse {
|
export interface MinedTransactionResponse extends TransactionResponse {
|
||||||
|
/**
|
||||||
|
* The block number this transaction occurred in.
|
||||||
|
*/
|
||||||
blockNumber: number;
|
blockNumber: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block hash this transaction occurred in.
|
||||||
|
*/
|
||||||
blockHash: string;
|
blockHash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The date this transaction occurred on.
|
||||||
|
*/
|
||||||
date: Date;
|
date: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
export type ReplacementDetectionSetup = {
|
/**
|
||||||
to: string;
|
* A **TransactionResponse** includes all properties about a transaction
|
||||||
from: string;
|
* that was sent to the network, which may or may not be included in a
|
||||||
value: bigint;
|
* block.
|
||||||
data: string;
|
*
|
||||||
nonce: number;
|
* The [[TransactionResponse-isMined]] can be used to check if the
|
||||||
block: number;
|
* transaction has been mined as well as type guard that the otherwise
|
||||||
};
|
* possibly ``null`` properties are defined.
|
||||||
*/
|
*/
|
||||||
export class TransactionResponse implements TransactionLike<string>, TransactionResponseParams {
|
export class TransactionResponse implements TransactionLike<string>, TransactionResponseParams {
|
||||||
/**
|
/**
|
||||||
* The provider this is connected to, which will influence how its
|
* The provider this is connected to, which will influence how its
|
||||||
@ -858,8 +1262,7 @@ export class TransactionResponse implements TransactionLike<string>, Transaction
|
|||||||
#startBlock: number;
|
#startBlock: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new TransactionResponse with %%tx%% parameters
|
* @_ignore:
|
||||||
* connected to %%provider%%.
|
|
||||||
*/
|
*/
|
||||||
constructor(tx: TransactionResponseParams, provider: Provider) {
|
constructor(tx: TransactionResponseParams, provider: Provider) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
@ -893,7 +1296,7 @@ export class TransactionResponse implements TransactionLike<string>, Transaction
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a JSON representation of this transaction.
|
* Returns a JSON-compatible representation of this transaction.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): any {
|
||||||
const {
|
const {
|
||||||
@ -1272,17 +1675,40 @@ export type TopicFilter = Array<null | string | Array<string>>;
|
|||||||
// @TODO:
|
// @TODO:
|
||||||
//export type DeferableTopicFilter = Array<null | string | Promise<string> | Array<string | Promise<string>>>;
|
//export type DeferableTopicFilter = Array<null | string | Promise<string> | Array<string | Promise<string>>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An **EventFilter** allows efficiently filtering logs (also known as
|
||||||
|
* events) using bloom filters included within blocks.
|
||||||
|
*/
|
||||||
export interface EventFilter {
|
export interface EventFilter {
|
||||||
address?: AddressLike | Array<AddressLike>;
|
address?: AddressLike | Array<AddressLike>;
|
||||||
topics?: TopicFilter;
|
topics?: TopicFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **Filter** allows searching a specific range of blocks for mathcing
|
||||||
|
* logs.
|
||||||
|
*/
|
||||||
export interface Filter extends EventFilter {
|
export interface Filter extends EventFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The start block for the filter (inclusive).
|
||||||
|
*/
|
||||||
fromBlock?: BlockTag;
|
fromBlock?: BlockTag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The end block for the filter (inclusive).
|
||||||
|
*/
|
||||||
toBlock?: BlockTag;
|
toBlock?: BlockTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **FilterByBlockHash** allows searching a specific block for mathcing
|
||||||
|
* logs.
|
||||||
|
*/
|
||||||
export interface FilterByBlockHash extends EventFilter {
|
export interface FilterByBlockHash extends EventFilter {
|
||||||
|
/**
|
||||||
|
* The blockhash of the specific block for the filter.
|
||||||
|
*/
|
||||||
blockHash?: string;
|
blockHash?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1290,6 +1716,30 @@ export interface FilterByBlockHash extends EventFilter {
|
|||||||
//////////////////////
|
//////////////////////
|
||||||
// ProviderEvent
|
// ProviderEvent
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **ProviderEvent** provides the types of events that can be subscribed
|
||||||
|
* to on a [[Provider]].
|
||||||
|
*
|
||||||
|
* Each provider may include additional possible events it supports, but
|
||||||
|
* the most commonly supported are:
|
||||||
|
*
|
||||||
|
* **``"block"``** - calls the listener with the current block number on each
|
||||||
|
* new block.
|
||||||
|
*
|
||||||
|
* **``"error"``** - calls the listener on each async error that occurs during
|
||||||
|
* the event loop, with the error.
|
||||||
|
*
|
||||||
|
* **``"debug"``** - calls the listener on debug events, which can be used to
|
||||||
|
* troubleshoot network errors, provider problems, etc.
|
||||||
|
*
|
||||||
|
* **``transaction hash``** - calls the listener on each block after the
|
||||||
|
* transaction has been mined; generally ``.once`` is more appropriate for
|
||||||
|
* this event.
|
||||||
|
*
|
||||||
|
* **``Array``** - calls the listener on each log that matches the filter.
|
||||||
|
*
|
||||||
|
* [[EventFilter]] - calls the listener with each matching log
|
||||||
|
*/
|
||||||
export type ProviderEvent = string | Array<string | Array<string>> | EventFilter | OrphanFilter;
|
export type ProviderEvent = string | Array<string | Array<string>> | EventFilter | OrphanFilter;
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,12 +9,23 @@ import type {
|
|||||||
import type { Signer } from "./signer.js";
|
import type { Signer } from "./signer.js";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **NonceManager** wraps another [[Signer]] and automatically manages
|
||||||
|
* the nonce, ensuring serialized and sequential nonces are used during
|
||||||
|
* transaction.
|
||||||
|
*/
|
||||||
export class NonceManager extends AbstractSigner {
|
export class NonceManager extends AbstractSigner {
|
||||||
|
/**
|
||||||
|
* The Signer being managed.
|
||||||
|
*/
|
||||||
signer!: Signer;
|
signer!: Signer;
|
||||||
|
|
||||||
#noncePromise: null | Promise<number>;
|
#noncePromise: null | Promise<number>;
|
||||||
#delta: number;
|
#delta: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **NonceManager** to manage %%signer%%.
|
||||||
|
*/
|
||||||
constructor(signer: Signer) {
|
constructor(signer: Signer) {
|
||||||
super(signer.provider);
|
super(signer.provider);
|
||||||
defineProperties<NonceManager>(this, { signer });
|
defineProperties<NonceManager>(this, { signer });
|
||||||
@ -44,10 +55,18 @@ export class NonceManager extends AbstractSigner {
|
|||||||
return super.getNonce(blockTag);
|
return super.getNonce(blockTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manually increment the nonce. This may be useful when managng
|
||||||
|
* offline transactions.
|
||||||
|
*/
|
||||||
increment(): void {
|
increment(): void {
|
||||||
this.#delta++;
|
this.#delta++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the nonce, causing the **NonceManager** to reload the current
|
||||||
|
* nonce from the blockchain on the next transaction.
|
||||||
|
*/
|
||||||
reset(): void {
|
reset(): void {
|
||||||
this.#delta = 0;
|
this.#delta = 0;
|
||||||
this.#noncePromise = null;
|
this.#noncePromise = null;
|
||||||
|
@ -33,6 +33,11 @@ export class FilterIdSubscriber implements Subscriber {
|
|||||||
|
|
||||||
#hault: boolean;
|
#hault: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **FilterIdSubscriber** which will used [[_subscribe]]
|
||||||
|
* and [[_emitResults]] to setup the subscription and provide the event
|
||||||
|
* to the %%provider%%.
|
||||||
|
*/
|
||||||
constructor(provider: JsonRpcApiProvider) {
|
constructor(provider: JsonRpcApiProvider) {
|
||||||
this.#provider = provider;
|
this.#provider = provider;
|
||||||
|
|
||||||
@ -46,14 +51,23 @@ export class FilterIdSubscriber implements Subscriber {
|
|||||||
this.#hault = false;
|
this.#hault = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub-classes **must** override this to begin the subscription.
|
||||||
|
*/
|
||||||
_subscribe(provider: JsonRpcApiProvider): Promise<string> {
|
_subscribe(provider: JsonRpcApiProvider): Promise<string> {
|
||||||
throw new Error("subclasses must override this");
|
throw new Error("subclasses must override this");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub-classes **must** override this handle the events.
|
||||||
|
*/
|
||||||
_emitResults(provider: AbstractProvider, result: Array<any>): Promise<void> {
|
_emitResults(provider: AbstractProvider, result: Array<any>): Promise<void> {
|
||||||
throw new Error("subclasses must override this");
|
throw new Error("subclasses must override this");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub-classes **must** override this handle recovery on errors.
|
||||||
|
*/
|
||||||
_recover(provider: AbstractProvider): Subscriber {
|
_recover(provider: AbstractProvider): Subscriber {
|
||||||
throw new Error("subclasses must override this");
|
throw new Error("subclasses must override this");
|
||||||
}
|
}
|
||||||
@ -141,6 +155,10 @@ export class FilterIdSubscriber implements Subscriber {
|
|||||||
export class FilterIdEventSubscriber extends FilterIdSubscriber {
|
export class FilterIdEventSubscriber extends FilterIdSubscriber {
|
||||||
#event: EventFilter;
|
#event: EventFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new **FilterIdEventSubscriber** attached to %%provider%%
|
||||||
|
* listening for %%filter%%.
|
||||||
|
*/
|
||||||
constructor(provider: JsonRpcApiProvider, filter: EventFilter) {
|
constructor(provider: JsonRpcApiProvider, filter: EventFilter) {
|
||||||
super(provider);
|
super(provider);
|
||||||
this.#event = copy(filter);
|
this.#event = copy(filter);
|
||||||
|
@ -8,7 +8,7 @@ function copy(obj: any): any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @TODO
|
* Return the polling subscriber for common events.
|
||||||
*
|
*
|
||||||
* @_docloc: api/providers/abstract-provider
|
* @_docloc: api/providers/abstract-provider
|
||||||
*/
|
*/
|
||||||
@ -24,7 +24,8 @@ export function getPollingSubscriber(provider: AbstractProvider, event: Provider
|
|||||||
// @TODO: refactor this
|
// @TODO: refactor this
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @TODO
|
* A **PollingBlockSubscriber** polls at a regular interval for a change
|
||||||
|
* in the block number.
|
||||||
*
|
*
|
||||||
* @_docloc: api/providers/abstract-provider
|
* @_docloc: api/providers/abstract-provider
|
||||||
*/
|
*/
|
||||||
@ -38,6 +39,9 @@ export class PollingBlockSubscriber implements Subscriber {
|
|||||||
// indicates we still need to fetch an initial block number
|
// indicates we still need to fetch an initial block number
|
||||||
#blockNumber: number;
|
#blockNumber: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new **PollingBlockSubscriber** attached to %%provider%%.
|
||||||
|
*/
|
||||||
constructor(provider: AbstractProvider) {
|
constructor(provider: AbstractProvider) {
|
||||||
this.#provider = provider;
|
this.#provider = provider;
|
||||||
this.#poller = null;
|
this.#poller = null;
|
||||||
@ -46,6 +50,9 @@ export class PollingBlockSubscriber implements Subscriber {
|
|||||||
this.#blockNumber = -2;
|
this.#blockNumber = -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The polling interval.
|
||||||
|
*/
|
||||||
get pollingInterval(): number { return this.#interval; }
|
get pollingInterval(): number { return this.#interval; }
|
||||||
set pollingInterval(value: number) { this.#interval = value; }
|
set pollingInterval(value: number) { this.#interval = value; }
|
||||||
|
|
||||||
@ -107,7 +114,8 @@ export class PollingBlockSubscriber implements Subscriber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @TODO
|
* An **OnBlockSubscriber** can be sub-classed, with a [[_poll]]
|
||||||
|
* implmentation which will be called on every new block.
|
||||||
*
|
*
|
||||||
* @_docloc: api/providers/abstract-provider
|
* @_docloc: api/providers/abstract-provider
|
||||||
*/
|
*/
|
||||||
@ -116,6 +124,9 @@ export class OnBlockSubscriber implements Subscriber {
|
|||||||
#poll: (b: number) => void;
|
#poll: (b: number) => void;
|
||||||
#running: boolean;
|
#running: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new **OnBlockSubscriber** attached to %%provider%%.
|
||||||
|
*/
|
||||||
constructor(provider: AbstractProvider) {
|
constructor(provider: AbstractProvider) {
|
||||||
this.#provider = provider;
|
this.#provider = provider;
|
||||||
this.#running = false;
|
this.#running = false;
|
||||||
@ -124,6 +135,9 @@ export class OnBlockSubscriber implements Subscriber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on every new block.
|
||||||
|
*/
|
||||||
async _poll(blockNumber: number, provider: AbstractProvider): Promise<void> {
|
async _poll(blockNumber: number, provider: AbstractProvider): Promise<void> {
|
||||||
throw new Error("sub-classes must override this");
|
throw new Error("sub-classes must override this");
|
||||||
}
|
}
|
||||||
@ -148,7 +162,7 @@ export class OnBlockSubscriber implements Subscriber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @TODO
|
* @_ignore:
|
||||||
*
|
*
|
||||||
* @_docloc: api/providers/abstract-provider
|
* @_docloc: api/providers/abstract-provider
|
||||||
*/
|
*/
|
||||||
@ -167,13 +181,18 @@ export class PollingOrphanSubscriber extends OnBlockSubscriber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @TODO
|
* A **PollingTransactionSubscriber** will poll for a given transaction
|
||||||
|
* hash for its receipt.
|
||||||
*
|
*
|
||||||
* @_docloc: api/providers/abstract-provider
|
* @_docloc: api/providers/abstract-provider
|
||||||
*/
|
*/
|
||||||
export class PollingTransactionSubscriber extends OnBlockSubscriber {
|
export class PollingTransactionSubscriber extends OnBlockSubscriber {
|
||||||
#hash: string;
|
#hash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new **PollingTransactionSubscriber** attached to
|
||||||
|
* %%provider%%, listening for %%hash%%.
|
||||||
|
*/
|
||||||
constructor(provider: AbstractProvider, hash: string) {
|
constructor(provider: AbstractProvider, hash: string) {
|
||||||
super(provider);
|
super(provider);
|
||||||
this.#hash = hash;
|
this.#hash = hash;
|
||||||
@ -186,7 +205,7 @@ export class PollingTransactionSubscriber extends OnBlockSubscriber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @TODO
|
* A **PollingEventSubscriber** will poll for a given filter for its logs.
|
||||||
*
|
*
|
||||||
* @_docloc: api/providers/abstract-provider
|
* @_docloc: api/providers/abstract-provider
|
||||||
*/
|
*/
|
||||||
@ -201,6 +220,10 @@ export class PollingEventSubscriber implements Subscriber {
|
|||||||
// indicates we still need to fetch an initial block number
|
// indicates we still need to fetch an initial block number
|
||||||
#blockNumber: number;
|
#blockNumber: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new **PollingTransactionSubscriber** attached to
|
||||||
|
* %%provider%%, listening for %%filter%%.
|
||||||
|
*/
|
||||||
constructor(provider: AbstractProvider, filter: EventFilter) {
|
constructor(provider: AbstractProvider, filter: EventFilter) {
|
||||||
this.#provider = provider;
|
this.#provider = provider;
|
||||||
this.#filter = copy(filter);
|
this.#filter = copy(filter);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Transactions..
|
* Each state-changing operation on Ethereum requires a transaction.
|
||||||
*
|
*
|
||||||
* @_section api/transaction:Transactions [about-transactions]
|
* @_section api/transaction:Transactions [about-transactions]
|
||||||
*/
|
*/
|
||||||
|
@ -22,6 +22,11 @@ const BN_28 = BigInt(28)
|
|||||||
const BN_35 = BigInt(35);
|
const BN_35 = BigInt(35);
|
||||||
const BN_MAX_UINT = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
const BN_MAX_UINT = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A **TransactionLike** is an object which is appropriate as a loose
|
||||||
|
* input for many operations which will populate missing properties of
|
||||||
|
* a transaction.
|
||||||
|
*/
|
||||||
export interface TransactionLike<A = string> {
|
export interface TransactionLike<A = string> {
|
||||||
/**
|
/**
|
||||||
* The type.
|
* The type.
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* About Errors.
|
* All errors in ethers include properties to ensure they are both
|
||||||
|
* human-readable (i.e. ``.message``) and machine-readable (i.e. ``.code``).
|
||||||
|
*
|
||||||
|
* The [[isError]] function can be used to check the error ``code`` and
|
||||||
|
* provide a type guard for the properties present on that error interface.
|
||||||
*
|
*
|
||||||
* @_section: api/utils/errors:Errors [about-errors]
|
* @_section: api/utils/errors:Errors [about-errors]
|
||||||
*/
|
*/
|
||||||
@ -14,6 +18,10 @@ import type {
|
|||||||
|
|
||||||
import type { FetchRequest, FetchResponse } from "./fetch.js";
|
import type { FetchRequest, FetchResponse } from "./fetch.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An error may contain additional properties, but those must not
|
||||||
|
* conflict with any impliciat properties.
|
||||||
|
*/
|
||||||
export type ErrorInfo<T> = Omit<T, "code" | "name" | "message">;
|
export type ErrorInfo<T> = Omit<T, "code" | "name" | "message">;
|
||||||
|
|
||||||
|
|
||||||
@ -202,6 +210,9 @@ export interface UnsupportedOperationError extends EthersError<"UNSUPPORTED_OPER
|
|||||||
operation: string;
|
operation: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Error indicates a proplem connecting to a network.
|
||||||
|
*/
|
||||||
export interface NetworkError extends EthersError<"NETWORK_ERROR"> {
|
export interface NetworkError extends EthersError<"NETWORK_ERROR"> {
|
||||||
event: string;
|
event: string;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Explain events...
|
* Events allow for applications to use the observer pattern, which
|
||||||
|
* allows subscribing and publishing events, outside the normal
|
||||||
|
* execution paths.
|
||||||
*
|
*
|
||||||
* @_section api/utils/events:Events [about-events]
|
* @_section api/utils/events:Events [about-events]
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* Explain fetching here...
|
* Fetching content from the web is environment-specific, so Ethers
|
||||||
|
* provides an abstraction the each environment can implement to provide
|
||||||
|
* this service.
|
||||||
|
*
|
||||||
|
* On [Node.js](link-node), the ``http`` and ``https`` libs are used to
|
||||||
|
* create a request object, register event listeners and process data
|
||||||
|
* and populate the [[FetchResponse]].
|
||||||
|
*
|
||||||
|
* In a browser, the [DOM fetch](link-js-fetch) is used, and the resulting
|
||||||
|
* ``Promise`` is waited on to retreive the payload.
|
||||||
|
*
|
||||||
|
* The [[FetchRequest]] is responsible for handling many common situations,
|
||||||
|
* such as redirects, server throttling, authentcation, etc.
|
||||||
|
*
|
||||||
|
* It also handles common gateways, such as IPFS and data URIs.
|
||||||
*
|
*
|
||||||
* @_section api/utils/fetching:Fetching Web Content [about-fetch]
|
* @_section api/utils/fetching:Fetching Web Content [about-fetch]
|
||||||
*/
|
*/
|
||||||
@ -11,7 +25,9 @@ import { toUtf8Bytes, toUtf8String } from "./utf8.js"
|
|||||||
|
|
||||||
import { getUrl } from "./geturl.js";
|
import { getUrl } from "./geturl.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An environments implementation of ``getUrl`` must return this type.
|
||||||
|
*/
|
||||||
export type GetUrlResponse = {
|
export type GetUrlResponse = {
|
||||||
statusCode: number,
|
statusCode: number,
|
||||||
statusMessage: string,
|
statusMessage: string,
|
||||||
@ -19,10 +35,15 @@ export type GetUrlResponse = {
|
|||||||
body: null | Uint8Array
|
body: null | Uint8Array
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This can be used to control how throttling is handled in
|
||||||
|
* [[FetchRequest-setThrottleParams]].
|
||||||
|
*/
|
||||||
export type FetchThrottleParams = {
|
export type FetchThrottleParams = {
|
||||||
maxAttempts?: number;
|
maxAttempts?: number;
|
||||||
slotInterval?: number;
|
slotInterval?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before any network request, allowing updated headers (e.g. Bearer tokens), etc.
|
* Called before any network request, allowing updated headers (e.g. Bearer tokens), etc.
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* About fixed-point math...
|
* The **FixedNumber** class permits using values with decimal places,
|
||||||
|
* using fixed-pont math.
|
||||||
|
*
|
||||||
|
* Fixed-point math is still based on integers under-the-hood, but uses an
|
||||||
|
* internal offset to store fractional components below, and each operation
|
||||||
|
* corrects for this after each operation.
|
||||||
*
|
*
|
||||||
* @_section: api/utils/fixed-point-math:Fixed-Point Maths [about-fixed-point-math]
|
* @_section: api/utils/fixed-point-math:Fixed-Point Maths [about-fixed-point-math]
|
||||||
*/
|
*/
|
||||||
|
@ -113,6 +113,10 @@ export function getBigInt(value: BigNumberish, name?: string): bigint {
|
|||||||
assertArgument(false, "invalid BigNumberish value", name || "value", value);
|
assertArgument(false, "invalid BigNumberish value", name || "value", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns %%value%% as a bigint, validating it is valid as a bigint
|
||||||
|
* value and that it is positive.
|
||||||
|
*/
|
||||||
export function getUint(value: BigNumberish, name?: string): bigint {
|
export function getUint(value: BigNumberish, name?: string): bigint {
|
||||||
const result = getBigInt(value, name);
|
const result = getBigInt(value, name);
|
||||||
assert(result >= BN_0, "unsigned value cannot be negative", "NUMERIC_FAULT", {
|
assert(result >= BN_0, "unsigned value cannot be negative", "NUMERIC_FAULT", {
|
||||||
|
@ -18,7 +18,7 @@ import { Wordlist } from "./wordlist.js";
|
|||||||
* based on ASCII-7 small.
|
* based on ASCII-7 small.
|
||||||
*
|
*
|
||||||
* If necessary, there are tools within the ``generation/`` folder
|
* If necessary, there are tools within the ``generation/`` folder
|
||||||
* to create these necessary data.
|
* to create the necessary data.
|
||||||
*/
|
*/
|
||||||
export class WordlistOwl extends Wordlist {
|
export class WordlistOwl extends Wordlist {
|
||||||
#data: string;
|
#data: string;
|
||||||
@ -35,8 +35,14 @@ export class WordlistOwl extends Wordlist {
|
|||||||
this.#words = null;
|
this.#words = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The OWL-encoded data.
|
||||||
|
*/
|
||||||
get _data(): string { return this.#data; }
|
get _data(): string { return this.#data; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode all the words for the wordlist.
|
||||||
|
*/
|
||||||
_decodeWords(): Array<string> {
|
_decodeWords(): Array<string> {
|
||||||
return decodeOwl(this.#data);
|
return decodeOwl(this.#data);
|
||||||
}
|
}
|
||||||
|
@ -12,18 +12,29 @@ import { decodeOwlA } from "./decode-owla.js";
|
|||||||
* based on latin-1 small.
|
* based on latin-1 small.
|
||||||
*
|
*
|
||||||
* If necessary, there are tools within the ``generation/`` folder
|
* If necessary, there are tools within the ``generation/`` folder
|
||||||
* to create these necessary data.
|
* to create the necessary data.
|
||||||
*/
|
*/
|
||||||
export class WordlistOwlA extends WordlistOwl {
|
export class WordlistOwlA extends WordlistOwl {
|
||||||
#accent: string;
|
#accent: string;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Wordlist for %%locale%% using the OWLA %%data%%
|
||||||
|
* and %%accent%% data and validated against the %%checksum%%.
|
||||||
|
*/
|
||||||
constructor(locale: string, data: string, accent: string, checksum: string) {
|
constructor(locale: string, data: string, accent: string, checksum: string) {
|
||||||
super(locale, data, checksum);
|
super(locale, data, checksum);
|
||||||
this.#accent = accent;
|
this.#accent = accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The OWLA-encoded accent data.
|
||||||
|
*/
|
||||||
get _accent(): string { return this.#accent; }
|
get _accent(): string { return this.#accent; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode all the words for the wordlist.
|
||||||
|
*/
|
||||||
_decodeWords(): Array<string> {
|
_decodeWords(): Array<string> {
|
||||||
return decodeOwlA(this._data, this._accent);
|
return decodeOwlA(this._data, this._accent);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user