From 4e8fccc8cd37cee055242a0e041c0e012ed3e40c Mon Sep 17 00:00:00 2001 From: findolor Date: Thu, 13 Feb 2025 13:58:54 +0100 Subject: [PATCH 1/6] sort vaults in order detail query --- crates/js_api/src/subgraph/order.rs | 55 ++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/crates/js_api/src/subgraph/order.rs b/crates/js_api/src/subgraph/order.rs index 1c23ffffb..b3949596a 100644 --- a/crates/js_api/src/subgraph/order.rs +++ b/crates/js_api/src/subgraph/order.rs @@ -1,12 +1,23 @@ +use std::collections::{HashMap, HashSet}; + use cynic::Id; -use rain_orderbook_bindings::wasm_traits::prelude::*; +use rain_orderbook_bindings::{impl_all_wasm_traits, wasm_traits::prelude::*}; use rain_orderbook_common::types::OrderDetailExtended; use rain_orderbook_subgraph_client::{ - types::common::{Order, OrdersListFilterArgs}, + types::common::{Order, OrdersListFilterArgs, Vault}, MultiOrderbookSubgraphClient, MultiSubgraphArgs, OrderbookSubgraphClient, OrderbookSubgraphClientError, PaginationArgs, }; use reqwest::Url; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Clone, Tsify)] +pub struct OrderWithSortedVaults { + #[tsify(type = "OrderSubgraph")] + pub order: Order, + pub vaults: HashMap>, +} +impl_all_wasm_traits!(OrderWithSortedVaults); /// Internal function to fetch a single order /// Returns the Order struct @@ -29,12 +40,48 @@ pub async fn get_orders( Ok(to_value(&orders)?) } +fn sort_vaults(order: &Order) -> HashMap> { + let mut sorted_vaults: HashMap> = HashMap::new(); + + let input_ids: HashSet<_> = order.inputs.iter().map(|v| &v.vault_id).collect(); + let output_ids: HashSet<_> = order.outputs.iter().map(|v| &v.vault_id).collect(); + + sorted_vaults.insert("inputs".to_string(), Vec::new()); + sorted_vaults.insert("outputs".to_string(), Vec::new()); + sorted_vaults.insert("inputs_outputs".to_string(), Vec::new()); + + for vault in &order.inputs { + if output_ids.contains(&vault.vault_id) { + sorted_vaults + .get_mut("inputs_outputs") + .unwrap() + .push(vault.clone()); + } else { + sorted_vaults.get_mut("inputs").unwrap().push(vault.clone()); + } + } + + for vault in &order.outputs { + if !input_ids.contains(&vault.vault_id) { + sorted_vaults + .get_mut("outputs") + .unwrap() + .push(vault.clone()); + } + } + + sorted_vaults +} + /// Fetch a single order -/// Returns the Order struct +/// Returns the Order struct with sorted vaults #[wasm_bindgen(js_name = "getOrder")] pub async fn get_order(url: &str, id: &str) -> Result { let order = get_sg_order(url, id).await?; - Ok(to_value(&order)?) + Ok(to_value(&OrderWithSortedVaults { + order: order.clone(), + vaults: sort_vaults(&order), + })?) } /// Extend an order to include Rainlang string From 49cbde7a167543fc95e85778e143be1ac8788015 Mon Sep 17 00:00:00 2001 From: findolor Date: Thu, 13 Feb 2025 13:58:58 +0100 Subject: [PATCH 2/6] update tests --- packages/orderbook/test/js_api/order.test.ts | 134 +++++++++++++++++-- 1 file changed, 125 insertions(+), 9 deletions(-) diff --git a/packages/orderbook/test/js_api/order.test.ts b/packages/orderbook/test/js_api/order.test.ts index 037efe826..3536d0f34 100644 --- a/packages/orderbook/test/js_api/order.test.ts +++ b/packages/orderbook/test/js_api/order.test.ts @@ -1,7 +1,13 @@ import assert from 'assert'; import { getLocal } from 'mockttp'; import { describe, it, beforeEach, afterEach } from 'vitest'; -import { Order, OrderPerformance, OrderWithSubgraphName, Trade } from '../../dist/types/js_api.js'; +import { + OrderPerformance, + OrderSubgraph, + OrderWithSortedVaults, + OrderWithSubgraphName, + Trade +} from '../../dist/types/js_api.js'; import { getOrders, getOrder, @@ -19,7 +25,7 @@ const order1 = { owner: '0x0000000000000000000000000000000000000000', outputs: [ { - id: '0x0000000000000000000000000000000000000000', + id: '0x0000000000000000000000000000000000000001', token: { id: '0x0000000000000000000000000000000000000000', address: '0x0000000000000000000000000000000000000000', @@ -28,7 +34,7 @@ const order1 = { decimals: '0' }, balance: '0', - vaultId: '0', + vaultId: '0x1', owner: '0x0000000000000000000000000000000000000000', ordersAsOutput: [], ordersAsInput: [], @@ -40,7 +46,7 @@ const order1 = { ], inputs: [ { - id: '0x0000000000000000000000000000000000000000', + id: '0x0000000000000000000000000000000000000002', token: { id: '0x0000000000000000000000000000000000000000', address: '0x0000000000000000000000000000000000000000', @@ -49,7 +55,7 @@ const order1 = { decimals: '0' }, balance: '0', - vaultId: '0', + vaultId: '0x2', owner: '0x0000000000000000000000000000000000000000', ordersAsOutput: [], ordersAsInput: [], @@ -77,7 +83,7 @@ const order1 = { }, trades: [] }; -const order2: Order = { +const order2 = { id: 'order2', orderBytes: '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', @@ -142,7 +148,7 @@ const order2: Order = { id: '0x0000000000000000000000000000000000000000' }, trades: [] -} as unknown as Order; +} as unknown as OrderSubgraph; export const order3 = { id: 'order1', @@ -372,8 +378,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Order', async function ( await mockServer.forPost('/sg1').thenReply(200, JSON.stringify({ data: { order: order1 } })); try { - const result: Order = await getOrder(mockServer.url + '/sg1', order1.id); - assert.equal(result.id, order1.id); + const result: OrderWithSortedVaults = await getOrder(mockServer.url + '/sg1', order1.id); + assert.equal(result.order.id, order1.id); } catch (e) { console.log(e); assert.fail('expected to resolve, but failed' + (e instanceof Error ? e.message : String(e))); @@ -617,4 +623,114 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Order', async function ( mockServer.stop(); assert.deepEqual(result, expected); }); + + it('should return vaults sorted by inputs, outputs and inputs and outputs', async () => { + const inputs = [ + { + id: '0x0000000000000000000000000000000000000001', + token: { + id: '0x0000000000000000000000000000000000000000', + address: '0x0000000000000000000000000000000000000000', + name: 'T2', + symbol: 'T2', + decimals: '0' + }, + balance: '0', + vaultId: '0x1', + owner: '0x0000000000000000000000000000000000000000', + ordersAsOutput: [], + ordersAsInput: [], + balanceChanges: [], + orderbook: { + id: '0x0000000000000000000000000000000000000000' + } + }, + { + id: '0x0000000000000000000000000000000000000003', + token: { + id: '0x0000000000000000000000000000000000000000', + address: '0x0000000000000000000000000000000000000000', + name: 'T3', + symbol: 'T3', + decimals: '0' + }, + balance: '0', + vaultId: '0x3', + owner: '0x0000000000000000000000000000000000000000', + ordersAsOutput: [], + ordersAsInput: [], + balanceChanges: [], + orderbook: { + id: '0x0000000000000000000000000000000000000000' + } + } + ]; + const outputs = [ + { + id: '0x0000000000000000000000000000000000000002', + token: { + id: '0x0000000000000000000000000000000000000000', + address: '0x0000000000000000000000000000000000000000', + name: 'T2', + symbol: 'T2', + decimals: '0' + }, + balance: '0', + vaultId: '0x2', + owner: '0x0000000000000000000000000000000000000000', + ordersAsOutput: [], + ordersAsInput: [], + balanceChanges: [], + orderbook: { + id: '0x0000000000000000000000000000000000000000' + } + }, + { + id: '0x0000000000000000000000000000000000000003', + token: { + id: '0x0000000000000000000000000000000000000000', + address: '0x0000000000000000000000000000000000000000', + name: 'T3', + symbol: 'T3', + decimals: '0' + }, + balance: '0', + vaultId: '0x3', + owner: '0x0000000000000000000000000000000000000000', + ordersAsOutput: [], + ordersAsInput: [], + balanceChanges: [], + orderbook: { + id: '0x0000000000000000000000000000000000000000' + } + } + ]; + await mockServer + .forPost('/sg1') + .once() + .thenReply(200, JSON.stringify({ data: { order: { ...order1, inputs, outputs } } })); + + try { + const result: OrderWithSortedVaults = await getOrder(mockServer.url + '/sg1', order1.id); + + const inputs = result.vaults.get('inputs'); + const outputs = result.vaults.get('outputs'); + const inputsOutputs = result.vaults.get('inputs_outputs'); + + if (!inputs || !outputs || !inputsOutputs) { + assert.fail('inputs, outputs or inputsOutputs should not be null'); + } + + assert.equal(inputs.length, 1); + assert.equal(outputs.length, 1); + assert.equal(inputsOutputs.length, 1); + + assert.equal(inputs[0].vaultId, '0x1'); + assert.equal(outputs[0].vaultId, '0x2'); + assert.equal(inputsOutputs[0].vaultId, '0x3'); + } catch (e) { + console.log(e); + assert.fail('expected to resolve, but failed' + (e instanceof Error ? e.message : String(e))); + } + }); }); From 394f5ee0f329bcc0b1d1371c453f1b1e22c52cac Mon Sep 17 00:00:00 2001 From: findolor Date: Thu, 13 Feb 2025 15:10:14 +0100 Subject: [PATCH 3/6] fix sorting logic --- crates/js_api/src/subgraph/order.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/js_api/src/subgraph/order.rs b/crates/js_api/src/subgraph/order.rs index b3949596a..edfb80060 100644 --- a/crates/js_api/src/subgraph/order.rs +++ b/crates/js_api/src/subgraph/order.rs @@ -43,15 +43,15 @@ pub async fn get_orders( fn sort_vaults(order: &Order) -> HashMap> { let mut sorted_vaults: HashMap> = HashMap::new(); - let input_ids: HashSet<_> = order.inputs.iter().map(|v| &v.vault_id).collect(); - let output_ids: HashSet<_> = order.outputs.iter().map(|v| &v.vault_id).collect(); + let input_ids: HashSet<_> = order.inputs.iter().map(|v| &v.id).collect(); + let output_ids: HashSet<_> = order.outputs.iter().map(|v| &v.id).collect(); sorted_vaults.insert("inputs".to_string(), Vec::new()); sorted_vaults.insert("outputs".to_string(), Vec::new()); sorted_vaults.insert("inputs_outputs".to_string(), Vec::new()); for vault in &order.inputs { - if output_ids.contains(&vault.vault_id) { + if output_ids.contains(&vault.id) { sorted_vaults .get_mut("inputs_outputs") .unwrap() @@ -62,7 +62,7 @@ fn sort_vaults(order: &Order) -> HashMap> { } for vault in &order.outputs { - if !input_ids.contains(&vault.vault_id) { + if !input_ids.contains(&vault.id) { sorted_vaults .get_mut("outputs") .unwrap() From d7350a32c08dd4ae4b75a7da0c39f8efa2e5e408 Mon Sep 17 00:00:00 2001 From: findolor Date: Thu, 13 Feb 2025 15:10:22 +0100 Subject: [PATCH 4/6] update tests --- packages/orderbook/test/js_api/order.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/orderbook/test/js_api/order.test.ts b/packages/orderbook/test/js_api/order.test.ts index 3536d0f34..dda2643c0 100644 --- a/packages/orderbook/test/js_api/order.test.ts +++ b/packages/orderbook/test/js_api/order.test.ts @@ -725,9 +725,9 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Order', async function ( assert.equal(outputs.length, 1); assert.equal(inputsOutputs.length, 1); - assert.equal(inputs[0].vaultId, '0x1'); - assert.equal(outputs[0].vaultId, '0x2'); - assert.equal(inputsOutputs[0].vaultId, '0x3'); + assert.equal(inputs[0].id, '0x0000000000000000000000000000000000000001'); + assert.equal(outputs[0].id, '0x0000000000000000000000000000000000000002'); + assert.equal(inputsOutputs[0].id, '0x0000000000000000000000000000000000000003'); } catch (e) { console.log(e); assert.fail('expected to resolve, but failed' + (e instanceof Error ? e.message : String(e))); From 5d541c1af4bddfb0684b68e7b2f85859954c7431 Mon Sep 17 00:00:00 2001 From: findolor Date: Thu, 13 Feb 2025 15:10:42 +0100 Subject: [PATCH 5/6] refactor the vaults component in order detail --- .../lib/components/detail/OrderDetail.svelte | 104 ++++++++---------- 1 file changed, 48 insertions(+), 56 deletions(-) diff --git a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte index 890c3aeaf..d5241bd0c 100644 --- a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte @@ -12,7 +12,12 @@ import { QKEY_ORDER } from '../../queries/keys'; import CodeMirrorRainlang from '../CodeMirrorRainlang.svelte'; import { queryClient } from '../../stores/queryClient'; - import { getOrder, type OrderSubgraph, type Vault } from '@rainlanguage/orderbook/js_api'; + import { + getOrder, + type OrderSubgraph, + type OrderWithSortedVaults, + type Vault + } from '@rainlanguage/orderbook/js_api'; import { createQuery } from '@tanstack/svelte-query'; import { Button, TabItem, Tabs } from 'flowbite-svelte'; import { onDestroy } from 'svelte'; @@ -66,7 +71,7 @@ let codeMirrorDisabled = true; let codeMirrorStyles = {}; - $: orderDetailQuery = createQuery({ + $: orderDetailQuery = createQuery({ queryKey: [id, QKEY_ORDER + id], queryFn: () => getOrder(subgraphUrl, id), enabled: !!subgraphUrl @@ -96,16 +101,16 @@ >
Order - +
- - {#if data && $signerAddress === data.owner && data.active && handleOrderRemoveModal && $wagmiConfig && chainId && orderbookAddress} + + {#if data && $signerAddress === data.order.owner && data.order.active && handleOrderRemoveModal && $wagmiConfig && chainId && orderbookAddress}