Skip to content

Commit 4fd158b

Browse files
committed
fix(wallet): lock utxo right after submitting, run input selection with availableUtxo set
1 parent 22de0c7 commit 4fd158b

File tree

6 files changed

+20
-18
lines changed

6 files changed

+20
-18
lines changed

packages/wallet/src/InMemoryTransactionTracker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ export class InMemoryTransactionTracker extends Emittery<TransactionTrackerEvent
3030
this.#pollInterval = pollInterval;
3131
}
3232

33-
async trackTransaction(transaction: CSL.Transaction): Promise<void> {
33+
async trackTransaction(transaction: CSL.Transaction, submitted: Promise<void> = Promise.resolve()): Promise<void> {
34+
await submitted;
3435
const body = transaction.body();
3536
const hash = Buffer.from(this.#csl.hash_transaction(body).to_bytes()).toString('hex');
3637
this.#logger.debug('InMemoryTransactionTracker.trackTransaction', hash);

packages/wallet/src/InMemoryUtxoRepository.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ export interface InMemoryUtxoRepositoryProps {
1919
logger?: Logger;
2020
}
2121

22-
// Review: is comparing txIn enough to identify unique utxo?
2322
const utxoEquals = ([txIn1]: [Schema.TxIn, Schema.TxOut], [txIn2]: [Schema.TxIn, Schema.TxOut]): boolean =>
2423
txIn1.txId === txIn2.txId && txIn1.index === txIn2.index;
2524
export class InMemoryUtxoRepository extends Emittery<UtxoRepositoryEvents> implements UtxoRepository {
@@ -93,7 +92,7 @@ export class InMemoryUtxoRepository extends Emittery<UtxoRepositoryEvents> imple
9392
await this.sync();
9493
}
9594
return this.#inputSelector.select({
96-
utxo: new Set(Ogmios.ogmiosToCsl(this.#csl).utxo(this.allUtxos)),
95+
utxo: new Set(Ogmios.ogmiosToCsl(this.#csl).utxo(this.availableUtxos)),
9796
outputs,
9897
constraints,
9998
implicitCoin

packages/wallet/src/SingleAddressWallet.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import Schema from '@cardano-ogmios/schema';
2-
import { CardanoProvider, Ogmios, Transaction, CardanoSerializationLib, CSL } from '@cardano-sdk/core';
2+
import { CardanoProvider, Ogmios, Transaction, CardanoSerializationLib, CSL, ProviderError } from '@cardano-sdk/core';
33
import { UtxoRepository } from './types';
44
import { dummyLogger, Logger } from 'ts-log';
55
import { defaultSelectionConstraints } from '@cardano-sdk/cip2';
66
import { computeImplicitCoin, createTransactionInternals, InitializeTxProps, TxInternals } from './Transaction';
7-
import { KeyManagement, TransactionTracker } from '.';
7+
import { KeyManagement, TransactionError, TransactionFailure, TransactionTracker } from '.';
88

99
export interface SubmitTxResult {
1010
/**
1111
* Resolves when transaction is submitted.
12-
* Rejects with ProviderError.
12+
* Rejects with {TransactionError}.
1313
*/
1414
submitted: Promise<void>;
1515
/**
1616
* Resolves when transaction is submitted and confirmed.
17-
* Rejects with TransactionError.
17+
* Rejects with {TransactionError}.
1818
*/
1919
confirmed: Promise<void>;
2020
}
@@ -23,12 +23,6 @@ export interface SingleAddressWallet {
2323
initializeTx: (props: InitializeTxProps) => Promise<TxInternals>;
2424
name: string;
2525
signTx: (body: CSL.TransactionBody, hash: CSL.TransactionHash) => Promise<CSL.Transaction>;
26-
/**
27-
* Submits transaction.
28-
*
29-
* @returns {Promise<SubmitTxResult>} promise that resolves when transaction is submitted,
30-
* but not confirmed yet. Rejects with TransactionError { FailedToSubmit }
31-
*/
3226
submitTx: (tx: CSL.Transaction) => SubmitTxResult;
3327
}
3428

@@ -92,10 +86,16 @@ export const createSingleAddressWallet = async (
9286
name,
9387
signTx,
9488
submitTx: (tx) => {
95-
const submitted = provider.submitTx(tx);
89+
const submitted = provider.submitTx(tx).catch((error) => {
90+
if (error instanceof ProviderError) {
91+
throw new TransactionError(TransactionFailure.FailedToSubmit, error, error.detail);
92+
}
93+
throw new TransactionError(TransactionFailure.FailedToSubmit, error);
94+
});
95+
const confirmed = txTracker.trackTransaction(tx, submitted);
9696
return {
9797
submitted,
98-
confirmed: submitted.then(() => txTracker.trackTransaction(tx))
98+
confirmed
9999
};
100100
}
101101
};

packages/wallet/src/TransactionError.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { CustomError } from 'ts-custom-error';
22

33
export enum TransactionFailure {
4+
FailedToSubmit = 'FAILED_TO_SUBMIT',
5+
Unknown = 'UNKNOWN',
46
CannotTrack = 'CANNOT_TRACK',
57
Timeout = 'TIMEOUT'
68
}

packages/wallet/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@ export interface TransactionTracker extends Emittery<TransactionTrackerEvents> {
3030
/**
3131
* Track a new transaction
3232
*/
33-
trackTransaction(transaction: CSL.Transaction): Promise<void>;
33+
trackTransaction(transaction: CSL.Transaction, submitted?: Promise<void>): Promise<void>;
3434
}

packages/wallet/test/SingleAddressWallet.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ describe('Wallet', () => {
7575
test('submitTx', async () => {
7676
const { body, hash } = await wallet.initializeTx(props);
7777
const tx = await wallet.signTx(body, hash);
78-
const { confirmed } = wallet.submitTx(tx);
78+
const { submitted, confirmed } = wallet.submitTx(tx);
7979
await confirmed;
8080
expect(provider.submitTx).toBeCalledTimes(1);
8181
expect(provider.submitTx).toBeCalledWith(tx);
8282
expect(txTracker.trackTransaction).toBeCalledTimes(1);
83-
expect(txTracker.trackTransaction).toBeCalledWith(tx);
83+
expect(txTracker.trackTransaction).toBeCalledWith(tx, submitted);
8484
});
8585
});
8686
});

0 commit comments

Comments
 (0)