@pythnetwork/price-pusher 4.1.2 → 5.4.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.
Files changed (48) hide show
  1. package/README.md +36 -2
  2. package/lib/aptos/aptos.d.ts +31 -0
  3. package/lib/aptos/aptos.d.ts.map +1 -0
  4. package/lib/aptos/aptos.js +139 -0
  5. package/lib/aptos/command.d.ts +18 -0
  6. package/lib/aptos/command.d.ts.map +1 -0
  7. package/lib/aptos/command.js +82 -0
  8. package/lib/common.d.ts +5 -0
  9. package/lib/common.d.ts.map +1 -0
  10. package/lib/common.js +2 -0
  11. package/lib/controller.d.ts +2 -1
  12. package/lib/controller.d.ts.map +1 -0
  13. package/lib/controller.js +10 -2
  14. package/lib/evm/command.d.ts +1 -0
  15. package/lib/evm/command.d.ts.map +1 -0
  16. package/lib/evm/command.js +3 -0
  17. package/lib/evm/custom-gas-station.d.ts +1 -0
  18. package/lib/evm/custom-gas-station.d.ts.map +1 -0
  19. package/lib/evm/evm.d.ts +1 -0
  20. package/lib/evm/evm.d.ts.map +1 -0
  21. package/lib/evm/evm.js +9 -1
  22. package/lib/index.d.ts +1 -0
  23. package/lib/index.d.ts.map +1 -0
  24. package/lib/index.js +4 -0
  25. package/lib/injective/command.d.ts +2 -0
  26. package/lib/injective/command.d.ts.map +1 -0
  27. package/lib/injective/command.js +13 -2
  28. package/lib/injective/injective.d.ts +2 -0
  29. package/lib/injective/injective.d.ts.map +1 -0
  30. package/lib/injective/injective.js +35 -34
  31. package/lib/interface.d.ts +1 -0
  32. package/lib/interface.d.ts.map +1 -0
  33. package/lib/options.d.ts +1 -0
  34. package/lib/options.d.ts.map +1 -0
  35. package/lib/price-config.d.ts +10 -1
  36. package/lib/price-config.d.ts.map +1 -0
  37. package/lib/price-config.js +39 -10
  38. package/lib/pyth-price-listener.d.ts +1 -0
  39. package/lib/pyth-price-listener.d.ts.map +1 -0
  40. package/lib/sui/command.d.ts +24 -0
  41. package/lib/sui/command.d.ts.map +1 -0
  42. package/lib/sui/command.js +132 -0
  43. package/lib/sui/sui.d.ts +42 -0
  44. package/lib/sui/sui.d.ts.map +1 -0
  45. package/lib/sui/sui.js +358 -0
  46. package/lib/utils.d.ts +1 -0
  47. package/lib/utils.d.ts.map +1 -0
  48. package/package.json +5 -3
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InjectivePricePusher = exports.InjectivePriceListener = void 0;
4
4
  const interface_1 = require("../interface");
5
5
  const sdk_ts_1 = require("@injectivelabs/sdk-ts");
6
- const utils_1 = require("@injectivelabs/utils");
6
+ const DEFAULT_GAS_PRICE = 500000000;
7
7
  // this use price without leading 0x
