@injectivelabs/wallet-core 0.0.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 (76) hide show
  1. package/README.md +77 -0
  2. package/dist/cjs/broadcaster/MsgBroadcaster.d.ts +125 -0
  3. package/dist/cjs/broadcaster/MsgBroadcaster.d.ts.map +1 -0
  4. package/dist/cjs/broadcaster/MsgBroadcaster.js +703 -0
  5. package/dist/cjs/broadcaster/MsgBroadcaster.js.map +1 -0
  6. package/dist/cjs/broadcaster/Web3Broadcaster.d.ts +30 -0
  7. package/dist/cjs/broadcaster/Web3Broadcaster.d.ts.map +1 -0
  8. package/dist/cjs/broadcaster/Web3Broadcaster.js +41 -0
  9. package/dist/cjs/broadcaster/Web3Broadcaster.js.map +1 -0
  10. package/dist/cjs/broadcaster/index.d.ts +4 -0
  11. package/dist/cjs/broadcaster/index.d.ts.map +1 -0
  12. package/dist/cjs/broadcaster/index.js +20 -0
  13. package/dist/cjs/broadcaster/index.js.map +1 -0
  14. package/dist/cjs/broadcaster/types.d.ts +33 -0
  15. package/dist/cjs/broadcaster/types.d.ts.map +1 -0
  16. package/dist/cjs/broadcaster/types.js +3 -0
  17. package/dist/cjs/broadcaster/types.js.map +1 -0
  18. package/dist/cjs/index.d.ts +4 -0
  19. package/dist/cjs/index.d.ts.map +1 -0
  20. package/dist/cjs/index.js +20 -0
  21. package/dist/cjs/index.js.map +1 -0
  22. package/dist/cjs/package.json +3 -0
  23. package/dist/cjs/strategy/BaseWalletStrategy.d.ts +45 -0
  24. package/dist/cjs/strategy/BaseWalletStrategy.d.ts.map +1 -0
  25. package/dist/cjs/strategy/BaseWalletStrategy.js +154 -0
  26. package/dist/cjs/strategy/BaseWalletStrategy.js.map +1 -0
  27. package/dist/cjs/strategy/index.d.ts +3 -0
  28. package/dist/cjs/strategy/index.d.ts.map +1 -0
  29. package/dist/cjs/strategy/index.js +9 -0
  30. package/dist/cjs/strategy/index.js.map +1 -0
  31. package/dist/cjs/utils/index.d.ts +2 -0
  32. package/dist/cjs/utils/index.d.ts.map +1 -0
  33. package/dist/cjs/utils/index.js +18 -0
  34. package/dist/cjs/utils/index.js.map +1 -0
  35. package/dist/cjs/utils/tx.d.ts +2 -0
  36. package/dist/cjs/utils/tx.d.ts.map +1 -0
  37. package/dist/cjs/utils/tx.js +12 -0
  38. package/dist/cjs/utils/tx.js.map +1 -0
  39. package/dist/esm/broadcaster/MsgBroadcaster.d.ts +125 -0
  40. package/dist/esm/broadcaster/MsgBroadcaster.d.ts.map +1 -0
  41. package/dist/esm/broadcaster/MsgBroadcaster.js +704 -0
  42. package/dist/esm/broadcaster/MsgBroadcaster.js.map +1 -0
  43. package/dist/esm/broadcaster/Web3Broadcaster.d.ts +30 -0
  44. package/dist/esm/broadcaster/Web3Broadcaster.d.ts.map +1 -0
  45. package/dist/esm/broadcaster/Web3Broadcaster.js +28 -0
  46. package/dist/esm/broadcaster/Web3Broadcaster.js.map +1 -0
  47. package/dist/esm/broadcaster/index.d.ts +4 -0
  48. package/dist/esm/broadcaster/index.d.ts.map +1 -0
  49. package/dist/esm/broadcaster/index.js +4 -0
  50. package/dist/esm/broadcaster/index.js.map +1 -0
  51. package/dist/esm/broadcaster/types.d.ts +33 -0
  52. package/dist/esm/broadcaster/types.d.ts.map +1 -0
  53. package/dist/esm/broadcaster/types.js +2 -0
  54. package/dist/esm/broadcaster/types.js.map +1 -0
  55. package/dist/esm/index.d.ts +4 -0
  56. package/dist/esm/index.d.ts.map +1 -0
  57. package/dist/esm/index.js +4 -0
  58. package/dist/esm/index.js.map +1 -0
  59. package/dist/esm/package.json +3 -0
  60. package/dist/esm/strategy/BaseWalletStrategy.d.ts +45 -0
  61. package/dist/esm/strategy/BaseWalletStrategy.d.ts.map +1 -0
  62. package/dist/esm/strategy/BaseWalletStrategy.js +121 -0
  63. package/dist/esm/strategy/BaseWalletStrategy.js.map +1 -0
  64. package/dist/esm/strategy/index.d.ts +3 -0
  65. package/dist/esm/strategy/index.d.ts.map +1 -0
  66. package/dist/esm/strategy/index.js +3 -0
  67. package/dist/esm/strategy/index.js.map +1 -0
  68. package/dist/esm/utils/index.d.ts +2 -0
  69. package/dist/esm/utils/index.d.ts.map +1 -0
  70. package/dist/esm/utils/index.js +2 -0
  71. package/dist/esm/utils/index.js.map +1 -0
  72. package/dist/esm/utils/tx.d.ts +2 -0
  73. package/dist/esm/utils/tx.d.ts.map +1 -0
  74. package/dist/esm/utils/tx.js +8 -0
  75. package/dist/esm/utils/tx.js.map +1 -0
  76. package/package.json +57 -0
