Repository: solana-labs/solana-program-library
Pull request #7006 (2024-07-10 22:10:43)

token-2022: add token 2022 argument to token cli for easy use
Instead of copying the token program id of the token22 program one can now just write: 
```
create-token --token-program-2022
or
create-token -2
```


Woody4618: Im also not 100% sure if restrict_to_program_id should be true or false. My guess reading line 2215 command_accounts is that it should be true.  

Patch:
diff --git a/token/cli/README.md b/token/cli/README.md
index 1d706b560..3583effac 100644
--- a/token/cli/README.md
+++ b/token/cli/README.md
@@ -33,3 +33,10 @@ After that, you can run the tests as any other Rust project:
 ```sh
 cargo test
 ```
+
+To run it locally you can do it like this:
+
+```sh
+cargo build --manifest-path token/cli/Cargo.toml
+target/debug/spl-token <command>
+```
diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs
index acb2b62fc..f162ccc0d 100644
--- a/token/cli/src/clap_app.rs
+++ b/token/cli/src/clap_app.rs
@@ -591,6 +591,14 @@ pub fn app<'a, 'b>(
                 .possible_values(&["json", "json-compact"])
                 .help("Return information in specified output format"),
         )
+        .arg(
+            Arg::with_name("program_2022")
+                .long("program-2022")
+                .takes_value(false)
+                .global(true)
+                .conflicts_with("program_id")
+                .help("Use token extension program token 2022 with program id: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"),
+        )
         .arg(
             Arg::with_name("program_id")
                 .short("p")
@@ -599,6 +607,7 @@ pub fn app<'a, 'b>(
                 .takes_value(true)
                 .global(true)
                 .validator(is_valid_token_program_id)
+                .conflicts_with("program_2022")
                 .help("SPL Token program id"),
         )
         .arg(
diff --git a/token/cli/src/config.rs b/token/cli/src/config.rs
index 89137a51b..c1aa6c53c 100644
--- a/token/cli/src/config.rs
+++ b/token/cli/src/config.rs
@@ -260,28 +260,29 @@ impl<'a> Config<'a> {
         let dump_transaction_message = matches.is_present(DUMP_TRANSACTION_MESSAGE.name);
 
         let default_program_id = spl_token::id();
-        let (program_id, restrict_to_program_id) =
-            if let Some(program_id) = value_of(matches, "program_id") {
-                (program_id, true)
-            } else if !sign_only {
-                if let Some(address) = value_of(matches, "token")
-                    .or_else(|| value_of(matches, "account"))
-                    .or_else(|| value_of(matches, "address"))
-                {
-                    (
-                        rpc_client
-                            .get_account(&address)
-                            .await
-                            .map(|account| account.owner)
-                            .unwrap_or(default_program_id),
-                        false,
-                    )
-                } else {
-                    (default_program_id, false)
-                }
+        let (program_id, restrict_to_program_id) = if matches.is_present("program_2022") {
+            (spl_token_2022::id(), true)
+        } else if let Some(program_id) = value_of(matches, "program_id") {
+            (program_id, true)
+        } else if !sign_only {
+            if let Some(address) = value_of(matches, "token")
+                .or_else(|| value_of(matches, "account"))
+                .or_else(|| value_of(matches, "address"))
+            {
+                (
+                    rpc_client
+                        .get_account(&address)
+                        .await
+                        .map(|account| account.owner)
+                        .unwrap_or(default_program_id),
+                    false,
+                )
             } else {
                 (default_program_id, false)
-            };
+            }
+        } else {
+            (default_program_id, false)
+        };
 
         // need to specify a compute limit if compute price and blockhash are specified
         if matches.is_present(BLOCKHASH_ARG.name)


Test patch:
diff --git a/token/cli/tests/command.rs b/token/cli/tests/command.rs
index 705c37caf..2ebf12385 100644
--- a/token/cli/tests/command.rs
+++ b/token/cli/tests/command.rs
@@ -92,6 +92,7 @@ async fn main() {
     // maybe come up with a way to do this through a some macro tag on the function?
     let tests = vec![
         async_trial!(create_token_default, test_validator, payer),
+        async_trial!(create_token_2022, test_validator, payer),
         async_trial!(create_token_interest_bearing, test_validator, payer),
         async_trial!(set_interest_rate, test_validator, payer),
         async_trial!(supply, test_validator, payer),
@@ -496,6 +497,43 @@ async fn create_token_default(test_validator: &TestValidator, payer: &Keypair) {
     }
 }
 
+async fn create_token_2022(test_validator: &TestValidator, payer: &Keypair) {
+    let config = test_config_with_default_signer(test_validator, payer, &spl_token_2022::id());
+    let mut wallet_manager = None;
+    let mut bulk_signers: Vec<Arc<dyn Signer>> = Vec::new();
+    let mut multisigner_ids = Vec::new();
+
+    let args = &[
+        "spl-token",
+        CommandName::CreateToken.into(),
+        "--program-2022",
+    ];
+
+    let default_decimals = format!("{}", spl_token_2022::native_mint::DECIMALS);
+    let minimum_signers_help = minimum_signers_help_string();
+    let multisig_member_help = multisig_member_help_string();
+
+    let app_matches = app(
+        &default_decimals,
+        &minimum_signers_help,
+        &multisig_member_help,
+    )
+    .get_matches_from(args);
+
+    let config = Config::new_with_clients_and_ws_url(
+        &app_matches,
+        &mut wallet_manager,
+        &mut bulk_signers,
+        &mut multisigner_ids,
+        config.rpc_client.clone(),
+        config.program_client.clone(),
+        config.websocket_url.clone(),
+    )
+    .await;
+
+    assert_eq!(config.program_id, spl_token_2022::ID);
+}
+
 async fn create_token_interest_bearing(test_validator: &TestValidator, payer: &Keypair) {
     let config = test_config_with_default_signer(test_validator, payer, &spl_token_2022::id());
     let rate_bps: i16 = 100;