From 2ee0656f5d96a0173fd6fff6725756d75eaf8d18 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Mon, 17 Feb 2025 13:25:48 +0100 Subject: [PATCH 01/36] remove all use of args --- .../src/__tests__/OrderDetail.test.svelte | 19 ++++++--- .../src/__tests__/OrderDetail.test.ts | 33 +++++++++++++-- .../detail/DepositOrWithdrawButtons.svelte | 11 +---- .../lib/components/detail/OrderDetail.svelte | 40 +++++-------------- .../lib/components/detail/VaultDetail.svelte | 10 +---- packages/ui-components/src/lib/index.ts | 9 ++++- .../src/lib/types/transaction.ts | 36 +++++++++++++++++ packages/webapp/src/lib/services/modal.ts | 19 ++++----- 8 files changed, 111 insertions(+), 66 deletions(-) diff --git a/packages/ui-components/src/__tests__/OrderDetail.test.svelte b/packages/ui-components/src/__tests__/OrderDetail.test.svelte index a1b46623b..7b5bd8c91 100644 --- a/packages/ui-components/src/__tests__/OrderDetail.test.svelte +++ b/packages/ui-components/src/__tests__/OrderDetail.test.svelte @@ -9,14 +9,16 @@ import type { Readable } from 'svelte/store'; import { Button } from 'flowbite-svelte'; import DepositOrWithdrawButtons from '../lib/components/detail/DepositOrWithdrawButtons.svelte'; - + import type { OrderRemoveModalArgs } from '../lib/types/transaction'; + import type { Config } from 'wagmi'; export let walletAddressMatchesOrBlank: Readable<(address: string) => boolean> | undefined = undefined; - export let handleOrderRemoveModal: - | ((order: OrderSubgraph, refetch: () => void) => void) - | undefined = undefined; + export let handleOrderRemoveModal: ((args: OrderRemoveModalArgs) => void) | undefined = undefined; export let id: string; export let subgraphUrl: string; + export let chainId: number; + export let orderbookAddress: string; + export let wagmiConfig: Config; $: orderDetailQuery = createQuery({ queryKey: [id, QKEY_ORDER + id], @@ -32,7 +34,14 @@ diff --git a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte index e5023ce46..f791ed203 100644 --- a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte @@ -21,23 +21,24 @@ import { page } from '$app/stores'; import DepositOrWithdrawButtons from './DepositOrWithdrawButtons.svelte'; import type { Config } from 'wagmi'; + import type { Hex } from 'viem'; import type { - DepositOrWithdrawModalArgs, - OrderRemoveModalArgs, + DepositOrWithdrawModalProps, + OrderRemoveModalProps, QuoteDebugModalHandler, DebugTradeModalHandler - } from '../../types/transaction'; - + } from '../../types/modal'; export let handleDepositOrWithdrawModal: - | ((args: DepositOrWithdrawModalArgs) => void) + | ((props: DepositOrWithdrawModalProps) => void) | undefined = undefined; - export let handleOrderRemoveModal: ((args: OrderRemoveModalArgs) => void) | undefined = undefined; + export let handleOrderRemoveModal: ((props: OrderRemoveModalProps) => void) | undefined = + undefined; export let handleQuoteDebugModal: QuoteDebugModalHandler | undefined = undefined; export const handleDebugTradeModal: DebugTradeModalHandler | undefined = undefined; export let colorTheme; export let codeMirrorTheme; export let lightweightChartsTheme; - export let orderbookAddress: string | undefined = undefined; + export let orderbookAddress: Hex | undefined = undefined; export let id: string; export let rpcUrl: string; export let subgraphUrl: string; @@ -88,11 +89,13 @@ color="dark" on:click={() => handleOrderRemoveModal({ - order: data.order, - onRemove: $orderDetailQuery.refetch, - wagmiConfig: $wagmiConfig, - chainId, - orderbookAddress + open: true, + args: { + order: data.order, + onRemove: $orderDetailQuery.refetch, + chainId, + orderbookAddress + } })} disabled={!handleOrderRemoveModal} > diff --git a/packages/ui-components/src/lib/components/detail/TanstackOrderQuote.svelte b/packages/ui-components/src/lib/components/detail/TanstackOrderQuote.svelte index e2db7ef67..684916537 100644 --- a/packages/ui-components/src/lib/components/detail/TanstackOrderQuote.svelte +++ b/packages/ui-components/src/lib/components/detail/TanstackOrderQuote.svelte @@ -4,6 +4,7 @@ import { getOrderQuote, type BatchOrderQuotesResponse } from '@rainlanguage/orderbook/quote'; import { QKEY_ORDER_QUOTE } from '../../queries/keys'; import { formatUnits, hexToNumber, isHex } from 'viem'; + import type { Hex } from 'viem'; import { createQuery } from '@tanstack/svelte-query'; import type { OrderSubgraph } from '@rainlanguage/orderbook/js_api'; import { @@ -20,13 +21,13 @@ export let id: string; export let order: OrderSubgraph; export let rpcUrl: string; - export let orderbookAddress: string = ''; + export let orderbookAddress: Hex; export let handleQuoteDebugModal: | undefined | (( order: OrderSubgraph, rpcUrl: string, - orderbookAddress: string, + orderbookAddress: Hex, inputIndex: number, outputIndex: number, pairName: string, diff --git a/packages/ui-components/src/lib/index.ts b/packages/ui-components/src/lib/index.ts index 73786c31f..42c317b45 100644 --- a/packages/ui-components/src/lib/index.ts +++ b/packages/ui-components/src/lib/index.ts @@ -75,12 +75,17 @@ export { } from './stores/transactionStore'; export type { DeploymentArgs, - DepositOrWithdrawModalArgs, - OrderRemoveModalArgs, + DepositOrWithdrawArgs, + OrderRemoveArgs, +} from './types/transaction'; +export type { + DepositOrWithdrawModalProps, + OrderRemoveModalProps, QuoteDebugModalHandler, DebugTradeModalHandler, - DisclaimerModalArgs -} from './types/transaction'; + DeployModalProps, + DisclaimerModalProps +} from './types/modal'; // Functions export { createResolvableQuery, createResolvableInfiniteQuery } from './__mocks__/queries'; diff --git a/packages/ui-components/src/lib/types/modal.ts b/packages/ui-components/src/lib/types/modal.ts new file mode 100644 index 000000000..10f2394cf --- /dev/null +++ b/packages/ui-components/src/lib/types/modal.ts @@ -0,0 +1,34 @@ +import type { OrderSubgraph } from '@rainlanguage/orderbook/js_api'; +import type { DepositOrWithdrawArgs, OrderRemoveArgs, DeploymentArgs } from './transaction'; + +export type DepositOrWithdrawModalProps = { + open: boolean; + args: DepositOrWithdrawArgs; +}; + +export type OrderRemoveModalProps = { + open: boolean; + args: OrderRemoveArgs +}; + +export type DeployModalProps = { + open: boolean; + args: DeploymentArgs; +}; + +export type DisclaimerModalProps = { + open: boolean; + onAccept: () => void; +}; +export type QuoteDebugModalHandler = ( + order: OrderSubgraph, + rpcUrl: string, + orderbook: string, + inputIOIndex: number, + outputIOIndex: number, + pair: string, + blockNumber?: number +) => void; + +export type DebugTradeModalHandler = (hash: string, rpcUrl: string) => void; + diff --git a/packages/ui-components/src/lib/types/transaction.ts b/packages/ui-components/src/lib/types/transaction.ts index ecf177bd9..b24f0f41f 100644 --- a/packages/ui-components/src/lib/types/transaction.ts +++ b/packages/ui-components/src/lib/types/transaction.ts @@ -1,7 +1,6 @@ import type { ExtendedApprovalCalldata } from '$lib/stores/transactionStore'; import type { DepositAndAddOrderCalldataResult } from '@rainlanguage/orderbook/js_api'; import type { Hex } from 'viem'; -import type { Config } from 'wagmi'; import type { OrderSubgraph, Vault } from '@rainlanguage/orderbook/js_api'; export type DeploymentArgs = { @@ -13,7 +12,7 @@ export type DeploymentArgs = { network: string; }; -export type DepositOrWithdrawModalArgs = { +export type DepositOrWithdrawArgs = { vault: Vault; onDepositOrWithdraw: () => void; action: 'deposit' | 'withdraw'; @@ -22,26 +21,9 @@ export type DepositOrWithdrawModalArgs = { subgraphUrl: string; }; -export type OrderRemoveModalArgs = { +export type OrderRemoveArgs = { order: OrderSubgraph; onRemove: () => void; - wagmiConfig: Config; chainId: number; - orderbookAddress: string; -}; - -export type QuoteDebugModalHandler = ( - order: OrderSubgraph, - rpcUrl: string, - orderbook: string, - inputIOIndex: number, - outputIOIndex: number, - pair: string, - blockNumber?: number -) => void; - -export type DebugTradeModalHandler = (hash: string, rpcUrl: string) => void; - -export type DisclaimerModalArgs = { - onAccept: () => void; + orderbookAddress: Hex; }; diff --git a/packages/webapp/src/lib/components/DeployModal.svelte b/packages/webapp/src/lib/components/DeployModal.svelte index 1c4e9870b..8a7034950 100644 --- a/packages/webapp/src/lib/components/DeployModal.svelte +++ b/packages/webapp/src/lib/components/DeployModal.svelte @@ -1,17 +1,10 @@ diff --git a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte index 4f00e36d4..0c8ee068d 100644 --- a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte +++ b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte @@ -1,11 +1,15 @@ - + diff --git a/packages/webapp/src/lib/components/TransactionModal.svelte b/packages/webapp/src/lib/components/TransactionModal.svelte index 182fe024a..e17e9eebc 100644 --- a/packages/webapp/src/lib/components/TransactionModal.svelte +++ b/packages/webapp/src/lib/components/TransactionModal.svelte @@ -14,11 +14,6 @@ function handleClose() { open = false; } - const dispatch = createEventDispatcher(); - - $: if ($transactionStore.status === TransactionStatus.SUCCESS) { - dispatch('success'); - } $: if (!open) { transactionStore.reset(); @@ -79,7 +74,7 @@ {:else}
diff --git a/packages/webapp/src/lib/services/modal.ts b/packages/webapp/src/lib/services/modal.ts index 1cd36aa60..0c8240546 100644 --- a/packages/webapp/src/lib/services/modal.ts +++ b/packages/webapp/src/lib/services/modal.ts @@ -4,23 +4,24 @@ import OrderRemoveModal from '$lib/components/OrderRemoveModal.svelte'; import { DisclaimerModal, type DeploymentArgs, - type DepositOrWithdrawModalArgs, - type OrderRemoveModalArgs, - type DisclaimerModalArgs + type DepositOrWithdrawModalProps, + type OrderRemoveModalProps, + type DisclaimerModalProps, + type DeployModalProps } from '@rainlanguage/ui-components'; -export const handleDeployModal = (args: Omit) => { - new DeployModal({ target: document.body, props: { ...args, open: true } }); +export const handleDeployModal = (props: DeployModalProps) => { + new DeployModal({ target: document.body, props }); }; -export const handleDepositOrWithdrawModal = (args: Omit) => { - new DepositOrWithdrawModal({ target: document.body, props: { ...args, open: true } }); +export const handleDepositOrWithdrawModal = (props: DepositOrWithdrawModalProps) => { + new DepositOrWithdrawModal({ target: document.body, props}); }; -export const handleOrderRemoveModal = (args: Omit) => { - new OrderRemoveModal({ target: document.body, props: { ...args, open: true } }); +export const handleOrderRemoveModal = (props: OrderRemoveModalProps) => { + new OrderRemoveModal({ target: document.body, props}); }; -export const handleDisclaimerModal = (args: Omit) => { - new DisclaimerModal({ target: document.body, props: { ...args, open: true } }); +export const handleDisclaimerModal = (props: DisclaimerModalProps) => { + new DisclaimerModal({ target: document.body, props }); }; From d88dd5419b86c1c3d2d2a661afa07e5f06e8ec23 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Mon, 17 Feb 2025 17:41:09 +0100 Subject: [PATCH 06/36] add --- .../components/DepositOrWithdrawModal.svelte | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte index 0c8ee068d..7296322cf 100644 --- a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte +++ b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte @@ -37,6 +37,9 @@ const { action, vault, chainId, rpcUrl, subgraphUrl } = args; + type Action = 'deposit' | 'withdraw'; + const actionType = action as Action; + let currentStep = 1; let amount: bigint = 0n; let userBalance: bigint = 0n; @@ -83,11 +86,8 @@ transactionStore.handleDepositOrWithdrawTransaction({ config: $wagmiConfig, transactionCalldata: depositCalldata, - action, approvalCalldata, - chainId, - vault, - subgraphUrl + ...args }); } else if (action === 'withdraw') { const withdrawCalldata: WithdrawCalldataResult = await getVaultWithdrawCalldata( @@ -98,10 +98,7 @@ transactionStore.handleDepositOrWithdrawTransaction({ config: $wagmiConfig, transactionCalldata: withdrawCalldata, - action, - chainId, - vault, - subgraphUrl + ...args }); } } @@ -139,7 +136,7 @@ @@ -151,7 +148,7 @@ {#if switchChainError}

{switchChainError}

{/if} - {#if amountGreaterThanBalance[action]} + {#if amountGreaterThanBalance[actionType]}

Amount cannot exceed available balance.

{/if} From e6d72c79c816e08d9b04ec28e25f1ea95b2a3b36 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Mon, 17 Feb 2025 18:14:53 +0100 Subject: [PATCH 07/36] formatted --- .../webapp/src/__tests__/DeployModal.test.ts | 45 ++- .../__tests__/DepositOrWithdrawModal.test.ts | 292 +++++++++--------- .../src/__tests__/OrderRemoveModal.test.ts | 23 +- .../components/DepositOrWithdrawModal.svelte | 10 +- .../lib/components/OrderRemoveModal.svelte | 9 +- .../lib/components/TransactionModal.svelte | 5 + 6 files changed, 206 insertions(+), 178 deletions(-) diff --git a/packages/webapp/src/__tests__/DeployModal.test.ts b/packages/webapp/src/__tests__/DeployModal.test.ts index f42f444e6..c4d7d60c4 100644 --- a/packages/webapp/src/__tests__/DeployModal.test.ts +++ b/packages/webapp/src/__tests__/DeployModal.test.ts @@ -1,11 +1,9 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render } from '@testing-library/svelte'; import DeployModal from '../lib/components/DeployModal.svelte'; -import { transactionStore } from '@rainlanguage/ui-components'; -import type { ComponentProps } from 'svelte'; import { get } from 'svelte/store'; +import type { DeployModalProps } from '@rainlanguage/ui-components'; -export type DeployModalProps = ComponentProps; const { mockTransactionStore } = await vi.hoisted(() => import('@rainlanguage/ui-components')); const { mockWagmiConfigStore } = await vi.hoisted(() => import('$lib/__mocks__/stores')); vi.mock('@rainlanguage/ui-components', async (importOriginal) => { @@ -24,36 +22,35 @@ vi.mock('$lib/stores/wagmi', () => { describe('DeployModal', () => { const mockProps = { open: true, - approvals: { - approvalCalldata: '0x', - token: '0x', - spender: '0x' - }, - deploymentCalldata: { - calldata: '0x', - value: 0n - }, - orderbookAddress: '0x123' as const, - chainId: 1 + args: { + approvals: { + approvalCalldata: '0x', + token: '0x', + spender: '0x' + }, + deploymentCalldata: { + calldata: '0x', + value: 0n + }, + orderbookAddress: '0x123' as const, + chainId: 1, + subgraphUrl: 'https://example.com', + network: 'mainnet' + } } as unknown as DeployModalProps; - beforeEach(() => { - vi.clearAllMocks(); - }); - it('renders and initiates transaction handling', () => { const config = get(mockWagmiConfigStore); const handleDeploymentTransactionSpy = vi.spyOn( - transactionStore, + mockTransactionStore, 'handleDeploymentTransaction' ); + render(DeployModal, { props: mockProps }); + expect(handleDeploymentTransactionSpy).toHaveBeenCalledWith({ - config: config, - approvals: mockProps.approvals, - deploymentCalldata: mockProps.deploymentCalldata, - orderbookAddress: mockProps.orderbookAddress, - chainId: mockProps.chainId + config, + ...mockProps.args }); }); }); diff --git a/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts b/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts index fa4ca41e0..4e6a4969b 100644 --- a/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts +++ b/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts @@ -6,151 +6,165 @@ import { signerAddress } from '$lib/stores/wagmi'; import { readContract, switchChain } from '@wagmi/core'; import type { ComponentProps } from 'svelte'; + export type ModalProps = ComponentProps; vi.mock('@rainlanguage/orderbook/js_api', () => ({ - getVaultDepositCalldata: vi.fn().mockResolvedValue({ to: '0x123', data: '0x456' }), - getVaultApprovalCalldata: vi.fn().mockResolvedValue({ to: '0x789', data: '0xabc' }), - getVaultWithdrawCalldata: vi.fn().mockResolvedValue({ to: '0xdef', data: '0xghi' }) + getVaultDepositCalldata: vi.fn().mockResolvedValue({ to: '0x123', data: '0x456' }), + getVaultApprovalCalldata: vi.fn().mockResolvedValue({ to: '0x789', data: '0xabc' }), + getVaultWithdrawCalldata: vi.fn().mockResolvedValue({ to: '0xdef', data: '0xghi' }) })); vi.mock('@wagmi/core', () => ({ - readContract: vi.fn(), - switchChain: vi.fn() + readContract: vi.fn(), + switchChain: vi.fn() })); describe('DepositOrWithdrawModal', () => { - const mockVault = { - token: { - address: '0x123', - symbol: 'TEST', - decimals: '18' - }, - vaultId: '1', - balance: BigInt(1) - }; - - const defaultProps = { - open: true, - action: 'deposit' as const, - vault: mockVault, - chainId: 1, - rpcUrl: 'https://example.com', - onDepositOrWithdraw: vi.fn() - } as unknown as ModalProps; - - beforeEach(() => { - vi.clearAllMocks(); - transactionStore.reset(); - signerAddress.set('0x123'); - }); - - it('renders deposit modal correctly', () => { - render(DepositOrWithdrawModal, defaultProps); - expect(screen.getByText('Enter Amount')).toBeInTheDocument(); - expect(screen.getByText('Deposit')).toBeInTheDocument(); - }); - - it('renders withdraw modal correctly', () => { - render(DepositOrWithdrawModal, { - ...defaultProps, - action: 'withdraw' - }); - expect(screen.getByText('Enter Amount')).toBeInTheDocument(); - expect(screen.getByText('Withdraw')).toBeInTheDocument(); - }); - - it('disables continue button when amount is 0', () => { - render(DepositOrWithdrawModal, defaultProps); - const continueButton = screen.getByText('Deposit'); - expect(continueButton).toBeDisabled(); - }); - - it('shows wallet connect button when not connected', () => { - signerAddress.set(''); - render(DepositOrWithdrawModal, defaultProps); - expect(screen.getByText('Connect Wallet')).toBeInTheDocument(); - }); - - it('handles deposit transaction correctly', async () => { - const handleTransactionSpy = vi.spyOn(transactionStore, 'handleDepositOrWithdrawTransaction'); - render(DepositOrWithdrawModal, defaultProps); - - const input = screen.getByRole('textbox'); - await fireEvent.input(input, { target: { value: '1' } }); - - const depositButton = screen.getByText('Deposit'); - await fireEvent.click(depositButton); - - expect(handleTransactionSpy).toHaveBeenCalledWith( - expect.objectContaining({ - action: 'deposit', - chainId: 1, - vault: mockVault - }) - ); - }); - - it('Blocks deposit if not enough balance in wallet', async () => { - (readContract as Mock).mockReturnValue(BigInt(0)); - - render(DepositOrWithdrawModal, defaultProps); - - const input = screen.getByRole('textbox'); - await fireEvent.input(input, { target: { value: '1' } }); - - await waitFor(() => { - expect(screen.getByTestId('error')).toBeInTheDocument(); - }); - }); - - it('Blocks withdrawal if not enough balance in vault', async () => { - render(DepositOrWithdrawModal, defaultProps); - - const input = screen.getByRole('textbox'); - await fireEvent.input(input, { target: { value: '2' } }); - - await waitFor(() => { - expect(screen.getByTestId('error')).toBeInTheDocument(); - }); - }); - - it('handles withdraw transaction correctly', async () => { - const handleTransactionSpy = vi.spyOn(transactionStore, 'handleDepositOrWithdrawTransaction'); - render(DepositOrWithdrawModal, { - ...defaultProps, - action: 'withdraw' - }); - - const input = screen.getByRole('textbox'); - await fireEvent.input(input, { target: { value: '1' } }); - - const withdrawButton = screen.getByText('Withdraw'); - await fireEvent.click(withdrawButton); - - expect(handleTransactionSpy).toHaveBeenCalledWith( - expect.objectContaining({ - action: 'withdraw', - chainId: 1, - vault: mockVault - }) - ); - }); - - it('closes modal and resets state', async () => { - render(DepositOrWithdrawModal, defaultProps); - - const cancelButton = screen.getByText('Cancel'); - await fireEvent.click(cancelButton); - - expect(screen.queryByText('Enter Amount')).not.toBeInTheDocument(); - }); - - it('shows an error if you fail to connect to the target chain', async () => { - (switchChain as Mock).mockRejectedValue(new Error('Failed to switch chain')); - render(DepositOrWithdrawModal, defaultProps); - await waitFor(() => { - expect(screen.getByTestId('chain-error')).toBeInTheDocument(); - }); - }); -}); + const mockVault = { + token: { + address: '0x123', + symbol: 'TEST', + decimals: '18' + }, + vaultId: '1', + balance: BigInt(1) + }; + + const defaultProps = { + open: true, + args: { + action: 'deposit' as const, + vault: mockVault, + chainId: 1, + rpcUrl: 'https://example.com', + onDepositOrWithdraw: vi.fn() + } + } as unknown as ModalProps; + + beforeEach(() => { + vi.clearAllMocks(); + transactionStore.reset(); + signerAddress.set('0x123'); + }); + + it('renders deposit modal correctly', () => { + render(DepositOrWithdrawModal, defaultProps); + expect(screen.getByText('Enter Amount')).toBeInTheDocument(); + expect(screen.getByText('Deposit')).toBeInTheDocument(); + }); + + it('renders withdraw modal correctly', () => { + render(DepositOrWithdrawModal, { + ...defaultProps, + args: { + ...defaultProps.args, + action: 'withdraw' + } + }); + expect(screen.getByText('Enter Amount')).toBeInTheDocument(); + expect(screen.getByText('Withdraw')).toBeInTheDocument(); + }); + + it('handles deposit transaction correctly', async () => { + const handleTransactionSpy = vi.spyOn(transactionStore, 'handleDepositOrWithdrawTransaction'); + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '1' } }); + + const depositButton = screen.getByText('Deposit'); + await fireEvent.click(depositButton); + + expect(handleTransactionSpy).toHaveBeenCalledWith({ + action: 'deposit', + chainId: 1, + vault: mockVault, + config: undefined, + subgraphUrl: undefined, + approvalCalldata: { to: '0x789', data: '0xabc' }, + transactionCalldata: { to: '0x123', data: '0x456' } + }); + }); + + it('handles withdraw transaction correctly', async () => { + const handleTransactionSpy = vi.spyOn(transactionStore, 'handleDepositOrWithdrawTransaction'); + render(DepositOrWithdrawModal, { + ...defaultProps, + args: { + ...defaultProps.args, + action: 'withdraw' + } + }); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '1' } }); + + const withdrawButton = screen.getByText('Withdraw'); + await fireEvent.click(withdrawButton); + + expect(handleTransactionSpy).toHaveBeenCalledWith({ + config: undefined, + transactionCalldata: { to: '0xdef', data: '0xghi' }, + action: 'withdraw', + chainId: 1, + vault: mockVault, + subgraphUrl: undefined + }); + }); + + it('shows error when amount exceeds balance for deposit', async () => { + (readContract as Mock).mockResolvedValue(BigInt(0)); + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '2' } }); + + expect(screen.getByTestId('error')).toHaveTextContent('Amount cannot exceed available balance.'); + }); + + it('shows error when amount exceeds balance for withdraw', async () => { + render(DepositOrWithdrawModal, { + ...defaultProps, + args: { + ...defaultProps.args, + action: 'withdraw' + } + }); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '2' } }); + + expect(screen.getByTestId('error')).toHaveTextContent('Amount cannot exceed available balance.'); + }); + + it('shows chain switch error when switching fails', async () => { + (switchChain as Mock).mockRejectedValue(new Error('Failed to switch chain')); + render(DepositOrWithdrawModal, defaultProps); + + await waitFor(() => { + expect(screen.getByTestId('chain-error')).toHaveTextContent('Switch to Ethereum to check your balance.'); + }); + }); + + it('disables continue button when amount is 0', () => { + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + fireEvent.input(input, { target: { value: '0' } }); + + const continueButton = screen.getByText('Deposit'); + expect(continueButton).toBeDisabled(); + }); + + it('disables continue button when amount exceeds balance', async () => { + (readContract as Mock).mockResolvedValue(BigInt(0)); + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '1' } }); + + const continueButton = screen.getByText('Deposit'); + expect(continueButton).toBeDisabled(); + }); +}); \ No newline at end of file diff --git a/packages/webapp/src/__tests__/OrderRemoveModal.test.ts b/packages/webapp/src/__tests__/OrderRemoveModal.test.ts index 327c45d87..ca9c1ec05 100644 --- a/packages/webapp/src/__tests__/OrderRemoveModal.test.ts +++ b/packages/webapp/src/__tests__/OrderRemoveModal.test.ts @@ -2,9 +2,7 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/svelte'; import OrderRemoveModal from '$lib/components/OrderRemoveModal.svelte'; import { transactionStore } from '@rainlanguage/ui-components'; -import type { ComponentProps } from 'svelte'; - -export type ModalProps = ComponentProps; +import type { OrderRemoveModalProps } from '@rainlanguage/ui-components'; vi.mock('@rainlanguage/orderbook/js_api', () => ({ getRemoveOrderCalldata: vi.fn().mockResolvedValue('0x123') @@ -21,12 +19,14 @@ describe('OrderRemoveModal', () => { const defaultProps = { open: true, - order: mockOrder, - onRemove: vi.fn(), - wagmiConfig: {}, - chainId: 1, - orderbookAddress: '0x789' - } as unknown as ModalProps; + args: { + order: mockOrder, + chainId: 1, + orderbookAddress: '0x789', + config: {}, + onRemove: vi.fn() + } + } as unknown as OrderRemoveModalProps; beforeEach(() => { vi.clearAllMocks(); @@ -43,7 +43,8 @@ describe('OrderRemoveModal', () => { expect.objectContaining({ chainId: 1, orderbookAddress: '0x789', - config: {} + config: {}, + removeOrderCalldata: '0x123' }) ); }); @@ -64,6 +65,6 @@ describe('OrderRemoveModal', () => { transactionStore.transactionSuccess('0x123'); await vi.runAllTimersAsync(); - expect(defaultProps.onRemove).toHaveBeenCalled(); + expect(defaultProps.args.onRemove).toHaveBeenCalled(); }); }); diff --git a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte index 7296322cf..b9a15ff84 100644 --- a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte +++ b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte @@ -87,7 +87,10 @@ config: $wagmiConfig, transactionCalldata: depositCalldata, approvalCalldata, - ...args + action, + chainId, + vault, + subgraphUrl }); } else if (action === 'withdraw') { const withdrawCalldata: WithdrawCalldataResult = await getVaultWithdrawCalldata( @@ -98,7 +101,10 @@ transactionStore.handleDepositOrWithdrawTransaction({ config: $wagmiConfig, transactionCalldata: withdrawCalldata, - ...args + action, + chainId, + vault, + subgraphUrl }); } } diff --git a/packages/webapp/src/lib/components/OrderRemoveModal.svelte b/packages/webapp/src/lib/components/OrderRemoveModal.svelte index 4ecbef111..c457cf921 100644 --- a/packages/webapp/src/lib/components/OrderRemoveModal.svelte +++ b/packages/webapp/src/lib/components/OrderRemoveModal.svelte @@ -1,7 +1,6 @@ - + diff --git a/packages/webapp/src/lib/components/TransactionModal.svelte b/packages/webapp/src/lib/components/TransactionModal.svelte index e17e9eebc..04bd8731e 100644 --- a/packages/webapp/src/lib/components/TransactionModal.svelte +++ b/packages/webapp/src/lib/components/TransactionModal.svelte @@ -14,6 +14,11 @@ function handleClose() { open = false; } + const dispatch = createEventDispatcher(); + + $: if ($transactionStore.status === TransactionStatus.SUCCESS) { + dispatch('success'); + } $: if (!open) { transactionStore.reset(); From 160cadd8717e414ad09c078fe45807941080b3db Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Mon, 17 Feb 2025 18:14:59 +0100 Subject: [PATCH 08/36] formatated --- packages/ui-components/src/lib/index.ts | 6 +- packages/ui-components/src/lib/types/modal.ts | 3 +- .../__tests__/DepositOrWithdrawModal.test.ts | 310 +++++++++--------- .../lib/components/TransactionModal.svelte | 2 +- packages/webapp/src/lib/services/modal.ts | 4 +- 5 files changed, 163 insertions(+), 162 deletions(-) diff --git a/packages/ui-components/src/lib/index.ts b/packages/ui-components/src/lib/index.ts index 42c317b45..f17c1d097 100644 --- a/packages/ui-components/src/lib/index.ts +++ b/packages/ui-components/src/lib/index.ts @@ -73,11 +73,7 @@ export { type TransactionState, type ExtendedApprovalCalldata } from './stores/transactionStore'; -export type { - DeploymentArgs, - DepositOrWithdrawArgs, - OrderRemoveArgs, -} from './types/transaction'; +export type { DeploymentArgs, DepositOrWithdrawArgs, OrderRemoveArgs } from './types/transaction'; export type { DepositOrWithdrawModalProps, OrderRemoveModalProps, diff --git a/packages/ui-components/src/lib/types/modal.ts b/packages/ui-components/src/lib/types/modal.ts index 10f2394cf..dbee2f872 100644 --- a/packages/ui-components/src/lib/types/modal.ts +++ b/packages/ui-components/src/lib/types/modal.ts @@ -8,7 +8,7 @@ export type DepositOrWithdrawModalProps = { export type OrderRemoveModalProps = { open: boolean; - args: OrderRemoveArgs + args: OrderRemoveArgs; }; export type DeployModalProps = { @@ -31,4 +31,3 @@ export type QuoteDebugModalHandler = ( ) => void; export type DebugTradeModalHandler = (hash: string, rpcUrl: string) => void; - diff --git a/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts b/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts index 4e6a4969b..171f82535 100644 --- a/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts +++ b/packages/webapp/src/__tests__/DepositOrWithdrawModal.test.ts @@ -10,161 +10,167 @@ import type { ComponentProps } from 'svelte'; export type ModalProps = ComponentProps; vi.mock('@rainlanguage/orderbook/js_api', () => ({ - getVaultDepositCalldata: vi.fn().mockResolvedValue({ to: '0x123', data: '0x456' }), - getVaultApprovalCalldata: vi.fn().mockResolvedValue({ to: '0x789', data: '0xabc' }), - getVaultWithdrawCalldata: vi.fn().mockResolvedValue({ to: '0xdef', data: '0xghi' }) + getVaultDepositCalldata: vi.fn().mockResolvedValue({ to: '0x123', data: '0x456' }), + getVaultApprovalCalldata: vi.fn().mockResolvedValue({ to: '0x789', data: '0xabc' }), + getVaultWithdrawCalldata: vi.fn().mockResolvedValue({ to: '0xdef', data: '0xghi' }) })); vi.mock('@wagmi/core', () => ({ - readContract: vi.fn(), - switchChain: vi.fn() + readContract: vi.fn(), + switchChain: vi.fn() })); describe('DepositOrWithdrawModal', () => { - const mockVault = { - token: { - address: '0x123', - symbol: 'TEST', - decimals: '18' - }, - vaultId: '1', - balance: BigInt(1) - }; - - const defaultProps = { - open: true, - args: { - action: 'deposit' as const, - vault: mockVault, - chainId: 1, - rpcUrl: 'https://example.com', - onDepositOrWithdraw: vi.fn() - } - } as unknown as ModalProps; - - beforeEach(() => { - vi.clearAllMocks(); - transactionStore.reset(); - signerAddress.set('0x123'); - }); - - it('renders deposit modal correctly', () => { - render(DepositOrWithdrawModal, defaultProps); - expect(screen.getByText('Enter Amount')).toBeInTheDocument(); - expect(screen.getByText('Deposit')).toBeInTheDocument(); - }); - - it('renders withdraw modal correctly', () => { - render(DepositOrWithdrawModal, { - ...defaultProps, - args: { - ...defaultProps.args, - action: 'withdraw' - } - }); - expect(screen.getByText('Enter Amount')).toBeInTheDocument(); - expect(screen.getByText('Withdraw')).toBeInTheDocument(); - }); - - it('handles deposit transaction correctly', async () => { - const handleTransactionSpy = vi.spyOn(transactionStore, 'handleDepositOrWithdrawTransaction'); - render(DepositOrWithdrawModal, defaultProps); - - const input = screen.getByRole('textbox'); - await fireEvent.input(input, { target: { value: '1' } }); - - const depositButton = screen.getByText('Deposit'); - await fireEvent.click(depositButton); - - expect(handleTransactionSpy).toHaveBeenCalledWith({ - action: 'deposit', - chainId: 1, - vault: mockVault, - config: undefined, - subgraphUrl: undefined, - approvalCalldata: { to: '0x789', data: '0xabc' }, - transactionCalldata: { to: '0x123', data: '0x456' } - }); - }); - - it('handles withdraw transaction correctly', async () => { - const handleTransactionSpy = vi.spyOn(transactionStore, 'handleDepositOrWithdrawTransaction'); - render(DepositOrWithdrawModal, { - ...defaultProps, - args: { - ...defaultProps.args, - action: 'withdraw' - } - }); - - const input = screen.getByRole('textbox'); - await fireEvent.input(input, { target: { value: '1' } }); - - const withdrawButton = screen.getByText('Withdraw'); - await fireEvent.click(withdrawButton); - - expect(handleTransactionSpy).toHaveBeenCalledWith({ - config: undefined, - transactionCalldata: { to: '0xdef', data: '0xghi' }, - action: 'withdraw', - chainId: 1, - vault: mockVault, - subgraphUrl: undefined - }); - }); - - it('shows error when amount exceeds balance for deposit', async () => { - (readContract as Mock).mockResolvedValue(BigInt(0)); - render(DepositOrWithdrawModal, defaultProps); - - const input = screen.getByRole('textbox'); - await fireEvent.input(input, { target: { value: '2' } }); - - expect(screen.getByTestId('error')).toHaveTextContent('Amount cannot exceed available balance.'); - }); - - it('shows error when amount exceeds balance for withdraw', async () => { - render(DepositOrWithdrawModal, { - ...defaultProps, - args: { - ...defaultProps.args, - action: 'withdraw' - } - }); - - const input = screen.getByRole('textbox'); - await fireEvent.input(input, { target: { value: '2' } }); - - expect(screen.getByTestId('error')).toHaveTextContent('Amount cannot exceed available balance.'); - }); - - it('shows chain switch error when switching fails', async () => { - (switchChain as Mock).mockRejectedValue(new Error('Failed to switch chain')); - render(DepositOrWithdrawModal, defaultProps); - - await waitFor(() => { - expect(screen.getByTestId('chain-error')).toHaveTextContent('Switch to Ethereum to check your balance.'); - }); - }); - - it('disables continue button when amount is 0', () => { - render(DepositOrWithdrawModal, defaultProps); - - const input = screen.getByRole('textbox'); - fireEvent.input(input, { target: { value: '0' } }); - - const continueButton = screen.getByText('Deposit'); - expect(continueButton).toBeDisabled(); - }); - - it('disables continue button when amount exceeds balance', async () => { - (readContract as Mock).mockResolvedValue(BigInt(0)); - render(DepositOrWithdrawModal, defaultProps); - - const input = screen.getByRole('textbox'); - await fireEvent.input(input, { target: { value: '1' } }); - - const continueButton = screen.getByText('Deposit'); - expect(continueButton).toBeDisabled(); - }); -}); \ No newline at end of file + const mockVault = { + token: { + address: '0x123', + symbol: 'TEST', + decimals: '18' + }, + vaultId: '1', + balance: BigInt(1) + }; + + const defaultProps = { + open: true, + args: { + action: 'deposit' as const, + vault: mockVault, + chainId: 1, + rpcUrl: 'https://example.com', + onDepositOrWithdraw: vi.fn() + } + } as unknown as ModalProps; + + beforeEach(() => { + vi.clearAllMocks(); + transactionStore.reset(); + signerAddress.set('0x123'); + }); + + it('renders deposit modal correctly', () => { + render(DepositOrWithdrawModal, defaultProps); + expect(screen.getByText('Enter Amount')).toBeInTheDocument(); + expect(screen.getByText('Deposit')).toBeInTheDocument(); + }); + + it('renders withdraw modal correctly', () => { + render(DepositOrWithdrawModal, { + ...defaultProps, + args: { + ...defaultProps.args, + action: 'withdraw' + } + }); + expect(screen.getByText('Enter Amount')).toBeInTheDocument(); + expect(screen.getByText('Withdraw')).toBeInTheDocument(); + }); + + it('handles deposit transaction correctly', async () => { + const handleTransactionSpy = vi.spyOn(transactionStore, 'handleDepositOrWithdrawTransaction'); + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '1' } }); + + const depositButton = screen.getByText('Deposit'); + await fireEvent.click(depositButton); + + expect(handleTransactionSpy).toHaveBeenCalledWith({ + action: 'deposit', + chainId: 1, + vault: mockVault, + config: undefined, + subgraphUrl: undefined, + approvalCalldata: { to: '0x789', data: '0xabc' }, + transactionCalldata: { to: '0x123', data: '0x456' } + }); + }); + + it('handles withdraw transaction correctly', async () => { + const handleTransactionSpy = vi.spyOn(transactionStore, 'handleDepositOrWithdrawTransaction'); + render(DepositOrWithdrawModal, { + ...defaultProps, + args: { + ...defaultProps.args, + action: 'withdraw' + } + }); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '1' } }); + + const withdrawButton = screen.getByText('Withdraw'); + await fireEvent.click(withdrawButton); + + expect(handleTransactionSpy).toHaveBeenCalledWith({ + config: undefined, + transactionCalldata: { to: '0xdef', data: '0xghi' }, + action: 'withdraw', + chainId: 1, + vault: mockVault, + subgraphUrl: undefined + }); + }); + + it('shows error when amount exceeds balance for deposit', async () => { + (readContract as Mock).mockResolvedValue(BigInt(0)); + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '2' } }); + + expect(screen.getByTestId('error')).toHaveTextContent( + 'Amount cannot exceed available balance.' + ); + }); + + it('shows error when amount exceeds balance for withdraw', async () => { + render(DepositOrWithdrawModal, { + ...defaultProps, + args: { + ...defaultProps.args, + action: 'withdraw' + } + }); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '2' } }); + + expect(screen.getByTestId('error')).toHaveTextContent( + 'Amount cannot exceed available balance.' + ); + }); + + it('shows chain switch error when switching fails', async () => { + (switchChain as Mock).mockRejectedValue(new Error('Failed to switch chain')); + render(DepositOrWithdrawModal, defaultProps); + + await waitFor(() => { + expect(screen.getByTestId('chain-error')).toHaveTextContent( + 'Switch to Ethereum to check your balance.' + ); + }); + }); + + it('disables continue button when amount is 0', () => { + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + fireEvent.input(input, { target: { value: '0' } }); + + const continueButton = screen.getByText('Deposit'); + expect(continueButton).toBeDisabled(); + }); + + it('disables continue button when amount exceeds balance', async () => { + (readContract as Mock).mockResolvedValue(BigInt(0)); + render(DepositOrWithdrawModal, defaultProps); + + const input = screen.getByRole('textbox'); + await fireEvent.input(input, { target: { value: '1' } }); + + const continueButton = screen.getByText('Deposit'); + expect(continueButton).toBeDisabled(); + }); +}); diff --git a/packages/webapp/src/lib/components/TransactionModal.svelte b/packages/webapp/src/lib/components/TransactionModal.svelte index 04bd8731e..182fe024a 100644 --- a/packages/webapp/src/lib/components/TransactionModal.svelte +++ b/packages/webapp/src/lib/components/TransactionModal.svelte @@ -79,7 +79,7 @@ {:else}
diff --git a/packages/webapp/src/lib/services/modal.ts b/packages/webapp/src/lib/services/modal.ts index 0c8240546..990e062bc 100644 --- a/packages/webapp/src/lib/services/modal.ts +++ b/packages/webapp/src/lib/services/modal.ts @@ -15,11 +15,11 @@ export const handleDeployModal = (props: DeployModalProps) => { }; export const handleDepositOrWithdrawModal = (props: DepositOrWithdrawModalProps) => { - new DepositOrWithdrawModal({ target: document.body, props}); + new DepositOrWithdrawModal({ target: document.body, props }); }; export const handleOrderRemoveModal = (props: OrderRemoveModalProps) => { - new OrderRemoveModal({ target: document.body, props}); + new OrderRemoveModal({ target: document.body, props }); }; export const handleDisclaimerModal = (props: DisclaimerModalProps) => { From b9190bc24a46f103caf2d66fd79750f961ce74dc Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Mon, 17 Feb 2025 18:28:11 +0100 Subject: [PATCH 09/36] fix checks --- .../src/__tests__/DeploymentSteps.test.ts | 196 ++++++------------ .../src/__tests__/OrderDetail.test.ts | 4 - .../deployment/DeploymentSteps.svelte | 20 +- .../lib/components/detail/OrderDetail.svelte | 2 +- .../lib/components/detail/VaultDetail.svelte | 4 +- .../routes/orders/[network]-[id]/+page.svelte | 4 +- 6 files changed, 76 insertions(+), 154 deletions(-) diff --git a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts index 993434cb9..525b8ef7d 100644 --- a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts +++ b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts @@ -6,8 +6,7 @@ import type { ComponentProps } from 'svelte'; import { writable } from 'svelte/store'; import type { AppKit } from '@reown/appkit'; import type { ConfigSource } from '../lib/typeshare/config'; -import type { DeploymentArgs } from '$lib/types/transaction'; -import type { DisclaimerModal } from '$lib'; +import type { DeployModalProps, DisclaimerModalProps } from '../lib/types/modal'; const { mockWagmiConfigStore, mockConnectedStore } = await vi.hoisted( () => import('../lib/__mocks__/stores') @@ -572,22 +571,31 @@ min-trade-amount: mul(min-amount 0.9), "Min trade amount."), :call<'set-cost-basis-io-ratio>();`; -describe('DeploymentSteps', () => { - const mockDeployment = { +const mockDeployment = { + key: 'flare-sflr-wflr', + name: 'SFLR<>WFLR on Flare', + description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.', + deposits: [], + fields: [], + select_tokens: [], + deployment: { key: 'flare-sflr-wflr', - name: 'SFLR<>WFLR on Flare', - description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.', - deposits: [], - fields: [], - select_tokens: [], - deployment: { + scenario: { + key: 'flare', + bindings: {} + } as Scenario, + order: { key: 'flare-sflr-wflr', - scenario: { + network: { + key: 'flare', + 'chain-id': 14, + 'network-id': 14, + rpc: 'https://rpc.ankr.com/flare', + label: 'Flare', + currency: 'FLR' + }, + deployer: { key: 'flare', - bindings: {} - } as Scenario, - order: { - key: 'flare-sflr-wflr', network: { key: 'flare', 'chain-id': 14, @@ -596,28 +604,36 @@ describe('DeploymentSteps', () => { label: 'Flare', currency: 'FLR' }, - deployer: { - key: 'flare', - network: { - key: 'flare', - 'chain-id': 14, - 'network-id': 14, - rpc: 'https://rpc.ankr.com/flare', - label: 'Flare', - currency: 'FLR' - }, - address: '0x0' - }, - orderbook: { - id: 'flare', - address: '0x0' - }, - inputs: [], - outputs: [] - } + address: '0x0' + }, + orderbook: { + id: 'flare', + address: '0x0' + }, + inputs: [], + outputs: [] } - }; + } +}; + +const defaultProps: DeploymentStepsProps = { + dotrain, + strategyDetail: { + name: 'SFLR<>WFLR on Flare', + description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.', + short_description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.' + }, + deployment: mockDeployment, + wagmiConfig: mockWagmiConfigStore, + wagmiConnected: mockConnectedStore, + appKitModal: writable({} as AppKit), + handleDeployModal: vi.fn() as unknown as (args: DeployModalProps) => void, + handleDisclaimerModal: vi.fn() as unknown as (args: DisclaimerModalProps) => void, + settings: writable({} as ConfigSource), + handleUpdateGuiState: vi.fn() +}; +describe('DeploymentSteps', () => { beforeEach(() => { vi.clearAllMocks(); }); @@ -629,26 +645,7 @@ describe('DeploymentSteps', () => { getNetworkKey: vi.fn() }); - render(DeploymentSteps, { - props: { - dotrain, - strategyDetail: { - name: 'SFLR<>WFLR on Flare', - description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.', - short_description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.' - }, - deployment: mockDeployment, - wagmiConfig: mockWagmiConfigStore, - wagmiConnected: mockConnectedStore, - appKitModal: writable({} as AppKit), - handleDeployModal: vi.fn() as unknown as (args: DeploymentArgs) => void, - handleDisclaimerModal: vi.fn() as unknown as ( - args: ComponentProps - ) => void, - settings: writable({} as ConfigSource), - handleUpdateGuiState: vi.fn() - } - }); + render(DeploymentSteps, { props: defaultProps }); await waitFor(() => { expect(screen.getByText('SFLR<>WFLR on Flare')).toBeInTheDocument(); @@ -663,32 +660,11 @@ describe('DeploymentSteps', () => { getNetworkKey: vi.fn() }); - render(DeploymentSteps, { - props: { - dotrain, - strategyDetail: { - name: 'SFLR<>WFLR on Flare', - description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.', - short_description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.' - }, - deployment: mockDeployment, - wagmiConfig: mockWagmiConfigStore, - wagmiConnected: mockConnectedStore, - appKitModal: writable({} as AppKit), - handleDeployModal: vi.fn() as unknown as (args: DeploymentArgs) => void, - handleDisclaimerModal: vi.fn() as unknown as ( - args: ComponentProps - ) => void, - settings: writable({} as ConfigSource), - handleUpdateGuiState: vi.fn() - } - }); + render(DeploymentSteps, { props: defaultProps }); await waitFor(() => { expect(screen.getByText('Select Tokens')).toBeInTheDocument(); - expect( - screen.getByText('Select the tokens that you want to use in your order.') - ).toBeInTheDocument(); + expect(screen.getByText('Select the tokens that you want to use in your order.')).toBeInTheDocument(); }); }); @@ -697,26 +673,7 @@ describe('DeploymentSteps', () => { new Error('Failed to initialize GUI') ); - render(DeploymentSteps, { - props: { - dotrain, - strategyDetail: { - name: 'SFLR<>WFLR on Flare', - description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.', - short_description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.' - }, - deployment: mockDeployment, - wagmiConfig: mockWagmiConfigStore, - wagmiConnected: mockConnectedStore, - appKitModal: writable({} as AppKit), - handleDeployModal: vi.fn() as unknown as (args: DeploymentArgs) => void, - handleDisclaimerModal: vi.fn() as unknown as ( - args: ComponentProps - ) => void, - settings: writable({} as ConfigSource), - handleUpdateGuiState: vi.fn() - } - }); + render(DeploymentSteps, { props: defaultProps }); await waitFor(() => { expect(screen.getByText('Error loading GUI')).toBeInTheDocument(); @@ -742,31 +699,13 @@ describe('DeploymentSteps', () => { getNetworkKey: vi.fn() }); - render(DeploymentSteps, { - props: { - dotrain, - strategyDetail: { - name: 'SFLR<>WFLR on Flare', - description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.', - short_description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.' - }, - deployment: mockDeployment, - wagmiConfig: mockWagmiConfigStore, - wagmiConnected: mockConnectedStore, - appKitModal: writable({} as AppKit), - handleDeployModal: vi.fn() as unknown as (args: DeploymentArgs) => void, - handleDisclaimerModal: vi.fn() as unknown as ( - args: ComponentProps - ) => void, - settings: writable({} as ConfigSource), - handleUpdateGuiState: vi.fn() - } - }); + render(DeploymentSteps, { props: defaultProps }); await waitFor(() => { expect(screen.getByText('Deploy Strategy')).toBeInTheDocument(); }); }); + it('shows connect wallet button when not connected', async () => { mockConnectedStore.mockSetSubscribeValue(false); (DotrainOrderGui.chooseDeployment as Mock).mockResolvedValue({ @@ -785,26 +724,7 @@ describe('DeploymentSteps', () => { getNetworkKey: vi.fn() }); - render(DeploymentSteps, { - props: { - dotrain, - strategyDetail: { - name: 'SFLR<>WFLR on Flare', - description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.', - short_description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.' - }, - deployment: mockDeployment, - wagmiConfig: mockWagmiConfigStore, - wagmiConnected: mockConnectedStore, - appKitModal: writable({} as AppKit), - handleDeployModal: vi.fn() as unknown as (args: DeploymentArgs) => void, - handleDisclaimerModal: vi.fn() as unknown as ( - args: ComponentProps - ) => void, - settings: writable({} as ConfigSource), - handleUpdateGuiState: vi.fn() - } - }); + render(DeploymentSteps, { props: defaultProps }); await waitFor(() => { expect(screen.getByText('Connect Wallet')).toBeInTheDocument(); diff --git a/packages/ui-components/src/__tests__/OrderDetail.test.ts b/packages/ui-components/src/__tests__/OrderDetail.test.ts index b87061ae4..b7dad943a 100644 --- a/packages/ui-components/src/__tests__/OrderDetail.test.ts +++ b/packages/ui-components/src/__tests__/OrderDetail.test.ts @@ -54,7 +54,6 @@ describe('OrderDetail Component', () => { id: 'mockId', subgraphUrl: 'https://example.com', walletAddressMatchesOrBlank: mockWalletAddressMatchesOrBlankStore, - wagmiConfig, chainId, orderbookAddress } @@ -87,7 +86,6 @@ describe('OrderDetail Component', () => { subgraphUrl: 'https://example.com', walletAddressMatchesOrBlank: mockWalletAddressMatchesOrBlankStore, handleOrderRemoveModal, - wagmiConfig, chainId, orderbookAddress } @@ -108,7 +106,6 @@ describe('OrderDetail Component', () => { subgraphUrl: 'https://example.com', walletAddressMatchesOrBlank: mockWalletAddressMatchesOrBlankStore, handleOrderRemoveModal: vi.fn(), - wagmiConfig, chainId, orderbookAddress } @@ -209,7 +206,6 @@ describe('OrderDetail Component', () => { id: mockOrderWithVaults.id, subgraphUrl: 'https://example.com', walletAddressMatchesOrBlank: mockWalletAddressMatchesOrBlankStore, - wagmiConfig, chainId, orderbookAddress } diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index c37866a41..32bc8fe56 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -25,7 +25,7 @@ import { onMount } from 'svelte'; import ShareChoicesButton from './ShareChoicesButton.svelte'; import { handleShareChoices } from '../../services/handleShareChoices'; - import type { DeploymentArgs, DisclaimerModalArgs } from '../../types/transaction'; + import type { DisclaimerModalProps, DeployModalProps } from '../../types/modal'; import { getDeploymentTransactionArgs } from './getDeploymentTransactionArgs'; import type { HandleAddOrderResult } from './getDeploymentTransactionArgs'; enum DeploymentStepErrors { @@ -47,8 +47,8 @@ export let deployment: GuiDeployment; export let strategyDetail: NameAndDescription; - export let handleDeployModal: (args: DeploymentArgs) => void; - export let handleDisclaimerModal: (args: DisclaimerModalArgs) => void; + export let handleDeployModal: (args: DeployModalProps) => void; + export let handleDisclaimerModal: (args: DisclaimerModalProps) => void; export let handleUpdateGuiState: (gui: DotrainOrderGui) => void; let selectTokens: SelectTokens | null = null; @@ -236,13 +236,19 @@ } handleDeployModal({ - ...result, - subgraphUrl: subgraphUrl, - network: networkKey + open: true, + args: { + ...result, + subgraphUrl: subgraphUrl, + network: networkKey + } }); }; - handleDisclaimerModal({ onAccept }); + handleDisclaimerModal({ + open: true, + onAccept + }); } const areAllTokensSelected = async () => { diff --git a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte index f791ed203..3f17a275a 100644 --- a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte @@ -38,7 +38,7 @@ export let colorTheme; export let codeMirrorTheme; export let lightweightChartsTheme; - export let orderbookAddress: Hex | undefined = undefined; + export let orderbookAddress: Hex; export let id: string; export let rpcUrl: string; export let subgraphUrl: string; diff --git a/packages/ui-components/src/lib/components/detail/VaultDetail.svelte b/packages/ui-components/src/lib/components/detail/VaultDetail.svelte index d60fee8c8..6c7a0b953 100644 --- a/packages/ui-components/src/lib/components/detail/VaultDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/VaultDetail.svelte @@ -22,10 +22,10 @@ import type { AppStoresInterface } from '../../types/appStores'; import type { Config } from 'wagmi'; import DepositOrWithdrawButtons from './DepositOrWithdrawButtons.svelte'; - import type { DepositOrWithdrawModalArgs } from '../../types/transaction'; + import type { DepositOrWithdrawModalProps } from '../../types/modal'; export let handleDepositOrWithdrawModal: - | ((args: DepositOrWithdrawModalArgs) => void) + | ((args: DepositOrWithdrawModalProps) => void) | undefined = undefined; export let id: string; export let network: string; diff --git a/tauri-app/src/routes/orders/[network]-[id]/+page.svelte b/tauri-app/src/routes/orders/[network]-[id]/+page.svelte index 49dc4f336..b7782d6e5 100644 --- a/tauri-app/src/routes/orders/[network]-[id]/+page.svelte +++ b/tauri-app/src/routes/orders/[network]-[id]/+page.svelte @@ -5,10 +5,10 @@ import { codeMirrorTheme, lightweightChartsTheme, colorTheme } from '$lib/stores/darkMode'; import { settings } from '$lib/stores/settings'; import { handleDebugTradeModal, handleQuoteDebugModal } from '$lib/services/modal'; - + import type { Hex } from 'viem'; const { id, network } = $page.params; - const orderbookAddress = $settings?.orderbooks?.[network]?.address; + const orderbookAddress = $settings?.orderbooks?.[network]?.address as Hex; const subgraphUrl = $settings?.subgraphs?.[network]; const rpcUrl = $settings?.networks?.[network]?.rpc; const chainId = $settings?.networks?.[network]?.['chain-id']; From 29f3e133f4ff80196c5b443fbb6de962e4602a09 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Mon, 17 Feb 2025 18:32:01 +0100 Subject: [PATCH 10/36] tweak message --- .../webapp/src/lib/components/DepositOrWithdrawModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte index b9a15ff84..3066c256e 100644 --- a/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte +++ b/packages/webapp/src/lib/components/DepositOrWithdrawModal.svelte @@ -46,7 +46,7 @@ let switchChainError = ''; const messages = { - success: 'Your transaction was successful.', + success: 'Transaction successful.', pending: 'Processing your transaction...', error: 'Transaction failed.' }; From 4a5fb724fbd4b791ed0112cfc03a65123c504411 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Mon, 17 Feb 2025 19:21:07 +0100 Subject: [PATCH 11/36] remove events WIP --- crates/js_api/src/subgraph/mod.rs | 1 + crates/js_api/src/subgraph/remove_order.rs | 16 ++ crates/subgraph/src/orderbook_client.rs | 21 +++ crates/subgraph/src/types/common.rs | 16 ++ crates/subgraph/src/types/mod.rs | 1 + crates/subgraph/src/types/remove_order.rs | 16 ++ .../orderbook/test/js_api/addOrder.test.ts | 1 + .../orderbook/test/js_api/removeOrder.test.ts | 145 ++++++++++++++++++ 8 files changed, 217 insertions(+) create mode 100644 crates/js_api/src/subgraph/remove_order.rs create mode 100644 crates/subgraph/src/types/remove_order.rs create mode 100644 packages/orderbook/test/js_api/removeOrder.test.ts diff --git a/crates/js_api/src/subgraph/mod.rs b/crates/js_api/src/subgraph/mod.rs index 7b843a1ba..6441ab039 100644 --- a/crates/js_api/src/subgraph/mod.rs +++ b/crates/js_api/src/subgraph/mod.rs @@ -9,6 +9,7 @@ use wasm_bindgen::{JsError, JsValue}; pub mod add_order; pub mod order; +pub mod remove_order; pub mod transaction; pub mod vault; diff --git a/crates/js_api/src/subgraph/remove_order.rs b/crates/js_api/src/subgraph/remove_order.rs new file mode 100644 index 000000000..472385799 --- /dev/null +++ b/crates/js_api/src/subgraph/remove_order.rs @@ -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 Remove Orders for a given transaction +/// Returns an array of RemoveOrder structs +#[wasm_bindgen(js_name = "getTransactionRemoveOrders")] +pub async fn get_transaction_remove_orders( + url: &str, + tx_hash: &str, +) -> Result { + let client = OrderbookSubgraphClient::new(Url::parse(url)?); + let remove_orders = client.transaction_remove_orders(Id::new(tx_hash)).await?; + Ok(to_value(&remove_orders)?) +} diff --git a/crates/subgraph/src/orderbook_client.rs b/crates/subgraph/src/orderbook_client.rs index c7096bc9f..b6d09b36b 100644 --- a/crates/subgraph/src/orderbook_client.rs +++ b/crates/subgraph/src/orderbook_client.rs @@ -9,6 +9,7 @@ use crate::types::order::{ OrdersListQuery, }; use crate::types::order_trade::{OrderTradeDetailQuery, OrderTradesListQuery}; +use crate::types::remove_order::{TransactionRemoveOrdersQuery, TransactionRemoveOrdersVariables}; use crate::types::transaction::TransactionDetailQuery; use crate::types::vault::{VaultDetailQuery, VaultsListQuery}; use crate::vault_balance_changes_query::VaultBalanceChangesListPageQueryClient; @@ -416,4 +417,24 @@ impl OrderbookSubgraphClient { Ok(data.add_orders) } + + /// Fetch all remove orders for a given transaction + pub async fn transaction_remove_orders( + &self, + id: Id, + ) -> Result, OrderbookSubgraphClientError> { + let data = self + .query::( + TransactionRemoveOrdersVariables { + id: Bytes(id.inner().to_string()), + }, + ) + .await?; + + if data.remove_orders.is_empty() { + return Err(OrderbookSubgraphClientError::Empty); + } + + Ok(data.remove_orders) + } } diff --git a/crates/subgraph/src/types/common.rs b/crates/subgraph/src/types/common.rs index 18404311d..77d5da20e 100644 --- a/crates/subgraph/src/types/common.rs +++ b/crates/subgraph/src/types/common.rs @@ -97,6 +97,7 @@ pub struct Order { pub meta: Option, pub add_events: Vec, pub trades: Vec, + pub remove_events: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -381,6 +382,12 @@ pub struct Transaction { pub struct AddOrder { pub transaction: Transaction, } +#[derive(cynic::QueryFragment, Debug, Serialize, Clone)] +#[cfg_attr(target_family = "wasm", derive(Tsify))] +#[typeshare] +pub struct RemoveOrder { + pub transaction: Transaction, +} #[derive(cynic::QueryFragment, Debug, Serialize, Clone)] #[cfg_attr(target_family = "wasm", derive(Tsify))] @@ -391,6 +398,15 @@ pub struct AddOrderWithOrder { pub order: Order, } +#[derive(cynic::QueryFragment, Debug, Serialize, Clone)] +#[cfg_attr(target_family = "wasm", derive(Tsify))] +#[cynic(graphql_type = "RemoveOrder")] +pub struct RemoveOrderWithOrder { + pub transaction: Transaction, + #[cfg_attr(target_family = "wasm", tsify(type = "OrderSubgraph"))] + pub order: Order, +} + #[derive(cynic::Scalar, Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(target_family = "wasm", derive(Tsify), serde(rename = "SgBigInt"))] #[typeshare] diff --git a/crates/subgraph/src/types/mod.rs b/crates/subgraph/src/types/mod.rs index 59d6e66af..72b169a62 100644 --- a/crates/subgraph/src/types/mod.rs +++ b/crates/subgraph/src/types/mod.rs @@ -4,6 +4,7 @@ mod impls; pub mod order; pub mod order_detail_traits; pub mod order_trade; +pub mod remove_order; pub mod transaction; pub mod vault; diff --git a/crates/subgraph/src/types/remove_order.rs b/crates/subgraph/src/types/remove_order.rs new file mode 100644 index 000000000..7359ca178 --- /dev/null +++ b/crates/subgraph/src/types/remove_order.rs @@ -0,0 +1,16 @@ +use super::common::{Bytes, RemoveOrderWithOrder}; +use crate::schema; +use typeshare::typeshare; + +#[derive(cynic::QueryVariables, Debug)] +pub struct TransactionRemoveOrdersVariables { + pub id: Bytes, +} + +#[derive(cynic::QueryFragment, Debug)] +#[cynic(graphql_type = "Query", variables = "TransactionRemoveOrdersVariables")] +#[typeshare] +pub struct TransactionRemoveOrdersQuery { + #[arguments(where: { transaction_: { id: $id } })] + pub remove_orders: Vec, +} diff --git a/packages/orderbook/test/js_api/addOrder.test.ts b/packages/orderbook/test/js_api/addOrder.test.ts index 5bcc1cc3c..154bb13fa 100644 --- a/packages/orderbook/test/js_api/addOrder.test.ts +++ b/packages/orderbook/test/js_api/addOrder.test.ts @@ -19,6 +19,7 @@ const mockAddOrder: AddOrderWithOrder = { timestamp: '1739448802' }, order: { + removeEvents: [], id: '0x1a69eeb7970d3c8d5776493327fb262e31fc880c9cc4a951607418a7963d9fa1', orderBytes: '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000f08bcbce72f62c95dcb7c07dcb5ed26acfcfbc1100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000640392c489ef67afdc348209452c338ea5ba2b6152b936e152f610d05e1a20621a40000000000000000000000005fb33d710f8b58de4c9fdec703b5c2487a5219d600000000000000000000000084c6e7f5a1e5dd89594cc25bef4722a1b8871ae60000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000049d000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000c7d713b49da0000914d696e20747261646520616d6f756e742e00000000000000000000000000008b616d6f756e742d75736564000000000000000000000000000000000000000000000000000000000000000000000000000000000000000340aad21b3b70000000000000000000000000000000000000000000000000006194049f30f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000e043da6172500008f6c6173742d74726164652d74696d65000000000000000000000000000000008d6c6173742d74726164652d696f0000000000000000000000000000000000008c696e697469616c2d74696d650000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f05b59d3b200000000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000020000915e36ef882941816356bc3718df868054f868ad000000000000000000000000000000000000000000000000000000000000027d0a00000024007400e0015801b401e001f40218025c080500040b20000200100001001000000b120003001000010b110004001000030b0100051305000201100001011000003d120000011000020010000003100404211200001d02000001100003031000010c1200004911000003100404001000012b12000001100003031000010c1200004a0200001a0b00090b1000060b20000700100000001000011b1200001a10000047120000001000001a1000004712000001100000011000002e12000001100005011000042e120000001000053d12000001100004001000042e1200000010000601100005001000032e120000481200011d0b020a0010000001100000011000062713000001100003031000010c12000049110000001000030010000247120000001000010b110008001000050110000700100001201200001f12000001100000011000004712000000100006001000073d120000011000002b12000000100008001000043b120000160901080b1000070b10000901100008001000013d1200001b12000001100006001000013d1200000b100009001000033a120000001000040010000248120001001000000b110008001000053d12000000100006001000042b1200000a0401011a10000001100009031000010c1200004a020000001000000110000a031000010c1200004a020000040200010110000b031000010c120000491100000803000201100009031000010c120000491100000110000a031000010c12000049110000100c01030110000d001000002e1200000110000c3e120000001000010010000100100001001000010010000100100001001000010010000100100001001000013d1a0000020100010210000e3611000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001d80c49bbbcd1c0911346656b529df9e5c2f783d0000000000000000000000000000000000000000000000000000000000000012a6e3c06415539f92823a18ba63e1c0303040c4892970a0d1e3a27663d7583b33000000000000000000000000000000000000000000000000000000000000000100000000000000000000000012e605bc104e93b45e1ad99f9e555f659051c2bb0000000000000000000000000000000000000000000000000000000000000012a6e3c06415539f92823a18ba63e1c0303040c4892970a0d1e3a27663d7583b33', diff --git a/packages/orderbook/test/js_api/removeOrder.test.ts b/packages/orderbook/test/js_api/removeOrder.test.ts new file mode 100644 index 000000000..2ccfaf6fa --- /dev/null +++ b/packages/orderbook/test/js_api/removeOrder.test.ts @@ -0,0 +1,145 @@ +import assert from 'assert'; +import { getLocal } from 'mockttp'; +import { describe, it, beforeEach, afterEach } from 'vitest'; +import { Transaction, RemoveOrderWithOrder } from '../../dist/types/js_api.js'; +import { getTransactionRemoveOrders } from '../../dist/cjs/js_api.js'; + +const transaction1: Transaction = { + id: '0x0da3659c0fd5258e962bf339afeaffddb06cc7a473802228b9586fe7503ed13a', + from: '0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11', + blockNumber: '37623990', + timestamp: '1739815758' +}; + +const mockRemoveOrder: RemoveOrderWithOrder = { + transaction: { + id: '0x0da3659c0fd5258e962bf339afeaffddb06cc7a473802228b9586fe7503ed13a', + from: '0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11', + blockNumber: '37623990', + timestamp: '1739815758' + }, + order: { + id: '0xd1639ec740f1fcfa7ca4aac827df554a03e88a36f13818d08ed77863f1be8177', + orderBytes: + '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000f08bcbce72f62c95dcb7c07dcb5ed26acfcfbc1100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000260a815e3d897b3376629372a3afc69a320a611d52f3cf914335b9bc31021eec2990000000000000000000000005fb33d710f8b58de4c9fdec703b5c2487a5219d600000000000000000000000084c6e7f5a1e5dd89594cc25bef4722a1b8871ae6000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000020000000000000000000000001d80c49bbbcd1c0911346656b529df9e5c2f783d0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000002d0200000024080500021810000001100001361100000110000101100000031000041e12000022130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001d80c49bbbcd1c0911346656b529df9e5c2f783d0000000000000000000000000000000000000000000000000000000000000012d863ddba8cdc7d7c413aa97726cfab247fe88490a271785ae7bfee35fdc4765600000000000000000000000000000000000000000000000000000000000000010000000000000000000000001d80c49bbbcd1c0911346656b529df9e5c2f783d0000000000000000000000000000000000000000000000000000000000000012d863ddba8cdc7d7c413aa97726cfab247fe88490a271785ae7bfee35fdc47656', + orderHash: '0xb0d70b12a2ddb9fd96b5a5f20d778c4adf81d5c9c9b7755b7ca2f015545f9077', + owner: '0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11', + outputs: [ + { + id: '0x62505c1dc17df48ee33b6365accc6f022e04a56ec326ed94ad42d6af2e1e2cc7', + owner: '0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11', + vaultId: '97876023468725745973349024037907513632727724269320958133054700715755104925270', + balance: '0', + token: { + id: '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', + address: '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', + name: 'Wrapped Flare', + symbol: 'WFLR', + decimals: '18' + }, + orderbook: { + id: '0xcee8cd002f151a536394e564b84076c41bbbcd4d' + }, + ordersAsOutput: [ + { + id: '0xd1639ec740f1fcfa7ca4aac827df554a03e88a36f13818d08ed77863f1be8177', + orderHash: '0xb0d70b12a2ddb9fd96b5a5f20d778c4adf81d5c9c9b7755b7ca2f015545f9077', + active: false + } + ], + ordersAsInput: [ + { + id: '0xd1639ec740f1fcfa7ca4aac827df554a03e88a36f13818d08ed77863f1be8177', + orderHash: '0xb0d70b12a2ddb9fd96b5a5f20d778c4adf81d5c9c9b7755b7ca2f015545f9077', + active: false + } + ], + balanceChanges: [] + } + ], + inputs: [ + { + id: '0x62505c1dc17df48ee33b6365accc6f022e04a56ec326ed94ad42d6af2e1e2cc7', + owner: '0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11', + vaultId: '97876023468725745973349024037907513632727724269320958133054700715755104925270', + balance: '0', + token: { + id: '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', + address: '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', + name: 'Wrapped Flare', + symbol: 'WFLR', + decimals: '18' + }, + orderbook: { + id: '0xcee8cd002f151a536394e564b84076c41bbbcd4d' + }, + ordersAsOutput: [ + { + id: '0xd1639ec740f1fcfa7ca4aac827df554a03e88a36f13818d08ed77863f1be8177', + orderHash: '0xb0d70b12a2ddb9fd96b5a5f20d778c4adf81d5c9c9b7755b7ca2f015545f9077', + active: false + } + ], + ordersAsInput: [ + { + id: '0xd1639ec740f1fcfa7ca4aac827df554a03e88a36f13818d08ed77863f1be8177', + orderHash: '0xb0d70b12a2ddb9fd96b5a5f20d778c4adf81d5c9c9b7755b7ca2f015545f9077', + active: false + } + ], + balanceChanges: [] + } + ], + orderbook: { + id: '0xcee8cd002f151a536394e564b84076c41bbbcd4d' + }, + active: false, + timestampAdded: '1739813495', + meta: '0xff0a89c674ee7874a30058ed2f2a20302e2063616c63756c6174652d696f202a2f200a7573696e672d776f7264732d66726f6d203078466532343131434461313933443945346538334135633233344337466433323031303138383361430a6d61782d6f75747075743a206d61782d76616c756528292c0a696f3a206966280a2020657175616c2d746f280a202020206f75747075742d746f6b656e28290a202020203078316438306334396262626364316330393131333436363536623532396466396535633266373833640a2020290a2020310a2020696e762831290a293b0a0a2f2a20312e2068616e646c652d696f202a2f200a3a3b011bff13109e41336ff20278186170706c69636174696f6e2f6f637465742d73747265616d', + addEvents: [ + { + transaction: { + id: '0xea3caf78e023487df10792f0a86d6988e165ff514870ef66f31a1c928874c982', + from: '0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11', + blockNumber: '37622839', + timestamp: '1739813495' + } + } + ], + trades: [], + removeEvents: [ + { + transaction: { + id: '0x0da3659c0fd5258e962bf339afeaffddb06cc7a473802228b9586fe7503ed13a', + from: '0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11', + blockNumber: '37623990', + timestamp: '1739815758' + } + } + ] + } +}; + +const removeOrders: RemoveOrderWithOrder[] = [mockRemoveOrder]; + +describe('Rain Orderbook JS API Package Bindgen Tests - Remove Order', async function () { + const mockServer = getLocal(); + beforeEach(() => mockServer.start(8099)); + afterEach(() => mockServer.stop()); + + it('should fetch remove orders for a transaction', async () => { + await mockServer + .forPost('/sg1') + .thenReply(200, JSON.stringify({ data: { removeOrders: removeOrders } })); + try { + const result: RemoveOrderWithOrder[] = await getTransactionRemoveOrders( + mockServer.url, + transaction1.id + ); + console.log(JSON.stringify(result, null, 2)); + assert.equal(result[0].order.id, mockRemoveOrder.order.id); + } catch (e) { + assert.fail('expected to resolve, but failed' + (e instanceof Error ? e.message : String(e))); + } + }); +}); From bb04d0a338595a12c0441c218220e8476030cda8 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Mon, 17 Feb 2025 19:24:12 +0100 Subject: [PATCH 12/36] format --- packages/ui-components/src/__tests__/DeploymentSteps.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts index 525b8ef7d..59638aca4 100644 --- a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts +++ b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts @@ -664,7 +664,9 @@ describe('DeploymentSteps', () => { await waitFor(() => { expect(screen.getByText('Select Tokens')).toBeInTheDocument(); - expect(screen.getByText('Select the tokens that you want to use in your order.')).toBeInTheDocument(); + expect( + screen.getByText('Select the tokens that you want to use in your order.') + ).toBeInTheDocument(); }); }); From 5affb033b2745ec231f3c30cdfca4b6afb2eeab1 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Mon, 17 Feb 2025 19:42:52 +0100 Subject: [PATCH 13/36] rrmm --- packages/ui-components/src/__tests__/OrderDetail.test.svelte | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ui-components/src/__tests__/OrderDetail.test.svelte b/packages/ui-components/src/__tests__/OrderDetail.test.svelte index fe3655ac9..b779e0b72 100644 --- a/packages/ui-components/src/__tests__/OrderDetail.test.svelte +++ b/packages/ui-components/src/__tests__/OrderDetail.test.svelte @@ -10,9 +10,8 @@ import { Button } from 'flowbite-svelte'; import DepositOrWithdrawButtons from '../lib/components/detail/DepositOrWithdrawButtons.svelte'; import type { OrderRemoveModalProps } from '../lib/types/modal'; - - import type { Config } from 'wagmi'; import type { Hex } from 'viem'; + export let walletAddressMatchesOrBlank: Readable<(address: string) => boolean> | undefined = undefined; export let handleOrderRemoveModal: ((props: OrderRemoveModalProps) => void) | undefined = From 35190958ee31eebd0e314614f602cd8dfa419df3 Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 10:53:23 +0300 Subject: [PATCH 14/36] create any functions for deposits and vault ids --- crates/js_api/src/gui/deposits.rs | 5 +++++ crates/js_api/src/gui/order_operations.rs | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/crates/js_api/src/gui/deposits.rs b/crates/js_api/src/gui/deposits.rs index edcd741bf..b8b885e56 100644 --- a/crates/js_api/src/gui/deposits.rs +++ b/crates/js_api/src/gui/deposits.rs @@ -138,4 +138,9 @@ impl DotrainOrderGui { } Ok(missing_deposits) } + + #[wasm_bindgen(js_name = "hasAnyDeposit")] + pub fn has_any_deposit(&self) -> bool { + !self.deposits.is_empty() + } } diff --git a/crates/js_api/src/gui/order_operations.rs b/crates/js_api/src/gui/order_operations.rs index cf4c8572f..4b6438234 100644 --- a/crates/js_api/src/gui/order_operations.rs +++ b/crates/js_api/src/gui/order_operations.rs @@ -344,6 +344,12 @@ impl DotrainOrderGui { Ok(IOVaultIds(map)) } + #[wasm_bindgen(js_name = "hasAnyVaultId")] + pub fn has_any_vault_id(&self) -> Result { + let map = self.get_vault_ids()?; + Ok(map.0.values().any(|ids| ids.iter().any(|id| id.is_some()))) + } + #[wasm_bindgen(js_name = "updateScenarioBindings")] pub fn update_scenario_bindings(&mut self) -> Result<(), GuiError> { let deployment = self.get_current_deployment()?; From d8337de5732d97291f90f7e5110ec3efbbdacfd9 Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 10:53:28 +0300 Subject: [PATCH 15/36] update tests --- packages/orderbook/test/js_api/gui.test.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/orderbook/test/js_api/gui.test.ts b/packages/orderbook/test/js_api/gui.test.ts index 2204bca30..d270a594a 100644 --- a/packages/orderbook/test/js_api/gui.test.ts +++ b/packages/orderbook/test/js_api/gui.test.ts @@ -5,11 +5,9 @@ import { AddOrderCalldataResult, AllFieldValuesResult, AllowancesResult, - ApprovalCalldataResult, DeploymentDetails, DeploymentKeys, DepositAndAddOrderCalldataResult, - DepositCalldataResult, Gui, GuiDeployment, IOVaultIds, @@ -447,9 +445,13 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () }); it('should add deposit', async () => { + assert.equal(gui.hasAnyDeposit(), false); + gui.saveDeposit('token1', '50.6'); const deposits: TokenDeposit[] = gui.getDeposits(); assert.equal(deposits.length, 1); + + assert.equal(gui.hasAnyDeposit(), true); }); it('should update deposit', async () => { @@ -1178,8 +1180,12 @@ ${dotrainWithoutVaultIds}`; assert.equal(currentDeployment.deployment.order.inputs[0].vaultId, undefined); assert.equal(currentDeployment.deployment.order.outputs[0].vaultId, undefined); + assert.equal(gui.hasAnyVaultId(), false); + gui.setVaultId(true, 0, '0x123'); + assert.equal(gui.hasAnyVaultId(), true); + assert.equal(gui.getVaultIds().get('input')?.[0], '0x123'); assert.equal(gui.getVaultIds().get('output')?.[0], undefined); From 45b760833353529c4fbb7914289776ac0a937769 Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 10:54:29 +0300 Subject: [PATCH 16/36] update UI --- .../lib/components/deployment/DeploymentSteps.svelte | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index 08d9354b5..bb025128c 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -254,15 +254,9 @@ if (!allTokensSelected) return; // if we have deposits or vault ids set, show advanced options - const vaultIds = gui.getVaultIds(); - const inputVaultIds = vaultIds.get('input'); - const outputVaultIds = vaultIds.get('output'); - const deposits = gui.getDeposits(); - if ( - deposits.length > 0 || - (inputVaultIds && inputVaultIds.some((v) => v)) || - (outputVaultIds && outputVaultIds.some((v) => v)) - ) { + const hasDeposits = gui.hasAnyDeposit(); + const hasVaultIds = gui.hasAnyVaultId(); + if (hasDeposits || hasVaultIds) { showAdvancedOptions = true; } } catch (e) { From 45dc5ad0bdd0e8f11c406150c994006f8f3d55b2 Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 11:20:01 +0300 Subject: [PATCH 17/36] fix tests --- crates/subgraph/src/types/common.rs | 2 +- packages/orderbook/test/js_api/addOrder.test.ts | 4 ++-- packages/orderbook/test/js_api/order.test.ts | 9 ++++++--- packages/orderbook/test/js_api/removeOrder.test.ts | 8 ++++---- packages/orderbook/test/js_api/vault.test.ts | 3 ++- packages/orderbook/test/quote/test.test.ts | 14 ++++++++------ 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/crates/subgraph/src/types/common.rs b/crates/subgraph/src/types/common.rs index 77d5da20e..39da8c964 100644 --- a/crates/subgraph/src/types/common.rs +++ b/crates/subgraph/src/types/common.rs @@ -97,7 +97,7 @@ pub struct Order { pub meta: Option, pub add_events: Vec, pub trades: Vec, - pub remove_events: Option>, + pub remove_events: Vec, } #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/packages/orderbook/test/js_api/addOrder.test.ts b/packages/orderbook/test/js_api/addOrder.test.ts index 154bb13fa..49cda9e52 100644 --- a/packages/orderbook/test/js_api/addOrder.test.ts +++ b/packages/orderbook/test/js_api/addOrder.test.ts @@ -19,7 +19,6 @@ const mockAddOrder: AddOrderWithOrder = { timestamp: '1739448802' }, order: { - removeEvents: [], id: '0x1a69eeb7970d3c8d5776493327fb262e31fc880c9cc4a951607418a7963d9fa1', orderBytes: '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000f08bcbce72f62c95dcb7c07dcb5ed26acfcfbc1100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000640392c489ef67afdc348209452c338ea5ba2b6152b936e152f610d05e1a20621a40000000000000000000000005fb33d710f8b58de4c9fdec703b5c2487a5219d600000000000000000000000084c6e7f5a1e5dd89594cc25bef4722a1b8871ae60000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000049d000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000c7d713b49da0000914d696e20747261646520616d6f756e742e00000000000000000000000000008b616d6f756e742d75736564000000000000000000000000000000000000000000000000000000000000000000000000000000000000000340aad21b3b70000000000000000000000000000000000000000000000000006194049f30f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000e043da6172500008f6c6173742d74726164652d74696d65000000000000000000000000000000008d6c6173742d74726164652d696f0000000000000000000000000000000000008c696e697469616c2d74696d650000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f05b59d3b200000000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000020000915e36ef882941816356bc3718df868054f868ad000000000000000000000000000000000000000000000000000000000000027d0a00000024007400e0015801b401e001f40218025c080500040b20000200100001001000000b120003001000010b110004001000030b0100051305000201100001011000003d120000011000020010000003100404211200001d02000001100003031000010c1200004911000003100404001000012b12000001100003031000010c1200004a0200001a0b00090b1000060b20000700100000001000011b1200001a10000047120000001000001a1000004712000001100000011000002e12000001100005011000042e120000001000053d12000001100004001000042e1200000010000601100005001000032e120000481200011d0b020a0010000001100000011000062713000001100003031000010c12000049110000001000030010000247120000001000010b110008001000050110000700100001201200001f12000001100000011000004712000000100006001000073d120000011000002b12000000100008001000043b120000160901080b1000070b10000901100008001000013d1200001b12000001100006001000013d1200000b100009001000033a120000001000040010000248120001001000000b110008001000053d12000000100006001000042b1200000a0401011a10000001100009031000010c1200004a020000001000000110000a031000010c1200004a020000040200010110000b031000010c120000491100000803000201100009031000010c120000491100000110000a031000010c12000049110000100c01030110000d001000002e1200000110000c3e120000001000010010000100100001001000010010000100100001001000010010000100100001001000013d1a0000020100010210000e3611000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001d80c49bbbcd1c0911346656b529df9e5c2f783d0000000000000000000000000000000000000000000000000000000000000012a6e3c06415539f92823a18ba63e1c0303040c4892970a0d1e3a27663d7583b33000000000000000000000000000000000000000000000000000000000000000100000000000000000000000012e605bc104e93b45e1ad99f9e555f659051c2bb0000000000000000000000000000000000000000000000000000000000000012a6e3c06415539f92823a18ba63e1c0303040c4892970a0d1e3a27663d7583b33', @@ -353,7 +352,8 @@ const mockAddOrder: AddOrderWithOrder = { } } ], - trades: [] + trades: [], + removeEvents: [] } }; diff --git a/packages/orderbook/test/js_api/order.test.ts b/packages/orderbook/test/js_api/order.test.ts index dda2643c0..e7065cea9 100644 --- a/packages/orderbook/test/js_api/order.test.ts +++ b/packages/orderbook/test/js_api/order.test.ts @@ -81,7 +81,8 @@ const order1 = { orderbook: { id: '0x0000000000000000000000000000000000000000' }, - trades: [] + trades: [], + removeEvents: [] }; const order2 = { id: 'order2', @@ -147,7 +148,8 @@ const order2 = { orderbook: { id: '0x0000000000000000000000000000000000000000' }, - trades: [] + trades: [], + removeEvents: [] } as unknown as OrderSubgraph; export const order3 = { @@ -214,7 +216,8 @@ export const order3 = { orderbook: { id: '0x0000000000000000000000000000000000000000' }, - trades: [] + trades: [], + removeEvents: [] }; const mockOrderTradesList: Trade[] = [ diff --git a/packages/orderbook/test/js_api/removeOrder.test.ts b/packages/orderbook/test/js_api/removeOrder.test.ts index 2ccfaf6fa..c16b97e89 100644 --- a/packages/orderbook/test/js_api/removeOrder.test.ts +++ b/packages/orderbook/test/js_api/removeOrder.test.ts @@ -6,9 +6,9 @@ import { getTransactionRemoveOrders } from '../../dist/cjs/js_api.js'; const transaction1: Transaction = { id: '0x0da3659c0fd5258e962bf339afeaffddb06cc7a473802228b9586fe7503ed13a', - from: '0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11', - blockNumber: '37623990', - timestamp: '1739815758' + from: '0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11', + blockNumber: '37623990', + timestamp: '1739815758' }; const mockRemoveOrder: RemoveOrderWithOrder = { @@ -133,7 +133,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Remove Order', async fun .thenReply(200, JSON.stringify({ data: { removeOrders: removeOrders } })); try { const result: RemoveOrderWithOrder[] = await getTransactionRemoveOrders( - mockServer.url, + mockServer.url + '/sg1', transaction1.id ); console.log(JSON.stringify(result, null, 2)); diff --git a/packages/orderbook/test/js_api/vault.test.ts b/packages/orderbook/test/js_api/vault.test.ts index fe8e53a72..a268d0f94 100644 --- a/packages/orderbook/test/js_api/vault.test.ts +++ b/packages/orderbook/test/js_api/vault.test.ts @@ -231,7 +231,8 @@ describe('Rain Orderbook JS API Package Bindgen Vault Tests', async function () orderbook: { id: '0x0000000000000000000000000000000000000000' }, - trades: [] + trades: [], + removeEvents: [] }; it('should get deposit calldata for a vault', async () => { diff --git a/packages/orderbook/test/quote/test.test.ts b/packages/orderbook/test/quote/test.test.ts index a45d0ebbc..a7558762e 100644 --- a/packages/orderbook/test/quote/test.test.ts +++ b/packages/orderbook/test/quote/test.test.ts @@ -5,8 +5,7 @@ import { QuoteSpec, QuoteTarget, OrderQuoteValue, - BatchOrderQuotesResponse, - Order + BatchOrderQuotesResponse } from '../../dist/types/quote'; import { getId, @@ -14,6 +13,7 @@ import { getQuoteTargetFromSubgraph, getOrderQuote } from '../../dist/cjs/quote'; +import { OrderSubgraph } from '../../dist/types/js_api'; describe('Rain Orderbook Quote Package Bindgen Tests', async function () { const mockServer = getLocal(); @@ -98,7 +98,8 @@ describe('Rain Orderbook Quote Package Bindgen Tests', async function () { orderbook: { id: '0x0000000000000000000000000000000000000000' }, - trades: [] + trades: [], + removeEvents: [] } ] } @@ -208,7 +209,7 @@ describe('Rain Orderbook Quote Package Bindgen Tests', async function () { .thenSendJsonRpcResult( '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002' ); - const order: Order = { + const order = { id: '0x46891c626a8a188610b902ee4a0ce8a7e81915e1b922584f8168d14525899dfb', orderBytes: '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', @@ -272,8 +273,9 @@ describe('Rain Orderbook Quote Package Bindgen Tests', async function () { orderbook: { id: '0x0000000000000000000000000000000000000000' }, - trades: [] - }; + trades: [], + removeEvents: [] + } as unknown as OrderSubgraph; const result = await getOrderQuote([order], mockServer.url + '/rpc-url'); const expected: BatchOrderQuotesResponse[] = [ { From 31fb0375db336b7f16165ff25c06d16d65b64bfa Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 11:44:56 +0300 Subject: [PATCH 18/36] create helper for pre calldata generation --- crates/js_api/src/gui/order_operations.rs | 65 +++++++++++++++-------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/crates/js_api/src/gui/order_operations.rs b/crates/js_api/src/gui/order_operations.rs index cf4c8572f..54c54067a 100644 --- a/crates/js_api/src/gui/order_operations.rs +++ b/crates/js_api/src/gui/order_operations.rs @@ -9,6 +9,14 @@ use rain_orderbook_bindings::OrderBook::multicallCall; use rain_orderbook_common::{deposit::DepositArgs, dotrain_order, transaction::TransactionArgs}; use std::{collections::HashMap, str::FromStr, sync::Arc}; +pub enum CalldataFunction { + Allowance, + Approval, + Deposit, + AddOrder, + DepositAndAddOrder, +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] pub struct TokenAllowance { @@ -53,6 +61,10 @@ impl_all_wasm_traits!(DepositAndAddOrderCalldataResult); pub struct IOVaultIds(HashMap>>); impl_all_wasm_traits!(IOVaultIds); +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] +pub struct DeploymentTransactionArgs {} +impl_all_wasm_traits!(DeploymentTransactionArgs); + #[wasm_bindgen] impl DotrainOrderGui { fn get_orderbook(&self) -> Result, GuiError> { @@ -129,13 +141,32 @@ impl DotrainOrderGui { }) } + fn prepare_calldata_generation( + &mut self, + calldata_function: CalldataFunction, + ) -> Result { + let deployment = self.get_current_deployment()?; + self.check_select_tokens()?; + match calldata_function { + CalldataFunction::Deposit => { + self.populate_vault_ids(&deployment)?; + } + CalldataFunction::AddOrder | CalldataFunction::DepositAndAddOrder => { + self.check_field_values()?; + self.populate_vault_ids(&deployment)?; + self.update_bindings(&deployment)?; + } + _ => {} + } + Ok(self.get_current_deployment()?) + } + /// Check allowances for all inputs and outputs of the order /// /// Returns a vector of [`TokenAllowance`] objects #[wasm_bindgen(js_name = "checkAllowances")] - pub async fn check_allowances(&self, owner: String) -> Result { - let deployment = self.get_current_deployment()?; - self.check_select_tokens()?; + pub async fn check_allowances(&mut self, owner: String) -> Result { + let deployment = self.prepare_calldata_generation(CalldataFunction::Allowance)?; let orderbook = self.get_orderbook()?; let vaults_and_deposits = self.get_vaults_and_deposits(&deployment).await?; @@ -166,11 +197,10 @@ impl DotrainOrderGui { /// Returns a vector of [`ApprovalCalldata`] objects #[wasm_bindgen(js_name = "generateApprovalCalldatas")] pub async fn generate_approval_calldatas( - &self, + &mut self, owner: String, ) -> Result { - let deployment = self.get_current_deployment()?; - self.check_select_tokens()?; + let deployment = self.prepare_calldata_generation(CalldataFunction::Approval)?; let deposits_map = self.get_deposits_as_map().await?; if deposits_map.is_empty() { @@ -210,10 +240,7 @@ impl DotrainOrderGui { /// Returns a vector of bytes #[wasm_bindgen(js_name = "generateDepositCalldatas")] pub async fn generate_deposit_calldatas(&mut self) -> Result { - let deployment = self.get_current_deployment()?; - self.check_select_tokens()?; - self.populate_vault_ids(&deployment)?; - let deployment = self.get_current_deployment()?; + let deployment = self.prepare_calldata_generation(CalldataFunction::Deposit)?; let token_deposits = self .get_vaults_and_deposits(&deployment) @@ -251,13 +278,7 @@ impl DotrainOrderGui { pub async fn generate_add_order_calldata( &mut self, ) -> Result { - let deployment = self.get_current_deployment()?; - self.check_select_tokens()?; - self.check_field_values()?; - self.populate_vault_ids(&deployment)?; - self.update_bindings(&deployment)?; - let deployment = self.get_current_deployment()?; - + let deployment = self.prepare_calldata_generation(CalldataFunction::AddOrder)?; let calldata = self .dotrain_order .generate_add_order_calldata(&deployment.key) @@ -269,12 +290,7 @@ impl DotrainOrderGui { pub async fn generate_deposit_and_add_order_calldatas( &mut self, ) -> Result { - let deployment = self.get_current_deployment()?; - self.check_select_tokens()?; - self.check_field_values()?; - self.populate_vault_ids(&deployment)?; - self.update_bindings(&deployment)?; - let deployment = self.get_current_deployment()?; + let deployment = self.prepare_calldata_generation(CalldataFunction::DepositAndAddOrder)?; let mut calls = Vec::new(); @@ -350,4 +366,7 @@ impl DotrainOrderGui { self.update_bindings(&deployment)?; Ok(()) } + + // #[wasm_bindgen(js_name = "getDeploymentTransactionArgs")] + // pub fn get_deployment_transaction_args(&self) -> Result {} } From d9c3153cac2745c554d6a68a5ee1f60097d37e33 Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 13:05:24 +0300 Subject: [PATCH 19/36] add new wasm function to get deployment transaction args --- crates/common/src/dotrain_order/calldata.rs | 4 +- crates/js_api/src/gui/order_operations.rs | 66 ++++++++++++++++++++- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/crates/common/src/dotrain_order/calldata.rs b/crates/common/src/dotrain_order/calldata.rs index 72ad88686..ed48a0c05 100644 --- a/crates/common/src/dotrain_order/calldata.rs +++ b/crates/common/src/dotrain_order/calldata.rs @@ -15,9 +15,9 @@ use std::{collections::HashMap, str::FromStr, sync::Arc}; #[cfg_attr(target_family = "wasm", derive(Tsify))] pub struct ApprovalCalldata { #[cfg_attr(target_family = "wasm", tsify(type = "string"))] - token: Address, + pub token: Address, #[cfg_attr(target_family = "wasm", tsify(type = "string"))] - calldata: Bytes, + pub calldata: Bytes, } #[cfg(target_family = "wasm")] impl_all_wasm_traits!(ApprovalCalldata); diff --git a/crates/js_api/src/gui/order_operations.rs b/crates/js_api/src/gui/order_operations.rs index 54c54067a..b46a88c27 100644 --- a/crates/js_api/src/gui/order_operations.rs +++ b/crates/js_api/src/gui/order_operations.rs @@ -62,7 +62,19 @@ pub struct IOVaultIds(HashMap>>); impl_all_wasm_traits!(IOVaultIds); #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] -pub struct DeploymentTransactionArgs {} +pub struct ExtendedApprovalCalldata { + calldata: Bytes, + symbol: String, +} +impl_all_wasm_traits!(ExtendedApprovalCalldata); + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] +pub struct DeploymentTransactionArgs { + approvals: Vec, + deployment_calldata: Bytes, + orderbook_address: Address, + chain_id: u64, +} impl_all_wasm_traits!(DeploymentTransactionArgs); #[wasm_bindgen] @@ -367,6 +379,54 @@ impl DotrainOrderGui { Ok(()) } - // #[wasm_bindgen(js_name = "getDeploymentTransactionArgs")] - // pub fn get_deployment_transaction_args(&self) -> Result {} + #[wasm_bindgen(js_name = "getDeploymentTransactionArgs")] + pub async fn get_deployment_transaction_args( + &mut self, + owner: String, + ) -> Result { + let deployment = self.prepare_calldata_generation(CalldataFunction::DepositAndAddOrder)?; + + let mut approvals = Vec::new(); + let approval_calldata = self.generate_approval_calldatas(owner).await?; + match approval_calldata { + ApprovalCalldataResult::Calldatas(calldatas) => { + let mut output_token_infos = HashMap::new(); + for output in deployment.deployment.order.outputs.clone() { + if output.token.is_none() { + return Err(GuiError::SelectTokensNotSet); + } + let token = output.token.as_ref().unwrap(); + let token_info = self.get_token_info(token.key.clone()).await?; + output_token_infos.insert(token.address.clone(), token_info); + } + + for calldata in calldatas.iter() { + let token_info = output_token_infos + .get(&calldata.token) + .ok_or(GuiError::TokenNotFound(calldata.token.to_string()))?; + approvals.push(ExtendedApprovalCalldata { + calldata: calldata.calldata.clone(), + symbol: token_info.symbol.clone(), + }); + } + } + _ => {} + } + + let deposit_and_add_order_calldata = + self.generate_deposit_and_add_order_calldatas().await?; + + Ok(DeploymentTransactionArgs { + approvals, + deployment_calldata: deposit_and_add_order_calldata.0, + orderbook_address: deployment + .deployment + .order + .orderbook + .as_ref() + .ok_or(GuiError::OrderbookNotFound)? + .address, + chain_id: deployment.deployment.order.network.chain_id, + }) + } } From c07a8f0d72b2820a81ac0e58bd3db3df95039f1d Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 13:05:39 +0300 Subject: [PATCH 20/36] update tests --- packages/orderbook/test/js_api/gui.test.ts | 57 +++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/packages/orderbook/test/js_api/gui.test.ts b/packages/orderbook/test/js_api/gui.test.ts index 2204bca30..b533544cd 100644 --- a/packages/orderbook/test/js_api/gui.test.ts +++ b/packages/orderbook/test/js_api/gui.test.ts @@ -5,11 +5,10 @@ import { AddOrderCalldataResult, AllFieldValuesResult, AllowancesResult, - ApprovalCalldataResult, DeploymentDetails, DeploymentKeys, + DeploymentTransactionArgs, DepositAndAddOrderCalldataResult, - DepositCalldataResult, Gui, GuiDeployment, IOVaultIds, @@ -1229,6 +1228,60 @@ ${dotrainWithoutVaultIds}`; const calldatas = await gui.generateDepositCalldatas(); assert.equal(calldatas.Calldatas.length, 0); }); + + it('should generate deployment transaction args', async () => { + await mockServer + .forPost('/rpc-url') + .thenSendJsonRpcResult( + '0x00000000000000000000000000000000000000000000003635C9ADC5DEA00000' + ); + await mockServer + .forPost('/rpc-url') + .withBodyIncluding('0xf0cfdd37') + .thenSendJsonRpcResult(`0x${'0'.repeat(24) + '1'.repeat(40)}`); + await mockServer + .forPost('/rpc-url') + .withBodyIncluding('0xc19423bc') + .thenSendJsonRpcResult(`0x${'0'.repeat(24) + '2'.repeat(40)}`); + await mockServer + .forPost('/rpc-url') + .withBodyIncluding('0x24376855') + .thenSendJsonRpcResult(`0x${'0'.repeat(24) + '3'.repeat(40)}`); + await mockServer + .forPost('/rpc-url') + .withBodyIncluding('0xa3869e14') + .thenSendJsonRpcResult( + '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000021234000000000000000000000000000000000000000000000000000000000000' + ); + + gui.saveDeposit('token2', '5000'); + gui.saveFieldValue('test-binding', { + isPreset: false, + value: '10' + }); + + let result: DeploymentTransactionArgs = await gui.getDeploymentTransactionArgs( + '0x1234567890abcdef1234567890abcdef12345678' + ); + + assert.equal(result.approvals.length, 1); + assert.equal( + result.approvals[0].calldata, + '0x095ea7b3000000000000000000000000c95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a600000000000000000000000000000000000000000000010f0cf064dd59200000' + ); + assert.equal(result.approvals[0].symbol, 'T2'); + assert.equal(result.deployment_calldata.length, 3146); + assert.equal(result.orderbook_address, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); + assert.equal(result.chain_id, 123); + + gui.removeDeposit('token2'); + result = await gui.getDeploymentTransactionArgs('0x1234567890abcdef1234567890abcdef12345678'); + + assert.equal(result.approvals.length, 0); + assert.equal(result.deployment_calldata.length, 2634); + assert.equal(result.orderbook_address, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); + assert.equal(result.chain_id, 123); + }); }); describe('select tokens tests', async () => { From e241534ff6b31f5ecd5e4d76b47ea1876227ae96 Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 13:20:37 +0300 Subject: [PATCH 21/36] add additional field to extended approval calldata --- crates/js_api/src/gui/order_operations.rs | 7 +++++-- packages/orderbook/test/js_api/gui.test.ts | 12 ++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/js_api/src/gui/order_operations.rs b/crates/js_api/src/gui/order_operations.rs index b46a88c27..925c26005 100644 --- a/crates/js_api/src/gui/order_operations.rs +++ b/crates/js_api/src/gui/order_operations.rs @@ -63,12 +63,14 @@ impl_all_wasm_traits!(IOVaultIds); #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] pub struct ExtendedApprovalCalldata { - calldata: Bytes, - symbol: String, + pub token: Address, + pub calldata: Bytes, + pub symbol: String, } impl_all_wasm_traits!(ExtendedApprovalCalldata); #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] +#[serde(rename_all = "camelCase")] pub struct DeploymentTransactionArgs { approvals: Vec, deployment_calldata: Bytes, @@ -405,6 +407,7 @@ impl DotrainOrderGui { .get(&calldata.token) .ok_or(GuiError::TokenNotFound(calldata.token.to_string()))?; approvals.push(ExtendedApprovalCalldata { + token: calldata.token, calldata: calldata.calldata.clone(), symbol: token_info.symbol.clone(), }); diff --git a/packages/orderbook/test/js_api/gui.test.ts b/packages/orderbook/test/js_api/gui.test.ts index b533544cd..ec5a3e837 100644 --- a/packages/orderbook/test/js_api/gui.test.ts +++ b/packages/orderbook/test/js_api/gui.test.ts @@ -1270,17 +1270,17 @@ ${dotrainWithoutVaultIds}`; '0x095ea7b3000000000000000000000000c95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a600000000000000000000000000000000000000000000010f0cf064dd59200000' ); assert.equal(result.approvals[0].symbol, 'T2'); - assert.equal(result.deployment_calldata.length, 3146); - assert.equal(result.orderbook_address, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); - assert.equal(result.chain_id, 123); + assert.equal(result.deploymentCalldata.length, 3146); + assert.equal(result.orderbookAddress, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); + assert.equal(result.chainId, 123); gui.removeDeposit('token2'); result = await gui.getDeploymentTransactionArgs('0x1234567890abcdef1234567890abcdef12345678'); assert.equal(result.approvals.length, 0); - assert.equal(result.deployment_calldata.length, 2634); - assert.equal(result.orderbook_address, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); - assert.equal(result.chain_id, 123); + assert.equal(result.deploymentCalldata.length, 2634); + assert.equal(result.orderbookAddress, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); + assert.equal(result.chainId, 123); }); }); From b758d4740dc35142d081227c5941cabaf20b6dfa Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 13:20:49 +0300 Subject: [PATCH 22/36] update ui function --- .../deployment/DeploymentSteps.svelte | 2 +- .../getDeploymentTransactionArgs.ts | 71 ++----------------- 2 files changed, 5 insertions(+), 68 deletions(-) diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index 08d9354b5..03407ca24 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -216,7 +216,7 @@ checkingDeployment = true; try { - result = await getDeploymentTransactionArgs(gui, $wagmiConfig, allTokenOutputs); + result = await getDeploymentTransactionArgs(gui, $wagmiConfig); } catch (e) { checkingDeployment = false; error = DeploymentStepErrors.ADD_ORDER_FAILED; diff --git a/packages/ui-components/src/lib/components/deployment/getDeploymentTransactionArgs.ts b/packages/ui-components/src/lib/components/deployment/getDeploymentTransactionArgs.ts index 4070187ce..004198a85 100644 --- a/packages/ui-components/src/lib/components/deployment/getDeploymentTransactionArgs.ts +++ b/packages/ui-components/src/lib/components/deployment/getDeploymentTransactionArgs.ts @@ -4,7 +4,6 @@ import type { DepositAndAddOrderCalldataResult, DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; -import type { OrderIO } from '@rainlanguage/orderbook/js_api'; import type { Hex } from 'viem'; import type { ExtendedApprovalCalldata } from '$lib/stores/transactionStore'; @@ -12,12 +11,7 @@ export enum AddOrderErrors { ADD_ORDER_FAILED = 'Failed to add order', MISSING_GUI = 'Order GUI is required', MISSING_CONFIG = 'Wagmi config is required', - NO_WALLET = 'No wallet address found', - INVALID_CHAIN_ID = 'Invalid chain ID in deployment', - MISSING_ORDERBOOK = 'Orderbook address not found', - TOKEN_INFO_FAILED = 'Failed to fetch token information', - APPROVAL_FAILED = 'Failed to generate approval calldata', - DEPLOYMENT_FAILED = 'Failed to generate deployment calldata' + NO_WALLET = 'No wallet address found' } export interface HandleAddOrderResult { @@ -29,8 +23,7 @@ export interface HandleAddOrderResult { export async function getDeploymentTransactionArgs( gui: DotrainOrderGui | null, - wagmiConfig: Config | undefined, - allTokenOutputs: OrderIO[] + wagmiConfig: Config | undefined ): Promise { if (!gui) { throw new Error(AddOrderErrors.MISSING_GUI); @@ -45,64 +38,8 @@ export async function getDeploymentTransactionArgs( throw new Error(AddOrderErrors.NO_WALLET); } - let approvalResults; - try { - approvalResults = await gui.generateApprovalCalldatas(address); - } catch (error) { - throw new Error( - `${AddOrderErrors.APPROVAL_FAILED}: ${error instanceof Error ? error.message : 'Unknown error'}` - ); - } - - let deploymentCalldata; - try { - deploymentCalldata = await gui.generateDepositAndAddOrderCalldatas(); - } catch (error) { - throw new Error( - `${AddOrderErrors.DEPLOYMENT_FAILED}: ${error instanceof Error ? error.message : 'Unknown error'}` - ); - } - - const currentDeployment = gui.getCurrentDeployment(); - const chainId = currentDeployment?.deployment?.order?.network?.['chain-id'] as number; - if (!chainId) { - throw new Error(AddOrderErrors.INVALID_CHAIN_ID); - } - - // @ts-expect-error orderbook is not typed - const orderbookAddress = currentDeployment?.deployment?.order?.orderbook?.address; - if (!orderbookAddress) { - throw new Error(AddOrderErrors.MISSING_ORDERBOOK); - } - - let approvals: ExtendedApprovalCalldata[] = []; - - try { - const outputTokenInfos = await Promise.all( - allTokenOutputs.map((token) => { - const key = token.token?.key; - if (!key) throw new Error('Token key is missing'); - return gui.getTokenInfo(key); - }) - ); - - if (approvalResults !== 'NoDeposits') { - approvals = approvalResults.Calldatas.map((approval) => { - const token = outputTokenInfos.find((token) => token?.address === approval.token); - if (!token) { - throw new Error(`Token info not found for address: ${approval.token}`); - } - return { - ...approval, - symbol: token.symbol - }; - }); - } - } catch (error) { - throw new Error( - `${AddOrderErrors.TOKEN_INFO_FAILED}: ${error instanceof Error ? error.message : 'Unknown error'}` - ); - } + const { approvals, deploymentCalldata, orderbookAddress, chainId } = + await gui.getDeploymentTransactionArgs(address); return { approvals, From f22151ddf314ee15b4fa7441842136541cbbf188 Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 13:20:54 +0300 Subject: [PATCH 23/36] update ui tests --- .../getDeploymentTransactionArgs.test.ts | 138 +++--------------- 1 file changed, 17 insertions(+), 121 deletions(-) diff --git a/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts b/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts index a85760ebe..3c8d34030 100644 --- a/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts +++ b/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts @@ -5,7 +5,7 @@ import { } from '../lib/components/deployment/getDeploymentTransactionArgs'; import { getAccount } from '@wagmi/core'; import type { Config } from '@wagmi/core'; -import type { DotrainOrderGui, OrderIO } from '@rainlanguage/orderbook/js_api'; +import type { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; // Mock wagmi/core vi.mock('@wagmi/core', () => ({ @@ -15,36 +15,22 @@ vi.mock('@wagmi/core', () => ({ describe('getDeploymentTransactionArgs', () => { let mockGui: DotrainOrderGui; let mockWagmiConfig: Config; - let mockTokenOutputs: OrderIO[]; beforeEach(() => { vi.clearAllMocks(); // Mock GUI with successful responses mockGui = { - generateApprovalCalldatas: vi.fn().mockResolvedValue([{ token: '0x123', amount: '1000' }]), - generateDepositAndAddOrderCalldatas: vi.fn().mockResolvedValue({ - deposit: '0xdeposit', - addOrder: '0xaddOrder' - }), - getCurrentDeployment: vi.fn().mockReturnValue({ - deployment: { - order: { - network: { 'chain-id': 1 }, - orderbook: { address: '0xorderbook' } - } - } - }), - getTokenInfo: vi.fn().mockResolvedValue({ - address: '0x123', - symbol: 'TEST' + getDeploymentTransactionArgs: vi.fn().mockResolvedValue({ + chainId: 1, + orderbookAddress: '0xorderbook', + approvals: [{ token: '0x123', calldata: '0x1', symbol: 'TEST' }], + deploymentCalldata: '0x1' }) } as unknown as DotrainOrderGui; mockWagmiConfig = {} as Config; (getAccount as Mock).mockReturnValue({ address: '0xuser' }); - - mockTokenOutputs = [{ token: { key: 'token1' } }] as OrderIO[]; }); describe('successful cases', () => { @@ -52,14 +38,11 @@ describe('getDeploymentTransactionArgs', () => { mockGui.generateApprovalCalldatas = vi.fn().mockResolvedValue({ Calldatas: [{ token: '0x123', amount: '1000' }] }); - const result = await getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs); + const result = await getDeploymentTransactionArgs(mockGui, mockWagmiConfig); expect(result).toEqual({ - approvals: [{ token: '0x123', amount: '1000', symbol: 'TEST' }], - deploymentCalldata: { - deposit: '0xdeposit', - addOrder: '0xaddOrder' - }, + approvals: [{ token: '0x123', calldata: '0x1', symbol: 'TEST' }], + deploymentCalldata: '0x1', orderbookAddress: '0xorderbook', chainId: 1 }); @@ -71,108 +54,21 @@ describe('getDeploymentTransactionArgs', () => { describe('input validation errors', () => { it('should throw MISSING_GUI when GUI is null', async () => { - await expect( - getDeploymentTransactionArgs(null, mockWagmiConfig, mockTokenOutputs) - ).rejects.toThrow(AddOrderErrors.MISSING_GUI); + await expect(getDeploymentTransactionArgs(null, mockWagmiConfig)).rejects.toThrow( + AddOrderErrors.MISSING_GUI + ); }); it('should throw MISSING_CONFIG when wagmiConfig is undefined', async () => { - await expect( - getDeploymentTransactionArgs(mockGui, undefined, mockTokenOutputs) - ).rejects.toThrow(AddOrderErrors.MISSING_CONFIG); + await expect(getDeploymentTransactionArgs(mockGui, undefined)).rejects.toThrow( + AddOrderErrors.MISSING_CONFIG + ); }); it('should throw NO_WALLET when wallet address is not found', async () => { (getAccount as Mock).mockReturnValue({ address: null }); - await expect( - getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs) - ).rejects.toThrow(AddOrderErrors.NO_WALLET); - }); - }); - - describe('deployment errors', () => { - it('should throw INVALID_CHAIN_ID when chain ID is missing', async () => { - mockGui.getCurrentDeployment = vi.fn().mockReturnValue({ - deployment: { - order: { - network: {}, - orderbook: { address: '0xorderbook' } - } - } - }); - - await expect( - getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs) - ).rejects.toThrow(AddOrderErrors.INVALID_CHAIN_ID); - }); - - it('should throw MISSING_ORDERBOOK when orderbook address is missing', async () => { - mockGui.getCurrentDeployment = vi.fn().mockReturnValue({ - deployment: { - order: { - network: { 'chain-id': 1 }, - orderbook: {} - } - } - }); - - await expect( - getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs) - ).rejects.toThrow(AddOrderErrors.MISSING_ORDERBOOK); - }); - }); - - describe('approval and calldata errors', () => { - it('should throw APPROVAL_FAILED when generateApprovalCalldatas fails', async () => { - mockGui.generateApprovalCalldatas = vi.fn().mockRejectedValue(new Error('Approval error')); - - await expect( - getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs) - ).rejects.toThrow(`${AddOrderErrors.APPROVAL_FAILED}: Approval error`); - }); - - it('should throw DEPLOYMENT_FAILED when generateDepositAndAddOrderCalldatas fails', async () => { - mockGui.generateDepositAndAddOrderCalldatas = vi - .fn() - .mockRejectedValue(new Error('Deployment error')); - - await expect( - getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs) - ).rejects.toThrow(`${AddOrderErrors.DEPLOYMENT_FAILED}: Deployment error`); - }); - }); - - describe('token info errors', () => { - it('should throw TOKEN_INFO_FAILED when token key is missing', async () => { - const invalidTokenOutputs = [{ token: {} }] as OrderIO[]; - - await expect( - getDeploymentTransactionArgs(mockGui, mockWagmiConfig, invalidTokenOutputs) - ).rejects.toThrow(`${AddOrderErrors.TOKEN_INFO_FAILED}: Token key is missing`); - }); - - it('should throw TOKEN_INFO_FAILED when getTokenInfo fails', async () => { - mockGui.getTokenInfo = vi.fn().mockRejectedValue(new Error('Token info error')); - - await expect( - getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs) - ).rejects.toThrow(`${AddOrderErrors.TOKEN_INFO_FAILED}: Token info error`); - }); - - it('should throw TOKEN_INFO_FAILED when token info is not found for approval', async () => { - mockGui.getTokenInfo = vi.fn().mockResolvedValue({ - address: '0x456', // Different address than the approval token - symbol: 'TEST' - }); - - mockGui.generateApprovalCalldatas = vi.fn().mockResolvedValue({ - Calldatas: [{ token: '0x123', amount: '1000' }] - }); - - await expect( - getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs) - ).rejects.toThrow( - `${AddOrderErrors.TOKEN_INFO_FAILED}: Token info not found for address: 0x123` + await expect(getDeploymentTransactionArgs(mockGui, mockWagmiConfig)).rejects.toThrow( + AddOrderErrors.NO_WALLET ); }); }); From 6ddd551645e94a0ca35503f8809b1abbc8f45d6d Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Tue, 18 Feb 2025 11:25:51 +0100 Subject: [PATCH 24/36] remove all --- packages/webapp/src/__tests__/DeployModal.test.ts | 2 +- packages/webapp/src/lib/services/modal.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/webapp/src/__tests__/DeployModal.test.ts b/packages/webapp/src/__tests__/DeployModal.test.ts index c4d7d60c4..67341d6f2 100644 --- a/packages/webapp/src/__tests__/DeployModal.test.ts +++ b/packages/webapp/src/__tests__/DeployModal.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi } from 'vitest'; import { render } from '@testing-library/svelte'; import DeployModal from '../lib/components/DeployModal.svelte'; import { get } from 'svelte/store'; diff --git a/packages/webapp/src/lib/services/modal.ts b/packages/webapp/src/lib/services/modal.ts index 990e062bc..082ac281b 100644 --- a/packages/webapp/src/lib/services/modal.ts +++ b/packages/webapp/src/lib/services/modal.ts @@ -3,7 +3,6 @@ import DepositOrWithdrawModal from '$lib/components/DepositOrWithdrawModal.svelt import OrderRemoveModal from '$lib/components/OrderRemoveModal.svelte'; import { DisclaimerModal, - type DeploymentArgs, type DepositOrWithdrawModalProps, type OrderRemoveModalProps, type DisclaimerModalProps, From 9daa3715c4a9cd95ed750a5b16edd3a0c30ab4d2 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Tue, 18 Feb 2025 11:44:51 +0100 Subject: [PATCH 25/36] fix types --- crates/subgraph/src/performance/order_performance.rs | 1 + crates/subgraph/src/types/order_detail_traits.rs | 3 ++- packages/orderbook/test/js_api/removeOrder.test.ts | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/subgraph/src/performance/order_performance.rs b/crates/subgraph/src/performance/order_performance.rs index 3a366b1a9..39717dc57 100644 --- a/crates/subgraph/src/performance/order_performance.rs +++ b/crates/subgraph/src/performance/order_performance.rs @@ -824,6 +824,7 @@ mod test { meta: None, add_events: vec![], trades: vec![], + remove_events: vec![], } } diff --git a/crates/subgraph/src/types/order_detail_traits.rs b/crates/subgraph/src/types/order_detail_traits.rs index dc6e5e8af..92e783de1 100644 --- a/crates/subgraph/src/types/order_detail_traits.rs +++ b/crates/subgraph/src/types/order_detail_traits.rs @@ -82,7 +82,8 @@ mod tests { }, // Only the order_bytes field is used for the conversion order_bytes: Bytes("0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000006171c21b2e553c59a64d1337211b77c367cefe5d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000379b966dc6b117dd47b5fc5308534256a4ab1bcc0000000000000000000000006e4b01603edbda617002a077420e98c86595748e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000000000000000015020000000c020200020110000001100001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000050c5725949a6f0c72e6c4a641f24049a917db0cb000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291300000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001".into()), - trades: vec![] + trades: vec![], + remove_events: vec![], }; let order_v3: OrderV3 = order_detail.try_into().unwrap(); diff --git a/packages/orderbook/test/js_api/removeOrder.test.ts b/packages/orderbook/test/js_api/removeOrder.test.ts index c16b97e89..a216f0c76 100644 --- a/packages/orderbook/test/js_api/removeOrder.test.ts +++ b/packages/orderbook/test/js_api/removeOrder.test.ts @@ -136,7 +136,6 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Remove Order', async fun mockServer.url + '/sg1', transaction1.id ); - console.log(JSON.stringify(result, null, 2)); assert.equal(result[0].order.id, mockRemoveOrder.order.id); } catch (e) { assert.fail('expected to resolve, but failed' + (e instanceof Error ? e.message : String(e))); From 5fbb7750898850e090297d4bacf33be0edee5a34 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Tue, 18 Feb 2025 12:39:59 +0100 Subject: [PATCH 26/36] type --- tauri-app/src-tauri/src/commands/order_quote.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tauri-app/src-tauri/src/commands/order_quote.rs b/tauri-app/src-tauri/src/commands/order_quote.rs index c29438c0b..aa367a7ff 100644 --- a/tauri-app/src-tauri/src/commands/order_quote.rs +++ b/tauri-app/src-tauri/src/commands/order_quote.rs @@ -170,6 +170,7 @@ amount price: 16 52; meta: None, timestamp_added: BigInt(0.to_string()), trades: vec![], + remove_events: vec![], }; let input_io_index = 0; From f80ec53d78995977ae87b97e802fc4626eabbcb0 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Tue, 18 Feb 2025 13:04:12 +0100 Subject: [PATCH 27/36] type --- crates/quote/src/order_quotes.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/quote/src/order_quotes.rs b/crates/quote/src/order_quotes.rs index f6d38b52e..683a082cb 100644 --- a/crates/quote/src/order_quotes.rs +++ b/crates/quote/src/order_quotes.rs @@ -317,6 +317,7 @@ amount price: context<3 0>() context<4 0>(); meta: None, timestamp_added: BigInt(0.to_string()), trades: vec![], + remove_events: vec![], }; let result = get_order_quotes(vec![order], None, local_evm.url(), None) From 36fb2bc341373014eaa2218ceeb45dfaa6e7c6de Mon Sep 17 00:00:00 2001 From: findolor Date: Tue, 18 Feb 2025 15:15:22 +0300 Subject: [PATCH 28/36] fix test --- .../src/__tests__/getDeploymentTransactionArgs.test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts b/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts index 3c8d34030..29144a8a8 100644 --- a/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts +++ b/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts @@ -46,9 +46,6 @@ describe('getDeploymentTransactionArgs', () => { orderbookAddress: '0xorderbook', chainId: 1 }); - - expect(mockGui.generateApprovalCalldatas).toHaveBeenCalledWith('0xuser'); - expect(mockGui.generateDepositAndAddOrderCalldatas).toHaveBeenCalled(); }); }); From 37c0f425ffdf6cf6e727e1430ffcdb92069443e9 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Tue, 18 Feb 2025 13:32:47 +0100 Subject: [PATCH 29/36] update tests --- .../src/__tests__/transactionStore.test.ts | 58 ++++++++++++++++++- .../lib/components/detail/OrderDetail.svelte | 4 +- .../src/lib/stores/transactionStore.ts | 38 ++++++++++-- .../src/lib/types/transaction.ts | 2 + .../lib/components/TransactionModal.svelte | 17 +++--- 5 files changed, 103 insertions(+), 16 deletions(-) diff --git a/packages/ui-components/src/__tests__/transactionStore.test.ts b/packages/ui-components/src/__tests__/transactionStore.test.ts index 2d3396849..f8f72969b 100644 --- a/packages/ui-components/src/__tests__/transactionStore.test.ts +++ b/packages/ui-components/src/__tests__/transactionStore.test.ts @@ -5,7 +5,7 @@ import transactionStore, { TransactionErrorMessage } from '../lib/stores/transactionStore'; import { waitForTransactionReceipt, sendTransaction, switchChain, type Config } from '@wagmi/core'; -import { getTransaction, getTransactionAddOrders } from '@rainlanguage/orderbook/js_api'; +import { getTransaction, getTransactionAddOrders, getTransactionRemoveOrders } from '@rainlanguage/orderbook/js_api'; import { waitFor } from '@testing-library/svelte'; vi.mock('@wagmi/core', () => ({ @@ -16,7 +16,8 @@ vi.mock('@wagmi/core', () => ({ vi.mock('@rainlanguage/orderbook/js_api', () => ({ getTransaction: vi.fn(), - getTransactionAddOrders: vi.fn() + getTransactionAddOrders: vi.fn(), + getTransactionRemoveOrders: vi.fn() })); describe('transactionStore', () => { @@ -32,7 +33,8 @@ describe('transactionStore', () => { transactionSuccess, transactionError, awaitTransactionIndexing, - awaitNewOrderIndexing + awaitNewOrderIndexing, + awaitRemoveOrderIndexing } = transactionStore; beforeEach(() => { @@ -339,4 +341,54 @@ describe('transactionStore', () => { vi.useRealTimers(); }); + + it('should handle successful remove order indexing', async () => { + const mockSubgraphUrl = 'test.com'; + const mockTxHash = 'mockHash'; + const mockNetwork = 'flare'; + + (getTransactionRemoveOrders as Mock).mockResolvedValue([ + { + order: { + id: 'removedOrder123' + } + } + ]); + + vi.useFakeTimers({ shouldAdvanceTime: true }); + + await awaitRemoveOrderIndexing(mockSubgraphUrl, mockTxHash, mockNetwork); + + vi.runOnlyPendingTimers(); + + await waitFor(() => { + expect(get(transactionStore).status).toBe(TransactionStatus.SUCCESS); + expect(get(transactionStore).hash).toBe(mockTxHash); + }); + }); + + it('should handle remove order indexing timeout', async () => { + vi.useFakeTimers(); + const mockSubgraphUrl = 'test.com'; + const mockTxHash = 'mockHash'; + const mockNetwork = 'flare'; + + (getTransactionRemoveOrders as Mock).mockResolvedValue([]); + + const indexingPromise = awaitRemoveOrderIndexing(mockSubgraphUrl, mockTxHash, mockNetwork); + + expect(get(transactionStore).status).toBe(TransactionStatus.PENDING_SUBGRAPH); + expect(get(transactionStore).message).toBe('Waiting for order removal to be indexed...'); + + await vi.advanceTimersByTime(10000); + await indexingPromise; + + expect(get(transactionStore).status).toBe(TransactionStatus.ERROR); + expect(get(transactionStore).message).toBe( + 'The subgraph took too long to respond. Please check again later.' + ); + expect(get(transactionStore).error).toBe(TransactionErrorMessage.TIMEOUT); + + vi.useRealTimers(); + }); }); diff --git a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte index 3f17a275a..ccbbff012 100644 --- a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte @@ -94,7 +94,9 @@ order: data.order, onRemove: $orderDetailQuery.refetch, chainId, - orderbookAddress + orderbookAddress, + subgraphUrl, + network: subgraphName } })} disabled={!handleOrderRemoveModal} diff --git a/packages/ui-components/src/lib/stores/transactionStore.ts b/packages/ui-components/src/lib/stores/transactionStore.ts index ffc2bd88d..3c6200541 100644 --- a/packages/ui-components/src/lib/stores/transactionStore.ts +++ b/packages/ui-components/src/lib/stores/transactionStore.ts @@ -11,7 +11,7 @@ import type { Vault, WithdrawCalldataResult } from '@rainlanguage/orderbook/js_api'; -import { getTransaction, getTransactionAddOrders } from '@rainlanguage/orderbook/js_api'; +import { getTransaction, getTransactionAddOrders, getTransactionRemoveOrders } from '@rainlanguage/orderbook/js_api'; export const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000'; export const ONE = BigInt('1000000000000000000'); @@ -68,6 +68,8 @@ export type RemoveOrderTransactionArgs = { orderbookAddress: Hex; removeOrderCalldata: RemoveOrderCalldata; chainId: number; + subgraphUrl: string; + network: string; }; export type TransactionState = { @@ -166,6 +168,31 @@ const transactionStore = () => { }, 1000); }; + const awaitRemoveOrderIndexing = async (subgraphUrl: string, txHash: string, network?: string) => { + update((state) => ({ + ...state, + status: TransactionStatus.PENDING_SUBGRAPH, + message: 'Waiting for order removal to be indexed...' + })); + + let attempts = 0; + const interval: NodeJS.Timeout = setInterval(async () => { + attempts++; + const removeOrders = await getTransactionRemoveOrders(subgraphUrl, txHash); + if (attempts >= 10) { + update((state) => ({ + ...state, + message: 'The subgraph took too long to respond. Please check again later.' + })); + clearInterval(interval); + return transactionError(TransactionErrorMessage.TIMEOUT); + } else if (removeOrders?.length > 0) { + clearInterval(interval); + return transactionSuccess(txHash); + } + }, 1000); + }; + const checkingWalletAllowance = (message?: string) => update((state) => ({ ...state, @@ -334,7 +361,9 @@ const transactionStore = () => { config, orderbookAddress, removeOrderCalldata, - chainId + chainId, + subgraphUrl, + network }: RemoveOrderTransactionArgs) => { try { await switchChain(config, { chainId }); @@ -356,7 +385,7 @@ const transactionStore = () => { try { awaitDeployTx(hash); await waitForTransactionReceipt(config, { hash }); - return transactionSuccess(hash, 'Order removed successfully.'); + return awaitRemoveOrderIndexing(subgraphUrl, hash, network); } catch { return transactionError(TransactionErrorMessage.REMOVE_ORDER_FAILED); } @@ -374,7 +403,8 @@ const transactionStore = () => { transactionSuccess, transactionError, awaitTransactionIndexing, - awaitNewOrderIndexing + awaitNewOrderIndexing, + awaitRemoveOrderIndexing }; }; diff --git a/packages/ui-components/src/lib/types/transaction.ts b/packages/ui-components/src/lib/types/transaction.ts index b24f0f41f..47f178d69 100644 --- a/packages/ui-components/src/lib/types/transaction.ts +++ b/packages/ui-components/src/lib/types/transaction.ts @@ -26,4 +26,6 @@ export type OrderRemoveArgs = { onRemove: () => void; chainId: number; orderbookAddress: Hex; + subgraphUrl: string; + network: string; }; diff --git a/packages/webapp/src/lib/components/TransactionModal.svelte b/packages/webapp/src/lib/components/TransactionModal.svelte index 182fe024a..6eeb25412 100644 --- a/packages/webapp/src/lib/components/TransactionModal.svelte +++ b/packages/webapp/src/lib/components/TransactionModal.svelte @@ -53,12 +53,12 @@

-

- {messages.success} -

-
+
+

+ {messages.success} +

{#if $transactionStore.message}

{/if} - +

+
{#if $transactionStore.newOrderId && $transactionStore.network} @@ -79,7 +80,7 @@
{:else}
From c7f79446094166a5600560e92497ee38d508ec30 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Tue, 18 Feb 2025 14:25:16 +0100 Subject: [PATCH 30/36] format --- .../src/__tests__/OrderDetail.test.svelte | 4 +++- .../src/__tests__/transactionStore.test.ts | 6 +++++- .../ui-components/src/lib/stores/transactionStore.ts | 12 ++++++++++-- .../src/lib/components/TransactionModal.svelte | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/ui-components/src/__tests__/OrderDetail.test.svelte b/packages/ui-components/src/__tests__/OrderDetail.test.svelte index b779e0b72..1747c9506 100644 --- a/packages/ui-components/src/__tests__/OrderDetail.test.svelte +++ b/packages/ui-components/src/__tests__/OrderDetail.test.svelte @@ -42,7 +42,9 @@ order: data.order, onRemove: $orderDetailQuery.refetch, chainId, - orderbookAddress + orderbookAddress, + subgraphUrl, + network: 'subgraphName' } })} disabled={!handleOrderRemoveModal} diff --git a/packages/ui-components/src/__tests__/transactionStore.test.ts b/packages/ui-components/src/__tests__/transactionStore.test.ts index f8f72969b..a24023901 100644 --- a/packages/ui-components/src/__tests__/transactionStore.test.ts +++ b/packages/ui-components/src/__tests__/transactionStore.test.ts @@ -5,7 +5,11 @@ import transactionStore, { TransactionErrorMessage } from '../lib/stores/transactionStore'; import { waitForTransactionReceipt, sendTransaction, switchChain, type Config } from '@wagmi/core'; -import { getTransaction, getTransactionAddOrders, getTransactionRemoveOrders } from '@rainlanguage/orderbook/js_api'; +import { + getTransaction, + getTransactionAddOrders, + getTransactionRemoveOrders +} from '@rainlanguage/orderbook/js_api'; import { waitFor } from '@testing-library/svelte'; vi.mock('@wagmi/core', () => ({ diff --git a/packages/ui-components/src/lib/stores/transactionStore.ts b/packages/ui-components/src/lib/stores/transactionStore.ts index 3c6200541..e3493173a 100644 --- a/packages/ui-components/src/lib/stores/transactionStore.ts +++ b/packages/ui-components/src/lib/stores/transactionStore.ts @@ -11,7 +11,11 @@ import type { Vault, WithdrawCalldataResult } from '@rainlanguage/orderbook/js_api'; -import { getTransaction, getTransactionAddOrders, getTransactionRemoveOrders } from '@rainlanguage/orderbook/js_api'; +import { + getTransaction, + getTransactionAddOrders, + getTransactionRemoveOrders +} from '@rainlanguage/orderbook/js_api'; export const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000'; export const ONE = BigInt('1000000000000000000'); @@ -168,7 +172,11 @@ const transactionStore = () => { }, 1000); }; - const awaitRemoveOrderIndexing = async (subgraphUrl: string, txHash: string, network?: string) => { + const awaitRemoveOrderIndexing = async ( + subgraphUrl: string, + txHash: string, + network?: string + ) => { update((state) => ({ ...state, status: TransactionStatus.PENDING_SUBGRAPH, diff --git a/packages/webapp/src/lib/components/TransactionModal.svelte b/packages/webapp/src/lib/components/TransactionModal.svelte index 6eeb25412..78a14b490 100644 --- a/packages/webapp/src/lib/components/TransactionModal.svelte +++ b/packages/webapp/src/lib/components/TransactionModal.svelte @@ -80,7 +80,7 @@
{:else}
From 7d29b35ba0c4b0d7ef72e4c6b2b1c1956c6100aa Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Tue, 18 Feb 2025 20:11:43 +0100 Subject: [PATCH 31/36] update test case snapshots --- crates/cli/src/commands/order/detail.rs | 3 ++- crates/cli/src/commands/order/list.rs | 3 ++- crates/quote/src/cli/mod.rs | 3 ++- crates/quote/src/quote.rs | 3 ++- ...atch_order_test__batch_order_query_gql_output.snap | 8 ++++++++ .../order_test__orders_query_gql_output.snap | 9 +++++++++ .../orders_test__orders_query_gql_output.snap | 11 ++++++++++- .../src/lib/components/detail/OrderDetail.svelte | 3 +-- .../ui-components/src/lib/stores/transactionStore.ts | 8 ++------ packages/ui-components/src/lib/types/transaction.ts | 1 - 10 files changed, 38 insertions(+), 14 deletions(-) diff --git a/crates/cli/src/commands/order/detail.rs b/crates/cli/src/commands/order/detail.rs index 77719c3df..61d1cd946 100644 --- a/crates/cli/src/commands/order/detail.rs +++ b/crates/cli/src/commands/order/detail.rs @@ -136,7 +136,8 @@ mod tests { "from": encode_prefixed(alloy::primitives::Address::random()) } }], - "trades": [] + "trades": [], + "removeEvents": [] } } }) diff --git a/crates/cli/src/commands/order/list.rs b/crates/cli/src/commands/order/list.rs index e5dbd4427..51184b695 100644 --- a/crates/cli/src/commands/order/list.rs +++ b/crates/cli/src/commands/order/list.rs @@ -264,7 +264,8 @@ mod tests { "from": encode_prefixed(alloy::primitives::Address::random()) } }], - "trades": [] + "trades": [], + "removeEvents": [] }] } }) diff --git a/crates/quote/src/cli/mod.rs b/crates/quote/src/cli/mod.rs index a15d252dc..4c3be47f2 100644 --- a/crates/quote/src/cli/mod.rs +++ b/crates/quote/src/cli/mod.rs @@ -378,7 +378,8 @@ mod tests { }], "meta": null, "timestampAdded": "0", - "trades": [] + "trades": [], + "removeEvents": [] }] } }); diff --git a/crates/quote/src/quote.rs b/crates/quote/src/quote.rs index bc113ea44..16ca5d90a 100644 --- a/crates/quote/src/quote.rs +++ b/crates/quote/src/quote.rs @@ -431,7 +431,8 @@ mod tests { }], "meta": null, "timestampAdded": "0", - "trades": [] + "trades": [], + "removeEvents": [] }); let retrun_sg_data = if batch { json!({ diff --git a/crates/subgraph/tests/snapshots/batch_order_test__batch_order_query_gql_output.snap b/crates/subgraph/tests/snapshots/batch_order_test__batch_order_query_gql_output.snap index b02666f22..f5f249bd6 100644 --- a/crates/subgraph/tests/snapshots/batch_order_test__batch_order_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/batch_order_test__batch_order_query_gql_output.snap @@ -309,5 +309,13 @@ query BatchOrderDetailQuery($id_list: Order_filter!) { trades { id } + removeEvents { + transaction { + id + from + blockNumber + timestamp + } + } } } diff --git a/crates/subgraph/tests/snapshots/order_test__orders_query_gql_output.snap b/crates/subgraph/tests/snapshots/order_test__orders_query_gql_output.snap index 754ed1164..84b3f0b88 100644 --- a/crates/subgraph/tests/snapshots/order_test__orders_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/order_test__orders_query_gql_output.snap @@ -1,5 +1,6 @@ --- source: crates/subgraph/tests/order_test.rs +assertion_line: 13 expression: request_body.query --- query OrderDetailQuery($id: ID!) { @@ -309,5 +310,13 @@ query OrderDetailQuery($id: ID!) { trades { id } + removeEvents { + transaction { + id + from + blockNumber + timestamp + } + } } } diff --git a/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap b/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap index 7e6dd6dcb..f53bf6761 100644 --- a/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap @@ -1,5 +1,6 @@ --- source: crates/subgraph/tests/orders_test.rs +assertion_line: 15 expression: request_body.query --- query OrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { @@ -21,7 +22,7 @@ query OrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { decimals } orderbook { - id + id } ordersAsOutput(orderBy: timestampAdded, orderDirection: desc) { id @@ -309,5 +310,13 @@ query OrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { trades { id } + removeEvents { + transaction { + id + from + blockNumber + timestamp + } + } } } diff --git a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte index ccbbff012..66dadb7d9 100644 --- a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte @@ -95,8 +95,7 @@ onRemove: $orderDetailQuery.refetch, chainId, orderbookAddress, - subgraphUrl, - network: subgraphName + subgraphUrl } })} disabled={!handleOrderRemoveModal} diff --git a/packages/ui-components/src/lib/stores/transactionStore.ts b/packages/ui-components/src/lib/stores/transactionStore.ts index e3493173a..a6744ba80 100644 --- a/packages/ui-components/src/lib/stores/transactionStore.ts +++ b/packages/ui-components/src/lib/stores/transactionStore.ts @@ -172,11 +172,7 @@ const transactionStore = () => { }, 1000); }; - const awaitRemoveOrderIndexing = async ( - subgraphUrl: string, - txHash: string, - network?: string - ) => { + const awaitRemoveOrderIndexing = async (subgraphUrl: string, txHash: string) => { update((state) => ({ ...state, status: TransactionStatus.PENDING_SUBGRAPH, @@ -393,7 +389,7 @@ const transactionStore = () => { try { awaitDeployTx(hash); await waitForTransactionReceipt(config, { hash }); - return awaitRemoveOrderIndexing(subgraphUrl, hash, network); + return awaitRemoveOrderIndexing(subgraphUrl, hash); } catch { return transactionError(TransactionErrorMessage.REMOVE_ORDER_FAILED); } diff --git a/packages/ui-components/src/lib/types/transaction.ts b/packages/ui-components/src/lib/types/transaction.ts index 47f178d69..3b33e2c7b 100644 --- a/packages/ui-components/src/lib/types/transaction.ts +++ b/packages/ui-components/src/lib/types/transaction.ts @@ -27,5 +27,4 @@ export type OrderRemoveArgs = { chainId: number; orderbookAddress: Hex; subgraphUrl: string; - network: string; }; From 9abb9bfd8e8580be6d3de82a84567cba4a4f8f91 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Tue, 18 Feb 2025 20:26:30 +0100 Subject: [PATCH 32/36] remove network --- packages/ui-components/src/lib/stores/transactionStore.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ui-components/src/lib/stores/transactionStore.ts b/packages/ui-components/src/lib/stores/transactionStore.ts index a6744ba80..8559551e5 100644 --- a/packages/ui-components/src/lib/stores/transactionStore.ts +++ b/packages/ui-components/src/lib/stores/transactionStore.ts @@ -366,8 +366,7 @@ const transactionStore = () => { orderbookAddress, removeOrderCalldata, chainId, - subgraphUrl, - network + subgraphUrl }: RemoveOrderTransactionArgs) => { try { await switchChain(config, { chainId }); From bf807c81a81097833a1baaa49121671ec202caa3 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Tue, 18 Feb 2025 20:49:35 +0100 Subject: [PATCH 33/36] snpashot --- .../tests/snapshots/orders_test__orders_query_gql_output.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap b/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap index f53bf6761..9dca63e17 100644 --- a/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap @@ -22,7 +22,7 @@ query OrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { decimals } orderbook { - id + id } ordersAsOutput(orderBy: timestampAdded, orderDirection: desc) { id From 58e5a8adec93cb4e408f2ce10c5b764e1e03fcc6 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Tue, 18 Feb 2025 21:18:28 +0100 Subject: [PATCH 34/36] args --- packages/ui-components/src/lib/stores/transactionStore.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ui-components/src/lib/stores/transactionStore.ts b/packages/ui-components/src/lib/stores/transactionStore.ts index 8559551e5..689b25468 100644 --- a/packages/ui-components/src/lib/stores/transactionStore.ts +++ b/packages/ui-components/src/lib/stores/transactionStore.ts @@ -73,7 +73,6 @@ export type RemoveOrderTransactionArgs = { removeOrderCalldata: RemoveOrderCalldata; chainId: number; subgraphUrl: string; - network: string; }; export type TransactionState = { From fbdd4c38bec1f57f63198d839beb434301611ae3 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Wed, 19 Feb 2025 09:06:30 +0100 Subject: [PATCH 35/36] rm unused in tests --- .../ui-components/src/__tests__/OrderDetail.test.svelte | 3 +-- .../ui-components/src/__tests__/transactionStore.test.ts | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/ui-components/src/__tests__/OrderDetail.test.svelte b/packages/ui-components/src/__tests__/OrderDetail.test.svelte index 1747c9506..db5b7d727 100644 --- a/packages/ui-components/src/__tests__/OrderDetail.test.svelte +++ b/packages/ui-components/src/__tests__/OrderDetail.test.svelte @@ -43,8 +43,7 @@ onRemove: $orderDetailQuery.refetch, chainId, orderbookAddress, - subgraphUrl, - network: 'subgraphName' + subgraphUrl } })} disabled={!handleOrderRemoveModal} diff --git a/packages/ui-components/src/__tests__/transactionStore.test.ts b/packages/ui-components/src/__tests__/transactionStore.test.ts index a24023901..114d7fa58 100644 --- a/packages/ui-components/src/__tests__/transactionStore.test.ts +++ b/packages/ui-components/src/__tests__/transactionStore.test.ts @@ -349,7 +349,6 @@ describe('transactionStore', () => { it('should handle successful remove order indexing', async () => { const mockSubgraphUrl = 'test.com'; const mockTxHash = 'mockHash'; - const mockNetwork = 'flare'; (getTransactionRemoveOrders as Mock).mockResolvedValue([ { @@ -361,7 +360,7 @@ describe('transactionStore', () => { vi.useFakeTimers({ shouldAdvanceTime: true }); - await awaitRemoveOrderIndexing(mockSubgraphUrl, mockTxHash, mockNetwork); + await awaitRemoveOrderIndexing(mockSubgraphUrl, mockTxHash); vi.runOnlyPendingTimers(); @@ -375,11 +374,10 @@ describe('transactionStore', () => { vi.useFakeTimers(); const mockSubgraphUrl = 'test.com'; const mockTxHash = 'mockHash'; - const mockNetwork = 'flare'; (getTransactionRemoveOrders as Mock).mockResolvedValue([]); - const indexingPromise = awaitRemoveOrderIndexing(mockSubgraphUrl, mockTxHash, mockNetwork); + const indexingPromise = awaitRemoveOrderIndexing(mockSubgraphUrl, mockTxHash); expect(get(transactionStore).status).toBe(TransactionStatus.PENDING_SUBGRAPH); expect(get(transactionStore).message).toBe('Waiting for order removal to be indexed...'); From 9c4f71b1dccee24ec6818eb716d6aaee4441caab Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Wed, 19 Feb 2025 11:36:36 +0100 Subject: [PATCH 36/36] re-run --- packages/ui-components/src/__tests__/transactionStore.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-components/src/__tests__/transactionStore.test.ts b/packages/ui-components/src/__tests__/transactionStore.test.ts index 2d3396849..2d9e7843e 100644 --- a/packages/ui-components/src/__tests__/transactionStore.test.ts +++ b/packages/ui-components/src/__tests__/transactionStore.test.ts @@ -1,5 +1,5 @@ -import { describe, it, expect, vi, beforeEach, afterAll, type Mock } from 'vitest'; import { get } from 'svelte/store'; +import { describe, it, expect, vi, beforeEach, afterAll, type Mock } from 'vitest'; import transactionStore, { TransactionStatus, TransactionErrorMessage