Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getTransaction wasm function, to poll for new txs #1260

Merged
merged 30 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3e288c4
Add getTransaction
hardingjam Feb 10, 2025
8bd686d
getting the tc and polling
hardingjam Feb 11, 2025
03b8e83
add deploymemt
hardingjam Feb 11, 2025
f0645e8
add wait for tx
hardingjam Feb 11, 2025
9c73aec
add tests
hardingjam Feb 11, 2025
914a903
Merge branch 'main' into 02/10/25-Add-getTransaction-wasm-fn
hardingjam Feb 11, 2025
72ea287
test not passing
hardingjam Feb 12, 2025
30af707
format test
hardingjam Feb 12, 2025
391df8e
invalidate queries on tx success
hardingjam Feb 13, 2025
affd03d
WIP live update
hardingjam Feb 13, 2025
8690ff3
wip, trying to get chart updating automatically without re-rendering
hardingjam Feb 13, 2025
9b49a8e
Merge branch 'main' into 02/10/25-Add-getTransaction-wasm-fn
hardingjam Feb 13, 2025
a654c20
invalidate queries and show toast
hardingjam Feb 13, 2025
8fec5eb
remove logs
hardingjam Feb 13, 2025
9d1a141
update reactively on transaction success
hardingjam Feb 13, 2025
fff8ee3
add refetch on success
hardingjam Feb 13, 2025
6c62abc
update chart test
hardingjam Feb 13, 2025
314e0ac
mock getNetworkKey
hardingjam Feb 13, 2025
3ed5517
test returning network
hardingjam Feb 13, 2025
7278c03
Merge branch 'main' into 02/10/25-Add-getTransaction-wasm-fn
hardingjam Feb 14, 2025
981d68e
add
hardingjam Feb 14, 2025
35753c6
tx test not working
hardingjam Feb 14, 2025
16906ad
logging status
hardingjam Feb 14, 2025
16d4354
rm unused logs
hardingjam Feb 14, 2025
a140ab0
timer fix
hardyjosh Feb 14, 2025
44057c9
rm logs
hardingjam Feb 14, 2025
56b72e7
lint
hardingjam Feb 14, 2025
e105801
Merge branch 'main' into 02/10/25-Add-getTransaction-wasm-fn
hardingjam Feb 14, 2025
5f34657
rm only
hardingjam Feb 14, 2025
8b7dec3
Merge branch 'main' into 02/10/25-Add-getTransaction-wasm-fn
hardingjam Feb 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions crates/js_api/src/gui/select_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ impl DotrainOrderGui {
Ok(())
}

#[wasm_bindgen(js_name = "getNetworkKey")]
pub fn get_network_key(&self) -> Result<String, GuiError> {
let order_key = Deployment::parse_order_key(
self.dotrain_order.dotrain_yaml().documents,
&self.selected_deployment,
)?;
let network_key =
Order::parse_network_key(self.dotrain_order.dotrain_yaml().documents, &order_key)?;
Ok(network_key)
}

