Skip to content

Commit

Permalink
Updated unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaszslabon committed Nov 1, 2023
1 parent c90b155 commit f65ef2a
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 142 deletions.
6 changes: 6 additions & 0 deletions typescript/src/services/redemptions/redemptions-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,12 @@ export class RedemptionsService {
}
}

// Should never happen if the wallet has the main UTXO registered in the
// Bridge. It could only happen due to some serious error, e.g. wrong main
// UTXO hash stored in the Bridge or Bitcoin blockchain data corruption.
console.error(
`main UTXO with hash ${mainUtxoHash.toPrefixedString()} not found for wallet ${walletPublicKeyHash.toString()}`
)
return undefined
}

Expand Down
317 changes: 179 additions & 138 deletions typescript/test/services/redemptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,23 +79,33 @@ describe("Redemptions", () => {

// Prepare wallet transaction history for main UTXO lookup.
// Set only relevant fields.
const transactionHistory = new Map<string, BitcoinTx[]>()
transactionHistory.set(walletAddress, [
{
transactionHash: mainUtxo.transactionHash,
outputs: [
{
outputIndex: mainUtxo.outputIndex,
value: mainUtxo.value,
scriptPubKey: BitcoinAddressConverter.addressToOutputScript(
walletAddress,
BitcoinNetwork.Testnet
),
},
],
} as BitcoinTx,

const transaction = {
transactionHash: mainUtxo.transactionHash,
outputs: [
{
outputIndex: mainUtxo.outputIndex,
value: mainUtxo.value,
scriptPubKey: BitcoinAddressConverter.addressToOutputScript(
walletAddress,
BitcoinNetwork.Testnet
),
},
],
}

const walletTransactions = new Map<string, BitcoinTx>()
walletTransactions.set(
transaction.transactionHash.toString(),
transaction as BitcoinTx
)
bitcoinClient.transactions = walletTransactions

const walletTransactionHashes = new Map<string, BitcoinTxHash[]>()
walletTransactionHashes.set(walletPublicKeyHash.toString(), [
transaction.transactionHash,
])
bitcoinClient.transactionHistory = transactionHistory
bitcoinClient.transactionHashes = walletTransactionHashes

const redemptionsService = new RedemptionsService(
tbtcContracts,
Expand Down Expand Up @@ -268,19 +278,27 @@ describe("Redemptions", () => {
(wallet) => wallet.event
)

const walletsTransactionHistory = new Map<string, BitcoinTx[]>()
const walletTransactions = new Map<string, BitcoinTx>()
const walletTransactionHashes = new Map<string, BitcoinTxHash[]>()

walletsOrder.forEach((wallet) => {
const {
state,
mainUtxoHash,
walletPublicKey,
btcAddress,
transactions,
pendingRedemptionsValue,
} = wallet.data

walletsTransactionHistory.set(btcAddress, transactions)
transactions.forEach((tx) => {
walletTransactions.set(tx.transactionHash.toString(), tx)
})

walletTransactionHashes.set(
wallet.event.walletPublicKeyHash.toString(),
transactions.map((tx) => tx.transactionHash)
)

tbtcContracts.bridge.setWallet(
wallet.event.walletPublicKeyHash.toPrefixedString(),
{
Expand All @@ -292,7 +310,8 @@ describe("Redemptions", () => {
)
})

bitcoinClient.transactionHistory = walletsTransactionHistory
bitcoinClient.transactions = walletTransactions
bitcoinClient.transactionHashes = walletTransactionHashes

redemptionsService = new TestRedemptionsService(
tbtcContracts,
Expand Down Expand Up @@ -538,6 +557,13 @@ describe("Redemptions", () => {
}
}

// Helper function for preparing transaction hashes.
const getTransactionHashes = (
transactions: BitcoinTx[]
): BitcoinTxHash[] => {
return transactions.map((t) => t.transactionHash)
}

// Create a fake wallet witness transaction history that consists of 6 transactions.
const walletWitnessTransactionHistory: BitcoinTx[] = [
mockTransaction(
Expand Down Expand Up @@ -669,134 +695,149 @@ describe("Redemptions", () => {
})

context("when wallet main UTXO is set in the Bridge", () => {
const tests = [
{
testName: "recent witness transaction",
// Set the main UTXO hash based on the latest transaction from walletWitnessTransactionHistory.
actualMainUtxo: {
transactionHash: Hex.from(
"ea374ab6842723c647c3fc0ab281ca0641eaa768576cf9df695ca5b827140214"
),
outputIndex: 1,
value: BigNumber.from(200000),
},
expectedMainUtxo: {
transactionHash: Hex.from(
"ea374ab6842723c647c3fc0ab281ca0641eaa768576cf9df695ca5b827140214"
),
outputIndex: 1,
value: BigNumber.from(200000),
},
},
{
testName: "recent legacy transaction",
// Set the main UTXO hash based on the second last transaction from walletLegacyTransactionHistory.
actualMainUtxo: {
transactionHash: Hex.from(
"05dabb0291c0a6aa522de5ded5cb6d14ee2159e7ff109d3ef0f21de128b56b94"
),
outputIndex: 0,
value: BigNumber.from(100000),
},
expectedMainUtxo: {
transactionHash: Hex.from(
"05dabb0291c0a6aa522de5ded5cb6d14ee2159e7ff109d3ef0f21de128b56b94"
),
outputIndex: 0,
value: BigNumber.from(100000),
},
},
{
testName: "old witness transaction",
// Set the main UTXO hash based on the oldest transaction from walletWitnessTransactionHistory.
actualMainUtxo: {
transactionHash: Hex.from(
"3ca4ae3f8ee3b48949192bc7a146c8d9862267816258c85e02a44678364551e1"
),
outputIndex: 0,
value: BigNumber.from(100000),
},
expectedMainUtxo: undefined,
},
{
testName: "old legacy transaction",
// Set the main UTXO hash based on the oldest transaction from walletLegacyTransactionHistory.
actualMainUtxo: {
transactionHash: Hex.from(
"230a19d8867ff3f5b409e924d9dd6413188e215f9bb52f1c47de6154dac42267"
),
outputIndex: 1,
value: BigNumber.from(200000),
},
expectedMainUtxo: undefined,
},
]
context(
"when the transaction representing main UTXO could not be found",
() => {
// This scenario should never happen. It could only happen due to some
// serious error.
beforeEach(async () => {
tbtcContracts.bridge.setWallet(
walletPublicKeyHash.toPrefixedString(),
{
// Set main UTXO hash to some non-zero-filled hash.
mainUtxoHash: Hex.from(
"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
),
} as Wallet
)
})

it("should return undefined", async () => {
const mainUtxo = await redemptionsService.determineWalletMainUtxo(
walletPublicKeyHash,
BitcoinNetwork.Testnet
)

expect(mainUtxo).to.be.undefined
})
}
)

tests.forEach(({ testName, actualMainUtxo, expectedMainUtxo }) => {
context(`with main UTXO coming from ${testName}`, () => {
const networkTests = [
context(
"when the transaction representing main UTXO could be found",
() => {
const tests = [
{
testName: "recent witness transaction",
// Set the main UTXO hash based on the latest transaction from walletWitnessTransactionHistory.
mainUtxo: {
transactionHash: Hex.from(
"ea374ab6842723c647c3fc0ab281ca0641eaa768576cf9df695ca5b827140214"
),
outputIndex: 1,
value: BigNumber.from(200000),
},
},
{
testName: "recent legacy transaction",
// Set the main UTXO hash based on the second last transaction from walletLegacyTransactionHistory.
mainUtxo: {
transactionHash: Hex.from(
"05dabb0291c0a6aa522de5ded5cb6d14ee2159e7ff109d3ef0f21de128b56b94"
),
outputIndex: 0,
value: BigNumber.from(100000),
},
},
{
networkTestName: "bitcoin testnet",
network: BitcoinNetwork.Testnet,
testName: "old witness transaction",
// Set the main UTXO hash based on the oldest transaction from walletWitnessTransactionHistory.
mainUtxo: {
transactionHash: Hex.from(
"3ca4ae3f8ee3b48949192bc7a146c8d9862267816258c85e02a44678364551e1"
),
outputIndex: 0,
value: BigNumber.from(100000),
},
},
{
networkTestName: "bitcoin mainnet",
network: BitcoinNetwork.Mainnet,
testName: "old legacy transaction",
// Set the main UTXO hash based on the oldest transaction from walletLegacyTransactionHistory.
mainUtxo: {
transactionHash: Hex.from(
"230a19d8867ff3f5b409e924d9dd6413188e215f9bb52f1c47de6154dac42267"
),
outputIndex: 1,
value: BigNumber.from(200000),
},
},
]

networkTests.forEach(({ networkTestName, network }) => {
context(`with ${networkTestName} network`, () => {
beforeEach(async () => {
bitcoinNetwork = network

const walletWitnessAddress =
BitcoinAddressConverter.publicKeyHashToAddress(
walletPublicKeyHash,
true,
bitcoinNetwork
)
const walletLegacyAddress =
BitcoinAddressConverter.publicKeyHashToAddress(
walletPublicKeyHash,
false,
bitcoinNetwork
)

// Record the fake transaction history for both address types.
const transactionHistory = new Map<string, BitcoinTx[]>()
transactionHistory.set(
walletWitnessAddress,
walletWitnessTransactionHistory
)
transactionHistory.set(
walletLegacyAddress,
walletLegacyTransactionHistory
)
bitcoinClient.transactionHistory = transactionHistory

tbtcContracts.bridge.setWallet(
walletPublicKeyHash.toPrefixedString(),
{
mainUtxoHash:
tbtcContracts.bridge.buildUtxoHash(actualMainUtxo),
} as Wallet
)
})

it("should return the expected main UTXO", async () => {
const mainUtxo =
await redemptionsService.determineWalletMainUtxo(
walletPublicKeyHash,
bitcoinNetwork
)

expect(mainUtxo).to.be.eql(expectedMainUtxo)
tests.forEach(({ testName, mainUtxo }) => {
context(`with main UTXO coming from ${testName}`, () => {
const networkTests = [
{
networkTestName: "bitcoin testnet",
network: BitcoinNetwork.Testnet,
},
{
networkTestName: "bitcoin mainnet",
network: BitcoinNetwork.Mainnet,
},
]

networkTests.forEach(({ networkTestName, network }) => {
context(`with ${networkTestName} network`, () => {
beforeEach(async () => {
bitcoinNetwork = network

// Record transaction and transaction hashes.
const transactions = new Map<string, BitcoinTx>()
const allTransactions = [
...walletWitnessTransactionHistory,
...walletLegacyTransactionHistory,
]
allTransactions.forEach((tx) => {
transactions.set(tx.transactionHash.toString(), tx)
})
bitcoinClient.transactions = transactions

const transactionHashes = new Map<
string,
BitcoinTxHash[]
>()
transactionHashes.set(walletPublicKeyHash.toString(), [
...getTransactionHashes(
walletWitnessTransactionHistory
),
...getTransactionHashes(walletLegacyTransactionHistory),
])
bitcoinClient.transactionHashes = transactionHashes

tbtcContracts.bridge.setWallet(
walletPublicKeyHash.toPrefixedString(),
{
mainUtxoHash:
tbtcContracts.bridge.buildUtxoHash(mainUtxo),
} as Wallet
)
})

it("should return the expected main UTXO", async () => {
const mainUtxo =
await redemptionsService.determineWalletMainUtxo(
walletPublicKeyHash,
bitcoinNetwork
)

expect(mainUtxo).to.be.eql(mainUtxo)
})
})
})
})
})
})
})
}
)
})
})
})
Expand Down
Loading

0 comments on commit f65ef2a

Please sign in to comment.