account: ENS support

- Related to https://github.com/status-im/status-python-sdk/issues/14
This commit is contained in:
Nick Ninov
2026-06-23 12:29:00 +03:00
parent 82de859915
commit a5e97fa99d
3 changed files with 85 additions and 52 deletions
+17 -11
View File
@@ -101,7 +101,7 @@ class Account:
# In case if there is a hanging logged in session
self.logout()
def login(self, password: str, key_uid: Optional[str] = None, display_name: Optional[str] = None, mnemonic: Optional[str] = None, infura_token: Optional[str] = None, alchemy_token: Optional[str] = None, coingecko_api_key: Optional[str] = None):
def login(self, password: str, key_uid: Optional[str] = None, name: Optional[str] = None, mnemonic: Optional[str] = None, infura_token: Optional[str] = None, alchemy_token: Optional[str] = None, coingecko_api_key: Optional[str] = None):
"""
Login to the given account. If it does not exist,
it will be created and automatically logged in.
@@ -109,20 +109,20 @@ class Account:
Parameters:
- `password` - your Status password
- `key_uid` - your key unique identifier. If not provided `display_name` will be used to fetch it. This means that each `display_name` can be linked to one `key_uid`
- `display_name` - your Status display name. Use `display_name` and `password` parameter combination if you have a 1 to 1 mapping (each display name has a unique `key_uid`)
- `name` - your Status display name or ENS. Use `name` and `password` parameter combination if you have a 1 to 1 mapping (ENS has a unique `key_uid`)
- `mnemonic` - the mnemonic when creating an account. Use this field with `password` and `display_name` to recover an account
- `infura_token` - https://www.infura.io/ RPC token to allow Status Backend to use a wallet
- `alchemy_token` - https://alchemy.com/ RPC token to allow Status Backend to use a wallet
- `coingecko_api_key` - https://www.coingecko.com/ API key to allow Status Backend to use a wallet
"""
if not key_uid and not display_name:
if not key_uid and not name:
raise exceptions.InvalidContactError()
available_accounts = self.available_accounts
# Login combination: display_name + password
# Login combination: display_name (or ENS) + password
if not key_uid:
for account in available_accounts:
if account["display_name"] != display_name:
if account["name"] != name:
continue
key_uid = account["key_uid"]
@@ -131,7 +131,7 @@ class Account:
else:
available_key_uids = [current["key_uid"] for current in available_accounts]
if key_uid not in available_key_uids:
info = "\n".join([f"{current['key_uid']} - {current['display_name']}" for current in self.available_accounts])
info = "\n".join([f"{current['key_uid']} - {current['name']}" for current in self.available_accounts])
raise exceptions.InvalidContactError(f"Given Key Unique Identifier is invalid...\nAvailable Key Unique Identifiers:\n{info}")
is_new_account = isinstance(key_uid, type(None))
@@ -145,11 +145,11 @@ class Account:
}
if is_new_account or is_recovery:
self.__validate_display_name(display_name)
self.__validate_display_name(name)
params = {
"rootDataDir": self.__docker_data_folder,
"kdfIterations": self.__kd_iterations,
"displayName": display_name,
"displayName": name,
"password": password,
"customizationColor": "primary",
"wakuV2LightClient": False,
@@ -159,7 +159,7 @@ class Account:
self.logger.info(f"Logging in with Key UID - {key_uid}")
if is_new_account:
self.logger.info(f"Creating account with display_name {display_name}")
self.logger.info(f"Creating account with display_name {name}")
url_key = "create"
if is_recovery:
@@ -202,6 +202,7 @@ class Account:
self.logger.info("Successfully logged in!")
event: dict = signal_event["event"]["settings"]
ens_info: list[dict] = signal_event["event"].get("ensUsernames", [])
self.__info = {
"public_key": event["public-key"],
"url": None,
@@ -213,6 +214,10 @@ class Account:
"bio": event.get("bio", ""),
"password": password,
"wallet_address": event["dapps-address"],
"ens": {
"preferred_name": event.get("preferred-name"),
"usernames": ens_info
},
"logged_in_timestamp": datetime.datetime.now()
}
self.__info["url"] = self.__call_rpc("urls", "shareUserURLWithData", [event["public-key"]]).get("result")
@@ -255,7 +260,8 @@ class Account:
current_available_accounts = [
{
"display_name": account["name"],
"name": account["name"],
"is_ens": account["name"].endswith(".eth"),
"key_uid": account["key-uid"],
"created_at": datetime.datetime.fromtimestamp(account["timestamp"])
}
@@ -1226,7 +1232,7 @@ class Account:
params = {
"filePath": os.path.join(self.__docker_backup_folder, file_name).replace("\\", "/")
}
self.logger.info(f"Trying to load {file_path}")
self.logger.info(f"Loading backup file: {file_path}")
response = requests.post(self.__urls["http"]["load_backup"], json=params)
error: str = response.json().get("error", "")
+68 -41
View File
@@ -143,23 +143,23 @@ An account can also be recovered if the [`mnemonic`](https://status.app/help/pro
|-----|-----|-----|-------------|
| `password` | `str` | Yes | Password used to encrypt the account |
| `key_uid` | `str` | Yes* | Unique key identifier of the account. If provided, the account will be logged in directly using this identifier. If not provided, then you must use `display_name` and `password` to login. |
| `display_name` | `str` | Yes* | Display name of the account. Used to resolve the `key_uid` if it is not provided, or to create a new account if one does not already exist. This field is required if an account needs to be recovered with `mnemonic`. |
| `name` | `str` | Yes* | Display name or [ENS name](https://status.app/help/profile/transfer-your-ens-name-to-status) of the account. Used to resolve the `key_uid` if it is not provided, or to create a new account if one does not already exist. This field is required if an account needs to be recovered with `mnemonic`. |
| `mnemonic` | `str` | No | The [mnemonic](https://status.app/help/profile/understand-your-status-keys-and-recovery-phrase#about-your-recovery-phrase) from [`info`](./account.md#info). Use this field with `password` and `display_name` to recover the account. If you have [`.bkp`](./account.md#backup) files, in the backup Docker volume they will be automatically picked up and loaded.<br><br>**Note**: You can pass a different `display_name` but that will be internal only. When an account is recovered setting [`display_name`](./account.md#display_name) can be buggy. Ideally when recovering the account, use the original `display_name` of the account. |
| `infura_token` | `str` | No | [RPC token](https://www.infura.io/) used by Status Backend for the Ethereum RPC component of the wallet. |
| `alchemy_token` | `str` | No | Used to fetch [wallet transactions](./account.md#get_transactionsrefreshfalse) to fetch wallet transaction history via the Alchemy REST API, so no separate key is needed for transactions. |
| `coingecko_api_key` | `str` | No | [API key](https://www.coingecko.com/) used by Status Backend to fetch token prices. |
Wallet functionality is split into three components, each backed by a token: Ethereum RPC (`infura_token`), transactions (`alchemy_token`) and prices (`coingecko_api_key`). All three must be provided for wallet RPC methods to work if any is missing, wallet calls raise a `WalletNotConfiguredError`.
Wallet functionality is split into three components, each backed by a token: Ethereum RPC (`infura_token`), transactions (`alchemy_token`) and prices (`coingecko_api_key`). All three must be provided for wallet RPC methods to work - if any is missing, wallet calls raise a `WalletNotConfiguredError`.
Returns the current `Account` instance, allowing method chaining.
#### Login with `display_name`
#### Login with Display name
```python
from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -171,6 +171,25 @@ The code above is equivalent to the following screen on Status App:
**Note**: This assumes that `display_name` and is unique for every `key_uid`. If there are duplicated `display_names` then the first found match will be used. You can log in with `key_uid` if you have `display_name` duplicates.
#### Login with ENS
```python
from bot import Account
account = Account()
params = {
"name": "malte.stateofus.eth",
"password": "SNTPUMP"
}
account.login(**params)
```
You can purchase a **universal username** on Status App:
![ENS purchase](./images/ens.png)
#### Login with `key_uid`
```python
@@ -191,7 +210,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"mnemonic" : "phrase_1 phrase_2 phrase_3 phrase_4 phrase_5 phrase_6 phrase_7 phrase_8 phrase_9 phrase_10 phrase_11 phrase_12"
}
@@ -212,7 +231,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -221,7 +240,7 @@ params = {
account.login(**params)
```
**Note**: `infura_token`, `alchemy_token` and `coingecko_api_key` can be used when creating, recovering and logging in to an account. All three are required to enable wallet functionality if any is missing, those calls raise a `WalletNotConfiguredError`.
**Note**: `infura_token`, `alchemy_token` and `coingecko_api_key` can be used when creating, recovering and logging in to an account. All three are required to enable wallet functionality - if any is missing, those calls raise a `WalletNotConfiguredError`.
### `logout()`
@@ -232,7 +251,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -258,7 +277,7 @@ from bot import Account
account = Account(backup_folder=r"C:\\Users\\me\\status-backups")
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -283,7 +302,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -315,7 +334,7 @@ import datetime
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -346,7 +365,7 @@ from rich.pretty import Pretty
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -384,7 +403,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -427,7 +446,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -457,7 +476,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -491,7 +510,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -524,7 +543,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -551,7 +570,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -579,7 +598,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -611,7 +630,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -690,7 +709,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -729,7 +748,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -755,7 +774,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -780,7 +799,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -806,7 +825,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -846,7 +865,14 @@ This property is useful when you want to:
**You will have to know the passwords for the given `key_uid`.**
Returns `list[dict]`.
Returns `list[dict]`, one entry per locally available account.
| Key | Type | Description |
|----|----|-------------|
| `name` | `str` | The account's name. For accounts using an [ENS](https://status.app/help/profile/transfer-your-ens-name-to-status) name, this is the ENS name (e.g. `malte.stateofus.eth`). For accounts that do not have an ENS name, this will be their display name. |
| `is_ens` | `bool` | `True` when `display_name` is an ENS name (ends with `.eth`), otherwise `False`. Useful for telling apart plain display names from universal usernames. |
| `key_uid` | `str` | Internal Status key identifier for the account. Can be passed to [`login`](./account.md#loginpassword-key_uidnone-display_namenone-mnemonicnone-infura_tokennone-alchemy_tokennone-coingecko_api_keynone) as `key_uid`. |
| `created_at` | `datetime.datetime` | Timestamp when the account was created locally. |
```python
from bot import Account
@@ -874,6 +900,7 @@ Provides information about the currently logged-in account. If `login()` has not
| `display_name` | `str` | Display name of the account. |
| `password` | `str` | Password used to encrypt the account locally. |
| `wallet_address` | `str` | Ethereum wallet address associated with the account. |
| `ens` | `dict` | The account's [ENS](https://status.app/help/profile/transfer-your-ens-name-to-status) details. Contains `preferred_name` (`str` or `None`) - the ENS name the account has chosen to display - and `usernames` (`list[dict]`) - every ENS username registered to the account. Both are empty / `None` when no ENS name is set. |
| `logged_in_timestamp` | `datetime.datetime` | Timestamp when the account successfully logged in. |
```python
@@ -881,7 +908,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -900,7 +927,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -916,7 +943,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -939,7 +966,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -955,7 +982,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -972,7 +999,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -994,7 +1021,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -1012,7 +1039,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -1123,7 +1150,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -1191,7 +1218,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -1228,7 +1255,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -1257,7 +1284,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP"
}
account.login(**params)
@@ -1288,7 +1315,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -1318,7 +1345,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
@@ -1336,7 +1363,7 @@ from bot import Account
account = Account()
params = {
"display_name": "status-app-bot",
"name": "status-app-bot",
"password": "SNTPUMP",
"infura_token": "token from https://www.infura.io/",
"alchemy_token": "token from https://www.alchemy.com/",
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB