"],
+ "js": ["content-script.js"]
+ }
+ ],
+ "background": {
+ "service_worker": "service-worker.js",
+ "type": "module"
+ },
+ "manifest_version": 3
+}
diff --git a/linera-web/src/components/linera-logo/index.ts b/linera-web/src/components/linera-logo/index.ts
new file mode 100644
index 0000000..41f8413
--- /dev/null
+++ b/linera-web/src/components/linera-logo/index.ts
@@ -0,0 +1,23 @@
+import { LitElement, html, css } from 'lit'
+import { customElement } from 'lit/decorators.js'
+import lineraLogo from './logo.svg';
+
+@customElement('linera-logo')
+export class LineraLogo extends LitElement {
+ static styles = css`
+ img {
+ padding: 2rem;
+ max-width: 30rem;
+ }
+ `;
+
+ render = () => html`
+
+ `;
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'linera-logo': LineraLogo
+ }
+}
diff --git a/linera-web/src/components/linera-logo/logo.svg b/linera-web/src/components/linera-logo/logo.svg
new file mode 100644
index 0000000..4fd7433
--- /dev/null
+++ b/linera-web/src/components/linera-logo/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/linera-web/src/content-script/index.ts b/linera-web/src/content-script/index.ts
new file mode 100644
index 0000000..3d446b7
--- /dev/null
+++ b/linera-web/src/content-script/index.ts
@@ -0,0 +1 @@
+console.log("Content script");
diff --git a/linera-web/src/env.d.ts b/linera-web/src/env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/linera-web/src/env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/linera-web/src/index.css b/linera-web/src/index.css
new file mode 100644
index 0000000..a9f6b20
--- /dev/null
+++ b/linera-web/src/index.css
@@ -0,0 +1,30 @@
+@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
+
+:root {
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+
+ --color-linera-red: #ff2a00;
+ --color-linera-blue: #0e2630;
+ --color-linera-teal: #70d4d3;
+ --color-linera-beige: #d6ba92;
+ --color-linera-white: #ffffff;
+
+ --color-background: var(--color-linera-white);
+ --color-foreground: var(--color-linera-blue);
+}
+
+body {
+ background-color: var(--color-background);
+ color: var(--color-foreground);
+ font-family: Poppins;
+
+ margin: 1rem;
+ min-width: 20rem;
+}
+
+h2 {
+ font-size: 150%;
+}
diff --git a/linera-web/src/options/index.html b/linera-web/src/options/index.html
new file mode 100644
index 0000000..c52aead
--- /dev/null
+++ b/linera-web/src/options/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Linera
+
+
+
+
+
+ This is the Linera options page.
+
+
+
diff --git a/linera-web/src/popup/index.html b/linera-web/src/popup/index.html
new file mode 100644
index 0000000..be9b679
--- /dev/null
+++ b/linera-web/src/popup/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Linera
+
+
+
+
+
+ This is the Linera popup.
+
+
+
diff --git a/linera-web/src/service-worker/index.ts b/linera-web/src/service-worker/index.ts
new file mode 100644
index 0000000..525f780
--- /dev/null
+++ b/linera-web/src/service-worker/index.ts
@@ -0,0 +1 @@
+import './setup.ts';
diff --git a/linera-web/src/service-worker/setup.ts b/linera-web/src/service-worker/setup.ts
new file mode 100644
index 0000000..cb72ac4
--- /dev/null
+++ b/linera-web/src/service-worker/setup.ts
@@ -0,0 +1,10 @@
+chrome.sidePanel.setPanelBehavior({
+ openPanelOnActionClick: true,
+}).catch((error) => console.error(error));
+
+chrome.runtime.onInstalled.addListener(async () => {
+ const windowId = (await chrome.windows.getCurrent()).id;
+ if (windowId === undefined) return;
+ chrome.action.setPopup({ popup: "src/welcome/index.html" });
+ await chrome.action.openPopup({ windowId });
+});
diff --git a/linera-web/src/sidebar/index.html b/linera-web/src/sidebar/index.html
new file mode 100644
index 0000000..0a69370
--- /dev/null
+++ b/linera-web/src/sidebar/index.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Linera
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/linera-web/src/sidebar/index.ts b/linera-web/src/sidebar/index.ts
new file mode 100644
index 0000000..66976dd
--- /dev/null
+++ b/linera-web/src/sidebar/index.ts
@@ -0,0 +1,78 @@
+import { LitElement, html, css } from 'lit'
+import { customElement, property } from 'lit/decorators.js'
+
+type Wallet = {
+ default: string;
+};
+
+@customElement('linera-wallet-picker')
+export class WalletPicker extends LitElement {
+ static styles = css`
+ input[type="file"] {
+ display: none;
+ }
+
+ label {
+ background-color: var(--color-linera-teal);
+ padding: 0.75em;
+ border-radius: 0.75em;
+ font-weight: bold;
+ display: inline-block;
+ }
+ `;
+
+ @property()
+ wallet?: Wallet;
+
+ @property()
+ onChange?: (event: Event) => void;
+
+ render = () => html`
+
+ `;
+
+ private async _onChange(event: Event & { target: HTMLInputElement }) {
+ const contents = await event.target.files![0].text();
+ this.onChange?.(contents);
+ }
+}
+
+@customElement('linera-sidebar')
+export class Sidebar extends LitElement {
+ wallet?: Wallet;
+
+ static styles = css`
+ .chain-id {
+ background-color: var(--color-linera-beige);
+ font-family: monospace;
+ overflow-wrap: break-word;
+ padding: 3px;
+ }
+ `;
+
+ render = () => html`
+ Wallet
+ ${this.wallet && html`Your current wallet is ${this.wallet.default}.
`}
+
+ `;
+
+ constructor() {
+ super();
+ let wallet = window.localStorage.getItem("wallet");
+ if (wallet) this.wallet = JSON.parse(wallet);
+ }
+
+ private async onWalletChange(wallet: string) {
+ window.localStorage.setItem("wallet", wallet);
+ this.wallet = JSON.parse(wallet);
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'linera-sidebar': Sidebar
+ }
+}
diff --git a/linera-web/src/sidebar/style.css b/linera-web/src/sidebar/style.css
new file mode 100644
index 0000000..e69de29
diff --git a/linera-web/src/sidebar/wallet-picker.ts b/linera-web/src/sidebar/wallet-picker.ts
new file mode 100644
index 0000000..e69de29
diff --git a/linera-web/src/welcome/index.html b/linera-web/src/welcome/index.html
new file mode 100644
index 0000000..c01d217
--- /dev/null
+++ b/linera-web/src/welcome/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ Linera
+
+
+
+
+
+
+ Welcome to Linera!
+ Click this button at any time to manage your chains.
+
+
+
diff --git a/linera-web/tsconfig.json b/linera-web/tsconfig.json
new file mode 100644
index 0000000..7a42345
--- /dev/null
+++ b/linera-web/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "target": "ES2021",
+ "experimentalDecorators": true,
+ "useDefineForClassFields": false,
+ "module": "ESNext",
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "skipLibCheck": true,
+
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "plugins": [
+ {
+ "name": "ts-lit-plugin",
+ "strict": true
+ }
+ ]
+ },
+ "include": ["src"]
+}
diff --git a/linera-web/vite.config.ts b/linera-web/vite.config.ts
new file mode 100644
index 0000000..c91cc3d
--- /dev/null
+++ b/linera-web/vite.config.ts
@@ -0,0 +1,23 @@
+import { resolve } from 'path'
+import { defineConfig } from 'vite'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ build: {
+ rollupOptions: {
+ input: {
+ popup: resolve(__dirname, 'src/popup/index.html'),
+ sidebar: resolve(__dirname, 'src/sidebar/index.html'),
+ options: resolve(__dirname, 'src/options/index.html'),
+ welcome: resolve(__dirname, 'src/welcome/index.html'),
+ "content-script": resolve(__dirname, 'src/content-script/index.ts'),
+ "service-worker": resolve(__dirname, 'src/service-worker/index.ts'),
+ manifest: resolve(__dirname, 'public/manifest.json'),
+ },
+ output: {
+ preserveModules: false,
+ entryFileNames: '[name].js',
+ }
+ },
+ },
+})
diff --git a/manifest.json b/manifest.json
deleted file mode 100644
index 4244b0b..0000000
--- a/manifest.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name" : "linera-web",
- "version" : "1.0",
- "description" : "linera-web",
- "permissions": [],
- "content_scripts": [
- {
- "matches": ["file:///*"],
- "js": ["content_script.js"]
- }
- ],
- "background": {
- "service_worker": "service_worker.js",
- "type": "module"
- },
- "content_security_policy": {
- "extension_pages": "script-src 'self' 'wasm-unsafe-eval';"
- },
- "manifest_version": 3
-}