@pythnetwork/price-pusher 5.4.2 → 5.4.4

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.
@@ -9,14 +9,15 @@ export declare class AptosPriceListener extends ChainPriceListener {
9
9
  });
10
10
  getOnChainPriceInfo(priceId: string): Promise<PriceInfo | undefined>;
11
11
  }
12
+ export declare const APTOS_ACCOUNT_HD_PATH = "m/44'/637'/0'/0'/0'";
12
13
  export declare class AptosPricePusher implements IPricePusher {
13
14
  private priceServiceConnection;
14
15
  private pythContractAddress;
15
16
  private endpoint;
16
17
  private mnemonic;
17
18
  private overrideGasPriceMultiplier;
18
- private lastPushAttempt;
19
- private readonly accountHDPath;
19
+ private lastSequenceNumber;
20
+ private sequenceNumberLocked;
20
21
  constructor(priceServiceConnection: PriceServiceConnection, pythContractAddress: string, endpoint: string, mnemonic: string, overrideGasPriceMultiplier: number);
21
22
  /**
22
23
  * Gets price update data which then can be submitted to the Pyth contract to update the prices.
@@ -27,5 +28,6 @@ export declare class AptosPricePusher implements IPricePusher {
27
28
  */
28
29
  getPriceFeedsUpdateData(priceIds: string[]): Promise<number[][]>;
29
30
  updatePriceFeed(priceIds: string[], pubTimesToPush: number[]): Promise<void>;
31
+ private tryGetNextSequenceNumber;
30
32
  }
31
33
  //# sourceMappingURL=aptos.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aptos.d.ts","sourceRoot":"","sources":["../../src/aptos/aptos.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAG3E,qBAAa,kBAAmB,SAAQ,kBAAkB;IAEtD,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,QAAQ;gBADR,UAAU,EAAE,MAAM,EAClB,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;CA6C3E;AAED,qBAAa,gBAAiB,YAAW,YAAY;IAKjD,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,0BAA0B;IARpC,OAAO,CAAC,eAAe,CAA0B;IAEjD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;gBAE7C,sBAAsB,EAAE,sBAAsB,EAC9C,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,0BAA0B,EAAE,MAAM;IAG5C;;;;;;OAMG;IACG,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAQhE,eAAe,CACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,IAAI,CAAC;CAyFjB"}
