@w3lib/evm-batch-call 0.4.2 → 0.6.0
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/CHANGELOG.md +29 -0
- package/README.md +242 -2
- package/dist/fallback.d.ts +5 -0
- package/dist/fallback.d.ts.map +1 -1
- package/dist/fallback.js +7 -0
- package/dist/fallback.js.map +1 -1
- package/dist/liquidity/common.d.ts +72 -0
- package/dist/liquidity/common.d.ts.map +1 -0
- package/dist/liquidity/common.js +271 -0
- package/dist/liquidity/common.js.map +1 -0
- package/dist/liquidity/concentrated.d.ts +19 -0
- package/dist/liquidity/concentrated.d.ts.map +1 -0
- package/dist/liquidity/concentrated.js +106 -0
- package/dist/liquidity/concentrated.js.map +1 -0
- package/dist/liquidity/index.d.ts +42 -0
- package/dist/liquidity/index.d.ts.map +1 -0
- package/dist/liquidity/index.js +143 -0
- package/dist/liquidity/index.js.map +1 -0
- package/dist/liquidity/types.d.ts +182 -0
- package/dist/liquidity/types.d.ts.map +1 -0
- package/dist/liquidity/types.js +2 -0
- package/dist/liquidity/types.js.map +1 -0
- package/dist/liquidity/v2.d.ts +5 -0
- package/dist/liquidity/v2.d.ts.map +1 -0
- package/dist/liquidity/v2.js +342 -0
- package/dist/liquidity/v2.js.map +1 -0
- package/dist/liquidity/v3.d.ts +6 -0
- package/dist/liquidity/v3.d.ts.map +1 -0
- package/dist/liquidity/v3.js +310 -0
- package/dist/liquidity/v3.js.map +1 -0
- package/dist/liquidity/v4.d.ts +5 -0
- package/dist/liquidity/v4.d.ts.map +1 -0
- package/dist/liquidity/v4.js +279 -0
- package/dist/liquidity/v4.js.map +1 -0
- package/dist/lp.d.ts +156 -0
- package/dist/lp.d.ts.map +1 -0
- package/dist/lp.js +510 -0
- package/dist/lp.js.map +1 -0
- package/dist/lpMath.d.ts +80 -0
- package/dist/lpMath.d.ts.map +1 -0
- package/dist/lpMath.js +312 -0
- package/dist/lpMath.js.map +1 -0
- package/dist/lpV4.d.ts +108 -0
- package/dist/lpV4.d.ts.map +1 -0
- package/dist/lpV4.js +283 -0
- package/dist/lpV4.js.map +1 -0
- package/dist/owner.d.ts +1 -1
- package/dist/owner.d.ts.map +1 -1
- package/dist/owner.js +18 -5
- package/dist/owner.js.map +1 -1
- package/dist/scan.d.ts +54 -0
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +124 -92
- package/dist/scan.js.map +1 -1
- package/dist/source.d.ts +2 -0
- package/dist/source.d.ts.map +1 -1
- package/dist/source.js +4 -0
- package/dist/source.js.map +1 -1
- package/dist/subpaths/liquidity.d.ts +24 -0
- package/dist/subpaths/liquidity.d.ts.map +1 -0
- package/dist/subpaths/liquidity.js +21 -0
- package/dist/subpaths/liquidity.js.map +1 -0
- package/dist/subpaths/lp.d.ts +33 -0
- package/dist/subpaths/lp.d.ts.map +1 -0
- package/dist/subpaths/lp.js +47 -0
- package/dist/subpaths/lp.js.map +1 -0
- package/dist/subpaths/write.d.ts +20 -0
- package/dist/subpaths/write.d.ts.map +1 -0
- package/dist/subpaths/write.js +18 -0
- package/dist/subpaths/write.js.map +1 -0
- package/dist/tron.d.ts +2 -0
- package/dist/tron.d.ts.map +1 -1
- package/dist/tron.js +4 -0
- package/dist/tron.js.map +1 -1
- package/dist/write/batch.d.ts +88 -0
- package/dist/write/batch.d.ts.map +1 -0
- package/dist/write/batch.js +231 -0
- package/dist/write/batch.js.map +1 -0
- package/dist/write/collect.d.ts +53 -0
- package/dist/write/collect.d.ts.map +1 -0
- package/dist/write/collect.js +255 -0
- package/dist/write/collect.js.map +1 -0
- package/dist/write/rpc.d.ts +68 -0
- package/dist/write/rpc.d.ts.map +1 -0
- package/dist/write/rpc.js +236 -0
- package/dist/write/rpc.js.map +1 -0
- package/dist/write/send.d.ts +124 -0
- package/dist/write/send.d.ts.map +1 -0
- package/dist/write/send.js +373 -0
- package/dist/write/send.js.map +1 -0
- package/dist/write/signer.d.ts +58 -0
- package/dist/write/signer.d.ts.map +1 -0
- package/dist/write/signer.js +41 -0
- package/dist/write/signer.js.map +1 -0
- package/dist/write/transfer.d.ts +83 -0
- package/dist/write/transfer.d.ts.map +1 -0
- package/dist/write/transfer.js +259 -0
- package/dist/write/transfer.js.map +1 -0
- package/dist/write/tron.d.ts +60 -0
- package/dist/write/tron.d.ts.map +1 -0
- package/dist/write/tron.js +960 -0
- package/dist/write/tron.js.map +1 -0
- package/package.json +26 -5
- package/src/fallback.ts +8 -0
- package/src/liquidity/common.ts +314 -0
- package/src/liquidity/concentrated.ts +121 -0
- package/src/liquidity/index.ts +171 -0
- package/src/liquidity/types.ts +194 -0
- package/src/liquidity/v2.ts +371 -0
- package/src/liquidity/v3.ts +382 -0
- package/src/liquidity/v4.ts +348 -0
- package/src/lp.ts +739 -0
- package/src/lpMath.ts +336 -0
- package/src/lpV4.ts +406 -0
- package/src/owner.ts +19 -6
- package/src/scan.ts +155 -86
- package/src/source.ts +5 -0
- package/src/subpaths/liquidity.ts +52 -0
- package/src/subpaths/lp.ts +90 -0
- package/src/subpaths/write.ts +26 -0
- package/src/tron.ts +5 -0
- package/src/write/batch.ts +302 -0
- package/src/write/collect.ts +312 -0
- package/src/write/rpc.ts +277 -0
- package/src/write/send.ts +490 -0
- package/src/write/signer.ts +90 -0
- package/src/write/transfer.ts +344 -0
- package/src/write/tron.ts +1105 -0
package/src/write/rpc.ts
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { Interface, Transaction, isError, type Provider as EthersProvider, type TransactionReceipt, type TransactionRequest } from 'ethers'
|
|
2
|
+
|
|
3
|
+
import type { EthersLikeProvider } from '../aggregate.js'
|
|
4
|
+
import { decodeRevertReason, isExecutionError } from '../errors.js'
|
|
5
|
+
import { FallbackRpc, errorText } from '../fallback.js'
|
|
6
|
+
import type { Provider } from '../provider.js'
|
|
7
|
+
import { ChainCheckedProvider } from '../source.js'
|
|
8
|
+
import { TronProvider, isTronChain } from '../tron.js'
|
|
9
|
+
|
|
10
|
+
/** 写操作要用到的节点方法(ethers 的 JsonRpcProvider / BrowserProvider 都有) */
|
|
11
|
+
type WriteNode = Pick<EthersProvider, 'getTransactionCount' | 'estimateGas' | 'getFeeData' | 'broadcastTransaction' | 'getTransactionReceipt' | 'getCode' | 'getBalance' | 'call'>
|
|
12
|
+
|
|
13
|
+
export interface FeeData {
|
|
14
|
+
gasPrice: bigint | null
|
|
15
|
+
maxFeePerGas: bigint | null
|
|
16
|
+
maxPriorityFeePerGas: bigint | null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 广播结果:已进交易池(含节点说已经有这笔);nonce 已被用掉(可能就是这笔已上链,也可能被别的交易占用);
|
|
21
|
+
* 或不确定(超时、连接失败,或前一个节点超时后另一个节点拒绝:前一个节点也许已经收下了),交易可能已经发出
|
|
22
|
+
*/
|
|
23
|
+
export type BroadcastOutcome = 'accepted' | 'nonce-used' | { uncertain: string }
|
|
24
|
+
|
|
25
|
+
/** 换节点也不会变的失败(余额不足、revert、gas 参数不合法等),不再请求其他节点 */
|
|
26
|
+
class Final {
|
|
27
|
+
constructor(readonly error: unknown) {}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 节点对“交易池里已经有这笔交易”的各种说法:同一笔签名交易发到多个节点 / 重发时会遇到,视为成功
|
|
31
|
+
const ALREADY_KNOWN_RE = /already known|known transaction|already imported|already exists|alreadyknown|already in (the )?(tx|transaction)?\s*pool/i
|
|
32
|
+
const NONCE_USED_RE = /nonce too low|nonce has already been used|nonce is too low|invalid nonce|old nonce/i
|
|
33
|
+
// 交易本身的问题:换节点结果一样
|
|
34
|
+
const TX_INVALID_RE =
|
|
35
|
+
/insufficient funds|intrinsic gas too low|exceeds block gas limit|gas limit reached|max fee per gas less than block base fee|fee cap less than block base fee|underpriced|tip higher than|max priority fee per gas higher than|invalid sender|invalid chain id|only replay-protected|transaction type not supported|tx type not supported|oversized data/i
|
|
36
|
+
|
|
37
|
+
/** 广播被节点明确拒绝、换节点也一样(交易没进交易池) */
|
|
38
|
+
export function isFinalBroadcastError(err: unknown): boolean {
|
|
39
|
+
return isError(err, 'INSUFFICIENT_FUNDS') || isError(err, 'REPLACEMENT_UNDERPRICED') || isError(err, 'INVALID_ARGUMENT') || TX_INVALID_RE.test(errorText(err))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** 节点明确拒绝了这笔交易(给出了 JSON-RPC 错误,或限频):交易肯定没进这个节点的交易池 */
|
|
43
|
+
function isRejection(err: unknown): boolean {
|
|
44
|
+
const e = err as { error?: { message?: unknown }; info?: { error?: { message?: unknown } } } | null
|
|
45
|
+
const message = e?.error?.message ?? e?.info?.error?.message
|
|
46
|
+
if (isFinalBroadcastError(err) || /too many requests|rate.?limit|\b429\b/i.test(errorText(err))) return true
|
|
47
|
+
return typeof message === 'string' && !/timeout|timed out|busy|unavailable|overload|try again/i.test(message)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function isFinalEstimateError(err: unknown): boolean {
|
|
51
|
+
return isExecutionError(err) || isError(err, 'INSUFFICIENT_FUNDS') || isError(err, 'INVALID_ARGUMENT') || /insufficient funds|gas required exceeds allowance|transaction type not supported/i.test(errorText(err))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** 预估 / 执行失败的可读原因:优先解析 revert 数据(Error(string) / Panic),否则取节点的原始信息 */
|
|
55
|
+
export function failureText(err: unknown): string {
|
|
56
|
+
const data = (err as { data?: unknown } | null)?.data
|
|
57
|
+
const reason = typeof data === 'string' ? decodeRevertReason(data) : null
|
|
58
|
+
if (reason) {
|
|
59
|
+
return `execution reverted: ${reason}`
|
|
60
|
+
}
|
|
61
|
+
return errorText(err)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** 预估 gas 时 revert 带回的数据(解析 7702 批量执行里是第几个调用失败用) */
|
|
65
|
+
export function revertData(err: unknown): string | null {
|
|
66
|
+
const data = (err as { data?: unknown } | null)?.data
|
|
67
|
+
return typeof data === 'string' && data !== '0x' ? data : null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function asWriteNode(node: EthersLikeProvider, method: keyof WriteNode): WriteNode {
|
|
71
|
+
if (typeof (node as Partial<WriteNode>)[method] !== 'function') {
|
|
72
|
+
throw new Error(`${method} is not supported by this node; pass an RPC URL or an ethers Provider`)
|
|
73
|
+
}
|
|
74
|
+
return node as unknown as WriteNode
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 在 Provider 的节点上执行请求:多节点时与 call / getBalance 相同的故障切换(ChainCheckedProvider 先校验链);
|
|
79
|
+
* isFinal 判定为确定性的错误(revert、余额不足等)直接抛出,不拿去别的节点重试
|
|
80
|
+
*/
|
|
81
|
+
export async function runOnNodes<T>(rpc: EthersLikeProvider, method: string, fn: (node: EthersLikeProvider) => Promise<T>, isFinal: (err: unknown) => boolean = () => false): Promise<T> {
|
|
82
|
+
const guarded = (node: EthersLikeProvider): Promise<T | Final> => {
|
|
83
|
+
if (node instanceof ChainCheckedProvider) {
|
|
84
|
+
return node.request((inner) => guarded(inner))
|
|
85
|
+
}
|
|
86
|
+
return fn(node).catch((err: unknown) => {
|
|
87
|
+
if (isFinal(err)) {
|
|
88
|
+
return new Final(err)
|
|
89
|
+
}
|
|
90
|
+
throw err
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
const result = rpc instanceof FallbackRpc ? await rpc.request(method, guarded) : await guarded(rpc)
|
|
94
|
+
if (result instanceof Final) {
|
|
95
|
+
throw result.error
|
|
96
|
+
}
|
|
97
|
+
return result
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 写操作的节点访问:nonce、fee、预估 gas、广播、查回执,都经过 Provider 的多节点故障切换。
|
|
102
|
+
* 确定性错误(revert、余额不足等)直接抛出,不拿去别的节点重试
|
|
103
|
+
*/
|
|
104
|
+
export class WriteRpc {
|
|
105
|
+
constructor(
|
|
106
|
+
readonly rpc: EthersLikeProvider,
|
|
107
|
+
readonly chainId: number,
|
|
108
|
+
) {}
|
|
109
|
+
|
|
110
|
+
static async from(provider: Provider): Promise<WriteRpc> {
|
|
111
|
+
const chainId = await provider.getChainId()
|
|
112
|
+
if (isTronChain(chainId)) {
|
|
113
|
+
throw new Error('This operation is not supported on Tron')
|
|
114
|
+
}
|
|
115
|
+
return new WriteRpc(provider.rpc, chainId)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
#run<T>(method: keyof WriteNode, fn: (node: WriteNode) => Promise<T>, isFinal?: (err: unknown) => boolean): Promise<T> {
|
|
119
|
+
return runOnNodes(
|
|
120
|
+
this.rpc,
|
|
121
|
+
method,
|
|
122
|
+
(node) => {
|
|
123
|
+
if (node instanceof TronProvider) {
|
|
124
|
+
return Promise.reject(new Error('This operation is not supported on Tron'))
|
|
125
|
+
}
|
|
126
|
+
return fn(asWriteNode(node, method))
|
|
127
|
+
},
|
|
128
|
+
isFinal,
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** 本次批量操作里各钱包已用到的 nonce + 1(同一个 WriteRpc 分几轮发送时接上) */
|
|
133
|
+
readonly #nextNonce = new Map<string, number>()
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* 下一个可用的 nonce:节点的 pending 计数(含交易池里待确认的交易)与本次已用过的取大者。
|
|
137
|
+
* 多节点时先返回的节点可能还没看到刚发出的交易,只信节点会拿到已用过的 nonce
|
|
138
|
+
*/
|
|
139
|
+
async nonce(address: string): Promise<number> {
|
|
140
|
+
const pending = await this.#run('getTransactionCount', (node) => node.getTransactionCount(address, 'pending'))
|
|
141
|
+
return Math.max(pending, this.#nextNonce.get(address.toLowerCase()) ?? 0)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** 已上链的交易数(latest nonce) */
|
|
145
|
+
latestNonce(address: string): Promise<number> {
|
|
146
|
+
return this.#run('getTransactionCount', (node) => node.getTransactionCount(address, 'latest'))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** 记录 nonce 已被占用(交易已广播,或节点说已被用掉) */
|
|
150
|
+
useNonce(address: string, nonce: number): void {
|
|
151
|
+
const key = address.toLowerCase()
|
|
152
|
+
this.#nextNonce.set(key, Math.max(this.#nextNonce.get(key) ?? 0, nonce + 1))
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
code(address: string): Promise<string> {
|
|
156
|
+
return this.#run('getCode', (node) => node.getCode(address))
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async feeData(): Promise<FeeData> {
|
|
160
|
+
const fee = await this.#run('getFeeData', (node) => node.getFeeData())
|
|
161
|
+
return { gasPrice: fee.gasPrice, maxFeePerGas: fee.maxFeePerGas, maxPriorityFeePerGas: fee.maxPriorityFeePerGas }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** 预估 gas;revert / 余额不足等直接抛出(error.data 是 revert 数据) */
|
|
165
|
+
estimateGas(tx: TransactionRequest): Promise<bigint> {
|
|
166
|
+
return this.#run('estimateGas', (node) => node.estimateGas(tx), isFinalEstimateError)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** eth_call;revert 直接抛出 */
|
|
170
|
+
call(tx: TransactionRequest): Promise<string> {
|
|
171
|
+
return this.#run('call', (node) => node.call(tx), isExecutionError)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 广播已签名的交易。同一笔签名交易重复广播是安全的:节点说已经有了视为成功;
|
|
176
|
+
* nonce 已被用掉时返回 'nonce-used'(调用方查回执确认是不是这笔已上链)。其他交易本身的问题直接抛出
|
|
177
|
+
*/
|
|
178
|
+
async broadcast(signed: string): Promise<BroadcastOutcome> {
|
|
179
|
+
// 记录各节点的结果:只有所有尝试都是“明确拒绝”、并且没有还在进行中的尝试时,才能确定交易没发出去
|
|
180
|
+
let attempts = 0
|
|
181
|
+
let rejections = 0
|
|
182
|
+
let pending = 0
|
|
183
|
+
try {
|
|
184
|
+
return await this.#run(
|
|
185
|
+
'broadcastTransaction',
|
|
186
|
+
async (node) => {
|
|
187
|
+
attempts++
|
|
188
|
+
pending++
|
|
189
|
+
try {
|
|
190
|
+
await node.broadcastTransaction(signed)
|
|
191
|
+
return 'accepted' as const
|
|
192
|
+
} catch (err) {
|
|
193
|
+
const text = errorText(err)
|
|
194
|
+
if (ALREADY_KNOWN_RE.test(text)) {
|
|
195
|
+
return 'accepted' as const
|
|
196
|
+
}
|
|
197
|
+
if (isError(err, 'NONCE_EXPIRED') || NONCE_USED_RE.test(text)) {
|
|
198
|
+
return 'nonce-used' as const
|
|
199
|
+
}
|
|
200
|
+
if (isRejection(err)) rejections++
|
|
201
|
+
throw err
|
|
202
|
+
} finally {
|
|
203
|
+
pending--
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
// 明确拒绝、而且之前没有不确定的尝试:不再问别的节点
|
|
207
|
+
(err) => isFinalBroadcastError(err) && rejections === attempts && pending === 0,
|
|
208
|
+
)
|
|
209
|
+
} catch (err) {
|
|
210
|
+
if (attempts === 0 || rejections === attempts) {
|
|
211
|
+
throw err
|
|
212
|
+
}
|
|
213
|
+
return { uncertain: `broadcast not acknowledged: ${failureText(err)}` }
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
receipt(hash: string): Promise<TransactionReceipt | null> {
|
|
218
|
+
return this.#run('getTransactionReceipt', (node) => node.getTransactionReceipt(hash))
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** 已签名交易的哈希 */
|
|
223
|
+
export function signedHash(signed: string): string {
|
|
224
|
+
return Transaction.from(signed).hash as string
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// OP Stack(GasPriceOracle)与 Scroll(L1GasPriceOracle)的 L1 数据费:不包含在 gasLimit × gasPrice 里,单独从余额里扣。
|
|
228
|
+
// 扫空主币余额时要预留,否则交易因余额不足失败
|
|
229
|
+
const L1_ORACLES = ['0x420000000000000000000000000000000000000F', '0x5300000000000000000000000000000000000002'] as const
|
|
230
|
+
const l1OracleInterface = new Interface(['function getL1Fee(bytes data) view returns (uint256)'])
|
|
231
|
+
/** chainId → 这条链的 L1 费用预言机地址(null 表示不是这类链) */
|
|
232
|
+
const l1OracleByChain = new Map<number, string | null>()
|
|
233
|
+
|
|
234
|
+
/** 测试用 */
|
|
235
|
+
export function resetL1OracleCache(): void {
|
|
236
|
+
l1OracleByChain.clear()
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async function l1Oracle(rpc: WriteRpc): Promise<string | null> {
|
|
240
|
+
const cached = l1OracleByChain.get(rpc.chainId)
|
|
241
|
+
if (cached !== undefined) {
|
|
242
|
+
return cached
|
|
243
|
+
}
|
|
244
|
+
let found: string | null = null
|
|
245
|
+
for (const address of L1_ORACLES) {
|
|
246
|
+
try {
|
|
247
|
+
const code = await rpc.code(address)
|
|
248
|
+
if (code && code !== '0x') {
|
|
249
|
+
found = address
|
|
250
|
+
break
|
|
251
|
+
}
|
|
252
|
+
} catch {
|
|
253
|
+
return null // 节点出错:这次按没有处理,下次再查
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
l1OracleByChain.set(rpc.chainId, found)
|
|
257
|
+
return found
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* 交易的 L1 数据费(OP Stack / Scroll),其他链为 0。结果加 25% 余量(L1 gas 价格在交易上链前可能上涨)。
|
|
262
|
+
* 查询失败时返回 0(不阻塞发送,只影响扫空主币时的预留)
|
|
263
|
+
*/
|
|
264
|
+
export async function l1Fee(rpc: WriteRpc, tx: TransactionRequest): Promise<bigint> {
|
|
265
|
+
const oracle = await l1Oracle(rpc)
|
|
266
|
+
if (!oracle) {
|
|
267
|
+
return 0n
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
const unsigned = Transaction.from({ ...tx, from: undefined, chainId: rpc.chainId } as Parameters<typeof Transaction.from>[0]).unsignedSerialized
|
|
271
|
+
const data = await rpc.call({ to: oracle, data: l1OracleInterface.encodeFunctionData('getL1Fee', [unsigned]) })
|
|
272
|
+
const [fee] = l1OracleInterface.decodeFunctionResult('getL1Fee', data)
|
|
273
|
+
return ((fee as bigint) * 125n) / 100n
|
|
274
|
+
} catch {
|
|
275
|
+
return 0n
|
|
276
|
+
}
|
|
277
|
+
}
|