feeless402 0.2.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.
- feeless402-0.2.0/LICENSE +21 -0
- feeless402-0.2.0/PKG-INFO +120 -0
- feeless402-0.2.0/README.md +89 -0
- feeless402-0.2.0/feeless402.egg-info/PKG-INFO +120 -0
- feeless402-0.2.0/feeless402.egg-info/SOURCES.txt +19 -0
- feeless402-0.2.0/feeless402.egg-info/dependency_links.txt +1 -0
- feeless402-0.2.0/feeless402.egg-info/entry_points.txt +3 -0
- feeless402-0.2.0/feeless402.egg-info/requires.txt +14 -0
- feeless402-0.2.0/feeless402.egg-info/top_level.txt +1 -0
- feeless402-0.2.0/nano_pay/__init__.py +17 -0
- feeless402-0.2.0/nano_pay/cli.py +330 -0
- feeless402-0.2.0/nano_pay/mcp_server.py +167 -0
- feeless402-0.2.0/nano_pay/rpc.py +111 -0
- feeless402-0.2.0/nano_pay/server.py +307 -0
- feeless402-0.2.0/nano_pay/topup.py +88 -0
- feeless402-0.2.0/nano_pay/verify.py +108 -0
- feeless402-0.2.0/nano_pay/wallet.py +197 -0
- feeless402-0.2.0/nano_pay/x402.py +262 -0
- feeless402-0.2.0/pyproject.toml +38 -0
- feeless402-0.2.0/setup.cfg +4 -0
- feeless402-0.2.0/tests/test_payment_path.py +216 -0
feeless402-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Feeless402 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.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: feeless402
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Feeless x402 micropayments for AI agents — self-custodied XNO wallet, pay-per-call client, merchant server with railHint, faucet, and MCP server
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://feeless402.com
|
|
7
|
+
Project-URL: Specification, https://railhint.com
|
|
8
|
+
Project-URL: Source, https://github.com/feeless402/feeless402
|
|
9
|
+
Keywords: x402,micropayments,ai-agents,nano,xno,http-402,mcp,railhint
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
15
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: nanopy
|
|
20
|
+
Requires-Dist: requests
|
|
21
|
+
Provides-Extra: server
|
|
22
|
+
Requires-Dist: fastapi; extra == "server"
|
|
23
|
+
Requires-Dist: uvicorn[standard]; extra == "server"
|
|
24
|
+
Provides-Extra: mcp
|
|
25
|
+
Requires-Dist: mcp>=2.0; extra == "mcp"
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: fastapi; extra == "all"
|
|
28
|
+
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
29
|
+
Requires-Dist: mcp>=2.0; extra == "all"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# nano-pay · Feeless402
|
|
33
|
+
|
|
34
|
+
Self-custodied Nano (XNO) wallet + x402 payment client **and** merchant
|
|
35
|
+
server, built for AI agents. Client spends; `nano-pay serve` earns — paid
|
|
36
|
+
endpoints, on-ledger verification/settlement (no facilitator), a starter
|
|
37
|
+
faucet, and the `railHint` x402 extension that teaches visiting agents how
|
|
38
|
+
to onboard (see SPEC-railhint.md). Site: site/index.html + site/llms.txt.
|
|
39
|
+
|
|
40
|
+
**The pitch, in one number:** the same $5 buys 5,000 API calls paid as
|
|
41
|
+
per-call USDC-on-Base x402 payments (merchants floor prices at 0.001 USDC),
|
|
42
|
+
or ~1.8 million calls paid in Nano at the true metered price
|
|
43
|
+
($0.0000027/call observed live at nano-gpt.com). Top up once, micropay
|
|
44
|
+
forever.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install -e . # needs Python 3.10+; pulls nanopy + requests
|
|
50
|
+
nano-pay init # creates ~/.nano-pay/wallet.json (chmod 600)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Agent flow
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
nano-pay topup 5 # quote: $5 USDC-BASE → ~12.3 XNO (NanSwap)
|
|
57
|
+
nano-pay topup 5 --execute # create order (set NANSWAP_API_KEY)
|
|
58
|
+
# → send USDC to the returned deposit address; XNO arrives in 30-60s
|
|
59
|
+
nano-pay receive # pocket incoming XNO
|
|
60
|
+
nano-pay quote https://nano-gpt.com/api/v1/chat/completions \
|
|
61
|
+
--json '{"model":"gpt-5-nano","messages":[{"role":"user","content":"hi"}]}'
|
|
62
|
+
nano-pay pay https://nano-gpt.com/api/v1/chat/completions \
|
|
63
|
+
--json '{"model":"gpt-5-nano","messages":[{"role":"user","content":"hi"}]}'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`pay` handles the whole x402 handshake: request → parse the 402 quote
|
|
67
|
+
(both the x402nano/`PAYMENT-REQUIRED` v2 dialect and the NanoGPT/`accepts`
|
|
68
|
+
v1 dialect) → price-cap check → sign a send state block locally → retry
|
|
69
|
+
with `PAYMENT-SIGNATURE` + `X-PAYMENT` headers. The server settles the
|
|
70
|
+
block via its facilitator; nothing is broadcast unless the server accepts.
|
|
71
|
+
|
|
72
|
+
## Design notes
|
|
73
|
+
|
|
74
|
+
- **Self-custody:** seed never leaves `~/.nano-pay/wallet.json` (0600).
|
|
75
|
+
- **No node required:** public RPC failover (rpc.nano.to, somenano,
|
|
76
|
+
rainstorm.city, nanoslo); all signing and PoW happen locally (nanopy
|
|
77
|
+
C extension). RPC `work_generate` is tried first, local PoW is the
|
|
78
|
+
fallback (~25s), and work for the next block is pre-cached after every
|
|
79
|
+
transaction so steady-state payments are instant.
|
|
80
|
+
- **Safety rails:** per-payment price cap (`--max-xno`, default 0.05);
|
|
81
|
+
`quote` command inspects any endpoint's price without paying;
|
|
82
|
+
balance is always re-synced from the network, never trusted locally.
|
|
83
|
+
- **Top-ups without custody:** `topup` quotes/creates swaps directly with
|
|
84
|
+
NanSwap's API (1,400+ input assets, ~$0.02 minimum). This tool never
|
|
85
|
+
holds or routes funds.
|
|
86
|
+
|
|
87
|
+
## Fork-hazard note (x402 payments)
|
|
88
|
+
|
|
89
|
+
An x402 payment signs a block the *server* broadcasts. If the server
|
|
90
|
+
errors after receiving the block, it may still settle it late. The wallet
|
|
91
|
+
re-syncs its frontier from the network before every operation, so a late
|
|
92
|
+
settlement is picked up naturally; a competing block signed in the
|
|
93
|
+
meantime simply makes one of the two invalid (funds are never at risk,
|
|
94
|
+
but don't fire concurrent payments from one wallet).
|
|
95
|
+
|
|
96
|
+
## Status
|
|
97
|
+
|
|
98
|
+
Beta (v0.2.0). Proven on mainnet with real funds: live paid calls to
|
|
99
|
+
NanoGPT ($0.0000096/call, confirmed on-ledger), full merchant loop
|
|
100
|
+
(verify → settle → confirm, no facilitator), PoW-gated faucet claims,
|
|
101
|
+
and a complete stranger-agent lifecycle (fresh wallet → PoW claim →
|
|
102
|
+
paid API call → confirmed) in under 3 minutes. 13-test suite covers the
|
|
103
|
+
payment path offline. Not audited — keep only working capital in it.
|
|
104
|
+
|
|
105
|
+
## Security notes (read before holding real funds)
|
|
106
|
+
|
|
107
|
+
- **Self-custody**: the seed lives only in `~/.nano-pay/*.json` (0600).
|
|
108
|
+
No tool or log path ever prints it. Back it up offline.
|
|
109
|
+
- **Working capital only**: this is beta wallet software. Keep a few
|
|
110
|
+
dollars in it, not your savings.
|
|
111
|
+
- **Spend caps**: `pay` refuses quotes above `--max-xno` (default 0.05).
|
|
112
|
+
MCP `x402_pay` enforces the same cap parameter.
|
|
113
|
+
- **railHint is advisory**: hints from remote servers are untrusted
|
|
114
|
+
input. This client never executes remote bootstrap strings; it only
|
|
115
|
+
acts on structured offers that pass its own checks, and `accepts`
|
|
116
|
+
always binds, never the hint.
|
|
117
|
+
- **Merchant fork guard**: servers cache accepted frontiers and reject
|
|
118
|
+
duplicate-frontier blocks; payer balance/frontier/signature are
|
|
119
|
+
verified against the live ledger before settlement.
|
|
120
|
+
- Not audited. MIT — no warranty.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# nano-pay · Feeless402
|
|
2
|
+
|
|
3
|
+
Self-custodied Nano (XNO) wallet + x402 payment client **and** merchant
|
|
4
|
+
server, built for AI agents. Client spends; `nano-pay serve` earns — paid
|
|
5
|
+
endpoints, on-ledger verification/settlement (no facilitator), a starter
|
|
6
|
+
faucet, and the `railHint` x402 extension that teaches visiting agents how
|
|
7
|
+
to onboard (see SPEC-railhint.md). Site: site/index.html + site/llms.txt.
|
|
8
|
+
|
|
9
|
+
**The pitch, in one number:** the same $5 buys 5,000 API calls paid as
|
|
10
|
+
per-call USDC-on-Base x402 payments (merchants floor prices at 0.001 USDC),
|
|
11
|
+
or ~1.8 million calls paid in Nano at the true metered price
|
|
12
|
+
($0.0000027/call observed live at nano-gpt.com). Top up once, micropay
|
|
13
|
+
forever.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install -e . # needs Python 3.10+; pulls nanopy + requests
|
|
19
|
+
nano-pay init # creates ~/.nano-pay/wallet.json (chmod 600)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Agent flow
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
nano-pay topup 5 # quote: $5 USDC-BASE → ~12.3 XNO (NanSwap)
|
|
26
|
+
nano-pay topup 5 --execute # create order (set NANSWAP_API_KEY)
|
|
27
|
+
# → send USDC to the returned deposit address; XNO arrives in 30-60s
|
|
28
|
+
nano-pay receive # pocket incoming XNO
|
|
29
|
+
nano-pay quote https://nano-gpt.com/api/v1/chat/completions \
|
|
30
|
+
--json '{"model":"gpt-5-nano","messages":[{"role":"user","content":"hi"}]}'
|
|
31
|
+
nano-pay pay https://nano-gpt.com/api/v1/chat/completions \
|
|
32
|
+
--json '{"model":"gpt-5-nano","messages":[{"role":"user","content":"hi"}]}'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`pay` handles the whole x402 handshake: request → parse the 402 quote
|
|
36
|
+
(both the x402nano/`PAYMENT-REQUIRED` v2 dialect and the NanoGPT/`accepts`
|
|
37
|
+
v1 dialect) → price-cap check → sign a send state block locally → retry
|
|
38
|
+
with `PAYMENT-SIGNATURE` + `X-PAYMENT` headers. The server settles the
|
|
39
|
+
block via its facilitator; nothing is broadcast unless the server accepts.
|
|
40
|
+
|
|
41
|
+
## Design notes
|
|
42
|
+
|
|
43
|
+
- **Self-custody:** seed never leaves `~/.nano-pay/wallet.json` (0600).
|
|
44
|
+
- **No node required:** public RPC failover (rpc.nano.to, somenano,
|
|
45
|
+
rainstorm.city, nanoslo); all signing and PoW happen locally (nanopy
|
|
46
|
+
C extension). RPC `work_generate` is tried first, local PoW is the
|
|
47
|
+
fallback (~25s), and work for the next block is pre-cached after every
|
|
48
|
+
transaction so steady-state payments are instant.
|
|
49
|
+
- **Safety rails:** per-payment price cap (`--max-xno`, default 0.05);
|
|
50
|
+
`quote` command inspects any endpoint's price without paying;
|
|
51
|
+
balance is always re-synced from the network, never trusted locally.
|
|
52
|
+
- **Top-ups without custody:** `topup` quotes/creates swaps directly with
|
|
53
|
+
NanSwap's API (1,400+ input assets, ~$0.02 minimum). This tool never
|
|
54
|
+
holds or routes funds.
|
|
55
|
+
|
|
56
|
+
## Fork-hazard note (x402 payments)
|
|
57
|
+
|
|
58
|
+
An x402 payment signs a block the *server* broadcasts. If the server
|
|
59
|
+
errors after receiving the block, it may still settle it late. The wallet
|
|
60
|
+
re-syncs its frontier from the network before every operation, so a late
|
|
61
|
+
settlement is picked up naturally; a competing block signed in the
|
|
62
|
+
meantime simply makes one of the two invalid (funds are never at risk,
|
|
63
|
+
but don't fire concurrent payments from one wallet).
|
|
64
|
+
|
|
65
|
+
## Status
|
|
66
|
+
|
|
67
|
+
Beta (v0.2.0). Proven on mainnet with real funds: live paid calls to
|
|
68
|
+
NanoGPT ($0.0000096/call, confirmed on-ledger), full merchant loop
|
|
69
|
+
(verify → settle → confirm, no facilitator), PoW-gated faucet claims,
|
|
70
|
+
and a complete stranger-agent lifecycle (fresh wallet → PoW claim →
|
|
71
|
+
paid API call → confirmed) in under 3 minutes. 13-test suite covers the
|
|
72
|
+
payment path offline. Not audited — keep only working capital in it.
|
|
73
|
+
|
|
74
|
+
## Security notes (read before holding real funds)
|
|
75
|
+
|
|
76
|
+
- **Self-custody**: the seed lives only in `~/.nano-pay/*.json` (0600).
|
|
77
|
+
No tool or log path ever prints it. Back it up offline.
|
|
78
|
+
- **Working capital only**: this is beta wallet software. Keep a few
|
|
79
|
+
dollars in it, not your savings.
|
|
80
|
+
- **Spend caps**: `pay` refuses quotes above `--max-xno` (default 0.05).
|
|
81
|
+
MCP `x402_pay` enforces the same cap parameter.
|
|
82
|
+
- **railHint is advisory**: hints from remote servers are untrusted
|
|
83
|
+
input. This client never executes remote bootstrap strings; it only
|
|
84
|
+
acts on structured offers that pass its own checks, and `accepts`
|
|
85
|
+
always binds, never the hint.
|
|
86
|
+
- **Merchant fork guard**: servers cache accepted frontiers and reject
|
|
87
|
+
duplicate-frontier blocks; payer balance/frontier/signature are
|
|
88
|
+
verified against the live ledger before settlement.
|
|
89
|
+
- Not audited. MIT — no warranty.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: feeless402
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Feeless x402 micropayments for AI agents — self-custodied XNO wallet, pay-per-call client, merchant server with railHint, faucet, and MCP server
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://feeless402.com
|
|
7
|
+
Project-URL: Specification, https://railhint.com
|
|
8
|
+
Project-URL: Source, https://github.com/feeless402/feeless402
|
|
9
|
+
Keywords: x402,micropayments,ai-agents,nano,xno,http-402,mcp,railhint
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
15
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: nanopy
|
|
20
|
+
Requires-Dist: requests
|
|
21
|
+
Provides-Extra: server
|
|
22
|
+
Requires-Dist: fastapi; extra == "server"
|
|
23
|
+
Requires-Dist: uvicorn[standard]; extra == "server"
|
|
24
|
+
Provides-Extra: mcp
|
|
25
|
+
Requires-Dist: mcp>=2.0; extra == "mcp"
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: fastapi; extra == "all"
|
|
28
|
+
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
29
|
+
Requires-Dist: mcp>=2.0; extra == "all"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# nano-pay · Feeless402
|
|
33
|
+
|
|
34
|
+
Self-custodied Nano (XNO) wallet + x402 payment client **and** merchant
|
|
35
|
+
server, built for AI agents. Client spends; `nano-pay serve` earns — paid
|
|
36
|
+
endpoints, on-ledger verification/settlement (no facilitator), a starter
|
|
37
|
+
faucet, and the `railHint` x402 extension that teaches visiting agents how
|
|
38
|
+
to onboard (see SPEC-railhint.md). Site: site/index.html + site/llms.txt.
|
|
39
|
+
|
|
40
|
+
**The pitch, in one number:** the same $5 buys 5,000 API calls paid as
|
|
41
|
+
per-call USDC-on-Base x402 payments (merchants floor prices at 0.001 USDC),
|
|
42
|
+
or ~1.8 million calls paid in Nano at the true metered price
|
|
43
|
+
($0.0000027/call observed live at nano-gpt.com). Top up once, micropay
|
|
44
|
+
forever.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install -e . # needs Python 3.10+; pulls nanopy + requests
|
|
50
|
+
nano-pay init # creates ~/.nano-pay/wallet.json (chmod 600)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Agent flow
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
nano-pay topup 5 # quote: $5 USDC-BASE → ~12.3 XNO (NanSwap)
|
|
57
|
+
nano-pay topup 5 --execute # create order (set NANSWAP_API_KEY)
|
|
58
|
+
# → send USDC to the returned deposit address; XNO arrives in 30-60s
|
|
59
|
+
nano-pay receive # pocket incoming XNO
|
|
60
|
+
nano-pay quote https://nano-gpt.com/api/v1/chat/completions \
|
|
61
|
+
--json '{"model":"gpt-5-nano","messages":[{"role":"user","content":"hi"}]}'
|
|
62
|
+
nano-pay pay https://nano-gpt.com/api/v1/chat/completions \
|
|
63
|
+
--json '{"model":"gpt-5-nano","messages":[{"role":"user","content":"hi"}]}'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`pay` handles the whole x402 handshake: request → parse the 402 quote
|
|
67
|
+
(both the x402nano/`PAYMENT-REQUIRED` v2 dialect and the NanoGPT/`accepts`
|
|
68
|
+
v1 dialect) → price-cap check → sign a send state block locally → retry
|
|
69
|
+
with `PAYMENT-SIGNATURE` + `X-PAYMENT` headers. The server settles the
|
|
70
|
+
block via its facilitator; nothing is broadcast unless the server accepts.
|
|
71
|
+
|
|
72
|
+
## Design notes
|
|
73
|
+
|
|
74
|
+
- **Self-custody:** seed never leaves `~/.nano-pay/wallet.json` (0600).
|
|
75
|
+
- **No node required:** public RPC failover (rpc.nano.to, somenano,
|
|
76
|
+
rainstorm.city, nanoslo); all signing and PoW happen locally (nanopy
|
|
77
|
+
C extension). RPC `work_generate` is tried first, local PoW is the
|
|
78
|
+
fallback (~25s), and work for the next block is pre-cached after every
|
|
79
|
+
transaction so steady-state payments are instant.
|
|
80
|
+
- **Safety rails:** per-payment price cap (`--max-xno`, default 0.05);
|
|
81
|
+
`quote` command inspects any endpoint's price without paying;
|
|
82
|
+
balance is always re-synced from the network, never trusted locally.
|
|
83
|
+
- **Top-ups without custody:** `topup` quotes/creates swaps directly with
|
|
84
|
+
NanSwap's API (1,400+ input assets, ~$0.02 minimum). This tool never
|
|
85
|
+
holds or routes funds.
|
|
86
|
+
|
|
87
|
+
## Fork-hazard note (x402 payments)
|
|
88
|
+
|
|
89
|
+
An x402 payment signs a block the *server* broadcasts. If the server
|
|
90
|
+
errors after receiving the block, it may still settle it late. The wallet
|
|
91
|
+
re-syncs its frontier from the network before every operation, so a late
|
|
92
|
+
settlement is picked up naturally; a competing block signed in the
|
|
93
|
+
meantime simply makes one of the two invalid (funds are never at risk,
|
|
94
|
+
but don't fire concurrent payments from one wallet).
|
|
95
|
+
|
|
96
|
+
## Status
|
|
97
|
+
|
|
98
|
+
Beta (v0.2.0). Proven on mainnet with real funds: live paid calls to
|
|
99
|
+
NanoGPT ($0.0000096/call, confirmed on-ledger), full merchant loop
|
|
100
|
+
(verify → settle → confirm, no facilitator), PoW-gated faucet claims,
|
|
101
|
+
and a complete stranger-agent lifecycle (fresh wallet → PoW claim →
|
|
102
|
+
paid API call → confirmed) in under 3 minutes. 13-test suite covers the
|
|
103
|
+
payment path offline. Not audited — keep only working capital in it.
|
|
104
|
+
|
|
105
|
+
## Security notes (read before holding real funds)
|
|
106
|
+
|
|
107
|
+
- **Self-custody**: the seed lives only in `~/.nano-pay/*.json` (0600).
|
|
108
|
+
No tool or log path ever prints it. Back it up offline.
|
|
109
|
+
- **Working capital only**: this is beta wallet software. Keep a few
|
|
110
|
+
dollars in it, not your savings.
|
|
111
|
+
- **Spend caps**: `pay` refuses quotes above `--max-xno` (default 0.05).
|
|
112
|
+
MCP `x402_pay` enforces the same cap parameter.
|
|
113
|
+
- **railHint is advisory**: hints from remote servers are untrusted
|
|
114
|
+
input. This client never executes remote bootstrap strings; it only
|
|
115
|
+
acts on structured offers that pass its own checks, and `accepts`
|
|
116
|
+
always binds, never the hint.
|
|
117
|
+
- **Merchant fork guard**: servers cache accepted frontiers and reject
|
|
118
|
+
duplicate-frontier blocks; payer balance/frontier/signature are
|
|
119
|
+
verified against the live ledger before settlement.
|
|
120
|
+
- Not audited. MIT — no warranty.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
feeless402.egg-info/PKG-INFO
|
|
5
|
+
feeless402.egg-info/SOURCES.txt
|
|
6
|
+
feeless402.egg-info/dependency_links.txt
|
|
7
|
+
feeless402.egg-info/entry_points.txt
|
|
8
|
+
feeless402.egg-info/requires.txt
|
|
9
|
+
feeless402.egg-info/top_level.txt
|
|
10
|
+
nano_pay/__init__.py
|
|
11
|
+
nano_pay/cli.py
|
|
12
|
+
nano_pay/mcp_server.py
|
|
13
|
+
nano_pay/rpc.py
|
|
14
|
+
nano_pay/server.py
|
|
15
|
+
nano_pay/topup.py
|
|
16
|
+
nano_pay/verify.py
|
|
17
|
+
nano_pay/wallet.py
|
|
18
|
+
nano_pay/x402.py
|
|
19
|
+
tests/test_payment_path.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nano_pay
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""nano-pay: self-custodied Nano (XNO) wallet + x402 payment client for AI agents."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.1.0"
|
|
4
|
+
|
|
5
|
+
RAW_PER_XNO = 10**30
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def xno_to_raw(xno) -> int:
|
|
9
|
+
from decimal import Decimal
|
|
10
|
+
|
|
11
|
+
return int(Decimal(str(xno)) * RAW_PER_XNO)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def raw_to_xno(raw: int) -> str:
|
|
15
|
+
from decimal import Decimal
|
|
16
|
+
|
|
17
|
+
return str((Decimal(raw) / RAW_PER_XNO).normalize())
|