diff --git a/backend/consensus/base.py b/backend/consensus/base.py index 3886cbd38..273c19a9c 100644 --- a/backend/consensus/base.py +++ b/backend/consensus/base.py @@ -151,9 +151,7 @@ async def exec_transaction( Node, ] = node_factory, ): - msg_handler = self.msg_handler.with_client_session( - transaction.client_session_id - ) + msg_handler = self.msg_handler if ( transactions_processor.get_transaction_by_hash(transaction.hash)["status"] != TransactionStatus.PENDING.value @@ -361,7 +359,6 @@ async def exec_transaction( type=TransactionType.RUN_CONTRACT.value, nonce=nonce, leader_only=transaction.leader_only, # Cascade - client_session_id=transaction.client_session_id, triggered_by_hash=transaction.hash, ) diff --git a/backend/database_handler/migration/versions/579e86111b36_remove_client_session_id_from_.py b/backend/database_handler/migration/versions/579e86111b36_remove_client_session_id_from_.py new file mode 100644 index 000000000..cea67ce1f --- /dev/null +++ b/backend/database_handler/migration/versions/579e86111b36_remove_client_session_id_from_.py @@ -0,0 +1,39 @@ +"""remove client session id from transactions + +Revision ID: 579e86111b36 +Revises: ab256b41602a +Create Date: 2024-11-08 10:41:56.112444 + +""" + +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = "579e86111b36" +down_revision: Union[str, None] = "ab256b41602a" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("transactions", "client_session_id") + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column( + "transactions", + sa.Column( + "client_session_id", + sa.VARCHAR(length=255), + autoincrement=False, + nullable=True, + ), + ) + # ### end Alembic commands ### diff --git a/backend/database_handler/models.py b/backend/database_handler/models.py index 73d640685..6cde88963 100644 --- a/backend/database_handler/models.py +++ b/backend/database_handler/models.py @@ -89,9 +89,6 @@ class Transactions(Base): created_at: Mapped[Optional[datetime.datetime]] = mapped_column( DateTime(True), server_default=func.current_timestamp(), init=False ) - client_session_id: Mapped[Optional[str]] = mapped_column( - String(255) - ) # Used to identify the client session that is subscribed to this transaction's events leader_only: Mapped[bool] = mapped_column(Boolean) r: Mapped[Optional[int]] = mapped_column(Integer) s: Mapped[Optional[int]] = mapped_column(Integer) diff --git a/backend/database_handler/transactions_processor.py b/backend/database_handler/transactions_processor.py index faa1a76bc..98a6e6496 100644 --- a/backend/database_handler/transactions_processor.py +++ b/backend/database_handler/transactions_processor.py @@ -43,7 +43,6 @@ def _parse_transaction_data(transaction_data: Transactions) -> dict: "v": transaction_data.v, "created_at": transaction_data.created_at.isoformat(), "leader_only": transaction_data.leader_only, - "client_session_id": transaction_data.client_session_id, "triggered_by": transaction_data.triggered_by_hash, "triggered_transactions": [ transaction.hash @@ -113,7 +112,6 @@ def insert_transaction( type: int, nonce: int, leader_only: bool, - client_session_id: str | None, triggered_by_hash: ( str | None ) = None, # If filled, the transaction must be present in the database (committed) @@ -146,7 +144,6 @@ def insert_transaction( s=None, v=None, leader_only=leader_only, - client_session_id=client_session_id, triggered_by=( self.session.query(Transactions).filter_by(hash=triggered_by_hash).one() if triggered_by_hash diff --git a/backend/domain/types.py b/backend/domain/types.py index 6ed2e0dcc..b93ec5b94 100644 --- a/backend/domain/types.py +++ b/backend/domain/types.py @@ -79,7 +79,6 @@ class Transaction: leader_only: bool = ( False # Flag to indicate if this transaction should be processed only by the leader. Used for fast and cheap execution of transactions. ) - client_session_id: str | None = None def to_dict(self): return { @@ -98,7 +97,6 @@ def to_dict(self): "s": self.s, "v": self.v, "leader_only": self.leader_only, - "client_session_id": self.client_session_id, } @@ -119,5 +117,4 @@ def transaction_from_dict(input: dict) -> Transaction: s=input.get("s"), v=input.get("v"), leader_only=input.get("leader_only", False), - client_session_id=input["client_session_id"], ) diff --git a/backend/protocol_rpc/endpoints.py b/backend/protocol_rpc/endpoints.py index 6ac1d840f..edf9e316c 100644 --- a/backend/protocol_rpc/endpoints.py +++ b/backend/protocol_rpc/endpoints.py @@ -72,7 +72,7 @@ def fund_account( nonce = transactions_processor.get_transaction_count(None) transaction_hash = transactions_processor.insert_transaction( - None, account_address, None, amount, 0, nonce, False, get_client_session_id() + None, account_address, None, amount, 0, nonce, False ) return transaction_hash @@ -485,7 +485,6 @@ def send_raw_transaction( transaction_type, nonce, leader_only, - get_client_session_id(), ) return transaction_hash diff --git a/backend/protocol_rpc/message_handler/base.py b/backend/protocol_rpc/message_handler/base.py index d739c981e..0eb33c5d3 100644 --- a/backend/protocol_rpc/message_handler/base.py +++ b/backend/protocol_rpc/message_handler/base.py @@ -41,13 +41,20 @@ def log_endpoint_info(self, func): return log_endpoint_info_wrapper(self, self.config)(func) def _socket_emit(self, log_event: LogEvent): - self.socketio.emit( - log_event.name, - log_event.to_dict(), - to=log_event.client_session_id - or self.client_session_id - or get_client_session_id(), - ) + if log_event.name == "transaction_status_updated": + self.socketio.emit( + log_event.name, + log_event.to_dict(), + room=log_event.data.get("hash"), + ) + else: + self.socketio.emit( + log_event.name, + log_event.to_dict(), + to=log_event.client_session_id + or self.client_session_id + or get_client_session_id(), + ) def _log_message(self, log_event: LogEvent): logging_status = log_event.type.value diff --git a/backend/protocol_rpc/server.py b/backend/protocol_rpc/server.py index a2fcd763c..14392191c 100644 --- a/backend/protocol_rpc/server.py +++ b/backend/protocol_rpc/server.py @@ -6,7 +6,7 @@ import logging from flask import Flask from flask_jsonrpc import JSONRPC -from flask_socketio import SocketIO +from flask_socketio import SocketIO, join_room, leave_room from flask_cors import CORS from flask_sqlalchemy import SQLAlchemy from sqlalchemy import create_engine @@ -131,6 +131,17 @@ def run_socketio(): host="0.0.0.0", allow_unsafe_werkzeug=True, ) + + @socketio.on("subscribe") + def handle_subscribe(topics): + for topic in topics: + join_room(topic) + + @socketio.on("unsubscribe") + def handle_unsubscribe(topics): + for topic in topics: + leave_room(topic) + logging.getLogger("werkzeug").setLevel( os.environ.get("FLASK_LOG_LEVEL", logging.ERROR) ) diff --git a/frontend/src/components/Simulator/TransactionItem.vue b/frontend/src/components/Simulator/TransactionItem.vue index 11f17d69f..363adbb79 100644 --- a/frontend/src/components/Simulator/TransactionItem.vue +++ b/frontend/src/components/Simulator/TransactionItem.vue @@ -16,7 +16,6 @@ const nodeStore = useNodeStore(); const props = defineProps<{ transaction: TransactionItem; }>(); -console.log('🚀 ~ transaction:', props.transaction); const isDetailsModalOpen = ref(false); diff --git a/frontend/src/hooks/index.ts b/frontend/src/hooks/index.ts index 55ceb3d8c..950835dfc 100644 --- a/frontend/src/hooks/index.ts +++ b/frontend/src/hooks/index.ts @@ -8,3 +8,4 @@ export * from './useInputMap'; export * from './useContractQueries'; export * from './useFileName'; export * from './useSetupStores'; +export * from './useTransactionListener'; diff --git a/frontend/src/hooks/useSetupStores.ts b/frontend/src/hooks/useSetupStores.ts index 9dff7c6c3..f920c743e 100644 --- a/frontend/src/hooks/useSetupStores.ts +++ b/frontend/src/hooks/useSetupStores.ts @@ -5,7 +5,7 @@ import { useNodeStore, useTutorialStore, } from '@/stores'; -import { useDb } from '@/hooks'; +import { useDb, useTransactionListener } from '@/hooks'; import { v4 as uuidv4 } from 'uuid'; import type { Address } from '@/types'; @@ -17,6 +17,7 @@ export const useSetupStores = () => { const nodeStore = useNodeStore(); const tutorialStore = useTutorialStore(); const db = useDb(); + const transactionListener = useTransactionListener(); const contractFiles = await db.contractFiles.toArray(); const exampleFiles = contractFiles.filter((c) => c.example); @@ -48,6 +49,9 @@ export const useSetupStores = () => { contractsStore.deployedContracts = await db.deployedContracts.toArray(); transactionsStore.transactions = await db.transactions.toArray(); + transactionsStore.initSubscriptions(); + transactionsStore.refreshPendingTransactions(); + transactionListener.init(); contractsStore.getInitialOpenedFiles(); tutorialStore.resetTutorialState(); nodeStore.getValidatorsData(); diff --git a/frontend/src/hooks/useTransactionListener.ts b/frontend/src/hooks/useTransactionListener.ts new file mode 100644 index 000000000..f3540cfa7 --- /dev/null +++ b/frontend/src/hooks/useTransactionListener.ts @@ -0,0 +1,40 @@ +import { useTransactionsStore } from '@/stores'; +import type { TransactionItem } from '@/types'; +import { useWebSocketClient } from '@/hooks'; + +export function useTransactionListener() { + const transactionsStore = useTransactionsStore(); + const webSocketClient = useWebSocketClient(); + + function init() { + webSocketClient.on( + 'transaction_status_updated', + handleTransactionStatusUpdate, + ); + } + + async function handleTransactionStatusUpdate(eventData: any) { + const newTx = await transactionsStore.getTransaction(eventData.data.hash); + + if (!newTx) { + console.warn('Server tx not found for local tx:', newTx); + transactionsStore.removeTransaction(newTx); + return; + } + + const currentTx = transactionsStore.transactions.find( + (t: TransactionItem) => t.hash === eventData.data.hash, + ); + + if (!currentTx) { + // This happens regularly when local transactions get cleared (e.g. user clears all txs or deploys new contract instance) + return; + } + + transactionsStore.updateTransaction(newTx); + } + + return { + init, + }; +} diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 3bc6aaa33..0daba34f9 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -4,7 +4,7 @@ import { createPinia } from 'pinia'; import Notifications from '@kyvg/vue3-notification'; import App from './App.vue'; import router from './router'; -import { persistStorePlugin, TransactionsListenerPlugin } from '@/plugins'; +import { persistStorePlugin } from '@/plugins'; import { VueSpinnersPlugin } from 'vue3-spinners'; import registerGlobalComponents from '@/components/global/registerGlobalComponents'; import { VueQueryPlugin } from '@tanstack/vue-query'; @@ -32,9 +32,6 @@ app.use(FloatingVue, { }); app.use(Notifications); app.use(VueSpinnersPlugin); -app.use(TransactionsListenerPlugin, { - interval: 5000, -}); const plausible = createPlausible({ init: { diff --git a/frontend/src/plugins/index.ts b/frontend/src/plugins/index.ts index fdadd23d4..cea2295b5 100644 --- a/frontend/src/plugins/index.ts +++ b/frontend/src/plugins/index.ts @@ -1,2 +1 @@ export * from './persistStore'; -export * from './transactionsListener'; diff --git a/frontend/src/plugins/transactionsListener.ts b/frontend/src/plugins/transactionsListener.ts deleted file mode 100644 index 5e829f74b..000000000 --- a/frontend/src/plugins/transactionsListener.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { useContractsStore, useTransactionsStore } from '@/stores'; -import type { TransactionItem } from '@/types'; -import type { App } from 'vue'; - -const ENABLE_LOGS = false; - -export const TransactionsListenerPlugin = { - install(_app: App, { interval = 5000 }: { interval: number }) { - const contractsStore = useContractsStore(); - const transactionsStore = useTransactionsStore(); - - const listener = async () => { - const pendingTxs = transactionsStore.transactions.filter( - (tx: TransactionItem) => - tx.status !== 'FINALIZED' && - transactionsStore.processingQueue.findIndex( - (q) => q.hash !== tx.hash, - ) === -1, - ) as TransactionItem[]; - - transactionsStore.processingQueue.push(...pendingTxs); - if (transactionsStore.processingQueue.length > 0) { - for (const item of transactionsStore.processingQueue) { - const tx = await transactionsStore.getTransaction(item.hash); - if (!tx) { - // Remove the transaction from the processing queue and storage if not found - transactionsStore.processingQueue = - transactionsStore.processingQueue.filter( - (t) => t.hash !== item.hash, - ); - transactionsStore.removeTransaction(item); - } else { - const currentTx = transactionsStore.processingQueue.find( - (t) => t.hash === tx?.hash, - ); - transactionsStore.updateTransaction(tx); - transactionsStore.processingQueue = - transactionsStore.processingQueue.filter( - (t) => t.hash !== tx?.hash, - ); - // if finalized and is contract add to the contract store dpeloyed - if (tx?.status === 'FINALIZED' && currentTx?.type === 'deploy') { - if (ENABLE_LOGS) { - console.log('New deployed contract', currentTx); - } - - contractsStore.addDeployedContract({ - contractId: currentTx.localContractId, - address: tx.data.contract_address, - defaultState: '{}', - }); - currentTx.data.contractAddress = tx.data.contractAddress; - } - } - } - - if (ENABLE_LOGS) { - console.log(`There are ${pendingTxs.length} pending transactions`); - } - } - }; - setInterval(listener, interval); - }, -}; diff --git a/frontend/src/stores/contracts.ts b/frontend/src/stores/contracts.ts index c4b4f1e42..2a5b0f4ae 100644 --- a/frontend/src/stores/contracts.ts +++ b/frontend/src/stores/contracts.ts @@ -111,6 +111,7 @@ export const useContractsStore = defineStore('contractsStore', () => { const index = deployedContracts.value.findIndex( (c) => c.contractId === contractId, ); + const newItem = { contractId, address, defaultState }; if (index === -1) { diff --git a/frontend/src/stores/node.ts b/frontend/src/stores/node.ts index 666e20de9..402b4e56e 100644 --- a/frontend/src/stores/node.ts +++ b/frontend/src/stores/node.ts @@ -42,13 +42,13 @@ export const useNodeStore = defineStore('nodeStore', () => { ]; trackedEvents.forEach((eventName) => { - webSocketClient.on(eventName, (data: any) => { + webSocketClient.on(eventName, (eventData: any) => { addLog({ - scope: data.scope, - name: data.name, - type: data.type, - message: data.message, - data: data.data, + scope: eventData.scope, + name: eventData.name, + type: eventData.type, + message: eventData.message, + data: eventData.data, }); }); }); diff --git a/frontend/src/stores/transactions.ts b/frontend/src/stores/transactions.ts index f8e462d4a..df72fb464 100644 --- a/frontend/src/stores/transactions.ts +++ b/frontend/src/stores/transactions.ts @@ -1,62 +1,113 @@ import { defineStore } from 'pinia'; -import { computed, ref } from 'vue'; +import { ref } from 'vue'; import type { TransactionItem } from '@/types'; -import { useRpcClient } from '@/hooks'; +import { useRpcClient, useWebSocketClient } from '@/hooks'; +import { useContractsStore } from '@/stores'; export const useTransactionsStore = defineStore('transactionsStore', () => { const rpcClient = useRpcClient(); - const pendingTransactions = computed(() => - transactions.value.filter((t) => t.status === 'PENDING'), - ); - const processingQueue = ref([]); + const webSocketClient = useWebSocketClient(); const transactions = ref([]); + const contractsStore = useContractsStore(); + const subscriptions = new Set(); function addTransaction(tx: TransactionItem) { transactions.value.unshift(tx); // Push on top in case there's no date property yet + subscribe([tx.hash]); } function removeTransaction(tx: TransactionItem) { transactions.value = transactions.value.filter((t) => t.hash !== tx.hash); + unsubscribe(tx.hash); } function updateTransaction(tx: any) { - const index = transactions.value.findIndex((t) => t.hash === tx.hash); - if (index !== -1) { - const current = transactions.value[index]; - transactions.value.splice(index, 1, { - ...current, + const currentTxIndex = transactions.value.findIndex( + (t) => t.hash === tx.hash, + ); + + if (currentTxIndex !== -1) { + const currentTx = transactions.value[currentTxIndex]; + + transactions.value.splice(currentTxIndex, 1, { + ...currentTx, status: tx.status, data: tx, }); + + if ( + currentTx.status === 'ACCEPTED' && + currentTx.type === 'deploy' && + tx.status === 'FINALIZED' + ) { + contractsStore.addDeployedContract({ + contractId: currentTx.localContractId, + address: tx.data.contract_address, + defaultState: '{}', + }); + } } else { // Temporary logging to debug always-PENDING transactions console.warn('Transaction not found', tx); - console.trace('updateTransaction', tx); // Temporary logging to debug always-PENDING transactions + console.trace('updateTransaction', tx); } } + async function refreshPendingTransactions() { + const pendingTxs = transactions.value.filter( + (tx: TransactionItem) => tx.status !== 'FINALIZED', + ) as TransactionItem[]; + + await Promise.all( + pendingTxs.map(async (tx) => { + const newTx = await getTransaction(tx.hash); + updateTransaction(newTx); + }), + ); + } + async function getTransaction(hash: string) { return rpcClient.getTransactionByHash(hash); } function clearTransactionsForContract(contractId: string) { - processingQueue.value = processingQueue.value.filter( - (t) => t.localContractId !== contractId, + const contractTxs = transactions.value.filter( + (t) => t.localContractId === contractId, ); + contractTxs.forEach((t) => unsubscribe(t.hash)); + transactions.value = transactions.value.filter( (t) => t.localContractId !== contractId, ); } + function subscribe(topics: string[]) { + subscriptions.add(topics); + if (webSocketClient.connected) { + webSocketClient.emit('subscribe', topics); + } + } + + function unsubscribe(topic: string) { + const deleted = subscriptions.delete(topic); + if (deleted && webSocketClient.connected) { + webSocketClient.emit('unsubscribe', [topic]); + } + } + + function initSubscriptions() { + subscribe(transactions.value.map((t) => t.hash)); + } + return { transactions, - pendingTransactions, - processingQueue, getTransaction, addTransaction, removeTransaction, updateTransaction, clearTransactionsForContract, + refreshPendingTransactions, + initSubscriptions, }; }); diff --git a/frontend/test/unit/hooks/useTransactionListener.test.ts b/frontend/test/unit/hooks/useTransactionListener.test.ts new file mode 100644 index 000000000..fa2a4f2fa --- /dev/null +++ b/frontend/test/unit/hooks/useTransactionListener.test.ts @@ -0,0 +1,92 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { useTransactionListener } from '@/hooks/useTransactionListener'; +import { useTransactionsStore } from '@/stores'; +import { useWebSocketClient } from '@/hooks'; + +vi.mock('@/stores', () => ({ + useTransactionsStore: vi.fn(), +})); + +vi.mock('@/hooks', () => ({ + useWebSocketClient: vi.fn(), +})); + +describe('useTransactionListener', () => { + let transactionsStoreMock: any; + let webSocketClientMock: any; + + beforeEach(() => { + transactionsStoreMock = { + getTransaction: vi.fn(), + removeTransaction: vi.fn(), + updateTransaction: vi.fn(), + transactions: [], + }; + + webSocketClientMock = { + on: vi.fn(), + }; + + (useTransactionsStore as any).mockReturnValue(transactionsStoreMock); + (useWebSocketClient as any).mockReturnValue(webSocketClientMock); + }); + + it('should initialize and set up websocket listener', () => { + const { init } = useTransactionListener(); + init(); + + expect(webSocketClientMock.on).toHaveBeenCalledWith( + 'transaction_status_updated', + expect.any(Function), + ); + }); + + it('should handle transaction status update correctly', async () => { + const { init } = useTransactionListener(); + init(); + + const handleTransactionStatusUpdate = + webSocketClientMock.on.mock.calls[0][1]; + + const eventData = { data: { hash: '123' } }; + const newTx = { hash: '123', status: 'confirmed' }; + transactionsStoreMock.getTransaction.mockResolvedValue(newTx); + transactionsStoreMock.transactions = [{ hash: '123', status: 'pending' }]; + + await handleTransactionStatusUpdate(eventData); + + expect(transactionsStoreMock.updateTransaction).toHaveBeenCalledWith(newTx); + }); + + it('should remove transaction if server tx not found', async () => { + const { init } = useTransactionListener(); + init(); + + const handleTransactionStatusUpdate = + webSocketClientMock.on.mock.calls[0][1]; + + const eventData = { data: { hash: '123' } }; + transactionsStoreMock.getTransaction.mockResolvedValue(null); + + await handleTransactionStatusUpdate(eventData); + + expect(transactionsStoreMock.removeTransaction).toHaveBeenCalledWith(null); + }); + + it('should do nothing if local transaction is not found', async () => { + const { init } = useTransactionListener(); + init(); + + const handleTransactionStatusUpdate = + webSocketClientMock.on.mock.calls[0][1]; + + const eventData = { data: { hash: '123' } }; + const newTx = { hash: '123', status: 'confirmed' }; + transactionsStoreMock.getTransaction.mockResolvedValue(newTx); + transactionsStoreMock.transactions = []; + + await handleTransactionStatusUpdate(eventData); + + expect(transactionsStoreMock.updateTransaction).not.toHaveBeenCalled(); + }); +}); diff --git a/frontend/test/unit/stores/transactions.test.ts b/frontend/test/unit/stores/transactions.test.ts index 2d4fc50df..8e043e26a 100644 --- a/frontend/test/unit/stores/transactions.test.ts +++ b/frontend/test/unit/stores/transactions.test.ts @@ -6,6 +6,21 @@ import { type TransactionItem } from '@/types'; vi.mock('@/hooks', () => ({ useRpcClient: vi.fn(), + useWebSocketClient: vi.fn(() => ({ + connected: true, + emit: vi.fn(), + })), + useDb: vi.fn(() => ({ + transaction: vi.fn(), + get: vi.fn(), + put: vi.fn(), + })), + useSetupStores: vi.fn(() => ({ + setupStores: vi.fn(), + })), + useFileName: vi.fn(() => ({ + cleanupFileName: vi.fn(), + })), })); const testTransaction: TransactionItem = { @@ -32,7 +47,6 @@ describe('useTransactionsStore', () => { (useRpcClient as Mock).mockReturnValue(mockRpcClient); transactionsStore = useTransactionsStore(); transactionsStore.transactions = []; - transactionsStore.processingQueue = []; mockRpcClient.getTransactionByHash.mockClear(); }); @@ -82,28 +96,29 @@ describe('useTransactionsStore', () => { transactionsStore.addTransaction(tx1); transactionsStore.addTransaction(tx2); - transactionsStore.processingQueue = [tx1]; - transactionsStore.clearTransactionsForContract('contract-1'); expect(transactionsStore.transactions).toEqual([tx2]); - expect(transactionsStore.processingQueue).toEqual([]); }); - it('should compute pending transactions', () => { - const tx1 = { - ...testTransaction, - hash: '0x1234567890123456789012345678901234567891', - status: 'FINALIZED', - }; - const tx2 = { + it('should refresh pending transactions', async () => { + const pendingTransaction = { ...testTransaction, - hash: '0x1234567890123456789012345678901234567892', status: 'PENDING', }; + const updatedTransaction = { + ...pendingTransaction, + status: 'FINALIZED', + }; + + transactionsStore.addTransaction(pendingTransaction); + mockRpcClient.getTransactionByHash.mockResolvedValue(updatedTransaction); - transactionsStore.transactions = [tx1, tx2]; + await transactionsStore.refreshPendingTransactions(); - expect(transactionsStore.pendingTransactions).toEqual([tx2]); + expect(mockRpcClient.getTransactionByHash).toHaveBeenCalledWith( + pendingTransaction.hash, + ); + expect(transactionsStore.transactions[0].status).toBe('FINALIZED'); }); }); diff --git a/sonar-project.properties b/sonar-project.properties index fc6f9ca7e..f16d422f5 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -4,5 +4,5 @@ sonar.projectKey=yeagerai_genlayer-simulator # relative paths to source directories. More details and properties are described # in https://sonarcloud.io/documentation/project-administration/narrowing-the-focus/ sonar.sources=. -sonar.exclusions=tests/**, +sonar.exclusions=tests/**,frontend/test/**/* sonar.python.coverage.reportPaths=coverage.xml diff --git a/tests/db-sqlalchemy/chain_snapshot_test.py b/tests/db-sqlalchemy/chain_snapshot_test.py index b3f855f2d..09cc9b4ee 100644 --- a/tests/db-sqlalchemy/chain_snapshot_test.py +++ b/tests/db-sqlalchemy/chain_snapshot_test.py @@ -23,7 +23,6 @@ def test_chain_snapshot(session: Session): s=None, v=None, leader_only=False, - client_session_id=None, triggered_by_hash=None, ) @@ -43,7 +42,6 @@ def test_chain_snapshot(session: Session): s=None, v=None, leader_only=False, - client_session_id=None, triggered_by_hash="0xdef", ) @@ -63,7 +61,6 @@ def test_chain_snapshot(session: Session): s=None, v=None, leader_only=False, - client_session_id=None, triggered_by_hash=None, )