Struct Transaction

Source
pub struct Transaction<'a, P: JsonRpcProvider + 'static> {
    pub network: Option<&'a RpcClient<P>>,
    pub version: u8,
    pub nonce: u32,
    pub valid_until_block: u32,
    pub signers: Vec<Signer>,
    pub size: i32,
    pub sys_fee: i64,
    pub net_fee: i64,
    pub attributes: Vec<TransactionAttribute>,
    pub script: Bytes,
    pub witnesses: Vec<Witness>,
    /* private fields */
}
Expand description

A Neo N3 blockchain transaction.

The Transaction struct represents a transaction on the Neo N3 blockchain. It contains all the necessary information for a transaction, including version, nonce, validity period, signers, fees, attributes, script, and witnesses.

§Fields

  • network - An optional reference to an RPC client for network operations.
  • version - The transaction version.
  • nonce - A random number to prevent transaction duplication.
  • valid_until_block - The block height until which the transaction is valid.
  • signers - A list of transaction signers.
  • size - The size of the transaction in bytes.
  • sys_fee - The system fee for the transaction.
  • net_fee - The network fee for the transaction.
  • attributes - Transaction attributes.
  • script - The transaction script.
  • witnesses - Transaction witnesses (signatures).
  • block_count_when_sent - The block count when the transaction was sent.

§Examples

use neo3::neo_builder::{Transaction, TransactionBuilder};
use neo3::neo_clients::{HttpProvider, RpcClient};

fn example() -> Result<(), Box<dyn std::error::Error>> {
    // Create a new transaction (placeholder)
    // let tx = Transaction::new();

    // Transactions are typically created using the TransactionBuilder
    let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
    let client = RpcClient::new(provider);
    // let mut tx_builder = TransactionBuilder::with_client(&client);
    Ok(())
}

Fields§

§network: Option<&'a RpcClient<P>>§version: u8§nonce: u32§valid_until_block: u32§signers: Vec<Signer>§size: i32§sys_fee: i64§net_fee: i64§attributes: Vec<TransactionAttribute>§script: Bytes§witnesses: Vec<Witness>

Implementations§

Source§

impl<'a, P: JsonRpcProvider + 'static> Transaction<'a, P>

Source

pub fn network(&self) -> &Option<&'a RpcClient<P>>

Source

pub fn version(&self) -> &u8

Source

pub fn nonce(&self) -> &u32

Source

pub fn valid_until_block(&self) -> &u32

Source

pub fn signers(&self) -> &Vec<Signer>

Source

pub fn size(&self) -> &i32

Source

pub fn sys_fee(&self) -> &i64

Source

pub fn net_fee(&self) -> &i64

Source

pub fn attributes(&self) -> &Vec<TransactionAttribute>

Source

pub fn script(&self) -> &Bytes

Source

pub fn witnesses(&self) -> &Vec<Witness>

Source§

impl<'a, P: JsonRpcProvider + 'static> Transaction<'a, P>

Source

pub fn set_network(&mut self, val: Option<&'a RpcClient<P>>) -> &mut Self

Source

pub fn set_version(&mut self, val: u8) -> &mut Self

Source

pub fn set_nonce(&mut self, val: u32) -> &mut Self

Source

pub fn set_valid_until_block(&mut self, val: u32) -> &mut Self

Source

pub fn set_signers(&mut self, val: Vec<Signer>) -> &mut Self

Source

pub fn set_size(&mut self, val: i32) -> &mut Self

Source

pub fn set_sys_fee(&mut self, val: i64) -> &mut Self

Source

pub fn set_net_fee(&mut self, val: i64) -> &mut Self

Source

pub fn set_attributes(&mut self, val: Vec<TransactionAttribute>) -> &mut Self

Source

pub fn set_script(&mut self, val: Bytes) -> &mut Self

Source

pub fn set_witnesses(&mut self, val: Vec<Witness>) -> &mut Self

Source§

impl<'a, T: JsonRpcProvider + 'static> Transaction<'a, T>

Source

pub fn new() -> Self

Source

pub fn pay<K: Into<NameOrAddress>, V: Into<U256>>(_to: K, _value: V) -> Self

Convenience function for sending a new payment transaction to the receiver.

Source

pub fn add_witness(&mut self, witness: Witness)

Source

pub async fn get_hash_data(&self) -> Result<Bytes, TransactionError>

Source

pub async fn send_tx(&mut self) -> Result<RawTransaction, TransactionError>

Sends the transaction to the Neo N3 network.

This method validates the transaction, converts it to a hexadecimal string, and sends it to the network using the RPC client. It also records the current block count for transaction tracking purposes.

§Returns

A Result containing the RawTransaction response if successful, or a TransactionError if an error occurs.

§Errors

Returns an error if:

  • The number of signers does not match the number of witnesses
  • The transaction exceeds the maximum transaction size
  • The network client encounters an error when sending the transaction
§Examples
use neo3::neo_builder::{ScriptBuilder, AccountSigner, TransactionBuilder, CallFlags};
use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
use neo3::neo_protocol::{Account, AccountTrait};
use neo3::neo_types::{Address, ContractParameter, ScriptHash, AddressExtension};
use std::str::FromStr;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to Neo N3 TestNet
    let provider = HttpProvider::new("https://testnet1.neo.org:443").unwrap();
    let client = RpcClient::new(provider);
     
    // Load your account from WIF or keystore
    let private_key = "your_private_key_here";
    let account = Account::from_wif(private_key)?;
     
    // Create a token transfer transaction
    let from_address = account.get_address();
    let to_address = "NdUL5oDPD159KeFpD5A9zw5xNF1xLX6nLT";
    let amount = 1_000_000; // 1 GAS (with 8 decimals)
     
    let mut script_builder = ScriptBuilder::new();
    let script = script_builder.contract_call(
        &ScriptHash::from_str("d2a4cff31913016155e38e474a2c06d08be276cf")?, // GAS token
        "transfer",
        &[
            ContractParameter::from(account.get_script_hash()),
            ContractParameter::from(Address::from_str(to_address)?.address_to_script_hash()?),
            ContractParameter::integer(amount),
            ContractParameter::any()
        ],
        Some(CallFlags::All)
    )?;
     
    // Build the transaction with proper fee calculation
    let mut tx_builder = TransactionBuilder::with_client(&client);
    tx_builder.extend_script(script.to_bytes());
    let account_signer = AccountSigner::called_by_entry(&account)?;
    tx_builder.set_signers(vec![account_signer.into()])?;
    tx_builder.valid_until_block(client.get_block_count().await? + 2400)?; // ~1 hour validity
     
    // Sign the transaction and get signed transaction
    let signed_transaction = tx_builder.sign().await?;
     
    // Send the transaction to the network
    let mut transaction = signed_transaction;
    let response = transaction.send_tx().await?;
    println!("✅ Transaction sent successfully!");
    println!("Transaction ID: {}", response.hash);
    println!("Transferred {} GAS to {}", amount as f64 / 100_000_000.0, to_address);
     
    Ok(())
}
Source

