feat(wallet_ffi): program elfs and program deployment

This commit is contained in:
Pravdyvy 2026-06-04 21:05:58 +03:00
parent a999563a2d
commit 7ccd8e2435
5 changed files with 341 additions and 0 deletions

1
Cargo.lock generated
View File

@ -10724,6 +10724,7 @@ name = "wallet-ffi"
version = "0.1.0"
dependencies = [
"cbindgen",
"common",
"key_protocol",
"lee",
"lee_core",

View File

@ -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

View File

@ -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;

View File

@ -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
}

View File

@ -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.
*