Skip to content

Commit

Permalink
Merge pull request #128 from rainlanguage/2024-01-23-gui-chainid
Browse files Browse the repository at this point in the history
2024 01 23 gui chainid
  • Loading branch information
thedavidmeister authored Jan 25, 2024
2 parents 802e9e3 + c735fc6 commit 3f33dd5
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 17 deletions.
3 changes: 2 additions & 1 deletion crates/cli/src/commands/vault/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ pub type Deposit = CliTransactionCommandArgs<CliDepositArgs>;

impl Execute for Deposit {
async fn execute(&self) -> Result<()> {
let tx_args: TransactionArgs = self.transaction_args.clone().into();
let mut tx_args: TransactionArgs = self.transaction_args.clone().into();
tx_args.try_fill_chain_id().await?;
let deposit_args: DepositArgs = self.cmd_args.clone().into();

println!("----- Transaction (1/2): Approve ERC20 token spend -----");
Expand Down
3 changes: 2 additions & 1 deletion crates/cli/src/commands/vault/withdraw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ pub type Withdraw = CliTransactionCommandArgs<CliWithdrawArgs>;

impl Execute for Withdraw {
async fn execute(&self) -> Result<()> {
let tx_args: TransactionArgs = self.transaction_args.clone().into();
let mut tx_args: TransactionArgs = self.transaction_args.clone().into();
tx_args.try_fill_chain_id().await?;
let withdraw_args: WithdrawArgs = self.cmd_args.clone().into();

println!("----- Withdraw tokens from Vault -----");
Expand Down
4 changes: 2 additions & 2 deletions crates/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ pub enum Orderbook {
Order(Order),

#[command(subcommand)]
Vault(Vault),
Vault(Box<Vault>),
}

impl Orderbook {
pub async fn execute(self) -> Result<()> {
match self {
Orderbook::Order(order) => order.execute().await,
Orderbook::Vault(vault) => vault.execute().await,
Orderbook::Vault(vault) => (*vault).execute().await,
}
}
}
2 changes: 1 addition & 1 deletion crates/cli/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct CliTransactionArgs {
pub derivation_index: Option<usize>,

#[arg(short, long, help = "Chain ID of the network")]
pub chain_id: u64,
pub chain_id: Option<u64>,

#[arg(short, long, help = "RPC URL")]
pub rpc_url: String,
Expand Down
4 changes: 2 additions & 2 deletions crates/common/src/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl DepositArgs {
.clone()
.try_into_ledger_client()
.await
.map_err(WritableTransactionExecuteError::LedgerClient)?;
.map_err(WritableTransactionExecuteError::TransactionArgs)?;

let ledger_address = ethers_address_to_alloy(ledger_client.client.address());
let approve_call = self.clone().into_approve_call(ledger_address);
Expand All @@ -90,7 +90,7 @@ impl DepositArgs {
.clone()
.try_into_ledger_client()
.await
.map_err(WritableTransactionExecuteError::LedgerClient)?;
.map_err(WritableTransactionExecuteError::TransactionArgs)?;

let deposit_call: depositCall = self.clone().try_into().map_err(|_| {
WritableTransactionExecuteError::InvalidArgs(
Expand Down
42 changes: 37 additions & 5 deletions crates/common/src/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use alloy_ethers_typecast::{
client::{LedgerClient, LedgerClientError},
transaction::{
WriteContractParameters, WriteContractParametersBuilder,
WriteContractParametersBuilderError,
ReadableClientError, ReadableClientHttp, WriteContractParameters,
WriteContractParametersBuilder, WriteContractParametersBuilderError,
},
};
use alloy_primitives::{hex::FromHexError, Address, U256};
Expand All @@ -15,13 +15,21 @@ pub enum TransactionArgsError {
ParseOrderbookAddress(#[from] FromHexError),
#[error("Build parameters error: {0}")]
BuildParameters(#[from] WriteContractParametersBuilderError),
#[error("Parse Chain ID U256 to u64 error")]
ChainIdParse,
#[error("Chain ID is required, but set to None")]
ChainIdNone,
#[error("Readable client error: {0}")]
ReadableClient(#[from] ReadableClientError),
#[error("Ledger Client Error {0}")]
LedgerClient(#[from] LedgerClientError),
}

#[derive(Clone)]
pub struct TransactionArgs {
pub orderbook_address: String,
pub derivation_index: Option<usize>,
pub chain_id: u64,
pub chain_id: Option<u64>,
pub rpc_url: String,
pub max_priority_fee_per_gas: Option<U256>,
pub max_fee_per_gas: Option<U256>,
Expand All @@ -46,7 +54,31 @@ impl TransactionArgs {
.map_err(TransactionArgsError::BuildParameters)
}

pub async fn try_into_ledger_client(self) -> Result<LedgerClient, LedgerClientError> {
LedgerClient::new(self.derivation_index, self.chain_id, self.rpc_url.clone()).await
pub async fn try_fill_chain_id(&mut self) -> Result<(), TransactionArgsError> {
if self.chain_id.is_none() {
let chain_id = ReadableClientHttp::new_from_url(self.rpc_url.clone())
.map_err(TransactionArgsError::ReadableClient)?
.get_chainid()
.await
.map_err(TransactionArgsError::ReadableClient)?;
let chain_id_u64: u64 = chain_id
.try_into()
.map_err(|_| TransactionArgsError::ChainIdParse)?;

self.chain_id = Some(chain_id_u64);
}

Ok(())
}

pub async fn try_into_ledger_client(self) -> Result<LedgerClient, TransactionArgsError> {
match self.chain_id {
Some(chain_id) => {
LedgerClient::new(self.derivation_index, chain_id, self.rpc_url.clone())
.await
.map_err(TransactionArgsError::LedgerClient)
}
None => Err(TransactionArgsError::ChainIdNone),
}
}
}
2 changes: 1 addition & 1 deletion crates/common/src/withdraw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl WithdrawArgs {
.clone()
.try_into_ledger_client()
.await
.map_err(WritableTransactionExecuteError::LedgerClient)?;
.map_err(WritableTransactionExecuteError::TransactionArgs)?;

let withdraw_call: withdrawCall = self.clone().try_into().map_err(|_| {
WritableTransactionExecuteError::InvalidArgs(
Expand Down
16 changes: 16 additions & 0 deletions tauri-app/src-tauri/src/commands/chain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use alloy_ethers_typecast::transaction::ReadableClientHttp;

#[tauri::command]
pub async fn get_chainid(rpc_url: String) -> Result<u64, String> {
let chain_id = ReadableClientHttp::new_from_url(rpc_url)
.map_err(|_| String::from("Failed to connect to RPC URL"))?
.get_chainid()
.await
.map_err(|_| String::from("Failed to get Chain ID"))?;

let chain_id_u64: u64 = chain_id
.try_into()
.map_err(|_| String::from("Failed to convert Chain ID to u64"))?;

Ok(chain_id_u64)
}
1 change: 1 addition & 0 deletions tauri-app/src-tauri/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod chain;
pub mod vault;
pub mod wallet;
4 changes: 3 additions & 1 deletion tauri-app/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

mod commands;
use commands::chain::get_chainid;
use commands::vault::{vault_detail, vaults_list};
use commands::wallet::get_address_from_ledger;

Expand All @@ -10,7 +11,8 @@ fn main() {
.invoke_handler(tauri::generate_handler![
vaults_list,
vault_detail,
get_address_from_ledger
get_address_from_ledger,
get_chainid
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
Expand Down
29 changes: 29 additions & 0 deletions tauri-app/src/lib/stores/chain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import find from 'lodash/find';
import { derived, writable, get } from 'svelte/store';
import * as chains from 'viem/chains'
import { rpcUrl } from './settings';
import { toasts } from './toasts';
import { ToastMessageType } from '$lib/typeshare/toast';
import { invoke } from '@tauri-apps/api';

export const chainId = writable(parseInt(localStorage.getItem("settings.chainId") || '1'))

chainId.subscribe(value => {
localStorage.setItem("settings.chainId", (value || 0).toString());
});

export async function updateChainId() {
try {
const val: number = await invoke('get_chainid', {rpcUrl: get(rpcUrl)});
chainId.set(val);
} catch(e) {
toasts.add({
message_type: ToastMessageType.Error,
text: e as string
});
}
}

export const activeChain = derived(chainId, (val) => {
return find(Object.values(chains), (c) => c.id === val);
})
9 changes: 8 additions & 1 deletion tauri-app/src/lib/stores/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { isUrlValid } from '$lib/utils/url';
import { writable, derived } from 'svelte/store';
import every from 'lodash/every';
import { isAddress } from 'viem';
import { updateChainId } from '$lib/stores/chain';

export const rpcUrl = writable(localStorage.getItem("settings.rpcUrl") || '');
export const subgraphUrl = writable(localStorage.getItem("settings.subgraphUrl") || '');
Expand Down Expand Up @@ -30,6 +31,12 @@ export const isSubgraphUrlValid = derived(subgraphUrl, (val) => isUrlValid(val))
export const isOrderbookAddressValid = derived(orderbookAddress, (val) => isAddress(val));
export const isWalletAddressValid = derived(walletAddress, (val) => isAddress(val));

isRpcUrlValid.subscribe(value => {
if(value) {
updateChainId();
}
})

export const isSettingsDefined = derived([rpcUrl, subgraphUrl, orderbookAddress], (vals) => every(vals.map((v) => v && v.trim().length > 0)));
export const isSettingsValid = derived([isRpcUrlValid, isSubgraphUrlValid], (vals) => every(vals));
export const isSettingsDefinedAndValid = derived([isSettingsDefined, isSettingsValid], (vals) => every(vals));
export const isSettingsDefinedAndValid = derived([isSettingsDefined, isSettingsValid], (vals) => every(vals));
12 changes: 10 additions & 2 deletions tauri-app/src/routes/settings/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
isRpcUrlValid,
isSubgraphUrlValid,
isOrderbookAddressValid,
isWalletAddressValid,
isSettingsDefinedAndValid,
} from '$lib/stores/settings';
import { activeChain } from '$lib/stores/chain';
import InputLedgerWallet from '$lib/InputLedgerWallet.svelte';
</script>

Expand Down Expand Up @@ -40,10 +40,18 @@
/>
for a reliable hosted RPC service provider. Or visit
<BadgeExternalLink href="https://chainlist.org/" text="Chainlist" /> for find other publically
available RPC providerss.
available RPC providers.
</Helper>
</div>

{#if $isRpcUrlValid && $activeChain}
<div class="mb-8">
<Label class="bold mb-2 block text-xl">Chain</Label>
<Input label="RPC URL" name="chainId" required bind:value={$activeChain.name} disabled />
<Helper class="mt-2 text-sm">Automatically determined by your RPC URL.</Helper>
</div>
{/if}

<div class="mb-8">
<Label class="bold mb-2 block text-xl">Subgraph URL</Label>
<Input label="Subgraph URL" name="subgraphUrl" required bind:value={$subgraphUrl} />
Expand Down

0 comments on commit 3f33dd5

Please sign in to comment.