Python-Cardano / pycardano

A lightweight Cardano library in Python
https://pycardano.readthedocs.io
MIT License
215 stars 68 forks source link

Error when submit NFT minting tx #165

Closed reitcircles closed 1 year ago

reitcircles commented 1 year ago

Discussed in https://github.com/Python-Cardano/pycardano/discussions/164

Originally posted by **reitcircles** February 14, 2023 When submitting tx for the NFT minting of this example: https://github.com/Python-Cardano/pycardano/blob/main/examples/native_token.py `blockfrost.utils.ApiError: {'error': 'Bad Request', 'message': '"transaction read error RawCborDecodeError [DecoderErrorDeserialiseFailure \\"Byron Tx\\" (DeserialiseFailure 1 \\"Size mismatch when decoding TxAux.\\\\nExpected 2, but found 4.\\"),DecoderErrorDeserialiseFailure \\"Shelley Tx\\" (DeserialiseFailure 1 \\"Size mismatch when decoding \\\\nRecord RecD.\\\\nExpected 4, but found 3.\\"),DecoderErrorDeserialiseFailure \\"Shelley Tx\\" (DeserialiseFailure 1 \\"Size mismatch when decoding \\\\nRecord RecD.\\\\nExpected 4, but found 3.\\"),DecoderErrorDeserialiseFailure \\"Shelley Tx\\" (DeserialiseFailure 1 \\"Size mismatch when decoding \\\\nRecord RecD.\\\\nExpected 4, but found 3.\\"),DecoderErrorDeserialiseFailure \\"Shelley Tx\\" (DeserialiseFailure 43 \\"expected string\\"),DecoderErrorDeserialiseFailure \\"Shelley Tx\\" (DeserialiseFailure 43 \\"expected string\\")]"', 'status_code': 400}` Does anyone have a clue how to solve this ?
nielstron commented 1 year ago

This looks a lot like the issue discussed here and actually an issue of cardano-submit-api and not pycardano https://github.com/ImperatorLang/eopsin/discussions/46

reitcircles commented 1 year ago

This looks a lot like the issue discussed here and actually an issue of cardano-submit-api and not pycardano ImperatorLang/eopsin#46

No.We are not using cardano-submit-api directly. We are submitting via the blockfrost frost interface.

nielstron commented 1 year ago

Please read the attached discussion. Blockfrost is internally using the cardano-submit-api

reitcircles commented 1 year ago

This looks a lot like the issue discussed here and actually an issue of cardano-submit-api and not pycardano ImperatorLang/eopsin#46

Can I submit this somehow to the local cardano node running on my server ? Say using cardano-cli ? In other words can i use the cbor generated and use cardano-cli ? Are the format compatible ...any clue ? Because frankly neither can i change submit api and nor blockfrost. We need to find a solution rather than putting the blame on others ...

And i am taking here an example (that should work), as it is in this repository examples. Right ?

cffls commented 1 year ago

Hi @reitcircles , could you confirm you are using exactly the same script? I just reran the script and it succeeded. Here is the test account, and you can see it just minted two NFTs.

reitcircles commented 1 year ago

Hi @reitcircles , could you confirm you are using exactly the same script? I just reran the script and it succeeded. Here is the test account, and you can see it just minted two NFTs.

Got it. Why it coming out as an error while it should not. I have a perfect working example that mints using cardano-cli. here is the problem.

min_val = min_lovelace(
    chain_context, output=TransactionOutput(clientAddress, Value(0, my_nft))
)                                                                                                                                                                                        
builder.add_output(TransactionOutput(clientAddress, Value(min_val, my_nft)))

It is messing up the output transaction. It should send it only to the clientAddress the NFT and rest of the change to the payment address and look what it does. It tries to send NFT to both ...!!

