zhlink 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.
zhlink-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,212 @@
1
+ Metadata-Version: 2.4
2
+ Name: zhlink
3
+ Version: 0.1.0
4
+ Summary: Self-contained Python library for ZHCASH addresses, balances, ZHC sends, and USDZ gas-free sends.
5
+ Author: ZHCASH
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: cryptography>=42
9
+ Requires-Dist: httpx==0.28.1
10
+ Requires-Dist: mnemonic==0.21
11
+ Requires-Dist: pycryptodome>=3.20
12
+
13
+ # ZHLink Python Library
14
+
15
+ `zhlink` is a self-contained Python library for ZHCASH.
16
+
17
+ The public API is intentionally small:
18
+
19
+ - create a new ZHC address;
20
+ - check ZHC + USDZ balance;
21
+ - send native ZHC from a private key;
22
+ - send USDZ with admin-paid ZHC gas;
23
+ - optionally read extra ZRC-20 token balances.
24
+
25
+ The raw transaction engine is bundled inside the package. Normal users only
26
+ import `zhlink`.
27
+
28
+ ## Install
29
+
30
+ Recommended Python:
31
+
32
+ - Python `3.10` or newer is required.
33
+ - Python `3.10` and `3.11` are the safest choices for deployment.
34
+ - Python `3.12` should work.
35
+ - Python `3.9` and older are not supported.
36
+
37
+ From PyPI:
38
+
39
+ ```bash
40
+ pip install zhlink
41
+ ```
42
+
43
+ From this folder:
44
+
45
+ ```bash
46
+ cd /root/wallet/zhlink
47
+ python3 -m venv .venv
48
+ . .venv/bin/activate
49
+ pip install -e .
50
+ ```
51
+
52
+ For direct local use without install:
53
+
54
+ ```bash
55
+ cd /root/wallet/zhlink
56
+ export PYTHONPATH=/root/wallet/zhlink
57
+ ```
58
+
59
+ ## Create Address
60
+
61
+ ```python
62
+ from zhlink import create_address
63
+
64
+ wallet = create_address()
65
+
66
+ print(wallet.address)
67
+ print(wallet.priv_key)
68
+ ```
69
+
70
+ Private keys are generated locally. The library never sends private keys to
71
+ ZeroScan or RPC.
72
+
73
+ ## Get Balance
74
+
75
+ By default `get_balance` returns ZHC and USDZ.
76
+
77
+ ```python
78
+ from zhlink import get_balance
79
+
80
+ balance = get_balance("Z...")
81
+
82
+ print(balance["zhc"])
83
+ print(balance["usdz"])
84
+ ```
85
+
86
+ Extra ZRC-20 tokens can be requested when needed:
87
+
88
+ ```python
89
+ from zhlink import get_balance
90
+
91
+ balance = get_balance(
92
+ "Z...",
93
+ tokens={"EDS": "dc71958156a945d3071374521e1a7a42f5ba8038"},
94
+ )
95
+
96
+ print(balance["tokens"]["EDS"])
97
+ ```
98
+
99
+ ## Send ZHC
100
+
101
+ ```python
102
+ from zhlink import send_zhc
103
+
104
+ result = send_zhc(
105
+ private_key_wif="L...",
106
+ to_address="Z...",
107
+ amount="1.25",
108
+ )
109
+
110
+ print(result)
111
+ ```
112
+
113
+ The sender address is derived from the private key automatically.
114
+
115
+ ## Send USDZ Gas-Free
116
+
117
+ `send_usdz_gas_free` signs the USDZ transfer with the sender key and pays ZHC
118
+ gas from the admin gas wallet.
119
+
120
+ ```python
121
+ from zhlink import send_usdz_gas_free
122
+
123
+ result = send_usdz_gas_free(
124
+ sender_private_key_wif="L...",
125
+ admin_private_key_wif="K...",
126
+ to_address="Z...",
127
+ amount="0.1",
128
+ )
129
+
130
+ print(result["broadcast"]["txid"])
131
+ ```
132
+
133
+ The function does the required checks automatically:
134
+
135
+ 1. derives sender/admin addresses from WIF keys;
136
+ 2. checks sender USDZ balance;
137
+ 3. runs `callcontract` dry-run;
138
+ 4. loads admin gas UTXO from ZeroScan;
139
+ 5. skips locally used gas UTXO;
140
+ 6. builds and signs rawtx locally;
141
+ 7. runs `testmempoolaccept`;
142
+ 8. if one UTXO is rejected, tries another UTXO;
143
+ 9. broadcasts through ZeroScan;
144
+ 10. falls back to RPC `sendrawtransaction`.
145
+
146
+ For mass sends, prepare independent admin gas UTXO first. One gas-free transfer
147
+ needs one spendable admin gas UTXO. The recommended ticket size is `0.5 ZHC`.
148
+
149
+ ```python
150
+ from zhlink import admin_gas_wallet_info
151
+
152
+ info = admin_gas_wallet_info("K...")
153
+ print(info["suitable_gas_utxo_count"])
154
+ print(info["recommended_split_count"])
155
+ ```
156
+
157
+ ## Custom RPC / ZeroScan
158
+
159
+ Defaults:
160
+
161
+ - ZeroScan API: `https://ws.zeroscan.st`, `https://ws.zeroscan.io`
162
+ - RPC: `https://rpc.zeroscan.st`
163
+ - USDZ contract: `a48d0ee7365ce1add8e595de4d54344239f8ca28`
164
+
165
+ Override them when needed:
166
+
167
+ ```python
168
+ from zhlink import ZHLinkConfig, get_balance
169
+
170
+ config = ZHLinkConfig.public_network(
171
+ zeroscan_endpoints=("https://ws.zeroscan.st", "https://ws.zeroscan.io"),
172
+ public_rpc_urls=("https://rpc.zeroscan.st", "https://my-node.example/rpc"),
173
+ )
174
+
175
+ print(get_balance("Z...", config=config))
176
+ ```
177
+
178
+ ## Examples
179
+
180
+ Run examples one by one:
181
+
182
+ ```bash
183
+ cd /root/wallet/zhlink
184
+ PYTHONPATH=. python3 examples/create_wallet.py
185
+ PYTHONPATH=. python3 examples/create_bip39_wallet.py
186
+ PYTHONPATH=. ZHLINK_ADDRESS="Z..." python3 examples/check_balance.py
187
+ ```
188
+
189
+ Run all safe examples at once:
190
+
191
+ ```bash
192
+ cd /root/wallet/zhlink
193
+ PYTHONPATH=. python3 examples/run_all_examples.py
194
+ ```
195
+
196
+ Send examples are guarded by `RUN_REAL_SEND=1` and will not broadcast by
197
+ accident. Never commit real private keys.
198
+
199
+ ## Publishing
200
+
201
+ GitHub Actions workflow `.github/workflows/python-publish.yml` builds, tests,
202
+ checks, and publishes the package to PyPI.
203
+
204
+ Release flow:
205
+
206
+ ```bash
207
+ git tag v0.1.0
208
+ git push origin v0.1.0
209
+ ```
210
+
211
+ The workflow uses PyPI Trusted Publishing, so the PyPI project must allow this
212
+ GitHub repository/workflow as a trusted publisher.
zhlink-0.1.0/README.md ADDED
@@ -0,0 +1,200 @@
1
+ # ZHLink Python Library
2
+
3
+ `zhlink` is a self-contained Python library for ZHCASH.
4
+
5
+ The public API is intentionally small:
6
+
7
+ - create a new ZHC address;
8
+ - check ZHC + USDZ balance;
9
+ - send native ZHC from a private key;
10
+ - send USDZ with admin-paid ZHC gas;
11
+ - optionally read extra ZRC-20 token balances.
12
+
13
+ The raw transaction engine is bundled inside the package. Normal users only
14
+ import `zhlink`.
15
+
16
+ ## Install
17
+
18
+ Recommended Python:
19
+
20
+ - Python `3.10` or newer is required.
21
+ - Python `3.10` and `3.11` are the safest choices for deployment.
22
+ - Python `3.12` should work.
23
+ - Python `3.9` and older are not supported.
24
+
25
+ From PyPI:
26
+
27
+ ```bash
28
+ pip install zhlink
29
+ ```
30
+
31
+ From this folder:
32
+
33
+ ```bash
34
+ cd /root/wallet/zhlink
35
+ python3 -m venv .venv
36
+ . .venv/bin/activate
37
+ pip install -e .
38
+ ```
39
+
40
+ For direct local use without install:
41
+
42
+ ```bash
43
+ cd /root/wallet/zhlink
44
+ export PYTHONPATH=/root/wallet/zhlink
45
+ ```
46
+
47
+ ## Create Address
48
+
49
+ ```python
50
+ from zhlink import create_address
51
+
52
+ wallet = create_address()
53
+
54
+ print(wallet.address)
55
+ print(wallet.priv_key)
56
+ ```
57
+
58
+ Private keys are generated locally. The library never sends private keys to
59
+ ZeroScan or RPC.
60
+
61
+ ## Get Balance
62
+
63
+ By default `get_balance` returns ZHC and USDZ.
64
+
65
+ ```python
66
+ from zhlink import get_balance
67
+
68
+ balance = get_balance("Z...")
69
+
70
+ print(balance["zhc"])
71
+ print(balance["usdz"])
72
+ ```
73
+
74
+ Extra ZRC-20 tokens can be requested when needed:
75
+
76
+ ```python
77
+ from zhlink import get_balance
78
+
79
+ balance = get_balance(
80
+ "Z...",
81
+ tokens={"EDS": "dc71958156a945d3071374521e1a7a42f5ba8038"},
82
+ )
83
+
84
+ print(balance["tokens"]["EDS"])
85
+ ```
86
+
87
+ ## Send ZHC
88
+
89
+ ```python
90
+ from zhlink import send_zhc
91
+
92
+ result = send_zhc(
93
+ private_key_wif="L...",
94
+ to_address="Z...",
95
+ amount="1.25",
96
+ )
97
+
98
+ print(result)
99
+ ```
100
+
101
+ The sender address is derived from the private key automatically.
102
+
103
+ ## Send USDZ Gas-Free
104
+
105
+ `send_usdz_gas_free` signs the USDZ transfer with the sender key and pays ZHC
106
+ gas from the admin gas wallet.
107
+
108
+ ```python
109
+ from zhlink import send_usdz_gas_free
110
+
111
+ result = send_usdz_gas_free(
112
+ sender_private_key_wif="L...",
113
+ admin_private_key_wif="K...",
114
+ to_address="Z...",
115
+ amount="0.1",
116
+ )
117
+
118
+ print(result["broadcast"]["txid"])
119
+ ```
120
+
121
+ The function does the required checks automatically:
122
+
123
+ 1. derives sender/admin addresses from WIF keys;
124
+ 2. checks sender USDZ balance;
125
+ 3. runs `callcontract` dry-run;
126
+ 4. loads admin gas UTXO from ZeroScan;
127
+ 5. skips locally used gas UTXO;
128
+ 6. builds and signs rawtx locally;
129
+ 7. runs `testmempoolaccept`;
130
+ 8. if one UTXO is rejected, tries another UTXO;
131
+ 9. broadcasts through ZeroScan;
132
+ 10. falls back to RPC `sendrawtransaction`.
133
+
134
+ For mass sends, prepare independent admin gas UTXO first. One gas-free transfer
135
+ needs one spendable admin gas UTXO. The recommended ticket size is `0.5 ZHC`.
136
+
137
+ ```python
138
+ from zhlink import admin_gas_wallet_info
139
+
140
+ info = admin_gas_wallet_info("K...")
141
+ print(info["suitable_gas_utxo_count"])
142
+ print(info["recommended_split_count"])
143
+ ```
144
+
145
+ ## Custom RPC / ZeroScan
146
+
147
+ Defaults:
148
+
149
+ - ZeroScan API: `https://ws.zeroscan.st`, `https://ws.zeroscan.io`
150
+ - RPC: `https://rpc.zeroscan.st`
151
+ - USDZ contract: `a48d0ee7365ce1add8e595de4d54344239f8ca28`
152
+
153
+ Override them when needed:
154
+
155
+ ```python
156
+ from zhlink import ZHLinkConfig, get_balance
157
+
158
+ config = ZHLinkConfig.public_network(
159
+ zeroscan_endpoints=("https://ws.zeroscan.st", "https://ws.zeroscan.io"),
160
+ public_rpc_urls=("https://rpc.zeroscan.st", "https://my-node.example/rpc"),
161
+ )
162
+
163
+ print(get_balance("Z...", config=config))
164
+ ```
165
+
166
+ ## Examples
167
+
168
+ Run examples one by one:
169
+
170
+ ```bash
171
+ cd /root/wallet/zhlink
172
+ PYTHONPATH=. python3 examples/create_wallet.py
173
+ PYTHONPATH=. python3 examples/create_bip39_wallet.py
174
+ PYTHONPATH=. ZHLINK_ADDRESS="Z..." python3 examples/check_balance.py
175
+ ```
176
+
177
+ Run all safe examples at once:
178
+
179
+ ```bash
180
+ cd /root/wallet/zhlink
181
+ PYTHONPATH=. python3 examples/run_all_examples.py
182
+ ```
183
+
184
+ Send examples are guarded by `RUN_REAL_SEND=1` and will not broadcast by
185
+ accident. Never commit real private keys.
186
+
187
+ ## Publishing
188
+
189
+ GitHub Actions workflow `.github/workflows/python-publish.yml` builds, tests,
190
+ checks, and publishes the package to PyPI.
191
+
192
+ Release flow:
193
+
194
+ ```bash
195
+ git tag v0.1.0
196
+ git push origin v0.1.0
197
+ ```
198
+
199
+ The workflow uses PyPI Trusted Publishing, so the PyPI project must allow this
200
+ GitHub repository/workflow as a trusted publisher.
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "zhlink"
7
+ version = "0.1.0"
8
+ description = "Self-contained Python library for ZHCASH addresses, balances, ZHC sends, and USDZ gas-free sends."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = [
12
+ "cryptography>=42",
13
+ "httpx==0.28.1",
14
+ "mnemonic==0.21",
15
+ "pycryptodome>=3.20",
16
+ ]
17
+ authors = [
18
+ { name = "ZHCASH" },
19
+ ]
20
+
21
+ [tool.setuptools]
22
+ include-package-data = true
23
+
24
+ [tool.setuptools.packages.find]
25
+ where = ["."]
26
+ include = ["zhlink*"]
27
+
28
+ [tool.setuptools.package-data]
29
+ zhlink = [
30
+ "_vendor/bip39_english.txt",
31
+ "_vendor/zhc_rawtx/*.py",
32
+ ]
zhlink-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+