Skip to content

Commit

Permalink
Merge pull request #1078 from rainlanguage/Port-vault-queries
Browse files Browse the repository at this point in the history
Port vault queries and components
  • Loading branch information
hardyjosh authored Jan 2, 2025
2 parents a078a2c + c15b67c commit e597349
Show file tree
Hide file tree
Showing 34 changed files with 884 additions and 1,389 deletions.
15 changes: 15 additions & 0 deletions crates/js_api/src/subgraph/vault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,18 @@ pub async fn get_vault(url: &str, id: &str) -> Result<JsValue, OrderbookSubgraph
let vault = client.vault_detail(Id::new(id)).await?;
Ok(to_value(&vault)?)
}

/// Fetch balance changes for a vault
/// Returns a list of VaultBalanceChangeUnwrapped structs
#[wasm_bindgen(js_name = "getVaultBalanceChanges")]
pub async fn get_vault_balance_changes(
url: &str,
id: &str,
pagination_args: PaginationArgs,
) -> Result<JsValue, OrderbookSubgraphClientError> {
let client = OrderbookSubgraphClient::new(Url::parse(url)?);
let changes = client
.vault_balance_changes_list(Id::new(id), pagination_args)
.await?;
Ok(to_value(&changes)?)
}
4 changes: 3 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 67 additions & 2 deletions packages/orderbook/test/js_api/vault.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import assert from 'assert';
import { getLocal } from 'mockttp';
import { describe, it, beforeEach, afterEach } from 'vitest';
import { Vault, VaultWithSubgraphName } from '../../dist/types/js_api.js';
import { getVaults, getVault } from '../../dist/cjs/js_api.js';
import { Vault, VaultWithSubgraphName, Deposit } from '../../dist/types/js_api.js';
import { getVaults, getVault, getVaultBalanceChanges } from '../../dist/cjs/js_api.js';
import { VaultBalanceChange } from '../../dist/types/quote.js';

const vault1: Vault = {
id: 'vault1',
Expand Down Expand Up @@ -89,4 +90,68 @@ describe('Rain Orderbook JS API Package Bindgen Vault Tests', async function ()
assert.fail('expected to resolve, but failed');
}
});

it('should fetch vault balance changes', async () => {
const mockVaultBalanceChanges = [
{
"__typename": "Deposit",
"amount": "5000000000000000000",
"newVaultBalance": "5000000000000000000",
"oldVaultBalance": "0",
"vault": {
"id": "0x166aeed725f0f3ef9fe62f2a9054035756d55e5560b17afa1ae439e9cd362902",
"vaultId": "1",
"token": {
"id": "0x1d80c49bbbcd1c0911346656b529df9e5c2f783d",
"address": "0x1d80c49bbbcd1c0911346656b529df9e5c2f783d",
"name": "Wrapped Flare",
"symbol": "WFLR",
"decimals": "18"
}
},
"timestamp": "1734054063",
"transaction": {
"id": "0x85857b5c6d0b277f9e971b6b45cab98720f90b8f24d65df020776d675b71fc22",
"from": "0x7177b9d00bb5dbcaaf069cc63190902763783b09",
"blockNumber": "34407047",
"timestamp": "1734054063"
},
"orderbook": {
"id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d"
}
}
];

await mockServer
.forPost('/sg3')
.once()
.thenReply(200, JSON.stringify({ data: { vaultBalanceChanges: mockVaultBalanceChanges } }));

try {
const result: Deposit[] = await getVaultBalanceChanges(
mockServer.url + '/sg3',
vault1.id,
{ page: 1, pageSize: 1 }
);
assert.equal(result[0].__typename, 'Deposit');
assert.equal(result[0].amount, '5000000000000000000');
assert.equal(result[0].newVaultBalance, '5000000000000000000');
assert.equal(result[0].oldVaultBalance, '0');

} catch (e) {
console.log(e);
assert.fail('expected to resolve, but failed');
}
});

it('should handle errors when fetching vault balance changes', async () => {
await mockServer.forPost('/sg1').thenReply(500, 'Internal Server Error');

try {
await getVaultBalanceChanges(mockServer.url + '/sg1', 'vault1', { page: 1, pageSize: 10 });
assert.fail('expected to reject, but resolved');
} catch (e) {
assert.ok(e);
}
});
});
3 changes: 2 additions & 1 deletion packages/ui-components/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export default ts.config(
},
rules: {
'no-console': process.env.NODE_ENV === 'production' || process.env.CI ? 'error' : 'off',
'no-trailing-spaces': 'error'
'no-trailing-spaces': 'error',
'@typescript-eslint/ban-ts-comment': 'off'
}
},
{
Expand Down
4 changes: 3 additions & 1 deletion packages/ui-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
"types": "./dist/index.d.ts",
"type": "module",
"dependencies": {
"flowbite-svelte": "^0.44.21"
"flowbite-svelte": "^0.44.21",
"@sveltejs/kit": "^2.0.0",
"svelte": "^4.2.7"
}
}
5 changes: 2 additions & 3 deletions packages/ui-components/src/__tests__/ButtonVaultLink.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import ButtonVaultLink from '../lib/components/ButtonVaultLink.svelte';
import * as navigation from '$app/navigation';
import { userEvent } from '@testing-library/user-event';
import type { Vault } from '@rainlanguage/orderbook/js_api';

