@pythnetwork/price-pusher 8.3.0 → 8.3.2
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/LICENSE +1 -1
- package/README.md +5 -1
- package/lib/index.js +2 -0
- package/lib/solana/solana.d.ts +3 -2
- package/lib/solana/solana.d.ts.map +1 -1
- package/lib/solana/solana.js +28 -7
- package/lib/ton/command.d.ts +20 -0
- package/lib/ton/command.d.ts.map +1 -0
- package/lib/ton/command.js +83 -0
- package/lib/ton/ton.d.ts +27 -0
- package/lib/ton/ton.d.ts.map +1 -0
- package/lib/ton/ton.js +93 -0
- package/package.json +8 -5
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -75,7 +75,11 @@ You can get the list of available price feeds from
|
|
|
75
75
|
|
|
76
76
|
Price pusher communicates with [Hermes][] price service to get the most recent price updates. Hermes listens to the
|
|
77
77
|
Pythnet and Wormhole network to get latest price updates, and serves REST and websocket APIs for consumers to fetch the
|
|
78
|
-
updates.
|
|
78
|
+
updates.
|
|
79
|
+
|
|
80
|
+
NOTE: It is recommended to use stable hermes endpoints. If you are running the price pusher for **Aptos Testnet**, **Sui Testnet**, or **Near Testnet**, we recommend you use beta hermes endpoints.
|
|
81
|
+
|
|
82
|
+
Pyth hosts [public endpoints](https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes) for Hermes; however, it is recommended to get a private endpoint from one of the
|
|
79
83
|
Hermes RPC providers for more reliability. Please refer to [this
|
|
80
84
|
document](https://docs.pyth.network/documentation/pythnet-price-feeds/hermes) for more information.
|
|
81
85
|
|
package/lib/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const command_4 = __importDefault(require("./sui/command"));
|
|
|
13
13
|
const command_5 = __importDefault(require("./near/command"));
|
|
14
14
|
const command_6 = __importDefault(require("./solana/command"));
|
|
15
15
|
const command_7 = __importDefault(require("./fuel/command"));
|
|
16
|
+
const command_8 = __importDefault(require("./ton/command"));
|
|
16
17
|
(0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
17
18
|
.parserConfiguration({
|
|
18
19
|
"parse-numbers": false,
|
|
@@ -26,4 +27,5 @@ const command_7 = __importDefault(require("./fuel/command"));
|
|
|
26
27
|
.command(command_4.default)
|
|
27
28
|
.command(command_5.default)
|
|
28
29
|
.command(command_6.default)
|
|
30
|
+
.command(command_8.default)
|
|
29
31
|
.help().argv;
|
package/lib/solana/solana.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare class SolanaPricePusher implements IPricePusher {
|
|
|
22
22
|
private shardId;
|
|
23
23
|
private computeUnitPriceMicroLamports;
|
|
24
24
|
constructor(pythSolanaReceiver: PythSolanaReceiver, priceServiceConnection: PriceServiceConnection, logger: Logger, shardId: number, computeUnitPriceMicroLamports: number);
|
|
25
|
-
updatePriceFeed(priceIds: string[]
|
|
25
|
+
updatePriceFeed(priceIds: string[]): Promise<void>;
|
|
26
26
|
}
|
|
27
27
|
export declare class SolanaPricePusherJito implements IPricePusher {
|
|
28
28
|
private pythSolanaReceiver;
|
|
@@ -37,6 +37,7 @@ export declare class SolanaPricePusherJito implements IPricePusher {
|
|
|
37
37
|
private updatesPerJitoBundle;
|
|
38
38
|
constructor(pythSolanaReceiver: PythSolanaReceiver, priceServiceConnection: PriceServiceConnection, logger: Logger, shardId: number, defaultJitoTipLamports: number, dynamicJitoTips: boolean, maxJitoTipLamports: number, searcherClient: SearcherClient, jitoBundleSize: number, updatesPerJitoBundle: number);
|
|
39
39
|
getRecentJitoTipLamports(): Promise<number | undefined>;
|
|
40
|
-
|
|
40
|
+
private sleep;
|
|
41
|
+
updatePriceFeed(priceIds: string[]): Promise<void>;
|
|
41
42
|
}
|
|
42
43
|
//# sourceMappingURL=solana.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solana.d.ts","sourceRoot":"","sources":["../../src/solana/solana.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAK3E,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAExE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAK9B,qBAAa,mBAAoB,SAAQ,kBAAkB;IAEvD,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,OAAO;IAEf,OAAO,CAAC,MAAM;gBAHN,kBAAkB,EAAE,kBAAkB,EACtC,OAAO,EAAE,MAAM,EACvB,UAAU,EAAE,SAAS,EAAE,EACf,MAAM,EAAE,MAAM,EACtB,MAAM,EAAE;QACN,gBAAgB,EAAE,iBAAiB,CAAC;KACrC;YAOW,WAAW;IAuBnB,KAAK;IAOL,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;CA0B3E;AAED,qBAAa,iBAAkB,YAAW,YAAY;IAElD,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,6BAA6B;gBAJ7B,kBAAkB,EAAE,kBAAkB,EACtC,sBAAsB,EAAE,sBAAsB,EAC9C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,6BAA6B,EAAE,MAAM;IAGzC,eAAe,
|
|
1
|
+
{"version":3,"file":"solana.d.ts","sourceRoot":"","sources":["../../src/solana/solana.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAK3E,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAExE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAK9B,qBAAa,mBAAoB,SAAQ,kBAAkB;IAEvD,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,OAAO;IAEf,OAAO,CAAC,MAAM;gBAHN,kBAAkB,EAAE,kBAAkB,EACtC,OAAO,EAAE,MAAM,EACvB,UAAU,EAAE,SAAS,EAAE,EACf,MAAM,EAAE,MAAM,EACtB,MAAM,EAAE;QACN,gBAAgB,EAAE,iBAAiB,CAAC;KACrC;YAOW,WAAW;IAuBnB,KAAK;IAOL,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;CA0B3E;AAED,qBAAa,iBAAkB,YAAW,YAAY;IAElD,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,6BAA6B;gBAJ7B,kBAAkB,EAAE,kBAAkB,EACtC,sBAAsB,EAAE,sBAAsB,EAC9C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,6BAA6B,EAAE,MAAM;IAGzC,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CA+CzD;AAED,qBAAa,qBAAsB,YAAW,YAAY;IAEtD,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,oBAAoB;gBATpB,kBAAkB,EAAE,kBAAkB,EACtC,sBAAsB,EAAE,sBAAsB,EAC9C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,sBAAsB,EAAE,MAAM,EAC9B,eAAe,EAAE,OAAO,EACxB,kBAAkB,EAAE,MAAM,EAC1B,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,MAAM,EACtB,oBAAoB,EAAE,MAAM;IAGhC,wBAAwB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;YAsB/C,KAAK;IAIb,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAqEzD"}
|
package/lib/solana/solana.js
CHANGED
|
@@ -73,9 +73,7 @@ class SolanaPricePusher {
|
|
|
73
73
|
this.shardId = shardId;
|
|
74
74
|
this.computeUnitPriceMicroLamports = computeUnitPriceMicroLamports;
|
|
75
75
|
}
|
|
76
|
-
async updatePriceFeed(priceIds
|
|
77
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
78
|
-
_pubTimesToPush) {
|
|
76
|
+
async updatePriceFeed(priceIds) {
|
|
79
77
|
if (priceIds.length === 0) {
|
|
80
78
|
return;
|
|
81
79
|
}
|
|
@@ -150,9 +148,10 @@ class SolanaPricePusherJito {
|
|
|
150
148
|
return undefined;
|
|
151
149
|
}
|
|
152
150
|
}
|
|
153
|
-
async
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
async sleep(ms) {
|
|
152
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
153
|
+
}
|
|
154
|
+
async updatePriceFeed(priceIds) {
|
|
156
155
|
const recentJitoTip = await this.getRecentJitoTipLamports();
|
|
157
156
|
const jitoTip = this.dynamicJitoTips && recentJitoTip !== undefined
|
|
158
157
|
? Math.max(this.defaultJitoTipLamports, recentJitoTip)
|
|
@@ -179,7 +178,29 @@ class SolanaPricePusherJito {
|
|
|
179
178
|
tightComputeBudget: true,
|
|
180
179
|
jitoBundleSize: this.jitoBundleSize,
|
|
181
180
|
});
|
|
182
|
-
|
|
181
|
+
let retries = 60;
|
|
182
|
+
while (retries > 0) {
|
|
183
|
+
try {
|
|
184
|
+
await (0, solana_utils_1.sendTransactionsJito)(transactions, this.searcherClient, this.pythSolanaReceiver.wallet);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
if (err.code === 8 && err.details?.includes("Rate limit exceeded")) {
|
|
189
|
+
this.logger.warn("Rate limit hit, waiting before retry...");
|
|
190
|
+
await this.sleep(1100); // Wait slightly more than 1 second
|
|
191
|
+
retries--;
|
|
192
|
+
if (retries === 0) {
|
|
193
|
+
this.logger.error("Max retries reached for rate limit");
|
|
194
|
+
throw err;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
throw err;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Add a delay between bundles to avoid rate limiting
|
|
203
|
+
await this.sleep(1100);
|
|
183
204
|
}
|
|
184
205
|
}
|
|
185
206
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Options } from "yargs";
|
|
2
|
+
declare const _default: {
|
|
3
|
+
command: string;
|
|
4
|
+
describe: string;
|
|
5
|
+
builder: {
|
|
6
|
+
"controller-log-level": Options;
|
|
7
|
+
"price-service-connection-log-level": Options;
|
|
8
|
+
"log-level": Options;
|
|
9
|
+
"polling-frequency": Options;
|
|
10
|
+
"pushing-frequency": Options;
|
|
11
|
+
"price-service-endpoint": Options;
|
|
12
|
+
"price-config-file": Options;
|
|
13
|
+
endpoint: Options;
|
|
14
|
+
"private-key-file": Options;
|
|
15
|
+
"pyth-contract-address": Options;
|
|
16
|
+
};
|
|
17
|
+
handler: (argv: any) => Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
export default _default;
|
|
20
|
+
//# sourceMappingURL=command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/ton/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;;;;;;;;;;;;;;;;oBAsCC,GAAG;;AA3BpC,wBA+FE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const options = __importStar(require("../options"));
|
|
30
|
+
const price_config_1 = require("../price-config");
|
|
31
|
+
const price_service_client_1 = require("@pythnetwork/price-service-client");
|
|
32
|
+
const pyth_price_listener_1 = require("../pyth-price-listener");
|
|
33
|
+
const ton_1 = require("./ton");
|
|
34
|
+
const controller_1 = require("../controller");
|
|
35
|
+
const ton_2 = require("@ton/ton");
|
|
36
|
+
const fs_1 = __importDefault(require("fs"));
|
|
37
|
+
const pino_1 = __importDefault(require("pino"));
|
|
38
|
+
exports.default = {
|
|
39
|
+
command: "ton",
|
|
40
|
+
describe: "run price pusher for TON",
|
|
41
|
+
builder: {
|
|
42
|
+
endpoint: {
|
|
43
|
+
description: "TON RPC API endpoint",
|
|
44
|
+
type: "string",
|
|
45
|
+
required: true,
|
|
46
|
+
},
|
|
47
|
+
"private-key-file": {
|
|
48
|
+
description: "Path to the private key file",
|
|
49
|
+
type: "string",
|
|
50
|
+
required: true,
|
|
51
|
+
},
|
|
52
|
+
"pyth-contract-address": {
|
|
53
|
+
description: "Pyth contract address on TON",
|
|
54
|
+
type: "string",
|
|
55
|
+
required: true,
|
|
56
|
+
},
|
|
57
|
+
...options.priceConfigFile,
|
|
58
|
+
...options.priceServiceEndpoint,
|
|
59
|
+
...options.pushingFrequency,
|
|
60
|
+
...options.pollingFrequency,
|
|
61
|
+
...options.logLevel,
|
|
62
|
+
...options.priceServiceConnectionLogLevel,
|
|
63
|
+
...options.controllerLogLevel,
|
|
64
|
+
},
|
|
65
|
+
handler: async function (argv) {
|
|
66
|
+
const { endpoint, privateKeyFile, pythContractAddress, priceConfigFile, priceServiceEndpoint, pushingFrequency, pollingFrequency, logLevel, priceServiceConnectionLogLevel, controllerLogLevel, } = argv;
|
|
67
|
+
const logger = (0, pino_1.default)({ level: logLevel });
|
|
68
|
+
const priceConfigs = (0, price_config_1.readPriceConfigFile)(priceConfigFile);
|
|
69
|
+
const priceServiceConnection = new price_service_client_1.PriceServiceConnection(priceServiceEndpoint, {
|
|
70
|
+
logger: logger.child({ module: "PriceServiceConnection" }, { level: priceServiceConnectionLogLevel }),
|
|
71
|
+
});
|
|
72
|
+
const priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));
|
|
73
|
+
const pythListener = new pyth_price_listener_1.PythPriceListener(priceServiceConnection, priceItems, logger.child({ module: "PythPriceListener" }));
|
|
74
|
+
const client = new ton_2.TonClient({ endpoint });
|
|
75
|
+
const privateKey = fs_1.default.readFileSync(privateKeyFile, "utf8").trim();
|
|
76
|
+
const contractAddress = ton_2.Address.parse(pythContractAddress);
|
|
77
|
+
const provider = client.provider(contractAddress);
|
|
78
|
+
const tonPriceListener = new ton_1.TonPriceListener(provider, contractAddress, priceItems, logger.child({ module: "TonPriceListener" }), { pollingFrequency });
|
|
79
|
+
const tonPricePusher = new ton_1.TonPricePusher(client, privateKey, contractAddress, priceServiceConnection, logger.child({ module: "TonPricePusher" }));
|
|
80
|
+
const controller = new controller_1.Controller(priceConfigs, pythListener, tonPriceListener, tonPricePusher, logger.child({ module: "Controller" }, { level: controllerLogLevel }), { pushingFrequency });
|
|
81
|
+
await controller.start();
|
|
82
|
+
},
|
|
83
|
+
};
|
package/lib/ton/ton.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
|
|
2
|
+
import { ChainPriceListener, IPricePusher, PriceInfo, PriceItem } from "../interface";
|
|
3
|
+
import { DurationInSeconds } from "../utils";
|
|
4
|
+
import { Logger } from "pino";
|
|
5
|
+
import { Address, ContractProvider, TonClient } from "@ton/ton";
|
|
6
|
+
export declare class TonPriceListener extends ChainPriceListener {
|
|
7
|
+
private provider;
|
|
8
|
+
private contractAddress;
|
|
9
|
+
private logger;
|
|
10
|
+
private contract;
|
|
11
|
+
constructor(provider: ContractProvider, contractAddress: Address, priceItems: PriceItem[], logger: Logger, config: {
|
|
12
|
+
pollingFrequency: DurationInSeconds;
|
|
13
|
+
});
|
|
14
|
+
getOnChainPriceInfo(priceId: string): Promise<PriceInfo | undefined>;
|
|
15
|
+
}
|
|
16
|
+
export declare class TonPricePusher implements IPricePusher {
|
|
17
|
+
private client;
|
|
18
|
+
private privateKey;
|
|
19
|
+
private contractAddress;
|
|
20
|
+
private priceServiceConnection;
|
|
21
|
+
private logger;
|
|
22
|
+
private contract;
|
|
23
|
+
private sender;
|
|
24
|
+
constructor(client: TonClient, privateKey: string, contractAddress: Address, priceServiceConnection: PriceServiceConnection, logger: Logger);
|
|
25
|
+
updatePriceFeed(priceIds: string[], pubTimesToPush: number[]): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=ton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ton.d.ts","sourceRoot":"","sources":["../../src/ton/ton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAgB,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EACL,OAAO,EACP,gBAAgB,EAGhB,SAAS,EAEV,MAAM,UAAU,CAAC;AAOlB,qBAAa,gBAAiB,SAAQ,kBAAkB;IAIpD,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,eAAe;IAEvB,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,QAAQ,CAA+B;gBAGrC,QAAQ,EAAE,gBAAgB,EAC1B,eAAe,EAAE,OAAO,EAChC,UAAU,EAAE,SAAS,EAAE,EACf,MAAM,EAAE,MAAM,EACtB,MAAM,EAAE;QACN,gBAAgB,EAAE,iBAAiB,CAAC;KACrC;IAQG,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;CAqB3E;AAED,qBAAa,cAAe,YAAW,YAAY;IAK/C,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,MAAM;IARhB,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,MAAM,CAAS;gBAGb,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,OAAO,EACxB,sBAAsB,EAAE,sBAAsB,EAC9C,MAAM,EAAE,MAAM;IAclB,eAAe,CACnB,QAAQ,EAAE,MAAM,EAAE,EAElB,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,IAAI,CAAC;CAmCjB"}
|
package/lib/ton/ton.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TonPricePusher = exports.TonPriceListener = void 0;
|
|
4
|
+
const interface_1 = require("../interface");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const ton_1 = require("@ton/ton");
|
|
7
|
+
const crypto_1 = require("@ton/crypto");
|
|
8
|
+
const pyth_ton_js_1 = require("@pythnetwork/pyth-ton-js");
|
|
9
|
+
class TonPriceListener extends interface_1.ChainPriceListener {
|
|
10
|
+
provider;
|
|
11
|
+
contractAddress;
|
|
12
|
+
logger;
|
|
13
|
+
contract;
|
|
14
|
+
constructor(provider, contractAddress, priceItems, logger, config) {
|
|
15
|
+
super(config.pollingFrequency, priceItems);
|
|
16
|
+
this.provider = provider;
|
|
17
|
+
this.contractAddress = contractAddress;
|
|
18
|
+
this.logger = logger;
|
|
19
|
+
this.contract = this.provider.open(pyth_ton_js_1.PythContract.createFromAddress(this.contractAddress));
|
|
20
|
+
}
|
|
21
|
+
async getOnChainPriceInfo(priceId) {
|
|
22
|
+
try {
|
|
23
|
+
const formattedPriceId = (0, utils_1.addLeading0x)(priceId);
|
|
24
|
+
const priceInfo = await this.contract.getPriceUnsafe(formattedPriceId);
|
|
25
|
+
this.logger.debug(`Polled a TON on chain price for feed ${this.priceIdToAlias.get(priceId)} (${priceId}).`);
|
|
26
|
+
return {
|
|
27
|
+
conf: priceInfo.conf.toString(),
|
|
28
|
+
price: priceInfo.price.toString(),
|
|
29
|
+
publishTime: priceInfo.publishTime,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
this.logger.error({ err, priceId }, `Polling on-chain price failed.`);
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.TonPriceListener = TonPriceListener;
|
|
39
|
+
class TonPricePusher {
|
|
40
|
+
client;
|
|
41
|
+
privateKey;
|
|
42
|
+
contractAddress;
|
|
43
|
+
priceServiceConnection;
|
|
44
|
+
logger;
|
|
45
|
+
contract;
|
|
46
|
+
sender;
|
|
47
|
+
constructor(client, privateKey, contractAddress, priceServiceConnection, logger) {
|
|
48
|
+
this.client = client;
|
|
49
|
+
this.privateKey = privateKey;
|
|
50
|
+
this.contractAddress = contractAddress;
|
|
51
|
+
this.priceServiceConnection = priceServiceConnection;
|
|
52
|
+
this.logger = logger;
|
|
53
|
+
this.contract = this.client
|
|
54
|
+
.provider(this.contractAddress)
|
|
55
|
+
.open(pyth_ton_js_1.PythContract.createFromAddress(this.contractAddress));
|
|
56
|
+
const keyPair = (0, crypto_1.keyPairFromSeed)(Buffer.from(this.privateKey, "hex"));
|
|
57
|
+
const wallet = ton_1.WalletContractV4.create({
|
|
58
|
+
publicKey: keyPair.publicKey,
|
|
59
|
+
workchain: 0, // workchain 0 is the masterchain
|
|
60
|
+
});
|
|
61
|
+
const provider = this.client.open(wallet);
|
|
62
|
+
this.sender = provider.sender(keyPair.secretKey);
|
|
63
|
+
}
|
|
64
|
+
async updatePriceFeed(priceIds,
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
66
|
+
pubTimesToPush) {
|
|
67
|
+
if (priceIds.length === 0) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
let priceFeedUpdateData;
|
|
71
|
+
try {
|
|
72
|
+
priceFeedUpdateData = await this.priceServiceConnection.getLatestVaas(priceIds);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
this.logger.error(err, "getPriceFeedsUpdateData failed");
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
for (const updateData of priceFeedUpdateData) {
|
|
80
|
+
const updateDataBuffer = Buffer.from(updateData, "base64");
|
|
81
|
+
const updateFee = await this.contract.getUpdateFee(updateDataBuffer);
|
|
82
|
+
const totalFee = (0, pyth_ton_js_1.calculateUpdatePriceFeedsFee)(BigInt(priceIds.length)) +
|
|
83
|
+
BigInt(updateFee);
|
|
84
|
+
await this.contract.sendUpdatePriceFeeds(this.sender, updateDataBuffer, totalFee);
|
|
85
|
+
}
|
|
86
|
+
this.logger.info("updatePriceFeed successful");
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
this.logger.error(err, "updatePriceFeed failed");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.TonPricePusher = TonPricePusher;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pythnetwork/price-pusher",
|
|
3
|
-
"version": "8.3.
|
|
3
|
+
"version": "8.3.2",
|
|
4
4
|
"description": "Pyth Price Pusher",
|
|
5
5
|
"homepage": "https://pyth.network",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -61,13 +61,16 @@
|
|
|
61
61
|
"@injectivelabs/sdk-ts": "1.10.72",
|
|
62
62
|
"@mysten/sui": "^1.3.0",
|
|
63
63
|
"@pythnetwork/price-service-client": "1.9.0",
|
|
64
|
-
"@pythnetwork/price-service-sdk": "^1.
|
|
64
|
+
"@pythnetwork/price-service-sdk": "^1.8.0",
|
|
65
65
|
"@pythnetwork/pyth-fuel-js": "1.0.7",
|
|
66
66
|
"@pythnetwork/pyth-sdk-solidity": "4.0.0",
|
|
67
|
-
"@pythnetwork/pyth-solana-receiver": "0.
|
|
67
|
+
"@pythnetwork/pyth-solana-receiver": "0.9.1",
|
|
68
68
|
"@pythnetwork/pyth-sui-js": "2.1.0",
|
|
69
|
-
"@pythnetwork/
|
|
69
|
+
"@pythnetwork/pyth-ton-js": "0.1.2",
|
|
70
|
+
"@pythnetwork/solana-utils": "0.4.3",
|
|
70
71
|
"@solana/web3.js": "^1.93.0",
|
|
72
|
+
"@ton/crypto": "^3.3.0",
|
|
73
|
+
"@ton/ton": "^15.1.0",
|
|
71
74
|
"@types/pino": "^7.0.5",
|
|
72
75
|
"aptos": "^1.8.5",
|
|
73
76
|
"fuels": "^0.94.5",
|
|
@@ -79,5 +82,5 @@
|
|
|
79
82
|
"yaml": "^2.1.1",
|
|
80
83
|
"yargs": "^17.5.1"
|
|
81
84
|
},
|
|
82
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "cdaf99e8629cd6af655a5f1c2c5750de9bc485dd"
|
|
83
86
|
}
|