From 50ac2803da37e4027fb044a3ce2ae26ccb75283a Mon Sep 17 00:00:00 2001 From: Gabriel Koerich Date: Thu, 28 Apr 2022 15:50:36 -0300 Subject: [PATCH 1/2] Add token account methods to SplTokenProgram --- src/Programs/SplTokenProgram.php | 63 +++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src/Programs/SplTokenProgram.php b/src/Programs/SplTokenProgram.php index e4adf30..a0aefe1 100644 --- a/src/Programs/SplTokenProgram.php +++ b/src/Programs/SplTokenProgram.php @@ -3,13 +3,29 @@ namespace Tighten\SolanaPhpSdk\Programs; use Tighten\SolanaPhpSdk\Program; +use Tighten\SolanaPhpSdk\PublicKey; +use Tighten\SolanaPhpSdk\Util\AccountMeta; +use Tighten\SolanaPhpSdk\Programs\SystemProgram; +use Tighten\SolanaPhpSdk\TransactionInstruction; +use Tighten\SolanaPhpSdk\Exceptions\InputValidationException; class SplTokenProgram extends Program { public const SOLANA_TOKEN_PROGRAM_ID = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'; + public const SOLANA_ASSOCIATED_TOKEN_PROGRAM_ID = 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'; + + public static function programId(): PublicKey + { + return new PublicKey(self::SOLANA_TOKEN_PROGRAM_ID); + } + + public static function associatedProgramId(): PublicKey + { + return new PublicKey(self::SOLANA_ASSOCIATED_TOKEN_PROGRAM_ID); + } + /** - * @param string $pubKey * @return mixed */ public function getTokenAccountsByOwner(string $pubKey) @@ -24,4 +40,49 @@ public function getTokenAccountsByOwner(string $pubKey) ], ]); } + + public static function getAssociatedTokenAddress( + PublicKey $associatedProgramId, + PublicKey $programId, + PublicKey $mint, + PublicKey $owner, + bool $allowOwnerOffCurve = false + ): PublicKey { + if (! $allowOwnerOffCurve && ! PublicKey::isOnCurve($owner)) { + throw new InputValidationException("Owner cannot sign: {$owner->toBase58()}"); + } + + return PublicKey::findProgramAddress([ + $owner->toBuffer(), + $programId->toBuffer(), + $mint->toBuffer() + ], $associatedProgramId)[0]; + } + + public static function createAssociatedTokenAccountInstruction( + PublicKey $associatedProgramId, + PublicKey $programId, + PublicKey $mint, + PublicKey $associatedAccount, + PublicKey $owner, + PublicKey $payer, + ): TransactionInstruction { + $data = new Buffer(); + + $keys = [ + new AccountMeta($payer, true, true), + new AccountMeta($associatedAccount, false, true), + new AccountMeta($owner, false, false), + new AccountMeta($mint, false, false), + new AccountMeta(SystemProgram::programId(), false, false), + new AccountMeta($programId, false, false), + new AccountMeta(SysVar::rent(), false, false), + ]; + + return new TransactionInstruction( + $associatedProgramId, + $keys, + $data + ); + } } From 007e6eef8b2e50fbb6b363fa850eb58d7b0d515e Mon Sep 17 00:00:00 2001 From: Gabriel Koerich Date: Thu, 28 Apr 2022 15:51:21 -0300 Subject: [PATCH 2/2] Test program ids and token account --- tests/Unit/SplTokenProgramTest.php | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/Unit/SplTokenProgramTest.php diff --git a/tests/Unit/SplTokenProgramTest.php b/tests/Unit/SplTokenProgramTest.php new file mode 100644 index 0000000..c43032c --- /dev/null +++ b/tests/Unit/SplTokenProgramTest.php @@ -0,0 +1,38 @@ +assertEquals('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', SplTokenProgram::SOLANA_TOKEN_PROGRAM_ID); + $this->assertEquals('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', SplTokenProgram::programId()->toBase58()); + + $this->assertEquals('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', SplTokenProgram::SOLANA_ASSOCIATED_TOKEN_PROGRAM_ID); + $this->assertEquals('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', SplTokenProgram::associatedProgramId()->toBase58()); + } + + /** @test */ + public function it_getAssociatedTokenAddress() + { + $mint = new PublicKey('2hvKBnhXZVvZadKX5QKkiyU7pVXXe5ZNMZhAoeXJdHxj'); + $owner = new PublicKey('Gk9HLj4qg1nTu2s7cdpm6PPgosxqUjya1cbhif4Lo6qv'); + + $tokenAccount = SplTokenProgram::getAssociatedTokenAddress( + SplTokenProgram::associatedProgramId(), + SplTokenProgram::programId(), + $mint, + $owner, + true + ); + + $this->assertEquals('27f5ubUFNrfXBwgqrH1sKMPuQVmm99qUuZxuJNtd5As4', $tokenAccount->toBase58()); + } +}