11from __future__ import annotations
22
33from decimal import Decimal
4- from typing import TYPE_CHECKING
4+ from typing import TYPE_CHECKING , Optional
55
66from eth_utils import to_normalized_address
77from superfluid import CFA_V1 , Operation , Web3FlowInfo
88
99from aleph .sdk .exceptions import InsufficientFundsError
1010
11- from ..evm_utils import get_super_token_address , to_human_readable_token , to_wei_token
11+ from ..evm_utils import (
12+ FlowUpdate ,
13+ from_wei_token ,
14+ get_super_token_address ,
15+ to_wei_token ,
16+ )
1217
1318if TYPE_CHECKING :
1419 from aleph .sdk .chains .ethereum import ETHAccount
@@ -44,6 +49,7 @@ async def _execute_operation_with_account(self, operation: Operation) -> str:
4449 return await self .account ._sign_and_send_transaction (populated_transaction )
4550
4651 def can_start_flow (self , flow : Decimal , block = True ) -> bool :
52+ """Check if the account has enough funds to start a Superfluid flow of the given size."""
4753 valid = False
4854 if self .account .can_transact (block = block ):
4955 balance = self .account .get_super_token_balance ()
@@ -52,7 +58,7 @@ def can_start_flow(self, flow: Decimal, block=True) -> bool:
5258 if not valid and block :
5359 raise InsufficientFundsError (
5460 required_funds = float (MIN_FLOW_4H ),
55- available_funds = to_human_readable_token ( balance ),
61+ available_funds = float ( from_wei_token ( balance ) ),
5662 )
5763 return valid
5864
@@ -96,3 +102,51 @@ async def update_flow(self, receiver: str, flow: Decimal) -> str:
96102 flow_rate = int (to_wei_token (flow )),
97103 ),
98104 )
105+
106+ async def manage_flow (
107+ self ,
108+ receiver : str ,
109+ flow : Decimal ,
110+ update_type : FlowUpdate ,
111+ ) -> Optional [str ]:
112+ """
113+ Update the flow of a Superfluid stream between a sender and receiver.
114+ This function either increases or decreases the flow rate between the sender and receiver,
115+ based on the update_type. If no flow exists and the update type is augmentation, it creates a new flow
116+ with the specified rate. If the update type is reduction and the reduction amount brings the flow to zero
117+ or below, the flow is deleted.
118+
119+ :param receiver: Address of the receiver in hexadecimal format.
120+ :param flow: The flow rate to be added or removed (in ether).
121+ :param update_type: The type of update to perform (augmentation or reduction).
122+ :return: The transaction hash of the executed operation (create, update, or delete flow).
123+ """
124+
125+ # Retrieve current flow info
126+ flow_info : Web3FlowInfo = await self .account .get_flow (receiver )
127+
128+ current_flow_rate_wei : Decimal = Decimal (flow_info ["flowRate" ] or "0" )
129+ flow_rate_wei : int = int (to_wei_token (flow ))
130+
131+ if update_type == FlowUpdate .INCREASE :
132+ if current_flow_rate_wei > 0 :
133+ # Update existing flow by increasing the rate
134+ new_flow_rate_wei = current_flow_rate_wei + flow_rate_wei
135+ new_flow_rate_ether = from_wei_token (new_flow_rate_wei )
136+ return await self .account .update_flow (receiver , new_flow_rate_ether )
137+ else :
138+ # Create a new flow if none exists
139+ return await self .account .create_flow (receiver , flow )
140+ else :
141+ if current_flow_rate_wei > 0 :
142+ # Reduce the existing flow
143+ new_flow_rate_wei = current_flow_rate_wei - flow_rate_wei
144+ # Ensure to not leave infinitesimal flows
145+ # Often, there were 1-10 wei remaining in the flow rate, which prevented the flow from being deleted
146+ if new_flow_rate_wei > 99 :
147+ new_flow_rate_ether = from_wei_token (new_flow_rate_wei )
148+ return await self .account .update_flow (receiver , new_flow_rate_ether )
149+ else :
150+ # Delete the flow if the new flow rate is zero or negative
151+ return await self .account .delete_flow (receiver )
152+ return None
0 commit comments