微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 Python AlgoSDK 恢复 Algorand 钱包?

如何解决如何使用 Python AlgoSDK 恢复 Algorand 钱包?

尽管官方 algosdk(algorand 的 Python SDK)文档表明只需调用以下函数 (link) 即可恢复钱包:

create_wallet(name,pswd,driver_name='sqlite',master_deriv_key=None)

第四个参数:

master_deriv_key (str,optional) – if recovering a wallet,include

钱包恢复在我的代码中不起作用,也会导致出现异常。此外,algorand 官方文档还展示了如何使用上述功能恢复钱包 (link):

# recover the wallet by passing mdk when creating a wallet
new_wallet = kcl.create_wallet("MyTestWallet2","testpassword",master_deriv_key=mdk)

在下面,您可以观看我的代码,这是我编写的一个非常简单的代码段,用于使用 algorand SDK 进行一些测试:

from algosdk import kmd
from algosdk import mnemonic

kmd_clt = kmd.KMDClient('855d39510cce40caf11de4c941b37632d1529ec970156214528a33a0ae8473b4','http://127.0.0.1:6969')
if kmd_clt:
    kmd_wlt_mdk = None
    kmd_wlt_list = kmd_clt.list_wallets()
    for kmd_wlt in kmd_wlt_list:
        kmd_name = kmd_wlt['name']
        kmd_id = kmd_wlt['id']
        if kmd_name == 'wallet_name':
            kmd_wlt_hdl = kmd_clt.init_wallet_handle(kmd_id,'wallet_password')
            if kmd_wlt_hdl:
                kmd_wlt_mdk = kmd_clt.export_master_derivation_key(kmd_wlt_hdl,'wallet_password')
            break
    if kmd_wlt_mdk:
        kmd_wlt = kmd_clt.create_wallet('wallet_name','wallet_password',master_deriv_key=kmd_wlt_mdk)
        kmd_wlt_hdl = kmd_clt.init_wallet_handle(kmd_wlt['id'],'wallet_password')
        acc_addr_list = kmd_clt.list_keys(kmd_wlt_hdl)
        for acc_addr in acc_addr_list:
            account_address = acc_addr
            print(account_address)
            account_key = kmd_clt.export_key(kmd_wlt_hdl,account_address)
            print(account_key)
            account_mnemonic = mnemonic.from_private_key(account_key)
            print(account_mnemonic)

下面,您可以查看 Traceback 和运行时返回的错误消息:

Traceback (most recent call last):
  File "/home/emiliano/anaconda3/lib/python3.7/site-packages/algosdk/kmd.py",line 63,in kmd_request
    resp = urlopen(req)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py",line 222,in urlopen
    return opener.open(url,data,timeout)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py",line 531,in open
    response = meth(req,response)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py",line 641,in http_response
    'http',request,response,code,msg,hdrs)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py",line 569,in error
    return self._call_chain(*args)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py",line 503,in _call_chain
    result = func(*args)
  File "/home/emiliano/anaconda3/lib/python3.7/urllib/request.py",line 649,in http_error_default
    raise HTTPError(req.full_url,hdrs,fp)
urllib.error.HTTPError: HTTP Error 400: Bad Request

During handling of the above exception,another exception occurred:

Traceback (most recent call last):
  File "/home/emiliano/anaconda3/lib/python3.7/site-packages/algosdk/kmd.py",line 67,in kmd_request
    raise error.KMDHTTPError(json.loads(e)["message"])
algosdk.error.KMDHTTPError: wallet with same name already exists

During handling of the above exception,another exception occurred:

Traceback (most recent call last):
  File "algorand_test.py",line 49,in <module>
    kmd_wlt = kmd_clt.create_wallet('emiliano','emiliano',master_deriv_key=kmd_wlt_mdk)
  File "/home/emiliano/anaconda3/lib/python3.7/site-packages/algosdk/kmd.py",line 118,in create_wallet
    return self.kmd_request("POST",req,data=query)["wallet"]
  File "/home/emiliano/anaconda3/lib/python3.7/site-packages/algosdk/kmd.py",line 69,in kmd_request
    raise error.KMDHTTPError(e)
algosdk.error.KMDHTTPError: {
  "error": true,"message": "wallet with same name already exists"
}

似乎很清楚 create_wallet 函数是如何导致这种行为的罪魁祸首,导致返回错误“同名钱包已经存在”。 algorand SDK 的内部结构非常简单,API 是 REST 方法的包装器。函数 create_wallet 只是 (link):

def create_wallet(self,name,driver_name="sqlite",master_deriv_key=None):
    """
    Create a new wallet.
    Args:
        name (str): wallet name
        pswd (str): wallet password
        driver_name (str,optional): name of the driver
        master_deriv_key (str,optional): if recovering a wallet,include
    Returns:
        dict: dictionary containing wallet information
    """
    req = "/wallet"
    query = {
        "wallet_driver_name": driver_name,"wallet_name": name,"wallet_password": pswd
    }
    if master_deriv_key:
        query["master_derivation_key"] = master_deriv_key
    return self.kmd_request("POST",data=query)["wallet"]

我确定输入中传递的主派生密钥是正确的,因为我已经使用控制台中的 goal 命令对其进行了检查。

有没有其他人遇到过这种类型的问题?

解决方法

总而言之,Algorand 的 REST API 文档并未明确建议在制作 POST /v1/wallet (link) 时使用主派生密钥来检索钱包。相反,Python SDK 的 Algorand 文档建议可以将 Master-Derivation-Key 传递给 create_wallet 函数,然后该函数执行之前所述的 HTTP POST,以恢复现有的钱包 (link)。

正如我在上面的问题中所解释的,create_wallet 无法恢复电子钱包,因为基础 POST /v1/wallet 失败。在@Arty 的建议下,这已被证明如下:

curl -X POST -H "X-KMD-API-Token: <kmd-token>" -H "Content-Type: application/json" -d '{"wallet_driver_name": "sqlite","wallet_name": <wallet-name>,"wallet_password": <wallet-password>,"master_derivation_key": <master-derivation-key>}' <kmd-address-and-port>/v1/wallet

返回的

{ "error": true,"message": "wallet with same name already exists" }

我将此问题通知了 Algorand 支持,我目前正在等待回复。无论如何,为了让问题的标题有意义,我想分享另一种可能的解决方案,通过依赖 Python SDK 来恢复钱包:

from algosdk import kmd
from algosdk import wallet
from algosdk import mnemonic

kmd_clt = kmd.KMDClient(<kmd-token>,<kmd-address-and-port>)
if kmd_clt:
    kmd_wlt_mdk = None
    kmd_wlt_list = kmd_clt.list_wallets()
    for kmd_wlt in kmd_wlt_list:
        kmd_name = kmd_wlt['name']
        kmd_id = kmd_wlt['id']
        if kmd_name == <wallet-name>:
            kmd_wlt_hdl = kmd_clt.init_wallet_handle(kmd_id,<wallet-password>)
            if kmd_wlt_hdl:
                kmd_wlt_mdk = kmd_clt.export_master_derivation_key(kmd_wlt_hdl,<wallet-password>)
            break
    if kmd_wlt_mdk:
        wlt = wallet.Wallet(<wallet-name>,<wallet-password>,kmd_clt,mdk=kmd_wlt_mdk)
        if wlt:
            acc_addr_list = wlt.list_keys()
            for acc_addr in acc_addr_list:
                account_address = acc_addr
                print(account_address)
                account_key = wlt.export_key(acc_addr)
                print(account_key)
                account_mnemonic = mnemonic.from_private_key(account_key)
                print(account_mnemonic)

我希望它在未来对其他人有用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?