All checks were successful
Publish to PyPI Registry / publish (release) Successful in 23s
transaction.get_interchain / block.get_interchain take per_chain= and chains= kwargs mapping to prime-node's ?perChain=&chains= params. Default (no kwargs) returns one anchor per chain. Shared interchain_query() helper, exported; pytest.
231 lines
6.3 KiB
Markdown
231 lines
6.3 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.
|
|
|
|
## Interchain trace
|
|
|
|
`transaction.get_interchain` / `block.get_interchain` trace a prime block to the
|
|
public-chain anchors covering it. By default they return the **first anchor per
|
|
chain** (anchor proofs are chained, so the earliest per chain is the meaningful
|
|
one):
|
|
|
|
```python
|
|
# Default: first anchor per chain (ETH, BTC, …)
|
|
trace = client.block.get_interchain("42")
|
|
|
|
# Up to 3 anchors per chain
|
|
trace = client.block.get_interchain("42", per_chain=3)
|
|
|
|
# All anchors, only the ETH-mainnet chain ("1"); "0" = BTC
|
|
trace = client.block.get_interchain("42", per_chain=0, chains=["1"])
|
|
```
|
|
|
|
## 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
|