Skip to content

Commit

Permalink
✨ Add Approve
Browse files Browse the repository at this point in the history
  • Loading branch information
BertrandD committed Nov 29, 2024
1 parent 53809cb commit edd292c
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 13 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 10 additions & 7 deletions crates/server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct ApproveRequest {
username: String,
password: String,
spender: String,
token: String,
amount: u128,
}

Expand All @@ -142,6 +143,7 @@ async fn approve(Json(payload): Json<ApproveRequest>) -> Result<impl IntoRespons
payload.username.into(),
payload.password,
payload.spender,
payload.token.into(),
payload.amount,
)
.await?;
Expand Down Expand Up @@ -338,6 +340,7 @@ async fn do_approve(
identity: Identity,
password: String,
spender: String,
token: ContractName,
amount: u128,
) -> Result<TxHash, AppError> {
let node_url = env::var("NODE_URL").unwrap_or_else(|_| "http://localhost:4321".to_string());
Expand All @@ -358,16 +361,16 @@ async fn do_approve(

let blobs = vec![
identity_cf.as_blob(ContractName("hydentity".to_owned())),
hyllar_cf.as_blob(ContractName("hyllar".to_owned()), None, None),
hyllar_cf.as_blob(token.clone(), None, None),
];

let hydentity_proof = contract::run(
&client,
&"hydentity".into(),
HYDENTITY_BIN,
|token: hydentity::Hydentity| -> ContractInput<hydentity::Hydentity> {
|state: hydentity::Hydentity| -> ContractInput<hydentity::Hydentity> {
ContractInput::<Hydentity> {
initial_state: token,
initial_state: state,
identity: identity.clone(),
tx_hash: "".into(),
private_blob: BlobData(password.clone()),
Expand All @@ -379,11 +382,11 @@ async fn do_approve(
.await?;
let transfer_proof = contract::run(
&client,
&"hyllar".into(),
&token.clone(),
HYLLAR_BIN,
|token: hyllar::HyllarToken| -> ContractInput<hyllar::HyllarToken> {
|state: hyllar::HyllarToken| -> ContractInput<hyllar::HyllarToken> {
ContractInput::<HyllarToken> {
initial_state: token,
initial_state: state,
identity: identity.clone(),
tx_hash: "".into(),
private_blob: BlobData(vec![]),
Expand All @@ -402,7 +405,7 @@ async fn do_approve(
hydentity_proof,
)
.await?;
contract::send_proof(&client, tx_hash.clone(), "hyllar".into(), transfer_proof).await?;
contract::send_proof(&client, tx_hash.clone(), token, transfer_proof).await?;

Ok(tx_hash)
}
Expand Down
10 changes: 9 additions & 1 deletion crates/ui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub enum Tab {
Faucet,
Transfer,
Swap,
Approve,
}

pub enum Msg {
Expand All @@ -22,7 +23,7 @@ impl Component for App {

fn create(_ctx: &Context<Self>) -> Self {
Self {
active_tab: Tab::Faucet, // Onglet par défaut
active_tab: Tab::Approve, // Onglet par défaut
}
}

Expand All @@ -41,6 +42,7 @@ impl Component for App {
Tab::Faucet => html! { <crate::faucet::Faucet /> },
Tab::Transfer => html! { <crate::transfer::Transfer /> },
Tab::Swap => html! { <crate::swap::Swap /> },
Tab::Approve => html! { <crate::approve::Approve /> },
};

html! {
Expand All @@ -64,6 +66,12 @@ impl Component for App {
>
{"Transfer"}
</button>
<button
class={if self.active_tab == Tab::Approve { "tab active" } else { "tab" }}
onclick={ctx.link().callback(|_| Msg::SwitchTab(Tab::Approve))}
>
{"Approve"}
</button>
<button
class={if self.active_tab == Tab::Swap { "tab active" } else { "tab" }}
onclick={ctx.link().callback(|_| Msg::SwitchTab(Tab::Swap))}
Expand Down
161 changes: 161 additions & 0 deletions crates/ui/src/approve.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
use hyllar::{HyllarToken, HyllarTokenContract};
use sdk::erc20::ERC20;
use yew::prelude::*;

use crate::{
client::WalletClient, contracts::spawn_fetch_state, selector::TokenSelector,
text_input::TextInput,
};

pub enum Msg {
SetUserName(String),
SetPassword(String),
SetSpender(String),
SetAmount(String),
SetProgress(String),
ContractStateUpdate(HyllarToken),
TokenChanged(String),
Transfer,
}

#[derive(Default)]
pub struct Approve {
username: String,
password: String,
selected_token: String,
spender: String,
progress: String,
amount: String,
state: Option<HyllarTokenContract>,
}

impl Approve {
fn approve(
ctx: &Context<Self>,
name: String,
password: String,
spender: String,
token: String,
amount: u128,
) {
ctx.link()
.send_message(Msg::SetProgress("Approving...".to_string()));

ctx.link().send_future(async move {
match WalletClient::default()
.approve(name.clone(), password, spender, token, amount)
.await
{
Ok(_) => Msg::SetProgress(format!("Approve successful for user {}", name)),
Err(e) => Msg::SetProgress(format!("{}", e)),
}
});
}
fn display_name(user: &str) -> String {
format!("{}.hydentity", user)
}
}

impl Component for Approve {
type Message = Msg;
type Properties = ();

fn create(ctx: &Context<Self>) -> Self {
let state_cb = ctx.link().callback(Msg::ContractStateUpdate);
spawn_fetch_state(state_cb);
Self {
amount: "0".to_owned(),
selected_token: "hyllar".to_owned(),
..Self::default()
}
}

fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::SetUserName(next_username) => self.username = next_username,
Msg::SetSpender(next_username) => self.spender = next_username,
Msg::SetPassword(next_password) => self.password = next_password,
Msg::SetAmount(next_amount) => self.amount = next_amount,
Msg::SetProgress(progress) => self.progress = progress,
Msg::Transfer => Self::approve(
ctx,
Self::display_name(&self.username),
self.password.clone(),
self.spender.clone(),
self.selected_token.clone(),
self.amount.parse::<u128>().unwrap_or(0),
),
Msg::ContractStateUpdate(state) => {
self.state = Some(HyllarTokenContract::init(
state,
sdk::Identity(self.username.clone()),
))
}
Msg::TokenChanged(token) => {
self.selected_token = token;
}
};
true
}

fn view(&self, ctx: &Context<Self>) -> Html {
let display_balance = match &self.state {
Some(token) => {
let balance = token
.balance_of(&Self::display_name(&self.username))
.unwrap_or(0);
html! {
<span>{format!("Balance: {}", balance)}</span>
}
}
None => html! {
<span></span>
},
};

html! {
<div>
<div>
<TokenSelector
on_token_change={ctx.link().callback(Msg::TokenChanged)}
/>

<div>
{"Username:"}
</div>
<div>
<TextInput suffix={".hydentity"} on_change={ctx.link().callback(Msg::SetUserName)} value={self.username.clone()} />
</div>
<div>
{"Password:"}
</div>
<div>
<TextInput on_change={ctx.link().callback(Msg::SetPassword)} value={self.password.clone()} />
</div>
<div>
{"Spender:"}
</div>
<div>
<TextInput on_change={ctx.link().callback(Msg::SetSpender)} value={self.spender.clone()} />
</div>
<div>
{"Amount:"}
</div>
<div>
<TextInput on_change={ctx.link().callback(Msg::SetAmount)} value={self.amount.clone()} />
</div>
<div>{display_balance}</div>
</div>
<div class="readout">
<button onclick={ctx.link().callback(|_| Msg::Transfer)} class="submit-button">
{"Transfer "} {self.amount.clone()} {" "} { self.selected_token.clone() } {" from "} {Self::display_name(&self.username)} {" to "} {Self::display_name(&self.spender)}

</button>
</div>
<div class="progress">
{self.progress.clone()}
</div>
</div>
}
}
}
36 changes: 36 additions & 0 deletions crates/ui/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,42 @@ impl WalletClient {
Ok(())
}

pub async fn approve(
&self,
username: String,
password: String,
spender: String,
token: String,
amount: u128,
) -> Result<()> {
#[derive(Serialize)]
struct ApproveRequest {
username: String,
password: String,
spender: String,
token: String,
amount: u128,
}

let request = ApproveRequest {
username,
password,
spender,
token,
amount,
};

let url = format!("{}/approve", self.base_url);
let response = self.http_client.post(&url).json(&request).send().await?;

if !response.status().is_success() {
let error_text = response.text().await?;
bail!("Approve request failed: {}", error_text);
}

Ok(())
}

pub async fn swap(
&self,
username: String,
Expand Down
1 change: 1 addition & 0 deletions crates/ui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
mod text_input;

mod app;
mod approve;
mod client;
mod contracts;
mod faucet;
Expand Down

0 comments on commit edd292c

Please sign in to comment.