使用Blockfrost API在Cardano保存元数据时遇RawCborDecodeError报错
问题分析与解决
核心问题
你收到400错误的原因是使用了错误的API端点并发送了无效的CBOR数据。/tx/submit 端点要求接收的是完整签名后的Cardano交易CBOR数据,而不是你当前构造的包含metadata的自定义payload。Blockfrost无法将你的payload解析为合法交易,因此抛出了RawCborDecodeError。
至于你在仪表盘中看到的交易,大概率不是这次请求产生的——可能是之前提交的合法交易,或者是仪表盘中的误显示。
正确的交易提交流程
要通过Blockfrost API提交带metadata的交易,需要遵循以下步骤:
- 构建未签名的交易(包含输入、输出、metadata等)
- 离线签名交易(使用你的私钥)
- 提交签名后的CBOR交易到
/tx/submit
修正后的代码示例
下面是符合Blockfrost API规范的代码流程:
import requests import cbor2 from config import config # 假设你的config模块正确导入 def build_and_submit_tx(data_id, data): receiving_address = "你的接收地址" sender_address = "你的发送地址" utxo_tx_hash = "你要使用的UTXO的交易哈希" utxo_index = 0 # UTXO在交易中的索引 lovelace_amount = 100000 # 要发送的ADA数量(以lovelace为单位) # 1. 构建未签名交易 build_url = "https://cardano-preprod.blockfrost.io/api/v0/tx/build" build_payload = { "inputs": [ { "address": sender_address, "tx_hash": utxo_tx_hash, "output_index": utxo_index } ], "outputs": [ { "address": receiving_address, "amount": [{"unit": "lovelace", "quantity": str(lovelace_amount)}] }, # 必须包含找零输出,否则会丢失剩余ADA { "address": sender_address, "amount": [{"unit": "lovelace", "quantity": "剩余的lovelace数量"}] } ], "metadata": { int(data_id): { # Cardano metadata的key必须是整数 "content": data # 自定义metadata内容,注意类型要符合Cardano规范 } } } build_headers = { "project_id": config('CARDANO_PROJECT_ID'), "Content-Type": "application/json" } build_response = requests.post(build_url, headers=build_headers, json=build_payload) if build_response.status_code != 200: print(f"构建未签名交易失败: {build_response.text}") return build_response unsigned_tx_cbor = build_response.content # 2. 离线签名交易(这里需要你自己实现签名逻辑,使用你的私钥) # 注意:永远不要在代码中硬编码私钥,更不要通过网络传输私钥 signed_tx_cbor = sign_transaction(unsigned_tx_cbor, "你的私钥") # 替换为实际的签名函数 # 3. 提交签名后的交易 submit_url = "https://cardano-preprod.blockfrost.io/api/v0/tx/submit" submit_headers = { "project_id": config('CARDANO_PROJECT_ID'), "Content-Type": "application/cbor" } submit_response = requests.post(submit_url, headers=submit_headers, data=signed_tx_cbor) if submit_response.status_code == 200: print(f"交易提交成功,交易哈希: {submit_response.text}") else: print(f"交易提交失败: {submit_response.text}") return submit_response # 示例签名函数(需要根据你使用的库实现,比如pycardano) def sign_transaction(unsigned_tx_cbor, private_key): # 使用pycardano或其他Cardano库完成签名 from pycardano import Transaction, PaymentSigningKey, PaymentVerificationKey sk = PaymentSigningKey.from_json(private_key) vk = PaymentVerificationKey.from_signing_key(sk) tx = Transaction.from_cbor(unsigned_tx_cbor) signed_tx = tx.sign([sk]) return signed_tx.to_cbor()
关键注意事项
- Metadata格式: Cardano的metadata要求顶级key必须是整数(0到2^64-1),值的类型需要符合Cardano的CBOR规范(字符串、数字、数组、对象等)。
- 找零输出: 交易必须包含找零输出,否则未使用的ADA会被当作手续费扣除。
- 签名安全: 签名操作必须离线完成,绝对不能将私钥暴露在网络或代码中。
- UTXO选择: 确保你使用的UTXO存在且有足够的余额支付交易金额和手续费。
内容的提问来源于stack exchange,提问作者mev
相关产品推荐
相关产品推荐

