Skip to content

Commit 6244a8e

Browse files
fixup! feat(wallet): the wallet now only fetches UTXOs on tx history change
1 parent 08301b5 commit 6244a8e

File tree

1 file changed

+49
-47
lines changed

1 file changed

+49
-47
lines changed

packages/wallet/src/services/TransactionsTracker.ts

Lines changed: 49 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,30 @@ const getLastTransactionsAtBlock = (
123123
return txsFromSameBlock;
124124
};
125125

126+
export const revertLastBlock = (
127+
localTransactions: Cardano.HydratedTx[],
128+
blockNo: Cardano.BlockNo,
129+
rollback$: Subject<Cardano.HydratedTx>,
130+
logger: Logger
131+
) => {
132+
const result = [...localTransactions];
133+
134+
while (result.length > 0) {
135+
const lastKnownTx = result[result.length - 1];
136+
137+
if (lastKnownTx.blockHeader.blockNo === blockNo) {
138+
logger.debug(`Transaction ${lastKnownTx.id} was rolled back`);
139+
140+
rollback$.next(lastKnownTx);
141+
result.pop();
142+
} else {
143+
break;
144+
}
145+
}
146+
147+
return result;
148+
};
149+
126150
const findIntersectionAndUpdateTxStore = ({
127151
chainHistoryProvider,
128152
logger,
@@ -148,12 +172,9 @@ const findIntersectionAndUpdateTxStore = ({
148172
combinator: exhaustMap,
149173
equals: transactionsEquals,
150174
onFatalError,
151-
// eslint-disable-next-line complexity
152175
provider: async () => {
153176
// eslint-disable-next-line no-constant-condition
154177
while (true) {
155-
let rollbackOccured = false;
156-
157178
const lastStoredTransaction: Cardano.HydratedTx | undefined = localTransactions[localTransactions.length - 1];
158179

159180
lastStoredTransaction &&
@@ -172,65 +193,46 @@ const findIntersectionAndUpdateTxStore = ({
172193
lowerBound !== undefined && `since block ${lowerBound}`
173194
);
174195

196+
// Fetching transactions from scratch, nothing else to do here.
175197
if (lowerBound === undefined) {
176-
localTransactions = newTransactions;
177-
return localTransactions;
198+
return newTransactions;
178199
}
179200

201+
// If no transactions found from that block range, it means the last known block has been rolled back.
180202
if (newTransactions.length === 0) {
181-
// If no transactions found from that block range, it means the last known block has been rolled back.
182-
while (localTransactions.length > 0) {
183-
const lastKnownTx = localTransactions[localTransactions.length - 1];
184-
185-
if (lastKnownTx.blockHeader.blockNo === lowerBound) {
186-
rollbackOccured = true;
187-
logger.debug(`Transaction ${lastKnownTx.id} was rolled back`);
188-
rollback$.next(lastKnownTx);
189-
localTransactions.pop();
190-
} else {
191-
break;
192-
}
193-
}
194-
203+
localTransactions = revertLastBlock(localTransactions, lowerBound, rollback$, logger);
195204
continue;
196205
}
197206

198207
const localTxsFromSameBlock = getLastTransactionsAtBlock(localTransactions, lowerBound);
208+
const firstSegmentOfNewTransactions = newTransactions.slice(0, localTxsFromSameBlock.length);
199209

200-
// Roll back transactions from this block not found in the result
201-
for (const localTx of localTxsFromSameBlock) {
202-
const txFound = newTransactions.find((tx) => tx.id === localTx.id);
203-
204-
if (!txFound) {
205-
rollbackOccured = true;
206-
logger.debug(`Transaction ${localTx.id} was rolled back`);
207-
rollback$.next(localTx);
210+
// The first segment of new transaction should match exactly (same txs and same order) our last know TXs. Otherwise
211+
// roll them back and re-apply in new order.
212+
const sameLength = localTxsFromSameBlock.length === firstSegmentOfNewTransactions.length;
213+
const sameOrder =
214+
sameLength && localTxsFromSameBlock.every((tx, index) => tx.id === firstSegmentOfNewTransactions[index].id);
208215

209-
const index = localTransactions.findLastIndex((tx) => tx.id === localTx.id);
216+
if (!sameLength || !sameOrder) {
217+
localTransactions = revertLastBlock(localTransactions, lowerBound, rollback$, logger);
218+
localTransactions = [...localTransactions, ...newTransactions];
219+
store.setAll(localTransactions);
210220

211-
if (index !== -1) {
212-
localTransactions.splice(index, 1);
213-
}
214-
}
221+
continue;
215222
}
216223

217-
if (!rollbackOccured) {
218-
const lastLocalTxs = localTransactions.slice(-newTransactions.length);
219-
220-
const areTransactionsSame =
221-
lastLocalTxs.length === newTransactions.length &&
222-
lastLocalTxs.every((tx, index) => tx.id === newTransactions[index].id);
224+
// No rollbacks, if they overlap 100% do nothing, otherwise add the difference.
225+
const areTransactionsSame =
226+
newTransactions.length === localTxsFromSameBlock.length &&
227+
localTxsFromSameBlock.every((tx, index) => tx.id === newTransactions[index].id);
223228

224-
if (!areTransactionsSame) {
225-
// Remove overlapping transactions
226-
localTransactions = localTransactions.slice(0, -localTxsFromSameBlock.length);
227-
localTransactions = [...localTransactions, ...newTransactions];
228-
229-
store.setAll(localTransactions);
230-
}
231-
232-
return localTransactions;
229+
if (!areTransactionsSame) {
230+
// Skip overlapping transactions to avoid duplicates
231+
localTransactions = [...localTransactions, ...newTransactions.slice(localTxsFromSameBlock.length)];
232+
store.setAll(localTransactions);
233233
}
234+
235+
return localTransactions;
234236
}
235237
},
236238
retryBackoffConfig,

0 commit comments

Comments
 (0)