@@ -0,0 +1,703 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.MsgBroadcaster = void 0;
13
+ const sdk_ts_1 = require("@injectivelabs/sdk-ts");
14
+ const utils_1 = require("@injectivelabs/utils");
15
+ const exceptions_1 = require("@injectivelabs/exceptions");
16
+ const networks_1 = require("@injectivelabs/networks");
17
+ const tx_1 = require("./../utils/tx");
18
+ const wallet_base_1 = require("@injectivelabs/wallet-base");
19
+ const getEthereumWalletPubKey = ({ pubKey, eip712TypedData, signature, }) => {
20
+ if (pubKey) {
21
+ return pubKey;
22
+ }
23
+ return (0, sdk_ts_1.hexToBase64)((0, sdk_ts_1.recoverTypedSignaturePubKey)(eip712TypedData, signature));
24
+ };
25
+ /**
26
+ * This class is used to broadcast transactions
27
+ * using the WalletStrategy as a handler
28
+ * for the sign/broadcast flow of the transactions
29
+ *
30
+ * Mainly used for building UI products
31
+ */
32
+ class MsgBroadcaster {
33
+ constructor(options) {
34
+ this.txTimeout = utils_1.DEFAULT_BLOCK_TIMEOUT_HEIGHT;
35
+ this.simulateTx = true;
36
+ this.txTimeoutOnFeeDelegation = false;
37
+ this.gasBufferCoefficient = 1.2;
38
+ const networkInfo = (0, networks_1.getNetworkInfo)(options.network);
39
+ this.options = options;
40
+ this.simulateTx =
41
+ options.simulateTx !== undefined ? options.simulateTx : true;
42
+ this.txTimeout = options.txTimeout || utils_1.DEFAULT_BLOCK_TIMEOUT_HEIGHT;
43
+ this.txTimeoutOnFeeDelegation =
44
+ options.txTimeoutOnFeeDelegation !== undefined
45
+ ? options.txTimeoutOnFeeDelegation
46
+ : true;
47
+ this.gasBufferCoefficient = options.gasBufferCoefficient || 1.2;
48
+ this.chainId = options.chainId || networkInfo.chainId;
49
+ this.ethereumChainId =
50
+ options.ethereumChainId || networkInfo.ethereumChainId;
51
+ this.endpoints = options.endpoints || (0, networks_1.getNetworkEndpoints)(options.network);
52
+ this.walletStrategy = options.walletStrategy;
53
+ }
54
+ setOptions(options) {
55
+ this.simulateTx = options.simulateTx || this.simulateTx;
56
+ this.txTimeout = options.txTimeout || this.txTimeout;
57
+ this.txTimeoutOnFeeDelegation =
58
+ options.txTimeoutOnFeeDelegation || this.txTimeoutOnFeeDelegation;
59
+ }
60
+ /**
61
+ * Broadcasting the transaction using the client
62
+ * side approach for both cosmos and ethereum native wallets
63
+ *
64
+ * @param tx
65
+ * @returns {string} transaction hash
66
+ */
67
+ broadcast(tx) {
68
+ return __awaiter(this, void 0, void 0, function* () {
69
+ const { walletStrategy } = this;
70
+ const txWithAddresses = Object.assign(Object.assign({}, tx), { ethereumAddress: (0, wallet_base_1.getEthereumSignerAddress)(tx.injectiveAddress), injectiveAddress: (0, wallet_base_1.getInjectiveSignerAddress)(tx.injectiveAddress) });
71
+ if (sdk_ts_1.ofacWallets.includes(txWithAddresses.ethereumAddress)) {
72
+ throw new exceptions_1.GeneralException(new Error('You cannot execute this transaction'));
73
+ }
74
+ return (0, wallet_base_1.isCosmosWallet)(walletStrategy.wallet)
75
+ ? this.broadcastCosmos(txWithAddresses)
76
+ : (0, wallet_base_1.isEip712V2OnlyWallet)(walletStrategy.wallet)
77
+ ? this.broadcastWeb3V2(txWithAddresses)
78
+ : this.broadcastWeb3(txWithAddresses);
79
+ });
80
+ }
81
+ /**
82
+ * Broadcasting the transaction using the client
83
+ * side approach for both cosmos and ethereum native wallets
84
+ * Note: using EIP712_V2 for Ethereum wallets
85
+ *
86
+ * @param tx
87
+ * @returns {string} transaction hash
88
+ */
89
+ broadcastV2(tx) {
90
+ return __awaiter(this, void 0, void 0, function* () {
91
+ const { walletStrategy } = this;
92
+ const txWithAddresses = Object.assign(Object.assign({}, tx), { ethereumAddress: (0, wallet_base_1.getEthereumSignerAddress)(tx.injectiveAddress), injectiveAddress: (0, wallet_base_1.getInjectiveSignerAddress)(tx.injectiveAddress) });
93
+ if (sdk_ts_1.ofacWallets.includes(txWithAddresses.ethereumAddress)) {
94
+ throw new exceptions_1.GeneralException(new Error('You cannot execute this transaction'));
95
+ }
96
+ return (0, wallet_base_1.isCosmosWallet)(walletStrategy.wallet)
97
+ ? this.broadcastCosmos(txWithAddresses)
98
+ : this.broadcastWeb3V2(txWithAddresses);
99
+ });
100
+ }
101
+ /**
102
+ * Broadcasting the transaction using the feeDelegation
103
+ * support approach for both cosmos and ethereum native wallets
104
+ *
105
+ * @param tx
106
+ * @returns {string} transaction hash
107
+ */
108
+ broadcastWithFeeDelegation(tx) {
109
+ return __awaiter(this, void 0, void 0, function* () {
110
+ const { walletStrategy } = this;
111
+ const txWithAddresses = Object.assign(Object.assign({}, tx), { ethereumAddress: (0, wallet_base_1.getEthereumSignerAddress)(tx.injectiveAddress), injectiveAddress: (0, wallet_base_1.getInjectiveSignerAddress)(tx.injectiveAddress) });
112
+ if (sdk_ts_1.ofacWallets.includes(txWithAddresses.ethereumAddress)) {
113
+ throw new exceptions_1.GeneralException(new Error('You cannot execute this transaction'));
114
+ }
115
+ return (0, wallet_base_1.isCosmosWallet)(walletStrategy.wallet)
116
+ ? this.broadcastCosmosWithFeeDelegation(txWithAddresses)
117
+ : this.broadcastWeb3WithFeeDelegation(txWithAddresses);
118
+ });
119
+ }
120
+ /**
121
+ * Prepare/sign/broadcast transaction using
122
+ * Ethereum native wallets on the client side.
123
+ *
124
+ * Note: Gas estimation not available
125
+ *
126
+ * @param tx The transaction that needs to be broadcasted
127
+ * @returns transaction hash
128
+ */
129
+ broadcastWeb3(tx) {
130
+ return __awaiter(this, void 0, void 0, function* () {
131
+ var _a, _b;
132
+ const { chainId, txTimeout, endpoints, ethereumChainId, walletStrategy } = this;
133
+ const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
134
+ if (!ethereumChainId) {
135
+ throw new exceptions_1.GeneralException(new Error('Please provide ethereumChainId'));
136
+ }
137
+ /** Account Details * */
138
+ const accountDetails = yield new sdk_ts_1.ChainGrpcAuthApi(endpoints.grpc).fetchAccount(tx.injectiveAddress);
139
+ const { baseAccount } = accountDetails;
140
+ /** Block Details */
141
+ const latestBlock = yield new sdk_ts_1.ChainGrpcTendermintApi(endpoints.grpc).fetchLatestBlock();
142
+ const latestHeight = latestBlock.header.height;
143
+ const timeoutHeight = new utils_1.BigNumberInBase(latestHeight).plus(txTimeout);
144
+ const gas = (((_a = tx.gas) === null || _a === void 0 ? void 0 : _a.gas) || (0, sdk_ts_1.getGasPriceBasedOnMessage)(msgs)).toString();
145
+ let stdFee = (0, utils_1.getStdFee)(Object.assign(Object.assign({}, tx.gas), { gas }));
146
+ /**
147
+ * Account has been created on chain
148
+ * and we can simulate the transaction
149
+ * to estimate the gas
150
+ **/
151
+ if (baseAccount.pubKey) {
152
+ const { stdFee: simulatedStdFee } = yield this.getTxWithSignersAndStdFee({
153
+ chainId,
154
+ signMode: sdk_ts_1.SIGN_EIP712,
155
+ memo: tx.memo,
156
+ message: msgs,
157
+ timeoutHeight: timeoutHeight.toNumber(),
158
+ signers: {
159
+ pubKey: baseAccount.pubKey.key,
160
+ accountNumber: baseAccount.accountNumber,
161
+ sequence: baseAccount.sequence,
162
+ },
163
+ fee: stdFee,
164
+ });
165
+ stdFee = simulatedStdFee;
166
+ }
167
+ /** EIP712 for signing on Ethereum wallets */
168
+ const eip712TypedData = (0, sdk_ts_1.getEip712TypedData)({
169
+ msgs,
170
+ fee: stdFee,
171
+ tx: {
172
+ memo: tx.memo,
173
+ accountNumber: baseAccount.accountNumber.toString(),
174
+ sequence: baseAccount.sequence.toString(),
175
+ timeoutHeight: timeoutHeight.toFixed(),
176
+ chainId,
177
+ },
178
+ ethereumChainId,
179
+ });
180
+ /** Signing on Ethereum */
181
+ const signature = yield walletStrategy.signEip712TypedData(JSON.stringify(eip712TypedData), tx.ethereumAddress);
182
+ const pubKeyOrSignatureDerivedPubKey = getEthereumWalletPubKey({
183
+ pubKey: (_b = baseAccount.pubKey) === null || _b === void 0 ? void 0 : _b.key,
184
+ eip712TypedData,
185
+ signature,
186
+ });
187
+ /** Preparing the transaction for client broadcasting */
188
+ const { txRaw } = (0, sdk_ts_1.createTransaction)({
189
+ message: msgs,
190
+ memo: tx.memo,
191
+ signMode: sdk_ts_1.SIGN_EIP712,
192
+ fee: stdFee,
193
+ pubKey: pubKeyOrSignatureDerivedPubKey,
194
+ sequence: baseAccount.sequence,
195
+ timeoutHeight: timeoutHeight.toNumber(),
196
+ accountNumber: baseAccount.accountNumber,
197
+ chainId,
198
+ });
199
+ const web3Extension = (0, sdk_ts_1.createWeb3Extension)({
200
+ ethereumChainId,
201
+ });
202
+ const txRawEip712 = (0, sdk_ts_1.createTxRawEIP712)(txRaw, web3Extension);
203
+ /** Append Signatures */
204
+ txRawEip712.signatures = [(0, sdk_ts_1.hexToBuff)(signature)];
205
+ return walletStrategy.sendTransaction(txRawEip712, {
206
+ chainId,
207
+ endpoints,
208
+ txTimeout,
209
+ address: tx.injectiveAddress,
210
+ });
211
+ });
212
+ }
213
+ /**
214
+ * Prepare/sign/broadcast transaction using
215
+ * Ethereum native wallets on the client side.
216
+ *
217
+ * Note: Gas estimation not available
218
+ *
219
+ * @param tx The transaction that needs to be broadcasted
220
+ * @returns transaction hash
221
+ */
222
+ broadcastWeb3V2(tx) {
223
+ return __awaiter(this, void 0, void 0, function* () {
224
+ var _a, _b;
225
+ const { walletStrategy, chainId, txTimeout, endpoints, ethereumChainId } = this;
226
+ const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
227
+ if (!ethereumChainId) {
228
+ throw new exceptions_1.GeneralException(new Error('Please provide ethereumChainId'));
229
+ }
230
+ /** Account Details * */
231
+ const accountDetails = yield new sdk_ts_1.ChainGrpcAuthApi(endpoints.grpc).fetchAccount(tx.injectiveAddress);
232
+ const { baseAccount } = accountDetails;
233
+ /** Block Details */
234
+ const latestBlock = yield new sdk_ts_1.ChainGrpcTendermintApi(endpoints.grpc).fetchLatestBlock();
235
+ const latestHeight = latestBlock.header.height;
236
+ const timeoutHeight = new utils_1.BigNumberInBase(latestHeight).plus(txTimeout);
237
+ const gas = (((_a = tx.gas) === null || _a === void 0 ? void 0 : _a.gas) || (0, sdk_ts_1.getGasPriceBasedOnMessage)(msgs)).toString();
238
+ let stdFee = (0, utils_1.getStdFee)(Object.assign(Object.assign({}, tx.gas), { gas }));
239
+ /**
240
+ * Account has been created on chain
241
+ * and we can simulate the transaction
242
+ * to estimate the gas
243
+ **/
244
+ if (baseAccount.pubKey) {
245
+ const { stdFee: simulatedStdFee } = yield this.getTxWithSignersAndStdFee({
246
+ chainId,
247
+ signMode: sdk_ts_1.SIGN_EIP712_V2,
248
+ memo: tx.memo,
249
+ message: msgs,
250
+ timeoutHeight: timeoutHeight.toNumber(),
251
+ signers: {
252
+ pubKey: baseAccount.pubKey.key,
253
+ accountNumber: baseAccount.accountNumber,
254
+ sequence: baseAccount.sequence,
255
+ },
256
+ fee: stdFee,
257
+ });
258
+ stdFee = simulatedStdFee;
259
+ }
260
+ /** EIP712 for signing on Ethereum wallets */
261
+ const eip712TypedData = (0, sdk_ts_1.getEip712TypedDataV2)({
262
+ msgs,
263
+ fee: stdFee,
264
+ tx: {
265
+ memo: tx.memo,
266
+ accountNumber: baseAccount.accountNumber.toString(),
267
+ sequence: baseAccount.sequence.toString(),
268
+ timeoutHeight: timeoutHeight.toFixed(),
269
+ chainId,
270
+ },
271
+ ethereumChainId,
272
+ });
273
+ /** Signing on Ethereum */
274
+ const signature = yield walletStrategy.signEip712TypedData(JSON.stringify(eip712TypedData), tx.ethereumAddress);
275
+ const pubKeyOrSignatureDerivedPubKey = getEthereumWalletPubKey({
276
+ pubKey: (_b = baseAccount.pubKey) === null || _b === void 0 ? void 0 : _b.key,
277
+ eip712TypedData,
278
+ signature,
279
+ });
280
+ const { txRaw } = (0, sdk_ts_1.createTransaction)({
281
+ message: msgs,
282
+ memo: tx.memo,
283
+ signMode: sdk_ts_1.SIGN_EIP712_V2,
284
+ fee: stdFee,
285
+ pubKey: pubKeyOrSignatureDerivedPubKey,
286
+ sequence: baseAccount.sequence,
287
+ timeoutHeight: timeoutHeight.toNumber(),
288
+ accountNumber: baseAccount.accountNumber,
289
+ chainId,
290
+ });
291
+ const web3Extension = (0, sdk_ts_1.createWeb3Extension)({
292
+ ethereumChainId,
293
+ });
294
+ const txRawEip712 = (0, sdk_ts_1.createTxRawEIP712)(txRaw, web3Extension);
295
+ /** Append Signatures */
296
+ txRawEip712.signatures = [(0, sdk_ts_1.hexToBuff)(signature)];
297
+ return walletStrategy.sendTransaction(txRawEip712, {
298
+ chainId,
299
+ endpoints,
300
+ txTimeout,
301
+ address: tx.injectiveAddress,
302
+ });
303
+ });
304
+ }
305
+ /**
306
+ * Prepare/sign/broadcast transaction using
307
+ * Ethereum native wallets using the Web3Gateway.
308
+ *
309
+ * @param tx The transaction that needs to be broadcasted
310
+ * @returns transaction hash
311
+ */
312
+ broadcastWeb3WithFeeDelegation(tx) {
313
+ return __awaiter(this, void 0, void 0, function* () {
314
+ const { txTimeout, endpoints, simulateTx, walletStrategy, ethereumChainId, txTimeoutOnFeeDelegation, } = this;
315
+ const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
316
+ const web3Msgs = msgs.map((msg) => msg.toWeb3());
317
+ if (!ethereumChainId) {
318
+ throw new exceptions_1.GeneralException(new Error('Please provide ethereumChainId'));
319
+ }
320
+ const transactionApi = new sdk_ts_1.IndexerGrpcWeb3GwApi(endpoints.web3gw || endpoints.indexer);
321
+ let timeoutHeight = undefined;
322
+ if (txTimeoutOnFeeDelegation) {
323
+ const latestBlock = yield new sdk_ts_1.ChainGrpcTendermintApi(endpoints.grpc).fetchLatestBlock();
324
+ const latestHeight = latestBlock.header.height;
325
+ timeoutHeight = new utils_1.BigNumberInBase(latestHeight)
326
+ .plus(txTimeout)
327
+ .toNumber();
328
+ }
329
+ const txResponse = yield transactionApi.prepareTxRequest({
330
+ timeoutHeight,
331
+ memo: tx.memo,
332
+ message: web3Msgs,
333
+ address: tx.ethereumAddress,
334
+ chainId: ethereumChainId,
335
+ gasLimit: (0, sdk_ts_1.getGasPriceBasedOnMessage)(msgs),
336
+ estimateGas: simulateTx,
337
+ });
338
+ const signature = yield walletStrategy.signEip712TypedData(txResponse.data, tx.ethereumAddress);
339
+ const response = yield transactionApi.broadcastTxRequest({
340
+ signature,
341
+ txResponse,
342
+ message: web3Msgs,
343
+ chainId: ethereumChainId,
344
+ });
345
+ try {
346
+ const txResponse = yield new sdk_ts_1.TxGrpcApi(endpoints.grpc).fetchTxPoll(response.txHash);
347
+ return txResponse;
348
+ }
349
+ catch (e) {
350
+ /**
351
+ * First MsgExec transaction with a PrivateKey wallet
352
+ * always runs out of gas for some reason, temporary solution
353
+ * to just broadcast the transaction twice
354
+ **/
355
+ if (walletStrategy.wallet === wallet_base_1.Wallet.PrivateKey &&
356
+ (0, tx_1.checkIfTxRunOutOfGas)(e)) {
357
+ /** Account Details * */
358
+ const accountDetails = yield new sdk_ts_1.ChainGrpcAuthApi(endpoints.grpc).fetchAccount(tx.injectiveAddress);
359
+ const { baseAccount } = accountDetails;
360
+ /** We only do it on the first account tx fail */
361
+ if (baseAccount.sequence > 1) {
362
+ throw e;
363
+ }
364
+ return yield this.broadcastWeb3WithFeeDelegation(tx);
365
+ }
366
+ throw e;
367
+ }
368
+ });
369
+ }
370
+ /**
371
+ * Prepare/sign/broadcast transaction using
372
+ * Cosmos native wallets on the client side.
373
+ *
374
+ * @param tx The transaction that needs to be broadcasted
375
+ * @returns transaction hash
376
+ */
377
+ broadcastCosmos(tx) {
378
+ return __awaiter(this, void 0, void 0, function* () {
379
+ var _a, _b, _c;
380
+ const { walletStrategy, txTimeout, endpoints, chainId } = this;
381
+ const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
382
+ /**
383
+ * When using Ledger with Keplr/Leap we have
384
+ * to send EIP712 to sign on Keplr/Leap
385
+ */
386
+ if ([wallet_base_1.Wallet.Keplr, wallet_base_1.Wallet.Leap].includes(walletStrategy.getWallet())) {
387
+ const walletDeviceType = yield walletStrategy.getWalletDeviceType();
388
+ const isLedgerConnected = walletDeviceType === wallet_base_1.WalletDeviceType.Hardware;
389
+ if (isLedgerConnected) {
390
+ return this.experimentalBroadcastWalletThroughLedger(tx);
391
+ }
392
+ }
393
+ /** Account Details * */
394
+ const accountDetails = yield new sdk_ts_1.ChainGrpcAuthApi(endpoints.grpc).fetchAccount(tx.injectiveAddress);
395
+ const { baseAccount } = accountDetails;
396
+ /** Block Details */
397
+ const latestBlock = yield new sdk_ts_1.ChainGrpcTendermintApi(endpoints.grpc).fetchLatestBlock();
398
+ const latestHeight = latestBlock.header.height;
399
+ const timeoutHeight = new utils_1.BigNumberInBase(latestHeight).plus(txTimeout);
400
+ const signMode = (0, wallet_base_1.isCosmosAminoOnlyWallet)(walletStrategy.wallet)
401
+ ? sdk_ts_1.SIGN_EIP712
402
+ : sdk_ts_1.SIGN_DIRECT;
403
+ const pubKey = yield walletStrategy.getPubKey(tx.injectiveAddress);
404
+ const gas = (((_a = tx.gas) === null || _a === void 0 ? void 0 : _a.gas) || (0, sdk_ts_1.getGasPriceBasedOnMessage)(msgs)).toString();
405
+ /** Prepare the Transaction * */
406
+ const { txRaw } = yield this.getTxWithSignersAndStdFee({
407
+ chainId,
408
+ signMode,
409
+ memo: tx.memo,
410
+ message: msgs,
411
+ timeoutHeight: timeoutHeight.toNumber(),
412
+ signers: {
413
+ pubKey,
414
+ accountNumber: baseAccount.accountNumber,
415
+ sequence: baseAccount.sequence,
416
+ },
417
+ fee: (0, utils_1.getStdFee)(Object.assign(Object.assign({}, tx.gas), { gas })),
418
+ });
419
+ /** Ledger using Cosmos app only allows signing amino docs */
420
+ if ((0, wallet_base_1.isCosmosAminoOnlyWallet)(walletStrategy.wallet)) {
421
+ const aminoSignDoc = (0, sdk_ts_1.getAminoStdSignDoc)(Object.assign(Object.assign(Object.assign({}, tx), baseAccount), { msgs,
422
+ chainId, gas: gas || ((_c = (_b = tx.gas) === null || _b === void 0 ? void 0 : _b.gas) === null || _c === void 0 ? void 0 : _c.toString()), timeoutHeight: timeoutHeight.toFixed() }));
423
+ const signResponse = yield walletStrategy.signAminoCosmosTransaction({
424
+ signDoc: aminoSignDoc,
425
+ address: tx.injectiveAddress,
426
+ });
427
+ txRaw.signatures = [
428
+ Buffer.from(signResponse.signature.signature, 'base64'),
429
+ ];
430
+ return walletStrategy.sendTransaction(txRaw, {
431
+ chainId,
432
+ endpoints,
433
+ txTimeout,
434
+ address: tx.injectiveAddress,
435
+ });
436
+ }
437
+ const directSignResponse = (yield walletStrategy.signCosmosTransaction({
438
+ txRaw,
439
+ chainId,
440
+ address: tx.injectiveAddress,
441
+ accountNumber: baseAccount.accountNumber,
442
+ }));
443
+ return walletStrategy.sendTransaction(directSignResponse, {
444
+ chainId,
445
+ endpoints,
446
+ txTimeout,
447
+ address: tx.injectiveAddress,
448
+ });
449
+ });
450
+ }
451
+ /**
452
+ * We use this method only when we want to broadcast a transaction using Ledger on Keplr/Leap for Injective
453
+ *
454
+ * Note: Gas estimation not available
455
+ * @param tx the transaction that needs to be broadcasted
456
+ */
457
+ experimentalBroadcastWalletThroughLedger(tx) {
458
+ return __awaiter(this, void 0, void 0, function* () {
459
+ var _a, _b, _c;
460
+ const { chainId, txTimeout, endpoints, simulateTx, walletStrategy, ethereumChainId, } = this;
461
+ const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
462
+ /**
463
+ * We can only use this method
464
+ * when Ledger is connected through Keplr
465
+ */
466
+ if ([wallet_base_1.Wallet.Keplr, wallet_base_1.Wallet.Leap].includes(walletStrategy.getWallet())) {
467
+ const walletDeviceType = yield walletStrategy.getWalletDeviceType();
468
+ const isLedgerConnected = walletDeviceType === wallet_base_1.WalletDeviceType.Hardware;
469
+ if (!isLedgerConnected) {
470
+ throw new exceptions_1.GeneralException(new Error(`This method can only be used when Ledger is connected through ${walletStrategy.getWallet()}`));
471
+ }
472
+ }
473
+ if (!ethereumChainId) {
474
+ throw new exceptions_1.GeneralException(new Error('Please provide ethereumChainId'));
475
+ }
476
+ const cosmosWallet = walletStrategy.getCosmosWallet(chainId);
477
+ /** Account Details * */
478
+ const accountDetails = yield new sdk_ts_1.ChainGrpcAuthApi(endpoints.grpc).fetchAccount(tx.injectiveAddress);
479
+ const { baseAccount } = accountDetails;
480
+ /** Block Details */
481
+ const latestBlock = yield new sdk_ts_1.ChainGrpcTendermintApi(endpoints.grpc).fetchLatestBlock();
482
+ const latestHeight = latestBlock.header.height;
483
+ const timeoutHeight = new utils_1.BigNumberInBase(latestHeight).plus(txTimeout);
484
+ const pubKey = yield walletStrategy.getPubKey();
485
+ const gas = (((_a = tx.gas) === null || _a === void 0 ? void 0 : _a.gas) || (0, sdk_ts_1.getGasPriceBasedOnMessage)(msgs)).toString();
486
+ /** EIP712 for signing on Ethereum wallets */
487
+ const eip712TypedData = (0, sdk_ts_1.getEip712TypedData)({
488
+ msgs,
489
+ fee: (0, utils_1.getStdFee)(Object.assign(Object.assign({}, tx.gas), { gas })),
490
+ tx: {
491
+ memo: tx.memo,
492
+ accountNumber: baseAccount.accountNumber.toString(),
493
+ sequence: baseAccount.sequence.toString(),
494
+ timeoutHeight: timeoutHeight.toFixed(),
495
+ chainId,
496
+ },
497
+ ethereumChainId,
498
+ });
499
+ const aminoSignResponse = yield cosmosWallet.signEIP712CosmosTx({
500
+ eip712: eip712TypedData,
501
+ signDoc: (0, wallet_base_1.createEip712StdSignDoc)(Object.assign(Object.assign(Object.assign({}, tx), baseAccount), { msgs,
502
+ chainId, gas: gas || ((_c = (_b = tx.gas) === null || _b === void 0 ? void 0 : _b.gas) === null || _c === void 0 ? void 0 : _c.toString()), timeoutHeight: timeoutHeight.toFixed() })),
503
+ });
504
+ /**
505
+ * Create TxRaw from the signed tx that we
506
+ * get as a response in case the user changed the fee/memo
507
+ * on the Keplr popup
508
+ */
509
+ const { txRaw } = (0, sdk_ts_1.createTransaction)({
510
+ pubKey,
511
+ message: msgs,
512
+ memo: aminoSignResponse.signed.memo,
513
+ signMode: sdk_ts_1.SIGN_EIP712,
514
+ fee: aminoSignResponse.signed.fee,
515
+ sequence: parseInt(aminoSignResponse.signed.sequence, 10),
516
+ timeoutHeight: parseInt(aminoSignResponse.signed.timeout_height, 10),
517
+ accountNumber: parseInt(aminoSignResponse.signed.account_number, 10),
518
+ chainId,
519
+ });
520
+ /** Preparing the transaction for client broadcasting */
521
+ const web3Extension = (0, sdk_ts_1.createWeb3Extension)({
522
+ ethereumChainId,
523
+ });
524
+ const txRawEip712 = (0, sdk_ts_1.createTxRawEIP712)(txRaw, web3Extension);
525
+ if (simulateTx) {
526
+ yield this.simulateTxRaw(txRawEip712);
527
+ }
528
+ /** Append Signatures */
529
+ const signatureBuff = Buffer.from(aminoSignResponse.signature.signature, 'base64');
530
+ txRawEip712.signatures = [signatureBuff];
531
+ /** Broadcast the transaction */
532
+ const response = yield new sdk_ts_1.TxGrpcApi(endpoints.grpc).broadcast(txRawEip712, { txTimeout });
533
+ if (response.code !== 0) {
534
+ throw new exceptions_1.TransactionException(new Error(response.rawLog), {
535
+ code: exceptions_1.UnspecifiedErrorCode,
536
+ contextCode: response.code,
537
+ contextModule: response.codespace,
538
+ });
539
+ }
540
+ return response;
541
+ });
542
+ }
543
+ /**
544
+ * Prepare/sign/broadcast transaction using
545
+ * Cosmos native wallets using the Web3Gateway.
546
+ *
547
+ * @param tx The transaction that needs to be broadcasted
548
+ * @returns transaction hash
549
+ */
550
+ broadcastCosmosWithFeeDelegation(tx) {
551
+ return __awaiter(this, void 0, void 0, function* () {
552
+ var _a;
553
+ const { options, chainId, txTimeout, endpoints, walletStrategy, txTimeoutOnFeeDelegation, } = this;
554
+ const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
555
+ /**
556
+ * We can only use this method when Keplr is connected
557
+ * with ledger
558
+ */
559
+ if (walletStrategy.getWallet() === wallet_base_1.Wallet.Keplr) {
560
+ const walletDeviceType = yield walletStrategy.getWalletDeviceType();
561
+ const isLedgerConnectedOnKeplr = walletDeviceType === wallet_base_1.WalletDeviceType.Hardware;
562
+ if (isLedgerConnectedOnKeplr) {
563
+ throw new exceptions_1.GeneralException(new Error('Keplr + Ledger is not available with fee delegation. Connect with Ledger directly.'));
564
+ }
565
+ }
566
+ const cosmosWallet = walletStrategy.getCosmosWallet(chainId);
567
+ const feePayerPubKey = yield this.fetchFeePayerPubKey(options.feePayerPubKey);
568
+ const feePayerPublicKey = sdk_ts_1.PublicKey.fromBase64(feePayerPubKey);
569
+ const feePayer = feePayerPublicKey.toAddress().address;
570
+ /** Account Details * */
571
+ const chainGrpcAuthApi = new sdk_ts_1.ChainGrpcAuthApi(endpoints.grpc);
572
+ const accountDetails = yield chainGrpcAuthApi.fetchAccount(tx.injectiveAddress);
573
+ const feePayerAccountDetails = yield chainGrpcAuthApi.fetchAccount(feePayer);
574
+ const { baseAccount } = accountDetails;
575
+ const { baseAccount: feePayerBaseAccount } = feePayerAccountDetails;
576
+ /** Block Details */
577
+ const latestBlock = yield new sdk_ts_1.ChainGrpcTendermintApi(endpoints.grpc).fetchLatestBlock();
578
+ const latestHeight = latestBlock.header.height;
579
+ const timeoutHeight = new utils_1.BigNumberInBase(latestHeight).plus(txTimeoutOnFeeDelegation ? txTimeout : utils_1.DEFAULT_BLOCK_TIMEOUT_HEIGHT);
580
+ const pubKey = yield walletStrategy.getPubKey();
581
+ const gas = (((_a = tx.gas) === null || _a === void 0 ? void 0 : _a.gas) || (0, sdk_ts_1.getGasPriceBasedOnMessage)(msgs)).toString();
582
+ /** Prepare the Transaction * */
583
+ const { txRaw } = yield this.getTxWithSignersAndStdFee({
584
+ chainId,
585
+ memo: tx.memo,
586
+ message: msgs,
587
+ timeoutHeight: timeoutHeight.toNumber(),
588
+ signers: [
589
+ {
590
+ pubKey,
591
+ accountNumber: baseAccount.accountNumber,
592
+ sequence: baseAccount.sequence,
593
+ },
594
+ {
595
+ pubKey: feePayerPublicKey.toBase64(),
596
+ accountNumber: feePayerBaseAccount.accountNumber,
597
+ sequence: feePayerBaseAccount.sequence,
598
+ },
599
+ ],
600
+ fee: (0, utils_1.getStdFee)(Object.assign(Object.assign({}, tx.gas), { gas, payer: feePayer })),
601
+ });
602
+ // Temporary remove tx gas check because Keplr doesn't recognize feePayer
603
+ if (walletStrategy.wallet === wallet_base_1.Wallet.Keplr &&
604
+ cosmosWallet.disableGasCheck) {
605
+ cosmosWallet.disableGasCheck(chainId);
606
+ }
607
+ const directSignResponse = (yield walletStrategy.signCosmosTransaction({
608
+ txRaw,
609
+ chainId,
610
+ address: tx.injectiveAddress,
611
+ accountNumber: baseAccount.accountNumber,
612
+ }));
613
+ const transactionApi = new sdk_ts_1.IndexerGrpcWeb3GwApi(endpoints.web3gw || endpoints.indexer);
614
+ const response = yield transactionApi.broadcastCosmosTxRequest({
615
+ address: tx.injectiveAddress,
616
+ txRaw: (0, sdk_ts_1.createTxRawFromSigResponse)(directSignResponse),
617
+ signature: directSignResponse.signature.signature,
618
+ pubKey: directSignResponse.signature.pub_key || {
619
+ value: pubKey,
620
+ type: '/injective.crypto.v1beta1.ethsecp256k1.PubKey',
621
+ },
622
+ });
623
+ // Re-enable tx gas check removed above
624
+ if (walletStrategy.wallet === wallet_base_1.Wallet.Keplr && cosmosWallet.enableGasCheck) {
625
+ cosmosWallet.enableGasCheck(chainId);
626
+ }
627
+ return yield new sdk_ts_1.TxGrpcApi(endpoints.grpc).fetchTxPoll(response.txHash);
628
+ });
629
+ }
630
+ /**
631
+ * Fetch the fee payer's pub key from the web3 gateway
632
+ *
633
+ * Returns a base64 version of it
634
+ */
635
+ fetchFeePayerPubKey(existingFeePayerPubKey) {
636
+ return __awaiter(this, void 0, void 0, function* () {
637
+ if (existingFeePayerPubKey) {
638
+ return existingFeePayerPubKey;
639
+ }
640
+ const { endpoints } = this;
641
+ const transactionApi = new sdk_ts_1.IndexerGrpcWeb3GwApi(endpoints.web3gw || endpoints.indexer);
642
+ const response = yield transactionApi.fetchFeePayer();
643
+ if (!response.feePayerPubKey) {
644
+ throw new exceptions_1.GeneralException(new Error('Please provide a feePayerPubKey'));
645
+ }
646
+ if (response.feePayerPubKey.key.startsWith('0x') ||
647
+ response.feePayerPubKey.key.length === 66) {
648
+ return Buffer.from(response.feePayerPubKey.key, 'hex').toString('base64');
649
+ }
650
+ return response.feePayerPubKey.key;
651
+ });
652
+ }
653
+ /**
654
+ * In case we don't want to simulate the transaction
655
+ * we get the gas limit based on the message type.
656
+ *
657
+ * If we want to simulate the transaction we set the
658
+ * gas limit based on the simulation and add a small multiplier
659
+ * to be safe (factor of 1.2 as default)
660
+ */
661
+ getTxWithSignersAndStdFee(args) {
662
+ return __awaiter(this, void 0, void 0, function* () {
663
+ var _a;
664
+ const { simulateTx } = this;
665
+ if (!simulateTx) {
666
+ return Object.assign(Object.assign({}, (0, sdk_ts_1.createTransactionWithSigners)(args)), { stdFee: (0, utils_1.getStdFee)(args.fee) });
667
+ }
668
+ const result = yield this.simulateTxWithSigners(args);
669
+ if (!((_a = result.gasInfo) === null || _a === void 0 ? void 0 : _a.gasUsed)) {
670
+ return Object.assign(Object.assign({}, (0, sdk_ts_1.createTransactionWithSigners)(args)), { stdFee: (0, utils_1.getStdFee)(args.fee) });
671
+ }
672
+ const stdGasFee = Object.assign({}, (0, utils_1.getStdFee)(Object.assign(Object.assign({}, (0, utils_1.getStdFee)(args.fee)), { gas: new utils_1.BigNumberInBase(result.gasInfo.gasUsed)
673
+ .times(this.gasBufferCoefficient)
674
+ .toFixed() })));
675
+ return Object.assign(Object.assign({}, (0, sdk_ts_1.createTransactionWithSigners)(Object.assign(Object.assign({}, args), { fee: stdGasFee }))), { stdFee: stdGasFee });
676
+ });
677
+ }
678
+ /**
679
+ * Create TxRaw and simulate it
680
+ */
681
+ simulateTxRaw(txRaw) {
682
+ return __awaiter(this, void 0, void 0, function* () {
683
+ const { endpoints } = this;
684
+ txRaw.signatures = [new Uint8Array(0)];
685
+ const simulationResponse = yield new sdk_ts_1.TxGrpcApi(endpoints.grpc).simulate(txRaw);
686
+ return simulationResponse;
687
+ });
688
+ }
689
+ /**
690
+ * Create TxRaw and simulate it
691
+ */
692
+ simulateTxWithSigners(args) {
693
+ return __awaiter(this, void 0, void 0, function* () {
694
+ const { endpoints } = this;
695
+ const { txRaw } = (0, sdk_ts_1.createTransactionWithSigners)(args);
696
+ txRaw.signatures = Array(Array.isArray(args.signers) ? args.signers.length : 1).fill(new Uint8Array(0));
697
+ const simulationResponse = yield new sdk_ts_1.TxGrpcApi(endpoints.grpc).simulate(txRaw);
698
+ return simulationResponse;
699
+ });
700
+ }
701
+ }
702
+ exports.MsgBroadcaster = MsgBroadcaster;
703
+ //# sourceMappingURL=MsgBroadcaster.js.map