@woof-software/contracts-tools-sdk-ethers 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/lib/abis/index.d.ts +2 -0
- package/lib/abis/index.js +2 -0
- package/lib/abis/multicall.abi.json +440 -0
- package/lib/config.d.ts +37 -0
- package/lib/config.js +38 -0
- package/lib/constant.d.ts +12 -0
- package/lib/constant.js +12 -0
- package/lib/contract/base-contract.d.ts +23 -0
- package/lib/contract/base-contract.js +191 -0
- package/lib/contract/contract-create-call-name.d.ts +1 -0
- package/lib/contract/contract-create-call-name.js +1 -0
- package/lib/contract/index.d.ts +1 -0
- package/lib/contract/index.js +1 -0
- package/lib/errors/contracts-errors.d.ts +9 -0
- package/lib/errors/contracts-errors.js +9 -0
- package/lib/errors/index.d.ts +2 -0
- package/lib/errors/index.js +2 -0
- package/lib/errors/multicall-errors.d.ts +8 -0
- package/lib/errors/multicall-errors.js +8 -0
- package/lib/helpers/index.d.ts +6 -0
- package/lib/helpers/index.js +6 -0
- package/lib/helpers/is-parsable.d.ts +2 -0
- package/lib/helpers/is-parsable.js +1 -0
- package/lib/helpers/is-signer.d.ts +2 -0
- package/lib/helpers/is-signer.js +3 -0
- package/lib/helpers/is-static-array.d.ts +2 -0
- package/lib/helpers/is-static-array.js +2 -0
- package/lib/helpers/is-static-method.d.ts +2 -0
- package/lib/helpers/is-static-method.js +4 -0
- package/lib/helpers/priority-call.d.ts +5 -0
- package/lib/helpers/priority-call.js +55 -0
- package/lib/helpers/wait-for-address-txs.d.ts +2 -0
- package/lib/helpers/wait-for-address-txs.js +9 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +5 -0
- package/lib/multicall/index.d.ts +5 -0
- package/lib/multicall/index.js +5 -0
- package/lib/multicall/multicall-error-event-name.d.ts +2 -0
- package/lib/multicall/multicall-error-event-name.js +1 -0
- package/lib/multicall/multicall-generate-tag.d.ts +1 -0
- package/lib/multicall/multicall-generate-tag.js +1 -0
- package/lib/multicall/multicall-normalize-tags.d.ts +2 -0
- package/lib/multicall/multicall-normalize-tags.js +6 -0
- package/lib/multicall/multicall-result-event-name.d.ts +2 -0
- package/lib/multicall/multicall-result-event-name.js +1 -0
- package/lib/multicall/multicall-split-calls.d.ts +2 -0
- package/lib/multicall/multicall-split-calls.js +19 -0
- package/lib/multicall/multicall-unit.d.ts +48 -0
- package/lib/multicall/multicall-unit.js +367 -0
- package/lib/types/call-mutability.d.ts +4 -0
- package/lib/types/call-mutability.js +5 -0
- package/lib/types/contract/contract-auto-methods.d.ts +13 -0
- package/lib/types/contract/contract-auto-methods.js +1 -0
- package/lib/types/contract/contract-call-options.d.ts +9 -0
- package/lib/types/contract/contract-call-options.js +1 -0
- package/lib/types/contract/contract-call.d.ts +10 -0
- package/lib/types/contract/contract-call.js +1 -0
- package/lib/types/contract/contract-get-logs-options.d.ts +5 -0
- package/lib/types/contract/contract-get-logs-options.js +1 -0
- package/lib/types/contract/contract-options.d.ts +12 -0
- package/lib/types/contract/contract-options.js +1 -0
- package/lib/types/contract/dynamic-contract-constructor-args.d.ts +8 -0
- package/lib/types/contract/dynamic-contract-constructor-args.js +1 -0
- package/lib/types/contract/dynamic-contract-constructor.d.ts +3 -0
- package/lib/types/contract/dynamic-contract-constructor.js +1 -0
- package/lib/types/contract/dynamic-contract.d.ts +3 -0
- package/lib/types/contract/dynamic-contract.js +1 -0
- package/lib/types/contract/index.d.ts +6 -0
- package/lib/types/contract/index.js +6 -0
- package/lib/types/index.d.ts +6 -0
- package/lib/types/index.js +6 -0
- package/lib/types/multicall/index.d.ts +5 -0
- package/lib/types/multicall/index.js +5 -0
- package/lib/types/multicall/multicall-decodable-data.d.ts +5 -0
- package/lib/types/multicall/multicall-decodable-data.js +1 -0
- package/lib/types/multicall/multicall-options.d.ts +15 -0
- package/lib/types/multicall/multicall-options.js +1 -0
- package/lib/types/multicall/multicall-response.d.ts +5 -0
- package/lib/types/multicall/multicall-response.js +1 -0
- package/lib/types/multicall/multicall-tags.d.ts +4 -0
- package/lib/types/multicall/multicall-tags.js +1 -0
- package/lib/types/multicall/multicall-wait-options.d.ts +5 -0
- package/lib/types/multicall/multicall-wait-options.js +1 -0
- package/lib/types/priority-call-options.d.ts +8 -0
- package/lib/types/priority-call-options.js +1 -0
- package/lib/types/split-calls.d.ts +9 -0
- package/lib/types/split-calls.js +1 -0
- package/lib/types/state-mutabiity.d.ts +6 -0
- package/lib/types/state-mutabiity.js +7 -0
- package/lib/utils/check-signals.d.ts +1 -0
- package/lib/utils/check-signals.js +4 -0
- package/lib/utils/create-signals-promise.d.ts +1 -0
- package/lib/utils/create-signals-promise.js +8 -0
- package/lib/utils/create-timeout-signal.d.ts +1 -0
- package/lib/utils/create-timeout-signal.js +5 -0
- package/lib/utils/index.d.ts +6 -0
- package/lib/utils/index.js +6 -0
- package/lib/utils/race-with-signals.d.ts +1 -0
- package/lib/utils/race-with-signals.js +9 -0
- package/lib/utils/wait-with-signals.d.ts +1 -0
- package/lib/utils/wait-with-signals.js +18 -0
- package/package.json +44 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { Contract as EthersContract, Wallet, WebSocketProvider, } from "ethers";
|
|
2
|
+
import { config } from "../config";
|
|
3
|
+
import { CONTRACTS_ERRORS } from "../errors";
|
|
4
|
+
import { isSigner, isStaticMethod } from "../helpers";
|
|
5
|
+
import { CallMutability, } from "../types";
|
|
6
|
+
import { checkSignals, createTimeoutSignal, priorityCall, raceWithSignals, waitWithSignals, } from "../utils";
|
|
7
|
+
import { contractCreateCallName } from "./contract-create-call-name";
|
|
8
|
+
export class BaseContract {
|
|
9
|
+
static createAutoClass(abi, address, driver, options) {
|
|
10
|
+
return class extends this {
|
|
11
|
+
constructor(args) {
|
|
12
|
+
super(args?.abi || abi, args?.address || address, args?.driver || driver, args?.options || options);
|
|
13
|
+
for (const fragment of Object.values(this.interface.fragments)) {
|
|
14
|
+
if (fragment.type === "function") {
|
|
15
|
+
const funcFragment = fragment;
|
|
16
|
+
const name = funcFragment.name;
|
|
17
|
+
if (!(name in this)) {
|
|
18
|
+
Object.defineProperty(this, name, {
|
|
19
|
+
value: async (args = [], options) => this.call(name, args, options),
|
|
20
|
+
writable: true,
|
|
21
|
+
enumerable: true,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
const getCallName = contractCreateCallName(name);
|
|
25
|
+
if (!(getCallName in this)) {
|
|
26
|
+
Object.defineProperty(this, getCallName, {
|
|
27
|
+
value: (args = [], callData = {}) => this.getCall(name, args, callData),
|
|
28
|
+
writable: true,
|
|
29
|
+
enumerable: true,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
static createAutoInstance(abi, address, driver, options) {
|
|
38
|
+
const AutoClass = this.createAutoClass(abi, address, driver, options);
|
|
39
|
+
return new AutoClass({ abi, address, driver, options });
|
|
40
|
+
}
|
|
41
|
+
constructor(abi, address = "0x0000000000000000000000000000000000000000", driver, options = {}) {
|
|
42
|
+
this.contractOptions = {};
|
|
43
|
+
this.address = address;
|
|
44
|
+
this.driver = driver;
|
|
45
|
+
this.isCallable = !!address && !!driver;
|
|
46
|
+
this.isReadonly = !this.isCallable || !(driver instanceof Wallet);
|
|
47
|
+
this.contract = new EthersContract(address, abi, driver);
|
|
48
|
+
this.contractOptions = {
|
|
49
|
+
staticCallsTimeoutMs: config.contract.staticCalls.timeoutMs,
|
|
50
|
+
mutableCallsTimeoutMs: config.contract.mutableCalls.timeoutMs,
|
|
51
|
+
...options,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
get provider() {
|
|
55
|
+
if (!this.driver)
|
|
56
|
+
return null;
|
|
57
|
+
return this.driver.provider;
|
|
58
|
+
}
|
|
59
|
+
get signer() {
|
|
60
|
+
if (isSigner(this.driver))
|
|
61
|
+
return this.driver;
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
get interface() {
|
|
65
|
+
return this.contract.interface;
|
|
66
|
+
}
|
|
67
|
+
async call(method, args = [], options = {}) {
|
|
68
|
+
if (!this.isCallable)
|
|
69
|
+
throw CONTRACTS_ERRORS.NON_CALLABLE_CONTRACT_INVOCATION;
|
|
70
|
+
const methodFn = this.contract[method];
|
|
71
|
+
if (!methodFn)
|
|
72
|
+
throw CONTRACTS_ERRORS.METHOD_NOT_DEFINED(method);
|
|
73
|
+
const functionFragment = this.contract.interface.getFunction(method);
|
|
74
|
+
if (!functionFragment)
|
|
75
|
+
throw CONTRACTS_ERRORS.FRAGMENT_NOT_DEFINED(method);
|
|
76
|
+
const callOptions = {
|
|
77
|
+
forceMutability: this.contractOptions.forceMutability,
|
|
78
|
+
highPriorityTx: this.contractOptions.highPriorityTxs,
|
|
79
|
+
priorityOptions: this.contractOptions.priorityOptions,
|
|
80
|
+
...options,
|
|
81
|
+
};
|
|
82
|
+
const isStatic = callOptions.forceMutability
|
|
83
|
+
? callOptions.forceMutability === CallMutability.Static
|
|
84
|
+
: isStaticMethod(functionFragment.stateMutability);
|
|
85
|
+
const localSignals = [];
|
|
86
|
+
if (callOptions.signals)
|
|
87
|
+
localSignals.push(...callOptions.signals);
|
|
88
|
+
if (callOptions.timeoutMs)
|
|
89
|
+
localSignals.push(this.getTimeoutSignal(isStatic, callOptions.timeoutMs));
|
|
90
|
+
if (isStatic) {
|
|
91
|
+
return raceWithSignals(() => methodFn.staticCall(...args), localSignals);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
if (this.isReadonly)
|
|
95
|
+
throw CONTRACTS_ERRORS.READ_ONLY_CONTRACT_MUTATION;
|
|
96
|
+
let tx;
|
|
97
|
+
if (callOptions.highPriorityTx) {
|
|
98
|
+
const provider = this.driver?.provider;
|
|
99
|
+
tx = await raceWithSignals(() => priorityCall(provider, this.driver, this.contract, method, args, {
|
|
100
|
+
signals: localSignals,
|
|
101
|
+
...options.priorityOptions,
|
|
102
|
+
}), localSignals);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
tx = await raceWithSignals(() => methodFn(...args), localSignals);
|
|
106
|
+
}
|
|
107
|
+
return tx;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
getCall(methodName, args = [], callData = {}) {
|
|
111
|
+
if (!this.address)
|
|
112
|
+
throw CONTRACTS_ERRORS.NON_CALLABLE_CONTRACT_INVOCATION;
|
|
113
|
+
const functionFragment = this.interface.getFunction(methodName);
|
|
114
|
+
if (!functionFragment)
|
|
115
|
+
throw CONTRACTS_ERRORS.FRAGMENT_NOT_DEFINED(methodName);
|
|
116
|
+
return {
|
|
117
|
+
method: methodName,
|
|
118
|
+
target: this.address,
|
|
119
|
+
allowFailure: config.multicallUnit.allowFailure,
|
|
120
|
+
callData: this.interface.encodeFunctionData(methodName, args),
|
|
121
|
+
stateMutability: functionFragment.stateMutability,
|
|
122
|
+
contractInterface: this.interface,
|
|
123
|
+
...callData,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
async listenEvent(eventName, listener) {
|
|
127
|
+
if (!this.isCallable)
|
|
128
|
+
throw CONTRACTS_ERRORS.NON_CALLABLE_CONTRACT_INVOCATION;
|
|
129
|
+
if (!(this.provider instanceof WebSocketProvider))
|
|
130
|
+
throw CONTRACTS_ERRORS.MISSING_WEBSOCKET_PROVIDER;
|
|
131
|
+
return this.contract.on(eventName, listener);
|
|
132
|
+
}
|
|
133
|
+
async getLogs(fromBlock, eventsNames = [], toBlock = 0, options = {}) {
|
|
134
|
+
const descriptions = [];
|
|
135
|
+
for await (const description of this.getLogsStream(fromBlock, eventsNames, toBlock, options)) {
|
|
136
|
+
descriptions.push(description);
|
|
137
|
+
}
|
|
138
|
+
return descriptions;
|
|
139
|
+
}
|
|
140
|
+
async *getLogsStream(fromBlock, eventsNames = [], toBlock = 0, // Latest by default
|
|
141
|
+
options = {}) {
|
|
142
|
+
if (!this.isCallable)
|
|
143
|
+
throw CONTRACTS_ERRORS.NON_CALLABLE_CONTRACT_INVOCATION;
|
|
144
|
+
const streamOptions = {
|
|
145
|
+
blocksStep: this.contractOptions.logsBlocksStep ||
|
|
146
|
+
config.contract.logsGathering.blocksStep,
|
|
147
|
+
delayMs: this.contractOptions.logsDelayMs ||
|
|
148
|
+
config.contract.logsGathering.delayMs,
|
|
149
|
+
...options,
|
|
150
|
+
};
|
|
151
|
+
const topics = eventsNames.map((event) => this.contract.getEvent(event).fragment.topicHash);
|
|
152
|
+
checkSignals(options.signals);
|
|
153
|
+
const finToBlock = toBlock
|
|
154
|
+
? toBlock
|
|
155
|
+
: await this.provider.getBlockNumber();
|
|
156
|
+
const finFromBlock = fromBlock < 0 ? finToBlock + fromBlock : fromBlock;
|
|
157
|
+
for (let from = finFromBlock; from < finToBlock; from += streamOptions.blocksStep) {
|
|
158
|
+
checkSignals(options.signals);
|
|
159
|
+
const to = Math.min(from + streamOptions.blocksStep, finToBlock);
|
|
160
|
+
const localLogs = await this.provider.getLogs({
|
|
161
|
+
fromBlock: from,
|
|
162
|
+
toBlock: to,
|
|
163
|
+
address: this.address,
|
|
164
|
+
topics: topics.length ? [topics] : undefined,
|
|
165
|
+
});
|
|
166
|
+
for (const log of localLogs) {
|
|
167
|
+
checkSignals(options.signals);
|
|
168
|
+
const description = this.interface.parseLog(log);
|
|
169
|
+
if (!description)
|
|
170
|
+
continue;
|
|
171
|
+
yield description;
|
|
172
|
+
}
|
|
173
|
+
await waitWithSignals(streamOptions.delayMs, options.signals);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
getTimeoutSignal(isStatic, timeoutMs) {
|
|
177
|
+
let timeout;
|
|
178
|
+
if (timeoutMs) {
|
|
179
|
+
timeout = timeoutMs;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
if (isStatic) {
|
|
183
|
+
timeout = this.contractOptions.staticCallsTimeoutMs;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
timeout = this.contractOptions.mutableCallsTimeoutMs;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return createTimeoutSignal(timeout);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const contractCreateCallName: (name: string) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const contractCreateCallName = (name) => `${name.startsWith("get") ? name : `get${name[0].toUpperCase()}${name.slice(1)}`}Call`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./base-contract";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./base-contract";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const CONTRACTS_ERRORS: {
|
|
2
|
+
NON_CALLABLE_CONTRACT_INVOCATION: Error;
|
|
3
|
+
READ_ONLY_CONTRACT_MUTATION: Error;
|
|
4
|
+
MISSING_CONTRACT_ADDRESS: Error;
|
|
5
|
+
METHOD_NOT_DEFINED: (methodName: any) => Error;
|
|
6
|
+
FRAGMENT_NOT_DEFINED: (methodName: any) => Error;
|
|
7
|
+
MISSING_WEBSOCKET_PROVIDER: Error;
|
|
8
|
+
MISSING_PROVIDER: Error;
|
|
9
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const CONTRACTS_ERRORS = {
|
|
2
|
+
NON_CALLABLE_CONTRACT_INVOCATION: new Error("The contract was created as non-callable, but an attempt was made to call it!"),
|
|
3
|
+
READ_ONLY_CONTRACT_MUTATION: new Error("The contract was created as read-only, but an attempt was made to call mutable method!"),
|
|
4
|
+
MISSING_CONTRACT_ADDRESS: new Error("A contract address was not provided!"),
|
|
5
|
+
METHOD_NOT_DEFINED: (methodName) => new Error(`Method "${methodName}" was not found on the contract!`),
|
|
6
|
+
FRAGMENT_NOT_DEFINED: (methodName) => new Error(`Fragment for method "${methodName}" was not found on the contract!`),
|
|
7
|
+
MISSING_WEBSOCKET_PROVIDER: new Error("Attempted to listen for contract events, but no WebSocketProvider was provided!"),
|
|
8
|
+
MISSING_PROVIDER: new Error("A provider is required, but none was provided!"),
|
|
9
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const MULTICALL_ERRORS = {
|
|
2
|
+
SIMULTANEOUS_INVOCATIONS: new Error("Multicall -> Another execution was triggered during processing."),
|
|
3
|
+
RESULT_NOT_FOUND: new Error("Multicall result not found."),
|
|
4
|
+
RESPONSE_NOT_FOUND: new Error("Multicall response not found."),
|
|
5
|
+
RECEIPT_NOT_FOUND: new Error("Multicall receipt not received."),
|
|
6
|
+
MISSING_PROVIDER_INTERFACE: new Error("MulticallProvider -> Missing contractInterface in customData."),
|
|
7
|
+
MISSING_PROVIDER_CALL_DATA: new Error('MulticallProvider -> Missing "to" or "data".'),
|
|
8
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const isParsable = (call) => call.method !== undefined && call.contractInterface !== undefined;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Contract, Provider, TransactionRequest } from "ethers";
|
|
2
|
+
import type { PriorityCallOptions } from "../types";
|
|
3
|
+
export declare function priorityCall(provider: Provider, signer: {
|
|
4
|
+
sendTransaction: (txn: TransactionRequest) => Promise<any>;
|
|
5
|
+
}, contract: Contract, method: string, args?: any[], options?: PriorityCallOptions): Promise<any>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { DEFAULT_PRIORITY_CALL_MULTIPLIER } from "../constant";
|
|
2
|
+
import { checkSignals, createTimeoutSignal } from "../utils";
|
|
3
|
+
export async function priorityCall(provider, signer, contract, method, args = [], options = {}) {
|
|
4
|
+
const localOptions = {
|
|
5
|
+
multiplier: DEFAULT_PRIORITY_CALL_MULTIPLIER,
|
|
6
|
+
...options,
|
|
7
|
+
};
|
|
8
|
+
const localSignals = [];
|
|
9
|
+
if (localOptions.signals)
|
|
10
|
+
localSignals.push(...localOptions.signals);
|
|
11
|
+
if (localOptions.timeoutMs)
|
|
12
|
+
localSignals.push(createTimeoutSignal(localOptions.timeoutMs));
|
|
13
|
+
checkSignals(localSignals);
|
|
14
|
+
const [originalFeeData, originalGasLimit] = await gatherOriginalData(provider, contract, method, args, localOptions.asynchronous ?? false, localSignals);
|
|
15
|
+
const maxFeePerGas = Math.ceil(localOptions.multiplier * Number(originalFeeData.maxFeePerGas));
|
|
16
|
+
const maxPriorityFeePerGas = Math.ceil(localOptions.multiplier * Number(originalFeeData.maxPriorityFeePerGas));
|
|
17
|
+
const gasLimit = Math.ceil(localOptions.multiplier * Number(originalGasLimit));
|
|
18
|
+
checkSignals(localSignals);
|
|
19
|
+
const txn = await contract
|
|
20
|
+
.getFunction(method)
|
|
21
|
+
.populateTransaction(...args, {
|
|
22
|
+
gasLimit,
|
|
23
|
+
maxFeePerGas,
|
|
24
|
+
maxPriorityFeePerGas,
|
|
25
|
+
});
|
|
26
|
+
// Prevents conflicts when using signer.sendTransaction(txn), as the signer should determine the from address.
|
|
27
|
+
// Avoids potential issues if from is incorrectly set or differs from the signer's address.
|
|
28
|
+
delete txn.from;
|
|
29
|
+
if (localOptions.provideChainId) {
|
|
30
|
+
checkSignals(localSignals);
|
|
31
|
+
const network = await provider.getNetwork();
|
|
32
|
+
txn.chainId = network.chainId;
|
|
33
|
+
}
|
|
34
|
+
else if (localOptions.chainId) {
|
|
35
|
+
txn.chainId = localOptions.chainId;
|
|
36
|
+
}
|
|
37
|
+
checkSignals(localSignals);
|
|
38
|
+
return signer.sendTransaction(txn);
|
|
39
|
+
}
|
|
40
|
+
async function gatherOriginalData(provider, contract, method, args = [], asynchronous, signals) {
|
|
41
|
+
let originalFeeData;
|
|
42
|
+
let originalGasLimit;
|
|
43
|
+
checkSignals(signals);
|
|
44
|
+
if (asynchronous) {
|
|
45
|
+
[originalFeeData, originalGasLimit] = await Promise.all([
|
|
46
|
+
provider.getFeeData(),
|
|
47
|
+
contract.getFunction(method).estimateGas(...args),
|
|
48
|
+
]);
|
|
49
|
+
return [originalFeeData, originalGasLimit];
|
|
50
|
+
}
|
|
51
|
+
originalFeeData = await provider.getFeeData();
|
|
52
|
+
checkSignals(signals);
|
|
53
|
+
originalGasLimit = await contract.getFunction(method).estimateGas(...args);
|
|
54
|
+
return [originalFeeData, originalGasLimit];
|
|
55
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const waitForAddressTxs = async (address, provider, delayMs = 1000) => {
|
|
2
|
+
let flag = true;
|
|
3
|
+
while (flag) {
|
|
4
|
+
const pendingNonce = await provider.getTransactionCount(address, "pending");
|
|
5
|
+
const latestNonce = await provider.getTransactionCount(address, "latest");
|
|
6
|
+
flag = pendingNonce > latestNonce;
|
|
7
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
8
|
+
}
|
|
9
|
+
};
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const multicallErrorEventName = (normalizedTags) => `error:${String(normalizedTags)}`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const multicallGenerateTag: () => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const multicallGenerateTag = () => `tag:${Date.now()}:${crypto.randomUUID()}`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const multicallResultEventName = (normalizedTags) => `result:${String(normalizedTags)}`;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isStaticMethod } from "../helpers";
|
|
2
|
+
export const multicallSplitCalls = (calls, tags) => calls.reduce((acc, call, index) => {
|
|
3
|
+
if (isStaticMethod(call.stateMutability)) {
|
|
4
|
+
acc.staticCalls.push(call);
|
|
5
|
+
acc.staticIndexes.push(index);
|
|
6
|
+
}
|
|
7
|
+
else {
|
|
8
|
+
acc.mutableCalls.push(call);
|
|
9
|
+
acc.mutableTags.push(tags[index]);
|
|
10
|
+
acc.mutableIndexes.push(index);
|
|
11
|
+
}
|
|
12
|
+
return acc;
|
|
13
|
+
}, {
|
|
14
|
+
staticCalls: [],
|
|
15
|
+
staticIndexes: [],
|
|
16
|
+
mutableCalls: [],
|
|
17
|
+
mutableTags: [],
|
|
18
|
+
mutableIndexes: [],
|
|
19
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import type { Provider, Signer, TransactionReceipt, TransactionResponse } from "ethers";
|
|
3
|
+
import { BaseContract } from "../contract";
|
|
4
|
+
import { type ContractCall, type MulticallOptions, type MulticallTags, type MulticallWaitOptions, type Tagable } from "../types";
|
|
5
|
+
export type Response = [success: boolean, rawData: string];
|
|
6
|
+
export declare class MulticallUnit extends BaseContract {
|
|
7
|
+
protected _units: Map<Tagable, ContractCall>;
|
|
8
|
+
protected _response: Response[];
|
|
9
|
+
protected _rawData: Map<Tagable, string>;
|
|
10
|
+
protected _callsSuccess: Map<Tagable, boolean>;
|
|
11
|
+
protected _lastSuccess: boolean | undefined;
|
|
12
|
+
protected _isExecuting: boolean;
|
|
13
|
+
protected _emitter: EventEmitter<[never]>;
|
|
14
|
+
protected _multicallOptions: MulticallOptions;
|
|
15
|
+
protected _txResponses: Map<any, any>;
|
|
16
|
+
protected _txReceipts: Map<any, any>;
|
|
17
|
+
constructor(driver: Signer | Provider, options?: MulticallOptions, multicallAddress?: string);
|
|
18
|
+
clear(): void;
|
|
19
|
+
add(contractCall: ContractCall, tags: MulticallTags): MulticallTags;
|
|
20
|
+
get tags(): Tagable[];
|
|
21
|
+
get calls(): ContractCall[];
|
|
22
|
+
get response(): Response[];
|
|
23
|
+
get success(): boolean | undefined;
|
|
24
|
+
get static(): boolean;
|
|
25
|
+
get executing(): boolean;
|
|
26
|
+
isSuccess(tags: MulticallTags): boolean | undefined;
|
|
27
|
+
getRaw(tags: MulticallTags): string | null;
|
|
28
|
+
getSingle<T>(tags: MulticallTags): T | null;
|
|
29
|
+
getArray<T>(tags: MulticallTags, deep?: boolean): T | null;
|
|
30
|
+
run(options?: Partial<MulticallOptions>): Promise<boolean>;
|
|
31
|
+
private processStaticCalls;
|
|
32
|
+
private processMutableCalls;
|
|
33
|
+
private saveResponse;
|
|
34
|
+
getOrThrow<T>(tags: MulticallTags, deep?: boolean): T;
|
|
35
|
+
get<T>(tags: MulticallTags, deep?: boolean): T | null;
|
|
36
|
+
private getDecodableData;
|
|
37
|
+
waitRawOrThrow(tags: MulticallTags, options?: MulticallWaitOptions): Promise<string>;
|
|
38
|
+
waitRaw(tags: MulticallTags, options?: MulticallWaitOptions): Promise<string | null>;
|
|
39
|
+
wait(tags: MulticallTags, options?: MulticallWaitOptions): Promise<void>;
|
|
40
|
+
waitTxOrThrow(tags: MulticallTags, options?: MulticallWaitOptions): Promise<TransactionResponse>;
|
|
41
|
+
waitTx(tags: MulticallTags, options?: MulticallWaitOptions): Promise<TransactionResponse | null>;
|
|
42
|
+
getTxResponse(tags: MulticallTags): TransactionResponse | null;
|
|
43
|
+
getTxResponseOrThrow(tags: MulticallTags): TransactionResponse;
|
|
44
|
+
getTxReceipt(tags: MulticallTags): TransactionReceipt | null;
|
|
45
|
+
getObjectOrThrow<T>(tags: MulticallTags, deep?: boolean): T;
|
|
46
|
+
getObject<T>(tags: MulticallTags, deep?: boolean): T | null;
|
|
47
|
+
waitFor<T>(tags: MulticallTags, options?: MulticallWaitOptions): Promise<T>;
|
|
48
|
+
}
|