hermes-swap 0.6.3 → 0.6.5
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/dist/cjs/aggregator.cjs +143 -45
- package/dist/cjs/aggregator.d.ts +7 -1
- package/dist/cjs/types.d.ts +1 -0
- package/dist/esm/aggregator.d.ts +7 -1
- package/dist/esm/aggregator.mjs +457 -249
- package/dist/esm/types.d.ts +1 -0
- package/package.json +1 -1
package/dist/cjs/aggregator.cjs
CHANGED
|
@@ -43,6 +43,7 @@ var _Aggregator = class {
|
|
|
43
43
|
constructor(config, providerClient, quoterClient) {
|
|
44
44
|
this.builderConfigMap = /* @__PURE__ */ new Map();
|
|
45
45
|
this.broadcastRpcsMap = /* @__PURE__ */ new Map();
|
|
46
|
+
this.sequencerRpcsMap = /* @__PURE__ */ new Map();
|
|
46
47
|
this.aggregatorAddressMap = /* @__PURE__ */ new Map();
|
|
47
48
|
this.aggregatorMap = /* @__PURE__ */ new Map();
|
|
48
49
|
this.config = config;
|
|
@@ -52,16 +53,17 @@ var _Aggregator = class {
|
|
|
52
53
|
if (config.flashbotSigner) {
|
|
53
54
|
this.flashbotSigner = new import_ethers.ethers.Wallet(config.flashbotSigner);
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
for (const [chainName, builderCfg] of Object.entries(config.builderConfig ?? {})) {
|
|
57
|
+
this.builderConfigMap.set(chainName, builderCfg);
|
|
58
|
+
}
|
|
59
|
+
for (const [chainName, urls] of Object.entries(config.broadcastRpcs ?? {})) {
|
|
60
|
+
if (urls.length > 0) {
|
|
61
|
+
this.broadcastRpcsMap.set(chainName, urls);
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.broadcastRpcsMap.set(chainName, urls);
|
|
64
|
-
}
|
|
64
|
+
for (const [chainName, url] of Object.entries(this.getSequencerRpcs(config))) {
|
|
65
|
+
if (url) {
|
|
66
|
+
this.sequencerRpcsMap.set(chainName, url);
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
69
|
for (const [chainName, aggregatorAddress] of Object.entries(config.aggregatorAddress)) {
|
|
@@ -116,6 +118,15 @@ var _Aggregator = class {
|
|
|
116
118
|
}
|
|
117
119
|
throw new Error(`No builder config for chain: ${chain}`);
|
|
118
120
|
}
|
|
121
|
+
getSequencerRpcs(config) {
|
|
122
|
+
const merged = {
|
|
123
|
+
..._Aggregator.DEFAULT_SEQUENCER_RPC_BY_CHAIN
|
|
124
|
+
};
|
|
125
|
+
for (const [chainName, url] of Object.entries(config.sequencerRpcs ?? {})) {
|
|
126
|
+
merged[chainName] = url;
|
|
127
|
+
}
|
|
128
|
+
return merged;
|
|
129
|
+
}
|
|
119
130
|
buildBundleRequestBody(builderCfg, rawTxs, targetBlock) {
|
|
120
131
|
const method = builderCfg.method ?? "eth_sendBundle";
|
|
121
132
|
if (builderCfg.blockParamStyle === "decimal") {
|
|
@@ -863,6 +874,9 @@ var _Aggregator = class {
|
|
|
863
874
|
})
|
|
864
875
|
);
|
|
865
876
|
}
|
|
877
|
+
static isBenignBroadcastError(message) {
|
|
878
|
+
return message.includes("already known") || message.includes("nonce too low") || message.includes("nonce has already been used") || message.includes("ALREADY_EXISTS") || message.includes("NONCE_EXPIRED");
|
|
879
|
+
}
|
|
866
880
|
async waitForBundleInclusion(provider, txHash, maxTargetBlock, signal) {
|
|
867
881
|
const deadline = Date.now() + _Aggregator.BUNDLE_INCLUSION_TIMEOUT_MS;
|
|
868
882
|
while (Date.now() < deadline) {
|
|
@@ -881,21 +895,31 @@ var _Aggregator = class {
|
|
|
881
895
|
}
|
|
882
896
|
return null;
|
|
883
897
|
}
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
898
|
+
async sendSignedTxToChannels(chain, signedTx, txHash, channels) {
|
|
899
|
+
const results = await Promise.all(
|
|
900
|
+
channels.map(async ({ label, send }) => {
|
|
901
|
+
var _a, _b, _c, _d, _e;
|
|
902
|
+
const sendTs = Date.now();
|
|
903
|
+
try {
|
|
904
|
+
await send();
|
|
905
|
+
_Aggregator.traceLog(chain, "log", `广播${label} OK, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
906
|
+
return { label, ok: true };
|
|
907
|
+
} catch (err) {
|
|
908
|
+
const msg = ((_c = (_b = (_a = err == null ? void 0 : err.response) == null ? void 0 : _a.data) == null ? void 0 : _b.error) == null ? void 0 : _c.message) ?? ((_e = (_d = err == null ? void 0 : err.response) == null ? void 0 : _d.data) == null ? void 0 : _e.message) ?? (err == null ? void 0 : err.message) ?? String(err);
|
|
909
|
+
if (_Aggregator.isBenignBroadcastError(msg)) {
|
|
892
910
|
_Aggregator.traceLog(chain, "log", `广播${label} already-known, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
893
|
-
|
|
894
|
-
_Aggregator.traceLog(chain, "warn", `广播${label} 失败: ${msg}, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
911
|
+
return { label, ok: true };
|
|
895
912
|
}
|
|
913
|
+
_Aggregator.traceLog(chain, "warn", `广播${label} 失败: ${msg}, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
914
|
+
return { label, ok: false, msg };
|
|
896
915
|
}
|
|
897
|
-
)
|
|
916
|
+
})
|
|
917
|
+
);
|
|
918
|
+
if (results.some((result) => result.ok)) {
|
|
919
|
+
return;
|
|
898
920
|
}
|
|
921
|
+
const detail = results.map((result) => `${result.label}: ${result.msg ?? "unknown error"}`).join("; ");
|
|
922
|
+
throw new Error(`All broadcast channels failed for ${txHash}: ${detail}`);
|
|
899
923
|
}
|
|
900
924
|
raceForReceipt(chain, txHash, providers, ownedProviders = [], timeoutMs = _Aggregator.TX_CONFIRM_TIMEOUT_MS) {
|
|
901
925
|
return new Promise((resolve, reject) => {
|
|
@@ -948,17 +972,66 @@ var _Aggregator = class {
|
|
|
948
972
|
}, timeoutMs);
|
|
949
973
|
});
|
|
950
974
|
}
|
|
975
|
+
buildSequencerChannel(chain, signedTx) {
|
|
976
|
+
const sequencerUrl = _Aggregator.SEQUENCER_CHAINS.has(chain) ? this.sequencerRpcsMap.get(chain) : void 0;
|
|
977
|
+
if (!sequencerUrl)
|
|
978
|
+
return null;
|
|
979
|
+
return {
|
|
980
|
+
label: `Sequencer[${new URL(sequencerUrl).hostname}]`,
|
|
981
|
+
send: async () => {
|
|
982
|
+
var _a;
|
|
983
|
+
const resp = await import_axios.default.post(
|
|
984
|
+
sequencerUrl,
|
|
985
|
+
{ jsonrpc: "2.0", id: 1, method: "eth_sendRawTransaction", params: [signedTx] },
|
|
986
|
+
{ timeout: 5e3 }
|
|
987
|
+
);
|
|
988
|
+
if ((_a = resp.data) == null ? void 0 : _a.error) {
|
|
989
|
+
throw new Error(resp.data.error.message ?? JSON.stringify(resp.data.error));
|
|
990
|
+
}
|
|
991
|
+
return resp;
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
}
|
|
951
995
|
async sendContractTx(chain, contract, method, args, txReq) {
|
|
952
996
|
const extraUrls = this.broadcastRpcsMap.get(chain);
|
|
997
|
+
const hasSequencer = _Aggregator.SEQUENCER_CHAINS.has(chain) && this.sequencerRpcsMap.has(chain);
|
|
953
998
|
if (!extraUrls || extraUrls.length === 0) {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
999
|
+
if (!hasSequencer) {
|
|
1000
|
+
_Aggregator.traceLog(chain, "log", `渠道=单RPC直发, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}`);
|
|
1001
|
+
const sendTs = Date.now();
|
|
1002
|
+
const txResponse = await contract[method](...args, txReq);
|
|
1003
|
+
_Aggregator.traceLog(chain, "log", `单RPC已发送, txHash=${txResponse.hash}, 耗时=${Date.now() - sendTs}ms`);
|
|
1004
|
+
const receipt3 = await txResponse.wait();
|
|
1005
|
+
const singleProvider = this.providerClient.getProvider(chain);
|
|
1006
|
+
const blockTs3 = await this.getBlockTimestampStr(singleProvider, receipt3.blockNumber);
|
|
1007
|
+
_Aggregator.traceLog(chain, "log", `单RPC上链确认, txHash=${receipt3.hash}, blockNumber=${receipt3.blockNumber}, 出块时间=${blockTs3}, gasUsed=${receipt3.gasUsed}, status=${receipt3.status}`);
|
|
1008
|
+
if (receipt3.status === 0) {
|
|
1009
|
+
throw new import_types.TransactionRevertedError(receipt3.hash, receipt3.gasUsed);
|
|
1010
|
+
}
|
|
1011
|
+
return receipt3;
|
|
1012
|
+
}
|
|
1013
|
+
_Aggregator.traceLog(chain, "log", `渠道=单RPC+排序器直发, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}`);
|
|
1014
|
+
const wallet2 = this.providerClient.getWallet(chain);
|
|
1015
|
+
const populated2 = await contract[method].populateTransaction(...args, txReq);
|
|
1016
|
+
delete populated2.from;
|
|
1017
|
+
const network2 = await wallet2.provider.getNetwork();
|
|
1018
|
+
populated2.chainId = network2.chainId;
|
|
1019
|
+
const signedTx2 = await wallet2.signTransaction(populated2);
|
|
1020
|
+
const txHash2 = import_ethers.ethers.keccak256(signedTx2);
|
|
1021
|
+
const mainProvider2 = wallet2.provider;
|
|
1022
|
+
_Aggregator.traceLog(chain, "log", `单RPC+排序器并行广播, txHash=${txHash2}`);
|
|
1023
|
+
const broadcastTs2 = Date.now();
|
|
1024
|
+
const providers = [{ provider: mainProvider2, label: "RPC[0/主]" }];
|
|
1025
|
+
const sequencerChannel2 = this.buildSequencerChannel(chain, signedTx2);
|
|
1026
|
+
const channels2 = [
|
|
1027
|
+
...providers.map(({ provider, label }) => ({ label, send: () => provider.broadcastTransaction(signedTx2) })),
|
|
1028
|
+
...sequencerChannel2 ? [sequencerChannel2] : []
|
|
1029
|
+
];
|
|
1030
|
+
const receiptPromise2 = this.raceForReceipt(chain, txHash2, providers);
|
|
1031
|
+
await this.sendSignedTxToChannels(chain, signedTx2, txHash2, channels2);
|
|
1032
|
+
const receipt2 = await receiptPromise2;
|
|
1033
|
+
const blockTs2 = await this.getBlockTimestampStr(mainProvider2, receipt2.blockNumber);
|
|
1034
|
+
_Aggregator.traceLog(chain, "log", `单RPC+排序器上链确认, txHash=${receipt2.hash}, blockNumber=${receipt2.blockNumber}, 出块时间=${blockTs2}, gasUsed=${receipt2.gasUsed}, status=${receipt2.status}, 总耗时=${Date.now() - broadcastTs2}ms`);
|
|
962
1035
|
if (receipt2.status === 0) {
|
|
963
1036
|
throw new import_types.TransactionRevertedError(receipt2.hash, receipt2.gasUsed);
|
|
964
1037
|
}
|
|
@@ -982,11 +1055,17 @@ var _Aggregator = class {
|
|
|
982
1055
|
_Aggregator.traceLog(
|
|
983
1056
|
chain,
|
|
984
1057
|
"log",
|
|
985
|
-
`渠道=多RPC广播, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}, 当前区块=${currentBlock}, 期望上链区块=${currentBlock + 1}, txHash=${txHash}, RPC数量=${allProviders.length}(主1+副${extraUrls.length})`
|
|
1058
|
+
`渠道=多RPC广播, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}, 当前区块=${currentBlock}, 期望上链区块=${currentBlock + 1}, txHash=${txHash}, RPC数量=${allProviders.length}(主1+副${extraUrls.length})${hasSequencer ? ", +排序器直发" : ""}`
|
|
986
1059
|
);
|
|
987
1060
|
const broadcastTs = Date.now();
|
|
988
|
-
this.
|
|
989
|
-
const
|
|
1061
|
+
const sequencerChannel = this.buildSequencerChannel(chain, signedTx);
|
|
1062
|
+
const channels = [
|
|
1063
|
+
...allProviders.map(({ provider, label }) => ({ label, send: () => provider.broadcastTransaction(signedTx) })),
|
|
1064
|
+
...sequencerChannel ? [sequencerChannel] : []
|
|
1065
|
+
];
|
|
1066
|
+
const receiptPromise = this.raceForReceipt(chain, txHash, allProviders, ownedProviders);
|
|
1067
|
+
await this.sendSignedTxToChannels(chain, signedTx, txHash, channels);
|
|
1068
|
+
const receipt = await receiptPromise;
|
|
990
1069
|
const blockTs = await this.getBlockTimestampStr(mainProvider, receipt.blockNumber);
|
|
991
1070
|
_Aggregator.traceLog(
|
|
992
1071
|
chain,
|
|
@@ -1194,26 +1273,45 @@ var _Aggregator = class {
|
|
|
1194
1273
|
}
|
|
1195
1274
|
};
|
|
1196
1275
|
var Aggregator = _Aggregator;
|
|
1276
|
+
// private static readonly DEFAULT_ETH_BUILDERS: Record<string, string> = {
|
|
1277
|
+
// 'beaverbuild.org': 'https://rpc.beaverbuild.org',
|
|
1278
|
+
// Titan: 'https://rpc.titanbuilder.xyz',
|
|
1279
|
+
// flashbots: 'https://relay.flashbots.net',
|
|
1280
|
+
// bloXroute: 'https://api.blxrbdn.com',
|
|
1281
|
+
// rsync: 'https://rsync-builder.xyz',
|
|
1282
|
+
// 'builder0x69.io': 'https://builder0x69.io',
|
|
1283
|
+
// bloxroute: 'https://bloxroute.max-profit.blxrbdn.com',
|
|
1284
|
+
// blocknative: 'https://builder.blocknative.com',
|
|
1285
|
+
// eden: 'https://relay.edennetwork.io',
|
|
1286
|
+
// ultra_sound_relay: 'https://relay.ultrasound.money',
|
|
1287
|
+
// lokibuilder: 'https://relay.lokibuilder.xyz',
|
|
1288
|
+
// penguinbuild: 'https://relay.penguinbuild.org',
|
|
1289
|
+
// gambit: 'https://builder.gmbit.co',
|
|
1290
|
+
// jetbuilder: 'https://relay.jetbld.xyz',
|
|
1291
|
+
// f1b: 'https://builder.f1b.io',
|
|
1292
|
+
// buildai: 'https://relay.buildai.net',
|
|
1293
|
+
// tbuilder: 'https://relay.tbuilder.xyz',
|
|
1294
|
+
// bobabuilder: 'https://relay.boba-builder.com',
|
|
1295
|
+
// };
|
|
1197
1296
|
Aggregator.DEFAULT_ETH_BUILDERS = {
|
|
1198
1297
|
"beaverbuild.org": "https://rpc.beaverbuild.org",
|
|
1199
1298
|
Titan: "https://rpc.titanbuilder.xyz",
|
|
1200
1299
|
flashbots: "https://relay.flashbots.net",
|
|
1201
|
-
bloXroute:
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
f1b: "https://builder.f1b.io",
|
|
1213
|
-
buildai: "https://relay.buildai.net",
|
|
1214
|
-
tbuilder: "https://relay.tbuilder.xyz",
|
|
1215
|
-
bobabuilder: "https://relay.boba-builder.com"
|
|
1300
|
+
// bloXroute: 'https://mev.api.blxrbdn.com', // 旧 api.blxrbdn.com 也行,需配置 Authorization 头
|
|
1301
|
+
lightspeedbuilder: "https://rpc.lightspeedbuilder.info",
|
|
1302
|
+
// 新增,实测直接可用
|
|
1303
|
+
// buildernet: 'https://rpc.buildernet.org', // 新增,Flashbots 生态,需签名头(同 flashbots 格式)
|
|
1304
|
+
nfactorial: "https://rpc.nfactorial.xyz"
|
|
1305
|
+
// 新增,支持 bundle rebate
|
|
1306
|
+
};
|
|
1307
|
+
Aggregator.DEFAULT_SEQUENCER_RPC_BY_CHAIN = {
|
|
1308
|
+
[import_types.ChainNameEnum.ARB]: "https://arb1-sequencer.arbitrum.io/rpc",
|
|
1309
|
+
[import_types.ChainNameEnum.BASE]: "https://mainnet-sequencer.base.org",
|
|
1310
|
+
[import_types.ChainNameEnum.ETHERLINK]: "https://relay.mainnet.etherlink.com"
|
|
1216
1311
|
};
|
|
1312
|
+
Aggregator.SEQUENCER_CHAINS = new Set(
|
|
1313
|
+
Object.keys(_Aggregator.DEFAULT_SEQUENCER_RPC_BY_CHAIN)
|
|
1314
|
+
);
|
|
1217
1315
|
Aggregator.TX_CONFIRM_TIMEOUT_MS = 12e4;
|
|
1218
1316
|
Aggregator.BUNDLE_POLL_INTERVAL_MS = 500;
|
|
1219
1317
|
Aggregator.BUNDLE_INCLUSION_TIMEOUT_MS = 3e4;
|
package/dist/cjs/aggregator.d.ts
CHANGED
|
@@ -10,17 +10,21 @@ declare class Aggregator {
|
|
|
10
10
|
private readonly flashbotSigner?;
|
|
11
11
|
private readonly builderConfigMap;
|
|
12
12
|
private readonly broadcastRpcsMap;
|
|
13
|
+
private readonly sequencerRpcsMap;
|
|
13
14
|
private aggregatorAddressMap;
|
|
14
15
|
private aggregatorMap;
|
|
15
16
|
private static traceLog;
|
|
16
17
|
private static formatBlockTimestamp;
|
|
17
18
|
private getBlockTimestampStr;
|
|
18
19
|
private static readonly DEFAULT_ETH_BUILDERS;
|
|
20
|
+
private static readonly DEFAULT_SEQUENCER_RPC_BY_CHAIN;
|
|
21
|
+
private static readonly SEQUENCER_CHAINS;
|
|
19
22
|
constructor(config: IConfig, providerClient?: Provider, quoterClient?: Quoter);
|
|
20
23
|
getAggregator(chain: ChainNameEnum): Contract;
|
|
21
24
|
getAggregatorAddress(chain: ChainNameEnum): string;
|
|
22
25
|
signRequestBody(body: unknown, signer: ethers.Wallet): Promise<string>;
|
|
23
26
|
private getBuilderConfig;
|
|
27
|
+
private getSequencerRpcs;
|
|
24
28
|
private buildBundleRequestBody;
|
|
25
29
|
sendBundle(chain: ChainNameEnum, rawTxs: string[], targetBlock: number, signer?: ethers.Wallet): Promise<{
|
|
26
30
|
sent: number;
|
|
@@ -53,9 +57,11 @@ declare class Aggregator {
|
|
|
53
57
|
private static readonly TX_CONFIRM_TIMEOUT_MS;
|
|
54
58
|
private static readonly BUNDLE_POLL_INTERVAL_MS;
|
|
55
59
|
private static readonly BUNDLE_INCLUSION_TIMEOUT_MS;
|
|
60
|
+
private static isBenignBroadcastError;
|
|
56
61
|
private waitForBundleInclusion;
|
|
57
|
-
private
|
|
62
|
+
private sendSignedTxToChannels;
|
|
58
63
|
private raceForReceipt;
|
|
64
|
+
private buildSequencerChannel;
|
|
59
65
|
private sendContractTx;
|
|
60
66
|
private submitBundleTx;
|
|
61
67
|
private swapByFlashbots;
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export interface IConfig {
|
|
|
14
14
|
flashbotSigner?: string;
|
|
15
15
|
builderConfig?: Record<string, IBuilderConfig>;
|
|
16
16
|
broadcastRpcs?: Record<string, string[]>;
|
|
17
|
+
sequencerRpcs?: Record<string, string>;
|
|
17
18
|
}
|
|
18
19
|
export interface IExpectByPathParams {
|
|
19
20
|
chain: ChainNameEnum;
|
package/dist/esm/aggregator.d.ts
CHANGED
|
@@ -10,17 +10,21 @@ declare class Aggregator {
|
|
|
10
10
|
private readonly flashbotSigner?;
|
|
11
11
|
private readonly builderConfigMap;
|
|
12
12
|
private readonly broadcastRpcsMap;
|
|
13
|
+
private readonly sequencerRpcsMap;
|
|
13
14
|
private aggregatorAddressMap;
|
|
14
15
|
private aggregatorMap;
|
|
15
16
|
private static traceLog;
|
|
16
17
|
private static formatBlockTimestamp;
|
|
17
18
|
private getBlockTimestampStr;
|
|
18
19
|
private static readonly DEFAULT_ETH_BUILDERS;
|
|
20
|
+
private static readonly DEFAULT_SEQUENCER_RPC_BY_CHAIN;
|
|
21
|
+
private static readonly SEQUENCER_CHAINS;
|
|
19
22
|
constructor(config: IConfig, providerClient?: Provider, quoterClient?: Quoter);
|
|
20
23
|
getAggregator(chain: ChainNameEnum): Contract;
|
|
21
24
|
getAggregatorAddress(chain: ChainNameEnum): string;
|
|
22
25
|
signRequestBody(body: unknown, signer: ethers.Wallet): Promise<string>;
|
|
23
26
|
private getBuilderConfig;
|
|
27
|
+
private getSequencerRpcs;
|
|
24
28
|
private buildBundleRequestBody;
|
|
25
29
|
sendBundle(chain: ChainNameEnum, rawTxs: string[], targetBlock: number, signer?: ethers.Wallet): Promise<{
|
|
26
30
|
sent: number;
|
|
@@ -53,9 +57,11 @@ declare class Aggregator {
|
|
|
53
57
|
private static readonly TX_CONFIRM_TIMEOUT_MS;
|
|
54
58
|
private static readonly BUNDLE_POLL_INTERVAL_MS;
|
|
55
59
|
private static readonly BUNDLE_INCLUSION_TIMEOUT_MS;
|
|
60
|
+
private static isBenignBroadcastError;
|
|
56
61
|
private waitForBundleInclusion;
|
|
57
|
-
private
|
|
62
|
+
private sendSignedTxToChannels;
|
|
58
63
|
private raceForReceipt;
|
|
64
|
+
private buildSequencerChannel;
|
|
59
65
|
private sendContractTx;
|
|
60
66
|
private submitBundleTx;
|
|
61
67
|
private swapByFlashbots;
|