Skip to content

Commit

Permalink
Merge branch '88-fix-cardanochain-tx-extra-condition-verification' in…
Browse files Browse the repository at this point in the history
…to 'dev'

Resolve "fix CardanoChain tx extra condition verification"

Closes #88

See merge request ergo/rosen-bridge/rosen-chains!94
  • Loading branch information
vorujack committed Feb 20, 2024
2 parents 292efd8 + 786e2d3 commit 8e0796f
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 270 deletions.
7 changes: 7 additions & 0 deletions .changeset/lazy-deers-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@rosen-chains/abstract-chain': major
---

change verifyTransactionExtraConditions to abstract
implement getRWTToken
implement getTxConfirmationStatus
5 changes: 5 additions & 0 deletions .changeset/rich-meals-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rosen-chains/cardano': patch
---

fix verifyTransactionExtraConditions function name
22 changes: 15 additions & 7 deletions packages/abstract-chain/lib/AbstractChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,9 @@ abstract class AbstractChain {
* @param transaction the PaymentTransaction
* @returns true if the transaction is verified
*/
verifyTransactionExtraConditions = (
abstract verifyTransactionExtraConditions: (
transaction: PaymentTransaction
): boolean => {
return true;
};
) => boolean;

/**
* verifies an event data with its corresponding lock transaction
Expand Down Expand Up @@ -160,10 +158,18 @@ abstract class AbstractChain {
* @param transactionType type of the transaction
* @returns the transaction confirmation status
*/
abstract getTxConfirmationStatus: (
getTxConfirmationStatus = async (
transactionId: string,
transactionType: TransactionType
) => Promise<ConfirmationStatus>;
): Promise<ConfirmationStatus> => {
const requiredConfirmation =
this.getTxRequiredConfirmation(transactionType);
const confirmation = await this.network.getTxConfirmation(transactionId);
if (confirmation >= requiredConfirmation)
return ConfirmationStatus.ConfirmedEnough;
else if (confirmation === -1) return ConfirmationStatus.NotFound;
else return ConfirmationStatus.NotConfirmedEnough;
};

/**
* gets the amount of each asset in the address
Expand Down Expand Up @@ -243,7 +249,9 @@ abstract class AbstractChain {
* gets the RWT token id
* @returns RWT token id
*/
abstract getRWTToken: () => string;
getRWTToken = (): string => {
return this.configs.rwtId;
};

/**
* converts json representation of the payment transaction to PaymentTransaction
Expand Down
88 changes: 87 additions & 1 deletion packages/abstract-chain/tests/AbstractChain.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import TestChainNetwork from './network/TestChainNetwork';
import {
AssetBalance,
ChainConfigs,
ConfirmationStatus,
PaymentTransaction,
TransactionType,
} from '../lib';
Expand All @@ -11,12 +12,13 @@ import { when } from 'jest-when';
const spyOn = jest.spyOn;

describe('AbstractChain', () => {
const paymentTxConfirmation = 6;
const generateChainObject = (network: TestChainNetwork) => {
const config: ChainConfigs = {
fee: 100n,
confirmations: {
observation: 5,
payment: 6,
payment: paymentTxConfirmation,
cold: 7,
manual: 8,
},
Expand Down Expand Up @@ -129,6 +131,90 @@ describe('AbstractChain', () => {
});
});

describe('getTxConfirmationStatus', () => {
const txId = 'tx-id';
const txType = TransactionType.payment;
const requiredConfirmation = paymentTxConfirmation;
const network = new TestChainNetwork();

/**
* @target ErgoChain.getTxConfirmationStatus should return
* ConfirmedEnough when tx confirmation is more than required number
* @dependencies
* @scenario
* - mock a network object to return enough confirmation for mocked txId
* - run test
* - check returned value
* @expected
* - it should return `ConfirmedEnough` enum
*/
it('should return ConfirmedEnough when tx confirmation is more than required number', async () => {
// mock a network object to return enough confirmation for mocked txId
const getTxConfirmationSpy = spyOn(network, 'getTxConfirmation');
when(getTxConfirmationSpy)
.calledWith(txId)
.mockResolvedValueOnce(requiredConfirmation + 1);

// run test
const chain = generateChainObject(network);
const result = await chain.getTxConfirmationStatus(txId, txType);

// check returned value
expect(result).toEqual(ConfirmationStatus.ConfirmedEnough);
});

/**
* @target ErgoChain.getTxConfirmationStatus should return
* NotConfirmedEnough when payment tx confirmation is less than required number
* @dependencies
* @scenario
* - mock a network object to return insufficient confirmation for mocked
* txId
* - run test
* - check returned value
* @expected
* - it should return `NotConfirmedEnough` enum
*/
it('should return NotConfirmedEnough when tx confirmation is less than required number', async () => {
// mock a network object to return insufficient confirmation for mocked
const getTxConfirmationSpy = spyOn(network, 'getTxConfirmation');
when(getTxConfirmationSpy)
.calledWith(txId)
.mockResolvedValueOnce(requiredConfirmation - 1);

// run test
const chain = generateChainObject(network);
const result = await chain.getTxConfirmationStatus(txId, txType);

// check returned value
expect(result).toEqual(ConfirmationStatus.NotConfirmedEnough);
});

/**
* @target ErgoChain.getTxConfirmationStatus should return
* NotFound when tx confirmation is -1
* @dependencies
* @scenario
* - mock a network object to return -1 confirmation for mocked txId
* - run test
* - check returned value
* @expected
* - it should return `NotFound` enum
*/
it('should return NotFound when tx confirmation is -1', async () => {
// mock a network object to return enough confirmation for mocked txId
const getTxConfirmationSpy = spyOn(network, 'getTxConfirmation');
when(getTxConfirmationSpy).calledWith(txId).mockResolvedValueOnce(-1);

// run test
const chain = generateChainObject(network);
const result = await chain.getTxConfirmationStatus(txId, txType);

// check returned value
expect(result).toEqual(ConfirmationStatus.NotFound);
});
});

