Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

None type error when trying to api.mint #8

Open
fourleafcoder opened this issue Sep 7, 2021 · 39 comments
Open

None type error when trying to api.mint #8

fourleafcoder opened this issue Sep 7, 2021 · 39 comments

Comments

@fourleafcoder
Copy link

fourleafcoder commented Sep 7, 2021

Traceback (most recent call last):
File "/Users/xxx/PycharmProjects/Solana/test/test_api.py", line 95, in
test()
File "/Users/xxx/PycharmProjects/Solana/test/test_api.py", line 68, in test
mint_to_response = api.mint(api_endpoint, "xxx", "xxx", "https://testing.com")
File "/Users/xxx/PycharmProjects/Solana/api/metaplex_api.py", line 77, in mint
tx, signers = mint(api_endpoint, self.account, contract_key, dest_key, link, supply=supply)
File "/Users/xxx/PycharmProjects/Solana/metaplex/transactions.py", line 164, in mint
metadata = get_metadata(client, mint_account)
File "/Users/xxx/PycharmProjects/Solana/metaplex/metadata.py", line 180, in get_metadata
data = base64.b64decode(client.get_account_info(metadata_account)['result']['value']['data'][0])
TypeError: 'NoneType' object is not subscriptable

When I did some digging infact its true based on the value is none your looking for in the line - what are you looking for here? The JSON is providing a null field.

print(client.get_account_info("D3EjGmwj33jVS5ZqYPr4njJMVBGR682rwYCTRAKswD1p"))
{'jsonrpc': '2.0', 'result': {'context': {'slot': 93025204}, 'value': {'data': ['', 'base64'], 'executable': False, 'lamports': 1000000000, 'owner': '11111111111111111111111111111111', 'rentEpoch': 227}}, 'id': 1}

