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

how to transfer tokens using this SDK i.e. spl-token transfer? #21

Open
mkocurek opened this issue Jan 4, 2022 · 10 comments
Open

how to transfer tokens using this SDK i.e. spl-token transfer? #21

mkocurek opened this issue Jan 4, 2022 · 10 comments

Comments

@mkocurek
Copy link

mkocurek commented Jan 4, 2022

not an issue but a question or a feature request

is it possible to transfer tokens using this SDK like with the Solana CLI using a terminal?

Terminal Example:
$spl-token transfer --allow-unfunded-recipient --fund-recipient [token address] [amount of tokens] [recipients wallet]

@neverything
Copy link
Contributor

I believe it's not yet fully integrated, but haven't tested it https://github.com/tighten/solana-php-sdk#transactions

@ghost
Copy link

ghost commented Jan 21, 2022

Anymore info on this would be highly appreciated ❤️

@neverything
Copy link
Contributor

Seems like it's being worked on #28

@impozzible
Copy link

@suchpro Were you able to figure this out

@impozzible
Copy link

I can transfer tokens now, but the amount sent is not encoded properly I believe to the right decimal so it sends a wrong value

@ghost
Copy link

ghost commented May 22, 2022

@impozzible haven't tested it yet

@impozzible
Copy link

impozzible commented May 23, 2022

Figured it out, incase someone else runs into this issue

public function createTransferInstruction(
        PublicKey $source,
        PublicKey $destination,
        PublicKey $owner,
        int $amount
    ): TransactionInstruction {
        $data = [
            // uint32
            ...unpack("C*", pack("C", 3)),
            // int64
            ...unpack("C*", pack("P", $amount)),
        ];
        // dd($data);
        $keys =  [
            new AccountMeta($source, false, true),
            new AccountMeta($destination, false, true),
            new AccountMeta($owner,true,true),
        ];

        return new TransactionInstruction(
            new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
            $keys,
            $data
        );
    }```

@Igor360
Copy link

Igor360 commented Jun 20, 2022

'Transfer' instruction is deprecated for now and token developers recommend to use 'TransferChecked' instruction, sample code:

    public function createTransferCheckedInstruction(
        string $source,
        string $destination,
        string $owner,
        string $mint,
        int    $amount,
        int    $decimals
    ): TransactionInstruction
    {
        /**
         * TokenInstructions :
         *   Transfer = 3,
         *   TransferChecked = 12,
         */
        $data = [
            // u8
            ...unpack("C*", pack("C", 12)),  // token instruction index
            // u64
            ...unpack("C*", pack("P", $amount)), // amount without decimals
            // u8
            ...unpack("C*", pack("C", $decimals)),   // token decimals
        ];
        $keys = [
            new AccountMeta(new PublicKey($source), false, true), // source account address
            new AccountMeta(new PublicKey($mint), false, false), // mint token address
            new AccountMeta(new PublicKey($destination), false, true), // destination account address, if not exist need call
            new AccountMeta(new PublicKey($owner), true, true), // singer address, wallet who will be sing tx
        ];

        return new TransactionInstruction(
            new PublicKey(SplTokenProgram::SOLANA_TOKEN_PROGRAM_ID),
            $keys,
            $data
        );
    }

In case when you doesn't have token Account address you must to create it, for this action get associated token address with following function

  public static function getAssociatedTokenAccount(string $mint, string $publicKeyAddress): PublicKey
    {
        $publicKeyAccount = new PublicKey($publicKeyAddress);
        $publicKeyMint = new PublicKey($mint);
        $programId = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
        $seed = [
            $publicKeyAccount->toBuffer(),
            $programId->toBuffer(),
            $publicKeyMint->toBuffer()
        ];
        return \Arr::first(PublicKey::findProgramAddress($seed, new PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"))); // ATTENTION : It's function not working correctly in latest version of package, now latest is "^0.3.2", for solve it change package version to "dev-main
    }

Then add instruction for create token address into your transaction, but if account already created not add this instruction to transaction object

public static function createAssociatedTokenAccountInstruction(
        string $payer, // tx payer address. it address wallet whose using for sining transaction 
        string $associatedToken, // generated token address, for get call function "getAssociatedTokenAccount"
        string $owner, //  wallet address for which you want to create associated token wallet
        string $mint,   // Token mint address
        string $programId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
        string $associatedTokenProgramId = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
    ): TransactionInstruction
    {
        $data = [];
        $keys = [
            new AccountMeta(new PublicKey($payer), true, true),
            new AccountMeta(new PublicKey($associatedToken), false, true),
            new AccountMeta(new PublicKey($owner), false, false),
            new AccountMeta(new PublicKey($mint), false, false),
            new AccountMeta(new PublicKey("11111111111111111111111111111111"), false, false),
            new AccountMeta(new PublicKey($programId), false, false),
            new AccountMeta(new PublicKey("SysvarRent111111111111111111111111111111111"), false, false),
        ];

        return new TransactionInstruction(
            new PublicKey($associatedTokenProgramId),
            $keys,
            $data
        );
    }

@Scrivs
Copy link

Scrivs commented Jan 9, 2023

Does anyone have an example of full code on this working? I keep getting a

Transaction simulation failed: Error processing Instruction 0: invalid account data for instruction

error

@Scrivs
Copy link

Scrivs commented Jan 9, 2023

Figured it out, incase someone else runs into this issue

public function createTransferInstruction(
        PublicKey $source,
        PublicKey $destination,
        PublicKey $owner,
        int $amount
    ): TransactionInstruction {
        $data = [
            // uint32
            ...unpack("C*", pack("C", 3)),
            // int64
            ...unpack("C*", pack("P", $amount)),
        ];
        // dd($data);
        $keys =  [
            new AccountMeta($source, false, true),
            new AccountMeta($destination, false, true),
            new AccountMeta($owner,true,true),
        ];

        return new TransactionInstruction(
            new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
            $keys,
            $data
        );
    }```

Can you post your full code for sending a token please?

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

5 participants