ward-protocol 0.2.4__tar.gz → 0.2.6__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.
- ward_protocol-0.2.6/PKG-INFO +208 -0
- ward_protocol-0.2.6/README.md +176 -0
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/pyproject.toml +6 -6
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/__init__.py +52 -35
- ward_protocol-0.2.6/ward/adapters/__init__.py +19 -0
- ward_protocol-0.2.6/ward/adapters/_config.py +17 -0
- ward_protocol-0.2.6/ward/adapters/axelar.py +400 -0
- ward_protocol-0.2.6/ward/adapters/flare.py +355 -0
- ward_protocol-0.2.6/ward/adapters/hedera.py +345 -0
- ward_protocol-0.2.6/ward/adapters/solana.py +357 -0
- ward_protocol-0.2.6/ward/adapters/stellar.py +365 -0
- ward_protocol-0.2.6/ward/adapters/wormhole.py +379 -0
- ward_protocol-0.2.6/ward/adapters/xdc.py +356 -0
- ward_protocol-0.2.6/ward/chain.py +179 -0
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/chain_reader.py +2 -6
- ward_protocol-0.2.6/ward/client.py +391 -0
- ward_protocol-0.2.6/ward/constants.py +148 -0
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/coverage.py +26 -1
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/keys.py +53 -10
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/monitor.py +11 -14
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/pool.py +175 -28
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/primitives.py +159 -27
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/registry.py +49 -9
- ward_protocol-0.2.6/ward/resolver.py +168 -0
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/settlement.py +110 -69
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/tx_builder.py +4 -1
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/validator.py +166 -66
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/vault_monitor.py +63 -46
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward/webhooks.py +39 -19
- ward_protocol-0.2.6/ward_protocol.egg-info/PKG-INFO +208 -0
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward_protocol.egg-info/SOURCES.txt +11 -0
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward_protocol.egg-info/requires.txt +3 -3
- ward_protocol-0.2.4/PKG-INFO +0 -342
- ward_protocol-0.2.4/README.md +0 -310
- ward_protocol-0.2.4/ward/client.py +0 -210
- ward_protocol-0.2.4/ward/constants.py +0 -163
- ward_protocol-0.2.4/ward_protocol.egg-info/PKG-INFO +0 -342
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/LICENSE +0 -0
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/setup.cfg +0 -0
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward_client.py +0 -0
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward_protocol.egg-info/dependency_links.txt +0 -0
- {ward_protocol-0.2.4 → ward_protocol-0.2.6}/ward_protocol.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ward-protocol
|
|
3
|
+
Version: 0.2.6
|
|
4
|
+
Summary: Deterministic default resolution for XLS-66 lending vaults on the XRP Ledger
|
|
5
|
+
Author-email: Ward Protocol <team@wardprotocol.org>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://wardprotocol.org
|
|
8
|
+
Project-URL: Repository, https://wardprotocol.org
|
|
9
|
+
Project-URL: Documentation, https://api.wardprotocol.org/docs
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/wflores9/ward-protocol/issues
|
|
11
|
+
Keywords: xrpl,default-protection,defi,blockchain,escrow,nft,xls-66
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
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: Topic :: Office/Business :: Financial
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: xrpl-py<5.0.0,>=4.5.0
|
|
24
|
+
Requires-Dist: httpx<1.0.0,>=0.25.0
|
|
25
|
+
Requires-Dist: pydantic<3.0.0,>=2.5.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-cov>=4.1; extra == "dev"
|
|
30
|
+
Requires-Dist: anyio[trio]>=4.0; extra == "dev"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# Ward Protocol
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/ward-protocol/)
|
|
36
|
+
[](#running-tests)
|
|
37
|
+
[](https://github.com/wflores9/ward-protocol/actions/workflows/test.yml)
|
|
38
|
+
[](https://pypi.org/project/ward-protocol/)
|
|
39
|
+
[](LICENSE)
|
|
40
|
+
|
|
41
|
+
> **`ward_signed = False — always.`**
|
|
42
|
+
> Ward constructs unsigned transactions. Institutions sign. XRPL settles.
|
|
43
|
+
> Ward is never a counterparty, never a custodian, never a signatory.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Overview
|
|
48
|
+
|
|
49
|
+
Ward Protocol is the open specification for deterministic default resolution on XLS-66 institutional lending vaults on the XRP Ledger. When a borrower defaults, nine on-chain checks run automatically against live ledger state — no oracle, no human judgment, no Ward signature. The outcome is the same every time, for every institution, regardless of who runs the vault. See real-world scenarios at [wardprotocol.org/use-cases](https://wardprotocol.org/use-cases).
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## How It Works
|
|
54
|
+
|
|
55
|
+
Full specification at [wardprotocol.org/spec](https://wardprotocol.org/spec).
|
|
56
|
+
|
|
57
|
+
Nine deterministic steps — all state from the XRPL ledger:
|
|
58
|
+
|
|
59
|
+
| Step | Check |
|
|
60
|
+
|------|-------|
|
|
61
|
+
| 1 | NFT existence + taxon 281 (XLS-20) |
|
|
62
|
+
| 2 | Policy validity — ledger `close_time` + matching on-chain premium payment |
|
|
63
|
+
| 3 | Vault address binding — NFT metadata vault == defaulted vault |
|
|
64
|
+
| 4 | `LSF_LOAN_DEFAULT` flag on `LedgerEntry(index=loan_id)` |
|
|
65
|
+
| 5 | Vault loss > 0 drops |
|
|
66
|
+
| 6 | Pool usable balance ≥ vault loss (balance − XRPL reserve) |
|
|
67
|
+
| 7 | Replay protection — NFT still live (burn-on-settlement) |
|
|
68
|
+
| 8 | Claimant holds NFT — `AccountNFTs(account=claimant)` |
|
|
69
|
+
| 9 | Pool solvency + rate limit (≤ 3/NFT/300 s, ratio ≥ 1.5×) |
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Live Status
|
|
74
|
+
|
|
75
|
+
| Metric | Value |
|
|
76
|
+
|--------|-------|
|
|
77
|
+
| SDK Version | v0.2.5 |
|
|
78
|
+
| Hosted API | api.wardprotocol.org — live |
|
|
79
|
+
| Python Tests | 317/317 passing (3.10 · 3.11 · 3.12) |
|
|
80
|
+
| Rust Tests | 40/40 passing |
|
|
81
|
+
| TypeScript Tests | 45/45 passing |
|
|
82
|
+
| Altnet E2E | F·01–F·04 confirmed on-chain |
|
|
83
|
+
| XRPLF Standard | Discussion #474 — active |
|
|
84
|
+
| Swell 2026 | Application submitted |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Quick Start
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
pip install ward-protocol==0.2.5
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
import asyncio
|
|
96
|
+
from ward import WardClient, ClaimValidator
|
|
97
|
+
|
|
98
|
+
# Purchase default-protection coverage
|
|
99
|
+
client = WardClient(url="https://s.altnet.rippletest.net:51234/")
|
|
100
|
+
result = await client.purchase_coverage(
|
|
101
|
+
wallet=depositor_wallet, # institution signs — Ward never does
|
|
102
|
+
vault_address="rVaultXXX...",
|
|
103
|
+
coverage_drops=500_000_000, # 500 XRP
|
|
104
|
+
period_days=90,
|
|
105
|
+
pool_address="rPoolXXX...",
|
|
106
|
+
)
|
|
107
|
+
assert result["ward_signed"] is False # invariant
|
|
108
|
+
|
|
109
|
+
# Validate a claim — 9 steps, all on-chain
|
|
110
|
+
validator = ClaimValidator(url="https://s.altnet.rippletest.net:51234/")
|
|
111
|
+
claim = await validator.validate_claim(
|
|
112
|
+
claimant_address="rClaimantXXX...",
|
|
113
|
+
nft_token_id="A" * 64,
|
|
114
|
+
defaulted_vault="rVaultXXX...",
|
|
115
|
+
loan_id="B" * 64,
|
|
116
|
+
pool_address="rPoolXXX...",
|
|
117
|
+
)
|
|
118
|
+
print(claim.approved) # True
|
|
119
|
+
print(claim.steps_passed) # 9
|
|
120
|
+
print(claim.claim_payout_drops) # min(vault_loss, policy_coverage)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## SDK & API
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
pip install ward-protocol # Python SDK
|
|
129
|
+
npm install ward-protocol # TypeScript SDK
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Hosted API:** `https://api.wardprotocol.org`
|
|
133
|
+
- `GET /health` — status check
|
|
134
|
+
- `POST /keys/generate` — API key (Developer tier, no auth required)
|
|
135
|
+
- `POST /validate` — 9-step claim validation
|
|
136
|
+
- `POST /purchase` — unsigned coverage transaction
|
|
137
|
+
|
|
138
|
+
Full docs: [wardprotocol.org/docs](https://wardprotocol.org/docs)
|
|
139
|
+
Build guide: [wardprotocol.org/build](https://wardprotocol.org/build)
|
|
140
|
+
Institutional readiness: [docs/institutional-readiness.md](docs/institutional-readiness.md)
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## XLS Standards
|
|
145
|
+
|
|
146
|
+
| Standard | Role in Ward |
|
|
147
|
+
|----------|-------------|
|
|
148
|
+
| XLS-66 | Lending vault + loan lifecycle — Ward resolves defaults |
|
|
149
|
+
| XLS-20 | Policy NFT (taxon 281, `TF_BURNABLE`, non-transferable) |
|
|
150
|
+
| XLS-70 | KYC/AML credential NFT (taxon 282) |
|
|
151
|
+
| XLS-80 | Domain verification for vault operators |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Multi-Chain Roadmap
|
|
156
|
+
|
|
157
|
+
| Chain | Status | Notes |
|
|
158
|
+
|-------|--------|-------|
|
|
159
|
+
| XRPL | **Live** | Altnet E2E confirmed, mainnet at XLS-66 launch |
|
|
160
|
+
| Flare EVM | Phase 1.5 | FDC enables XRPL state verification from Flare |
|
|
161
|
+
| Hedera | Phase 2 | HCS + HTS + Solidity contracts |
|
|
162
|
+
| Solana | Phase 3 | Anchor + Metaplex pNFT (Anodos Finance call June 12) |
|
|
163
|
+
| Stellar | Phase 4 | Soroban + Horizon SSE + SEP-0010 |
|
|
164
|
+
| XDC | Evaluating | XDC Network — XLS-66 compatibility assessment |
|
|
165
|
+
|
|
166
|
+
Integration plans: [docs/integration/](docs/integration/)
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Running Tests
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Python (317 unit tests)
|
|
174
|
+
pip install -r requirements.txt
|
|
175
|
+
python -m pytest test_ward.py -m "not integration" -v
|
|
176
|
+
|
|
177
|
+
# Rust (40 tests)
|
|
178
|
+
cd ward && cargo test
|
|
179
|
+
|
|
180
|
+
# TypeScript (45 tests)
|
|
181
|
+
cd sdk/typescript && npm install && npm test
|
|
182
|
+
|
|
183
|
+
# Lint
|
|
184
|
+
ruff check ward/ --select=E,F,W,I --ignore=E501
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Community
|
|
190
|
+
|
|
191
|
+
- **Discord:** [discord.gg/cGm9m5pEGK](https://discord.gg/cGm9m5pEGK)
|
|
192
|
+
- **XRPLF Discussion #474:** [github.com/XRPLF/XRPL-Standards/discussions/474](https://github.com/XRPLF/XRPL-Standards/discussions/474)
|
|
193
|
+
- **Website:** [wardprotocol.org](https://wardprotocol.org)
|
|
194
|
+
- **PyPI:** [pypi.org/project/ward-protocol](https://pypi.org/project/ward-protocol/)
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## License
|
|
199
|
+
|
|
200
|
+
The Ward Protocol specification and SDK are MIT licensed.
|
|
201
|
+
The hosted API at `api.wardprotocol.org` is subject to commercial terms.
|
|
202
|
+
Ward Protocol is protocol software — not an insurance product, financial instrument, or regulated entity.
|
|
203
|
+
|
|
204
|
+
See [wardprotocol.org/terms](https://wardprotocol.org/terms)
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
`ward_signed = False — always.`
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Ward Protocol
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/ward-protocol/)
|
|
4
|
+
[](#running-tests)
|
|
5
|
+
[](https://github.com/wflores9/ward-protocol/actions/workflows/test.yml)
|
|
6
|
+
[](https://pypi.org/project/ward-protocol/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
> **`ward_signed = False — always.`**
|
|
10
|
+
> Ward constructs unsigned transactions. Institutions sign. XRPL settles.
|
|
11
|
+
> Ward is never a counterparty, never a custodian, never a signatory.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
|
|
17
|
+
Ward Protocol is the open specification for deterministic default resolution on XLS-66 institutional lending vaults on the XRP Ledger. When a borrower defaults, nine on-chain checks run automatically against live ledger state — no oracle, no human judgment, no Ward signature. The outcome is the same every time, for every institution, regardless of who runs the vault. See real-world scenarios at [wardprotocol.org/use-cases](https://wardprotocol.org/use-cases).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## How It Works
|
|
22
|
+
|
|
23
|
+
Full specification at [wardprotocol.org/spec](https://wardprotocol.org/spec).
|
|
24
|
+
|
|
25
|
+
Nine deterministic steps — all state from the XRPL ledger:
|
|
26
|
+
|
|
27
|
+
| Step | Check |
|
|
28
|
+
|------|-------|
|
|
29
|
+
| 1 | NFT existence + taxon 281 (XLS-20) |
|
|
30
|
+
| 2 | Policy validity — ledger `close_time` + matching on-chain premium payment |
|
|
31
|
+
| 3 | Vault address binding — NFT metadata vault == defaulted vault |
|
|
32
|
+
| 4 | `LSF_LOAN_DEFAULT` flag on `LedgerEntry(index=loan_id)` |
|
|
33
|
+
| 5 | Vault loss > 0 drops |
|
|
34
|
+
| 6 | Pool usable balance ≥ vault loss (balance − XRPL reserve) |
|
|
35
|
+
| 7 | Replay protection — NFT still live (burn-on-settlement) |
|
|
36
|
+
| 8 | Claimant holds NFT — `AccountNFTs(account=claimant)` |
|
|
37
|
+
| 9 | Pool solvency + rate limit (≤ 3/NFT/300 s, ratio ≥ 1.5×) |
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Live Status
|
|
42
|
+
|
|
43
|
+
| Metric | Value |
|
|
44
|
+
|--------|-------|
|
|
45
|
+
| SDK Version | v0.2.5 |
|
|
46
|
+
| Hosted API | api.wardprotocol.org — live |
|
|
47
|
+
| Python Tests | 317/317 passing (3.10 · 3.11 · 3.12) |
|
|
48
|
+
| Rust Tests | 40/40 passing |
|
|
49
|
+
| TypeScript Tests | 45/45 passing |
|
|
50
|
+
| Altnet E2E | F·01–F·04 confirmed on-chain |
|
|
51
|
+
| XRPLF Standard | Discussion #474 — active |
|
|
52
|
+
| Swell 2026 | Application submitted |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
pip install ward-protocol==0.2.5
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
import asyncio
|
|
64
|
+
from ward import WardClient, ClaimValidator
|
|
65
|
+
|
|
66
|
+
# Purchase default-protection coverage
|
|
67
|
+
client = WardClient(url="https://s.altnet.rippletest.net:51234/")
|
|
68
|
+
result = await client.purchase_coverage(
|
|
69
|
+
wallet=depositor_wallet, # institution signs — Ward never does
|
|
70
|
+
vault_address="rVaultXXX...",
|
|
71
|
+
coverage_drops=500_000_000, # 500 XRP
|
|
72
|
+
period_days=90,
|
|
73
|
+
pool_address="rPoolXXX...",
|
|
74
|
+
)
|
|
75
|
+
assert result["ward_signed"] is False # invariant
|
|
76
|
+
|
|
77
|
+
# Validate a claim — 9 steps, all on-chain
|
|
78
|
+
validator = ClaimValidator(url="https://s.altnet.rippletest.net:51234/")
|
|
79
|
+
claim = await validator.validate_claim(
|
|
80
|
+
claimant_address="rClaimantXXX...",
|
|
81
|
+
nft_token_id="A" * 64,
|
|
82
|
+
defaulted_vault="rVaultXXX...",
|
|
83
|
+
loan_id="B" * 64,
|
|
84
|
+
pool_address="rPoolXXX...",
|
|
85
|
+
)
|
|
86
|
+
print(claim.approved) # True
|
|
87
|
+
print(claim.steps_passed) # 9
|
|
88
|
+
print(claim.claim_payout_drops) # min(vault_loss, policy_coverage)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## SDK & API
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pip install ward-protocol # Python SDK
|
|
97
|
+
npm install ward-protocol # TypeScript SDK
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Hosted API:** `https://api.wardprotocol.org`
|
|
101
|
+
- `GET /health` — status check
|
|
102
|
+
- `POST /keys/generate` — API key (Developer tier, no auth required)
|
|
103
|
+
- `POST /validate` — 9-step claim validation
|
|
104
|
+
- `POST /purchase` — unsigned coverage transaction
|
|
105
|
+
|
|
106
|
+
Full docs: [wardprotocol.org/docs](https://wardprotocol.org/docs)
|
|
107
|
+
Build guide: [wardprotocol.org/build](https://wardprotocol.org/build)
|
|
108
|
+
Institutional readiness: [docs/institutional-readiness.md](docs/institutional-readiness.md)
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## XLS Standards
|
|
113
|
+
|
|
114
|
+
| Standard | Role in Ward |
|
|
115
|
+
|----------|-------------|
|
|
116
|
+
| XLS-66 | Lending vault + loan lifecycle — Ward resolves defaults |
|
|
117
|
+
| XLS-20 | Policy NFT (taxon 281, `TF_BURNABLE`, non-transferable) |
|
|
118
|
+
| XLS-70 | KYC/AML credential NFT (taxon 282) |
|
|
119
|
+
| XLS-80 | Domain verification for vault operators |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Multi-Chain Roadmap
|
|
124
|
+
|
|
125
|
+
| Chain | Status | Notes |
|
|
126
|
+
|-------|--------|-------|
|
|
127
|
+
| XRPL | **Live** | Altnet E2E confirmed, mainnet at XLS-66 launch |
|
|
128
|
+
| Flare EVM | Phase 1.5 | FDC enables XRPL state verification from Flare |
|
|
129
|
+
| Hedera | Phase 2 | HCS + HTS + Solidity contracts |
|
|
130
|
+
| Solana | Phase 3 | Anchor + Metaplex pNFT (Anodos Finance call June 12) |
|
|
131
|
+
| Stellar | Phase 4 | Soroban + Horizon SSE + SEP-0010 |
|
|
132
|
+
| XDC | Evaluating | XDC Network — XLS-66 compatibility assessment |
|
|
133
|
+
|
|
134
|
+
Integration plans: [docs/integration/](docs/integration/)
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Running Tests
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Python (317 unit tests)
|
|
142
|
+
pip install -r requirements.txt
|
|
143
|
+
python -m pytest test_ward.py -m "not integration" -v
|
|
144
|
+
|
|
145
|
+
# Rust (40 tests)
|
|
146
|
+
cd ward && cargo test
|
|
147
|
+
|
|
148
|
+
# TypeScript (45 tests)
|
|
149
|
+
cd sdk/typescript && npm install && npm test
|
|
150
|
+
|
|
151
|
+
# Lint
|
|
152
|
+
ruff check ward/ --select=E,F,W,I --ignore=E501
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Community
|
|
158
|
+
|
|
159
|
+
- **Discord:** [discord.gg/cGm9m5pEGK](https://discord.gg/cGm9m5pEGK)
|
|
160
|
+
- **XRPLF Discussion #474:** [github.com/XRPLF/XRPL-Standards/discussions/474](https://github.com/XRPLF/XRPL-Standards/discussions/474)
|
|
161
|
+
- **Website:** [wardprotocol.org](https://wardprotocol.org)
|
|
162
|
+
- **PyPI:** [pypi.org/project/ward-protocol](https://pypi.org/project/ward-protocol/)
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
The Ward Protocol specification and SDK are MIT licensed.
|
|
169
|
+
The hosted API at `api.wardprotocol.org` is subject to commercial terms.
|
|
170
|
+
Ward Protocol is protocol software — not an insurance product, financial instrument, or regulated entity.
|
|
171
|
+
|
|
172
|
+
See [wardprotocol.org/terms](https://wardprotocol.org/terms)
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
`ward_signed = False — always.`
|
|
@@ -5,8 +5,8 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "ward-protocol"
|
|
8
|
-
version = "0.2.
|
|
9
|
-
description = "
|
|
8
|
+
version = "0.2.6"
|
|
9
|
+
description = "Deterministic default resolution for XLS-66 lending vaults on the XRP Ledger"
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
12
|
license = {text = "MIT"}
|
|
@@ -25,9 +25,9 @@ classifiers = [
|
|
|
25
25
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
26
|
]
|
|
27
27
|
dependencies = [
|
|
28
|
-
"xrpl-py>=4.5.0",
|
|
29
|
-
"httpx>=0.25.0",
|
|
30
|
-
"pydantic>=2.5.0",
|
|
28
|
+
"xrpl-py>=4.5.0,<5.0.0",
|
|
29
|
+
"httpx>=0.25.0,<1.0.0",
|
|
30
|
+
"pydantic>=2.5.0,<3.0.0",
|
|
31
31
|
]
|
|
32
32
|
|
|
33
33
|
|
|
@@ -42,7 +42,7 @@ dev = [
|
|
|
42
42
|
|
|
43
43
|
[project.urls]
|
|
44
44
|
Homepage = "https://wardprotocol.org"
|
|
45
|
-
Repository = "https://
|
|
45
|
+
Repository = "https://wardprotocol.org"
|
|
46
46
|
Documentation = "https://api.wardprotocol.org/docs"
|
|
47
47
|
"Bug Tracker" = "https://github.com/wflores9/ward-protocol/issues"
|
|
48
48
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Ward Protocol SDK — Public Package API v0.2.
|
|
2
|
+
Ward Protocol SDK — Public Package API v0.2.4
|
|
3
3
|
|
|
4
4
|
from ward import WardClient, VaultMonitor, ClaimValidator
|
|
5
5
|
from ward import EscrowSettlement, PoolHealthMonitor
|
|
@@ -7,20 +7,19 @@ Ward Protocol SDK — Public Package API v0.2.2
|
|
|
7
7
|
from ward import PoolHealth, VerifiedDefault, ValidationResult
|
|
8
8
|
|
|
9
9
|
Changelog:
|
|
10
|
-
v0.2.
|
|
11
|
-
|
|
10
|
+
v0.2.4 README/stats corrected; CI workflows overhauled; ruff.toml added.
|
|
11
|
+
v0.2.3 On-chain coverage registry; webhook notifications; TypeScript SDK.
|
|
12
|
+
v0.2.2 Add ripple_time_now, get_ledger_close_time exports; full __all__.
|
|
12
13
|
v0.2.1 Add ClaimValidator, ValidationResult, EscrowSettlement, EscrowRecord.
|
|
13
14
|
v0.2.0 Initial modular split from ward_client monolith.
|
|
14
15
|
"""
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
__version__ = "0.2.3"
|
|
17
|
+
__version__ = "0.2.4"
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
from ward.client import WardClient
|
|
21
21
|
from ward.constants import (
|
|
22
22
|
ALLOWED_WS_URLS,
|
|
23
|
-
VaultRegistration,
|
|
24
23
|
CLAIM_RATE_LIMIT_MAX,
|
|
25
24
|
CLAIM_RATE_LIMIT_WINDOW_S,
|
|
26
25
|
CREDENTIAL_NFT_TAXON,
|
|
@@ -43,6 +42,7 @@ from ward.constants import (
|
|
|
43
42
|
XRPL_BASE_RESERVE_DROPS,
|
|
44
43
|
XRPL_OWNER_RESERVE_DROPS,
|
|
45
44
|
LicenseTier,
|
|
45
|
+
VaultRegistration,
|
|
46
46
|
)
|
|
47
47
|
from ward.pool import PoolHealth, PoolHealthMonitor
|
|
48
48
|
from ward.primitives import (
|
|
@@ -50,16 +50,16 @@ from ward.primitives import (
|
|
|
50
50
|
SecurityError,
|
|
51
51
|
ValidationError,
|
|
52
52
|
WardError,
|
|
53
|
+
build_unsigned_tx,
|
|
53
54
|
check_rate_limit,
|
|
54
55
|
generate_claim_preimage,
|
|
55
56
|
get_ledger_close_time,
|
|
56
57
|
make_preimage_condition,
|
|
57
58
|
ripple_time_now,
|
|
58
|
-
|
|
59
|
+
validate_condition_hex,
|
|
59
60
|
validate_drops,
|
|
60
61
|
validate_drops_amount,
|
|
61
62
|
validate_nft_id,
|
|
62
|
-
validate_wallet,
|
|
63
63
|
validate_xrpl_address,
|
|
64
64
|
)
|
|
65
65
|
from ward.registry import (
|
|
@@ -74,48 +74,65 @@ from ward.vault_monitor import DefaultSignal, VaultMonitor, VerifiedDefault
|
|
|
74
74
|
|
|
75
75
|
__all__ = [
|
|
76
76
|
# Registry
|
|
77
|
-
"register_vault",
|
|
77
|
+
"register_vault",
|
|
78
|
+
"get_vaults",
|
|
79
|
+
"get_vault",
|
|
80
|
+
"deregister_vault",
|
|
78
81
|
"VaultRegistration",
|
|
79
|
-
|
|
80
82
|
# Core SDK classes
|
|
81
83
|
"WardClient",
|
|
82
|
-
"VaultMonitor",
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
|
|
84
|
+
"VaultMonitor",
|
|
85
|
+
"VerifiedDefault",
|
|
86
|
+
"DefaultSignal",
|
|
87
|
+
"ClaimValidator",
|
|
88
|
+
"ValidationResult",
|
|
89
|
+
"EscrowSettlement",
|
|
90
|
+
"EscrowRecord",
|
|
91
|
+
"PoolHealthMonitor",
|
|
92
|
+
"PoolHealth",
|
|
87
93
|
# Errors
|
|
88
|
-
"WardError",
|
|
89
|
-
|
|
94
|
+
"WardError",
|
|
95
|
+
"ValidationError",
|
|
96
|
+
"SecurityError",
|
|
97
|
+
"LedgerError",
|
|
90
98
|
# Validators / crypto utilities
|
|
91
|
-
"
|
|
92
|
-
"
|
|
99
|
+
"validate_condition_hex",
|
|
100
|
+
"validate_xrpl_address",
|
|
101
|
+
"validate_drops_amount",
|
|
102
|
+
"validate_drops",
|
|
103
|
+
"validate_nft_id",
|
|
93
104
|
"check_rate_limit",
|
|
94
|
-
"make_preimage_condition",
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
|
|
105
|
+
"make_preimage_condition",
|
|
106
|
+
"generate_claim_preimage",
|
|
107
|
+
"get_ledger_close_time",
|
|
108
|
+
"ripple_time_now",
|
|
109
|
+
"build_unsigned_tx",
|
|
98
110
|
# Licensing tier
|
|
99
111
|
"LicenseTier",
|
|
100
|
-
|
|
101
112
|
# Network endpoints
|
|
102
|
-
"DEFAULT_TESTNET_URL",
|
|
103
|
-
"
|
|
113
|
+
"DEFAULT_TESTNET_URL",
|
|
114
|
+
"DEFAULT_TESTNET_WS",
|
|
115
|
+
"DEFAULT_MAINNET_URL",
|
|
116
|
+
"DEFAULT_MAINNET_WS",
|
|
104
117
|
"ALLOWED_WS_URLS",
|
|
105
|
-
|
|
106
118
|
# NFT / taxon constants
|
|
107
|
-
"WARD_POLICY_TAXON",
|
|
108
|
-
"
|
|
119
|
+
"WARD_POLICY_TAXON",
|
|
120
|
+
"WARD_CREDENTIAL_TAXON",
|
|
121
|
+
"CREDENTIAL_NFT_TAXON",
|
|
122
|
+
"TF_BURNABLE",
|
|
123
|
+
"TF_TRANSFERABLE",
|
|
109
124
|
"VALID_KYC_TYPES",
|
|
110
|
-
|
|
111
125
|
# Risk / rate constants
|
|
112
126
|
"MIN_COVERAGE_RATIO",
|
|
113
|
-
"CLAIM_RATE_LIMIT_MAX",
|
|
114
|
-
"
|
|
127
|
+
"CLAIM_RATE_LIMIT_MAX",
|
|
128
|
+
"CLAIM_RATE_LIMIT_WINDOW_S",
|
|
129
|
+
"ESCROW_DISPUTE_HOURS",
|
|
130
|
+
"ESCROW_CANCEL_HOURS",
|
|
115
131
|
"MONITOR_HEARTBEAT_TIMEOUT_S",
|
|
116
|
-
|
|
117
132
|
# XRPL chain constants
|
|
118
133
|
"LSF_LOAN_DEFAULT",
|
|
119
|
-
"XRPL_BASE_RESERVE_DROPS",
|
|
120
|
-
"
|
|
134
|
+
"XRPL_BASE_RESERVE_DROPS",
|
|
135
|
+
"XRPL_OWNER_RESERVE_DROPS",
|
|
136
|
+
"XRP_MAX_DROPS",
|
|
137
|
+
"RIPPLE_EPOCH_OFFSET",
|
|
121
138
|
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Ward Protocol chain adapters."""
|
|
2
|
+
|
|
3
|
+
from ward.adapters.axelar import AxelarAdapter
|
|
4
|
+
from ward.adapters.flare import FlareAdapter
|
|
5
|
+
from ward.adapters.hedera import HederaAdapter
|
|
6
|
+
from ward.adapters.solana import SolanaAdapter
|
|
7
|
+
from ward.adapters.stellar import StellarAdapter
|
|
8
|
+
from ward.adapters.wormhole import WormholeNTTAdapter
|
|
9
|
+
from ward.adapters.xdc import XDCAdapter
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"WormholeNTTAdapter",
|
|
13
|
+
"FlareAdapter",
|
|
14
|
+
"AxelarAdapter",
|
|
15
|
+
"SolanaAdapter",
|
|
16
|
+
"HederaAdapter",
|
|
17
|
+
"StellarAdapter",
|
|
18
|
+
"XDCAdapter",
|
|
19
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Shared configuration guards for institutional-grade chain adapters."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def require_non_placeholder(
|
|
7
|
+
value: str,
|
|
8
|
+
*,
|
|
9
|
+
field_name: str,
|
|
10
|
+
invalid_values: set[str],
|
|
11
|
+
) -> str:
|
|
12
|
+
"""Reject placeholder configuration that would silently misroute funds."""
|
|
13
|
+
if value in invalid_values:
|
|
14
|
+
raise ValueError(
|
|
15
|
+
f"{field_name} must be explicitly configured; placeholder defaults are blocked"
|
|
16
|
+
)
|
|
17
|
+
return value
|