print(client.get_account_info("

")['result']['value']['data'][0])
''

@crypt0miester
Copy link
Contributor

is that address the mint account public key? in other words the program ID?
then you will have data

the data is in this case is metadata of the NFT (the metaplex metadata json schema)

@fourleafcoder
Copy link
Author

No it is blank if you look at ['result']['value']['data'][0] in the structure its null:

'result': {'context': {'slot': 93025204}, 'value': {'data': ['', 'base64']

@jarry-xiao
Copy link
Contributor

Looks like this account has yet to be initialized/populated with data

@fourleafcoder
Copy link
Author

fourleafcoder commented Sep 8, 2021

Where does that get done I dont see that in any of the documentation? I've also queried Dagen Apes on Mainnet - the Update Authority account and its the same blank?

print(client.get_account_info("DC2mkgwhy56w3viNtHDjJQmc7SGu2QX785bS4aexojwX"))
{'jsonrpc': '2.0', 'result': {'context': {'slot': 95601447}, 'value': {'data': ['', 'base64'], 'executable': False, 'lamports': 102810501050, 'owner': '11111111111111111111111111111111', 'rentEpoch': 221}}, 'id': 1}

@jarry-xiao
Copy link
Contributor

I think the update authority is supposed to be empty. Check the protocol source code. What exactly are you trying to do?

@fourleafcoder
Copy link
Author

fourleafcoder commented Sep 9, 2021 via email

@jarry-xiao
Copy link
Contributor

jarry-xiao commented Sep 9, 2021

You are more than welcome to make a PR with the update_metadata fix. I did push some changes a few days ago. Is your branch up to date?

@fourleafcoder
Copy link
Author

Not sure I've got the skills yet. Yeah its the latest pull I've got.

@fourleafcoder
Copy link
Author

Can give it a go.. its just the transmission onto the Solana network I need help with.

@saurcodes
Copy link

Did you find any resolution, I am getting same issue

{'jsonrpc': '2.0', 'result': {'context': {'slot': 82578549}, 'value': {'data': ['', 'base64'], 'executable': False, 'lamports': 20000000000, 'owner': '11111111111111111111111111111111', 'rentEpoch': 191}}, 'id': 3}

@alikopasa
Copy link

+1
I'm getting same error too. btw sometimes it is working properly.

data = base64.b64decode(client.get_account_info(metadata_account)['result']['value']['data'][0]) TypeError: 'NoneType' object is not subscriptable

@rhamnett
Copy link

Something is wrong on testnet and devnet, things are working fine on mainnet-beta. This looks to be aproblem at the solana API end where it's not returning the metadata

@mgheghe
Copy link

mgheghe commented Oct 7, 2021

Same error on devnet, is there anyone who made it work on mainnet?

@CyberAthlet
Copy link

Faced the same problem today. is this issue because of devnet have some troubles these days?

@crypt0miester
Copy link
Contributor

run the test_api.py, if it works then your code is missing something.

@batprem
Copy link

batprem commented Oct 31, 2021

I found the same issue and fixed it by editing metadata.py.

In the function get_metadata, I added

client_metadata_account = dict(client.get_account_info(metadata_account))

before base64 decoding then it worked (but I don't know why).

The new function will look like:

def get_metadata(client, mint_key):
    metadata_account = get_metadata_account(mint_key)
    print("Test")
    client_metadata_account = dict(client.get_account_info(metadata_account))
    data = base64.b64decode(client_metadata_account['result']['value']['data'][0])
    metadata = unpack_metadata_account(data)
    return metadata

@rhamnett
Copy link

@batprem In my experience it was the raw metadata being returned from the API which was sometimes empty, therefore I think you may have just got lucky when you retried. Just a thought.

@batprem
Copy link

batprem commented Nov 1, 2021

@rhamnett It's hards to say but I tried uploading with my modified function and original function by more than 10 times for each. The modified one significantly made all successful attempts whereas the original one made all fail.

In my guess, it would be about asyncio issue. When API function is first called then the result hold the None value and wait for a replacement. Then, dict parsing forces the variable to await the result and replace None.

@batprem batprem mentioned this issue Nov 1, 2021
@ifczt
Copy link

ifczt commented Dec 4, 2021

@rhamnett It's hards to say but I tried uploading with my modified function and original function by more than 10 times for each. The modified one significantly made all successful attempts whereas the original one made all fail.

In my guess, it would be about asyncio issue. When API function is first called then the result hold the None value and wait for a replacement. Then, dict parsing forces the variable to await the result and replace None.

Hello, can you solve this problem? I tried your method and will get some improvement, but sometimes I still make the mistake of agreeing.

@Aystub
Copy link

Aystub commented Dec 15, 2021

I think it might be a timing issue with the deployment of the Program not propagating everywhere by the time the mint is called (on devnet anyway). So for example doing like:

result = api.deploy(api_endpoint, name, symbol, fees)
contract_key = json.loads(result).get('contract')
time.sleep(30)
api.mint(api_endpoint, contract_key, public_key, link_to_json_file)

seems to work 100% of the time for me. Without that sleep, it's super inconsistent (tests included). Also, the 30 seconds there might be overkill I just picked a huge number for testing the theory.

@jarry-xiao
Copy link
Contributor

I think a generally good idea for this API is to change the default confirmation status to Confirmed. When I initially built out this API I wasn't aware of that feature. I think it will make using this a lot more seamless. I currently don't have the cycles to implement this, but I think it would be great if a community member would build out this small change.

@phoebexiong
Copy link

Traceback (most recent call last): File "/Users/xxx/PycharmProjects/Solana/test/test_api.py", line 95, in test() File "/Users/xxx/PycharmProjects/Solana/test/test_api.py", line 68, in test mint_to_response = api.mint(api_endpoint, "xxx", "xxx", "https://testing.com") File "/Users/xxx/PycharmProjects/Solana/api/metaplex_api.py", line 77, in mint tx, signers = mint(api_endpoint, self.account, contract_key, dest_key, link, supply=supply) File "/Users/xxx/PycharmProjects/Solana/metaplex/transactions.py", line 164, in mint metadata = get_metadata(client, mint_account) File "/Users/xxx/PycharmProjects/Solana/metaplex/metadata.py", line 180, in get_metadata data = base64.b64decode(client.get_account_info(metadata_account)['result']['value']['data'][0]) TypeError: 'NoneType' object is not subscriptable

When I did some digging infact its true based on the value is none your looking for in the line - what are you looking for here? The JSON is providing a null field.

print(client.get_account_info("D3EjGmwj33jVS5ZqYPr4njJMVBGR682rwYCTRAKswD1p")) {'jsonrpc': '2.0', 'result': {'context': {'slot': 93025204}, 'value': {'data': ['', 'base64'], 'executable': False, 'lamports': 1000000000, 'owner': '11111111111111111111111111111111', 'rentEpoch': 227}}, 'id': 1}

print(client.get_account_info("

")['result']['value']['data'][0])
''

make sure that when you deploy it (before even calling the mint), the contract name and contract symbol fields match the name and symbol fields in your metadata json. as soon as I changed this, the mint worked.

@nurav97
Copy link

nurav97 commented Dec 28, 2021

@jarry-xiao is their any solution for this issue I am facing the same since many days and cannot find the solution .

@crypt0miester
Copy link
Contributor

@jarry-xiao is their any solution for this issue I am facing the same since many days and cannot find the solution .

see if sleeping for 30 seconds after you deploy then mint would work. this just makes sure that the data has been propagated into the blockchain.

the cleaner way is to "await" for 31 confirmations for the deploy transaction.

@nurav97
Copy link

nurav97 commented Dec 28, 2021

@crypt0miester sleeping works sometimes but not all the time we need to be sure that its robust and works .

I also have another question say I want to create say 10 NFT with different metadata do I have to call deploy and mint 10 times or only call deploy 1 and mint 10 times

is this correct

@crypt0miester
Copy link
Contributor

@crypt0miester sleeping works sometimes but not all the time we need to be sure that its robust and works .

I also have another question say I want to create say 10 NFT with different metadata do I have to call deploy and mint 10 times or only call deploy 1 and mint 10 times

example

**for i in range(10):**
    # alter the json file
    todayDateString = todays_date.strftime("%m/%d/%Y")
    _alterJson(todayDateString)

    # # read the json file and upload to arweave
    with open('Metadata/metadata.json', 'r') as notjson:
        Json_data = notjson.read()
        transaction = Transaction(wallet, data=Json_data)
        transaction.add_tag('Content-Type', 'application/json')
        transaction.sign()
        # Get the trnsaction id for arweave
        trx_id = transaction.id
        transaction.send()

    # create the account
    **result = json.loads(api.deploy(test_api_endpoint, TOKEN_NAME, TOKEN_SYMBOL, 0))**
    # check the result status or fail
    assert result['status'] == 200, "Sorry the account deploy failed"
    contract_key = result.get('contract')
    DEPLOYED.append(contract_key)
    print("current account ",contract_key)

    # Create actual token
    **minted = json.loads(api.mint(test_api_endpoint, contract_key, TEST_PUBLIC_KEY, "https://arweave.net/" + trx_id))**
    MINTED.append(minted)
    assert minted['status'] == 200, "Sorry the token mint failed"

    todays_date += timedelta(days=1)

print("Finished minting")
print("All Accounts : ", DEPLOYED)
print("All Minted   : ", MINTED)

is this correct

are you on devnet or main?

always be ready for deployment failure. solana might be lagging and transactions might fail.

but each nft has its own contract I believe. so 10 deployments and 10 mints. that's why there is a supply in deploy function.

@nurav97
Copy link

nurav97 commented Dec 28, 2021

@crypt0miester thanks i am working on devnet

do you know what @jarry-xiao is talking about to set default status to confirmed for deploy i dont understand how to implement it

@crypt0miester
Copy link
Contributor

@crypt0miester thanks i am working on devnet

do you know what @jarry-xiao is talking about to set default status to confirmed for deploy i dont understand how to implement it

yes.

here is a hint https://github.com/metaplex-foundation/python-api/blob/main/utils/execution_engine.py

I'm on vacation. cant help you more.

@rgarade
Copy link

rgarade commented Dec 30, 2021

@crypt0miester can you tell me {'code': -32002, 'message': 'Transaction simulation failed: Attempt to debit an account but found no record of a prior credit.', 'data': {'accounts': None, 'err': 'AccountNotFound', 'logs': []}} why this error occurred .
I have just added the transaction options parameters in send_transaction function like that,
result=client.send_transaction(tx,*signers,opts=TxOpts(skip_confirmation=True,skip_preflight=False,preflight_commitment='confirmed')).

@crypt0miester
Copy link
Contributor

@crypt0miester can you tell me {'code': -32002, 'message': 'Transaction simulation failed: Attempt to debit an account but found no record of a prior credit.', 'data': {'accounts': None, 'err': 'AccountNotFound', 'logs': []}} why this error occurred .
I have just added the transaction options parameters in send_transaction function like that,
result=client.send_transaction(tx,*signers,opts=TxOpts(skip_confirmation=True,skip_preflight=False,preflight_commitment='confirmed')).

check if you have solanas in the wallet address.

secondly change skip_confirmation=False or it will not check if the txn is confirmed or not to begin with. True will just skip the checking.

and please open a new issue.

@FFEvan
Copy link

FFEvan commented Jan 3, 2022

I actually think this issues is fixed by preserving the order of signers, without skipping confirmation or preflight. I will submit PR with the update that has been consistently fixing the issue on my side.

@Aystub
Copy link

Aystub commented Jan 3, 2022

Expanding on @FFEvan's comment, it comes down to this line: https://github.com/metaplex-foundation/python-api/blob/main/utils/execution_engine.py#L8

Converting the list of signers into a Set removes duplicates but doesn't guarantee order preservation. In addition, we tracked down some issues in solana-py surrounding how they were initialzing their Keypair class. It was rather unoptimized, which was causing situations here in execution_engine.py where the Keypair was being used before it had finished computing its public_key property. This is what causes the AccountNotFound error, the Keypair doesn't have a public_key yet at the time it's used so of course the account cannot be found.

@FFEvan should have the PR up soon. These changes have completely resolved the issues for us. Hundreds of mints over the course of multiple days and multiple machines.

ulmentflam pushed a commit to ulmentflam/python-api that referenced this issue Jan 3, 2022
@nurav97
Copy link

nurav97 commented Jan 4, 2022

@FFEvan @Aystub thanks this has solved the none error .

is their a way to speedup the nft minting process as i want to mint 1k nfts which is currently taking lot of time

@mdergueche
Copy link

hi @DevVarunn reading Solana documentation, I think I know what is the issue with the code. steps are explained in this blog:
https://learn.figment.io/tutorials/sol-mint-token

the idea is that you need to Create an account to handle the tokens. by definition in the Solana documentation:

https://docs.solana.com/developing/programming-model/accounts
the accounts are used as folder to store data. It needs to collect rent in each Lamport. if there is not funds, then you loose the data. the issue I see in the code, we do not create token account (here I'm not talking about your own wallet).

At least this is the lead I have right now reading the code.

@mdergueche
Copy link

mdergueche commented Jan 20, 2022

thanks @DevVarunn I merged the fix from Evan which is in nuthsell:
updating to .2 solana library
updating metaplex_api.py
updating metada.py
and most importantly removing duplicates in execution engine.

but the code still throws the same error. are you sure you fix works?

@nurav97
Copy link

nurav97 commented Jan 21, 2022

@mdergueche yes this solved the issue for me have made 100s of deploy/mint after that didn't get the error again,

you can try to set the skipPreflight ,skipconfirmation flags to false the might help

also I want to find a way to calculate cost of minting i.e. transaction cost + account rent before mint if any one know ho to do that then please comment

@mdergueche
Copy link

mdergueche commented Jan 22, 2022

@nurav97 I'm trying all combination here. so I followed again the read me file and created this code, does this work for your end or am I doing something wrong:

import base58
import json
import os
import time
from api.metaplex_api import wallet, MetaplexAPI
from cryptography.fernet import Fernet
from solana.rpc.api import Client
from solana.keypair import Keypair

def test():
account = Keypair()
cfg = {"PRIVATE_KEY": base58.b58encode(account.seed).decode("ascii"), "PUBLIC_KEY": str(account.public_key), "DECRYPTION_KEY": Fernet.generate_key().decode("ascii")}
api_endpoint = "https://api.devnet.solana.com/"
Client(api_endpoint).request_airdrop(account.public_key, int(1e10))
metaplex = MetaplexAPI(cfg)
seller_basis_fees = 0 # value in 10000
Deploy_det = metaplex.deploy(api_endpoint, "A"*32, "A"*10, seller_basis_fees)
Details = wallet()
print('Details :',json.loads(Details).get('address'))
print('Wallet :',Details)
print('Deploy :',Deploy_det)
print('Contract :', json.loads(Deploy_det).get('contract'))
metaplex.topup(api_endpoint, Details[0])
divinity_json_file = 'https://arweave.net/1eH7bZS-6HZH4YOc8T_tGp2Rq25dlhclXJkoa6U55mM/'
mint_res = metaplex.mint(api_endpoint, json.loads(Deploy_det).get('contract'), json.loads(Details).get('address'), divinity_json_file)

@sarangjain40
Copy link

Is the solved? I am still getting the error. I have made the changes in metplex/metadata.py -

def get_metadata(client, mint_key):
metadata_account = get_metadata_account(mint_key)
client_metadata_account = dict(client.get_account_info(metadata_account))
data = base64.b64decode(client_metadata_account['result']['value']['data'][0])
#data = base64.b64decode(client.get_account_info(metadata_account)['result']['value']['data'][0])
metadata = unpack_metadata_account(data)
return metadata

But I am still getting the TypeError: 'NoneType' object is not subscriptable

Thanks In Advance for any help or suggestion

@crypt0miester
Copy link
Contributor

crypt0miester commented Feb 26, 2022

hi, sorry I've been on vacation.

try this dirty workaround. (use at own risk)


def get_metadata(client, mint_key):
    metadata_account = get_metadata_account(mint_key)
    print(client.get_account_info(metadata_account))
    try: 
        data = base64.b64decode(client.get_account_info(metadata_account)['result']['value']['data'][0])
        metadata = unpack_metadata_account(data)
    except:
        print("data is still none, sleeping for 10 secs")
        time.sleep(10)
    finally:
        data = base64.b64decode(client.get_account_info(metadata_account)['result']['value']['data'][0])
        metadata = unpack_metadata_account(data)

    return metadata

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests