qorechain-sdk 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qorechain_sdk-0.3.0/.gitignore +49 -0
- qorechain_sdk-0.3.0/PKG-INFO +301 -0
- qorechain_sdk-0.3.0/README.md +267 -0
- qorechain_sdk-0.3.0/pyproject.toml +88 -0
- qorechain_sdk-0.3.0/src/qorechain/__init__.py +239 -0
- qorechain_sdk-0.3.0/src/qorechain/accounts.py +173 -0
- qorechain_sdk-0.3.0/src/qorechain/address.py +79 -0
- qorechain_sdk-0.3.0/src/qorechain/client.py +115 -0
- qorechain_sdk-0.3.0/src/qorechain/denom.py +87 -0
- qorechain_sdk-0.3.0/src/qorechain/errors.py +150 -0
- qorechain_sdk-0.3.0/src/qorechain/fees.py +67 -0
- qorechain_sdk-0.3.0/src/qorechain/gas.py +186 -0
- qorechain_sdk-0.3.0/src/qorechain/jsonrpc.py +112 -0
- qorechain_sdk-0.3.0/src/qorechain/messages/__init__.py +97 -0
- qorechain_sdk-0.3.0/src/qorechain/messages/_composer.py +60 -0
- qorechain_sdk-0.3.0/src/qorechain/messages/cosmos.py +105 -0
- qorechain_sdk-0.3.0/src/qorechain/messages/qorechain.py +242 -0
- qorechain_sdk-0.3.0/src/qorechain/messages/registry.py +210 -0
- qorechain_sdk-0.3.0/src/qorechain/networks.py +109 -0
- qorechain_sdk-0.3.0/src/qorechain/pqc.py +134 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/abstractaccount/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/abstractaccount/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/abstractaccount/v1/tx_pb2.py +64 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/abstractaccount/v1/tx_pb2.pyi +51 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/amm/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/amm/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/amm/v1/tx_pb2.py +139 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/amm/v1/tx_pb2.pyi +127 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/bridge/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/bridge/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/bridge/v1/tx_pb2.py +84 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/bridge/v1/tx_pb2.pyi +89 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/crossvm/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/crossvm/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/crossvm/v1/query_pb2.py +51 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/crossvm/v1/query_pb2.pyi +74 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/crossvm/v1/tx_pb2.py +67 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/crossvm/v1/tx_pb2.pyi +42 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/license/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/license/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/license/v1/tx_pb2.py +90 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/license/v1/tx_pb2.pyi +68 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/lightnode/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/lightnode/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/lightnode/v1/query_pb2.py +59 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/lightnode/v1/query_pb2.pyi +108 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/lightnode/v1/tx_pb2.py +73 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/lightnode/v1/tx_pb2.pyi +54 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/multilayer/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/multilayer/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/multilayer/v1/tx_pb2.py +118 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/multilayer/v1/tx_pb2.pyi +155 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/pqc/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/pqc/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/pqc/v1/query_pb2.py +43 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/pqc/v1/query_pb2.pyi +41 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/pqc/v1/tx_pb2.py +96 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/pqc/v1/tx_pb2.pyi +92 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/qca/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/qca/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/qca/v1/query_pb2.py +41 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/qca/v1/query_pb2.pyi +49 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/rdk/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/rdk/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/rdk/v1/tx_pb2.py +114 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/rdk/v1/tx_pb2.pyi +122 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/reputation/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/reputation/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/reputation/v1/query_pb2.py +41 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/reputation/v1/query_pb2.pyi +24 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/rlconsensus/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/rlconsensus/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/rlconsensus/v1/query_pb2.py +62 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/rlconsensus/v1/query_pb2.pyi +115 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/rlconsensus/v1/tx_pb2.py +69 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/rlconsensus/v1/tx_pb2.pyi +61 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/svm/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/svm/v1/__init__.py +1 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/svm/v1/query_pb2.py +53 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/svm/v1/query_pb2.pyi +71 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/svm/v1/tx_pb2.py +90 -0
- qorechain_sdk-0.3.0/src/qorechain/proto/qorechain/svm/v1/tx_pb2.pyi +83 -0
- qorechain_sdk-0.3.0/src/qorechain/py.typed +0 -0
- qorechain_sdk-0.3.0/src/qorechain/qor.py +218 -0
- qorechain_sdk-0.3.0/src/qorechain/query/__init__.py +27 -0
- qorechain_sdk-0.3.0/src/qorechain/query/grpc.py +296 -0
- qorechain_sdk-0.3.0/src/qorechain/rest.py +222 -0
- qorechain_sdk-0.3.0/src/qorechain/search.py +92 -0
- qorechain_sdk-0.3.0/src/qorechain/subscribe.py +162 -0
- qorechain_sdk-0.3.0/src/qorechain/track.py +184 -0
- qorechain_sdk-0.3.0/src/qorechain/tx.py +427 -0
- qorechain_sdk-0.3.0/src/qorechain/utils/__init__.py +41 -0
- qorechain_sdk-0.3.0/src/qorechain/utils/hash.py +58 -0
- qorechain_sdk-0.3.0/src/qorechain/utils/units.py +94 -0
- qorechain_sdk-0.3.0/src/qorechain/utils/validation.py +94 -0
- qorechain_sdk-0.3.0/tests/test_accounts.py +104 -0
- qorechain_sdk-0.3.0/tests/test_address.py +63 -0
- qorechain_sdk-0.3.0/tests/test_client.py +72 -0
- qorechain_sdk-0.3.0/tests/test_denom.py +79 -0
- qorechain_sdk-0.3.0/tests/test_errors.py +66 -0
- qorechain_sdk-0.3.0/tests/test_gas.py +84 -0
- qorechain_sdk-0.3.0/tests/test_messages.py +324 -0
- qorechain_sdk-0.3.0/tests/test_networks.py +49 -0
- qorechain_sdk-0.3.0/tests/test_pqc.py +106 -0
- qorechain_sdk-0.3.0/tests/test_query.py +190 -0
- qorechain_sdk-0.3.0/tests/test_query_grpc.py +102 -0
- qorechain_sdk-0.3.0/tests/test_search.py +89 -0
- qorechain_sdk-0.3.0/tests/test_subscribe.py +83 -0
- qorechain_sdk-0.3.0/tests/test_track.py +116 -0
- qorechain_sdk-0.3.0/tests/test_tx.py +312 -0
- qorechain_sdk-0.3.0/tests/test_utils.py +103 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Secrets / env
|
|
2
|
+
.env
|
|
3
|
+
.env.*
|
|
4
|
+
!.env.example
|
|
5
|
+
*.pem
|
|
6
|
+
*.key
|
|
7
|
+
*.enc
|
|
8
|
+
secrets/
|
|
9
|
+
|
|
10
|
+
# Node / TS
|
|
11
|
+
node_modules/
|
|
12
|
+
dist/
|
|
13
|
+
build/
|
|
14
|
+
*.tsbuildinfo
|
|
15
|
+
coverage/
|
|
16
|
+
.turbo/
|
|
17
|
+
|
|
18
|
+
# Generated proto staging
|
|
19
|
+
proto/github.com/
|
|
20
|
+
|
|
21
|
+
# CLI bundles a copy of templates/ at build time; the source of truth is the
|
|
22
|
+
# root templates/ dir, so the generated copy is not tracked.
|
|
23
|
+
cli/templates/
|
|
24
|
+
|
|
25
|
+
# Generated API docs (run `pnpm --filter @qorechain/sdk docs:api`)
|
|
26
|
+
docs/api/
|
|
27
|
+
packages/ts/docs/
|
|
28
|
+
|
|
29
|
+
# Docusaurus docs site (standalone; not in the pnpm workspace)
|
|
30
|
+
.docusaurus/
|
|
31
|
+
docs/.docusaurus/
|
|
32
|
+
docs/build/
|
|
33
|
+
|
|
34
|
+
# Per-language (placeholders)
|
|
35
|
+
target/
|
|
36
|
+
__pycache__/
|
|
37
|
+
*.py[cod]
|
|
38
|
+
.venv/
|
|
39
|
+
*.egg-info/
|
|
40
|
+
.pytest_cache/
|
|
41
|
+
.mypy_cache/
|
|
42
|
+
.ruff_cache/
|
|
43
|
+
|
|
44
|
+
# OS / IDE
|
|
45
|
+
.DS_Store
|
|
46
|
+
Thumbs.db
|
|
47
|
+
.idea/
|
|
48
|
+
.vscode/
|
|
49
|
+
*.swp
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qorechain-sdk
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Python SDK for QoreChain — typed messages for every module, queries, auto-gas, tx tracking, subscriptions, accounts (native/EVM/SVM), and post-quantum signing.
|
|
5
|
+
Project-URL: Homepage, https://github.com/qorechain/qorechain-sdk
|
|
6
|
+
Project-URL: Repository, https://github.com/qorechain/qorechain-sdk
|
|
7
|
+
Project-URL: Issues, https://github.com/qorechain/qorechain-sdk/issues
|
|
8
|
+
Author-email: Liviu Epure <liviu.etty@gmail.com>
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
Keywords: blockchain,cosmos,dilithium,evm,ml-dsa,post-quantum,qorechain,svm
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: base58<3,>=2.1
|
|
21
|
+
Requires-Dist: bech32<2,>=1.2
|
|
22
|
+
Requires-Dist: bip-utils<3,>=2.9
|
|
23
|
+
Requires-Dist: cosmpy<1,>=0.11
|
|
24
|
+
Requires-Dist: dilithium-py>=1.1
|
|
25
|
+
Requires-Dist: httpx<1,>=0.27
|
|
26
|
+
Requires-Dist: websockets<16,>=12
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
31
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# qorechain (Python SDK)
|
|
36
|
+
|
|
37
|
+
A typed Python SDK for QoreChain — typed messages for every module, typed query
|
|
38
|
+
clients, auto-gas, tx tracking, error decoding, block/tx search, websocket
|
|
39
|
+
subscriptions, network presets, denom/address utilities, HD account derivation
|
|
40
|
+
(native / EVM / SVM), post-quantum (ML-DSA-87) signing, and read clients (REST +
|
|
41
|
+
`qor_` JSON-RPC). It mirrors the QoreChain TypeScript SDK surface with idiomatic
|
|
42
|
+
Python.
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install qorechain-sdk
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Python 3.10+ is required. The package ships type hints and a `py.typed` marker.
|
|
51
|
+
|
|
52
|
+
## Quickstart
|
|
53
|
+
|
|
54
|
+
### Connect a client
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from qorechain import create_client
|
|
58
|
+
|
|
59
|
+
# Defaults to the testnet preset (localhost endpoints).
|
|
60
|
+
client = create_client()
|
|
61
|
+
print(client.network.chain_id) # "qorechain-diana"
|
|
62
|
+
|
|
63
|
+
# Read account balances over REST.
|
|
64
|
+
balances = client.rest.get_all_balances("qor15yk64u7zc9g9k2yr2wmzeva5qgwxps6yjecvvu")
|
|
65
|
+
|
|
66
|
+
# Call the qor_ JSON-RPC namespace.
|
|
67
|
+
stats = client.qor.get_ai_stats()
|
|
68
|
+
|
|
69
|
+
# Estimate a fee (AI oracle with a deterministic static fallback).
|
|
70
|
+
fee = client.fees.estimate("fast")
|
|
71
|
+
|
|
72
|
+
client.close()
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Mainnet (chain id `qorechain-vladi`) is live; select it and override the
|
|
76
|
+
localhost defaults with your node URLs:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
client = create_client(
|
|
80
|
+
network="mainnet",
|
|
81
|
+
endpoints={
|
|
82
|
+
"rest": "https://rest.qore.network",
|
|
83
|
+
"evm_rpc": "https://evm.qore.network",
|
|
84
|
+
},
|
|
85
|
+
)
|
|
86
|
+
print(client.network.chain_id) # "qorechain-vladi"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Derive accounts
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from qorechain import (
|
|
93
|
+
generate_mnemonic,
|
|
94
|
+
derive_native_account,
|
|
95
|
+
derive_evm_account,
|
|
96
|
+
derive_svm_account,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
mnemonic = generate_mnemonic() # 12 words; use generate_mnemonic(256) for 24
|
|
100
|
+
|
|
101
|
+
native = derive_native_account(mnemonic, 0) # qor1...
|
|
102
|
+
evm = derive_evm_account(mnemonic, 0) # 0x... (EIP-55 checksummed)
|
|
103
|
+
svm = derive_svm_account(mnemonic, 0) # base58 ed25519 pubkey
|
|
104
|
+
|
|
105
|
+
print(native.address, evm.address, svm.address)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Derivation schemes:
|
|
109
|
+
|
|
110
|
+
| Type | Curve | Path | Address |
|
|
111
|
+
| ------ | --------- | --------------------- | ------- |
|
|
112
|
+
| native | secp256k1 | `m/44'/118'/0'/0/{i}` | bech32 `qor` of `ripemd160(sha256(pubkey))` |
|
|
113
|
+
| evm | secp256k1 | `m/44'/60'/0'/0/{i}` | `0x` + `keccak256(pubkey)[-20:]`, EIP-55 |
|
|
114
|
+
| svm | ed25519 | `m/44'/501'/{i}'/0'` | base58 of the 32-byte public key |
|
|
115
|
+
|
|
116
|
+
The mnemonic is validated (words **and** checksum) before any key is derived, so
|
|
117
|
+
a typo'd phrase raises rather than silently producing a wrong account.
|
|
118
|
+
|
|
119
|
+
### Denomination math
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from qorechain import to_base, from_base
|
|
123
|
+
|
|
124
|
+
to_base("1.5") # "1500000" (QOR -> uqor, exponent 6)
|
|
125
|
+
from_base("1500000") # "1.5"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
All conversions use integer arithmetic — never floats — so they are exact.
|
|
129
|
+
|
|
130
|
+
### Post-quantum signing (ML-DSA-87 / Dilithium-5)
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from qorechain import (
|
|
134
|
+
generate_pqc_keypair,
|
|
135
|
+
pqc_sign,
|
|
136
|
+
pqc_verify,
|
|
137
|
+
build_hybrid_signature_extension,
|
|
138
|
+
ALGORITHM_DILITHIUM5,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
kp = generate_pqc_keypair() # public 2592 B, secret 4896 B
|
|
142
|
+
sig = pqc_sign(kp.secret_key, b"msg") # signature 4627 B
|
|
143
|
+
assert pqc_verify(kp.public_key, b"msg", sig)
|
|
144
|
+
|
|
145
|
+
# Build the on-chain hybrid-signature extension (base64-encoded, Go-JSON shape).
|
|
146
|
+
ext = build_hybrid_signature_extension(ALGORITHM_DILITHIUM5, sig, kp.public_key)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Async clients
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
import asyncio
|
|
153
|
+
from qorechain import AsyncRestClient, AsyncQorClient
|
|
154
|
+
|
|
155
|
+
async def main():
|
|
156
|
+
async with AsyncRestClient("http://localhost:1317") as rest:
|
|
157
|
+
await rest.get_ai_stats()
|
|
158
|
+
async with AsyncQorClient("http://localhost:8545") as qor:
|
|
159
|
+
await qor.get_tokenomics_overview()
|
|
160
|
+
|
|
161
|
+
asyncio.run(main())
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Typed messages for every module
|
|
165
|
+
|
|
166
|
+
`msg.<module>.<name>(...)` builds any of the chain's 49 custom messages (across
|
|
167
|
+
amm / bridge / rdk / multilayer / pqc / svm / lightnode / license /
|
|
168
|
+
abstractaccount / crossvm / rlconsensus) plus the standard Cosmos modules
|
|
169
|
+
(bank / staking / distribution / gov / authz / feegrant / ibc). Each returns a
|
|
170
|
+
`Msg` (`{type_url, value}`) you pass to `send_messages` or the hybrid PQC path.
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
from cosmpy.protos.cosmos.base.v1beta1.coin_pb2 import Coin
|
|
174
|
+
from qorechain import msg, send_messages, build_hybrid_tx, generate_pqc_keypair
|
|
175
|
+
|
|
176
|
+
swap = msg.amm.swap_exact_in(
|
|
177
|
+
sender=native.address,
|
|
178
|
+
pool_id=1,
|
|
179
|
+
token_in=Coin(denom="uqor", amount="1000000"),
|
|
180
|
+
denom_out="uusdc",
|
|
181
|
+
min_out="990000",
|
|
182
|
+
)
|
|
183
|
+
delegate = msg.staking.delegate(delegator_address=native.address, validator_address="qorvaloper1...")
|
|
184
|
+
|
|
185
|
+
# Classical tx carrying any messages.
|
|
186
|
+
built = send_messages(
|
|
187
|
+
account=native, messages=[swap, delegate],
|
|
188
|
+
chain_id="qorechain-diana", account_number=0, sequence=0,
|
|
189
|
+
fee={"amount": [{"denom": "uqor", "amount": "5000"}], "gas": "200000"},
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# Or a quantum-safe hybrid (classical + ML-DSA-87) tx over the same messages.
|
|
193
|
+
hybrid = build_hybrid_tx(
|
|
194
|
+
account=native, pqc_keypair=generate_pqc_keypair(), messages=[swap],
|
|
195
|
+
fee={"amount": [{"denom": "uqor", "amount": "5000"}], "gas": "200000"},
|
|
196
|
+
chain_id="qorechain-diana", account_number=0, sequence=0,
|
|
197
|
+
)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The `qorechain_registry()` type-URL → proto map and `decode_any(type_url, value)`
|
|
201
|
+
let you parse any supported message back into a typed object.
|
|
202
|
+
|
|
203
|
+
### Typed query clients (gRPC)
|
|
204
|
+
|
|
205
|
+
Modules with a `Query` service (crossvm, lightnode, pqc, qca, reputation,
|
|
206
|
+
rlconsensus, svm) expose typed callers over a gRPC channel:
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
from qorechain import connect_query_clients
|
|
210
|
+
|
|
211
|
+
with connect_query_clients("localhost:9090") as q:
|
|
212
|
+
res = q.crossvm.message("msg-123") # -> QueryMessageResponse
|
|
213
|
+
node = q.lightnode.light_node(native.address)
|
|
214
|
+
acct = q.pqc.account(native.address)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Auto-gas, errors, tracking, search
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
from qorechain import (
|
|
221
|
+
auto_fee, GasPrice, calculate_fee, # gas
|
|
222
|
+
decode_tx_error, QoreTxError, # errors
|
|
223
|
+
wait_for_tx, broadcast_and_wait, with_retry, # tracking
|
|
224
|
+
get_tx, get_block, search_txs, build_events_query, # search
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
# Simulate -> gas_used x 1.4 x 0.025uqor.
|
|
228
|
+
fee = auto_fee("http://localhost:1317", built)
|
|
229
|
+
calculate_fee(200000, GasPrice.from_string("0.025uqor"))
|
|
230
|
+
|
|
231
|
+
# Wait for inclusion; raises a typed QoreTxError on a non-zero code.
|
|
232
|
+
included = wait_for_tx(client.rest, "TXHASH")
|
|
233
|
+
|
|
234
|
+
search_txs(client.rest, {"message.sender": native.address}, limit=20, order_by="desc")
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Websocket subscriptions
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
from qorechain import SubscriptionClient
|
|
241
|
+
|
|
242
|
+
async def run():
|
|
243
|
+
sub = await SubscriptionClient.connect("http://localhost:26657")
|
|
244
|
+
async def on_block(ev): print("block", ev)
|
|
245
|
+
unsubscribe = await sub.subscribe_new_blocks(on_block)
|
|
246
|
+
await sub.subscribe_tx({"message.sender": native.address}, lambda ev: ...)
|
|
247
|
+
# ... later ...
|
|
248
|
+
await unsubscribe()
|
|
249
|
+
await sub.close()
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Utilities
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
from qorechain import (
|
|
256
|
+
sha256_hex, keccak256_hex, ripemd160_hex,
|
|
257
|
+
parse_units, format_units,
|
|
258
|
+
is_valid_evm_address, is_valid_svm_address, to_checksum_address,
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
parse_units("1.5", 18) # 1500000000000000000
|
|
262
|
+
format_units(1500000000000000000, 18) # "1.5"
|
|
263
|
+
to_checksum_address("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed")
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Regenerating protobuf code (maintainers)
|
|
267
|
+
|
|
268
|
+
The generated protobuf modules under `src/qorechain/proto/` are committed, so
|
|
269
|
+
users never run `protoc`. To regenerate after a proto change (requires `buf`):
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
bash scripts/codegen-py.sh
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
It runs `buf generate` (public-registry `protocolbuffers/python` + `pyi`
|
|
276
|
+
plugins, pinned to the protobuf 5.29.x line), rewrites dependency imports to
|
|
277
|
+
`cosmpy`'s bundled protos so the gencode shares one descriptor pool, and writes
|
|
278
|
+
package `__init__.py` files.
|
|
279
|
+
|
|
280
|
+
## Out of scope (use a dedicated library)
|
|
281
|
+
|
|
282
|
+
Browser-wallet adapters (Keplr / MetaMask / Phantom) and viem / `@solana/web3.js`
|
|
283
|
+
-style EVM/SVM clients are intentionally **not** part of this SDK — they are
|
|
284
|
+
JS/browser-specific. In Python, talk to the EVM with [web3.py](https://web3py.readthedocs.io)
|
|
285
|
+
and to the SVM with [solana-py](https://michaelhly.github.io/solana-py/), pointing
|
|
286
|
+
them at the network's `evm_rpc` / `svm_rpc` endpoints. This SDK covers the native
|
|
287
|
+
(Cosmos-SDK) chain surface end to end.
|
|
288
|
+
|
|
289
|
+
## Development
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
python -m venv .venv
|
|
293
|
+
.venv/bin/pip install -e "packages/py[dev]"
|
|
294
|
+
.venv/bin/pytest packages/py
|
|
295
|
+
.venv/bin/mypy packages/py/src
|
|
296
|
+
.venv/bin/ruff check packages/py/src packages/py/tests
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
Apache-2.0
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# qorechain (Python SDK)
|
|
2
|
+
|
|
3
|
+
A typed Python SDK for QoreChain — typed messages for every module, typed query
|
|
4
|
+
clients, auto-gas, tx tracking, error decoding, block/tx search, websocket
|
|
5
|
+
subscriptions, network presets, denom/address utilities, HD account derivation
|
|
6
|
+
(native / EVM / SVM), post-quantum (ML-DSA-87) signing, and read clients (REST +
|
|
7
|
+
`qor_` JSON-RPC). It mirrors the QoreChain TypeScript SDK surface with idiomatic
|
|
8
|
+
Python.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install qorechain-sdk
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Python 3.10+ is required. The package ships type hints and a `py.typed` marker.
|
|
17
|
+
|
|
18
|
+
## Quickstart
|
|
19
|
+
|
|
20
|
+
### Connect a client
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from qorechain import create_client
|
|
24
|
+
|
|
25
|
+
# Defaults to the testnet preset (localhost endpoints).
|
|
26
|
+
client = create_client()
|
|
27
|
+
print(client.network.chain_id) # "qorechain-diana"
|
|
28
|
+
|
|
29
|
+
# Read account balances over REST.
|
|
30
|
+
balances = client.rest.get_all_balances("qor15yk64u7zc9g9k2yr2wmzeva5qgwxps6yjecvvu")
|
|
31
|
+
|
|
32
|
+
# Call the qor_ JSON-RPC namespace.
|
|
33
|
+
stats = client.qor.get_ai_stats()
|
|
34
|
+
|
|
35
|
+
# Estimate a fee (AI oracle with a deterministic static fallback).
|
|
36
|
+
fee = client.fees.estimate("fast")
|
|
37
|
+
|
|
38
|
+
client.close()
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Mainnet (chain id `qorechain-vladi`) is live; select it and override the
|
|
42
|
+
localhost defaults with your node URLs:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
client = create_client(
|
|
46
|
+
network="mainnet",
|
|
47
|
+
endpoints={
|
|
48
|
+
"rest": "https://rest.qore.network",
|
|
49
|
+
"evm_rpc": "https://evm.qore.network",
|
|
50
|
+
},
|
|
51
|
+
)
|
|
52
|
+
print(client.network.chain_id) # "qorechain-vladi"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Derive accounts
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from qorechain import (
|
|
59
|
+
generate_mnemonic,
|
|
60
|
+
derive_native_account,
|
|
61
|
+
derive_evm_account,
|
|
62
|
+
derive_svm_account,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
mnemonic = generate_mnemonic() # 12 words; use generate_mnemonic(256) for 24
|
|
66
|
+
|
|
67
|
+
native = derive_native_account(mnemonic, 0) # qor1...
|
|
68
|
+
evm = derive_evm_account(mnemonic, 0) # 0x... (EIP-55 checksummed)
|
|
69
|
+
svm = derive_svm_account(mnemonic, 0) # base58 ed25519 pubkey
|
|
70
|
+
|
|
71
|
+
print(native.address, evm.address, svm.address)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Derivation schemes:
|
|
75
|
+
|
|
76
|
+
| Type | Curve | Path | Address |
|
|
77
|
+
| ------ | --------- | --------------------- | ------- |
|
|
78
|
+
| native | secp256k1 | `m/44'/118'/0'/0/{i}` | bech32 `qor` of `ripemd160(sha256(pubkey))` |
|
|
79
|
+
| evm | secp256k1 | `m/44'/60'/0'/0/{i}` | `0x` + `keccak256(pubkey)[-20:]`, EIP-55 |
|
|
80
|
+
| svm | ed25519 | `m/44'/501'/{i}'/0'` | base58 of the 32-byte public key |
|
|
81
|
+
|
|
82
|
+
The mnemonic is validated (words **and** checksum) before any key is derived, so
|
|
83
|
+
a typo'd phrase raises rather than silently producing a wrong account.
|
|
84
|
+
|
|
85
|
+
### Denomination math
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from qorechain import to_base, from_base
|
|
89
|
+
|
|
90
|
+
to_base("1.5") # "1500000" (QOR -> uqor, exponent 6)
|
|
91
|
+
from_base("1500000") # "1.5"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
All conversions use integer arithmetic — never floats — so they are exact.
|
|
95
|
+
|
|
96
|
+
### Post-quantum signing (ML-DSA-87 / Dilithium-5)
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from qorechain import (
|
|
100
|
+
generate_pqc_keypair,
|
|
101
|
+
pqc_sign,
|
|
102
|
+
pqc_verify,
|
|
103
|
+
build_hybrid_signature_extension,
|
|
104
|
+
ALGORITHM_DILITHIUM5,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
kp = generate_pqc_keypair() # public 2592 B, secret 4896 B
|
|
108
|
+
sig = pqc_sign(kp.secret_key, b"msg") # signature 4627 B
|
|
109
|
+
assert pqc_verify(kp.public_key, b"msg", sig)
|
|
110
|
+
|
|
111
|
+
# Build the on-chain hybrid-signature extension (base64-encoded, Go-JSON shape).
|
|
112
|
+
ext = build_hybrid_signature_extension(ALGORITHM_DILITHIUM5, sig, kp.public_key)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Async clients
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
import asyncio
|
|
119
|
+
from qorechain import AsyncRestClient, AsyncQorClient
|
|
120
|
+
|
|
121
|
+
async def main():
|
|
122
|
+
async with AsyncRestClient("http://localhost:1317") as rest:
|
|
123
|
+
await rest.get_ai_stats()
|
|
124
|
+
async with AsyncQorClient("http://localhost:8545") as qor:
|
|
125
|
+
await qor.get_tokenomics_overview()
|
|
126
|
+
|
|
127
|
+
asyncio.run(main())
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Typed messages for every module
|
|
131
|
+
|
|
132
|
+
`msg.<module>.<name>(...)` builds any of the chain's 49 custom messages (across
|
|
133
|
+
amm / bridge / rdk / multilayer / pqc / svm / lightnode / license /
|
|
134
|
+
abstractaccount / crossvm / rlconsensus) plus the standard Cosmos modules
|
|
135
|
+
(bank / staking / distribution / gov / authz / feegrant / ibc). Each returns a
|
|
136
|
+
`Msg` (`{type_url, value}`) you pass to `send_messages` or the hybrid PQC path.
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from cosmpy.protos.cosmos.base.v1beta1.coin_pb2 import Coin
|
|
140
|
+
from qorechain import msg, send_messages, build_hybrid_tx, generate_pqc_keypair
|
|
141
|
+
|
|
142
|
+
swap = msg.amm.swap_exact_in(
|
|
143
|
+
sender=native.address,
|
|
144
|
+
pool_id=1,
|
|
145
|
+
token_in=Coin(denom="uqor", amount="1000000"),
|
|
146
|
+
denom_out="uusdc",
|
|
147
|
+
min_out="990000",
|
|
148
|
+
)
|
|
149
|
+
delegate = msg.staking.delegate(delegator_address=native.address, validator_address="qorvaloper1...")
|
|
150
|
+
|
|
151
|
+
# Classical tx carrying any messages.
|
|
152
|
+
built = send_messages(
|
|
153
|
+
account=native, messages=[swap, delegate],
|
|
154
|
+
chain_id="qorechain-diana", account_number=0, sequence=0,
|
|
155
|
+
fee={"amount": [{"denom": "uqor", "amount": "5000"}], "gas": "200000"},
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Or a quantum-safe hybrid (classical + ML-DSA-87) tx over the same messages.
|
|
159
|
+
hybrid = build_hybrid_tx(
|
|
160
|
+
account=native, pqc_keypair=generate_pqc_keypair(), messages=[swap],
|
|
161
|
+
fee={"amount": [{"denom": "uqor", "amount": "5000"}], "gas": "200000"},
|
|
162
|
+
chain_id="qorechain-diana", account_number=0, sequence=0,
|
|
163
|
+
)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The `qorechain_registry()` type-URL → proto map and `decode_any(type_url, value)`
|
|
167
|
+
let you parse any supported message back into a typed object.
|
|
168
|
+
|
|
169
|
+
### Typed query clients (gRPC)
|
|
170
|
+
|
|
171
|
+
Modules with a `Query` service (crossvm, lightnode, pqc, qca, reputation,
|
|
172
|
+
rlconsensus, svm) expose typed callers over a gRPC channel:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from qorechain import connect_query_clients
|
|
176
|
+
|
|
177
|
+
with connect_query_clients("localhost:9090") as q:
|
|
178
|
+
res = q.crossvm.message("msg-123") # -> QueryMessageResponse
|
|
179
|
+
node = q.lightnode.light_node(native.address)
|
|
180
|
+
acct = q.pqc.account(native.address)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Auto-gas, errors, tracking, search
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
from qorechain import (
|
|
187
|
+
auto_fee, GasPrice, calculate_fee, # gas
|
|
188
|
+
decode_tx_error, QoreTxError, # errors
|
|
189
|
+
wait_for_tx, broadcast_and_wait, with_retry, # tracking
|
|
190
|
+
get_tx, get_block, search_txs, build_events_query, # search
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Simulate -> gas_used x 1.4 x 0.025uqor.
|
|
194
|
+
fee = auto_fee("http://localhost:1317", built)
|
|
195
|
+
calculate_fee(200000, GasPrice.from_string("0.025uqor"))
|
|
196
|
+
|
|
197
|
+
# Wait for inclusion; raises a typed QoreTxError on a non-zero code.
|
|
198
|
+
included = wait_for_tx(client.rest, "TXHASH")
|
|
199
|
+
|
|
200
|
+
search_txs(client.rest, {"message.sender": native.address}, limit=20, order_by="desc")
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Websocket subscriptions
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
from qorechain import SubscriptionClient
|
|
207
|
+
|
|
208
|
+
async def run():
|
|
209
|
+
sub = await SubscriptionClient.connect("http://localhost:26657")
|
|
210
|
+
async def on_block(ev): print("block", ev)
|
|
211
|
+
unsubscribe = await sub.subscribe_new_blocks(on_block)
|
|
212
|
+
await sub.subscribe_tx({"message.sender": native.address}, lambda ev: ...)
|
|
213
|
+
# ... later ...
|
|
214
|
+
await unsubscribe()
|
|
215
|
+
await sub.close()
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Utilities
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
from qorechain import (
|
|
222
|
+
sha256_hex, keccak256_hex, ripemd160_hex,
|
|
223
|
+
parse_units, format_units,
|
|
224
|
+
is_valid_evm_address, is_valid_svm_address, to_checksum_address,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
parse_units("1.5", 18) # 1500000000000000000
|
|
228
|
+
format_units(1500000000000000000, 18) # "1.5"
|
|
229
|
+
to_checksum_address("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed")
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Regenerating protobuf code (maintainers)
|
|
233
|
+
|
|
234
|
+
The generated protobuf modules under `src/qorechain/proto/` are committed, so
|
|
235
|
+
users never run `protoc`. To regenerate after a proto change (requires `buf`):
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
bash scripts/codegen-py.sh
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
It runs `buf generate` (public-registry `protocolbuffers/python` + `pyi`
|
|
242
|
+
plugins, pinned to the protobuf 5.29.x line), rewrites dependency imports to
|
|
243
|
+
`cosmpy`'s bundled protos so the gencode shares one descriptor pool, and writes
|
|
244
|
+
package `__init__.py` files.
|
|
245
|
+
|
|
246
|
+
## Out of scope (use a dedicated library)
|
|
247
|
+
|
|
248
|
+
Browser-wallet adapters (Keplr / MetaMask / Phantom) and viem / `@solana/web3.js`
|
|
249
|
+
-style EVM/SVM clients are intentionally **not** part of this SDK — they are
|
|
250
|
+
JS/browser-specific. In Python, talk to the EVM with [web3.py](https://web3py.readthedocs.io)
|
|
251
|
+
and to the SVM with [solana-py](https://michaelhly.github.io/solana-py/), pointing
|
|
252
|
+
them at the network's `evm_rpc` / `svm_rpc` endpoints. This SDK covers the native
|
|
253
|
+
(Cosmos-SDK) chain surface end to end.
|
|
254
|
+
|
|
255
|
+
## Development
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
python -m venv .venv
|
|
259
|
+
.venv/bin/pip install -e "packages/py[dev]"
|
|
260
|
+
.venv/bin/pytest packages/py
|
|
261
|
+
.venv/bin/mypy packages/py/src
|
|
262
|
+
.venv/bin/ruff check packages/py/src packages/py/tests
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## License
|
|
266
|
+
|
|
267
|
+
Apache-2.0
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "qorechain-sdk"
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Python SDK for QoreChain — typed messages for every module, queries, auto-gas, tx tracking, subscriptions, accounts (native/EVM/SVM), and post-quantum signing."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "Apache-2.0"
|
|
12
|
+
authors = [{ name = "Liviu Epure", email = "liviu.etty@gmail.com" }]
|
|
13
|
+
keywords = ["qorechain", "blockchain", "cosmos", "evm", "svm", "post-quantum", "ml-dsa", "dilithium"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: Apache Software License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Typing :: Typed",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"httpx>=0.27,<1",
|
|
26
|
+
"bip-utils>=2.9,<3",
|
|
27
|
+
"bech32>=1.2,<2",
|
|
28
|
+
"base58>=2.1,<3",
|
|
29
|
+
"dilithium-py>=1.1",
|
|
30
|
+
"cosmpy>=0.11,<1",
|
|
31
|
+
"websockets>=12,<16",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"pytest>=8",
|
|
37
|
+
"pytest-asyncio>=0.23",
|
|
38
|
+
"respx>=0.21",
|
|
39
|
+
"mypy>=1.10",
|
|
40
|
+
"ruff>=0.5",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/qorechain/qorechain-sdk"
|
|
45
|
+
Repository = "https://github.com/qorechain/qorechain-sdk"
|
|
46
|
+
Issues = "https://github.com/qorechain/qorechain-sdk/issues"
|
|
47
|
+
|
|
48
|
+
[tool.hatch.build.targets.wheel]
|
|
49
|
+
packages = ["src/qorechain"]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
asyncio_mode = "auto"
|
|
54
|
+
|
|
55
|
+
[tool.mypy]
|
|
56
|
+
python_version = "3.10"
|
|
57
|
+
strict = true
|
|
58
|
+
files = ["src/qorechain"]
|
|
59
|
+
# Generated protobuf gencode is not hand-written and ships its own .pyi stubs;
|
|
60
|
+
# exclude it from strict checking (it is consumed via cosmpy's Any packing).
|
|
61
|
+
exclude = "src/qorechain/proto/"
|
|
62
|
+
|
|
63
|
+
# Third-party crypto libs ship no type stubs / py.typed marker.
|
|
64
|
+
[[tool.mypy.overrides]]
|
|
65
|
+
module = [
|
|
66
|
+
"bip_utils.*",
|
|
67
|
+
"dilithium_py.*",
|
|
68
|
+
"bech32.*",
|
|
69
|
+
"base58.*",
|
|
70
|
+
"cosmpy.*",
|
|
71
|
+
"google.protobuf.*",
|
|
72
|
+
"websockets.*",
|
|
73
|
+
"grpc",
|
|
74
|
+
"grpc.*",
|
|
75
|
+
"Crypto.*",
|
|
76
|
+
# Generated protobuf modules consumed by the typed message layer.
|
|
77
|
+
"qorechain.proto.*",
|
|
78
|
+
]
|
|
79
|
+
ignore_missing_imports = true
|
|
80
|
+
|
|
81
|
+
[tool.ruff]
|
|
82
|
+
line-length = 100
|
|
83
|
+
target-version = "py310"
|
|
84
|
+
# Generated protobuf gencode is not linted (DO NOT EDIT).
|
|
85
|
+
extend-exclude = ["src/qorechain/proto"]
|
|
86
|
+
|
|
87
|
+
[tool.ruff.lint]
|
|
88
|
+
select = ["E", "F", "I", "UP", "B"]
|