1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use alloc::vec::Vec;
use eosio::{
    AccountName, Action, DataStream, NumBytes, Read, ReadError, Transaction,
    TransactionId, Write, WriteError,
};

/// This method will abort execution of wasm without failing the contract. This
/// is used to bypass all cleanup / destructors that would normally be called.
#[inline]
pub fn eosio_exit<C>(code: C)
where
    C: Into<i32>,
{
    unsafe { eosio_cdt_sys::eosio_exit(code.into()) }
}

/// Sends an inline action.
///
/// # Errors
///
/// Will return `Err` if there was an issue serializing the action.
#[inline]
pub fn send_inline_action(action: &Action<Vec<u8>>) -> Result<(), WriteError> {
    let size = action.num_bytes();
    let mut bytes = vec![0_u8; size];
    let mut pos = 0;
    action.write(&mut bytes, &mut pos)?;
    let ptr = bytes[..].as_mut_ptr();
    unsafe { eosio_cdt_sys::send_inline(ptr, pos) }
    Ok(())
}

/// Sends a context free inline action.
///
/// # Errors
///
/// Will return `Err` if there was an issue serializing the action.
#[inline]
pub fn send_context_free_inline_action(
    action: &Action<Vec<u8>>,
) -> Result<(), WriteError> {
    let size = action.num_bytes();
    let mut bytes = vec![0_u8; size];
    let mut pos = 0;
    action.write(&mut bytes, &mut pos)?;
    let ptr = bytes[..].as_mut_ptr();
    unsafe { eosio_cdt_sys::send_context_free_inline(ptr, pos) }
    Ok(())
}

/// Sends a deferred transaction
///
/// # Errors
///
/// Will return `Err` if there was an issue serializing the transaction.
#[inline]
pub fn send_deferred<I, P, T>(
    id: I,
    payer: P,
    trx: T,
    replace_existing: bool,
) -> Result<(), WriteError>
where
    I: AsRef<TransactionId>,
    P: AsRef<AccountName>,
    T: AsRef<Transaction>,
{
    let bytes = trx.as_ref().pack()?;
    send_deferred_bytes(id, payer, bytes, replace_existing);
    Ok(())
}

/// Sends a deferred transaction from raw bytes.
#[inline]
pub fn send_deferred_bytes<I, P, T>(
    id: I,
    payer: P,
    bytes: T,
    replace_existing: bool,
) where
    I: AsRef<TransactionId>,
    P: AsRef<AccountName>,
    T: AsRef<[u8]>,
{
    let id = id.as_ref().as_u128();
    let id_ptr = &id as *const _ as *const u128;
    let bytes = bytes.as_ref();
    unsafe {
        eosio_cdt_sys::send_deferred(
            id_ptr,
            payer.as_ref().as_u64(),
            bytes.as_ptr(),
            bytes.len(),
            replace_existing.into(),
        )
    }
}

/// Cancels a deferred transaction
#[must_use]
#[inline]
pub fn cancel_deferred<I: AsRef<TransactionId>>(id: I) -> bool {
    let sender_id = id.as_ref().as_u128();
    let sender_id_ptr = &sender_id as *const _ as *const u128;
    let result = unsafe { eosio_cdt_sys::cancel_deferred(sender_id_ptr) };
    result == 1
}

/// Reads action data
///
/// # Errors
///
/// Will return `Err` if there was a problem reading the action data.
#[inline]
pub fn read_action_data<T: Read>() -> Result<T, ReadError> {
    let num_bytes = unsafe { eosio_cdt_sys::action_data_size() };
    let mut bytes = vec![0_u8; num_bytes as usize];
    let ptr: *mut eosio_cdt_sys::c_void =
        &mut bytes[..] as *mut _ as *mut eosio_cdt_sys::c_void;
    unsafe {
        eosio_cdt_sys::read_action_data(ptr, num_bytes);
    }
    let mut pos = 0;
    T::read(&bytes, &mut pos)
}

/// Get a `DataStream` of the current action data
#[must_use]
#[inline]
pub fn current_data_stream() -> DataStream {
    let num_bytes = unsafe { eosio_cdt_sys::action_data_size() };
    let mut bytes = vec![0_u8; num_bytes as usize];
    let ptr: *mut eosio_cdt_sys::c_void =
        &mut bytes[..] as *mut _ as *mut eosio_cdt_sys::c_void;
    unsafe {
        eosio_cdt_sys::read_action_data(ptr, num_bytes);
    }
    bytes.into()
}