neo3/neo_contract/famous/
neocompound.rs

1use async_trait::async_trait;
2use primitive_types::H160;
3use serde::{Deserialize, Serialize};
4use std::str::FromStr;
5
6use crate::{
7	builder::{AccountSigner, TransactionBuilder},
8	neo_clients::{APITrait, JsonRpcProvider, RpcClient},
9	neo_contract::{ContractError, SmartContractTrait},
10	neo_protocol::Account,
11};
12use neo3::prelude::*;
13
14/// NeoCompound contract interface for Neo N3
15///
16/// NeoCompound is an automated interest compounding service for Neo ecosystem tokens.
17/// This contract interface provides methods to interact with the NeoCompound smart contract.
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct NeoCompoundContract<'a, P: JsonRpcProvider> {
20	#[serde(deserialize_with = "deserialize_script_hash")]
21	#[serde(serialize_with = "serialize_script_hash")]
22	script_hash: ScriptHash,
23	#[serde(skip)]
24	provider: Option<&'a RpcClient<P>>,
25}
26
27impl<'a, P: JsonRpcProvider + 'static> NeoCompoundContract<'a, P> {
28	/// The script hash of the NeoCompound contract on Neo N3 MainNet
29	pub const CONTRACT_HASH: &'static str = "f0151f528127558851b39c2cd8aa47da7418ab28";
30
31	// Method constants
32	/// Method name for depositing tokens
33	pub const DEPOSIT: &'static str = "deposit";
34	/// Method name for withdrawing tokens
35	pub const WITHDRAW: &'static str = "withdraw";
36	/// Method name for compounding interest
37	pub const COMPOUND: &'static str = "compound";
38	/// Method name for getting the APY
39	pub const GET_APY: &'static str = "getAPY";
40
41	/// Creates a new NeoCompoundContract instance with the default contract hash
42	///
43	/// # Arguments
44	///
45	/// * `provider` - An optional reference to an RPC client
46	///
47	/// # Returns
48	///
49	/// A new NeoCompoundContract instance
50	pub fn new(provider: Option<&'a RpcClient<P>>) -> Self {
51		Self { script_hash: ScriptHash::from_str(Self::CONTRACT_HASH).unwrap(), provider }
52	}
53
54	/// Creates a new NeoCompoundContract instance with a custom script hash
55	///
56	/// # Arguments
57	///
58	/// * `script_hash` - The script hash of the NeoCompound contract
59	/// * `provider` - An optional reference to an RPC client
60	///
61	/// # Returns
62	///
63	/// A new NeoCompoundContract instance
64	pub fn with_script_hash(script_hash: ScriptHash, provider: Option<&'a RpcClient<P>>) -> Self {
65		Self { script_hash, provider }
66	}
67
68	/// Deposits tokens into NeoCompound
69	///
70	/// # Arguments
71	///
72	/// * `token` - The script hash of the token to deposit
73	/// * `amount` - The amount of tokens to deposit
74	/// * `account` - The account that will sign the transaction
75	///
76	/// # Returns
77	///
78	/// A transaction builder that can be used to build and sign the transaction
79	pub async fn deposit(
80		&self,
81		token: &ScriptHash,
82		amount: i64,
83		account: &Account,
84	) -> Result<TransactionBuilder<P>, ContractError> {
85		let params = vec![token.into(), ContractParameter::integer(amount)];
86
87		let mut builder = self.invoke_function(Self::DEPOSIT, params).await?;
88		builder.set_signers(vec![AccountSigner::called_by_entry(account).unwrap().into()]);
89
90		Ok(builder)
91	}
92
93	/// Withdraws tokens from NeoCompound
94	///
95	/// # Arguments
96	///
97	/// * `token` - The script hash of the token to withdraw
98	/// * `amount` - The amount of tokens to withdraw
99	/// * `account` - The account that will sign the transaction
100	///
101	/// # Returns
102	///
103	/// A transaction builder that can be used to build and sign the transaction
104	pub async fn withdraw(
105		&self,
106		token: &ScriptHash,
107		amount: i64,
108		account: &Account,
109	) -> Result<TransactionBuilder<P>, ContractError> {
110		let params = vec![token.into(), ContractParameter::integer(amount)];
111
112		let mut builder = self.invoke_function(Self::WITHDRAW, params).await?;
113		builder.set_signers(vec![AccountSigner::called_by_entry(account).unwrap().into()]);
114
115		Ok(builder)
116	}
117
118	/// Compounds interest for a specific token
119	///
120	/// # Arguments
121	///
122	/// * `token` - The script hash of the token to compound interest for
123	/// * `account` - The account that will sign the transaction
124	///
125	/// # Returns
126	///
127	/// A transaction builder that can be used to build and sign the transaction
128	pub async fn compound(
129		&self,
130		token: &ScriptHash,
131		account: &Account,
132	) -> Result<TransactionBuilder<P>, ContractError> {
133		let params = vec![token.into()];
134
135		let mut builder = self.invoke_function(Self::COMPOUND, params).await?;
136		builder.set_signers(vec![AccountSigner::called_by_entry(account).unwrap().into()]);
137
138		Ok(builder)
139	}
140
141	/// Gets the current APY for a specific token
142	///
143	/// # Arguments
144	///
145	/// * `token` - The script hash of the token to get the APY for
146	///
147	/// # Returns
148	///
149	/// The APY as a floating-point percentage
150	pub async fn get_apy(&self, token: &ScriptHash) -> Result<f64, ContractError> {
151		let result = self.call_function_returning_int(Self::GET_APY, vec![token.into()]).await?;
152		// Convert the integer result to a floating-point percentage (assuming APY is stored as an integer with a fixed decimal point)
153		Ok(result as f64 / 100.0) // Assuming 2 decimal places for percentage
154	}
155}
156
157#[async_trait]
158impl<'a, P: JsonRpcProvider> SmartContractTrait<'a> for NeoCompoundContract<'a, P> {
159	type P = P;
160
161	fn script_hash(&self) -> H160 {
162		self.script_hash
163	}
164
165	fn set_script_hash(&mut self, script_hash: H160) {
166		self.script_hash = script_hash;
167	}
168
169	fn provider(&self) -> Option<&RpcClient<P>> {
170		self.provider
171	}
172}