From 7ccd8e2435a29ee91bfecb90cb062b1541dac442 Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Thu, 4 Jun 2026 21:05:58 +0300 Subject: [PATCH] feat(wallet_ffi): program elfs and program deployment --- Cargo.lock | 1 + lez/wallet-ffi/Cargo.toml | 1 + lez/wallet-ffi/src/lib.rs | 1 + lez/wallet-ffi/src/program_deployment.rs | 230 +++++++++++++++++++++++ lez/wallet-ffi/wallet_ffi.h | 108 +++++++++++ 5 files changed, 341 insertions(+) create mode 100644 lez/wallet-ffi/src/program_deployment.rs diff --git a/Cargo.lock b/Cargo.lock index ca35ce96..1b956512 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10724,6 +10724,7 @@ name = "wallet-ffi" version = "0.1.0" dependencies = [ "cbindgen", + "common", "key_protocol", "lee", "lee_core", diff --git a/lez/wallet-ffi/Cargo.toml b/lez/wallet-ffi/Cargo.toml index 45e94ee6..1e8b6395 100644 --- a/lez/wallet-ffi/Cargo.toml +++ b/lez/wallet-ffi/Cargo.toml @@ -15,6 +15,7 @@ wallet.workspace = true lee.workspace = true lee_core.workspace = true sequencer_service_rpc = { workspace = true, features = ["client"] } +common.workspace = true tokio.workspace = true key_protocol.workspace = true diff --git a/lez/wallet-ffi/src/lib.rs b/lez/wallet-ffi/src/lib.rs index 37e422cd..6f4c1808 100644 --- a/lez/wallet-ffi/src/lib.rs +++ b/lez/wallet-ffi/src/lib.rs @@ -46,6 +46,7 @@ pub mod error; pub mod generic_transaction; pub mod keys; pub mod pinata; +pub mod program_deployment; pub mod sync; pub mod transfer; pub mod types; diff --git a/lez/wallet-ffi/src/program_deployment.rs b/lez/wallet-ffi/src/program_deployment.rs new file mode 100644 index 00000000..52b11271 --- /dev/null +++ b/lez/wallet-ffi/src/program_deployment.rs @@ -0,0 +1,230 @@ +use std::{ffi::CString, ptr, slice}; + +use common::transaction::LeeTransaction; +use lee::{program::Program, ProgramDeploymentTransaction}; +use sequencer_service_rpc::RpcClient as _; + +use crate::{ + block_on, + error::{print_error, WalletFfiError}, + generic_transaction::{FfiProgram, FfiTransactionResult}, + wallet::get_wallet, + WalletHandle, +}; + +/// Send a program deployment transaction. +/// +/// Publishes program for future use. +/// +/// # Parameters +/// - `handle`: Valid wallet handle +/// - `elf_data`: Valid pointer to elf data in bytes +/// - `elf_size`: Size of elf data +/// - `out_result`: Output pointer for transfer result +/// +/// # Returns +/// - `Success` if deployment was submitted successfully +/// - Error code on other failures +/// +/// # Memory +/// The result must be freed with `wallet_ffi_free_transaction_result()`. +/// +/// # Safety +/// - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open` +/// - `elf_data` must be a valid pointer to elf data +/// - `out_result` must be a valid pointer to a `FfiTransferResult` struct +#[no_mangle] +pub unsafe extern "C" fn wallet_ffi_program_deployment( + handle: *mut WalletHandle, + elf_data: *const u8, + elf_size: usize, + out_result: *mut FfiTransactionResult, +) -> WalletFfiError { + let wrapper = match get_wallet(handle) { + Ok(w) => w, + Err(e) => return e, + }; + + if elf_data.is_null() || out_result.is_null() { + print_error("Null pointer argument"); + return WalletFfiError::NullPointer; + } + + let wallet = match wrapper.core.lock() { + Ok(w) => w, + Err(e) => { + print_error(format!("Failed to lock wallet: {e}")); + return WalletFfiError::InternalError; + } + }; + + let elf = unsafe { slice::from_raw_parts(elf_data, elf_size) }.to_vec(); + + let message = lee::program_deployment_transaction::Message::new(elf); + let transaction = ProgramDeploymentTransaction::new(message); + + match block_on( + wallet + .sequencer_client + .send_transaction(LeeTransaction::ProgramDeployment(transaction)), + ) { + Ok(tx_hash) => { + let tx_hash = CString::new(tx_hash.to_string()) + .map_or(ptr::null_mut(), std::ffi::CString::into_raw); + + unsafe { + (*out_result).tx_hash = tx_hash; + (*out_result).success = true; + } + WalletFfiError::Success + } + Err(e) => { + print_error(format!("Deployment failed: {e:?}")); + unsafe { + (*out_result).tx_hash = ptr::null_mut(); + (*out_result).success = false; + } + WalletFfiError::NetworkError + } + } +} + +/// Writes elf data of authenticated transfer program into buffer. +/// +/// WARNING: Result is not consisent and change between versions, use for testing purposes only. +/// +/// # Parameters +/// - `ffi_program`: Valid pointer to `FfiProgram` +/// +/// # Returns +/// - `Success` if deployment was submitted successfully +/// - Error code on other failures +/// +/// # Memory +/// - freeing this data is a responsibility of a user +/// +/// # Safety +/// - `ffi_program` must be a non-null pointer +#[no_mangle] +pub unsafe extern "C" fn wallet_ffi_transfer_elf(ffi_program: *mut FfiProgram) -> WalletFfiError { + if ffi_program.is_null() { + print_error("Null pointer argument"); + return WalletFfiError::NullPointer; + } + + let elf = Program::authenticated_transfer_program().elf().to_vec(); + + let (raw_elf_data, raw_elf_size, _) = elf.into_raw_parts(); + + unsafe { + (*ffi_program).elf_data = raw_elf_data; + (*ffi_program).elf_size = raw_elf_size; + }; + + WalletFfiError::Success +} + +/// Writes elf data of authenticated token program into buffer. +/// +/// WARNING: Result is not consisent and change between versions, use for testing purposes only. +/// +/// # Parameters +/// - `ffi_program`: Valid pointer to `FfiProgram` +/// +/// # Returns +/// - `Success` if deployment was submitted successfully +/// - Error code on other failures +/// +/// # Memory +/// - freeing this data is a responsibility of a user +/// +/// # Safety +/// - `ffi_program` must be a non-null pointer +#[no_mangle] +pub unsafe extern "C" fn wallet_ffi_token_elf(ffi_program: *mut FfiProgram) -> WalletFfiError { + if ffi_program.is_null() { + print_error("Null pointer argument"); + return WalletFfiError::NullPointer; + } + + let elf = Program::token().elf().to_vec(); + + let (raw_elf_data, raw_elf_size, _) = elf.into_raw_parts(); + + unsafe { + (*ffi_program).elf_data = raw_elf_data; + (*ffi_program).elf_size = raw_elf_size; + }; + + WalletFfiError::Success +} + +/// Writes elf data of amm into buffer. +/// +/// WARNING: Result is not consisent and change between versions, use for testing purposes only. +/// +/// # Parameters +/// - `ffi_program`: Valid pointer to `FfiProgram` +/// +/// # Returns +/// - `Success` if deployment was submitted successfully +/// - Error code on other failures +/// +/// # Memory +/// - freeing this data is a responsibility of a user +/// +/// # Safety +/// - `ffi_program` must be a non-null pointer +#[no_mangle] +pub unsafe extern "C" fn wallet_ffi_amm_elf(ffi_program: *mut FfiProgram) -> WalletFfiError { + if ffi_program.is_null() { + print_error("Null pointer argument"); + return WalletFfiError::NullPointer; + } + + let elf = Program::amm().elf().to_vec(); + + let (raw_elf_data, raw_elf_size, _) = elf.into_raw_parts(); + + unsafe { + (*ffi_program).elf_data = raw_elf_data; + (*ffi_program).elf_size = raw_elf_size; + }; + + WalletFfiError::Success +} + +/// Writes elf data of ata into buffer. +/// +/// WARNING: Result is not consisent and change between versions, use for testing purposes only. +/// +/// # Parameters +/// - `ffi_program`: Valid pointer to `FfiProgram` +/// +/// # Returns +/// - `Success` if deployment was submitted successfully +/// - Error code on other failures +/// +/// # Memory +/// - freeing this data is a responsibility of a user +/// +/// # Safety +/// - `ffi_program` must be a non-null pointer +#[no_mangle] +pub unsafe extern "C" fn wallet_ffi_ata_elf(ffi_program: *mut FfiProgram) -> WalletFfiError { + if ffi_program.is_null() { + print_error("Null pointer argument"); + return WalletFfiError::NullPointer; + } + + let elf = Program::ata().elf().to_vec(); + + let (raw_elf_data, raw_elf_size, _) = elf.into_raw_parts(); + + unsafe { + (*ffi_program).elf_data = raw_elf_data; + (*ffi_program).elf_size = raw_elf_size; + }; + + WalletFfiError::Success +} diff --git a/lez/wallet-ffi/wallet_ffi.h b/lez/wallet-ffi/wallet_ffi.h index 0c2f14df..4ce452cf 100644 --- a/lez/wallet-ffi/wallet_ffi.h +++ b/lez/wallet-ffi/wallet_ffi.h @@ -868,6 +868,114 @@ enum WalletFfiError wallet_ffi_claim_pinata_private_owned_not_initialized(struct const uint8_t (*solution)[16], struct FfiTransferResult *out_result); +/** + * Send a program deployment transaction. + * + * Publishes program for future use. + * + * # Parameters + * - `handle`: Valid wallet handle + * - `elf_data`: Valid pointer to elf data in bytes + * - `elf_size`: Size of elf data + * - `out_result`: Output pointer for transfer result + * + * # Returns + * - `Success` if deployment was submitted successfully + * - Error code on other failures + * + * # Memory + * The result must be freed with `wallet_ffi_free_transaction_result()`. + * + * # Safety + * - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open` + * - `elf_data` must be a valid pointer to elf data + * - `out_result` must be a valid pointer to a `FfiTransferResult` struct + */ +enum WalletFfiError wallet_ffi_program_deployment(struct WalletHandle *handle, + const uint8_t *elf_data, + uintptr_t elf_size, + struct FfiTransactionResult *out_result); + +/** + * Writes elf data of authenticated transfer program into buffer. + * + * WARNING: Result is not consisent and change between versions, use for testing purposes only. + * + * # Parameters + * - `ffi_program`: Valid pointer to `FfiProgram` + * + * # Returns + * - `Success` if deployment was submitted successfully + * - Error code on other failures + * + * # Memory + * - freeing this data is a responsibility of a user + * + * # Safety + * - `ffi_program` must be a non-null pointer + */ +enum WalletFfiError wallet_ffi_transfer_elf(struct FfiProgram *ffi_program); + +/** + * Writes elf data of authenticated token program into buffer. + * + * WARNING: Result is not consisent and change between versions, use for testing purposes only. + * + * # Parameters + * - `ffi_program`: Valid pointer to `FfiProgram` + * + * # Returns + * - `Success` if deployment was submitted successfully + * - Error code on other failures + * + * # Memory + * - freeing this data is a responsibility of a user + * + * # Safety + * - `ffi_program` must be a non-null pointer + */ +enum WalletFfiError wallet_ffi_token_elf(struct FfiProgram *ffi_program); + +/** + * Writes elf data of amm into buffer. + * + * WARNING: Result is not consisent and change between versions, use for testing purposes only. + * + * # Parameters + * - `ffi_program`: Valid pointer to `FfiProgram` + * + * # Returns + * - `Success` if deployment was submitted successfully + * - Error code on other failures + * + * # Memory + * - freeing this data is a responsibility of a user + * + * # Safety + * - `ffi_program` must be a non-null pointer + */ +enum WalletFfiError wallet_ffi_amm_elf(struct FfiProgram *ffi_program); + +/** + * Writes elf data of ata into buffer. + * + * WARNING: Result is not consisent and change between versions, use for testing purposes only. + * + * # Parameters + * - `ffi_program`: Valid pointer to `FfiProgram` + * + * # Returns + * - `Success` if deployment was submitted successfully + * - Error code on other failures + * + * # Memory + * - freeing this data is a responsibility of a user + * + * # Safety + * - `ffi_program` must be a non-null pointer + */ +enum WalletFfiError wallet_ffi_ata_elf(struct FfiProgram *ffi_program); + /** * Synchronize private accounts to a specific block. *