Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,26 @@ jobs:
- name: Dependency audit
run: pip-audit

spec:
name: Specification copy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Read spec/VERSION
id: spec
run: echo "version=$(cat spec/VERSION)" >> "$GITHUB_OUTPUT"

- name: Check out mina-sdk-spec at that tag
uses: actions/checkout@v4
with:
repository: o1-labs/mina-sdk-spec
ref: ${{ steps.spec.outputs.version }}
path: .mina-sdk-spec

- name: Check that spec/ is the tag's copy
run: .mina-sdk-spec/scripts/sync.sh --check .

test:
runs-on: ubuntu-latest
strategy:
Expand All @@ -88,6 +108,7 @@ jobs:
- name: Run unit tests with coverage
run: |
pytest tests/test_types.py tests/test_daemon_client.py \
tests/test_spec.py tests/test_common_api.py \
-v --cov=mina_sdk --cov-report=term-missing --cov-report=xml

- name: Upload coverage
Expand Down
72 changes: 0 additions & 72 deletions .github/workflows/schema-drift.yml

This file was deleted.

35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- The common API of the Mina SDKs, from
[mina-sdk-spec](https://github.com/o1-labs/mina-sdk-spec) v0.1.0: `spec/`
is a copy at the tag in `spec/VERSION`. `tests/test_spec.py` checks that
the query strings are the specification's documents, and a CI job checks
that `spec/` is the tag's copy.
- Methods of the common API that this SDK did not have: `get_daemon_metrics`,
`get_genesis_block`, `get_block`, `get_pooled_zkapp_commands`,
`get_transaction_status`, `get_genesis_constants`, `get_tracked_accounts`,
`get_snark_pool`, `get_fork_config`, `send_zkapp` and `unlock_account`.
- Signatures made outside the daemon: `signature=SignatureInput(...)` on
`send_payment` and `send_delegation`.
- Result fields of the common API: more `DaemonStatus` fields
(`AddrsAndPorts`); `AccountData` token symbol, voting-for, receipt chain
hash, timing, permissions and zkApp state; `AccountBalance.block_height`;
`BlockInfo` previous state hash, epoch, block creator, coinbase receiver,
epoch data, dates, ledger hashes, coinbase, fee transfers and user
commands; kind, source, receiver, amount, fee and memo of a sent command.
- `AccountNotFoundError`, a `ValueError`, from `get_account`.
- Integration tests of the new methods.
- `DaemonConnectionError` exception (replaces shadowed `ConnectionError`)
- `Currency.__rmul__` for `3 * Currency(10)` support
- Export all public types from `mina_sdk`: `AccountBalance`, `AccountData`,
Expand All @@ -24,10 +43,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Negative `Currency` values are rejected with `ValueError`

### Changed
- Every query is a named operation of the specification. Nullable variables
are always sent, as null when omitted: `get_account` and
`get_pooled_user_commands` use one document each
(`queries.GET_ACCOUNT_WITH_TOKEN` and `queries.POOLED_USER_COMMANDS_ALL`
are deprecated aliases), and `get_best_chain` sends `maxLength: null`.
- `get_pooled_user_commands` returns `PooledUserCommand` objects, not
dictionaries. `command["hash"]` and `command.get("hash")` still work for the
keys of the dictionaries; the daemon's `from` is the attribute `from_`.
- `SendPaymentResult` and `SendDelegationResult` are aliases of the new
`SubmittedCommand`.
- `Currency.__mul__` only accepts `int` scalars (was also accepting `Currency`,
which produced nonsensical nanomina-squared units)
- `ConnectionError` is now an alias for `DaemonConnectionError` (backwards compatible)

### Removed
- The schema drift check (`scripts/check_schema_drift.py`, the Schema Drift
Check workflow and `src/mina_sdk/schema/`). The documents of this SDK are
the documents of mina-sdk-spec, whose weekly drift job validates them
against the lightnet daemons of `master`, `compatible` and `develop`.

## [0.1.0] - 2025-11-20

### Added
Expand Down
52 changes: 38 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,41 @@ client = MinaDaemonClient(

## API Reference

The Mina SDKs have the same API, defined in
[mina-sdk-spec](https://github.com/o1-labs/mina-sdk-spec). `spec/` is a copy
of it at the tag in `spec/VERSION`. `tests/test_spec.py` checks that this
SDK's queries are the specification's documents, and CI checks that `spec/`
is the tag's copy. The ITN client of the specification is not in this SDK yet.

### Queries

| Method | Returns | Description |
|--------|---------|-------------|
| `get_sync_status()` | `str` | Node sync status (SYNCED, BOOTSTRAP, etc.) |
| `get_daemon_status()` | `DaemonStatus` | Comprehensive daemon status |
| `get_daemon_status()` | `DaemonStatus` | Daemon status: chain length, peers, addresses, block production keys |
| `get_daemon_metrics()` | `DaemonMetrics` | Transaction and snark pool metrics, block production delay |
| `get_network_id()` | `str` | Network identifier |
| `get_account(public_key)` | `AccountData` | Account balance, nonce, delegate |
| `get_best_chain(max_length)` | `list[BlockInfo]` | Recent blocks from best chain |
| `get_account(public_key, token_id=None)` | `AccountData` | Balance, nonce, delegate, timing, permissions, zkApp state |
| `get_best_chain(max_length=None)` | `list[BlockInfo]` | Recent blocks from the best chain |
| `get_genesis_block()` | `BlockInfo` | The genesis block |
| `get_block(state_hash=None, height=None)` | `BlockInfo` | One block; give exactly one of the two |
| `get_peers()` | `list[PeerInfo]` | Connected peers |
| `get_pooled_user_commands(public_key)` | `list[dict]` | Pending transactions |
| `get_pooled_user_commands(public_key=None)` | `list[PooledUserCommand]` | Pending payments and delegations |
| `get_pooled_zkapp_commands(public_key=None)` | `list[ZkappCommandResult]` | Pending zkApp commands |
| `get_transaction_status(payment=None, zkapp_transaction=None)` | `TransactionStatus` | `PENDING`, `INCLUDED` or `UNKNOWN`; give exactly one ID |
| `get_genesis_constants()` | `GenesisConstants` | Genesis timestamp, coinbase, account creation fee |
| `get_tracked_accounts()` | `list[TrackedAccount]` | Accounts in the daemon's keystore |
| `get_snark_pool()` | `list[CompletedWork]` | Completed snark work |
| `get_fork_config()` | `Any` | The daemon's fork configuration (JSON) |

### Mutations

| Method | Returns | Description |
|--------|---------|-------------|
| `send_payment(sender, receiver, amount, fee)` | `SendPaymentResult` | Send a payment |
| `send_delegation(sender, delegate_to, fee)` | `SendDelegationResult` | Delegate stake |
| `send_payment(sender, receiver, amount, fee, signature=None)` | `SendPaymentResult` | Send a payment; `signature` for one made outside the daemon |
| `send_delegation(sender, delegate_to, fee, signature=None)` | `SendDelegationResult` | Delegate stake; `signature` likewise |
| `send_zkapp(zkapp_command)` | `ZkappCommandResult` | Send a signed zkApp command (JSON) |
| `unlock_account(public_key, password)` | `str` | Unlock a keystore account so the daemon can sign with it |
| `set_snark_worker(public_key)` | `str \| None` | Set/unset SNARK worker |
| `set_snark_work_fee(fee)` | `str` | Set SNARK work fee |

Expand Down Expand Up @@ -133,13 +150,20 @@ All response types are importable from the top-level package:

```python
from mina_sdk import (
AccountBalance, # total, liquid, locked balances
AccountData, # public_key, nonce, balance, delegate, token_id
BlockInfo, # state_hash, height, slots, creator, tx count
DaemonStatus, # sync_status, chain height, peers, uptime
AccountBalance, # total, liquid, locked balances, block height
AccountData, # public_key, nonce, balance, delegate, timing, permissions, zkApp state
BlockInfo, # state_hash, height, slots, creator, epochs, ledger hashes, transactions
DaemonStatus, # sync_status, chain height, peers, uptime, addresses
DaemonMetrics, # pool sizes and diffs, block production delay
PeerInfo, # peer_id, host, port
SendPaymentResult, # id, hash, nonce
SendDelegationResult, # id, hash, nonce
PooledUserCommand, # a pending payment or delegation
SubmittedCommand, # result of send_payment / send_delegation
ZkappCommandResult, # a pending or sent zkApp command
CompletedWork, # snark pool entry
GenesisConstants,
TrackedAccount,
TransactionStatus,
SignatureInput, # field, scalar
)
```

Expand Down Expand Up @@ -175,11 +199,11 @@ The daemon is not running or not reachable at the configured URI. Check:

**GraphQLError: field not found**

The SDK's queries may be out of sync with the daemon's GraphQL schema. This can happen after a daemon upgrade. Check the [schema drift CI](https://github.com/MinaProtocol/mina-sdk-python/actions/workflows/schema-drift.yml) for compatibility status.
The SDK's queries may be out of sync with the daemon's GraphQL schema. This can happen after a daemon upgrade. Check the documents against your node with mina-sdk-spec: `python3 scripts/check.py --endpoint http://your-node:3085/graphql` (in a clone of [mina-sdk-spec](https://github.com/o1-labs/mina-sdk-spec)).

**Account not found**

`get_account()` raises `ValueError` when the account doesn't exist on the ledger. This is normal for new accounts that haven't received any transactions yet.
`get_account()` raises `AccountNotFoundError` (a `ValueError`) when the account doesn't exist on the ledger. This is normal for new accounts that haven't received any transactions yet.

## License

Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ ignore = [
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["S101", "S106"]
"examples/*" = ["T201"]
# The documents are copied from spec/operations.graphql and are not wrapped.
"src/mina_sdk/daemon/queries.py" = ["E501"]

[tool.ruff.format]
quote-style = "double"
Expand Down
Loading
Loading