1
+ {"version":3,"file":"aptos.d.ts","sourceRoot":"","sources":["../../src/aptos/aptos.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAE3E,qBAAa,kBAAmB,SAAQ,kBAAkB;IAEtD,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,QAAQ;gBADR,UAAU,EAAE,MAAM,EAClB,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;CA6C3E;AAGD,eAAO,MAAM,qBAAqB,wBAAwB,CAAC;AAC3D,qBAAa,gBAAiB,YAAW,YAAY;IAOjD,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,0BAA0B;IATpC,OAAO,CAAC,kBAAkB,CAAqB;IAE/C,OAAO,CAAC,oBAAoB,CAAU;gBAG5B,sBAAsB,EAAE,sBAAsB,EAC9C,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,0BAA0B,EAAE,MAAM;IAK5C;;;;;;OAMG;IACG,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAQhE,eAAe,CACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,IAAI,CAAC;YA4DF,wBAAwB;CA+BvC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AptosPricePusher = exports.AptosPriceListener = void 0;
3
+ exports.AptosPricePusher = exports.APTOS_ACCOUNT_HD_PATH = exports.AptosPriceListener = void 0;
4
4
  const interface_1 = require("../interface");
5
5
  const aptos_1 = require("aptos");
6
6
  class AptosPriceListener extends interface_1.ChainPriceListener {
@@ -42,20 +42,25 @@ class AptosPriceListener extends interface_1.ChainPriceListener {
42
42
  }
43
43
  }
44
44
  exports.AptosPriceListener = AptosPriceListener;
45
+ // Derivation path for aptos accounts
46
+ exports.APTOS_ACCOUNT_HD_PATH = "m/44'/637'/0'/0'/0'";
45
47
  class AptosPricePusher {
46
48
  priceServiceConnection;
47
49
  pythContractAddress;
48
50
  endpoint;
49
51
  mnemonic;
50
52
  overrideGasPriceMultiplier;
51
- lastPushAttempt;
52
- accountHDPath = "m/44'/637'/0'/0'/0'";
53
+ // The last sequence number that has a transaction submitted.
54
+ lastSequenceNumber;
55
+ // If true, we are trying to fetch the most recent sequence number from the blockchain.
56
+ sequenceNumberLocked;
53
57
  constructor(priceServiceConnection, pythContractAddress, endpoint, mnemonic, overrideGasPriceMultiplier) {
54
58
  this.priceServiceConnection = priceServiceConnection;
55
59
  this.pythContractAddress = pythContractAddress;
56
60
  this.endpoint = endpoint;
57
61
  this.mnemonic = mnemonic;
58
62
  this.overrideGasPriceMultiplier = overrideGasPriceMultiplier;
63
+ this.sequenceNumberLocked = false;
59
64
  }
60
65
  /**
61
66
  * Gets price update data which then can be submitted to the Pyth contract to update the prices.
@@ -86,54 +91,59 @@ class AptosPricePusher {
86
91
  return;
87
92
  }
88
93
  try {
89
- const account = aptos_1.AptosAccount.fromDerivePath(this.accountHDPath, this.mnemonic);
94
+ const account = aptos_1.AptosAccount.fromDerivePath(exports.APTOS_ACCOUNT_HD_PATH, this.mnemonic);
90
95
  const client = new aptos_1.AptosClient(this.endpoint);
96
+ const sequenceNumber = await this.tryGetNextSequenceNumber(client, account);
91
97
  const rawTx = await client.generateTransaction(account.address(), {
92
- function: `${this.pythContractAddress}::pyth::update_price_feeds_if_fresh_with_funder`,
98
+ function: `${this.pythContractAddress}::pyth::update_price_feeds_with_funder`,
93
99
  type_arguments: [],
94
- arguments: [
95
- priceFeedUpdateData,
96
- priceIds.map((priceId) => Buffer.from(priceId, "hex")),
97
- pubTimesToPush,
98
- ],
100
+ arguments: [priceFeedUpdateData],
101
+ }, {
102
+ sequence_number: sequenceNumber.toFixed(),
99
103
  });
100
- const simulation = await client.simulateTransaction(account, rawTx, {
101
- estimateGasUnitPrice: true,
102
- estimateMaxGasAmount: true,
103
- estimatePrioritizedGasUnitPrice: true,
104
- });
105
- // Transactions on Aptos can be prioritized by paying a higher gas unit price.
106
- // We are storing the gas unit price paid for the last transaction.
107
- // If that transaction is not added to the block, we are increasing the gas unit price
108
- // by multiplying the old gas unit price with `this.overrideGasPriceMultiplier`.
109
- // After which we are sending a transaction with the same sequence number as the last
110
- // transaction. Since they have the same sequence number only one of them will be added to
111
- // the block and we won't be paying fees twice.
112
- let gasUnitPrice = Number(simulation[0].gas_unit_price);
113
- if (this.lastPushAttempt !== undefined &&
114
- Number(simulation[0].sequence_number) === this.lastPushAttempt.nonce) {
115
- const newGasUnitPrice = Number(this.lastPushAttempt.gasPrice * this.overrideGasPriceMultiplier);
116
- if (gasUnitPrice < newGasUnitPrice)
117
- gasUnitPrice = newGasUnitPrice;
118
- }
119
- const gasUsed = Number(simulation[0].gas_used) * 1.5;
120
- const maxGasAmount = Number(gasUnitPrice * gasUsed);
121
- const rawTxWithFee = new aptos_1.TxnBuilderTypes.RawTransaction(rawTx.sender, rawTx.sequence_number, rawTx.payload, BigInt(maxGasAmount.toFixed()), BigInt(gasUnitPrice.toFixed()), rawTx.expiration_timestamp_secs, rawTx.chain_id);
122
- const signedTx = await client.signTransaction(account, rawTxWithFee);
104
+ const signedTx = await client.signTransaction(account, rawTx);
123
105
  const pendingTx = await client.submitTransaction(signedTx);
124
- console.log("Succesfully broadcasted txHash:", pendingTx.hash);
125
- // Update lastAttempt
126
- this.lastPushAttempt = {
127
- nonce: Number(pendingTx.sequence_number),
128
- gasPrice: gasUnitPrice,
129
- };
106
+ console.log("Successfully broadcasted txHash:", pendingTx.hash);
130
107
  return;
131
108
  }
132
109
  catch (e) {
133
110
  console.error("Error executing messages");
134
111
  console.log(e);
112
+ // Reset the sequence number to re-sync it (in case that was the issue)
113
+ this.lastSequenceNumber = undefined;
135
114
  return;
136
115
  }
137
116
  }
117
+ // Try to get the next sequence number for account. This function uses a local cache
118
+ // to predict the next sequence number if possible; if not, it fetches the number from
119
+ // the blockchain itself (and caches it for later).
120
+ async tryGetNextSequenceNumber(client, account) {
121
+ if (this.lastSequenceNumber !== undefined) {
122
+ this.lastSequenceNumber += 1;
123
+ return this.lastSequenceNumber;
124
+ }
125
+ else {
126
+ // Fetch from the blockchain if we don't have the local cache.
127
+ // Note that this is locked so that only 1 fetch occurs regardless of how many updates
128
+ // happen during that fetch.
129
+ if (!this.sequenceNumberLocked) {
130
+ try {
131
+ this.sequenceNumberLocked = true;
132
+ this.lastSequenceNumber = Number((await client.getAccount(account.address())).sequence_number);
133
+ console.log(`Fetched account sequence number: ${this.lastSequenceNumber}`);
134
+ return this.lastSequenceNumber;
135
+ }
136
+ catch (e) {
137
+ throw new Error("Failed to retrieve sequence number");
138
+ }
139
+ finally {
140
+ this.sequenceNumberLocked = false;
141
+ }
142
+ }
143
+ else {
144
+ throw new Error("Waiting for sequence number in another thread.");
145
+ }
146
+ }
147
+ }
138
148
  }
139
149
  exports.AptosPricePusher = AptosPricePusher;
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/aptos/command.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;;;;;;;;;;;;;;oBA6BL,GAAG;;AA1B9B,wBAsFE"}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/aptos/command.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;;;;;;;;;;;;;;oBAkCL,GAAG;;AA1B9B,wBA2FE"}
@@ -33,6 +33,7 @@ const fs_1 = __importDefault(require("fs"));
33
33
  const pyth_price_listener_1 = require("../pyth-price-listener");
34
34
  const controller_1 = require("../controller");
35
35
  const aptos_1 = require("./aptos");
36
+ const aptos_2 = require("aptos");
36
37
  exports.default = {
37
38
  command: "aptos",
38
39
  describe: "run price pusher for aptos",
@@ -72,6 +73,8 @@ exports.default = {
72
73
  },
73
74
  });
74
75
  const mnemonic = fs_1.default.readFileSync(mnemonicFile, "utf-8").trim();
76
+ const account = aptos_2.AptosAccount.fromDerivePath(aptos_1.APTOS_ACCOUNT_HD_PATH, mnemonic);
77
+ console.log(`Pushing from account address: ${account.address()}`);
75
78
  const priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));
76
79
  const pythListener = new pyth_price_listener_1.PythPriceListener(priceServiceConnection, priceItems);
77
80
  const aptosListener = new aptos_1.AptosPriceListener(pythContractAddress, endpoint, priceItems, { pollingFrequency });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pythnetwork/price-pusher",
3
- "version": "5.4.2",
3
+ "version": "5.4.4",
4
4
  "description": "Pyth Price Pusher",
5
5
  "homepage": "https://pyth.network",
6
6
  "main": "lib/index.js",
@@ -63,5 +63,5 @@
63
63
  "yaml": "^2.1.1",
64
64
  "yargs": "^17.5.1"
65
65
  },
66
- "gitHead": "5e44fa4c95ae7120ee8a05f145b27470d2c48e7b"
66
+ "gitHead": "2c334b6b9249914c1f88541cb55235388e404030"
67
67
  }