Skip to content

Commit

Permalink
Add token_type to InsufficientFundsError + displayable_amount()
Browse files Browse the repository at this point in the history
  • Loading branch information
philogicae committed Feb 6, 2025
1 parent 84e6a80 commit 30190e6
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 17 deletions.
2 changes: 2 additions & 0 deletions src/aleph/sdk/chains/ethereum.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from web3.types import TxParams, TxReceipt

from aleph.sdk.exceptions import InsufficientFundsError
from aleph.sdk.types import TokenType

from ..conf import settings
from ..connectors.superfluid import Superfluid
Expand Down Expand Up @@ -107,6 +108,7 @@ def can_transact(self, block=True) -> bool:
valid = balance > MIN_ETH_BALANCE_WEI if self.chain else False
if not valid and block:
raise InsufficientFundsError(
token_type=TokenType.GAS,
required_funds=MIN_ETH_BALANCE,
available_funds=float(from_wei_token(balance)),
)
Expand Down
6 changes: 4 additions & 2 deletions src/aleph/sdk/client/authenticated_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

from ..conf import settings
from ..exceptions import BroadcastError, InsufficientFundsError, InvalidMessageError
from ..types import Account, StorageEnum
from ..types import Account, StorageEnum, TokenType
from ..utils import extended_json_encoder, make_instance_content, parse_volume
from .abstract import AuthenticatedAlephClient
from .http import AlephHttpClient
Expand Down Expand Up @@ -569,7 +569,9 @@ async def create_instance(
account_balance = float(error["account_balance"])
required_balance = float(error["required_balance"])
raise InsufficientFundsError(
required_funds=required_balance, available_funds=account_balance
token_type=TokenType.ALEPH,
required_funds=required_balance,
available_funds=account_balance,
)
else:
raise ValueError(f"Unknown error code {error_code}: {rejected_message}")
Expand Down
7 changes: 4 additions & 3 deletions src/aleph/sdk/connectors/superfluid.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
from eth_utils import to_normalized_address
from superfluid import CFA_V1, Operation, Web3FlowInfo

from aleph.sdk.exceptions import InsufficientFundsError

from ..evm_utils import (
from aleph.sdk.evm_utils import (
FlowUpdate,
from_wei_token,
get_super_token_address,
to_wei_token,
)
from aleph.sdk.exceptions import InsufficientFundsError
from aleph.sdk.types import TokenType

if TYPE_CHECKING:
from aleph.sdk.chains.ethereum import ETHAccount
Expand Down Expand Up @@ -57,6 +57,7 @@ def can_start_flow(self, flow: Decimal, block=True) -> bool:
valid = balance > MIN_FLOW_4H
if not valid and block:
raise InsufficientFundsError(
token_type=TokenType.ALEPH,
required_funds=float(MIN_FLOW_4H),
available_funds=float(from_wei_token(balance)),
)
Expand Down
2 changes: 1 addition & 1 deletion src/aleph/sdk/evm_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def to_wei_token(amount: Decimal) -> Decimal:

def ether_rounding(amount: Decimal) -> Decimal:
"""Rounds the given value to 18 decimals."""
return amount.quantize(Decimal(1) / 10**18, rounding=ROUND_CEILING)
return amount.quantize(Decimal(1) / Decimal(10**18), rounding=ROUND_CEILING)


def get_chain_id(chain: Union[Chain, str, None]) -> Optional[int]:
Expand Down
15 changes: 11 additions & 4 deletions src/aleph/sdk/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from abc import ABC

from .types import TokenType
from .utils import displayable_amount


class QueryError(ABC, ValueError):
"""The result of an API query is inconsistent."""
Expand Down Expand Up @@ -69,14 +72,18 @@ class ForgottenMessageError(QueryError):
class InsufficientFundsError(Exception):
"""Raised when the account does not have enough funds to perform an action"""

token_type: TokenType
required_funds: float
available_funds: float

def __init__(self, required_funds: float, available_funds: float):
self.required_funds = required_funds
self.available_funds = available_funds
def __init__(
self, token_type: TokenType, required_funds: float, available_funds: float
):
self.token_type = token_type
self.required_funds = displayable_amount(required_funds, decimals=8)
self.available_funds = displayable_amount(available_funds, decimals=8)
super().__init__(
f"Insufficient funds: required {required_funds}, available {available_funds}"
f"Insufficient funds ({self.token_type.value}): required {self.required_funds}, available {self.available_funds}"
)


Expand Down
13 changes: 13 additions & 0 deletions src/aleph/sdk/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,20 @@ class ChainInfo(BaseModel):


class StoredContent(BaseModel):
"""
A stored content.
"""

filename: Optional[str]
hash: Optional[str]
url: Optional[str]
error: Optional[str]


class TokenType(str, Enum):
"""
A token type.
"""

GAS = "GAS"
ALEPH = "ALEPH"
25 changes: 18 additions & 7 deletions src/aleph/sdk/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os
import subprocess
from datetime import date, datetime, time
from decimal import ROUND_CEILING, Decimal
from enum import Enum
from pathlib import Path
from shutil import make_archive
Expand All @@ -28,13 +29,7 @@
from uuid import UUID
from zipfile import BadZipFile, ZipFile

from aleph_message.models import (
Chain,
InstanceContent,
ItemHash,
MessageType,
ProgramContent,
)
from aleph_message.models import Chain, InstanceContent, ItemHash, MessageType
from aleph_message.models.execution.base import Payment, PaymentType
from aleph_message.models.execution.environment import (
HostRequirements,
Expand Down Expand Up @@ -418,6 +413,22 @@ def safe_getattr(obj, attr, default=None):
return obj


def displayable_amount(
amount: str | int | float | Decimal, decimals: Optional[int] = None
) -> str:
"""Returns the amount as a string without unnecessary decimals."""

str_amount = ""
try:
dec_amount = Decimal(amount)
if decimals:
dec_amount = dec_amount.quantize(Decimal(1) / Decimal(10**decimals))
str_amount = str(format(dec_amount.normalize(), "f"))
except ValueError as e:
raise ValueError(f"Invalid amount: {amount}") from e
return str_amount


def make_instance_content(
rootfs: str,
rootfs_size: int,
Expand Down

0 comments on commit 30190e6

Please sign in to comment.