@w3lib/evm-batch-call 0.4.1 → 0.5.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.
Files changed (92) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +166 -3
  3. package/dist/aggregate.d.ts.map +1 -1
  4. package/dist/aggregate.js +153 -40
  5. package/dist/aggregate.js.map +1 -1
  6. package/dist/fallback.d.ts +20 -0
  7. package/dist/fallback.d.ts.map +1 -1
  8. package/dist/fallback.js +36 -5
  9. package/dist/fallback.js.map +1 -1
  10. package/dist/lp.d.ts +149 -0
  11. package/dist/lp.d.ts.map +1 -0
  12. package/dist/lp.js +499 -0
  13. package/dist/lp.js.map +1 -0
  14. package/dist/lpMath.d.ts +25 -0
  15. package/dist/lpMath.d.ts.map +1 -0
  16. package/dist/lpMath.js +103 -0
  17. package/dist/lpMath.js.map +1 -0
  18. package/dist/lpV4.d.ts +108 -0
  19. package/dist/lpV4.d.ts.map +1 -0
  20. package/dist/lpV4.js +283 -0
  21. package/dist/lpV4.js.map +1 -0
  22. package/dist/owner.d.ts +1 -1
  23. package/dist/owner.d.ts.map +1 -1
  24. package/dist/owner.js +18 -5
  25. package/dist/owner.js.map +1 -1
  26. package/dist/scan.d.ts +54 -0
  27. package/dist/scan.d.ts.map +1 -1
  28. package/dist/scan.js +124 -92
  29. package/dist/scan.js.map +1 -1
  30. package/dist/source.d.ts +2 -0
  31. package/dist/source.d.ts.map +1 -1
  32. package/dist/source.js +4 -0
  33. package/dist/source.js.map +1 -1
  34. package/dist/subpaths/lp.d.ts +33 -0
  35. package/dist/subpaths/lp.d.ts.map +1 -0
  36. package/dist/subpaths/lp.js +47 -0
  37. package/dist/subpaths/lp.js.map +1 -0
  38. package/dist/subpaths/write.d.ts +20 -0
  39. package/dist/subpaths/write.d.ts.map +1 -0
  40. package/dist/subpaths/write.js +18 -0
  41. package/dist/subpaths/write.js.map +1 -0
  42. package/dist/tron.d.ts +2 -0
  43. package/dist/tron.d.ts.map +1 -1
  44. package/dist/tron.js +4 -0
  45. package/dist/tron.js.map +1 -1
  46. package/dist/write/batch.d.ts +88 -0
  47. package/dist/write/batch.d.ts.map +1 -0
  48. package/dist/write/batch.js +231 -0
  49. package/dist/write/batch.js.map +1 -0
  50. package/dist/write/collect.d.ts +53 -0
  51. package/dist/write/collect.d.ts.map +1 -0
  52. package/dist/write/collect.js +255 -0
  53. package/dist/write/collect.js.map +1 -0
  54. package/dist/write/rpc.d.ts +68 -0
  55. package/dist/write/rpc.d.ts.map +1 -0
  56. package/dist/write/rpc.js +236 -0
  57. package/dist/write/rpc.js.map +1 -0
  58. package/dist/write/send.d.ts +124 -0
  59. package/dist/write/send.d.ts.map +1 -0
  60. package/dist/write/send.js +373 -0
  61. package/dist/write/send.js.map +1 -0
  62. package/dist/write/signer.d.ts +58 -0
  63. package/dist/write/signer.d.ts.map +1 -0
  64. package/dist/write/signer.js +41 -0
  65. package/dist/write/signer.js.map +1 -0
  66. package/dist/write/transfer.d.ts +83 -0
  67. package/dist/write/transfer.d.ts.map +1 -0
  68. package/dist/write/transfer.js +259 -0
  69. package/dist/write/transfer.js.map +1 -0
  70. package/dist/write/tron.d.ts +58 -0
  71. package/dist/write/tron.d.ts.map +1 -0
  72. package/dist/write/tron.js +956 -0
  73. package/dist/write/tron.js.map +1 -0
  74. package/package.json +27 -14
  75. package/src/aggregate.ts +168 -36
  76. package/src/fallback.ts +55 -11
  77. package/src/lp.ts +721 -0
  78. package/src/lpMath.ts +113 -0
  79. package/src/lpV4.ts +406 -0
  80. package/src/owner.ts +19 -6
  81. package/src/scan.ts +155 -86
  82. package/src/source.ts +5 -0
  83. package/src/subpaths/lp.ts +71 -0
  84. package/src/subpaths/write.ts +26 -0
  85. package/src/tron.ts +5 -0
  86. package/src/write/batch.ts +302 -0
  87. package/src/write/collect.ts +312 -0
  88. package/src/write/rpc.ts +277 -0
  89. package/src/write/send.ts +490 -0
  90. package/src/write/signer.ts +90 -0
  91. package/src/write/transfer.ts +344 -0
  92. package/src/write/tron.ts +1100 -0
