Skip to content

Commit

Permalink
Merge pull request #1202 from rainlanguage/2025-01-22-deposit-withdra…
Browse files Browse the repository at this point in the history
…w-calldatas

Adding wasm bindings for vault deposit/withdraw calldata generation
  • Loading branch information
hardyjosh authored Feb 4, 2025
2 parents 769a491 + 0bbd51c commit 2cdbc2a
Show file tree
Hide file tree
Showing 13 changed files with 338 additions and 25 deletions.
3 changes: 1 addition & 2 deletions crates/common/src/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,10 @@ impl DepositArgs {
pub async fn get_approve_calldata(
&self,
transaction_args: TransactionArgs,
current_allowance: U256,
) -> Result<Vec<u8>, WritableTransactionExecuteError> {
let approve_call = approveCall {
spender: transaction_args.orderbook_address,
amount: self.amount - current_allowance,
amount: self.amount,
};
Ok(approve_call.abi_encode())
}
Expand Down
4 changes: 1 addition & 3 deletions crates/common/src/dotrain_order/calldata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ impl DotrainOrder {
.await?;

if allowance < deposit_amount {
let approve_call = deposit_args
.get_approve_calldata(transaction_args, allowance)
.await?;
let approve_call = deposit_args.get_approve_calldata(transaction_args).await?;
calldatas.push(ApprovalCalldata {
token: output_token.address,
calldata: Bytes::copy_from_slice(&approve_call),
Expand Down
4 changes: 4 additions & 0 deletions crates/js_api/src/gui/order_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ impl_all_wasm_traits!(ApprovalCalldataResult);
pub struct DepositCalldataResult(Vec<Bytes>);
impl_all_wasm_traits!(DepositCalldataResult);

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)]
pub struct WithdrawCalldataResult(Vec<Bytes>);
impl_all_wasm_traits!(WithdrawCalldataResult);

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)]
pub struct AddOrderCalldataResult(Bytes);
impl_all_wasm_traits!(AddOrderCalldataResult);
Expand Down
38 changes: 38 additions & 0 deletions crates/js_api/src/subgraph/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,40 @@
use alloy::{hex::FromHexError, primitives::ruint::ParseError};
use rain_orderbook_common::{
deposit::DepositError, dotrain_order::calldata::DotrainOrderCalldataError,
transaction::WritableTransactionExecuteError,
};
use rain_orderbook_subgraph_client::OrderbookSubgraphClientError;
use thiserror::Error;
use wasm_bindgen::{JsError, JsValue};

pub mod order;
pub mod vault;

#[derive(Error, Debug)]
pub enum SubgraphError {
#[error("Invalid amount")]
InvalidAmount,
#[error("Invalid output index")]
InvalidOutputIndex,
#[error("Invalid input index")]
InvalidInputIndex,
#[error(transparent)]
OrderbookSubgraphClientError(#[from] OrderbookSubgraphClientError),
#[error(transparent)]
DotrainOrderCalldataError(#[from] DotrainOrderCalldataError),
#[error(transparent)]
WritableTransactionExecuteError(#[from] WritableTransactionExecuteError),
#[error(transparent)]
ParseError(#[from] ParseError),
#[error(transparent)]
FromHexError(#[from] FromHexError),
#[error(transparent)]
SerdeWasmBindgenError(#[from] serde_wasm_bindgen::Error),
#[error(transparent)]
DepositError(#[from] DepositError),
}
impl From<SubgraphError> for JsValue {
fn from(value: SubgraphError) -> Self {
JsError::new(&value.to_string()).into()
}
}
2 changes: 1 addition & 1 deletion crates/js_api/src/subgraph/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use reqwest::Url;

/// Internal function to fetch a single order
/// Returns the Order struct
async fn get_sg_order(url: &str, id: &str) -> Result<Order, OrderbookSubgraphClientError> {
pub async fn get_sg_order(url: &str, id: &str) -> Result<Order, OrderbookSubgraphClientError> {
let client = OrderbookSubgraphClient::new(Url::parse(url)?);
let order = client.order_detail(Id::new(id)).await?;
Ok(order)
Expand Down
123 changes: 122 additions & 1 deletion crates/js_api/src/subgraph/vault.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use super::SubgraphError;
use alloy::primitives::{Address, Bytes, U256};
use cynic::Id;
use rain_orderbook_bindings::wasm_traits::prelude::*;
use rain_orderbook_subgraph_client::types::common::VaultsListFilterArgs;
use rain_orderbook_common::deposit::DepositArgs;
use rain_orderbook_common::transaction::TransactionArgs;
use rain_orderbook_common::withdraw::WithdrawArgs;
use rain_orderbook_subgraph_client::types::common::{Order, Vault, VaultsListFilterArgs};
use rain_orderbook_subgraph_client::{
MultiOrderbookSubgraphClient, MultiSubgraphArgs, OrderbookSubgraphClient,
OrderbookSubgraphClientError, PaginationArgs,
};
use reqwest::Url;
use std::str::FromStr;

/// Fetch all vaults from multiple subgraphs
/// Returns a list of VaultWithSubgraphName structs
Expand Down Expand Up @@ -43,3 +49,118 @@ pub async fn get_vault_balance_changes(
.await?;
Ok(to_value(&changes)?)
}

/// Get deposit calldata for a vault
/// Returns a string of the calldata
#[wasm_bindgen(js_name = "getVaultDepositCalldata")]
pub async fn get_vault_deposit_calldata(
vault: &Vault,
deposit_amount: &str,
) -> Result<JsValue, SubgraphError> {
let deposit_amount = validate_amount(deposit_amount)?;

let deposit_args = DepositArgs {
token: Address::from_str(&vault.token.address.0)?,
vault_id: U256::from_str(&vault.vault_id.0)?,
amount: deposit_amount,
};

Ok(to_value(&Bytes::copy_from_slice(
&deposit_args.get_deposit_calldata().await?,
))?)
}

/// Get withdraw calldata for a vault
#[wasm_bindgen(js_name = "getVaultWithdrawCalldata")]
pub async fn get_vault_withdraw_calldata(
vault: &Vault,
withdraw_amount: &str,
) -> Result<JsValue, SubgraphError> {
let withdraw_amount = validate_amount(withdraw_amount)?;

Ok(to_value(&Bytes::copy_from_slice(
&WithdrawArgs {
token: Address::from_str(&vault.token.address.0)?,
vault_id: U256::from_str(&vault.vault_id.0)?,
target_amount: withdraw_amount,
}
.get_withdraw_calldata()
.await?,
))?)
}

#[wasm_bindgen(js_name = "getVaultApprovalCalldata")]
pub async fn get_vault_approval_calldata(
rpc_url: &str,
vault: &Vault,
deposit_amount: &str,
) -> Result<JsValue, SubgraphError> {
let deposit_amount = validate_amount(deposit_amount)?;
let owner = Address::from_str(&vault.owner.0)?;

let (deposit_args, transaction_args) =
get_deposit_and_transaction_args(rpc_url, &vault, deposit_amount)?;

let allowance = deposit_args
.read_allowance(owner, transaction_args.clone())
.await?;
if allowance > deposit_amount {
return Err(SubgraphError::InvalidAmount);
}

Ok(to_value(&Bytes::copy_from_slice(
&deposit_args.get_approve_calldata(transaction_args).await?,
))?)
}

#[wasm_bindgen(js_name = "checkVaultAllowance")]
pub async fn check_vault_allowance(rpc_url: &str, vault: &Vault) -> Result<JsValue, SubgraphError> {
let (deposit_args, transaction_args) =
get_deposit_and_transaction_args(rpc_url, &vault, U256::ZERO)?;

Ok(to_value(
&deposit_args
.read_allowance(Address::from_str(&vault.owner.0)?, transaction_args.clone())
.await?,
)?)
}

pub fn validate_amount(amount: &str) -> Result<U256, SubgraphError> {
let amount = U256::from_str(&amount)?;
if amount == U256::ZERO {
return Err(SubgraphError::InvalidAmount);
}
Ok(amount)
}

pub fn validate_io_index(order: &Order, is_input: bool, index: u8) -> Result<usize, SubgraphError> {
let index = index as usize;
if is_input {
if order.inputs.len() <= index {
return Err(SubgraphError::InvalidInputIndex);
}
} else {
if order.outputs.len() <= index {
return Err(SubgraphError::InvalidOutputIndex);
}
}
Ok(index)
}

pub fn get_deposit_and_transaction_args(
rpc_url: &str,
vault: &Vault,
amount: U256,
) -> Result<(DepositArgs, TransactionArgs), SubgraphError> {
let deposit_args = DepositArgs {
token: Address::from_str(&vault.token.address.0)?,
vault_id: U256::from_str(&vault.vault_id.0)?,
amount,
};
let transaction_args = TransactionArgs {
orderbook_address: Address::from_str(&vault.orderbook.id.0)?,
rpc_url: rpc_url.to_string(),
..Default::default()
};
Ok((deposit_args, transaction_args))
}
2 changes: 1 addition & 1 deletion packages/orderbook/test/js_api/gui.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ ${dotrain}`;
// 5000 - 1000 = 4000 * 10^18
assert.equal(
approvalCalldatas[0].calldata,
'0x095ea7b3000000000000000000000000c95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a60000000000000000000000000000000000000000000000d8d726b7177a800000'
'0x095ea7b3000000000000000000000000c95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a600000000000000000000000000000000000000000000010f0cf064dd59200000'
);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/orderbook/test/js_api/order.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const order2: Order = {
trades: []
} as unknown as Order;

const order3 = {
export const order3 = {
id: 'order1',
orderBytes:
'0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
Expand Down
Loading

0 comments on commit 2cdbc2a

Please sign in to comment.