@keplr-wallet/background 0.12.312 → 0.13.0
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/build/index.d.ts +1 -0
- package/build/index.js +7 -1
- package/build/index.js.map +1 -1
- package/build/keyring-cosmos/service.d.ts +10 -0
- package/build/keyring-cosmos/service.js +100 -0
- package/build/keyring-cosmos/service.js.map +1 -1
- package/build/keyring-ethereum/service.d.ts +5 -0
- package/build/keyring-ethereum/service.js +66 -0
- package/build/keyring-ethereum/service.js.map +1 -1
- package/build/recent-send-history/api.d.ts +31 -0
- package/build/recent-send-history/api.js +97 -0
- package/build/recent-send-history/api.js.map +1 -0
- package/build/recent-send-history/handler.js +36 -0
- package/build/recent-send-history/handler.js.map +1 -1
- package/build/recent-send-history/init.js +5 -0
- package/build/recent-send-history/init.js.map +1 -1
- package/build/recent-send-history/messages.d.ts +76 -1
- package/build/recent-send-history/messages.js +121 -1
- package/build/recent-send-history/messages.js.map +1 -1
- package/build/recent-send-history/service.d.ts +262 -9
- package/build/recent-send-history/service.js +2103 -812
- package/build/recent-send-history/service.js.map +1 -1
- package/build/recent-send-history/types.d.ts +214 -22
- package/build/recent-send-history/types.js +21 -0
- package/build/recent-send-history/types.js.map +1 -1
- package/build/tx/service.d.ts +2 -0
- package/build/tx/service.js +35 -0
- package/build/tx/service.js.map +1 -1
- package/build/tx-ethereum/service.d.ts +2 -0
- package/build/tx-ethereum/service.js +42 -0
- package/build/tx-ethereum/service.js.map +1 -1
- package/build/tx-executor/constants.d.ts +1 -0
- package/build/tx-executor/constants.js +5 -0
- package/build/tx-executor/constants.js.map +1 -0
- package/build/tx-executor/handler.d.ts +3 -0
- package/build/tx-executor/handler.js +45 -0
- package/build/tx-executor/handler.js.map +1 -0
- package/build/tx-executor/index.d.ts +3 -0
- package/build/tx-executor/index.js +20 -0
- package/build/tx-executor/index.js.map +1 -0
- package/build/tx-executor/init.d.ts +3 -0
- package/build/tx-executor/init.js +14 -0
- package/build/tx-executor/init.js.map +1 -0
- package/build/tx-executor/internal.d.ts +4 -0
- package/build/tx-executor/internal.js +24 -0
- package/build/tx-executor/internal.js.map +1 -0
- package/build/tx-executor/messages.d.ts +53 -0
- package/build/tx-executor/messages.js +116 -0
- package/build/tx-executor/messages.js.map +1 -0
- package/build/tx-executor/service.d.ts +67 -0
- package/build/tx-executor/service.js +715 -0
- package/build/tx-executor/service.js.map +1 -0
- package/build/tx-executor/types.d.ts +105 -0
- package/build/tx-executor/types.js +33 -0
- package/build/tx-executor/types.js.map +1 -0
- package/build/tx-executor/utils/cosmos.d.ts +59 -0
- package/build/tx-executor/utils/cosmos.js +526 -0
- package/build/tx-executor/utils/cosmos.js.map +1 -0
- package/build/tx-executor/utils/evm.d.ts +4 -0
- package/build/tx-executor/utils/evm.js +236 -0
- package/build/tx-executor/utils/evm.js.map +1 -0
- package/package.json +13 -13
- package/src/index.ts +24 -1
- package/src/keyring-cosmos/service.ts +151 -0
- package/src/keyring-ethereum/service.ts +103 -6
- package/src/recent-send-history/api.ts +119 -0
- package/src/recent-send-history/handler.ts +84 -0
- package/src/recent-send-history/init.ts +10 -0
- package/src/recent-send-history/messages.ts +163 -1
- package/src/recent-send-history/service.ts +3042 -1153
- package/src/recent-send-history/types.ts +268 -31
- package/src/tx/service.ts +41 -0
- package/src/tx-ethereum/service.ts +57 -0
- package/src/tx-executor/constants.ts +1 -0
- package/src/tx-executor/handler.ts +71 -0
- package/src/tx-executor/index.ts +3 -0
- package/src/tx-executor/init.ts +20 -0
- package/src/tx-executor/internal.ts +9 -0
- package/src/tx-executor/messages.ts +157 -0
- package/src/tx-executor/service.ts +1025 -0
- package/src/tx-executor/types.ts +161 -0
- package/src/tx-executor/utils/cosmos.ts +771 -0
- package/src/tx-executor/utils/evm.ts +310 -0
|
@@ -0,0 +1,715 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
9
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
10
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
11
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
12
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
13
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
14
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.BackgroundTxExecutorService = void 0;
|
|
19
|
+
const chains_1 = require("../chains");
|
|
20
|
+
const router_1 = require("@keplr-wallet/router");
|
|
21
|
+
const types_1 = require("./types");
|
|
22
|
+
const mobx_1 = require("mobx");
|
|
23
|
+
const types_2 = require("@keplr-wallet/types");
|
|
24
|
+
const transactions_1 = require("@ethersproject/transactions");
|
|
25
|
+
const cosmos_1 = require("@keplr-wallet/cosmos");
|
|
26
|
+
const tx_1 = require("@keplr-wallet/proto-types/cosmos/tx/v1beta1/tx");
|
|
27
|
+
const cosmos_2 = require("./utils/cosmos");
|
|
28
|
+
const evm_1 = require("./utils/evm");
|
|
29
|
+
class BackgroundTxExecutorService {
|
|
30
|
+
constructor(kvStore, chainsService, keyRingCosmosService, keyRingEthereumService, backgroundTxService, backgroundTxEthereumService, analyticsService, recentSendHistoryService, subscriber) {
|
|
31
|
+
this.kvStore = kvStore;
|
|
32
|
+
this.chainsService = chainsService;
|
|
33
|
+
this.keyRingCosmosService = keyRingCosmosService;
|
|
34
|
+
this.keyRingEthereumService = keyRingEthereumService;
|
|
35
|
+
this.backgroundTxService = backgroundTxService;
|
|
36
|
+
this.backgroundTxEthereumService = backgroundTxEthereumService;
|
|
37
|
+
this.analyticsService = analyticsService;
|
|
38
|
+
this.recentSendHistoryService = recentSendHistoryService;
|
|
39
|
+
this.subscriber = subscriber;
|
|
40
|
+
this.recentTxExecutionSeq = 0;
|
|
41
|
+
// Key: id (sequence, it should be increased by 1 for each)
|
|
42
|
+
this.recentTxExecutionMap = new Map();
|
|
43
|
+
(0, mobx_1.makeObservable)(this);
|
|
44
|
+
}
|
|
45
|
+
init() {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
const recentTxExecutionSeqSaved = yield this.kvStore.get("recentTxExecutionSeq");
|
|
48
|
+
if (recentTxExecutionSeqSaved) {
|
|
49
|
+
(0, mobx_1.runInAction)(() => {
|
|
50
|
+
this.recentTxExecutionSeq = recentTxExecutionSeqSaved;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
(0, mobx_1.autorun)(() => {
|
|
54
|
+
const js = (0, mobx_1.toJS)(this.recentTxExecutionSeq);
|
|
55
|
+
this.kvStore.set("recentTxExecutionSeq", js);
|
|
56
|
+
});
|
|
57
|
+
const recentTxExecutionMapSaved = yield this.kvStore.get("recentSerializedTxExecutionMap");
|
|
58
|
+
if (recentTxExecutionMapSaved) {
|
|
59
|
+
(0, mobx_1.runInAction)(() => {
|
|
60
|
+
const entries = Object.entries(recentTxExecutionMapSaved);
|
|
61
|
+
const sorted = entries
|
|
62
|
+
.map(([key, value]) => [key, JSON.parse(value)])
|
|
63
|
+
.sort(([, a], [, b]) => parseInt(a.id) - parseInt(b.id));
|
|
64
|
+
for (const [key, execution] of sorted) {
|
|
65
|
+
this.recentTxExecutionMap.set(key, execution);
|
|
66
|
+
}
|
|
67
|
+
this.cleanupOldExecutions();
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
(0, mobx_1.autorun)(() => {
|
|
71
|
+
const js = (0, mobx_1.toJS)(this.recentTxExecutionMap);
|
|
72
|
+
const serialized = {};
|
|
73
|
+
for (const [key, value] of js) {
|
|
74
|
+
// only persist executions that are BLOCKED
|
|
75
|
+
if (value.status === types_1.TxExecutionStatus.BLOCKED) {
|
|
76
|
+
serialized[key] = JSON.stringify(value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
this.kvStore
|
|
80
|
+
.set("recentSerializedTxExecutionMap", serialized)
|
|
81
|
+
.catch((e) => {
|
|
82
|
+
console.error("[TxExecutor] kvStore save failed:", e);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
this.subscriber.subscribe((event) => this.handleTxExecutionEvent(event));
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
handleTxExecutionEvent(event) {
|
|
89
|
+
if (event.type === "remove") {
|
|
90
|
+
this.removeTxExecution(event.executionId);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const { executionId, executableChainIds } = event;
|
|
94
|
+
const execution = this.getTxExecution(executionId);
|
|
95
|
+
if (!execution) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const newExecutableChainIds = executableChainIds.filter((chainId) => !execution.executableChainIds.includes(chainId));
|
|
99
|
+
if (newExecutableChainIds.length === 0) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// update the executable chain ids
|
|
103
|
+
execution.executableChainIds = Array.from(new Set([...execution.executableChainIds, ...newExecutableChainIds]));
|
|
104
|
+
// if there is a pending tx that is executable, force display the swap v2 history
|
|
105
|
+
if (execution.type === types_1.TxExecutionType.SWAP_V2 &&
|
|
106
|
+
execution.historyId != null) {
|
|
107
|
+
const hasExecutableTx = execution.txs.some((tx) => (tx.status === types_1.BackgroundTxStatus.PENDING ||
|
|
108
|
+
tx.status === types_1.BackgroundTxStatus.BLOCKED) &&
|
|
109
|
+
execution.executableChainIds.includes(tx.chainId));
|
|
110
|
+
if (hasExecutableTx) {
|
|
111
|
+
this.recentSendHistoryService.showSwapV2History(execution.historyId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
recordAndExecuteTxs(env, vaultId, type, txs, executableChainIds, historyData, historyTxIndex) {
|
|
116
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
117
|
+
if (!env.isInternalMsg) {
|
|
118
|
+
throw new router_1.KeplrError("direct-tx-executor", 101, "Not internal message");
|
|
119
|
+
}
|
|
120
|
+
const keyInfo = this.keyRingCosmosService.keyRingService.getKeyInfo(vaultId);
|
|
121
|
+
if (!keyInfo) {
|
|
122
|
+
throw new router_1.KeplrError("direct-tx-executor", 120, "Key info not found");
|
|
123
|
+
}
|
|
124
|
+
// If any of the transactions are not executable or the key is hardware wallet,
|
|
125
|
+
// auto sign is disabled.
|
|
126
|
+
const preventAutoSign = txs.some((tx) => !executableChainIds.includes(tx.chainId)) ||
|
|
127
|
+
keyInfo.type === "ledger" ||
|
|
128
|
+
keyInfo.type === "keystone";
|
|
129
|
+
/**
|
|
130
|
+
* If preventAutoSign is true, at least one executable transaction must already be signed.
|
|
131
|
+
* For example, in an EVM bundle (like ERC20 approve + swap) where simulation is not possible,
|
|
132
|
+
* the UI might execute 'approve' (tx[0]) first and set its txHash, then sign the swap (tx[1]).
|
|
133
|
+
* Both tx[0] and tx[1] are executable, but tx[0] has already been executed and doesn't need to be signed again.
|
|
134
|
+
* So, ensure that at least one executable tx is already signed before proceeding.
|
|
135
|
+
*/
|
|
136
|
+
if (preventAutoSign) {
|
|
137
|
+
const executableTxs = txs.filter((tx) => executableChainIds.includes(tx.chainId));
|
|
138
|
+
if (executableTxs.length === 0) {
|
|
139
|
+
throw new router_1.KeplrError("direct-tx-executor", 122, "No executable txs");
|
|
140
|
+
}
|
|
141
|
+
if (executableTxs.every((tx) => tx.signedTx == null)) {
|
|
142
|
+
throw new router_1.KeplrError("direct-tx-executor", 123, "No signed txs found with preventAutoSign");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const id = (0, mobx_1.runInAction)(() => {
|
|
146
|
+
return (this.recentTxExecutionSeq++).toString();
|
|
147
|
+
});
|
|
148
|
+
const execution = Object.assign({ id, status: types_1.TxExecutionStatus.PENDING, vaultId: vaultId, txs, txIndex: -1, executableChainIds: executableChainIds, timestamp: Date.now(), type,
|
|
149
|
+
preventAutoSign,
|
|
150
|
+
historyTxIndex }, (type !== types_1.TxExecutionType.UNDEFINED ? { historyData } : {}));
|
|
151
|
+
(0, mobx_1.runInAction)(() => {
|
|
152
|
+
this.recentTxExecutionMap.set(id, execution);
|
|
153
|
+
});
|
|
154
|
+
return yield this.executeTxs(id);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Execute blocked transactions by execution id and transaction index
|
|
159
|
+
*/
|
|
160
|
+
resumeTx(env, id, txIndex, signedTx, ibcSwapData) {
|
|
161
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
162
|
+
if (!env.isInternalMsg) {
|
|
163
|
+
throw new router_1.KeplrError("direct-tx-executor", 101, "Not internal message");
|
|
164
|
+
}
|
|
165
|
+
return yield this.executeTxs(id, {
|
|
166
|
+
txIndex,
|
|
167
|
+
signedTx,
|
|
168
|
+
ibcSwapData,
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
executeTxs(id, options) {
|
|
173
|
+
var _a, _b, _c;
|
|
174
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
175
|
+
const execution = this.getTxExecution(id);
|
|
176
|
+
if (!execution) {
|
|
177
|
+
throw new router_1.KeplrError("direct-tx-executor", 121, "Execution not found");
|
|
178
|
+
}
|
|
179
|
+
if (execution.status === types_1.TxExecutionStatus.PROCESSING) {
|
|
180
|
+
throw new router_1.KeplrError("direct-tx-executor", 130, "Execution is already processing");
|
|
181
|
+
}
|
|
182
|
+
// Only pending or blocked executions can be executed
|
|
183
|
+
const needExecute = execution.status === types_1.TxExecutionStatus.PENDING ||
|
|
184
|
+
execution.status === types_1.TxExecutionStatus.BLOCKED;
|
|
185
|
+
if (!needExecute) {
|
|
186
|
+
return {
|
|
187
|
+
status: execution.status,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const keyInfo = this.keyRingCosmosService.keyRingService.getKeyInfo(execution.vaultId);
|
|
191
|
+
if (!keyInfo) {
|
|
192
|
+
throw new router_1.KeplrError("direct-tx-executor", 120, "Key info not found");
|
|
193
|
+
}
|
|
194
|
+
const executionStartIndex = Math.min((_a = options === null || options === void 0 ? void 0 : options.txIndex) !== null && _a !== void 0 ? _a : (execution.txIndex < 0 ? 0 : execution.txIndex), execution.txs.length - 1);
|
|
195
|
+
(0, mobx_1.runInAction)(() => {
|
|
196
|
+
execution.status = types_1.TxExecutionStatus.PROCESSING;
|
|
197
|
+
});
|
|
198
|
+
for (let i = executionStartIndex; i < execution.txs.length; i++) {
|
|
199
|
+
const currentTx = execution.txs[i];
|
|
200
|
+
const providedSignedTx = (options === null || options === void 0 ? void 0 : options.txIndex) != null && i === options.txIndex
|
|
201
|
+
? options.signedTx
|
|
202
|
+
: undefined;
|
|
203
|
+
const result = yield this.executePendingTx(execution.vaultId, currentTx, execution.executableChainIds, (_b = execution.preventAutoSign) !== null && _b !== void 0 ? _b : false, providedSignedTx);
|
|
204
|
+
// update the tx status and related fields
|
|
205
|
+
(0, mobx_1.runInAction)(() => {
|
|
206
|
+
execution.txIndex = i;
|
|
207
|
+
currentTx.status = result.status;
|
|
208
|
+
if (result.txHash != null) {
|
|
209
|
+
currentTx.txHash = result.txHash;
|
|
210
|
+
}
|
|
211
|
+
if (result.error != null) {
|
|
212
|
+
currentTx.error = result.error;
|
|
213
|
+
}
|
|
214
|
+
currentTx.signedTx = undefined;
|
|
215
|
+
});
|
|
216
|
+
switch (result.status) {
|
|
217
|
+
case types_1.BackgroundTxStatus.CONFIRMED: {
|
|
218
|
+
if (providedSignedTx) {
|
|
219
|
+
// 외부에서 제공된 signed tx로 실행한 경우 (= multi tx 재개 케이스)
|
|
220
|
+
//
|
|
221
|
+
// 이번에 처리된 트랜잭션이 multi tx swap의 마지막 트랜잭션이라고 optimistically 가정하고,
|
|
222
|
+
// 추가적인 히스토리 데이터를 기록해야 한다.
|
|
223
|
+
//
|
|
224
|
+
// [배경]
|
|
225
|
+
// Skip에서 기본적으로 smart relay 기능을 활성화해 놓았으므로,
|
|
226
|
+
// multi tx swap이 필요한 경우는 다음과 같다:
|
|
227
|
+
// - A 체인에서 브릿지, 메시징 프로토콜, 또는 IBC Eureka를 통해 B 체인으로 자산을 전송
|
|
228
|
+
// - B 체인에서 사용자 주소로 릴리즈되는 자산이 wrapped asset이거나 IBC swap이 필요한 asset
|
|
229
|
+
//
|
|
230
|
+
// [마지막 트랜잭션의 유형]
|
|
231
|
+
// 따라서 multi tx swap의 마지막 트랜잭션은 아래 두 가지 중 하나라고 가정할 수 있다:
|
|
232
|
+
// 1. Wrapped asset → Native asset 변환 트랜잭션 (EVM)
|
|
233
|
+
// 2. IBC swap이 필요한 asset의 IBC swap 트랜잭션 (Cosmos)
|
|
234
|
+
//
|
|
235
|
+
// [트랜잭션 타입별 처리]
|
|
236
|
+
// 1. EVM: txHash를 additionalTrackingData에 저장 → debug_traceTransaction으로 추적
|
|
237
|
+
// 2. Cosmos: 외부에서 IBC swap data를 받아 additionalTrackingData에 저장 → IBC swap tracking
|
|
238
|
+
if (execution.type === types_1.TxExecutionType.SWAP_V2 &&
|
|
239
|
+
execution.historyId != null) {
|
|
240
|
+
const currentTx = execution.txs[i];
|
|
241
|
+
switch (currentTx.type) {
|
|
242
|
+
case types_1.BackgroundTxType.EVM: {
|
|
243
|
+
if (result.txHash != null) {
|
|
244
|
+
this.recentSendHistoryService.setSwapV2AdditionalTrackingData(execution.historyId, {
|
|
245
|
+
type: "evm",
|
|
246
|
+
chainId: currentTx.chainId,
|
|
247
|
+
txHash: result.txHash,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
case types_1.BackgroundTxType.COSMOS: {
|
|
253
|
+
const ibcSwapData = options === null || options === void 0 ? void 0 : options.ibcSwapData;
|
|
254
|
+
if (ibcSwapData != null && result.txHash != null) {
|
|
255
|
+
this.recentSendHistoryService.setSwapV2AdditionalTrackingData(execution.historyId, { type: "cosmos-ibc", ibcSwapData, txHash: result.txHash });
|
|
256
|
+
}
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
default: {
|
|
260
|
+
// noop
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
case types_1.BackgroundTxStatus.FAILED: {
|
|
269
|
+
this.recordSwapV2HistoryErrorIfNeeded(execution, (_c = result.error) !== null && _c !== void 0 ? _c : `${i + 1}th transaction failed`);
|
|
270
|
+
this.removeTxExecution(id);
|
|
271
|
+
return {
|
|
272
|
+
status: types_1.TxExecutionStatus.FAILED,
|
|
273
|
+
error: result.error,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
case types_1.BackgroundTxStatus.BLOCKED: {
|
|
277
|
+
/**
|
|
278
|
+
* If the tx is BLOCKED, it means multiple transactions are required
|
|
279
|
+
* to be executed on different chains.
|
|
280
|
+
*
|
|
281
|
+
* - The execution should be stopped here,
|
|
282
|
+
* - Record the history if needed,
|
|
283
|
+
* - The execution should be resumed later when the condition is met.
|
|
284
|
+
*/
|
|
285
|
+
(0, mobx_1.runInAction)(() => {
|
|
286
|
+
execution.status = types_1.TxExecutionStatus.BLOCKED;
|
|
287
|
+
this.recordHistoryIfNeeded(execution);
|
|
288
|
+
// no need to keep the history data anymore
|
|
289
|
+
delete execution.historyData;
|
|
290
|
+
});
|
|
291
|
+
return {
|
|
292
|
+
status: types_1.TxExecutionStatus.BLOCKED,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
default: {
|
|
296
|
+
throw new router_1.KeplrError("direct-tx-executor", 131, "Unexpected tx status: " + result.status);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
this.recordHistoryIfNeeded(execution);
|
|
301
|
+
this.clearSwapV2HistoryBackgroundExecutionIdIfNeeded(execution);
|
|
302
|
+
this.removeTxExecution(id);
|
|
303
|
+
return {
|
|
304
|
+
status: types_1.TxExecutionStatus.COMPLETED,
|
|
305
|
+
};
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Execute a pending transaction without modifying observable state.
|
|
310
|
+
* Returns the result which should be applied by the caller using runInAction.
|
|
311
|
+
* This reduces autorun trigger count by batching state updates.
|
|
312
|
+
*/
|
|
313
|
+
executePendingTx(vaultId, tx, executableChainIds, preventAutoSign, providedSignedTx) {
|
|
314
|
+
var _a, _b, _c, _d;
|
|
315
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
316
|
+
const status = tx.status;
|
|
317
|
+
let signedTx = (_a = tx.signedTx) !== null && _a !== void 0 ? _a : providedSignedTx;
|
|
318
|
+
let txHash = tx.txHash;
|
|
319
|
+
let error;
|
|
320
|
+
// Already in final state
|
|
321
|
+
if (status === types_1.BackgroundTxStatus.CONFIRMED ||
|
|
322
|
+
status === types_1.BackgroundTxStatus.FAILED) {
|
|
323
|
+
return { status, txHash, error };
|
|
324
|
+
}
|
|
325
|
+
// Check if blocked
|
|
326
|
+
const isBlocked = !executableChainIds.includes(tx.chainId);
|
|
327
|
+
if (isBlocked) {
|
|
328
|
+
return { status: types_1.BackgroundTxStatus.BLOCKED, txHash, error };
|
|
329
|
+
}
|
|
330
|
+
// If preventAutoSign and not signed, block
|
|
331
|
+
if (preventAutoSign && signedTx == null) {
|
|
332
|
+
return { status: types_1.BackgroundTxStatus.BLOCKED, txHash, error };
|
|
333
|
+
}
|
|
334
|
+
// if not signed, sign the tx
|
|
335
|
+
if (signedTx == null) {
|
|
336
|
+
try {
|
|
337
|
+
const signResult = yield this.signTx(vaultId, tx);
|
|
338
|
+
signedTx = signResult;
|
|
339
|
+
}
|
|
340
|
+
catch (e) {
|
|
341
|
+
console.error(`[TxExecutor] tx signing failed:`, e);
|
|
342
|
+
return {
|
|
343
|
+
status: types_1.BackgroundTxStatus.FAILED,
|
|
344
|
+
txHash,
|
|
345
|
+
error: (_b = e.message) !== null && _b !== void 0 ? _b : "Transaction signing failed",
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// if tx hash is not set, broadcast the tx
|
|
350
|
+
if (txHash == null) {
|
|
351
|
+
try {
|
|
352
|
+
const txWithSignedTx = Object.assign(Object.assign({}, tx), { signedTx });
|
|
353
|
+
const broadcastResult = yield this.broadcastTx(txWithSignedTx);
|
|
354
|
+
txHash = broadcastResult;
|
|
355
|
+
}
|
|
356
|
+
catch (e) {
|
|
357
|
+
console.error(`[TxExecutor] tx broadcast failed:`, e);
|
|
358
|
+
return {
|
|
359
|
+
status: types_1.BackgroundTxStatus.FAILED,
|
|
360
|
+
txHash,
|
|
361
|
+
error: (_c = e.message) !== null && _c !== void 0 ? _c : "Transaction broadcasting failed",
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// trace the tx
|
|
366
|
+
try {
|
|
367
|
+
const txWithHash = Object.assign(Object.assign({}, tx), { txHash });
|
|
368
|
+
const confirmed = yield this.traceTx(txWithHash);
|
|
369
|
+
if (confirmed) {
|
|
370
|
+
return { status: types_1.BackgroundTxStatus.CONFIRMED, txHash };
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
status: types_1.BackgroundTxStatus.FAILED,
|
|
374
|
+
txHash,
|
|
375
|
+
error: "Transaction confirmation failed",
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
catch (e) {
|
|
379
|
+
console.error(`[TxExecutor] tx trace failed:`, e);
|
|
380
|
+
return {
|
|
381
|
+
status: types_1.BackgroundTxStatus.FAILED,
|
|
382
|
+
txHash,
|
|
383
|
+
error: (_d = e.message) !== null && _d !== void 0 ? _d : "Transaction confirmation failed",
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
signTx(vaultId, tx) {
|
|
389
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
390
|
+
switch (tx.type) {
|
|
391
|
+
case types_1.BackgroundTxType.EVM: {
|
|
392
|
+
return this.signEvmTx(vaultId, tx);
|
|
393
|
+
}
|
|
394
|
+
case types_1.BackgroundTxType.COSMOS: {
|
|
395
|
+
return this.signCosmosTx(vaultId, tx);
|
|
396
|
+
}
|
|
397
|
+
default: {
|
|
398
|
+
throw new router_1.KeplrError("direct-tx-executor", 143, "Unknown tx type");
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
signEvmTx(vaultId, tx) {
|
|
404
|
+
var _a;
|
|
405
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
406
|
+
const keyInfo = yield this.keyRingCosmosService.getKey(vaultId, tx.chainId);
|
|
407
|
+
const isHardware = keyInfo.isNanoLedger || keyInfo.isKeystone;
|
|
408
|
+
const signer = keyInfo.ethereumHexAddress;
|
|
409
|
+
// For hardware wallets, the signedTx must be provided externally when calling resumeTx or recordAndExecuteTxs.
|
|
410
|
+
if (isHardware) {
|
|
411
|
+
throw new router_1.KeplrError("direct-tx-executor", 140, "Hardware wallet signing should be triggered from user interaction");
|
|
412
|
+
}
|
|
413
|
+
const origin = typeof browser !== "undefined"
|
|
414
|
+
? new URL(browser.runtime.getURL("/")).origin
|
|
415
|
+
: "extension";
|
|
416
|
+
const chainInfo = this.chainsService.getChainInfoOrThrow(tx.chainId);
|
|
417
|
+
const evmInfo = chains_1.ChainsService.getEVMInfo(chainInfo);
|
|
418
|
+
if (!evmInfo) {
|
|
419
|
+
throw new router_1.KeplrError("direct-tx-executor", 142, "Not EVM chain");
|
|
420
|
+
}
|
|
421
|
+
const unsignedTx = yield (0, evm_1.fillUnsignedEVMTx)(origin, evmInfo, signer, tx.txData, (_a = tx.feeType) !== null && _a !== void 0 ? _a : "average");
|
|
422
|
+
const result = yield this.keyRingEthereumService.signEthereumPreAuthorized(vaultId, tx.chainId, signer, Buffer.from(JSON.stringify(unsignedTx)), types_2.EthSignType.TRANSACTION);
|
|
423
|
+
const signedTxData = JSON.parse(Buffer.from(result.signingData).toString());
|
|
424
|
+
const isEIP1559 = !!signedTxData.maxFeePerGas || !!signedTxData.maxPriorityFeePerGas;
|
|
425
|
+
if (isEIP1559) {
|
|
426
|
+
signedTxData.type = transactions_1.TransactionTypes.eip1559;
|
|
427
|
+
}
|
|
428
|
+
delete signedTxData.from;
|
|
429
|
+
return (0, transactions_1.serialize)(signedTxData, result.signature);
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
signCosmosTx(vaultId, tx) {
|
|
433
|
+
var _a, _b, _c, _d, _e;
|
|
434
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
435
|
+
const keyInfo = yield this.keyRingCosmosService.getKey(vaultId, tx.chainId);
|
|
436
|
+
const isHardware = keyInfo.isNanoLedger || keyInfo.isKeystone;
|
|
437
|
+
const signer = keyInfo.bech32Address;
|
|
438
|
+
// For hardware wallets, the signedTx must be provided externally when calling resumeTx or recordAndExecuteTxs.
|
|
439
|
+
if (isHardware) {
|
|
440
|
+
throw new router_1.KeplrError("direct-tx-executor", 140, "Hardware wallet signing should be triggered from user interaction");
|
|
441
|
+
}
|
|
442
|
+
const origin = typeof browser !== "undefined"
|
|
443
|
+
? new URL(browser.runtime.getURL("/")).origin
|
|
444
|
+
: "extension";
|
|
445
|
+
const chainInfo = this.chainsService.getChainInfoOrThrow(tx.chainId);
|
|
446
|
+
const aminoMsgs = (_a = tx.txData.aminoMsgs) !== null && _a !== void 0 ? _a : [];
|
|
447
|
+
const protoMsgs = tx.txData.protoMsgs;
|
|
448
|
+
const pseudoFee = {
|
|
449
|
+
amount: [
|
|
450
|
+
{
|
|
451
|
+
denom: chainInfo.currencies[0].coinMinimalDenom,
|
|
452
|
+
amount: "1",
|
|
453
|
+
},
|
|
454
|
+
],
|
|
455
|
+
gas: "100000",
|
|
456
|
+
};
|
|
457
|
+
const memo = (_b = tx.txData.memo) !== null && _b !== void 0 ? _b : "";
|
|
458
|
+
const isDirectSign = aminoMsgs.length === 0;
|
|
459
|
+
if (protoMsgs.length === 0) {
|
|
460
|
+
throw new Error("There is no msg to send");
|
|
461
|
+
}
|
|
462
|
+
if (!isDirectSign && aminoMsgs.length !== protoMsgs.length) {
|
|
463
|
+
throw new Error("The length of aminoMsgs and protoMsgs are different");
|
|
464
|
+
}
|
|
465
|
+
const account = yield cosmos_1.BaseAccount.fetchFromRest(chainInfo.rest, signer, true);
|
|
466
|
+
let fee = tx.txData.fee; // use provided fee if exists
|
|
467
|
+
if (fee == null) {
|
|
468
|
+
const { gasUsed } = yield (0, cosmos_2.simulateCosmosTx)(signer, chainInfo, protoMsgs, pseudoFee, memo);
|
|
469
|
+
const feeCurrency = (_c = chainInfo.feeCurrencies.find((currency) => currency.coinMinimalDenom === tx.feeCurrencyDenom)) !== null && _c !== void 0 ? _c : chainInfo.currencies[0];
|
|
470
|
+
const { gasPrice } = yield (0, cosmos_2.getCosmosGasPrice)(chainInfo, (_d = tx.feeType) !== null && _d !== void 0 ? _d : "average", feeCurrency);
|
|
471
|
+
fee = (0, cosmos_2.calculateCosmosStdFee)(feeCurrency, gasUsed, gasPrice, chainInfo.features);
|
|
472
|
+
}
|
|
473
|
+
if (isDirectSign) {
|
|
474
|
+
const { signDoc, bodyBytes, authInfoBytes } = (0, cosmos_2.prepareSignDocForDirectSigning)({
|
|
475
|
+
chainInfo,
|
|
476
|
+
accountNumber: account.getAccountNumber().toString(),
|
|
477
|
+
sequence: account.getSequence().toString(),
|
|
478
|
+
protoMsgs,
|
|
479
|
+
fee,
|
|
480
|
+
memo,
|
|
481
|
+
pubKey: keyInfo.pubKey,
|
|
482
|
+
});
|
|
483
|
+
const { signature } = yield this.keyRingCosmosService.signDirectPreAuthorized(origin, vaultId, tx.chainId, signer, signDoc);
|
|
484
|
+
const signedTx = tx_1.TxRaw.encode({
|
|
485
|
+
bodyBytes,
|
|
486
|
+
authInfoBytes,
|
|
487
|
+
signatures: [Buffer.from(signature.signature, "base64")],
|
|
488
|
+
}).finish();
|
|
489
|
+
return Buffer.from(signedTx).toString("base64");
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
const signDoc = (0, cosmos_2.prepareSignDocForAminoSigning)({
|
|
493
|
+
chainInfo,
|
|
494
|
+
accountNumber: account.getAccountNumber().toString(),
|
|
495
|
+
sequence: account.getSequence().toString(),
|
|
496
|
+
aminoMsgs: (_e = tx.txData.aminoMsgs) !== null && _e !== void 0 ? _e : [],
|
|
497
|
+
fee,
|
|
498
|
+
memo,
|
|
499
|
+
eip712Signing: false,
|
|
500
|
+
signer,
|
|
501
|
+
});
|
|
502
|
+
const signResponse = yield this.keyRingCosmosService.signAminoPreAuthorized(origin, vaultId, tx.chainId, signer, signDoc);
|
|
503
|
+
const signedTx = (0, cosmos_2.buildSignedTxFromAminoSignResponse)({
|
|
504
|
+
protoMsgs,
|
|
505
|
+
signResponse,
|
|
506
|
+
chainInfo,
|
|
507
|
+
eip712Signing: false,
|
|
508
|
+
});
|
|
509
|
+
return Buffer.from(signedTx.tx).toString("base64");
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
broadcastTx(tx) {
|
|
514
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
515
|
+
switch (tx.type) {
|
|
516
|
+
case types_1.BackgroundTxType.EVM: {
|
|
517
|
+
return this.broadcastEvmTx(tx);
|
|
518
|
+
}
|
|
519
|
+
case types_1.BackgroundTxType.COSMOS: {
|
|
520
|
+
return this.broadcastCosmosTx(tx);
|
|
521
|
+
}
|
|
522
|
+
default: {
|
|
523
|
+
throw new router_1.KeplrError("direct-tx-executor", 143, "Unknown tx type");
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
broadcastEvmTx(tx) {
|
|
529
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
530
|
+
// assume the signed tx is valid if exists
|
|
531
|
+
if (!tx.signedTx) {
|
|
532
|
+
throw new router_1.KeplrError("direct-tx-executor", 132, "Signed tx not found");
|
|
533
|
+
}
|
|
534
|
+
const origin = typeof browser !== "undefined"
|
|
535
|
+
? new URL(browser.runtime.getURL("/")).origin
|
|
536
|
+
: "extension";
|
|
537
|
+
const signedTxBytes = Buffer.from(tx.signedTx.replace("0x", ""), "hex");
|
|
538
|
+
const txHash = yield this.backgroundTxEthereumService.sendEthereumTx(origin, tx.chainId, signedTxBytes, {
|
|
539
|
+
silent: true,
|
|
540
|
+
skipTracingTxResult: true,
|
|
541
|
+
});
|
|
542
|
+
return txHash;
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
broadcastCosmosTx(tx) {
|
|
546
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
547
|
+
if (!tx.signedTx) {
|
|
548
|
+
throw new router_1.KeplrError("direct-tx-executor", 132, "Signed tx not found");
|
|
549
|
+
}
|
|
550
|
+
const signedTxBytes = Buffer.from(tx.signedTx, "base64");
|
|
551
|
+
// broadcast the tx
|
|
552
|
+
const txHash = yield this.backgroundTxService.sendTx(tx.chainId, signedTxBytes, "sync", {
|
|
553
|
+
silent: true,
|
|
554
|
+
skipTracingTxResult: true,
|
|
555
|
+
});
|
|
556
|
+
return Buffer.from(txHash).toString("hex");
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
traceTx(tx) {
|
|
560
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
561
|
+
switch (tx.type) {
|
|
562
|
+
case types_1.BackgroundTxType.EVM: {
|
|
563
|
+
return this.traceEvmTx(tx);
|
|
564
|
+
}
|
|
565
|
+
case types_1.BackgroundTxType.COSMOS: {
|
|
566
|
+
return this.traceCosmosTx(tx);
|
|
567
|
+
}
|
|
568
|
+
default: {
|
|
569
|
+
throw new router_1.KeplrError("direct-tx-executor", 143, "Unknown tx type");
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
traceEvmTx(tx) {
|
|
575
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
576
|
+
if (!tx.txHash) {
|
|
577
|
+
throw new router_1.KeplrError("direct-tx-executor", 133, "Tx hash not found");
|
|
578
|
+
}
|
|
579
|
+
const origin = typeof browser !== "undefined"
|
|
580
|
+
? new URL(browser.runtime.getURL("/")).origin
|
|
581
|
+
: "extension";
|
|
582
|
+
const txReceipt = yield this.backgroundTxEthereumService.getEthereumTxReceipt(origin, tx.chainId, tx.txHash);
|
|
583
|
+
if (!txReceipt) {
|
|
584
|
+
return false;
|
|
585
|
+
}
|
|
586
|
+
return txReceipt.status === types_2.EthTxStatus.Success;
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
traceCosmosTx(tx) {
|
|
590
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
591
|
+
if (!tx.txHash) {
|
|
592
|
+
throw new router_1.KeplrError("direct-tx-executor", 133, "Tx hash not found");
|
|
593
|
+
}
|
|
594
|
+
const txResult = yield this.backgroundTxService.traceTx(tx.chainId, tx.txHash);
|
|
595
|
+
if (!txResult) {
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
// Tendermint/CometBFT omits the code field when tx is successful (code=0)
|
|
599
|
+
// If code is present and non-zero, it's a failure
|
|
600
|
+
if (txResult.code != null && txResult.code !== 0) {
|
|
601
|
+
return false;
|
|
602
|
+
}
|
|
603
|
+
return true;
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Find the index of the most recent confirmed transaction with executable chain ids.
|
|
608
|
+
* Returns -1 if not found.
|
|
609
|
+
*/
|
|
610
|
+
findHistoryTxIndex(execution) {
|
|
611
|
+
if (execution.historyTxIndex != null) {
|
|
612
|
+
return execution.historyTxIndex;
|
|
613
|
+
}
|
|
614
|
+
for (let i = execution.txs.length - 1; i >= 0; i--) {
|
|
615
|
+
const tx = execution.txs[i];
|
|
616
|
+
if (execution.executableChainIds.includes(tx.chainId) &&
|
|
617
|
+
tx.status === types_1.BackgroundTxStatus.CONFIRMED) {
|
|
618
|
+
return i;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
return -1;
|
|
622
|
+
}
|
|
623
|
+
recordHistoryIfNeeded(execution) {
|
|
624
|
+
switch (execution.type) {
|
|
625
|
+
case types_1.TxExecutionType.SWAP_V2: {
|
|
626
|
+
if (execution.historyId != null || execution.historyData == null) {
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
const historyTxIndex = this.findHistoryTxIndex(execution);
|
|
630
|
+
if (historyTxIndex < 0) {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
const tx = execution.txs[historyTxIndex];
|
|
634
|
+
if (!tx || tx.txHash == null) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
const historyData = execution.historyData;
|
|
638
|
+
const backgroundExecutionId = execution.txs.some((tx) => tx.status === types_1.BackgroundTxStatus.BLOCKED)
|
|
639
|
+
? execution.id
|
|
640
|
+
: undefined;
|
|
641
|
+
const id = this.recentSendHistoryService.recordTxWithSwapV2(historyData.fromChainId, historyData.toChainId, historyData.provider, historyData.destinationAsset, historyData.simpleRoute, historyData.sender, historyData.recipient, historyData.amount, historyData.notificationInfo, historyData.routeDurationSeconds, tx.txHash, historyData.isOnlyUseBridge, backgroundExecutionId);
|
|
642
|
+
execution.historyId = id;
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
default: {
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
getRecentTxExecutions() {
|
|
651
|
+
return Array.from(this.recentTxExecutionMap.values());
|
|
652
|
+
}
|
|
653
|
+
getTxExecution(id) {
|
|
654
|
+
const execution = this.recentTxExecutionMap.get(id);
|
|
655
|
+
if (!execution) {
|
|
656
|
+
return undefined;
|
|
657
|
+
}
|
|
658
|
+
return execution;
|
|
659
|
+
}
|
|
660
|
+
removeTxExecution(id) {
|
|
661
|
+
this.recentTxExecutionMap.delete(id);
|
|
662
|
+
}
|
|
663
|
+
cleanupOldExecutions() {
|
|
664
|
+
const completedStatuses = [
|
|
665
|
+
types_1.TxExecutionStatus.COMPLETED,
|
|
666
|
+
types_1.TxExecutionStatus.FAILED,
|
|
667
|
+
];
|
|
668
|
+
const idsToDelete = [];
|
|
669
|
+
for (const [id, execution] of this.recentTxExecutionMap) {
|
|
670
|
+
// 비정상 종료된 PROCESSING 상태 → FAILED 처리
|
|
671
|
+
// (브라우저 종료, 시스템 재부팅, 익스텐션 업데이트 등)
|
|
672
|
+
if (execution.status === types_1.TxExecutionStatus.PROCESSING) {
|
|
673
|
+
execution.status = types_1.TxExecutionStatus.FAILED;
|
|
674
|
+
}
|
|
675
|
+
if (completedStatuses.includes(execution.status)) {
|
|
676
|
+
idsToDelete.push(id);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
for (const id of idsToDelete) {
|
|
680
|
+
this.recentTxExecutionMap.delete(id);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
recordSwapV2HistoryErrorIfNeeded(execution, error) {
|
|
684
|
+
if (execution.type === types_1.TxExecutionType.SWAP_V2 &&
|
|
685
|
+
execution.historyId != null) {
|
|
686
|
+
this.recentSendHistoryService.setSwapV2HistoryError(execution.historyId, error);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
clearSwapV2HistoryBackgroundExecutionIdIfNeeded(execution) {
|
|
690
|
+
if (execution.type === types_1.TxExecutionType.SWAP_V2 &&
|
|
691
|
+
execution.historyId != null) {
|
|
692
|
+
this.recentSendHistoryService.clearSwapV2HistoryBackgroundExecutionId(execution.historyId);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
__decorate([
|
|
697
|
+
mobx_1.observable
|
|
698
|
+
], BackgroundTxExecutorService.prototype, "recentTxExecutionSeq", void 0);
|
|
699
|
+
__decorate([
|
|
700
|
+
mobx_1.observable
|
|
701
|
+
], BackgroundTxExecutorService.prototype, "recentTxExecutionMap", void 0);
|
|
702
|
+
__decorate([
|
|
703
|
+
mobx_1.action
|
|
704
|
+
], BackgroundTxExecutorService.prototype, "handleTxExecutionEvent", null);
|
|
705
|
+
__decorate([
|
|
706
|
+
mobx_1.action
|
|
707
|
+
], BackgroundTxExecutorService.prototype, "recordHistoryIfNeeded", null);
|
|
708
|
+
__decorate([
|
|
709
|
+
mobx_1.action
|
|
710
|
+
], BackgroundTxExecutorService.prototype, "removeTxExecution", null);
|
|
711
|
+
__decorate([
|
|
712
|
+
mobx_1.action
|
|
713
|
+
], BackgroundTxExecutorService.prototype, "cleanupOldExecutions", null);
|
|
714
|
+
exports.BackgroundTxExecutorService = BackgroundTxExecutorService;
|
|
715
|
+
//# sourceMappingURL=service.js.map
|