├── src ├── routes │ ├── +layout.js │ ├── +page.svelte │ ├── delegate │ │ └── +page.svelte │ ├── revoke │ │ └── +page.svelte │ └── +layout.svelte ├── assets │ ├── icons │ │ ├── check.svg │ │ ├── copy.svg │ │ ├── moon-solid.svg │ │ ├── arrow-left.svg │ │ ├── sun-solid.svg │ │ ├── link.svg │ │ ├── etherscan.svg │ │ └── github.svg │ └── illustrations │ │ ├── puzzled.svg │ │ ├── king.svg │ │ └── decapitation.svg ├── components │ ├── DelegationRegistry.svelte │ ├── ChainWarning.svelte │ ├── delegationRegistry │ │ ├── NavBar.svelte │ │ ├── Card.svelte │ │ ├── Delegate.svelte │ │ ├── Main.svelte │ │ ├── RevokeItemPaginator.svelte │ │ └── Revoke.svelte │ ├── HammerLoader.svelte │ ├── Footer.svelte │ ├── Header.svelte │ ├── Select.svelte │ ├── InputFloatingLabel.svelte │ ├── Table.svelte │ ├── ThemeToggle.svelte │ └── AccountModal.svelte ├── store.ts ├── app.d.ts ├── app.html ├── constants.ts ├── abis │ └── abis.ts └── utils.ts ├── static ├── favicon.ico ├── favicon.png ├── metamask.png ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── mstile-150x150.png ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── fonts │ └── NotoSans │ │ ├── NotoSans-Bold.ttf │ │ ├── NotoSans-Medium.ttf │ │ ├── NotoSans-Regular.ttf │ │ ├── NotoSans-SemiBold.ttf │ │ └── OFL.txt ├── browserconfig.xml ├── site.webmanifest ├── global.css ├── safari-pinned-tab.svg └── walletconnect.svg ├── .gitmodules ├── .gitignore ├── .eslintignore ├── .prettierignore ├── deploy-contracts.sh ├── playwright.config.ts ├── vite.config.ts ├── tests └── test.ts ├── .prettierrc.json ├── LICENSE ├── svelte.config.js ├── flake.nix ├── tsconfig.json ├── .eslintrc.cjs ├── shell.nix ├── package.json ├── README.md └── flake.lock /src/routes/+layout.js: -------------------------------------------------------------------------------- 1 | // src/routes/+layout.js 2 | export const prerender = true; 3 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/favicon.ico -------------------------------------------------------------------------------- /static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/favicon.png -------------------------------------------------------------------------------- /static/metamask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/metamask.png -------------------------------------------------------------------------------- /static/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/favicon-16x16.png -------------------------------------------------------------------------------- /static/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/favicon-32x32.png -------------------------------------------------------------------------------- /static/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/apple-touch-icon.png -------------------------------------------------------------------------------- /static/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/mstile-150x150.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "token-delegation"] 2 | path = token-delegation 3 | url = https://github.com/0xfoobar/token-delegation 4 | -------------------------------------------------------------------------------- /static/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/android-chrome-192x192.png -------------------------------------------------------------------------------- /static/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | -------------------------------------------------------------------------------- /static/fonts/NotoSans/NotoSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/fonts/NotoSans/NotoSans-Bold.ttf -------------------------------------------------------------------------------- /static/fonts/NotoSans/NotoSans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/fonts/NotoSans/NotoSans-Medium.ttf -------------------------------------------------------------------------------- /static/fonts/NotoSans/NotoSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/fonts/NotoSans/NotoSans-Regular.ttf -------------------------------------------------------------------------------- /static/fonts/NotoSans/NotoSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xfoobar/delegate-frontend-legacy/HEAD/static/fonts/NotoSans/NotoSans-SemiBold.ttf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | .envrc 10 | /.direnv 11 | /.netlify 12 | .npmrc 13 | -------------------------------------------------------------------------------- /src/assets/icons/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | token-delegation/ 10 | /.netlify 11 | 12 | # Ignore files for PNPM, NPM and YARN 13 | pnpm-lock.yaml 14 | package-lock.json 15 | yarn.lock 16 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | token-delegation/ 10 | /.netlify 11 | .npmrc 12 | 13 | # Ignore files for PNPM, NPM and YARN 14 | pnpm-lock.yaml 15 | package-lock.json 16 | yarn.lock 17 | -------------------------------------------------------------------------------- /deploy-contracts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export ANVIL_DEFAULT_PK=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 3 | cd token-delegation 4 | forge create --rpc-url http://127.0.0.1:8545 --private-key ${ANVIL_DEFAULT_PK} src/DelegationRegistry.sol:DelegationRegistry 5 | cd .. 6 | -------------------------------------------------------------------------------- /playwright.config.ts: -------------------------------------------------------------------------------- 1 | import type { PlaywrightTestConfig } from '@playwright/test'; 2 | 3 | const config: PlaywrightTestConfig = { 4 | webServer: { 5 | command: 'npm run build && npm run preview', 6 | port: 4173 7 | }, 8 | testDir: './tests' 9 | }; 10 | 11 | export default config; 12 | -------------------------------------------------------------------------------- /static/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #00aba9 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import svg from '@poppanator/sveltekit-svg'; 3 | import type { UserConfig } from 'vite'; 4 | 5 | const config: UserConfig = { 6 | plugins: [sveltekit(), svg({ includePaths: ['./src/assets'] })] 7 | }; 8 | 9 | export default config; 10 | -------------------------------------------------------------------------------- /tests/test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from '@playwright/test'; 2 | 3 | test('card headers contain the correct symbols', async ({ page }) => { 4 | await page.goto('/'); 5 | expect(await page.textContent('h1')).toContain('Ê'); 6 | expect(await page.textContent('h1')).toContain('Ơ'); 7 | page.textContent(''); 8 | }); 9 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "useTabs": true, 4 | "tabWidth": 2, 5 | "semi": true, 6 | "printWidth": 100, 7 | "singleQuote": true, 8 | "bracketSpacing": true, 9 | "pluginSearchDirs": ["."], 10 | "svelteIndentScriptAndStyle": false, 11 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 12 | } 13 | -------------------------------------------------------------------------------- /src/components/DelegationRegistry.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | {#if $connected && $contracts.delegationRegistry} 6 |
test
7 | {:else} 8 | Please connect wallet 9 | {/if} 10 | 11 | 17 | -------------------------------------------------------------------------------- /src/assets/icons/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * ---------------------------------------------------------------------------- 3 | * "THE BEER-WARE LICENSE" (Revision 420): 4 | * <0xnook@protonmail.com> wrote this file. You 5 | * can do whatever you want with this stuff. If we meet some day, and you think 6 | * this stuff is worth it, you can buy me a beer in return - nook 7 | * ---------------------------------------------------------------------------- 8 | */ 9 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-static'; 2 | import preprocess from 'svelte-preprocess'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://github.com/sveltejs/svelte-preprocess 7 | // for more information about preprocessors 8 | preprocess: preprocess(), 9 | outDir: 'build', 10 | kit: { 11 | adapter: adapter() 12 | } 13 | }; 14 | 15 | export default config; 16 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | utils.url = "github:numtide/flake-utils"; 5 | foundry.url = "github:shazow/foundry.nix"; 6 | }; 7 | 8 | outputs = { self, nixpkgs, utils, foundry }: 9 | utils.lib.eachDefaultSystem (system: 10 | let 11 | pkgs = import nixpkgs { 12 | inherit system; 13 | overlays = [ foundry.overlay ]; 14 | }; 15 | in { 16 | devShell = pkgs.callPackage ./shell.nix {}; 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /static/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "delegate.cash", 3 | "short_name": "delegate", 4 | "theme_color": "#000", 5 | "background_color": "#fff", 6 | "display": "browser", 7 | "orientation": "any", 8 | "scope": ".", 9 | "start_url": "./", 10 | "icons": [ 11 | { 12 | "src": "/android-chrome-192x192.png", 13 | "sizes": "192x192", 14 | "type": "image/png" 15 | }, 16 | { 17 | "src": "/android-chrome-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/components/ChainWarning.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
Connected to unsupported chain!
7 | 8 | 21 | -------------------------------------------------------------------------------- /src/assets/icons/moon-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/store.ts: -------------------------------------------------------------------------------- 1 | import { browser } from '$app/environment'; 2 | import { writable, derived } from 'svelte/store'; 3 | import { chainId, connected } from 'svelte-ethers-store'; 4 | 5 | import { contractAddresses } from './constants'; 6 | 7 | export const accountModalHidden = writable(true); 8 | export const providerType = writable(browser ? localStorage.getItem('providertype') : ''); 9 | export const connectedToSupportedChain = derived( 10 | [chainId, connected], 11 | ([$chainId, $connected]) => $chainId in contractAddresses && $connected 12 | ); 13 | export const currentTheme = writable(browser ? localStorage.getItem('theme') : ''); 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "typeRoots": ["./app.d.ts"] 13 | } 14 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 15 | // 16 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 17 | // from the referenced tsconfig.json - TypeScript does not merge them in 18 | } 19 | -------------------------------------------------------------------------------- /src/assets/icons/arrow-left.svg: -------------------------------------------------------------------------------- 1 | 6 | 10 | 16 | 17 | -------------------------------------------------------------------------------- /src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | // and what to do when importing types 4 | declare namespace App { 5 | // interface Locals {} 6 | // interface PageData {} 7 | // interface Platform {} 8 | } 9 | 10 | interface NavOption { 11 | key: string; 12 | value: string; 13 | tooltip: string; 14 | } 15 | 16 | interface DelegateResponse { 17 | delegate: string; 18 | contract_?: string; 19 | tokenId?: number; 20 | } 21 | 22 | type DelegateKind = 'wallet' | 'contract' | 'token'; 23 | 24 | type RevokeKind = DelegateKind | 'other'; 25 | 26 | interface TableCell { 27 | value: string | number; 28 | onClick?: function; 29 | isButton?: boolean; // for inverting color 30 | } 31 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | %sveltekit.head% 14 | 15 | 16 |
%sveltekit.body%
17 | 18 | 19 | -------------------------------------------------------------------------------- /src/assets/icons/sun-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/delegationRegistry/NavBar.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 19 | 20 | 50 | -------------------------------------------------------------------------------- /src/assets/icons/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [ 8 | { 9 | files: ['*.svelte'], 10 | processor: 'svelte3/svelte3' 11 | }, 12 | /* disable no-undef rules for svelte and ts files since typescript 13 | already handles it better */ 14 | { 15 | files: ['*.svelte', '*.ts'], 16 | rules: { 17 | 'no-undef': 'off' 18 | } 19 | } 20 | ], 21 | settings: { 22 | 'svelte3/typescript': () => require('typescript') 23 | }, 24 | parserOptions: { 25 | sourceType: 'module', 26 | ecmaVersion: 2020 27 | }, 28 | env: { 29 | browser: true, 30 | es2017: true, 31 | node: true 32 | }, 33 | rules: { 34 | // ignore params starting with _ 35 | 'no-unused-vars': [2, { args: 'all', argsIgnorePattern: '^_' }], 36 | '@typescript-eslint/ban-ts-comment': [ 37 | 'error', 38 | { 39 | 'ts-ignore': 'allow-with-description' 40 | } 41 | ] 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | { mkShell, git, nodejs, solc, foundry-bin }: 2 | mkShell { 3 | nativeBuildInputs = [ git nodejs foundry-bin solc ]; 4 | shellHook = '' 5 | # check if node dependencies are installed 6 | if [ ! -d ./node_modules ] 7 | then 8 | echo "node_modules not present, installing" 9 | npm install 10 | fi 11 | 12 | # add npm binaries to path 13 | export PATH="$PWD/node_modules/.bin/:$PATH" 14 | 15 | # clone contract submodules if not present 16 | if [ ! -f ./token-delegation/foundry.toml ] 17 | then 18 | git submodule init 19 | git submodule update 20 | fi 21 | 22 | # compile contracts 23 | # need to descend into contract submodule cus forge -c fails 24 | if [ ! -d ./token-delegation/out ] 25 | then 26 | cd token-delegation 27 | forge build 28 | # needs to be run twice for some reason 29 | forge build 30 | cd .. 31 | fi 32 | 33 | # make shell scripts executable 34 | chmod +x deploy-contracts.sh 35 | ''; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/assets/icons/etherscan.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | interface ContractAddress { 2 | delegationRegistry: string; 3 | } 4 | 5 | // for prompting user to switch changes via header select 6 | export const chainOptions: Record = { 7 | 1: 'Ethereum', 8 | 137: 'Polygon', 9 | 42220: 'Celo', 10 | 5: 'Goerli', 11 | 80001: 'Mumbai' 12 | }; 13 | 14 | export const contractAddresses: Record = { 15 | // eth main chain 16 | 1: { 17 | delegationRegistry: '0x00000000000076A84feF008CDAbe6409d2FE638B' 18 | }, 19 | // polygon 20 | 137: { 21 | delegationRegistry: '0x00000000000076A84feF008CDAbe6409d2FE638B' 22 | }, 23 | // celo 24 | 42220: { 25 | delegationRegistry: '0x00000000000076A84feF008CDAbe6409d2FE638B' 26 | }, 27 | // goerli 28 | 5: { 29 | delegationRegistry: '0x00000000000076A84feF008CDAbe6409d2FE638B' 30 | }, 31 | // mumbai 32 | 80001: { 33 | delegationRegistry: '0x00000000000076A84feF008CDAbe6409d2FE638B' 34 | }, 35 | // local node 36 | 1337: { 37 | delegationRegistry: '0x5fbdb2315678afecb367f032d93f642f64180aa3' 38 | } 39 | }; 40 | 41 | export const nftExplorerURL: Record = { 42 | 1: 'https://www.nftscan.com', 43 | 137: 'https://polygon.nftscan.com' 44 | }; 45 | -------------------------------------------------------------------------------- /src/routes/delegate/+page.svelte: -------------------------------------------------------------------------------- 1 | 25 | 26 |
27 | 33 | 34 | 35 | 36 |
37 | 38 | 45 | -------------------------------------------------------------------------------- /src/routes/revoke/+page.svelte: -------------------------------------------------------------------------------- 1 | 31 | 32 |
33 | 39 | 40 | 41 | 42 |
43 | 44 | 51 | -------------------------------------------------------------------------------- /src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 | 28 | {#key $accountModalHidden} 29 | 30 | {/key} 31 | 32 |
33 |
34 | 35 | 36 |
37 |
38 | 39 | 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "token-delegation-interface", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite dev --host", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "test": "playwright test", 10 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 11 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 12 | "lint": "prettier --check . && eslint .", 13 | "format": "prettier --write ." 14 | }, 15 | "devDependencies": { 16 | "@playwright/test": "^1.26.0", 17 | "@poppanator/sveltekit-svg": "^1.0.0", 18 | "@sveltejs/adapter-static": "^1.0.0-next.43", 19 | "@sveltejs/kit": "^1.0.0-next.493", 20 | "@typescript-eslint/eslint-plugin": "^5.38.0", 21 | "@typescript-eslint/parser": "^5.38.0", 22 | "eslint": "^8.23.1", 23 | "eslint-config-prettier": "^8.5.0", 24 | "eslint-plugin-svelte3": "^4.0.0", 25 | "prettier": "^2.7.1", 26 | "prettier-plugin-svelte": "^2.7.0", 27 | "svelte": "^3.50.1", 28 | "svelte-check": "^2.9.0", 29 | "svelte-preprocess": "^4.10.7", 30 | "tslib": "^2.4.0", 31 | "typescript": "^4.8.3", 32 | "vite": "^3.1.3" 33 | }, 34 | "type": "module", 35 | "dependencies": { 36 | "@walletconnect/web3-provider": "^1.8.0", 37 | "ethers": "^5.7.1", 38 | "svelte-ethers-store": "^2.5.8" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/assets/icons/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/illustrations/puzzled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/components/HammerLoader.svelte: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | 7 |
8 |
Loading...
9 |
10 | 11 | 82 | -------------------------------------------------------------------------------- /src/components/Footer.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 |
21 |
22 | 23 |
24 | 25 |
26 | 29 | 35 |
36 |
37 | 38 | 67 | -------------------------------------------------------------------------------- /src/abis/abis.ts: -------------------------------------------------------------------------------- 1 | export const IDelegationRegistryABI = [ 2 | 'event DelegateForAll(address vault, address delegate, bool value)', 3 | 'event DelegateForContract(address vault, address delegate, address contract_, bool value)', 4 | 'event DelegateForToken(address vault, address delegate, address contract_, uint256 tokenId, bool value)', 5 | 'event RevokeAllDelegates(address vault)', 6 | 'event RevokeDelegate(address vault, address delegate)', 7 | 'function checkDelegateForAll(address delegate, address vault) view returns (bool)', 8 | 'function checkDelegateForContract(address delegate, address vault, address contract_) view returns (bool)', 9 | 'function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId) view returns (bool)', 10 | 'function delegateForAll(address delegate, bool value)', 11 | 'function delegateForContract(address delegate, address contract_, bool value)', 12 | 'function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value)', 13 | 'function getContractLevelDelegations(address vault) view returns (tuple(address contract_, address delegate)[] delegations)', 14 | 'function getDelegatesForAll(address vault) view returns (address[])', 15 | 'function getDelegatesForContract(address vault, address contract_) view returns (address[])', 16 | 'function getDelegatesForToken(address vault, address contract_, uint256 tokenId) view returns (address[])', 17 | 'function getDelegationsByDelegate(address delegate) view returns (tuple(uint8 type_, address vault, address delegate, address contract_, uint256 tokenId)[])', 18 | 'function getTokenLevelDelegations(address vault) view returns (tuple(address contract_, uint256 tokenId, address delegate)[] delegations)', 19 | 'function revokeAllDelegates()', 20 | 'function revokeDelegate(address delegate)', 21 | 'function revokeSelf(address vault)' 22 | ]; 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # delegate-cash-frontend 2 | 3 | An interface for [EIP-5639: Delegation Registry](https://eips.ethereum.org/EIPS/eip-5639), with source code available at [0xfoobar/token-delegation](https://github.com/0xfoobar/token-delegation), 4 | 5 | Built with [svelte-kit](https://svelte.dev/), [ethers](https://ethers.io/#!/app-link/welcome.ethers.space/) and [svelte-ethers-store](https://gitlab.com/clb1/svelte-ethers-store). 6 | 7 | ## Quick start 8 | 9 | A nix dev environment with all the needed dependencies for running the frontend and compiling the contracts, and running an evm local chain is included for convenience 10 | 11 | 0. Clone the project with submodules `git clone --recurse-submodules git@github.com:0xfoobar/delegate-cash-frontend.git` 12 | 1. Install [nix](https://nix.dev/tutorials/install-nix) 13 | 2. Enable [flake support](https://nixos.wiki/wiki/Flakes#Enable_flakes) 14 | 3. Run `nix develop`, this will install all npm deps and compile the contracts 15 | 4. (optional) install [direnv](https://direnv.net/) and run `echo "use flake > .envrc` to automatically load all deps when entering the folder 16 | 5. On a new terminal enter `anvil --chain-id 1337` to run an ethereum local node, copy one of the private keys and import to metamask to be able to sign transactions 17 | 6. On a separate terminal enter `./deploy-contracts.sh` to deploy the contracts to a local fork 18 | 7. Run `npm run dev` to start a frontend dev server 19 | 20 | ## Credits 21 | 22 | Initial version by [0xnook](https://github.com/0xnook/) 23 | 24 | Illustrations by [denkishi](https://www.fiverr.com/denkishi) 25 | 26 | UI components [table](https://codepen.io/pablorgarcia/pen/ARdVgx), [floating label inputs](https://codepen.io/devesh8/pen/MWYEJEP), [theme toggler](https://codepen.io/PaulinaSurazynska/details/bGVpBOb) and [hammer loader](https://www.fiverr.com/denkishi), where taken and adapted from individual codepen authors. 27 | 28 | Design inspired by a beloved swedish furniture manufacturer. 29 | -------------------------------------------------------------------------------- /src/components/Header.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 |

{$page.routeId ? 'DELEGATE.CASH' : ''}

13 |
14 | {#if $chainId} 15 | 18 | 21 | {:else if inputType === 'number'} 22 | 29 | 32 | {/if} 33 |
34 | 35 | 78 | -------------------------------------------------------------------------------- /static/global.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Noto Sans'; 3 | font-style: normal; 4 | font-weight: 400; 5 | font-display: swap; 6 | src: url('/fonts/NotoSans/NotoSans-Regular.ttf') format('truetype'); 7 | } 8 | 9 | @font-face { 10 | font-family: 'Noto Sans'; 11 | font-style: normal; 12 | font-weight: 500; 13 | font-display: swap; 14 | src: url('/fonts/NotoSans/NotoSans-Medium.ttf') format('truetype'); 15 | } 16 | 17 | @font-face { 18 | font-family: 'Noto Sans'; 19 | font-style: normal; 20 | font-weight: 600; 21 | font-display: swap; 22 | src: url('/fonts/NotoSans/NotoSans-SemiBold.ttf') format('truetype'); 23 | } 24 | 25 | @font-face { 26 | font-family: 'Noto Sans'; 27 | font-style: normal; 28 | font-weight: 700; 29 | font-display: swap; 30 | src: url('/fonts/NotoSans/NotoSans-Bold.ttf') format('truetype'); 31 | } 32 | 33 | body { 34 | font-family: 'Noto Sans', sans-serif; 35 | padding: 0; 36 | margin: 0; 37 | height: 100%; 38 | background-color: var(--background-color); 39 | color: var(--outline-color); 40 | } 41 | 42 | /* styles to add global tooltip */ 43 | [data-tooltip] { 44 | position: relative; 45 | z-index: 2; 46 | display: block; 47 | } 48 | 49 | [data-tooltip]:before, 50 | [data-tooltip]:after { 51 | visibility: hidden; 52 | opacity: 0; 53 | pointer-events: none; 54 | transition: 0.2s ease-out; 55 | transform: translate(-50%, 5px); 56 | } 57 | 58 | [data-tooltip]:before { 59 | position: absolute; 60 | bottom: 100%; 61 | left: 50%; 62 | margin-bottom: 5px; 63 | padding: 7px; 64 | width: 100%; 65 | min-width: 8rem; 66 | max-width: 14rem; 67 | -webkit-border-radius: 3px; 68 | -moz-border-radius: 3px; 69 | border-radius: 3px; 70 | background-color: var(--outline-color); 71 | color: var(--background-color); 72 | content: attr(data-tooltip); 73 | text-align: center; 74 | font-size: 14px; 75 | font-weight: normal; 76 | line-height: 1.2; 77 | transition: 0.2s ease-out; 78 | } 79 | 80 | [data-tooltip]:after { 81 | position: absolute; 82 | bottom: 100%; 83 | left: 50%; 84 | width: 0; 85 | border-top: 6px solid var(--outline-color); 86 | border-right: 5px solid transparent; 87 | border-left: 5px solid transparent; 88 | content: ' '; 89 | font-size: 0; 90 | line-height: 0; 91 | } 92 | 93 | [data-tooltip]:hover:before, 94 | [data-tooltip]:hover:after { 95 | visibility: visible; 96 | opacity: 1; 97 | transform: translate(-50%, 0); 98 | } 99 | [data-tooltip='false']:hover:before, 100 | [data-tooltip='false']:hover:after { 101 | visibility: hidden; 102 | opacity: 0; 103 | } 104 | -------------------------------------------------------------------------------- /src/components/Table.svelte: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | {#each columns as column} 12 | 13 | {/each} 14 | 15 | 16 | 17 | {#each rows as row} 18 | 19 | {#each row as cell} 20 | 21 | {/each} 22 | 23 | {/each} 24 | 25 |
{column}
{cell.value}
26 | 27 | 104 | -------------------------------------------------------------------------------- /src/components/delegationRegistry/Card.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 | 15 | 16 | 17 |

{header}

18 | 19 |
20 | 21 |
22 | 23 | 24 | 25 | 26 |
27 | 28 | 95 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "locked": { 5 | "lastModified": 1644229661, 6 | "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", 7 | "owner": "numtide", 8 | "repo": "flake-utils", 9 | "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "numtide", 14 | "repo": "flake-utils", 15 | "type": "github" 16 | } 17 | }, 18 | "foundry": { 19 | "inputs": { 20 | "flake-utils": "flake-utils", 21 | "nixpkgs": "nixpkgs" 22 | }, 23 | "locked": { 24 | "lastModified": 1663751681, 25 | "narHash": "sha256-KM0FE22ixbDw02Fsi7h8eXRJ4OblJi8SvxnIVVMFdIA=", 26 | "owner": "shazow", 27 | "repo": "foundry.nix", 28 | "rev": "aa5d22e29a2fd5c46d56289c7a9c3e2a1d266dce", 29 | "type": "github" 30 | }, 31 | "original": { 32 | "owner": "shazow", 33 | "repo": "foundry.nix", 34 | "type": "github" 35 | } 36 | }, 37 | "nixpkgs": { 38 | "locked": { 39 | "lastModified": 1643805626, 40 | "narHash": "sha256-AXLDVMG+UaAGsGSpOtQHPIKB+IZ0KSd9WS77aanGzgc=", 41 | "owner": "nixos", 42 | "repo": "nixpkgs", 43 | "rev": "554d2d8aa25b6e583575459c297ec23750adb6cb", 44 | "type": "github" 45 | }, 46 | "original": { 47 | "owner": "nixos", 48 | "ref": "nixos-unstable", 49 | "repo": "nixpkgs", 50 | "type": "github" 51 | } 52 | }, 53 | "nixpkgs_2": { 54 | "locked": { 55 | "lastModified": 1663757063, 56 | "narHash": "sha256-H+BPgoXuVcdi3g5BH4cact4osjfjntaTQTdA/HNiCYE=", 57 | "owner": "NixOS", 58 | "repo": "nixpkgs", 59 | "rev": "a0e390471362e27349abc1090197e09fe8c59d16", 60 | "type": "github" 61 | }, 62 | "original": { 63 | "owner": "NixOS", 64 | "ref": "nixpkgs-unstable", 65 | "repo": "nixpkgs", 66 | "type": "github" 67 | } 68 | }, 69 | "root": { 70 | "inputs": { 71 | "foundry": "foundry", 72 | "nixpkgs": "nixpkgs_2", 73 | "utils": "utils" 74 | } 75 | }, 76 | "utils": { 77 | "locked": { 78 | "lastModified": 1659877975, 79 | "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", 80 | "owner": "numtide", 81 | "repo": "flake-utils", 82 | "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", 83 | "type": "github" 84 | }, 85 | "original": { 86 | "owner": "numtide", 87 | "repo": "flake-utils", 88 | "type": "github" 89 | } 90 | } 91 | }, 92 | "root": "root", 93 | "version": 7 94 | } 95 | -------------------------------------------------------------------------------- /src/components/delegationRegistry/Delegate.svelte: -------------------------------------------------------------------------------- 1 | 34 | 35 |
36 |
37 | 42 | 43 | {#if delegateKind === 'contract' || delegateKind === 'token'} 44 | 49 | {/if} 50 | 51 | {#if delegateKind === 'token'} 52 | 58 | {/if} 59 |
60 | 61 | 64 |
65 | 66 | 107 | -------------------------------------------------------------------------------- /src/components/ThemeToggle.svelte: -------------------------------------------------------------------------------- 1 | 2 | 61 | 62 |
63 | 70 |