Files
prime-sdk-python/README.md
Andrew Miller 7b1e9f6309
All checks were successful
Publish to PyPI Registry / publish (release) Successful in 1m14s
Add proof-measure client + Gitea PyPI publish; bump to 0.4.0
proof-measure is a separate, public, unauthenticated Dragonchain service. Adds:
- UnauthenticatedClient: HMAC-free transport mirroring Client (session
  injection, allow_redirects=False, from_dict decoding).
- ProofMeasureClient: get_security / report / health; default base URL
  https://proof-measure.dragonchain.com. Standalone (ProofMeasureClient()) and
  via DragonchainSDK.proof_measure.
- Proof-measure dataclass models (decimals as strings, timestamps as int).
- .gitea/workflows/publish.yml: build + twine upload to the Gitea PyPI registry
  on release (the SDK had no publish workflow before).

Also fixes 3 pre-existing failing tests: _FakeSession.request didn't accept the
allow_redirects kwarg the client now passes (added by the prior redirect change),
so the suite was red at HEAD.
2026-06-04 13:53:16 -04:00

213 lines
5.7 KiB
Markdown

# Dragonchain Python SDK
A self-contained Python SDK for interacting with Dragonchain (Prime) nodes.
## Installation
```bash
pip install prime-sdk-python
```
Or, from a local checkout:
```bash
pip install -e .
```
Requires Python 3.9+.
## Usage
```python
from prime_sdk import DragonchainSDK, TransactionCreateRequest
# Initialize the SDK
client = DragonchainSDK(
"your-public-id",
"your-auth-key-id",
"your-auth-key",
"https://your-dragonchain-endpoint.com",
)
# Check system health (raises DragonchainAPIError if unhealthy)
client.system.health()
# Get system status
status = client.system.status()
print(f"Chain ID: {status.id}, Level: {status.level}")
# Create a transaction
resp = client.transaction.create(
TransactionCreateRequest(
txn_type="my-transaction-type",
payload='{"message": "Hello Dragonchain"}',
tag="example-tag",
)
)
print(f"Created transaction: {resp.transaction_id}")
```
## Transaction Modes
`create` and `create_bulk` return **immediately** with the assigned transaction
ID(s). They do **not** wait for block inclusion. Blocks are assembled
asynchronously on a ~5-second cycle.
### Fire and Forget
Most use cases only need the transaction ID. No polling required.
```python
resp = client.transaction.create(
TransactionCreateRequest(
txn_type="my-transaction-type",
payload='{"message": "Hello Dragonchain"}',
)
)
print("Transaction ID:", resp.transaction_id)
# Done — no need to wait for a block.
```
### Wait for Block
If you need the block ID (e.g. for interchain verification or Daria), poll
`get` until `header.block_id` is populated.
```python
import time
resp = client.transaction.create(
TransactionCreateRequest(
txn_type="my-transaction-type",
payload='{"message": "Hello Dragonchain"}',
)
)
while True:
txn = client.transaction.get(resp.transaction_id)
if txn.header.block_id:
print("Block ID:", txn.header.block_id)
break
time.sleep(2)
```
## Loading credentials from a file
The SDK can read chain credentials from a YAML file:
```yaml
default: my-public-id
chains:
- name: my-chain
publicId: my-public-id
authKeyId: my-auth-key-id
authKey: my-auth-key
endpoint: https://chains.dragonchain.com
```
```python
from prime_sdk import DragonchainSDK
from prime_sdk.credentials import load_config
cfg = load_config("~/.dragonchain/credentials.yaml")
chain = cfg.get_default_chain()
client = DragonchainSDK(
chain.public_id, chain.auth_key_id, chain.auth_key, chain.endpoint
)
```
## Available Endpoints
### System
- `system.health()` — Check system health
- `system.status()` — Get system status
### Transaction
- `transaction.create(req)` — Create a new transaction
- `transaction.create_bulk(req)` — Create multiple transactions
- `transaction.get(transaction_id)` — Get transaction by ID
- `transaction.list()` — List all transactions
### Transaction Type
- `transaction_type.create(req)` — Create a new transaction type
- `transaction_type.get(txn_type)` — Get transaction type by name
- `transaction_type.list()` — List all transaction types
- `transaction_type.delete(txn_type)` — Delete a transaction type
### Smart Contract
- `contract.create(req)` — Create a new smart contract
- `contract.get(contract_id)` — Get smart contract by ID
- `contract.list()` — List all smart contracts
- `contract.update(contract_id, req)` — Update a smart contract
- `contract.upload(contract_id, filepath)` — Upload smart contract code
- `contract.delete(contract_id)` — Delete a smart contract
### Block
- `block.get(block_id)` — Get block by ID
### Proof Measure (public, unauthenticated)
- `proof_measure.get_security(network, since=None)` — A network's accumulated security since `since` (unix seconds), as a raw measure + USD valuation. `network` = `"BTC"` or `"ETH"`.
- `proof_measure.report(req)` — Per-transaction "securedBy" report over interchain anchors.
- `proof_measure.health()` — Service liveness.
## Proof Measure
`proof-measure` is a separate, **public, unauthenticated** Dragonchain service
(the measured-immutability / "securedBy" metric) at
`https://proof-measure.dragonchain.com`. It needs no credentials. Decimal fields
are returned as strings (full precision) and timestamps as int unix seconds.
```python
import time
from prime_sdk import ProofMeasureClient, ReportRequest, ReportAnchorInput
# Via the main SDK (targets the default public endpoint):
sec = client.proof_measure.get_security("BTC", int(time.time()) - 3600)
print(f"BTC secured by {sec.value_usd_formatted} ({sec.raw.value} {sec.raw.unit})")
# Or standalone — no prime credentials needed:
pm = ProofMeasureClient() # or ProofMeasureClient("http://localhost:9481")
report = pm.report(
ReportRequest(
transaction_id="tx-123",
prime_id="my-prime",
block_id="42",
anchors=[
ReportAnchorInput(tx_hash="0x...", timestamp=anchor_unix, network="BTC"),
ReportAnchorInput(tx_hash="0x...", timestamp=anchor_unix, network="ETH"),
],
)
)
print(f"Secured by {report.total_value_usd_formatted} across {len(report.anchors)} anchors")
pm.health()
```
## Authentication
The SDK uses HMAC-SHA256 authentication. You need to provide:
- `public_id` — Your Dragonchain public ID
- `auth_key_id` — Your authentication key ID
- `auth_key` — Your authentication key
- `base_url` — The base URL of your Dragonchain node (e.g. "https://chains.dragonchain.com")
## Error handling
Any non-2xx response raises `prime_sdk.DragonchainAPIError`, which exposes
`.status_code` and `.body`:
```python
from prime_sdk import DragonchainAPIError
try:
client.transaction.get("nonexistent-id")
except DragonchainAPIError as e:
print(e.status_code, e.body)
```
## License
Apache-2.0