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
//! A module that contains structs representing entry points and entry point callers.

use casper_types::CLType;

use crate::args::EntrypointArgument;
use crate::call_def::CallDef;
use crate::casper_types::bytesrepr::Bytes;
use crate::{host::HostEnv, prelude::*, ContractEnv, OdraResult};

/// A struct representing an entry point caller.
///
/// The caller is used by the host environment to call entry points of a contract.
///
/// This struct is responsible for calling the entry points of a contract.
/// It holds the host environment, a list of entry points, and a function pointer
/// that takes a contract environment and a call definition as arguments and returns
/// a result in the form of bytes.
#[derive(Clone)]
pub struct EntryPointsCaller {
    f: fn(contract_env: ContractEnv, call_def: CallDef) -> OdraResult<Bytes>,
    host_env: HostEnv,
    entry_points: Vec<EntryPoint>
}

impl EntryPointsCaller {
    /// Creates a new instance of `EntryPointsCaller`.
    ///
    /// # Arguments
    ///
    /// * `host_env` - The host environment.
    /// * `entry_points` - A collection of available entry points.
    /// * `f` - A function pointer that performs a call using a given contract environment and a call definition
    ///         and returns a result in the form of bytes.
    ///
    /// # Returns
    ///
    /// A new instance of `EntryPointsCaller`.
    pub fn new(
        host_env: HostEnv,
        entry_points: Vec<EntryPoint>,
        f: fn(contract_env: ContractEnv, call_def: CallDef) -> OdraResult<Bytes>
    ) -> Self {
        EntryPointsCaller {
            f,
            host_env,
            entry_points
        }
    }

    /// Calls the entry point with the given call definition.
    /// Returns the result of the entry point call in the form of bytes.
    pub fn call(&self, call_def: CallDef) -> OdraResult<Bytes> {
        (self.f)(self.host_env.contract_env(), call_def)
    }

    /// Returns a reference to the list of entry points.
    pub fn entry_points(&self) -> &[EntryPoint] {
        self.entry_points.as_ref()
    }
}

/// A struct representing an entry point.
#[derive(Clone)]
pub struct EntryPoint {
    /// The name of the entry point.
    pub name: String,
    /// The collection of arguments to the entry point.
    pub args: Vec<Argument>,
    /// A flag indicating whether the entry point is payable.
    pub is_payable: bool
}

impl EntryPoint {
    /// Creates a new instance of `EntryPoint`.
    pub fn new(name: String, args: Vec<Argument>) -> Self {
        Self {
            name,
            args,
            is_payable: false
        }
    }

    /// Creates a new instance of payable `EntryPoint`.
    pub fn new_payable(name: String, args: Vec<Argument>) -> Self {
        Self {
            name,
            args,
            is_payable: true
        }
    }
}

/// A struct representing an argument to entry point.
#[derive(Clone)]
pub struct Argument {
    /// The name of the argument.
    pub name: String,
    /// The type of the argument.
    pub ty: CLType
}

impl Argument {
    /// Creates a new instance of `Argument`.
    pub fn new<T: EntrypointArgument>(name: String) -> Self {
        Self {
            name,
            ty: T::cl_type()
        }
    }
}