-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement blockchain transaction handling system
- Loading branch information
1 parent
6a09c1a
commit c85db20
Showing
6 changed files
with
737 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
from dataclasses import dataclass | ||
from enum import Enum | ||
|
||
|
||
class BlockchainTransactionEvent(Enum): | ||
""" | ||
Enumeration of possible blockchain transaction events. | ||
Each event represents a specific state or transition in the transaction lifecycle: | ||
- TransactionRejected (901): Transaction was rejected by the network | ||
- TransactionBroadcasted (902): Transaction was successfully broadcast to the network | ||
- TransactionConfirmed (903): Transaction was confirmed in a block | ||
- TransactionFinalized (904): Transaction is considered final (enough confirmations) | ||
- TransactionFailed (905): Transaction execution failed | ||
- TransactionCancelled (906): Transaction was cancelled by the user | ||
""" | ||
|
||
TransactionRejected = 901 | ||
TransactionBroadcasted = 902 | ||
TransactionConfirmed = 903 | ||
TransactionFinalized = 904 | ||
TransactionFailed = 905 | ||
TransactionCancelled = 906 | ||
|
||
|
||
@dataclass | ||
class TransactionEvent: | ||
""" | ||
Base class for all transaction events. | ||
Attributes: | ||
timestamp (float): Unix timestamp when the event occurred | ||
client_operation_id (str): Unique identifier for the transaction operation | ||
""" | ||
|
||
timestamp: float | ||
client_operation_id: str | ||
|
||
|
||
@dataclass | ||
class TransactionBroadcastedEvent(TransactionEvent): | ||
"""Event emitted when a transaction is successfully broadcast to the blockchain network.""" | ||
|
||
pass | ||
|
||
|
||
@dataclass | ||
class TransactionConfirmedEvent(TransactionEvent): | ||
"""Event emitted when a transaction is confirmed in a block on the blockchain.""" | ||
|
||
pass | ||
|
||
|
||
@dataclass | ||
class TransactionFinalizedEvent(TransactionEvent): | ||
"""Event emitted when a transaction has received enough confirmations to be considered final.""" | ||
|
||
pass | ||
|
||
|
||
@dataclass | ||
class TransactionFailedEvent(TransactionEvent): | ||
"""Event emitted when a transaction execution fails on the blockchain.""" | ||
|
||
pass | ||
|
||
|
||
@dataclass | ||
class TransactionRejectedEvent(TransactionEvent): | ||
"""Event emitted when a transaction is rejected by the blockchain network.""" | ||
|
||
pass | ||
|
||
|
||
@dataclass | ||
class TransactionCancelledEvent(TransactionEvent): | ||
"""Event emitted when a transaction is cancelled by the user before execution.""" | ||
|
||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
from enum import Enum | ||
from typing import Any | ||
|
||
from pydantic import BaseModel, ConfigDict, Field | ||
|
||
from financepype.assets.blockchain import BlockchainAsset | ||
from financepype.operations.fees import FeeImpactType, FeeType, OperationFee | ||
from financepype.operators.blockchains.identifier import BlockchainIdentifier | ||
|
||
|
||
class BlockchainTransactionState(Enum): | ||
""" | ||
Enumeration of possible blockchain transaction states. | ||
States represent the current status of a transaction in its lifecycle: | ||
- PENDING_BROADCAST: Transaction created but not yet sent to the network | ||
- BROADCASTED: Transaction sent to the network, awaiting confirmation | ||
- CONFIRMED: Transaction included in a block and confirmed | ||
- FINALIZED: Transaction has enough confirmations to be considered immutable | ||
- FAILED: Transaction execution failed on the blockchain | ||
- REJECTED: Transaction rejected during simulation or by network | ||
- CANCELLED: Transaction cancelled by the user before execution | ||
""" | ||
|
||
PENDING_BROADCAST = "pending" # Not processed by a provider | ||
BROADCASTED = "broadcasted" # Sent to a provider, but not confirmed yet | ||
CONFIRMED = "completed" # Confirmed on the blockchain | ||
FINALIZED = "finalized" # Confirmed and unchangeable on the blockchain | ||
FAILED = "failed" # Processed by a provider, but failed | ||
REJECTED = "rejected" # Rejected in the simulation or by a provider | ||
CANCELLED = "cancelled" # Cancelled by the user | ||
|
||
|
||
class BlockchainTransactionFee(OperationFee): | ||
""" | ||
Represents the fee structure for a blockchain transaction. | ||
Attributes: | ||
asset (BlockchainAsset | None): The asset in which the fee is paid | ||
fee_type (FeeType): Type of fee (always ABSOLUTE) | ||
impact_type (FeeImpactType): How the fee impacts the transaction cost (always ADDED_TO_COSTS) | ||
""" | ||
|
||
asset: BlockchainAsset | None = None | ||
fee_type: FeeType = Field(default=FeeType.ABSOLUTE, init=False) | ||
impact_type: FeeImpactType = Field(default=FeeImpactType.ADDED_TO_COSTS, init=False) | ||
|
||
|
||
class BlockchainTransactionReceipt(BaseModel): | ||
""" | ||
Immutable receipt of a processed blockchain transaction. | ||
Attributes: | ||
transaction_id (BlockchainIdentifier): Unique identifier of the transaction | ||
data (Any): Additional transaction-specific data from the blockchain | ||
""" | ||
|
||
model_config = ConfigDict(frozen=True) | ||
|
||
transaction_id: BlockchainIdentifier | ||
data: Any | ||
|
||
|
||
class BlockchainTransactionUpdate(BaseModel): | ||
""" | ||
Represents an update to a blockchain transaction's status. | ||
Attributes: | ||
update_timestamp (float): Unix timestamp of when the update occurred | ||
client_transaction_id (str): Client-side identifier for the transaction | ||
transaction_id (BlockchainIdentifier): Blockchain-specific transaction identifier | ||
new_state (BlockchainTransactionState): Updated state of the transaction | ||
receipt (BlockchainTransactionReceipt | None): Transaction receipt if available | ||
explorer_link (str | None): URL to view transaction in blockchain explorer | ||
other_data (dict[str, Any]): Additional transaction-specific data | ||
""" | ||
|
||
update_timestamp: float | ||
client_transaction_id: str | ||
transaction_id: BlockchainIdentifier | ||
new_state: BlockchainTransactionState | ||
receipt: BlockchainTransactionReceipt | None = None | ||
explorer_link: str | None = None | ||
other_data: dict[str, Any] = Field(default_factory=dict) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
from abc import abstractmethod | ||
from collections.abc import Callable | ||
from typing import Any | ||
|
||
from financepype.operations.proposal import OperationProposal | ||
from financepype.operations.transactions.transaction import BlockchainTransaction | ||
from financepype.owners.owner_id import OwnerIdentifier | ||
|
||
|
||
class TransactionProposal(OperationProposal): | ||
""" | ||
A proposal for executing a blockchain transaction. | ||
This class represents a proposed blockchain transaction that can be executed | ||
through a specific wallet. It encapsulates all the necessary information | ||
and validation logic required to execute the transaction. | ||
Attributes: | ||
owner_identifier (OwnerIdentifier): The wallet that will execute the transaction | ||
executed_operation (BlockchainTransaction): The executed transaction (after execution) | ||
""" | ||
|
||
owner_identifier: OwnerIdentifier | ||
executed_operation: BlockchainTransaction | None = None | ||
|
||
# === Properties === | ||
|
||
@property | ||
def can_be_executed(self) -> bool: | ||
""" | ||
Indicates whether the proposal is ready to be executed. | ||
Returns: | ||
bool: Always True for transaction proposals | ||
""" | ||
return True | ||
|
||
@property | ||
@abstractmethod | ||
def execute_function(self) -> Callable[[], BlockchainTransaction]: | ||
""" | ||
The function that will be called to execute the transaction. | ||
Returns: | ||
Callable[[], BlockchainTransaction]: A function that creates and executes the transaction | ||
""" | ||
raise NotImplementedError | ||
|
||
@property | ||
@abstractmethod | ||
def execute_kwargs(self) -> dict[str, Any]: | ||
""" | ||
The keyword arguments to pass to the execute function. | ||
Returns: | ||
dict[str, Any]: Dictionary of arguments needed to execute the transaction | ||
""" | ||
raise NotImplementedError | ||
|
||
# === Execution === | ||
|
||
def execute(self) -> BlockchainTransaction: | ||
""" | ||
Executes the proposed transaction. | ||
This method creates and executes a blockchain transaction using the | ||
specified wallet and execution parameters. | ||
Returns: | ||
BlockchainTransaction: The executed transaction | ||
Raises: | ||
ValueError: If the proposal has already been executed or cannot be executed | ||
""" | ||
if self.executed: | ||
raise ValueError("Proposal already executed.") | ||
|
||
if not self.can_be_executed: | ||
raise ValueError("Proposal not prepared to be executed.") | ||
|
||
self.executed_operation = self.execute_function(**self.execute_kwargs) | ||
return self.executed_operation |
Oops, something went wrong.