@prb/effect-evm 1.0.0-beta.7 → 1.0.0-beta.8
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 +3 -0
- package/dist/gas/estimator.d.ts.map +1 -1
- package/dist/gas/estimator.js +61 -45
- package/dist/gas/estimator.js.map +1 -1
- package/dist/gas/service.d.ts.map +1 -1
- package/dist/gas/service.js +14 -2
- package/dist/gas/service.js.map +1 -1
- package/dist/gas/service.test.integration.js +24 -0
- package/dist/gas/service.test.integration.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
[](https://effect.website)
|
|
5
5
|
[](https://viem.sh)
|
|
6
6
|
|
|
7
|
+
> [!WARNING] This is experimental, beta software. It is provided "as is" without warranty of any kind, express or
|
|
8
|
+
> implied.
|
|
9
|
+
|
|
7
10
|
Type-safe, composable EVM abstractions for [Effect](https://effect.website), built on [viem](https://viem.sh).
|
|
8
11
|
|
|
9
12
|
## 📦 Installation
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"estimator.d.ts","sourceRoot":"","sources":["../../src/gas/estimator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"estimator.d.ts","sourceRoot":"","sources":["../../src/gas/estimator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAEhE,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAwEF,eAAO,MAAM,mBAAmB,GAC9B,qBAAqB,wBAAwB,EAC7C,SAAS,MAAM,KACd,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,wBAAwB,GAAG,mBAAmB,CAapE,CAAC;AAEL,eAAO,MAAM,sBAAsB,GACjC,qBAAqB,wBAAwB,EAC7C,SAAS,MAAM,KACd,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,wBAAwB,GAAG,mBAAmB,CAuE1F,CAAC"}
|
package/dist/gas/estimator.js
CHANGED
|
@@ -12,6 +12,52 @@ const SPEED_CONFIDENCE = {
|
|
|
12
12
|
slow: 70,
|
|
13
13
|
standard: 85,
|
|
14
14
|
};
|
|
15
|
+
function isBaseFeeMissing(baseFee) {
|
|
16
|
+
return baseFee === null || baseFee === undefined;
|
|
17
|
+
}
|
|
18
|
+
function getLegacyFeeEstimates(client, chainId) {
|
|
19
|
+
return Effect.gen(function* () {
|
|
20
|
+
const gasPrice = yield* Effect.tryPromise({
|
|
21
|
+
catch: (cause) => new GasPriceUnavailableError({
|
|
22
|
+
cause,
|
|
23
|
+
chainId,
|
|
24
|
+
message: `Failed to get gas price: ${String(cause)}`,
|
|
25
|
+
}),
|
|
26
|
+
try: () => client.getGasPrice(),
|
|
27
|
+
});
|
|
28
|
+
const estimates = {
|
|
29
|
+
fast: {
|
|
30
|
+
confidence: SPEED_CONFIDENCE.fast,
|
|
31
|
+
estimatedBaseFee: 0n,
|
|
32
|
+
gasPrice: (gasPrice * 125n) / 100n,
|
|
33
|
+
maxFeePerGas: (gasPrice * 125n) / 100n,
|
|
34
|
+
maxPriorityFeePerGas: 0n,
|
|
35
|
+
},
|
|
36
|
+
instant: {
|
|
37
|
+
confidence: SPEED_CONFIDENCE.instant,
|
|
38
|
+
estimatedBaseFee: 0n,
|
|
39
|
+
gasPrice: (gasPrice * 150n) / 100n,
|
|
40
|
+
maxFeePerGas: (gasPrice * 150n) / 100n,
|
|
41
|
+
maxPriorityFeePerGas: 0n,
|
|
42
|
+
},
|
|
43
|
+
slow: {
|
|
44
|
+
confidence: SPEED_CONFIDENCE.slow,
|
|
45
|
+
estimatedBaseFee: 0n,
|
|
46
|
+
gasPrice: (gasPrice * 90n) / 100n,
|
|
47
|
+
maxFeePerGas: (gasPrice * 90n) / 100n,
|
|
48
|
+
maxPriorityFeePerGas: 0n,
|
|
49
|
+
},
|
|
50
|
+
standard: {
|
|
51
|
+
confidence: SPEED_CONFIDENCE.standard,
|
|
52
|
+
estimatedBaseFee: 0n,
|
|
53
|
+
gasPrice,
|
|
54
|
+
maxFeePerGas: gasPrice,
|
|
55
|
+
maxPriorityFeePerGas: 0n,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
return estimates;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
15
61
|
export const supportsEip1559Impl = (publicClientService, chainId) => Effect.gen(function* () {
|
|
16
62
|
const client = yield* publicClientService.get(chainId);
|
|
17
63
|
const block = yield* Effect.tryPromise({
|
|
@@ -46,12 +92,20 @@ export const getAllFeeEstimatesImpl = (publicClientService, chainId) => Effect.g
|
|
|
46
92
|
try: () => client.estimateMaxPriorityFeePerGas(),
|
|
47
93
|
}),
|
|
48
94
|
], { concurrency: 2 });
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
95
|
+
let baseFee = block.baseFeePerGas;
|
|
96
|
+
if (isBaseFeeMissing(baseFee)) {
|
|
97
|
+
const latestBlock = yield* Effect.tryPromise({
|
|
98
|
+
catch: (cause) => new GasPriceUnavailableError({
|
|
99
|
+
cause,
|
|
100
|
+
chainId,
|
|
101
|
+
message: `Failed to get latest block: ${String(cause)}`,
|
|
102
|
+
}),
|
|
103
|
+
try: () => client.getBlock({ blockTag: "latest" }),
|
|
104
|
+
});
|
|
105
|
+
baseFee = latestBlock.baseFeePerGas;
|
|
106
|
+
}
|
|
107
|
+
if (isBaseFeeMissing(baseFee)) {
|
|
108
|
+
return yield* getLegacyFeeEstimates(client, chainId);
|
|
55
109
|
}
|
|
56
110
|
const makeEstimate = (speed) => {
|
|
57
111
|
const priority = maxPriorityFeePerGas + SPEED_ADJUSTMENTS[speed];
|
|
@@ -70,44 +124,6 @@ export const getAllFeeEstimatesImpl = (publicClientService, chainId) => Effect.g
|
|
|
70
124
|
};
|
|
71
125
|
return estimates;
|
|
72
126
|
}
|
|
73
|
-
|
|
74
|
-
catch: (cause) => new GasPriceUnavailableError({
|
|
75
|
-
cause,
|
|
76
|
-
chainId,
|
|
77
|
-
message: `Failed to get gas price: ${String(cause)}`,
|
|
78
|
-
}),
|
|
79
|
-
try: () => client.getGasPrice(),
|
|
80
|
-
});
|
|
81
|
-
const estimates = {
|
|
82
|
-
fast: {
|
|
83
|
-
confidence: SPEED_CONFIDENCE.fast,
|
|
84
|
-
estimatedBaseFee: 0n,
|
|
85
|
-
gasPrice: (gasPrice * 125n) / 100n,
|
|
86
|
-
maxFeePerGas: (gasPrice * 125n) / 100n,
|
|
87
|
-
maxPriorityFeePerGas: 0n,
|
|
88
|
-
},
|
|
89
|
-
instant: {
|
|
90
|
-
confidence: SPEED_CONFIDENCE.instant,
|
|
91
|
-
estimatedBaseFee: 0n,
|
|
92
|
-
gasPrice: (gasPrice * 150n) / 100n,
|
|
93
|
-
maxFeePerGas: (gasPrice * 150n) / 100n,
|
|
94
|
-
maxPriorityFeePerGas: 0n,
|
|
95
|
-
},
|
|
96
|
-
slow: {
|
|
97
|
-
confidence: SPEED_CONFIDENCE.slow,
|
|
98
|
-
estimatedBaseFee: 0n,
|
|
99
|
-
gasPrice: (gasPrice * 90n) / 100n,
|
|
100
|
-
maxFeePerGas: (gasPrice * 90n) / 100n,
|
|
101
|
-
maxPriorityFeePerGas: 0n,
|
|
102
|
-
},
|
|
103
|
-
standard: {
|
|
104
|
-
confidence: SPEED_CONFIDENCE.standard,
|
|
105
|
-
estimatedBaseFee: 0n,
|
|
106
|
-
gasPrice,
|
|
107
|
-
maxFeePerGas: gasPrice,
|
|
108
|
-
maxPriorityFeePerGas: 0n,
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
return estimates;
|
|
127
|
+
return yield* getLegacyFeeEstimates(client, chainId);
|
|
112
128
|
});
|
|
113
129
|
//# sourceMappingURL=estimator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"estimator.js","sourceRoot":"","sources":["../../src/gas/estimator.ts"],"names":[],"mappings":"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","sourcesContent":["import { Effect } from \"effect\";\nimport type { ClientNotFoundError } from \"@/src/core/errors/index.js\";\nimport type { PublicClientServiceShape } from \"@/src/core/index.js\";\nimport { GasPriceUnavailableError } from \"@/src/gas/errors.js\";\n\nexport type GasSpeed = \"slow\" | \"standard\" | \"fast\" | \"instant\";\n\nexport type FeeEstimate = {\n confidence: number; // 0-100\n estimatedBaseFee: bigint;\n gasPrice?: bigint;\n maxFeePerGas: bigint;\n maxPriorityFeePerGas: bigint;\n};\n\n// Priority fee adjustments in gwei\nconst SPEED_ADJUSTMENTS: Record<GasSpeed, bigint> = {\n fast: 2_500_000_000n, // 2.5 gwei\n instant: 5_000_000_000n, // 5 gwei\n slow: 1_000_000_000n, // 1 gwei\n standard: 1_500_000_000n, // 1.5 gwei\n};\n\n// Confidence levels for each speed tier\nconst SPEED_CONFIDENCE: Record<GasSpeed, number> = {\n fast: 95,\n instant: 99,\n slow: 70,\n standard: 85,\n};\n\nexport const supportsEip1559Impl = (\n publicClientService: PublicClientServiceShape,\n chainId: number\n): Effect.Effect<boolean, GasPriceUnavailableError | ClientNotFoundError> =>\n Effect.gen(function* () {\n const client = yield* publicClientService.get(chainId);\n const block = yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId,\n message: `Failed to check EIP-1559 support: ${String(cause)}`,\n }),\n try: () => client.getBlock({ blockTag: \"latest\" }),\n });\n return block.baseFeePerGas !== null && block.baseFeePerGas !== undefined;\n });\n\nexport const getAllFeeEstimatesImpl = (\n publicClientService: PublicClientServiceShape,\n chainId: number\n): Effect.Effect<Record<GasSpeed, FeeEstimate>, GasPriceUnavailableError | ClientNotFoundError> =>\n Effect.gen(function* () {\n const client = yield* publicClientService.get(chainId);\n const supportsEip1559 = yield* supportsEip1559Impl(publicClientService, chainId);\n\n if (supportsEip1559) {\n // EIP-1559 fee estimation\n const [block, maxPriorityFeePerGas] = yield* Effect.all(\n [\n Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId,\n message: `Failed to get pending block: ${String(cause)}`,\n }),\n try: () => client.getBlock({ blockTag: \"pending\" }),\n }),\n Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId,\n message: `Failed to estimate max priority fee: ${String(cause)}`,\n }),\n try: () => client.estimateMaxPriorityFeePerGas(),\n }),\n ],\n { concurrency: 2 }\n );\n\n const baseFee = block.baseFeePerGas;\n if (!baseFee) {\n return yield* Effect.fail(\n new GasPriceUnavailableError({\n chainId,\n message: \"Base fee not available despite EIP-1559 support\",\n })\n );\n }\n\n // Build estimates for each speed tier\n const makeEstimate = (speed: GasSpeed): FeeEstimate => {\n const priority = maxPriorityFeePerGas + SPEED_ADJUSTMENTS[speed];\n return {\n confidence: SPEED_CONFIDENCE[speed],\n estimatedBaseFee: baseFee,\n maxFeePerGas: baseFee * 2n + priority,\n maxPriorityFeePerGas: priority,\n };\n };\n\n const estimates: Record<GasSpeed, FeeEstimate> = {\n fast: makeEstimate(\"fast\"),\n instant: makeEstimate(\"instant\"),\n slow: makeEstimate(\"slow\"),\n standard: makeEstimate(\"standard\"),\n };\n\n return estimates;\n }\n\n // Legacy gas price estimation\n const gasPrice = yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId,\n message: `Failed to get gas price: ${String(cause)}`,\n }),\n try: () => client.getGasPrice(),\n });\n\n // Create estimates using gas price multipliers\n const estimates: Record<GasSpeed, FeeEstimate> = {\n fast: {\n confidence: SPEED_CONFIDENCE.fast,\n estimatedBaseFee: 0n,\n gasPrice: (gasPrice * 125n) / 100n, // 1.25x\n maxFeePerGas: (gasPrice * 125n) / 100n,\n maxPriorityFeePerGas: 0n,\n },\n instant: {\n confidence: SPEED_CONFIDENCE.instant,\n estimatedBaseFee: 0n,\n gasPrice: (gasPrice * 150n) / 100n, // 1.5x\n maxFeePerGas: (gasPrice * 150n) / 100n,\n maxPriorityFeePerGas: 0n,\n },\n slow: {\n confidence: SPEED_CONFIDENCE.slow,\n estimatedBaseFee: 0n,\n gasPrice: (gasPrice * 90n) / 100n, // 0.9x\n maxFeePerGas: (gasPrice * 90n) / 100n,\n maxPriorityFeePerGas: 0n,\n },\n standard: {\n confidence: SPEED_CONFIDENCE.standard,\n estimatedBaseFee: 0n,\n gasPrice,\n maxFeePerGas: gasPrice,\n maxPriorityFeePerGas: 0n,\n },\n };\n\n return estimates;\n });\n"]}
|
|
1
|
+
{"version":3,"file":"estimator.js","sourceRoot":"","sources":["../../src/gas/estimator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAa/D,MAAM,iBAAiB,GAA6B;IAClD,IAAI,EAAE,WAAc;IACpB,OAAO,EAAE,WAAc;IACvB,IAAI,EAAE,WAAc;IACpB,QAAQ,EAAE,WAAc;CACzB,CAAC;AAGF,MAAM,gBAAgB,GAA6B;IACjD,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;IACR,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,SAAS,gBAAgB,CAAC,OAAkC;IAC1D,OAAO,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,CAAC;AACnD,CAAC;AAED,SAAS,qBAAqB,CAC5B,MAAoB,EACpB,OAAe;IAEf,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;YACxC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,wBAAwB,CAAC;gBAC3B,KAAK;gBACL,OAAO;gBACP,OAAO,EAAE,4BAA4B,MAAM,CAAC,KAAK,CAAC,EAAE;aACrD,CAAC;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE;SAChC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAkC;YAC/C,IAAI,EAAE;gBACJ,UAAU,EAAE,gBAAgB,CAAC,IAAI;gBACjC,gBAAgB,EAAE,EAAE;gBACpB,QAAQ,EAAE,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,IAAI;gBAClC,YAAY,EAAE,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,IAAI;gBACtC,oBAAoB,EAAE,EAAE;aACzB;YACD,OAAO,EAAE;gBACP,UAAU,EAAE,gBAAgB,CAAC,OAAO;gBACpC,gBAAgB,EAAE,EAAE;gBACpB,QAAQ,EAAE,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,IAAI;gBAClC,YAAY,EAAE,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,IAAI;gBACtC,oBAAoB,EAAE,EAAE;aACzB;YACD,IAAI,EAAE;gBACJ,UAAU,EAAE,gBAAgB,CAAC,IAAI;gBACjC,gBAAgB,EAAE,EAAE;gBACpB,QAAQ,EAAE,CAAC,QAAQ,GAAG,GAAG,CAAC,GAAG,IAAI;gBACjC,YAAY,EAAE,CAAC,QAAQ,GAAG,GAAG,CAAC,GAAG,IAAI;gBACrC,oBAAoB,EAAE,EAAE;aACzB;YACD,QAAQ,EAAE;gBACR,UAAU,EAAE,gBAAgB,CAAC,QAAQ;gBACrC,gBAAgB,EAAE,EAAE;gBACpB,QAAQ;gBACR,YAAY,EAAE,QAAQ;gBACtB,oBAAoB,EAAE,EAAE;aACzB;SACF,CAAC;QAEF,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,mBAA6C,EAC7C,OAAe,EACyD,EAAE,CAC1E,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;QACrC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,wBAAwB,CAAC;YAC3B,KAAK;YACL,OAAO;YACP,OAAO,EAAE,qCAAqC,MAAM,CAAC,KAAK,CAAC,EAAE;SAC9D,CAAC;QACJ,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;KACnD,CAAC,CAAC;IACH,OAAO,KAAK,CAAC,aAAa,KAAK,IAAI,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,CAAC;AAC3E,CAAC,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,mBAA6C,EAC7C,OAAe,EAC+E,EAAE,CAChG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC;IAEjF,IAAI,eAAe,EAAE,CAAC;QAEpB,MAAM,CAAC,KAAK,EAAE,oBAAoB,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CACrD;YACE,MAAM,CAAC,UAAU,CAAC;gBAChB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,wBAAwB,CAAC;oBAC3B,KAAK;oBACL,OAAO;oBACP,OAAO,EAAE,gCAAgC,MAAM,CAAC,KAAK,CAAC,EAAE;iBACzD,CAAC;gBACJ,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;aACpD,CAAC;YACF,MAAM,CAAC,UAAU,CAAC;gBAChB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,wBAAwB,CAAC;oBAC3B,KAAK;oBACL,OAAO;oBACP,OAAO,EAAE,wCAAwC,MAAM,CAAC,KAAK,CAAC,EAAE;iBACjE,CAAC;gBACJ,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,4BAA4B,EAAE;aACjD,CAAC;SACH,EACD,EAAE,WAAW,EAAE,CAAC,EAAE,CACnB,CAAC;QAEF,IAAI,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC;QAClC,IAAI,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBAC3C,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,wBAAwB,CAAC;oBAC3B,KAAK;oBACL,OAAO;oBACP,OAAO,EAAE,+BAA+B,MAAM,CAAC,KAAK,CAAC,EAAE;iBACxD,CAAC;gBACJ,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;aACnD,CAAC,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,aAAa,CAAC;QACtC,CAAC;QAED,IAAI,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC,CAAC,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC;QAGD,MAAM,YAAY,GAAG,CAAC,KAAe,EAAe,EAAE;YACpD,MAAM,QAAQ,GAAG,oBAAoB,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACjE,OAAO;gBACL,UAAU,EAAE,gBAAgB,CAAC,KAAK,CAAC;gBACnC,gBAAgB,EAAE,OAAO;gBACzB,YAAY,EAAE,OAAO,GAAG,EAAE,GAAG,QAAQ;gBACrC,oBAAoB,EAAE,QAAQ;aAC/B,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,SAAS,GAAkC;YAC/C,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC;YAC1B,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC;YAChC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC;YAC1B,QAAQ,EAAE,YAAY,CAAC,UAAU,CAAC;SACnC,CAAC;QAEF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,CAAC,CAAC,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC","sourcesContent":["import { Effect } from \"effect\";\nimport type { PublicClient } from \"viem\";\nimport type { ClientNotFoundError } from \"@/src/core/errors/index.js\";\nimport type { PublicClientServiceShape } from \"@/src/core/index.js\";\nimport { GasPriceUnavailableError } from \"@/src/gas/errors.js\";\n\nexport type GasSpeed = \"slow\" | \"standard\" | \"fast\" | \"instant\";\n\nexport type FeeEstimate = {\n confidence: number; // 0-100\n estimatedBaseFee: bigint;\n gasPrice?: bigint;\n maxFeePerGas: bigint;\n maxPriorityFeePerGas: bigint;\n};\n\n// Priority fee adjustments in gwei\nconst SPEED_ADJUSTMENTS: Record<GasSpeed, bigint> = {\n fast: 2_500_000_000n, // 2.5 gwei\n instant: 5_000_000_000n, // 5 gwei\n slow: 1_000_000_000n, // 1 gwei\n standard: 1_500_000_000n, // 1.5 gwei\n};\n\n// Confidence levels for each speed tier\nconst SPEED_CONFIDENCE: Record<GasSpeed, number> = {\n fast: 95,\n instant: 99,\n slow: 70,\n standard: 85,\n};\n\nfunction isBaseFeeMissing(baseFee: bigint | null | undefined): baseFee is null | undefined {\n return baseFee === null || baseFee === undefined;\n}\n\nfunction getLegacyFeeEstimates(\n client: PublicClient,\n chainId: number\n): Effect.Effect<Record<GasSpeed, FeeEstimate>, GasPriceUnavailableError> {\n return Effect.gen(function* () {\n const gasPrice = yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId,\n message: `Failed to get gas price: ${String(cause)}`,\n }),\n try: () => client.getGasPrice(),\n });\n\n const estimates: Record<GasSpeed, FeeEstimate> = {\n fast: {\n confidence: SPEED_CONFIDENCE.fast,\n estimatedBaseFee: 0n,\n gasPrice: (gasPrice * 125n) / 100n, // 1.25x\n maxFeePerGas: (gasPrice * 125n) / 100n,\n maxPriorityFeePerGas: 0n,\n },\n instant: {\n confidence: SPEED_CONFIDENCE.instant,\n estimatedBaseFee: 0n,\n gasPrice: (gasPrice * 150n) / 100n, // 1.5x\n maxFeePerGas: (gasPrice * 150n) / 100n,\n maxPriorityFeePerGas: 0n,\n },\n slow: {\n confidence: SPEED_CONFIDENCE.slow,\n estimatedBaseFee: 0n,\n gasPrice: (gasPrice * 90n) / 100n, // 0.9x\n maxFeePerGas: (gasPrice * 90n) / 100n,\n maxPriorityFeePerGas: 0n,\n },\n standard: {\n confidence: SPEED_CONFIDENCE.standard,\n estimatedBaseFee: 0n,\n gasPrice,\n maxFeePerGas: gasPrice,\n maxPriorityFeePerGas: 0n,\n },\n };\n\n return estimates;\n });\n}\n\nexport const supportsEip1559Impl = (\n publicClientService: PublicClientServiceShape,\n chainId: number\n): Effect.Effect<boolean, GasPriceUnavailableError | ClientNotFoundError> =>\n Effect.gen(function* () {\n const client = yield* publicClientService.get(chainId);\n const block = yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId,\n message: `Failed to check EIP-1559 support: ${String(cause)}`,\n }),\n try: () => client.getBlock({ blockTag: \"latest\" }),\n });\n return block.baseFeePerGas !== null && block.baseFeePerGas !== undefined;\n });\n\nexport const getAllFeeEstimatesImpl = (\n publicClientService: PublicClientServiceShape,\n chainId: number\n): Effect.Effect<Record<GasSpeed, FeeEstimate>, GasPriceUnavailableError | ClientNotFoundError> =>\n Effect.gen(function* () {\n const client = yield* publicClientService.get(chainId);\n const supportsEip1559 = yield* supportsEip1559Impl(publicClientService, chainId);\n\n if (supportsEip1559) {\n // EIP-1559 fee estimation\n const [block, maxPriorityFeePerGas] = yield* Effect.all(\n [\n Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId,\n message: `Failed to get pending block: ${String(cause)}`,\n }),\n try: () => client.getBlock({ blockTag: \"pending\" }),\n }),\n Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId,\n message: `Failed to estimate max priority fee: ${String(cause)}`,\n }),\n try: () => client.estimateMaxPriorityFeePerGas(),\n }),\n ],\n { concurrency: 2 }\n );\n\n let baseFee = block.baseFeePerGas;\n if (isBaseFeeMissing(baseFee)) {\n const latestBlock = yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId,\n message: `Failed to get latest block: ${String(cause)}`,\n }),\n try: () => client.getBlock({ blockTag: \"latest\" }),\n });\n baseFee = latestBlock.baseFeePerGas;\n }\n\n if (isBaseFeeMissing(baseFee)) {\n return yield* getLegacyFeeEstimates(client, chainId);\n }\n\n // Build estimates for each speed tier\n const makeEstimate = (speed: GasSpeed): FeeEstimate => {\n const priority = maxPriorityFeePerGas + SPEED_ADJUSTMENTS[speed];\n return {\n confidence: SPEED_CONFIDENCE[speed],\n estimatedBaseFee: baseFee,\n maxFeePerGas: baseFee * 2n + priority,\n maxPriorityFeePerGas: priority,\n };\n };\n\n const estimates: Record<GasSpeed, FeeEstimate> = {\n fast: makeEstimate(\"fast\"),\n instant: makeEstimate(\"instant\"),\n slow: makeEstimate(\"slow\"),\n standard: makeEstimate(\"standard\"),\n };\n\n return estimates;\n }\n\n return yield* getLegacyFeeEstimates(client, chainId);\n });\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/gas/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAIpE,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE;QAC9B,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,QAAQ,CAAC;KAClB,KAAK,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,wBAAwB,GAAG,mBAAmB,CAAC,CAAC;IAEjF,QAAQ,CAAC,kBAAkB,EAAE,CAAC,MAAM,EAAE;QACpC,OAAO,EAAE,MAAM,CAAC;KACjB,KAAK,MAAM,CAAC,MAAM,CACjB,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,EAC7B,wBAAwB,GAAG,mBAAmB,CAC/C,CAAC;IAEF,QAAQ,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE;QAC5B,OAAO,EAAE,MAAM,CAAC;KACjB,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,GAAG,mBAAmB,CAAC,CAAC;IAE5E,QAAQ,CAAC,iBAAiB,EAAE,CAAC,MAAM,EAAE;QACnC,OAAO,EAAE,MAAM,CAAC;KACjB,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,GAAG,mBAAmB,CAAC,CAAC;IAE5E,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE;QAC7B,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,GAAG,CAAC;QACX,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,EAAE,EAAE,OAAO,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,GAAG,mBAAmB,CAAC,CAAC;IAE5E,QAAQ,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE;QACjC,OAAO,EAAE,MAAM,CAAC;KACjB,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,wBAAwB,GAAG,mBAAmB,CAAC,CAAC;CAC9E,CAAC;;AAEF,qBAAa,UAAW,SAAQ,eAA4D;CAAG;AAE/F,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/gas/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAIpE,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE;QAC9B,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,QAAQ,CAAC;KAClB,KAAK,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,wBAAwB,GAAG,mBAAmB,CAAC,CAAC;IAEjF,QAAQ,CAAC,kBAAkB,EAAE,CAAC,MAAM,EAAE;QACpC,OAAO,EAAE,MAAM,CAAC;KACjB,KAAK,MAAM,CAAC,MAAM,CACjB,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,EAC7B,wBAAwB,GAAG,mBAAmB,CAC/C,CAAC;IAEF,QAAQ,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE;QAC5B,OAAO,EAAE,MAAM,CAAC;KACjB,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,GAAG,mBAAmB,CAAC,CAAC;IAE5E,QAAQ,CAAC,iBAAiB,EAAE,CAAC,MAAM,EAAE;QACnC,OAAO,EAAE,MAAM,CAAC;KACjB,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,GAAG,mBAAmB,CAAC,CAAC;IAE5E,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE;QAC7B,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,GAAG,CAAC;QACX,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,EAAE,EAAE,OAAO,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,GAAG,mBAAmB,CAAC,CAAC;IAE5E,QAAQ,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE;QACjC,OAAO,EAAE,MAAM,CAAC;KACjB,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,wBAAwB,GAAG,mBAAmB,CAAC,CAAC;CAC9E,CAAC;;AAEF,qBAAa,UAAW,SAAQ,eAA4D;CAAG;AAE/F,eAAO,MAAM,cAAc,qDA6I1B,CAAC"}
|
package/dist/gas/service.js
CHANGED
|
@@ -56,13 +56,25 @@ export const GasServiceLive = Layer.effect(GasService, Effect.gen(function* () {
|
|
|
56
56
|
}),
|
|
57
57
|
try: () => client.getBlock({ blockTag: "pending" }),
|
|
58
58
|
});
|
|
59
|
-
|
|
59
|
+
let baseFee = block.baseFeePerGas;
|
|
60
|
+
if (baseFee === null || baseFee === undefined) {
|
|
61
|
+
const latestBlock = yield* Effect.tryPromise({
|
|
62
|
+
catch: (cause) => new GasPriceUnavailableError({
|
|
63
|
+
cause,
|
|
64
|
+
chainId: params.chainId,
|
|
65
|
+
message: `Failed to get latest block: ${String(cause)}`,
|
|
66
|
+
}),
|
|
67
|
+
try: () => client.getBlock({ blockTag: "latest" }),
|
|
68
|
+
});
|
|
69
|
+
baseFee = latestBlock.baseFeePerGas;
|
|
70
|
+
}
|
|
71
|
+
if (baseFee === null || baseFee === undefined) {
|
|
60
72
|
return yield* Effect.fail(new GasPriceUnavailableError({
|
|
61
73
|
chainId: params.chainId,
|
|
62
74
|
message: "Base fee not available (chain may not support EIP-1559)",
|
|
63
75
|
}));
|
|
64
76
|
}
|
|
65
|
-
return
|
|
77
|
+
return baseFee;
|
|
66
78
|
}).pipe(Effect.withSpan(SpanNames.GAS_GET_BASE_FEE, {
|
|
67
79
|
attributes: {
|
|
68
80
|
chainId: params.chainId,
|
package/dist/gas/service.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/gas/service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Context, Effect, Layer } from \"effect\";\nimport type { Address, Hex } from \"viem\";\nimport type { ClientNotFoundError } from \"@/src/core/errors/index.js\";\nimport { PublicClientService } from \"@/src/core/index.js\";\nimport { GasPriceUnavailableError } from \"@/src/gas/errors.js\";\nimport type { FeeEstimate, GasSpeed } from \"@/src/gas/estimator.js\";\nimport { getAllFeeEstimatesImpl, supportsEip1559Impl } from \"@/src/gas/estimator.js\";\nimport { SpanNames } from \"@/src/telemetry/index.js\";\n\nexport type GasServiceShape = {\n readonly estimateFees: (params: {\n chainId: number;\n speed?: GasSpeed;\n }) => Effect.Effect<FeeEstimate, GasPriceUnavailableError | ClientNotFoundError>;\n\n readonly getAllFeeEstimates: (params: {\n chainId: number;\n }) => Effect.Effect<\n Record<GasSpeed, FeeEstimate>,\n GasPriceUnavailableError | ClientNotFoundError\n >;\n\n readonly getBaseFee: (params: {\n chainId: number;\n }) => Effect.Effect<bigint, GasPriceUnavailableError | ClientNotFoundError>;\n\n readonly getMaxPriorityFee: (params: {\n chainId: number;\n }) => Effect.Effect<bigint, GasPriceUnavailableError | ClientNotFoundError>;\n\n readonly estimateGas: (params: {\n chainId: number;\n data?: Hex;\n from?: Address;\n to: Address;\n value?: bigint;\n }) => Effect.Effect<bigint, GasPriceUnavailableError | ClientNotFoundError>;\n\n readonly supportsEip1559: (params: {\n chainId: number;\n }) => Effect.Effect<boolean, GasPriceUnavailableError | ClientNotFoundError>;\n};\n\nexport class GasService extends Context.Tag(\"ew3/GasService\")<GasService, GasServiceShape>() {}\n\nexport const GasServiceLive = Layer.effect(\n GasService,\n Effect.gen(function* () {\n const publicClientService = yield* PublicClientService;\n\n return GasService.of({\n estimateFees: (params: { chainId: number; speed?: GasSpeed }) =>\n Effect.gen(function* () {\n const allEstimates = yield* getAllFeeEstimatesImpl(publicClientService, params.chainId);\n const speed = params.speed ?? \"standard\";\n return allEstimates[speed];\n }).pipe(\n Effect.withSpan(SpanNames.GAS_ESTIMATE_FEES, {\n attributes: {\n chainId: params.chainId,\n speed: params.speed ?? \"standard\",\n },\n })\n ),\n\n estimateGas: (params: {\n chainId: number;\n data?: Hex;\n from?: Address;\n to: Address;\n value?: bigint;\n }) =>\n Effect.gen(function* () {\n const client = yield* publicClientService.get(params.chainId);\n return yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId: params.chainId,\n message: `Failed to estimate gas: ${String(cause)}`,\n }),\n try: () =>\n client.estimateGas({\n ...(params.from ? { account: params.from } : {}),\n data: params.data,\n to: params.to,\n value: params.value,\n }),\n });\n }).pipe(\n Effect.withSpan(SpanNames.GAS_ESTIMATE_GAS, {\n attributes: {\n chainId: params.chainId,\n to: params.to,\n },\n })\n ),\n\n getAllFeeEstimates: (params: { chainId: number }) =>\n Effect.gen(function* () {\n return yield* getAllFeeEstimatesImpl(publicClientService, params.chainId);\n }).pipe(\n Effect.withSpan(SpanNames.GAS_GET_ALL_ESTIMATES, {\n attributes: {\n chainId: params.chainId,\n },\n })\n ),\n\n getBaseFee: (params: { chainId: number }) =>\n Effect.gen(function* () {\n const client = yield* publicClientService.get(params.chainId);\n const block = yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId: params.chainId,\n message: `Failed to get base fee: ${String(cause)}`,\n }),\n try: () => client.getBlock({ blockTag: \"pending\" }),\n });\n\n if (!block.baseFeePerGas) {\n return yield* Effect.fail(\n new GasPriceUnavailableError({\n chainId: params.chainId,\n message: \"Base fee not available (chain may not support EIP-1559)\",\n })\n );\n }\n\n return block.baseFeePerGas;\n }).pipe(\n Effect.withSpan(SpanNames.GAS_GET_BASE_FEE, {\n attributes: {\n chainId: params.chainId,\n },\n })\n ),\n\n getMaxPriorityFee: (params: { chainId: number }) =>\n Effect.gen(function* () {\n const client = yield* publicClientService.get(params.chainId);\n return yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId: params.chainId,\n message: `Failed to get max priority fee: ${String(cause)}`,\n }),\n try: () => client.estimateMaxPriorityFeePerGas(),\n });\n }).pipe(\n Effect.withSpan(SpanNames.GAS_GET_MAX_PRIORITY_FEE, {\n attributes: {\n chainId: params.chainId,\n },\n })\n ),\n\n supportsEip1559: (params: { chainId: number }) =>\n Effect.gen(function* () {\n return yield* supportsEip1559Impl(publicClientService, params.chainId);\n }).pipe(\n Effect.withSpan(SpanNames.GAS_SUPPORTS_EIP1559, {\n attributes: {\n chainId: params.chainId,\n },\n })\n ),\n });\n })\n);\n"]}
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/gas/service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Context, Effect, Layer } from \"effect\";\nimport type { Address, Hex } from \"viem\";\nimport type { ClientNotFoundError } from \"@/src/core/errors/index.js\";\nimport { PublicClientService } from \"@/src/core/index.js\";\nimport { GasPriceUnavailableError } from \"@/src/gas/errors.js\";\nimport type { FeeEstimate, GasSpeed } from \"@/src/gas/estimator.js\";\nimport { getAllFeeEstimatesImpl, supportsEip1559Impl } from \"@/src/gas/estimator.js\";\nimport { SpanNames } from \"@/src/telemetry/index.js\";\n\nexport type GasServiceShape = {\n readonly estimateFees: (params: {\n chainId: number;\n speed?: GasSpeed;\n }) => Effect.Effect<FeeEstimate, GasPriceUnavailableError | ClientNotFoundError>;\n\n readonly getAllFeeEstimates: (params: {\n chainId: number;\n }) => Effect.Effect<\n Record<GasSpeed, FeeEstimate>,\n GasPriceUnavailableError | ClientNotFoundError\n >;\n\n readonly getBaseFee: (params: {\n chainId: number;\n }) => Effect.Effect<bigint, GasPriceUnavailableError | ClientNotFoundError>;\n\n readonly getMaxPriorityFee: (params: {\n chainId: number;\n }) => Effect.Effect<bigint, GasPriceUnavailableError | ClientNotFoundError>;\n\n readonly estimateGas: (params: {\n chainId: number;\n data?: Hex;\n from?: Address;\n to: Address;\n value?: bigint;\n }) => Effect.Effect<bigint, GasPriceUnavailableError | ClientNotFoundError>;\n\n readonly supportsEip1559: (params: {\n chainId: number;\n }) => Effect.Effect<boolean, GasPriceUnavailableError | ClientNotFoundError>;\n};\n\nexport class GasService extends Context.Tag(\"ew3/GasService\")<GasService, GasServiceShape>() {}\n\nexport const GasServiceLive = Layer.effect(\n GasService,\n Effect.gen(function* () {\n const publicClientService = yield* PublicClientService;\n\n return GasService.of({\n estimateFees: (params: { chainId: number; speed?: GasSpeed }) =>\n Effect.gen(function* () {\n const allEstimates = yield* getAllFeeEstimatesImpl(publicClientService, params.chainId);\n const speed = params.speed ?? \"standard\";\n return allEstimates[speed];\n }).pipe(\n Effect.withSpan(SpanNames.GAS_ESTIMATE_FEES, {\n attributes: {\n chainId: params.chainId,\n speed: params.speed ?? \"standard\",\n },\n })\n ),\n\n estimateGas: (params: {\n chainId: number;\n data?: Hex;\n from?: Address;\n to: Address;\n value?: bigint;\n }) =>\n Effect.gen(function* () {\n const client = yield* publicClientService.get(params.chainId);\n return yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId: params.chainId,\n message: `Failed to estimate gas: ${String(cause)}`,\n }),\n try: () =>\n client.estimateGas({\n ...(params.from ? { account: params.from } : {}),\n data: params.data,\n to: params.to,\n value: params.value,\n }),\n });\n }).pipe(\n Effect.withSpan(SpanNames.GAS_ESTIMATE_GAS, {\n attributes: {\n chainId: params.chainId,\n to: params.to,\n },\n })\n ),\n\n getAllFeeEstimates: (params: { chainId: number }) =>\n Effect.gen(function* () {\n return yield* getAllFeeEstimatesImpl(publicClientService, params.chainId);\n }).pipe(\n Effect.withSpan(SpanNames.GAS_GET_ALL_ESTIMATES, {\n attributes: {\n chainId: params.chainId,\n },\n })\n ),\n\n getBaseFee: (params: { chainId: number }) =>\n Effect.gen(function* () {\n const client = yield* publicClientService.get(params.chainId);\n const block = yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId: params.chainId,\n message: `Failed to get base fee: ${String(cause)}`,\n }),\n try: () => client.getBlock({ blockTag: \"pending\" }),\n });\n\n let baseFee = block.baseFeePerGas;\n if (baseFee === null || baseFee === undefined) {\n const latestBlock = yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId: params.chainId,\n message: `Failed to get latest block: ${String(cause)}`,\n }),\n try: () => client.getBlock({ blockTag: \"latest\" }),\n });\n baseFee = latestBlock.baseFeePerGas;\n }\n\n if (baseFee === null || baseFee === undefined) {\n return yield* Effect.fail(\n new GasPriceUnavailableError({\n chainId: params.chainId,\n message: \"Base fee not available (chain may not support EIP-1559)\",\n })\n );\n }\n\n return baseFee;\n }).pipe(\n Effect.withSpan(SpanNames.GAS_GET_BASE_FEE, {\n attributes: {\n chainId: params.chainId,\n },\n })\n ),\n\n getMaxPriorityFee: (params: { chainId: number }) =>\n Effect.gen(function* () {\n const client = yield* publicClientService.get(params.chainId);\n return yield* Effect.tryPromise({\n catch: (cause) =>\n new GasPriceUnavailableError({\n cause,\n chainId: params.chainId,\n message: `Failed to get max priority fee: ${String(cause)}`,\n }),\n try: () => client.estimateMaxPriorityFeePerGas(),\n });\n }).pipe(\n Effect.withSpan(SpanNames.GAS_GET_MAX_PRIORITY_FEE, {\n attributes: {\n chainId: params.chainId,\n },\n })\n ),\n\n supportsEip1559: (params: { chainId: number }) =>\n Effect.gen(function* () {\n return yield* supportsEip1559Impl(publicClientService, params.chainId);\n }).pipe(\n Effect.withSpan(SpanNames.GAS_SUPPORTS_EIP1559, {\n attributes: {\n chainId: params.chainId,\n },\n })\n ),\n });\n })\n);\n"]}
|
|
@@ -40,6 +40,20 @@ describe("GasService (Live)", () => {
|
|
|
40
40
|
getGasPrice: async () => 45000000000n,
|
|
41
41
|
},
|
|
42
42
|
});
|
|
43
|
+
const pendingBaseFeeMissingLayer = makeEffectEvmTestLayer({
|
|
44
|
+
publicClient: {
|
|
45
|
+
estimateGas: async () => MIN_TX_GAS,
|
|
46
|
+
estimateMaxPriorityFeePerGas: async () => 1500000000n,
|
|
47
|
+
getBlock: (params) => {
|
|
48
|
+
const p = params;
|
|
49
|
+
if (p?.blockTag === "pending") {
|
|
50
|
+
return Promise.resolve({ ...DEFAULT_BLOCK, baseFeePerGas: null });
|
|
51
|
+
}
|
|
52
|
+
return Promise.resolve(DEFAULT_BLOCK);
|
|
53
|
+
},
|
|
54
|
+
getGasPrice: async () => 45000000000n,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
43
57
|
describe("EIP-1559 estimation", () => {
|
|
44
58
|
it.effect("uses estimateMaxPriorityFeePerGas as baseline", () => Effect.gen(function* () {
|
|
45
59
|
const service = yield* GasService;
|
|
@@ -61,6 +75,16 @@ describe("GasService (Live)", () => {
|
|
|
61
75
|
});
|
|
62
76
|
expect(supports).toBe(true);
|
|
63
77
|
}).pipe(Effect.provide(eip1559Layer)));
|
|
78
|
+
it.effect("falls back to latest base fee when pending is missing", () => Effect.gen(function* () {
|
|
79
|
+
const service = yield* GasService;
|
|
80
|
+
const estimates = yield* service.getAllFeeEstimates({
|
|
81
|
+
chainId: mainnet.id,
|
|
82
|
+
});
|
|
83
|
+
const expectedPriority = 1500000000n + 1500000000n;
|
|
84
|
+
const baseFee = 30000000000n;
|
|
85
|
+
expect(estimates.standard.estimatedBaseFee).toBe(baseFee);
|
|
86
|
+
expect(estimates.standard.maxFeePerGas).toBe(baseFee * 2n + expectedPriority);
|
|
87
|
+
}).pipe(Effect.provide(pendingBaseFeeMissingLayer)));
|
|
64
88
|
});
|
|
65
89
|
describe("Legacy estimation", () => {
|
|
66
90
|
const legacyLayer = makeEffectEvmTestLayer({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.test.integration.js","sourceRoot":"","sources":["../../src/gas/service.test.integration.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"@effect/vitest\";\nimport { Cause, Effect, Exit } from \"effect\";\nimport type { Address, Block } from \"viem\";\nimport { mainnet } from \"viem/chains\";\nimport { MIN_TX_GAS } from \"@/src/constants/index.js\";\nimport { ClientNotFoundError } from \"@/src/core/index.js\";\nimport { GasPriceUnavailableError, GasService } from \"@/src/gas/index.js\";\nimport { makeEffectEvmTestLayer } from \"@/src/testing-kit/index.js\";\n\nconst DEFAULT_BLOCK: Block = {\n baseFeePerGas: 30000000000n,\n blobGasUsed: 0n,\n difficulty: 0n,\n excessBlobGas: 0n,\n extraData: \"0x\",\n gasLimit: 30000000n,\n gasUsed: 12000000n,\n hash: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n logsBloom: \"0x00\",\n miner: \"0x0000000000000000000000000000000000000000\",\n mixHash: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n nonce: \"0x0000000000000000\",\n number: 1000n,\n parentHash: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n receiptsRoot: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n sealFields: [],\n sha3Uncles: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n size: 1024n,\n stateRoot: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n timestamp: 1700000000n,\n totalDifficulty: 0n,\n transactions: [],\n transactionsRoot: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n uncles: [],\n};\n\ndescribe(\"GasService (Live)\", () => {\n const eip1559Layer = makeEffectEvmTestLayer({\n publicClient: {\n estimateGas: async () => MIN_TX_GAS,\n estimateMaxPriorityFeePerGas: async () => 1500000000n, // 1.5 gwei baseline\n getBlock: async () => DEFAULT_BLOCK,\n getGasPrice: async () => 45000000000n,\n },\n });\n\n describe(\"EIP-1559 estimation\", () => {\n it.effect(\"uses estimateMaxPriorityFeePerGas as baseline\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const estimates = yield* service.getAllFeeEstimates({\n chainId: mainnet.id,\n });\n\n expect(estimates.slow.maxPriorityFeePerGas).toBe(2500000000n);\n expect(estimates.standard.maxPriorityFeePerGas).toBe(3000000000n);\n expect(estimates.fast.maxPriorityFeePerGas).toBe(4000000000n);\n expect(estimates.instant.maxPriorityFeePerGas).toBe(6500000000n);\n\n expect(estimates.instant.maxPriorityFeePerGas).toBeGreaterThan(\n estimates.fast.maxPriorityFeePerGas\n );\n expect(estimates.fast.maxPriorityFeePerGas).toBeGreaterThan(\n estimates.standard.maxPriorityFeePerGas\n );\n expect(estimates.standard.maxPriorityFeePerGas).toBeGreaterThan(\n estimates.slow.maxPriorityFeePerGas\n );\n }).pipe(Effect.provide(eip1559Layer))\n );\n\n it.effect(\"supportsEip1559 returns true\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const supports = yield* service.supportsEip1559({\n chainId: mainnet.id,\n });\n expect(supports).toBe(true);\n }).pipe(Effect.provide(eip1559Layer))\n );\n });\n\n describe(\"Legacy estimation\", () => {\n const legacyLayer = makeEffectEvmTestLayer({\n publicClient: {\n getBlock: async () => ({ ...DEFAULT_BLOCK, baseFeePerGas: null }),\n getGasPrice: async () => 1000n,\n },\n });\n\n it.effect(\"falls back to gasPrice multipliers\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const estimates = yield* service.getAllFeeEstimates({\n chainId: mainnet.id,\n });\n\n expect(estimates.standard.gasPrice).toBe(1000n);\n expect(estimates.slow.gasPrice).toBe(900n);\n expect(estimates.fast.gasPrice).toBe(1250n);\n expect(estimates.instant.gasPrice).toBe(1500n);\n expect(estimates.standard.maxPriorityFeePerGas).toBe(0n);\n }).pipe(Effect.provide(legacyLayer))\n );\n\n it.effect(\"supportsEip1559 returns false\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const supports = yield* service.supportsEip1559({\n chainId: mainnet.id,\n });\n expect(supports).toBe(false);\n }).pipe(Effect.provide(legacyLayer))\n );\n\n it.effect(\"getBaseFee fails with GasPriceUnavailableError\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const exit = yield* service.getBaseFee({ chainId: mainnet.id }).pipe(Effect.exit);\n\n expect(Exit.isFailure(exit)).toBe(true);\n if (Exit.isFailure(exit)) {\n const error = Cause.failureOption(exit.cause);\n expect(error._tag).toBe(\"Some\");\n if (error._tag === \"Some\") {\n expect(error.value).toBeInstanceOf(GasPriceUnavailableError);\n }\n }\n }).pipe(Effect.provide(legacyLayer))\n );\n });\n\n describe(\"estimateGas\", () => {\n it.effect(\"returns gas estimate\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const gas = yield* service.estimateGas({\n chainId: mainnet.id,\n to: \"0x1234567890123456789012345678901234567890\" as Address,\n });\n\n expect(gas).toBe(MIN_TX_GAS);\n }).pipe(Effect.provide(eip1559Layer))\n );\n });\n\n describe(\"unsupported chainId\", () => {\n it.effect(\"fails with ClientNotFoundError\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const exit = yield* service.getAllFeeEstimates({ chainId: 999 }).pipe(Effect.exit);\n\n expect(Exit.isFailure(exit)).toBe(true);\n if (Exit.isFailure(exit)) {\n const error = Cause.failureOption(exit.cause);\n expect(error._tag).toBe(\"Some\");\n if (error._tag === \"Some\") {\n expect(error.value).toBeInstanceOf(ClientNotFoundError);\n }\n }\n }).pipe(Effect.provide(eip1559Layer))\n );\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"service.test.integration.js","sourceRoot":"","sources":["../../src/gas/service.test.integration.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"@effect/vitest\";\nimport { Cause, Effect, Exit } from \"effect\";\nimport type { Address, Block } from \"viem\";\nimport { mainnet } from \"viem/chains\";\nimport { MIN_TX_GAS } from \"@/src/constants/index.js\";\nimport { ClientNotFoundError } from \"@/src/core/index.js\";\nimport { GasPriceUnavailableError, GasService } from \"@/src/gas/index.js\";\nimport { makeEffectEvmTestLayer } from \"@/src/testing-kit/index.js\";\n\nconst DEFAULT_BLOCK: Block = {\n baseFeePerGas: 30000000000n,\n blobGasUsed: 0n,\n difficulty: 0n,\n excessBlobGas: 0n,\n extraData: \"0x\",\n gasLimit: 30000000n,\n gasUsed: 12000000n,\n hash: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n logsBloom: \"0x00\",\n miner: \"0x0000000000000000000000000000000000000000\",\n mixHash: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n nonce: \"0x0000000000000000\",\n number: 1000n,\n parentHash: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n receiptsRoot: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n sealFields: [],\n sha3Uncles: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n size: 1024n,\n stateRoot: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n timestamp: 1700000000n,\n totalDifficulty: 0n,\n transactions: [],\n transactionsRoot: \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\",\n uncles: [],\n};\n\ndescribe(\"GasService (Live)\", () => {\n const eip1559Layer = makeEffectEvmTestLayer({\n publicClient: {\n estimateGas: async () => MIN_TX_GAS,\n estimateMaxPriorityFeePerGas: async () => 1500000000n, // 1.5 gwei baseline\n getBlock: async () => DEFAULT_BLOCK,\n getGasPrice: async () => 45000000000n,\n },\n });\n const pendingBaseFeeMissingLayer = makeEffectEvmTestLayer({\n publicClient: {\n estimateGas: async () => MIN_TX_GAS,\n estimateMaxPriorityFeePerGas: async () => 1500000000n, // 1.5 gwei baseline\n getBlock: (params: unknown) => {\n const p = params as { blockTag?: \"latest\" | \"pending\" } | undefined;\n if (p?.blockTag === \"pending\") {\n return Promise.resolve({ ...DEFAULT_BLOCK, baseFeePerGas: null });\n }\n return Promise.resolve(DEFAULT_BLOCK);\n },\n getGasPrice: async () => 45000000000n,\n },\n });\n\n describe(\"EIP-1559 estimation\", () => {\n it.effect(\"uses estimateMaxPriorityFeePerGas as baseline\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const estimates = yield* service.getAllFeeEstimates({\n chainId: mainnet.id,\n });\n\n expect(estimates.slow.maxPriorityFeePerGas).toBe(2500000000n);\n expect(estimates.standard.maxPriorityFeePerGas).toBe(3000000000n);\n expect(estimates.fast.maxPriorityFeePerGas).toBe(4000000000n);\n expect(estimates.instant.maxPriorityFeePerGas).toBe(6500000000n);\n\n expect(estimates.instant.maxPriorityFeePerGas).toBeGreaterThan(\n estimates.fast.maxPriorityFeePerGas\n );\n expect(estimates.fast.maxPriorityFeePerGas).toBeGreaterThan(\n estimates.standard.maxPriorityFeePerGas\n );\n expect(estimates.standard.maxPriorityFeePerGas).toBeGreaterThan(\n estimates.slow.maxPriorityFeePerGas\n );\n }).pipe(Effect.provide(eip1559Layer))\n );\n\n it.effect(\"supportsEip1559 returns true\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const supports = yield* service.supportsEip1559({\n chainId: mainnet.id,\n });\n expect(supports).toBe(true);\n }).pipe(Effect.provide(eip1559Layer))\n );\n\n it.effect(\"falls back to latest base fee when pending is missing\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const estimates = yield* service.getAllFeeEstimates({\n chainId: mainnet.id,\n });\n\n const expectedPriority = 1500000000n + 1500000000n;\n const baseFee = 30000000000n; // DEFAULT_BLOCK.baseFeePerGas\n expect(estimates.standard.estimatedBaseFee).toBe(baseFee);\n expect(estimates.standard.maxFeePerGas).toBe(baseFee * 2n + expectedPriority);\n }).pipe(Effect.provide(pendingBaseFeeMissingLayer))\n );\n });\n\n describe(\"Legacy estimation\", () => {\n const legacyLayer = makeEffectEvmTestLayer({\n publicClient: {\n getBlock: async () => ({ ...DEFAULT_BLOCK, baseFeePerGas: null }),\n getGasPrice: async () => 1000n,\n },\n });\n\n it.effect(\"falls back to gasPrice multipliers\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const estimates = yield* service.getAllFeeEstimates({\n chainId: mainnet.id,\n });\n\n expect(estimates.standard.gasPrice).toBe(1000n);\n expect(estimates.slow.gasPrice).toBe(900n);\n expect(estimates.fast.gasPrice).toBe(1250n);\n expect(estimates.instant.gasPrice).toBe(1500n);\n expect(estimates.standard.maxPriorityFeePerGas).toBe(0n);\n }).pipe(Effect.provide(legacyLayer))\n );\n\n it.effect(\"supportsEip1559 returns false\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const supports = yield* service.supportsEip1559({\n chainId: mainnet.id,\n });\n expect(supports).toBe(false);\n }).pipe(Effect.provide(legacyLayer))\n );\n\n it.effect(\"getBaseFee fails with GasPriceUnavailableError\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const exit = yield* service.getBaseFee({ chainId: mainnet.id }).pipe(Effect.exit);\n\n expect(Exit.isFailure(exit)).toBe(true);\n if (Exit.isFailure(exit)) {\n const error = Cause.failureOption(exit.cause);\n expect(error._tag).toBe(\"Some\");\n if (error._tag === \"Some\") {\n expect(error.value).toBeInstanceOf(GasPriceUnavailableError);\n }\n }\n }).pipe(Effect.provide(legacyLayer))\n );\n });\n\n describe(\"estimateGas\", () => {\n it.effect(\"returns gas estimate\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const gas = yield* service.estimateGas({\n chainId: mainnet.id,\n to: \"0x1234567890123456789012345678901234567890\" as Address,\n });\n\n expect(gas).toBe(MIN_TX_GAS);\n }).pipe(Effect.provide(eip1559Layer))\n );\n });\n\n describe(\"unsupported chainId\", () => {\n it.effect(\"fails with ClientNotFoundError\", () =>\n Effect.gen(function* () {\n const service = yield* GasService;\n const exit = yield* service.getAllFeeEstimates({ chainId: 999 }).pipe(Effect.exit);\n\n expect(Exit.isFailure(exit)).toBe(true);\n if (Exit.isFailure(exit)) {\n const error = Cause.failureOption(exit.cause);\n expect(error._tag).toBe(\"Some\");\n if (error._tag === \"Some\") {\n expect(error.value).toBeInstanceOf(ClientNotFoundError);\n }\n }\n }).pipe(Effect.provide(eip1559Layer))\n );\n });\n});\n"]}
|