digirails 0.1.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.
- digirails-0.1.0/.gitignore +22 -0
- digirails-0.1.0/LICENSE +21 -0
- digirails-0.1.0/PKG-INFO +155 -0
- digirails-0.1.0/README.md +119 -0
- digirails-0.1.0/examples/cross_sdk_buyer.py +62 -0
- digirails-0.1.0/examples/quickstart_buyer.py +36 -0
- digirails-0.1.0/examples/quickstart_seller.py +47 -0
- digirails-0.1.0/examples/regtest_demo.py +86 -0
- digirails-0.1.0/pyproject.toml +57 -0
- digirails-0.1.0/src/digirails/__init__.py +39 -0
- digirails-0.1.0/src/digirails/_opreturn.py +168 -0
- digirails-0.1.0/src/digirails/_version.py +1 -0
- digirails-0.1.0/src/digirails/agent.py +208 -0
- digirails-0.1.0/src/digirails/config.py +66 -0
- digirails-0.1.0/src/digirails/crypto/__init__.py +19 -0
- digirails-0.1.0/src/digirails/crypto/base58.py +66 -0
- digirails-0.1.0/src/digirails/crypto/bech32.py +132 -0
- digirails-0.1.0/src/digirails/crypto/keys.py +146 -0
- digirails-0.1.0/src/digirails/crypto/script.py +84 -0
- digirails-0.1.0/src/digirails/crypto/transaction.py +295 -0
- digirails-0.1.0/src/digirails/discovery/__init__.py +0 -0
- digirails-0.1.0/src/digirails/discovery/manifest_client.py +28 -0
- digirails-0.1.0/src/digirails/exceptions.py +43 -0
- digirails-0.1.0/src/digirails/models/__init__.py +28 -0
- digirails-0.1.0/src/digirails/models/enums.py +78 -0
- digirails-0.1.0/src/digirails/models/manifest.py +58 -0
- digirails-0.1.0/src/digirails/models/messages.py +117 -0
- digirails-0.1.0/src/digirails/network/__init__.py +22 -0
- digirails-0.1.0/src/digirails/network/constants.py +66 -0
- digirails-0.1.0/src/digirails/network/params.py +59 -0
- digirails-0.1.0/src/digirails/payment/__init__.py +0 -0
- digirails-0.1.0/src/digirails/payment/buyer.py +134 -0
- digirails-0.1.0/src/digirails/payment/flow.py +50 -0
- digirails-0.1.0/src/digirails/payment/seller.py +238 -0
- digirails-0.1.0/src/digirails/payment/verification.py +123 -0
- digirails-0.1.0/src/digirails/rpc/__init__.py +0 -0
- digirails-0.1.0/src/digirails/rpc/client.py +135 -0
- digirails-0.1.0/src/digirails/server.py +128 -0
- digirails-0.1.0/src/digirails/wallet/__init__.py +0 -0
- digirails-0.1.0/src/digirails/wallet/keystore.py +126 -0
- digirails-0.1.0/src/digirails/wallet/utxo.py +74 -0
- digirails-0.1.0/src/digirails/wallet/wallet.py +256 -0
- digirails-0.1.0/tests/conftest.py +16 -0
- digirails-0.1.0/tests/test_auto_refund.py +281 -0
- digirails-0.1.0/tests/test_bech32.py +52 -0
- digirails-0.1.0/tests/test_crypto.py +111 -0
- digirails-0.1.0/tests/test_models.py +174 -0
- digirails-0.1.0/tests/test_opreturn.py +222 -0
- digirails-0.1.0/tests/test_transaction.py +118 -0
- digirails-0.1.0/tests/test_wallet.py +108 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.eggs/
|
|
8
|
+
*.egg
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
env/
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
htmlcov/
|
|
16
|
+
.coverage
|
|
17
|
+
*.so
|
|
18
|
+
*.dylib
|
|
19
|
+
*.pyd
|
|
20
|
+
.env
|
|
21
|
+
*.keyfile
|
|
22
|
+
NUL
|
digirails-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DigiRails Protocol Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
digirails-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: digirails
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the DR-Pay protocol — AI agent payments on DigiByte
|
|
5
|
+
Project-URL: Homepage, https://github.com/digirails-protocol/digirails-python
|
|
6
|
+
Project-URL: Repository, https://github.com/digirails-protocol/digirails-python
|
|
7
|
+
Project-URL: Specification, https://github.com/digirails-protocol/digirails-spec
|
|
8
|
+
Author: DigiRails Protocol
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai-agents,blockchain,cryptocurrency,digibyte,payments
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Framework :: AsyncIO
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: aiohttp>=3.9
|
|
23
|
+
Requires-Dist: cryptography>=42.0
|
|
24
|
+
Requires-Dist: ecdsa>=0.19
|
|
25
|
+
Requires-Dist: pydantic>=2.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: aioresponses; extra == 'dev'
|
|
28
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
33
|
+
Provides-Extra: fast
|
|
34
|
+
Requires-Dist: coincurve>=20.0; extra == 'fast'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# digirails
|
|
38
|
+
|
|
39
|
+
Python SDK for the [DR-Pay protocol](https://github.com/digirails-protocol/digirails-spec) — permissionless AI agent payments on DigiByte.
|
|
40
|
+
|
|
41
|
+
## What is this?
|
|
42
|
+
|
|
43
|
+
DigiRails enables autonomous AI agents to discover, negotiate with, and pay each other using DigiByte's Layer 1 blockchain. This SDK implements the DR-Pay protocol: the 4-message payment flow, agent identity, service manifests, and on-chain data encoding.
|
|
44
|
+
|
|
45
|
+
Every payment settles on-chain as a standard DigiByte transaction. No sidechains, no Layer 2, no API keys.
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install digirails
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
### Buyer — purchase a service in one call
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
import asyncio
|
|
59
|
+
from digirails import Agent, REGTEST
|
|
60
|
+
|
|
61
|
+
async def main():
|
|
62
|
+
async with Agent.generate(
|
|
63
|
+
network=REGTEST,
|
|
64
|
+
rpc_url="http://digirails:digirails@127.0.0.1:18443",
|
|
65
|
+
) as buyer:
|
|
66
|
+
result = await buyer.request_service(
|
|
67
|
+
seller_url="http://127.0.0.1:9001",
|
|
68
|
+
service_id="echo",
|
|
69
|
+
params={"message": "Hello from DigiRails!"},
|
|
70
|
+
max_amount="0.01",
|
|
71
|
+
)
|
|
72
|
+
print(result.result)
|
|
73
|
+
|
|
74
|
+
asyncio.run(main())
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Seller — offer a service
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import asyncio
|
|
81
|
+
from digirails import Agent, ServiceCategory, REGTEST
|
|
82
|
+
|
|
83
|
+
def handle_echo(params: dict) -> dict:
|
|
84
|
+
return {"echo": params.get("message", "")}
|
|
85
|
+
|
|
86
|
+
async def main():
|
|
87
|
+
seller = Agent.generate(
|
|
88
|
+
network=REGTEST,
|
|
89
|
+
rpc_url="http://digirails:digirails@127.0.0.1:18443",
|
|
90
|
+
)
|
|
91
|
+
seller.register_service(
|
|
92
|
+
service_id="echo",
|
|
93
|
+
handler=handle_echo,
|
|
94
|
+
price="0.001",
|
|
95
|
+
category=ServiceCategory.GENERAL_COMPUTE,
|
|
96
|
+
)
|
|
97
|
+
await seller.serve(port=9001)
|
|
98
|
+
await asyncio.Event().wait() # Run forever
|
|
99
|
+
|
|
100
|
+
asyncio.run(main())
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## What happens under the hood
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
Buyer Seller
|
|
107
|
+
| |
|
|
108
|
+
| GET /.well-known/digirails.json |
|
|
109
|
+
|----------------------------------->| 1. Discover manifest
|
|
110
|
+
|<-----------------------------------|
|
|
111
|
+
| |
|
|
112
|
+
| POST /drpay/request |
|
|
113
|
+
|----------------------------------->| 2. SERVICE_REQUEST
|
|
114
|
+
|<-----------------------------------| 3. PAYMENT_INVOICE
|
|
115
|
+
| |
|
|
116
|
+
| [build, sign, broadcast tx] |
|
|
117
|
+
| |
|
|
118
|
+
| POST /drpay/broadcast |
|
|
119
|
+
|----------------------------------->| 4. PAYMENT_BROADCAST
|
|
120
|
+
| | 5. Verify payment
|
|
121
|
+
| | 6. Execute service
|
|
122
|
+
|<-----------------------------------| 7. SERVICE_DELIVERY
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Regtest Demo
|
|
126
|
+
|
|
127
|
+
Run the self-contained demo with two agents transacting locally:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# 1. Start DigiByte Core in regtest mode
|
|
131
|
+
digibyted -regtest -daemon -server \
|
|
132
|
+
-rpcuser=digirails -rpcpassword=digirails \
|
|
133
|
+
-txindex=1 -fallbackfee=0.0001
|
|
134
|
+
|
|
135
|
+
# 2. Run the demo
|
|
136
|
+
python examples/regtest_demo.py
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Features
|
|
140
|
+
|
|
141
|
+
- **Light mode**: No DigiByte node required. Connects to `rpc.digirails.org` or any RPC endpoint.
|
|
142
|
+
- **Async-native**: Built on asyncio + aiohttp.
|
|
143
|
+
- **Type-safe**: Pydantic models for all protocol messages.
|
|
144
|
+
- **4 dependencies**: pydantic, aiohttp, cryptography, ecdsa. All with pre-built wheels.
|
|
145
|
+
- **SegWit transactions**: BIP-143 signing for P2WPKH inputs.
|
|
146
|
+
- **Encrypted keystore**: AES-256-GCM encrypted key files.
|
|
147
|
+
- **All 18 service categories** from the DR-Pay spec.
|
|
148
|
+
|
|
149
|
+
## Protocol Version
|
|
150
|
+
|
|
151
|
+
Implements DR-Pay specification v0.3.0.
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
MIT
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# digirails
|
|
2
|
+
|
|
3
|
+
Python SDK for the [DR-Pay protocol](https://github.com/digirails-protocol/digirails-spec) — permissionless AI agent payments on DigiByte.
|
|
4
|
+
|
|
5
|
+
## What is this?
|
|
6
|
+
|
|
7
|
+
DigiRails enables autonomous AI agents to discover, negotiate with, and pay each other using DigiByte's Layer 1 blockchain. This SDK implements the DR-Pay protocol: the 4-message payment flow, agent identity, service manifests, and on-chain data encoding.
|
|
8
|
+
|
|
9
|
+
Every payment settles on-chain as a standard DigiByte transaction. No sidechains, no Layer 2, no API keys.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install digirails
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### Buyer — purchase a service in one call
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import asyncio
|
|
23
|
+
from digirails import Agent, REGTEST
|
|
24
|
+
|
|
25
|
+
async def main():
|
|
26
|
+
async with Agent.generate(
|
|
27
|
+
network=REGTEST,
|
|
28
|
+
rpc_url="http://digirails:digirails@127.0.0.1:18443",
|
|
29
|
+
) as buyer:
|
|
30
|
+
result = await buyer.request_service(
|
|
31
|
+
seller_url="http://127.0.0.1:9001",
|
|
32
|
+
service_id="echo",
|
|
33
|
+
params={"message": "Hello from DigiRails!"},
|
|
34
|
+
max_amount="0.01",
|
|
35
|
+
)
|
|
36
|
+
print(result.result)
|
|
37
|
+
|
|
38
|
+
asyncio.run(main())
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Seller — offer a service
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
import asyncio
|
|
45
|
+
from digirails import Agent, ServiceCategory, REGTEST
|
|
46
|
+
|
|
47
|
+
def handle_echo(params: dict) -> dict:
|
|
48
|
+
return {"echo": params.get("message", "")}
|
|
49
|
+
|
|
50
|
+
async def main():
|
|
51
|
+
seller = Agent.generate(
|
|
52
|
+
network=REGTEST,
|
|
53
|
+
rpc_url="http://digirails:digirails@127.0.0.1:18443",
|
|
54
|
+
)
|
|
55
|
+
seller.register_service(
|
|
56
|
+
service_id="echo",
|
|
57
|
+
handler=handle_echo,
|
|
58
|
+
price="0.001",
|
|
59
|
+
category=ServiceCategory.GENERAL_COMPUTE,
|
|
60
|
+
)
|
|
61
|
+
await seller.serve(port=9001)
|
|
62
|
+
await asyncio.Event().wait() # Run forever
|
|
63
|
+
|
|
64
|
+
asyncio.run(main())
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## What happens under the hood
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Buyer Seller
|
|
71
|
+
| |
|
|
72
|
+
| GET /.well-known/digirails.json |
|
|
73
|
+
|----------------------------------->| 1. Discover manifest
|
|
74
|
+
|<-----------------------------------|
|
|
75
|
+
| |
|
|
76
|
+
| POST /drpay/request |
|
|
77
|
+
|----------------------------------->| 2. SERVICE_REQUEST
|
|
78
|
+
|<-----------------------------------| 3. PAYMENT_INVOICE
|
|
79
|
+
| |
|
|
80
|
+
| [build, sign, broadcast tx] |
|
|
81
|
+
| |
|
|
82
|
+
| POST /drpay/broadcast |
|
|
83
|
+
|----------------------------------->| 4. PAYMENT_BROADCAST
|
|
84
|
+
| | 5. Verify payment
|
|
85
|
+
| | 6. Execute service
|
|
86
|
+
|<-----------------------------------| 7. SERVICE_DELIVERY
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Regtest Demo
|
|
90
|
+
|
|
91
|
+
Run the self-contained demo with two agents transacting locally:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# 1. Start DigiByte Core in regtest mode
|
|
95
|
+
digibyted -regtest -daemon -server \
|
|
96
|
+
-rpcuser=digirails -rpcpassword=digirails \
|
|
97
|
+
-txindex=1 -fallbackfee=0.0001
|
|
98
|
+
|
|
99
|
+
# 2. Run the demo
|
|
100
|
+
python examples/regtest_demo.py
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Features
|
|
104
|
+
|
|
105
|
+
- **Light mode**: No DigiByte node required. Connects to `rpc.digirails.org` or any RPC endpoint.
|
|
106
|
+
- **Async-native**: Built on asyncio + aiohttp.
|
|
107
|
+
- **Type-safe**: Pydantic models for all protocol messages.
|
|
108
|
+
- **4 dependencies**: pydantic, aiohttp, cryptography, ecdsa. All with pre-built wheels.
|
|
109
|
+
- **SegWit transactions**: BIP-143 signing for P2WPKH inputs.
|
|
110
|
+
- **Encrypted keystore**: AES-256-GCM encrypted key files.
|
|
111
|
+
- **All 18 service categories** from the DR-Pay spec.
|
|
112
|
+
|
|
113
|
+
## Protocol Version
|
|
114
|
+
|
|
115
|
+
Implements DR-Pay specification v0.3.0.
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
MIT
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Cross-SDK test: Python buyer paying a Node.js seller.
|
|
2
|
+
|
|
3
|
+
Prerequisites:
|
|
4
|
+
1. DGB Core regtest running with a legacy wallet
|
|
5
|
+
2. Node.js seller running: npx tsx examples/cross_sdk_seller.ts
|
|
6
|
+
(from the digirails-node directory)
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python cross_sdk_buyer.py
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
from digirails import Agent, REGTEST
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async def main():
|
|
17
|
+
rpc_url = "http://digirails:digirails@127.0.0.1:18443"
|
|
18
|
+
|
|
19
|
+
buyer = Agent.generate(network=REGTEST, rpc_url=rpc_url)
|
|
20
|
+
print(f"PYTHON BUYER address: {buyer.address}")
|
|
21
|
+
|
|
22
|
+
# Fund buyer
|
|
23
|
+
await buyer.rpc.importaddress(buyer.address, "buyer", False)
|
|
24
|
+
await buyer.rpc.generatetoaddress(101, buyer.address)
|
|
25
|
+
balance = await buyer.balance()
|
|
26
|
+
print(f"Buyer funded: {balance} DGB")
|
|
27
|
+
print()
|
|
28
|
+
|
|
29
|
+
# Discover Node.js seller manifest
|
|
30
|
+
manifest = await buyer.discover("http://127.0.0.1:9003")
|
|
31
|
+
if manifest:
|
|
32
|
+
print(f"Discovered seller: {manifest.agent}")
|
|
33
|
+
print(f" Services: {[s.id for s in manifest.services]}")
|
|
34
|
+
else:
|
|
35
|
+
print("ERROR: Could not discover seller manifest!")
|
|
36
|
+
await buyer.close()
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
print()
|
|
40
|
+
print("=== Cross-SDK Payment Flow (Python buyer -> Node.js seller) ===")
|
|
41
|
+
|
|
42
|
+
result = await buyer.request_service(
|
|
43
|
+
seller_url="http://127.0.0.1:9003",
|
|
44
|
+
service_id="echo",
|
|
45
|
+
params={"message": "Hello from Python to Node.js!"},
|
|
46
|
+
max_amount="0.01",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
print(f"Result: {result.result}")
|
|
50
|
+
print(f"Status: {result.status}")
|
|
51
|
+
print()
|
|
52
|
+
|
|
53
|
+
if result.result and result.result.get("cross_sdk"):
|
|
54
|
+
print("=== CROSS-SDK INTEROP TEST PASSED ===")
|
|
55
|
+
else:
|
|
56
|
+
print("=== CROSS-SDK TEST FAILED ===")
|
|
57
|
+
|
|
58
|
+
await buyer.close()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
if __name__ == "__main__":
|
|
62
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Buy a service from a DigiRails agent.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
python quickstart_buyer.py
|
|
5
|
+
|
|
6
|
+
Requires a seller running at http://127.0.0.1:9001.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
|
|
11
|
+
from digirails import Agent, REGTEST
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def main():
|
|
15
|
+
async with Agent.generate(
|
|
16
|
+
network=REGTEST,
|
|
17
|
+
rpc_url="http://digirails:digirails@127.0.0.1:18443",
|
|
18
|
+
) as buyer:
|
|
19
|
+
print(f"Buyer address: {buyer.address}")
|
|
20
|
+
|
|
21
|
+
# Fund the buyer (regtest only: mine 101 blocks for coinbase maturity)
|
|
22
|
+
await buyer.rpc.generatetoaddress(101, buyer.address)
|
|
23
|
+
print(f"Balance: {await buyer.balance()} DGB")
|
|
24
|
+
|
|
25
|
+
# Buy a service — one line!
|
|
26
|
+
result = await buyer.request_service(
|
|
27
|
+
seller_url="http://127.0.0.1:9001",
|
|
28
|
+
service_id="echo",
|
|
29
|
+
params={"message": "Hello from DigiRails!"},
|
|
30
|
+
max_amount="0.01",
|
|
31
|
+
)
|
|
32
|
+
print(f"Service delivered: {result.result}")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Sell a service via DigiRails.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
python quickstart_seller.py
|
|
5
|
+
|
|
6
|
+
Starts a server on port 9001 that other agents can buy from.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
|
|
11
|
+
from digirails import Agent, ServiceCategory, REGTEST
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def handle_echo(params: dict) -> dict:
|
|
15
|
+
"""Simple echo service handler."""
|
|
16
|
+
return {"echo": params.get("message", "No message provided")}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
async def main():
|
|
20
|
+
seller = Agent.generate(
|
|
21
|
+
network=REGTEST,
|
|
22
|
+
rpc_url="http://digirails:digirails@127.0.0.1:18443",
|
|
23
|
+
)
|
|
24
|
+
print(f"Seller address: {seller.address}")
|
|
25
|
+
|
|
26
|
+
seller.register_service(
|
|
27
|
+
service_id="echo",
|
|
28
|
+
handler=handle_echo,
|
|
29
|
+
price="0.001",
|
|
30
|
+
description="Simple echo service — returns your message back",
|
|
31
|
+
category=ServiceCategory.GENERAL_COMPUTE,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
print("Starting server on http://0.0.0.0:9001")
|
|
35
|
+
print("Other agents can now buy the 'echo' service.")
|
|
36
|
+
await seller.serve(port=9001)
|
|
37
|
+
|
|
38
|
+
# Keep running
|
|
39
|
+
try:
|
|
40
|
+
while True:
|
|
41
|
+
await asyncio.sleep(3600)
|
|
42
|
+
except KeyboardInterrupt:
|
|
43
|
+
await seller.close()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Self-contained regtest demo: two agents transact.
|
|
2
|
+
|
|
3
|
+
Prerequisites:
|
|
4
|
+
1. DigiByte Core running in regtest mode:
|
|
5
|
+
digibyted -regtest -daemon -server -rpcuser=digirails -rpcpassword=digirails -txindex=1 -fallbackfee=0.0001
|
|
6
|
+
|
|
7
|
+
2. Install the SDK:
|
|
8
|
+
pip install digirails
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
python regtest_demo.py
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import asyncio
|
|
15
|
+
|
|
16
|
+
from digirails import Agent, ServiceCategory, REGTEST
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def handle_echo(params: dict) -> dict:
|
|
20
|
+
"""Echo service: returns the input message."""
|
|
21
|
+
return {"echo": params.get("message", "(empty)"), "processed_by": "digirails-demo-seller"}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
async def main():
|
|
25
|
+
rpc_url = "http://digirails:digirails@127.0.0.1:18443"
|
|
26
|
+
|
|
27
|
+
# --- Create agents ---
|
|
28
|
+
seller = Agent.generate(network=REGTEST, rpc_url=rpc_url)
|
|
29
|
+
buyer = Agent.generate(network=REGTEST, rpc_url=rpc_url)
|
|
30
|
+
|
|
31
|
+
print(f"Seller address: {seller.address}")
|
|
32
|
+
print(f"Buyer address: {buyer.address}")
|
|
33
|
+
print()
|
|
34
|
+
|
|
35
|
+
# --- Register a service on the seller ---
|
|
36
|
+
seller.register_service(
|
|
37
|
+
service_id="echo",
|
|
38
|
+
handler=handle_echo,
|
|
39
|
+
price="0.001",
|
|
40
|
+
description="Echo service",
|
|
41
|
+
category=ServiceCategory.GENERAL_COMPUTE,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Start seller HTTP server in background
|
|
45
|
+
await seller.serve(host="127.0.0.1", port=9001)
|
|
46
|
+
print("Seller server running on http://127.0.0.1:9001")
|
|
47
|
+
|
|
48
|
+
# --- Fund the buyer ---
|
|
49
|
+
# Import buyer's address so listunspent can find coinbase outputs
|
|
50
|
+
await buyer.rpc.importaddress(buyer.address, "buyer", False)
|
|
51
|
+
# Mine 101 blocks to buyer's address (coinbase maturity = 100)
|
|
52
|
+
await buyer.rpc.generatetoaddress(101, buyer.address)
|
|
53
|
+
balance = await buyer.balance()
|
|
54
|
+
print(f"Buyer funded: {balance} DGB")
|
|
55
|
+
print()
|
|
56
|
+
|
|
57
|
+
# --- Execute the payment flow ---
|
|
58
|
+
print("=== Payment Flow ===")
|
|
59
|
+
print("1. Buyer discovers seller manifest...")
|
|
60
|
+
print("2. Buyer sends SERVICE_REQUEST...")
|
|
61
|
+
print("3. Seller returns PAYMENT_INVOICE...")
|
|
62
|
+
print("4. Buyer builds, signs, broadcasts TX...")
|
|
63
|
+
print("5. Buyer sends PAYMENT_BROADCAST...")
|
|
64
|
+
print("6. Seller verifies payment, executes service...")
|
|
65
|
+
print("7. Seller returns SERVICE_DELIVERY...")
|
|
66
|
+
print()
|
|
67
|
+
|
|
68
|
+
result = await buyer.request_service(
|
|
69
|
+
seller_url="http://127.0.0.1:9001",
|
|
70
|
+
service_id="echo",
|
|
71
|
+
params={"message": "Hello from DigiRails!"},
|
|
72
|
+
max_amount="0.01",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
print(f"Result: {result.result}")
|
|
76
|
+
print(f"Status: {result.status}")
|
|
77
|
+
print()
|
|
78
|
+
print("=== Demo Complete ===")
|
|
79
|
+
|
|
80
|
+
# Cleanup
|
|
81
|
+
await seller.close()
|
|
82
|
+
await buyer.close()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "digirails"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for the DR-Pay protocol — AI agent payments on DigiByte"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "DigiRails Protocol" }]
|
|
13
|
+
keywords = ["digibyte", "payments", "ai-agents", "blockchain", "cryptocurrency"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Framework :: AsyncIO",
|
|
23
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"pydantic>=2.0",
|
|
27
|
+
"aiohttp>=3.9",
|
|
28
|
+
"cryptography>=42.0",
|
|
29
|
+
"ecdsa>=0.19",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
fast = ["coincurve>=20.0"]
|
|
34
|
+
dev = [
|
|
35
|
+
"pytest>=8.0",
|
|
36
|
+
"pytest-asyncio>=0.23",
|
|
37
|
+
"pytest-cov",
|
|
38
|
+
"aioresponses",
|
|
39
|
+
"ruff",
|
|
40
|
+
"mypy",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/digirails-protocol/digirails-python"
|
|
45
|
+
Repository = "https://github.com/digirails-protocol/digirails-python"
|
|
46
|
+
Specification = "https://github.com/digirails-protocol/digirails-spec"
|
|
47
|
+
|
|
48
|
+
[tool.hatch.build.targets.wheel]
|
|
49
|
+
packages = ["src/digirails"]
|
|
50
|
+
|
|
51
|
+
[tool.ruff]
|
|
52
|
+
target-version = "py310"
|
|
53
|
+
line-length = 100
|
|
54
|
+
|
|
55
|
+
[tool.pytest.ini_options]
|
|
56
|
+
asyncio_mode = "auto"
|
|
57
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""DigiRails — Python SDK for the DR-Pay protocol."""
|
|
2
|
+
|
|
3
|
+
from digirails._version import __version__
|
|
4
|
+
from digirails.agent import Agent
|
|
5
|
+
from digirails.config import DigiRailsConfig
|
|
6
|
+
from digirails.models.enums import ConfirmationTier, ErrorCode, ServiceCategory
|
|
7
|
+
from digirails.models.manifest import Manifest, Service
|
|
8
|
+
from digirails.models.messages import (
|
|
9
|
+
ErrorResponse,
|
|
10
|
+
PaymentBroadcast,
|
|
11
|
+
PaymentInvoice,
|
|
12
|
+
PaymentRequest,
|
|
13
|
+
RefundInfo,
|
|
14
|
+
ServiceDelivery,
|
|
15
|
+
)
|
|
16
|
+
from digirails.network.params import MAINNET, REGTEST, TESTNET, NetworkParams
|
|
17
|
+
from digirails.wallet.wallet import Wallet
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"__version__",
|
|
21
|
+
"Agent",
|
|
22
|
+
"DigiRailsConfig",
|
|
23
|
+
"Wallet",
|
|
24
|
+
"Manifest",
|
|
25
|
+
"Service",
|
|
26
|
+
"PaymentRequest",
|
|
27
|
+
"PaymentInvoice",
|
|
28
|
+
"PaymentBroadcast",
|
|
29
|
+
"ServiceDelivery",
|
|
30
|
+
"ErrorResponse",
|
|
31
|
+
"RefundInfo",
|
|
32
|
+
"ConfirmationTier",
|
|
33
|
+
"ServiceCategory",
|
|
34
|
+
"ErrorCode",
|
|
35
|
+
"NetworkParams",
|
|
36
|
+
"MAINNET",
|
|
37
|
+
"TESTNET",
|
|
38
|
+
"REGTEST",
|
|
39
|
+
]
|