From a1bdaa19d3be0a3cc1c07fa983008ebe829a4c87 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Fri, 14 Feb 2025 18:23:48 +0100 Subject: [PATCH 01/15] test and add disclaimer modal --- .../getDeploymentTransactionArgs.test.ts | 172 ++++++++++++++++++ .../deployment/DeploymentSteps.svelte | 53 +++--- .../deployment/DisclaimerModal.svelte | 107 +++++++++++ .../deployment/DisclaimerModal.test.ts | 89 +++++++++ .../getDeploymentTransactionArgs.ts | 109 +++++++++++ 5 files changed, 501 insertions(+), 29 deletions(-) create mode 100644 packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts create mode 100644 packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte create mode 100644 packages/ui-components/src/lib/components/deployment/DisclaimerModal.test.ts create mode 100644 packages/ui-components/src/lib/components/deployment/getDeploymentTransactionArgs.ts diff --git a/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts b/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts new file mode 100644 index 000000000..67c858ebd --- /dev/null +++ b/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts @@ -0,0 +1,172 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { + getDeploymentTransactionArgs, + AddOrderErrors +} 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'; + +// Mock wagmi/core +vi.mock('@wagmi/core', () => ({ + getAccount: vi.fn() +})); + +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' + }) + } as unknown as DotrainOrderGui; + + mockWagmiConfig = {} as Config; + (getAccount as any).mockReturnValue({ address: '0xuser' }); + + mockTokenOutputs = [{ token: { key: 'token1' } }] as OrderIO[]; + }); + + describe('successful cases', () => { + it('should successfully return deployment transaction args', async () => { + const result = await getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs); + + expect(result).toEqual({ + approvals: [{ token: '0x123', amount: '1000', symbol: 'TEST' }], + deploymentCalldata: { + deposit: '0xdeposit', + addOrder: '0xaddOrder' + }, + orderbookAddress: '0xorderbook', + chainId: 1 + }); + + expect(mockGui.generateApprovalCalldatas).toHaveBeenCalledWith('0xuser'); + expect(mockGui.generateDepositAndAddOrderCalldatas).toHaveBeenCalled(); + }); + }); + + 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); + }); + + it('should throw MISSING_CONFIG when wagmiConfig is undefined', async () => { + await expect( + getDeploymentTransactionArgs(mockGui, undefined, mockTokenOutputs) + ).rejects.toThrow(AddOrderErrors.MISSING_CONFIG); + }); + + it('should throw NO_WALLET when wallet address is not found', async () => { + (getAccount as any).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' + }); + + await expect( + getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs) + ).rejects.toThrow( + `${AddOrderErrors.TOKEN_INFO_FAILED}: Token info not found for address: 0x123` + ); + }); + }); +}); diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index c8e2454ba..676e2c148 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -18,13 +18,16 @@ } from '@rainlanguage/orderbook/js_api'; import { fade } from 'svelte/transition'; import { Button, Toggle } from 'flowbite-svelte'; - import { getAccount, type Config } from '@wagmi/core'; + import { type Config } from '@wagmi/core'; import { type Writable } from 'svelte/store'; import type { AppKit } from '@reown/appkit'; import type { Hex } from 'viem'; import { page } from '$app/stores'; import { onMount } from 'svelte'; import ShareChoicesButton from './ShareChoicesButton.svelte'; + import { getDeploymentTransactionArgs } from './getDeploymentTransactionArgs'; + import DisclaimerModal from './DisclaimerModal.svelte'; + enum DeploymentStepErrors { NO_GUI = 'Error loading GUI', NO_STRATEGY = 'No valid strategy exists at this URL', @@ -59,6 +62,7 @@ let gui: DotrainOrderGui | null = null; let error: DeploymentStepErrors | null = null; let errorDetails: string | null = null; + let showDisclaimerModal = false; export let wagmiConfig: Writable; export let wagmiConnected: Writable; @@ -155,34 +159,15 @@ } } - async function handleAddOrder() { - try { - if (!gui || !$wagmiConfig) return; - const { address } = getAccount($wagmiConfig); - if (!address) return; - let approvals = await gui.generateApprovalCalldatas(address); - const deploymentCalldata = await gui.generateDepositAndAddOrderCalldatas(); - const chainId = gui.getCurrentDeployment().deployment.order.network['chain-id'] as number; - // @ts-expect-error orderbook is not typed - const orderbookAddress = gui.getCurrentDeployment().deployment.order.orderbook.address; - const outputTokenInfos = await Promise.all( - allTokenOutputs.map((token) => gui?.getTokenInfo(token.token?.key as string)) - ); - - approvals = approvals.map((approval) => { - const token = outputTokenInfos.find((token) => token?.address === approval.token); - return { - ...approval, - symbol: token?.symbol - }; - }); + async function handleAddOrderClick() { + showDisclaimerModal = true; + } - handleDeployModal({ - approvals, - deploymentCalldata, - orderbookAddress, - chainId - }); + async function handleAcceptDisclaimer() { + try { + showDisclaimerModal = false; + const result = await getDeploymentTransactionArgs(gui, $wagmiConfig, allTokenOutputs); + handleDeployModal(result); } catch (e) { error = DeploymentStepErrors.ADD_ORDER_FAILED; errorDetails = e instanceof Error ? e.message : 'Unknown error'; @@ -278,7 +263,7 @@
{#if $wagmiConnected} - + {:else} @@ -299,3 +284,13 @@ {/if} {/if}
+ +{#if showDisclaimerModal && gui && allTokenOutputs && wagmiConfig} + +{/if} diff --git a/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte b/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte new file mode 100644 index 000000000..fa2d9e310 --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte @@ -0,0 +1,107 @@ + + + +
+
+ +
+ + + Before you deploy your strategy, make sure you understand the following... + +
+
+
    +
  • + This front end is provided as a tool to interact with the Raindex smart contracts. +
  • +
  • + You are deploying your own strategy and depositing funds to an immutable smart contract + using your own wallet and private keys. +
  • +
  • + Nobody is custodying your funds, there is no recourse for recovery of funds if lost. +
  • +
  • There is no endorsement or guarantee provided with these strategies.
  • +
  • + Do not proceed if you do not understand the strategy you are deploying. +
  • +
  • Do not invest unless you are prepared to lose all funds.
  • +
+
+
+ + +
+
+ {#if error} + {error} + {/if} + {#if errorDetails} + {errorDetails} + {/if} +
+
+
diff --git a/packages/ui-components/src/lib/components/deployment/DisclaimerModal.test.ts b/packages/ui-components/src/lib/components/deployment/DisclaimerModal.test.ts new file mode 100644 index 000000000..2d40f7090 --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/DisclaimerModal.test.ts @@ -0,0 +1,89 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { render, screen, fireEvent } from '@testing-library/svelte'; +import DisclaimerModal from './DisclaimerModal.svelte'; +import { getDeploymentTransactionArgs } from './getDeploymentTransactionArgs'; +import { writable } from 'svelte/store'; + +// Mock the getDeploymentTransactionArgs module +vi.mock('./getDeploymentTransactionArgs', () => ({ + getDeploymentTransactionArgs: vi.fn() +})); + +describe('DisclaimerModal', () => { + const mockGui = {} as any; + const mockOutputs = [] as any[]; + const mockWagmiConfig = writable(undefined); + const mockHandleDeployModal = vi.fn(); + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('calls getDeploymentTransactionArgs when opened', async () => { + const mockResult = { + approvals: {}, + deploymentCalldata: {}, + orderbookAddress: '0x123', + chainId: 1 + }; + (getDeploymentTransactionArgs as any).mockResolvedValue(mockResult); + + render(DisclaimerModal, { + props: { + open: true, + gui: mockGui, + allTokenOutputs: mockOutputs, + wagmiConfig: mockWagmiConfig, + handleDeployModal: mockHandleDeployModal + } + }); + + expect(getDeploymentTransactionArgs).toHaveBeenCalledWith(mockGui, undefined, mockOutputs); + }); + + it('shows error message when getDeploymentTransactionArgs fails', async () => { + const errorMessage = 'Test error message'; + (getDeploymentTransactionArgs as any).mockRejectedValue(new Error(errorMessage)); + + render(DisclaimerModal, { + props: { + open: true, + gui: mockGui, + allTokenOutputs: mockOutputs, + wagmiConfig: mockWagmiConfig, + handleDeployModal: mockHandleDeployModal + } + }); + + const errorText = await screen.findByText('Error getting deployment transaction data:'); + const errorDetails = await screen.findByText(errorMessage); + expect(errorText).toBeInTheDocument(); + expect(errorDetails).toBeInTheDocument(); + }); + + it('calls handleDeployModal with result when accepting disclaimer', async () => { + const mockResult = { + approvals: {}, + deploymentCalldata: {}, + orderbookAddress: '0x123', + chainId: 1 + }; + (getDeploymentTransactionArgs as any).mockResolvedValue(mockResult); + + render(DisclaimerModal, { + props: { + open: true, + gui: mockGui, + allTokenOutputs: mockOutputs, + wagmiConfig: mockWagmiConfig, + handleDeployModal: mockHandleDeployModal + } + }); + + // Wait for the Deploy button to be enabled + const deployButton = await screen.findByText('Deploy'); + await fireEvent.click(deployButton); + + expect(mockHandleDeployModal).toHaveBeenCalledWith(mockResult); + }); +}); diff --git a/packages/ui-components/src/lib/components/deployment/getDeploymentTransactionArgs.ts b/packages/ui-components/src/lib/components/deployment/getDeploymentTransactionArgs.ts new file mode 100644 index 000000000..654af40d4 --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/getDeploymentTransactionArgs.ts @@ -0,0 +1,109 @@ +import type { Config } from '@wagmi/core'; +import { getAccount } from '@wagmi/core'; +import type { + ApprovalCalldataResult, + DepositAndAddOrderCalldataResult, + DotrainOrderGui +} from '@rainlanguage/orderbook/js_api'; +import type { OrderIO } from '@rainlanguage/orderbook/js_api'; +import type { Hex } from 'viem'; + +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' +} + +export interface HandleAddOrderResult { + approvals: ApprovalCalldataResult; + deploymentCalldata: DepositAndAddOrderCalldataResult; + orderbookAddress: Hex; + chainId: number; +} + +export async function getDeploymentTransactionArgs( + gui: DotrainOrderGui | null, + wagmiConfig: Config | undefined, + allTokenOutputs: OrderIO[] +): Promise { + if (!gui) { + throw new Error(AddOrderErrors.MISSING_GUI); + } + + if (!wagmiConfig) { + throw new Error(AddOrderErrors.MISSING_CONFIG); + } + + const { address } = getAccount(wagmiConfig); + if (!address) { + throw new Error(AddOrderErrors.NO_WALLET); + } + + let approvals; + try { + approvals = 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); + } + + 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); + }) + ); + + approvals = approvals.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'}` + ); + } + + return { + approvals, + deploymentCalldata, + orderbookAddress, + chainId + }; +} From 6d0ad726f935c6c7306b00a02237ec001eb639cb Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Fri, 14 Feb 2025 18:24:52 +0100 Subject: [PATCH 02/15] move test file --- .../deployment => __tests__}/DisclaimerModal.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) rename packages/ui-components/src/{lib/components/deployment => __tests__}/DisclaimerModal.test.ts (91%) diff --git a/packages/ui-components/src/lib/components/deployment/DisclaimerModal.test.ts b/packages/ui-components/src/__tests__/DisclaimerModal.test.ts similarity index 91% rename from packages/ui-components/src/lib/components/deployment/DisclaimerModal.test.ts rename to packages/ui-components/src/__tests__/DisclaimerModal.test.ts index 2d40f7090..8665d31b6 100644 --- a/packages/ui-components/src/lib/components/deployment/DisclaimerModal.test.ts +++ b/packages/ui-components/src/__tests__/DisclaimerModal.test.ts @@ -1,10 +1,9 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/svelte'; -import DisclaimerModal from './DisclaimerModal.svelte'; -import { getDeploymentTransactionArgs } from './getDeploymentTransactionArgs'; +import DisclaimerModal from '../lib/components/deployment/DisclaimerModal.svelte'; +import { getDeploymentTransactionArgs } from '../lib/components/deployment/getDeploymentTransactionArgs'; import { writable } from 'svelte/store'; -// Mock the getDeploymentTransactionArgs module vi.mock('./getDeploymentTransactionArgs', () => ({ getDeploymentTransactionArgs: vi.fn() })); @@ -80,7 +79,6 @@ describe('DisclaimerModal', () => { } }); - // Wait for the Deploy button to be enabled const deployButton = await screen.findByText('Deploy'); await fireEvent.click(deployButton); From 0e1ba2ac8999ae3085e5a141fff5dca62f1241ea Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Fri, 14 Feb 2025 18:42:41 +0100 Subject: [PATCH 03/15] lint format --- .../src/__tests__/DisclaimerModal.test.ts | 14 ++++++++------ .../__tests__/getDeploymentTransactionArgs.test.ts | 6 +++--- .../components/deployment/DeploymentSteps.svelte | 11 ----------- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/packages/ui-components/src/__tests__/DisclaimerModal.test.ts b/packages/ui-components/src/__tests__/DisclaimerModal.test.ts index 8665d31b6..8792de62e 100644 --- a/packages/ui-components/src/__tests__/DisclaimerModal.test.ts +++ b/packages/ui-components/src/__tests__/DisclaimerModal.test.ts @@ -1,16 +1,18 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/svelte'; import DisclaimerModal from '../lib/components/deployment/DisclaimerModal.svelte'; import { getDeploymentTransactionArgs } from '../lib/components/deployment/getDeploymentTransactionArgs'; import { writable } from 'svelte/store'; +import type { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; +import type { OrderIO } from '@rainlanguage/orderbook/js_api'; vi.mock('./getDeploymentTransactionArgs', () => ({ getDeploymentTransactionArgs: vi.fn() })); describe('DisclaimerModal', () => { - const mockGui = {} as any; - const mockOutputs = [] as any[]; + const mockGui = {} as DotrainOrderGui; + const mockOutputs = [] as OrderIO[]; const mockWagmiConfig = writable(undefined); const mockHandleDeployModal = vi.fn(); @@ -25,7 +27,7 @@ describe('DisclaimerModal', () => { orderbookAddress: '0x123', chainId: 1 }; - (getDeploymentTransactionArgs as any).mockResolvedValue(mockResult); + (getDeploymentTransactionArgs as Mock).mockResolvedValue(mockResult); render(DisclaimerModal, { props: { @@ -42,7 +44,7 @@ describe('DisclaimerModal', () => { it('shows error message when getDeploymentTransactionArgs fails', async () => { const errorMessage = 'Test error message'; - (getDeploymentTransactionArgs as any).mockRejectedValue(new Error(errorMessage)); + (getDeploymentTransactionArgs as Mock).mockRejectedValue(new Error(errorMessage)); render(DisclaimerModal, { props: { @@ -67,7 +69,7 @@ describe('DisclaimerModal', () => { orderbookAddress: '0x123', chainId: 1 }; - (getDeploymentTransactionArgs as any).mockResolvedValue(mockResult); + (getDeploymentTransactionArgs as Mock).mockResolvedValue(mockResult); render(DisclaimerModal, { props: { diff --git a/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts b/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts index 67c858ebd..286505ecb 100644 --- a/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts +++ b/packages/ui-components/src/__tests__/getDeploymentTransactionArgs.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { getDeploymentTransactionArgs, AddOrderErrors @@ -42,7 +42,7 @@ describe('getDeploymentTransactionArgs', () => { } as unknown as DotrainOrderGui; mockWagmiConfig = {} as Config; - (getAccount as any).mockReturnValue({ address: '0xuser' }); + (getAccount as Mock).mockReturnValue({ address: '0xuser' }); mockTokenOutputs = [{ token: { key: 'token1' } }] as OrderIO[]; }); @@ -80,7 +80,7 @@ describe('getDeploymentTransactionArgs', () => { }); it('should throw NO_WALLET when wallet address is not found', async () => { - (getAccount as any).mockReturnValue({ address: null }); + (getAccount as Mock).mockReturnValue({ address: null }); await expect( getDeploymentTransactionArgs(mockGui, mockWagmiConfig, mockTokenOutputs) ).rejects.toThrow(AddOrderErrors.NO_WALLET); diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index 676e2c148..89fd1f7d4 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -163,17 +163,6 @@ showDisclaimerModal = true; } - async function handleAcceptDisclaimer() { - try { - showDisclaimerModal = false; - const result = await getDeploymentTransactionArgs(gui, $wagmiConfig, allTokenOutputs); - handleDeployModal(result); - } catch (e) { - error = DeploymentStepErrors.ADD_ORDER_FAILED; - errorDetails = e instanceof Error ? e.message : 'Unknown error'; - } - } - async function handleShareChoices() { // copy the current url to the clipboard navigator.clipboard.writeText($page.url.toString()); From 5bed01a2ff069141b414b932e1cda33e82cfae48 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Fri, 14 Feb 2025 19:17:02 +0100 Subject: [PATCH 04/15] remove unused --- .../src/lib/components/deployment/DeploymentSteps.svelte | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index 89fd1f7d4..d9974a560 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -25,7 +25,6 @@ import { page } from '$app/stores'; import { onMount } from 'svelte'; import ShareChoicesButton from './ShareChoicesButton.svelte'; - import { getDeploymentTransactionArgs } from './getDeploymentTransactionArgs'; import DisclaimerModal from './DisclaimerModal.svelte'; enum DeploymentStepErrors { From f3e23693480eb61b45b8b4ce3d2824a58e9ba03f Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Fri, 14 Feb 2025 21:00:52 +0100 Subject: [PATCH 05/15] fix inport --- packages/ui-components/src/__tests__/DisclaimerModal.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-components/src/__tests__/DisclaimerModal.test.ts b/packages/ui-components/src/__tests__/DisclaimerModal.test.ts index 8792de62e..f586ba53b 100644 --- a/packages/ui-components/src/__tests__/DisclaimerModal.test.ts +++ b/packages/ui-components/src/__tests__/DisclaimerModal.test.ts @@ -6,7 +6,7 @@ import { writable } from 'svelte/store'; import type { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; import type { OrderIO } from '@rainlanguage/orderbook/js_api'; -vi.mock('./getDeploymentTransactionArgs', () => ({ +vi.mock('../lib/components/deployment/getDeploymentTransactionArgs', () => ({ getDeploymentTransactionArgs: vi.fn() })); From a49cb510768e129459fc51ab40e6febeb5296b37 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Sat, 15 Feb 2025 17:11:52 +0100 Subject: [PATCH 06/15] use modal service handler --- .../deployment/DeploymentSteps.svelte | 86 ++++++++----------- .../deployment/DisclaimerModal.svelte | 6 +- packages/ui-components/src/lib/index.ts | 1 + .../src/lib/components/DeployModal.svelte | 2 +- packages/webapp/src/lib/services/modal.ts | 49 +++-------- .../[deploymentKey]/+page.svelte | 3 +- 6 files changed, 58 insertions(+), 89 deletions(-) diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index f9ffc509f..6dd0d42f2 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -26,7 +26,6 @@ import { page } from '$app/stores'; import { onMount } from 'svelte'; import ShareChoicesButton from './ShareChoicesButton.svelte'; - import DisclaimerModal from './DisclaimerModal.svelte'; import { handleShareChoices } from '$lib/services/handleShareChoices'; enum DeploymentStepErrors { @@ -53,6 +52,19 @@ chainId: number; subgraphUrl: string; }) => void; + export let handleDisclaimerModal: (args: { + gui: DotrainOrderGui; + allTokenOutputs: OrderIO[]; + wagmiConfig: Writable; + subgraphUrl: string; + handleDeployModal: (args: { + approvals: ApprovalCalldataResult; + deploymentCalldata: DepositAndAddOrderCalldataResult; + orderbookAddress: Hex; + chainId: number; + subgraphUrl: string; + }) => void; + }) => void; export let handleUpdateGuiState: (gui: DotrainOrderGui) => void; let selectTokens: SelectTokens | null = null; @@ -72,7 +84,6 @@ export let wagmiConnected: Writable; export let appKitModal: Writable; export let stateFromUrl: string | null = null; - $: if (deployment) { handleDeploymentChange(deployment.key); } @@ -165,42 +176,6 @@ } } - async function handleAddOrderClick() { - showDisclaimerModal = true; - try { - if (!gui || !$wagmiConfig) return; - const { address } = getAccount($wagmiConfig); - if (!address) return; - let approvals = await gui.generateApprovalCalldatas(address); - const deploymentCalldata = await gui.generateDepositAndAddOrderCalldatas(); - const chainId = gui.getCurrentDeployment().deployment.order.network['chain-id'] as number; - // @ts-expect-error orderbook is not typed - const orderbookAddress = gui.getCurrentDeployment().deployment.order.orderbook.address; - const outputTokenInfos = await Promise.all( - allTokenOutputs.map((token) => gui?.getTokenInfo(token.token?.key as string)) - ); - - approvals = approvals.map((approval) => { - const token = outputTokenInfos.find((token) => token?.address === approval.token); - return { - ...approval, - symbol: token?.symbol - }; - }); - - handleDeployModal({ - approvals, - deploymentCalldata, - orderbookAddress, - chainId, - subgraphUrl - }); - } catch (e) { - error = DeploymentStepErrors.ADD_ORDER_FAILED; - errorDetails = e instanceof Error ? e.message : 'Unknown error'; - } - } - async function _handleShareChoices() { if (!gui) return; await handleShareChoices(gui); @@ -228,6 +203,29 @@ handleUpdateGuiState(gui); } + async function handleDeployButtonClick() { + if (!gui) { + error = DeploymentStepErrors.NO_GUI; + return; + } + if (!allTokenOutputs) { + error = DeploymentStepErrors.NO_TOKEN_OUTPUTS; + return; + } + if (!wagmiConfig) { + error = DeploymentStepErrors.NO_CHAIN; + return; + } + + handleDisclaimerModal({ + gui, + allTokenOutputs, + wagmiConfig, + subgraphUrl, + handleDeployModal + }); + } + const areAllTokensSelected = async () => { if (gui) { try { @@ -292,7 +290,7 @@
{#if $wagmiConnected} - + {:else} @@ -313,13 +311,3 @@ {/if} {/if}
- -{#if showDisclaimerModal && gui && allTokenOutputs && wagmiConfig} - -{/if} diff --git a/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte b/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte index fa2d9e310..68b06e552 100644 --- a/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte +++ b/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte @@ -12,15 +12,17 @@ } from '@rainlanguage/orderbook/js_api'; import type { Hex } from 'viem'; import type { HandleAddOrderResult } from './getDeploymentTransactionArgs'; - export let open: boolean; + export let open: boolean = false; export let gui: DotrainOrderGui; export let allTokenOutputs: OrderIO[]; export let wagmiConfig: Writable; + export let subgraphUrl: string; export let handleDeployModal: (args: { approvals: ApprovalCalldataResult; deploymentCalldata: DepositAndAddOrderCalldataResult; orderbookAddress: Hex; chainId: number; + subgraphUrl: string; }) => void; let result: HandleAddOrderResult | null = null; @@ -49,7 +51,7 @@ return; } else { open = false; - handleDeployModal(result); + handleDeployModal({ ...result, subgraphUrl: subgraphUrl }); } } diff --git a/packages/ui-components/src/lib/index.ts b/packages/ui-components/src/lib/index.ts index 38baec9eb..753c17ffb 100644 --- a/packages/ui-components/src/lib/index.ts +++ b/packages/ui-components/src/lib/index.ts @@ -62,6 +62,7 @@ export { default as InputHex } from './components/input/InputHex.svelte'; export { default as InputTokenAmount } from './components/input/InputTokenAmount.svelte'; export { default as WalletConnect } from './components/wallet/WalletConnect.svelte'; export { default as StrategyShortTile } from './components/deployment/StrategyShortTile.svelte'; +export { default as DisclaimerModal } from './components/deployment/DisclaimerModal.svelte'; //Types export type { AppStoresInterface } from './types/appStores.ts'; diff --git a/packages/webapp/src/lib/components/DeployModal.svelte b/packages/webapp/src/lib/components/DeployModal.svelte index 2111651d6..162f397d8 100644 --- a/packages/webapp/src/lib/components/DeployModal.svelte +++ b/packages/webapp/src/lib/components/DeployModal.svelte @@ -8,7 +8,7 @@ import { wagmiConfig } from '$lib/stores/wagmi'; import TransactionModal from './TransactionModal.svelte'; - export let open: boolean; + export let open: boolean = false; export let approvals: ApprovalCalldataResult; export let deploymentCalldata: DepositAndAddOrderCalldataResult; export let orderbookAddress: Hex; diff --git a/packages/webapp/src/lib/services/modal.ts b/packages/webapp/src/lib/services/modal.ts index 3342ea98d..c69ed3007 100644 --- a/packages/webapp/src/lib/services/modal.ts +++ b/packages/webapp/src/lib/services/modal.ts @@ -1,49 +1,26 @@ import DeployModal from '$lib/components/DeployModal.svelte'; import DepositOrWithdrawModal from '$lib/components/DepositOrWithdrawModal.svelte'; import OrderRemoveModal from '$lib/components/OrderRemoveModal.svelte'; -import type { - ApprovalCalldataResult, - DepositAndAddOrderCalldataResult, - OrderSubgraph, - Vault -} from '@rainlanguage/orderbook/js_api'; -import type { Hex } from 'viem'; -import type { Config } from 'wagmi'; +import { DisclaimerModal } from '@rainlanguage/ui-components'; +import type { ComponentProps } from 'svelte'; -export type DeployModalProps = { - approvals: ApprovalCalldataResult; - deploymentCalldata: DepositAndAddOrderCalldataResult; - orderbookAddress: Hex; - chainId: number; - subgraphUrl: string; -}; - -export type DepositOrWithdrawModalProps = { - vault: Vault; - onDepositOrWithdraw: () => void; - action: 'deposit' | 'withdraw'; - chainId: number; - rpcUrl: string; - subgraphUrl: string; -}; - -export type OrderRemoveModalProps = { - order: OrderSubgraph; - onRemove: () => void; - open?: boolean; - wagmiConfig: Config; - chainId: number; - orderbookAddress: string; -}; +export type DisclaimerModalProps = ComponentProps; +export type DepositOrWithdrawModalProps = ComponentProps; +export type OrderRemoveModalProps = ComponentProps; +export type DeployModalProps = ComponentProps; export const handleDeployModal = (args: DeployModalProps) => { - new DeployModal({ target: document.body, props: { open: true, ...args } }); + new DeployModal({ target: document.body, props: { ...args, open: true } }); }; export const handleDepositOrWithdrawModal = (args: DepositOrWithdrawModalProps) => { - new DepositOrWithdrawModal({ target: document.body, props: { open: true, ...args } }); + new DepositOrWithdrawModal({ target: document.body, props: { ...args, open: true } }); }; export const handleOrderRemoveModal = (args: OrderRemoveModalProps) => { - new OrderRemoveModal({ target: document.body, props: { open: true, ...args } }); + new OrderRemoveModal({ target: document.body, props: { ...args, open: true } }); +}; + +export const handleDisclaimerModal = (args: DisclaimerModalProps) => { + new DisclaimerModal({ target: document.body, props: { ...args, open: true } }); }; diff --git a/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte b/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte index 8ed5fd5dd..3a012b5cc 100644 --- a/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte +++ b/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte @@ -3,7 +3,7 @@ import { goto } from '$app/navigation'; import { DeploymentSteps, PageHeader } from '@rainlanguage/ui-components'; import { wagmiConfig, connected, appKitModal } from '$lib/stores/wagmi'; - import { handleDeployModal } from '$lib/services/modal'; + import { handleDeployModal, handleDisclaimerModal } from '$lib/services/modal'; import { handleUpdateGuiState } from '$lib/services/handleUpdateGuiState'; const { settings } = $page.data.stores; const { dotrain, deployment } = $page.data; @@ -33,5 +33,6 @@ {settings} {stateFromUrl} {handleUpdateGuiState} + {handleDisclaimerModal} /> {/if} From cfb0df9a29f00294c3af514ba448cafef18e15e6 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Sat, 15 Feb 2025 19:29:33 +0100 Subject: [PATCH 07/15] fix types --- .../components/deployment/DeploymentSteps.svelte | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index 6dd0d42f2..46c3627f1 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -45,25 +45,22 @@ export let settings: Writable; export let dotrain: string; export let deployment: GuiDeployment; - export let handleDeployModal: (args: { + + type DeploymentArgs = { approvals: ApprovalCalldataResult; deploymentCalldata: DepositAndAddOrderCalldataResult; orderbookAddress: Hex; chainId: number; subgraphUrl: string; - }) => void; + }; + + export let handleDeployModal: (args: DeploymentArgs) => void; export let handleDisclaimerModal: (args: { gui: DotrainOrderGui; allTokenOutputs: OrderIO[]; wagmiConfig: Writable; subgraphUrl: string; - handleDeployModal: (args: { - approvals: ApprovalCalldataResult; - deploymentCalldata: DepositAndAddOrderCalldataResult; - orderbookAddress: Hex; - chainId: number; - subgraphUrl: string; - }) => void; + handleDeployModal: (args: DeploymentArgs) => void; }) => void; export let handleUpdateGuiState: (gui: DotrainOrderGui) => void; @@ -76,7 +73,6 @@ let gui: DotrainOrderGui | null = null; let error: DeploymentStepErrors | null = null; let errorDetails: string | null = null; - let showDisclaimerModal = false; let networkKey: string | null = null; let subgraphUrl: string = ''; From 2754565005d08821b4b5c3cd9b8095e553f7a831 Mon Sep 17 00:00:00 2001 From: highonhopium Date: Sat, 15 Feb 2025 18:33:07 +0000 Subject: [PATCH 08/15] type --- .../lib/components/deployment/DeploymentSteps.svelte | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index 46c3627f1..f896718a5 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -27,6 +27,8 @@ import { onMount } from 'svelte'; import ShareChoicesButton from './ShareChoicesButton.svelte'; import { handleShareChoices } from '$lib/services/handleShareChoices'; + import DisclaimerModal from './DisclaimerModal.svelte'; + import type { ComponentProps } from 'svelte'; enum DeploymentStepErrors { NO_GUI = 'Error loading GUI', @@ -55,13 +57,7 @@ }; export let handleDeployModal: (args: DeploymentArgs) => void; - export let handleDisclaimerModal: (args: { - gui: DotrainOrderGui; - allTokenOutputs: OrderIO[]; - wagmiConfig: Writable; - subgraphUrl: string; - handleDeployModal: (args: DeploymentArgs) => void; - }) => void; + export let handleDisclaimerModal: (args: ComponentProps) => void; export let handleUpdateGuiState: (gui: DotrainOrderGui) => void; let selectTokens: SelectTokens | null = null; From a4963a69469d1cbaeb9ec927b48d86e662d95f35 Mon Sep 17 00:00:00 2001 From: highonhopium Date: Sat, 15 Feb 2025 18:38:13 +0000 Subject: [PATCH 09/15] types --- .../deployment/DeploymentSteps.svelte | 9 +-------- .../deployment/DisclaimerModal.svelte | 18 ++++-------------- packages/ui-components/src/lib/index.ts | 1 + .../ui-components/src/lib/types/transaction.ts | 11 +++++++++++ packages/webapp/src/lib/services/modal.ts | 5 ++--- 5 files changed, 19 insertions(+), 25 deletions(-) diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index f896718a5..cf9a743d6 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -29,6 +29,7 @@ import { handleShareChoices } from '$lib/services/handleShareChoices'; import DisclaimerModal from './DisclaimerModal.svelte'; import type { ComponentProps } from 'svelte'; + import type { DeploymentArgs } from '$lib/types/transaction'; enum DeploymentStepErrors { NO_GUI = 'Error loading GUI', @@ -48,14 +49,6 @@ export let dotrain: string; export let deployment: GuiDeployment; - type DeploymentArgs = { - approvals: ApprovalCalldataResult; - deploymentCalldata: DepositAndAddOrderCalldataResult; - orderbookAddress: Hex; - chainId: number; - subgraphUrl: string; - }; - export let handleDeployModal: (args: DeploymentArgs) => void; export let handleDisclaimerModal: (args: ComponentProps) => void; export let handleUpdateGuiState: (gui: DotrainOrderGui) => void; diff --git a/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte b/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte index 68b06e552..ba6b25bf2 100644 --- a/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte +++ b/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte @@ -4,26 +4,16 @@ import { getDeploymentTransactionArgs } from './getDeploymentTransactionArgs'; import type { Config } from 'wagmi'; import type { Writable } from 'svelte/store'; - import type { - ApprovalCalldataResult, - DepositAndAddOrderCalldataResult, - DotrainOrderGui, - OrderIO - } from '@rainlanguage/orderbook/js_api'; - import type { Hex } from 'viem'; + import type { DotrainOrderGui, OrderIO } from '@rainlanguage/orderbook/js_api'; + import type { DeploymentArgs } from '@rainlanguage/ui-components'; import type { HandleAddOrderResult } from './getDeploymentTransactionArgs'; + import type { DeploymentArgs } from '$lib/types/transaction'; export let open: boolean = false; export let gui: DotrainOrderGui; export let allTokenOutputs: OrderIO[]; export let wagmiConfig: Writable; export let subgraphUrl: string; - export let handleDeployModal: (args: { - approvals: ApprovalCalldataResult; - deploymentCalldata: DepositAndAddOrderCalldataResult; - orderbookAddress: Hex; - chainId: number; - subgraphUrl: string; - }) => void; + export let handleDeployModal: (args: DeploymentArgs) => void; let result: HandleAddOrderResult | null = null; let error: string | null = null; diff --git a/packages/ui-components/src/lib/index.ts b/packages/ui-components/src/lib/index.ts index 753c17ffb..06691116c 100644 --- a/packages/ui-components/src/lib/index.ts +++ b/packages/ui-components/src/lib/index.ts @@ -72,6 +72,7 @@ export { TransactionErrorMessage, type TransactionState } from './stores/transactionStore'; +export type { DeploymentArgs } from './types/transaction'; // Functions export { createResolvableQuery, createResolvableInfiniteQuery } from './__mocks__/queries'; diff --git a/packages/ui-components/src/lib/types/transaction.ts b/packages/ui-components/src/lib/types/transaction.ts index e69de29bb..e2bfc3da0 100644 --- a/packages/ui-components/src/lib/types/transaction.ts +++ b/packages/ui-components/src/lib/types/transaction.ts @@ -0,0 +1,11 @@ +import type { DepositAndAddOrderCalldataResult } from '@rainlanguage/orderbook/js_api'; +import type { ApprovalCalldataResult } from '@rainlanguage/orderbook/js_api'; +import type { Hex } from 'viem'; + +export type DeploymentArgs = { + approvals: ApprovalCalldataResult; + deploymentCalldata: DepositAndAddOrderCalldataResult; + orderbookAddress: Hex; + chainId: number; + subgraphUrl: string; +}; diff --git a/packages/webapp/src/lib/services/modal.ts b/packages/webapp/src/lib/services/modal.ts index c69ed3007..756e5b621 100644 --- a/packages/webapp/src/lib/services/modal.ts +++ b/packages/webapp/src/lib/services/modal.ts @@ -1,15 +1,14 @@ import DeployModal from '$lib/components/DeployModal.svelte'; import DepositOrWithdrawModal from '$lib/components/DepositOrWithdrawModal.svelte'; import OrderRemoveModal from '$lib/components/OrderRemoveModal.svelte'; -import { DisclaimerModal } from '@rainlanguage/ui-components'; +import { DisclaimerModal, type DeploymentArgs } from '@rainlanguage/ui-components'; import type { ComponentProps } from 'svelte'; export type DisclaimerModalProps = ComponentProps; export type DepositOrWithdrawModalProps = ComponentProps; export type OrderRemoveModalProps = ComponentProps; -export type DeployModalProps = ComponentProps; -export const handleDeployModal = (args: DeployModalProps) => { +export const handleDeployModal = (args: DeploymentArgs) => { new DeployModal({ target: document.body, props: { ...args, open: true } }); }; From 71e3972b77e9316195d50fef75fa57d48180eb93 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Sat, 15 Feb 2025 20:08:29 +0100 Subject: [PATCH 10/15] rm unused --- .../src/lib/components/deployment/DeploymentSteps.svelte | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index cf9a743d6..13829a325 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -13,8 +13,6 @@ type GuiFieldDefinition, type GuiDeployment, type OrderIO, - type ApprovalCalldataResult, - type DepositAndAddOrderCalldataResult, type SelectTokens } from '@rainlanguage/orderbook/js_api'; import { fade } from 'svelte/transition'; @@ -22,7 +20,6 @@ import { type Config } from '@wagmi/core'; import { type Writable } from 'svelte/store'; import type { AppKit } from '@reown/appkit'; - import type { Hex } from 'viem'; import { page } from '$app/stores'; import { onMount } from 'svelte'; import ShareChoicesButton from './ShareChoicesButton.svelte'; From 75c5e5b6f27a6225b30b8f8b1c6826b44a6227bc Mon Sep 17 00:00:00 2001 From: highonhopium Date: Sat, 15 Feb 2025 19:14:45 +0000 Subject: [PATCH 11/15] tests and types --- .../src/__tests__/DeploymentSteps.test.ts | 29 +++++++++++++++---- .../src/__tests__/DisclaimerModal.test.ts | 10 +++++-- .../deployment/DisclaimerModal.svelte | 1 - packages/webapp/src/lib/services/modal.ts | 8 ++--- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts index 46566e7f3..6836d4e63 100644 --- a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts +++ b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts @@ -2,11 +2,13 @@ import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { render, screen, waitFor } from '@testing-library/svelte'; import DeploymentSteps from '../lib/components/deployment/DeploymentSteps.svelte'; import { DotrainOrderGui, type Scenario } from '@rainlanguage/orderbook/js_api'; - import type { ComponentProps } from 'svelte'; import { writable } from 'svelte/store'; import type { AppKit } from '@reown/appkit'; import type { ConfigSource } from '../lib/typeshare/config'; +import type { DeploymentArgs } from '$lib/types/transaction'; +import type { DisclaimerModal } from '$lib'; + const { mockWagmiConfigStore, mockConnectedStore } = await vi.hoisted( () => import('../lib/__mocks__/stores') ); @@ -634,7 +636,10 @@ describe('DeploymentSteps', () => { wagmiConfig: mockWagmiConfigStore, wagmiConnected: mockConnectedStore, appKitModal: writable({} as AppKit), - handleDeployModal: vi.fn(), + 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() } @@ -660,7 +665,10 @@ describe('DeploymentSteps', () => { wagmiConfig: mockWagmiConfigStore, wagmiConnected: mockConnectedStore, appKitModal: writable({} as AppKit), - handleDeployModal: vi.fn(), + 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() } @@ -686,7 +694,10 @@ describe('DeploymentSteps', () => { wagmiConfig: mockWagmiConfigStore, wagmiConnected: mockConnectedStore, appKitModal: writable({} as AppKit), - handleDeployModal: vi.fn(), + 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() } @@ -723,7 +734,10 @@ describe('DeploymentSteps', () => { wagmiConfig: mockWagmiConfigStore, wagmiConnected: mockConnectedStore, appKitModal: writable({} as AppKit), - handleDeployModal: vi.fn(), + 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() } @@ -758,7 +772,10 @@ describe('DeploymentSteps', () => { wagmiConfig: mockWagmiConfigStore, wagmiConnected: mockConnectedStore, appKitModal: writable({} as AppKit), - handleDeployModal: vi.fn(), + 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() } diff --git a/packages/ui-components/src/__tests__/DisclaimerModal.test.ts b/packages/ui-components/src/__tests__/DisclaimerModal.test.ts index f586ba53b..2f581b297 100644 --- a/packages/ui-components/src/__tests__/DisclaimerModal.test.ts +++ b/packages/ui-components/src/__tests__/DisclaimerModal.test.ts @@ -5,7 +5,7 @@ import { getDeploymentTransactionArgs } from '../lib/components/deployment/getDe import { writable } from 'svelte/store'; import type { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; import type { OrderIO } from '@rainlanguage/orderbook/js_api'; - +import type { DeploymentArgs } from '../lib/types/transaction'; vi.mock('../lib/components/deployment/getDeploymentTransactionArgs', () => ({ getDeploymentTransactionArgs: vi.fn() })); @@ -14,7 +14,7 @@ describe('DisclaimerModal', () => { const mockGui = {} as DotrainOrderGui; const mockOutputs = [] as OrderIO[]; const mockWagmiConfig = writable(undefined); - const mockHandleDeployModal = vi.fn(); + const mockHandleDeployModal = vi.fn() as unknown as (args: DeploymentArgs) => void; beforeEach(() => { vi.clearAllMocks(); @@ -35,6 +35,7 @@ describe('DisclaimerModal', () => { gui: mockGui, allTokenOutputs: mockOutputs, wagmiConfig: mockWagmiConfig, + subgraphUrl: 'https://example.com', handleDeployModal: mockHandleDeployModal } }); @@ -52,6 +53,7 @@ describe('DisclaimerModal', () => { gui: mockGui, allTokenOutputs: mockOutputs, wagmiConfig: mockWagmiConfig, + subgraphUrl: 'https://example.com', handleDeployModal: mockHandleDeployModal } }); @@ -67,7 +69,8 @@ describe('DisclaimerModal', () => { approvals: {}, deploymentCalldata: {}, orderbookAddress: '0x123', - chainId: 1 + chainId: 1, + subgraphUrl: 'https://example.com' }; (getDeploymentTransactionArgs as Mock).mockResolvedValue(mockResult); @@ -77,6 +80,7 @@ describe('DisclaimerModal', () => { gui: mockGui, allTokenOutputs: mockOutputs, wagmiConfig: mockWagmiConfig, + subgraphUrl: 'https://example.com', handleDeployModal: mockHandleDeployModal } }); diff --git a/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte b/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte index ba6b25bf2..c3df99998 100644 --- a/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte +++ b/packages/ui-components/src/lib/components/deployment/DisclaimerModal.svelte @@ -7,7 +7,6 @@ import type { DotrainOrderGui, OrderIO } from '@rainlanguage/orderbook/js_api'; import type { DeploymentArgs } from '@rainlanguage/ui-components'; import type { HandleAddOrderResult } from './getDeploymentTransactionArgs'; - import type { DeploymentArgs } from '$lib/types/transaction'; export let open: boolean = false; export let gui: DotrainOrderGui; export let allTokenOutputs: OrderIO[]; diff --git a/packages/webapp/src/lib/services/modal.ts b/packages/webapp/src/lib/services/modal.ts index 756e5b621..c86c32519 100644 --- a/packages/webapp/src/lib/services/modal.ts +++ b/packages/webapp/src/lib/services/modal.ts @@ -8,18 +8,18 @@ export type DisclaimerModalProps = ComponentProps; export type DepositOrWithdrawModalProps = ComponentProps; export type OrderRemoveModalProps = ComponentProps; -export const handleDeployModal = (args: DeploymentArgs) => { +export const handleDeployModal = (args: Omit) => { new DeployModal({ target: document.body, props: { ...args, open: true } }); }; -export const handleDepositOrWithdrawModal = (args: DepositOrWithdrawModalProps) => { +export const handleDepositOrWithdrawModal = (args: Omit) => { new DepositOrWithdrawModal({ target: document.body, props: { ...args, open: true } }); }; -export const handleOrderRemoveModal = (args: OrderRemoveModalProps) => { +export const handleOrderRemoveModal = (args: Omit) => { new OrderRemoveModal({ target: document.body, props: { ...args, open: true } }); }; -export const handleDisclaimerModal = (args: DisclaimerModalProps) => { +export const handleDisclaimerModal = (args: Omit) => { new DisclaimerModal({ target: document.body, props: { ...args, open: true } }); }; From f04f389e3b2e06b1bf5b38b6cd22765d31ebae0e Mon Sep 17 00:00:00 2001 From: highonhopium Date: Sat, 15 Feb 2025 19:58:02 +0000 Subject: [PATCH 12/15] updates --- .../deployment/DeploymentSteps.svelte | 83 ++++++++++++++----- .../deployment/DisclaimerModal.svelte | 67 +++------------ .../components/wallet/WalletConnect.svelte | 5 +- .../webapp/src/lib/components/Sidebar.svelte | 4 +- 4 files changed, 77 insertions(+), 82 deletions(-) diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index 13829a325..fad9102b8 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -1,11 +1,11 @@ - -
+ +
@@ -56,7 +21,7 @@
-
    +
    • This front end is provided as a tool to interact with the Raindex smart contracts.
    • @@ -74,25 +39,13 @@
    • Do not invest unless you are prepared to lose all funds.
-
+
- {deployButtonText} - - -
-
- {#if error} - {error} - {/if} - {#if errorDetails} - {errorDetails} - {/if} +
diff --git a/packages/ui-components/src/lib/components/wallet/WalletConnect.svelte b/packages/ui-components/src/lib/components/wallet/WalletConnect.svelte index b222936e3..8e2f5896e 100644 --- a/packages/ui-components/src/lib/components/wallet/WalletConnect.svelte +++ b/packages/ui-components/src/lib/components/wallet/WalletConnect.svelte @@ -3,8 +3,10 @@ import { CheckCircleOutline } from 'flowbite-svelte-icons'; import type { Writable } from 'svelte/store'; import type { AppKit } from '@reown/appkit'; + import { twMerge } from 'tailwind-merge'; export let appKitModal: Writable; export let connected: Writable; + export let classes: string = ''; function handleClick() { $appKitModal.open(); } @@ -13,7 +15,8 @@