CLIENT_ADDRESS: 'addr_test1qrfn62h0jtn4848jukgu6uzutulpay5vhcdhwnm4ldr8qadsqj43gyduezd0crpju8l9ps4fuu94z0rp86t00c4m3nzs9jjpk5' 

 'outputs': [
      {
        'address': 'addr_test1qrfn62h0jtn4848jukgu6uzutulpay5vhcdhwnm4ldr8qadsqj43gyduezd0crpju8l9ps4fuu94z0rp86t00c4m3nzs9jjpk5',
        'amount': {
          'coin': 1426610,
          'multi_asset': {ScriptHash(hex='4f56826db927636a5f92ca3bc08c36f7d83ba8f86e5a84deb1fc75bf'): {AssetName(b'MY_NFT_1'): 1, AssetName(b'MY_NFT_2'): 1}},
        },
        'datum': None,
        'datum_hash': None,
        'post_alonzo': False,
        'script': None,
      },
      {
        'address': addr_test1qzylgj0pzzm722x3vkp6nde7h5cuzt2m4g9c69n5dj0w5rqd74hhzeetur4qr9v9e2mce0uxlzqelhuy9dq2027dh78sgh34ld,
        'amount': {
          'coin': 2169654380,
          'multi_asset': {ScriptHash(hex='a0d0840931231723edc4bf384aecc786467d924693daac22c553fdf1'): {AssetName(b'MY_NFT_1'): 1, AssetName(b'MY_NFT_2'): 1}},
        },
        'datum': None,
        'datum_hash': None,
        'post_alonzo': False,
        'script': None,
      },
    ],

I am trying to send the NFT to a different address than the payment address. A perfectly valid address. And then it comes up with the above error. No clue why.

cffls commented 1 year ago

See these two lines are slightly different?

        'address': 'addr_test1qrfn62h0jtn4848jukgu6uzutulpay5vhcdhwnm4ldr8qadsqj43gyduezd0crpju8l9ps4fuu94z0rp86t00c4m3nzs9jjpk5',

        'address': addr_test1qzylgj0pzzm722x3vkp6nde7h5cuzt2m4g9c69n5dj0w5rqd74hhzeetur4qr9v9e2mce0uxlzqelhuy9dq2027dh78sgh34ld,

In the first line, the address is a string (wrong), while in the second, the address is an Address object (correct). I think the problem could be fixed by doing this:

clientAddr = Address.from_primitive(clientAddress)

min_val = min_lovelace(
    chain_context, output=TransactionOutput(clientAddr, Value(0, my_nft))
)                                                                                                                                                                                        
builder.add_output(TransactionOutput(clientAddr, Value(min_val, my_nft)))

This is probably one of the most common mistake when using pycardano. I will add a check in the serialization of TransactionOutput to make sure a string is not passed in by mistake.

reitcircles commented 1 year ago
clientAddr = Address.from_primitive(clientAddress)

thanks ... i was just looking into this already ...let me try. &&& Solved ...

nielstron commented 1 year ago

tagging @while0x1 who had a similar issue

cffls commented 1 year ago

Auto correction is added in this commit: https://github.com/Python-Cardano/pycardano/commit/4bf6a626f6f6093ae368b5bd980b1271d9cae4e4.

while0x1 commented 1 year ago

This looks a lot like the issue discussed here and actually an issue of cardano-submit-api and not pycardano ImperatorLang/eopsin#46

Can I submit this somehow to the local cardano node running on my server ? Say using cardano-cli ? In other words can i use the cbor generated and use cardano-cli ? Are the format compatible ...any clue ? Because frankly neither can i change submit api and nor blockfrost. We need to find a solution rather than putting the blame on others ...

And i am taking here an example (that should work), as it is in this repository examples. Right ?

I discovered you can take CBOR generated from a cardano-cli build command and then just pass it to a CIP30 wallet for signing after a couple of transformations through pycardano:

Procedure:

take cbor from cardano cli remove first byte and last 2 bytes create a transaction body with the parsed CBOR

restored_tx_body = TransactionBody.from_cbor(<remove first byte and last 2 bytes>)
#import into py cardano transaction and set empty witness
tx = Transaction(restored_tx_body, TransactionWitnessSet())
tx.to_cbor()
#take cbor from to_cbor and sign with CIP30 wallet
#get signed cbor witness hex output from the signTx() call and set witness in pycardano
witness = TransactionWitnessSet.from_cbor()
#import witness into transaction
tx.transaction_witness_set = witness
#export cbor for tx submission
tx.to_cbor
#submitTx() in your cip30 Wallet