@pythnetwork/price-pusher 10.2.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.
Files changed (127) hide show
  1. package/{lib/aptos/aptos.js → dist/aptos/aptos.cjs} +80 -76
  2. package/{lib → dist}/aptos/aptos.d.ts +5 -5
  3. package/{lib/aptos/balance-tracker.js → dist/aptos/balance-tracker.cjs} +37 -25
  4. package/{lib → dist}/aptos/balance-tracker.d.ts +9 -9
  5. package/dist/aptos/command.cjs +161 -0
  6. package/{lib → dist}/aptos/command.d.ts +1 -2
  7. package/dist/common.cjs +4 -0
  8. package/{lib → dist}/common.d.ts +0 -1
  9. package/{lib/controller.js → dist/controller.cjs} +35 -33
  10. package/{lib → dist}/controller.d.ts +5 -6
  11. package/dist/evm/balance-tracker.cjs +58 -0
  12. package/{lib → dist}/evm/balance-tracker.d.ts +10 -10
  13. package/dist/evm/command.cjs +205 -0
  14. package/{lib → dist}/evm/command.d.ts +1 -2
  15. package/dist/evm/custom-gas-station.cjs +54 -0
  16. package/{lib → dist}/evm/custom-gas-station.d.ts +1 -2
  17. package/dist/evm/evm.cjs +287 -0
  18. package/{lib → dist}/evm/evm.d.ts +8 -7
  19. package/{lib/evm/pyth-abi.js → dist/evm/pyth-abi.cjs} +181 -160
  20. package/{lib → dist}/evm/pyth-abi.d.ts +0 -1
  21. package/dist/evm/pyth-contract.cjs +17 -0
  22. package/{lib → dist}/evm/pyth-contract.d.ts +3 -4
  23. package/dist/evm/super-wallet.cjs +90 -0
  24. package/{lib → dist}/evm/super-wallet.d.ts +1 -2
  25. package/dist/fuel/command.cjs +135 -0
  26. package/{lib → dist}/fuel/command.d.ts +1 -2
  27. package/dist/fuel/fuel.cjs +108 -0
  28. package/{lib → dist}/fuel/fuel.d.ts +5 -5
  29. package/dist/index.cjs +25 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/injective/command.cjs +150 -0
  32. package/{lib → dist}/injective/command.d.ts +1 -2
  33. package/{lib/injective/injective.js → dist/injective/injective.cjs} +100 -98
  34. package/{lib → dist}/injective/injective.d.ts +7 -6
  35. package/dist/interface.cjs +142 -0
  36. package/{lib → dist}/interface.d.ts +12 -13
  37. package/dist/metrics.cjs +218 -0
  38. package/{lib → dist}/metrics.d.ts +10 -11
  39. package/dist/near/command.cjs +129 -0
  40. package/{lib → dist}/near/command.d.ts +1 -2
  41. package/dist/near/near.cjs +183 -0
  42. package/{lib → dist}/near/near.d.ts +5 -5
  43. package/dist/options.cjs +132 -0
  44. package/{lib → dist}/options.d.ts +1 -2
  45. package/dist/package.json +1 -0
  46. package/dist/price-config.cjs +104 -0
  47. package/{lib → dist}/price-config.d.ts +5 -6
  48. package/{lib/pyth-price-listener.js → dist/pyth-price-listener.cjs} +30 -24
  49. package/{lib → dist}/pyth-price-listener.d.ts +4 -4
  50. package/dist/solana/balance-tracker.cjs +60 -0
  51. package/{lib → dist}/solana/balance-tracker.d.ts +9 -9
  52. package/dist/solana/command.cjs +259 -0
  53. package/{lib → dist}/solana/command.d.ts +2 -3
  54. package/{lib/solana/solana.js → dist/solana/solana.cjs} +90 -78
  55. package/{lib → dist}/solana/solana.d.ts +6 -6
  56. package/dist/sui/balance-tracker.cjs +58 -0
  57. package/{lib → dist}/sui/balance-tracker.d.ts +9 -9
  58. package/dist/sui/command.cjs +190 -0
  59. package/{lib → dist}/sui/command.d.ts +1 -2
  60. package/{lib/sui/sui.js → dist/sui/sui.cjs} +145 -133
  61. package/{lib → dist}/sui/sui.d.ts +7 -8
  62. package/dist/ton/command.cjs +137 -0
  63. package/{lib → dist}/ton/command.d.ts +1 -2
  64. package/dist/ton/ton.cjs +103 -0
  65. package/{lib → dist}/ton/ton.d.ts +7 -6
  66. package/dist/utils.cjs +102 -0
  67. package/{lib → dist}/utils.d.ts +4 -4
  68. package/package.json +161 -20
  69. package/lib/aptos/aptos.d.ts.map +0 -1
  70. package/lib/aptos/balance-tracker.d.ts.map +0 -1
  71. package/lib/aptos/command.d.ts.map +0 -1
  72. package/lib/aptos/command.js +0 -126
  73. package/lib/common.d.ts.map +0 -1
  74. package/lib/common.js +0 -2
  75. package/lib/controller.d.ts.map +0 -1
  76. package/lib/evm/balance-tracker.d.ts.map +0 -1
  77. package/lib/evm/balance-tracker.js +0 -49
  78. package/lib/evm/command.d.ts.map +0 -1
  79. package/lib/evm/command.js +0 -178
  80. package/lib/evm/custom-gas-station.d.ts.map +0 -1
  81. package/lib/evm/custom-gas-station.js +0 -40
  82. package/lib/evm/evm.d.ts.map +0 -1
  83. package/lib/evm/evm.js +0 -270
  84. package/lib/evm/pyth-abi.d.ts.map +0 -1
  85. package/lib/evm/pyth-contract.d.ts.map +0 -1
  86. package/lib/evm/pyth-contract.js +0 -11
  87. package/lib/evm/super-wallet.d.ts.map +0 -1
  88. package/lib/evm/super-wallet.js +0 -73
  89. package/lib/fuel/command.d.ts.map +0 -1
  90. package/lib/fuel/command.js +0 -98
  91. package/lib/fuel/fuel.d.ts.map +0 -1
  92. package/lib/fuel/fuel.js +0 -101
  93. package/lib/index.d.ts +0 -3
  94. package/lib/index.d.ts.map +0 -1
  95. package/lib/index.js +0 -34
  96. package/lib/injective/command.d.ts.map +0 -1
  97. package/lib/injective/command.js +0 -119
  98. package/lib/injective/injective.d.ts.map +0 -1
  99. package/lib/interface.d.ts.map +0 -1
  100. package/lib/interface.js +0 -122
  101. package/lib/metrics.d.ts.map +0 -1
  102. package/lib/metrics.js +0 -152
  103. package/lib/near/command.d.ts.map +0 -1
  104. package/lib/near/command.js +0 -103
  105. package/lib/near/near.d.ts.map +0 -1
  106. package/lib/near/near.js +0 -168
  107. package/lib/options.d.ts.map +0 -1
  108. package/lib/options.js +0 -84
  109. package/lib/price-config.d.ts.map +0 -1
  110. package/lib/price-config.js +0 -114
  111. package/lib/pyth-price-listener.d.ts.map +0 -1
  112. package/lib/solana/balance-tracker.d.ts.map +0 -1
  113. package/lib/solana/balance-tracker.js +0 -51
  114. package/lib/solana/command.d.ts.map +0 -1
  115. package/lib/solana/command.js +0 -223
  116. package/lib/solana/solana.d.ts.map +0 -1
  117. package/lib/sui/balance-tracker.d.ts.map +0 -1
  118. package/lib/sui/balance-tracker.js +0 -49
  119. package/lib/sui/command.d.ts.map +0 -1
  120. package/lib/sui/command.js +0 -160
  121. package/lib/sui/sui.d.ts.map +0 -1
  122. package/lib/ton/command.d.ts.map +0 -1
  123. package/lib/ton/command.js +0 -99
  124. package/lib/ton/ton.d.ts.map +0 -1
  125. package/lib/ton/ton.js +0 -97
  126. package/lib/utils.d.ts.map +0 -1
  127. package/lib/utils.js +0 -61