#[wasm_bindgen(js_name = "saveSelectToken")]
pub async fn save_select_token(
&mut self,
Expand Down
1 change: 1 addition & 0 deletions crates/js_api/src/subgraph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use thiserror::Error;
use wasm_bindgen::{JsError, JsValue};

pub mod order;
pub mod transaction;
pub mod vault;

#[derive(Error, Debug)]
Expand Down
16 changes: 16 additions & 0 deletions crates/js_api/src/subgraph/transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use cynic::Id;
use rain_orderbook_bindings::wasm_traits::prelude::*;
use rain_orderbook_subgraph_client::{OrderbookSubgraphClient, OrderbookSubgraphClientError};
use reqwest::Url;

/// Internal function to fetch a single transaction
/// Returns the Transaction struct
#[wasm_bindgen(js_name = "getTransaction")]
pub async fn get_transaction(
url: &str,
tx_hash: &str,
) -> Result<JsValue, OrderbookSubgraphClientError> {
let client = OrderbookSubgraphClient::new(Url::parse(url)?);
let transaction = client.transaction_detail(Id::new(tx_hash)).await?;
Ok(to_value(&transaction)?)
}
16 changes: 16 additions & 0 deletions crates/subgraph/src/orderbook_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::types::order::{
OrdersListQuery,
};
use crate::types::order_trade::{OrderTradeDetailQuery, OrderTradesListQuery};
use crate::types::transaction::TransactionDetailQuery;
use crate::types::vault::{VaultDetailQuery, VaultsListQuery};
use crate::vault_balance_changes_query::VaultBalanceChangesListPageQueryClient;
use cynic::Id;
Expand All @@ -25,6 +26,8 @@ pub enum OrderbookSubgraphClientError {
CynicClientError(#[from] CynicClientError),
#[error("Subgraph query returned no data")]
Empty,
#[error("Request timed out")]
RequestTimedOut,
#[error(transparent)]
PaginationClientError(#[from] PaginationClientError),
#[error(transparent)]
Expand Down Expand Up @@ -379,4 +382,17 @@ impl OrderbookSubgraphClient {
}
Ok(all_pages_merged)
}

pub async fn transaction_detail(
&self,
id: Id,
) -> Result<Transaction, OrderbookSubgraphClientError> {
let data = self
.query::<TransactionDetailQuery, IdQueryVariables>(IdQueryVariables { id: &id })
.await?;
let transaction = data
.transaction
.ok_or(OrderbookSubgraphClientError::Empty)?;
Ok(transaction)
}
}
1 change: 1 addition & 0 deletions crates/subgraph/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod impls;
pub mod order;
pub mod order_detail_traits;
pub mod order_trade;
pub mod transaction;
pub mod vault;

pub use cynic::Id;
12 changes: 12 additions & 0 deletions crates/subgraph/src/types/transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use super::common::*;
use crate::schema;
use typeshare::typeshare;

#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Query", variables = "IdQueryVariables")]
#[typeshare]
pub struct TransactionDetailQuery {
#[arguments(id: $id)]
#[typeshare(typescript(type = "TransactionSubgraph"))]
pub transaction: Option<Transaction>,
}
5 changes: 5 additions & 0 deletions packages/orderbook/test/js_api/gui.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1386,5 +1386,10 @@ ${dotrainWithoutVaultIds}`;
"Missing required field 'tokens' in root"
);
});

it('should get network key', async () => {
const networkKey = gui.getNetworkKey();
assert.equal(networkKey, 'some-network');
});
});
});
31 changes: 31 additions & 0 deletions packages/orderbook/test/js_api/transaction.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import assert from 'assert';
import { getLocal } from 'mockttp';
import { describe, it, beforeEach, afterEach } from 'vitest';
import { Transaction } from '../../dist/types/js_api.js';
import { getTransaction } from '../../dist/cjs/js_api.js';

const transaction1 = {
id: 'tx1',
from: '0x1',
blockNumber: '1',
timestamp: '1'
} as unknown as Transaction;

describe('Rain Orderbook JS API Package Bindgen Tests - Order', async function () {
const mockServer = getLocal();
beforeEach(() => mockServer.start(8090));
afterEach(() => mockServer.stop());

it('should fetch a single transaction', async () => {
await mockServer
.forPost('/sg1')
.thenReply(200, JSON.stringify({ data: { transaction: transaction1 } }));

try {
const result: Transaction = await getTransaction(mockServer.url + '/sg1', transaction1.id);
assert.equal(result.id, transaction1.id);
} catch (e) {
assert.fail('expected to resolve, but failed' + (e instanceof Error ? e.message : String(e)));
}
});
});
18 changes: 14 additions & 4 deletions packages/ui-components/src/__tests__/DeploymentSteps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DotrainOrderGui, type Scenario } from '@rainlanguage/orderbook/js_api';
import type { ComponentProps } from 'svelte';
import { writable } from 'svelte/store';
import type { AppKit } from '@reown/appkit';
import type { ConfigSource } from '../lib/typeshare/config';
const { mockWagmiConfigStore, mockConnectedStore } = await vi.hoisted(
() => import('../lib/__mocks__/stores')
);
Expand Down Expand Up @@ -622,7 +623,8 @@ describe('DeploymentSteps', () => {
it('shows deployment details when provided', async () => {
(DotrainOrderGui.chooseDeployment as Mock).mockResolvedValue({
getSelectTokens: () => [],
getTokenInfo: vi.fn()
getTokenInfo: vi.fn(),
getNetworkKey: vi.fn()
});

render(DeploymentSteps, {
Expand All @@ -633,6 +635,7 @@ describe('DeploymentSteps', () => {
wagmiConnected: mockConnectedStore,
appKitModal: writable({} as AppKit),
handleDeployModal: vi.fn(),
settings: writable({} as ConfigSource),
handleUpdateGuiState: vi.fn()
}
});
Expand All @@ -646,7 +649,8 @@ describe('DeploymentSteps', () => {
const mockSelectTokens = ['token1', 'token2'];
(DotrainOrderGui.chooseDeployment as Mock).mockResolvedValue({
getSelectTokens: () => mockSelectTokens,
getTokenInfo: vi.fn()
getTokenInfo: vi.fn(),
getNetworkKey: vi.fn()
});

render(DeploymentSteps, {
Expand All @@ -657,6 +661,7 @@ describe('DeploymentSteps', () => {
wagmiConnected: mockConnectedStore,
appKitModal: writable({} as AppKit),
handleDeployModal: vi.fn(),
settings: writable({} as ConfigSource),
handleUpdateGuiState: vi.fn()
}
});
Expand All @@ -682,6 +687,7 @@ describe('DeploymentSteps', () => {
wagmiConnected: mockConnectedStore,
appKitModal: writable({} as AppKit),
handleDeployModal: vi.fn(),
settings: writable({} as ConfigSource),
handleUpdateGuiState: vi.fn()
}
});
Expand All @@ -706,7 +712,8 @@ describe('DeploymentSteps', () => {
deposits: []
}),
getAllFieldDefinitions: () => [],
getTokenInfo: vi.fn()
getTokenInfo: vi.fn(),
getNetworkKey: vi.fn()
});

render(DeploymentSteps, {
Expand All @@ -717,6 +724,7 @@ describe('DeploymentSteps', () => {
wagmiConnected: mockConnectedStore,
appKitModal: writable({} as AppKit),
handleDeployModal: vi.fn(),
settings: writable({} as ConfigSource),
handleUpdateGuiState: vi.fn()
}
});
Expand All @@ -739,7 +747,8 @@ describe('DeploymentSteps', () => {
deposits: []
}),
getAllFieldDefinitions: () => [],
getTokenInfo: vi.fn()
getTokenInfo: vi.fn(),
getNetworkKey: vi.fn()
});

render(DeploymentSteps, {
Expand All @@ -750,6 +759,7 @@ describe('DeploymentSteps', () => {
wagmiConnected: mockConnectedStore,
appKitModal: writable({} as AppKit),
handleDeployModal: vi.fn(),
settings: writable({} as ConfigSource),
handleUpdateGuiState: vi.fn()
}
});
Expand Down
36 changes: 25 additions & 11 deletions packages/ui-components/src/__tests__/LightweightChart.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ const setDataMock = vi.fn();
const applyOptionsMock = vi.fn();
const setVisibleRangeMock = vi.fn();
const removeMock = vi.fn();
const updateMock = vi.fn();

vi.mock('lightweight-charts', async (importOriginal) => ({
...((await importOriginal()) as object),
createChart: vi.fn(() => ({
addLineSeries: vi.fn(() => ({
setData: setDataMock
setData: setDataMock,
update: updateMock
})),
remove: removeMock,
applyOptions: applyOptionsMock,
Expand Down Expand Up @@ -96,23 +98,18 @@ test('renders with data correctly', async () => {
});
});

test('updates data correctly when props change', async () => {
test('updates data correctly when new data points are added', async () => {
const title = 'test title';
const emptyMessage = 'empty message';
const loading = false;
const priceSymbol = '$';
const createSeries = (chart: IChartApi) => chart.addLineSeries();

const initialData: { value: number; time: UTCTimestamp; color?: string }[] = [
const initialData = [
{ value: 10, time: 1529899200 as UTCTimestamp },
{ value: 20, time: 1529899300 as UTCTimestamp }
];

const newData: { value: number; time: UTCTimestamp; color?: string }[] = [
{ value: 15, time: 1529900000 as UTCTimestamp },
{ value: 25, time: 1529900300 as UTCTimestamp }
];

const { component } = render(LightweightChart, {
title,
emptyMessage,
Expand All @@ -123,15 +120,32 @@ test('updates data correctly when props change', async () => {
lightweightChartsTheme: readable({ test: 'test' })
});

// First render should call setData with initial data
await waitFor(() => {
expect(setDataMock).toHaveBeenCalledWith(initialData);
});

// Update data prop
await act(() => component.$set({ data: newData }));
// Add new data points
const newDataPoints = [
...initialData,
{ value: 30, time: 1529899400 as UTCTimestamp },
{ value: 40, time: 1529899500 as UTCTimestamp }
];

// Update with new data that includes additional points
await act(() => component.$set({ data: newDataPoints }));

// Should call update for each new point
await waitFor(() => {
expect(setDataMock).toHaveBeenCalledWith(newData);
expect(updateMock).toHaveBeenCalledTimes(2);
expect(updateMock).toHaveBeenCalledWith({
value: 30,
time: 1529899400 as UTCTimestamp
});
expect(updateMock).toHaveBeenCalledWith({
value: 40,
time: 1529899500 as UTCTimestamp
});
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
rpcUrl="https://example.com"
query={orderDetailQuery}
handleDepositOrWithdrawModal={() => {}}
{subgraphUrl}
/>
</svelte:fragment>
</ButtonVaultLink>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import VaultBalanceChart from '../lib/components/charts/VaultBalanceChart.svelte
import type { Vault } from '@rainlanguage/orderbook/js_api';
import { getVaultBalanceChanges } from '@rainlanguage/orderbook/js_api';
import { writable } from 'svelte/store';
import type { ComponentProps } from 'svelte';

type VaultBalanceChartProps = ComponentProps<VaultBalanceChart>;

vi.mock('@rainlanguage/orderbook/js_api', () => ({
getVaultBalanceChanges: vi.fn()
Expand Down Expand Up @@ -42,8 +45,9 @@ test('calls getVaultBalanceChanges with correct arguments', async () => {
props: {
vault: mockVault,
subgraphUrl: 'https://example.com',
lightweightChartsTheme: writable({})
},
lightweightChartsTheme: writable({}),
id: 'vault1'
} as VaultBalanceChartProps,
context: new Map([['$$_queryClient', queryClient]])
});

Expand Down
Loading