Skip to main content

Python SDK for the DataDID developer platform — Data API and DID API clients

Project description

Getting Started with datadid-sdk-python

DataDID is a developer platform that combines decentralized identity (DID) with user authentication and action records. The SDK provides two clients:

  • DataClient — authentication, user info, and action records (data-be.metamemo.one)
  • DIDClient — DID creation/deletion and file operations (prodidapi.memolabs.org)

Installation

pip install datadid-sdk-python

Requirements: Python 3.10+


Quick Start

import asyncio
from datadid import DataClient

async def main():
    client = DataClient.production()

    # Log in — the client stores the access token automatically
    tokens = await client.login_with_email_password("you@example.com", "yourpassword")

    # Fetch your profile
    me = await client.get_me()
    print(me.uid, me.role)

asyncio.run(main())

Servers

Client Purpose Production URL Test URL
DataClient Auth, user info, action records https://data-be.metamemo.one https://test-data-be-v2.memolabs.net
DIDClient DID creation, file operations https://prodidapi.memolabs.org https://testdidapi.memolabs.org

Part 1 — DataClient

Create a client

from datadid import DataClient
from datadid.data.types import DataClientOptions

client = DataClient.production()
# or: client = DataClient.testnet()
# or: client = DataClient(DataClientOptions(base_url="https://data-be.metamemo.one"))

Login with email (verification code)

# Step 1: send a code to the user's inbox
await client.send_email_code("alice@example.com")

# Step 2: log in with the code
tokens = await client.login_with_email(
    "alice@example.com",
    "123456",  # code from inbox
    "Web",     # source: a string identifying your app — e.g. "Web", "App", "Mobile"
)

print(tokens.access_token)
print(tokens.refresh_token)

After a successful login the client stores the access token automatically. All subsequent calls that need authentication will use it.


Register a new account

await client.send_email_code("bob@example.com")

tokens = await client.register_with_email(
    "bob@example.com",
    "123456",     # code from inbox
    "mypassword", # choose a password
    "Web",
)

Login with email + password

tokens = await client.login_with_email_password(
    "alice@example.com",
    "mypassword",
)

Reset password

await client.send_email_code("alice@example.com")

await client.reset_password(
    "alice@example.com",
    "123456",      # code from inbox
    "newpassword",
)

Login with Telegram

tokens = await client.login_with_telegram(
    telegram_init_data,  # string from Telegram WebApp.initData
    "App",
)

Login with Pi Browser

tokens = await client.login_with_pi(
    pi_access_token,  # access token from Pi Browser SDK
    "App",
)

Login with EVM wallet (MetaMask, etc.)

# Step 1: request a challenge message from the server
message = await client.get_evm_challenge(
    "0xYourWalletAddress",
    chain_id=985,  # optional
)

# Step 2: sign the message with the user's wallet
# (using eth_account or any signing library)
from eth_account.messages import encode_defunct
from eth_account import Account
signed = Account.sign_message(encode_defunct(text=message), private_key=private_key)
signature = signed.signature.hex()

# Step 3: submit the signature to log in
result = await client.login_with_evm(message, signature, "Web")

print(result.access_token)
print(result.did)     # the user's DID string (e.g. "did:memo:...")
print(result.number)  # the user's numeric platform ID

Refresh an access token

new_access_token = await client.refresh_token(tokens.refresh_token)

Get current user info

# Basic info (uid, email, username, role)
me = await client.get_me()
print(me.uid, me.role)

# Full profile (avatar, DID, linked social accounts, etc.)
info = await client.get_user_info()
print(info.name)
print(info.address)        # numeric platform ID (e.g. "2018955010523533312")
print(info.did)
print(info.email)
print(info.telegram_info)  # if linked
print(info.twitter_info)   # if linked
print(info.discord_info)   # if linked
print(info.pi_info)        # if linked

Action records

Action records are the platform's points/achievement system. Each action has a numeric ID. When a user completes an action, a record is stored with the points earned and a Unix timestamp.

# Check if the user has completed action #61
record = await client.get_action_record(61)
if record:
    print(f"Completed at {record.time}, earned {record.points} points")
else:
    print("Not completed yet")

# Mark action #61 as completed
await client.add_action_record(61)

# With extra options (some actions require additional data)
await client.add_action_record(61, {"some_option": "value"})

Error handling

from datadid import DataDIDApiError

try:
    await client.login_with_email_password("alice@example.com", "wrongpassword")
except DataDIDApiError as err:
    print(str(err))          # human-readable message
    print(err.status_code)   # HTTP status code (e.g. 401, 500)
    print(err.response_body) # raw JSON from the server

Manual token management

By default, login methods store the access token on the client automatically. You can disable this:

from datadid import DataClient
from datadid.data.types import DataClientOptions

client = DataClient(DataClientOptions(
    base_url="https://data-be.metamemo.one",
    disable_auto_token=True,
))

tokens = await client.login_with_email("alice@example.com", "123456", "Web")

# Token was NOT stored automatically — set it yourself:
client.set_access_token(tokens.access_token)

# Read the current token at any time:
token = client.get_access_token()

Part 2 — DIDClient

DID operations use a sign-then-submit pattern. You never send your private key to the server — you only sign a message locally, and the server pays the gas fee and submits the transaction on your behalf.

The pattern for every write operation:

  1. Ask the server for a message to sign
  2. Sign that message with your wallet (free, off-chain)
  3. Submit the signature — the server does the rest

Create a client

from datadid import DIDClient

did_client = DIDClient.production()
# or: did_client = DIDClient.testnet()

Create a DID

address = "0xYourWalletAddress"

# Step 1: get the message to sign
message = await did_client.get_create_message(address)

