Skip to content

Commit

Permalink
port OrderDetail
Browse files Browse the repository at this point in the history
  • Loading branch information
hardingjam committed Dec 4, 2024
1 parent 580dc31 commit c25b824
Show file tree
Hide file tree
Showing 16 changed files with 243 additions and 91 deletions.
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"svelte.enable-ts-plugin": true,

"rust-analyzer.linkedProjects": ["./Cargo.toml", "tauri-app/src-tauri/Cargo.toml"],
// Don't push this
"rust-analyzer.cargo.target": "wasm32-unknown-unknown",

"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
Expand Down
33 changes: 24 additions & 9 deletions crates/js_api/src/subgraph/order.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
use cynic::Id;
use rain_orderbook_bindings::wasm_traits::prelude::*;
use rain_orderbook_common::types::OrderDetailExtended;
use rain_orderbook_subgraph_client::{
types::common::OrdersListFilterArgs, MultiOrderbookSubgraphClient, MultiSubgraphArgs,
OrderbookSubgraphClient, OrderbookSubgraphClientError, PaginationArgs
types::common::{Order, OrdersListFilterArgs},
MultiOrderbookSubgraphClient, MultiSubgraphArgs, OrderbookSubgraphClient,
OrderbookSubgraphClientError, PaginationArgs,
};
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> {
let client = OrderbookSubgraphClient::new(Url::parse(url)?);
let order = client.order_detail(Id::new(id)).await?;
Ok(order)
}