describe('hasLockAddressEnoughAssets', () => {
const requiredAssets = {
nativeToken: 100n,
Expand Down
3 changes: 1 addition & 2 deletions packages/abstract-chain/tests/TestChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ class TestChain extends AbstractChain {
generateTransaction = this.notImplemented;
extractTransactionOrder = this.notImplemented;
verifyTransactionFee = this.notImplemented;
verifyTransactionExtraConditions = this.notImplemented;
verifyEvent = this.notImplemented;
isTxValid = this.notImplemented;
signTransaction = this.notImplemented;
getTxConfirmationStatus = this.notImplemented;
submitTransaction = this.notImplemented;
isTxInMempool = this.notImplemented;
getMinimumNativeToken = this.notImplemented;
getRWTToken = this.notImplemented;
PaymentTransactionFromJson = this.notImplemented;
rawTxToPaymentTransaction = this.notImplemented;

Expand Down
3 changes: 1 addition & 2 deletions packages/abstract-chain/tests/TestUtxoChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@ class TestUtxoChain extends AbstractUtxoChain<string> {
getTransactionAssets = this.notImplemented;
extractTransactionOrder = this.notImplemented;
verifyTransactionFee = this.notImplemented;
verifyTransactionExtraConditions = this.notImplemented;
verifyEvent = this.notImplemented;
isTxValid = this.notImplemented;
signTransaction = this.notImplemented;
getTxConfirmationStatus = this.notImplemented;
getLockAddressAssets = this.notImplemented;
submitTransaction = this.notImplemented;
isTxInMempool = this.notImplemented;
getMempoolBoxMapping = this.notImplemented;
getMinimumNativeToken = this.notImplemented;
getRWTToken = this.notImplemented;
PaymentTransactionFromJson = this.notImplemented;
rawTxToPaymentTransaction = this.notImplemented;

Expand Down
5 changes: 4 additions & 1 deletion packages/abstract-chain/tests/network/TestChainNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ class TestUtxoChainNetwork extends AbstractChainNetwork<string> {
};

getHeight = this.notImplemented;
getTxConfirmation = this.notImplemented;
getAddressAssets = this.notImplemented;
getTransaction = this.notImplemented;
getBlockTransactionIds = this.notImplemented;
getBlockInfo = this.notImplemented;
submitTransaction = this.notImplemented;
getMempoolTransactions = this.notImplemented;
getTokenDetail = this.notImplemented;

getTxConfirmation = (transactionId: string): Promise<number> => {
throw Error('Not mocked');
};
}

export default TestUtxoChainNetwork;
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class TestUtxoChainNetwork extends AbstractUtxoChainNetwork<string, string> {
};

getHeight = this.notImplemented;
getTxConfirmation = this.notImplemented;
getAddressAssets = this.notImplemented;
getTransaction = this.notImplemented;
getBlockTransactionIds = this.notImplemented;
Expand All @@ -20,6 +19,10 @@ class TestUtxoChainNetwork extends AbstractUtxoChainNetwork<string, string> {
isBoxUnspentAndValid = this.notImplemented;
getTokenDetail = this.notImplemented;

getTxConfirmation = (transactionId: string): Promise<number> => {
throw Error('Not mocked');
};

getAddressBoxes = (
address: string,
offset: number,
Expand Down
31 changes: 3 additions & 28 deletions packages/chains/cardano/lib/CardanoChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,9 @@ class CardanoChain extends AbstractUtxoChain<CardanoUtxo> {
* @param transaction to verify
* @returns true if all conditions are met
*/
verifyExtraCondition = (transaction: PaymentTransaction): boolean => {
verifyTransactionExtraConditions = (
transaction: PaymentTransaction
): boolean => {
const tx = Serializer.deserialize(transaction.txBytes);

// check metadata
Expand All @@ -623,25 +625,6 @@ class CardanoChain extends AbstractUtxoChain<CardanoUtxo> {
return true;
};

/**
* extracts confirmation status for a transaction
* @param transactionId the transaction id
* @param transactionType type of the transaction
* @returns the transaction confirmation status
*/
getTxConfirmationStatus = async (
transactionId: string,
transactionType: TransactionType
): Promise<ConfirmationStatus> => {
const requiredConfirmation =
this.getTxRequiredConfirmation(transactionType);
const confirmation = await this.network.getTxConfirmation(transactionId);
if (confirmation >= requiredConfirmation)
return ConfirmationStatus.ConfirmedEnough;
else if (confirmation === -1) return ConfirmationStatus.NotFound;
else return ConfirmationStatus.NotConfirmedEnough;
};

/**
* gets the minimum amount of native token for assetTransfer
* @returns the minimum amount
Expand All @@ -650,14 +633,6 @@ class CardanoChain extends AbstractUtxoChain<CardanoUtxo> {
return this.configs.minBoxValue;
};

/**
* gets the RWT token id
* @returns RWT token id
*/
getRWTToken = (): string => {
return this.configs.rwtId;
};

/**
* generates mapping from input box id to serialized string of output box (filtered by address, containing the token)
* @param txs list of transactions
Expand Down
Loading

0 comments on commit 8e0796f

Please sign in to comment.