Skip to content

Commit

Permalink
Merge branch 'main' into 177-upgrade-pydantic-version
Browse files Browse the repository at this point in the history
  • Loading branch information
Antonyjin authored Nov 26, 2024
2 parents 00177ae + a1c7313 commit 5028e86
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-12, macos-13, macos-14, ubuntu-22.04, ubuntu-24.04]
os: [macos-13, macos-14, ubuntu-22.04, ubuntu-24.04]
runs-on: ${{ matrix.os }}

steps:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ MANIFEST

# Per-project virtualenvs
.venv*/
venv/*
**/device.key

# environment variables
Expand Down
46 changes: 35 additions & 11 deletions src/aleph/sdk/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

from aleph.sdk.chains.common import get_fallback_private_key
from aleph.sdk.chains.ethereum import ETHAccount
from aleph.sdk.chains.evm import EVMAccount
from aleph.sdk.chains.remote import RemoteAccount
from aleph.sdk.chains.solana import SOLAccount
from aleph.sdk.chains.substrate import DOTAccount
from aleph.sdk.conf import load_main_configuration, settings
from aleph.sdk.evm_utils import get_chains_with_super_token
from aleph.sdk.types import AccountFromPrivateKey
Expand All @@ -18,10 +20,24 @@
T = TypeVar("T", bound=AccountFromPrivateKey)

chain_account_map: Dict[Chain, Type[T]] = { # type: ignore
Chain.ETH: ETHAccount,
Chain.ARBITRUM: EVMAccount,
Chain.AVAX: ETHAccount,
Chain.BASE: ETHAccount,
Chain.BLAST: EVMAccount,
Chain.BOB: EVMAccount,
Chain.CYBER: EVMAccount,
Chain.DOT: DOTAccount,
Chain.ETH: ETHAccount,
Chain.FRAXTAL: EVMAccount,
Chain.LINEA: EVMAccount,
Chain.LISK: EVMAccount,
Chain.METIS: EVMAccount,
Chain.MODE: EVMAccount,
Chain.OPTIMISM: EVMAccount,
Chain.POL: EVMAccount,
Chain.SOL: SOLAccount,
Chain.WORLDCHAIN: EVMAccount,
Chain.ZORA: EVMAccount,
}


