@@ -19,6 +19,7 @@ import {
1919 TxResponse ,
2020 createTransactionFromMsg ,
2121} from "@injectivelabs/sdk-ts" ;
22+ import { Account } from "@injectivelabs/sdk-ts/dist/cjs/client/chain/types/auth" ;
2223
2324const DEFAULT_GAS_PRICE = 500000000 ;
2425
@@ -93,6 +94,7 @@ type InjectiveConfig = {
9394export class InjectivePricePusher implements IPricePusher {
9495 private wallet : PrivateKey ;
9596 private chainConfig : InjectiveConfig ;
97+ private account : Account | null = null ;
9698
9799 constructor (
98100 private priceServiceConnection : PriceServiceConnection ,
@@ -116,12 +118,14 @@ export class InjectivePricePusher implements IPricePusher {
116118
117119 private async signAndBroadcastMsg ( msg : Msgs ) : Promise < TxResponse > {
118120 const chainGrpcAuthApi = new ChainGrpcAuthApi ( this . grpcEndpoint ) ;
119- const account = await chainGrpcAuthApi . fetchAccount (
121+ // Fetch the latest account details only if it's not stored.
122+ this . account ??= await chainGrpcAuthApi . fetchAccount (
120123 this . injectiveAddress ( )
121124 ) ;
125+
122126 const { txRaw : simulateTxRaw } = createTransactionFromMsg ( {
123- sequence : account . baseAccount . sequence ,
124- accountNumber : account . baseAccount . accountNumber ,
127+ sequence : this . account . baseAccount . sequence ,
128+ accountNumber : this . account . baseAccount . accountNumber ,
125129 message : msg ,
126130 chainId : this . chainConfig . chainId ,
127131 pubKey : this . wallet . toPublicKey ( ) . toBase64 ( ) ,
@@ -137,23 +141,20 @@ export class InjectivePricePusher implements IPricePusher {
137141 // gas passed with the transaction should be more than that
138142 // in order for it to be successfully executed
139143 // this multiplier takes care of that
144+ const gas = ( gasUsed * this . chainConfig . gasMultiplier ) . toFixed ( ) ;
140145 const fee = {
141146 amount : [
142147 {
143148 denom : "inj" ,
144- amount : (
145- gasUsed *
146- this . chainConfig . gasPrice *
147- this . chainConfig . gasMultiplier
148- ) . toFixed ( ) ,
149+ amount : ( Number ( gas ) * this . chainConfig . gasPrice ) . toFixed ( ) ,
149150 } ,
150151 ] ,
151- gas : ( gasUsed * this . chainConfig . gasMultiplier ) . toFixed ( ) ,
152+ gas,
152153 } ;
153154
154155 const { signBytes, txRaw } = createTransactionFromMsg ( {
155- sequence : account . baseAccount . sequence ,
156- accountNumber : account . baseAccount . accountNumber ,
156+ sequence : this . account . baseAccount . sequence ,
157+ accountNumber : this . account . baseAccount . accountNumber ,
157158 message : msg ,
158159 chainId : this . chainConfig . chainId ,
159160 fee,
@@ -162,11 +163,23 @@ export class InjectivePricePusher implements IPricePusher {
162163
163164 const sig = await this . wallet . sign ( Buffer . from ( signBytes ) ) ;
164165
165- /** Append Signatures */
166- txRaw . signatures = [ sig ] ;
167- const txResponse = await txService . broadcast ( txRaw ) ;
166+ try {
167+ this . account . baseAccount . sequence ++ ;
168+
169+ /** Append Signatures */
170+ txRaw . signatures = [ sig ] ;
171+ // this takes approx 5 seconds
172+ const txResponse = await txService . broadcast ( txRaw ) ;
168173
169- return txResponse ;
174+ return txResponse ;
175+ } catch ( e : any ) {
176+ // The sequence number was invalid and hence we will have to fetch it again.
177+ if ( e . message . match ( / a c c o u n t s e q u e n c e m i s m a t c h / ) !== null ) {
178+ // We need to fetch the account details again.
179+ this . account = null ;
180+ }
181+ throw e ;
182+ }
170183 }
171184
172185 async getPriceFeedUpdateObject ( priceIds : string [ ] ) : Promise < any > {
@@ -200,27 +213,12 @@ export class InjectivePricePusher implements IPricePusher {
200213 return ;
201214 }
202215
203- let updateFeeQueryResponse : UpdateFeeResponse ;
204- try {
205- const api = new ChainGrpcWasmApi ( this . grpcEndpoint ) ;
206- const { data } = await api . fetchSmartContractState (
207- this . pythContractAddress ,
208- Buffer . from (
209- JSON . stringify ( {
210- get_update_fee : {
211- vaas : priceFeedUpdateObject . update_price_feeds . data ,
212- } ,
213- } )
214- ) . toString ( "base64" )
215- ) ;
216-
217- const json = Buffer . from ( data ) . toString ( ) ;
218- updateFeeQueryResponse = JSON . parse ( json ) ;
219- } catch ( e ) {
220- console . error ( "Error fetching update fee" ) ;
221- console . error ( e ) ;
222- return ;
223- }
216+ // In order to reduce the number of API calls
217+ // We are calculating the fee using the same logic as in contract.
218+ const updateFeeQueryResponse : UpdateFeeResponse = {
219+ denom : "inj" ,
220+ amount : priceFeedUpdateObject . update_price_feeds . data . length . toFixed ( ) ,
221+ } ;
224222
225223 try {
226224 const executeMsg = MsgExecuteContract . fromJSON ( {
@@ -231,9 +229,6 @@ export class InjectivePricePusher implements IPricePusher {
231229 } ) ;
232230
233231 const rs = await this . signAndBroadcastMsg ( executeMsg ) ;
234-
235- if ( rs . code !== 0 ) throw new Error ( "Error: transaction failed" ) ;
236-
237232 console . log ( "Succesfully broadcasted txHash:" , rs . txHash ) ;
238233 } catch ( e : any ) {
239234 if ( e . message . match ( / a c c o u n t i n j [ a - z A - Z 0 - 9 ] + n o t f o u n d / ) !== null ) {
0 commit comments