@@ -0,0 +1,124 @@
1
+ import { type TransactionRequest } from 'ethers';
2
+ import { WriteRpc } from './rpc.js';
3
+ import type { ResolvedSigner } from './signer.js';
4
+ /**
5
+ * 每个调用的状态:
6
+ * - confirmed:已上链且执行成功
7
+ * - reverted:已上链但执行失败(手续费已扣)
8
+ * - failed:没有发出去(预估 revert、余额不足、节点拒绝、用户在钱包里拒绝等),不花手续费
9
+ * - sent:已广播,没等确认(wait: false,或等待中途取消)。广播时超时 / 节点都连不上(交易可能已进交易池)也算 sent,error 里有说明
10
+ * - pending:等到超时还没确认,之后仍可能上链(可用 hash 自行查询)
11
+ * - skipped:没有执行:同一钱包前面的调用失败(continueOnError 为 false 时)、已取消,或同一笔批量交易里的其他调用失败
12
+ * - simulated:dryRun 预估通过
13
+ */
14
+ export type WriteStatus = 'confirmed' | 'reverted' | 'failed' | 'sent' | 'pending' | 'skipped' | 'simulated';
15
+ /** 发送参数(batchCall / batchTransfer / batchCollect 共用) */
16
+ export interface SendOptions {
17
+ /** 等待上链确认。默认 true;false 时广播后即返回,status 为 'sent' */
18
+ wait?: boolean;
19
+ /** 等待确认的最长时间(毫秒),超时的交易 status 为 'pending'。默认 180000 */
20
+ timeout?: number;
21
+ /** 查询回执的间隔(毫秒),默认 2000。等待期间每 5 次查询重发一次原交易(防止被交易池丢弃,重发同一笔签名交易是安全的) */
22
+ pollInterval?: number;
23
+ /** 同时处理的钱包数(同一钱包的交易总是按 nonce 顺序发),默认 8 */
24
+ concurrency?: number;
25
+ /** gas 预估值的放大倍数,默认 1.2(预估值正好 21000 的普通转账不放大) */
26
+ gasMultiplier?: number;
27
+ /** 固定 gasPrice(legacy 交易) */
28
+ gasPrice?: bigint;
29
+ /** 固定 EIP-1559 费用,不传时按节点的 getFeeData(maxFee = 2 × baseFee + priorityFee) */
30
+ maxFeePerGas?: bigint;
31
+ maxPriorityFeePerGas?: bigint;
32
+ /** 只预估 gas、不发送,status 为 'simulated' 或 'failed'。注意:依赖前一笔交易结果的调用(如先 approve 再 transferFrom)预估会失败 */
33
+ dryRun?: boolean;
34
+ /** 取消:不再发新交易,已发出的不再等待确认(status 为 'sent') */
35
+ signal?: AbortSignal;
36
+ /** 每个结果状态变化时回调(sent / confirmed / failed …),用于展示进度 */
37
+ onUpdate?: (result: WriteResult) => void;
38
+ }
39
+ /** 只在 Tron 上生效的发送参数 */
40
+ export interface TronSendOptions {
41
+ /**
42
+ * 合约调用的 fee_limit(sun,最多烧多少 TRX 换能量)。默认按模拟的能量 × 能量单价 × 1.5。
43
+ * 能量不够时交易上链但执行失败(OUT_OF_ENERGY),已烧的 TRX 不退
44
+ */
45
+ feeLimit?: bigint;
46
+ /** 交易过期仍未上链时(按固化区块判断),换新的参考区块重发的次数。默认 2 */
47
+ retries?: number;
48
+ }
49
+ /** 每个调用的结果,都是字符串 / 数字 / null,可以直接 JSON.stringify */
50
+ export interface WriteResult {
51
+ /** 在输入里的下标 */
52
+ index: number;
53
+ /** 发送的钱包地址 */
54
+ from: string;
55
+ /** 调用的目标地址(7702 批量交易里是每个子调用的目标) */
56
+ to: string;
57
+ status: WriteStatus;
58
+ /** 交易哈希(7702 / Disperse 里同一笔交易的多个调用相同) */
59
+ hash: string | null;
60
+ nonce: number | null;
61
+ gasLimit: string | null;
62
+ gasUsed: string | null;
63
+ /** 实际手续费(wei),gasUsed × effectiveGasPrice,不含 OP Stack 的 L1 数据费 */
64
+ fee: string | null;
65
+ blockNumber: number | null;
66
+ error: string | null;
67
+ }
68
+ /** 交易层面的结果(一笔交易可能对应多个调用的结果) */
69
+ export interface TxOutcome {
70
+ status: WriteStatus;
71
+ hash: string | null;
72
+ nonce: number | null;
73
+ gasLimit: bigint | null;
74
+ gasUsed: bigint | null;
75
+ fee: bigint | null;
76
+ blockNumber: number | null;
77
+ error: string | null;
78
+ /** 预估失败时的 revert 数据 */
79
+ revertData: string | null;
80
+ }
81
+ /** 要发送的一笔交易 */
82
+ export interface TxJob {
83
+ signer: ResolvedSigner;
84
+ /** 生成交易内容;nonce 是这笔交易将使用的 nonce(7702 授权签名要用),交给钱包发送时为 null */
85
+ build(nonce: number | null): Promise<Pick<TransactionRequest, 'to' | 'data' | 'value' | 'authorizationList'>>;
86
+ /** 指定 gasLimit 时不预估 */
87
+ gasLimit?: bigint;
88
+ /** 发送前失败后同一钱包后面的交易是否继续(默认 false:后面的标记为 skipped)。已发出、之后上链 revert 的不影响后面的交易 */
89
+ continueOnError?: boolean;
90
+ /** 状态变化时回调 */
91
+ onUpdate?(outcome: TxOutcome): void;
92
+ }
93
+ export interface TxFees {
94
+ type: 0 | 2;
95
+ gasPrice?: bigint;
96
+ maxFeePerGas?: bigint;
97
+ maxPriorityFeePerGas?: bigint;
98
+ /** 每单位 gas 最多花多少(预留余额用):legacy 为 gasPrice,1559 为 maxFeePerGas */
99
+ perGas: bigint;
100
+ }
101
+ /** 交易费用参数:用户指定的优先,否则按节点的 getFeeData;结果缓存 30 秒,同一批交易共用 */
102
+ export declare class FeeSource {
103
+ #private;
104
+ readonly rpc: WriteRpc;
105
+ readonly options: Pick<SendOptions, 'gasPrice' | 'maxFeePerGas' | 'maxPriorityFeePerGas'>;
106
+ constructor(rpc: WriteRpc, options?: Pick<SendOptions, 'gasPrice' | 'maxFeePerGas' | 'maxPriorityFeePerGas'>);
107
+ /** 固定为给定的费用,不再查节点(预留余额和实际发送要用同一个价格时) */
108
+ static fixed(rpc: WriteRpc, fee: TxFees): FeeSource;
109
+ get(): Promise<TxFees>;
110
+ }
111
+ /** gas 预估值乘以放大倍数(正好 21000 的普通转账不放大) */
112
+ export declare function applyGasMultiplier(gas: bigint, multiplier?: number): bigint;
113
+ export declare function emptyOutcome(status: WriteStatus, error?: string | null): TxOutcome;
114
+ /** 并发数为 limit 的 map,结果按输入顺序 */
115
+ export declare function mapPool<T, R>(items: readonly T[], limit: number, fn: (item: T, index: number) => Promise<R>): Promise<R[]>;
116
+ /**
117
+ * 发送一批交易:同一钱包按顺序、用本地维护的 nonce 连续发出(不等上一笔确认),不同钱包并发。
118
+ * 预估失败且同一钱包还有未确认的交易时,先等它们确认再重新预估一次——后一笔依赖前一笔的结果时(先 approve 再调用)自动正确处理。
119
+ * 返回值与 jobs 一一对应
120
+ */
121
+ export declare function sendJobs(rpc: WriteRpc, jobs: readonly TxJob[], options: SendOptions, fees?: FeeSource): Promise<TxOutcome[]>;
122
+ /** 交易结果转成调用结果(字符串 / 数字,可 JSON 序列化) */
123
+ export declare function toWriteResult(index: number, from: string, to: string, outcome: TxOutcome): WriteResult;
124
+ //# sourceMappingURL=send.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/write/send.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,kBAAkB,EAAE,MAAM,QAAQ,CAAA;AAElF,OAAO,EAAE,QAAQ,EAAqD,MAAM,UAAU,CAAA;AACtF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAA;AAE5G,wDAAwD;AACxD,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,kGAAkG;IAClG,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA;CACzC;AAED,uBAAuB;AACvB,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,oDAAoD;AACpD,MAAM,WAAW,WAAW;IAC1B,cAAc;IACd,KAAK,EAAE,MAAM,CAAA;IACb,cAAc;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,WAAW,CAAA;IACnB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,kEAAkE;IAClE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,+BAA+B;AAC/B,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,WAAW,CAAA;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,uBAAuB;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,eAAe;AACf,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,cAAc,CAAA;IACtB,8DAA8D;IAC9D,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,IAAI,GAAG,MAAM,GAAG,OAAO,GAAG,mBAAmB,CAAC,CAAC,CAAA;IAC7G,uBAAuB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,cAAc;IACd,QAAQ,CAAC,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;IACX,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAA;CACf;AAID,yDAAyD;AACzD,qBAAa,SAAS;;IAIlB,QAAQ,CAAC,GAAG,EAAE,QAAQ;IACtB,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,cAAc,GAAG,sBAAsB,CAAC;gBADhF,GAAG,EAAE,QAAQ,EACb,OAAO,GAAE,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,cAAc,GAAG,sBAAsB,CAAM;IAGhG,wCAAwC;IACxC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS;IAInD,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;CAmBvB;AAiBD,uCAAuC;AACvC,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,SAAM,GAAG,MAAM,CAKxE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,GAAE,MAAM,GAAG,IAAW,GAAG,SAAS,CAExF;AAED,+BAA+B;AAC/B,wBAAsB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAWhI;AA4BD;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,YAA8B,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAcpJ;AAkPD,sCAAsC;AACtC,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,WAAW,CActG"}
@@ -0,0 +1,373 @@
1
+ import { isError } from 'ethers';
2
+ import { WriteRpc, failureText, revertData, signedHash } from './rpc.js';
3
+ const FEE_TTL = 30_000;
4
+ /** 交易费用参数:用户指定的优先,否则按节点的 getFeeData;结果缓存 30 秒,同一批交易共用 */
5
+ export class FeeSource {
6
+ rpc;
7
+ options;
8
+ #cached = null;
9
+ constructor(rpc, options = {}) {
10
+ this.rpc = rpc;
11
+ this.options = options;
12
+ }
13
+ /** 固定为给定的费用,不再查节点(预留余额和实际发送要用同一个价格时) */
14
+ static fixed(rpc, fee) {
15
+ return new FeeSource(rpc, fee.type === 0 ? { gasPrice: fee.gasPrice } : { maxFeePerGas: fee.maxFeePerGas, maxPriorityFeePerGas: fee.maxPriorityFeePerGas });
16
+ }
17
+ get() {
18
+ const { gasPrice, maxFeePerGas, maxPriorityFeePerGas } = this.options;
19
+ if (gasPrice !== undefined) {
20
+ return Promise.resolve({ type: 0, gasPrice, perGas: gasPrice });
21
+ }
22
+ if (maxFeePerGas !== undefined && maxPriorityFeePerGas !== undefined) {
23
+ return Promise.resolve({ type: 2, maxFeePerGas, maxPriorityFeePerGas, perGas: maxFeePerGas });
24
+ }
25
+ if (!this.#cached || Date.now() - this.#cached.at > FEE_TTL) {
26
+ const fees = this.rpc.feeData().then((data) => toFees(data, maxFeePerGas, maxPriorityFeePerGas));
27
+ fees.catch(() => {
28
+ if (this.#cached?.fees === fees) {
29
+ this.#cached = null;
30
+ }
31
+ });
32
+ this.#cached = { at: Date.now(), fees };
33
+ }
34
+ return this.#cached.fees;
35
+ }
36
+ }
37
+ function toFees(data, maxFee, priority) {
38
+ if (data.maxFeePerGas === null || data.maxPriorityFeePerGas === null) {
39
+ if (data.gasPrice === null) {
40
+ throw new Error('Unable to get gas price from the node');
41
+ }
42
+ return { type: 0, gasPrice: data.gasPrice, perGas: data.gasPrice };
43
+ }
44
+ const maxPriorityFeePerGas = priority ?? data.maxPriorityFeePerGas;
45
+ let maxFeePerGas = maxFee ?? data.maxFeePerGas;
46
+ if (maxFeePerGas < maxPriorityFeePerGas) {
47
+ maxFeePerGas = maxPriorityFeePerGas;
48
+ }
49
+ return { type: 2, maxFeePerGas, maxPriorityFeePerGas, perGas: maxFeePerGas };
50
+ }
51
+ /** gas 预估值乘以放大倍数(正好 21000 的普通转账不放大) */
52
+ export function applyGasMultiplier(gas, multiplier = 1.2) {
53
+ if (gas === 21000n || multiplier <= 1) {
54
+ return gas;
55
+ }
56
+ return (gas * BigInt(Math.round(multiplier * 1000))) / 1000n;
57
+ }
58
+ export function emptyOutcome(status, error = null) {
59
+ return { status, hash: null, nonce: null, gasLimit: null, gasUsed: null, fee: null, blockNumber: null, error, revertData: null };
60
+ }
61
+ /** 并发数为 limit 的 map,结果按输入顺序 */
62
+ export async function mapPool(items, limit, fn) {
63
+ const results = new Array(items.length);
64
+ let next = 0;
65
+ const worker = async () => {
66
+ while (next < items.length) {
67
+ const i = next++;
68
+ results[i] = await fn(items[i], i);
69
+ }
70
+ };
71
+ await Promise.all(Array.from({ length: Math.min(Math.max(1, limit), items.length) }, worker));
72
+ return results;
73
+ }
74
+ function sleep(ms, signal) {
75
+ return new Promise((resolve) => {
76
+ if (signal?.aborted) {
77
+ resolve();
78
+ return;
79
+ }
80
+ const timer = setTimeout(done, ms);
81
+ function done() {
82
+ clearTimeout(timer);
83
+ signal?.removeEventListener('abort', done);
84
+ resolve();
85
+ }
86
+ signal?.addEventListener('abort', done, { once: true });
87
+ });
88
+ }
89
+ /**
90
+ * 发送一批交易:同一钱包按顺序、用本地维护的 nonce 连续发出(不等上一笔确认),不同钱包并发。
91
+ * 预估失败且同一钱包还有未确认的交易时,先等它们确认再重新预估一次——后一笔依赖前一笔的结果时(先 approve 再调用)自动正确处理。
92
+ * 返回值与 jobs 一一对应
93
+ */
94
+ export async function sendJobs(rpc, jobs, options, fees = new FeeSource(rpc, options)) {
95
+ const outcomes = jobs.map(() => emptyOutcome('skipped'));
96
+ const groups = new Map();
97
+ jobs.forEach((job, i) => {
98
+ const key = job.signer.address.toLowerCase();
99
+ const list = groups.get(key);
100
+ if (list) {
101
+ list.push(i);
102
+ }
103
+ else {
104
+ groups.set(key, [i]);
105
+ }
106
+ });
107
+ await mapPool([...groups.values()], options.concurrency ?? 8, (indexes) => sendGroup(rpc, jobs, indexes, outcomes, options, fees));
108
+ return outcomes;
109
+ }
110
+ async function sendGroup(rpc, jobs, indexes, outcomes, options, fees) {
111
+ const { signal, dryRun = false, wait = true } = options;
112
+ const first = jobs[indexes[0]];
113
+ const { signer, address, local } = first.signer;
114
+ const inFlight = [];
115
+ const update = (job, outcome, patch) => {
116
+ Object.assign(outcome, patch);
117
+ try {
118
+ job.onUpdate?.(outcome);
119
+ }
120
+ catch {
121
+ // 调用方的进度回调出错不能打断发送(已经发出的交易还要继续跟踪)
122
+ }
123
+ };
124
+ const watch = (item) => (item.watching ??= confirm(rpc, item, options, update));
125
+ /** 等同一钱包已发出的交易都确认(后面的调用依赖它们的结果时) */
126
+ const settle = async () => {
127
+ await Promise.all(inFlight.map(watch));
128
+ };
129
+ let nonce = null;
130
+ /** 上一笔带了 7702 授权:等它确认后再发下一笔 */
131
+ let authorized = null;
132
+ let stopped = false;
133
+ /** 浏览器钱包当前所在的链已核对过 */
134
+ let chainChecked = false;
135
+ for (const i of indexes) {
136
+ const job = jobs[i];
137
+ const outcome = outcomes[i];
138
+ if (authorized && !stopped && !signal?.aborted) {
139
+ // 自己签的授权会让账户 nonce 再加一(授权无效时不加),而且委托状态变了:等上链后重新取 nonce、重新生成
140
+ await settle();
141
+ const done = authorized.status === 'confirmed' || authorized.status === 'reverted';
142
+ authorized = null;
143
+ nonce = null;
144
+ if (!done) {
145
+ // 授权交易还没上链:之后的 nonce 不确定(上链后账户 nonce 会加 2),后面的交易发了也上不了链
146
+ stopped = true;
147
+ update(job, outcome, { status: 'skipped', error: 'skipped: the delegation transaction is not confirmed yet' });
148
+ continue;
149
+ }
150
+ }
151
+ if (stopped || signal?.aborted) {
152
+ update(job, outcome, { status: 'skipped', error: signal?.aborted ? 'aborted' : 'skipped: a previous call from this wallet failed' });
153
+ continue;
154
+ }
155
+ const fail = (error, extra = {}) => {
156
+ update(job, outcome, { status: 'failed', error, ...extra });
157
+ if (!job.continueOnError) {
158
+ stopped = true;
159
+ }
160
+ };
161
+ try {
162
+ if (local && nonce === null) {
163
+ nonce = await rpc.nonce(address);
164
+ }
165
+ let tx = await job.build(local ? nonce : null);
166
+ let gasLimit = job.gasLimit;
167
+ if (gasLimit === undefined) {
168
+ const estimate = () => rpc.estimateGas({ ...tx, from: address });
169
+ try {
170
+ gasLimit = await estimate();
171
+ }
172
+ catch (err) {
173
+ if (!inFlight.some((item) => item.outcome.status === 'sent')) {
174
+ throw err;
175
+ }
176
+ // 可能依赖前面还没确认的交易:等它们确认后重新生成(7702 授权的 nonce 不变)、重新预估
177
+ await settle();
178
+ if (signal?.aborted) {
179
+ update(job, outcome, { status: 'skipped', error: 'aborted' });
180
+ continue;
181
+ }
182
+ tx = await job.build(local ? nonce : null);
183
+ gasLimit = await estimate();
184
+ }
185
+ gasLimit = applyGasMultiplier(gasLimit, options.gasMultiplier);
186
+ }
187
+ if (dryRun) {
188
+ update(job, outcome, { status: 'simulated', gasLimit });
189
+ continue;
190
+ }
191
+ if (!local) {
192
+ if (!chainChecked) {
193
+ // 浏览器钱包在它当前所在的链上签名发送:先确认和 Provider 是同一条链,否则会在别的链上真的转账
194
+ const walletChain = await walletChainId(signer);
195
+ if (walletChain !== null && walletChain !== rpc.chainId) {
196
+ throw new Error(`The wallet is on chain ${walletChain}, expected ${rpc.chainId}; switch the network in the wallet first`);
197
+ }
198
+ chainChecked = true;
199
+ }
200
+ let hash;
201
+ let note = null;
202
+ try {
203
+ // 带上 chainId:钱包(如 MetaMask)会拒绝与当前链不一致的交易
204
+ hash = (await signer.sendTransaction({ ...tx, gasLimit, chainId: rpc.chainId })).hash;
205
+ }
206
+ catch (err) {
207
+ // ethers 在钱包广播之后还会查一次交易,查询失败(如用户切换了网络)时错误里带着已经发出的哈希:不能报 failed
208
+ const sentHash = err?.info?.sendTransactionHash;
209
+ if (typeof sentHash !== 'string')
210
+ throw err;
211
+ hash = sentHash;
212
+ note = `sent, but the wallet reported: ${failureText(err)}`;
213
+ }
214
+ update(job, outcome, { status: 'sent', hash, gasLimit, error: note });
215
+ inFlight.push({ job, outcome, hash, signed: null });
216
+ }
217
+ else {
218
+ const fee = await fees.get();
219
+ /** 广播结果不确定时的说明(超时、节点都连不上等):交易可能已经进了交易池,不能报 failed(用户会重试、重复付款),按已发出继续跟踪 */
220
+ let uncertain = null;
221
+ const broadcast = async (raw) => {
222
+ const result = await rpc.broadcast(raw);
223
+ if (typeof result === 'object') {
224
+ uncertain = result.uncertain;
225
+ return 'accepted';
226
+ }
227
+ return result;
228
+ };
229
+ const sign = (n, request) => signer.signTransaction({
230
+ ...request,
231
+ ...txFeeFields(fee, request.authorizationList ? 4 : undefined),
232
+ chainId: rpc.chainId,
233
+ nonce: n,
234
+ gasLimit,
235
+ });
236
+ let used = nonce;
237
+ let signed = await sign(used, tx);
238
+ let hash = signedHash(signed);
239
+ if ((await broadcast(signed)) === 'nonce-used') {
240
+ // nonce 被用掉了:可能就是这笔已经上链(节点超时后换节点重发、或重复执行同一批),也可能被钱包在别处发的交易占用。
241
+ // 多查几次回执(节点可能落后),确定这笔没上链才换 nonce 重发;查询出错时不确定,按已发出跟踪,绝不重发
242
+ const state = await minedState(rpc, hash, options);
243
+ if (state === 'unknown') {
244
+ uncertain = 'nonce already used; unable to confirm whether this transaction was mined';
245
+ }
246
+ else if (state === 'absent') {
247
+ rpc.useNonce(address, used);
248
+ used = await rpc.nonce(address);
249
+ tx = await job.build(used);
250
+ signed = await sign(used, tx);
251
+ hash = signedHash(signed);
252
+ if ((await broadcast(signed)) === 'nonce-used') {
253
+ rpc.useNonce(address, used);
254
+ nonce = null; // 下一笔重新取 nonce
255
+ fail('nonce already used by another transaction');
256
+ continue;
257
+ }
258
+ }
259
+ }
260
+ nonce = used + 1;
261
+ rpc.useNonce(address, used);
262
+ authorized = tx.authorizationList?.length ? outcome : null;
263
+ update(job, outcome, { status: 'sent', hash, nonce: used, gasLimit, error: uncertain });
264
+ inFlight.push({ job, outcome, hash, signed });
265
+ }
266
+ const item = inFlight[inFlight.length - 1];
267
+ if (wait) {
268
+ void watch(item);
269
+ }
270
+ }
271
+ catch (err) {
272
+ if (isError(err, 'ACTION_REJECTED')) {
273
+ fail('rejected by user');
274
+ continue;
275
+ }
276
+ fail(failureText(err), { revertData: revertData(err) });
277
+ }
278
+ }
279
+ if (wait) {
280
+ await settle();
281
+ }
282
+ }
283
+ /** 浏览器钱包当前所在的链;问不到时为 null(这时靠交易里的 chainId 让钱包校验) */
284
+ async function walletChainId(signer) {
285
+ const provider = signer.provider;
286
+ if (typeof provider?.send !== 'function')
287
+ return null;
288
+ try {
289
+ return Number(await provider.send('eth_chainId', []));
290
+ }
291
+ catch {
292
+ return null;
293
+ }
294
+ }
295
+ /** 这笔交易有没有上链:多查几次回执(节点可能落后)。查到为 'mined';每次都成功查询但都没有为 'absent';有查询出错为 'unknown' */
296
+ async function minedState(rpc, hash, options) {
297
+ let errors = 0;
298
+ for (let i = 0; i < 5; i++) {
299
+ if (i > 0)
300
+ await sleep(options.pollInterval ?? 2_000, options.signal);
301
+ // 已取消:不再发新交易,也就不需要判断是否换 nonce 重发;没查够几轮也不能断定没上链
302
+ if (options.signal?.aborted)
303
+ return 'unknown';
304
+ try {
305
+ if (await rpc.receipt(hash))
306
+ return 'mined';
307
+ }
308
+ catch {
309
+ errors++;
310
+ }
311
+ }
312
+ return errors ? 'unknown' : 'absent';
313
+ }
314
+ /** 7702 授权交易(type 4)也必须用 1559 费用字段 */
315
+ function txFeeFields(fee, type) {
316
+ if (type === 4) {
317
+ return fee.type === 2
318
+ ? { type: 4, maxFeePerGas: fee.maxFeePerGas, maxPriorityFeePerGas: fee.maxPriorityFeePerGas }
319
+ : { type: 4, maxFeePerGas: fee.gasPrice, maxPriorityFeePerGas: fee.gasPrice };
320
+ }
321
+ return fee.type === 2 ? { type: 2, maxFeePerGas: fee.maxFeePerGas, maxPriorityFeePerGas: fee.maxPriorityFeePerGas } : { type: 0, gasPrice: fee.gasPrice };
322
+ }
323
+ /** 轮询回执直到确认 / 超时 / 取消;等待期间定期重发原交易 */
324
+ async function confirm(rpc, item, options, update) {
325
+ const { timeout = 180_000, pollInterval = 2_000, signal } = options;
326
+ const deadline = Date.now() + timeout;
327
+ let polls = 0;
328
+ while (!signal?.aborted) {
329
+ let receipt = null;
330
+ try {
331
+ receipt = await rpc.receipt(item.hash);
332
+ }
333
+ catch {
334
+ // 节点暂时出错:下次再查
335
+ }
336
+ if (receipt) {
337
+ update(item.job, item.outcome, {
338
+ status: receipt.status === 1 ? 'confirmed' : 'reverted',
339
+ gasUsed: receipt.gasUsed,
340
+ fee: receipt.fee,
341
+ blockNumber: receipt.blockNumber,
342
+ error: receipt.status === 1 ? null : 'execution reverted',
343
+ });
344
+ return;
345
+ }
346
+ if (Date.now() >= deadline) {
347
+ const note = `not confirmed within ${timeout}ms`;
348
+ update(item.job, item.outcome, { status: 'pending', error: item.outcome.error ? `${item.outcome.error}; ${note}` : note });
349
+ return;
350
+ }
351
+ if (item.signed && ++polls % 5 === 0) {
352
+ void rpc.broadcast(item.signed).catch(() => { });
353
+ }
354
+ await sleep(Math.min(pollInterval, Math.max(0, deadline - Date.now())), signal);
355
+ }
356
+ }
357
+ /** 交易结果转成调用结果(字符串 / 数字,可 JSON 序列化) */
358
+ export function toWriteResult(index, from, to, outcome) {
359
+ return {
360
+ index,
361
+ from,
362
+ to,
363
+ status: outcome.status,
364
+ hash: outcome.hash,
365
+ nonce: outcome.nonce,
366
+ gasLimit: outcome.gasLimit?.toString() ?? null,
367
+ gasUsed: outcome.gasUsed?.toString() ?? null,
368
+ fee: outcome.fee?.toString() ?? null,
369
+ blockNumber: outcome.blockNumber,
370
+ error: outcome.error,
371
+ };
372
+ }
373
+ //# sourceMappingURL=send.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/write/send.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { type Authorization, type AuthorizationRequest, type TransactionRequest } from 'ethers';
2
+ /**
3
+ * 发交易的钱包,两种都可以:
4
+ * - 私钥字符串(0x 开头的 32 字节十六进制),内部用 ethers BaseWallet 在本地签名
5
+ * - ethers Signer:Wallet / HDNodeWallet 等能本地签名的(signTransaction),
6
+ * 或浏览器钱包的 JsonRpcSigner(`await new BrowserProvider(window.ethereum).getSigner()`,由钱包签名并发送,每笔需要用户确认)
7
+ */
8
+ export type SignerInput = string | WriteSigner | TronSigner | TronWalletLike;
9
+ /**
10
+ * Tron 浏览器钱包:注入的 tronWeb(`window.tronWeb`,TronLink / OKX 等),或 @tronweb3/tronwallet-adapter 的 adapter。
11
+ * 每笔交易钱包弹一次确认(Tron 钱包不支持一次签多笔)
12
+ */
13
+ export type TronWalletLike = {
14
+ defaultAddress?: {
15
+ base58?: string | boolean;
16
+ };
17
+ trx: {
18
+ sign(transaction: any): Promise<any>;
19
+ };
20
+ } | {
21
+ address: string | null;
22
+ signTransaction(transaction: any): Promise<any>;
23
+ };
24
+ /**
25
+ * Tron 上的自定义签名器:对交易 ID(32 字节摘要,0x 开头)做 secp256k1 签名,返回 65 字节签名(r、s、v)的十六进制。
26
+ * 用于 KMS / 硬件钱包等;Tron 上私钥和 ethers Wallet 也可以直接传
27
+ */
28
+ export interface TronSigner {
29
+ /** T 开头或 0x 格式的地址 */
30
+ address: string;
31
+ signDigest(digest: string): Promise<string>;
32
+ }
33
+ /** 只用到 ethers Signer 的这几个方法 */
34
+ export interface WriteSigner {
35
+ getAddress(): Promise<string>;
36
+ /** 本地签名(Wallet 等)。浏览器钱包不支持,改用 sendTransaction */
37
+ signTransaction?(tx: TransactionRequest): Promise<string>;
38
+ /** 由钱包签名并广播(浏览器钱包),返回交易哈希 */
39
+ sendTransaction?(tx: TransactionRequest): Promise<{
40
+ hash: string;
41
+ }>;
42
+ /** EIP-7702 授权签名(ethers Wallet 支持;'7702' 模式需要) */
43
+ authorize?(auth: AuthorizationRequest): Promise<Authorization>;
44
+ }
45
+ /** 归一化后的钱包 */
46
+ export interface ResolvedSigner {
47
+ address: string;
48
+ signer: WriteSigner;
49
+ /** true:本地签名,自己管 nonce、可以重发;false:交给钱包发送(浏览器钱包) */
50
+ local: boolean;
51
+ }
52
+ export declare function isPrivateKey(value: unknown): value is string;
53
+ /**
54
+ * 把输入归一化成钱包;同一个私钥 / Signer 对象只解析一次(cache 由调用方按批次传入)。
55
+ * 私钥格式不对时抛错,错误信息里不带私钥内容
56
+ */
57
+ export declare function resolveSigner(input: SignerInput, cache?: Map<SignerInput, Promise<ResolvedSigner>>): Promise<ResolvedSigner>;
58
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/write/signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,KAAK,kBAAkB,EAAE,MAAM,QAAQ,CAAA;AAElJ;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,CAAA;AAE5E;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,cAAc,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAAC,GAAG,EAAE;QAAE,IAAI,CAAC,WAAW,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;KAAE,CAAA;CAAE,GACjG;IAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,eAAe,CAAC,WAAW,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;CAAE,CAAA;AAE/E;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CAC5C;AAED,+BAA+B;AAC/B,MAAM,WAAW,WAAW;IAC1B,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;IAC7B,iDAAiD;IACjD,eAAe,CAAC,CAAC,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACzD,6BAA6B;IAC7B,eAAe,CAAC,CAAC,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACnE,kDAAkD;IAClD,SAAS,CAAC,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;CAC/D;AAED,cAAc;AACd,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,WAAW,CAAA;IACnB,mDAAmD;IACnD,KAAK,EAAE,OAAO,CAAA;CACf;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE5D;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,GAAE,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,cAAc,CAAC,CAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAO7I"}
@@ -0,0 +1,41 @@
1
+ import { BaseWallet, JsonRpcSigner, SigningKey, getAddress } from 'ethers';
2
+ const PRIVATE_KEY_RE = /^(0x)?[0-9a-fA-F]{64}$/;
3
+ export function isPrivateKey(value) {
4
+ return typeof value === 'string' && PRIVATE_KEY_RE.test(value);
5
+ }
6
+ /**
7
+ * 把输入归一化成钱包;同一个私钥 / Signer 对象只解析一次(cache 由调用方按批次传入)。
8
+ * 私钥格式不对时抛错,错误信息里不带私钥内容
9
+ */
10
+ export async function resolveSigner(input, cache = new Map()) {
11
+ let resolved = cache.get(input);
12
+ if (!resolved) {
13
+ resolved = toSigner(input);
14
+ cache.set(input, resolved);
15
+ }
16
+ return resolved;
17
+ }
18
+ async function toSigner(input) {
19
+ if (typeof input === 'string') {
20
+ if (!isPrivateKey(input)) {
21
+ throw new Error('Invalid private key: expected 32 bytes of hex');
22
+ }
23
+ // BaseWallet 而不是 Wallet:Wallet 带 JSON keystore 加解密(scrypt / AES),打包体积大很多,这里用不到
24
+ const wallet = new BaseWallet(new SigningKey(input.startsWith('0x') ? input : `0x${input}`));
25
+ return { address: wallet.address, signer: wallet, local: true };
26
+ }
27
+ if (!input || typeof input.getAddress !== 'function') {
28
+ throw new Error('Invalid signer: expected a private key or an ethers Signer');
29
+ }
30
+ return fromEthersSigner(input);
31
+ }
32
+ async function fromEthersSigner(input) {
33
+ const address = getAddress(await input.getAddress());
34
+ // JsonRpcSigner 的 signTransaction 走 eth_signTransaction,浏览器钱包基本都不支持,只能让钱包自己发送
35
+ const local = typeof input.signTransaction === 'function' && !(input instanceof JsonRpcSigner);
36
+ if (!local && typeof input.sendTransaction !== 'function') {
37
+ throw new Error('Signer must implement signTransaction or sendTransaction');
38
+ }
39
+ return { address, signer: input, local };
40
+ }
41
+ //# sourceMappingURL=signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.js","sourceRoot":"","sources":["../../src/write/signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAA0E,MAAM,QAAQ,CAAA;AA+ClJ,MAAM,cAAc,GAAG,wBAAwB,CAAA;AAE/C,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AAChE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAkB,EAAE,QAAmD,IAAI,GAAG,EAAE;IAClH,IAAI,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;QAC1B,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;IAC5B,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,KAAkB;IACxC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAClE,CAAC;QACD,+EAA+E;QAC/E,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAA;QAC5F,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;IACjE,CAAC;IACD,IAAI,CAAC,KAAK,IAAI,OAAQ,KAAqB,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAA;IAC/E,CAAC;IACD,OAAO,gBAAgB,CAAC,KAAoB,CAAC,CAAA;AAC/C,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,KAAkB;IAChD,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC,CAAA;IACpD,8EAA8E;IAC9E,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,eAAe,KAAK,UAAU,IAAI,CAAC,CAAC,KAAK,YAAY,aAAa,CAAC,CAAA;IAC9F,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IAC7E,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;AAC1C,CAAC"}