pub async fn track_tx(&self, max_blocks: u32) -> Result<(), TransactionError>

Tracks a transaction until it appears in a block.

This method waits for the transaction to be included in a block by monitoring new blocks as they are added to the blockchain. It returns when the transaction is found in a block.

§Arguments
  • max_blocks - The maximum number of blocks to wait for the transaction to appear
§Returns
  • Ok(()) - If the transaction is found in a block
  • Err(TransactionError) - If the transaction is not found after waiting for max_blocks blocks
§Errors

Returns an error if:

  • The transaction has not been sent yet
  • The maximum number of blocks is reached without finding the transaction
  • There is an error communicating with the blockchain
§Examples
use neo3::neo_builder::{ScriptBuilder, AccountSigner, TransactionBuilder, CallFlags};
use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
use neo3::neo_protocol::{Account, AccountTrait};
use neo3::neo_types::{ContractParameter, ScriptHash};
use std::str::FromStr;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize provider and client
    let provider = HttpProvider::new("https://testnet1.neo.org:443").unwrap();
    let client = RpcClient::new(provider);
     
    // Load account and create smart contract deployment transaction
    let account = Account::from_wif("your_private_key_here")?;
     
    // Load contract NEF and manifest
    let nef_bytes = std::fs::read("path/to/contract.nef")?;
    let manifest_bytes = std::fs::read("path/to/contract.manifest.json")?;
     
    let mut script_builder = ScriptBuilder::new();
    let deploy_script = script_builder.contract_call(
        &ScriptHash::from_str("0xfffdc93764dbaddd97c48f252a53ea4643faa3fd")?, // ContractManagement
        "deploy",
        &[
            ContractParameter::byte_array(nef_bytes),
            ContractParameter::byte_array(manifest_bytes),
            ContractParameter::any() // Optional data parameter
        ],
        Some(CallFlags::All)
    )?;
     
    // Build transaction with appropriate settings for contract deployment
    let mut tx_builder = TransactionBuilder::with_client(&client);
    tx_builder.extend_script(deploy_script.to_bytes());
    let account_signer = AccountSigner::called_by_entry(&account)?;
    tx_builder.set_signers(vec![account_signer.into()])?;
    tx_builder.valid_until_block(client.get_block_count().await? + 2400)?;
     
    // Sign the transaction and get signed transaction
    let signed_transaction = tx_builder.sign().await?;
     
    // Send the transaction
    let mut transaction = signed_transaction;
    let response = transaction.send_tx().await?;
    println!("✅ Contract deployment transaction sent!");
    println!("Transaction ID: {}", response.hash);
     
    // Track the transaction until confirmation
    println!("⏳ Waiting for transaction confirmation...");
    transaction.track_tx(15).await?; // Wait up to 15 blocks (~15 seconds)
    println!("🎉 Contract deployment confirmed!");
     
    Ok(())
}
Source

pub async fn get_application_log<P>( &self, provider: &P, ) -> Result<ApplicationLog, TransactionError>
where P: APITrait,

Retrieves the application log for this transaction.

Application logs contain detailed information about the execution of a transaction, including notifications, stack items, and any exceptions that occurred during execution.

§Arguments
  • provider - A provider implementing the APITrait to make the RPC call.
