Skip to content

Commit 5c3be6a

Browse files
authored
refactor(apps/price_pusher): Use viem instead of web3 for evm pusher (#1829)
Web3 library is not very widely used anymore due to its complex and magical internal design. Some users were reporting issues like strange timeouts or unsupported RPC calls via web3 (and the deprecated HDWalletProvider by truffle that we use). This change refactors the code to use Viem. The experience with Viem is nice: it has strong types and good utilities. The error handling is also very well designed. The downside is that it has a steep learning curve to get it right. This change refactors the code based on the PR reviews to make it simpler as well. Lastly the version is bumped as a major release because the behaviour and logs have changed and it might affect production environments. It also signals the users to test it out properly before using it which is good because all the failure cases might not be handled.
1 parent 7fddbd6 commit 5c3be6a

File tree

9 files changed

+1064
-270
lines changed

9 files changed

+1064
-270
lines changed

apps/price_pusher/package.json

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pythnetwork/price-pusher",
3-
"version": "7.1.0",
3+
"version": "8.0.0-alpha",
44
"description": "Pyth Price Pusher",
55
"homepage": "https://pyth.network",
66
"main": "lib/index.js",
@@ -64,16 +64,13 @@
6464
"@pythnetwork/pyth-sui-js": "workspace:*",
6565
"@pythnetwork/solana-utils": "workspace:*",
6666
"@solana/web3.js": "^1.93.0",
67-
"@truffle/hdwallet-provider": "^2.1.3",
6867
"@types/pino": "^7.0.5",
6968
"aptos": "^1.8.5",
7069
"jito-ts": "^3.0.1",
7170
"joi": "^17.6.0",
7271
"near-api-js": "^3.0.2",
7372
"pino": "^9.2.0",
74-
"web3": "^1.8.1",
75-
"web3-core": "^1.8.1",
76-
"web3-eth-contract": "^1.8.1",
73+
"viem": "^2.19.4",
7774
"yaml": "^2.1.1",
7875
"yargs": "^17.5.1"
7976
}

apps/price_pusher/src/evm/command.ts

+18-12
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import * as options from "../options";
55
import { readPriceConfigFile } from "../price-config";
66
import { PythPriceListener } from "../pyth-price-listener";
77
import { Controller } from "../controller";
8-
import { EvmPriceListener, EvmPricePusher, PythContractFactory } from "./evm";
8+
import { EvmPriceListener, EvmPricePusher } from "./evm";
99
import { getCustomGasStation } from "./custom-gas-station";
1010
import pino from "pino";
11+
import { createClient } from "./super-wallet";
12+
import { createPythContract } from "./pyth-contract";
13+
import { isWsEndpoint } from "../utils";
1114

1215
export default {
1316
command: "evm",
@@ -77,7 +80,7 @@ export default {
7780
...options.priceServiceConnectionLogLevel,
7881
...options.controllerLogLevel,
7982
},
80-
handler: function (argv: any) {
83+
handler: async function (argv: any) {
8184
// FIXME: type checks for this
8285
const {
8386
endpoint,
@@ -121,20 +124,22 @@ export default {
121124
logger.child({ module: "PythPriceListener" })
122125
);
123126

124-
const pythContractFactory = new PythContractFactory(
125-
endpoint,
126-
mnemonic,
127-
pythContractAddress
128-
);
127+
const client = await createClient(endpoint, mnemonic);
128+
const pythContract = createPythContract(client, pythContractAddress);
129+
129130
logger.info(
130-
`Pushing updates from wallet address: ${pythContractFactory
131-
.createWeb3PayerProvider()
132-
.getAddress()}`
131+
`Pushing updates from wallet address: ${client.account.address}`
133132
);
134133

134+
// It is possible to watch the events in the non-ws endpoints, either by getFilter
135+
// or by getLogs, but it is very expensive and our polling mechanism does it
136+
// in a more efficient way. So we only do it with ws endpoints.
137+
const watchEvents = isWsEndpoint(endpoint);
138+
135139
const evmListener = new EvmPriceListener(
136-
pythContractFactory,
140+
pythContract,
137141
priceItems,
142+
watchEvents,
138143
logger.child({ module: "EvmPriceListener" }),
139144
{
140145
pollingFrequency,
@@ -148,7 +153,8 @@ export default {
148153
);
149154
const evmPusher = new EvmPricePusher(
150155
priceServiceConnection,
151-
pythContractFactory,
156+
client,
157+
pythContract,
152158
logger.child({ module: "EvmPricePusher" }),
153159
overrideGasPriceMultiplier,
154160
overrideGasPriceMultiplierCap,

apps/price_pusher/src/evm/custom-gas-station.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import Web3 from "web3";
21
import {
32
CustomGasChainId,
43
TxSpeed,
@@ -7,8 +6,9 @@ import {
76
customGasChainIds,
87
} from "../utils";
98
import { Logger } from "pino";
9+
import { parseGwei } from "viem";
1010

11-
type chainMethods = Record<CustomGasChainId, () => Promise<string | undefined>>;
11+
type chainMethods = Record<CustomGasChainId, () => Promise<bigint | undefined>>;
1212

1313
export class CustomGasStation {
1414
private chain: CustomGasChainId;
@@ -29,11 +29,10 @@ export class CustomGasStation {
2929

3030
private async fetchMaticMainnetGasPrice() {
3131
try {
32-
const res = await fetch("https://gasstation-mainnet.matic.network/v2");
32+
const res = await fetch("https://gasstation.polygon.technology/v2");
3333
const jsonRes = await res.json();
3434
const gasPrice = jsonRes[this.speed].maxFee;
35-
const gweiGasPrice = Web3.utils.toWei(gasPrice.toFixed(2), "Gwei");
36-
return gweiGasPrice.toString();
35+
return parseGwei(gasPrice.toFixed(2));
3736
} catch (err) {
3837
this.logger.error(
3938
err,

0 commit comments

Comments
 (0)