/// Fetch all orders from multiple subgraphs
/// Returns a list of OrderWithSubgraphName structs
#[wasm_bindgen(js_name = "getOrders")]
Expand All @@ -23,11 +33,20 @@ pub async fn get_orders(
/// Returns the Order struct
#[wasm_bindgen(js_name = "getOrder")]
pub async fn get_order(url: &str, id: &str) -> Result<JsValue, OrderbookSubgraphClientError> {
let client = OrderbookSubgraphClient::new(Url::parse(url)?);
let order = client.order_detail(Id::new(id)).await?;
let order = get_sg_order(url, id).await?;
Ok(to_value(&order)?)
}

/// Extend an order to include Rainlang string
/// Returns an OrderDetailExtended struct
#[wasm_bindgen(js_name = "extendOrder")]
pub fn order_detail_extended(order: Order) -> Result<JsValue, OrderbookSubgraphClientError> {
let order_extended: OrderDetailExtended = order
.try_into()
.map_err(|_| OrderbookSubgraphClientError::OrderDetailExtendError)?;
Ok(to_value(&order_extended)?)
}

/// Fetch trades for a specific order
/// Returns a list of Trade structs
#[wasm_bindgen(js_name = "getOrderTradesList")]
Expand Down Expand Up @@ -94,11 +113,7 @@ pub async fn order_vaults_volume(
) -> Result<JsValue, OrderbookSubgraphClientError> {
let client = OrderbookSubgraphClient::new(Url::parse(url)?);
let volumes = client
.order_vaults_volume(
Id::new(order_id),
start_timestamp,
end_timestamp,
)
.order_vaults_volume(Id::new(order_id), start_timestamp, end_timestamp)
.await?;
Ok(to_value(&volumes)?)
}
2 changes: 2 additions & 0 deletions crates/subgraph/src/orderbook_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub enum OrderbookSubgraphClientError {
#[cfg(target_family = "wasm")]
#[error(transparent)]
SerdeWasmBindgenError(#[from] serde_wasm_bindgen::Error),
#[error("Failed to extend the order detail")]
OrderDetailExtendError,
}

#[cfg(target_family = "wasm")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
<script lang="ts">
import CodeMirror from 'svelte-codemirror-editor';
import { RainlangLR } from 'codemirror-rainlang';
import type { Order } from '@rainlanguage/orderbook/js_api';
import { extendOrder } from '@rainlanguage/orderbook/js_api';
export let value: string;
export let order: Order | undefined = undefined;
export let rainlangText: string = '';
export let disabled = false;
export let styles = {};
export let codeMirrorTheme;
$: value = order ? extendOrder(order).rainlang : rainlangText;
</script>

<CodeMirror
Expand Down
145 changes: 145 additions & 0 deletions packages/ui-components/src/lib/components/detail/OrderDetail.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<script lang="ts">
import Hash, { HashType } from '../Hash.svelte';
import BadgeActive from '../BadgeActive.svelte';
import OrderTradesChart from '../charts/OrderTradesChart.svelte';
import OrderTradesListTable from '../tables/OrderTradesListTable.svelte';
import TanstackOrderQuote from './TanstackOrderQuote.svelte';
import TanstackPageContentDetail from './TanstackPageContentDetail.svelte';
import CardProperty from '../CardProperty.svelte';
import { formatTimestampSecondsAsLocal } from '../../utils/time';
import ButtonVaultLink from '../ButtonVaultLink.svelte';
import OrderVaultsVolTable from '../tables/OrderVaultsVolTable.svelte';
import { QKEY_ORDER } from '../../queries/keys';
import CodeMirrorRainlang from '../CodeMirrorRainlang.svelte';
import { getOrder, type Order } from '@rainlanguage/orderbook/js_api';
import { createQuery } from '@tanstack/svelte-query';
import { Button, TabItem, Tabs } from 'flowbite-svelte';
export let walletAddressMatchesOrBlank: ((address: string) => boolean) | undefined = undefined;
export let handleOrderRemoveModal: ((order: Order, refetch: () => void) => void) | undefined =
undefined;
export let handleQuoteDebugModal:
| ((order: Order, rpcUrl: string, orderbookAddress: string) => void)
| undefined = undefined;
export let handleDebugTradeModal: ((hash: string, rpcUrl: string) => void) | undefined =
undefined;
export let colorTheme;
export let codeMirrorTheme;
export let lightweightChartsTheme;
export let orderbookAddress: string | undefined = undefined;
export let id: string;
export let rpcUrl: string;
export let subgraphUrl: string;
$: orderDetailQuery = createQuery<Order>({
queryKey: [id, QKEY_ORDER + id],
queryFn: () => getOrder(subgraphUrl, id || ''),
enabled: !!subgraphUrl && !!id
});
</script>

<h1>Order Trades</h1>

<TanstackPageContentDetail query={orderDetailQuery} emptyMessage="Order not found">
<svelte:fragment slot="top" let:data={order}>
<div class="flex gap-x-4 text-3xl font-medium dark:text-white">
<div class="flex gap-x-2">
<span class="font-light">Order</span>
<Hash shorten value={order.orderHash} />
</div>
<BadgeActive active={order.active} large />
</div>
{#if order && walletAddressMatchesOrBlank?.(order.owner) && order.active && handleOrderRemoveModal}
<Button
color="dark"
on:click={() => handleOrderRemoveModal(order, $orderDetailQuery.refetch)}
disabled={!handleOrderRemoveModal}
>
Remove
</Button>
{/if}
</svelte:fragment>
<svelte:fragment slot="card" let:data={order}>
<div class="flex flex-col gap-y-6">
<CardProperty>
<svelte:fragment slot="key">Orderbook</svelte:fragment>
<svelte:fragment slot="value">
<Hash type={HashType.Identifier} shorten={false} value={order.orderbook.id} />
</svelte:fragment>
</CardProperty>

<CardProperty>
<svelte:fragment slot="key">Owner</svelte:fragment>
<svelte:fragment slot="value">
<Hash type={HashType.Wallet} shorten={false} value={order.owner} />
</svelte:fragment>
</CardProperty>

<CardProperty>
<svelte:fragment slot="key">Created</svelte:fragment>
<svelte:fragment slot="value">
{formatTimestampSecondsAsLocal(BigInt(order.timestampAdded))}
</svelte:fragment>
</CardProperty>

<CardProperty>
<svelte:fragment slot="key">Input vaults</svelte:fragment>
<svelte:fragment slot="value">
<div class="mb-2 flex justify-end">
<span>Balance</span>
</div>
<div class="space-y-2">
{#each order.inputs || [] as t}
<ButtonVaultLink tokenVault={t} />
{/each}
</div>
</svelte:fragment>
</CardProperty>

<CardProperty>
<svelte:fragment slot="key">Output vaults</svelte:fragment>
<svelte:fragment slot="value">
<div class="mb-2 flex justify-end">
<span>Balance</span>
</div>
<div class="space-y-2">
{#each order.outputs || [] as t}
<ButtonVaultLink tokenVault={t} />
{/each}
</div>
</svelte:fragment>
</CardProperty>
</div>
</svelte:fragment>
<svelte:fragment slot="chart">
<OrderTradesChart {id} {subgraphUrl} {colorTheme} {lightweightChartsTheme} />
</svelte:fragment>
<svelte:fragment slot="below" let:data={order}>
<TanstackOrderQuote
{id}
{order}
{rpcUrl}
orderbookAddress={orderbookAddress || ''}
{handleQuoteDebugModal}
/>
<Tabs
style="underline"
contentClass="mt-4"
defaultClass="flex flex-wrap space-x-2 rtl:space-x-reverse mt-4"
>
<TabItem open title="Rainlang source">
<div class="mb-8 overflow-hidden rounded-lg border dark:border-none">
<CodeMirrorRainlang disabled={true} {order} {codeMirrorTheme} />
</div>
</TabItem>
<TabItem title="Trades">
<OrderTradesListTable {id} {subgraphUrl} {rpcUrl} {handleDebugTradeModal} />
</TabItem>
<TabItem title="Volume">
<OrderVaultsVolTable {id} {subgraphUrl} />
</TabItem>
</Tabs>
</svelte:fragment>
</TanstackPageContentDetail>
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script lang="ts" generics="T">
import type { Order } from '@rainlanguage/orderbook/js_api';
import Refresh from '../icon/Refresh.svelte';
import EditableSpan from '../EditableSpan.svelte';
import { getOrderQuote } from '@rainlanguage/orderbook/quote';
import type { Order as OrderPackage } from '@rainlanguage/orderbook/quote';
import type { Order as OrderTypeshare } from '../../typeshare/subgraphTypes';
import { QKEY_ORDER_QUOTE } from '../../queries/keys';
import { formatUnits, hexToNumber, isHex } from 'viem';
import { createQuery } from '@tanstack/svelte-query';
Expand All @@ -19,19 +19,19 @@
import { BugOutline, PauseSolid, PlaySolid } from 'flowbite-svelte-icons';
export let id: string;
export let order: OrderTypeshare;
export let order: Order;
export let rpcUrl: string;
export let orderbookAddress: string = '';
export let handleQuoteDebugModal:
| undefined
| ((
order: OrderTypeshare,
order: Order,
rpcUrl: string,
orderbookAddress: string,
inputIndex: number,
outputIndex: number,
pairName: string,
blockNumber: number
blockNumber?: number
) => void) = undefined;
let enabled = true;
Expand All @@ -42,13 +42,13 @@
$: orderQuoteQuery = createQuery({
queryKey: [QKEY_ORDER_QUOTE + id],
queryFn: () => getOrderQuote([order as OrderPackage], rpcUrl),
queryFn: () => getOrderQuote([order], rpcUrl),
enabled: !!id && enabled,
refetchInterval: 10000
});
let blockNumber: number | undefined;
$: orderModalArg = order as OrderTypeshare;
$: orderModalArg = order;
</script>

<div class="mt-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
// eslint-disable-next-line no-undef
let data: NonNullable<T>;
$: console.log('query', $query);
$: if ($query.data) {
console.log('data', $query.data);
data = $query.data;
}
</script>
Expand Down
1 change: 1 addition & 0 deletions packages/ui-components/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export { default as TanstackPageContentDetail } from './components/detail/Tansta
export { default as TanstackOrderQuote } from './components/detail/TanstackOrderQuote.svelte';
export { default as EditableSpan } from './components/EditableSpan.svelte';
export { default as OrderVaultsVolTable } from './components/tables/OrderVaultsVolTable.svelte';
export { default as OrderDetail } from './components/detail/OrderDetail.svelte';

//Types
export type { AppStoresInterface } from './types/appStores.ts';
Expand Down
39 changes: 4 additions & 35 deletions packages/webapp/src/routes/orders/[network]-[id]/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,43 +1,12 @@
<script lang="ts">
import { OrderDetail } from '@rainlanguage/ui-components';
import { page } from '$app/stores';
import {
OrderTradesChart,
OrderTradesListTable,
colorTheme,
lightweightChartsTheme,
TanstackOrderQuote,
QKEY_ORDER,
OrderVaultsVolTable,
CodeMirrorRainlang,
lightCodeMirrorTheme
} from '@rainlanguage/ui-components';
import { getOrder } from '@rainlanguage/orderbook/js_api';
import { createQuery } from '@tanstack/svelte-query';
const { colorTheme, codeMirrorTheme, lightweightChartsTheme } = $page.data.stores;
const { id, network } = $page.params;
const { settings } = $page.data.stores;
const subgraphUrl = $settings.subgraphs[network];
const rpcUrl = $settings.networks[network]?.rpc;
$: orderDetailQuery = createQuery({
queryKey: [id, QKEY_ORDER + id],
queryFn: () => getOrder(subgraphUrl, id || ''),
enabled: !!subgraphUrl && !!id
});
$: order = $orderDetailQuery.data;
$: console.log('ORDER', order, 'RAINLANG', order.rainlang);
</script>

<h1>Order Trades</h1>
{#if $orderDetailQuery.data}
<CodeMirrorRainlang
disabled={true}
value={order.rainlang}
codeMirrorTheme={lightCodeMirrorTheme}
/>

<TanstackOrderQuote {id} {order} {rpcUrl} />
<OrderTradesChart {id} {subgraphUrl} {colorTheme} {lightweightChartsTheme} />
<OrderTradesListTable {id} {subgraphUrl} {rpcUrl} />
<OrderVaultsVolTable {id} {subgraphUrl} />
{/if}
<OrderDetail {id} {subgraphUrl} {rpcUrl} {colorTheme} {codeMirrorTheme} {lightweightChartsTheme} />
Loading

0 comments on commit c25b824

Please sign in to comment.