From 0ec6676a3fc65f23e400d16586b4111918a8d75b Mon Sep 17 00:00:00 2001 From: Sam Ruberti Date: Fri, 16 Jun 2023 11:31:11 -0400 Subject: [PATCH 1/5] feat: add incrementer ui --- incrementer/frontend/.gitignore | 21 + incrementer/frontend/README.md | 4 + incrementer/frontend/index.html | 13 + incrementer/frontend/package.json | 30 ++ incrementer/frontend/postcss.config.js | 6 + incrementer/frontend/public/logo.svg | 1 + incrementer/frontend/src/App.tsx | 60 +++ incrementer/frontend/src/Global.css | 3 + .../frontend/src/assets/incrementer.json | 398 ++++++++++++++++++ incrementer/frontend/src/constants.ts | 2 + incrementer/frontend/src/main.tsx | 27 ++ incrementer/frontend/src/vite-env.d.ts | 1 + incrementer/frontend/tailwind.config.js | 2 + incrementer/frontend/tsconfig.json | 25 ++ incrementer/frontend/tsconfig.node.json | 10 + incrementer/frontend/vite.config.ts | 7 + package.json | 3 +- 17 files changed, 612 insertions(+), 1 deletion(-) create mode 100644 incrementer/frontend/.gitignore create mode 100644 incrementer/frontend/README.md create mode 100644 incrementer/frontend/index.html create mode 100644 incrementer/frontend/package.json create mode 100644 incrementer/frontend/postcss.config.js create mode 100644 incrementer/frontend/public/logo.svg create mode 100644 incrementer/frontend/src/App.tsx create mode 100644 incrementer/frontend/src/Global.css create mode 100644 incrementer/frontend/src/assets/incrementer.json create mode 100644 incrementer/frontend/src/constants.ts create mode 100644 incrementer/frontend/src/main.tsx create mode 100644 incrementer/frontend/src/vite-env.d.ts create mode 100644 incrementer/frontend/tailwind.config.js create mode 100644 incrementer/frontend/tsconfig.json create mode 100644 incrementer/frontend/tsconfig.node.json create mode 100644 incrementer/frontend/vite.config.ts diff --git a/incrementer/frontend/.gitignore b/incrementer/frontend/.gitignore new file mode 100644 index 00000000..c13f37b6 --- /dev/null +++ b/incrementer/frontend/.gitignore @@ -0,0 +1,21 @@ +# Logs +logs +*.log +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/incrementer/frontend/README.md b/incrementer/frontend/README.md new file mode 100644 index 00000000..ad88c572 --- /dev/null +++ b/incrementer/frontend/README.md @@ -0,0 +1,4 @@ +# Have Questions? + +For any questions about building front end applications with [useink](https://use.ink/frontend/overview/), join the [Element chat](https://matrix.to/#/%23useink:parity.io). + diff --git a/incrementer/frontend/index.html b/incrementer/frontend/index.html new file mode 100644 index 00000000..e4d2ac59 --- /dev/null +++ b/incrementer/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + ink! Examples + + +
+ + + diff --git a/incrementer/frontend/package.json b/incrementer/frontend/package.json new file mode 100644 index 00000000..d3d31477 --- /dev/null +++ b/incrementer/frontend/package.json @@ -0,0 +1,30 @@ +{ + "name": "incrementer", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "ui": "workspace:ui@*" + }, + "devDependencies": { + "@types/react": "^18.0.37", + "@types/react-dom": "^18.0.11", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", + "@vitejs/plugin-react": "^4.0.0", + "autoprefixer": "^10.4.14", + "eslint": "^8.38.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.3.4", + "postcss": "^8.4.24", + "tailwindcss": "^3.3.2", + "typescript": "^5.0.2", + "vite": "^4.3.9" + } +} diff --git a/incrementer/frontend/postcss.config.js b/incrementer/frontend/postcss.config.js new file mode 100644 index 00000000..2aa7205d --- /dev/null +++ b/incrementer/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/incrementer/frontend/public/logo.svg b/incrementer/frontend/public/logo.svg new file mode 100644 index 00000000..c31ded82 --- /dev/null +++ b/incrementer/frontend/public/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/incrementer/frontend/src/App.tsx b/incrementer/frontend/src/App.tsx new file mode 100644 index 00000000..b11908a5 --- /dev/null +++ b/incrementer/frontend/src/App.tsx @@ -0,0 +1,60 @@ +import metadata from './assets/incrementer.json'; +import { CONTRACT_ROCOCO_ADDRESS } from './constants'; +import { useState } from 'react'; +import { Button, Card, ConnectButton, InkLayout, NumberInput } from 'ui'; +import { useCallSubscription, useContract, useTx, useWallet } from 'useink'; +import { useTxNotifications } from 'useink/notifications'; +import { pickDecoded, shouldDisable } from 'useink/utils'; + +function App() { + const { account } = useWallet(); + const contract = useContract(CONTRACT_ROCOCO_ADDRESS, metadata); + const getSub = useCallSubscription(contract, 'get', [], { + defaultCaller: true, + }); + const [incAmount, setIncAmount] = useState(1); + const inc = useTx(contract, 'inc'); + useTxNotifications(inc); + + return ( + + +

+ {metadata.contract.name.toUpperCase()} +

+ +

+ Current Number:{' '} + {pickDecoded(getSub.result)} +

+ + setIncAmount(v)} + value={incAmount} + min={1} + max={100} + /> + + {account ? ( + + ) : ( + + )} +
+
+ ); +} + +export default App; diff --git a/incrementer/frontend/src/Global.css b/incrementer/frontend/src/Global.css new file mode 100644 index 00000000..bd6213e1 --- /dev/null +++ b/incrementer/frontend/src/Global.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/incrementer/frontend/src/assets/incrementer.json b/incrementer/frontend/src/assets/incrementer.json new file mode 100644 index 00000000..264ffe71 --- /dev/null +++ b/incrementer/frontend/src/assets/incrementer.json @@ -0,0 +1,398 @@ +{ + "source": { + "hash": "0xd03eed0bc4ad710b89b43a76efa9790b909220047e6a3b4d886f1428fcff349f", + "language": "ink! 4.2.0", + "compiler": "rustc 1.70.0", + "build_info": { + "build_mode": "Release", + "cargo_contract_version": "2.2.1", + "rust_toolchain": "stable-x86_64-apple-darwin", + "wasm_opt_settings": { + "keep_debug_symbols": false, + "optimization_passes": "Z" + } + } + }, + "contract": { + "name": "incrementer", + "version": "4.2.0", + "authors": [ + "Parity Technologies " + ] + }, + "spec": { + "constructors": [ + { + "args": [ + { + "label": "init_value", + "type": { + "displayName": [ + "i32" + ], + "type": 0 + } + } + ], + "default": false, + "docs": [], + "label": "new", + "payable": false, + "returnType": { + "displayName": [ + "ink_primitives", + "ConstructorResult" + ], + "type": 1 + }, + "selector": "0x9bae9d5e" + }, + { + "args": [], + "default": false, + "docs": [], + "label": "new_default", + "payable": false, + "returnType": { + "displayName": [ + "ink_primitives", + "ConstructorResult" + ], + "type": 1 + }, + "selector": "0x61ef7e3e" + } + ], + "docs": [], + "environment": { + "accountId": { + "displayName": [ + "AccountId" + ], + "type": 5 + }, + "balance": { + "displayName": [ + "Balance" + ], + "type": 8 + }, + "blockNumber": { + "displayName": [ + "BlockNumber" + ], + "type": 11 + }, + "chainExtension": { + "displayName": [ + "ChainExtension" + ], + "type": 12 + }, + "hash": { + "displayName": [ + "Hash" + ], + "type": 9 + }, + "maxEventTopics": 4, + "timestamp": { + "displayName": [ + "Timestamp" + ], + "type": 10 + } + }, + "events": [], + "lang_error": { + "displayName": [ + "ink", + "LangError" + ], + "type": 3 + }, + "messages": [ + { + "args": [ + { + "label": "by", + "type": { + "displayName": [ + "i32" + ], + "type": 0 + } + } + ], + "default": false, + "docs": [], + "label": "inc", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 1 + }, + "selector": "0x1d32619f" + }, + { + "args": [], + "default": false, + "docs": [], + "label": "get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 4 + }, + "selector": "0x2f865bd9" + } + ] + }, + "storage": { + "root": { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "leaf": { + "key": "0x00000000", + "ty": 0 + } + }, + "name": "value" + } + ], + "name": "Incrementer" + } + }, + "root_key": "0x00000000" + } + }, + "types": [ + { + "id": 0, + "type": { + "def": { + "primitive": "i32" + } + } + }, + { + "id": 1, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 2 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 2 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 2, + "type": { + "def": { + "tuple": [] + } + } + }, + { + "id": 3, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 1, + "name": "CouldNotReadInput" + } + ] + } + }, + "path": [ + "ink_primitives", + "LangError" + ] + } + }, + { + "id": 4, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 0 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 0 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 5, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 6, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "AccountId" + ] + } + }, + { + "id": 6, + "type": { + "def": { + "array": { + "len": 32, + "type": 7 + } + } + } + }, + { + "id": 7, + "type": { + "def": { + "primitive": "u8" + } + } + }, + { + "id": 8, + "type": { + "def": { + "primitive": "u128" + } + } + }, + { + "id": 9, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 6, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "Hash" + ] + } + }, + { + "id": 10, + "type": { + "def": { + "primitive": "u64" + } + } + }, + { + "id": 11, + "type": { + "def": { + "primitive": "u32" + } + } + }, + { + "id": 12, + "type": { + "def": { + "variant": {} + }, + "path": [ + "ink_env", + "types", + "NoChainExtension" + ] + } + } + ], + "version": "4" +} \ No newline at end of file diff --git a/incrementer/frontend/src/constants.ts b/incrementer/frontend/src/constants.ts new file mode 100644 index 00000000..ec2b8808 --- /dev/null +++ b/incrementer/frontend/src/constants.ts @@ -0,0 +1,2 @@ +export const CONTRACT_ROCOCO_ADDRESS = + '5GPBKgHopZS3tniuTMfPccr4QARh4uso2ej933Sx7RZrRbMH'; diff --git a/incrementer/frontend/src/main.tsx b/incrementer/frontend/src/main.tsx new file mode 100644 index 00000000..84ac05f0 --- /dev/null +++ b/incrementer/frontend/src/main.tsx @@ -0,0 +1,27 @@ +import App from './App.tsx'; +import './Global.css'; +import metadata from './assets/incrementer.json'; +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import 'ui/style.css'; +import { UseInkProvider } from 'useink'; +import { RococoContractsTestnet } from 'useink/chains'; +import { NotificationsProvider } from 'useink/notifications'; + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + + + + + + , +); diff --git a/incrementer/frontend/src/vite-env.d.ts b/incrementer/frontend/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/incrementer/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/incrementer/frontend/tailwind.config.js b/incrementer/frontend/tailwind.config.js new file mode 100644 index 00000000..c120a39a --- /dev/null +++ b/incrementer/frontend/tailwind.config.js @@ -0,0 +1,2 @@ +import config from '../../ui/tailwind.config'; +export default config; \ No newline at end of file diff --git a/incrementer/frontend/tsconfig.json b/incrementer/frontend/tsconfig.json new file mode 100644 index 00000000..a7fc6fbf --- /dev/null +++ b/incrementer/frontend/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/incrementer/frontend/tsconfig.node.json b/incrementer/frontend/tsconfig.node.json new file mode 100644 index 00000000..42872c59 --- /dev/null +++ b/incrementer/frontend/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/incrementer/frontend/vite.config.ts b/incrementer/frontend/vite.config.ts new file mode 100644 index 00000000..4e7004eb --- /dev/null +++ b/incrementer/frontend/vite.config.ts @@ -0,0 +1,7 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}); diff --git a/package.json b/package.json index 1a30146f..18650445 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "lint": "rome check ./*", "lint:fix": "pnpm lint --apply-unsafe", "build:ui": "pnpm --filter ui build", - "flipper": "pnpm --filter ui dev & pnpm --filter flipper dev" + "flipper": "pnpm --filter ui dev & pnpm --filter flipper dev", + "incrementer": "pnpm --filter ui dev & pnpm --filter incrementer dev" }, "packages": [ "ui", From e0e2a1edf87c1fe3cba33bcd80906510ee8a4675 Mon Sep 17 00:00:00 2001 From: Sam Ruberti Date: Fri, 16 Jun 2023 11:57:41 -0400 Subject: [PATCH 2/5] feat: add basic_contract_caller ui --- README.md | 6 + basic-contract-caller/lib.rs | 7 + basic-contract-caller/other_contract/lib.rs | 5 + basic_contract_caller/frontend/.gitignore | 21 + basic_contract_caller/frontend/README.md | 4 + basic_contract_caller/frontend/index.html | 13 + basic_contract_caller/frontend/package.json | 30 ++ .../frontend/postcss.config.js | 6 + .../frontend/public/logo.svg | 1 + basic_contract_caller/frontend/src/App.tsx | 61 +++ basic_contract_caller/frontend/src/Global.css | 7 + basic_contract_caller/frontend/src/Other.tsx | 30 ++ .../src/assets/basic_contract_caller.json | 446 ++++++++++++++++++ .../frontend/src/assets/other_contract.json | 431 +++++++++++++++++ .../frontend/src/constants.ts | 2 + basic_contract_caller/frontend/src/main.tsx | 27 ++ .../frontend/src/vite-env.d.ts | 1 + .../frontend/tailwind.config.js | 2 + basic_contract_caller/frontend/tsconfig.json | 25 + .../frontend/tsconfig.node.json | 10 + basic_contract_caller/frontend/vite.config.ts | 7 + package.json | 5 +- ui/src/Accounts/Accounts.tsx | 4 +- ui/src/Button/Button.tsx | 4 +- ui/src/Link/Link.tsx | 26 + ui/src/Link/index.ts | 1 + ui/src/NumberInput/NumberInput.tsx | 9 +- ui/src/index.ts | 1 + 28 files changed, 1181 insertions(+), 11 deletions(-) create mode 100644 basic_contract_caller/frontend/.gitignore create mode 100644 basic_contract_caller/frontend/README.md create mode 100644 basic_contract_caller/frontend/index.html create mode 100644 basic_contract_caller/frontend/package.json create mode 100644 basic_contract_caller/frontend/postcss.config.js create mode 100644 basic_contract_caller/frontend/public/logo.svg create mode 100644 basic_contract_caller/frontend/src/App.tsx create mode 100644 basic_contract_caller/frontend/src/Global.css create mode 100644 basic_contract_caller/frontend/src/Other.tsx create mode 100644 basic_contract_caller/frontend/src/assets/basic_contract_caller.json create mode 100644 basic_contract_caller/frontend/src/assets/other_contract.json create mode 100644 basic_contract_caller/frontend/src/constants.ts create mode 100644 basic_contract_caller/frontend/src/main.tsx create mode 100644 basic_contract_caller/frontend/src/vite-env.d.ts create mode 100644 basic_contract_caller/frontend/tailwind.config.js create mode 100644 basic_contract_caller/frontend/tsconfig.json create mode 100644 basic_contract_caller/frontend/tsconfig.node.json create mode 100644 basic_contract_caller/frontend/vite.config.ts create mode 100644 ui/src/Link/Link.tsx create mode 100644 ui/src/Link/index.ts diff --git a/README.md b/README.md index a189131a..d61b79d1 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,12 @@ The `.contract` file combines the Wasm and metadata into one file and can be use 4. Run each example with `pnpm `. e.g. `pnpm flipper` 5. Visit [http://localhost:5173](http://localhost:5173) in your browser. +### Commands + +* `pnpm flipper` +* `pnpm incrementer` +* `pnpm contract_transfer` + All examples are built with [useink](https://use.ink/frontend/overview), a React hooks library built by the ink! team. ## License diff --git a/basic-contract-caller/lib.rs b/basic-contract-caller/lib.rs index f988caab..14df01c2 100755 --- a/basic-contract-caller/lib.rs +++ b/basic-contract-caller/lib.rs @@ -37,5 +37,12 @@ mod basic_contract_caller { self.other_contract.flip(); self.other_contract.get() } + + /// Get the address of the other contract after it has been instantiated. We can + /// use this so we can call the other contract on the frontend. + #[ink(message)] + pub fn other(&mut self) -> AccountId { + self.other_contract.account_id() + } } } diff --git a/basic-contract-caller/other_contract/lib.rs b/basic-contract-caller/other_contract/lib.rs index 53e51019..00eabdb4 100755 --- a/basic-contract-caller/other_contract/lib.rs +++ b/basic-contract-caller/other_contract/lib.rs @@ -29,5 +29,10 @@ mod other_contract { pub fn get(&self) -> bool { self.value } + + #[ink(message)] + pub fn account_id(&self) -> AccountId { + self.env().account_id() + } } } diff --git a/basic_contract_caller/frontend/.gitignore b/basic_contract_caller/frontend/.gitignore new file mode 100644 index 00000000..c13f37b6 --- /dev/null +++ b/basic_contract_caller/frontend/.gitignore @@ -0,0 +1,21 @@ +# Logs +logs +*.log +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/basic_contract_caller/frontend/README.md b/basic_contract_caller/frontend/README.md new file mode 100644 index 00000000..ad88c572 --- /dev/null +++ b/basic_contract_caller/frontend/README.md @@ -0,0 +1,4 @@ +# Have Questions? + +For any questions about building front end applications with [useink](https://use.ink/frontend/overview/), join the [Element chat](https://matrix.to/#/%23useink:parity.io). + diff --git a/basic_contract_caller/frontend/index.html b/basic_contract_caller/frontend/index.html new file mode 100644 index 00000000..e4d2ac59 --- /dev/null +++ b/basic_contract_caller/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + ink! Examples + + +
+ + + diff --git a/basic_contract_caller/frontend/package.json b/basic_contract_caller/frontend/package.json new file mode 100644 index 00000000..a50868f9 --- /dev/null +++ b/basic_contract_caller/frontend/package.json @@ -0,0 +1,30 @@ +{ + "name": "basic_contract_caller", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "ui": "workspace:ui@*" + }, + "devDependencies": { + "@types/react": "^18.0.37", + "@types/react-dom": "^18.0.11", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", + "@vitejs/plugin-react": "^4.0.0", + "autoprefixer": "^10.4.14", + "eslint": "^8.38.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.3.4", + "postcss": "^8.4.24", + "tailwindcss": "^3.3.2", + "typescript": "^5.0.2", + "vite": "^4.3.9" + } +} diff --git a/basic_contract_caller/frontend/postcss.config.js b/basic_contract_caller/frontend/postcss.config.js new file mode 100644 index 00000000..2aa7205d --- /dev/null +++ b/basic_contract_caller/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/basic_contract_caller/frontend/public/logo.svg b/basic_contract_caller/frontend/public/logo.svg new file mode 100644 index 00000000..c31ded82 --- /dev/null +++ b/basic_contract_caller/frontend/public/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/basic_contract_caller/frontend/src/App.tsx b/basic_contract_caller/frontend/src/App.tsx new file mode 100644 index 00000000..20b39b67 --- /dev/null +++ b/basic_contract_caller/frontend/src/App.tsx @@ -0,0 +1,61 @@ +import { Other } from './Other'; +import basicContractMetadata from './assets/basic_contract_caller.json'; +import { BASIC_CONTRACT_ROCOCO_ADDRESS } from './constants'; +import { useEffect } from 'react'; +import { Button, Card, ConnectButton, InkLayout } from 'ui'; +import { useCall, useContract, useTx, useWallet } from 'useink'; +import { useTxNotifications } from 'useink/notifications'; +import { isPendingSignature, pickDecoded, shouldDisable } from 'useink/utils'; + +function App() { + const { account } = useWallet(); + const basicContract = useContract( + BASIC_CONTRACT_ROCOCO_ADDRESS, + basicContractMetadata, + ); + const flipAndGet = useTx(basicContract, 'flipAndGet'); + useTxNotifications(flipAndGet); + + const other = useCall(basicContract, 'other'); + + useEffect(() => { + other?.send([], { defaultCaller: true }); + }, [other.send]); + + const otherAddress = pickDecoded(other.result); + + return ( + +
+ +

+ {basicContractMetadata.contract.name.toUpperCase()} +

+ + {account ? ( + + ) : ( + + )} +
+ + {otherAddress && } +
+
+ ); +} + +export default App; diff --git a/basic_contract_caller/frontend/src/Global.css b/basic_contract_caller/frontend/src/Global.css new file mode 100644 index 00000000..c2f5c12e --- /dev/null +++ b/basic_contract_caller/frontend/src/Global.css @@ -0,0 +1,7 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +body { + background-color: #1A1452; +} \ No newline at end of file diff --git a/basic_contract_caller/frontend/src/Other.tsx b/basic_contract_caller/frontend/src/Other.tsx new file mode 100644 index 00000000..84f93b69 --- /dev/null +++ b/basic_contract_caller/frontend/src/Other.tsx @@ -0,0 +1,30 @@ +import otherContractMetadata from './assets/other_contract.json'; +import { Card } from 'ui'; +import { useCallSubscription, useContract } from 'useink'; +import { pickDecoded } from 'useink/utils'; + +interface Props { + address: string; +} + +export const Other: React.FC = ({ address }) => { + const otherContract = useContract(address, otherContractMetadata); + const getOtherSub = useCallSubscription(otherContract, 'get', [], { + defaultCaller: true, + }); + + return ( + +

+ {otherContractMetadata.contract.name.toUpperCase()} +

+ +

+ Flipped:{' '} + + {pickDecoded(getOtherSub.result)?.toString()} + +

+
+ ); +}; diff --git a/basic_contract_caller/frontend/src/assets/basic_contract_caller.json b/basic_contract_caller/frontend/src/assets/basic_contract_caller.json new file mode 100644 index 00000000..ca8feda4 --- /dev/null +++ b/basic_contract_caller/frontend/src/assets/basic_contract_caller.json @@ -0,0 +1,446 @@ +{ + "source": { + "hash": "0x116670008181c58c5b65ea9c97a22b2a5eb205372a9428c6ee4560787edd1dbd", + "language": "ink! 4.2.0", + "compiler": "rustc 1.70.0", + "build_info": { + "build_mode": "Release", + "cargo_contract_version": "2.2.1", + "rust_toolchain": "stable-x86_64-apple-darwin", + "wasm_opt_settings": { + "keep_debug_symbols": false, + "optimization_passes": "Z" + } + } + }, + "contract": { + "name": "basic_contract_caller", + "version": "4.2.0", + "authors": [ + "Parity Technologies " + ] + }, + "spec": { + "constructors": [ + { + "args": [ + { + "label": "other_contract_code_hash", + "type": { + "displayName": [ + "Hash" + ], + "type": 3 + } + } + ], + "default": false, + "docs": [ + "In order to use the `OtherContract` we first need to **instantiate** it.", + "", + "To do this we will use the uploaded `code_hash` of `OtherContract`." + ], + "label": "new", + "payable": false, + "returnType": { + "displayName": [ + "ink_primitives", + "ConstructorResult" + ], + "type": 4 + }, + "selector": "0x9bae9d5e" + } + ], + "docs": [], + "environment": { + "accountId": { + "displayName": [ + "AccountId" + ], + "type": 0 + }, + "balance": { + "displayName": [ + "Balance" + ], + "type": 10 + }, + "blockNumber": { + "displayName": [ + "BlockNumber" + ], + "type": 12 + }, + "chainExtension": { + "displayName": [ + "ChainExtension" + ], + "type": 13 + }, + "hash": { + "displayName": [ + "Hash" + ], + "type": 3 + }, + "maxEventTopics": 4, + "timestamp": { + "displayName": [ + "Timestamp" + ], + "type": 11 + } + }, + "events": [], + "lang_error": { + "displayName": [ + "ink", + "LangError" + ], + "type": 6 + }, + "messages": [ + { + "args": [], + "default": false, + "docs": [ + " Using the `ContractRef` we can call all the messages of the `OtherContract` as", + " if they were normal Rust methods (because at the end of the day, they", + " are!)." + ], + "label": "flip_and_get", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 7 + }, + "selector": "0x2e233661" + }, + { + "args": [], + "default": false, + "docs": [ + " Get the address of the other contract after it has been instantiated. We can", + " use this so we can call the other contract on the frontend." + ], + "label": "other", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 9 + }, + "selector": "0x96396e0f" + } + ] + }, + "storage": { + "root": { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "leaf": { + "key": "0x00000000", + "ty": 0 + } + }, + "name": "account_id" + } + ], + "name": "CallBuilder" + } + }, + "name": "inner" + } + ], + "name": "OtherContractRef" + } + }, + "name": "other_contract" + } + ], + "name": "BasicContractCaller" + } + }, + "root_key": "0x00000000" + } + }, + "types": [ + { + "id": 0, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 1, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "AccountId" + ] + } + }, + { + "id": 1, + "type": { + "def": { + "array": { + "len": 32, + "type": 2 + } + } + } + }, + { + "id": 2, + "type": { + "def": { + "primitive": "u8" + } + } + }, + { + "id": 3, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 1, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "Hash" + ] + } + }, + { + "id": 4, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 5 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 6 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 5 + }, + { + "name": "E", + "type": 6 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 5, + "type": { + "def": { + "tuple": [] + } + } + }, + { + "id": 6, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 1, + "name": "CouldNotReadInput" + } + ] + } + }, + "path": [ + "ink_primitives", + "LangError" + ] + } + }, + { + "id": 7, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 8 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 6 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 8 + }, + { + "name": "E", + "type": 6 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 8, + "type": { + "def": { + "primitive": "bool" + } + } + }, + { + "id": 9, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 0 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 6 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 0 + }, + { + "name": "E", + "type": 6 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 10, + "type": { + "def": { + "primitive": "u128" + } + } + }, + { + "id": 11, + "type": { + "def": { + "primitive": "u64" + } + } + }, + { + "id": 12, + "type": { + "def": { + "primitive": "u32" + } + } + }, + { + "id": 13, + "type": { + "def": { + "variant": {} + }, + "path": [ + "ink_env", + "types", + "NoChainExtension" + ] + } + } + ], + "version": "4" +} \ No newline at end of file diff --git a/basic_contract_caller/frontend/src/assets/other_contract.json b/basic_contract_caller/frontend/src/assets/other_contract.json new file mode 100644 index 00000000..3c05b931 --- /dev/null +++ b/basic_contract_caller/frontend/src/assets/other_contract.json @@ -0,0 +1,431 @@ +{ + "source": { + "hash": "0x8b9fdab59f82fc96ba8f8bba270e706a3900ec4fe9c92a249263f3fb63f8cb58", + "language": "ink! 4.2.0", + "compiler": "rustc 1.70.0", + "build_info": { + "build_mode": "Release", + "cargo_contract_version": "2.2.1", + "rust_toolchain": "stable-x86_64-apple-darwin", + "wasm_opt_settings": { + "keep_debug_symbols": false, + "optimization_passes": "Z" + } + } + }, + "contract": { + "name": "other_contract", + "version": "4.2.0", + "authors": [ + "Parity Technologies " + ] + }, + "spec": { + "constructors": [ + { + "args": [ + { + "label": "init_value", + "type": { + "displayName": [ + "bool" + ], + "type": 0 + } + } + ], + "default": false, + "docs": [], + "label": "new", + "payable": false, + "returnType": { + "displayName": [ + "ink_primitives", + "ConstructorResult" + ], + "type": 1 + }, + "selector": "0x9bae9d5e" + } + ], + "docs": [], + "environment": { + "accountId": { + "displayName": [ + "AccountId" + ], + "type": 6 + }, + "balance": { + "displayName": [ + "Balance" + ], + "type": 9 + }, + "blockNumber": { + "displayName": [ + "BlockNumber" + ], + "type": 12 + }, + "chainExtension": { + "displayName": [ + "ChainExtension" + ], + "type": 13 + }, + "hash": { + "displayName": [ + "Hash" + ], + "type": 10 + }, + "maxEventTopics": 4, + "timestamp": { + "displayName": [ + "Timestamp" + ], + "type": 11 + } + }, + "events": [], + "lang_error": { + "displayName": [ + "ink", + "LangError" + ], + "type": 3 + }, + "messages": [ + { + "args": [], + "default": false, + "docs": [], + "label": "flip", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 1 + }, + "selector": "0x633aa551" + }, + { + "args": [], + "default": false, + "docs": [], + "label": "get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 4 + }, + "selector": "0x2f865bd9" + }, + { + "args": [], + "default": false, + "docs": [], + "label": "account_id", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 5 + }, + "selector": "0x2be79821" + } + ] + }, + "storage": { + "root": { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "leaf": { + "key": "0x00000000", + "ty": 0 + } + }, + "name": "value" + } + ], + "name": "OtherContract" + } + }, + "root_key": "0x00000000" + } + }, + "types": [ + { + "id": 0, + "type": { + "def": { + "primitive": "bool" + } + } + }, + { + "id": 1, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 2 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 2 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 2, + "type": { + "def": { + "tuple": [] + } + } + }, + { + "id": 3, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 1, + "name": "CouldNotReadInput" + } + ] + } + }, + "path": [ + "ink_primitives", + "LangError" + ] + } + }, + { + "id": 4, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 0 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 0 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 5, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 6 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 6 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 6, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 7, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "AccountId" + ] + } + }, + { + "id": 7, + "type": { + "def": { + "array": { + "len": 32, + "type": 8 + } + } + } + }, + { + "id": 8, + "type": { + "def": { + "primitive": "u8" + } + } + }, + { + "id": 9, + "type": { + "def": { + "primitive": "u128" + } + } + }, + { + "id": 10, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 7, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "Hash" + ] + } + }, + { + "id": 11, + "type": { + "def": { + "primitive": "u64" + } + } + }, + { + "id": 12, + "type": { + "def": { + "primitive": "u32" + } + } + }, + { + "id": 13, + "type": { + "def": { + "variant": {} + }, + "path": [ + "ink_env", + "types", + "NoChainExtension" + ] + } + } + ], + "version": "4" +} \ No newline at end of file diff --git a/basic_contract_caller/frontend/src/constants.ts b/basic_contract_caller/frontend/src/constants.ts new file mode 100644 index 00000000..54cc8400 --- /dev/null +++ b/basic_contract_caller/frontend/src/constants.ts @@ -0,0 +1,2 @@ +export const BASIC_CONTRACT_ROCOCO_ADDRESS = + '5EnufwqqxnkWT6hc1LgjYWQGUsqQCtcr5192K2HuQJtRJgCi'; diff --git a/basic_contract_caller/frontend/src/main.tsx b/basic_contract_caller/frontend/src/main.tsx new file mode 100644 index 00000000..2ce2c515 --- /dev/null +++ b/basic_contract_caller/frontend/src/main.tsx @@ -0,0 +1,27 @@ +import App from './App.tsx'; +import './Global.css'; +import metadata from './assets/basic_contract_caller.json'; +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import 'ui/style.css'; +import { UseInkProvider } from 'useink'; +import { RococoContractsTestnet } from 'useink/chains'; +import { NotificationsProvider } from 'useink/notifications'; + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + + + + + + , +); diff --git a/basic_contract_caller/frontend/src/vite-env.d.ts b/basic_contract_caller/frontend/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/basic_contract_caller/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/basic_contract_caller/frontend/tailwind.config.js b/basic_contract_caller/frontend/tailwind.config.js new file mode 100644 index 00000000..c120a39a --- /dev/null +++ b/basic_contract_caller/frontend/tailwind.config.js @@ -0,0 +1,2 @@ +import config from '../../ui/tailwind.config'; +export default config; \ No newline at end of file diff --git a/basic_contract_caller/frontend/tsconfig.json b/basic_contract_caller/frontend/tsconfig.json new file mode 100644 index 00000000..a7fc6fbf --- /dev/null +++ b/basic_contract_caller/frontend/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/basic_contract_caller/frontend/tsconfig.node.json b/basic_contract_caller/frontend/tsconfig.node.json new file mode 100644 index 00000000..42872c59 --- /dev/null +++ b/basic_contract_caller/frontend/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/basic_contract_caller/frontend/vite.config.ts b/basic_contract_caller/frontend/vite.config.ts new file mode 100644 index 00000000..4e7004eb --- /dev/null +++ b/basic_contract_caller/frontend/vite.config.ts @@ -0,0 +1,7 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}); diff --git a/package.json b/package.json index 18650445..955eda91 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "lint:fix": "pnpm lint --apply-unsafe", "build:ui": "pnpm --filter ui build", "flipper": "pnpm --filter ui dev & pnpm --filter flipper dev", - "incrementer": "pnpm --filter ui dev & pnpm --filter incrementer dev" + "incrementer": "pnpm --filter ui dev & pnpm --filter incrementer dev", + "basic_contract_caller": "pnpm --filter ui dev & pnpm --filter basic_contract_caller dev" }, "packages": [ "ui", @@ -21,7 +22,7 @@ "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", - "useink": "^1.5.1" + "useink": "^1.7.5" }, "devDependencies": { "tailwindcss": "^3.3.2", diff --git a/ui/src/Accounts/Accounts.tsx b/ui/src/Accounts/Accounts.tsx index 8c9fd4e8..183c686b 100644 --- a/ui/src/Accounts/Accounts.tsx +++ b/ui/src/Accounts/Accounts.tsx @@ -15,7 +15,7 @@ export const Accounts: React.FC = ({ className }) => { return (
@@ -28,7 +28,7 @@ export const Accounts: React.FC = ({ className }) => {
= ({ ...rest }) => { const classes = classNames( - 'bg-brand-900 hover:opacity-80 transition ease-in-out px-6 py-2 border-none disabled:text-opacity-70', - 'text-base tracking-wide font-semibold rounded-full disabled:opacity-50 disabled:hover:bg-opacity-50', + 'bg-brand-900 hover:bg-brand-800 transition ease-in-out px-6 py-2 border-none', + 'text-base tracking-wide font-semibold rounded-full disabled:bg-brand-450', 'focus:ring-none disabled:cursor-not-allowed focus:outline-none focus:ring-0 focus:ring-offset-0 text-white', className, ); diff --git a/ui/src/Link/Link.tsx b/ui/src/Link/Link.tsx new file mode 100644 index 00000000..347d5cb9 --- /dev/null +++ b/ui/src/Link/Link.tsx @@ -0,0 +1,26 @@ +import classNames from 'classnames'; +import React, { + AnchorHTMLAttributes, + DetailedHTMLProps, + PropsWithChildren, +} from 'react'; + +type LinkHTMLProps = DetailedHTMLProps< + AnchorHTMLAttributes, + HTMLAnchorElement +>; + +type LinkProps = PropsWithChildren; + +export const Link: React.FC = ({ children, className, ...rest }) => { + const classes = classNames( + 'underline text-sm text-brand-300 font-semibold transition duration-25 hover:text-brand-450', + className, + ); + + return ( + + {children} + + ); +}; diff --git a/ui/src/Link/index.ts b/ui/src/Link/index.ts new file mode 100644 index 00000000..3db78f51 --- /dev/null +++ b/ui/src/Link/index.ts @@ -0,0 +1 @@ +export * from './Link'; diff --git a/ui/src/NumberInput/NumberInput.tsx b/ui/src/NumberInput/NumberInput.tsx index f3ae7cfd..535f104d 100644 --- a/ui/src/NumberInput/NumberInput.tsx +++ b/ui/src/NumberInput/NumberInput.tsx @@ -13,12 +13,11 @@ type Props = ClassNameable & { }; const COMMON_CLASSES = [ - 'bg-brand-500 text-white border-none focuse:outline-none focus-visible:outline-none', - 'focus:outline-none disabled:text-white/80 py-4 flex items-center justify-center', + 'bg-brand-500 disabled:bg-brand-450 text-white border-none focuse:outline-none focus-visible:outline-none', + 'focus:outline-none disabled:text-white/80 py-4 flex items-center justify-center disabled:cursor-not-allowed', ].join(' '); -const BUTTON_CLASSES = - 'hover:bg-brand-800 disabled:bg-brand-450 disabled:cursor-not-allowed'; +const BUTTON_CLASSES = 'hover:bg-brand-900'; export const NumberInput: React.FC = ({ value, @@ -52,7 +51,7 @@ export const NumberInput: React.FC = ({ Date: Fri, 16 Jun 2023 11:57:41 -0400 Subject: [PATCH 3/5] feat: add basic_contract_caller ui --- README.md | 6 + basic-contract-caller/lib.rs | 7 + basic-contract-caller/other_contract/lib.rs | 5 + basic_contract_caller/frontend/.gitignore | 21 + basic_contract_caller/frontend/README.md | 4 + basic_contract_caller/frontend/index.html | 13 + basic_contract_caller/frontend/package.json | 30 ++ .../frontend/postcss.config.js | 6 + .../frontend/public/logo.svg | 1 + basic_contract_caller/frontend/src/App.tsx | 61 +++ basic_contract_caller/frontend/src/Global.css | 7 + basic_contract_caller/frontend/src/Other.tsx | 30 ++ .../src/assets/basic_contract_caller.json | 446 ++++++++++++++++++ .../frontend/src/assets/other_contract.json | 431 +++++++++++++++++ .../frontend/src/constants.ts | 2 + basic_contract_caller/frontend/src/main.tsx | 27 ++ .../frontend/src/vite-env.d.ts | 1 + .../frontend/tailwind.config.js | 2 + basic_contract_caller/frontend/tsconfig.json | 25 + .../frontend/tsconfig.node.json | 10 + basic_contract_caller/frontend/vite.config.ts | 7 + package.json | 5 +- ui/src/Accounts/Accounts.tsx | 4 +- ui/src/Button/Button.tsx | 4 +- ui/src/Link/Link.tsx | 26 + ui/src/Link/index.ts | 1 + ui/src/NumberInput/NumberInput.tsx | 9 +- ui/src/index.ts | 1 + 28 files changed, 1181 insertions(+), 11 deletions(-) create mode 100644 basic_contract_caller/frontend/.gitignore create mode 100644 basic_contract_caller/frontend/README.md create mode 100644 basic_contract_caller/frontend/index.html create mode 100644 basic_contract_caller/frontend/package.json create mode 100644 basic_contract_caller/frontend/postcss.config.js create mode 100644 basic_contract_caller/frontend/public/logo.svg create mode 100644 basic_contract_caller/frontend/src/App.tsx create mode 100644 basic_contract_caller/frontend/src/Global.css create mode 100644 basic_contract_caller/frontend/src/Other.tsx create mode 100644 basic_contract_caller/frontend/src/assets/basic_contract_caller.json create mode 100644 basic_contract_caller/frontend/src/assets/other_contract.json create mode 100644 basic_contract_caller/frontend/src/constants.ts create mode 100644 basic_contract_caller/frontend/src/main.tsx create mode 100644 basic_contract_caller/frontend/src/vite-env.d.ts create mode 100644 basic_contract_caller/frontend/tailwind.config.js create mode 100644 basic_contract_caller/frontend/tsconfig.json create mode 100644 basic_contract_caller/frontend/tsconfig.node.json create mode 100644 basic_contract_caller/frontend/vite.config.ts create mode 100644 ui/src/Link/Link.tsx create mode 100644 ui/src/Link/index.ts diff --git a/README.md b/README.md index a189131a..d61b79d1 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,12 @@ The `.contract` file combines the Wasm and metadata into one file and can be use 4. Run each example with `pnpm `. e.g. `pnpm flipper` 5. Visit [http://localhost:5173](http://localhost:5173) in your browser. +### Commands + +* `pnpm flipper` +* `pnpm incrementer` +* `pnpm contract_transfer` + All examples are built with [useink](https://use.ink/frontend/overview), a React hooks library built by the ink! team. ## License diff --git a/basic-contract-caller/lib.rs b/basic-contract-caller/lib.rs index f988caab..14df01c2 100755 --- a/basic-contract-caller/lib.rs +++ b/basic-contract-caller/lib.rs @@ -37,5 +37,12 @@ mod basic_contract_caller { self.other_contract.flip(); self.other_contract.get() } + + /// Get the address of the other contract after it has been instantiated. We can + /// use this so we can call the other contract on the frontend. + #[ink(message)] + pub fn other(&mut self) -> AccountId { + self.other_contract.account_id() + } } } diff --git a/basic-contract-caller/other_contract/lib.rs b/basic-contract-caller/other_contract/lib.rs index 53e51019..00eabdb4 100755 --- a/basic-contract-caller/other_contract/lib.rs +++ b/basic-contract-caller/other_contract/lib.rs @@ -29,5 +29,10 @@ mod other_contract { pub fn get(&self) -> bool { self.value } + + #[ink(message)] + pub fn account_id(&self) -> AccountId { + self.env().account_id() + } } } diff --git a/basic_contract_caller/frontend/.gitignore b/basic_contract_caller/frontend/.gitignore new file mode 100644 index 00000000..c13f37b6 --- /dev/null +++ b/basic_contract_caller/frontend/.gitignore @@ -0,0 +1,21 @@ +# Logs +logs +*.log +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/basic_contract_caller/frontend/README.md b/basic_contract_caller/frontend/README.md new file mode 100644 index 00000000..ad88c572 --- /dev/null +++ b/basic_contract_caller/frontend/README.md @@ -0,0 +1,4 @@ +# Have Questions? + +For any questions about building front end applications with [useink](https://use.ink/frontend/overview/), join the [Element chat](https://matrix.to/#/%23useink:parity.io). + diff --git a/basic_contract_caller/frontend/index.html b/basic_contract_caller/frontend/index.html new file mode 100644 index 00000000..e4d2ac59 --- /dev/null +++ b/basic_contract_caller/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + ink! Examples + + +
+ + + diff --git a/basic_contract_caller/frontend/package.json b/basic_contract_caller/frontend/package.json new file mode 100644 index 00000000..a50868f9 --- /dev/null +++ b/basic_contract_caller/frontend/package.json @@ -0,0 +1,30 @@ +{ + "name": "basic_contract_caller", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "ui": "workspace:ui@*" + }, + "devDependencies": { + "@types/react": "^18.0.37", + "@types/react-dom": "^18.0.11", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", + "@vitejs/plugin-react": "^4.0.0", + "autoprefixer": "^10.4.14", + "eslint": "^8.38.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.3.4", + "postcss": "^8.4.24", + "tailwindcss": "^3.3.2", + "typescript": "^5.0.2", + "vite": "^4.3.9" + } +} diff --git a/basic_contract_caller/frontend/postcss.config.js b/basic_contract_caller/frontend/postcss.config.js new file mode 100644 index 00000000..2aa7205d --- /dev/null +++ b/basic_contract_caller/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/basic_contract_caller/frontend/public/logo.svg b/basic_contract_caller/frontend/public/logo.svg new file mode 100644 index 00000000..c31ded82 --- /dev/null +++ b/basic_contract_caller/frontend/public/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/basic_contract_caller/frontend/src/App.tsx b/basic_contract_caller/frontend/src/App.tsx new file mode 100644 index 00000000..20b39b67 --- /dev/null +++ b/basic_contract_caller/frontend/src/App.tsx @@ -0,0 +1,61 @@ +import { Other } from './Other'; +import basicContractMetadata from './assets/basic_contract_caller.json'; +import { BASIC_CONTRACT_ROCOCO_ADDRESS } from './constants'; +import { useEffect } from 'react'; +import { Button, Card, ConnectButton, InkLayout } from 'ui'; +import { useCall, useContract, useTx, useWallet } from 'useink'; +import { useTxNotifications } from 'useink/notifications'; +import { isPendingSignature, pickDecoded, shouldDisable } from 'useink/utils'; + +function App() { + const { account } = useWallet(); + const basicContract = useContract( + BASIC_CONTRACT_ROCOCO_ADDRESS, + basicContractMetadata, + ); + const flipAndGet = useTx(basicContract, 'flipAndGet'); + useTxNotifications(flipAndGet); + + const other = useCall(basicContract, 'other'); + + useEffect(() => { + other?.send([], { defaultCaller: true }); + }, [other.send]); + + const otherAddress = pickDecoded(other.result); + + return ( + +
+ +

+ {basicContractMetadata.contract.name.toUpperCase()} +

+ + {account ? ( + + ) : ( + + )} +
+ + {otherAddress && } +
+
+ ); +} + +export default App; diff --git a/basic_contract_caller/frontend/src/Global.css b/basic_contract_caller/frontend/src/Global.css new file mode 100644 index 00000000..c2f5c12e --- /dev/null +++ b/basic_contract_caller/frontend/src/Global.css @@ -0,0 +1,7 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +body { + background-color: #1A1452; +} \ No newline at end of file diff --git a/basic_contract_caller/frontend/src/Other.tsx b/basic_contract_caller/frontend/src/Other.tsx new file mode 100644 index 00000000..84f93b69 --- /dev/null +++ b/basic_contract_caller/frontend/src/Other.tsx @@ -0,0 +1,30 @@ +import otherContractMetadata from './assets/other_contract.json'; +import { Card } from 'ui'; +import { useCallSubscription, useContract } from 'useink'; +import { pickDecoded } from 'useink/utils'; + +interface Props { + address: string; +} + +export const Other: React.FC = ({ address }) => { + const otherContract = useContract(address, otherContractMetadata); + const getOtherSub = useCallSubscription(otherContract, 'get', [], { + defaultCaller: true, + }); + + return ( + +

+ {otherContractMetadata.contract.name.toUpperCase()} +

+ +

+ Flipped:{' '} + + {pickDecoded(getOtherSub.result)?.toString()} + +

+
+ ); +}; diff --git a/basic_contract_caller/frontend/src/assets/basic_contract_caller.json b/basic_contract_caller/frontend/src/assets/basic_contract_caller.json new file mode 100644 index 00000000..ca8feda4 --- /dev/null +++ b/basic_contract_caller/frontend/src/assets/basic_contract_caller.json @@ -0,0 +1,446 @@ +{ + "source": { + "hash": "0x116670008181c58c5b65ea9c97a22b2a5eb205372a9428c6ee4560787edd1dbd", + "language": "ink! 4.2.0", + "compiler": "rustc 1.70.0", + "build_info": { + "build_mode": "Release", + "cargo_contract_version": "2.2.1", + "rust_toolchain": "stable-x86_64-apple-darwin", + "wasm_opt_settings": { + "keep_debug_symbols": false, + "optimization_passes": "Z" + } + } + }, + "contract": { + "name": "basic_contract_caller", + "version": "4.2.0", + "authors": [ + "Parity Technologies " + ] + }, + "spec": { + "constructors": [ + { + "args": [ + { + "label": "other_contract_code_hash", + "type": { + "displayName": [ + "Hash" + ], + "type": 3 + } + } + ], + "default": false, + "docs": [ + "In order to use the `OtherContract` we first need to **instantiate** it.", + "", + "To do this we will use the uploaded `code_hash` of `OtherContract`." + ], + "label": "new", + "payable": false, + "returnType": { + "displayName": [ + "ink_primitives", + "ConstructorResult" + ], + "type": 4 + }, + "selector": "0x9bae9d5e" + } + ], + "docs": [], + "environment": { + "accountId": { + "displayName": [ + "AccountId" + ], + "type": 0 + }, + "balance": { + "displayName": [ + "Balance" + ], + "type": 10 + }, + "blockNumber": { + "displayName": [ + "BlockNumber" + ], + "type": 12 + }, + "chainExtension": { + "displayName": [ + "ChainExtension" + ], + "type": 13 + }, + "hash": { + "displayName": [ + "Hash" + ], + "type": 3 + }, + "maxEventTopics": 4, + "timestamp": { + "displayName": [ + "Timestamp" + ], + "type": 11 + } + }, + "events": [], + "lang_error": { + "displayName": [ + "ink", + "LangError" + ], + "type": 6 + }, + "messages": [ + { + "args": [], + "default": false, + "docs": [ + " Using the `ContractRef` we can call all the messages of the `OtherContract` as", + " if they were normal Rust methods (because at the end of the day, they", + " are!)." + ], + "label": "flip_and_get", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 7 + }, + "selector": "0x2e233661" + }, + { + "args": [], + "default": false, + "docs": [ + " Get the address of the other contract after it has been instantiated. We can", + " use this so we can call the other contract on the frontend." + ], + "label": "other", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 9 + }, + "selector": "0x96396e0f" + } + ] + }, + "storage": { + "root": { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "leaf": { + "key": "0x00000000", + "ty": 0 + } + }, + "name": "account_id" + } + ], + "name": "CallBuilder" + } + }, + "name": "inner" + } + ], + "name": "OtherContractRef" + } + }, + "name": "other_contract" + } + ], + "name": "BasicContractCaller" + } + }, + "root_key": "0x00000000" + } + }, + "types": [ + { + "id": 0, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 1, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "AccountId" + ] + } + }, + { + "id": 1, + "type": { + "def": { + "array": { + "len": 32, + "type": 2 + } + } + } + }, + { + "id": 2, + "type": { + "def": { + "primitive": "u8" + } + } + }, + { + "id": 3, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 1, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "Hash" + ] + } + }, + { + "id": 4, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 5 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 6 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 5 + }, + { + "name": "E", + "type": 6 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 5, + "type": { + "def": { + "tuple": [] + } + } + }, + { + "id": 6, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 1, + "name": "CouldNotReadInput" + } + ] + } + }, + "path": [ + "ink_primitives", + "LangError" + ] + } + }, + { + "id": 7, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 8 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 6 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 8 + }, + { + "name": "E", + "type": 6 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 8, + "type": { + "def": { + "primitive": "bool" + } + } + }, + { + "id": 9, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 0 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 6 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 0 + }, + { + "name": "E", + "type": 6 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 10, + "type": { + "def": { + "primitive": "u128" + } + } + }, + { + "id": 11, + "type": { + "def": { + "primitive": "u64" + } + } + }, + { + "id": 12, + "type": { + "def": { + "primitive": "u32" + } + } + }, + { + "id": 13, + "type": { + "def": { + "variant": {} + }, + "path": [ + "ink_env", + "types", + "NoChainExtension" + ] + } + } + ], + "version": "4" +} \ No newline at end of file diff --git a/basic_contract_caller/frontend/src/assets/other_contract.json b/basic_contract_caller/frontend/src/assets/other_contract.json new file mode 100644 index 00000000..3c05b931 --- /dev/null +++ b/basic_contract_caller/frontend/src/assets/other_contract.json @@ -0,0 +1,431 @@ +{ + "source": { + "hash": "0x8b9fdab59f82fc96ba8f8bba270e706a3900ec4fe9c92a249263f3fb63f8cb58", + "language": "ink! 4.2.0", + "compiler": "rustc 1.70.0", + "build_info": { + "build_mode": "Release", + "cargo_contract_version": "2.2.1", + "rust_toolchain": "stable-x86_64-apple-darwin", + "wasm_opt_settings": { + "keep_debug_symbols": false, + "optimization_passes": "Z" + } + } + }, + "contract": { + "name": "other_contract", + "version": "4.2.0", + "authors": [ + "Parity Technologies " + ] + }, + "spec": { + "constructors": [ + { + "args": [ + { + "label": "init_value", + "type": { + "displayName": [ + "bool" + ], + "type": 0 + } + } + ], + "default": false, + "docs": [], + "label": "new", + "payable": false, + "returnType": { + "displayName": [ + "ink_primitives", + "ConstructorResult" + ], + "type": 1 + }, + "selector": "0x9bae9d5e" + } + ], + "docs": [], + "environment": { + "accountId": { + "displayName": [ + "AccountId" + ], + "type": 6 + }, + "balance": { + "displayName": [ + "Balance" + ], + "type": 9 + }, + "blockNumber": { + "displayName": [ + "BlockNumber" + ], + "type": 12 + }, + "chainExtension": { + "displayName": [ + "ChainExtension" + ], + "type": 13 + }, + "hash": { + "displayName": [ + "Hash" + ], + "type": 10 + }, + "maxEventTopics": 4, + "timestamp": { + "displayName": [ + "Timestamp" + ], + "type": 11 + } + }, + "events": [], + "lang_error": { + "displayName": [ + "ink", + "LangError" + ], + "type": 3 + }, + "messages": [ + { + "args": [], + "default": false, + "docs": [], + "label": "flip", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 1 + }, + "selector": "0x633aa551" + }, + { + "args": [], + "default": false, + "docs": [], + "label": "get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 4 + }, + "selector": "0x2f865bd9" + }, + { + "args": [], + "default": false, + "docs": [], + "label": "account_id", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 5 + }, + "selector": "0x2be79821" + } + ] + }, + "storage": { + "root": { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "leaf": { + "key": "0x00000000", + "ty": 0 + } + }, + "name": "value" + } + ], + "name": "OtherContract" + } + }, + "root_key": "0x00000000" + } + }, + "types": [ + { + "id": 0, + "type": { + "def": { + "primitive": "bool" + } + } + }, + { + "id": 1, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 2 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 2 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 2, + "type": { + "def": { + "tuple": [] + } + } + }, + { + "id": 3, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 1, + "name": "CouldNotReadInput" + } + ] + } + }, + "path": [ + "ink_primitives", + "LangError" + ] + } + }, + { + "id": 4, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 0 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 0 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 5, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 6 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 6 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 6, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 7, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "AccountId" + ] + } + }, + { + "id": 7, + "type": { + "def": { + "array": { + "len": 32, + "type": 8 + } + } + } + }, + { + "id": 8, + "type": { + "def": { + "primitive": "u8" + } + } + }, + { + "id": 9, + "type": { + "def": { + "primitive": "u128" + } + } + }, + { + "id": 10, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 7, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "Hash" + ] + } + }, + { + "id": 11, + "type": { + "def": { + "primitive": "u64" + } + } + }, + { + "id": 12, + "type": { + "def": { + "primitive": "u32" + } + } + }, + { + "id": 13, + "type": { + "def": { + "variant": {} + }, + "path": [ + "ink_env", + "types", + "NoChainExtension" + ] + } + } + ], + "version": "4" +} \ No newline at end of file diff --git a/basic_contract_caller/frontend/src/constants.ts b/basic_contract_caller/frontend/src/constants.ts new file mode 100644 index 00000000..54cc8400 --- /dev/null +++ b/basic_contract_caller/frontend/src/constants.ts @@ -0,0 +1,2 @@ +export const BASIC_CONTRACT_ROCOCO_ADDRESS = + '5EnufwqqxnkWT6hc1LgjYWQGUsqQCtcr5192K2HuQJtRJgCi'; diff --git a/basic_contract_caller/frontend/src/main.tsx b/basic_contract_caller/frontend/src/main.tsx new file mode 100644 index 00000000..2ce2c515 --- /dev/null +++ b/basic_contract_caller/frontend/src/main.tsx @@ -0,0 +1,27 @@ +import App from './App.tsx'; +import './Global.css'; +import metadata from './assets/basic_contract_caller.json'; +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import 'ui/style.css'; +import { UseInkProvider } from 'useink'; +import { RococoContractsTestnet } from 'useink/chains'; +import { NotificationsProvider } from 'useink/notifications'; + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + + + + + + , +); diff --git a/basic_contract_caller/frontend/src/vite-env.d.ts b/basic_contract_caller/frontend/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/basic_contract_caller/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/basic_contract_caller/frontend/tailwind.config.js b/basic_contract_caller/frontend/tailwind.config.js new file mode 100644 index 00000000..c120a39a --- /dev/null +++ b/basic_contract_caller/frontend/tailwind.config.js @@ -0,0 +1,2 @@ +import config from '../../ui/tailwind.config'; +export default config; \ No newline at end of file diff --git a/basic_contract_caller/frontend/tsconfig.json b/basic_contract_caller/frontend/tsconfig.json new file mode 100644 index 00000000..a7fc6fbf --- /dev/null +++ b/basic_contract_caller/frontend/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/basic_contract_caller/frontend/tsconfig.node.json b/basic_contract_caller/frontend/tsconfig.node.json new file mode 100644 index 00000000..42872c59 --- /dev/null +++ b/basic_contract_caller/frontend/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/basic_contract_caller/frontend/vite.config.ts b/basic_contract_caller/frontend/vite.config.ts new file mode 100644 index 00000000..4e7004eb --- /dev/null +++ b/basic_contract_caller/frontend/vite.config.ts @@ -0,0 +1,7 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}); diff --git a/package.json b/package.json index 18650445..955eda91 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "lint:fix": "pnpm lint --apply-unsafe", "build:ui": "pnpm --filter ui build", "flipper": "pnpm --filter ui dev & pnpm --filter flipper dev", - "incrementer": "pnpm --filter ui dev & pnpm --filter incrementer dev" + "incrementer": "pnpm --filter ui dev & pnpm --filter incrementer dev", + "basic_contract_caller": "pnpm --filter ui dev & pnpm --filter basic_contract_caller dev" }, "packages": [ "ui", @@ -21,7 +22,7 @@ "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", - "useink": "^1.5.1" + "useink": "^1.7.5" }, "devDependencies": { "tailwindcss": "^3.3.2", diff --git a/ui/src/Accounts/Accounts.tsx b/ui/src/Accounts/Accounts.tsx index 8c9fd4e8..183c686b 100644 --- a/ui/src/Accounts/Accounts.tsx +++ b/ui/src/Accounts/Accounts.tsx @@ -15,7 +15,7 @@ export const Accounts: React.FC = ({ className }) => { return (
@@ -28,7 +28,7 @@ export const Accounts: React.FC = ({ className }) => {
= ({ ...rest }) => { const classes = classNames( - 'bg-brand-900 hover:opacity-80 transition ease-in-out px-6 py-2 border-none disabled:text-opacity-70', - 'text-base tracking-wide font-semibold rounded-full disabled:opacity-50 disabled:hover:bg-opacity-50', + 'bg-brand-900 hover:bg-brand-800 transition ease-in-out px-6 py-2 border-none', + 'text-base tracking-wide font-semibold rounded-full disabled:bg-brand-450', 'focus:ring-none disabled:cursor-not-allowed focus:outline-none focus:ring-0 focus:ring-offset-0 text-white', className, ); diff --git a/ui/src/Link/Link.tsx b/ui/src/Link/Link.tsx new file mode 100644 index 00000000..347d5cb9 --- /dev/null +++ b/ui/src/Link/Link.tsx @@ -0,0 +1,26 @@ +import classNames from 'classnames'; +import React, { + AnchorHTMLAttributes, + DetailedHTMLProps, + PropsWithChildren, +} from 'react'; + +type LinkHTMLProps = DetailedHTMLProps< + AnchorHTMLAttributes, + HTMLAnchorElement +>; + +type LinkProps = PropsWithChildren; + +export const Link: React.FC = ({ children, className, ...rest }) => { + const classes = classNames( + 'underline text-sm text-brand-300 font-semibold transition duration-25 hover:text-brand-450', + className, + ); + + return ( + + {children} + + ); +}; diff --git a/ui/src/Link/index.ts b/ui/src/Link/index.ts new file mode 100644 index 00000000..3db78f51 --- /dev/null +++ b/ui/src/Link/index.ts @@ -0,0 +1 @@ +export * from './Link'; diff --git a/ui/src/NumberInput/NumberInput.tsx b/ui/src/NumberInput/NumberInput.tsx index f3ae7cfd..535f104d 100644 --- a/ui/src/NumberInput/NumberInput.tsx +++ b/ui/src/NumberInput/NumberInput.tsx @@ -13,12 +13,11 @@ type Props = ClassNameable & { }; const COMMON_CLASSES = [ - 'bg-brand-500 text-white border-none focuse:outline-none focus-visible:outline-none', - 'focus:outline-none disabled:text-white/80 py-4 flex items-center justify-center', + 'bg-brand-500 disabled:bg-brand-450 text-white border-none focuse:outline-none focus-visible:outline-none', + 'focus:outline-none disabled:text-white/80 py-4 flex items-center justify-center disabled:cursor-not-allowed', ].join(' '); -const BUTTON_CLASSES = - 'hover:bg-brand-800 disabled:bg-brand-450 disabled:cursor-not-allowed'; +const BUTTON_CLASSES = 'hover:bg-brand-900'; export const NumberInput: React.FC = ({ value, @@ -52,7 +51,7 @@ export const NumberInput: React.FC = ({ Date: Thu, 9 Nov 2023 12:34:11 +0100 Subject: [PATCH 4/5] move frontend to correct folder --- .../frontend/.gitignore | 0 .../frontend/README.md | 0 .../frontend/index.html | 0 .../frontend/package.json | 0 .../frontend/postcss.config.js | 0 .../frontend/public/logo.svg | 0 .../frontend/src/App.tsx | 0 .../frontend/src/Global.css | 0 .../frontend/src/Other.tsx | 0 .../frontend/src/assets/basic_contract_caller.json | 0 .../frontend/src/assets/other_contract.json | 0 .../frontend/src/constants.ts | 0 .../frontend/src/main.tsx | 0 .../frontend/src/vite-env.d.ts | 0 .../frontend/tailwind.config.js | 0 .../frontend/tsconfig.json | 0 .../frontend/tsconfig.node.json | 0 .../frontend/vite.config.ts | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename {basic_contract_caller => basic-contract-caller}/frontend/.gitignore (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/README.md (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/index.html (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/package.json (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/postcss.config.js (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/public/logo.svg (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/src/App.tsx (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/src/Global.css (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/src/Other.tsx (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/src/assets/basic_contract_caller.json (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/src/assets/other_contract.json (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/src/constants.ts (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/src/main.tsx (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/src/vite-env.d.ts (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/tailwind.config.js (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/tsconfig.json (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/tsconfig.node.json (100%) rename {basic_contract_caller => basic-contract-caller}/frontend/vite.config.ts (100%) diff --git a/basic_contract_caller/frontend/.gitignore b/basic-contract-caller/frontend/.gitignore similarity index 100% rename from basic_contract_caller/frontend/.gitignore rename to basic-contract-caller/frontend/.gitignore diff --git a/basic_contract_caller/frontend/README.md b/basic-contract-caller/frontend/README.md similarity index 100% rename from basic_contract_caller/frontend/README.md rename to basic-contract-caller/frontend/README.md diff --git a/basic_contract_caller/frontend/index.html b/basic-contract-caller/frontend/index.html similarity index 100% rename from basic_contract_caller/frontend/index.html rename to basic-contract-caller/frontend/index.html diff --git a/basic_contract_caller/frontend/package.json b/basic-contract-caller/frontend/package.json similarity index 100% rename from basic_contract_caller/frontend/package.json rename to basic-contract-caller/frontend/package.json diff --git a/basic_contract_caller/frontend/postcss.config.js b/basic-contract-caller/frontend/postcss.config.js similarity index 100% rename from basic_contract_caller/frontend/postcss.config.js rename to basic-contract-caller/frontend/postcss.config.js diff --git a/basic_contract_caller/frontend/public/logo.svg b/basic-contract-caller/frontend/public/logo.svg similarity index 100% rename from basic_contract_caller/frontend/public/logo.svg rename to basic-contract-caller/frontend/public/logo.svg diff --git a/basic_contract_caller/frontend/src/App.tsx b/basic-contract-caller/frontend/src/App.tsx similarity index 100% rename from basic_contract_caller/frontend/src/App.tsx rename to basic-contract-caller/frontend/src/App.tsx diff --git a/basic_contract_caller/frontend/src/Global.css b/basic-contract-caller/frontend/src/Global.css similarity index 100% rename from basic_contract_caller/frontend/src/Global.css rename to basic-contract-caller/frontend/src/Global.css diff --git a/basic_contract_caller/frontend/src/Other.tsx b/basic-contract-caller/frontend/src/Other.tsx similarity index 100% rename from basic_contract_caller/frontend/src/Other.tsx rename to basic-contract-caller/frontend/src/Other.tsx diff --git a/basic_contract_caller/frontend/src/assets/basic_contract_caller.json b/basic-contract-caller/frontend/src/assets/basic_contract_caller.json similarity index 100% rename from basic_contract_caller/frontend/src/assets/basic_contract_caller.json rename to basic-contract-caller/frontend/src/assets/basic_contract_caller.json diff --git a/basic_contract_caller/frontend/src/assets/other_contract.json b/basic-contract-caller/frontend/src/assets/other_contract.json similarity index 100% rename from basic_contract_caller/frontend/src/assets/other_contract.json rename to basic-contract-caller/frontend/src/assets/other_contract.json diff --git a/basic_contract_caller/frontend/src/constants.ts b/basic-contract-caller/frontend/src/constants.ts similarity index 100% rename from basic_contract_caller/frontend/src/constants.ts rename to basic-contract-caller/frontend/src/constants.ts diff --git a/basic_contract_caller/frontend/src/main.tsx b/basic-contract-caller/frontend/src/main.tsx similarity index 100% rename from basic_contract_caller/frontend/src/main.tsx rename to basic-contract-caller/frontend/src/main.tsx diff --git a/basic_contract_caller/frontend/src/vite-env.d.ts b/basic-contract-caller/frontend/src/vite-env.d.ts similarity index 100% rename from basic_contract_caller/frontend/src/vite-env.d.ts rename to basic-contract-caller/frontend/src/vite-env.d.ts diff --git a/basic_contract_caller/frontend/tailwind.config.js b/basic-contract-caller/frontend/tailwind.config.js similarity index 100% rename from basic_contract_caller/frontend/tailwind.config.js rename to basic-contract-caller/frontend/tailwind.config.js diff --git a/basic_contract_caller/frontend/tsconfig.json b/basic-contract-caller/frontend/tsconfig.json similarity index 100% rename from basic_contract_caller/frontend/tsconfig.json rename to basic-contract-caller/frontend/tsconfig.json diff --git a/basic_contract_caller/frontend/tsconfig.node.json b/basic-contract-caller/frontend/tsconfig.node.json similarity index 100% rename from basic_contract_caller/frontend/tsconfig.node.json rename to basic-contract-caller/frontend/tsconfig.node.json diff --git a/basic_contract_caller/frontend/vite.config.ts b/basic-contract-caller/frontend/vite.config.ts similarity index 100% rename from basic_contract_caller/frontend/vite.config.ts rename to basic-contract-caller/frontend/vite.config.ts From 6f132963df53ae208914b930487d263950a2ccc8 Mon Sep 17 00:00:00 2001 From: peetzweg/ Date: Thu, 9 Nov 2023 12:35:36 +0100 Subject: [PATCH 5/5] ignore frontend folder for building testing matrix --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 048db79e..81e5c479 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,6 +54,7 @@ jobs: multi-contract-caller/** upgradeable-contracts/** ui/** + **/frontend/** json: true - name: Look for changes in multi and upgradable contracts