Closed neverything closed 2 years ago
Hey @neverything
Here is a working example of PublicKey::findProgramAddress():
$programId = new PublicKey('BPFLoader1111111111111111111111111111111111');
list($programAddress, $nonce) = PublicKey::findProgramAddress(
[Ed25519Keypair::bin2array('')],
$programId
);
Parameter 1 needs to be an array of int arrays (array<array<int>>
)
In the future, we can improve the DX so that you don't need to be concerned with binary information, but we are not there yet (thank you for being an early adopter! :D).
Now applying this to the code you are trying to replicate:
let [pda, bump] = await PublicKey.findProgramAddress([
Buffer.from("metadata"),
METADATA_PUBKEY.toBuffer(),
new PublicKey(address).toBuffer(),
], METADATA_PUBKEY)
In PHP should roughly look like:
$METADATA_PUBKEY = new PublicKey(<Metaplex base58 ID... I think it is: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s">);
list($pda, $bump) = PublicKey::findProgramAddress([
Ed25519Keypair::bin2array('metadata'),
$METADATA_PUBKEY->toBytes(),
(new PublicKey(address))->toBytes(),
], $METADATA_PUBKEY);
I think this package could benefit from a Buffer
class that can easily convert anything into a binary array. I'll try and work on that soon.
Wow @exzachlyvv thank you so much, with your help I got it working and can now get the proper programAddress
. Please let me know if I can assist with testing or anything.
Ha yes a proper Buffer
class would help a lot.
The next problem is going to be finding out how to deserialze the borsh data containing the metadata when calling:
$client->call('getAccountInfo', ['DSQiKA3zxbvXwJMT8kjUCVPRn9WbEnps18BoQPyRhxQp', ["encoding" => "base64"]]);
Hey @neverything
The addition of the Buffer
class is complete and merged into my fork. There will be some breaking changes in there for you.
This should now work for you:
$METADATA_PUBKEY = new PublicKey(<Metaplex base58 ID... I think it is: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s">);
list($pda, $bump) = PublicKey::findProgramAddress([
'metadata',
$METADATA_PUBKEY,
(new PublicKey(address)),
], $METADATA_PUBKEY);
Wow that's amazing @exzachlyvv will test it tonight. Thank you 🙏
Works like a charm @exzachlyvv! Thank you so much
@neverything What's your progress looking like on deserializing the Borsh data? I tried a few tools that all failed and ended up just doing some nasty string manipulation on a base64 decode, if I remember correctly.
@exzachlyvv Fantastic work on this man!!
@mattstauffer doing the same 😅. Running base64 decode and using regex to get the url for the json file. So far works with arweave, staratlas, ipfs.
As long as there is no borsh implementation for php (lack of skills on my side to build one myself😅), I might end up using Symfony Process to run a node/python/go implementation to get the borsh result and turn it into a dto or something 🤷♀️.
For now I'm happy to get the url to the json file for the nft.
I can work on a PHP port of the borsh library next :D
@mattstauffer my very nasty string manipulation in case you were wondering 🤣
protected function hasMetaDataUrl(string $metaDataRaw)
{
$raw_url = iconv(mb_detect_encoding($metaDataRaw, mb_detect_order(), true), "UTF-8//IGNORE", $metaDataRaw);
$raw_url = preg_replace('/[[:cntrl:]]/', '', $raw_url);
$raw_url = preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $raw_url);
$reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
if (preg_match($reg_exUrl, $raw_url, $url)) {
$url = Str::of($url[0])->before('\0');
if (Str::contains($url, 'https://arweave.net/')) {
$path = Str::after($url, 'https://arweave.net/');
$path = Str::substr($path, 0, 43);
$url = 'https://arweave.net/' . $path;
}
$this->metaDataUrl = $url;
return true;
} else {
return false;
}
}
Hey @exzachlyvv and @mattstauffer thank you so much for putting in so much effort to make this available in PHP.
Using the @exzachlyvv fork created, I'm trying to rebuild something like this https://www.vicyyn.com/#/nft?DqGGFuiWRiJ6Mim1qafLWn6FZzBGGcSTyFFSJ8RpuqE8
The code used on the site above is: https://github.com/vicyyn/MetaplexMetadata-js
It somehow espaces me how to use the
PublicKey::findProgramAddress
compared to the one in the repo above. I can't seem to get the seed part working properly.Any hint would be greatly appreciated