verze-app / solana-php-sdk

Simple PHP SDK for Solana JSON RPC endpoints
MIT License
88 stars 45 forks source link

Bug? ProgramAddress is wrong #12

Closed neverything closed 2 years ago

neverything commented 2 years ago

This morning I ran into an issue with PublicKey::findProgramAddress(). When I try to get the proper address for https://solscan.io/token/ApqMgGY9sbseui4QKoerDui61PbUADD1CfZZGWC6eWF5

In order to quickly fix it in my job, I did the following:

protected function maybeGetMetaData() : array
    {
        while ($this->currentNonce != 0) {
            $client = new SolanaRpcClient(SolanaRpcClient::MAINNET_ENDPOINT);
            $account = $client->call('getAccountInfo', [$this->programAddress, ["encoding" => "jsonParsed"]]);

            if (! $this->hasEncodedMetaData($account)) {
                $this->currentNonce--;
                $this->canGetProgramAddress();
                sleep(1);
                continue;
            }
            return $account;
        }
        return [];
    }

So basically as long as the getAccountInfo call returns an array that is missing the Borsh data $this->canGetProgramAddress is calling a custom version of findProgramAddress that accepts the nonce as a third parameter.

/**
     * @param  array  $seeds
     * @param  PublicKey  $programId
     * @param  int  $nonce
     * @return array 2 elements, [0] = PublicKey, [1] = integer
     * @throws BaseSolanaPhpSdkException
     */
    static function findProgramAddress(array $seeds, PublicKey $programId, int $nonce = 255): array
    {
        while ($nonce != 0) {
            try {
                $copyOfSeedsWithNonce = $seeds;
                array_push($copyOfSeedsWithNonce, [$nonce]);
                $address = PublicKey::createProgramAddress($copyOfSeedsWithNonce, $programId);
            } catch (\Exception $exception) {
                $nonce--;
                continue;
            }
            return [$address, $nonce];
        }

        throw new BaseSolanaPhpSdkException('Unable to find a viable program address nonce.');
    }

Not very elegant and I have to rate limit the calls to the enpoints 😅, but it does the trick for me.

exzachlyvv commented 2 years ago

What $seeds and $programId are you using?

neverything commented 2 years ago

Seeds were:

To reproduce:


    $METADATA_PUBKEY = new \Tighten\SolanaPhpSdk\PublicKey(Tighten\SolanaPhpSdk\Programs\MetaplexProgram::METAPLEX_PROGRAM_ID);

    $transaction = \Tighten\SolanaPhpSdk\PublicKey::findProgramAddress(
        [
            'metadata',
            $METADATA_PUBKEY,
            (new \Tighten\SolanaPhpSdk\PublicKey('ApqMgGY9sbseui4QKoerDui61PbUADD1CfZZGWC6eWF5')),
        ],
        $METADATA_PUBKEY,

    );
    dd($transaction[0]->toBase58());    
mattstauffer commented 2 years ago

@exzachlyvv D you need me to jump in here to try to be helpful? Even as ignorant as I am? 😆 or can you handle this some time?

neverything commented 2 years ago

No rush at all my workaround is working for now 😎.

Btw are you guys at Solana Breakpoint in Lisbon this week? Would love to say thanks for the work you have been putting into this.

exzachlyvv commented 2 years ago

Hey guys! I've gotten pulled away from Solana development for now so not sure I'll have too much time helping out with this project in the short term. Happy to step in if you get in a pinch 😄

I won't be at Solana Breakpoint 😢 but have fun 🕺

neverything commented 2 years ago

Hey @exzachlyvv ohh sad to hear and thanks for offering your help, I guess I'll need it eventually 😅. @mattstauffer should I try and prepare a seperate version for borsh-php based on the amazing work @exzachlyvv did so far? Still learning how to properly use it, but might have some time this weekend after breakpoint.

Btw. amazing event and good vibes only.

mattstauffer commented 2 years ago

@neverything Sorry I missed this question! I'd love that, if you're up for it!

danieljao commented 2 years ago

hi @neverything can i ask question? where did you add your workaround? can you please share, i believe i need your workaround too, i hope you can share

danieljao commented 2 years ago

hi @mattstauffer does the Metadata::fromBuffer return creator? im getting array but no value, is that correct? just confirming

neverything commented 2 years ago

@danieljao sorry just saw your question. The workaround is in my job class to get the NFT metadata.

danieljao commented 2 years ago

@danieljao sorry just saw your question. The workaround is in my job class to get the NFT metadata.

Hi @neverything just wondering if the Job class you have is in the repo? just wondering if i can check it out, thank you