From 78e274164a94cd4995c1507b40dc765f5068dcfc Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 29 Nov 2024 14:34:55 -0500 Subject: [PATCH] icepick sol create-token-account --- Cargo.lock | 472 ++++++++++++++++++++++ crates/by-chain/icepick-solana/Cargo.toml | 2 + crates/by-chain/icepick-solana/src/lib.rs | 67 +++ 3 files changed, 541 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 37e3776..05ba2b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,42 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "polyval", + "subtle", + "zeroize", +] + [[package]] name = "ahash" version = "0.8.11" @@ -555,6 +591,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "4.5.21" @@ -720,6 +766,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] @@ -733,6 +780,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -759,6 +815,7 @@ dependencies = [ "fiat-crypto", "rand_core 0.6.4", "rustc_version", + "serde", "subtle", "zeroize", ] @@ -1425,6 +1482,8 @@ dependencies = [ "serde_json", "solana-rpc-client", "solana-sdk", + "spl-associated-token-account", + "spl-token", "thiserror 2.0.3", ] @@ -1583,6 +1642,15 @@ dependencies = [ "hashbrown 0.15.1", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "ipnet" version = "2.10.1" @@ -1851,6 +1919,18 @@ dependencies = [ "autocfg", ] +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + [[package]] name = "mime" version = "0.3.17" @@ -2156,6 +2236,18 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -2770,6 +2862,19 @@ dependencies = [ "solana-stable-layout", ] +[[package]] +name = "solana-curve25519" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e5ba4b41a9dbe44ced90ef703670e01db50c9f8f71b632740b58285b2ed4ac" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "solana-program", + "thiserror 1.0.69", +] + [[package]] name = "solana-decode-error" version = "2.1.1" @@ -3323,6 +3428,12 @@ dependencies = [ "solana-pubkey", ] +[[package]] +name = "solana-security-txt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183" + [[package]] name = "solana-serde-varint" version = "2.1.1" @@ -3520,6 +3631,38 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "solana-zk-sdk" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13efd21dfbfd0e54125a6ed29bcc4b79b84b33eeb0a331580a3927e0cee96c0" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "itertools 0.12.1", + "js-sys", + "lazy_static", + "merlin", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "serde_json", + "sha3", + "solana-derivation-path", + "solana-program", + "solana-sdk", + "subtle", + "thiserror 1.0.69", + "wasm-bindgen", + "zeroize", +] + [[package]] name = "solana_rbpf" version = "0.8.5" @@ -3554,6 +3697,325 @@ dependencies = [ "der", ] +[[package]] +name = "spl-associated-token-account" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76fee7d65013667032d499adc3c895e286197a35a0d3a4643c80e7fd3e9969e3" +dependencies = [ + "borsh 1.5.3", + "num-derive", + "num-traits", + "solana-program", + "spl-associated-token-account-client", + "spl-token", + "spl-token-2022", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-associated-token-account-client" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f8349dbcbe575f354f9a533a21f272f3eb3808a49e2fdc1c34393b88ba76cb" +dependencies = [ + "solana-instruction", + "solana-pubkey", +] + +[[package]] +name = "spl-discriminator" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a20542d4c8264856d205c0090512f374dbf7b3124479a3d93ab6184ae3631aa" +dependencies = [ + "bytemuck", + "solana-program-error", + "solana-sha256-hasher", + "spl-discriminator-derive", +] + +[[package]] +name = "spl-discriminator-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" +dependencies = [ + "quote", + "spl-discriminator-syn", + "syn 2.0.87", +] + +[[package]] +name = "spl-discriminator-syn" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f05593b7ca9eac7caca309720f2eafb96355e037e6d373b909a80fe7b69b9" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.87", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-elgamal-registry" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a157622a63a4d12fbd8b347fd75ee442cb913137fa98647824c992fb049a15b" +dependencies = [ + "bytemuck", + "solana-program", + "solana-zk-sdk", + "spl-pod", + "spl-token-confidential-transfer-proof-extraction", +] + +[[package]] +name = "spl-memo" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f09647c0974e33366efeb83b8e2daebb329f0420149e74d3a4bd2c08cf9f7cb" +dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", +] + +[[package]] +name = "spl-pod" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a7d5950993e1ff2680bd989df298eeb169367fb2f9deeef1f132de6e4e8016" +dependencies = [ + "borsh 1.5.3", + "bytemuck", + "bytemuck_derive", + "num-derive", + "num-traits", + "solana-decode-error", + "solana-msg", + "solana-program-error", + "solana-program-option", + "solana-pubkey", + "solana-zk-sdk", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-program-error" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d39b5186f42b2b50168029d81e58e800b690877ef0b30580d107659250da1d1" +dependencies = [ + "num-derive", + "num-traits", + "solana-program", + "spl-program-error-derive", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-program-error-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d375dd76c517836353e093c2dbb490938ff72821ab568b545fd30ab3256b3e" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.87", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd99ff1e9ed2ab86e3fd582850d47a739fec1be9f4661cba1782d3a0f26805f3" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed320a6c934128d4f7e54fe00e16b8aeaecf215799d060ae14f93378da6dc834" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-2022" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b27f7405010ef816587c944536b0eafbcc35206ab6ba0f2ca79f1d28e488f4f" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program", + "solana-security-txt", + "solana-zk-sdk", + "spl-elgamal-registry", + "spl-memo", + "spl-pod", + "spl-token", + "spl-token-confidential-transfer-ciphertext-arithmetic", + "spl-token-confidential-transfer-proof-extraction", + "spl-token-confidential-transfer-proof-generation", + "spl-token-group-interface", + "spl-token-metadata-interface", + "spl-transfer-hook-interface", + "spl-type-length-value", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-confidential-transfer-ciphertext-arithmetic" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1f1bf731fc65546330a7929a9735679add70f828dd076a4e69b59d3afb5423c" +dependencies = [ + "base64 0.22.1", + "bytemuck", + "solana-curve25519", + "solana-zk-sdk", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-extraction" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "383937e637ccbe546f736d5115344351ebd4d2a076907582335261da58236816" +dependencies = [ + "bytemuck", + "solana-curve25519", + "solana-program", + "solana-zk-sdk", + "spl-pod", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-generation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8627184782eec1894de8ea26129c61303f1f0adeed65c20e0b10bc584f09356d" +dependencies = [ + "curve25519-dalek 4.1.3", + "solana-zk-sdk", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d595667ed72dbfed8c251708f406d7c2814a3fa6879893b323d56a10bedfc799" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", + "spl-discriminator", + "spl-pod", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb9c89dbc877abd735f05547dcf9e6e12c00c11d6d74d8817506cab4c99fdbb" +dependencies = [ + "borsh 1.5.3", + "num-derive", + "num-traits", + "solana-borsh", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", + "spl-discriminator", + "spl-pod", + "spl-type-length-value", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa7503d52107c33c88e845e1351565050362c2314036ddf19a36cd25137c043" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info", + "solana-cpi", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-tlv-account-resolution", + "spl-type-length-value", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-type-length-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba70ef09b13af616a4c987797870122863cba03acc4284f226a4473b043923f9" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info", + "solana-decode-error", + "solana-msg", + "solana-program-error", + "spl-discriminator", + "spl-pod", + "thiserror 1.0.69", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -3850,6 +4312,16 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "unreachable" version = "1.0.0" diff --git a/crates/by-chain/icepick-solana/Cargo.toml b/crates/by-chain/icepick-solana/Cargo.toml index f4b5834..514e1e0 100644 --- a/crates/by-chain/icepick-solana/Cargo.toml +++ b/crates/by-chain/icepick-solana/Cargo.toml @@ -10,4 +10,6 @@ serde = { workspace = true, features = ["derive"] } serde_json.workspace = true solana-rpc-client = { version = "2.1.1", default-features = false } solana-sdk = { version = "2.1.1" } +spl-associated-token-account = "6.0.0" +spl-token = "7.0.0" thiserror = "2.0.3" diff --git a/crates/by-chain/icepick-solana/src/lib.rs b/crates/by-chain/icepick-solana/src/lib.rs index 71ae395..9f5a3a7 100644 --- a/crates/by-chain/icepick-solana/src/lib.rs +++ b/crates/by-chain/icepick-solana/src/lib.rs @@ -101,6 +101,15 @@ pub struct Transfer { fee_payer_address: Option, } +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub struct CreateTokenAccount { + funder_address: Option, + wallet_address: String, + token_address: String, + blockhash: String, +} + #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "kebab-case")] pub struct Sign {} @@ -132,6 +141,7 @@ pub enum Operation { GenerateWallet(GenerateWallet), GetWalletAddress(GetWalletAddress), Transfer(Transfer), + CreateTokenAccount(CreateTokenAccount), Sign(Sign), Broadcast(Broadcast), } @@ -256,6 +266,29 @@ impl Module for Solana { fee_payer_address.clone(), ], }, + // kinda BS that you have to make an account for a token, but ok. + icepick_module::help::Operation { + name: "create-token-account".to_string(), + description: "Create an account for a given token".to_string(), + arguments: vec![ + Argument { + name: "wallet-address".to_string(), + description: "The address of the token.".to_string(), + r#type: ArgumentType::Required, + }, + Argument { + name: "token-address".to_string(), + description: "The address of the token.".to_string(), + r#type: ArgumentType::Required, + }, + blockhash.clone(), + Argument { + name: "funder-address".to_string(), + description: "The address of the funder (signer).".to_string(), + r#type: ArgumentType::Optional, + }, + ], + }, icepick_module::help::Operation { name: "sign".to_string(), description: "Sign a previously-generated transaction.".to_string(), @@ -356,6 +389,40 @@ impl Module for Solana { "derivation-accounts": requested_accounts, })) } + Operation::CreateTokenAccount(CreateTokenAccount { + funder_address, + wallet_address, + token_address, + blockhash, + }) => { + // TODO: allow changing derivation account of funder_address + use sata::instruction::create_associated_token_account; + use solana_sdk::pubkey::Pubkey; + use spl_associated_token_account as sata; + use spl_token::ID as TOKEN_ID; + let funder_address = funder_address.unwrap_or_else(|| wallet_address.clone()); + let funder_pubkey = Pubkey::from_str(&funder_address).unwrap(); + let wallet_pubkey = Pubkey::from_str(&wallet_address).unwrap(); + let token_pubkey = Pubkey::from_str(&token_address).unwrap(); + let instruction = create_associated_token_account( + &funder_pubkey, + &wallet_pubkey, + &token_pubkey, + &TOKEN_ID, + ); + let hash = solana_sdk::hash::Hash::from_str(&blockhash).unwrap(); + let message = solana_sdk::message::Message::new_with_blockhash( + &[instruction], + Some(&funder_pubkey), + &hash, + ); + let transaction = solana_sdk::transaction::Transaction::new_unsigned(message); + #[allow(clippy::identity_op)] + Ok(serde_json::json!({ + "blob": transaction, + "derivation-accounts": [0u32 | 1 << 31], + })) + } Operation::Sign(_) => { let blob = request.blob.expect("passed in instruction blob"); let mut transaction: solana_sdk::transaction::Transaction =