8
8
  class InjectivePriceListener extends interface_1.ChainPriceListener {
9
9
  pythContractAddress;
@@ -18,7 +18,7 @@ class InjectivePriceListener extends interface_1.ChainPriceListener {
18
18
  try {
19
19
  const api = new sdk_ts_1.ChainGrpcWasmApi(this.grpcEndpoint);
20
20
  const { data } = await api.fetchSmartContractState(this.pythContractAddress, Buffer.from(`{"price_feed":{"id":"${priceId}"}}`).toString("base64"));
21
- const json = Buffer.from(data, "base64").toString();
21
+ const json = Buffer.from(data).toString();
22
22
  priceQueryResponse = JSON.parse(json);
23
23
  }
24
24
  catch (e) {
@@ -41,6 +41,7 @@ class InjectivePricePusher {
41
41
  grpcEndpoint;
42
42
  wallet;
43
43
  chainConfig;
44
+ account = null;
44
45
  constructor(priceServiceConnection, pythContractAddress, grpcEndpoint, mnemonic, chainConfig) {
45
46
  this.priceServiceConnection = priceServiceConnection;
46
47
  this.pythContractAddress = pythContractAddress;
@@ -49,7 +50,7 @@ class InjectivePricePusher {
49
50
  this.chainConfig = {
50
51
  chainId: chainConfig?.chainId ?? "injective-888",
51
52
  gasMultiplier: chainConfig?.gasMultiplier ?? 1.2,
52
- gasPrice: chainConfig?.gasPrice ?? utils_1.DEFAULT_GAS_PRICE,
53
+ gasPrice: chainConfig?.gasPrice ?? DEFAULT_GAS_PRICE,
53
54
  };
54
55
  }
55
56
  injectiveAddress() {
@@ -57,10 +58,11 @@ class InjectivePricePusher {
57
58
  }
58
59
  async signAndBroadcastMsg(msg) {
59
60
  const chainGrpcAuthApi = new sdk_ts_1.ChainGrpcAuthApi(this.grpcEndpoint);
60
- const account = await chainGrpcAuthApi.fetchAccount(this.injectiveAddress());
61
+ // Fetch the latest account details only if it's not stored.
62
+ this.account ??= await chainGrpcAuthApi.fetchAccount(this.injectiveAddress());
61
63
  const { txRaw: simulateTxRaw } = (0, sdk_ts_1.createTransactionFromMsg)({
62
- sequence: account.baseAccount.sequence,
63
- accountNumber: account.baseAccount.accountNumber,
64
+ sequence: this.account.baseAccount.sequence,
65
+ accountNumber: this.account.baseAccount.accountNumber,
64
66
  message: msg,
65
67
  chainId: this.chainConfig.chainId,
66
68
  pubKey: this.wallet.toPublicKey().toBase64(),
@@ -72,30 +74,41 @@ class InjectivePricePusher {
72
74
  // gas passed with the transaction should be more than that
73
75
  // in order for it to be successfully executed
74
76
  // this multiplier takes care of that
77
+ const gas = (gasUsed * this.chainConfig.gasMultiplier).toFixed();
75
78
  const fee = {
76
79
  amount: [
77
80
  {
78
81
  denom: "inj",
79
- amount: (gasUsed *
80
- this.chainConfig.gasPrice *
81
- this.chainConfig.gasMultiplier).toFixed(),
82
+ amount: (Number(gas) * this.chainConfig.gasPrice).toFixed(),
82
83
  },
83
84
  ],
84
- gas: (gasUsed * this.chainConfig.gasMultiplier).toFixed(),
85
+ gas,
85
86
  };
86
87
  const { signBytes, txRaw } = (0, sdk_ts_1.createTransactionFromMsg)({
87
- sequence: account.baseAccount.sequence,
88
- accountNumber: account.baseAccount.accountNumber,
88
+ sequence: this.account.baseAccount.sequence,
89
+ accountNumber: this.account.baseAccount.accountNumber,
89
90
  message: msg,
90
91
  chainId: this.chainConfig.chainId,
91
92
  fee,
92
93
  pubKey: this.wallet.toPublicKey().toBase64(),
93
94
  });
94
95
  const sig = await this.wallet.sign(Buffer.from(signBytes));
95
- /** Append Signatures */
96
- txRaw.setSignaturesList([sig]);
97
- const txResponse = await txService.broadcast(txRaw);
98
- return txResponse;
96
+ try {
97
+ this.account.baseAccount.sequence++;
98
+ /** Append Signatures */
99
+ txRaw.signatures = [sig];
100
+ // this takes approx 5 seconds
101
+ const txResponse = await txService.broadcast(txRaw);
102
+ return txResponse;
103
+ }
104
+ catch (e) {
105
+ // The sequence number was invalid and hence we will have to fetch it again.
106
+ if (JSON.stringify(e).match(/account sequence mismatch/) !== null) {
107
+ // We need to fetch the account details again.
108
+ this.account = null;
109
+ }
110
+ throw e;
111
+ }
99
112
  }
100
113
  async getPriceFeedUpdateObject(priceIds) {
101
114
  const vaas = await this.priceServiceConnection.getLatestVaas(priceIds);
@@ -121,22 +134,12 @@ class InjectivePricePusher {
121
134
  console.error(e);
122
135
  return;
123
136
  }
124
- let updateFeeQueryResponse;
125
- try {
126
- const api = new sdk_ts_1.ChainGrpcWasmApi(this.grpcEndpoint);
127
- const { data } = await api.fetchSmartContractState(this.pythContractAddress, Buffer.from(JSON.stringify({
128
- get_update_fee: {
129
- vaas: priceFeedUpdateObject.update_price_feeds.data,
130
- },
131
- })).toString("base64"));
132
- const json = Buffer.from(data, "base64").toString();
133
- updateFeeQueryResponse = JSON.parse(json);
134
- }
135
- catch (e) {
136
- console.error("Error fetching update fee");
137
- console.error(e);
138
- return;
139
- }
137
+ // In order to reduce the number of API calls
138
+ // We are calculating the fee using the same logic as in contract.
139
+ const updateFeeQueryResponse = {
140
+ denom: "inj",
141
+ amount: priceFeedUpdateObject.update_price_feeds.data.length.toFixed(),
142
+ };
140
143
  try {
141
144
  const executeMsg = sdk_ts_1.MsgExecuteContract.fromJSON({
142
145
  sender: this.injectiveAddress(),
@@ -145,8 +148,6 @@ class InjectivePricePusher {
145
148
  funds: [updateFeeQueryResponse],
146
149
  });
147
150
  const rs = await this.signAndBroadcastMsg(executeMsg);
148
- if (rs.code !== 0)
149
- throw new Error("Error: transaction failed");
150
151
  console.log("Succesfully broadcasted txHash:", rs.txHash);
151
152
  }
152
153
  catch (e) {
@@ -29,3 +29,4 @@ export declare abstract class ChainPriceListener implements IPriceListener {
29
29
  export interface IPricePusher {
30
30
  updatePriceFeed(priceIds: string[], pubTimesToPush: UnixTimestamp[]): Promise<void>;
31
31
  }
32
+ //# sourceMappingURL=interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../src/interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,SAAS,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,aAAa,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,cAAc;IAE7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;CAC5D;AAED,8BAAsB,kBAAmB,YAAW,cAAc;IAK9D,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,gBAAgB;IACxB,SAAS,CAAC,UAAU,EAAE,SAAS,EAAE;IANnC,OAAO,CAAC,eAAe,CAA4B;IACnD,SAAS,CAAC,cAAc,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;gBAGvC,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,iBAAiB,EACjC,UAAU,EAAE,SAAS,EAAE;IAQ7B,KAAK;YASG,UAAU;IASxB,SAAS,CAAC,qBAAqB,CAC7B,OAAO,EAAE,SAAS,EAClB,aAAa,EAAE,SAAS;IAkB1B,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI1D,QAAQ,CAAC,mBAAmB,CAC1B,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;CAClC;AAED,MAAM,WAAW,YAAY;IAC3B,eAAe,CACb,QAAQ,EAAE,MAAM,EAAE,EAClB,cAAc,EAAE,aAAa,EAAE,GAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
package/lib/options.d.ts CHANGED
@@ -17,3 +17,4 @@ export declare const pushingFrequency: {
17
17
  export declare const mnemonicFile: {
18
18
  "mnemonic-file": Options;
19
19
  };
20
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,eAAO,MAAM,oBAAoB;;CAOhC,CAAC;AAEF,eAAO,MAAM,mBAAmB;;CAQ/B,CAAC;AAEF,eAAO,MAAM,eAAe;;CAM3B,CAAC;AAEF,eAAO,MAAM,gBAAgB;;CAQ5B,CAAC;AAEF,eAAO,MAAM,gBAAgB;;CAU5B,CAAC;AAEF,eAAO,MAAM,YAAY;;CAMxB,CAAC"}
@@ -7,12 +7,21 @@ export type PriceConfig = {
7
7
  timeDifference: DurationInSeconds;
8
8
  priceDeviation: PctNumber;
9
9
  confidenceRatio: PctNumber;
10
+ earlyUpdateTimeDifference: DurationInSeconds | undefined;
11
+ earlyUpdatePriceDeviation: PctNumber | undefined;
12
+ earlyUpdateConfidenceRatio: PctNumber | undefined;
10
13
  };
11
14
  export declare function readPriceConfigFile(path: string): PriceConfig[];
15
+ export declare enum UpdateCondition {
16
+ YES = 0,
17
+ EARLY = 1,
18
+ NO = 2
19
+ }
12
20
  /**
13
21
  * Checks whether on-chain price needs to be updated with the latest pyth price information.
14
22
  *
15
23
  * @param priceConfig Config of the price feed to check
16
24
  * @returns True if the on-chain price needs to be updated.
17
25
  */
18
- export declare function shouldUpdate(priceConfig: PriceConfig, sourceLatestPrice: PriceInfo | undefined, targetLatestPrice: PriceInfo | undefined): boolean;
26
+ export declare function shouldUpdate(priceConfig: PriceConfig, sourceLatestPrice: PriceInfo | undefined, targetLatestPrice: PriceInfo | undefined): UpdateCondition;
27
+ //# sourceMappingURL=price-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price-config.d.ts","sourceRoot":"","sources":["../src/price-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAI9D,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAmB,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAuBxC,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,SAAS,CAAC;IACd,cAAc,EAAE,iBAAiB,CAAC;IAClC,cAAc,EAAE,SAAS,CAAC;IAC1B,eAAe,EAAE,SAAS,CAAC;IAI3B,yBAAyB,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACzD,yBAAyB,EAAE,SAAS,GAAG,SAAS,CAAC;IACjD,0BAA0B,EAAE,SAAS,GAAG,SAAS,CAAC;CACnD,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAsB/D;AAED,oBAAY,eAAe;IAEzB,GAAG,IAAA;IAEH,KAAK,IAAA;IAEL,EAAE,IAAA;CACH;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,SAAS,GAAG,SAAS,EACxC,iBAAiB,EAAE,SAAS,GAAG,SAAS,GACvC,eAAe,CAmEjB"}
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.shouldUpdate = exports.readPriceConfigFile = void 0;
6
+ exports.shouldUpdate = exports.UpdateCondition = exports.readPriceConfigFile = void 0;
7
7
  const joi_1 = __importDefault(require("joi"));
8
8
  const yaml_1 = __importDefault(require("yaml"));
9
9
  const fs_1 = __importDefault(require("fs"));
@@ -17,6 +17,11 @@ const PriceConfigFileSchema = joi_1.default.array()
17
17
  time_difference: joi_1.default.number().required(),
18
18
  price_deviation: joi_1.default.number().required(),
19
19
  confidence_ratio: joi_1.default.number().required(),
20
+ early_update: joi_1.default.object({
21
+ time_difference: joi_1.default.number().optional(),
22
+ price_deviation: joi_1.default.number().optional(),
23
+ confidence_ratio: joi_1.default.number().optional(),
24
+ }).optional(),
20
25
  }))
21
26
  .unique("id")
22
27
  .unique("alias")
@@ -34,11 +39,23 @@ function readPriceConfigFile(path) {
34
39
  timeDifference: priceConfigRaw.time_difference,
35
40
  priceDeviation: priceConfigRaw.price_deviation,
36
41
  confidenceRatio: priceConfigRaw.confidence_ratio,
42
+ earlyUpdateTimeDifference: priceConfigRaw.early_update?.time_difference,
43
+ earlyUpdatePriceDeviation: priceConfigRaw.early_update?.price_deviation,
44
+ earlyUpdateConfidenceRatio: priceConfigRaw.early_update?.confidence_ratio,
37
45
  };
38
46
  return priceConfig;
39
47
  });
40
48
  }
41
49
  exports.readPriceConfigFile = readPriceConfigFile;
50
+ var UpdateCondition;
51
+ (function (UpdateCondition) {
52
+ // This price feed must be updated
53
+ UpdateCondition[UpdateCondition["YES"] = 0] = "YES";
54
+ // This price feed may be updated as part of a larger batch
55
+ UpdateCondition[UpdateCondition["EARLY"] = 1] = "EARLY";
56
+ // This price feed shouldn't be updated
57
+ UpdateCondition[UpdateCondition["NO"] = 2] = "NO";
58
+ })(UpdateCondition = exports.UpdateCondition || (exports.UpdateCondition = {}));
42
59
  /**
43
60
  * Checks whether on-chain price needs to be updated with the latest pyth price information.
44
61
  *
@@ -49,16 +66,16 @@ function shouldUpdate(priceConfig, sourceLatestPrice, targetLatestPrice) {
49
66
  const priceId = priceConfig.id;
50
67
  // There is no price to update the target with.
51
68
  if (sourceLatestPrice === undefined) {
52
- return false;
69
+ return UpdateCondition.YES;
53
70
  }
54
71
  // It means that price never existed there. So we should push the latest price feed.
55
72
  if (targetLatestPrice === undefined) {
56
73
  console.log(`${priceConfig.alias} (${priceId}) is not available on the target network. Pushing the price.`);
57
- return true;
74
+ return UpdateCondition.YES;
58
75
  }
59
76
  // The current price is not newer than the price onchain
60
77
  if (sourceLatestPrice.publishTime < targetLatestPrice.publishTime) {
61
- return false;
78
+ return UpdateCondition.NO;
62
79
  }
63
80
  const timeDifference = sourceLatestPrice.publishTime - targetLatestPrice.publishTime;
64
81
  const priceDeviationPct = (Math.abs(Number(sourceLatestPrice.price) - Number(targetLatestPrice.price)) /
@@ -68,12 +85,24 @@ function shouldUpdate(priceConfig, sourceLatestPrice, targetLatestPrice) {
68
85
  console.log(`Analyzing price ${priceConfig.alias} (${priceId})`);
69
86
  console.log("Source latest price: ", sourceLatestPrice);
70
87
  console.log("Target latest price: ", targetLatestPrice);
71
- console.log(`Time difference: ${timeDifference} (< ${priceConfig.timeDifference}?) OR ` +
72
- `Price deviation: ${priceDeviationPct.toFixed(5)}% (< ${priceConfig.priceDeviation}%?) OR ` +
73
- `Confidence ratio: ${confidenceRatioPct.toFixed(5)}% (< ${priceConfig.confidenceRatio}%?)`);
74
- const result = timeDifference >= priceConfig.timeDifference ||
88
+ console.log(`Time difference: ${timeDifference} (< ${priceConfig.timeDifference}? / early: < ${priceConfig.earlyUpdateTimeDifference}) OR ` +
89
+ `Price deviation: ${priceDeviationPct.toFixed(5)}% (< ${priceConfig.priceDeviation}%? / early: < ${priceConfig.earlyUpdatePriceDeviation}%?) OR ` +
90
+ `Confidence ratio: ${confidenceRatioPct.toFixed(5)}% (< ${priceConfig.confidenceRatio}%? / early: < ${priceConfig.earlyUpdatePriceDeviation}%?)`);
91
+ if (timeDifference >= priceConfig.timeDifference ||
75
92
  priceDeviationPct >= priceConfig.priceDeviation ||
76
- confidenceRatioPct >= priceConfig.confidenceRatio;
77
- return result;
93
+ confidenceRatioPct >= priceConfig.confidenceRatio) {
94
+ return UpdateCondition.YES;
95
+ }
96
+ else if ((priceConfig.earlyUpdateTimeDifference !== undefined &&
97
+ timeDifference >= priceConfig.earlyUpdateTimeDifference) ||
98
+ (priceConfig.earlyUpdatePriceDeviation !== undefined &&
99
+ priceDeviationPct >= priceConfig.earlyUpdatePriceDeviation) ||
100
+ (priceConfig.earlyUpdateConfidenceRatio !== undefined &&
101
+ confidenceRatioPct >= priceConfig.earlyUpdateConfidenceRatio)) {
102
+ return UpdateCondition.EARLY;
103
+ }
104
+ else {
105
+ return UpdateCondition.NO;
106
+ }
78
107
  }
79
108
  exports.shouldUpdate = shouldUpdate;
@@ -10,3 +10,4 @@ export declare class PythPriceListener implements IPriceListener {
10
10
  private onNewPriceFeed;
11
11
  getLatestPriceInfo(priceId: string): PriceInfo | undefined;
12
12
  }
13
+ //# sourceMappingURL=pyth-price-listener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pyth-price-listener.d.ts","sourceRoot":"","sources":["../src/pyth-price-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,sBAAsB,EACvB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEnE,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,eAAe,CAA4B;gBAEvC,UAAU,EAAE,sBAAsB,EAAE,UAAU,EAAE,SAAS,EAAE;IAWjE,KAAK;IAmBX,OAAO,CAAC,cAAc;IAsBtB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;CAG3D"}
@@ -0,0 +1,24 @@
1
+ import { Options } from "yargs";
2
+ declare const _default: {
3
+ command: string;
4
+ describe: string;
5
+ builder: {
6
+ "pushing-frequency": Options;
7
+ "polling-frequency": Options;
8
+ "mnemonic-file": Options;
9
+ "price-service-endpoint": Options;
10
+ "price-config-file": Options;
11
+ endpoint: Options;
12
+ "pyth-package-id": Options;
13
+ "pyth-state-id": Options;
14
+ "wormhole-package-id": Options;
15
+ "wormhole-state-id": Options;
16
+ "price-feed-to-price-info-object-table-id": Options;
17
+ "max-vaas-per-ptb": Options;
18
+ "num-gas-objects": Options;
19
+ "gas-budget": Options;
20
+ };
21
+ handler: (argv: any) => Promise<void>;
22
+ };
23
+ export default _default;
24
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/sui/command.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;oBAgFC,GAAG;;AA5EpC,wBA8JE"}
@@ -0,0 +1,132 @@
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 price_service_client_1 = require("@pythnetwork/price-service-client");
30
+ const options = __importStar(require("../options"));
31
+ const price_config_1 = require("../price-config");
32
+ const fs_1 = __importDefault(require("fs"));
33
+ const pyth_price_listener_1 = require("../pyth-price-listener");
34
+ const controller_1 = require("../controller");
35
+ const sui_1 = require("./sui");
36
+ const sui_js_1 = require("@mysten/sui.js");
37
+ exports.default = {
38
+ command: "sui",
39
+ describe: "Run price pusher for sui. Most of the arguments below are" +
40
+ "network specific, so there's one set of values for mainnet and" +
41
+ "another for testnet. See config.sui..sample.json for the " +
42
+ "appropriate values for your network. ",
43
+ builder: {
44
+ endpoint: {
45
+ description: "RPC endpoint URL for sui. The pusher will periodically" +
46
+ "poll for updates. The polling interval is configurable via the " +
47
+ "`polling-frequency` command-line argument.",
48
+ type: "string",
49
+ required: true,
50
+ },
51
+ "pyth-package-id": {
52
+ description: "Pyth Package Id. Can be found here" +
53
+ "https://docs.pyth.network/pythnet-price-feeds/sui",
54
+ type: "string",
55
+ required: true,
56
+ },
57
+ "pyth-state-id": {
58
+ description: "Pyth State Id. Can be found here" +
59
+ "https://docs.pyth.network/pythnet-price-feeds/sui",
60
+ type: "string",
61
+ required: true,
62
+ },
63
+ "wormhole-package-id": {
64
+ description: "Wormhole Package Id. Can be found here" +
65
+ "https://docs.pyth.network/pythnet-price-feeds/sui",
66
+ type: "string",
67
+ required: true,
68
+ },
69
+ "wormhole-state-id": {
70
+ description: "Wormhole State Id. Can be found here" +
71
+ "https://docs.pyth.network/pythnet-price-feeds/sui",
72
+ type: "string",
73
+ required: true,
74
+ },
75
+ "price-feed-to-price-info-object-table-id": {
76
+ description: "This is the id of the table which stored the information related to price data. You can find it here: " +
77
+ "https://docs.pyth.network/pythnet-price-feeds/sui",
78
+ type: "string",
79
+ required: true,
80
+ },
81
+ "max-vaas-per-ptb": {
82
+ description: "Maximum number of VAAs that can be included in a single PTB.",
83
+ type: "number",
84
+ required: true,
85
+ default: 1,
86
+ },
87
+ "num-gas-objects": {
88
+ description: "Number of gas objects in the pool.",
89
+ type: "number",
90
+ required: true,
91
+ default: 30,
92
+ },
93
+ "gas-budget": {
94
+ description: "Gas budget for each price update",
95
+ type: "number",
96
+ required: true,
97
+ default: 500_000_000,
98
+ },
99
+ ...options.priceConfigFile,
100
+ ...options.priceServiceEndpoint,
101
+ ...options.mnemonicFile,
102
+ ...options.pollingFrequency,
103
+ ...options.pushingFrequency,
104
+ },
105
+ handler: async function (argv) {
106
+ const { endpoint, priceConfigFile, priceServiceEndpoint, mnemonicFile, pushingFrequency, pollingFrequency, pythPackageId, pythStateId, wormholePackageId, wormholeStateId, priceFeedToPriceInfoObjectTableId, maxVaasPerPtb, numGasObjects, gasBudget, } = argv;
107
+ const priceConfigs = (0, price_config_1.readPriceConfigFile)(priceConfigFile);
108
+ const priceServiceConnection = new price_service_client_1.PriceServiceConnection(priceServiceEndpoint, {
109
+ logger: {
110
+ // Log only warnings and errors from the price service client
111
+ info: () => undefined,
112
+ warn: console.warn,
113
+ error: console.error,
114
+ debug: () => undefined,
115
+ trace: () => undefined,
116
+ },
117
+ priceFeedRequestConfig: {
118
+ binary: true,
119
+ },
120
+ });
121
+ const mnemonic = fs_1.default.readFileSync(mnemonicFile, "utf-8").trim();
122
+ console.log(`Pushing updates from wallet address: ${sui_js_1.Ed25519Keypair.deriveKeypair(mnemonic)
123
+ .getPublicKey()
124
+ .toSuiAddress()}`);
125
+ const priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));
126
+ const pythListener = new pyth_price_listener_1.PythPriceListener(priceServiceConnection, priceItems);
127
+ const suiListener = new sui_1.SuiPriceListener(pythPackageId, priceFeedToPriceInfoObjectTableId, endpoint, priceItems, { pollingFrequency });
128
+ const suiPusher = await sui_1.SuiPricePusher.createWithAutomaticGasPool(priceServiceConnection, pythPackageId, pythStateId, wormholePackageId, wormholeStateId, priceFeedToPriceInfoObjectTableId, maxVaasPerPtb, endpoint, mnemonic, gasBudget, numGasObjects);
129
+ const controller = new controller_1.Controller(priceConfigs, pythListener, suiListener, suiPusher, { pushingFrequency });
130
+ controller.start();
131
+ },
132
+ };
@@ -0,0 +1,42 @@
1
+ import { ChainPriceListener, IPricePusher, PriceInfo, PriceItem } from "../interface";
2
+ import { DurationInSeconds } from "../utils";
3
+ import { PriceServiceConnection } from "@pythnetwork/price-service-client";
4
+ import { RawSigner, SuiObjectRef } from "@mysten/sui.js";
5
+ export declare class SuiPriceListener extends ChainPriceListener {
6
+ private pythPackageId;
7
+ private priceFeedToPriceInfoObjectTableId;
8
+ private endpoint;
9
+ constructor(pythPackageId: string, priceFeedToPriceInfoObjectTableId: string, endpoint: string, priceItems: PriceItem[], config: {
10
+ pollingFrequency: DurationInSeconds;
11
+ });
12
+ getOnChainPriceInfo(priceId: string): Promise<PriceInfo | undefined>;
13
+ }
14
+ export declare class SuiPricePusher implements IPricePusher {
15
+ private readonly signer;
16
+ private priceServiceConnection;
17
+ private pythPackageId;
18
+ private pythStateId;
19
+ private wormholePackageId;
20
+ private wormholeStateId;
21
+ private priceFeedToPriceInfoObjectTableId;
22
+ private maxVaasPerPtb;
23
+ private gasBudget;
24
+ private gasPool;
25
+ constructor(signer: RawSigner, priceServiceConnection: PriceServiceConnection, pythPackageId: string, pythStateId: string, wormholePackageId: string, wormholeStateId: string, priceFeedToPriceInfoObjectTableId: string, maxVaasPerPtb: number, endpoint: string, mnemonic: string, gasBudget: number, gasPool: SuiObjectRef[]);
26
+ /**
27
+ * Create a price pusher with a pool of `numGasObjects` gas coins that will be used to send transactions.
28
+ * The gas coins of the wallet for the provided mnemonic will be merged and then evenly split into `numGasObjects`.
29
+ */
30
+ static createWithAutomaticGasPool(priceServiceConnection: PriceServiceConnection, pythPackageId: string, pythStateId: string, wormholePackageId: string, wormholeStateId: string, priceFeedToPriceInfoObjectTableId: string, maxVaasPerPtb: number, endpoint: string, mnemonic: string, gasBudget: number, numGasObjects: number): Promise<SuiPricePusher>;
31
+ updatePriceFeed(priceIds: string[], pubTimesToPush: number[]): Promise<void>;
32
+ private createPriceUpdateTransaction;
33
+ /** Send every transaction in txs in parallel, returning when all transactions have completed. */
34
+ private sendTransactionBlocks;
35
+ /** Send a single transaction block using a gas coin from the pool. */
36
+ private sendTransactionBlock;
37
+ private static initializeGasPool;
38
+ private static getAllGasCoins;
39
+ private static splitGasCoinEqually;
40
+ private static mergeGasCoinsIntoOne;
41
+ }
42
+ //# sourceMappingURL=sui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sui.d.ts","sourceRoot":"","sources":["../../src/sui/sui.ts"],"names":[],"mappings":"AAAA,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;AAC3E,OAAO,EAIL,SAAS,EAIT,YAAY,EAKb,MAAM,gBAAgB,CAAC;AAMxB,qBAAa,gBAAiB,SAAQ,kBAAkB;IAEpD,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,iCAAiC;IACzC,OAAO,CAAC,QAAQ;gBAFR,aAAa,EAAE,MAAM,EACrB,iCAAiC,EAAE,MAAM,EACzC,QAAQ,EAAE,MAAM,EACxB,UAAU,EAAE,SAAS,EAAE,EACvB,MAAM,EAAE;QACN,gBAAgB,EAAE,iBAAiB,CAAC;KACrC;IAKG,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;CAmD3E;AAED,qBAAa,cAAe,YAAW,YAAY;IAE/C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,iBAAiB;IACzB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,iCAAiC;IACzC,OAAO,CAAC,aAAa;IAGrB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,OAAO;gBAXE,MAAM,EAAE,SAAS,EAC1B,sBAAsB,EAAE,sBAAsB,EAC9C,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,eAAe,EAAE,MAAM,EACvB,iCAAiC,EAAE,MAAM,EACzC,aAAa,EAAE,MAAM,EAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EACR,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY,EAAE;IAGjC;;;OAGG;WACU,0BAA0B,CACrC,sBAAsB,EAAE,sBAAsB,EAC9C,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,eAAe,EAAE,MAAM,EACvB,iCAAiC,EAAE,MAAM,EACzC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,cAAc,CAAC;IAiCpB,eAAe,CACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,IAAI,CAAC;YAsDF,4BAA4B;IA2E1C,iGAAiG;YACnF,qBAAqB;IAMnC,sEAAsE;YACxD,oBAAoB;mBA6Cb,iBAAiB;mBA2BjB,cAAc;mBAiCd,mBAAmB;mBAsCnB,oBAAoB;CA2C1C"}