@pythnetwork/price-pusher 10.3.1 → 11.3.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.
- package/README.md +28 -7
- package/dist/aptos/aptos.cjs +7 -7
- package/dist/aptos/aptos.d.ts +1 -1
- package/dist/aptos/balance-tracker.cjs +7 -7
- package/dist/aptos/balance-tracker.d.ts +1 -1
- package/dist/aptos/command.cjs +20 -17
- package/dist/aptos/command.d.ts +3 -2
- package/dist/common.cjs +0 -3
- package/dist/common.d.ts +0 -4
- package/dist/controller.cjs +12 -7
- package/dist/controller.d.ts +1 -1
- package/dist/evm/balance-tracker.cjs +4 -4
- package/dist/evm/balance-tracker.d.ts +2 -2
- package/dist/evm/command.cjs +89 -40
- package/dist/evm/command.d.ts +12 -6
- package/dist/evm/evm.cjs +162 -58
- package/dist/evm/evm.d.ts +13 -8
- package/dist/evm/gas-price.cjs +114 -0
- package/dist/evm/gas-price.d.ts +33 -0
- package/dist/evm/pyth-contract.cjs +2 -2
- package/dist/evm/super-wallet.cjs +4 -4
- package/dist/evm/super-wallet.d.ts +1 -1
- package/dist/fuel/command.cjs +17 -14
- package/dist/fuel/command.d.ts +3 -2
- package/dist/fuel/fuel.d.ts +2 -2
- package/dist/injective/command.cjs +26 -23
- package/dist/injective/command.d.ts +5 -4
- package/dist/injective/injective.cjs +11 -11
- package/dist/injective/injective.d.ts +2 -3
- package/dist/interface.d.ts +1 -1
- package/dist/metrics.cjs +57 -35
- package/dist/metrics.d.ts +10 -5
- package/dist/near/command.cjs +22 -19
- package/dist/near/command.d.ts +5 -4
- package/dist/near/near.cjs +17 -16
- package/dist/near/near.d.ts +1 -1
- package/dist/options.cjs +36 -26
- package/dist/options.d.ts +3 -0
- package/dist/price-config.cjs +15 -15
- package/dist/pyth-price-listener.cjs +5 -3
- package/dist/pyth-price-listener.d.ts +2 -3
- package/dist/solana/balance-tracker.cjs +5 -5
- package/dist/solana/balance-tracker.d.ts +2 -2
- package/dist/solana/command.cjs +75 -60
- package/dist/solana/command.d.ts +13 -10
- package/dist/solana/solana.cjs +5 -5
- package/dist/solana/solana.d.ts +4 -4
- package/dist/sui/balance-tracker.cjs +6 -6
- package/dist/sui/balance-tracker.d.ts +5 -5
- package/dist/sui/command.cjs +84 -47
- package/dist/sui/command.d.ts +10 -6
- package/dist/sui/sui.cjs +159 -106
- package/dist/sui/sui.d.ts +31 -14
- package/dist/ton/command.cjs +17 -14
- package/dist/ton/command.d.ts +3 -2
- package/dist/ton/ton.d.ts +2 -3
- package/dist/utils.d.ts +1 -2
- package/package.json +127 -131
package/README.md
CHANGED
|
@@ -104,8 +104,19 @@ pnpm run start evm --endpoint wss://example-rpc.com \
|
|
|
104
104
|
[--override-gas-price-multiplier 1.1] \
|
|
105
105
|
[--override-gas-price-multiplier-cap 5] \
|
|
106
106
|
[--gas-limit 1000000] \
|
|
107
|
+
[--gas-pricing-strategy eip1559] \
|
|
108
|
+
[--base-fee-multiplier 1.2] \
|
|
109
|
+
[--priority-fee-multiplier 1] \
|
|
107
110
|
[--gas-price 160000000]
|
|
108
111
|
|
|
112
|
+
# The EVM pusher prices transactions with the `eip1559` strategy by default. It
|
|
113
|
+
# computes `maxFeePerGas` from the chain base fee (padded by `--base-fee-multiplier`
|
|
114
|
+
# to leave headroom for the base fee growing between blocks) plus an estimated
|
|
115
|
+
# priority fee (scaled by `--priority-fee-multiplier`). This avoids the deprecated
|
|
116
|
+
# `eth_gasPrice` RPC, which some RPCs mishandle. For chains that do not support
|
|
117
|
+
# EIP-1559 transactions, pass `--gas-pricing-strategy legacy`, which falls back to
|
|
118
|
+
# the single `gasPrice` model and where `--gas-price` / `--custom-gas-station` apply.
|
|
119
|
+
|
|
109
120
|
# For Injective
|
|
110
121
|
pnpm run start injective --grpc-endpoint https://grpc-endpoint.com \
|
|
111
122
|
--pyth-contract-address inj1z60tg0... --price-service-endpoint "https://example-hermes-rpc.com" \
|
|
@@ -129,19 +140,27 @@ pnpm run start aptos --endpoint https://fullnode.testnet.aptoslabs.com/v1 \
|
|
|
129
140
|
|
|
130
141
|
# For Sui
|
|
131
142
|
pnpm run start sui \
|
|
132
|
-
--endpoint https://
|
|
133
|
-
--
|
|
134
|
-
--pyth-
|
|
135
|
-
--
|
|
136
|
-
--wormhole-
|
|
137
|
-
--
|
|
143
|
+
--endpoint https://fullnode.testnet.sui.io:443 \
|
|
144
|
+
--network testnet \
|
|
145
|
+
--pyth-package-id 0xabf837e98c26087cba0883c0a7a28326b1fa3c5e1e2c5abdb486f9e8f594c837 \
|
|
146
|
+
--pyth-state-id 0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c \
|
|
147
|
+
--wormhole-package-id 0x21473617f3565d704aa67be73ea41243e9e34a42d434c31f8182c67ba01ccf49 \
|
|
148
|
+
--wormhole-state-id 0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790 \
|
|
149
|
+
--price-feed-to-price-info-object-table-id 0xcb858b77d8068c6c8c0d8a4ddfba95053268e4a31f8ecc49adccc4ec1570d3a7 \
|
|
138
150
|
--price-service-endpoint https://example-hermes-rpc.com \
|
|
139
151
|
--mnemonic-file ./mnemonic \
|
|
140
152
|
--price-config-file ./price-config.beta.sample.yaml \
|
|
153
|
+
[--endpoint-type json-rpc] \
|
|
141
154
|
[--pushing-frequency 10] \
|
|
142
155
|
[--polling-frequency 5] \
|
|
143
156
|
[--num-gas-objects 30]
|
|
144
157
|
|
|
158
|
+
# `--endpoint-type` selects the Sui RPC transport: `json-rpc` (default) or `grpc`.
|
|
159
|
+
# Sui Foundation is deprecating JSON-RPC (public endpoints off July 2026, removed
|
|
160
|
+
# from full nodes by mid-Oct 2026), so set `--endpoint-type grpc` and point
|
|
161
|
+
# `--endpoint` at a gRPC-web base URL to migrate. `grpc` uses @mysten/sui's
|
|
162
|
+
# experimental SuiGrpcClient.
|
|
163
|
+
|
|
145
164
|
# For Near
|
|
146
165
|
pnpm run start near \
|
|
147
166
|
--node-url https://rpc.testnet.near.org \
|
|
@@ -182,7 +201,9 @@ pnpm run start solana \
|
|
|
182
201
|
|
|
183
202
|
|
|
184
203
|
|
|
185
|
-
# Or, run the price pusher docker image instead of building from the source
|
|
204
|
+
# Or, run the price pusher docker image instead of building from the source.
|
|
205
|
+
# Note: There is no :latest tag. Find available version tags at:
|
|
206
|
+
# https://gallery.ecr.aws/pyth-network/xc-price-pusher
|
|
186
207
|
docker run public.ecr.aws/pyth-network/xc-price-pusher:v<version> -- npm run start -- <above-arguments>
|
|
187
208
|
```
|
|
188
209
|
|
package/dist/aptos/aptos.cjs
CHANGED
|
@@ -36,18 +36,18 @@ class AptosPriceListener extends _interface.ChainPriceListener {
|
|
|
36
36
|
// If undefined, there has been some change and we would need to update accordingly.
|
|
37
37
|
const handle = res.data.info.handle;
|
|
38
38
|
const priceItemRes = await client.getTableItem(handle, {
|
|
39
|
-
key_type: `${this.pythModule}::price_identifier::PriceIdentifier`,
|
|
40
|
-
value_type: `${this.pythModule}::price_info::PriceInfo`,
|
|
41
39
|
key: {
|
|
42
40
|
bytes: priceId
|
|
43
|
-
}
|
|
41
|
+
},
|
|
42
|
+
key_type: `${this.pythModule}::price_identifier::PriceIdentifier`,
|
|
43
|
+
value_type: `${this.pythModule}::price_info::PriceInfo`
|
|
44
44
|
});
|
|
45
45
|
const multiplier = priceItemRes.price_feed.price.price.negative === true ? -1 : 1;
|
|
46
46
|
const price = multiplier * Number(priceItemRes.price_feed.price.price.magnitude);
|
|
47
47
|
this.logger.debug(`Polled an Aptos on-chain price for feed ${this.priceIdToAlias.get(priceId) ?? ""} (${priceId}).`);
|
|
48
48
|
return {
|
|
49
|
-
price: price.toString(),
|
|
50
49
|
conf: priceItemRes.price_feed.price.conf,
|
|
50
|
+
price: price.toString(),
|
|
51
51
|
publishTime: Number(priceItemRes.price_feed.price.timestamp)
|
|
52
52
|
};
|
|
53
53
|
} catch (error) {
|
|
@@ -110,11 +110,11 @@ class AptosPricePusher {
|
|
|
110
110
|
const client = new _aptos.AptosClient(this.endpoint);
|
|
111
111
|
const sequenceNumber = await this.tryGetNextSequenceNumber(client, account);
|
|
112
112
|
const rawTx = await client.generateTransaction(account.address(), {
|
|
113
|
-
function: `${this.pythContractAddress}::pyth::update_price_feeds_with_funder`,
|
|
114
|
-
type_arguments: [],
|
|
115
113
|
arguments: [
|
|
116
114
|
priceFeedUpdateData
|
|
117
|
-
]
|
|
115
|
+
],
|
|
116
|
+
function: `${this.pythContractAddress}::pyth::update_price_feeds_with_funder`,
|
|
117
|
+
type_arguments: []
|
|
118
118
|
}, {
|
|
119
119
|
sequence_number: sequenceNumber.toFixed(0)
|
|
120
120
|
});
|
package/dist/aptos/aptos.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HermesClient } from "@pythnetwork/hermes-client";
|
|
1
|
+
import type { HermesClient } from "@pythnetwork/hermes-client";
|
|
2
2
|
import type { Logger } from "pino";
|
|
3
3
|
import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
|
|
4
4
|
import { ChainPriceListener } from "../interface.js";
|
|
@@ -30,8 +30,8 @@ class AptosBalanceTracker extends _interface.BaseBalanceTracker {
|
|
|
30
30
|
})
|
|
31
31
|
});
|
|
32
32
|
this.client = new _tssdk.Aptos(new _tssdk.AptosConfig({
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
fullnode: config.endpoint,
|
|
34
|
+
network: _tssdk.Network.CUSTOM
|
|
35
35
|
}));
|
|
36
36
|
this.aptosAddress = config.address;
|
|
37
37
|
// APT has 8 decimal places by default
|
|
@@ -62,12 +62,12 @@ class AptosBalanceTracker extends _interface.BaseBalanceTracker {
|
|
|
62
62
|
}
|
|
63
63
|
function createAptosBalanceTracker(params) {
|
|
64
64
|
return new AptosBalanceTracker({
|
|
65
|
-
endpoint: params.endpoint,
|
|
66
65
|
address: params.address,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
metrics: params.metrics,
|
|
66
|
+
decimals: params.decimals,
|
|
67
|
+
endpoint: params.endpoint,
|
|
70
68
|
logger: params.logger,
|
|
71
|
-
|
|
69
|
+
metrics: params.metrics,
|
|
70
|
+
network: params.network,
|
|
71
|
+
updateInterval: params.updateInterval
|
|
72
72
|
});
|
|
73
73
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
2
|
import type { BaseBalanceTrackerConfig, IBalanceTracker } from "../interface.js";
|
|
3
3
|
import { BaseBalanceTracker } from "../interface.js";
|
|
4
|
-
import { PricePusherMetrics } from "../metrics.js";
|
|
4
|
+
import type { PricePusherMetrics } from "../metrics.js";
|
|
5
5
|
import type { DurationInSeconds } from "../utils.js";
|
|
6
6
|
/**
|
|
7
7
|
* Aptos-specific configuration for balance tracker
|
package/dist/aptos/command.cjs
CHANGED
|
@@ -17,8 +17,8 @@ const _metrics = require("../metrics.cjs");
|
|
|
17
17
|
const _options = /*#__PURE__*/ _interop_require_wildcard(require("../options.cjs"));
|
|
18
18
|
const _priceconfig = require("../price-config.cjs");
|
|
19
19
|
const _pythpricelistener = require("../pyth-price-listener.cjs");
|
|
20
|
-
const _aptos1 = require("./aptos.cjs");
|
|
21
20
|
const _utils = require("../utils.cjs");
|
|
21
|
+
const _aptos1 = require("./aptos.cjs");
|
|
22
22
|
const _balancetracker = require("./balance-tracker.cjs");
|
|
23
23
|
function _interop_require_default(obj) {
|
|
24
24
|
return obj && obj.__esModule ? obj : {
|
|
@@ -67,22 +67,21 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
67
67
|
return newObj;
|
|
68
68
|
}
|
|
69
69
|
const _default = {
|
|
70
|
-
command: "aptos",
|
|
71
|
-
describe: "run price pusher for aptos",
|
|
72
70
|
builder: {
|
|
73
71
|
endpoint: {
|
|
74
72
|
description: "RPC endpoint endpoint URL for aptos. The pusher will periodically" + "poll for updates. The polling interval is configurable via the " + "`polling-frequency` command-line argument.",
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
required: true,
|
|
74
|
+
type: "string"
|
|
77
75
|
},
|
|
78
76
|
"override-gas-price-multiplier": {
|
|
77
|
+
default: 2,
|
|
79
78
|
description: "Multiply the gas price by this number if the transaction is not landing to override it. Default 2",
|
|
80
|
-
type: "number",
|
|
81
79
|
required: false,
|
|
82
|
-
|
|
80
|
+
type: "number"
|
|
83
81
|
},
|
|
84
82
|
..._options.priceConfigFile,
|
|
85
83
|
..._options.priceServiceEndpoint,
|
|
84
|
+
..._options.hermesAccessToken,
|
|
86
85
|
..._options.mnemonicFile,
|
|
87
86
|
..._options.pythContractAddress,
|
|
88
87
|
..._options.pollingFrequency,
|
|
@@ -92,14 +91,18 @@ const _default = {
|
|
|
92
91
|
..._options.enableMetrics,
|
|
93
92
|
..._options.metricsPort
|
|
94
93
|
},
|
|
94
|
+
command: "aptos",
|
|
95
|
+
describe: "run price pusher for aptos",
|
|
95
96
|
handler: async function(argv) {
|
|
96
97
|
// FIXME: type checks for this
|
|
97
|
-
const { endpoint, priceConfigFile, priceServiceEndpoint, mnemonicFile, pythContractAddress, pushingFrequency, pollingFrequency, overrideGasPriceMultiplier, logLevel, controllerLogLevel, enableMetrics, metricsPort } = argv;
|
|
98
|
+
const { endpoint, priceConfigFile, priceServiceEndpoint, hermesAccessToken, mnemonicFile, pythContractAddress, pushingFrequency, pollingFrequency, overrideGasPriceMultiplier, logLevel, controllerLogLevel, enableMetrics, metricsPort } = argv;
|
|
98
99
|
const logger = (0, _pino.default)({
|
|
99
100
|
level: logLevel
|
|
100
101
|
});
|
|
101
102
|
const priceConfigs = (0, _priceconfig.readPriceConfigFile)(priceConfigFile);
|
|
102
|
-
const hermesClient = new _hermesclient.HermesClient(priceServiceEndpoint
|
|
103
|
+
const hermesClient = new _hermesclient.HermesClient(priceServiceEndpoint, {
|
|
104
|
+
accessToken: hermesAccessToken
|
|
105
|
+
});
|
|
103
106
|
// Initialize metrics if enabled
|
|
104
107
|
let metrics;
|
|
105
108
|
if (enableMetrics) {
|
|
@@ -113,8 +116,8 @@ const _default = {
|
|
|
113
116
|
const account = _aptos.AptosAccount.fromDerivePath(_aptos1.APTOS_ACCOUNT_HD_PATH, mnemonic);
|
|
114
117
|
logger.info(`Pushing from account address: ${account.address()}`);
|
|
115
118
|
let priceItems = priceConfigs.map(({ id, alias })=>({
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
alias,
|
|
120
|
+
id
|
|
118
121
|
}));
|
|
119
122
|
// Better to filter out invalid price items before creating the pyth listener
|
|
120
123
|
const { existingPriceItems, invalidPriceItems } = await (0, _utils.filterInvalidPriceItems)(hermesClient, priceItems);
|
|
@@ -138,20 +141,20 @@ const _default = {
|
|
|
138
141
|
}, {
|
|
139
142
|
level: controllerLogLevel
|
|
140
143
|
}), {
|
|
141
|
-
|
|
142
|
-
|
|
144
|
+
metrics: metrics,
|
|
145
|
+
pushingFrequency
|
|
143
146
|
});
|
|
144
147
|
// Create and start the balance tracker if metrics are enabled
|
|
145
148
|
if (metrics) {
|
|
146
149
|
const balanceTracker = (0, _balancetracker.createAptosBalanceTracker)({
|
|
147
150
|
address: account.address().toString(),
|
|
148
151
|
endpoint,
|
|
149
|
-
network: "aptos",
|
|
150
|
-
updateInterval: pushingFrequency,
|
|
151
|
-
metrics,
|
|
152
152
|
logger: logger.child({
|
|
153
153
|
module: "AptosBalanceTracker"
|
|
154
|
-
})
|
|
154
|
+
}),
|
|
155
|
+
metrics,
|
|
156
|
+
network: "aptos",
|
|
157
|
+
updateInterval: pushingFrequency
|
|
155
158
|
});
|
|
156
159
|
// Start the balance tracker
|
|
157
160
|
await balanceTracker.start();
|
package/dist/aptos/command.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { Options } from "yargs";
|
|
2
2
|
declare const _default: {
|
|
3
|
-
command: string;
|
|
4
|
-
describe: string;
|
|
5
3
|
builder: {
|
|
6
4
|
"metrics-port": Options;
|
|
7
5
|
"enable-metrics": Options;
|
|
@@ -11,11 +9,14 @@ declare const _default: {
|
|
|
11
9
|
"polling-frequency": Options;
|
|
12
10
|
"pyth-contract-address": Options;
|
|
13
11
|
"mnemonic-file": Options;
|
|
12
|
+
"hermes-access-token": Options;
|
|
14
13
|
"price-service-endpoint": Options;
|
|
15
14
|
"price-config-file": Options;
|
|
16
15
|
endpoint: Options;
|
|
17
16
|
"override-gas-price-multiplier": Options;
|
|
18
17
|
};
|
|
18
|
+
command: string;
|
|
19
|
+
describe: string;
|
|
19
20
|
handler: (argv: any) => Promise<void>;
|
|
20
21
|
};
|
|
21
22
|
export default _default;
|
package/dist/common.cjs
CHANGED
package/dist/common.d.ts
CHANGED
package/dist/controller.cjs
CHANGED
|
@@ -28,6 +28,9 @@ class Controller {
|
|
|
28
28
|
this.metrics = config.metrics;
|
|
29
29
|
// Set the number of price feeds if metrics are enabled
|
|
30
30
|
this.metrics?.setPriceFeedsTotal(this.priceConfigs.length);
|
|
31
|
+
// Report unhealthy on /live if no loop iteration completes within a few
|
|
32
|
+
// pushing cycles (min 60s), so the k8s livenessProbe restarts a hung pod.
|
|
33
|
+
this.metrics?.setLivenessThresholdSeconds(Math.max(this.pushingFrequency * 5, 60));
|
|
31
34
|
}
|
|
32
35
|
async start() {
|
|
33
36
|
// start the listeners
|
|
@@ -49,13 +52,13 @@ class Controller {
|
|
|
49
52
|
const targetLatestPrice = this.targetPriceListener.getLatestPriceInfo(priceId);
|
|
50
53
|
const sourceLatestPrice = this.sourcePriceListener.getLatestPriceInfo(priceId);
|
|
51
54
|
if (this.metrics && targetLatestPrice && sourceLatestPrice) {
|
|
52
|
-
this.metrics.updateTimestamps(
|
|
53
|
-
this.metrics.updatePriceValues(
|
|
55
|
+
this.metrics.updateTimestamps(alias, targetLatestPrice.publishTime, sourceLatestPrice.publishTime, priceConfig.timeDifference);
|
|
56
|
+
this.metrics.updatePriceValues(alias, sourceLatestPrice.price, targetLatestPrice.price);
|
|
54
57
|
}
|
|
55
58
|
const priceShouldUpdate = (0, _priceconfig.shouldUpdate)(priceConfig, sourceLatestPrice, targetLatestPrice, this.logger);
|
|
56
59
|
// Record update condition in metrics
|
|
57
60
|
if (this.metrics) {
|
|
58
|
-
this.metrics.recordUpdateCondition(
|
|
61
|
+
this.metrics.recordUpdateCondition(alias, priceShouldUpdate);
|
|
59
62
|
}
|
|
60
63
|
if (priceShouldUpdate == _priceconfig.UpdateCondition.YES) {
|
|
61
64
|
pushThresholdMet = true;
|
|
@@ -68,8 +71,8 @@ class Controller {
|
|
|
68
71
|
if (pushThresholdMet) {
|
|
69
72
|
this.logger.info({
|
|
70
73
|
priceIds: pricesToPush.map((priceConfig)=>({
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
alias: priceConfig.alias,
|
|
75
|
+
id: priceConfig.id
|
|
73
76
|
}))
|
|
74
77
|
}, "Some of the checks triggered pushing update. Will push the updates for some feeds.");
|
|
75
78
|
// note that the priceIds are without leading "0x"
|
|
@@ -80,7 +83,7 @@ class Controller {
|
|
|
80
83
|
if (this.metrics) {
|
|
81
84
|
for (const config of pricesToPush){
|
|
82
85
|
const triggerValue = (0, _priceconfig.shouldUpdate)(config, this.sourcePriceListener.getLatestPriceInfo(config.id), this.targetPriceListener.getLatestPriceInfo(config.id), this.logger) === _priceconfig.UpdateCondition.YES ? "yes" : "early";
|
|
83
|
-
this.metrics.recordPriceUpdate(config.
|
|
86
|
+
this.metrics.recordPriceUpdate(config.alias, triggerValue);
|
|
84
87
|
}
|
|
85
88
|
}
|
|
86
89
|
} catch (error) {
|
|
@@ -92,13 +95,15 @@ class Controller {
|
|
|
92
95
|
if (this.metrics) {
|
|
93
96
|
for (const config of pricesToPush){
|
|
94
97
|
const triggerValue = (0, _priceconfig.shouldUpdate)(config, this.sourcePriceListener.getLatestPriceInfo(config.id), this.targetPriceListener.getLatestPriceInfo(config.id), this.logger) === _priceconfig.UpdateCondition.YES ? "yes" : "early";
|
|
95
|
-
this.metrics.recordPriceUpdateError(config.
|
|
98
|
+
this.metrics.recordPriceUpdateError(config.alias, triggerValue);
|
|
96
99
|
}
|
|
97
100
|
}
|
|
98
101
|
}
|
|
99
102
|
} else {
|
|
100
103
|
this.logger.info("None of the checks were triggered. No push needed.");
|
|
101
104
|
}
|
|
105
|
+
// Liveness heartbeat: mark this loop iteration as completed.
|
|
106
|
+
this.metrics?.recordLoopIteration();
|
|
102
107
|
await (0, _utils.sleep)(this.pushingFrequency * 1000);
|
|
103
108
|
}
|
|
104
109
|
}
|
package/dist/controller.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
2
|
import type { IPriceListener, IPricePusher } from "./interface.js";
|
|
3
|
-
import { PricePusherMetrics } from "./metrics.js";
|
|
3
|
+
import type { PricePusherMetrics } from "./metrics.js";
|
|
4
4
|
import type { PriceConfig } from "./price-config.js";
|
|
5
5
|
import type { DurationInSeconds } from "./utils.js";
|
|
6
6
|
export declare class Controller {
|
|
@@ -48,11 +48,11 @@ class EvmBalanceTracker extends _interface.BaseBalanceTracker {
|
|
|
48
48
|
}
|
|
49
49
|
function createEvmBalanceTracker(params) {
|
|
50
50
|
return new EvmBalanceTracker({
|
|
51
|
-
client: params.client,
|
|
52
51
|
address: params.address,
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
client: params.client,
|
|
53
|
+
logger: params.logger,
|
|
55
54
|
metrics: params.metrics,
|
|
56
|
-
|
|
55
|
+
network: params.network,
|
|
56
|
+
updateInterval: params.updateInterval
|
|
57
57
|
});
|
|
58
58
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
|
-
import type { SuperWalletClient } from "./super-wallet.js";
|
|
3
2
|
import type { BaseBalanceTrackerConfig, IBalanceTracker } from "../interface.js";
|
|
4
3
|
import { BaseBalanceTracker } from "../interface.js";
|
|
5
|
-
import { PricePusherMetrics } from "../metrics.js";
|
|
4
|
+
import type { PricePusherMetrics } from "../metrics.js";
|
|
6
5
|
import type { DurationInSeconds } from "../utils.js";
|
|
6
|
+
import type { SuperWalletClient } from "./super-wallet.js";
|
|
7
7
|
/**
|
|
8
8
|
* EVM-specific configuration for balance tracker
|
|
9
9
|
*/
|
package/dist/evm/command.cjs
CHANGED
|
@@ -12,16 +12,16 @@ const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
|
|
|
12
12
|
const _hermesclient = require("@pythnetwork/hermes-client");
|
|
13
13
|
const _pino = /*#__PURE__*/ _interop_require_default(require("pino"));
|
|
14
14
|
const _controller = require("../controller.cjs");
|
|
15
|
+
const _metrics = require("../metrics.cjs");
|
|
15
16
|
const _options = /*#__PURE__*/ _interop_require_wildcard(require("../options.cjs"));
|
|
16
17
|
const _priceconfig = require("../price-config.cjs");
|
|
17
18
|
const _pythpricelistener = require("../pyth-price-listener.cjs");
|
|
19
|
+
const _utils = require("../utils.cjs");
|
|
20
|
+
const _balancetracker = require("./balance-tracker.cjs");
|
|
18
21
|
const _customgasstation = require("./custom-gas-station.cjs");
|
|
19
22
|
const _evm = require("./evm.cjs");
|
|
20
23
|
const _pythcontract = require("./pyth-contract.cjs");
|
|
21
24
|
const _superwallet = require("./super-wallet.cjs");
|
|
22
|
-
const _metrics = require("../metrics.cjs");
|
|
23
|
-
const _utils = require("../utils.cjs");
|
|
24
|
-
const _balancetracker = require("./balance-tracker.cjs");
|
|
25
25
|
function _interop_require_default(obj) {
|
|
26
26
|
return obj && obj.__esModule ? obj : {
|
|
27
27
|
default: obj
|
|
@@ -69,58 +69,90 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
69
69
|
return newObj;
|
|
70
70
|
}
|
|
71
71
|
const _default = {
|
|
72
|
-
command: "evm",
|
|
73
|
-
describe: "run price pusher for evm",
|
|
74
72
|
builder: {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
required:
|
|
73
|
+
"base-fee-multiplier": {
|
|
74
|
+
default: 1.2,
|
|
75
|
+
description: "[eip1559 strategy only] Multiplier applied to the chain base fee when computing " + "maxFeePerGas. Values above 1 leave headroom for the base fee to grow between blocks. " + "Default to 1.2",
|
|
76
|
+
required: false,
|
|
77
|
+
type: "number"
|
|
79
78
|
},
|
|
80
79
|
"custom-gas-station": {
|
|
81
80
|
description: "If using a custom gas station, chainId of custom gas station to use",
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
required: false,
|
|
82
|
+
type: "number"
|
|
84
83
|
},
|
|
85
|
-
|
|
86
|
-
description: "
|
|
84
|
+
endpoint: {
|
|
85
|
+
description: "RPC endpoint URL for evm network. If you provide a normal HTTP endpoint, the pusher " + "will periodically poll for updates. The polling interval is configurable via the " + "`polling-frequency` command-line argument. If you provide a websocket RPC " + "endpoint (`ws[s]://...`), the price pusher will use event subscriptions to read " + "the current EVM price in addition to polling. ",
|
|
86
|
+
required: true,
|
|
87
|
+
type: "string"
|
|
88
|
+
},
|
|
89
|
+
"gas-limit": {
|
|
90
|
+
description: "Gas limit for the transaction",
|
|
91
|
+
required: false,
|
|
92
|
+
type: "number"
|
|
93
|
+
},
|
|
94
|
+
"gas-price": {
|
|
95
|
+
description: "[legacy strategy only] Override the gas price (in wei) that would be received from the RPC",
|
|
96
|
+
required: false,
|
|
97
|
+
type: "number"
|
|
98
|
+
},
|
|
99
|
+
"gas-pricing-strategy": {
|
|
87
100
|
choices: [
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"fast"
|
|
101
|
+
"eip1559",
|
|
102
|
+
"legacy"
|
|
91
103
|
],
|
|
104
|
+
default: "eip1559",
|
|
105
|
+
description: "How to price transactions. 'eip1559' (default and recommended) sources the " + "gas from the chain base fee and a priority fee, which is more robust as it " + "avoids the deprecated eth_gasPrice RPC. Use 'legacy' for chains that do not " + "support eip1559 transactions.",
|
|
92
106
|
required: false
|
|
93
107
|
},
|
|
94
108
|
"override-gas-price-multiplier": {
|
|
109
|
+
default: 1.1,
|
|
95
110
|
description: "Multiply the previous gas price by this number if the transaction is not landing to override. " + "Please note that the gas price can grow exponentially on consecutive failures; " + "to set a cap on the multiplier, use the `override-gas-price-multiplier-cap` option." + "Default to 1.1",
|
|
96
|
-
type: "number",
|
|
97
111
|
required: false,
|
|
98
|
-
|
|
112
|
+
type: "number"
|
|
99
113
|
},
|
|
100
114
|
"override-gas-price-multiplier-cap": {
|
|
115
|
+
default: 5,
|
|
101
116
|
description: "Maximum gas price multiplier to use in override compared to the RPC returned " + "gas price. Default to 5",
|
|
102
|
-
type: "number",
|
|
103
117
|
required: false,
|
|
104
|
-
|
|
118
|
+
type: "number"
|
|
105
119
|
},
|
|
106
|
-
"
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
required: false
|
|
120
|
+
"priority-fee-multiplier": {
|
|
121
|
+
default: 1,
|
|
122
|
+
description: "[eip1559 strategy only] Multiplier applied to the priority fee (tip) estimated from " + "the RPC. Default to 1",
|
|
123
|
+
required: false,
|
|
124
|
+
type: "number"
|
|
110
125
|
},
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
|
|
126
|
+
"receipt-poll-interval": {
|
|
127
|
+
default: 2,
|
|
128
|
+
description: "How often (in seconds) to poll for a sent transaction's receipt while waiting for " + "it to land. Default to 2",
|
|
129
|
+
required: false,
|
|
130
|
+
type: "number"
|
|
131
|
+
},
|
|
132
|
+
"receipt-wait-timeout": {
|
|
133
|
+
default: 60,
|
|
134
|
+
description: "Maximum time (in seconds) to poll for a sent transaction's receipt before giving " + "up. Bounds the wait so a transaction that never lands cannot be polled forever. " + "Default to 60",
|
|
135
|
+
required: false,
|
|
136
|
+
type: "number"
|
|
137
|
+
},
|
|
138
|
+
"tx-speed": {
|
|
139
|
+
choices: [
|
|
140
|
+
"slow",
|
|
141
|
+
"standard",
|
|
142
|
+
"fast"
|
|
143
|
+
],
|
|
144
|
+
description: "txSpeed for custom gas station. choose between 'slow'|'standard'|'fast'",
|
|
114
145
|
required: false
|
|
115
146
|
},
|
|
116
147
|
"update-fee-multiplier": {
|
|
148
|
+
default: 1,
|
|
117
149
|
description: "Multiplier for the fee to update the price. It is useful in networks " + "such as Hedera where setting on-chain getUpdateFee as the transaction value " + "won't work. Default to 1",
|
|
118
|
-
type: "number",
|
|
119
150
|
required: false,
|
|
120
|
-
|
|
151
|
+
type: "number"
|
|
121
152
|
},
|
|
122
153
|
..._options.priceConfigFile,
|
|
123
154
|
..._options.priceServiceEndpoint,
|
|
155
|
+
..._options.hermesAccessToken,
|
|
124
156
|
..._options.mnemonicFile,
|
|
125
157
|
..._options.pythContractAddress,
|
|
126
158
|
..._options.pollingFrequency,
|
|
@@ -130,18 +162,22 @@ const _default = {
|
|
|
130
162
|
..._options.enableMetrics,
|
|
131
163
|
..._options.metricsPort
|
|
132
164
|
},
|
|
165
|
+
command: "evm",
|
|
166
|
+
describe: "run price pusher for evm",
|
|
133
167
|
handler: async function(argv) {
|
|
134
168
|
// FIXME: type checks for this
|
|
135
|
-
const { endpoint, priceConfigFile, priceServiceEndpoint, mnemonicFile, pythContractAddress, pushingFrequency, pollingFrequency, customGasStation, txSpeed, overrideGasPriceMultiplier, overrideGasPriceMultiplierCap, gasLimit, gasPrice, updateFeeMultiplier, logLevel, controllerLogLevel, enableMetrics, metricsPort } = argv;
|
|
169
|
+
const { endpoint, priceConfigFile, priceServiceEndpoint, hermesAccessToken, mnemonicFile, pythContractAddress, pushingFrequency, pollingFrequency, customGasStation, txSpeed, overrideGasPriceMultiplier, overrideGasPriceMultiplierCap, gasLimit, gasPricingStrategy, gasPrice, baseFeeMultiplier, priorityFeeMultiplier, updateFeeMultiplier, receiptPollInterval, receiptWaitTimeout, logLevel, controllerLogLevel, enableMetrics, metricsPort } = argv;
|
|
136
170
|
const logger = (0, _pino.default)({
|
|
137
171
|
level: logLevel
|
|
138
172
|
});
|
|
139
173
|
const priceConfigs = (0, _priceconfig.readPriceConfigFile)(priceConfigFile);
|
|
140
|
-
const hermesClient = new _hermesclient.HermesClient(priceServiceEndpoint
|
|
174
|
+
const hermesClient = new _hermesclient.HermesClient(priceServiceEndpoint, {
|
|
175
|
+
accessToken: hermesAccessToken
|
|
176
|
+
});
|
|
141
177
|
const mnemonic = _nodefs.default.readFileSync(mnemonicFile, "utf8").trim();
|
|
142
178
|
let priceItems = priceConfigs.map(({ id, alias })=>({
|
|
143
|
-
|
|
144
|
-
|
|
179
|
+
alias,
|
|
180
|
+
id
|
|
145
181
|
}));
|
|
146
182
|
// Better to filter out invalid price items before creating the pyth listener
|
|
147
183
|
const { existingPriceItems, invalidPriceItems } = await (0, _utils.filterInvalidPriceItems)(hermesClient, priceItems);
|
|
@@ -176,26 +212,39 @@ const _default = {
|
|
|
176
212
|
const gasStation = (0, _customgasstation.getCustomGasStation)(logger.child({
|
|
177
213
|
module: "CustomGasStation"
|
|
178
214
|
}), customGasStation, txSpeed);
|
|
215
|
+
if (gasPricingStrategy === "eip1559" && (gasStation || gasPrice)) {
|
|
216
|
+
logger.warn("`--custom-gas-station`/`--tx-speed` and `--gas-price` only apply to the 'legacy' " + "gas pricing strategy and will be ignored. Use `--base-fee-multiplier` and " + "`--priority-fee-multiplier` to tune the 'eip1559' strategy.");
|
|
217
|
+
}
|
|
218
|
+
const gasPriceConfig = {
|
|
219
|
+
baseFeeMultiplier,
|
|
220
|
+
customGasStation: gasStation,
|
|
221
|
+
gasPrice,
|
|
222
|
+
priorityFeeMultiplier,
|
|
223
|
+
strategy: gasPricingStrategy
|
|
224
|
+
};
|
|
179
225
|
const evmPusher = new _evm.EvmPricePusher(hermesClient, client, pythContract, logger.child({
|
|
180
226
|
module: "EvmPricePusher"
|
|
181
|
-
}), overrideGasPriceMultiplier, overrideGasPriceMultiplierCap, updateFeeMultiplier,
|
|
227
|
+
}), overrideGasPriceMultiplier, overrideGasPriceMultiplierCap, updateFeeMultiplier, gasPriceConfig, gasLimit, // CLI values are in seconds; the pusher expects milliseconds. Defaults
|
|
228
|
+
// (60s / 2s) reproduce the pre-flag behaviour, so existing deployments
|
|
229
|
+
// that don't set these flags are unaffected.
|
|
230
|
+
receiptWaitTimeout * 1000, receiptPollInterval * 1000);
|
|
182
231
|
const controller = new _controller.Controller(priceConfigs, pythListener, evmListener, evmPusher, logger.child({
|
|
183
232
|
module: "Controller"
|
|
184
233
|
}, {
|
|
185
234
|
level: controllerLogLevel
|
|
186
235
|
}), {
|
|
187
|
-
|
|
188
|
-
|
|
236
|
+
metrics: metrics,
|
|
237
|
+
pushingFrequency
|
|
189
238
|
});
|
|
190
239
|
// Create and start the balance tracker if metrics are enabled
|
|
191
240
|
if (metrics) {
|
|
192
241
|
const balanceTracker = (0, _balancetracker.createEvmBalanceTracker)({
|
|
193
|
-
client,
|
|
194
242
|
address: client.account.address,
|
|
195
|
-
|
|
196
|
-
|
|
243
|
+
client,
|
|
244
|
+
logger,
|
|
197
245
|
metrics,
|
|
198
|
-
|
|
246
|
+
network: await client.getChainId().then((id)=>id.toString()),
|
|
247
|
+
updateInterval: pushingFrequency
|
|
199
248
|
});
|
|
200
249
|
// Start the balance tracker
|
|
201
250
|
await balanceTracker.start();
|
package/dist/evm/command.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { Options } from "yargs";
|
|
2
2
|
declare const _default: {
|
|
3
|
-
command: string;
|
|
4
|
-
describe: string;
|
|
5
3
|
builder: {
|
|
6
4
|
"metrics-port": Options;
|
|
7
5
|
"enable-metrics": Options;
|
|
@@ -11,17 +9,25 @@ declare const _default: {
|
|
|
11
9
|
"polling-frequency": Options;
|
|
12
10
|
"pyth-contract-address": Options;
|
|
13
11
|
"mnemonic-file": Options;
|
|
12
|
+
"hermes-access-token": Options;
|
|
14
13
|
"price-service-endpoint": Options;
|
|
15
14
|
"price-config-file": Options;
|
|
16
|
-
|
|
15
|
+
"base-fee-multiplier": Options;
|
|
17
16
|
"custom-gas-station": Options;
|
|
18
|
-
|
|
19
|
-
"override-gas-price-multiplier": Options;
|
|
20
|
-
"override-gas-price-multiplier-cap": Options;
|
|
17
|
+
endpoint: Options;
|
|
21
18
|
"gas-limit": Options;
|
|
22
19
|
"gas-price": Options;
|
|
20
|
+
"gas-pricing-strategy": Options;
|
|
21
|
+
"override-gas-price-multiplier": Options;
|
|
22
|
+
"override-gas-price-multiplier-cap": Options;
|
|
23
|
+
"priority-fee-multiplier": Options;
|
|
24
|
+
"receipt-poll-interval": Options;
|
|
25
|
+
"receipt-wait-timeout": Options;
|
|
26
|
+
"tx-speed": Options;
|
|
23
27
|
"update-fee-multiplier": Options;
|
|
24
28
|
};
|
|
29
|
+
command: string;
|
|
30
|
+
describe: string;
|
|
25
31
|
handler: (argv: any) => Promise<void>;
|
|
26
32
|
};
|
|
27
33
|
export default _default;
|