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 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
+