@injectivelabs/wallet-core 1.20.8 → 1.20.10
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/dist/cjs/BaseWalletStrategy-Bvs5nQRI.d.cts +71 -0
- package/dist/cjs/broadcaster-CPCJe4Al.cjs +1076 -0
- package/dist/cjs/broadcaster.cjs +5 -0
- package/dist/cjs/broadcaster.d.cts +3 -0
- package/dist/cjs/defineProperty-CImP5zIM.cjs +49 -0
- package/dist/cjs/index-DLoAMD9J.d.cts +1 -0
- package/dist/cjs/index-NsR1NUse.d.cts +246 -0
- package/dist/cjs/index.cjs +8 -1260
- package/dist/cjs/index.d.cts +3 -309
- package/dist/cjs/strategy-D8mmr647.cjs +167 -0
- package/dist/cjs/strategy.cjs +4 -0
- package/dist/cjs/strategy.d.cts +3 -0
- package/dist/esm/BaseWalletStrategy-D2xNJmzo.d.ts +71 -0
- package/dist/esm/broadcaster-CA8Ix8IA.js +1059 -0
- package/dist/esm/broadcaster.d.ts +3 -0
- package/dist/esm/broadcaster.js +4 -0
- package/dist/esm/defineProperty-D4YE9KXX.js +43 -0
- package/dist/esm/index-B98CLRUl.d.ts +246 -0
- package/dist/esm/index-DRYular4.d.ts +1 -0
- package/dist/esm/index.d.ts +3 -309
- package/dist/esm/index.js +3 -1255
- package/dist/esm/strategy-DU-V-GfI.js +162 -0
- package/dist/esm/strategy.d.ts +3 -0
- package/dist/esm/strategy.js +4 -0
- package/package.json +47 -7
|
@@ -0,0 +1,1059 @@
|
|
|
1
|
+
import { t as _defineProperty } from "./defineProperty-D4YE9KXX.js";
|
|
2
|
+
import { ChainCosmosErrorCode, GeneralException, TransactionChainErrorModule, TransactionException, UnspecifiedErrorCode, WalletException, Web3Exception, isThrownException } from "@injectivelabs/exceptions";
|
|
3
|
+
import { EvmChainId } from "@injectivelabs/ts-types";
|
|
4
|
+
import { PrivateKey, PublicKey } from "@injectivelabs/sdk-ts/core/accounts";
|
|
5
|
+
import { base64ToUint8Array, getGasPriceBasedOnMessage, hexToBase64, hexToBuff, hexToUint8Array, ofacList, recoverTypedSignaturePubKey, safeBigIntStringify, uint8ArrayToBase64 } from "@injectivelabs/sdk-ts/utils";
|
|
6
|
+
import { IndexerGrpcWeb3GwApi } from "@injectivelabs/sdk-ts/client/indexer";
|
|
7
|
+
import { getNetworkEndpoints, getNetworkInfo, isMainnet, isTestnet } from "@injectivelabs/networks";
|
|
8
|
+
import { ChainGrpcAuthApi, ChainGrpcTendermintApi, ChainGrpcTxFeesApi } from "@injectivelabs/sdk-ts/client/chain";
|
|
9
|
+
import { DEFAULT_BLOCK_TIMEOUT_HEIGHT, DEFAULT_BLOCK_TIME_IN_SECONDS, DEFAULT_GAS_PRICE, getStdFee, sleep, toBigNumber } from "@injectivelabs/utils";
|
|
10
|
+
import { Wallet, WalletDeviceType, WalletStrategyEmitterEventType, createEip712StdSignDoc, getEthereumSignerAddress, getInjectiveSignerAddress, isCosmosAminoOnlyWallet, isCosmosWallet, isEip712V2OnlyWallet, isEvmBrowserWallet } from "@injectivelabs/wallet-base";
|
|
11
|
+
import { CosmosTxV1Beta1TxPb, SIGN_DIRECT, SIGN_EIP712, SIGN_EIP712_V2, TxClient, TxGrpcApi, createTransaction, createTransactionWithSigners, createTxRawEIP712, createTxRawFromSigResponse, createWeb3Extension, getAminoStdSignDoc, getEip712TypedData, getEip712TypedDataV2 } from "@injectivelabs/sdk-ts/core/tx";
|
|
12
|
+
|
|
13
|
+
//#region src/utils/tx.ts
|
|
14
|
+
const checkIfTxRunOutOfGas = (e) => {
|
|
15
|
+
return e instanceof TransactionException && e.contextCode === ChainCosmosErrorCode.ErrOutOfGas && e.contextModule === TransactionChainErrorModule.CosmosSdk && e.originalMessage.includes("out of gas");
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/broadcaster/MsgBroadcaster.ts
|
|
20
|
+
const getEthereumWalletPubKey = async ({ pubKey, eip712TypedData, signature }) => {
|
|
21
|
+
if (pubKey) return pubKey;
|
|
22
|
+
return hexToBase64(await recoverTypedSignaturePubKey(eip712TypedData, signature));
|
|
23
|
+
};
|
|
24
|
+
const defaultRetriesConfig = () => ({ [`${TransactionChainErrorModule.CosmosSdk}-${ChainCosmosErrorCode.ErrMempoolIsFull}`]: {
|
|
25
|
+
retries: 0,
|
|
26
|
+
maxRetries: 10,
|
|
27
|
+
timeout: 1e3
|
|
28
|
+
} });
|
|
29
|
+
/**
|
|
30
|
+
* This class is used to broadcast transactions
|
|
31
|
+
* using the WalletStrategy as a handler
|
|
32
|
+
* for the sign/broadcast flow of the transactions
|
|
33
|
+
*
|
|
34
|
+
* Mainly used for building UI products
|
|
35
|
+
*/
|
|
36
|
+
var MsgBroadcaster = class {
|
|
37
|
+
constructor(options) {
|
|
38
|
+
_defineProperty(this, "options", void 0);
|
|
39
|
+
_defineProperty(this, "walletStrategy", void 0);
|
|
40
|
+
_defineProperty(this, "endpoints", void 0);
|
|
41
|
+
_defineProperty(this, "chainId", void 0);
|
|
42
|
+
_defineProperty(this, "txTimeout", DEFAULT_BLOCK_TIMEOUT_HEIGHT);
|
|
43
|
+
_defineProperty(this, "simulateTx", true);
|
|
44
|
+
_defineProperty(this, "txTimeoutOnFeeDelegation", false);
|
|
45
|
+
_defineProperty(this, "evmChainId", void 0);
|
|
46
|
+
_defineProperty(this, "gasBufferCoefficient", 1.2);
|
|
47
|
+
_defineProperty(this, "retriesOnError", defaultRetriesConfig());
|
|
48
|
+
_defineProperty(this, "httpHeaders", void 0);
|
|
49
|
+
_defineProperty(this, "txInclusion", void 0);
|
|
50
|
+
const networkInfo = getNetworkInfo(options.network);
|
|
51
|
+
this.options = options;
|
|
52
|
+
this.simulateTx = options.simulateTx !== void 0 ? options.simulateTx : true;
|
|
53
|
+
this.txTimeout = options.txTimeout || DEFAULT_BLOCK_TIMEOUT_HEIGHT;
|
|
54
|
+
this.txTimeoutOnFeeDelegation = options.txTimeoutOnFeeDelegation !== void 0 ? options.txTimeoutOnFeeDelegation : true;
|
|
55
|
+
this.gasBufferCoefficient = options.gasBufferCoefficient || 1.2;
|
|
56
|
+
this.chainId = options.chainId || networkInfo.chainId;
|
|
57
|
+
this.evmChainId = options.evmChainId || networkInfo.evmChainId;
|
|
58
|
+
this.endpoints = options.endpoints || getNetworkEndpoints(options.network);
|
|
59
|
+
this.walletStrategy = options.walletStrategy;
|
|
60
|
+
this.httpHeaders = options.httpHeaders;
|
|
61
|
+
this.txInclusion = options.txInclusion;
|
|
62
|
+
}
|
|
63
|
+
setOptions(options) {
|
|
64
|
+
this.simulateTx = options.simulateTx || this.simulateTx;
|
|
65
|
+
this.txTimeout = options.txTimeout || this.txTimeout;
|
|
66
|
+
this.txTimeoutOnFeeDelegation = options.txTimeoutOnFeeDelegation || this.txTimeoutOnFeeDelegation;
|
|
67
|
+
this.txInclusion = options.txInclusion || this.txInclusion;
|
|
68
|
+
}
|
|
69
|
+
async getEvmChainId() {
|
|
70
|
+
const { walletStrategy } = this;
|
|
71
|
+
if (!isEvmBrowserWallet(walletStrategy.wallet)) return this.evmChainId;
|
|
72
|
+
const mainnetEvmIds = [EvmChainId.Mainnet, EvmChainId.MainnetEvm];
|
|
73
|
+
const testnetEvmIds = [EvmChainId.Sepolia, EvmChainId.TestnetEvm];
|
|
74
|
+
const devnetEvmIds = [
|
|
75
|
+
EvmChainId.Sepolia,
|
|
76
|
+
EvmChainId.DevnetEvm,
|
|
77
|
+
EvmChainId.MainnetEvm,
|
|
78
|
+
EvmChainId.TestnetEvm
|
|
79
|
+
];
|
|
80
|
+
try {
|
|
81
|
+
const chainId = await walletStrategy.getEthereumChainId();
|
|
82
|
+
if (!chainId) return this.evmChainId;
|
|
83
|
+
const evmChainId = parseInt(chainId, 16);
|
|
84
|
+
if (isNaN(evmChainId)) return this.evmChainId;
|
|
85
|
+
if (isMainnet(this.options.network) && !mainnetEvmIds.includes(evmChainId) || isTestnet(this.options.network) && !testnetEvmIds.includes(evmChainId) || !isMainnet(this.options.network) && !isTestnet(this.options.network) && !devnetEvmIds.includes(evmChainId)) throw new WalletException(/* @__PURE__ */ new Error("Your selected network is incorrect"));
|
|
86
|
+
return evmChainId;
|
|
87
|
+
} catch (e) {
|
|
88
|
+
throw new WalletException(e);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Broadcasting the transaction using the client
|
|
93
|
+
* side approach for both cosmos and ethereum native wallets
|
|
94
|
+
*
|
|
95
|
+
* @param tx
|
|
96
|
+
* @returns {string} transaction hash
|
|
97
|
+
*/
|
|
98
|
+
async broadcast(tx) {
|
|
99
|
+
const { walletStrategy } = this;
|
|
100
|
+
const txWithAddresses = {
|
|
101
|
+
...tx,
|
|
102
|
+
ethereumAddress: getEthereumSignerAddress(tx.injectiveAddress),
|
|
103
|
+
injectiveAddress: getInjectiveSignerAddress(tx.injectiveAddress)
|
|
104
|
+
};
|
|
105
|
+
if (ofacList.includes(txWithAddresses.ethereumAddress)) throw new GeneralException(/* @__PURE__ */ new Error("You cannot execute this transaction"));
|
|
106
|
+
try {
|
|
107
|
+
return isCosmosWallet(walletStrategy.wallet) ? await this.broadcastDirectSign(txWithAddresses) : isEip712V2OnlyWallet(walletStrategy.wallet) ? await this.broadcastEip712V2(txWithAddresses) : await this.broadcastEip712(txWithAddresses);
|
|
108
|
+
} catch (e) {
|
|
109
|
+
const error = e;
|
|
110
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionFail);
|
|
111
|
+
if (isThrownException(error)) throw error;
|
|
112
|
+
throw new TransactionException(new Error(error));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Broadcasting the transaction using the client
|
|
117
|
+
* side approach for both cosmos and ethereum native wallets
|
|
118
|
+
* Note: using EIP712_V2 for Ethereum wallets
|
|
119
|
+
*
|
|
120
|
+
* @param tx
|
|
121
|
+
* @returns {string} transaction hash
|
|
122
|
+
*/
|
|
123
|
+
async broadcastV2(tx) {
|
|
124
|
+
const { walletStrategy } = this;
|
|
125
|
+
const txWithAddresses = {
|
|
126
|
+
...tx,
|
|
127
|
+
ethereumAddress: getEthereumSignerAddress(tx.injectiveAddress),
|
|
128
|
+
injectiveAddress: getInjectiveSignerAddress(tx.injectiveAddress)
|
|
129
|
+
};
|
|
130
|
+
if (ofacList.includes(txWithAddresses.ethereumAddress)) throw new GeneralException(/* @__PURE__ */ new Error("You cannot execute this transaction"));
|
|
131
|
+
try {
|
|
132
|
+
return isCosmosWallet(walletStrategy.wallet) ? await this.broadcastDirectSign(txWithAddresses) : await this.broadcastEip712V2(txWithAddresses);
|
|
133
|
+
} catch (e) {
|
|
134
|
+
const error = e;
|
|
135
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionFail);
|
|
136
|
+
if (isThrownException(error)) throw error;
|
|
137
|
+
throw new TransactionException(new Error(error));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Broadcasting the transaction using the feeDelegation
|
|
142
|
+
* support approach for both cosmos and ethereum native wallets
|
|
143
|
+
*
|
|
144
|
+
* @param tx
|
|
145
|
+
* @returns {string} transaction hash
|
|
146
|
+
*/
|
|
147
|
+
async broadcastWithFeeDelegation(tx) {
|
|
148
|
+
const { walletStrategy } = this;
|
|
149
|
+
const txWithAddresses = {
|
|
150
|
+
...tx,
|
|
151
|
+
ethereumAddress: getEthereumSignerAddress(tx.injectiveAddress),
|
|
152
|
+
injectiveAddress: getInjectiveSignerAddress(tx.injectiveAddress)
|
|
153
|
+
};
|
|
154
|
+
if (ofacList.includes(txWithAddresses.ethereumAddress)) throw new GeneralException(/* @__PURE__ */ new Error("You cannot execute this transaction"));
|
|
155
|
+
try {
|
|
156
|
+
return isCosmosWallet(walletStrategy.wallet) ? await this.broadcastDirectSignWithFeeDelegation(txWithAddresses) : await this.broadcastEip712WithFeeDelegation(txWithAddresses);
|
|
157
|
+
} catch (e) {
|
|
158
|
+
const error = e;
|
|
159
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionFail);
|
|
160
|
+
if (isThrownException(error)) throw error;
|
|
161
|
+
throw new TransactionException(new Error(error));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Sign and broadcast a pre-built transaction whose fee payer signature
|
|
166
|
+
* is already provided (e.g. from the RFQ executor / web3-gw `prepare`
|
|
167
|
+
* endpoint). The taker is signed locally with the supplied private key.
|
|
168
|
+
*
|
|
169
|
+
* Autosign-only: the caller passes the autosign private key directly
|
|
170
|
+
* (e.g. `sharedWalletStore.autoSign.privateKey`). We don't go through
|
|
171
|
+
* `walletStrategy.signCosmosTransaction` because the PK strategy stubs
|
|
172
|
+
* that out — and going through the wallet strategy would defeat the
|
|
173
|
+
* point of autosign (no popups).
|
|
174
|
+
*
|
|
175
|
+
* @param tx Base64-encoded or raw `TxRaw` bytes returned by the prepare endpoint
|
|
176
|
+
* @param feePayerSig Hex (`0x...`) or base64 fee payer signature
|
|
177
|
+
* @param accountNumber Account number of the taker
|
|
178
|
+
* @param privateKey Taker (autosign) private key — hex, with or without `0x`
|
|
179
|
+
* @returns transaction response with txHash
|
|
180
|
+
*/
|
|
181
|
+
async broadcastWithFeePayerSig({ tx, privateKey, feePayerSig, accountNumber, txInclusion, txTimeoutInBlocks: txTimeoutInBlocksParam }) {
|
|
182
|
+
const { chainId, endpoints, walletStrategy } = this;
|
|
183
|
+
const txTimeoutInBlocks = this.resolveTimeoutInBlocks(txTimeoutInBlocksParam);
|
|
184
|
+
const pk = PrivateKey.fromHex(privateKey);
|
|
185
|
+
if (ofacList.includes(pk.toHex().toLowerCase())) throw new GeneralException(/* @__PURE__ */ new Error("You cannot execute this transaction"));
|
|
186
|
+
const txBytes = typeof tx === "string" ? base64ToUint8Array(tx) : tx;
|
|
187
|
+
const txRaw = CosmosTxV1Beta1TxPb.TxRaw.fromBinary(txBytes);
|
|
188
|
+
try {
|
|
189
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionPreparationStart);
|
|
190
|
+
const signDoc = CosmosTxV1Beta1TxPb.SignDoc.create({
|
|
191
|
+
chainId,
|
|
192
|
+
bodyBytes: txRaw.bodyBytes,
|
|
193
|
+
authInfoBytes: txRaw.authInfoBytes,
|
|
194
|
+
accountNumber: BigInt(accountNumber)
|
|
195
|
+
});
|
|
196
|
+
const signDocBytes = CosmosTxV1Beta1TxPb.SignDoc.toBinary(signDoc);
|
|
197
|
+
const takerSig = await pk.sign(signDocBytes);
|
|
198
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionPreparationEnd);
|
|
199
|
+
txRaw.signatures = [takerSig, feePayerSig.startsWith("0x") ? hexToUint8Array(feePayerSig.slice(2)) : base64ToUint8Array(feePayerSig)];
|
|
200
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastStart);
|
|
201
|
+
const txInclusionOptions = this.resolveTxInclusionOptions({ txInclusion });
|
|
202
|
+
const txResponse = await new TxGrpcApi(endpoints.grpc).broadcast(txRaw, {
|
|
203
|
+
txTimeout: txTimeoutInBlocks,
|
|
204
|
+
...txInclusionOptions,
|
|
205
|
+
onBroadcast: () => {
|
|
206
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastSynced);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastEnd);
|
|
210
|
+
if (txResponse.code !== 0) throw new TransactionException(/* @__PURE__ */ new Error(`Transaction failed - ${txResponse.rawLog} - ${txResponse.txHash}`), {
|
|
211
|
+
code: UnspecifiedErrorCode,
|
|
212
|
+
contextCode: txResponse.code,
|
|
213
|
+
contextModule: txResponse.codespace
|
|
214
|
+
});
|
|
215
|
+
return txResponse;
|
|
216
|
+
} catch (e) {
|
|
217
|
+
const error = e;
|
|
218
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionFail);
|
|
219
|
+
if (isThrownException(error)) throw error;
|
|
220
|
+
throw new TransactionException(new Error(error));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Prepare/sign/broadcast transaction using
|
|
225
|
+
* Ethereum native wallets on the client side.
|
|
226
|
+
*
|
|
227
|
+
* Note: Gas estimation not available
|
|
228
|
+
*
|
|
229
|
+
* @param tx The transaction that needs to be broadcasted
|
|
230
|
+
* @returns transaction hash
|
|
231
|
+
*/
|
|
232
|
+
async broadcastEip712(tx) {
|
|
233
|
+
var _tx$gas, _baseAccount$pubKey;
|
|
234
|
+
const { chainId, endpoints, walletStrategy } = this;
|
|
235
|
+
const txTimeoutInBlocks = this.resolveTimeoutInBlocks(tx.txTimeoutInBlocks);
|
|
236
|
+
const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
|
|
237
|
+
const [evmChainId, { baseAccount, latestHeight }] = await Promise.all([this.getEvmChainId(), this.fetchAccountAndBlockDetails(tx.injectiveAddress, tx.accountDetails)]);
|
|
238
|
+
if (!evmChainId) throw new GeneralException(/* @__PURE__ */ new Error("Please provide evmChainId"));
|
|
239
|
+
const timeoutHeight = toBigNumber(latestHeight.toString()).plus(txTimeoutInBlocks);
|
|
240
|
+
const txTimeoutTimeInSeconds = txTimeoutInBlocks * DEFAULT_BLOCK_TIME_IN_SECONDS;
|
|
241
|
+
const txTimeoutTimeInMilliSeconds = txTimeoutTimeInSeconds * 1e3;
|
|
242
|
+
const gas = (((_tx$gas = tx.gas) === null || _tx$gas === void 0 ? void 0 : _tx$gas.gas) || getGasPriceBasedOnMessage(msgs)).toString();
|
|
243
|
+
let stdFee = getStdFee({
|
|
244
|
+
...tx.gas,
|
|
245
|
+
gas
|
|
246
|
+
});
|
|
247
|
+
/**
|
|
248
|
+
* Account has not been created on chain
|
|
249
|
+
* and we cannot simulate the transaction
|
|
250
|
+
* to estimate the gas
|
|
251
|
+
**/
|
|
252
|
+
if (!baseAccount.pubKey) stdFee = await this.getStdFeeWithDynamicBaseFee(stdFee);
|
|
253
|
+
else {
|
|
254
|
+
const { stdFee: simulatedStdFee } = await this.getTxWithSignersAndStdFee({
|
|
255
|
+
chainId,
|
|
256
|
+
signMode: SIGN_EIP712,
|
|
257
|
+
memo: tx.memo,
|
|
258
|
+
message: msgs,
|
|
259
|
+
timeoutHeight: timeoutHeight.toNumber(),
|
|
260
|
+
signers: {
|
|
261
|
+
pubKey: baseAccount.pubKey.key,
|
|
262
|
+
accountNumber: baseAccount.accountNumber,
|
|
263
|
+
sequence: baseAccount.sequence
|
|
264
|
+
},
|
|
265
|
+
fee: stdFee
|
|
266
|
+
});
|
|
267
|
+
stdFee = simulatedStdFee;
|
|
268
|
+
}
|
|
269
|
+
/** EIP712 for signing on Ethereum wallets */
|
|
270
|
+
const eip712TypedData = getEip712TypedData({
|
|
271
|
+
msgs,
|
|
272
|
+
fee: stdFee,
|
|
273
|
+
tx: {
|
|
274
|
+
memo: tx.memo,
|
|
275
|
+
accountNumber: baseAccount.accountNumber.toString(),
|
|
276
|
+
sequence: baseAccount.sequence.toString(),
|
|
277
|
+
timeoutHeight: timeoutHeight.toFixed(),
|
|
278
|
+
chainId
|
|
279
|
+
},
|
|
280
|
+
evmChainId
|
|
281
|
+
});
|
|
282
|
+
/** Signing on Ethereum */
|
|
283
|
+
const signature = await walletStrategy.signEip712TypedData(safeBigIntStringify(eip712TypedData), tx.ethereumAddress, { txTimeout: txTimeoutTimeInSeconds });
|
|
284
|
+
const pubKeyOrSignatureDerivedPubKey = await getEthereumWalletPubKey({
|
|
285
|
+
pubKey: (_baseAccount$pubKey = baseAccount.pubKey) === null || _baseAccount$pubKey === void 0 ? void 0 : _baseAccount$pubKey.key,
|
|
286
|
+
eip712TypedData,
|
|
287
|
+
signature
|
|
288
|
+
});
|
|
289
|
+
/** Preparing the transaction for client broadcasting */
|
|
290
|
+
const { txRaw } = createTransaction({
|
|
291
|
+
message: msgs,
|
|
292
|
+
memo: tx.memo,
|
|
293
|
+
signMode: SIGN_EIP712,
|
|
294
|
+
fee: stdFee,
|
|
295
|
+
pubKey: pubKeyOrSignatureDerivedPubKey,
|
|
296
|
+
sequence: baseAccount.sequence,
|
|
297
|
+
timeoutHeight: timeoutHeight.toNumber(),
|
|
298
|
+
accountNumber: baseAccount.accountNumber,
|
|
299
|
+
chainId
|
|
300
|
+
});
|
|
301
|
+
const txRawEip712 = createTxRawEIP712(txRaw, createWeb3Extension({ evmChainId }));
|
|
302
|
+
/** Append Signatures */
|
|
303
|
+
txRawEip712.signatures = [hexToBuff(signature)];
|
|
304
|
+
const inclusionWaiter = await this.prepareTxInclusionWaiter({
|
|
305
|
+
tx,
|
|
306
|
+
txRawOrSignResponse: txRawEip712,
|
|
307
|
+
timeout: txTimeoutTimeInMilliSeconds
|
|
308
|
+
});
|
|
309
|
+
let response;
|
|
310
|
+
try {
|
|
311
|
+
response = await walletStrategy.sendTransaction(txRawEip712, {
|
|
312
|
+
chainId,
|
|
313
|
+
endpoints,
|
|
314
|
+
txTimeout: txTimeoutInBlocks,
|
|
315
|
+
txInclusion: this.resolveTxInclusionOptions(tx),
|
|
316
|
+
address: tx.injectiveAddress,
|
|
317
|
+
onBroadcast: () => {
|
|
318
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastSynced);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
} catch (e) {
|
|
322
|
+
inclusionWaiter.close();
|
|
323
|
+
throw e;
|
|
324
|
+
}
|
|
325
|
+
const confirmedTx = await this.waitForPreparedTxInclusion({
|
|
326
|
+
tx,
|
|
327
|
+
inclusionWaiter,
|
|
328
|
+
responseTxHash: response.txHash,
|
|
329
|
+
timeout: txTimeoutTimeInMilliSeconds
|
|
330
|
+
});
|
|
331
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastEnd);
|
|
332
|
+
return confirmedTx;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Prepare/sign/broadcast transaction using
|
|
336
|
+
* Ethereum native wallets on the client side.
|
|
337
|
+
*
|
|
338
|
+
* Note: Gas estimation not available
|
|
339
|
+
*
|
|
340
|
+
* @param tx The transaction that needs to be broadcasted
|
|
341
|
+
* @returns transaction hash
|
|
342
|
+
*/
|
|
343
|
+
async broadcastEip712V2(tx) {
|
|
344
|
+
var _tx$gas2, _baseAccount$pubKey2;
|
|
345
|
+
const { chainId, endpoints, walletStrategy } = this;
|
|
346
|
+
const txTimeoutInBlocks = this.resolveTimeoutInBlocks(tx.txTimeoutInBlocks);
|
|
347
|
+
const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
|
|
348
|
+
const [evmChainId, { baseAccount, latestHeight }] = await Promise.all([this.getEvmChainId(), this.fetchAccountAndBlockDetails(tx.injectiveAddress, tx.accountDetails)]);
|
|
349
|
+
if (!evmChainId) throw new GeneralException(/* @__PURE__ */ new Error("Please provide evmChainId"));
|
|
350
|
+
const timeoutHeight = toBigNumber(latestHeight).plus(txTimeoutInBlocks);
|
|
351
|
+
const txTimeoutTimeInSeconds = txTimeoutInBlocks * DEFAULT_BLOCK_TIME_IN_SECONDS;
|
|
352
|
+
const txTimeoutTimeInMilliSeconds = txTimeoutTimeInSeconds * 1e3;
|
|
353
|
+
const gas = (((_tx$gas2 = tx.gas) === null || _tx$gas2 === void 0 ? void 0 : _tx$gas2.gas) || getGasPriceBasedOnMessage(msgs)).toString();
|
|
354
|
+
let stdFee = getStdFee({
|
|
355
|
+
...tx.gas,
|
|
356
|
+
gas
|
|
357
|
+
});
|
|
358
|
+
/**
|
|
359
|
+
* Account has not been created on chain
|
|
360
|
+
* and we cannot simulate the transaction
|
|
361
|
+
* to estimate the gas
|
|
362
|
+
**/
|
|
363
|
+
if (!baseAccount.pubKey) stdFee = await this.getStdFeeWithDynamicBaseFee(stdFee);
|
|
364
|
+
else {
|
|
365
|
+
const { stdFee: simulatedStdFee } = await this.getTxWithSignersAndStdFee({
|
|
366
|
+
chainId,
|
|
367
|
+
signMode: SIGN_EIP712_V2,
|
|
368
|
+
memo: tx.memo,
|
|
369
|
+
message: msgs,
|
|
370
|
+
timeoutHeight: timeoutHeight.toNumber(),
|
|
371
|
+
signers: {
|
|
372
|
+
pubKey: baseAccount.pubKey.key,
|
|
373
|
+
sequence: baseAccount.sequence,
|
|
374
|
+
accountNumber: baseAccount.accountNumber
|
|
375
|
+
},
|
|
376
|
+
fee: stdFee
|
|
377
|
+
});
|
|
378
|
+
stdFee = simulatedStdFee;
|
|
379
|
+
}
|
|
380
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionPreparationStart);
|
|
381
|
+
/** EIP712 for signing on Ethereum wallets */
|
|
382
|
+
const eip712TypedData = getEip712TypedDataV2({
|
|
383
|
+
msgs,
|
|
384
|
+
fee: stdFee,
|
|
385
|
+
tx: {
|
|
386
|
+
memo: tx.memo,
|
|
387
|
+
accountNumber: baseAccount.accountNumber.toString(),
|
|
388
|
+
sequence: baseAccount.sequence.toString(),
|
|
389
|
+
timeoutHeight: timeoutHeight.toFixed(),
|
|
390
|
+
chainId
|
|
391
|
+
},
|
|
392
|
+
evmChainId
|
|
393
|
+
});
|
|
394
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionPreparationEnd);
|
|
395
|
+
/** Signing on Ethereum */
|
|
396
|
+
const signature = await walletStrategy.signEip712TypedData(safeBigIntStringify(eip712TypedData), tx.ethereumAddress, { txTimeout: txTimeoutTimeInSeconds });
|
|
397
|
+
const pubKeyOrSignatureDerivedPubKey = await getEthereumWalletPubKey({
|
|
398
|
+
pubKey: (_baseAccount$pubKey2 = baseAccount.pubKey) === null || _baseAccount$pubKey2 === void 0 ? void 0 : _baseAccount$pubKey2.key,
|
|
399
|
+
eip712TypedData,
|
|
400
|
+
signature
|
|
401
|
+
});
|
|
402
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastStart);
|
|
403
|
+
const { txRaw } = createTransaction({
|
|
404
|
+
message: msgs,
|
|
405
|
+
memo: tx.memo,
|
|
406
|
+
signMode: SIGN_EIP712_V2,
|
|
407
|
+
fee: stdFee,
|
|
408
|
+
pubKey: pubKeyOrSignatureDerivedPubKey,
|
|
409
|
+
sequence: baseAccount.sequence,
|
|
410
|
+
timeoutHeight: timeoutHeight.toNumber(),
|
|
411
|
+
accountNumber: baseAccount.accountNumber,
|
|
412
|
+
chainId
|
|
413
|
+
});
|
|
414
|
+
const txRawEip712 = createTxRawEIP712(txRaw, createWeb3Extension({ evmChainId }));
|
|
415
|
+
/** Append Signatures */
|
|
416
|
+
txRawEip712.signatures = [hexToBuff(signature)];
|
|
417
|
+
const inclusionWaiter = await this.prepareTxInclusionWaiter({
|
|
418
|
+
tx,
|
|
419
|
+
timeout: txTimeoutTimeInMilliSeconds,
|
|
420
|
+
txRawOrSignResponse: txRawEip712
|
|
421
|
+
});
|
|
422
|
+
let response;
|
|
423
|
+
try {
|
|
424
|
+
response = await walletStrategy.sendTransaction(txRawEip712, {
|
|
425
|
+
chainId,
|
|
426
|
+
endpoints,
|
|
427
|
+
txTimeout: txTimeoutInBlocks,
|
|
428
|
+
txInclusion: this.resolveTxInclusionOptions(tx),
|
|
429
|
+
address: tx.injectiveAddress,
|
|
430
|
+
onBroadcast: () => {
|
|
431
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastSynced);
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
} catch (e) {
|
|
435
|
+
inclusionWaiter.close();
|
|
436
|
+
throw e;
|
|
437
|
+
}
|
|
438
|
+
const confirmedTx = await this.waitForPreparedTxInclusion({
|
|
439
|
+
tx,
|
|
440
|
+
inclusionWaiter,
|
|
441
|
+
responseTxHash: response.txHash,
|
|
442
|
+
timeout: txTimeoutTimeInMilliSeconds
|
|
443
|
+
});
|
|
444
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastEnd);
|
|
445
|
+
return confirmedTx;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Prepare/sign/broadcast transaction using
|
|
449
|
+
* Ethereum native wallets using the Web3Gateway.
|
|
450
|
+
*
|
|
451
|
+
* @param tx The transaction that needs to be broadcasted
|
|
452
|
+
* @returns transaction hash
|
|
453
|
+
*/
|
|
454
|
+
async broadcastEip712WithFeeDelegation(tx) {
|
|
455
|
+
const { endpoints, simulateTx, httpHeaders, walletStrategy, txTimeoutOnFeeDelegation } = this;
|
|
456
|
+
const txTimeoutInBlocks = this.resolveTimeoutInBlocks(tx.txTimeoutInBlocks);
|
|
457
|
+
const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
|
|
458
|
+
const web3Msgs = msgs.map((msg) => msg.toWeb3());
|
|
459
|
+
const evmChainId = await this.getEvmChainId();
|
|
460
|
+
if (!evmChainId) throw new GeneralException(/* @__PURE__ */ new Error("Please provide evmChainId"));
|
|
461
|
+
const transactionApi = new IndexerGrpcWeb3GwApi(endpoints.web3gw || endpoints.indexer);
|
|
462
|
+
if (httpHeaders) transactionApi.setMetadata(httpHeaders);
|
|
463
|
+
const txTimeoutTimeInSeconds = txTimeoutInBlocks * DEFAULT_BLOCK_TIME_IN_SECONDS;
|
|
464
|
+
const txTimeoutTimeInMilliSeconds = txTimeoutTimeInSeconds * 1e3;
|
|
465
|
+
let timeoutHeight = void 0;
|
|
466
|
+
if (txTimeoutOnFeeDelegation) timeoutHeight = toBigNumber((await new ChainGrpcTendermintApi(endpoints.grpc).fetchLatestBlock()).header.height.toString()).plus(txTimeoutInBlocks).toNumber();
|
|
467
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionPreparationStart);
|
|
468
|
+
const prepareTxResponse = await transactionApi.prepareTxRequest({
|
|
469
|
+
timeoutHeight,
|
|
470
|
+
memo: tx.memo,
|
|
471
|
+
message: web3Msgs,
|
|
472
|
+
address: tx.ethereumAddress,
|
|
473
|
+
chainId: evmChainId,
|
|
474
|
+
gasLimit: getGasPriceBasedOnMessage(msgs),
|
|
475
|
+
estimateGas: simulateTx
|
|
476
|
+
});
|
|
477
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionPreparationEnd);
|
|
478
|
+
const signature = await walletStrategy.signEip712TypedData(prepareTxResponse.data, tx.ethereumAddress, { txTimeout: txTimeoutTimeInSeconds });
|
|
479
|
+
const broadcast = async () => await transactionApi.broadcastTxRequest({
|
|
480
|
+
signature,
|
|
481
|
+
message: web3Msgs,
|
|
482
|
+
txResponse: prepareTxResponse,
|
|
483
|
+
chainId: evmChainId
|
|
484
|
+
});
|
|
485
|
+
try {
|
|
486
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastStart);
|
|
487
|
+
const response = await broadcast();
|
|
488
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastSynced);
|
|
489
|
+
const confirmedTx = await this.waitForTxInclusion({
|
|
490
|
+
tx,
|
|
491
|
+
txHash: response.txHash,
|
|
492
|
+
timeout: txTimeoutTimeInMilliSeconds
|
|
493
|
+
});
|
|
494
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastEnd);
|
|
495
|
+
return confirmedTx;
|
|
496
|
+
} catch (e) {
|
|
497
|
+
const error = e;
|
|
498
|
+
if (isThrownException(error)) {
|
|
499
|
+
const exception = error;
|
|
500
|
+
/**
|
|
501
|
+
* First MsgExec transaction with a PrivateKey wallet
|
|
502
|
+
* always runs out of gas for some reason, temporary solution
|
|
503
|
+
* to just broadcast the transaction twice
|
|
504
|
+
**/
|
|
505
|
+
if (walletStrategy.wallet === Wallet.PrivateKey && checkIfTxRunOutOfGas(exception)) {
|
|
506
|
+
const { baseAccount } = await new ChainGrpcAuthApi(endpoints.grpc).fetchAccount(tx.injectiveAddress);
|
|
507
|
+
/** We only do it on the first account tx fail */
|
|
508
|
+
if (baseAccount.sequence > 1) throw e;
|
|
509
|
+
return await this.broadcastEip712WithFeeDelegation(tx);
|
|
510
|
+
}
|
|
511
|
+
return await this.retryOnException(exception, broadcast);
|
|
512
|
+
}
|
|
513
|
+
throw e;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Prepare/sign/broadcast transaction using
|
|
518
|
+
* Cosmos native wallets on the client side.
|
|
519
|
+
*
|
|
520
|
+
* @param tx The transaction that needs to be broadcasted
|
|
521
|
+
* @returns transaction hash
|
|
522
|
+
*/
|
|
523
|
+
async broadcastDirectSign(tx) {
|
|
524
|
+
var _tx$gas3;
|
|
525
|
+
const { chainId, endpoints, walletStrategy } = this;
|
|
526
|
+
const txTimeoutInBlocks = this.resolveTimeoutInBlocks(tx.txTimeoutInBlocks);
|
|
527
|
+
const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
|
|
528
|
+
/**
|
|
529
|
+
* When using Ledger with Keplr/Leap we have
|
|
530
|
+
* to send EIP712 to sign on Keplr/Leap
|
|
531
|
+
*/
|
|
532
|
+
if ([Wallet.Keplr, Wallet.Leap].includes(walletStrategy.getWallet())) {
|
|
533
|
+
if (await walletStrategy.getWalletDeviceType() === WalletDeviceType.Hardware) return this.experimentalBroadcastWalletThroughLedger(tx);
|
|
534
|
+
}
|
|
535
|
+
const [{ baseAccount, latestHeight }, pubKey] = await Promise.all([this.fetchAccountAndBlockDetails(tx.injectiveAddress, tx.accountDetails), walletStrategy.getPubKey(tx.injectiveAddress)]);
|
|
536
|
+
const timeoutHeight = toBigNumber(latestHeight).plus(txTimeoutInBlocks);
|
|
537
|
+
const txTimeoutTimeInMilliSeconds = txTimeoutInBlocks * DEFAULT_BLOCK_TIME_IN_SECONDS * 1e3;
|
|
538
|
+
const signMode = isCosmosAminoOnlyWallet(walletStrategy.wallet) ? SIGN_EIP712 : SIGN_DIRECT;
|
|
539
|
+
const gas = (((_tx$gas3 = tx.gas) === null || _tx$gas3 === void 0 ? void 0 : _tx$gas3.gas) || getGasPriceBasedOnMessage(msgs)).toString();
|
|
540
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionPreparationStart);
|
|
541
|
+
/** Prepare the Transaction * */
|
|
542
|
+
const { txRaw } = await this.getTxWithSignersAndStdFee({
|
|
543
|
+
chainId,
|
|
544
|
+
signMode,
|
|
545
|
+
memo: tx.memo,
|
|
546
|
+
message: msgs,
|
|
547
|
+
timeoutHeight: timeoutHeight.toNumber(),
|
|
548
|
+
signers: {
|
|
549
|
+
pubKey,
|
|
550
|
+
accountNumber: baseAccount.accountNumber,
|
|
551
|
+
sequence: baseAccount.sequence
|
|
552
|
+
},
|
|
553
|
+
fee: getStdFee({
|
|
554
|
+
...tx.gas,
|
|
555
|
+
gas
|
|
556
|
+
})
|
|
557
|
+
});
|
|
558
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionPreparationEnd);
|
|
559
|
+
/** Ledger using Cosmos app only allows signing amino docs */
|
|
560
|
+
if (isCosmosAminoOnlyWallet(walletStrategy.wallet)) {
|
|
561
|
+
var _tx$gas4;
|
|
562
|
+
const aminoSignDoc = getAminoStdSignDoc({
|
|
563
|
+
...tx,
|
|
564
|
+
...baseAccount,
|
|
565
|
+
msgs,
|
|
566
|
+
chainId,
|
|
567
|
+
gas: gas || ((_tx$gas4 = tx.gas) === null || _tx$gas4 === void 0 || (_tx$gas4 = _tx$gas4.gas) === null || _tx$gas4 === void 0 ? void 0 : _tx$gas4.toString()),
|
|
568
|
+
timeoutHeight: timeoutHeight.toFixed()
|
|
569
|
+
});
|
|
570
|
+
txRaw.signatures = [base64ToUint8Array((await walletStrategy.signAminoCosmosTransaction({
|
|
571
|
+
signDoc: aminoSignDoc,
|
|
572
|
+
address: tx.injectiveAddress
|
|
573
|
+
})).signature.signature)];
|
|
574
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastStart);
|
|
575
|
+
const inclusionWaiter$1 = await this.prepareTxInclusionWaiter({
|
|
576
|
+
tx,
|
|
577
|
+
txRawOrSignResponse: txRaw,
|
|
578
|
+
timeout: txTimeoutTimeInMilliSeconds
|
|
579
|
+
});
|
|
580
|
+
let response$1;
|
|
581
|
+
try {
|
|
582
|
+
response$1 = await walletStrategy.sendTransaction(txRaw, {
|
|
583
|
+
chainId,
|
|
584
|
+
endpoints,
|
|
585
|
+
address: tx.injectiveAddress,
|
|
586
|
+
txTimeout: txTimeoutInBlocks,
|
|
587
|
+
txInclusion: this.resolveTxInclusionOptions(tx),
|
|
588
|
+
onBroadcast: () => {
|
|
589
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastSynced);
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
} catch (e) {
|
|
593
|
+
inclusionWaiter$1.close();
|
|
594
|
+
throw e;
|
|
595
|
+
}
|
|
596
|
+
const confirmedTx$1 = await this.waitForPreparedTxInclusion({
|
|
597
|
+
tx,
|
|
598
|
+
inclusionWaiter: inclusionWaiter$1,
|
|
599
|
+
timeout: txTimeoutTimeInMilliSeconds,
|
|
600
|
+
responseTxHash: response$1.txHash
|
|
601
|
+
});
|
|
602
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastEnd);
|
|
603
|
+
return confirmedTx$1;
|
|
604
|
+
}
|
|
605
|
+
const directSignResponse = await walletStrategy.signCosmosTransaction({
|
|
606
|
+
txRaw,
|
|
607
|
+
chainId,
|
|
608
|
+
address: tx.injectiveAddress,
|
|
609
|
+
accountNumber: baseAccount.accountNumber
|
|
610
|
+
});
|
|
611
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastStart);
|
|
612
|
+
const inclusionWaiter = await this.prepareTxInclusionWaiter({
|
|
613
|
+
tx,
|
|
614
|
+
timeout: txTimeoutTimeInMilliSeconds,
|
|
615
|
+
txRawOrSignResponse: directSignResponse
|
|
616
|
+
});
|
|
617
|
+
let response;
|
|
618
|
+
try {
|
|
619
|
+
response = await walletStrategy.sendTransaction(directSignResponse, {
|
|
620
|
+
chainId,
|
|
621
|
+
endpoints,
|
|
622
|
+
txTimeout: txTimeoutInBlocks,
|
|
623
|
+
txInclusion: this.resolveTxInclusionOptions(tx),
|
|
624
|
+
address: tx.injectiveAddress,
|
|
625
|
+
onBroadcast: () => {
|
|
626
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastSynced);
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
} catch (e) {
|
|
630
|
+
inclusionWaiter.close();
|
|
631
|
+
throw e;
|
|
632
|
+
}
|
|
633
|
+
const confirmedTx = await this.waitForPreparedTxInclusion({
|
|
634
|
+
tx,
|
|
635
|
+
inclusionWaiter,
|
|
636
|
+
responseTxHash: response.txHash,
|
|
637
|
+
timeout: txTimeoutTimeInMilliSeconds
|
|
638
|
+
});
|
|
639
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastEnd);
|
|
640
|
+
return confirmedTx;
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* We use this method only when we want to broadcast a transaction using Ledger on Keplr/Leap for Injective
|
|
644
|
+
*
|
|
645
|
+
* Note: Gas estimation not available
|
|
646
|
+
* @param tx the transaction that needs to be broadcasted
|
|
647
|
+
*/
|
|
648
|
+
async experimentalBroadcastWalletThroughLedger(tx) {
|
|
649
|
+
var _tx$gas5, _tx$gas6;
|
|
650
|
+
const { chainId, endpoints, evmChainId, simulateTx, walletStrategy } = this;
|
|
651
|
+
const txTimeoutInBlocks = this.resolveTimeoutInBlocks(tx.txTimeoutInBlocks);
|
|
652
|
+
const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
|
|
653
|
+
/**
|
|
654
|
+
* We can only use this method
|
|
655
|
+
* when Ledger is connected through Keplr
|
|
656
|
+
*/
|
|
657
|
+
if ([Wallet.Keplr, Wallet.Leap].includes(walletStrategy.getWallet())) {
|
|
658
|
+
if (!(await walletStrategy.getWalletDeviceType() === WalletDeviceType.Hardware)) throw new GeneralException(/* @__PURE__ */ new Error(`This method can only be used when Ledger is connected through ${walletStrategy.getWallet()}`));
|
|
659
|
+
}
|
|
660
|
+
if (!evmChainId) throw new GeneralException(/* @__PURE__ */ new Error("Please provide evmChainId"));
|
|
661
|
+
const cosmosWallet = walletStrategy.getCosmosWallet(chainId);
|
|
662
|
+
const [{ baseAccount, latestHeight }, pubKey] = await Promise.all([this.fetchAccountAndBlockDetails(tx.injectiveAddress, tx.accountDetails), walletStrategy.getPubKey()]);
|
|
663
|
+
const timeoutHeight = toBigNumber(latestHeight).plus(txTimeoutInBlocks);
|
|
664
|
+
const gas = (((_tx$gas5 = tx.gas) === null || _tx$gas5 === void 0 ? void 0 : _tx$gas5.gas) || getGasPriceBasedOnMessage(msgs)).toString();
|
|
665
|
+
/** EIP712 for signing on Ethereum wallets */
|
|
666
|
+
const eip712TypedData = getEip712TypedData({
|
|
667
|
+
msgs,
|
|
668
|
+
fee: await this.getStdFeeWithDynamicBaseFee({
|
|
669
|
+
...tx.gas,
|
|
670
|
+
gas
|
|
671
|
+
}),
|
|
672
|
+
tx: {
|
|
673
|
+
chainId,
|
|
674
|
+
memo: tx.memo,
|
|
675
|
+
timeoutHeight: timeoutHeight.toFixed(),
|
|
676
|
+
sequence: baseAccount.sequence.toString(),
|
|
677
|
+
accountNumber: baseAccount.accountNumber.toString()
|
|
678
|
+
},
|
|
679
|
+
evmChainId
|
|
680
|
+
});
|
|
681
|
+
const aminoSignResponse = await cosmosWallet.signEIP712CosmosTx({
|
|
682
|
+
eip712: eip712TypedData,
|
|
683
|
+
signDoc: createEip712StdSignDoc({
|
|
684
|
+
...tx,
|
|
685
|
+
...baseAccount,
|
|
686
|
+
msgs,
|
|
687
|
+
chainId,
|
|
688
|
+
gas: gas || ((_tx$gas6 = tx.gas) === null || _tx$gas6 === void 0 || (_tx$gas6 = _tx$gas6.gas) === null || _tx$gas6 === void 0 ? void 0 : _tx$gas6.toString()),
|
|
689
|
+
timeoutHeight: timeoutHeight.toFixed()
|
|
690
|
+
})
|
|
691
|
+
});
|
|
692
|
+
/**
|
|
693
|
+
* Create TxRaw from the signed tx that we
|
|
694
|
+
* get as a response in case the user changed the fee/memo
|
|
695
|
+
* on the Keplr popup
|
|
696
|
+
*/
|
|
697
|
+
const { txRaw } = createTransaction({
|
|
698
|
+
pubKey,
|
|
699
|
+
chainId,
|
|
700
|
+
message: msgs,
|
|
701
|
+
signMode: SIGN_EIP712,
|
|
702
|
+
memo: aminoSignResponse.signed.memo,
|
|
703
|
+
fee: aminoSignResponse.signed.fee,
|
|
704
|
+
sequence: parseInt(aminoSignResponse.signed.sequence, 10),
|
|
705
|
+
accountNumber: parseInt(aminoSignResponse.signed.account_number, 10),
|
|
706
|
+
timeoutHeight: parseInt(aminoSignResponse.signed.timeout_height, 10)
|
|
707
|
+
});
|
|
708
|
+
const txRawEip712 = createTxRawEIP712(txRaw, createWeb3Extension({ evmChainId }));
|
|
709
|
+
if (simulateTx) await this.simulateTxRaw(txRawEip712);
|
|
710
|
+
txRawEip712.signatures = [base64ToUint8Array(aminoSignResponse.signature.signature)];
|
|
711
|
+
/** Broadcast the transaction */
|
|
712
|
+
const response = await new TxGrpcApi(endpoints.grpc).broadcast(txRawEip712, {
|
|
713
|
+
txTimeout: txTimeoutInBlocks,
|
|
714
|
+
...this.resolveTxInclusionOptions(tx),
|
|
715
|
+
onBroadcast: () => {
|
|
716
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastSynced);
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
if (response.code !== 0) throw new TransactionException(new Error(response.rawLog), {
|
|
720
|
+
code: UnspecifiedErrorCode,
|
|
721
|
+
contextCode: response.code,
|
|
722
|
+
contextModule: response.codespace
|
|
723
|
+
});
|
|
724
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastEnd);
|
|
725
|
+
return response;
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Prepare/sign/broadcast transaction using
|
|
729
|
+
* Cosmos native wallets using the Web3Gateway.
|
|
730
|
+
*
|
|
731
|
+
* @param tx The transaction that needs to be broadcasted
|
|
732
|
+
* @returns transaction hash
|
|
733
|
+
*/
|
|
734
|
+
async broadcastDirectSignWithFeeDelegation(tx) {
|
|
735
|
+
var _tx$gas7;
|
|
736
|
+
const { options, chainId, endpoints, simulateTx, httpHeaders, walletStrategy, txTimeoutOnFeeDelegation } = this;
|
|
737
|
+
const txTimeoutInBlocks = this.resolveTimeoutInBlocks(tx.txTimeoutInBlocks);
|
|
738
|
+
const msgs = Array.isArray(tx.msgs) ? tx.msgs : [tx.msgs];
|
|
739
|
+
/**
|
|
740
|
+
* We can only use this method when Keplr is connected
|
|
741
|
+
* with ledger
|
|
742
|
+
*/
|
|
743
|
+
if (walletStrategy.getWallet() === Wallet.Keplr) {
|
|
744
|
+
if (await walletStrategy.getWalletDeviceType() === WalletDeviceType.Hardware) throw new GeneralException(/* @__PURE__ */ new Error("Keplr + Ledger is not available with fee delegation. Connect with Ledger directly."));
|
|
745
|
+
}
|
|
746
|
+
const cosmosWallet = walletStrategy.getCosmosWallet(chainId);
|
|
747
|
+
const canDisableCosmosGasCheck = [Wallet.Keplr, Wallet.OWallet].includes(walletStrategy.wallet);
|
|
748
|
+
const feePayerPubKey = await this.fetchFeePayerPubKey(options.feePayerPubKey);
|
|
749
|
+
const feePayerPublicKey = PublicKey.fromBase64(feePayerPubKey);
|
|
750
|
+
const feePayer = feePayerPublicKey.toAddress().address;
|
|
751
|
+
const transactionApi = new IndexerGrpcWeb3GwApi(endpoints.web3gw || endpoints.indexer);
|
|
752
|
+
if (httpHeaders) transactionApi.setMetadata(httpHeaders);
|
|
753
|
+
const fetchAccountBlockDetails = async () => {
|
|
754
|
+
try {
|
|
755
|
+
const { baseAccount: baseAccount$1, latestHeight: latestHeight$1 } = await this.fetchAccountAndBlockDetails(tx.injectiveAddress, tx.accountDetails);
|
|
756
|
+
return {
|
|
757
|
+
baseAccount: baseAccount$1,
|
|
758
|
+
latestHeight: latestHeight$1
|
|
759
|
+
};
|
|
760
|
+
} catch (e) {
|
|
761
|
+
const error = e;
|
|
762
|
+
if (isThrownException(error) && error.message.toLowerCase().includes(`account ${tx.injectiveAddress} not found`)) {
|
|
763
|
+
await transactionApi.prepareCosmosTxRequest({
|
|
764
|
+
address: tx.injectiveAddress,
|
|
765
|
+
message: msgs.map((msg) => msg.toWeb3Gw()),
|
|
766
|
+
memo: tx.memo,
|
|
767
|
+
estimateGas: simulateTx
|
|
768
|
+
});
|
|
769
|
+
const { baseAccount: baseAccount$1, latestHeight: latestHeight$1 } = await this.fetchAccountAndBlockDetails(tx.injectiveAddress);
|
|
770
|
+
return {
|
|
771
|
+
baseAccount: baseAccount$1,
|
|
772
|
+
latestHeight: latestHeight$1
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
throw e;
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
/** Account Details * */
|
|
779
|
+
const { baseAccount, latestHeight } = await fetchAccountBlockDetails();
|
|
780
|
+
const chainGrpcAuthApi = new ChainGrpcAuthApi(endpoints.grpc);
|
|
781
|
+
if (httpHeaders) chainGrpcAuthApi.setMetadata(httpHeaders);
|
|
782
|
+
const { baseAccount: feePayerBaseAccount } = await chainGrpcAuthApi.fetchAccount(feePayer);
|
|
783
|
+
const timeoutHeight = toBigNumber(latestHeight).plus(txTimeoutOnFeeDelegation ? txTimeoutInBlocks : DEFAULT_BLOCK_TIMEOUT_HEIGHT);
|
|
784
|
+
const txTimeoutTimeInMilliSeconds = txTimeoutInBlocks * DEFAULT_BLOCK_TIME_IN_SECONDS * 1e3;
|
|
785
|
+
const pubKey = await walletStrategy.getPubKey();
|
|
786
|
+
const gas = (((_tx$gas7 = tx.gas) === null || _tx$gas7 === void 0 ? void 0 : _tx$gas7.gas) || getGasPriceBasedOnMessage(msgs)).toString();
|
|
787
|
+
/** Prepare the Transaction * */
|
|
788
|
+
const { txRaw } = await this.getTxWithSignersAndStdFee({
|
|
789
|
+
chainId,
|
|
790
|
+
memo: tx.memo,
|
|
791
|
+
message: msgs,
|
|
792
|
+
timeoutHeight: timeoutHeight.toNumber(),
|
|
793
|
+
signers: [{
|
|
794
|
+
pubKey,
|
|
795
|
+
accountNumber: baseAccount.accountNumber,
|
|
796
|
+
sequence: baseAccount.sequence
|
|
797
|
+
}, {
|
|
798
|
+
pubKey: feePayerPublicKey.toBase64(),
|
|
799
|
+
accountNumber: feePayerBaseAccount.accountNumber,
|
|
800
|
+
sequence: feePayerBaseAccount.sequence
|
|
801
|
+
}],
|
|
802
|
+
fee: getStdFee({
|
|
803
|
+
...tx.gas,
|
|
804
|
+
gas,
|
|
805
|
+
payer: feePayer
|
|
806
|
+
})
|
|
807
|
+
});
|
|
808
|
+
if (canDisableCosmosGasCheck && cosmosWallet.disableGasCheck) cosmosWallet.disableGasCheck(chainId);
|
|
809
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionPreparationStart);
|
|
810
|
+
const directSignResponse = await walletStrategy.signCosmosTransaction({
|
|
811
|
+
txRaw,
|
|
812
|
+
chainId,
|
|
813
|
+
address: tx.injectiveAddress,
|
|
814
|
+
accountNumber: baseAccount.accountNumber
|
|
815
|
+
});
|
|
816
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionPreparationEnd);
|
|
817
|
+
const signedTxRaw = createTxRawFromSigResponse(directSignResponse);
|
|
818
|
+
const broadcast = async () => await transactionApi.broadcastCosmosTxRequest({
|
|
819
|
+
txRaw: signedTxRaw,
|
|
820
|
+
address: tx.injectiveAddress,
|
|
821
|
+
signature: directSignResponse.signature.signature,
|
|
822
|
+
pubKey: directSignResponse.signature.pub_key || {
|
|
823
|
+
value: pubKey,
|
|
824
|
+
type: "/injective.crypto.v1beta1.ethsecp256k1.PubKey"
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
try {
|
|
828
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastStart);
|
|
829
|
+
const inclusionWaiter = await this.prepareTxInclusionWaiter({
|
|
830
|
+
tx,
|
|
831
|
+
txRawOrSignResponse: signedTxRaw,
|
|
832
|
+
timeout: txTimeoutTimeInMilliSeconds
|
|
833
|
+
});
|
|
834
|
+
let response;
|
|
835
|
+
try {
|
|
836
|
+
response = await broadcast();
|
|
837
|
+
} catch (e) {
|
|
838
|
+
inclusionWaiter.close();
|
|
839
|
+
throw e;
|
|
840
|
+
}
|
|
841
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastSynced);
|
|
842
|
+
if (canDisableCosmosGasCheck && cosmosWallet.enableGasCheck) cosmosWallet.enableGasCheck(chainId);
|
|
843
|
+
const confirmedTx = await this.waitForPreparedTxInclusion({
|
|
844
|
+
tx,
|
|
845
|
+
inclusionWaiter,
|
|
846
|
+
responseTxHash: response.txHash,
|
|
847
|
+
timeout: txTimeoutTimeInMilliSeconds
|
|
848
|
+
});
|
|
849
|
+
walletStrategy.emit(WalletStrategyEmitterEventType.TransactionBroadcastEnd);
|
|
850
|
+
return confirmedTx;
|
|
851
|
+
} catch (e) {
|
|
852
|
+
const error = e;
|
|
853
|
+
if (isThrownException(error)) {
|
|
854
|
+
const exception = error;
|
|
855
|
+
return await this.retryOnException(exception, broadcast);
|
|
856
|
+
}
|
|
857
|
+
throw e;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Fetch the fee payer's pub key from the web3 gateway
|
|
862
|
+
*
|
|
863
|
+
* Returns a base64 version of it
|
|
864
|
+
*/
|
|
865
|
+
async fetchFeePayerPubKey(existingFeePayerPubKey) {
|
|
866
|
+
if (existingFeePayerPubKey) return existingFeePayerPubKey;
|
|
867
|
+
const { endpoints, httpHeaders } = this;
|
|
868
|
+
const transactionApi = new IndexerGrpcWeb3GwApi(endpoints.web3gw || endpoints.indexer);
|
|
869
|
+
if (httpHeaders) transactionApi.setMetadata(httpHeaders);
|
|
870
|
+
const response = await transactionApi.fetchFeePayer();
|
|
871
|
+
if (!response.feePayerPubKey) throw new GeneralException(/* @__PURE__ */ new Error("Please provide a feePayerPubKey"));
|
|
872
|
+
if (response.feePayerPubKey.key.startsWith("0x") || response.feePayerPubKey.key.length === 66) return uint8ArrayToBase64(hexToUint8Array(response.feePayerPubKey.key));
|
|
873
|
+
return response.feePayerPubKey.key;
|
|
874
|
+
}
|
|
875
|
+
async getStdFeeWithDynamicBaseFee(args) {
|
|
876
|
+
const client = new ChainGrpcTxFeesApi(this.endpoints.grpc);
|
|
877
|
+
let baseFee = DEFAULT_GAS_PRICE;
|
|
878
|
+
try {
|
|
879
|
+
const response = await client.fetchEipBaseFee();
|
|
880
|
+
baseFee = Number((response === null || response === void 0 ? void 0 : response.baseFee) || DEFAULT_GAS_PRICE);
|
|
881
|
+
} catch (_unused) {}
|
|
882
|
+
if (!args) return getStdFee(baseFee ? { gasPrice: baseFee } : {});
|
|
883
|
+
if (typeof args === "string") return getStdFee({
|
|
884
|
+
...baseFee && { gasPrice: toBigNumber(baseFee).toFixed() },
|
|
885
|
+
gas: args
|
|
886
|
+
});
|
|
887
|
+
return getStdFee({
|
|
888
|
+
...args,
|
|
889
|
+
...baseFee && { gasPrice: toBigNumber(baseFee).toFixed() }
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* In case we don't want to simulate the transaction
|
|
894
|
+
* we get the gas limit based on the message type.
|
|
895
|
+
*
|
|
896
|
+
* If we want to simulate the transaction we set the
|
|
897
|
+
* gas limit based on the simulation and add a small multiplier
|
|
898
|
+
* to be safe (factor of 1.2 as default)
|
|
899
|
+
*/
|
|
900
|
+
async getTxWithSignersAndStdFee(args) {
|
|
901
|
+
var _result$gasInfo;
|
|
902
|
+
const { simulateTx } = this;
|
|
903
|
+
if (!simulateTx) return {
|
|
904
|
+
...createTransactionWithSigners(args),
|
|
905
|
+
stdFee: await this.getStdFeeWithDynamicBaseFee(args.fee)
|
|
906
|
+
};
|
|
907
|
+
const result = await this.simulateTxWithSigners(args);
|
|
908
|
+
if (!((_result$gasInfo = result.gasInfo) === null || _result$gasInfo === void 0 ? void 0 : _result$gasInfo.gasUsed)) return {
|
|
909
|
+
...createTransactionWithSigners(args),
|
|
910
|
+
stdFee: await this.getStdFeeWithDynamicBaseFee(args.fee)
|
|
911
|
+
};
|
|
912
|
+
const stdGasFee = { ...await this.getStdFeeWithDynamicBaseFee({
|
|
913
|
+
...getStdFee(args.fee),
|
|
914
|
+
gas: toBigNumber(result.gasInfo.gasUsed).times(this.gasBufferCoefficient).toFixed()
|
|
915
|
+
}) };
|
|
916
|
+
return {
|
|
917
|
+
...createTransactionWithSigners({
|
|
918
|
+
...args,
|
|
919
|
+
fee: stdGasFee
|
|
920
|
+
}),
|
|
921
|
+
stdFee: stdGasFee
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Create TxRaw and simulate it
|
|
926
|
+
*/
|
|
927
|
+
async simulateTxRaw(txRaw) {
|
|
928
|
+
const { endpoints, httpHeaders } = this;
|
|
929
|
+
txRaw.signatures = [new Uint8Array(0)];
|
|
930
|
+
const client = new TxGrpcApi(endpoints.grpc);
|
|
931
|
+
if (httpHeaders) client.setMetadata(httpHeaders);
|
|
932
|
+
return await client.simulate(txRaw);
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Create TxRaw and simulate it
|
|
936
|
+
*/
|
|
937
|
+
async simulateTxWithSigners(args) {
|
|
938
|
+
const { endpoints, httpHeaders } = this;
|
|
939
|
+
const { txRaw } = createTransactionWithSigners(args);
|
|
940
|
+
txRaw.signatures = Array(Array.isArray(args.signers) ? args.signers.length : 1).fill(new Uint8Array(0));
|
|
941
|
+
const client = new TxGrpcApi(endpoints.grpc);
|
|
942
|
+
if (httpHeaders) client.setMetadata(httpHeaders);
|
|
943
|
+
return await client.simulate(txRaw);
|
|
944
|
+
}
|
|
945
|
+
async retryOnException(exception, retryLogic) {
|
|
946
|
+
const errorsToRetry = Object.keys(this.retriesOnError);
|
|
947
|
+
const errorKey = `${exception.contextModule}-${exception.contextCode}`;
|
|
948
|
+
if (!errorsToRetry.includes(errorKey)) throw exception;
|
|
949
|
+
const retryConfig = this.retriesOnError[errorKey];
|
|
950
|
+
if (retryConfig.retries >= retryConfig.maxRetries) {
|
|
951
|
+
this.retriesOnError = defaultRetriesConfig();
|
|
952
|
+
throw exception;
|
|
953
|
+
}
|
|
954
|
+
await sleep(retryConfig.timeout);
|
|
955
|
+
try {
|
|
956
|
+
retryConfig.retries += 1;
|
|
957
|
+
return await retryLogic();
|
|
958
|
+
} catch (e) {
|
|
959
|
+
const error = e;
|
|
960
|
+
if (isThrownException(error)) return this.retryOnException(error, retryLogic);
|
|
961
|
+
throw e;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
async fetchAccountAndBlockDetails(address, existingAccountDetails) {
|
|
965
|
+
const { endpoints, httpHeaders } = this;
|
|
966
|
+
const tendermintClient = new ChainGrpcTendermintApi(endpoints.grpc);
|
|
967
|
+
if (httpHeaders) tendermintClient.setMetadata(httpHeaders);
|
|
968
|
+
if (existingAccountDetails) return {
|
|
969
|
+
baseAccount: existingAccountDetails,
|
|
970
|
+
latestHeight: (await tendermintClient.fetchLatestBlock()).header.height.toString()
|
|
971
|
+
};
|
|
972
|
+
const chainClient = new ChainGrpcAuthApi(endpoints.grpc);
|
|
973
|
+
if (httpHeaders) chainClient.setMetadata(httpHeaders);
|
|
974
|
+
const [accountDetails, latestBlock] = await Promise.all([chainClient.fetchAccount(address), tendermintClient.fetchLatestBlock()]);
|
|
975
|
+
const { baseAccount } = accountDetails;
|
|
976
|
+
return {
|
|
977
|
+
baseAccount,
|
|
978
|
+
latestHeight: latestBlock.header.height.toString()
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
resolveTimeoutInBlocks(override) {
|
|
982
|
+
return typeof override === "number" && Number.isInteger(override) && override > 0 ? override : this.txTimeout;
|
|
983
|
+
}
|
|
984
|
+
resolveTxInclusionOptions(tx) {
|
|
985
|
+
var _txInclusion$eventInc;
|
|
986
|
+
const txInclusion = (tx === null || tx === void 0 ? void 0 : tx.txInclusion) || this.txInclusion;
|
|
987
|
+
if (!txInclusion) return;
|
|
988
|
+
return {
|
|
989
|
+
...txInclusion,
|
|
990
|
+
eventInclusion: {
|
|
991
|
+
...txInclusion.eventInclusion,
|
|
992
|
+
rpcEndpoint: ((_txInclusion$eventInc = txInclusion.eventInclusion) === null || _txInclusion$eventInc === void 0 ? void 0 : _txInclusion$eventInc.rpcEndpoint) || this.endpoints.rpc
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
createTxGrpcApi() {
|
|
997
|
+
const client = new TxGrpcApi(this.endpoints.grpc);
|
|
998
|
+
if (this.httpHeaders) client.setMetadata(this.httpHeaders);
|
|
999
|
+
return client;
|
|
1000
|
+
}
|
|
1001
|
+
async waitForTxInclusion({ tx, txHash, timeout }) {
|
|
1002
|
+
return this.createTxGrpcApi().waitForTxInclusion({
|
|
1003
|
+
txHash,
|
|
1004
|
+
timeout,
|
|
1005
|
+
options: this.resolveTxInclusionOptions(tx)
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
1008
|
+
async prepareTxInclusionWaiter({ tx, timeout, txRawOrSignResponse }) {
|
|
1009
|
+
const txRaw = createTxRawFromSigResponse(txRawOrSignResponse);
|
|
1010
|
+
const txHash = TxClient.hash(txRaw);
|
|
1011
|
+
return this.createTxGrpcApi().prepareTxInclusionWait({
|
|
1012
|
+
txHash,
|
|
1013
|
+
timeout,
|
|
1014
|
+
options: this.resolveTxInclusionOptions(tx)
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
async waitForPreparedTxInclusion({ tx, timeout, responseTxHash, inclusionWaiter }) {
|
|
1018
|
+
if (!inclusionWaiter) return this.waitForTxInclusion({
|
|
1019
|
+
tx,
|
|
1020
|
+
timeout,
|
|
1021
|
+
txHash: responseTxHash
|
|
1022
|
+
});
|
|
1023
|
+
const confirmedTx = await inclusionWaiter.wait(responseTxHash);
|
|
1024
|
+
if (!confirmedTx) throw new TransactionException(/* @__PURE__ */ new Error(`The transaction with ${responseTxHash} is not found`));
|
|
1025
|
+
return confirmedTx;
|
|
1026
|
+
}
|
|
1027
|
+
};
|
|
1028
|
+
|
|
1029
|
+
//#endregion
|
|
1030
|
+
//#region src/broadcaster/Web3Broadcaster.ts
|
|
1031
|
+
/**
|
|
1032
|
+
* Preparing and broadcasting
|
|
1033
|
+
* Ethereum transactions
|
|
1034
|
+
*/
|
|
1035
|
+
var Web3Broadcaster = class {
|
|
1036
|
+
constructor({ walletStrategy, evmChainId }) {
|
|
1037
|
+
_defineProperty(this, "walletStrategy", void 0);
|
|
1038
|
+
_defineProperty(this, "evmChainId", void 0);
|
|
1039
|
+
this.evmChainId = evmChainId;
|
|
1040
|
+
this.walletStrategy = walletStrategy;
|
|
1041
|
+
}
|
|
1042
|
+
async sendTransaction(args) {
|
|
1043
|
+
const { evmChainId, walletStrategy } = this;
|
|
1044
|
+
try {
|
|
1045
|
+
const chainId = args.evmChainId || evmChainId;
|
|
1046
|
+
const txHash = await walletStrategy.sendEvmTransaction(args.tx, {
|
|
1047
|
+
evmChainId: chainId,
|
|
1048
|
+
address: args.address
|
|
1049
|
+
});
|
|
1050
|
+
await walletStrategy.getEvmTransactionReceipt(txHash, chainId);
|
|
1051
|
+
return txHash;
|
|
1052
|
+
} catch (e) {
|
|
1053
|
+
throw new Web3Exception(new Error(e.message));
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
|
|
1058
|
+
//#endregion
|
|
1059
|
+
export { MsgBroadcaster as n, checkIfTxRunOutOfGas as r, Web3Broadcaster as t };
|