mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-04-12 06:03:08 +00:00
Merge 6721d8d96e71566f072bab2ededcf56d29b002b0 into 7473c2f7a9ab8da65870442f0b90c96293982446
This commit is contained in:
commit
35b06dbd36
@ -40,6 +40,8 @@ pub enum WalletFfiError {
|
||||
InvalidTypeConversion = 15,
|
||||
/// Invalid Key value.
|
||||
InvalidKeyValue = 16,
|
||||
/// Invalid argument value.
|
||||
InvalidArgument = 17,
|
||||
/// Internal error (catch-all).
|
||||
InternalError = 99,
|
||||
}
|
||||
|
||||
@ -94,6 +94,107 @@ pub unsafe extern "C" fn wallet_ffi_transfer_public(
|
||||
}
|
||||
}
|
||||
|
||||
/// Send an arbitrary public transaction to a program.
|
||||
///
|
||||
/// Builds a `PublicTransaction` from the given program, accounts, and instruction data,
|
||||
/// signs it with the signer's key, and submits to the sequencer.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `handle`: Valid wallet handle
|
||||
/// - `program_id`: 32-byte program ID
|
||||
/// - `accounts`: Pointer to array of 32-byte account IDs
|
||||
/// - `num_accounts`: Number of accounts in the array
|
||||
/// - `instruction_data`: Pointer to raw instruction bytes (Vec<u32> serialized as LE bytes)
|
||||
/// - `instruction_len`: Length of instruction data in bytes (must be multiple of 4)
|
||||
/// - `signer`: Signer account ID (must be owned by this wallet)
|
||||
/// - `out_result`: Output pointer for transfer result
|
||||
///
|
||||
/// # Safety
|
||||
/// All pointers must be valid. `instruction_len` must be a multiple of 4.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_send_public_transaction(
|
||||
handle: *mut WalletHandle,
|
||||
program_id: *const FfiBytes32,
|
||||
accounts: *const FfiBytes32,
|
||||
num_accounts: usize,
|
||||
instruction_data: *const u8,
|
||||
instruction_len: usize,
|
||||
signer: *const FfiBytes32,
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> WalletFfiError {
|
||||
let wrapper = match get_wallet(handle) {
|
||||
Ok(w) => w,
|
||||
Err(e) => return e,
|
||||
};
|
||||
|
||||
if program_id.is_null()
|
||||
|| accounts.is_null()
|
||||
|| instruction_data.is_null()
|
||||
|| signer.is_null()
|
||||
|| out_result.is_null()
|
||||
{
|
||||
print_error("Null pointer argument");
|
||||
return WalletFfiError::NullPointer;
|
||||
}
|
||||
|
||||
if instruction_len % 4 != 0 {
|
||||
print_error("instruction_len must be a multiple of 4");
|
||||
return WalletFfiError::InvalidArgument;
|
||||
}
|
||||
|
||||
let wallet = match wrapper.core.lock() {
|
||||
Ok(w) => w,
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to lock wallet: {e}"));
|
||||
return WalletFfiError::InternalError;
|
||||
}
|
||||
};
|
||||
|
||||
let pid_bytes = unsafe { (*program_id).data };
|
||||
let mut pid: nssa_core::program::ProgramId = [0u32; 8];
|
||||
for i in 0..8 {
|
||||
pid[i] = u32::from_le_bytes([
|
||||
pid_bytes[i * 4],
|
||||
pid_bytes[i * 4 + 1],
|
||||
pid_bytes[i * 4 + 2],
|
||||
pid_bytes[i * 4 + 3],
|
||||
]);
|
||||
}
|
||||
let signer_id = AccountId::new(unsafe { (*signer).data });
|
||||
|
||||
let account_ids: Vec<AccountId> = (0..num_accounts)
|
||||
.map(|i| AccountId::new(unsafe { (*accounts.add(i)).data }))
|
||||
.collect();
|
||||
|
||||
// Convert raw bytes to Vec<u32> (LE)
|
||||
let instr_slice = unsafe { std::slice::from_raw_parts(instruction_data, instruction_len) };
|
||||
let instr_u32: Vec<u32> = instr_slice
|
||||
.chunks_exact(4)
|
||||
.map(|c| u32::from_le_bytes([c[0], c[1], c[2], c[3]]))
|
||||
.collect();
|
||||
|
||||
match block_on(wallet.send_public_transaction(pid, account_ids, instr_u32, signer_id)) {
|
||||
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!("Transaction failed: {e:?}"));
|
||||
unsafe {
|
||||
(*out_result).tx_hash = ptr::null_mut();
|
||||
(*out_result).success = false;
|
||||
}
|
||||
map_execution_error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a shielded token transfer.
|
||||
///
|
||||
/// Transfers tokens from a public account to a private account.
|
||||
|
||||
@ -103,6 +103,10 @@ typedef enum WalletFfiError {
|
||||
* Invalid Key value.
|
||||
*/
|
||||
INVALID_KEY_VALUE = 16,
|
||||
/**
|
||||
* Invalid argument value.
|
||||
*/
|
||||
INVALID_ARGUMENT = 17,
|
||||
/**
|
||||
* Internal error (catch-all).
|
||||
*/
|
||||
@ -676,6 +680,34 @@ enum WalletFfiError wallet_ffi_transfer_public(struct WalletHandle *handle,
|
||||
const uint8_t (*amount)[16],
|
||||
struct FfiTransferResult *out_result);
|
||||
|
||||
/**
|
||||
* Send an arbitrary public transaction to a program.
|
||||
*
|
||||
* Builds a `PublicTransaction` from the given program, accounts, and instruction data,
|
||||
* signs it with the signer's key, and submits to the sequencer.
|
||||
*
|
||||
* # Parameters
|
||||
* - `handle`: Valid wallet handle
|
||||
* - `program_id`: 32-byte program ID
|
||||
* - `accounts`: Pointer to array of 32-byte account IDs
|
||||
* - `num_accounts`: Number of accounts in the array
|
||||
* - `instruction_data`: Pointer to raw instruction bytes (Vec<u32> serialized as LE bytes)
|
||||
* - `instruction_len`: Length of instruction data in bytes (must be multiple of 4)
|
||||
* - `signer`: Signer account ID (must be owned by this wallet)
|
||||
* - `out_result`: Output pointer for transfer result
|
||||
*
|
||||
* # Safety
|
||||
* All pointers must be valid. `instruction_len` must be a multiple of 4.
|
||||
*/
|
||||
enum WalletFfiError wallet_ffi_send_public_transaction(struct WalletHandle *handle,
|
||||
const struct FfiBytes32 *program_id,
|
||||
const struct FfiBytes32 *accounts,
|
||||
uintptr_t num_accounts,
|
||||
const uint8_t *instruction_data,
|
||||
uintptr_t instruction_len,
|
||||
const struct FfiBytes32 *signer,
|
||||
struct FfiTransferResult *out_result);
|
||||
|
||||
/**
|
||||
* Send a shielded token transfer.
|
||||
*
|
||||
|
||||
@ -290,6 +290,41 @@ impl WalletCore {
|
||||
.get_pub_account_signing_key(account_id)
|
||||
}
|
||||
|
||||
/// Send an arbitrary public transaction to a program.
|
||||
pub async fn send_public_transaction(
|
||||
&self,
|
||||
program_id: nssa_core::program::ProgramId,
|
||||
account_ids: Vec<AccountId>,
|
||||
instruction_data: InstructionData,
|
||||
signer: AccountId,
|
||||
) -> Result<HashType, ExecutionFailureKind> {
|
||||
let nonces = self
|
||||
.get_accounts_nonces(vec![signer])
|
||||
.await
|
||||
.map_err(ExecutionFailureKind::SequencerError)?;
|
||||
|
||||
let message = nssa::public_transaction::Message::new_preserialized(
|
||||
program_id,
|
||||
account_ids,
|
||||
nonces,
|
||||
instruction_data,
|
||||
);
|
||||
|
||||
let signing_key = self.storage.user_data.get_pub_account_signing_key(signer);
|
||||
let Some(signing_key) = signing_key else {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
let witness_set =
|
||||
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key]);
|
||||
let tx = nssa::PublicTransaction::new(message, witness_set);
|
||||
|
||||
Ok(self
|
||||
.sequencer_client
|
||||
.send_transaction(NSSATransaction::Public(tx))
|
||||
.await?)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_account_private(&self, account_id: AccountId) -> Option<Account> {
|
||||
self.storage
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user