|
| 1 | +import { roundRobinRandomImprove } from '@cardano-sdk/cip2'; |
| 2 | +import { Cardano, CardanoSerializationLib, loadCardanoSerializationLib } from '@cardano-sdk/core'; |
| 3 | +import { |
| 4 | + createSingleAddressWallet, |
| 5 | + InMemoryTransactionTracker, |
| 6 | + InMemoryUtxoRepository, |
| 7 | + KeyManagement, |
| 8 | + SingleAddressWallet, |
| 9 | + SingleAddressWalletProps, |
| 10 | + Transaction, |
| 11 | + TransactionError, |
| 12 | + TransactionFailure, |
| 13 | + TransactionTracker, |
| 14 | + UtxoRepository |
| 15 | +} from '@cardano-sdk/wallet'; |
| 16 | +import { providerStub } from '../ProviderStub'; |
| 17 | +// Not testing with a real provider |
| 18 | +// import { blockfrostProvider } from '@cardano-sdk/blockfrost'; |
| 19 | + |
| 20 | +const walletProps: SingleAddressWalletProps = { name: 'some-wallet' }; |
| 21 | +const networkId = Cardano.NetworkId.mainnet; |
| 22 | +const mnemonicWords = KeyManagement.util.generateMnemonicWords(); |
| 23 | +const password = 'your_password'; |
| 24 | + |
| 25 | +describe('integration/withdrawal', () => { |
| 26 | + let csl: CardanoSerializationLib; |
| 27 | + let keyManager: KeyManagement.KeyManager; |
| 28 | + let txTracker: TransactionTracker; |
| 29 | + let utxoRepository: UtxoRepository; |
| 30 | + let wallet: SingleAddressWallet; |
| 31 | + |
| 32 | + beforeAll(async () => { |
| 33 | + csl = await loadCardanoSerializationLib(); |
| 34 | + keyManager = KeyManagement.createInMemoryKeyManager({ csl, mnemonicWords, password, networkId }); |
| 35 | + const provider = providerStub(); |
| 36 | + const inputSelector = roundRobinRandomImprove(csl); |
| 37 | + txTracker = new InMemoryTransactionTracker({ csl, provider }); |
| 38 | + utxoRepository = new InMemoryUtxoRepository({ csl, provider, txTracker, inputSelector, keyManager }); |
| 39 | + wallet = await createSingleAddressWallet(walletProps, { |
| 40 | + csl, |
| 41 | + keyManager, |
| 42 | + provider, |
| 43 | + utxoRepository, |
| 44 | + txTracker |
| 45 | + }); |
| 46 | + |
| 47 | + // Call this to sync available balance |
| 48 | + await utxoRepository.sync(); |
| 49 | + }); |
| 50 | + |
| 51 | + it('does not throw', async () => { |
| 52 | + // This is not testing anything, just a usage example |
| 53 | + utxoRepository.on('transactionUntracked', (tx) => { |
| 54 | + // UtxoRepository is not sure whether it's UTxO can be spent due to failing to track transaction confirmation. |
| 55 | + // SubmitTxResult.confirmed has rejected. Calling trackTransaction will lock UTxO again: |
| 56 | + txTracker.trackTransaction(tx).catch((error) => { |
| 57 | + /* eslint-disable-next-line sonarjs/no-all-duplicated-branches */ |
| 58 | + if (error instanceof TransactionError && error.reason === TransactionFailure.Timeout) { |
| 59 | + // Transaction has expired and will not be confirmed. Therefore it's safe to spend the UTxO again. |
| 60 | + } else { |
| 61 | + // Probably wait a little bit and retry |
| 62 | + } |
| 63 | + }); |
| 64 | + }); |
| 65 | + |
| 66 | + const certFactory = new Transaction.CertificateFactory(csl, keyManager); |
| 67 | + |
| 68 | + const { body, hash } = await wallet.initializeTx({ |
| 69 | + certificates: [certFactory.stakeKeyDeregistration()], |
| 70 | + withdrawals: [Transaction.withdrawal(csl, keyManager, utxoRepository.rewards || 0)], |
| 71 | + outputs: new Set() // In a real transaction you would probably want to have some outputs |
| 72 | + }); |
| 73 | + // Calculated fee is returned by invoking body.fee() |
| 74 | + const tx = await wallet.signTx(body, hash); |
| 75 | + |
| 76 | + const { submitted, confirmed } = wallet.submitTx(tx); |
| 77 | + // Transaction is submitting. UTxO is locked. |
| 78 | + await submitted; |
| 79 | + // Transaction is successfully submitted, but not confirmed yet |
| 80 | + await confirmed; |
| 81 | + }); |
| 82 | +}); |
0 commit comments