# Step 2: sign it with your wallet (eth_account example)
from eth_account.messages import encode_defunct
from eth_account import Account
signed = Account.sign_message(encode_defunct(text=message), private_key=private_key)
signature = signed.signature.hex()

# Step 3: submit — server creates the DID on-chain
new_did = await did_client.create_did(signature, address)

print(new_did)  # "did:memo:abc123..."

Check if a DID exists

result = await did_client.get_did_exists("0xYourWalletAddress")
print(result)

Get DID info

info = await did_client.get_did_info("0xYourWalletAddress")
print(info.did)   # the DID string
print(info.info)  # list of DIDChainInfo(address, balance, chain)

Delete a DID

my_did = "did:memo:abc123..."

# Step 1: get the message to sign
message = await did_client.get_delete_message(my_did)

# Step 2: sign it
signature = ...

# Step 3: submit
result = await did_client.delete_did(signature, my_did)
print(result.status)

Upload a file

Files are stored directly by wallet address. For files that need their own on-chain DID, see mfile operations below.

await did_client.upload_file(file_data, "0xYourWalletAddress")

List files

files = await did_client.list_files("0xYourWalletAddress")

Download a file

file = await did_client.download_file("0xYourWalletAddress")

Upload an mfile (file with an on-chain DID)

An mfile is a file that gets its own DID minted on-chain, making it permanently addressable and verifiable on the Memo network. This uses the sign-then-submit pattern.

# Step 1: create the upload request — returns a message to sign
message = await did_client.create_mfile_upload(file_data, "0xYourWalletAddress")

# Step 2: sign it
signature = ...

# Step 3: confirm the upload
result = await did_client.confirm_mfile_upload(signature, "0xYourWalletAddress")

Download an mfile

file = await did_client.download_mfile(
    "did:mfile:bafkrei...",  # the mfile DID
    "0xYourWalletAddress",
)

Running the tests

python tests/run.py

Tests hit the real production and testnet servers. A valid access token is required.

  1. Copy .env.example to .env
  2. Paste your token as DATADID_TOKEN=eyJ...

To get a token: log into the DataDID app, open browser devtools (F12 → Network tab), find the login request, and copy the access_token from the response JSON. Tokens expire after 24 hours.

You can also pass the token inline without creating a .env file:

DATADID_TOKEN=eyJ... python tests/run.py        # macOS / Linux
set DATADID_TOKEN=eyJ... && python tests/run.py  # Windows cmd

API Reference

DataClient

Method Description
DataClient.production() Client for production
DataClient.testnet() Client for test server
set_access_token(token) Manually set the auth token
get_access_token() Read the current token
send_email_code(email) Send verification code to email
login_with_email(email, code, source, useragent?) Login with email + code
register_with_email(email, code, password, source, useragent?) Register new account
login_with_email_password(email, password) Login with email + password
reset_password(email, code, new_password) Reset password
login_with_telegram(initdata, source, useragent?) Login with Telegram
login_with_pi(pi_access_token, source, useragent?) Login with Pi Browser
get_evm_challenge(address, chain_id?, origin?) Get EVM sign-in challenge
login_with_evm(message, signature, source, useragent?) Login with EVM wallet signature
refresh_token(refresh_token) Get a new access token
get_me() Basic user info (uid, email, role)
get_user_info() Full user profile
get_action_record(action_id) Get action completion record (or None)
add_action_record(action_id, opts?) Record an action completion

DIDClient

Method Description
DIDClient.production() Client for production (prodidapi.memolabs.org)
DIDClient.testnet() Client for test server (testdidapi.memolabs.org)
get_create_message(address) Get message to sign before creating a DID
create_did(sig, address) Create a DID (submit signature)
create_did_admin(address) Admin: create DID without signature
create_ton_did(address) Create a Ton-network DID
get_did_exists(address) Check if a DID exists
get_did_info(address) Get DID info and chain balances
get_delete_message(did) Get message to sign before deleting a DID
delete_did(sig, did) Delete a DID (submit signature)
upload_file(data, address) Upload a file
list_files(address) List files for an address
download_file(address) Download a file
create_mfile_upload(data, address) Start an mfile upload (returns message to sign)
confirm_mfile_upload(sig, address) Confirm mfile upload (submit signature)
download_mfile(mdid, address) Download a file by its mfile DID

Error class

Attribute Type Description
str(err) str Human-readable error message
status_code int HTTP status code
response_body Any Raw JSON response from server

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

datadid_sdk_python-1.0.4.tar.gz (15.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

datadid_sdk_python-1.0.4-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file datadid_sdk_python-1.0.4.tar.gz.

File metadata

  • Download URL: datadid_sdk_python-1.0.4.tar.gz
  • Upload date:
  • Size: 15.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for datadid_sdk_python-1.0.4.tar.gz
Algorithm Hash digest
SHA256 c794f1edd430c7b50a87e8f9c7d45dba4e2d9737d61ec5da48a057ca47fdf9cf
MD5 50b4d02a55a873be7f7fa8974deab58a
BLAKE2b-256 7f17f47b6e155a1122066d8aab127e286697435b33678b566eb9fb5b118480c3

See more details on using hashes here.

File details

Details for the file datadid_sdk_python-1.0.4-py3-none-any.whl.

File metadata

File hashes

Hashes for datadid_sdk_python-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 49e4f8dfe220643214d7607f9d6ba1664ae8137bb9bbf6759a822265410768cf
MD5 d56215b12a0e9eff995fd36c70a9a6fc
BLAKE2b-256 46f3a9c865b396c218f26029b37db16709252173ce72cc7f5f9a50b621faee75

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page