Skip to content

Commit b3c697e

Browse files
authored
added customGasStation (#644)
1 parent b9cb10f commit b3c697e

File tree

4 files changed

+82
-5
lines changed

4 files changed

+82
-5
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Web3 from "web3";
2+
import {
3+
CustomGasChainId,
4+
TxSpeed,
5+
verifyValidOption,
6+
txSpeeds,
7+
customGasChainIds,
8+
} from "./utils";
9+
10+
type chainMethods = Record<CustomGasChainId, () => Promise<string>>;
11+
12+
export class CustomGasStation {
13+
private chain: CustomGasChainId;
14+
private speed: TxSpeed;
15+
private chainMethods: chainMethods = {
16+
137: this.fetchMaticMainnetGasPrice.bind(this),
17+
};
18+
constructor(chain: number, speed: string) {
19+
this.speed = verifyValidOption(speed, txSpeeds);
20+
this.chain = verifyValidOption(chain, customGasChainIds);
21+
}
22+
23+
async getCustomGasPrice() {
24+
return this.chainMethods[this.chain]();
25+
}
26+
27+
private async fetchMaticMainnetGasPrice() {
28+
const res = await fetch("https://gasstation-mainnet.matic.network/v2");
29+
const jsonRes = await res.json();
30+
const gasPrice = jsonRes[this.speed].maxFee;
31+
const gweiGasPrice = Web3.utils.toWei(gasPrice.toFixed(2), "Gwei");
32+
return gweiGasPrice.toString();
33+
}
34+
}

price_pusher/src/evm.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
HexString,
1818
UnixTimestamp,
1919
} from "@pythnetwork/pyth-common-js";
20+
import { CustomGasStation } from "./custom-gas-station";
2021

2122
export class EvmPriceListener extends ChainPriceListener {
2223
private pythContractFactory: PythContractFactory;
@@ -117,10 +118,14 @@ export class EvmPriceListener extends ChainPriceListener {
117118
}
118119

119120
export class EvmPricePusher implements ChainPricePusher {
121+
private customGasStation?: CustomGasStation;
120122
constructor(
121123
private connection: PriceServiceConnection,
122-
private pythContract: Contract
123-
) {}
124+
private pythContract: Contract,
125+
customGasStation?: CustomGasStation
126+
) {
127+
this.customGasStation = customGasStation;
128+
}
124129
// The pubTimes are passed here to use the values that triggered the push.
125130
// This is an optimization to avoid getting a newer value (as an update comes)
126131
// and will help multiple price pushers to have consistent behaviour.
@@ -145,19 +150,20 @@ export class EvmPricePusher implements ChainPricePusher {
145150
"Pushing ",
146151
priceIdsWith0x.map((priceIdWith0x) => `${priceIdWith0x}`)
147152
);
148-
149153
const updateFee = await this.pythContract.methods
150154
.getUpdateFee(priceFeedUpdateData)
151155
.call();
152156
console.log(`Update fee: ${updateFee}`);
153157

158+
const gasPrice = await this.customGasStation?.getCustomGasPrice();
159+
154160
this.pythContract.methods
155161
.updatePriceFeedsIfNecessary(
156162
priceFeedUpdateData,
157163
priceIdsWith0x,
158164
pubTimesToPush
159165
)
160-
.send({ value: updateFee })
166+
.send({ value: updateFee, gasPrice })
161167
.on("transactionHash", (hash: string) => {
162168
console.log(`Successful. Tx hash: ${hash}`);
163169
})

price_pusher/src/index.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { readPriceConfigFile } from "./price-config";
1212
import { PriceServiceConnection } from "@pythnetwork/pyth-common-js";
1313
import { InjectivePriceListener, InjectivePricePusher } from "./injective";
1414
import { ChainPricePusher, IPriceListener } from "./interface";
15+
import { CustomGasStation } from "./custom-gas-station";
1516

1617
const argv = yargs(hideBin(process.argv))
1718
.option("network", {
@@ -69,6 +70,18 @@ const argv = yargs(hideBin(process.argv))
6970
required: false,
7071
default: 5,
7172
})
73+
.option("custom-gas-station", {
74+
description:
75+
"If using a custom gas station, chainId of custom gas station to use",
76+
type: "number",
77+
required: false,
78+
})
79+
.option("tx-speed", {
80+
description:
81+
"txSpeed for custom gas station. choose between 'slow'|'standard'|'fast'",
82+
type: "string",
83+
required: false,
84+
})
7285
.help()
7386
.alias("help", "h")
7487
.parserConfiguration({
@@ -139,6 +152,7 @@ function getNetworkPriceListener(network: string): IPriceListener {
139152
}
140153

141154
function getNetworkPricePusher(network: string): ChainPricePusher {
155+
const gasStation = getCustomGasStation(argv.customGasStation, argv.txSpeed);
142156
switch (network) {
143157
case "evm": {
144158
const pythContractFactory = new PythContractFactory(
@@ -148,7 +162,8 @@ function getNetworkPricePusher(network: string): ChainPricePusher {
148162
);
149163
return new EvmPricePusher(
150164
priceServiceConnection,
151-
pythContractFactory.createPythContractWithPayer()
165+
pythContractFactory.createPythContractWithPayer(),
166+
gasStation
152167
);
153168
}
154169
case "injective":
@@ -163,6 +178,12 @@ function getNetworkPricePusher(network: string): ChainPricePusher {
163178
}
164179
}
165180

181+
function getCustomGasStation(customGasStation?: number, txSpeed?: string) {
182+
if (customGasStation && txSpeed) {
183+
return new CustomGasStation(customGasStation, txSpeed);
184+
}
185+
}
186+
166187
start({
167188
sourcePriceListener: pythPriceListener,
168189
targetPriceListener: getNetworkPriceListener(argv.network),

price_pusher/src/utils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { HexString } from "@pythnetwork/pyth-common-js";
22

33
export type PctNumber = number;
44
export type DurationInSeconds = number;
5+
export const txSpeeds = ["slow", "standard", "fast"] as const;
6+
export type TxSpeed = typeof txSpeeds[number];
7+
export const customGasChainIds = [137] as const;
8+
export type CustomGasChainId = typeof customGasChainIds[number];
59

610
export async function sleep(ms: number): Promise<void> {
711
return new Promise((resolve) => setTimeout(resolve, ms));
@@ -31,3 +35,15 @@ export function isWsEndpoint(endpoint: string): boolean {
3135

3236
return false;
3337
}
38+
39+
export function verifyValidOption<
40+
options extends Readonly<Array<any>>,
41+
validOption extends options[number]
42+
>(option: any, validOptions: options) {
43+
if (validOptions.includes(option)) {
44+
return option as validOption;
45+
}
46+
const errorString =
47+
option + " is not a valid option. Please choose between " + validOptions;
48+
throw new Error(errorString);
49+
}

0 commit comments

Comments
 (0)