Expand All @@ -43,7 +59,7 @@ def account_from_hex_string(
return account_type(bytes.fromhex(private_key_str)) # type: ignore

account_type = load_chain_account_type(chain)
account = account_type(bytes.fromhex(private_key_str))
account = account_type(bytes.fromhex(private_key_str), chain)
if chain in get_chains_with_super_token():
account.switch_chain(chain)
return account # type: ignore
Expand All @@ -62,7 +78,7 @@ def account_from_file(
return account_type(private_key) # type: ignore

account_type = load_chain_account_type(chain)
account = account_type(private_key)
account = account_type(private_key, chain)
if chain in get_chains_with_super_token():
account.switch_chain(chain)
return account
Expand All @@ -76,21 +92,29 @@ def _load_account(
) -> AccountFromPrivateKey:
"""Load an account from a private key string or file, or from the configuration file."""

# Loads configuration if no account_type is specified
if not account_type:
config = load_main_configuration(settings.CONFIG_FILE)
config = load_main_configuration(settings.CONFIG_FILE)
default_chain = settings.DEFAULT_CHAIN

if not chain:
if config and hasattr(config, "chain"):
account_type = load_chain_account_type(config.chain)
chain = config.chain
logger.debug(
f"Detected {config.chain} account for path {settings.CONFIG_FILE}"
)
else:
account_type = account_type = load_chain_account_type(
Chain.ETH
) # Defaults to ETHAccount
chain = default_chain
logger.warning(
f"No main configuration data found in {settings.CONFIG_FILE}, defaulting to {account_type and account_type.__name__}"
f"No main configuration found on path {settings.CONFIG_FILE}, defaulting to {chain}"
)
else:
chain = default_chain

# Loads configuration if no account_type is specified
if not account_type:
account_type = load_chain_account_type(chain)
logger.debug(
f"No account type specified defaulting to {account_type and account_type.__name__}"
)

# Loads private key from a string
if private_key_str:
Expand Down
48 changes: 48 additions & 0 deletions src/aleph/sdk/chains/evm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from decimal import Decimal
from pathlib import Path
from typing import Awaitable, Optional

from aleph_message.models import Chain
from eth_account import Account # type: ignore

from .common import get_fallback_private_key
from .ethereum import ETHAccount


class EVMAccount(ETHAccount):
def __init__(self, private_key: bytes, chain: Optional[Chain] = None):
super().__init__(private_key, chain)
# Decide if we have to send also the specified chain value or always use ETH
# if chain:
# self.CHAIN = chain

@staticmethod
def from_mnemonic(mnemonic: str, chain: Optional[Chain] = None) -> "EVMAccount":
Account.enable_unaudited_hdwallet_features()
return EVMAccount(
private_key=Account.from_mnemonic(mnemonic=mnemonic).key, chain=chain
)

def get_token_balance(self) -> Decimal:
raise ValueError(f"Token not implemented for this chain {self.CHAIN}")

def get_super_token_balance(self) -> Decimal:
raise ValueError(f"Super token not implemented for this chain {self.CHAIN}")

def create_flow(self, receiver: str, flow: Decimal) -> Awaitable[str]:
raise ValueError(f"Flow creation not implemented for this chain {self.CHAIN}")

def get_flow(self, receiver: str):
raise ValueError(f"Get flow not implemented for this chain {self.CHAIN}")

def update_flow(self, receiver: str, flow: Decimal) -> Awaitable[str]:
raise ValueError(f"Flow update not implemented for this chain {self.CHAIN}")

def delete_flow(self, receiver: str) -> Awaitable[str]:
raise ValueError(f"Flow deletion not implemented for this chain {self.CHAIN}")


def get_fallback_account(
path: Optional[Path] = None, chain: Optional[Chain] = None
) -> ETHAccount:
return ETHAccount(private_key=get_fallback_private_key(path=path), chain=chain)
62 changes: 58 additions & 4 deletions src/aleph/sdk/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,9 @@ class Settings(BaseSettings):
active=False,
),
# MAINNETS
Chain.ETH: ChainInfo(
chain_id=1,
rpc="https://eth-mainnet.public.blastapi.io",
token="0x27702a26126e0B3702af63Ee09aC4d1A084EF628",
Chain.ARBITRUM: ChainInfo(
chain_id=42161,
rpc="https://arbitrum-one.publicnode.com",
),
Chain.AVAX: ChainInfo(
chain_id=43114,
Expand All @@ -117,12 +116,65 @@ class Settings(BaseSettings):
token="0xc0Fbc4967259786C743361a5885ef49380473dCF",
super_token="0xc0Fbc4967259786C743361a5885ef49380473dCF",
),
Chain.BLAST: ChainInfo(
chain_id=81457,
rpc="https://blastl2-mainnet.public.blastapi.io",
),
Chain.BOB: ChainInfo(
chain_id=60808,
rpc="https://bob-mainnet.public.blastapi.io",
),
Chain.BSC: ChainInfo(
chain_id=56,
rpc="https://binance.llamarpc.com",
token="0x82D2f8E02Afb160Dd5A480a617692e62de9038C4",
active=False,
),
Chain.CYBER: ChainInfo(
chain_id=7560,
rpc="https://rpc.cyber.co",
),
Chain.ETH: ChainInfo(
chain_id=1,
rpc="https://eth-mainnet.public.blastapi.io",
token="0x27702a26126e0B3702af63Ee09aC4d1A084EF628",
),
Chain.FRAXTAL: ChainInfo(
chain_id=252,
rpc="https://rpc.frax.com",
),
Chain.LINEA: ChainInfo(
chain_id=59144,
rpc="https://linea-rpc.publicnode.com",
),
Chain.LISK: ChainInfo(
chain_id=1135,
rpc="https://rpc.api.lisk.com",
),
Chain.METIS: ChainInfo(
chain_id=1088,
rpc="https://metis.drpc.org",
),
Chain.MODE: ChainInfo(
chain_id=34443,
rpc="https://mode.drpc.org",
),
Chain.OPTIMISM: ChainInfo(
chain_id=10,
rpc="https://optimism-rpc.publicnode.com",
),
Chain.POL: ChainInfo(
chain_id=137,
rpc="https://polygon.gateway.tenderly.co",
),
Chain.WORLDCHAIN: ChainInfo(
chain_id=480,
rpc="https://worldchain-mainnet.gateway.tenderly.co",
),
Chain.ZORA: ChainInfo(
chain_id=7777777,
rpc="https://rpc.zora.energy/",
),
}
# Add all placeholders to allow easy dynamic setup of CHAINS
CHAINS_SEPOLIA_ACTIVE: Optional[bool] = None
Expand All @@ -136,6 +188,8 @@ class Settings(BaseSettings):
CHAINS_BASE_RPC: Optional[str] = None
CHAINS_BSC_RPC: Optional[str] = None

DEFAULT_CHAIN: Chain = Chain.ETH

# Dns resolver
DNS_IPFS_DOMAIN: ClassVar[str] = "ipfs.public.aleph.sh"
DNS_PROGRAM_DOMAIN: ClassVar[str] = "program.public.aleph.sh"
Expand Down
8 changes: 7 additions & 1 deletion src/aleph/sdk/evm_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,16 @@ def get_super_token_address(
return None


def get_chains_with_holding() -> List[Union[Chain, str]]:
def get_compatible_chains() -> List[Union[Chain, str]]:
return [chain for chain, info in settings.CHAINS.items() if info.active]


def get_chains_with_holding() -> List[Union[Chain, str]]:
return [
chain for chain, info in settings.CHAINS.items() if info.active and info.token
]


def get_chains_with_super_token() -> List[Union[Chain, str]]:
return [
chain
Expand Down
6 changes: 3 additions & 3 deletions src/aleph/sdk/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

__all__ = ("StorageEnum", "Account", "AccountFromPrivateKey", "GenericMessage")

from aleph_message.models import AlephMessage
from aleph_message.models import AlephMessage, Chain


class StorageEnum(str, Enum):
Expand Down Expand Up @@ -35,7 +35,7 @@ def get_public_key(self) -> str: ...
class AccountFromPrivateKey(Account, Protocol):
"""Only accounts that are initialized from a private key string are supported."""

def __init__(self, private_key: bytes): ...
def __init__(self, private_key: bytes, chain: Chain): ...

async def sign_raw(self, buffer: bytes) -> bytes: ...

Expand Down Expand Up @@ -77,6 +77,6 @@ class ChainInfo(BaseModel):

chain_id: int
rpc: str
token: str
token: Optional[str] = None
super_token: Optional[str] = None
active: bool = True

0 comments on commit 5028e86

Please sign in to comment.