aeknow 7.0.0__py3-none-any.whl
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.
- aeknow/README.md +1526 -0
- aeknow/__init__.py +16 -0
- aeknow/aens.py +532 -0
- aeknow/channel.py +533 -0
- aeknow/compiler.py +165 -0
- aeknow/contract.py +180 -0
- aeknow/contract_native.py +535 -0
- aeknow/contract_toolkit.py +1217 -0
- aeknow/crypto.py +372 -0
- aeknow/defaults.py +102 -0
- aeknow/exceptions.py +86 -0
- aeknow/hashing.py +328 -0
- aeknow/hdwallet.py +238 -0
- aeknow/identifiers.py +284 -0
- aeknow/message.py +254 -0
- aeknow/node.py +802 -0
- aeknow/openapi.py +419 -0
- aeknow/oracles.py +274 -0
- aeknow/requirements.txt +16 -0
- aeknow/signing.py +369 -0
- aeknow/transactions.py +1222 -0
- aeknow/utils.py +123 -0
- aeknow/wallet.py +161 -0
- aeknow-7.0.0.dist-info/METADATA +1568 -0
- aeknow-7.0.0.dist-info/RECORD +28 -0
- aeknow-7.0.0.dist-info/WHEEL +5 -0
- aeknow-7.0.0.dist-info/licenses/LICENSE +21 -0
- aeknow-7.0.0.dist-info/top_level.txt +1 -0
aeknow/README.md
ADDED
|
@@ -0,0 +1,1526 @@
|
|
|
1
|
+
# aeknow Python SDK
|
|
2
|
+
|
|
3
|
+
aeknow 区块链 Python SDK,提供完整的账户管理、交易构建、合约部署、AENS域名服务等功能。
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
- [安装](#安装)
|
|
8
|
+
- [快速开始](#快速开始)
|
|
9
|
+
- [模块说明](#模块说明)
|
|
10
|
+
- [signing - 账户与签名](#signing---账户与签名)
|
|
11
|
+
- [wallet - 助记词钱包](#wallet---助记词钱包)
|
|
12
|
+
- [hdwallet - HD钱包核心](#hdwallet---hd钱包核心)
|
|
13
|
+
- [message - 消息签名](#message---消息签名)
|
|
14
|
+
- [crypto - 消息加密](#crypto---消息加密)
|
|
15
|
+
- [hashing - 哈希工具](#hashing---哈希工具)
|
|
16
|
+
- [node - 节点客户端](#node---节点客户端)
|
|
17
|
+
- [compiler - 编译器客户端](#compiler---编译器客户端)
|
|
18
|
+
- [contract - 合约模块](#contract---合约模块)
|
|
19
|
+
- [contract_native - 原生合约管理](#contract_native---原生合约管理)
|
|
20
|
+
- [transactions - 交易构建](#transactions---交易构建)
|
|
21
|
+
- [aens - 域名服务](#aens---域名服务)
|
|
22
|
+
- [oracles - 预言机](#oracles---预言机)
|
|
23
|
+
- [utils - 工具函数](#utils---工具函数)
|
|
24
|
+
- [defaults - 默认配置](#defaults---默认配置)
|
|
25
|
+
- [identifiers - 标识符常量](#identifiers---标识符常量)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 安装
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install aeknow
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 依赖项
|
|
36
|
+
|
|
37
|
+
核心依赖:
|
|
38
|
+
|
|
39
|
+
| 包名 | 版本要求 | 说明 |
|
|
40
|
+
|------|----------|------|
|
|
41
|
+
| `pynacl` | >=1.4.0 | NaCl 加密库,用于签名和加密 |
|
|
42
|
+
| `base58` | >=2.1.0 | Base58 编解码 |
|
|
43
|
+
| `mnemonic` | >=0.20 | BIP39 助记词生成与验证 |
|
|
44
|
+
| `pyblake2` | >=1.1.2 | Blake2b 哈希算法 |
|
|
45
|
+
| `requests` | >=2.28.0 | HTTP 网络请求 |
|
|
46
|
+
| `rlp` | >=3.0.0 | RLP 编解码 |
|
|
47
|
+
|
|
48
|
+
安装依赖:
|
|
49
|
+
```bash
|
|
50
|
+
pip install pynacl base58 mnemonic pyblake2 requests rlp
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
或一键安装所有依赖:
|
|
54
|
+
```bash
|
|
55
|
+
pip install aeknow[all]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 快速开始
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from aeknow.signing import Account
|
|
64
|
+
from aeknow.node import NodeClient, Config
|
|
65
|
+
|
|
66
|
+
# 创建节点客户端
|
|
67
|
+
client = NodeClient(Config(external_url='https://sdk-mainnet.aepps.com'))
|
|
68
|
+
|
|
69
|
+
# 生成新账户
|
|
70
|
+
account = Account.generate()
|
|
71
|
+
print(f"地址: {account.get_address()}")
|
|
72
|
+
print(f"私钥: {account.get_secret_key()}")
|
|
73
|
+
|
|
74
|
+
# 查询余额
|
|
75
|
+
balance = client.get_balance(account.get_address())
|
|
76
|
+
print(f"余额: {balance} aettos")
|
|
77
|
+
|
|
78
|
+
# 转账
|
|
79
|
+
# tx = client.spend(account, "ak_recipient...", 1000000000000000000)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 模块说明
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## signing - 账户与签名
|
|
89
|
+
|
|
90
|
+
账户管理核心模块,提供密钥生成、签名、Keystore 加解密等功能。
|
|
91
|
+
|
|
92
|
+
### Account 类
|
|
93
|
+
|
|
94
|
+
#### 生成新账户
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from aeknow.signing import Account
|
|
98
|
+
|
|
99
|
+
# 生成随机账户
|
|
100
|
+
account = Account.generate()
|
|
101
|
+
print(account.get_address()) # ak_2swhL...
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### 从私钥导入
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
# 从 64 字节十六进制私钥导入
|
|
108
|
+
account = Account.from_secret_key_string("your_hex_secret_key_here")
|
|
109
|
+
print(account.get_address())
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### 从 Keystore 加载
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
# 加载 Keystore 文件
|
|
116
|
+
account = Account.from_keystore("path/to/keystore.json", "password")
|
|
117
|
+
print(account.get_address())
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### 保存到 Keystore
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
account = Account.generate()
|
|
124
|
+
|
|
125
|
+
# 保存到指定文件
|
|
126
|
+
account.save_to_keystore_file("wallet.json", "password")
|
|
127
|
+
|
|
128
|
+
# 保存到目录(自动生成文件名)
|
|
129
|
+
account.save_to_keystore("./keystores/", "password")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### 获取地址(不同格式)
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from aeknow.identifiers import ACCOUNT_API_FORMAT, ACCOUNT_SOFIA_FORMAT, ACCOUNT_RAW_FORMAT
|
|
136
|
+
|
|
137
|
+
# API 格式 (默认)
|
|
138
|
+
address = account.get_address() # ak_2swhL...
|
|
139
|
+
|
|
140
|
+
# Sophia 格式 (合约使用)
|
|
141
|
+
address_sophia = account.get_address(ACCOUNT_SOFIA_FORMAT) # 0x...
|
|
142
|
+
|
|
143
|
+
# 原始字节
|
|
144
|
+
address_raw = account.get_address(ACCOUNT_RAW_FORMAT) # bytes
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### 签名数据
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
data = b"Hello aeknow"
|
|
151
|
+
signature = account.sign(data)
|
|
152
|
+
print(signature.hex())
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### 验证签名
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
try:
|
|
159
|
+
account.verify(data, signature)
|
|
160
|
+
print("签名有效")
|
|
161
|
+
except:
|
|
162
|
+
print("签名无效")
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### 独立函数
|
|
166
|
+
|
|
167
|
+
#### is_signature_valid - 验证签名
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from aeknow.signing import is_signature_valid
|
|
171
|
+
|
|
172
|
+
is_valid = is_signature_valid(
|
|
173
|
+
account_id="ak_2swhL...",
|
|
174
|
+
signature=signature_bytes,
|
|
175
|
+
data=b"Hello aeknow"
|
|
176
|
+
)
|
|
177
|
+
print(f"签名有效: {is_valid}")
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### keystore_seal - 创建 Keystore
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
from aeknow.signing import keystore_seal
|
|
184
|
+
|
|
185
|
+
keystore = keystore_seal(
|
|
186
|
+
secret_key=account.signing_key,
|
|
187
|
+
password="your_password",
|
|
188
|
+
name="my_wallet"
|
|
189
|
+
)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### keystore_open - 解密 Keystore
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
from aeknow.signing import keystore_open
|
|
196
|
+
import json
|
|
197
|
+
|
|
198
|
+
with open("wallet.json") as f:
|
|
199
|
+
keystore = json.load(f)
|
|
200
|
+
|
|
201
|
+
private_key = keystore_open(keystore, "password")
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## wallet - 助记词钱包
|
|
207
|
+
|
|
208
|
+
对 HDWallet 的高级封装,提供简洁的助记词钱包操作接口。
|
|
209
|
+
|
|
210
|
+
### MnemonicWallet 类
|
|
211
|
+
|
|
212
|
+
#### 生成新钱包
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
from aeknow.wallet import MnemonicWallet
|
|
216
|
+
|
|
217
|
+
wallet = MnemonicWallet.generate()
|
|
218
|
+
print(f"助记词: {wallet.mnemonic}")
|
|
219
|
+
print(f"主地址: {wallet.address}")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### 从助记词导入
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
|
|
226
|
+
wallet = MnemonicWallet.from_mnemonic(mnemonic)
|
|
227
|
+
print(wallet.address)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### 从 Keystore 加载
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
wallet = MnemonicWallet.from_keystore("mnemonic_wallet.json", "password")
|
|
234
|
+
print(wallet.mnemonic)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### 获取主账户
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
account = wallet.account # Account 对象
|
|
241
|
+
print(account.get_address())
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### 派生子账户
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
# 派生单个账户
|
|
248
|
+
child_account = wallet.derive_account(index=0)
|
|
249
|
+
print(child_account.get_address())
|
|
250
|
+
|
|
251
|
+
# 派生多个账户
|
|
252
|
+
accounts = wallet.derive_accounts(count=5)
|
|
253
|
+
for path, acc in accounts:
|
|
254
|
+
print(f"{path}: {acc.get_address()}")
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
#### 保存钱包
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
# 保存助记词 Keystore
|
|
261
|
+
wallet.save_keystore("mnemonic_wallet.json", "password")
|
|
262
|
+
|
|
263
|
+
# 保存单个账户 Keystore
|
|
264
|
+
wallet.save_account_keystore("account_0.json", "password", index=0)
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### 便捷函数
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
from aeknow.wallet import generate_wallet, import_wallet, load_wallet
|
|
271
|
+
|
|
272
|
+
# 生成新钱包
|
|
273
|
+
wallet = generate_wallet()
|
|
274
|
+
|
|
275
|
+
# 从助记词导入
|
|
276
|
+
wallet = import_wallet("your mnemonic words here")
|
|
277
|
+
|
|
278
|
+
# 从 Keystore 加载
|
|
279
|
+
wallet = load_wallet("wallet.json", "password")
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## hdwallet - HD钱包核心
|
|
285
|
+
|
|
286
|
+
BIP39/BIP44 标准的 HD 钱包实现。
|
|
287
|
+
|
|
288
|
+
### HDWallet 类
|
|
289
|
+
|
|
290
|
+
#### 创建钱包
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
from aeknow.hdwallet import HDWallet
|
|
294
|
+
|
|
295
|
+
# 生成新助记词
|
|
296
|
+
wallet = HDWallet()
|
|
297
|
+
print(wallet.mnemonic)
|
|
298
|
+
|
|
299
|
+
# 从已有助记词创建
|
|
300
|
+
wallet = HDWallet("your mnemonic words here")
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### 生成助记词
|
|
304
|
+
|
|
305
|
+
```python
|
|
306
|
+
mnemonic = HDWallet.generate_mnemonic()
|
|
307
|
+
print(mnemonic) # 12 个单词
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### 获取主账户
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
master = wallet.get_master_account()
|
|
314
|
+
print(master.get_address()) # m/44'/457'/0'/0'/0'
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
#### 派生子账户
|
|
318
|
+
|
|
319
|
+
```python
|
|
320
|
+
# 派生路径: m/44'/457'/{account_index}'/0'/{address_index}'
|
|
321
|
+
path, account = wallet.derive_child(account_index=0, address_index=0)
|
|
322
|
+
print(f"{path}: {account.get_address()}")
|
|
323
|
+
|
|
324
|
+
# 自动递增 account_index
|
|
325
|
+
path1, acc1 = wallet.derive_child() # account_index=1
|
|
326
|
+
path2, acc2 = wallet.derive_child() # account_index=2
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
#### 保存/加载助记词 Keystore
|
|
330
|
+
|
|
331
|
+
```python
|
|
332
|
+
# 保存
|
|
333
|
+
wallet.save_mnemonic_to_keystore_file("mnemonic.json", "password")
|
|
334
|
+
|
|
335
|
+
# 加载
|
|
336
|
+
wallet = HDWallet.from_keystore("mnemonic.json", "password")
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## message - 消息签名
|
|
342
|
+
|
|
343
|
+
兼容 aepp-sdk-js 的消息签名模块。
|
|
344
|
+
|
|
345
|
+
### 核心函数
|
|
346
|
+
|
|
347
|
+
#### hash_message - 计算消息哈希
|
|
348
|
+
|
|
349
|
+
```python
|
|
350
|
+
from aeknow.message import hash_message
|
|
351
|
+
|
|
352
|
+
# 按 AE SDK 标准格式计算哈希
|
|
353
|
+
msg_hash = hash_message("Hello aeknow!")
|
|
354
|
+
print(msg_hash.hex())
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### sign_message - 签名消息
|
|
358
|
+
|
|
359
|
+
```python
|
|
360
|
+
from aeknow.message import sign_message
|
|
361
|
+
from aeknow.signing import Account
|
|
362
|
+
|
|
363
|
+
account = Account.generate()
|
|
364
|
+
signature = sign_message(account, "Hello aeknow!")
|
|
365
|
+
print(f"签名: {signature}") # 128 字符十六进制
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
#### verify_message - 验证签名
|
|
369
|
+
|
|
370
|
+
```python
|
|
371
|
+
from aeknow.message import verify_message
|
|
372
|
+
|
|
373
|
+
is_valid = verify_message(
|
|
374
|
+
address="ak_2swhL...",
|
|
375
|
+
message="Hello aeknow!",
|
|
376
|
+
signature="signature_hex_here"
|
|
377
|
+
)
|
|
378
|
+
print(f"签名有效: {is_valid}")
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### MessageSigner 类
|
|
382
|
+
|
|
383
|
+
```python
|
|
384
|
+
from aeknow.message import MessageSigner
|
|
385
|
+
|
|
386
|
+
# 从 Keystore 加载
|
|
387
|
+
signer = MessageSigner.from_keystore("wallet.json", "password")
|
|
388
|
+
|
|
389
|
+
# 或从私钥加载
|
|
390
|
+
signer = MessageSigner.from_secret_key("hex_secret_key")
|
|
391
|
+
|
|
392
|
+
# 或生成新账户
|
|
393
|
+
signer = MessageSigner.generate()
|
|
394
|
+
|
|
395
|
+
# 签名
|
|
396
|
+
result = signer.sign("Hello!")
|
|
397
|
+
print(result)
|
|
398
|
+
# {
|
|
399
|
+
# 'message': 'Hello!',
|
|
400
|
+
# 'address': 'ak_...',
|
|
401
|
+
# 'signature': '...',
|
|
402
|
+
# 'message_hash': '...'
|
|
403
|
+
# }
|
|
404
|
+
|
|
405
|
+
# 验证
|
|
406
|
+
is_valid = signer.verify("ak_...", "Hello!", "signature_hex")
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## crypto - 消息加密
|
|
412
|
+
|
|
413
|
+
基于 ED25519 -> X25519 密钥转换的 NaCl 加密模块。
|
|
414
|
+
|
|
415
|
+
### 加密方案
|
|
416
|
+
|
|
417
|
+
| 方案 | 说明 | 适用场景 |
|
|
418
|
+
|------|------|----------|
|
|
419
|
+
| SealedBox | 匿名加密,只需接收方公钥 | 公开投递、匿名消息 |
|
|
420
|
+
| Box | 双向认证加密,验证双方身份 | 私密通信、身份验证 |
|
|
421
|
+
|
|
422
|
+
### 核心函数
|
|
423
|
+
|
|
424
|
+
#### sealed_encrypt / sealed_decrypt - 匿名加密
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
from aeknow.crypto import sealed_encrypt, sealed_decrypt
|
|
428
|
+
from aeknow.signing import Account
|
|
429
|
+
|
|
430
|
+
# 加密(只需接收方地址)
|
|
431
|
+
ciphertext = sealed_encrypt("秘密消息", "ak_recipient...")
|
|
432
|
+
|
|
433
|
+
# 解密(需要接收方账户)
|
|
434
|
+
recipient = Account.from_keystore("recipient.json", "password")
|
|
435
|
+
plaintext = sealed_decrypt(ciphertext, recipient)
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
#### box_encrypt / box_decrypt - 双向认证加密
|
|
439
|
+
|
|
440
|
+
```python
|
|
441
|
+
from aeknow.crypto import box_encrypt, box_decrypt
|
|
442
|
+
|
|
443
|
+
# 加密(需要发送方账户 + 接收方地址)
|
|
444
|
+
sender = Account.from_keystore("sender.json", "password")
|
|
445
|
+
ciphertext = box_encrypt("秘密消息", sender, "ak_recipient...")
|
|
446
|
+
|
|
447
|
+
# 解密(需要接收方账户 + 发送方地址)
|
|
448
|
+
recipient = Account.from_keystore("recipient.json", "password")
|
|
449
|
+
plaintext = box_decrypt(ciphertext, recipient, "ak_sender...")
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### MessageCrypto 类
|
|
453
|
+
|
|
454
|
+
```python
|
|
455
|
+
from aeknow.crypto import MessageCrypto
|
|
456
|
+
|
|
457
|
+
# 初始化
|
|
458
|
+
crypto = MessageCrypto.from_keystore("wallet.json", "password")
|
|
459
|
+
# 或
|
|
460
|
+
crypto = MessageCrypto.from_mnemonic("your mnemonic words")
|
|
461
|
+
|
|
462
|
+
print(f"地址: {crypto.address}")
|
|
463
|
+
print(f"X25519 公钥: {crypto.x25519_public_hex}")
|
|
464
|
+
|
|
465
|
+
# 匿名加密(返回 Base64)
|
|
466
|
+
encrypted = crypto.sealed_encrypt("Hello", "ak_recipient...")
|
|
467
|
+
decrypted = crypto.sealed_decrypt(encrypted)
|
|
468
|
+
|
|
469
|
+
# 双向认证加密(返回 Base64)
|
|
470
|
+
encrypted = crypto.box_encrypt("Hello", "ak_recipient...")
|
|
471
|
+
decrypted = crypto.box_decrypt(encrypted, "ak_sender...")
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### 密钥转换函数
|
|
475
|
+
|
|
476
|
+
```python
|
|
477
|
+
from aeknow.crypto import (
|
|
478
|
+
ed25519_to_x25519_private,
|
|
479
|
+
ed25519_to_x25519_public,
|
|
480
|
+
account_to_x25519_keypair,
|
|
481
|
+
address_to_x25519_public,
|
|
482
|
+
get_key_info
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
# 获取账户密钥信息
|
|
486
|
+
info = get_key_info(account)
|
|
487
|
+
print(info)
|
|
488
|
+
# {
|
|
489
|
+
# 'address': 'ak_...',
|
|
490
|
+
# 'ed25519_public': '...',
|
|
491
|
+
# 'x25519_public': '...'
|
|
492
|
+
# }
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
## hashing - 哈希工具
|
|
498
|
+
|
|
499
|
+
编码、解码、哈希计算等底层工具函数。
|
|
500
|
+
|
|
501
|
+
### 编码/解码
|
|
502
|
+
|
|
503
|
+
```python
|
|
504
|
+
from aeknow.hashing import encode, decode
|
|
505
|
+
from aeknow.identifiers import ACCOUNT_ID
|
|
506
|
+
|
|
507
|
+
# 编码
|
|
508
|
+
raw_pubkey = bytes(32) # 32 字节公钥
|
|
509
|
+
encoded = encode(ACCOUNT_ID, raw_pubkey)
|
|
510
|
+
print(encoded) # ak_11111...
|
|
511
|
+
|
|
512
|
+
# 解码
|
|
513
|
+
raw_bytes = decode("ak_11111...")
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### RLP 编码
|
|
517
|
+
|
|
518
|
+
```python
|
|
519
|
+
from aeknow.hashing import encode_rlp, decode_rlp
|
|
520
|
+
from aeknow.identifiers import TRANSACTION
|
|
521
|
+
|
|
522
|
+
# 编码
|
|
523
|
+
data = [b"hello", b"world"]
|
|
524
|
+
encoded = encode_rlp(TRANSACTION, data)
|
|
525
|
+
|
|
526
|
+
# 解码
|
|
527
|
+
decoded = decode_rlp(encoded)
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### 哈希计算
|
|
531
|
+
|
|
532
|
+
```python
|
|
533
|
+
from aeknow.hashing import hash, hash_encode
|
|
534
|
+
from aeknow.identifiers import TRANSACTION_HASH
|
|
535
|
+
|
|
536
|
+
# 计算 blake2b 哈希
|
|
537
|
+
h = hash(b"data to hash")
|
|
538
|
+
print(h.hex())
|
|
539
|
+
|
|
540
|
+
# 计算并编码
|
|
541
|
+
encoded_hash = hash_encode(TRANSACTION_HASH, b"data to hash")
|
|
542
|
+
print(encoded_hash) # th_...
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### ID 相关函数
|
|
546
|
+
|
|
547
|
+
```python
|
|
548
|
+
from aeknow.hashing import name_id, contract_id, oracle_id, oracle_query_id, commitment_id
|
|
549
|
+
|
|
550
|
+
# 域名 ID
|
|
551
|
+
nm_id = name_id("example.chain")
|
|
552
|
+
|
|
553
|
+
# 合约 ID
|
|
554
|
+
ct_id = contract_id("ak_owner...", nonce=1)
|
|
555
|
+
|
|
556
|
+
# 预言机 ID
|
|
557
|
+
ok_id = oracle_id("ak_account...")
|
|
558
|
+
|
|
559
|
+
# 预言机查询 ID
|
|
560
|
+
oq_id = oracle_query_id("ak_sender...", nonce=1, oracle_id="ok_...")
|
|
561
|
+
|
|
562
|
+
# AENS 承诺 ID
|
|
563
|
+
cm_id, salt = commitment_id("example.chain")
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
### 随机数生成
|
|
567
|
+
|
|
568
|
+
```python
|
|
569
|
+
from aeknow.hashing import randint, randbytes
|
|
570
|
+
|
|
571
|
+
# 随机整数
|
|
572
|
+
n = randint(upper_bound=2**64)
|
|
573
|
+
|
|
574
|
+
# 随机字节
|
|
575
|
+
b = randbytes(size=32)
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
## node - 节点客户端
|
|
581
|
+
|
|
582
|
+
与 aeknow 节点交互的客户端。
|
|
583
|
+
|
|
584
|
+
### Config 配置类
|
|
585
|
+
|
|
586
|
+
```python
|
|
587
|
+
from aeknow.node import Config
|
|
588
|
+
|
|
589
|
+
config = Config(
|
|
590
|
+
external_url='https://sdk-mainnet.aepps.com', # 节点外部 URL
|
|
591
|
+
internal_url='http://localhost:3113', # 节点内部 URL(可选)
|
|
592
|
+
force_compatibility=False, # 是否忽略版本检查
|
|
593
|
+
blocking_mode=False, # 是否等待交易确认
|
|
594
|
+
network_id=None, # 网络 ID(自动检测)
|
|
595
|
+
# 交易参数
|
|
596
|
+
tx_gas_per_byte=20,
|
|
597
|
+
tx_base_gas=15000,
|
|
598
|
+
tx_gas_price=1000000000,
|
|
599
|
+
# 合约参数
|
|
600
|
+
contract_gas=10000,
|
|
601
|
+
contract_gas_price=1000000000,
|
|
602
|
+
# 轮询参数
|
|
603
|
+
poll_tx_max_retries=8,
|
|
604
|
+
poll_tx_retries_interval=2,
|
|
605
|
+
)
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
### NodeClient 类
|
|
609
|
+
|
|
610
|
+
#### 初始化
|
|
611
|
+
|
|
612
|
+
```python
|
|
613
|
+
from aeknow.node import NodeClient, Config
|
|
614
|
+
|
|
615
|
+
# 使用默认配置(主网)
|
|
616
|
+
client = NodeClient()
|
|
617
|
+
|
|
618
|
+
# 自定义配置
|
|
619
|
+
config = Config(external_url='https://testnet.aeknow.io')
|
|
620
|
+
client = NodeClient(config)
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
#### 查询链状态
|
|
624
|
+
|
|
625
|
+
```python
|
|
626
|
+
# 获取顶部区块
|
|
627
|
+
top = client.get_top_block()
|
|
628
|
+
print(f"高度: {top.height}")
|
|
629
|
+
|
|
630
|
+
# 获取当前高度
|
|
631
|
+
height = client.get_current_key_block_height()
|
|
632
|
+
|
|
633
|
+
# 获取节点状态
|
|
634
|
+
status = client.get_status()
|
|
635
|
+
print(f"网络: {status.network_id}")
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
#### 账户操作
|
|
639
|
+
|
|
640
|
+
```python
|
|
641
|
+
# 获取账户信息
|
|
642
|
+
account = client.get_account("ak_...")
|
|
643
|
+
print(f"余额: {account.balance}")
|
|
644
|
+
print(f"Nonce: {account.nonce}")
|
|
645
|
+
|
|
646
|
+
# 获取余额
|
|
647
|
+
balance = client.get_balance("ak_...")
|
|
648
|
+
|
|
649
|
+
# 获取下一个 nonce
|
|
650
|
+
nonce = client.get_next_nonce("ak_...")
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
#### 转账
|
|
654
|
+
|
|
655
|
+
```python
|
|
656
|
+
from aeknow.signing import Account
|
|
657
|
+
|
|
658
|
+
sender = Account.from_keystore("sender.json", "password")
|
|
659
|
+
|
|
660
|
+
# 简单转账
|
|
661
|
+
tx = client.spend(
|
|
662
|
+
account=sender,
|
|
663
|
+
recipient_id="ak_recipient...",
|
|
664
|
+
amount=1000000000000000000, # 1 AE (in aettos)
|
|
665
|
+
payload="转账备注"
|
|
666
|
+
)
|
|
667
|
+
print(f"交易哈希: {tx.hash}")
|
|
668
|
+
|
|
669
|
+
# 按百分比转账
|
|
670
|
+
tx = client.transfer_funds(
|
|
671
|
+
account=sender,
|
|
672
|
+
recipient_id="ak_recipient...",
|
|
673
|
+
percentage=0.5, # 转账 50%
|
|
674
|
+
include_fee=True # 从金额中扣除手续费
|
|
675
|
+
)
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
#### 交易操作
|
|
679
|
+
|
|
680
|
+
```python
|
|
681
|
+
# 签名交易
|
|
682
|
+
signed_tx = client.sign_transaction(account, unsigned_tx)
|
|
683
|
+
|
|
684
|
+
# 广播交易
|
|
685
|
+
tx_hash = client.broadcast_transaction(signed_tx)
|
|
686
|
+
|
|
687
|
+
# 获取交易
|
|
688
|
+
tx = client.get_transaction("th_...")
|
|
689
|
+
|
|
690
|
+
# 等待交易确认
|
|
691
|
+
block_height = client.wait_for_transaction("th_...")
|
|
692
|
+
|
|
693
|
+
# 等待多个区块确认
|
|
694
|
+
block_height = client.wait_for_confirmation("th_...")
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
#### 合约/域名/预言机
|
|
698
|
+
|
|
699
|
+
```python
|
|
700
|
+
# 创建合约对象
|
|
701
|
+
contract = client.Contract()
|
|
702
|
+
|
|
703
|
+
# 创建域名对象
|
|
704
|
+
name = client.AEName("example.chain")
|
|
705
|
+
|
|
706
|
+
# 创建预言机对象
|
|
707
|
+
oracle = client.Oracle()
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
## compiler - 编译器客户端
|
|
713
|
+
|
|
714
|
+
Sophia 合约编译器客户端。
|
|
715
|
+
|
|
716
|
+
### CompilerClient 类
|
|
717
|
+
|
|
718
|
+
```python
|
|
719
|
+
from aeknow.compiler import CompilerClient
|
|
720
|
+
|
|
721
|
+
# 使用默认编译器
|
|
722
|
+
compiler = CompilerClient()
|
|
723
|
+
|
|
724
|
+
# 指定编译器 URL
|
|
725
|
+
compiler = CompilerClient(compiler_url="https://v8.compiler.aepps.com")
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
#### 编译合约
|
|
729
|
+
|
|
730
|
+
```python
|
|
731
|
+
# 从源码编译
|
|
732
|
+
source_code = '''
|
|
733
|
+
@compiler >= 6
|
|
734
|
+
contract SimpleStorage =
|
|
735
|
+
record state = { value : int }
|
|
736
|
+
entrypoint init(v : int) = { value = v }
|
|
737
|
+
entrypoint get() = state.value
|
|
738
|
+
stateful entrypoint set(v : int) = put(state{ value = v })
|
|
739
|
+
'''
|
|
740
|
+
|
|
741
|
+
bytecode = compiler.compile(source_code)
|
|
742
|
+
print(bytecode) # cb_...
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
#### 生成 Calldata
|
|
746
|
+
|
|
747
|
+
```python
|
|
748
|
+
# 生成初始化 calldata
|
|
749
|
+
init_calldata = compiler.encode_calldata(source_code, "init", ["42"])
|
|
750
|
+
|
|
751
|
+
# 生成调用 calldata
|
|
752
|
+
call_calldata = compiler.encode_calldata(source_code, "set", ["100"])
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
#### 解码返回值
|
|
756
|
+
|
|
757
|
+
```python
|
|
758
|
+
# 解码调用结果
|
|
759
|
+
result = compiler.decode_call_result(source_code, "get", call_result_data)
|
|
760
|
+
print(result) # 42
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
#### 获取 ACI
|
|
764
|
+
|
|
765
|
+
```python
|
|
766
|
+
# 获取合约接口
|
|
767
|
+
aci = compiler.generate_aci(source_code)
|
|
768
|
+
print(aci)
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
---
|
|
772
|
+
|
|
773
|
+
## contract - 合约模块
|
|
774
|
+
|
|
775
|
+
低级合约操作模块。
|
|
776
|
+
|
|
777
|
+
### Contract 类
|
|
778
|
+
|
|
779
|
+
```python
|
|
780
|
+
from aeknow.node import NodeClient
|
|
781
|
+
from aeknow.signing import Account
|
|
782
|
+
|
|
783
|
+
client = NodeClient()
|
|
784
|
+
contract = client.Contract()
|
|
785
|
+
|
|
786
|
+
account = Account.from_keystore("wallet.json", "password")
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
#### 部署合约
|
|
790
|
+
|
|
791
|
+
```python
|
|
792
|
+
tx = contract.create(
|
|
793
|
+
account=account,
|
|
794
|
+
bytecode="cb_...", # 编译后的字节码
|
|
795
|
+
calldata="cb_...", # init 函数 calldata
|
|
796
|
+
amount=0, # 转入合约的金额
|
|
797
|
+
gas=100000, # Gas 限制
|
|
798
|
+
gas_price=1000000000 # Gas 价格
|
|
799
|
+
)
|
|
800
|
+
|
|
801
|
+
contract_id = tx.metadata.get("contract_id")
|
|
802
|
+
print(f"合约地址: {contract_id}")
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
#### 调用合约
|
|
806
|
+
|
|
807
|
+
```python
|
|
808
|
+
tx = contract.call(
|
|
809
|
+
contract_id="ct_...",
|
|
810
|
+
account=account,
|
|
811
|
+
function="set",
|
|
812
|
+
calldata="cb_...",
|
|
813
|
+
amount=0,
|
|
814
|
+
gas=100000
|
|
815
|
+
)
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
#### 静态调用(不上链)
|
|
819
|
+
|
|
820
|
+
```python
|
|
821
|
+
result = contract.call_static(
|
|
822
|
+
contract_id="ct_...",
|
|
823
|
+
function="get",
|
|
824
|
+
calldata="cb_..."
|
|
825
|
+
)
|
|
826
|
+
print(result.return_value)
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
#### 获取调用结果
|
|
830
|
+
|
|
831
|
+
```python
|
|
832
|
+
call_object = contract.get_call_object("th_...")
|
|
833
|
+
print(call_object.return_value)
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
#### 检查合约是否部署
|
|
837
|
+
|
|
838
|
+
```python
|
|
839
|
+
is_deployed = contract.is_deployed("ct_...")
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
---
|
|
843
|
+
|
|
844
|
+
## contract_native - 原生合约管理
|
|
845
|
+
|
|
846
|
+
高级合约管理器,自动处理编译、部署、调用。
|
|
847
|
+
|
|
848
|
+
### ContractManager 类
|
|
849
|
+
|
|
850
|
+
```python
|
|
851
|
+
from aeknow.contract_native import ContractManager
|
|
852
|
+
from aeknow.node import NodeClient
|
|
853
|
+
from aeknow.signing import Account
|
|
854
|
+
|
|
855
|
+
client = NodeClient()
|
|
856
|
+
account = Account.from_keystore("wallet.json", "password")
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
#### 从源码创建
|
|
860
|
+
|
|
861
|
+
```python
|
|
862
|
+
source_code = open("contract.aes").read()
|
|
863
|
+
|
|
864
|
+
manager = ContractManager(
|
|
865
|
+
client=client,
|
|
866
|
+
account=account,
|
|
867
|
+
source=source_code
|
|
868
|
+
)
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
#### 从已部署合约创建
|
|
872
|
+
|
|
873
|
+
```python
|
|
874
|
+
manager = ContractManager(
|
|
875
|
+
client=client,
|
|
876
|
+
account=account,
|
|
877
|
+
contract_id="ct_...",
|
|
878
|
+
source=source_code
|
|
879
|
+
)
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
#### 部署合约
|
|
883
|
+
|
|
884
|
+
```python
|
|
885
|
+
# 带初始参数部署
|
|
886
|
+
tx = manager.deploy("42") # init(42)
|
|
887
|
+
|
|
888
|
+
print(f"合约地址: {manager.contract_id}")
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
#### 调用合约函数
|
|
892
|
+
|
|
893
|
+
```python
|
|
894
|
+
# 写入调用(上链)
|
|
895
|
+
tx = manager.call("set", "100")
|
|
896
|
+
print(f"交易: {tx.hash}")
|
|
897
|
+
|
|
898
|
+
# 读取调用(不上链)
|
|
899
|
+
result = manager.call_static("get")
|
|
900
|
+
print(f"结果: {result}")
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
#### 解码事件
|
|
904
|
+
|
|
905
|
+
```python
|
|
906
|
+
# 获取交易事件
|
|
907
|
+
events = manager.get_events("th_...")
|
|
908
|
+
for event in events:
|
|
909
|
+
print(f"事件: {event}")
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
---
|
|
913
|
+
|
|
914
|
+
## transactions - 交易构建
|
|
915
|
+
|
|
916
|
+
底层交易构建模块,用于创建各类交易。
|
|
917
|
+
|
|
918
|
+
### TxBuilder 类
|
|
919
|
+
|
|
920
|
+
```python
|
|
921
|
+
from aeknow.transactions import TxBuilder
|
|
922
|
+
|
|
923
|
+
txb = TxBuilder(
|
|
924
|
+
base_gas=15000,
|
|
925
|
+
gas_per_byte=20,
|
|
926
|
+
gas_price=1000000000,
|
|
927
|
+
key_block_interval=3
|
|
928
|
+
)
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
#### 构建 Spend 交易
|
|
932
|
+
|
|
933
|
+
```python
|
|
934
|
+
tx = txb.tx_spend(
|
|
935
|
+
sender_id="ak_sender...",
|
|
936
|
+
recipient_id="ak_recipient...",
|
|
937
|
+
amount=1000000000000000000,
|
|
938
|
+
payload="备注",
|
|
939
|
+
fee=0, # 自动计算
|
|
940
|
+
ttl=0,
|
|
941
|
+
nonce=1
|
|
942
|
+
)
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
#### 构建合约创建交易
|
|
946
|
+
|
|
947
|
+
```python
|
|
948
|
+
tx = txb.tx_contract_create(
|
|
949
|
+
owner_id="ak_...",
|
|
950
|
+
code="cb_...",
|
|
951
|
+
calldata="cb_...",
|
|
952
|
+
amount=0,
|
|
953
|
+
deposit=0,
|
|
954
|
+
gas=100000,
|
|
955
|
+
gas_price=1000000000,
|
|
956
|
+
vm_version=8,
|
|
957
|
+
abi_version=3,
|
|
958
|
+
fee=0,
|
|
959
|
+
ttl=0,
|
|
960
|
+
nonce=1
|
|
961
|
+
)
|
|
962
|
+
```
|
|
963
|
+
|
|
964
|
+
#### 构建合约调用交易
|
|
965
|
+
|
|
966
|
+
```python
|
|
967
|
+
tx = txb.tx_contract_call(
|
|
968
|
+
caller_id="ak_...",
|
|
969
|
+
contract_id="ct_...",
|
|
970
|
+
calldata="cb_...",
|
|
971
|
+
function="set",
|
|
972
|
+
amount=0,
|
|
973
|
+
gas=100000,
|
|
974
|
+
gas_price=1000000000,
|
|
975
|
+
abi_version=3,
|
|
976
|
+
fee=0,
|
|
977
|
+
ttl=0,
|
|
978
|
+
nonce=1
|
|
979
|
+
)
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
### TxSigner 类
|
|
983
|
+
|
|
984
|
+
```python
|
|
985
|
+
from aeknow.transactions import TxSigner
|
|
986
|
+
from aeknow.signing import Account
|
|
987
|
+
|
|
988
|
+
account = Account.generate()
|
|
989
|
+
signer = TxSigner(account, network_id="ae_mainnet")
|
|
990
|
+
|
|
991
|
+
# 签名交易
|
|
992
|
+
signature = signer.sign_transaction(tx)
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
### TxObject 类
|
|
996
|
+
|
|
997
|
+
交易对象,包含交易数据和元信息。
|
|
998
|
+
|
|
999
|
+
```python
|
|
1000
|
+
# 属性
|
|
1001
|
+
tx.tx # 编码后的交易字符串
|
|
1002
|
+
tx.hash # 交易哈希 (th_...)
|
|
1003
|
+
tx.data # 交易数据对象
|
|
1004
|
+
tx.metadata # 元数据字典
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
---
|
|
1008
|
+
|
|
1009
|
+
## aens - 域名服务
|
|
1010
|
+
|
|
1011
|
+
aeknow 域名服务 (AENS) 模块。
|
|
1012
|
+
|
|
1013
|
+
### AEName 类
|
|
1014
|
+
|
|
1015
|
+
```python
|
|
1016
|
+
from aeknow.node import NodeClient
|
|
1017
|
+
from aeknow.signing import Account
|
|
1018
|
+
|
|
1019
|
+
client = NodeClient()
|
|
1020
|
+
account = Account.from_keystore("wallet.json", "password")
|
|
1021
|
+
|
|
1022
|
+
# 创建域名对象
|
|
1023
|
+
name = client.AEName("example.chain")
|
|
1024
|
+
```
|
|
1025
|
+
|
|
1026
|
+
#### 检查域名状态
|
|
1027
|
+
|
|
1028
|
+
```python
|
|
1029
|
+
# 更新状态
|
|
1030
|
+
name.update_status()
|
|
1031
|
+
print(name.status) # AVAILABLE / CLAIMED / PRECLAIMED
|
|
1032
|
+
|
|
1033
|
+
# 检查是否可用
|
|
1034
|
+
if name.is_available():
|
|
1035
|
+
print("域名可注册")
|
|
1036
|
+
|
|
1037
|
+
# 检查是否已注册
|
|
1038
|
+
if name.check_claimed():
|
|
1039
|
+
print(f"TTL: {name.name_ttl}")
|
|
1040
|
+
print(f"指针: {name.pointers}")
|
|
1041
|
+
```
|
|
1042
|
+
|
|
1043
|
+
#### 完整注册流程(阻塞模式)
|
|
1044
|
+
|
|
1045
|
+
```python
|
|
1046
|
+
# 一键注册(预注册 -> 注册 -> 更新指针)
|
|
1047
|
+
hashes = name.full_claim_blocking(
|
|
1048
|
+
account,
|
|
1049
|
+
account.get_address(), # 指向账户
|
|
1050
|
+
name_ttl=50000,
|
|
1051
|
+
client_ttl=84600
|
|
1052
|
+
)
|
|
1053
|
+
print(hashes['preclaim_tx'].hash)
|
|
1054
|
+
print(hashes['claim_tx'].hash)
|
|
1055
|
+
print(hashes['update_tx'].hash)
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
#### 分步注册
|
|
1059
|
+
|
|
1060
|
+
```python
|
|
1061
|
+
# Step 1: 预注册
|
|
1062
|
+
preclaim_tx = name.preclaim(account)
|
|
1063
|
+
print(f"预注册: {preclaim_tx.hash}")
|
|
1064
|
+
|
|
1065
|
+
# 等待确认...
|
|
1066
|
+
client.wait_for_confirmation(preclaim_tx.hash)
|
|
1067
|
+
|
|
1068
|
+
# Step 2: 注册
|
|
1069
|
+
claim_tx = name.claim(
|
|
1070
|
+
preclaim_tx.hash,
|
|
1071
|
+
account,
|
|
1072
|
+
preclaim_tx.metadata['salt']
|
|
1073
|
+
)
|
|
1074
|
+
print(f"注册: {claim_tx.hash}")
|
|
1075
|
+
|
|
1076
|
+
# 等待确认...
|
|
1077
|
+
client.wait_for_confirmation(claim_tx.hash)
|
|
1078
|
+
|
|
1079
|
+
# Step 3: 更新指针
|
|
1080
|
+
update_tx = name.update(
|
|
1081
|
+
account,
|
|
1082
|
+
account.get_address() # 指向账户
|
|
1083
|
+
)
|
|
1084
|
+
```
|
|
1085
|
+
|
|
1086
|
+
#### 更新域名指针
|
|
1087
|
+
|
|
1088
|
+
```python
|
|
1089
|
+
# 指向账户
|
|
1090
|
+
name.update(account, "ak_...")
|
|
1091
|
+
|
|
1092
|
+
# 指向合约
|
|
1093
|
+
name.update(account, "ct_...")
|
|
1094
|
+
|
|
1095
|
+
# 指向预言机
|
|
1096
|
+
name.update(account, "ok_...")
|
|
1097
|
+
|
|
1098
|
+
# 多个指针
|
|
1099
|
+
name.update(account, "ak_...", "ct_...")
|
|
1100
|
+
|
|
1101
|
+
# 自定义指针
|
|
1102
|
+
name.update(account, ("custom_key", "ak_..."))
|
|
1103
|
+
```
|
|
1104
|
+
|
|
1105
|
+
#### 转让域名
|
|
1106
|
+
|
|
1107
|
+
```python
|
|
1108
|
+
transfer_tx = name.transfer_ownership(
|
|
1109
|
+
account,
|
|
1110
|
+
recipient_id="ak_new_owner..."
|
|
1111
|
+
)
|
|
1112
|
+
```
|
|
1113
|
+
|
|
1114
|
+
#### 撤销域名
|
|
1115
|
+
|
|
1116
|
+
```python
|
|
1117
|
+
revoke_tx = name.revoke(account)
|
|
1118
|
+
```
|
|
1119
|
+
|
|
1120
|
+
#### 计算费用
|
|
1121
|
+
|
|
1122
|
+
```python
|
|
1123
|
+
from aeknow.aens import AEName
|
|
1124
|
+
|
|
1125
|
+
# 获取最低注册费
|
|
1126
|
+
min_fee = AEName.get_minimum_name_fee("example.chain")
|
|
1127
|
+
print(f"最低费用: {min_fee} aettos")
|
|
1128
|
+
|
|
1129
|
+
# 计算竞价费(+5%)
|
|
1130
|
+
bid_fee = AEName.compute_bid_fee("example.chain", start_fee=min_fee)
|
|
1131
|
+
|
|
1132
|
+
# 计算拍卖结束区块
|
|
1133
|
+
end_block = AEName.compute_auction_end_block("example.chain", claim_height=1000)
|
|
1134
|
+
```
|
|
1135
|
+
|
|
1136
|
+
### NameStatus 枚举
|
|
1137
|
+
|
|
1138
|
+
```python
|
|
1139
|
+
from aeknow.aens import NameStatus
|
|
1140
|
+
|
|
1141
|
+
NameStatus.AVAILABLE # 可用
|
|
1142
|
+
NameStatus.PRECLAIMED # 已预注册
|
|
1143
|
+
NameStatus.CLAIMED # 已注册
|
|
1144
|
+
NameStatus.REVOKED # 已撤销
|
|
1145
|
+
NameStatus.UNKNOWN # 未知
|
|
1146
|
+
```
|
|
1147
|
+
|
|
1148
|
+
---
|
|
1149
|
+
|
|
1150
|
+
## oracles - 预言机
|
|
1151
|
+
|
|
1152
|
+
aeknow 预言机模块。
|
|
1153
|
+
|
|
1154
|
+
### Oracle 类
|
|
1155
|
+
|
|
1156
|
+
```python
|
|
1157
|
+
from aeknow.node import NodeClient
|
|
1158
|
+
from aeknow.signing import Account
|
|
1159
|
+
|
|
1160
|
+
client = NodeClient()
|
|
1161
|
+
account = Account.from_keystore("wallet.json", "password")
|
|
1162
|
+
oracle = client.Oracle()
|
|
1163
|
+
```
|
|
1164
|
+
|
|
1165
|
+
#### 注册预言机
|
|
1166
|
+
|
|
1167
|
+
```python
|
|
1168
|
+
tx = oracle.register(
|
|
1169
|
+
account,
|
|
1170
|
+
query_format="string", # 查询格式
|
|
1171
|
+
response_format="string", # 响应格式
|
|
1172
|
+
query_fee=0, # 查询费用
|
|
1173
|
+
ttl_type='delta', # TTL 类型
|
|
1174
|
+
ttl_value=500 # TTL 值
|
|
1175
|
+
)
|
|
1176
|
+
|
|
1177
|
+
print(f"预言机 ID: {oracle.id}") # ok_...
|
|
1178
|
+
```
|
|
1179
|
+
|
|
1180
|
+
#### 响应查询
|
|
1181
|
+
|
|
1182
|
+
```python
|
|
1183
|
+
tx = oracle.respond(
|
|
1184
|
+
account,
|
|
1185
|
+
query_id="oq_...",
|
|
1186
|
+
response="Response data"
|
|
1187
|
+
)
|
|
1188
|
+
```
|
|
1189
|
+
|
|
1190
|
+
#### 延长 TTL
|
|
1191
|
+
|
|
1192
|
+
```python
|
|
1193
|
+
tx = oracle.extend(
|
|
1194
|
+
account,
|
|
1195
|
+
query_id="oq_...",
|
|
1196
|
+
response="",
|
|
1197
|
+
ttl_value=500
|
|
1198
|
+
)
|
|
1199
|
+
```
|
|
1200
|
+
|
|
1201
|
+
### OracleQuery 类
|
|
1202
|
+
|
|
1203
|
+
```python
|
|
1204
|
+
# 创建查询对象
|
|
1205
|
+
query = client.OracleQuery(oracle_id="ok_...")
|
|
1206
|
+
|
|
1207
|
+
# 执行查询
|
|
1208
|
+
tx = query.execute(
|
|
1209
|
+
sender=account,
|
|
1210
|
+
query="What is the price of AE?",
|
|
1211
|
+
query_fee=1000,
|
|
1212
|
+
query_ttl_value=10,
|
|
1213
|
+
response_ttl_value=10
|
|
1214
|
+
)
|
|
1215
|
+
|
|
1216
|
+
print(f"查询 ID: {query.id}") # oq_...
|
|
1217
|
+
|
|
1218
|
+
# 获取响应
|
|
1219
|
+
response = query.get_response_object()
|
|
1220
|
+
print(response)
|
|
1221
|
+
```
|
|
1222
|
+
|
|
1223
|
+
---
|
|
1224
|
+
|
|
1225
|
+
## utils - 工具函数
|
|
1226
|
+
|
|
1227
|
+
通用工具函数集合。
|
|
1228
|
+
|
|
1229
|
+
### 验证函数
|
|
1230
|
+
|
|
1231
|
+
```python
|
|
1232
|
+
from aeknow.utils import is_valid_hash, is_valid_aens_name, prefix_match
|
|
1233
|
+
|
|
1234
|
+
# 验证哈希
|
|
1235
|
+
is_valid = is_valid_hash("ak_...") # True
|
|
1236
|
+
is_valid = is_valid_hash("ak_...", prefix="ak") # True
|
|
1237
|
+
is_valid = is_valid_hash("th_...", prefix="ak") # False
|
|
1238
|
+
|
|
1239
|
+
# 验证域名
|
|
1240
|
+
is_valid = is_valid_aens_name("example.chain") # True
|
|
1241
|
+
is_valid = is_valid_aens_name("example.com") # False
|
|
1242
|
+
|
|
1243
|
+
# 前缀匹配
|
|
1244
|
+
match = prefix_match("ak", "ak_123") # True
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
### 金额转换
|
|
1248
|
+
|
|
1249
|
+
```python
|
|
1250
|
+
from aeknow.utils import amount_to_aettos, format_amount
|
|
1251
|
+
|
|
1252
|
+
# 转换为 aettos
|
|
1253
|
+
aettos = amount_to_aettos(1) # 1 aetto
|
|
1254
|
+
aettos = amount_to_aettos(1.5) # 1.5e18 aettos
|
|
1255
|
+
aettos = amount_to_aettos("1AE") # 1e18 aettos
|
|
1256
|
+
aettos = amount_to_aettos("1.5ae") # 1.5e18 aettos
|
|
1257
|
+
|
|
1258
|
+
# 格式化金额
|
|
1259
|
+
formatted = format_amount(1000000000000000000) # "1AE"
|
|
1260
|
+
formatted = format_amount(1500000000000000000) # "1.5AE"
|
|
1261
|
+
formatted = format_amount(1000000, -6, "microAE") # "1microAE"
|
|
1262
|
+
```
|
|
1263
|
+
|
|
1264
|
+
---
|
|
1265
|
+
|
|
1266
|
+
## defaults - 默认配置
|
|
1267
|
+
|
|
1268
|
+
SDK 默认参数配置。
|
|
1269
|
+
|
|
1270
|
+
```python
|
|
1271
|
+
from aeknow import defaults
|
|
1272
|
+
|
|
1273
|
+
# Gas 相关
|
|
1274
|
+
defaults.BASE_GAS # 15000
|
|
1275
|
+
defaults.GAS_PER_BYTE # 20
|
|
1276
|
+
defaults.GAS_PRICE # 1000000000 (1 Gwei)
|
|
1277
|
+
|
|
1278
|
+
# 交易
|
|
1279
|
+
defaults.TX_TTL # 0 (最大 TTL)
|
|
1280
|
+
defaults.FEE # 0 (自动计算)
|
|
1281
|
+
|
|
1282
|
+
# 合约
|
|
1283
|
+
defaults.CONTRACT_GAS # 10000
|
|
1284
|
+
defaults.CONTRACT_GAS_PRICE # 1000000000
|
|
1285
|
+
defaults.CONTRACT_DEPOSIT # 0
|
|
1286
|
+
defaults.CONTRACT_AMOUNT # 0
|
|
1287
|
+
|
|
1288
|
+
# 预言机
|
|
1289
|
+
defaults.ORACLE_TTL_TYPE # 'delta'
|
|
1290
|
+
defaults.ORACLE_TTL_VALUE # 500
|
|
1291
|
+
defaults.ORACLE_QUERY_FEE # 0
|
|
1292
|
+
|
|
1293
|
+
# 域名
|
|
1294
|
+
defaults.NAME_MAX_TTL # 50000 blocks
|
|
1295
|
+
defaults.NAME_FEE # 0
|
|
1296
|
+
defaults.NAME_BID_RANGES # {长度: 费用} 映射
|
|
1297
|
+
|
|
1298
|
+
# 链参数
|
|
1299
|
+
defaults.KEY_BLOCK_INTERVAL # 3 分钟
|
|
1300
|
+
defaults.KEY_BLOCK_CONFIRMATION_NUM # 3 个区块
|
|
1301
|
+
|
|
1302
|
+
# 轮询
|
|
1303
|
+
defaults.POLL_TX_MAX_RETRIES # 8
|
|
1304
|
+
defaults.POLL_TX_RETRIES_INTERVAL # 2 秒
|
|
1305
|
+
|
|
1306
|
+
# 编译器
|
|
1307
|
+
defaults.COMPILER_URL # "https://v8.compiler.aepps.com"
|
|
1308
|
+
|
|
1309
|
+
# Dry Run
|
|
1310
|
+
defaults.DRY_RUN_ADDRESS # 测试地址
|
|
1311
|
+
defaults.DRY_RUN_AMOUNT # 测试金额
|
|
1312
|
+
```
|
|
1313
|
+
|
|
1314
|
+
---
|
|
1315
|
+
|
|
1316
|
+
## identifiers - 标识符常量
|
|
1317
|
+
|
|
1318
|
+
各类 ID 前缀和协议常量。
|
|
1319
|
+
|
|
1320
|
+
### ID 前缀 (Base58)
|
|
1321
|
+
|
|
1322
|
+
```python
|
|
1323
|
+
from aeknow import identifiers
|
|
1324
|
+
|
|
1325
|
+
identifiers.ACCOUNT_ID # "ak" - 账户
|
|
1326
|
+
identifiers.CONTRACT_ID # "ct" - 合约
|
|
1327
|
+
identifiers.ORACLE_ID # "ok" - 预言机
|
|
1328
|
+
identifiers.ORACLE_QUERY_ID # "oq" - 预言机查询
|
|
1329
|
+
identifiers.NAME_ID # "nm" - 域名
|
|
1330
|
+
identifiers.CHANNEL_ID # "ch" - 通道
|
|
1331
|
+
identifiers.TRANSACTION_HASH # "th" - 交易哈希
|
|
1332
|
+
identifiers.KEY_BLOCK_HASH # "kh" - 关键块哈希
|
|
1333
|
+
identifiers.MICRO_BLOCK_HASH # "mh" - 微块哈希
|
|
1334
|
+
identifiers.COMMITMENT_ID # "cm" - 承诺
|
|
1335
|
+
identifiers.SIGNATURE # "sg" - 签名
|
|
1336
|
+
```
|
|
1337
|
+
|
|
1338
|
+
### ID 前缀 (Base64)
|
|
1339
|
+
|
|
1340
|
+
```python
|
|
1341
|
+
identifiers.BYTECODE # "cb" - 合约字节码
|
|
1342
|
+
identifiers.TRANSACTION # "tx" - 交易
|
|
1343
|
+
identifiers.BYTE_ARRAY # "ba" - 字节数组
|
|
1344
|
+
identifiers.ORACLE_QUERY # "ov" - 预言机查询
|
|
1345
|
+
identifiers.ORACLE_RESPONSE # "or" - 预言机响应
|
|
1346
|
+
```
|
|
1347
|
+
|
|
1348
|
+
### 账户地址格式
|
|
1349
|
+
|
|
1350
|
+
```python
|
|
1351
|
+
identifiers.ACCOUNT_API_FORMAT # 'api' - ak_xxx
|
|
1352
|
+
identifiers.ACCOUNT_SOFIA_FORMAT # 'sofia' - 0x...
|
|
1353
|
+
identifiers.ACCOUNT_RAW_FORMAT # 'raw' - bytes
|
|
1354
|
+
```
|
|
1355
|
+
|
|
1356
|
+
### VM/ABI 版本
|
|
1357
|
+
|
|
1358
|
+
```python
|
|
1359
|
+
identifiers.VM_FATE_3 # 8 (Ceres)
|
|
1360
|
+
identifiers.ABI_FATE # 3
|
|
1361
|
+
|
|
1362
|
+
# 协议版本映射
|
|
1363
|
+
identifiers.PROTOCOL_ABI_VM[identifiers.PROTOCOL_CERES]
|
|
1364
|
+
# {'vm': 8, 'abi': 3}
|
|
1365
|
+
```
|
|
1366
|
+
|
|
1367
|
+
### 网络 ID
|
|
1368
|
+
|
|
1369
|
+
```python
|
|
1370
|
+
identifiers.NETWORK_ID_MAINNET # "ae_mainnet"
|
|
1371
|
+
identifiers.NETWORK_ID_TESTNET # "ae_uat"
|
|
1372
|
+
```
|
|
1373
|
+
|
|
1374
|
+
### 账户类型
|
|
1375
|
+
|
|
1376
|
+
```python
|
|
1377
|
+
identifiers.ACCOUNT_KIND_BASIC # "basic"
|
|
1378
|
+
identifiers.ACCOUNT_KIND_GENERALIZED # "generalized"
|
|
1379
|
+
```
|
|
1380
|
+
|
|
1381
|
+
### Keystore 类型
|
|
1382
|
+
|
|
1383
|
+
```python
|
|
1384
|
+
identifiers.SECRET_TYPE_BIP39 # "ed25519-bip39-mnemonic"
|
|
1385
|
+
identifiers.SECRET_TYPE_SLIP0010 # "ed25519-slip0010-masterkey"
|
|
1386
|
+
```
|
|
1387
|
+
|
|
1388
|
+
---
|
|
1389
|
+
|
|
1390
|
+
## 异常类型
|
|
1391
|
+
|
|
1392
|
+
```python
|
|
1393
|
+
from aeknow.exceptions import (
|
|
1394
|
+
TransactionWaitTimeoutExpired, # 交易等待超时
|
|
1395
|
+
TransactionHashMismatch, # 交易哈希不匹配
|
|
1396
|
+
NameNotAvailable, # 域名不可用
|
|
1397
|
+
MissingPreclaim, # 缺少预注册
|
|
1398
|
+
NameUpdateError, # 域名更新错误
|
|
1399
|
+
NameTooEarlyClaim, # 过早注册
|
|
1400
|
+
NameCommitmentIdMismatch, # 承诺 ID 不匹配
|
|
1401
|
+
UnsupportedNodeVersion, # 节点版本不支持
|
|
1402
|
+
)
|
|
1403
|
+
```
|
|
1404
|
+
|
|
1405
|
+
---
|
|
1406
|
+
|
|
1407
|
+
## 完整示例
|
|
1408
|
+
|
|
1409
|
+
### 创建钱包并保存
|
|
1410
|
+
|
|
1411
|
+
```python
|
|
1412
|
+
from aeknow.wallet import MnemonicWallet
|
|
1413
|
+
|
|
1414
|
+
# 生成新钱包
|
|
1415
|
+
wallet = MnemonicWallet.generate()
|
|
1416
|
+
|
|
1417
|
+
print(f"助记词: {wallet.mnemonic}")
|
|
1418
|
+
print(f"地址: {wallet.address}")
|
|
1419
|
+
|
|
1420
|
+
# 保存 Keystore
|
|
1421
|
+
wallet.save_keystore("my_wallet.json", "secure_password")
|
|
1422
|
+
```
|
|
1423
|
+
|
|
1424
|
+
### 转账 AE
|
|
1425
|
+
|
|
1426
|
+
```python
|
|
1427
|
+
from aeknow.node import NodeClient, Config
|
|
1428
|
+
from aeknow.signing import Account
|
|
1429
|
+
|
|
1430
|
+
client = NodeClient(Config(external_url='https://sdk-mainnet.aepps.com'))
|
|
1431
|
+
account = Account.from_keystore("wallet.json", "password")
|
|
1432
|
+
|
|
1433
|
+
# 转账 1 AE
|
|
1434
|
+
tx = client.spend(
|
|
1435
|
+
account=account,
|
|
1436
|
+
recipient_id="ak_recipient...",
|
|
1437
|
+
amount="1AE",
|
|
1438
|
+
payload="Payment"
|
|
1439
|
+
)
|
|
1440
|
+
|
|
1441
|
+
print(f"交易哈希: {tx.hash}")
|
|
1442
|
+
```
|
|
1443
|
+
|
|
1444
|
+
### 部署和调用合约
|
|
1445
|
+
|
|
1446
|
+
```python
|
|
1447
|
+
from aeknow.node import NodeClient
|
|
1448
|
+
from aeknow.signing import Account
|
|
1449
|
+
from aeknow.contract_native import ContractManager
|
|
1450
|
+
|
|
1451
|
+
client = NodeClient()
|
|
1452
|
+
account = Account.from_keystore("wallet.json", "password")
|
|
1453
|
+
|
|
1454
|
+
source = '''
|
|
1455
|
+
@compiler >= 6
|
|
1456
|
+
contract Counter =
|
|
1457
|
+
record state = { count : int }
|
|
1458
|
+
entrypoint init(n : int) = { count = n }
|
|
1459
|
+
entrypoint get() = state.count
|
|
1460
|
+
stateful entrypoint add(n : int) = put(state{ count = state.count + n })
|
|
1461
|
+
'''
|
|
1462
|
+
|
|
1463
|
+
manager = ContractManager(client=client, account=account, source=source)
|
|
1464
|
+
|
|
1465
|
+
# 部署
|
|
1466
|
+
tx = manager.deploy("0") # init(0)
|
|
1467
|
+
print(f"合约地址: {manager.contract_id}")
|
|
1468
|
+
|
|
1469
|
+
# 调用
|
|
1470
|
+
tx = manager.call("add", "10")
|
|
1471
|
+
result = manager.call_static("get")
|
|
1472
|
+
print(f"Count: {result}")
|
|
1473
|
+
```
|
|
1474
|
+
|
|
1475
|
+
### 消息签名和验证
|
|
1476
|
+
|
|
1477
|
+
```python
|
|
1478
|
+
from aeknow.message import sign_message, verify_message
|
|
1479
|
+
from aeknow.signing import Account
|
|
1480
|
+
|
|
1481
|
+
account = Account.generate()
|
|
1482
|
+
|
|
1483
|
+
# 签名
|
|
1484
|
+
signature = sign_message(account, "Hello aeknow!")
|
|
1485
|
+
|
|
1486
|
+
# 验证
|
|
1487
|
+
is_valid = verify_message(account.get_address(), "Hello aeknow!", signature)
|
|
1488
|
+
print(f"签名有效: {is_valid}")
|
|
1489
|
+
```
|
|
1490
|
+
|
|
1491
|
+
### 加密通信
|
|
1492
|
+
|
|
1493
|
+
```python
|
|
1494
|
+
from aeknow.crypto import MessageCrypto
|
|
1495
|
+
from aeknow.signing import Account
|
|
1496
|
+
|
|
1497
|
+
# Alice 和 Bob 的账户
|
|
1498
|
+
alice = Account.generate()
|
|
1499
|
+
bob = Account.generate()
|
|
1500
|
+
|
|
1501
|
+
alice_crypto = MessageCrypto.from_account(alice)
|
|
1502
|
+
bob_crypto = MessageCrypto.from_account(bob)
|
|
1503
|
+
|
|
1504
|
+
# Alice 发送加密消息给 Bob
|
|
1505
|
+
encrypted = alice_crypto.box_encrypt("Secret message", bob.get_address())
|
|
1506
|
+
|
|
1507
|
+
# Bob 解密消息
|
|
1508
|
+
decrypted = bob_crypto.box_decrypt(encrypted, alice.get_address())
|
|
1509
|
+
print(decrypted) # "Secret message"
|
|
1510
|
+
```
|
|
1511
|
+
|
|
1512
|
+
---
|
|
1513
|
+
|
|
1514
|
+
## 版本兼容性
|
|
1515
|
+
|
|
1516
|
+
| SDK 版本 | 节点版本 | 编译器版本 |
|
|
1517
|
+
|----------|----------|------------|
|
|
1518
|
+
| 当前 | >=5.0.0, <=8.0.0 | >=4.1.0, <9.0.0 |
|
|
1519
|
+
|
|
1520
|
+
---
|
|
1521
|
+
|
|
1522
|
+
## License
|
|
1523
|
+
|
|
1524
|
+
MIT License
|
|
1525
|
+
|
|
1526
|
+
|