@@ -0,0 +1,218 @@
1
+ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/no-misused-promises */ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "PricePusherMetrics", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return PricePusherMetrics;
9
+ }
10
+ });
11
+ const _express = /*#__PURE__*/ _interop_require_default(require("express"));
12
+ const _promclient = require("prom-client");
13
+ const _priceconfig = require("./price-config.cjs");
14
+ function _interop_require_default(obj) {
15
+ return obj && obj.__esModule ? obj : {
16
+ default: obj
17
+ };
18
+ }
19
+ class PricePusherMetrics {
20
+ registry;
21
+ server;
22
+ logger;
23
+ // Metrics for price feed updates
24
+ lastPublishedTime;
25
+ priceUpdateAttempts;
26
+ priceFeedsTotal;
27
+ sourceTimestamp;
28
+ configuredTimeDifference;
29
+ sourcePriceValue;
30
+ targetPriceValue;
31
+ // Wallet metrics
32
+ walletBalance;
33
+ constructor(logger){
34
+ this.logger = logger;
35
+ this.registry = new _promclient.Registry();
36
+ this.server = (0, _express.default)();
37
+ // Register the default metrics (memory, CPU, etc.)
38
+ this.registry.setDefaultLabels({
39
+ app: "price_pusher"
40
+ });
41
+ // Create metrics
42
+ this.lastPublishedTime = new _promclient.Gauge({
43
+ name: "pyth_price_last_published_time",
44
+ help: "The last published time of a price feed in unix timestamp",
45
+ labelNames: [
46
+ "price_id",
47
+ "alias"
48
+ ],
49
+ registers: [
50
+ this.registry
51
+ ]
52
+ });
53
+ this.priceUpdateAttempts = new _promclient.Counter({
54
+ name: "pyth_price_update_attempts_total",
55
+ help: "Total number of price update attempts with their trigger condition and status",
56
+ labelNames: [
57
+ "price_id",
58
+ "alias",
59
+ "trigger",
60
+ "status"
61
+ ],
62
+ registers: [
63
+ this.registry
64
+ ]
65
+ });
66
+ this.priceFeedsTotal = new _promclient.Gauge({
67
+ name: "pyth_price_feeds_total",
68
+ help: "Total number of price feeds being monitored",
69
+ registers: [
70
+ this.registry
71
+ ]
72
+ });
73
+ this.sourceTimestamp = new _promclient.Gauge({
74
+ name: "pyth_source_timestamp",
75
+ help: "Latest source chain price publish timestamp",
76
+ labelNames: [
77
+ "price_id",
78
+ "alias"
79
+ ],
80
+ registers: [
81
+ this.registry
82
+ ]
83
+ });
84
+ this.configuredTimeDifference = new _promclient.Gauge({
85
+ name: "pyth_configured_time_difference",
86
+ help: "Configured time difference threshold between source and target chains",
87
+ labelNames: [
88
+ "price_id",
89
+ "alias"
90
+ ],
91
+ registers: [
92
+ this.registry
93
+ ]
94
+ });
95
+ this.sourcePriceValue = new _promclient.Gauge({
96
+ name: "pyth_source_price",
97
+ help: "Latest price value from Pyth source",
98
+ labelNames: [
99
+ "price_id",
100
+ "alias"
101
+ ],
102
+ registers: [
103
+ this.registry
104
+ ]
105
+ });
106
+ this.targetPriceValue = new _promclient.Gauge({
107
+ name: "pyth_target_price",
108
+ help: "Latest price value from target chain",
109
+ labelNames: [
110
+ "price_id",
111
+ "alias"
112
+ ],
113
+ registers: [
114
+ this.registry
115
+ ]
116
+ });
117
+ // Wallet balance metric
118
+ this.walletBalance = new _promclient.Gauge({
119
+ name: "pyth_wallet_balance",
120
+ help: "Current wallet balance of the price pusher in native token units",
121
+ labelNames: [
122
+ "wallet_address",
123
+ "network"
124
+ ],
125
+ registers: [
126
+ this.registry
127
+ ]
128
+ });
129
+ // Setup the metrics endpoint
130
+ this.server.get("/metrics", async (_, res)=>{
131
+ res.set("Content-Type", this.registry.contentType);
132
+ res.end(await this.registry.metrics());
133
+ });
134
+ }
135
+ // Start the metrics server
136
+ start(port) {
137
+ this.server.listen(port, ()=>{
138
+ this.logger.info(`Metrics server started on port ${port}`);
139
+ });
140
+ }
141
+ // Record a successful price update
142
+ recordPriceUpdate(priceId, alias, trigger = "yes") {
143
+ this.priceUpdateAttempts.inc({
144
+ price_id: priceId,
145
+ alias,
146
+ trigger: trigger.toLowerCase(),
147
+ status: "success"
148
+ });
149
+ }
150
+ // Record update condition status (YES/NO/EARLY)
151
+ recordUpdateCondition(priceId, alias, condition) {
152
+ const triggerLabel = _priceconfig.UpdateCondition[condition].toLowerCase();
153
+ // Only record as 'skipped' when the condition is NO
154
+ if (condition === _priceconfig.UpdateCondition.NO) {
155
+ this.priceUpdateAttempts.inc({
156
+ price_id: priceId,
157
+ alias,
158
+ trigger: triggerLabel,
159
+ status: "skipped"
160
+ });
161
+ }
162
+ // YES and EARLY don't increment the counter here - they'll be counted
163
+ // when recordPriceUpdate or recordPriceUpdateError is called
164
+ }
165
+ // Record a price update error
166
+ recordPriceUpdateError(priceId, alias, trigger = "yes") {
167
+ this.priceUpdateAttempts.inc({
168
+ price_id: priceId,
169
+ alias,
170
+ trigger: trigger.toLowerCase(),
171
+ status: "error"
172
+ });
173
+ }
174
+ // Set the number of price feeds
175
+ setPriceFeedsTotal(count) {
176
+ this.priceFeedsTotal.set(count);
177
+ }
178
+ // Update source, target and configured time difference timestamps
179
+ updateTimestamps(priceId, alias, targetLatestPricePublishTime, sourceLatestPricePublishTime, priceConfigTimeDifference) {
180
+ this.sourceTimestamp.set({
181
+ price_id: priceId,
182
+ alias
183
+ }, sourceLatestPricePublishTime);
184
+ this.lastPublishedTime.set({
185
+ price_id: priceId,
186
+ alias
187
+ }, targetLatestPricePublishTime);
188
+ this.configuredTimeDifference.set({
189
+ price_id: priceId,
190
+ alias
191
+ }, priceConfigTimeDifference);
192
+ }
193
+ // Update price values
194
+ updatePriceValues(priceId, alias, sourcePrice, targetPrice) {
195
+ if (sourcePrice !== undefined) {
196
+ this.sourcePriceValue.set({
197
+ price_id: priceId,
198
+ alias
199
+ }, Number(sourcePrice));
200
+ }
201
+ if (targetPrice !== undefined) {
202
+ this.targetPriceValue.set({
203
+ price_id: priceId,
204
+ alias
205
+ }, Number(targetPrice));
206
+ }
207
+ }
208
+ // Update wallet balance
209
+ updateWalletBalance(walletAddress, network, balance) {
210
+ // Convert to number for compatibility with prometheus
211
+ const balanceNum = typeof balance === "bigint" ? Number(balance) / 1e18 : balance;
212
+ this.walletBalance.set({
213
+ wallet_address: walletAddress,
214
+ network
215
+ }, balanceNum);
216
+ this.logger.debug(`Updated wallet balance metric: ${walletAddress} = ${balanceNum}`);
217
+ }
218
+ }
@@ -1,18 +1,18 @@
1
+ import type { Logger } from "pino";
1
2
  import { Counter, Gauge } from "prom-client";
