@pythnetwork/price-pusher 5.4.4 → 5.4.9
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 +4 -3
- package/lib/aptos/aptos.d.ts +11 -0
- package/lib/aptos/aptos.d.ts.map +1 -1
- package/lib/aptos/aptos.js +31 -1
- package/lib/injective/injective.d.ts.map +1 -1
- package/lib/injective/injective.js +40 -30
- package/lib/sui/command.js +5 -5
- package/lib/sui/sui.d.ts +15 -0
- package/lib/sui/sui.d.ts.map +1 -1
- package/lib/sui/sui.js +41 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Pyth is a cross-chain oracle that streams price updates over the peer-to-peer [W
|
|
|
8
8
|
These price updates can be consumed on any chain that has a deployment of the Pyth contract.
|
|
9
9
|
By default, Pyth does not automatically update the on-chain price every time the off-chain price changes;
|
|
10
10
|
instead, anyone can permissionlessly update the on-chain price prior to using it.
|
|
11
|
-
For more information please refer to [this document](https://docs.pyth.network/
|
|
11
|
+
For more information please refer to [this document](https://docs.pyth.network/documentation/how-pyth-works).
|
|
12
12
|
|
|
13
13
|
Protocols integrating with can update the on-chain Pyth prices in two different ways.
|
|
14
14
|
The first approach is on-demand updates: package a Pyth price update together with each transaction that depends on it.
|
|
@@ -79,8 +79,9 @@ npm run start -- injective --grpc-endpoint https://grpc-endpoint.com \
|
|
|
79
79
|
--pyth-contract-address inj1z60tg0... --price-service-endpoint "https://example-pyth-price.com" \
|
|
80
80
|
--price-config-file "path/to/price-config.testnet.sample.yaml" \
|
|
81
81
|
--mnemonic-file "path/to/mnemonic.txt" \
|
|
82
|
+
--network testnet \
|
|
82
83
|
[--pushing-frequency 10] \
|
|
83
|
-
[--polling-frequency 5]
|
|
84
|
+
[--polling-frequency 5]
|
|
84
85
|
|
|
85
86
|
# For Aptos
|
|
86
87
|
npm run start -- aptos --endpoint https://fullnode.testnet.aptoslabs.com/v1 \
|
|
@@ -88,7 +89,7 @@ npm run start -- aptos --endpoint https://fullnode.testnet.aptoslabs.com/v1 \
|
|
|
88
89
|
--price-config-file "./price-config.testnet.sample.yaml" \
|
|
89
90
|
--mnemonic-file "path/to/mnemonic.txt" \
|
|
90
91
|
[--pushing-frequency 10] \
|
|
91
|
-
[--polling-frequency 5]
|
|
92
|
+
[--polling-frequency 5]
|
|
92
93
|
|
|
93
94
|
# For Sui
|
|
94
95
|
npm run start -- sui \
|
package/lib/aptos/aptos.d.ts
CHANGED
|
@@ -10,6 +10,16 @@ export declare class AptosPriceListener extends ChainPriceListener {
|
|
|
10
10
|
getOnChainPriceInfo(priceId: string): Promise<PriceInfo | undefined>;
|
|
11
11
|
}
|
|
12
12
|
export declare const APTOS_ACCOUNT_HD_PATH = "m/44'/637'/0'/0'/0'";
|
|
13
|
+
/**
|
|
14
|
+
* The `AptosPricePusher` is designed for high-throughput of price updates.
|
|
15
|
+
* Achieving this property requires sacrificing some nice-to-have features of other
|
|
16
|
+
* pusher implementations that can reduce cost when running multiple pushers. Specifically,
|
|
17
|
+
* this implementation does not use `update_price_feeds_if_necssary` and simulate the transaction
|
|
18
|
+
* before submission.
|
|
19
|
+
*
|
|
20
|
+
* If multiple instances of this pusher are running in parallel, both of them will
|
|
21
|
+
* land all of their pushed updates on-chain.
|
|
22
|
+
*/
|
|
13
23
|
export declare class AptosPricePusher implements IPricePusher {
|
|
14
24
|
private priceServiceConnection;
|
|
15
25
|
private pythContractAddress;
|
|
@@ -28,6 +38,7 @@ export declare class AptosPricePusher implements IPricePusher {
|
|
|
28
38
|
*/
|
|
29
39
|
getPriceFeedsUpdateData(priceIds: string[]): Promise<number[][]>;
|
|
30
40
|
updatePriceFeed(priceIds: string[], pubTimesToPush: number[]): Promise<void>;
|
|
41
|
+
private waitForTransactionConfirmation;
|
|
31
42
|
private tryGetNextSequenceNumber;
|
|
32
43
|
}
|
|
33
44
|
//# sourceMappingURL=aptos.d.ts.map
|
package/lib/aptos/aptos.d.ts.map
CHANGED
|
@@ -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;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;
|
|
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;AAE3D;;;;;;;;;GASG;AACH,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;YAiEF,8BAA8B;YAsB9B,wBAAwB;CA+BvC"}
|
package/lib/aptos/aptos.js
CHANGED
|
@@ -44,6 +44,16 @@ class AptosPriceListener extends interface_1.ChainPriceListener {
|
|
|
44
44
|
exports.AptosPriceListener = AptosPriceListener;
|
|
45
45
|
// Derivation path for aptos accounts
|
|
46
46
|
exports.APTOS_ACCOUNT_HD_PATH = "m/44'/637'/0'/0'/0'";
|
|
47
|
+
/**
|
|
48
|
+
* The `AptosPricePusher` is designed for high-throughput of price updates.
|
|
49
|
+
* Achieving this property requires sacrificing some nice-to-have features of other
|
|
50
|
+
* pusher implementations that can reduce cost when running multiple pushers. Specifically,
|
|
51
|
+
* this implementation does not use `update_price_feeds_if_necssary` and simulate the transaction
|
|
52
|
+
* before submission.
|
|
53
|
+
*
|
|
54
|
+
* If multiple instances of this pusher are running in parallel, both of them will
|
|
55
|
+
* land all of their pushed updates on-chain.
|
|
56
|
+
*/
|
|
47
57
|
class AptosPricePusher {
|
|
48
58
|
priceServiceConnection;
|
|
49
59
|
pythContractAddress;
|
|
@@ -104,16 +114,36 @@ class AptosPricePusher {
|
|
|
104
114
|
const signedTx = await client.signTransaction(account, rawTx);
|
|
105
115
|
const pendingTx = await client.submitTransaction(signedTx);
|
|
106
116
|
console.log("Successfully broadcasted txHash:", pendingTx.hash);
|
|
117
|
+
// Sometimes broadcasted txs don't make it on-chain and they cause our sequence number
|
|
118
|
+
// to go out of sync. Missing transactions are rare and we don't want this check to block
|
|
119
|
+
// the next price update. So we use spawn a promise without awaiting on it to wait for the
|
|
120
|
+
// transaction to be confirmed and if it fails, it resets the sequence number and return.
|
|
121
|
+
this.waitForTransactionConfirmation(client, pendingTx.hash);
|
|
107
122
|
return;
|
|
108
123
|
}
|
|
109
124
|
catch (e) {
|
|
110
125
|
console.error("Error executing messages");
|
|
111
|
-
console.
|
|
126
|
+
console.error(e);
|
|
112
127
|
// Reset the sequence number to re-sync it (in case that was the issue)
|
|
113
128
|
this.lastSequenceNumber = undefined;
|
|
114
129
|
return;
|
|
115
130
|
}
|
|
116
131
|
}
|
|
132
|
+
// Wait for the transaction to be confirmed. If it fails, reset the sequence number.
|
|
133
|
+
async waitForTransactionConfirmation(client, txHash) {
|
|
134
|
+
try {
|
|
135
|
+
await client.waitForTransaction(txHash, {
|
|
136
|
+
checkSuccess: true,
|
|
137
|
+
timeoutSecs: 10,
|
|
138
|
+
});
|
|
139
|
+
console.log(`Transaction with txHash "${txHash}" confirmed.`);
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
console.error(`Transaction with txHash "${txHash}" failed to confirm.`);
|
|
143
|
+
console.error(e);
|
|
144
|
+
this.lastSequenceNumber = undefined;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
117
147
|
// Try to get the next sequence number for account. This function uses a local cache
|
|
118
148
|
// to predict the next sequence number if possible; if not, it fetches the number from
|
|
119
149
|
// the blockchain itself (and caches it for later).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injective.d.ts","sourceRoot":"","sources":["../../src/injective/injective.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,sBAAsB,EACvB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,SAAS,EACT,kBAAkB,EAClB,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAiC7C,qBAAa,sBAAuB,SAAQ,kBAAkB;IAE1D,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,YAAY;gBADZ,mBAAmB,EAAE,MAAM,EAC3B,YAAY,EAAE,MAAM,EAC5B,UAAU,EAAE,SAAS,EAAE,EACvB,MAAM,EAAE;QACN,gBAAgB,EAAE,iBAAiB,CAAC;KACrC;IAKG,mBAAmB,CACvB,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;CA6BlC;AAED,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AACF,qBAAa,oBAAqB,YAAW,YAAY;IAMrD,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,YAAY;IAPtB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,OAAO,CAAwB;gBAG7B,sBAAsB,EAAE,sBAAsB,EAC9C,mBAAmB,EAAE,MAAM,EAC3B,YAAY,EAAE,MAAM,EAC5B,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAWxC,OAAO,CAAC,gBAAgB;YAIV,mBAAmB;IAkE3B,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAU1D,eAAe,CACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"injective.d.ts","sourceRoot":"","sources":["../../src/injective/injective.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,sBAAsB,EACvB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,SAAS,EACT,kBAAkB,EAClB,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAiC7C,qBAAa,sBAAuB,SAAQ,kBAAkB;IAE1D,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,YAAY;gBADZ,mBAAmB,EAAE,MAAM,EAC3B,YAAY,EAAE,MAAM,EAC5B,UAAU,EAAE,SAAS,EAAE,EACvB,MAAM,EAAE;QACN,gBAAgB,EAAE,iBAAiB,CAAC;KACrC;IAKG,mBAAmB,CACvB,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;CA6BlC;AAED,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AACF,qBAAa,oBAAqB,YAAW,YAAY;IAMrD,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,YAAY;IAPtB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,OAAO,CAAwB;gBAG7B,sBAAsB,EAAE,sBAAsB,EAC9C,mBAAmB,EAAE,MAAM,EAC3B,YAAY,EAAE,MAAM,EAC5B,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAWxC,OAAO,CAAC,gBAAgB;YAIV,mBAAmB;IAkE3B,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAU1D,eAAe,CACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,IAAI,CAAC;CAmEjB"}
|
|
@@ -69,31 +69,31 @@ class InjectivePricePusher {
|
|
|
69
69
|
});
|
|
70
70
|
const txService = new sdk_ts_1.TxGrpcClient(this.grpcEndpoint);
|
|
71
71
|
// simulation
|
|
72
|
-
const { gasInfo: { gasUsed }, } = await txService.simulate(simulateTxRaw);
|
|
73
|
-
// simulation returns us the approximate gas used
|
|
74
|
-
// gas passed with the transaction should be more than that
|
|
75
|
-
// in order for it to be successfully executed
|
|
76
|
-
// this multiplier takes care of that
|
|
77
|
-
const gas = (gasUsed * this.chainConfig.gasMultiplier).toFixed();
|
|
78
|
-
const fee = {
|
|
79
|
-
amount: [
|
|
80
|
-
{
|
|
81
|
-
denom: "inj",
|
|
82
|
-
amount: (Number(gas) * this.chainConfig.gasPrice).toFixed(),
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
gas,
|
|
86
|
-
};
|
|
87
|
-
const { signBytes, txRaw } = (0, sdk_ts_1.createTransactionFromMsg)({
|
|
88
|
-
sequence: this.account.baseAccount.sequence,
|
|
89
|
-
accountNumber: this.account.baseAccount.accountNumber,
|
|
90
|
-
message: msg,
|
|
91
|
-
chainId: this.chainConfig.chainId,
|
|
92
|
-
fee,
|
|
93
|
-
pubKey: this.wallet.toPublicKey().toBase64(),
|
|
94
|
-
});
|
|
95
|
-
const sig = await this.wallet.sign(Buffer.from(signBytes));
|
|
96
72
|
try {
|
|
73
|
+
const { gasInfo: { gasUsed }, } = await txService.simulate(simulateTxRaw);
|
|
74
|
+
// simulation returns us the approximate gas used
|
|
75
|
+
// gas passed with the transaction should be more than that
|
|
76
|
+
// in order for it to be successfully executed
|
|
77
|
+
// this multiplier takes care of that
|
|
78
|
+
const gas = (gasUsed * this.chainConfig.gasMultiplier).toFixed();
|
|
79
|
+
const fee = {
|
|
80
|
+
amount: [
|
|
81
|
+
{
|
|
82
|
+
denom: "inj",
|
|
83
|
+
amount: (Number(gas) * this.chainConfig.gasPrice).toFixed(),
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
gas,
|
|
87
|
+
};
|
|
88
|
+
const { signBytes, txRaw } = (0, sdk_ts_1.createTransactionFromMsg)({
|
|
89
|
+
sequence: this.account.baseAccount.sequence,
|
|
90
|
+
accountNumber: this.account.baseAccount.accountNumber,
|
|
91
|
+
message: msg,
|
|
92
|
+
chainId: this.chainConfig.chainId,
|
|
93
|
+
fee,
|
|
94
|
+
pubKey: this.wallet.toPublicKey().toBase64(),
|
|
95
|
+
});
|
|
96
|
+
const sig = await this.wallet.sign(Buffer.from(signBytes));
|
|
97
97
|
this.account.baseAccount.sequence++;
|
|
98
98
|
/** Append Signatures */
|
|
99
99
|
txRaw.signatures = [sig];
|
|
@@ -134,12 +134,22 @@ class InjectivePricePusher {
|
|
|
134
134
|
console.error(e);
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
let updateFeeQueryResponse;
|
|
138
|
+
try {
|
|
139
|
+
const api = new sdk_ts_1.ChainGrpcWasmApi(this.grpcEndpoint);
|
|
140
|
+
const { data } = await api.fetchSmartContractState(this.pythContractAddress, Buffer.from(JSON.stringify({
|
|
141
|
+
get_update_fee: {
|
|
142
|
+
vaas: priceFeedUpdateObject.update_price_feeds.data,
|
|
143
|
+
},
|
|
144
|
+
})).toString("base64"));
|
|
145
|
+
const json = Buffer.from(data).toString();
|
|
146
|
+
updateFeeQueryResponse = JSON.parse(json);
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
console.error("Error fetching update fee");
|
|
150
|
+
console.error(e);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
143
153
|
try {
|
|
144
154
|
const executeMsg = sdk_ts_1.MsgExecuteContract.fromJSON({
|
|
145
155
|
sender: this.injectiveAddress(),
|
package/lib/sui/command.js
CHANGED
|
@@ -50,31 +50,31 @@ exports.default = {
|
|
|
50
50
|
},
|
|
51
51
|
"pyth-package-id": {
|
|
52
52
|
description: "Pyth Package Id. Can be found here" +
|
|
53
|
-
"https://docs.pyth.network/pythnet-price-feeds/sui",
|
|
53
|
+
"https://docs.pyth.network/documentation/pythnet-price-feeds/sui",
|
|
54
54
|
type: "string",
|
|
55
55
|
required: true,
|
|
56
56
|
},
|
|
57
57
|
"pyth-state-id": {
|
|
58
58
|
description: "Pyth State Id. Can be found here" +
|
|
59
|
-
"https://docs.pyth.network/pythnet-price-feeds/sui",
|
|
59
|
+
"https://docs.pyth.network/documentation/pythnet-price-feeds/sui",
|
|
60
60
|
type: "string",
|
|
61
61
|
required: true,
|
|
62
62
|
},
|
|
63
63
|
"wormhole-package-id": {
|
|
64
64
|
description: "Wormhole Package Id. Can be found here" +
|
|
65
|
-
"https://docs.pyth.network/pythnet-price-feeds/sui",
|
|
65
|
+
"https://docs.pyth.network/documentation/pythnet-price-feeds/sui",
|
|
66
66
|
type: "string",
|
|
67
67
|
required: true,
|
|
68
68
|
},
|
|
69
69
|
"wormhole-state-id": {
|
|
70
70
|
description: "Wormhole State Id. Can be found here" +
|
|
71
|
-
"https://docs.pyth.network/pythnet-price-feeds/sui",
|
|
71
|
+
"https://docs.pyth.network/documentation/pythnet-price-feeds/sui",
|
|
72
72
|
type: "string",
|
|
73
73
|
required: true,
|
|
74
74
|
},
|
|
75
75
|
"price-feed-to-price-info-object-table-id": {
|
|
76
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",
|
|
77
|
+
"https://docs.pyth.network/documentation/pythnet-price-feeds/sui",
|
|
78
78
|
type: "string",
|
|
79
79
|
required: true,
|
|
80
80
|
},
|
package/lib/sui/sui.d.ts
CHANGED
|
@@ -11,6 +11,20 @@ export declare class SuiPriceListener extends ChainPriceListener {
|
|
|
11
11
|
});
|
|
12
12
|
getOnChainPriceInfo(priceId: string): Promise<PriceInfo | undefined>;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* The `SuiPricePusher` is designed for high-throughput of price updates.
|
|
16
|
+
* Achieving this property requires sacrificing some nice-to-have features of other
|
|
17
|
+
* pusher implementations that can reduce cost when running multiple pushers. It also requires
|
|
18
|
+
* jumping through some Sui-specific hoops in order to maximize parallelism.
|
|
19
|
+
*
|
|
20
|
+
* The two main design features are:
|
|
21
|
+
* 1. This implementation does not use `update_price_feeds_if_necssary` and simulate the transaction
|
|
22
|
+
* before submission. If multiple instances of this pusher are running in parallel, all of them will
|
|
23
|
+
* land all of their pushed updates on-chain.
|
|
24
|
+
* 2. The pusher will split the Coin balance in the provided account into a pool of different Coin objects.
|
|
25
|
+
* Each transaction will be allocated a Coin object from this pool as needed. This process enables the
|
|
26
|
+
* transactions to avoid referencing the same owned objects, which allows them to be processed in parallel.
|
|
27
|
+
*/
|
|
14
28
|
export declare class SuiPricePusher implements IPricePusher {
|
|
15
29
|
private readonly signer;
|
|
16
30
|
private priceServiceConnection;
|
|
@@ -35,6 +49,7 @@ export declare class SuiPricePusher implements IPricePusher {
|
|
|
35
49
|
/** Send a single transaction block using a gas coin from the pool. */
|
|
36
50
|
private sendTransactionBlock;
|
|
37
51
|
private static initializeGasPool;
|
|
52
|
+
private static tryRefreshObjectReference;
|
|
38
53
|
private static getAllGasCoins;
|
|
39
54
|
private static splitGasCoinEqually;
|
|
40
55
|
private static mergeGasCoinsIntoOne;
|
package/lib/sui/sui.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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;;;;;;;;;;;;;GAaG;AACH,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;mBAsDb,iBAAiB;mBA8BjB,yBAAyB;mBAoBzB,cAAc;mBAiCd,mBAAmB;mBAsCnB,oBAAoB;CA2C1C"}
|
package/lib/sui/sui.js
CHANGED
|
@@ -51,6 +51,20 @@ class SuiPriceListener extends interface_1.ChainPriceListener {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
exports.SuiPriceListener = SuiPriceListener;
|
|
54
|
+
/**
|
|
55
|
+
* The `SuiPricePusher` is designed for high-throughput of price updates.
|
|
56
|
+
* Achieving this property requires sacrificing some nice-to-have features of other
|
|
57
|
+
* pusher implementations that can reduce cost when running multiple pushers. It also requires
|
|
58
|
+
* jumping through some Sui-specific hoops in order to maximize parallelism.
|
|
59
|
+
*
|
|
60
|
+
* The two main design features are:
|
|
61
|
+
* 1. This implementation does not use `update_price_feeds_if_necssary` and simulate the transaction
|
|
62
|
+
* before submission. If multiple instances of this pusher are running in parallel, all of them will
|
|
63
|
+
* land all of their pushed updates on-chain.
|
|
64
|
+
* 2. The pusher will split the Coin balance in the provided account into a pool of different Coin objects.
|
|
65
|
+
* Each transaction will be allocated a Coin object from this pool as needed. This process enables the
|
|
66
|
+
* transactions to avoid referencing the same owned objects, which allows them to be processed in parallel.
|
|
67
|
+
*/
|
|
54
68
|
class SuiPricePusher {
|
|
55
69
|
signer;
|
|
56
70
|
priceServiceConnection;
|
|
@@ -222,9 +236,14 @@ class SuiPricePusher {
|
|
|
222
236
|
console.warn(`The balance of gas object ${gasObject.objectId} is too low. Removing from pool.`);
|
|
223
237
|
}
|
|
224
238
|
else {
|
|
225
|
-
|
|
239
|
+
// Refresh the coin object here in case the error is caused by an object version mismatch.
|
|
240
|
+
nextGasObject = await SuiPricePusher.tryRefreshObjectReference(this.signer.provider, gasObject);
|
|
226
241
|
}
|
|
227
242
|
console.error(e);
|
|
243
|
+
if ("data" in e) {
|
|
244
|
+
console.error("Error has .data field:");
|
|
245
|
+
console.error(JSON.stringify(e.data));
|
|
246
|
+
}
|
|
228
247
|
}
|
|
229
248
|
if (nextGasObject !== undefined) {
|
|
230
249
|
this.gasPool.push(nextGasObject);
|
|
@@ -243,6 +262,27 @@ class SuiPricePusher {
|
|
|
243
262
|
console.log("Gas pool is filled with coins: ", gasPool);
|
|
244
263
|
return gasPool;
|
|
245
264
|
}
|
|
265
|
+
// Attempt to refresh the version of the provided object reference to point to the current version
|
|
266
|
+
// of the object. Return the provided object reference if an error occurs or the object could not
|
|
267
|
+
// be retrieved.
|
|
268
|
+
static async tryRefreshObjectReference(provider, ref) {
|
|
269
|
+
try {
|
|
270
|
+
const objectResponse = await provider.getObject({ id: ref.objectId });
|
|
271
|
+
if (objectResponse.data !== undefined) {
|
|
272
|
+
return {
|
|
273
|
+
digest: objectResponse.data.digest,
|
|
274
|
+
objectId: objectResponse.data.objectId,
|
|
275
|
+
version: objectResponse.data.version,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
return ref;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
return ref;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
246
286
|
static async getAllGasCoins(provider, owner) {
|
|
247
287
|
let hasNextPage = true;
|
|
248
288
|
let cursor;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pythnetwork/price-pusher",
|
|
3
|
-
"version": "5.4.
|
|
3
|
+
"version": "5.4.9",
|
|
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": "
|
|
66
|
+
"gitHead": "d5c3090442940a6a1d7c254be9896fa38b827e40"
|
|
67
67
|
}
|