Search code examples
multiversxerdpy

Erdpy: Token issuance transaction fails with code: internal_issue


I try to make an ESDT token issuance transaction using the following Python code

from erdpy.accounts import Account, Address
from erdpy.proxy import ElrondProxy
from erdpy.transactions import BunchOfTransactions
from erdpy.transactions import Transaction
from erdpy.wallet import signing


TOKEN_NAME = b"Cowdings"
TOKEN_SYMBOL = b"MOO"

DECIMALS = 18
SUPPLY = 1000 * 10**DECIMALS


def hex_string(s: str) -> str:
    assert type(s) == bytes, "Make sure everything is bytes data or utf-8 encoded"
    return hexlify(s).decode("ascii")


def hex_int(i: int) -> str:
    assert type(i) == int, "Make sure everything is bytes data or utf-8 encoded"
    return hex(i)[2:]


proxy = ElrondProxy("https://devnet-gateway.elrond.com")
sender = Account(pem_file="test-wallet.pem")
sender.sync_nonce(proxy)

tx = Transaction()
tx.nonce = sender.nonce
tx.value = str(0.05 * 10**18)  # 0.05 EGLD, as required for issuing a token according to the documentation
tx.sender = sender.address.bech32()
# System contract address to issue out the new token as per
# https://docs.elrond.com/developers/esdt-tokens/#issuance-of-fungible-esdt-tokens
tx.receiver = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"
tx.gasPrice = 1000000000
tx.gasLimit = 50000
tx.data = f"issue" \
          f"@{hex_string(TOKEN_NAME)}" \
          f"@{hex_string(TOKEN_SYMBOL)}" \
          f"@{hex_int(SUPPLY)}" \
          f"@{hex_int(DECIMALS)}" 

tx.chainID = "D"  # For devnet https://devnet-gateway.elrond.com/network/config
tx.version = 1

tx.signature = signing.sign_transaction(tx, sender)
tx.send(proxy)

It fails with

ProxyRequestError: Proxy request error for url [https://devnet-gateway.elrond.com/transaction/send]: 
{
    'data': None, 
    'error': 'transaction generation failed: invalid value', 
    'code': 'internal_issue'
}

Solution

  • You use str(0.05 * 10**18) to get the string for the value.

    However, this actually outputs the value in scientific notation, which isn't what the blockchain expects.

    >>> str(0.05 * 10**18)
    '5e+16'
    

    Converting it to int first will force the correct output, so you can use str(int(0.05 * 10**18)) instead :)

    The full code therefore should look like this:

    from erdpy.accounts import Account, Address
    from erdpy.proxy import ElrondProxy
    from erdpy.transactions import BunchOfTransactions
    from erdpy.transactions import Transaction
    from erdpy.wallet import signing
    
    
    TOKEN_NAME = b"Cowdings"
    TOKEN_SYMBOL = b"MOO"
    
    DECIMALS = 18
    SUPPLY = 1000 * 10**DECIMALS
    
    
    def hex_string(s: str) -> str:
        assert type(s) == bytes, "Make sure everything is bytes data or utf-8 encoded"
        return hexlify(s).decode("ascii")
    
    
    def hex_int(i: int) -> str:
        assert type(i) == int, "Make sure everything is bytes data or utf-8 encoded"
        return hex(i)[2:]
    
    
    proxy = ElrondProxy("https://devnet-gateway.elrond.com")
    sender = Account(pem_file="test-wallet.pem")
    sender.sync_nonce(proxy)
    
    tx = Transaction()
    tx.nonce = sender.nonce
    tx.value = str(int(0.05 * 10**18))  # 0.05 EGLD, as required for issuing a token according to the documentation
    tx.sender = sender.address.bech32()
    # System contract address to issue out the new token as per
    # https://docs.elrond.com/developers/esdt-tokens/#issuance-of-fungible-esdt-tokens
    tx.receiver = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"
    tx.gasPrice = 1000000000
    tx.gasLimit = 50000
    tx.data = f"issue" \
              f"@{hex_string(TOKEN_NAME)}" \
              f"@{hex_string(TOKEN_SYMBOL)}" \
              f"@{hex_int(SUPPLY)}" \
              f"@{hex_int(DECIMALS)}" 
    
    tx.chainID = "D"  # For devnet https://devnet-gateway.elrond.com/network/config
    tx.version = 1
    
    #New version for generating a signature:
    tx.signature = sender.sign_transaction(tx)
    
    #Old version which is now obsolete:
    #tx.signature = signing.sign_transaction(tx, sender)
    
    tx.send(proxy)