@@ -21,20 +21,19 @@ The Token Program's source is available on
2121
2222## Interface
2323
24- The on-chain Token Program is written in Rust and available on crates.io as
25- [ spl-token] ( https://docs.rs/spl-token ) . The program's [ instruction interface
26- documentation] ( https://docs.rs/spl-token/2.0.4/spl_token/instruction/enum.TokenInstruction.html )
27- can also be found there.
24+ The Token Program is written in Rust and available on [ crates.io] ( https://crates.io/crates/spl-token ) and [ docs.rs] ( https://docs.rs/spl-token ) .
2825
29- Auto-generated C bindings are also available for the on-chain Token Program and
30- available
26+ Auto-generated C bindings are also available
3127[ here] ( https://github.com/solana-labs/solana-program-library/blob/master/token/program/inc/token.h )
3228
3329[ JavaScript
3430bindings] ( https://github.com/solana-labs/solana-program-library/blob/master/token/js/client/token.js )
3531are available that support loading the Token Program on to a chain and issue
3632instructions.
3733
34+ See the [ SPL Associated Token Account] ( associated-token-account.md ) program for
35+ convention around wallet address to token account mapping and funding.
36+
3837## Command-line Utility
3938
4039The ` spl-token ` command-line utility can be used to experiment with SPL
@@ -71,9 +70,8 @@ solana config set --url https://devnet.solana.com
7170
7271#### Default Keypair
7372
74- See [ Keypair conventions]
75- (https://docs.solana.com/cli/conventions#keypair-conventions ) for information on
76- how to setup a keypair if you don't already have one.
73+ See [ Keypair conventions] ( https://docs.solana.com/cli/conventions#keypair-conventions )
74+ for information on how to setup a keypair if you don't already have one.
7775
7876Keypair File
7977```
@@ -161,7 +159,7 @@ Unwrapping GJTxcnA5Sydy8YRhqvHxbQ5QNsPyRKvzguodQEaShJje
161159Signature: f7opZ86ZHKGvkJBQsJ8Pk81v8F3v1VUfyd4kFs4CABmfTnSZK5BffETznUU3tEWvzibgKJASCf7TUpDmwGi8Rmh
162160```
163161
164- ### Example: Transferring tokens to another user, with sender-funding
162+ ### Example: Transferring tokens to another user
165163First the receiver uses ` spl-token create-account ` to create their associated
166164token account for the Token type. Then the receiver obtains their wallet
167165address by running ` solana address ` and provides it to the sender.
@@ -228,9 +226,6 @@ Account Token
228226CqAxDdBRnawzx9q4PYM3wrybLHBhDZ4P6BTV13WsRJYJ AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 50
229227```
230228
231- ### Example: Transferring tokens with sender funding
232- If the recipient a
233-
234229### Example: Create a non-fungible token
235230
236231Create the token type,
@@ -526,115 +521,70 @@ Although all SPL Token accounts do have their own address on-chain, there's no
526521need to surface these additional addresses to the user.
527522
528523There are two programs that are used by the wallet:
529- * SPL Token program - generic program that is used by all SPL Tokens
530- * SPL Associated Token Account program - this program defines the convention and the
531- provides the mechanism for mapping the user's wallet address to the associated
532- token accounts they hold.
533-
534- ### Associated Token Account
535- The associated token account convention allows all tokens to have the same
536- destination address, allowing the user share their main wallet address to
537- receive any SPL token.
538-
539- The following Rust function can be used to derive the address of a user's
540- associated token account for a given SPL Token mint:
541- ``` rust
542- /// Finds the associated token address for a given wallet
543- /// address and SPL Token mint
544- pub fn get_associated_token_address (
545- wallet_address : & Pubkey ,
546- spl_token_mint_address : & Pubkey ,
547- ) -> Pubkey {
548- Pubkey :: find_program_address (
549- & [
550- & primary_account_address . to_bytes (),
551- & spl_token :: id (). to_bytes (),
552- & spl_token_mint_address . to_bytes (),
553- ],
554- & spl_associated_token_account :: id ()
555- ). 0
556- }
557- ```
558-
559-
560- Javascript equivalent:
561- ```
562- import {PublicKey, PublicKeyNonce} from '@solana/web3.js';
563-
564- async function findAssociatedTokenAddress(
565- walletAddress: Pubkey,
566- tokenMintAddress: Pubkey
567- ): Promise<PublicKey> {
568- return PublicKey.findProgramAddress(
569- [
570- walletAddress.toBuffer(),
571- TOKEN_PROGRAM_ID.toBuffer(),
572- tokenMintAddress.toBuffer(),
573- ],
574- SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID
575- )[0];
576- }
577- ```
524+ * SPL Token program: generic program that is used by all SPL Tokens
525+ * [ SPL Associated Token Account] ( associated-token-account.md ) program: defines
526+ the convention and provides the mechanism for mapping the user's wallet
527+ address to the associated token accounts they hold.
578528
579529### How to fetch and display token holdings
580530The [ getTokenAccountsByOwner] ( https://docs.solana.com/apps/jsonrpc-api#gettokenaccountsbyowner )
581531JSON RPC method can be used to fetch all token accounts for a wallet address.
582532
583- For each token mint, the wallet could have be multiple token accounts: the
533+ For each token mint, the wallet could have multiple token accounts: the
584534associated token account and/or other ancillary token accounts
585535
586536By convention it is suggested that wallets roll up the balances from all token
587537accounts of the same token mint into a single balance for the user to shield the
588- user from this complexity. See the
589- [ Garbage Collecting Ancillary Token Accounts] ( #garbage-collecting-ancillary-token-accounts )
590- section for suggestions on how the wallet should clean up ancillary token accounts on the user's
538+ user from this complexity.
539+
540+ See the [ Garbage Collecting Ancillary Token Accounts] ( #garbage-collecting-ancillary-token-accounts )
541+ section for suggestions on how the wallet should clean up ancillary token accounts on the user's behalf.
591542
592543### Associated Token Account
593- Before the user can receive tokens their associated token account must be created
544+ Before the user can receive tokens, their associated token account must be created
594545on-chain, requiring a small amount of SOL to mark the account as rent-exempt.
595546
596547There's no restriction on who can create a user's associated token account. It
597548could either be created by the wallet on behalf of the user or funded by a 3rd
598549party through an airdrop campaign.
599550
600- Ultimately the
601- ` spl_associated_token_account::create_associated_token_account() ` instruction
602- just needs to be executed by some party.
551+ The creation process is described [ here] ( associated-token-account.md#creating-an-associated-token-account ) .
603552
604553#### Sample "Add Token" workflow
605- When the user wants to receive tokens, they should fund their associated token
606- account.
554+ The user should first fund their associated token when they want to receive tokens of a certain type.
607555
608- To do so, the wallet should provide a UI that allow the users to "add a token".
556+ The wallet should provide a UI that allow the users to "add a token".
609557The user selects the kind of token, and is presented with information about how
610- much SOL it will cost to add the token. Upon confirmation, the wallet sends a
611- transaction with the
612- ` spl_associated_token_account::create_associated_token_account() ` instruction.
558+ much SOL it will cost to add the token.
559+
560+ Upon confirmation, the wallet creates the associated token type as the described
561+ [ here] ( associated-token-account.md#creating-an-associated-token-account ) .
613562
614563#### Sample "Airdrop campaign" workflow
615564For each recipient wallet addresses, send a transaction containing:
616- 1 . ` spl_associated_token_account::create_associated_token_account() ` to create
617- the recipient's associated token account if necessary
618- 2 . ` TokenInstruction::Transfer ` to complete the airdrop
565+ 1 . Create the associated token account on the recipient's behalf.
566+ 2 . Use ` TokenInstruction::Transfer ` to complete the transfer
619567
620568#### Associated Token Account Ownership
621- The wallet should never use ` TokenInstruction::SetAuthority ` to set the
569+ ⚠️ The wallet should never use ` TokenInstruction::SetAuthority ` to set the
622570` AccountOwner ` authority of the associated token account to another address.
623571
624572### Ancillary Token Accounts
625573At any time ownership of an existing SPL Token account may be assigned to the
626574user. One way to accomplish this is with the
627- ` spl-token authorize <TOKEN_ADDRESS> owner <USER_ADDRESS> ` command.
575+ ` spl-token authorize <TOKEN_ADDRESS> owner <USER_ADDRESS> ` command. Wallets
576+ should be prepared to gracefully manage token accounts that they themselves did
577+ not create for the user.
628578
629579### Transferring Tokens Between Wallets
630580The preferred method of transferring tokens between wallets is to transfer into
631581associated token account of the recipient.
632582
633583The recipient must provide their main wallet address to the sender. The sender
634584then:
635- 1 . Derives the associated token account for the recipient using ` spl_associated_token_account::get_associated_token_address `
585+ 1 . Derives the associated token account for the recipient
6365861 . Fetches the recipient's associated token account over RPC and checks that it exists.
637- 1 . If the recipient's associated token accountdoes not exist, the sender wallet may choose to first fund the recipient's wallet at their expense
587+ 1 . If the recipient's associated token account does not exist, the sender wallet may choose to first fund the recipient's wallet at their expense
6385881 . Use ` TokenInstruction::Transfer ` to complete the transfer.
639589
640590### Registry for token details
@@ -663,3 +613,5 @@ Cleanup Pseudo Steps:
663613If adding one or more of clean up instructions cause the transaction to exceed
664614the maximum allowed transaction size, remove those extra clean up instructions.
665615They can be cleaned up during the next send operation.
616+
617+ The ` spl-token gc ` command provides an example implementation of this cleanup process.
0 commit comments