mirror of
https://github.com/status-im/status-python-sdk.git
synced 2026-08-30 21:51:14 +00:00
wallet: Account balance
- Related to https://github.com/status-im/status-bot/issues/16 - Get account balance - Convert account balance into fiat currency - Make properties private
This commit is contained in:
+73
-11
@@ -56,7 +56,7 @@ class Account:
|
||||
# All tokens in Status Backend
|
||||
self.__http_base_url = f"http{'s' if is_secure else ''}://{domain}:{port}/statusgo/"
|
||||
self.__ws_base_url = f"ws://{domain}:{port}/"
|
||||
self.urls = {
|
||||
self.__urls = {
|
||||
"http": {
|
||||
"initialize": f"{self.__http_base_url}InitializeApplication",
|
||||
"login": f"{self.__http_base_url}LoginAccount",
|
||||
@@ -71,7 +71,7 @@ class Account:
|
||||
"signals": f"{self.__ws_base_url}signals"
|
||||
}
|
||||
}
|
||||
self.__signal = Signal(self.urls["socket"]["signals"])
|
||||
self.__signal = Signal(self.__urls["socket"]["signals"])
|
||||
# Initialize profile
|
||||
self.available_accounts
|
||||
# In case if there is a hanging logged in session
|
||||
@@ -147,12 +147,14 @@ class Account:
|
||||
# Wallet usage
|
||||
if infura_token:
|
||||
params["infuraToken"] = infura_token
|
||||
self.__is_wallet_set = True
|
||||
|
||||
if coingecko_api_key:
|
||||
params["coingeckoApiKey"] = coingecko_api_key
|
||||
|
||||
url = self.urls["http"][url_key]
|
||||
if infura_token and coingecko_api_key:
|
||||
self.__is_wallet_set = True
|
||||
|
||||
url = self.__urls["http"][url_key]
|
||||
response = requests.post(url, json=params)
|
||||
signal_event = self.__signal.get("node.login")
|
||||
if signal_event["is_error"]:
|
||||
@@ -188,7 +190,7 @@ class Account:
|
||||
"""
|
||||
Logout of Status app. In a way this method behaves as a Status cleaner
|
||||
"""
|
||||
response = requests.post(self.urls["http"]["logout"])
|
||||
response = requests.post(self.__urls["http"]["logout"])
|
||||
self.__info = {}
|
||||
self.__is_messenger_launched = False
|
||||
self.__is_wallet_set = False
|
||||
@@ -203,7 +205,7 @@ class Account:
|
||||
"""
|
||||
All locally available accounts
|
||||
"""
|
||||
response = requests.post(self.urls["http"]["initialize"], json={
|
||||
response = requests.post(self.__urls["http"]["initialize"], json={
|
||||
"dataDir": self.__docker_data_folder
|
||||
})
|
||||
data: dict = response.json()
|
||||
@@ -432,6 +434,67 @@ class Account:
|
||||
self.__chains = {chain[key]["chainId"]: chain[key]["chainName"] for chain in result if chain.get(key)}
|
||||
return self.__chains
|
||||
|
||||
@property
|
||||
def balance(self) -> pd.DataFrame:
|
||||
"""
|
||||
Get the account's balance
|
||||
"""
|
||||
empty = pd.DataFrame(columns=["timestamp", "address", "chain_id", "amount", "symbol"])
|
||||
|
||||
params = [[self.info["wallet_address"]], True]
|
||||
results = self.__call_rpc("wallets", "fetchOrGetCachedWalletBalances", params).get("result", {}).get(self.info["wallet_address"].lower(), [])
|
||||
if not results:
|
||||
return empty.copy()
|
||||
|
||||
balance = pd.DataFrame(results)
|
||||
column_mapping = {"tokenAddress": "address", "tokenChainId": "chain_id", "balance": "amount", "hasError": "error"}
|
||||
balance = balance.rename(columns=column_mapping)[list(column_mapping.values())]\
|
||||
.astype({"chain_id": "int8", "amount": "float64"})
|
||||
|
||||
query = (balance["amount"] != 0) & (~balance["error"])
|
||||
if query.sum() == 0:
|
||||
return empty.copy()
|
||||
|
||||
redundant_columns = ["error", "decimals", "cross_chain_id", "source_id"]
|
||||
available_tokens = self.get_tokens()
|
||||
balance = balance.loc[query].merge(available_tokens, "left", ["address", "chain_id"])\
|
||||
.drop(redundant_columns, axis=1)\
|
||||
.drop_duplicates()\
|
||||
.sort_values("chain_id", ascending=True)\
|
||||
.reset_index(drop=True)\
|
||||
|
||||
balance.insert(0, "timestamp", datetime.datetime.now())
|
||||
return balance.copy()
|
||||
|
||||
def __getitem__(self, key: str) -> pd.DataFrame:
|
||||
"""
|
||||
Get the fiat currency balance
|
||||
"""
|
||||
ccy = key.upper()
|
||||
|
||||
if ccy not in self.__get_fiat_ccy():
|
||||
raise Exception(f"{ccy} is an invalid fiat (ISO 4217) currency code...")
|
||||
|
||||
balance = self.balance
|
||||
tokens = (balance["chain_id"].astype(str) + "-" + balance["address"]).to_list()
|
||||
|
||||
result = self.__call_rpc("wallets", "fetchPrices", [tokens, [ccy]]).get("result", {})
|
||||
if not result:
|
||||
return pd.DataFrame()
|
||||
rates = pd.DataFrame([
|
||||
{
|
||||
"chain_id": int(address.split("-")[0]),
|
||||
"address": address.split("-")[1],
|
||||
"rate": price,
|
||||
"ccy": ccy,
|
||||
}
|
||||
for address, prices in result.items()
|
||||
for ccy, price in prices.items()
|
||||
])
|
||||
balance = balance.merge(rates, "left", ["chain_id", "address"])
|
||||
balance["fiat_value"] = balance["amount"] * balance["rate"]
|
||||
return balance.copy()
|
||||
|
||||
def send_message(self, chat_id: str, message: str):
|
||||
"""
|
||||
Send a message to the given chat.
|
||||
@@ -597,7 +660,7 @@ class Account:
|
||||
- the Docker backup path (linked to a volume). The file name is unique per account.
|
||||
"""
|
||||
self.info
|
||||
response = requests.post(self.urls["http"]["create_backup"])
|
||||
response = requests.post(self.__urls["http"]["create_backup"])
|
||||
result: dict = response.json()
|
||||
file_path = result.get("filePath")
|
||||
|
||||
@@ -637,7 +700,6 @@ class Account:
|
||||
|
||||
return self.__available_tokens.copy()
|
||||
|
||||
|
||||
def get_balance(self, token_addresses: Union[list[str], str], chain_ids: Union[list[int], int] = 1, wallets: Optional[Union[list[str], str]] = None, ccy: Optional[Union[str, list[str]]] = None) -> pd.DataFrame:
|
||||
"""
|
||||
Get the current amount for the provided token addresses, chain IDs and wallets.
|
||||
@@ -841,7 +903,7 @@ class Account:
|
||||
"filePath": os.path.join(self.__docker_backup_folder, file_name)
|
||||
}
|
||||
self.logger.info(f"Trying to load {file_name}")
|
||||
response = requests.post(self.urls["http"]["load_backup"], json=params)
|
||||
response = requests.post(self.__urls["http"]["load_backup"], json=params)
|
||||
error: str = response.json().get("error", "")
|
||||
if len(error) == 0:
|
||||
self.__signal.get("messages.new")
|
||||
@@ -870,7 +932,7 @@ class Account:
|
||||
raise ValueError(f"Name {name} does not exist... Available options: {list(self.__prefix_mapping.keys())}")
|
||||
|
||||
if name == "wallet" and not self.__is_wallet_set:
|
||||
raise Exception(f"Cannot use this method without setting an `infura_token` when calling `login`.")
|
||||
raise Exception(f"Cannot use this method without setting an `infura_token` and `coingecko_api_key` when calling `login`.")
|
||||
|
||||
data = {
|
||||
'jsonrpc': '2.0',
|
||||
@@ -881,7 +943,7 @@ class Account:
|
||||
if params:
|
||||
data["params"] = params
|
||||
|
||||
response = requests.get(self.urls["http"]["rpc"], json=data)
|
||||
response = requests.get(self.__urls["http"]["rpc"], json=data)
|
||||
return response.json()
|
||||
|
||||
def __get_fiat_ccy(self) -> list[str]:
|
||||
|
||||
+63
-7
@@ -423,7 +423,8 @@ account = Account()
|
||||
params = {
|
||||
"display_name": "status-app-bot",
|
||||
"password": "SNTPUMP",
|
||||
"infura_token" : "token from https://www.infura.io/"
|
||||
"infura_token" : "token from https://www.infura.io/",
|
||||
"coingecko_api_key": "API key from https://www.coingecko.com/"
|
||||
}
|
||||
account.login(**params)
|
||||
available_tokens = account.get_tokens()
|
||||
@@ -454,7 +455,8 @@ account = Account()
|
||||
params = {
|
||||
"display_name": "status-app-bot",
|
||||
"password": "SNTPUMP",
|
||||
"infura_token" : "token from https://www.infura.io/"
|
||||
"infura_token" : "token from https://www.infura.io/",
|
||||
"coingecko_api_key": "API key from https://www.coingecko.com/"
|
||||
}
|
||||
account.login(**params)
|
||||
|
||||
@@ -479,7 +481,8 @@ account = Account()
|
||||
params = {
|
||||
"display_name": "status-app-bot",
|
||||
"password": "SNTPUMP",
|
||||
"infura_token" : "token from https://www.infura.io/"
|
||||
"infura_token" : "token from https://www.infura.io/",
|
||||
"coingecko_api_key": "API key from https://www.coingecko.com/"
|
||||
}
|
||||
account.login(**params)
|
||||
|
||||
@@ -505,7 +508,8 @@ account = Account()
|
||||
params = {
|
||||
"display_name": "status-app-bot",
|
||||
"password": "SNTPUMP",
|
||||
"infura_token" : "token from https://www.infura.io/"
|
||||
"infura_token" : "token from https://www.infura.io/",
|
||||
"coingecko_api_key": "API key from https://www.coingecko.com/"
|
||||
}
|
||||
account.login(**params)
|
||||
|
||||
@@ -535,7 +539,8 @@ account = Account()
|
||||
params = {
|
||||
"display_name": "status-app-bot",
|
||||
"password": "SNTPUMP",
|
||||
"infura_token" : "token from https://www.infura.io/"
|
||||
"infura_token" : "token from https://www.infura.io/",
|
||||
"coingecko_api_key": "API key from https://www.coingecko.com/"
|
||||
}
|
||||
account.login(**params)
|
||||
|
||||
@@ -876,7 +881,11 @@ Channel permissions:
|
||||
from bot import Account
|
||||
|
||||
account = Account()
|
||||
account.login("status-app-bot", "SNTPUMP")
|
||||
params = {
|
||||
"display_name": "status-app-bot",
|
||||
"password": "SNTPUMP"
|
||||
}
|
||||
account.login(**params)
|
||||
|
||||
for community in account.communities:
|
||||
print(community["name"], community["members"])
|
||||
@@ -938,8 +947,55 @@ account = Account()
|
||||
params = {
|
||||
"display_name": "status-app-bot",
|
||||
"password": "SNTPUMP",
|
||||
"infura_token" : "token from https://www.infura.io/"
|
||||
"infura_token" : "token from https://www.infura.io/",
|
||||
"coingecko_api_key": "API key from https://www.coingecko.com/"
|
||||
}
|
||||
account.login(**params)
|
||||
print(account.chains)
|
||||
```
|
||||
|
||||
#### `balance`
|
||||
|
||||
Retrieve the current **non-zero balances** token balances for the **logged-in account wallet** across all supported chains.
|
||||
|
||||
Returns `pd.DataFrame`.
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `timestamp` | `datetime.datetime` | Timestamp when the balance was fetched. |
|
||||
| `address` | `str` | Token contract address. |
|
||||
| `chain_id` | `int` | Chain ID where the token exists. |
|
||||
| `amount` | `float` | Token balance (adjusted using token decimals). |
|
||||
| `symbol` | `str` | Token symbol (e.g. `ETH`, `USDT`). |
|
||||
|
||||
```python
|
||||
from bot import Account
|
||||
|
||||
account = Account()
|
||||
|
||||
params = {
|
||||
"display_name": "status-app-bot",
|
||||
"password": "SNTPUMP",
|
||||
"infura_token" : "token from https://www.infura.io/",
|
||||
"coingecko_api_key": "API key from https://www.coingecko.com/"
|
||||
}
|
||||
account.login(**params)
|
||||
print(account.balance)
|
||||
```
|
||||
|
||||
You can convert the current balance into fiat currency by using a [ISO 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html) in the `[]` accessor:
|
||||
|
||||
```python
|
||||
from bot import Account
|
||||
|
||||
account = Account()
|
||||
|
||||
params = {
|
||||
"display_name": "status-app-bot",
|
||||
"password": "SNTPUMP",
|
||||
"infura_token" : "token from https://www.infura.io/",
|
||||
"coingecko_api_key": "API key from https://www.coingecko.com/"
|
||||
}
|
||||
account.login(**params)
|
||||
print(account["GBP"])
|
||||
```
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 160 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 132 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 137 KiB |
Reference in New Issue
Block a user