@pythnetwork/price-pusher 10.0.0 → 10.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 +31 -3
- package/{lib/aptos/aptos.js → dist/aptos/aptos.cjs} +80 -76
- package/{lib → dist}/aptos/aptos.d.ts +5 -5
- package/{lib/aptos/balance-tracker.js → dist/aptos/balance-tracker.cjs} +37 -25
- package/{lib → dist}/aptos/balance-tracker.d.ts +9 -9
- package/dist/aptos/command.cjs +161 -0
- package/{lib → dist}/aptos/command.d.ts +1 -2
- package/dist/common.cjs +4 -0
- package/{lib → dist}/common.d.ts +0 -1
- package/{lib/controller.js → dist/controller.cjs} +36 -33
- package/{lib → dist}/controller.d.ts +5 -6
- package/dist/evm/balance-tracker.cjs +58 -0
- package/{lib → dist}/evm/balance-tracker.d.ts +10 -10
- package/dist/evm/command.cjs +205 -0
- package/{lib → dist}/evm/command.d.ts +1 -2
- package/dist/evm/custom-gas-station.cjs +54 -0
- package/{lib → dist}/evm/custom-gas-station.d.ts +1 -2
- package/dist/evm/evm.cjs +287 -0
- package/{lib → dist}/evm/evm.d.ts +8 -7
- package/{lib/evm/pyth-abi.js → dist/evm/pyth-abi.cjs} +181 -160
- package/{lib → dist}/evm/pyth-abi.d.ts +0 -1
- package/dist/evm/pyth-contract.cjs +17 -0
- package/{lib → dist}/evm/pyth-contract.d.ts +3 -4
- package/dist/evm/super-wallet.cjs +90 -0
- package/{lib → dist}/evm/super-wallet.d.ts +1 -2
- package/dist/fuel/command.cjs +135 -0
- package/{lib → dist}/fuel/command.d.ts +1 -2
- package/dist/fuel/fuel.cjs +108 -0
- package/{lib → dist}/fuel/fuel.d.ts +5 -5
- package/dist/index.cjs +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/injective/command.cjs +150 -0
- package/{lib → dist}/injective/command.d.ts +1 -2
- package/{lib/injective/injective.js → dist/injective/injective.cjs} +100 -98
- package/{lib → dist}/injective/injective.d.ts +7 -6
- package/dist/interface.cjs +142 -0
- package/{lib → dist}/interface.d.ts +12 -13
- package/dist/metrics.cjs +218 -0
- package/{lib → dist}/metrics.d.ts +11 -9
- package/dist/near/command.cjs +129 -0
- package/{lib → dist}/near/command.d.ts +1 -2
- package/dist/near/near.cjs +183 -0
- package/{lib → dist}/near/near.d.ts +5 -5
- package/dist/options.cjs +132 -0
- package/{lib → dist}/options.d.ts +1 -2
- package/dist/package.json +1 -0
- package/dist/price-config.cjs +104 -0
- package/{lib → dist}/price-config.d.ts +5 -6
- package/{lib/pyth-price-listener.js → dist/pyth-price-listener.cjs} +30 -24
- package/{lib → dist}/pyth-price-listener.d.ts +4 -4
- package/dist/solana/balance-tracker.cjs +60 -0
- package/{lib → dist}/solana/balance-tracker.d.ts +9 -9
- package/dist/solana/command.cjs +259 -0
- package/{lib → dist}/solana/command.d.ts +2 -3
- package/{lib/solana/solana.js → dist/solana/solana.cjs} +90 -78
- package/{lib → dist}/solana/solana.d.ts +6 -6
- package/dist/sui/balance-tracker.cjs +58 -0
- package/{lib → dist}/sui/balance-tracker.d.ts +9 -9
- package/dist/sui/command.cjs +190 -0
- package/{lib → dist}/sui/command.d.ts +1 -2
- package/{lib/sui/sui.js → dist/sui/sui.cjs} +145 -133
- package/{lib → dist}/sui/sui.d.ts +7 -8
- package/dist/ton/command.cjs +137 -0
- package/{lib → dist}/ton/command.d.ts +1 -2
- package/dist/ton/ton.cjs +103 -0
- package/{lib → dist}/ton/ton.d.ts +7 -6
- package/dist/utils.cjs +102 -0
- package/{lib → dist}/utils.d.ts +4 -4
- package/package.json +161 -20
- package/lib/aptos/aptos.d.ts.map +0 -1
- package/lib/aptos/balance-tracker.d.ts.map +0 -1
- package/lib/aptos/command.d.ts.map +0 -1
- package/lib/aptos/command.js +0 -126
- package/lib/common.d.ts.map +0 -1
- package/lib/common.js +0 -2
- package/lib/controller.d.ts.map +0 -1
- package/lib/evm/balance-tracker.d.ts.map +0 -1
- package/lib/evm/balance-tracker.js +0 -49
- package/lib/evm/command.d.ts.map +0 -1
- package/lib/evm/command.js +0 -178
- package/lib/evm/custom-gas-station.d.ts.map +0 -1
- package/lib/evm/custom-gas-station.js +0 -40
- package/lib/evm/evm.d.ts.map +0 -1
- package/lib/evm/evm.js +0 -270
- package/lib/evm/pyth-abi.d.ts.map +0 -1
- package/lib/evm/pyth-contract.d.ts.map +0 -1
- package/lib/evm/pyth-contract.js +0 -11
- package/lib/evm/super-wallet.d.ts.map +0 -1
- package/lib/evm/super-wallet.js +0 -73
- package/lib/fuel/command.d.ts.map +0 -1
- package/lib/fuel/command.js +0 -98
- package/lib/fuel/fuel.d.ts.map +0 -1
- package/lib/fuel/fuel.js +0 -101
- package/lib/index.d.ts +0 -3
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -34
- package/lib/injective/command.d.ts.map +0 -1
- package/lib/injective/command.js +0 -119
- package/lib/injective/injective.d.ts.map +0 -1
- package/lib/interface.d.ts.map +0 -1
- package/lib/interface.js +0 -122
- package/lib/metrics.d.ts.map +0 -1
- package/lib/metrics.js +0 -129
- package/lib/near/command.d.ts.map +0 -1
- package/lib/near/command.js +0 -103
- package/lib/near/near.d.ts.map +0 -1
- package/lib/near/near.js +0 -168
- package/lib/options.d.ts.map +0 -1
- package/lib/options.js +0 -84
- package/lib/price-config.d.ts.map +0 -1
- package/lib/price-config.js +0 -114
- package/lib/pyth-price-listener.d.ts.map +0 -1
- package/lib/solana/balance-tracker.d.ts.map +0 -1
- package/lib/solana/balance-tracker.js +0 -51
- package/lib/solana/command.d.ts.map +0 -1
- package/lib/solana/command.js +0 -218
- package/lib/solana/solana.d.ts.map +0 -1
- package/lib/sui/balance-tracker.d.ts.map +0 -1
- package/lib/sui/balance-tracker.js +0 -49
- package/lib/sui/command.d.ts.map +0 -1
- package/lib/sui/command.js +0 -160
- package/lib/sui/sui.d.ts.map +0 -1
- package/lib/ton/command.d.ts.map +0 -1
- package/lib/ton/command.js +0 -99
- package/lib/ton/ton.d.ts.map +0 -1
- package/lib/ton/ton.js +0 -97
- package/lib/utils.d.ts.map +0 -1
- package/lib/utils.js +0 -61
|
@@ -1,45 +1,54 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unnecessary-condition */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ "use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get InjectivePriceListener () {
|
|
13
|
+
return InjectivePriceListener;
|
|
14
|
+
},
|
|
15
|
+
get InjectivePricePusher () {
|
|
16
|
+
return InjectivePricePusher;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const _sdkts = require("@injectivelabs/sdk-ts");
|
|
20
|
+
const _utils = require("@injectivelabs/utils");
|
|
21
|
+
const _interface = require("../interface.cjs");
|
|
22
|
+
const DEFAULT_GAS_PRICE = 160_000_000;
|
|
8
23
|
const DEFAULT_GAS_MULTIPLIER = 1.05;
|
|
9
24
|
const DEFAULT_PRICE_IDS_PROCESS_CHUNK_SIZE = -1;
|
|
10
25
|
const INJECTIVE_TESTNET_CHAIN_ID = "injective-888";
|
|
11
|
-
|
|
12
|
-
class InjectivePriceListener extends interface_1.ChainPriceListener {
|
|
26
|
+
class InjectivePriceListener extends _interface.ChainPriceListener {
|
|
13
27
|
pythContractAddress;
|
|
14
28
|
grpcEndpoint;
|
|
15
29
|
logger;
|
|
16
|
-
constructor(pythContractAddress, grpcEndpoint, priceItems, logger, config)
|
|
17
|
-
super(config.pollingFrequency, priceItems);
|
|
18
|
-
this.pythContractAddress = pythContractAddress;
|
|
19
|
-
this.grpcEndpoint = grpcEndpoint;
|
|
20
|
-
this.logger = logger;
|
|
30
|
+
constructor(pythContractAddress, grpcEndpoint, priceItems, logger, config){
|
|
31
|
+
super(config.pollingFrequency, priceItems), this.pythContractAddress = pythContractAddress, this.grpcEndpoint = grpcEndpoint, this.logger = logger;
|
|
21
32
|
}
|
|
22
33
|
async getOnChainPriceInfo(priceId) {
|
|
23
34
|
let priceQueryResponse;
|
|
24
35
|
try {
|
|
25
|
-
const api = new
|
|
36
|
+
const api = new _sdkts.ChainGrpcWasmApi(this.grpcEndpoint);
|
|
26
37
|
const { data } = await api.fetchSmartContractState(this.pythContractAddress, Buffer.from(`{"price_feed":{"id":"${priceId}"}}`).toString("base64"));
|
|
27
38
|
const json = Buffer.from(data).toString();
|
|
28
39
|
priceQueryResponse = JSON.parse(json);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
this.logger.error(err, `Polling on-chain price for ${priceId} failed.`);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
this.logger.error(error, `Polling on-chain price for ${priceId} failed.`);
|
|
32
42
|
return undefined;
|
|
33
43
|
}
|
|
34
44
|
this.logger.debug(`Polled an Injective on chain price for feed ${this.priceIdToAlias.get(priceId)} (${priceId}).`);
|
|
35
45
|
return {
|
|
36
46
|
conf: priceQueryResponse.price_feed.price.conf,
|
|
37
47
|
price: priceQueryResponse.price_feed.price.price,
|
|
38
|
-
publishTime: priceQueryResponse.price_feed.price.publish_time
|
|
48
|
+
publishTime: priceQueryResponse.price_feed.price.publish_time
|
|
39
49
|
};
|
|
40
50
|
}
|
|
41
51
|
}
|
|
42
|
-
exports.InjectivePriceListener = InjectivePriceListener;
|
|
43
52
|
class InjectivePricePusher {
|
|
44
53
|
hermesClient;
|
|
45
54
|
pythContractAddress;
|
|
@@ -47,8 +56,8 @@ class InjectivePricePusher {
|
|
|
47
56
|
logger;
|
|
48
57
|
mnemonic;
|
|
49
58
|
chainConfig;
|
|
50
|
-
accounts = {};
|
|
51
|
-
constructor(hermesClient, pythContractAddress, grpcEndpoint, logger, mnemonic, chainConfig)
|
|
59
|
+
accounts = {};
|
|
60
|
+
constructor(hermesClient, pythContractAddress, grpcEndpoint, logger, mnemonic, chainConfig){
|
|
52
61
|
this.hermesClient = hermesClient;
|
|
53
62
|
this.pythContractAddress = pythContractAddress;
|
|
54
63
|
this.grpcEndpoint = grpcEndpoint;
|
|
@@ -58,170 +67,163 @@ class InjectivePricePusher {
|
|
|
58
67
|
chainId: chainConfig?.chainId ?? INJECTIVE_TESTNET_CHAIN_ID,
|
|
59
68
|
gasMultiplier: chainConfig?.gasMultiplier ?? DEFAULT_GAS_MULTIPLIER,
|
|
60
69
|
gasPrice: chainConfig?.gasPrice ?? DEFAULT_GAS_PRICE,
|
|
61
|
-
priceIdsProcessChunkSize: chainConfig?.priceIdsProcessChunkSize ??
|
|
62
|
-
DEFAULT_PRICE_IDS_PROCESS_CHUNK_SIZE,
|
|
70
|
+
priceIdsProcessChunkSize: chainConfig?.priceIdsProcessChunkSize ?? DEFAULT_PRICE_IDS_PROCESS_CHUNK_SIZE
|
|
63
71
|
};
|
|
64
72
|
}
|
|
65
73
|
getWallet(index) {
|
|
66
|
-
if (this.chainConfig.priceIdsProcessChunkSize === -1 ||
|
|
67
|
-
this.
|
|
68
|
-
return sdk_ts_1.PrivateKey.fromMnemonic(this.mnemonic);
|
|
74
|
+
if (this.chainConfig.priceIdsProcessChunkSize === -1 || this.chainConfig.priceIdsProcessChunkSize === undefined) {
|
|
75
|
+
return _sdkts.PrivateKey.fromMnemonic(this.mnemonic);
|
|
69
76
|
}
|
|
70
|
-
return
|
|
77
|
+
return _sdkts.PrivateKey.fromMnemonic(this.mnemonic, `m/44'/60'/0'/0/${index}`);
|
|
71
78
|
}
|
|
72
79
|
async signAndBroadcastMsg(msg, index) {
|
|
73
|
-
const chainGrpcAuthApi = new
|
|
80
|
+
const chainGrpcAuthApi = new _sdkts.ChainGrpcAuthApi(this.grpcEndpoint);
|
|
74
81
|
const wallet = this.getWallet(index);
|
|
75
82
|
const injectiveAddress = wallet.toAddress().toBech32();
|
|
76
83
|
// Fetch the latest account details only if it's not stored.
|
|
77
|
-
this.accounts[injectiveAddress] ??=
|
|
78
|
-
await chainGrpcAuthApi.fetchAccount(injectiveAddress);
|
|
84
|
+
this.accounts[injectiveAddress] ??= await chainGrpcAuthApi.fetchAccount(injectiveAddress);
|
|
79
85
|
const account = this.accounts[injectiveAddress];
|
|
80
86
|
try {
|
|
81
|
-
const { signBytes, txRaw } = (0,
|
|
87
|
+
const { signBytes, txRaw } = (0, _sdkts.createTransactionFromMsg)({
|
|
82
88
|
sequence: account.baseAccount.sequence,
|
|
83
89
|
accountNumber: account.baseAccount.accountNumber,
|
|
84
90
|
message: msg,
|
|
85
91
|
chainId: this.chainConfig.chainId,
|
|
86
92
|
fee: await this.getStdFee(msg, index),
|
|
87
|
-
pubKey: wallet.toPublicKey().toBase64()
|
|
93
|
+
pubKey: wallet.toPublicKey().toBase64()
|
|
88
94
|
});
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
89
96
|
const sig = await wallet.sign(Buffer.from(signBytes));
|
|
90
|
-
/** Append Signatures */
|
|
91
|
-
|
|
97
|
+
/** Append Signatures */ txRaw.signatures = [
|
|
98
|
+
sig
|
|
99
|
+
];
|
|
92
100
|
// this takes approx 5 seconds
|
|
93
|
-
const txResponse = await new
|
|
101
|
+
const txResponse = await new _sdkts.TxGrpcApi(this.grpcEndpoint).broadcast(txRaw);
|
|
94
102
|
account.baseAccount.sequence++;
|
|
95
103
|
return txResponse;
|
|
96
|
-
}
|
|
97
|
-
catch (e) {
|
|
104
|
+
} catch (error) {
|
|
98
105
|
// The sequence number was invalid and hence we will have to fetch it again
|
|
99
|
-
if (
|
|
106
|
+
if (/account sequence mismatch/.exec(JSON.stringify(error)) !== null) {
|
|
100
107
|
this.accounts[injectiveAddress] = undefined;
|
|
101
108
|
}
|
|
102
|
-
throw
|
|
109
|
+
throw error;
|
|
103
110
|
}
|
|
104
111
|
}
|
|
105
112
|
async updatePriceFeed(priceIds, pubTimesToPush) {
|
|
106
113
|
if (priceIds.length === 0) {
|
|
107
114
|
return;
|
|
108
115
|
}
|
|
109
|
-
if (priceIds.length !== pubTimesToPush.length)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
await Promise.all(priceIdChunks.map((priceIdChunk, chunkIndex) => this.updatePriceFeedChunk(priceIdChunk, chunkIndex)));
|
|
116
|
+
if (priceIds.length !== pubTimesToPush.length) throw new Error("Invalid arguments");
|
|
117
|
+
const priceIdChunks = this.chainConfig.priceIdsProcessChunkSize === -1 ? [
|
|
118
|
+
priceIds
|
|
119
|
+
] : (0, _utils.splitArrayToChunks)({
|
|
120
|
+
array: priceIds,
|
|
121
|
+
chunkSize: Number(this.chainConfig.priceIdsProcessChunkSize)
|
|
122
|
+
});
|
|
123
|
+
await Promise.all(priceIdChunks.map((priceIdChunk, chunkIndex)=>this.updatePriceFeedChunk(priceIdChunk, chunkIndex)));
|
|
118
124
|
}
|
|
119
125
|
async updatePriceFeedChunk(priceIds, chunkIndex) {
|
|
120
126
|
try {
|
|
121
127
|
const priceFeedUpdateObject = await this.getPriceFeedUpdateObject(priceIds);
|
|
122
128
|
const updateFeeQueryResponse = await this.getUpdateFee(priceFeedUpdateObject.update_price_feeds.data);
|
|
123
129
|
const wallet = this.getWallet(chunkIndex);
|
|
124
|
-
const msg =
|
|
130
|
+
const msg = _sdkts.MsgExecuteContract.fromJSON({
|
|
125
131
|
sender: wallet.toAddress().toBech32(),
|
|
126
132
|
contractAddress: this.pythContractAddress,
|
|
127
133
|
msg: priceFeedUpdateObject,
|
|
128
|
-
funds: [
|
|
134
|
+
funds: [
|
|
135
|
+
updateFeeQueryResponse
|
|
136
|
+
]
|
|
129
137
|
});
|
|
130
138
|
const rs = await this.signAndBroadcastMsg(msg, chunkIndex);
|
|
131
|
-
this.logger.info({
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
139
|
+
this.logger.info({
|
|
140
|
+
hash: rs.txHash
|
|
141
|
+
}, `Successfully broadcasted txHash for chunk ${chunkIndex}`);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
if (error.message.match(/account inj[a-zA-Z0-9]+ not found/) !== null) {
|
|
144
|
+
this.logger.error(error, `Account not found for chunk ${chunkIndex}`);
|
|
136
145
|
throw new Error("Please check the mnemonic");
|
|
137
146
|
}
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
this.logger.error(err, `Insufficient funds for chunk ${chunkIndex}`);
|
|
147
|
+
if (error.message.match(/insufficient/) !== null && error.message.match(/funds/) !== null) {
|
|
148
|
+
this.logger.error(error, `Insufficient funds for chunk ${chunkIndex}`);
|
|
141
149
|
throw new Error("Insufficient funds");
|
|
142
150
|
}
|
|
143
|
-
this.logger.error(
|
|
151
|
+
this.logger.error(error, `Error executing messages for chunk ${chunkIndex}`);
|
|
144
152
|
}
|
|
145
153
|
}
|
|
146
154
|
/**
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
async getStdFee(msg, index) {
|
|
155
|
+
* Get the fee for the transaction (using simulation).
|
|
156
|
+
*
|
|
157
|
+
* We also apply a multiplier to the gas used to apply a small
|
|
158
|
+
* buffer to the gas that'll be used.
|
|
159
|
+
*/ async getStdFee(msg, index) {
|
|
153
160
|
const wallet = this.getWallet(index);
|
|
154
161
|
const injectiveAddress = wallet.toAddress().toBech32();
|
|
155
162
|
const account = this.accounts[injectiveAddress];
|
|
156
163
|
if (!account) {
|
|
157
164
|
throw new Error("Account not found");
|
|
158
165
|
}
|
|
159
|
-
const { txRaw: simulateTxRaw } = (0,
|
|
166
|
+
const { txRaw: simulateTxRaw } = (0, _sdkts.createTransactionFromMsg)({
|
|
160
167
|
sequence: account.baseAccount.sequence,
|
|
161
168
|
accountNumber: account.baseAccount.accountNumber,
|
|
162
169
|
message: msg,
|
|
163
170
|
chainId: this.chainConfig.chainId,
|
|
164
|
-
pubKey: wallet.toPublicKey().toBase64()
|
|
171
|
+
pubKey: wallet.toPublicKey().toBase64()
|
|
165
172
|
});
|
|
166
173
|
try {
|
|
167
|
-
const result = await new
|
|
168
|
-
const gas = (result.gasInfo.gasUsed * this.chainConfig.gasMultiplier).toFixed();
|
|
174
|
+
const result = await new _sdkts.TxGrpcApi(this.grpcEndpoint).simulate(simulateTxRaw);
|
|
175
|
+
const gas = (result.gasInfo.gasUsed * this.chainConfig.gasMultiplier).toFixed(0);
|
|
169
176
|
const fee = {
|
|
170
177
|
amount: [
|
|
171
178
|
{
|
|
172
179
|
denom: "inj",
|
|
173
|
-
amount: (Number(gas) * this.chainConfig.gasPrice).toFixed()
|
|
174
|
-
}
|
|
180
|
+
amount: (Number(gas) * this.chainConfig.gasPrice).toFixed(0)
|
|
181
|
+
}
|
|
175
182
|
],
|
|
176
|
-
gas
|
|
183
|
+
gas
|
|
177
184
|
};
|
|
178
185
|
return fee;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
throw err;
|
|
186
|
+
} catch (error) {
|
|
187
|
+
this.logger.error(error, `Error getting std fee`);
|
|
188
|
+
throw error;
|
|
183
189
|
}
|
|
184
190
|
}
|
|
185
191
|
/**
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
async getPriceFeedUpdateObject(priceIds) {
|
|
192
|
+
* Get the latest VAAs for updatePriceFeed and then push them
|
|
193
|
+
*/ async getPriceFeedUpdateObject(priceIds) {
|
|
189
194
|
try {
|
|
190
195
|
const response = await this.hermesClient.getLatestPriceUpdates(priceIds, {
|
|
191
196
|
encoding: "base64",
|
|
192
|
-
ignoreInvalidPriceIds: true
|
|
197
|
+
ignoreInvalidPriceIds: true
|
|
193
198
|
});
|
|
194
199
|
const vaas = response.binary.data;
|
|
195
200
|
return {
|
|
196
201
|
update_price_feeds: {
|
|
197
|
-
data: vaas
|
|
198
|
-
}
|
|
202
|
+
data: vaas
|
|
203
|
+
}
|
|
199
204
|
};
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
throw err;
|
|
205
|
+
} catch (error) {
|
|
206
|
+
this.logger.error(error, `Error fetching the latest vaas to push`);
|
|
207
|
+
throw error;
|
|
204
208
|
}
|
|
205
209
|
}
|
|
206
210
|
/**
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
async getUpdateFee(vaas) {
|
|
211
|
+
* Get the update fee for the given VAAs (i.e the fee that is paid to the pyth contract)
|
|
212
|
+
*/ async getUpdateFee(vaas) {
|
|
210
213
|
try {
|
|
211
|
-
const api = new
|
|
214
|
+
const api = new _sdkts.ChainGrpcWasmApi(this.grpcEndpoint);
|
|
212
215
|
const { data } = await api.fetchSmartContractState(this.pythContractAddress, Buffer.from(JSON.stringify({
|
|
213
216
|
get_update_fee: {
|
|
214
|
-
vaas
|
|
215
|
-
}
|
|
217
|
+
vaas
|
|
218
|
+
}
|
|
216
219
|
})).toString("base64"));
|
|
217
220
|
const json = Buffer.from(data).toString();
|
|
221
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
218
222
|
return JSON.parse(json);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
this.logger.error(err, `Error fetching update fee.`);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
this.logger.error(error, `Error fetching update fee.`);
|
|
222
225
|
// Throwing an error because it is likely an RPC issue
|
|
223
|
-
throw
|
|
226
|
+
throw error;
|
|
224
227
|
}
|
|
225
228
|
}
|
|
226
229
|
}
|
|
227
|
-
exports.InjectivePricePusher = InjectivePricePusher;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { HexString
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import type { HexString } from "@pythnetwork/hermes-client";
|
|
2
|
+
import { HermesClient } from "@pythnetwork/hermes-client";
|
|
3
|
+
import type { Logger } from "pino";
|
|
4
|
+
import type { PriceItem, PriceInfo, IPricePusher } from "../interface.js";
|
|
5
|
+
import { ChainPriceListener } from "../interface.js";
|
|
6
|
+
import type { DurationInSeconds } from "../utils.js";
|
|
5
7
|
type InjectiveConfig = {
|
|
6
8
|
chainId: string;
|
|
7
9
|
gasMultiplier: number;
|
|
@@ -24,7 +26,7 @@ export declare class InjectivePricePusher implements IPricePusher {
|
|
|
24
26
|
private logger;
|
|
25
27
|
private mnemonic;
|
|
26
28
|
private chainConfig;
|
|
27
|
-
private accounts;
|
|
29
|
+
private accounts;
|
|
28
30
|
constructor(hermesClient: HermesClient, pythContractAddress: string, grpcEndpoint: string, logger: Logger, mnemonic: string, chainConfig?: Partial<InjectiveConfig>);
|
|
29
31
|
private getWallet;
|
|
30
32
|
private signAndBroadcastMsg;
|
|
@@ -47,4 +49,3 @@ export declare class InjectivePricePusher implements IPricePusher {
|
|
|
47
49
|
private getUpdateFee;
|
|
48
50
|
}
|
|
49
51
|
export {};
|
|
50
|
-
//# sourceMappingURL=injective.d.ts.map
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get BaseBalanceTracker () {
|
|
13
|
+
return BaseBalanceTracker;
|
|
14
|
+
},
|
|
15
|
+
get ChainPriceListener () {
|
|
16
|
+
return ChainPriceListener;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
20
|
+
if (typeof WeakMap !== "function") return null;
|
|
21
|
+
var cacheBabelInterop = new WeakMap();
|
|
22
|
+
var cacheNodeInterop = new WeakMap();
|
|
23
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
24
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
25
|
+
})(nodeInterop);
|
|
26
|
+
}
|
|
27
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
28
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
29
|
+
return obj;
|
|
30
|
+
}
|
|
31
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
32
|
+
return {
|
|
33
|
+
default: obj
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
37
|
+
if (cache && cache.has(obj)) {
|
|
38
|
+
return cache.get(obj);
|
|
39
|
+
}
|
|
40
|
+
var newObj = {
|
|
41
|
+
__proto__: null
|
|
42
|
+
};
|
|
43
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
44
|
+
for(var key in obj){
|
|
45
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
46
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
47
|
+
if (desc && (desc.get || desc.set)) {
|
|
48
|
+
Object.defineProperty(newObj, key, desc);
|
|
49
|
+
} else {
|
|
50
|
+
newObj[key] = obj[key];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
newObj.default = obj;
|
|
55
|
+
if (cache) {
|
|
56
|
+
cache.set(obj, newObj);
|
|
57
|
+
}
|
|
58
|
+
return newObj;
|
|
59
|
+
}
|
|
60
|
+
class ChainPriceListener {
|
|
61
|
+
pollingFrequency;
|
|
62
|
+
priceItems;
|
|
63
|
+
latestPriceInfo;
|
|
64
|
+
priceIdToAlias;
|
|
65
|
+
constructor(pollingFrequency, priceItems){
|
|
66
|
+
this.pollingFrequency = pollingFrequency;
|
|
67
|
+
this.priceItems = priceItems;
|
|
68
|
+
this.latestPriceInfo = new Map();
|
|
69
|
+
this.priceIdToAlias = new Map(priceItems.map(({ id, alias })=>[
|
|
70
|
+
id,
|
|
71
|
+
alias
|
|
72
|
+
]));
|
|
73
|
+
}
|
|
74
|
+
async start() {
|
|
75
|
+
setInterval(()=>void this.pollPrices(), this.pollingFrequency * 1000);
|
|
76
|
+
await this.pollPrices();
|
|
77
|
+
}
|
|
78
|
+
async pollPrices() {
|
|
79
|
+
for (const { id: priceId } of this.priceItems){
|
|
80
|
+
const currentPriceInfo = await this.getOnChainPriceInfo(priceId);
|
|
81
|
+
if (currentPriceInfo !== undefined) {
|
|
82
|
+
this.updateLatestPriceInfo(priceId, currentPriceInfo);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
updateLatestPriceInfo(priceId, observedPrice) {
|
|
87
|
+
const cachedLatestPriceInfo = this.getLatestPriceInfo(priceId);
|
|
88
|
+
// Ignore the observed price if the cache already has newer
|
|
89
|
+
// price. This could happen because we are using polling and
|
|
90
|
+
// subscription at the same time.
|
|
91
|
+
if (cachedLatestPriceInfo !== undefined && cachedLatestPriceInfo.publishTime > observedPrice.publishTime) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
this.latestPriceInfo.set(priceId, observedPrice);
|
|
95
|
+
}
|
|
96
|
+
// Should return undefined only when the price does not exist.
|
|
97
|
+
getLatestPriceInfo(priceId) {
|
|
98
|
+
return this.latestPriceInfo.get(priceId);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
class BaseBalanceTracker {
|
|
102
|
+
address;
|
|
103
|
+
network;
|
|
104
|
+
updateInterval;
|
|
105
|
+
metrics;
|
|
106
|
+
logger;
|
|
107
|
+
isRunning = false;
|
|
108
|
+
constructor(config){
|
|
109
|
+
this.address = config.address;
|
|
110
|
+
this.network = config.network;
|
|
111
|
+
this.updateInterval = config.updateInterval;
|
|
112
|
+
this.metrics = config.metrics;
|
|
113
|
+
this.logger = config.logger;
|
|
114
|
+
}
|
|
115
|
+
async start() {
|
|
116
|
+
if (this.isRunning) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
this.isRunning = true;
|
|
120
|
+
// Initial balance update
|
|
121
|
+
await this.updateBalance();
|
|
122
|
+
// Start the update loop
|
|
123
|
+
void this.startUpdateLoop();
|
|
124
|
+
}
|
|
125
|
+
async startUpdateLoop() {
|
|
126
|
+
// We're using dynamic import to avoid circular dependencies
|
|
127
|
+
const { sleep } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("./utils.cjs")));
|
|
128
|
+
// Run in a loop to regularly update the balance
|
|
129
|
+
for(;;){
|
|
130
|
+
// Wait first, since we already did the initial update in start()
|
|
131
|
+
await sleep(this.updateInterval * 1000);
|
|
132
|
+
// Only continue if we're still running
|
|
133
|
+
if (!this.isRunning) {
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
await this.updateBalance();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
stop() {
|
|
140
|
+
this.isRunning = false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { HexString, UnixTimestamp } from "@pythnetwork/hermes-client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import type { HexString, UnixTimestamp } from "@pythnetwork/hermes-client";
|
|
2
|
+
import type { Logger } from "pino";
|
|
3
|
+
import { PricePusherMetrics } from "./metrics.js";
|
|
4
|
+
import type { DurationInSeconds } from "./utils.js";
|
|
5
5
|
export type PriceItem = {
|
|
6
6
|
id: HexString;
|
|
7
7
|
alias: string;
|
|
@@ -11,10 +11,10 @@ export type PriceInfo = {
|
|
|
11
11
|
conf: string;
|
|
12
12
|
publishTime: UnixTimestamp;
|
|
13
13
|
};
|
|
14
|
-
export
|
|
14
|
+
export type IPriceListener = {
|
|
15
15
|
start(): Promise<void>;
|
|
16
16
|
getLatestPriceInfo(priceId: string): PriceInfo | undefined;
|
|
17
|
-
}
|
|
17
|
+
};
|
|
18
18
|
export declare abstract class ChainPriceListener implements IPriceListener {
|
|
19
19
|
private pollingFrequency;
|
|
20
20
|
protected priceItems: PriceItem[];
|
|
@@ -27,13 +27,13 @@ export declare abstract class ChainPriceListener implements IPriceListener {
|
|
|
27
27
|
getLatestPriceInfo(priceId: string): PriceInfo | undefined;
|
|
28
28
|
abstract getOnChainPriceInfo(priceId: HexString): Promise<PriceInfo | undefined>;
|
|
29
29
|
}
|
|
30
|
-
export
|
|
30
|
+
export type IPricePusher = {
|
|
31
31
|
updatePriceFeed(priceIds: string[], pubTimesToPush: UnixTimestamp[]): Promise<void>;
|
|
32
|
-
}
|
|
32
|
+
};
|
|
33
33
|
/**
|
|
34
34
|
* Common configuration properties for all balance trackers
|
|
35
35
|
*/
|
|
36
|
-
export
|
|
36
|
+
export type BaseBalanceTrackerConfig = {
|
|
37
37
|
/** Address of the wallet to track */
|
|
38
38
|
address: string;
|
|
39
39
|
/** Name/ID of the network/chain */
|
|
@@ -44,12 +44,12 @@ export interface BaseBalanceTrackerConfig {
|
|
|
44
44
|
metrics: PricePusherMetrics;
|
|
45
45
|
/** Logger instance */
|
|
46
46
|
logger: Logger;
|
|
47
|
-
}
|
|
47
|
+
};
|
|
48
48
|
/**
|
|
49
49
|
* Interface for all balance trackers to implement
|
|
50
50
|
* Each chain will have its own implementation of this interface
|
|
51
51
|
*/
|
|
52
|
-
export
|
|
52
|
+
export type IBalanceTracker = {
|
|
53
53
|
/**
|
|
54
54
|
* Start tracking the wallet balance
|
|
55
55
|
*/
|
|
@@ -58,7 +58,7 @@ export interface IBalanceTracker {
|
|
|
58
58
|
* Stop tracking the wallet balance
|
|
59
59
|
*/
|
|
60
60
|
stop(): void;
|
|
61
|
-
}
|
|
61
|
+
};
|
|
62
62
|
/**
|
|
63
63
|
* Abstract base class that implements common functionality for all balance trackers
|
|
64
64
|
*/
|
|
@@ -79,4 +79,3 @@ export declare abstract class BaseBalanceTracker implements IBalanceTracker {
|
|
|
79
79
|
protected abstract updateBalance(): Promise<void>;
|
|
80
80
|
stop(): void;
|
|
81
81
|
}
|
|
82
|
-
//# sourceMappingURL=interface.d.ts.map
|