@@ -21,20 +21,19 @@ The Token Program's source is available on
21
21
22
22
## Interface
23
23
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 ) .
28
25
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
31
27
[ here] ( https://github.com/solana-labs/solana-program-library/blob/master/token/program/inc/token.h )
32
28
33
29
[ JavaScript
34
30
bindings] ( https://github.com/solana-labs/solana-program-library/blob/master/token/js/client/token.js )
35
31
are available that support loading the Token Program on to a chain and issue
36
32
instructions.
37
33
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
+
38
37
## Command-line Utility
39
38
40
39
The ` spl-token ` command-line utility can be used to experiment with SPL
@@ -71,9 +70,8 @@ solana config set --url https://devnet.solana.com
71
70
72
71
#### Default Keypair
73
72
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.
77
75
78
76
Keypair File
79
77
```
@@ -161,7 +159,7 @@ Unwrapping GJTxcnA5Sydy8YRhqvHxbQ5QNsPyRKvzguodQEaShJje
161
159
Signature: f7opZ86ZHKGvkJBQsJ8Pk81v8F3v1VUfyd4kFs4CABmfTnSZK5BffETznUU3tEWvzibgKJASCf7TUpDmwGi8Rmh
162
160
```
163
161
164
- ### Example: Transferring tokens to another user, with sender-funding
162
+ ### Example: Transferring tokens to another user
165
163
First the receiver uses ` spl-token create-account ` to create their associated
166
164
token account for the Token type. Then the receiver obtains their wallet
167
165
address by running ` solana address ` and provides it to the sender.
@@ -228,9 +226,6 @@ Account Token
228
226
CqAxDdBRnawzx9q4PYM3wrybLHBhDZ4P6BTV13WsRJYJ AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 50
229
227
```
230
228
231
- ### Example: Transferring tokens with sender funding
232
- If the recipient a
233
-
234
229
### Example: Create a non-fungible token
235
230
236
231
Create the token type,
@@ -526,115 +521,70 @@ Although all SPL Token accounts do have their own address on-chain, there's no
526
521
need to surface these additional addresses to the user.
527
522
528
523
There 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.
578
528
579
529
### How to fetch and display token holdings
580
530
The [ getTokenAccountsByOwner] ( https://docs.solana.com/apps/jsonrpc-api#gettokenaccountsbyowner )
581
531
JSON RPC method can be used to fetch all token accounts for a wallet address.
582
532
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
584
534
associated token account and/or other ancillary token accounts
585
535
586
536
By convention it is suggested that wallets roll up the balances from all token
587
537
accounts 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.
591
542
592
543
### 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
594
545
on-chain, requiring a small amount of SOL to mark the account as rent-exempt.
595
546
596
547
There's no restriction on who can create a user's associated token account. It
597
548
could either be created by the wallet on behalf of the user or funded by a 3rd
598
549
party through an airdrop campaign.
599
550
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 ) .
603
552
604
553
#### 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.
607
555
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".
609
557
The 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 ) .
613
562
614
563
#### Sample "Airdrop campaign" workflow
615
564
For 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
619
567
620
568
#### 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
622
570
` AccountOwner ` authority of the associated token account to another address.
623
571
624
572
### Ancillary Token Accounts
625
573
At any time ownership of an existing SPL Token account may be assigned to the
626
574
user. 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.
628
578
629
579
### Transferring Tokens Between Wallets
630
580
The preferred method of transferring tokens between wallets is to transfer into
631
581
associated token account of the recipient.
632
582
633
583
The recipient must provide their main wallet address to the sender. The sender
634
584
then:
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
636
586
1 . 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
638
588
1 . Use ` TokenInstruction::Transfer ` to complete the transfer.
639
589
640
590
### Registry for token details
@@ -663,3 +613,5 @@ Cleanup Pseudo Steps:
663
613
If adding one or more of clean up instructions cause the transaction to exceed
664
614
the maximum allowed transaction size, remove those extra clean up instructions.
665
615
They 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