2
- import { Logger } from "pino";
3
- import { UpdateCondition } from "./price-config";
3
+ import { UpdateCondition } from "./price-config.js";
4
4
  export declare class PricePusherMetrics {
5
5
  private registry;
6
6
  private server;
7
7
  private logger;
8
- lastPublishedTime: Gauge<string>;
9
- priceUpdateAttempts: Counter<string>;
10
- priceFeedsTotal: Gauge<string>;
11
- sourceTimestamp: Gauge<string>;
12
- configuredTimeDifference: Gauge<string>;
13
- sourcePriceValue: Gauge<string>;
14
- targetPriceValue: Gauge<string>;
15
- walletBalance: Gauge<string>;
8
+ lastPublishedTime: Gauge;
9
+ priceUpdateAttempts: Counter;
10
+ priceFeedsTotal: Gauge;
11
+ sourceTimestamp: Gauge;
12
+ configuredTimeDifference: Gauge;
13
+ sourcePriceValue: Gauge;
14
+ targetPriceValue: Gauge;
15
+ walletBalance: Gauge;
16
16
  constructor(logger: Logger);
17
17
  start(port: number): void;
18
18
  recordPriceUpdate(priceId: string, alias: string, trigger?: string): void;
@@ -23,4 +23,3 @@ export declare class PricePusherMetrics {
23
23
  updatePriceValues(priceId: string, alias: string, sourcePrice: string | undefined, targetPrice: string | undefined): void;
24
24
  updateWalletBalance(walletAddress: string, network: string, balance: bigint | number): void;
25
25
  }
26
- //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1,129 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-explicit-any */ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return _default;
9
+ }
10
+ });
11
+ const _hermesclient = require("@pythnetwork/hermes-client");
12
+ const _pino = require("pino");
13
+ const _controller = require("../controller.cjs");
14
+ const _options = /*#__PURE__*/ _interop_require_wildcard(require("../options.cjs"));
15
+ const _priceconfig = require("../price-config.cjs");
16
+ const _pythpricelistener = require("../pyth-price-listener.cjs");
17
+ const _near = require("./near.cjs");
18
+ const _utils = require("../utils.cjs");
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
+ const _default = {
61
+ command: "near",
62
+ describe: "run price pusher for near",
63
+ builder: {
64
+ "node-url": {
65
+ description: "NEAR RPC API url. used to make JSON RPC calls to interact with NEAR.",
66
+ type: "string",
67
+ required: true
68
+ },
69
+ network: {
70
+ description: "testnet or mainnet.",
71
+ type: "string",
72
+ required: true
73
+ },
74
+ "account-id": {
75
+ description: "payer account identifier.",
76
+ type: "string",
77
+ required: true
78
+ },
79
+ "private-key-path": {
80
+ description: "path to payer private key file.",
81
+ type: "string",
82
+ required: false
83
+ },
84
+ ..._options.priceConfigFile,
85
+ ..._options.priceServiceEndpoint,
86
+ ..._options.pythContractAddress,
87
+ ..._options.pollingFrequency,
88
+ ..._options.pushingFrequency,
89
+ ..._options.logLevel,
90
+ ..._options.controllerLogLevel
91
+ },
92
+ handler: async function(argv) {
93
+ // FIXME: type checks for this
94
+ const { nodeUrl, network, accountId, privateKeyPath, priceConfigFile, priceServiceEndpoint, pythContractAddress, pushingFrequency, pollingFrequency, logLevel, controllerLogLevel } = argv;
95
+ const logger = (0, _pino.pino)({
96
+ level: logLevel
97
+ });
98
+ const priceConfigs = (0, _priceconfig.readPriceConfigFile)(priceConfigFile);
99
+ const hermesClient = new _hermesclient.HermesClient(priceServiceEndpoint);
100
+ let priceItems = priceConfigs.map(({ id, alias })=>({
101
+ id,
102
+ alias
103
+ }));
104
+ // Better to filter out invalid price items before creating the pyth listener
105
+ const { existingPriceItems, invalidPriceItems } = await (0, _utils.filterInvalidPriceItems)(hermesClient, priceItems);
106
+ if (invalidPriceItems.length > 0) {
107
+ logger.error(`Invalid price id submitted for: ${invalidPriceItems.map(({ alias })=>alias).join(", ")}`);
108
+ }
109
+ priceItems = existingPriceItems;
110
+ const pythListener = new _pythpricelistener.PythPriceListener(hermesClient, priceItems, logger);
111
+ const nearAccount = new _near.NearAccount(network, accountId, nodeUrl, privateKeyPath, pythContractAddress);
112
+ const nearListener = new _near.NearPriceListener(nearAccount, priceItems, logger.child({
113
+ module: "NearPriceListener"
114
+ }), {
115
+ pollingFrequency
116
+ });
117
+ const nearPusher = new _near.NearPricePusher(nearAccount, hermesClient, logger.child({
118
+ module: "NearPricePusher"
119
+ }));
120
+ const controller = new _controller.Controller(priceConfigs, pythListener, nearListener, nearPusher, logger.child({
121
+ module: "Controller"
122
+ }, {
123
+ level: controllerLogLevel
124
+ }), {
125
+ pushingFrequency
126
+ });
127
+ void controller.start();
128
+ }
129
+ };
@@ -1,4 +1,4 @@
1
- import { Options } from "yargs";
1
+ import type { Options } from "yargs";
2
2
  declare const _default: {
3
3
  command: string;
4
4
  describe: string;
@@ -18,4 +18,3 @@ declare const _default: {
18
18
  handler: (argv: any) => Promise<void>;
19
19
  };
20
20
  export default _default;
21
- //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1,183 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable unicorn/no-array-reduce */ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* 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 NearAccount () {
13
+ return NearAccount;
14
+ },
15
+ get NearPriceListener () {
16
+ return NearPriceListener;
17
+ },
18
+ get NearPricePusher () {
19
+ return NearPricePusher;
20
+ }
21
+ });
22
+ const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
23
+ const _nodeos = /*#__PURE__*/ _interop_require_default(require("node:os"));
24
+ const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
25
+ const _nearapijs = require("near-api-js");
26
+ const _key_stores = require("near-api-js/lib/key_stores");
27
+ const _interface = require("../interface.cjs");
28
+ function _interop_require_default(obj) {
29
+ return obj && obj.__esModule ? obj : {
30
+ default: obj
31
+ };
32
+ }
33
+ class NearPriceListener extends _interface.ChainPriceListener {
34
+ account;
35
+ logger;
36
+ constructor(account, priceItems, logger, config){
37
+ super(config.pollingFrequency, priceItems), this.account = account, this.logger = logger;
38
+ }
39
+ async getOnChainPriceInfo(priceId) {
40
+ try {
41
+ const priceRaw = await this.account.getPriceUnsafe(priceId);
42
+ this.logger.debug(`Polled a NEAR on chain price for feed ${this.priceIdToAlias.get(priceId)} (${priceId}) ${JSON.stringify(priceRaw)}.`);
43
+ return priceRaw ? {
44
+ conf: priceRaw.conf,
45
+ price: priceRaw.price,
46
+ publishTime: priceRaw.publish_time
47
+ } : undefined;
48
+ } catch (error) {
49
+ this.logger.error(error, `Polling on-chain price for ${priceId} failed.:`);
50
+ return undefined;
51
+ }
52
+ }
53
+ }
54
+ class NearPricePusher {
55
+ account;
56
+ hermesClient;
57
+ logger;
58
+ constructor(account, hermesClient, logger){
59
+ this.account = account;
60
+ this.hermesClient = hermesClient;
61
+ this.logger = logger;
62
+ }
63
+ async updatePriceFeed(priceIds, pubTimesToPush) {
64
+ if (priceIds.length === 0) {
65
+ return;
66
+ }
67
+ if (priceIds.length !== pubTimesToPush.length) throw new Error("Invalid arguments");
68
+ let priceFeedUpdateData;
69
+ try {
70
+ priceFeedUpdateData = await this.getPriceFeedsUpdateData(priceIds);
71
+ } catch (error) {
72
+ this.logger.error(error, "getPriceFeedsUpdateData failed");
73
+ return;
74
+ }
75
+ for (const data of priceFeedUpdateData){
76
+ let updateFee;
77
+ try {
78
+ updateFee = await this.account.getUpdateFeeEstimate(data);
79
+ this.logger.debug(`Update fee: ${updateFee}`);
80
+ } catch (error) {
81
+ this.logger.error(error, "getUpdateFeeEstimate failed");
82
+ continue;
83
+ }
84
+ try {
85
+ const outcome = await this.account.updatePriceFeeds(data, updateFee);
86
+ const failureMessages = [];
87
+ const is_success = Object.values(outcome.receipts_outcome).reduce((is_success, receipt)=>{
88
+ if (Object.prototype.hasOwnProperty.call(receipt.outcome.status, "Failure")) {
89
+ failureMessages.push(receipt.outcome.status);
90
+ return false;
91
+ }
92
+ return is_success;
93
+ }, true);
94
+ if (is_success) {
95
+ this.logger.info({
96
+ hash: outcome.transaction.hash
97
+ }, "updatePriceFeeds successful.");
98
+ } else {
99
+ this.logger.error({
100
+ failureMessages
101
+ }, "updatePriceFeeds failed");
102
+ }
103
+ } catch (error) {
104
+ this.logger.error(error, "updatePriceFeeds failed");
105
+ }
106
+ }
107
+ }
108
+ async getPriceFeedsUpdateData(priceIds) {
109
+ const response = await this.hermesClient.getLatestPriceUpdates(priceIds, {
110
+ encoding: "base64",
111
+ ignoreInvalidPriceIds: true
112
+ });
113
+ return response.binary.data;
114
+ }
115
+ }
116
+ class NearAccount {
117
+ pythAccountId;
118
+ account;
119
+ constructor(network, accountId, nodeUrl, privateKeyPath, pythAccountId){
120
+ this.pythAccountId = pythAccountId;
121
+ const connection = this.getConnection(network, accountId, nodeUrl, privateKeyPath);
122
+ this.account = new _nearapijs.Account(connection, accountId);
123
+ }
124
+ async getPriceUnsafe(priceId) {
125
+ return await this.account.viewFunction({
126
+ contractId: this.pythAccountId,
127
+ methodName: "get_price_unsafe",
128
+ args: {
129
+ price_identifier: priceId
130
+ }
131
+ });
132
+ }
133
+ async getUpdateFeeEstimate(data) {
134
+ return await this.account.viewFunction({
135
+ contractId: this.pythAccountId,
136
+ methodName: "get_update_fee_estimate",
137
+ args: {
138
+ data
139
+ }
140
+ });
141
+ }
142
+ async updatePriceFeeds(data, updateFee) {
143
+ return await this.account.functionCall({
144
+ contractId: this.pythAccountId,
145
+ methodName: "update_price_feeds",
146
+ args: {
147
+ data
148
+ },
149
+ gas: "300000000000000",
150
+ attachedDeposit: updateFee
151
+ });
152
+ }
153
+ getConnection(network, accountId, nodeUrl, privateKeyPath) {
154
+ const content = _nodefs.default.readFileSync(// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
155
+ privateKeyPath || _nodepath.default.join(_nodeos.default.homedir(), ".near-credentials", network, accountId + ".json"));
156
+ const accountInfo = JSON.parse(content.toString());
157
+ let privateKey = accountInfo.private_key;
158
+ if (!privateKey && accountInfo.secret_key) {
159
+ privateKey = accountInfo.secret_key;
160
+ }
161
+ if (accountInfo.account_id && privateKey) {
162
+ const keyPair = _nearapijs.KeyPair.fromString(privateKey);
163
+ const keyStore = new _key_stores.InMemoryKeyStore();
164
+ void keyStore.setKey(network, accountInfo.account_id, keyPair);
165
+ return _nearapijs.Connection.fromConfig({
166
+ networkId: network,
167
+ provider: {
168
+ type: "JsonRpcProvider",
169
+ args: {
170
+ url: nodeUrl
171
+ }
172
+ },
173
+ signer: {
174
+ type: "InMemorySigner",
175
+ keyStore
176
+ },
177
+ jsvmAccountId: `jsvm.${network}`
178
+ });
179
+ } else {
180
+ throw new Error("Invalid key file!");
181
+ }
182
+ }
183
+ }
@@ -1,8 +1,9 @@
1
- import { IPricePusher, PriceInfo, ChainPriceListener, PriceItem } from "../interface";
2
1
  import { HermesClient } from "@pythnetwork/hermes-client";
3
- import { DurationInSeconds } from "../utils";
4
- import { FinalExecutionOutcome } from "near-api-js/lib/providers/provider";
5
- import { Logger } from "pino";
2
+ import type { FinalExecutionOutcome } from "near-api-js/lib/providers/provider";
3
+ import type { Logger } from "pino";
4
+ import type { IPricePusher, PriceInfo, PriceItem } from "../interface.js";
5
+ import { ChainPriceListener } from "../interface.js";
6
+ import type { DurationInSeconds } from "../utils.js";
6
7
  export declare class NearPriceListener extends ChainPriceListener {
7
8
  private account;
8
9
  private logger;
@@ -28,4 +29,3 @@ export declare class NearAccount {
28
29
  updatePriceFeeds(data: string, updateFee: any): Promise<FinalExecutionOutcome>;
29
30
  private getConnection;
30
31
  }
31
- //# sourceMappingURL=near.d.ts.map