From 7b36f5e0d4274a907000b032afbf56ba152c3197 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Wed, 12 Feb 2025 13:24:54 +0100 Subject: [PATCH 01/23] add markdown --- package-lock.json | 1 + package.json | 1 + .../src/__tests__/StrategySection.test.ts | 40 ++++++++++++++++++ .../deployment/StrategySection.svelte | 41 +++++++++++++++++-- packages/webapp/env.example | 2 +- 5 files changed, 81 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 58ffb73bd..c6fecdad3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "flowbite": "^2.2.1", "flowbite-svelte": "^0.44.21", "flowbite-svelte-icons": "^0.4.5", + "svelte-markdown": "^0.4.1", "wagmi": "^2.14.7" }, "devDependencies": { diff --git a/package.json b/package.json index d97f8df23..515471b18 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "flowbite": "^2.2.1", "flowbite-svelte": "^0.44.21", "flowbite-svelte-icons": "^0.4.5", + "svelte-markdown": "^0.4.1", "wagmi": "^2.14.7" } } diff --git a/packages/ui-components/src/__tests__/StrategySection.test.ts b/packages/ui-components/src/__tests__/StrategySection.test.ts index 9d9a1efdf..b7a3be6ad 100644 --- a/packages/ui-components/src/__tests__/StrategySection.test.ts +++ b/packages/ui-components/src/__tests__/StrategySection.test.ts @@ -15,6 +15,11 @@ vi.mock('@rainlanguage/orderbook/js_api', () => ({ } })); +vi.mock('svelte-markdown', async () => { + const mockSvelteMarkdown = (await import('../lib/__mocks__/MockComponent.svelte')).default; + return { default: mockSvelteMarkdown }; +}); + describe('StrategySection', () => { beforeEach(() => { vi.clearAllMocks(); @@ -111,4 +116,39 @@ describe('StrategySection', () => { expect(screen.getByText('Failed to fetch')).toBeInTheDocument(); }); }); + + it('renders markdown if description is a markdown url', async () => { + const mockDotrain = 'mock dotrain content'; + const mockStrategyDetails = { + name: 'Test Strategy', + description: 'https://example.com/description.md' + }; + const mockMarkdownContent = 'mock markdown content'; + + mockFetch + .mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve(mockDotrain) + }) + + .mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve(mockMarkdownContent) + }); + + vi.mocked(DotrainOrderGui.getStrategyDetails).mockResolvedValueOnce(mockStrategyDetails); + + render(StrategySection, { + props: { + strategyUrl: 'http://example.com/strategy', + strategyName: 'TestStrategy' + } + }); + + await waitFor(() => { + expect(screen.getByText('Test Strategy')).toBeInTheDocument(); + expect(screen.getByTestId('markdown-content')).toBeInTheDocument(); + expect(mockFetch).toHaveBeenCalledWith('https://example.com/description.md'); + }); + }); }); diff --git a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte b/packages/ui-components/src/lib/components/deployment/StrategySection.svelte index c631ec29d..3f061b7d9 100644 --- a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte +++ b/packages/ui-components/src/lib/components/deployment/StrategySection.svelte @@ -2,6 +2,7 @@ import { fade } from 'svelte/transition'; import { DotrainOrderGui, type NameAndDescription } from '@rainlanguage/orderbook/js_api'; import DeploymentsSection from './DeploymentsSection.svelte'; + import SvelteMarkdown from 'svelte-markdown'; export let strategyUrl: string = ''; export let strategyName: string = ''; @@ -10,6 +11,22 @@ let dotrain: string; let error: string; let errorDetails: string; + let markdownContent: string = ''; + + const isMarkdownUrl = (url: string): boolean => { + return url.trim().toLowerCase().endsWith('.md'); + }; + + const fetchMarkdownContent = async (url: string) => { + try { + const response = await fetch(url); + if (!response.ok) throw new Error(`Failed to fetch markdown: ${response.statusText}`); + return await response.text(); + } catch (e) { + console.error('Error fetching markdown:', e); + return null; + } + }; const getStrategy = async () => { try { @@ -21,6 +38,15 @@ } try { strategyDetails = await DotrainOrderGui.getStrategyDetails(dotrain); + console.log(strategyDetails); + if (strategyDetails.description && isMarkdownUrl(strategyDetails.description)) { + console.log('fetching markdown'); + const content = await fetchMarkdownContent(strategyDetails.description); + if (content) { + markdownContent = content; + console.log('markdownContent', markdownContent); + } + } } catch (e: unknown) { error = 'Error getting strategy details'; errorDetails = e instanceof Error ? e.message : 'Unknown error'; @@ -41,9 +67,18 @@

{strategyDetails.name}

-

- {strategyDetails.description} -

+ {#if isMarkdownUrl(strategyDetails.description) && markdownContent} +
+ +
+ {:else} +

+ {strategyDetails.description} +

+ {/if} diff --git a/packages/webapp/env.example b/packages/webapp/env.example index 023f373ba..282fe01e1 100644 --- a/packages/webapp/env.example +++ b/packages/webapp/env.example @@ -1 +1 @@ -PLUBLIC_WALLETCONNECT_PROJECT_ID= \ No newline at end of file +PUBLIC_WALLETCONNECT_PROJECT_ID= \ No newline at end of file From ea460c35a1967aca4323073ee2da6a7e1a61bc9b Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Wed, 12 Feb 2025 13:43:17 +0100 Subject: [PATCH 02/23] add base css and to format markdown --- package-lock.json | 118 ++++++++++++------ package.json | 5 +- .../deployment/StrategySection.svelte | 8 +- .../lib/components/detail/OrderDetail.svelte | 2 +- packages/webapp/postcss.config.js | 4 +- packages/webapp/src/app.css | 34 +++++ .../webapp/src/lib/components/Sidebar.svelte | 14 +-- postcss.config.js | 1 + src/app.css | 1 + 9 files changed, 135 insertions(+), 52 deletions(-) create mode 100644 postcss.config.js create mode 100644 src/app.css diff --git a/package-lock.json b/package-lock.json index c6fecdad3..b7b44e132 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@tailwindcss/typography": "^0.5.16", "@tanstack/svelte-query": "^5.59.20", "@testing-library/jest-dom": "^6.4.2", "@testing-library/svelte": "^5.1.0", @@ -50,7 +51,7 @@ "jsdom": "^24.0.0", "lodash": "^4.17.21", "mockttp": "^3.15.1", - "postcss": "^8.4.32", + "postcss": "^8.5.2", "prettier": "^3.3.2", "prettier-plugin-svelte": "^3.2.6", "prettier-plugin-tailwindcss": "^0.6.5", @@ -58,7 +59,7 @@ "svelte": "^4.2.7", "svelte-check": "^3.6.0", "tailwind-merge": "^2.5.4", - "tailwindcss": "^3.4.9", + "tailwindcss": "^3.4.17", "ts-node": "^10.9.1", "typescript": "^5.0.0", "typescript-eslint": "^8.0.0", @@ -4677,6 +4678,36 @@ "vite": "^5.0.0" } }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", + "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" + } + }, + "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@tanstack/query-core": { "version": "5.59.20", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.59.20.tgz", @@ -12173,6 +12204,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -12290,12 +12322,26 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", "license": "MIT" }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -12808,9 +12854,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", @@ -16600,9 +16646,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", + "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", "funding": [ { "type": "opencollective", @@ -16619,7 +16665,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -18651,33 +18697,33 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.14", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", - "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", - "chokidar": "^3.5.3", + "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.3.0", + "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", @@ -18723,6 +18769,18 @@ "node": ">= 6" } }, + "node_modules/tailwindcss/node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/tailwindcss/node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -18770,18 +18828,6 @@ } } }, - "node_modules/tailwindcss/node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, "node_modules/tailwindcss/node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", diff --git a/package.json b/package.json index 515471b18..b7f7b38a2 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@tailwindcss/typography": "^0.5.16", "@tanstack/svelte-query": "^5.59.20", "@testing-library/jest-dom": "^6.4.2", "@testing-library/svelte": "^5.1.0", @@ -52,7 +53,7 @@ "jsdom": "^24.0.0", "lodash": "^4.17.21", "mockttp": "^3.15.1", - "postcss": "^8.4.32", + "postcss": "^8.5.2", "prettier": "^3.3.2", "prettier-plugin-svelte": "^3.2.6", "prettier-plugin-tailwindcss": "^0.6.5", @@ -60,7 +61,7 @@ "svelte": "^4.2.7", "svelte-check": "^3.6.0", "tailwind-merge": "^2.5.4", - "tailwindcss": "^3.4.9", + "tailwindcss": "^3.4.17", "ts-node": "^10.9.1", "typescript": "^5.0.0", "typescript-eslint": "^8.0.0", diff --git a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte b/packages/ui-components/src/lib/components/deployment/StrategySection.svelte index 3f061b7d9..f72db3a26 100644 --- a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte +++ b/packages/ui-components/src/lib/components/deployment/StrategySection.svelte @@ -22,8 +22,7 @@ const response = await fetch(url); if (!response.ok) throw new Error(`Failed to fetch markdown: ${response.statusText}`); return await response.text(); - } catch (e) { - console.error('Error fetching markdown:', e); + } catch { return null; } }; @@ -40,11 +39,12 @@ strategyDetails = await DotrainOrderGui.getStrategyDetails(dotrain); console.log(strategyDetails); if (strategyDetails.description && isMarkdownUrl(strategyDetails.description)) { - console.log('fetching markdown'); const content = await fetchMarkdownContent(strategyDetails.description); if (content) { markdownContent = content; - console.log('markdownContent', markdownContent); + } else { + error = 'Error fetching markdown'; + errorDetails = 'Failed to fetch markdown content'; } } } catch (e: unknown) { diff --git a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte index 434c6ccd9..73854992c 100644 --- a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte @@ -196,7 +196,7 @@
diff --git a/packages/webapp/postcss.config.js b/packages/webapp/postcss.config.js index 2e7af2b7f..f1c8dac8d 100644 --- a/packages/webapp/postcss.config.js +++ b/packages/webapp/postcss.config.js @@ -1,6 +1,6 @@ -export default { +module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, - }, + } } diff --git a/packages/webapp/src/app.css b/packages/webapp/src/app.css index a31e44411..a15c106c9 100644 --- a/packages/webapp/src/app.css +++ b/packages/webapp/src/app.css @@ -1,3 +1,37 @@ @import 'tailwindcss/base'; @import 'tailwindcss/components'; @import 'tailwindcss/utilities'; + + +@layer base { + h1 { + @apply text-4xl font-bold mb-4; + } + h2 { + @apply text-3xl font-semibold mb-3; + } + h3 { + @apply text-2xl font-medium mb-2; + } + p { + @apply text-base mb-4 text-gray-700 dark:text-gray-300; + } + a { + @apply text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-200; + } + ul { + @apply list-disc list-inside mb-4; + } + ol { + @apply list-decimal list-inside mb-4; + } + li { + @apply mb-2; + } + blockquote { + @apply pl-4 border-l-4 border-gray-300 italic my-4; + } + code { + @apply bg-gray-100 dark:bg-gray-800 px-1 py-0.5 rounded; + } +} \ No newline at end of file diff --git a/packages/webapp/src/lib/components/Sidebar.svelte b/packages/webapp/src/lib/components/Sidebar.svelte index 732c04bfb..22f29afe4 100644 --- a/packages/webapp/src/lib/components/Sidebar.svelte +++ b/packages/webapp/src/lib/components/Sidebar.svelte @@ -65,12 +65,12 @@ {#if !sideBarHidden} (sideBarHidden = true)} /> {/if} - + - + @@ -89,7 +89,7 @@ - + @@ -103,10 +103,10 @@ - + - + - + diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 000000000..0519ecba6 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app.css b/src/app.css new file mode 100644 index 000000000..0519ecba6 --- /dev/null +++ b/src/app.css @@ -0,0 +1 @@ + \ No newline at end of file From 0003b97b57c951abb0880ad3431dcf3a1a201516 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Wed, 12 Feb 2025 17:33:10 +0100 Subject: [PATCH 03/23] add css rules and new registry --- crates/settings/src/gui.rs | 27 ++++++++++++++++++---- packages/webapp/postcss.config.js | 6 ++--- packages/webapp/src/lib/stores/registry.ts | 2 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/crates/settings/src/gui.rs b/crates/settings/src/gui.rs index 773f88809..06b405e10 100644 --- a/crates/settings/src/gui.rs +++ b/crates/settings/src/gui.rs @@ -263,7 +263,9 @@ impl_all_wasm_traits!(Gui); pub struct NameAndDescription { pub name: String, pub description: String, + pub short_description: Option, } + #[cfg(target_family = "wasm")] impl_all_wasm_traits!(NameAndDescription); @@ -376,7 +378,17 @@ impl Gui { Some("gui".to_string()), )?; - return Ok(NameAndDescription { name, description }); + let short_description = require_string( + get_hash_value(gui, "short-description", Some("gui".to_string()))?, + None, + Some("gui".to_string()), + )?; + + return Ok(NameAndDescription { + name, + description, + short_description: Some(short_description), + }); } } Err(YamlError::Field { @@ -422,8 +434,14 @@ impl Gui { Some(location.clone()), )?; - deployment_details - .insert(deployment_key, NameAndDescription { name, description }); + deployment_details.insert( + deployment_key, + NameAndDescription { + name, + description, + short_description: None, + }, + ); } } } @@ -1474,8 +1492,7 @@ gui: - binding: test name: test presets: - - value: - - test + - value: test "#; let error = Gui::parse_from_yaml_optional( vec![get_document(&format!("{yaml_prefix}{yaml}"))], diff --git a/packages/webapp/postcss.config.js b/packages/webapp/postcss.config.js index f1c8dac8d..e99ebc2c0 100644 --- a/packages/webapp/postcss.config.js +++ b/packages/webapp/postcss.config.js @@ -1,6 +1,6 @@ -module.exports = { +export default { plugins: { tailwindcss: {}, autoprefixer: {}, - } -} + }, +} \ No newline at end of file diff --git a/packages/webapp/src/lib/stores/registry.ts b/packages/webapp/src/lib/stores/registry.ts index f5a51698d..dc20a153c 100644 --- a/packages/webapp/src/lib/stores/registry.ts +++ b/packages/webapp/src/lib/stores/registry.ts @@ -1,5 +1,5 @@ import { writable } from 'svelte/store'; export const registryUrl = writable( - 'https://raw.githubusercontent.com/rainlanguage/rain.strategies/3b4ef719fc60064d62fff1366afd97d5715ddd4a/ports/registry' + 'https://raw.githubusercontent.com/rainlanguage/rain.strategies/refs/heads/main/ports/registry' ); From 55e536ac79c39a0bee9af426347340da3df64c7f Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Wed, 12 Feb 2025 17:49:45 +0100 Subject: [PATCH 04/23] update gui test --- packages/orderbook/test/js_api/gui.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/orderbook/test/js_api/gui.test.ts b/packages/orderbook/test/js_api/gui.test.ts index 32354e307..dc8612da9 100644 --- a/packages/orderbook/test/js_api/gui.test.ts +++ b/packages/orderbook/test/js_api/gui.test.ts @@ -22,10 +22,12 @@ const guiConfig = ` gui: name: Fixed limit description: Fixed limit order strategy + short-description: Buy WETH with USDC on Base. deployments: some-deployment: name: Buy WETH with USDC on Base. description: Buy WETH with USDC for fixed price on Base network. + short-description: Buy WETH with USDC on Base. deposits: - token: token1 min: 0 @@ -373,6 +375,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () await DotrainOrderGui.getStrategyDetails(dotrainWithGui); assert.equal(strategyDetails.name, 'Fixed limit'); assert.equal(strategyDetails.description, 'Fixed limit order strategy'); + assert.equal(strategyDetails.short_description, 'Buy WETH with USDC on Base.'); }); it('should get deployment details', async () => { From 59a6566effa8e20c659ec23cf10fe96a1da52ca5 Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Wed, 12 Feb 2025 18:19:39 +0100 Subject: [PATCH 05/23] console.log remove --- .../src/lib/components/deployment/StrategySection.svelte | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte b/packages/ui-components/src/lib/components/deployment/StrategySection.svelte index f72db3a26..6bb24b848 100644 --- a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte +++ b/packages/ui-components/src/lib/components/deployment/StrategySection.svelte @@ -37,7 +37,6 @@ } try { strategyDetails = await DotrainOrderGui.getStrategyDetails(dotrain); - console.log(strategyDetails); if (strategyDetails.description && isMarkdownUrl(strategyDetails.description)) { const content = await fetchMarkdownContent(strategyDetails.description); if (content) { From e457a01add01a916eabee78cc84397bc3be1237c Mon Sep 17 00:00:00 2001 From: highonhopium Date: Wed, 12 Feb 2025 21:56:09 +0000 Subject: [PATCH 06/23] wip routing fixes --- .../deployment/DeploymentSteps.svelte | 1 - .../deployment/StrategySection.svelte | 4 ++- .../{[deploymentKey]/+page.ts => +layout.ts} | 7 ++-- .../routes/deploy/[strategyName]/+page.svelte | 33 +++++++++++++++++++ .../src/routes/deploy/[strategyName]/+page.ts | 5 --- 5 files changed, 40 insertions(+), 10 deletions(-) rename packages/webapp/src/routes/deploy/[strategyName]/{[deploymentKey]/+page.ts => +layout.ts} (92%) create mode 100644 packages/webapp/src/routes/deploy/[strategyName]/+page.svelte delete mode 100644 packages/webapp/src/routes/deploy/[strategyName]/+page.ts diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index 2ea48366d..ebfbea3b1 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -132,7 +132,6 @@ try { allTokenOutputs = gui.getCurrentDeployment().deployment.order.outputs; } catch (e) { - console.error(e); error = DeploymentStepErrors.NO_TOKEN_OUTPUTS; errorDetails = e instanceof Error ? e.message : 'Unknown error'; } diff --git a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte b/packages/ui-components/src/lib/components/deployment/StrategySection.svelte index 2e6045b83..2f6d4fa0d 100644 --- a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte +++ b/packages/ui-components/src/lib/components/deployment/StrategySection.svelte @@ -57,6 +57,8 @@ }; $: getStrategy(); + + $: console.log(strategyDetails); {#if dotrain && strategyDetails} @@ -66,6 +68,7 @@

{strategyDetails.name}

+
{strategyDetails.short_description}
{#if isMarkdownUrl(strategyDetails.description) && markdownContent}
@@ -81,7 +84,6 @@
- {:else if error}
diff --git a/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.ts b/packages/webapp/src/routes/deploy/[strategyName]/+layout.ts similarity index 92% rename from packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.ts rename to packages/webapp/src/routes/deploy/[strategyName]/+layout.ts index 629672178..8b53d4fb1 100644 --- a/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.ts +++ b/packages/webapp/src/routes/deploy/[strategyName]/+layout.ts @@ -2,10 +2,10 @@ import { registryUrl } from '$lib/stores/registry'; import { rawDotrain } from '$lib/stores/raw-dotrain'; import { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; import { get } from 'svelte/store'; -import type { PageLoad } from './$types'; +import type { LayoutLoad } from './$types'; import { redirect } from '@sveltejs/kit'; -export const load: PageLoad = async ({ fetch, params, parent }) => { +export const load: LayoutLoad = async ({ fetch, params, parent }) => { const { strategyName, deploymentKey } = params; const { registry } = await parent(); if (registry) { @@ -59,7 +59,8 @@ export const load: PageLoad = async ({ fetch, params, parent }) => { strategyName, key, name, - description + description, + deployment }; } catch { throw redirect(307, '/deploy'); diff --git a/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte b/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte new file mode 100644 index 000000000..63c22bbf6 --- /dev/null +++ b/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte @@ -0,0 +1,33 @@ + + +
+
+
+

+ {strategyDetails.name} +

+
{strategyDetails.short_description}
+ {#if isMarkdownUrl(strategyDetails.description) && markdownContent} +
+ +
+ {:else} +

+ {strategyDetails.description} +

+ {/if} +
+ +
+
diff --git a/packages/webapp/src/routes/deploy/[strategyName]/+page.ts b/packages/webapp/src/routes/deploy/[strategyName]/+page.ts deleted file mode 100644 index f2323f5fd..000000000 --- a/packages/webapp/src/routes/deploy/[strategyName]/+page.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { redirect } from '@sveltejs/kit'; - -export const load = () => { - throw redirect(307, '/deploy'); -}; From 3d4caa0a504f86d46c5bd60019d996834e425cf1 Mon Sep 17 00:00:00 2001 From: highonhopium Date: Wed, 12 Feb 2025 23:32:41 +0000 Subject: [PATCH 07/23] wip --- .../deployment/DeploymentPage.svelte | 40 -------------- .../deployment/DeploymentSteps.svelte | 19 ++++--- .../deployment/StrategySection.svelte | 5 +- packages/ui-components/src/lib/index.ts | 1 - packages/webapp/src/lib/constants.ts | 2 + .../services}/getFileRegistry.ts | 13 +++++ packages/webapp/src/lib/stores/registry.ts | 5 -- packages/webapp/src/routes/deploy/+layout.ts | 7 +-- .../webapp/src/routes/deploy/+page.svelte | 18 +++--- .../routes/deploy/[strategyName]/+layout.ts | 55 ++++--------------- .../routes/deploy/[strategyName]/+page.svelte | 31 +---------- .../[strategyName]/[deploymentKey]/+layout.ts | 24 ++++++++ .../[deploymentKey]/+page.svelte | 17 +++--- 13 files changed, 87 insertions(+), 150 deletions(-) delete mode 100644 packages/ui-components/src/lib/components/deployment/DeploymentPage.svelte create mode 100644 packages/webapp/src/lib/constants.ts rename packages/webapp/src/{routes/deploy => lib/services}/getFileRegistry.ts (73%) delete mode 100644 packages/webapp/src/lib/stores/registry.ts create mode 100644 packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+layout.ts diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentPage.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentPage.svelte deleted file mode 100644 index 4ee92aee3..000000000 --- a/packages/ui-components/src/lib/components/deployment/DeploymentPage.svelte +++ /dev/null @@ -1,40 +0,0 @@ - - - diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index ebfbea3b1..9b9892dcb 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -9,12 +9,13 @@ DotrainOrderGui, type GuiDeposit, type GuiFieldDefinition, - type NameAndDescription, type GuiDeployment, type OrderIO, type ApprovalCalldataResult, type DepositAndAddOrderCalldataResult, - DotrainOrder + DotrainOrder, + type GuiSelectTokens, + type NameAndDescription } from '@rainlanguage/orderbook/js_api'; import { fade } from 'svelte/transition'; import { Button, Toggle } from 'flowbite-svelte'; @@ -41,8 +42,7 @@ } export let dotrain: string; - export let deployment: string; - export let deploymentDetails: NameAndDescription; + export let deployment: GuiDeployment; export let handleDeployModal: (args: { approvals: ApprovalCalldataResult; deploymentCalldata: DepositAndAddOrderCalldataResult; @@ -50,7 +50,9 @@ chainId: number; }) => void; export let handleUpdateGuiState: (gui: DotrainOrderGui) => void; - let selectTokens: string[] | null = null; + + let deploymentDetails: NameAndDescription | null = null; + let selectTokens: GuiSelectTokens[] | null = null; let allDepositFields: GuiDeposit[] = []; let allTokenOutputs: OrderIO[] = []; let allFieldDefinitions: GuiFieldDefinition[] = []; @@ -66,7 +68,7 @@ export let stateFromUrl: string | null = null; $: if (deployment) { - handleDeploymentChange(deployment); + handleDeploymentChange(deployment.key); } async function handleDeploymentChange(deployment: string) { @@ -76,6 +78,7 @@ try { gui = await DotrainOrderGui.chooseDeployment(dotrain, deployment); + deploymentDetails = await DotrainOrderGui.getStrategyDetails(dotrain); if (gui) { try { @@ -265,10 +268,10 @@ {#if deploymentDetails}

- {deploymentDetails.name} + {deployment.name}

- {deploymentDetails.description} + {deployment.description}

{/if} diff --git a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte b/packages/ui-components/src/lib/components/deployment/StrategySection.svelte index 2f6d4fa0d..6fa93ed31 100644 --- a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte +++ b/packages/ui-components/src/lib/components/deployment/StrategySection.svelte @@ -57,8 +57,6 @@ }; $: getStrategy(); - - $: console.log(strategyDetails); {#if dotrain && strategyDetails} @@ -68,9 +66,8 @@

{strategyDetails.name}

-
{strategyDetails.short_description}
{#if isMarkdownUrl(strategyDetails.description) && markdownContent} -
+
{:else} diff --git a/packages/ui-components/src/lib/index.ts b/packages/ui-components/src/lib/index.ts index 87396d207..36703339d 100644 --- a/packages/ui-components/src/lib/index.ts +++ b/packages/ui-components/src/lib/index.ts @@ -60,7 +60,6 @@ export { default as OrderOrVaultHash } from './components/OrderOrVaultHash.svelt export { default as License } from './components/License.svelte'; export { default as ButtonDarkMode } from './components/ButtonDarkMode.svelte'; export { default as StrategySection } from './components/deployment/StrategySection.svelte'; -export { default as DeploymentPage } from './components/deployment/DeploymentPage.svelte'; 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'; diff --git a/packages/webapp/src/lib/constants.ts b/packages/webapp/src/lib/constants.ts new file mode 100644 index 000000000..87a85bbde --- /dev/null +++ b/packages/webapp/src/lib/constants.ts @@ -0,0 +1,2 @@ +export const REGISTRY_URL = + 'https://raw.githubusercontent.com/rainlanguage/rain.strategies/refs/heads/main/ports/registry'; diff --git a/packages/webapp/src/routes/deploy/getFileRegistry.ts b/packages/webapp/src/lib/services/getFileRegistry.ts similarity index 73% rename from packages/webapp/src/routes/deploy/getFileRegistry.ts rename to packages/webapp/src/lib/services/getFileRegistry.ts index 41062a3dd..ff7af8293 100644 --- a/packages/webapp/src/routes/deploy/getFileRegistry.ts +++ b/packages/webapp/src/lib/services/getFileRegistry.ts @@ -1,3 +1,16 @@ +/** + * Fetches and parses a file registry from a given URL. + * The registry is expected to be a text file where each line contains a file name and URL separated by a space. + * + * @param url - The URL of the registry file to fetch + * @returns A Promise that resolves to an array of objects containing file names and their corresponding URLs + * @throws Will throw an error if the fetch fails, if the response is not ok, or if the registry format is invalid + * + * @example + * const files = await getFileRegistry('https://example.com/registry'); + * // Returns: [{ name: 'file1', url: 'https://example.com/file1.rain' }, ...] + */ + export const getFileRegistry = async (url: string) => { try { const response = await fetch(url); diff --git a/packages/webapp/src/lib/stores/registry.ts b/packages/webapp/src/lib/stores/registry.ts deleted file mode 100644 index dc20a153c..000000000 --- a/packages/webapp/src/lib/stores/registry.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { writable } from 'svelte/store'; - -export const registryUrl = writable( - 'https://raw.githubusercontent.com/rainlanguage/rain.strategies/refs/heads/main/ports/registry' -); diff --git a/packages/webapp/src/routes/deploy/+layout.ts b/packages/webapp/src/routes/deploy/+layout.ts index ab526df3e..b14f01b44 100644 --- a/packages/webapp/src/routes/deploy/+layout.ts +++ b/packages/webapp/src/routes/deploy/+layout.ts @@ -1,11 +1,8 @@ -import { registryUrl } from '$lib/stores/registry'; +import { REGISTRY_URL } from '$lib/constants'; import type { LayoutLoad } from './$types'; export const load: LayoutLoad = async ({ url }) => { // get the registry url from the url params const registry = url.searchParams.get('registry'); - if (registry) { - registryUrl.set(registry); - } - return { registry }; + return { registry: registry || REGISTRY_URL }; }; diff --git a/packages/webapp/src/routes/deploy/+page.svelte b/packages/webapp/src/routes/deploy/+page.svelte index 1259466d2..ceebf1a7b 100644 --- a/packages/webapp/src/routes/deploy/+page.svelte +++ b/packages/webapp/src/routes/deploy/+page.svelte @@ -1,12 +1,13 @@ @@ -61,7 +65,7 @@ id="strategy-url" type="url" placeholder="Enter URL to raw strategy registry file" - bind:value={$registryUrl} + bind:value={newRegistryUrl} />
@@ -79,7 +83,7 @@

diff --git a/packages/webapp/src/routes/deploy/[strategyName]/+layout.ts b/packages/webapp/src/routes/deploy/[strategyName]/+layout.ts index 8b53d4fb1..b5ae39337 100644 --- a/packages/webapp/src/routes/deploy/[strategyName]/+layout.ts +++ b/packages/webapp/src/routes/deploy/[strategyName]/+layout.ts @@ -1,32 +1,20 @@ -import { registryUrl } from '$lib/stores/registry'; import { rawDotrain } from '$lib/stores/raw-dotrain'; -import { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; import { get } from 'svelte/store'; import type { LayoutLoad } from './$types'; import { redirect } from '@sveltejs/kit'; +import { getFileRegistry } from '$lib/services/getFileRegistry'; export const load: LayoutLoad = async ({ fetch, params, parent }) => { - const { strategyName, deploymentKey } = params; + const { strategyName } = params; const { registry } = await parent(); - if (registry) { - registryUrl.set(registry); - } + + let dotrain; + try { - let dotrain; if (strategyName === 'raw' && get(rawDotrain)) { dotrain = get(rawDotrain); } else { - const _registryUrl = get(registryUrl); - const response = await fetch(_registryUrl); - const files = await response.text(); - - const fileList = files - .split('\n') - .filter(Boolean) - .map((line: string) => { - const [name, url] = line.split(' '); - return { name, url }; - }); + const fileList = await getFileRegistry(registry); const strategy = fileList.find((file: { name: string }) => file.name === strategyName); if (!strategy) { @@ -36,33 +24,12 @@ export const load: LayoutLoad = async ({ fetch, params, parent }) => { const dotrainResponse = await fetch(strategy.url); dotrain = await dotrainResponse.text(); } - - // Process deployments for both raw and registry strategies - const deploymentWithDetails = await DotrainOrderGui.getDeploymentDetails(dotrain); - const deployments = Array.from(deploymentWithDetails, ([key, details]) => ({ - key, - ...details - })); - - const deployment = deployments.find( - (deployment: { key: string }) => deployment.key === deploymentKey - ); - - if (!deployment) { - throw new Error(`Deployment ${deploymentKey} not found`); - } - - const { key, name, description } = deployment; - - return { - dotrain, - strategyName, - key, - name, - description, - deployment - }; } catch { throw redirect(307, '/deploy'); } + + return { + dotrain, + strategyName + }; }; diff --git a/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte b/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte index 63c22bbf6..26dbe5c4b 100644 --- a/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte +++ b/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte @@ -1,33 +1,8 @@ -
-
-
-

- {strategyDetails.name} -

-
{strategyDetails.short_description}
- {#if isMarkdownUrl(strategyDetails.description) && markdownContent} -
- -
- {:else} -

- {strategyDetails.description} -

- {/if} -
- -
-
+ diff --git a/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+layout.ts b/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+layout.ts new file mode 100644 index 000000000..c6e9f976b --- /dev/null +++ b/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+layout.ts @@ -0,0 +1,24 @@ +import { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; +import type { LayoutLoad } from '../$types'; + +export const load: LayoutLoad = async ({ params, parent }) => { + const { deploymentKey } = params; + const { dotrain } = await parent(); + + // Process deployments for both raw and registry strategies + const deploymentWithDetails = await DotrainOrderGui.getDeploymentDetails(dotrain); + const deployments = Array.from(deploymentWithDetails, ([key, details]) => ({ + key, + ...details + })); + + const deployment = deployments.find( + (deployment: { key: string }) => deployment.key === deploymentKey + ); + + if (!deployment) { + throw new Error(`Deployment ${deploymentKey} not found`); + } + + return { deployment, dotrain }; +}; diff --git a/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte b/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte index c54831e6f..6e5784d62 100644 --- a/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte +++ b/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte @@ -1,31 +1,32 @@ -{#if !dotrain || !key} +{#if !dotrain || !deployment}
Deployment not found. Redirecting to deployments page...
{:else} - {/if} From 1477f9863d7b21331093847fb1c0a002f47fcfd8 Mon Sep 17 00:00:00 2001 From: highonhopium Date: Thu, 13 Feb 2025 12:39:33 +0000 Subject: [PATCH 08/23] routing and cleanup --- packages/ui-components/package.json | 6 + ...gySection.test.ts => StrategyPage.test.ts} | 10 +- .../deployment/DeploymentSteps.svelte | 1 + .../deployment/DeploymentTile.svelte | 14 +- ...tegySection.svelte => StrategyPage.svelte} | 39 ++--- .../deployment/StrategyShortTile.svelte | 24 +++ packages/ui-components/src/lib/index.ts | 6 +- .../ui-components/src/lib/services/index.ts | 2 + .../src/lib/services/registry.ts} | 43 +++++- packages/webapp/src/routes/deploy/+layout.ts | 13 +- .../webapp/src/routes/deploy/+page.svelte | 137 +++++------------- .../deploy/[strategyName]/+layout.svelte | 7 - .../routes/deploy/[strategyName]/+layout.ts | 15 +- .../routes/deploy/[strategyName]/+page.svelte | 6 +- .../[deploymentKey]/+page.svelte | 33 ++++- 15 files changed, 191 insertions(+), 165 deletions(-) rename packages/ui-components/src/__tests__/{StrategySection.test.ts => StrategyPage.test.ts} (95%) rename packages/ui-components/src/lib/components/deployment/{StrategySection.svelte => StrategyPage.svelte} (67%) create mode 100644 packages/ui-components/src/lib/components/deployment/StrategyShortTile.svelte create mode 100644 packages/ui-components/src/lib/services/index.ts rename packages/{webapp/src/lib/services/getFileRegistry.ts => ui-components/src/lib/services/registry.ts} (61%) delete mode 100644 packages/webapp/src/routes/deploy/[strategyName]/+layout.svelte diff --git a/packages/ui-components/package.json b/packages/ui-components/package.json index b37deba33..9225134a3 100644 --- a/packages/ui-components/package.json +++ b/packages/ui-components/package.json @@ -12,6 +12,12 @@ "import": "./dist/index.js", "require": "./dist/index.js", "svelte": "./dist/index.js" + }, + "./services": { + "types": "./dist/services/index.d.ts", + "import": "./dist/services/index.js", + "require": "./dist/services/index.js", + "svelte": "./dist/services/index.js" } }, "scripts": { diff --git a/packages/ui-components/src/__tests__/StrategySection.test.ts b/packages/ui-components/src/__tests__/StrategyPage.test.ts similarity index 95% rename from packages/ui-components/src/__tests__/StrategySection.test.ts rename to packages/ui-components/src/__tests__/StrategyPage.test.ts index b7a3be6ad..f7fc5fd26 100644 --- a/packages/ui-components/src/__tests__/StrategySection.test.ts +++ b/packages/ui-components/src/__tests__/StrategyPage.test.ts @@ -1,5 +1,5 @@ import { render, screen, waitFor } from '@testing-library/svelte'; -import StrategySection from '../lib/components/deployment/StrategySection.svelte'; +import StrategyPage from '../lib/components/deployment/StrategyPage.svelte'; import { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; import { vi, describe, it, expect, beforeEach } from 'vitest'; @@ -33,7 +33,7 @@ describe('StrategySection', () => { }; vi.mocked(DotrainOrderGui.getStrategyDetails).mockResolvedValueOnce(mockStrategyDetails); - render(StrategySection, { + render(StrategyPage, { props: { rawDotrain: mockDotrain } @@ -60,7 +60,7 @@ describe('StrategySection', () => { // Mock DotrainOrderGui methods vi.mocked(DotrainOrderGui.getStrategyDetails).mockResolvedValueOnce(mockStrategyDetails); - render(StrategySection, { + render(StrategyPage, { props: { strategyUrl: 'http://example.com/strategy', strategyName: 'TestStrategy' @@ -85,7 +85,7 @@ describe('StrategySection', () => { // Mock DotrainOrderGui methods vi.mocked(DotrainOrderGui.getStrategyDetails).mockRejectedValueOnce(mockError); - render(StrategySection, { + render(StrategyPage, { props: { strategyUrl: 'http://example.com/strategy', strategyName: 'TestStrategy' @@ -104,7 +104,7 @@ describe('StrategySection', () => { // Mock fetch to reject mockFetch.mockRejectedValueOnce(mockError); - render(StrategySection, { + render(StrategyPage, { props: { strategyUrl: 'http://example.com/strategy', strategyName: 'TestStrategy' diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte index e58737260..192c70f39 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -26,6 +26,7 @@ import { page } from '$app/stores'; import { onMount } from 'svelte'; import ShareChoicesButton from './ShareChoicesButton.svelte'; + enum DeploymentStepErrors { NO_GUI = 'Error loading GUI', NO_STRATEGY = 'No valid strategy exists at this URL', diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentTile.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentTile.svelte index a55243b72..e12661aff 100644 --- a/packages/ui-components/src/lib/components/deployment/DeploymentTile.svelte +++ b/packages/ui-components/src/lib/components/deployment/DeploymentTile.svelte @@ -1,12 +1,24 @@

{name}

diff --git a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte b/packages/ui-components/src/lib/components/deployment/StrategyPage.svelte similarity index 67% rename from packages/ui-components/src/lib/components/deployment/StrategySection.svelte rename to packages/ui-components/src/lib/components/deployment/StrategyPage.svelte index 6fa93ed31..e6c8a6ce9 100644 --- a/packages/ui-components/src/lib/components/deployment/StrategySection.svelte +++ b/packages/ui-components/src/lib/components/deployment/StrategyPage.svelte @@ -6,9 +6,8 @@ export let strategyUrl: string = ''; export let strategyName: string = ''; - export let rawDotrain: string = ''; + export let dotrain: string = ''; let strategyDetails: NameAndDescription; - let dotrain: string; let error: string; let errorDetails: string; let markdownContent: string = ''; @@ -29,34 +28,23 @@ const getStrategy = async () => { try { - if (rawDotrain) { - dotrain = rawDotrain; - } else { - const response = await fetch(strategyUrl); - dotrain = await response.text(); - } - try { - strategyDetails = await DotrainOrderGui.getStrategyDetails(dotrain); - if (strategyDetails.description && isMarkdownUrl(strategyDetails.description)) { - const content = await fetchMarkdownContent(strategyDetails.description); - if (content) { - markdownContent = content; - } else { - error = 'Error fetching markdown'; - errorDetails = 'Failed to fetch markdown content'; - } + strategyDetails = await DotrainOrderGui.getStrategyDetails(dotrain); + if (strategyDetails.description && isMarkdownUrl(strategyDetails.description)) { + const content = await fetchMarkdownContent(strategyDetails.description); + if (content) { + markdownContent = content; + } else { + error = 'Error fetching markdown'; + errorDetails = 'Failed to fetch markdown content'; } - } catch (e: unknown) { - error = 'Error getting strategy details'; - errorDetails = e instanceof Error ? e.message : 'Unknown error'; } } catch (e: unknown) { - error = 'Error fetching strategy'; + error = 'Error getting strategy details'; errorDetails = e instanceof Error ? e.message : 'Unknown error'; } }; - $: getStrategy(); + getStrategy(); {#if dotrain && strategyDetails} @@ -79,7 +67,10 @@

{/if}

- +
+

Deployments

+ +
{:else if error} diff --git a/packages/ui-components/src/lib/components/deployment/StrategyShortTile.svelte b/packages/ui-components/src/lib/components/deployment/StrategyShortTile.svelte new file mode 100644 index 000000000..92a2575f9 --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/StrategyShortTile.svelte @@ -0,0 +1,24 @@ + + + +

{strategyDetails?.name}

+

{strategyDetails?.short_description}

+
diff --git a/packages/ui-components/src/lib/index.ts b/packages/ui-components/src/lib/index.ts index 36703339d..38baec9eb 100644 --- a/packages/ui-components/src/lib/index.ts +++ b/packages/ui-components/src/lib/index.ts @@ -1,5 +1,3 @@ -import './app.css'; - // Components export { default as CardProperty } from './components/CardProperty.svelte'; export { default as Hash, HashType } from './components/Hash.svelte'; @@ -59,10 +57,11 @@ export { default as CodeMirrorDotrain } from './components/CodeMirrorDotrain.sve export { default as OrderOrVaultHash } from './components/OrderOrVaultHash.svelte'; export { default as License } from './components/License.svelte'; export { default as ButtonDarkMode } from './components/ButtonDarkMode.svelte'; -export { default as StrategySection } from './components/deployment/StrategySection.svelte'; +export { default as StrategyPage } from './components/deployment/StrategyPage.svelte'; 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'; //Types export type { AppStoresInterface } from './types/appStores.ts'; @@ -86,7 +85,6 @@ export { prepareHistoricalOrderChartData } from './services/historicalOrderChart export { bigintToFloat } from './utils/number'; // Constants - export { DEFAULT_PAGE_SIZE, DEFAULT_REFRESH_INTERVAL } from './queries/constants'; export { QKEY_VAULTS, diff --git a/packages/ui-components/src/lib/services/index.ts b/packages/ui-components/src/lib/services/index.ts new file mode 100644 index 000000000..b1f3a1e4a --- /dev/null +++ b/packages/ui-components/src/lib/services/index.ts @@ -0,0 +1,2 @@ +export { fetchParseRegistry, fetchRegistryDotrains } from './registry'; +export type { RegistryDotrain, RegistryFile } from './registry'; diff --git a/packages/webapp/src/lib/services/getFileRegistry.ts b/packages/ui-components/src/lib/services/registry.ts similarity index 61% rename from packages/webapp/src/lib/services/getFileRegistry.ts rename to packages/ui-components/src/lib/services/registry.ts index ff7af8293..6fb86ac11 100644 --- a/packages/webapp/src/lib/services/getFileRegistry.ts +++ b/packages/ui-components/src/lib/services/registry.ts @@ -1,3 +1,13 @@ +export type RegistryFile = { + name: string; + url: string; +}; + +export type RegistryDotrain = { + name: string; + dotrain: string; +}; + /** * Fetches and parses a file registry from a given URL. * The registry is expected to be a text file where each line contains a file name and URL separated by a space. @@ -7,11 +17,11 @@ * @throws Will throw an error if the fetch fails, if the response is not ok, or if the registry format is invalid * * @example - * const files = await getFileRegistry('https://example.com/registry'); + * const files = await fetchParseRegistryFile('https://example.com/registry'); * // Returns: [{ name: 'file1', url: 'https://example.com/file1.rain' }, ...] */ -export const getFileRegistry = async (url: string) => { +export const fetchParseRegistry = async (url: string): Promise<{ name: string; url: string }[]> => { try { const response = await fetch(url); if (!response.ok) { @@ -34,6 +44,29 @@ export const getFileRegistry = async (url: string) => { } }; +export const fetchRegistryDotrains = async (url: string): Promise => { + const files = await fetchParseRegistry(url); + const dotrains = await Promise.all( + files.map(async (file) => { + try { + const response = await fetch(file.url); + if (!response.ok) { + throw new Error(`Failed to fetch dotrain for ${file.name}`); + } + const dotrain = await response.text(); + return { name: file.name, dotrain }; + } catch (e) { + throw new Error( + e instanceof Error + ? `Error fetching dotrain for ${file.name}: ${e.message}` + : `Unknown error fetching dotrain for ${file.name}` + ); + } + }) + ); + return dotrains; +}; + if (import.meta.vitest) { const { describe, it, expect, vi } = import.meta.vitest; @@ -47,7 +80,7 @@ file2.js https://example.com/file2.js`; text: () => Promise.resolve(mockResponse) }); - const result = await getFileRegistry('https://example.com/registry'); + const result = await fetchParseRegistry('https://example.com/registry'); expect(result).toEqual([ { name: 'file1.js', url: 'https://example.com/file1.js' }, { name: 'file2.js', url: 'https://example.com/file2.js' } @@ -59,7 +92,7 @@ file2.js https://example.com/file2.js`; ok: false }); - await expect(getFileRegistry('https://example.com/registry')).rejects.toThrow( + await expect(fetchParseRegistry('https://example.com/registry')).rejects.toThrow( 'Failed to fetch registry' ); }); @@ -67,7 +100,7 @@ file2.js https://example.com/file2.js`; it('should handle network errors', async () => { global.fetch = vi.fn().mockRejectedValue(new Error('Network error')); - await expect(getFileRegistry('https://example.com/registry')).rejects.toThrow( + await expect(fetchParseRegistry('https://example.com/registry')).rejects.toThrow( 'Network error' ); }); diff --git a/packages/webapp/src/routes/deploy/+layout.ts b/packages/webapp/src/routes/deploy/+layout.ts index b14f01b44..4f2fd310b 100644 --- a/packages/webapp/src/routes/deploy/+layout.ts +++ b/packages/webapp/src/routes/deploy/+layout.ts @@ -1,8 +1,19 @@ import { REGISTRY_URL } from '$lib/constants'; +import { fetchRegistryDotrains } from '@rainlanguage/ui-components/services'; import type { LayoutLoad } from './$types'; +import { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; export const load: LayoutLoad = async ({ url }) => { // get the registry url from the url params const registry = url.searchParams.get('registry'); - return { registry: registry || REGISTRY_URL }; + + const registryDotrains = await fetchRegistryDotrains(registry || REGISTRY_URL); + const strategyDetails = await Promise.all( + registryDotrains.map(async (registryDotrain) => { + const details = await DotrainOrderGui.getStrategyDetails(registryDotrain.dotrain); + return { ...registryDotrain, details }; + }) + ); + + return { registry: registry || REGISTRY_URL, registryDotrains, strategyDetails }; }; diff --git a/packages/webapp/src/routes/deploy/+page.svelte b/packages/webapp/src/routes/deploy/+page.svelte index ceebf1a7b..154bfc0b1 100644 --- a/packages/webapp/src/routes/deploy/+page.svelte +++ b/packages/webapp/src/routes/deploy/+page.svelte @@ -1,44 +1,12 @@ - - - diff --git a/packages/webapp/src/routes/deploy/[strategyName]/+layout.ts b/packages/webapp/src/routes/deploy/[strategyName]/+layout.ts index b5ae39337..e86af7694 100644 --- a/packages/webapp/src/routes/deploy/[strategyName]/+layout.ts +++ b/packages/webapp/src/routes/deploy/[strategyName]/+layout.ts @@ -2,11 +2,10 @@ import { rawDotrain } from '$lib/stores/raw-dotrain'; import { get } from 'svelte/store'; import type { LayoutLoad } from './$types'; import { redirect } from '@sveltejs/kit'; -import { getFileRegistry } from '$lib/services/getFileRegistry'; -export const load: LayoutLoad = async ({ fetch, params, parent }) => { +export const load: LayoutLoad = async ({ params, parent }) => { const { strategyName } = params; - const { registry } = await parent(); + const { registryDotrains } = await parent(); let dotrain; @@ -14,15 +13,7 @@ export const load: LayoutLoad = async ({ fetch, params, parent }) => { if (strategyName === 'raw' && get(rawDotrain)) { dotrain = get(rawDotrain); } else { - const fileList = await getFileRegistry(registry); - - const strategy = fileList.find((file: { name: string }) => file.name === strategyName); - if (!strategy) { - throw new Error(`Strategy ${strategyName} not found`); - } - - const dotrainResponse = await fetch(strategy.url); - dotrain = await dotrainResponse.text(); + dotrain = registryDotrains.find((dotrain) => dotrain.name === strategyName)?.dotrain; } } catch { throw redirect(307, '/deploy'); diff --git a/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte b/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte index 26dbe5c4b..f9433a798 100644 --- a/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte +++ b/packages/webapp/src/routes/deploy/[strategyName]/+page.svelte @@ -1,8 +1,10 @@ - + + + diff --git a/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte b/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte index 6e5784d62..1a7e0faf3 100644 --- a/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte +++ b/packages/webapp/src/routes/deploy/[strategyName]/[deploymentKey]/+page.svelte @@ -1,10 +1,12 @@ + + + (advancedMode = !advancedMode)}> + {'Advanced Mode'} + + + +
+ {#if advancedMode} +
+
+