WrongKeyLengthError: key length must be 58

Hi

I’m trying to create an asset and then send it to other addresses (all on the testnet). I can successfully create assets, signing with my account but when I try to send them, I get a wrongkeylength error despite using the same private key. I just can’t figure out what the issue is.

Has anyone of you encountered a similar error and knows how to solve it?

Thanks a lot in advance!!

Here the code:
for lockers in directory_lockers:
asset_id = directory_lockers[lockers][‘asset_id’]
receiving_address = directory_lockers[lockers][‘receiving_address’]
locker_object = directory_lockers[lockers][‘object’]
print(getattr(locker_object,“Master_Account”))
locker_object.distribute(asset_id,receiving_address)

The error I get is the following:

WrongKeyLengthError Traceback (most recent call last)
in
6 locker_object = directory_lockers[lockers][‘object’]
7 print(getattr(locker_object,“Master_Account”))
----> 8 locker_object.distribute(asset_id,receiving_address)
9

~\JLPY\lockertoken.py in distribute(self, asset_id, receiving_address)
120 }
121 txn = transaction.AssetTransferTxn(**data)
→ 122 stxn = txn.sign(self.Master_Account[‘sk’])
123 txid = algod_client.send_transaction(stxn)
124 gf.wait_for_confirmation

C:\Anaconda\lib\site-packages\algosdk\transaction.py in sign(self, private_key)
61 SignedTransaction: signed transaction with the signature
62 “”"
—> 63 sig = self.raw_sign(private_key)
64 sig = base64.b64encode(sig).decode()
65 authorizing_address = None

C:\Anaconda\lib\site-packages\algosdk\transaction.py in raw_sign(self, private_key)
80 “”"
81 private_key = base64.b64decode(private_key)
—> 82 txn = encoding.msgpack_encode(self)
83 to_sign = constants.txid_prefix + base64.b64decode(txn)
84 signing_key = SigningKey(private_key[:constants.key_len_bytes])

C:\Anaconda\lib\site-packages\algosdk\encoding.py in msgpack_encode(obj)
29 d = obj
30 if not isinstance(obj, dict):
—> 31 d = obj.dictify()
32 od = _sort_dict(d)
33 return base64.b64encode(msgpack.packb(od, use_bin_type=True)).decode()

C:\Anaconda\lib\site-packages\algosdk\transaction.py in dictify(self)
750 d[“aclose”] = encoding.decode_address(self.close_assets_to)
751 if self.receiver:
→ 752 d[“arcv”] = encoding.decode_address(self.receiver)
753 if self.revocation_target:
754 d[“asnd”] = encoding.decode_address(self.revocation_target)

C:\Anaconda\lib\site-packages\algosdk\encoding.py in decode_address(addr)
165 return addr
166 if not len(addr) == constants.address_len:
→ 167 raise error.WrongKeyLengthError
168 decoded = base64.b32decode(_correct_padding(addr))
169 addr = decoded[:-constants.check_sum_len_bytes]

WrongKeyLengthError: key length must be 58

Can you post the sdk code that actually creates the transactions?

Hi Jason

Of course and thanks already for looking at this thread. I am falling into despair…

The code uses the distribute function which is part of the LokerToken-class:

import json
from algosdk import account, algod, mnemonic, transaction, kmd

import generalfunctions as gf
import generalconstants as gc

class LockerToken:

algod_client = algod.AlgodClient(gc.algod_token, gc.algod_address, gc.headers)

def __init__(self, Master_Account, Locker_ID):
    self.Master_Account = Master_Account
    self.Locker_ID = Locker_ID


def wait_for_tx_confirmation(self,txid):
    algod_client = algod.AlgodClient(gc.algod_token, gc.algod_address, gc.headers)   
    last_round = algod_client.status().get('lastRound')
    while True:
        txinfo = algod_client.pending_transaction_info(txid)
        if txinfo.get('round') and txinfo.get('round') > 0:
            print("Transaction {} confirmed in round {}.".format(
               txid, txinfo.get('round')))
            break
        else:
            print("Waiting for confirmation...")
            last_round += 1
            algod_client.status_after_block(last_round)