§Returns

A Result containing the ApplicationLog if successful, or a TransactionError if an error occurs.

§Errors

Returns an error if:

  • The transaction has not been sent yet
  • The transaction ID cannot be calculated
  • The provider encounters an error when retrieving the application log
§Examples
use neo3::neo_builder::{ScriptBuilder, AccountSigner, TransactionBuilder, CallFlags};
use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
use neo3::neo_protocol::{Account, AccountTrait};
use neo3::neo_types::{ContractParameter, ScriptHash};
use std::str::FromStr;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Setup client connection
    let provider = HttpProvider::new("https://testnet1.neo.org:443").unwrap();
    let client = RpcClient::new(provider);
     
    // Load account for contract interaction
    let account = Account::from_wif("your_private_key_here")?;
    let contract_hash = ScriptHash::from_str("your_contract_hash_here")?;
     
    // Create a contract invocation transaction
    let mut script_builder = ScriptBuilder::new();
    let invoke_script = script_builder.contract_call(
        &contract_hash,
        "setValue", // Contract method name
        &[
            ContractParameter::string("myKey".to_string()),
            ContractParameter::string("myValue".to_string()),
            ContractParameter::integer(42)
        ],
        Some(CallFlags::All)
    )?;
     
    // Build and configure the transaction
    let mut tx_builder = TransactionBuilder::with_client(&client);
    tx_builder.extend_script(invoke_script.to_bytes());
    let account_signer = AccountSigner::called_by_entry(&account)?;
    tx_builder.set_signers(vec![account_signer.into()])?;
    tx_builder.valid_until_block(client.get_block_count().await? + 1200)?; // 20 minutes validity
     
    // Sign the transaction and get signed transaction
    let signed_transaction = tx_builder.sign().await?;
     
    // Send the transaction
    let mut transaction = signed_transaction;
    let response = transaction.send_tx().await?;
    println!("📤 Smart contract invocation sent!");
    println!("Transaction ID: {}", response.hash);
     
    // Wait for confirmation and get detailed execution results
    println!("⏳ Waiting for transaction confirmation...");
    transaction.track_tx(12).await?;
    println!("✅ Transaction confirmed!");
     
    // Analyze the execution results
    let app_log = transaction.get_application_log(&client).await?;
    println!("🔍 Transaction execution analysis:");
    if let Ok(execution) = app_log.get_first_execution() {
        println!("  Execution state: {:?}", execution.state);
        println!("  GAS consumed: {}", execution.gas_consumed);
         
        // Process contract notifications and events
        if !execution.notifications.is_empty() {
            println!("📋 Contract notifications:");
            for (i, notification) in execution.notifications.iter().enumerate() {
                println!("  {}. Event: {} from contract {}",
                    i + 1, notification.event_name, notification.contract);
                println!("     State: {:?}", notification.state);
            }
        }
         
        // Check execution stack for return values
        if !execution.stack.is_empty() {
            println!("📊 Return values: {:?}", execution.stack);
        }
         
        if execution.state.to_string() == "HALT" {
            println!("🎉 Smart contract executed successfully!");
        } else {
            println!("❌ Smart contract execution failed");
            if let Some(exception) = &execution.exception {
                println!("   Exception: {}", exception);
            }
        }
    }
     
    Ok(())
}

Trait Implementations§

Source§

impl<'a, P: Clone + JsonRpcProvider + 'static> Clone for Transaction<'a, P>

Source§

fn clone(&self) -> Transaction<'a, P>

Returns a duplicate of the value. Read more
1.0.0 · Source§

const fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a, P: Debug + JsonRpcProvider + 'static> Debug for Transaction<'a, P>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a, P: JsonRpcProvider + 'static> Default for Transaction<'a, P>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de, 'a, P: JsonRpcProvider + 'static> Deserialize<'de> for Transaction<'a, P>

Source§

fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<'a, P: JsonRpcProvider + 'static> Hash for Transaction<'a, P>

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<'a, P: JsonRpcProvider + 'static> NeoSerializable for Transaction<'a, P>

Source§

type Error = TransactionError

Source§

fn size(&self) -> usize

Source§

fn encode(&self, writer: &mut Encoder)

Source§

fn decode(reader: &mut Decoder<'_>) -> Result<Self, Self::Error>
where Self: Sized,

Source§

fn to_array(&self) -> Vec<u8>

Source§

impl<'a, P: JsonRpcProvider + 'static> PartialEq for Transaction<'a, P>

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

const fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a, P: JsonRpcProvider + 'static> Serialize for Transaction<'a, P>

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl<'a, P: JsonRpcProvider + 'static> Eq for Transaction<'a, P>

Auto Trait Implementations§

§

impl<'a, P> Freeze for Transaction<'a, P>

§

impl<'a, P> !RefUnwindSafe for Transaction<'a, P>

§

impl<'a, P> Send for Transaction<'a, P>

§

impl<'a, P> Sync for Transaction<'a, P>

§

impl<'a, P> Unpin for Transaction<'a, P>

§

impl<'a, P> !UnwindSafe for Transaction<'a, P>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where T: 'static,