// Mock the $app/navigation module
vi.mock('$app/navigation', () => ({
goto: vi.fn()
Expand All @@ -20,12 +19,12 @@ describe('ButtonVaultLink', () => {
symbol: 'TEST',
decimals: '18'
}
};
} as unknown as Vault;

it('should navigate to vault details page when clicked', async () => {
render(ButtonVaultLink, {
props: {
tokenVault: mockVault as unknown as Vault
tokenVault: mockVault
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ const mockTradeOrdersList: Trade[] = [
id: '0x00'
}
}
];
] as unknown as Trade[];

vi.mock('@tanstack/svelte-query');

Expand Down
122 changes: 122 additions & 0 deletions packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { render, screen, waitFor } from '@testing-library/svelte';
import { test, vi } from 'vitest';
import { expect } from '../lib/test/matchers';
import { QueryClient } from '@tanstack/svelte-query';
import VaultBalanceChangesTable from '../lib/components/tables/VaultBalanceChangesTable.svelte';
import type { VaultBalanceChange } from '@rainlanguage/orderbook/js_api';
import { formatTimestampSecondsAsLocal } from '../lib/utils/time';

vi.mock('@rainlanguage/orderbook/js_api', () => ({
getVaultBalanceChanges: vi.fn()
}));

test('renders the vault list table with correct data', async () => {
const queryClient = new QueryClient();

const mockVaultBalanceChanges: VaultBalanceChange[] = [
{
__typename: 'Withdrawal',
amount: '1000',
oldVaultBalance: '5000',
newVaultBalance: '4000',
vault: {
id: 'vault1',
vault_id: 'vault-id1',
token: {
id: 'token1',
address: '0xTokenAddress1',
name: 'Token1',
symbol: 'TKN1',
decimals: '18'
}
},
timestamp: '1625247600',
transaction: {
id: 'tx1',
from: '0xUser1',
timestamp: '0',
blockNumber: '0'
},
orderbook: {
id: '0x00'
}
}
// ... other mock data
] as unknown as VaultBalanceChange[];

// Mock the getVaultBalanceChanges function
const { getVaultBalanceChanges } = await import('@rainlanguage/orderbook/js_api');
vi.mocked(getVaultBalanceChanges).mockResolvedValue(mockVaultBalanceChanges);

render(VaultBalanceChangesTable, {
props: {
id: '100',
subgraphUrl: 'https://example.com'
},
context: new Map([['$$_queryClient', queryClient]])
});

await waitFor(() => {
const rows = screen.getAllByTestId('bodyRow');
expect(rows).toHaveLength(1);
});
});

test('it shows the correct data in the table', async () => {
const queryClient = new QueryClient();

const mockVaultBalanceChanges: VaultBalanceChange[] = [
{
__typename: 'Withdrawal',
amount: '1000',
oldVaultBalance: '5000',
newVaultBalance: '4000',
vault: {
id: 'vault1',
vault_id: 'vault-id1',
token: {
id: 'token1',
address: '0xTokenAddress1',
name: 'Token1',
symbol: 'TKN1',
decimals: '4'
}
},
timestamp: '1625247600',
transaction: {
id: 'tx1',
from: '0xUser1',
timestamp: '0',
blockNumber: '0'
},
orderbook: {
id: '0x00'
}
}
] as unknown as VaultBalanceChange[];

// Mock the getVaultBalanceChanges function
const { getVaultBalanceChanges } = await import('@rainlanguage/orderbook/js_api');
vi.mocked(getVaultBalanceChanges).mockResolvedValue(mockVaultBalanceChanges);

render(VaultBalanceChangesTable, {
props: {
id: '100',
subgraphUrl: 'https://example.com'
},
context: new Map([['$$_queryClient', queryClient]])
});

await waitFor(() => {
expect(screen.getByTestId('vaultBalanceChangesTableDate')).toHaveTextContent(
formatTimestampSecondsAsLocal(BigInt('1625247600'))
);
expect(screen.getByTestId('vaultBalanceChangesTableFrom')).toHaveTextContent('0xUse...User1');
expect(screen.getByTestId('vaultBalanceChangesTableTx')).toHaveTextContent('tx1');
expect(screen.getByTestId('vaultBalanceChangesTableBalanceChange')).toHaveTextContent(
'0.1 TKN1'
);
expect(screen.getByTestId('vaultBalanceChangesTableBalance')).toHaveTextContent('0.4 TKN1');
expect(screen.getByTestId('vaultBalanceChangesTableType')).toHaveTextContent('Withdrawal');
});
});
54 changes: 54 additions & 0 deletions packages/ui-components/src/__tests__/VaultBalanceChart.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { render } from '@testing-library/svelte';
import { expect, test, vi } from 'vitest';
import { QueryClient } from '@tanstack/svelte-query';
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';

vi.mock('@rainlanguage/orderbook/js_api', () => ({
getVaultBalanceChanges: vi.fn()
}));

vi.mock('../lib/components/charts/TanstackLightweightChartLine.svelte', async () => {
const MockLightweightChart = (await import('../lib/__mocks__/MockComponent.svelte')).default;
return { default: MockLightweightChart };
});

const mockVault: Vault = {
id: 'vault1',
vaultId: 'vault1',
token: {
id: 'token1',
address: '0xTokenAddress1',
name: 'Token1',
symbol: 'TKN1',
decimals: '18'
},
owner: '0xOwnerAddress',
ordersAsInput: [],
ordersAsOutput: [],
balanceChanges: [],
balance: '1000000000000000000',
orderbook: {
id: '0x00'
}
};

test('calls getVaultBalanceChanges with correct arguments', async () => {
const queryClient = new QueryClient();

render(VaultBalanceChart, {
props: {
vault: mockVault,
subgraphUrl: 'https://example.com',
lightweightChartsTheme: writable({})
},
context: new Map([['$$_queryClient', queryClient]])
});

expect(getVaultBalanceChanges).toHaveBeenCalledWith('https://example.com', 'vault1', {
page: 1,
pageSize: 1000
});
});
Loading

0 comments on commit e597349

Please sign in to comment.