def create(self):
    # Get network params for transactions.   
    algod_client = algod.AlgodClient(gc.algod_token, gc.algod_address, gc.headers)
    params = algod_client.suggested_params()
    first = params.get("lastRound")
    last = first + 1000
    gen = params.get("genesisID")
    gh = params.get("genesishashb64")
    min_fee = params.get("minFee")

    # Define parameters of new BCGLT
    data = {
        "sender": self.Master_Account['pk'],
        "fee": min_fee,
        "first": first,
        "last": last,
        "gh": gh,
        "total": 1,
        "default_frozen": False,
        "unit_name": "BCGLT",
        "asset_name": "BCG Locker Token " + self.Locker_ID,
        "manager": self.Master_Account['pk'],
        "reserve": self.Master_Account['pk'],
        "freeze": self.Master_Account['pk'],
        "clawback": self.Master_Account['pk'],
        "url": "https://path/to/my/asset/details",
        #url should point towards manual
        "flat_fee": True,
        "decimals": 0
    }

    # Construct Asset Creation transaction
    txn = transaction.AssetConfigTxn(**data)
    # Sign with secret key of creator
    stxn = txn.sign(self.Master_Account['sk'])

    # Send the transaction to the network and retrieve the txid.
    txid = algod_client.send_transaction(stxn)
    print("Transaction ID = ", txid)

    # Retrieve the asset ID of the newly created asset by first
    # ensuring that the creation transaction was confirmed,
    # then pulling account info of the creator and grabbing the
    # asset with the max asset ID.

    # Wait for the transaction to be confirmed
    self.wait_for_tx_confirmation(txid)
    return txid


def info(self):
    algod_client = algod.AlgodClient(gc.algod_token, gc.algod_address, gc.headers)
    try:
        # Pull account info for the creator
        account_info = algod_client.account_info(self.Master_Account['pk'])
        # Get max asset ID
        asset_id = max(
            map(lambda x: int(x), account_info.get('thisassettotal').keys()))
        print("Asset ID: {}".format(asset_id), json.dumps(account_info['thisassettotal'][str(asset_id)], indent=4))
        return asset_id
    except Exception as e:
        print(e)
        


def distribute(self, asset_id, receiving_address):
    algod_client = algod.AlgodClient(gc.algod_token, gc.algod_address, gc.headers)
    params = algod_client.suggested_params()   
    data = {
            "sender": self.Master_Account['pk'],
            "fee": params.get("minFee"),
            "first": params.get("lastRound"),
            "last": params.get("lastRound") + 1000,
            "gh": params.get("genesishashb64"),
            "receiver": receiving_address,
            "amt": 1,
            "index": asset_id,
            "flat_fee": True
            }
    txn = transaction.AssetTransferTxn(**data)
    stxn = txn.sign(self.Master_Account['sk'])
    txid = algod_client.send_transaction(stxn)
    gf.wait_for_confirmation
    account_info = algod_client.account_info(receiving_address)
    print(json.dumps(account_info['assets'][str(asset_id)], indent=4))

kind regards,
Max

Hey @maxpower glad you are here building assets. I believe your receiving_address is the issue, not the Master_Account. I see in the distribute method you pass in the receiving_address but I did not find where that was generated. Please ensure that the value being passed is a valid address, as it seems the length is not proper.

In addition, for an account to receive an asset, it must first opt into the asset by sending an opt in transaction to themselves.

Hey @maxpower did you get you asset transfer transaction sorted? We are here to help you succeed.

1 Like

Hey Ryan and Jason

Thanks so much for your answers (and sorry for my late reply)! I was really desperate cause I did not understand the error and couldn’t proceed. It was indeed the missing opt-in for some of the accounts that I tried to send assets to.

This community is so cool. Always so helpful :slight_smile:
Have a great day!

Glad you got it to work!

1 Like