├── client ├── public │ ├── _redirects │ ├── favicon.ico │ ├── img │ │ ├── logo.png │ │ ├── nft.avif │ │ ├── nft.jpeg │ │ ├── logo-black.png │ │ ├── floor.svg │ │ ├── Polygon.svg │ │ ├── Arb.svg │ │ └── Base.svg │ ├── robots.txt │ ├── manifest.json │ └── backgrounds │ │ └── background-circles.svg ├── README.md ├── .dockerignore ├── src │ ├── index.d.ts │ ├── App.tsx │ ├── theme.tsx │ ├── util │ │ └── index.ts │ ├── index.tsx │ ├── components │ │ ├── Navbar.tsx │ │ └── Footer.tsx │ └── pages │ │ └── Main.tsx ├── vercel.json ├── tsconfig.node.json ├── .gitignore ├── Dockerfile ├── vite.config.ts ├── tsconfig.json ├── package.json └── index.html ├── vm ├── bun.lockb ├── package.json ├── src │ ├── lexer.ts │ ├── parser.ts │ └── transpiler.ts ├── tsconfig.json ├── input.x ├── index.ts ├── utils │ └── index.ts ├── README.md ├── decode.ts └── .gitignore ├── rollup ├── bun.lockb ├── db.sqlite ├── deployment.json ├── genesis-state.json ├── README.md ├── utils.ts ├── package.json ├── tsconfig.json ├── stackr.config.ts ├── src │ ├── index.ts │ └── state.ts ├── .gitignore └── test │ └── test-requests.ts ├── .gitmodules ├── .gitignore └── README.md /client/public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 2 | -------------------------------------------------------------------------------- /vm/bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aa-labs/hIVM/HEAD/vm/bun.lockb -------------------------------------------------------------------------------- /rollup/bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aa-labs/hIVM/HEAD/rollup/bun.lockb -------------------------------------------------------------------------------- /rollup/db.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aa-labs/hIVM/HEAD/rollup/db.sqlite -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | #### Run locally 2 | 3 | ```bash 4 | yarn 5 | yarn run dev 6 | ``` 7 | -------------------------------------------------------------------------------- /rollup/deployment.json: -------------------------------------------------------------------------------- 1 | {"app_id":128,"app_inbox":"0xe95157e7f6b65ccf3d7a2176d1162825a1436593"} -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aa-labs/hIVM/HEAD/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aa-labs/hIVM/HEAD/client/public/img/logo.png -------------------------------------------------------------------------------- /client/public/img/nft.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aa-labs/hIVM/HEAD/client/public/img/nft.avif -------------------------------------------------------------------------------- /client/public/img/nft.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aa-labs/hIVM/HEAD/client/public/img/nft.jpeg -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /client/.dockerignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .dockerignore 3 | Dockerfile 4 | build 5 | node_modules 6 | README.md -------------------------------------------------------------------------------- /client/public/img/logo-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aa-labs/hIVM/HEAD/client/public/img/logo-black.png -------------------------------------------------------------------------------- /rollup/genesis-state.json: -------------------------------------------------------------------------------- 1 | { 2 | "state": { 3 | "byteCodes": [], 4 | "transactions": [] 5 | } 6 | } -------------------------------------------------------------------------------- /client/src/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'react-blockies' { 2 | const Blockies: any 3 | export default Blockies 4 | } -------------------------------------------------------------------------------- /client/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [ 3 | { 4 | "source": "/(.*)", 5 | "destination": "/" 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "practical-intents-solver"] 2 | path = practical-intents-solver 3 | url = git@github.com:ankurdubey521/practical-intents-solver.git 4 | -------------------------------------------------------------------------------- /client/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Main from "@/pages/Main"; 3 | 4 | const App = () => { 5 | return ( 6 | 7 |
8 | 9 | ); 10 | }; 11 | 12 | export default App; 13 | -------------------------------------------------------------------------------- /client/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "types": ["node"], 4 | "composite": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /rollup/README.md: -------------------------------------------------------------------------------- 1 | # counter 2 | 3 | To install dependencies: 4 | 5 | ```bash 6 | bun install 7 | ``` 8 | 9 | To run: 10 | 11 | ```bash 12 | bun run index.ts 13 | ``` 14 | 15 | This project was created using `bun init` in bun v1.0.4. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. 16 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /vm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "practical-compiler", 3 | "module": "index.ts", 4 | "type": "module", 5 | "devDependencies": { 6 | "bun-types": "latest" 7 | }, 8 | "scripts": { 9 | "start": "bun run index.ts" 10 | }, 11 | "peerDependencies": { 12 | "typescript": "^5.0.0" 13 | }, 14 | "dependencies": { 15 | "@stackr/stackr-js": "^0.1.5-alpha", 16 | "ethers": "5.7.2" 17 | } 18 | } -------------------------------------------------------------------------------- /vm/src/lexer.ts: -------------------------------------------------------------------------------- 1 | const lexer = (input: string): string[][] => { 2 | return input 3 | .split("\n") 4 | .map((line) => line.trim()) 5 | .filter((line) => line.length > 0 && !line.startsWith("//")) 6 | .reduce((acc: string[][], line: string) => { 7 | if (line.endsWith(":")) { 8 | acc.push([line]); 9 | } else if (acc.length > 0) { 10 | acc[acc.length - 1].push(line); 11 | } 12 | return acc; 13 | }, []); 14 | }; 15 | 16 | export { lexer }; 17 | -------------------------------------------------------------------------------- /client/Dockerfile: -------------------------------------------------------------------------------- 1 | 2 | FROM node:14 3 | 4 | # Set working directory 5 | WORKDIR /app 6 | 7 | # Copy our node module specification 8 | COPY package.json package.json 9 | COPY yarn.lock yarn.lock 10 | 11 | # install node modules and build assets 12 | RUN yarn install 13 | 14 | # Copy all files from current directory to working dir in image 15 | # Except the one defined in '.dockerignore' 16 | COPY . /app 17 | 18 | # Create production build of React App 19 | RUN yarn build 20 | EXPOSE 8080 21 | CMD yarn start -------------------------------------------------------------------------------- /rollup/utils.ts: -------------------------------------------------------------------------------- 1 | import { Domain, EIP712Types } from "@stackr/stackr-js"; 2 | import { ethers } from "ethers"; 3 | 4 | const getUserInput = async (types: EIP712Types, domain: Domain) => { 5 | const w = ethers.Wallet.createRandom(); 6 | 7 | const addr1 = ethers.hexlify(ethers.randomBytes(20)); 8 | 9 | const payload = { type: "increment" }; 10 | const signature = await w.signTypedData(domain, types, payload); 11 | 12 | return { 13 | data: { 14 | msgSender: w.address, 15 | payload, 16 | signature, 17 | }, 18 | }; 19 | }; 20 | -------------------------------------------------------------------------------- /rollup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "counter", 3 | "module": "index.ts", 4 | "type": "module", 5 | "devDependencies": { 6 | "bun-types": "latest" 7 | }, 8 | "peerDependencies": { 9 | "typescript": "^5.0.0" 10 | }, 11 | "dependencies": { 12 | "@stackr/stackr-js": "latest", 13 | "@types/cors": "^2.8.17", 14 | "@types/express": "^4.17.19", 15 | "body-parser": "^1.20.2", 16 | "cors": "^2.8.5", 17 | "ethers": "^6.7.1", 18 | "express": "^4.18.2", 19 | "sqlite": "^5.1.1", 20 | "sqlite3": "^5.1.6", 21 | "zod": "3.21.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "pi", 3 | "name": "pi", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "img/logo-cent.svg", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "img/logo-cent.svg", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } -------------------------------------------------------------------------------- /vm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ESNext"], 4 | "module": "esnext", 5 | "target": "esnext", 6 | "moduleResolution": "bundler", 7 | "moduleDetection": "force", 8 | "allowImportingTsExtensions": true, 9 | "noEmit": true, 10 | "composite": true, 11 | "strict": true, 12 | "downlevelIteration": true, 13 | "skipLibCheck": true, 14 | "jsx": "react-jsx", 15 | "allowSyntheticDefaultImports": true, 16 | "forceConsistentCasingInFileNames": true, 17 | "allowJs": true, 18 | "types": [ 19 | "bun-types" // add Bun global 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /client/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import path from "path"; 3 | import react from "@vitejs/plugin-react"; 4 | import tsconfigPaths from "vite-tsconfig-paths"; 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [react(), tsconfigPaths()], 9 | resolve: { 10 | alias: { 11 | find: "@", 12 | replacement: path.resolve(__dirname, "/src"), 13 | buffer: "buffer", 14 | }, 15 | extensions: [".js", ".ts"], 16 | }, 17 | optimizeDeps: { 18 | esbuildOptions: { 19 | define: { 20 | global: "globalThis", 21 | }, 22 | }, 23 | }, 24 | }); 25 | -------------------------------------------------------------------------------- /vm/input.x: -------------------------------------------------------------------------------- 1 | # practical-compiler 2 | 3 | USE: 4 | ADDR -> 0x0D125Df38bFd6eAA2478052ABB7d7E62d2CF604B 5 | 6 | // this will get the required funds from all the chains to dest chain 7 | CONSOLIDATE: 8 | CHAINS -> ARB, BASE 9 | DEST -> ARB 10 | VALUE -> 10 11 | 12 | // swap from all assets to dests 13 | SWAP: 14 | FROM -> ANY 15 | TO -> USDC 16 | VALUE -> 7000000 17 | CHAIN -> ARB 18 | 19 | // call a random address with a method 20 | CALL: 21 | ADDR -> 0x9CaeFEb398C3F2601Fb09E232f0a7eB37724b361 22 | DATA -> 0xa14481940000000000000000000000000d125df38bfd6eaa2478052abb7d7e62d2cf604b00000000000000000000000000000000000000000000000000000000004c4b40 23 | VALUE -> 0 24 | CHAIN -> ARB 25 | -------------------------------------------------------------------------------- /vm/index.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import { lexer } from "./src/lexer"; 3 | import { parser } from "./src/parser"; 4 | import { transpile } from "./src/transpiler"; 5 | 6 | const generateBytecode = (input: string): string => { 7 | const tokens = lexer(input); 8 | const parsed = parser(tokens); 9 | console.info("parsed tokens from lexer", parsed); 10 | return transpile(parsed); 11 | }; 12 | 13 | const main = (filePath: string): void => { 14 | fs.readFile(filePath, "utf8", (err: any, data: any) => { 15 | if (err) { 16 | console.error("Error reading the file:", err); 17 | return; 18 | } 19 | const bytecode = generateBytecode(data); 20 | console.log({ bytecode }); 21 | }); 22 | }; 23 | 24 | main("input.x"); 25 | -------------------------------------------------------------------------------- /client/public/img/floor.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /rollup/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ESNext"], 4 | "module": "esnext", 5 | "target": "esnext", 6 | "moduleResolution": "bundler", 7 | "moduleDetection": "force", 8 | "allowImportingTsExtensions": true, 9 | "noEmit": true, 10 | "composite": true, 11 | "strict": true, 12 | "downlevelIteration": true, 13 | "skipLibCheck": true, 14 | "jsx": "react-jsx", 15 | "allowSyntheticDefaultImports": true, 16 | "forceConsistentCasingInFileNames": true, 17 | "allowJs": true, 18 | "types": [ 19 | "bun-types" // add Bun global 20 | ] 21 | }, 22 | "include": [ 23 | "src/**/*", 24 | "test/**/*", 25 | "deployment.json", 26 | "stackr.config.ts", 27 | "genesis-state.json" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /vm/utils/index.ts: -------------------------------------------------------------------------------- 1 | import { hexlify } from "ethers/lib/utils"; 2 | 3 | export const encodeToHex = (bytecode: string): string => { 4 | let hexString = ""; 5 | for (let i = 0; i < bytecode.length; i++) { 6 | hexString += bytecode.charCodeAt(i).toString(16); 7 | } 8 | return hexString; 9 | }; 10 | 11 | export const decodeFromHex = (hexString: string): string => { 12 | let str = ""; 13 | for (let i = 0; i < hexString.length; i += 2) { 14 | str += String.fromCharCode(parseInt(hexString.substr(i, 2), 16)); 15 | } 16 | return str; 17 | }; 18 | 19 | export const toHex = (value: string | number): string => { 20 | if (typeof value === "number") { 21 | return hexlify(value).slice(0, 1); 22 | } else { 23 | return value.startsWith("0x") ? value : encodeToHex(value); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /vm/src/parser.ts: -------------------------------------------------------------------------------- 1 | interface ParsedToken { 2 | command: string; 3 | args: Record; 4 | } 5 | 6 | const parser = (tokens: string[][]): ParsedToken[] => { 7 | return tokens.map((block) => { 8 | const command = block[0].slice(0, -1); 9 | const args = block 10 | .slice(1) 11 | .reduce((acc: Record, line: string) => { 12 | const [key, value] = line.split(" -> ").map((item) => item.trim()); 13 | 14 | if (command === "CONSOLIDATE" && key === "CHAINS") { 15 | acc[key] = value.split(",").map((chain) => chain.trim()); 16 | } else { 17 | acc[key] = value; 18 | } 19 | 20 | return acc; 21 | }, {}); 22 | 23 | return { command, args }; 24 | }); 25 | }; 26 | 27 | export { parser }; 28 | -------------------------------------------------------------------------------- /vm/README.md: -------------------------------------------------------------------------------- 1 | ### practical-compiler 2 | 3 | ```bash 4 | bun install 5 | bun run index.ts 6 | ``` 7 | 8 | This is not compiler as such more like a transpiler 9 | Lexer -> tokens -> Parser -> AST -> Transpiler 10 | Lexer ->will read the file and tokenise with type and value 11 | for us will be simple, just read a line and split(" ") 12 | Parser / syntax analysis -> analyse the token structure 13 | Generate AST (tough part) 14 | Transpiler -> Use the AST to generate the output 15 | 16 | 17 | New changes -> 18 | We dont wanna read file, what we need 19 | - a method convert code to bytecode 20 | - then use the bbytecode to generate the logic 21 | 22 | For bytecode 23 | - define bytecode opcodes 24 | - compiler? method to convert code to bytecode (transpiler.ts) 25 | - interpreter/executor/vm? method to execute bytecode 26 | 27 | opcodes 28 | - CONSOLIDATE 29 | - SWAP 30 | - CALL 31 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "types": ["node"], 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": [ 7 | "src/*" 8 | ] 9 | }, 10 | "target": "ESNext", 11 | "useDefineForClassFields": true, 12 | "lib": [ 13 | "DOM", 14 | "DOM.Iterable", 15 | "ESNext" 16 | ], 17 | "allowJs": false, 18 | "skipLibCheck": true, 19 | "esModuleInterop": false, 20 | "allowSyntheticDefaultImports": true, 21 | "strict": true, 22 | "forceConsistentCasingInFileNames": true, 23 | "module": "ESNext", 24 | "moduleResolution": "Node", 25 | "resolveJsonModule": true, 26 | "isolatedModules": true, 27 | "noEmit": true, 28 | "jsx": "react-jsx" 29 | }, 30 | "include": [ 31 | "src" 32 | ], 33 | "references": [ 34 | { 35 | "path": "./tsconfig.node.json" 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /rollup/stackr.config.ts: -------------------------------------------------------------------------------- 1 | import { KeyPurpose, SignatureScheme, StackrConfig } from "@stackr/stackr-js"; 2 | 3 | // this file is generated by the deployment script 4 | import * as deployment from "./deployment.json"; 5 | 6 | const stackrConfig: StackrConfig = { 7 | stackrApp: { 8 | appId: deployment.app_id, 9 | appInbox: deployment.app_inbox, 10 | }, 11 | builder: { 12 | batchSize: 16, 13 | batchTime: 1000, 14 | }, 15 | syncer: { 16 | slotTime: 1000, 17 | vulcanRPC: "http://vulcan.stf.xyz", 18 | L1RPC: "http://rpc.stf.xyz", 19 | }, 20 | operator: { 21 | accounts: [ 22 | { 23 | privateKey: "c036423371f04df762d41da48e70072efd687496f6715ea2da6a668a6d34a9fa", 24 | purpose: KeyPurpose.BATCH, 25 | scheme: SignatureScheme.ECDSA, 26 | }, 27 | ], 28 | }, 29 | domain: { 30 | name: "Stackr MVP v0", 31 | version: "1", 32 | chainId: 69420, 33 | verifyingContract: deployment.app_inbox, 34 | salt: "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 35 | }, 36 | datastore: { 37 | filePath: "./datastore", 38 | }, 39 | }; 40 | 41 | export { stackrConfig }; 42 | -------------------------------------------------------------------------------- /client/src/theme.tsx: -------------------------------------------------------------------------------- 1 | import { createTheme } from "@mui/material/styles"; 2 | 3 | declare module "@mui/material/styles" { 4 | interface CustomTheme { 5 | } 6 | 7 | interface Theme extends CustomTheme {} 8 | interface ThemeOptions extends CustomTheme {} 9 | } 10 | 11 | const theme = createTheme({ 12 | components: { 13 | MuiTypography: { 14 | variants: [ 15 | { 16 | props: { variant: "h1" } /* component props */, 17 | style: { 18 | fontWeight: 400, 19 | fontSize: "2.5rem", 20 | lineHeight: "normal", 21 | letterSpacing: "normal", 22 | }, 23 | }, 24 | ], 25 | }, 26 | MuiAppBar: { 27 | styleOverrides: { 28 | colorPrimary: { 29 | backgroundColor: "rgb(255,254,246, 0.4)", 30 | boxShadow: "none", 31 | }, 32 | }, 33 | }, 34 | MuiContainer: { 35 | styleOverrides: { 36 | root: { 37 | maxWidth: "1400px !important", 38 | }, 39 | }, 40 | }, 41 | }, 42 | palette: { 43 | primary: { 44 | main: "#30475E", 45 | }, 46 | }, 47 | }); 48 | 49 | export default theme; 50 | -------------------------------------------------------------------------------- /client/public/img/Polygon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /client/src/util/index.ts: -------------------------------------------------------------------------------- 1 | import { toast } from "react-toastify"; 2 | 3 | export const truncateAddress = (address: string) => { 4 | return address.slice(0, 6) + "..." + address.slice(-4); 5 | }; 6 | 7 | export const showErrorMessage = (message: string) => { 8 | toast.error(message, { 9 | position: "top-right", 10 | autoClose: 5000, 11 | hideProgressBar: false, 12 | closeOnClick: false, 13 | pauseOnHover: true, 14 | draggable: true, 15 | progress: undefined, 16 | }); 17 | }; 18 | 19 | export const showInfoMessage = (message: string) => { 20 | toast.info(message, { 21 | position: "top-right", 22 | autoClose: 5000, 23 | hideProgressBar: false, 24 | closeOnClick: true, 25 | pauseOnHover: true, 26 | draggable: true, 27 | progress: undefined, 28 | }); 29 | }; 30 | 31 | export const showSuccessMessage = (message: string, txHash?: string) => { 32 | toast.success(message, { 33 | // onClick: () => { 34 | // window.open(`https://mumbai.polygonscan.com/tx/${txHash}`, "_blank"); 35 | // }, 36 | position: "top-right", 37 | autoClose: 5000, 38 | hideProgressBar: false, 39 | closeOnClick: false, 40 | pauseOnHover: true, 41 | draggable: true, 42 | progress: undefined, 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /vm/decode.ts: -------------------------------------------------------------------------------- 1 | const commandMap: Record = { 2 | "01": "USE", 3 | "02": "CONSOLIDATE", 4 | "03": "SWAP", 5 | "04": "CALL", 6 | }; 7 | 8 | const decodeHexString = (hexStr: string): string => { 9 | if (hexStr.length % 2 !== 0) { 10 | hexStr = "0" + hexStr; 11 | } 12 | let str = ""; 13 | for (let i = 0; i < hexStr.length; i += 2) { 14 | const charCode = parseInt(hexStr.substring(i, i + 2), 16); 15 | if (charCode >= 32 && charCode < 127) { 16 | str += String.fromCharCode(charCode); 17 | } else { 18 | return hexStr; 19 | } 20 | } 21 | return str; 22 | }; 23 | 24 | const executeBytecode = (hexBytecode: string): void => { 25 | hexBytecode = hexBytecode.startsWith("0x") 26 | ? hexBytecode.substring(2) 27 | : hexBytecode; 28 | const parts = hexBytecode.split("_"); 29 | const decodedArray: string[] = []; 30 | 31 | parts.forEach((part) => { 32 | if (commandMap[part]) { 33 | decodedArray.push(commandMap[part]); 34 | } else { 35 | const decodedPart = decodeHexString(part); 36 | decodedArray.push(decodedPart); 37 | } 38 | }); 39 | 40 | console.log("decoded array", decodedArray); 41 | }; 42 | 43 | executeBytecode( 44 | "0xabcd_01_3130_415242_42415345_7a6b45564d_415242_3_02_3130_55534443_414e59_03_415242_3130_ashcdkhcbdhk_1234_04" 45 | ); 46 | -------------------------------------------------------------------------------- /client/src/index.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from "react-dom/client"; 2 | import { ThemeProvider } from "@emotion/react"; 3 | import "react-toastify/dist/ReactToastify.css"; 4 | import "@rainbow-me/rainbowkit/styles.css"; 5 | import { getDefaultWallets, RainbowKitProvider } from "@rainbow-me/rainbowkit"; 6 | import { configureChains, createConfig, WagmiConfig } from "wagmi"; 7 | import { base } from "wagmi/chains"; 8 | import { publicProvider } from "wagmi/providers/public"; 9 | import theme from "./theme"; 10 | import App from "./App"; 11 | 12 | const { chains, publicClient } = configureChains([base], [publicProvider()]); 13 | const { connectors } = getDefaultWallets({ 14 | appName: "Practical Intent", 15 | projectId: "YOUR_PROJECT_ID", 16 | chains, 17 | }); 18 | const wagmiConfig = createConfig({ 19 | autoConnect: true, 20 | connectors, 21 | publicClient, 22 | }); 23 | 24 | const element = document.getElementById("root"); 25 | const root = createRoot(element!); 26 | 27 | const Index = () => { 28 | return ( 29 | 30 | 35 | 36 | 37 | 38 | 39 | 40 | ); 41 | }; 42 | 43 | root.render(); 44 | -------------------------------------------------------------------------------- /client/src/components/Navbar.tsx: -------------------------------------------------------------------------------- 1 | import { AppBar, Container } from "@mui/material"; 2 | import { makeStyles } from "@mui/styles"; 3 | import { ConnectButton } from "@rainbow-me/rainbowkit"; 4 | 5 | const Navbar = () => { 6 | const classes = useStyles(); 7 | 8 | return ( 9 | 10 | 11 |
12 | logo 13 | 14 |
15 |
16 |
17 | ); 18 | }; 19 | 20 | const useStyles = makeStyles(() => ({ 21 | container: { 22 | margin: "auto", 23 | padding: "0", 24 | "@media (max-width:1120px)": { 25 | padding: "0 20px", 26 | }, 27 | "@media (max-width:599px)": { 28 | padding: "0 15px", 29 | }, 30 | }, 31 | logo: { 32 | height: 50, 33 | marginRight: 10, 34 | userDrag: "none", 35 | "user-drag": "none", 36 | "-webkit-user-drag": "none", 37 | "user-select": "none", 38 | "-moz-user-select": "none", 39 | "-webkit-user-select": "none", 40 | "-ms-user-select": "none", 41 | }, 42 | nav: { 43 | height: "70px", 44 | padding: "0 30px", 45 | position: "relative", 46 | }, 47 | flexContainer: { 48 | display: "flex", 49 | justifyContent: "space-between", 50 | alignItems: "center", 51 | }, 52 | })); 53 | 54 | export default Navbar; 55 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "practical-intent", 3 | "version": "1.0.0", 4 | "private": true, 5 | "author": "@amanraj1608", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@covalenthq/client-sdk": "^0.6.7", 13 | "@emotion/react": "11.10.6", 14 | "@emotion/styled": "11.10.6", 15 | "@mui/icons-material": "5.11.11", 16 | "@mui/lab": "^5.0.0-alpha.123", 17 | "@mui/material": "5.11.12", 18 | "@mui/styles": "5.11.12", 19 | "@rainbow-me/rainbowkit": "1.2.0", 20 | "@types/node": "^20.5.7", 21 | "@types/uuid": "^9.0.7", 22 | "buffer": "^6.0.3", 23 | "cbor-x": "^1.5.4", 24 | "crypto-browserify": "^3.12.0", 25 | "ethers": "5.7.2", 26 | "merkletreejs": "^0.3.11", 27 | "process": "^0.11.10", 28 | "react": "18.2.0", 29 | "react-blockies": "^1.4.1", 30 | "react-dom": "18.2.0", 31 | "react-router-dom": "^5.3.4", 32 | "react-toastify": "^9.1.2", 33 | "viem": "1.18.3", 34 | "wagmi": "1.4.5" 35 | }, 36 | "browser": { 37 | "crypto": false 38 | }, 39 | "devDependencies": { 40 | "@types/node-forge": "^1.3.2", 41 | "@types/node-jose": "^1.1.10", 42 | "@types/react": "^18.0.28", 43 | "@types/react-dom": "^18.0.11", 44 | "@types/react-router-dom": "^5.3.3", 45 | "@vitejs/plugin-react": "3.1.0", 46 | "typescript": "5.0.2", 47 | "vite": "4.2.0", 48 | "vite-tsconfig-paths": "^4.0.7" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /vm/src/transpiler.ts: -------------------------------------------------------------------------------- 1 | import { hexlify } from "ethers/lib/utils"; 2 | 3 | interface ParsedToken { 4 | command: string; 5 | args: Record; 6 | } 7 | 8 | const OP_CODES: Record = { 9 | USE: 1, 10 | CONSOLIDATE: 2, 11 | SWAP: 3, 12 | CALL: 4, 13 | }; 14 | 15 | const toHexString = (num: number): string => { 16 | return hexlify(num).slice(2); 17 | }; 18 | 19 | const stringToHex = (str: string): string => { 20 | if (str.startsWith("0x")) { 21 | return str.slice(2); 22 | } 23 | 24 | let hex = ""; 25 | for (let i = 0; i < str.length; i++) { 26 | hex += str.charCodeAt(i).toString(16); 27 | } 28 | return hex; 29 | }; 30 | 31 | export const transpile = (parsedTokens: ParsedToken[]): string => { 32 | let bytecodeParts: string[] = []; 33 | 34 | for (const token of parsedTokens) { 35 | let argsPart: string[] = []; 36 | const argsEntries = Object.entries(token.args).reverse(); 37 | 38 | for (const [key, value] of argsEntries) { 39 | if (Array.isArray(value)) { 40 | for (let i = value.length - 1; i >= 0; i--) { 41 | argsPart.push(stringToHex(value[i])); 42 | } 43 | argsPart.push(value.length.toString()); 44 | } else { 45 | argsPart.push(stringToHex(value)); 46 | } 47 | } 48 | 49 | const opcode = toHexString(OP_CODES[token.command]); 50 | argsPart.push(opcode); 51 | 52 | bytecodeParts.push(argsPart.join("_")); 53 | } 54 | 55 | return "0x" + bytecodeParts.join("_"); 56 | }; 57 | -------------------------------------------------------------------------------- /client/public/img/Arb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Practical Intent 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 26 | 27 | 28 | 31 | 37 | 38 | 39 | 40 |
41 | 42 | 43 | 44 | 79 | 80 | -------------------------------------------------------------------------------- /client/src/components/Footer.tsx: -------------------------------------------------------------------------------- 1 | import { makeStyles } from "@mui/styles"; 2 | 3 | const Footer = () => { 4 | const classes = useStyles(); 5 | 6 | return ( 7 | 56 | ); 57 | }; 58 | 59 | const useStyles = makeStyles((theme) => ({ 60 | ...theme, 61 | footer: { 62 | position: "relative", 63 | borderTop: "2px solid #88AB8E", 64 | display: "block", 65 | padding: "20px 0 15px 0", 66 | background: "url(/img/floor.svg) center repeat", 67 | }, 68 | logo: { 69 | height: "60px", 70 | margin: "auto", 71 | marginBottom: "10px", 72 | }, 73 | text: { 74 | color: "#000", 75 | fontSize: "16px", 76 | fontWeight: 300, 77 | paddingBottom: 5, 78 | backgroundColor: "#AFC8AD", 79 | clipPath: "polygon(3% 0, 100% 0%, 97% 100%, 0% 100%)", 80 | padding: "5px 20px", 81 | }, 82 | })); 83 | 84 | export default Footer; 85 | -------------------------------------------------------------------------------- /rollup/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActionEvents, 3 | ActionSchema, 4 | BatcherEvents, 5 | BuilderEvents, 6 | FIFOStrategy, 7 | MicroRollup, 8 | } from "@stackr/stackr-js"; 9 | import bodyParser from "body-parser"; 10 | import express, { Request, Response } from "express"; 11 | import cors from "cors"; 12 | import { stackrConfig } from "../stackr.config"; 13 | import { ByteCodeRollup, byteCodeSTF } from "./state"; 14 | import { StateMachine } from "@stackr/stackr-js/execution"; 15 | 16 | // this file is generated by the deployment script 17 | import * as genesisState from "../genesis-state.json"; 18 | 19 | const rollup = async () => { 20 | const counterFsm = new StateMachine({ 21 | state: new ByteCodeRollup(genesisState.state), 22 | stf: byteCodeSTF, 23 | }); 24 | 25 | const actionSchemaType = { 26 | type: "String", 27 | id: "Uint", 28 | byteCode: "String", 29 | programCounter: "Uint", 30 | transactionData: { 31 | id: "Uint", 32 | type: "String", 33 | hashs: "String", 34 | }, 35 | }; 36 | 37 | const actionInput = new ActionSchema("update-state", actionSchemaType); 38 | 39 | const buildStrategy = new FIFOStrategy(); 40 | 41 | const { state, actions, events } = await MicroRollup({ 42 | config: stackrConfig, 43 | useState: counterFsm, 44 | useAction: actionInput, 45 | useBuilder: { strategy: buildStrategy, autorun: true }, 46 | useSyncer: { autorun: true }, 47 | }); 48 | 49 | events.action.onEvent(ActionEvents.SUBMIT_ACTION, (action) => { 50 | console.log("action submitted", action); 51 | }); 52 | 53 | events.batcher.onEvent(BatcherEvents.BATCH_ACTION, (batch) => { 54 | console.log("action batched", batch); 55 | }); 56 | 57 | events.builder.onEvent(BuilderEvents.ORDER_BATCH, (batch) => { 58 | console.log("action batch ordered", batch); 59 | }); 60 | 61 | return { state, actions }; 62 | }; 63 | 64 | const app = express(); 65 | app.use(bodyParser.json()); 66 | app.use(cors()); 67 | const { actions, state } = await rollup(); 68 | 69 | app.get("/", (req: Request, res: Response) => { 70 | res.send({ currentCount: state.get().state.getState() }); 71 | }); 72 | 73 | app.post("/", async (req: Request, res: Response) => { 74 | const schema = actions.getSchema("update-state"); 75 | 76 | if (!schema) { 77 | res.status(400).send({ message: "error" }); 78 | return; 79 | } 80 | 81 | try { 82 | const newAction = schema.newAction(req.body); 83 | const ack = await actions.submit(newAction); 84 | res.status(201).send({ ack }); 85 | } catch (e: any) { 86 | res.status(400).send({ error: e.message }); 87 | } 88 | }); 89 | 90 | app.listen(3000, () => { 91 | console.log("listening on port 3000"); 92 | }); 93 | 94 | // actionEventsEmitter.on(ActionEvents.SUBMIT_ACTION, (data) => { 95 | // console.log("submit_action - Event triggered : ", data.payload); 96 | // }); 97 | 98 | // executorEventsEmitter.on(ExecutorEvents.EXECUTE_SINGLE, (data) => { 99 | // console.log("execute_single - Event triggered : ", data); 100 | // }); 101 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | 15 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 16 | 17 | # Runtime data 18 | 19 | pids 20 | _.pid 21 | _.seed 22 | \*.pid.lock 23 | 24 | # Directory for instrumented libs generated by jscoverage/JSCover 25 | 26 | lib-cov 27 | 28 | # Coverage directory used by tools like istanbul 29 | 30 | coverage 31 | \*.lcov 32 | 33 | # nyc test coverage 34 | 35 | .nyc_output 36 | 37 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 38 | 39 | .grunt 40 | 41 | # Bower dependency directory (https://bower.io/) 42 | 43 | bower_components 44 | 45 | # node-waf configuration 46 | 47 | .lock-wscript 48 | 49 | # Compiled binary addons (https://nodejs.org/api/addons.html) 50 | 51 | build/Release 52 | 53 | # Dependency directories 54 | 55 | node_modules/ 56 | jspm_packages/ 57 | 58 | # Snowpack dependency directory (https://snowpack.dev/) 59 | 60 | web_modules/ 61 | 62 | # TypeScript cache 63 | 64 | \*.tsbuildinfo 65 | 66 | # Optional npm cache directory 67 | 68 | .npm 69 | 70 | # Optional eslint cache 71 | 72 | .eslintcache 73 | 74 | # Optional stylelint cache 75 | 76 | .stylelintcache 77 | 78 | # Microbundle cache 79 | 80 | .rpt2_cache/ 81 | .rts2_cache_cjs/ 82 | .rts2_cache_es/ 83 | .rts2_cache_umd/ 84 | 85 | # Optional REPL history 86 | 87 | .node_repl_history 88 | 89 | # Output of 'npm pack' 90 | 91 | \*.tgz 92 | 93 | # Yarn Integrity file 94 | 95 | .yarn-integrity 96 | 97 | # dotenv environment variable files 98 | 99 | .env 100 | .env.development.local 101 | .env.test.local 102 | .env.production.local 103 | .env.local 104 | 105 | # parcel-bundler cache (https://parceljs.org/) 106 | 107 | .cache 108 | .parcel-cache 109 | 110 | # Next.js build output 111 | 112 | .next 113 | out 114 | 115 | # Nuxt.js build / generate output 116 | 117 | .nuxt 118 | dist 119 | 120 | # Gatsby files 121 | 122 | .cache/ 123 | 124 | # Comment in the public line in if your project uses Gatsby and not Next.js 125 | 126 | # https://nextjs.org/blog/next-9-1#public-directory-support 127 | 128 | # public 129 | 130 | # vuepress build output 131 | 132 | .vuepress/dist 133 | 134 | # vuepress v2.x temp and cache directory 135 | 136 | .temp 137 | .cache 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.\* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | 177 | -------------------------------------------------------------------------------- /vm/.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | 15 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 16 | 17 | # Runtime data 18 | 19 | pids 20 | _.pid 21 | _.seed 22 | \*.pid.lock 23 | 24 | # Directory for instrumented libs generated by jscoverage/JSCover 25 | 26 | lib-cov 27 | 28 | # Coverage directory used by tools like istanbul 29 | 30 | coverage 31 | \*.lcov 32 | 33 | # nyc test coverage 34 | 35 | .nyc_output 36 | 37 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 38 | 39 | .grunt 40 | 41 | # Bower dependency directory (https://bower.io/) 42 | 43 | bower_components 44 | 45 | # node-waf configuration 46 | 47 | .lock-wscript 48 | 49 | # Compiled binary addons (https://nodejs.org/api/addons.html) 50 | 51 | build/Release 52 | 53 | # Dependency directories 54 | 55 | node_modules/ 56 | jspm_packages/ 57 | 58 | # Snowpack dependency directory (https://snowpack.dev/) 59 | 60 | web_modules/ 61 | 62 | # TypeScript cache 63 | 64 | \*.tsbuildinfo 65 | 66 | # Optional npm cache directory 67 | 68 | .npm 69 | 70 | # Optional eslint cache 71 | 72 | .eslintcache 73 | 74 | # Optional stylelint cache 75 | 76 | .stylelintcache 77 | 78 | # Microbundle cache 79 | 80 | .rpt2_cache/ 81 | .rts2_cache_cjs/ 82 | .rts2_cache_es/ 83 | .rts2_cache_umd/ 84 | 85 | # Optional REPL history 86 | 87 | .node_repl_history 88 | 89 | # Output of 'npm pack' 90 | 91 | \*.tgz 92 | 93 | # Yarn Integrity file 94 | 95 | .yarn-integrity 96 | 97 | # dotenv environment variable files 98 | 99 | .env 100 | .env.development.local 101 | .env.test.local 102 | .env.production.local 103 | .env.local 104 | 105 | # parcel-bundler cache (https://parceljs.org/) 106 | 107 | .cache 108 | .parcel-cache 109 | 110 | # Next.js build output 111 | 112 | .next 113 | out 114 | 115 | # Nuxt.js build / generate output 116 | 117 | .nuxt 118 | dist 119 | 120 | # Gatsby files 121 | 122 | .cache/ 123 | 124 | # Comment in the public line in if your project uses Gatsby and not Next.js 125 | 126 | # https://nextjs.org/blog/next-9-1#public-directory-support 127 | 128 | # public 129 | 130 | # vuepress build output 131 | 132 | .vuepress/dist 133 | 134 | # vuepress v2.x temp and cache directory 135 | 136 | .temp 137 | .cache 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.\* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | 177 | -------------------------------------------------------------------------------- /rollup/.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | 15 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 16 | 17 | # Runtime data 18 | 19 | pids 20 | _.pid 21 | _.seed 22 | \*.pid.lock 23 | 24 | # Directory for instrumented libs generated by jscoverage/JSCover 25 | 26 | lib-cov 27 | 28 | # Coverage directory used by tools like istanbul 29 | 30 | coverage 31 | \*.lcov 32 | 33 | # nyc test coverage 34 | 35 | .nyc_output 36 | 37 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 38 | 39 | .grunt 40 | 41 | # Bower dependency directory (https://bower.io/) 42 | 43 | bower_components 44 | 45 | # node-waf configuration 46 | 47 | .lock-wscript 48 | 49 | # Compiled binary addons (https://nodejs.org/api/addons.html) 50 | 51 | build/Release 52 | 53 | # Dependency directories 54 | 55 | node_modules/ 56 | jspm_packages/ 57 | 58 | # Snowpack dependency directory (https://snowpack.dev/) 59 | 60 | web_modules/ 61 | 62 | # TypeScript cache 63 | 64 | \*.tsbuildinfo 65 | 66 | # Optional npm cache directory 67 | 68 | .npm 69 | 70 | # Optional eslint cache 71 | 72 | .eslintcache 73 | 74 | # Optional stylelint cache 75 | 76 | .stylelintcache 77 | 78 | # Microbundle cache 79 | 80 | .rpt2_cache/ 81 | .rts2_cache_cjs/ 82 | .rts2_cache_es/ 83 | .rts2_cache_umd/ 84 | 85 | # Optional REPL history 86 | 87 | .node_repl_history 88 | 89 | # Output of 'npm pack' 90 | 91 | \*.tgz 92 | 93 | # Yarn Integrity file 94 | 95 | .yarn-integrity 96 | 97 | # dotenv environment variable files 98 | 99 | .env 100 | .env.development.local 101 | .env.test.local 102 | .env.production.local 103 | .env.local 104 | 105 | # parcel-bundler cache (https://parceljs.org/) 106 | 107 | .cache 108 | .parcel-cache 109 | 110 | # Next.js build output 111 | 112 | .next 113 | out 114 | 115 | # Nuxt.js build / generate output 116 | 117 | .nuxt 118 | dist 119 | 120 | # Gatsby files 121 | 122 | .cache/ 123 | 124 | # Comment in the public line in if your project uses Gatsby and not Next.js 125 | 126 | # https://nextjs.org/blog/next-9-1#public-directory-support 127 | 128 | # public 129 | 130 | # vuepress build output 131 | 132 | .vuepress/dist 133 | 134 | # vuepress v2.x temp and cache directory 135 | 136 | .temp 137 | .cache 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.\* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | 177 | datastore 178 | build -------------------------------------------------------------------------------- /rollup/test/test-requests.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | import { stackrConfig } from "../stackr.config"; 3 | import { ActionSchema } from "@stackr/stackr-js"; 4 | 5 | const actionInput = new ActionSchema("update-state", { 6 | type: "String", 7 | id: "Uint", 8 | byteCode: "String", 9 | programCounter: "Uint", 10 | transactionData: { 11 | id: "Uint", 12 | type: "String", 13 | hashs: "String", 14 | }, 15 | }); 16 | 17 | const getPayload = async (actionData: any) => { 18 | const wallet = new ethers.Wallet( 19 | stackrConfig.operator.accounts[0].privateKey 20 | ); 21 | // console.log("veryimp>", actionInput.EIP712TypedData.types); 22 | const sign = await wallet.signTypedData( 23 | stackrConfig.domain, 24 | actionInput.EIP712TypedData.types, 25 | actionData 26 | ); 27 | 28 | return JSON.stringify({ 29 | msgSender: wallet.address, 30 | signature: sign, 31 | payload: actionData, 32 | }); 33 | }; 34 | 35 | const addByteCode = async () => { 36 | const data = { 37 | type: "add", 38 | id: 5, // doesnt matter 39 | byteCode: 40 | "0x0D125Df38bFd6eAA2478052ABB7d7E62d2CF604B_01_313030_415242_42415345_415242_2_02_415242_3135303030303030_55534443_414e59_03_415242_30_a14481940000000000000000000000000d125df38bfd6eaa2478052abb7d7e62d2cf604b0000000000000000000000000000000000000000000000000000000000e4e1c0_9CaeFEb398C3F2601Fb09E232f0a7eB37724b361_04", 41 | programCounter: 0, // doesnt matter 42 | transactionData: { 43 | // doesnt matter 44 | id: 5, // doesnt matter 45 | type: "add", // doesnt matter 46 | hashs: "abc", // doesnt matter 47 | }, 48 | }; 49 | return getPayload(data); 50 | }; 51 | 52 | const addTransaction = async () => { 53 | const data = { 54 | type: "addTransaction", 55 | id: 5, 56 | byteCode: "your_byte_code_here", 57 | programCounter: 0, 58 | transactionData: { 59 | id: 4, 60 | type: "swap", 61 | hashs: "swap", 62 | }, 63 | }; 64 | return getPayload(data); 65 | }; 66 | 67 | const updateProgramCounter = async () => { 68 | const data = { 69 | type: "update", 70 | id: 1, 71 | byteCode: Math.ceil(Math.random() * 10000).toString(), 72 | programCounter: 0, 73 | transactionData: { 74 | id: 100, 75 | type: "add", 76 | hashs: "abc", 77 | }, 78 | }; 79 | return getPayload(data); 80 | }; 81 | 82 | const run = async (payload: string) => { 83 | const start = Date.now(); 84 | 85 | const res = await fetch("http://localhost:3000/", { 86 | method: "POST", 87 | body: payload, 88 | headers: { 89 | "Content-Type": "application/json", 90 | }, 91 | }); 92 | 93 | const end = Date.now(); 94 | 95 | const json = await res.json(); 96 | 97 | const elapsedSeconds = (end - start) / 1000; 98 | const requestsPerSecond = 1 / elapsedSeconds; 99 | 100 | console.log(`Requests per second: ${requestsPerSecond.toFixed(2)}`); 101 | console.log("response : ", json); 102 | }; 103 | 104 | function delay(ms: number) { 105 | return new Promise((resolve) => setTimeout(resolve, ms)); 106 | } 107 | 108 | for (let i = 0; i < 1; ++i) { 109 | // const addCode = await addByteCode(); 110 | // console.log(addCode); 111 | // await run(addCode); 112 | 113 | // await delay(2000); 114 | 115 | const updateCode = await updateProgramCounter(); 116 | await run(updateCode); 117 | 118 | // await delay(2000); 119 | 120 | // const addTransactions = await addTransaction(); 121 | // await run(addTransactions); 122 | } 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hIVM - Hybrid Intent Virtual Machine 2 | 3 | ![image](https://github.com/AmanRaj1608/hIVM/assets/16562513/737dde3b-33a0-4405-a791-d892b638dbb4) 4 | 5 | ## Overview 6 | hIVM (Hybrid Intents Virtual Machine) represents a significant leap forward in the field of intent-based programming. Bridging the gap between the expansive potential of generic networks and the precision of use-case-specific models, hIVM introduces a unique approach to decentralized application (DApp) development. This project aims to simplify the DApp development process while maintaining the adaptability and efficiency needed for sophisticated decentralized systems. 7 | 8 | ## Key Features 9 | - **Domain Specific Language (DSL)**: hIVM employs a custom-designed DSL that allows developers to express intents in a high-level, Turing-complete language. This DSL facilitates the creation of complex multi-flow DApps, enabling clear and concise programming of decentralized workflows. 10 | - **Stack-Based Virtual Machine**: The core of hIVM is a stack-based virtual machine architecture. It uses an assembler for converting high-level intents, specified in opcodes, into executable bytecode. 11 | - **Micro Rollup Integration**: The bytecode is uploaded to a micro rollup, which plays a crucial role in maintaining the execution state of DApps by tracking the program counter. This system allows for efficient and seamless execution management across various components of a DApp. 12 | - **Solver Ecosystem**: hIVM's architecture includes specialized solvers for primitive operations like SWAP, BRIDGE, and CALL. These solvers are responsible for executing specific parts of an intent, thereby abstracting complex implementation details from developers and optimizing the execution of these operations. 13 | - **Account Abstraction**: The platform extensively uses account abstraction, allowing users to delegate their funds to solvers. This enables seamless transaction execution and enhances the overall user experience. 14 | 15 | ## Benefits 16 | - **Improved Developer Experience**: Developers can focus on high-level, imperative flows without getting bogged down by the underlying complexities. hIVM's abstraction mechanisms significantly streamline the development process. 17 | - **Flexibility and Generality**: While developers define specific intents, the execution and optimization are managed by specialized solvers, allowing for flexible and general solutions to complex DApps. 18 | - **Efficient Problem Solving**: The solvers are designed to efficiently handle their respective operations, ensuring optimal problem-solving and transaction execution on the layer 1 network. 19 | 20 | # Getting Started 21 | [Instructions on installation, setup, and basic usage] 22 | 23 | ## Examples 24 | ```js 25 | // Define the counterfactual Smart Account address to be used on all chains. 26 | USE: 27 | ADDR -> 0x0D125Df38bFd6eAA2478052ABB7d7E62d2CF604B 28 | 29 | // Route funds such that ARB has >= 10$ worth of funds 30 | CONSOLIDATE: 31 | CHAINS -> ARB, BASE 32 | DEST -> ARB 33 | VALUE -> 10 34 | 35 | // Swap funds on ARB such that the wallet has >= 7 USDC 36 | SWAP: 37 | FROM -> ANY 38 | TO -> USDC 39 | VALUE -> 7000000 40 | CHAIN -> ARB 41 | 42 | // Mint an NFT on ARB by paying USDC 43 | CALL: 44 | ADDR -> 0x9CaeFEb398C3F2601Fb09E232f0a7eB37724b361 45 | DATA -> 0xa14481940000000000000000000000000d125df38bfd6eaa2478052abb7d7e62d2cf604b00000000000000000000000000000000000000000000000000000000004c4b40 46 | VALUE -> 0 47 | CHAIN -> ARB 48 | 49 | ``` 50 | 51 | ## Contributing 52 | We welcome contributions from the community! Please read our contributing guidelines to get started. 53 | -------------------------------------------------------------------------------- /rollup/src/state.ts: -------------------------------------------------------------------------------- 1 | import { RollupState, STF } from "@stackr/stackr-js/execution"; 2 | import { ethers, hexlify, toUtf8Bytes, keccak256 } from "ethers"; 3 | 4 | interface TransactionEntry { 5 | id: number; 6 | type: "consolidate" | "swap" | "call"; 7 | hashs: string; 8 | } 9 | interface ByteCodeEntry { 10 | id: number; 11 | byteCode: string; 12 | programCounter: number; 13 | } 14 | export type StateVariable = { 15 | byteCodes: ByteCodeEntry[]; 16 | transactions: TransactionEntry[]; 17 | }; 18 | 19 | interface StateTransport { 20 | state: StateVariable; 21 | } 22 | 23 | export interface ByteCodeActionInput { 24 | type: "add" | "update"; 25 | id: number; 26 | byteCode: string; 27 | programCounter: number; 28 | } 29 | 30 | export interface TransactionActionInput { 31 | type: "addTransaction" | "updateTransaction"; 32 | transactionData: { 33 | id: number; 34 | type: "consolidate" | "swap" | "call"; 35 | hashs: string; 36 | }; 37 | } 38 | 39 | export class ByteCodeRollup extends RollupState { 40 | constructor(byteCodes: StateVariable) { 41 | super(byteCodes); 42 | } 43 | 44 | createTransport(state: StateVariable): StateTransport { 45 | return { 46 | state: { 47 | byteCodes: state.byteCodes, 48 | transactions: state.transactions, 49 | }, 50 | }; 51 | } 52 | 53 | getState(): StateVariable { 54 | return this.transport.state; 55 | } 56 | 57 | calculateRoot(): ethers.BytesLike { 58 | const concatenatedByteCodes = (this.transport.state.byteCodes || []) 59 | .map((bc) => bc.byteCode) 60 | .join(""); 61 | 62 | const hexByteCodes = hexlify(toUtf8Bytes(concatenatedByteCodes)); 63 | 64 | return keccak256(hexByteCodes); 65 | } 66 | } 67 | 68 | export const byteCodeSTF: STF< 69 | ByteCodeRollup, 70 | ByteCodeActionInput | TransactionActionInput 71 | > = { 72 | identifier: "byteCodeSTF", 73 | 74 | apply( 75 | input: ByteCodeActionInput | TransactionActionInput, 76 | state: ByteCodeRollup 77 | ): void { 78 | let newState = state.getState(); 79 | if (newState.byteCodes === undefined) newState.byteCodes = []; 80 | if (newState.transactions === undefined) newState.transactions = []; 81 | console.log("imphere1", newState); 82 | if (input.type === "add" || input.type === "update") { 83 | console.log("imphere2", newState); 84 | switch (input.type) { 85 | case "add": 86 | if (input.byteCode) { 87 | newState.byteCodes.push({ 88 | id: newState.byteCodes.length + 1, 89 | byteCode: input.byteCode, 90 | programCounter: 0, 91 | }); 92 | } 93 | break; 94 | case "update": 95 | if (input.id && input.programCounter !== undefined) { 96 | const index = newState.byteCodes.findIndex( 97 | (bc) => bc.id === input.id 98 | ); 99 | if (index !== -1) { 100 | newState.byteCodes[index].programCounter = input.programCounter; 101 | } 102 | } 103 | break; 104 | default: 105 | throw new Error("Invalid action type for bytecode"); 106 | } 107 | state.transport.state.byteCodes = newState.byteCodes; 108 | } 109 | 110 | console.log("imphere", newState); 111 | if (input.type === "addTransaction" || input.type === "updateTransaction") { 112 | switch (input.type) { 113 | case "addTransaction": 114 | newState.transactions.push(input.transactionData); 115 | break; 116 | case "updateTransaction": 117 | // TODO: confirm with ankur if needed 118 | break; 119 | default: 120 | throw new Error("Invalid action type for transaction"); 121 | } 122 | state.transport.state.transactions = newState.transactions; 123 | } 124 | }, 125 | }; 126 | -------------------------------------------------------------------------------- /client/public/backgrounds/background-circles.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /client/src/pages/Main.tsx: -------------------------------------------------------------------------------- 1 | import { makeStyles } from "@mui/styles"; 2 | import { ToastContainer } from "react-toastify"; 3 | import { CovalentClient } from "@covalenthq/client-sdk"; 4 | // components 5 | import Navbar from "@/components/Navbar"; 6 | import Footer from "@/components/Footer"; 7 | import { useCallback, useEffect, useRef, useState } from "react"; 8 | import { ethers } from "ethers"; 9 | import { CircularProgress } from "@mui/material"; 10 | import { useSignMessage } from "wagmi"; 11 | import { showSuccessMessage } from "@/util"; 12 | 13 | const Main = () => { 14 | const classes = useStyles(); 15 | const { signMessageAsync, isLoading } = useSignMessage(); 16 | const [chains, setChains] = useState([ 17 | { 18 | name: "Arb", 19 | tokens: [] as any, 20 | imageUrl: "/img/Arb.svg", 21 | }, 22 | { 23 | name: "Polygon", 24 | tokens: [] as any, 25 | imageUrl: "/img/Polygon.svg", 26 | }, 27 | { 28 | name: "Base", 29 | tokens: [] as any, 30 | imageUrl: "/img/Base.svg", 31 | }, 32 | ]); 33 | const [doneTill, setDoneTill] = useState(0); 34 | const [pointerPosition, setPointerPosition] = useState(0); 35 | const [Loading, setLoading] = useState(false); 36 | const [bytecode, setBytecode] = useState( 37 | "0x0D125Df38bFd6eAA2478052ABB7d7E62d2CF604B_01_3130_415242_42415345_415242_2_02_415242_37303030303030_55534443_414e59_03_415242_30_a14481940000000000000000000000000d125df38bfd6eaa2478052abb7d7e62d2cf604b00000000000000000000000000000000000000000000000000000000004c4b40_9CaeFEb398C3F2601Fb09E232f0a7eB37724b361_04" 38 | ); 39 | const [transactionHashs, setTransactionHashs] = useState([]); 40 | 41 | const fetchData = useCallback(async () => { 42 | try { 43 | const client = new CovalentClient("ckey_7b58852d8d3a466ebb5306c717e"); 44 | const urls = [ 45 | client.BalanceService.getTokenBalancesForWalletAddress( 46 | "arbitrum-mainnet", 47 | "0x0D125Df38bFd6eAA2478052ABB7d7E62d2CF604B", 48 | { noSpam: true, noNftFetch: true } 49 | ), 50 | client.BalanceService.getTokenBalancesForWalletAddress( 51 | "polygon-zkevm-mainnet", 52 | "0x0D125Df38bFd6eAA2478052ABB7d7E62d2CF604B", 53 | { noSpam: true, noNftFetch: true } 54 | ), 55 | client.BalanceService.getTokenBalancesForWalletAddress( 56 | "base-mainnet", 57 | "0x0D125Df38bFd6eAA2478052ABB7d7E62d2CF604B", 58 | { noSpam: true, noNftFetch: true } 59 | ), 60 | ]; 61 | 62 | const responses = await Promise.all(urls); 63 | const data = await Promise.all( 64 | responses.map((response) => response.data) 65 | ); 66 | 67 | const updatedChains = chains.map((chain, index) => { 68 | const chainData = data[index]; 69 | 70 | return { 71 | ...chain, 72 | tokens: chainData.items.map((item) => { 73 | // Check if balance is not null, otherwise default to BigInt(0) 74 | const balanceBigInt = 75 | item.balance !== null ? BigInt(item.balance) : BigInt(0); 76 | const balanceInEth = 77 | balanceBigInt / BigInt(Math.pow(10, item.contract_decimals)); 78 | const formattedBalance = parseFloat( 79 | balanceInEth.toString() 80 | ).toFixed(2); 81 | 82 | return { 83 | name: item.contract_ticker_symbol, 84 | balance: formattedBalance, // Balance in ETH with up to 3 decimal places 85 | usdValue: item.pretty_quote, 86 | }; 87 | }), 88 | }; 89 | }); 90 | 91 | setChains(updatedChains); 92 | } catch (error) { 93 | console.error("Error fetching data:", error); 94 | } 95 | }, []); 96 | 97 | const fetchStatusFromRollup = useCallback(async () => { 98 | try { 99 | let rollupState = await fetch("http://localhost:3000/"); 100 | const json = await rollupState.json(); 101 | let pc = json.currentCount.byteCodes[0].programCounter + 1; 102 | // if ((pc = 1)) pc = 0; 103 | const pid = json.currentCount.byteCodes[0].id; 104 | 105 | const curByteCode = (json.currentCount.byteCodes[0].byteCode || "").split( 106 | "_" 107 | ); 108 | let length = 0; 109 | for (let i = 0; i < pc; ++i) { 110 | length += curByteCode[i].length + 1; 111 | } 112 | length -= 1; 113 | // console.log(pointer); 114 | // console.log(json.currentCount.byteCodes[0].byteCode.slice(0, length - 1)); 115 | setPointerPosition(length); 116 | console.log(length); 117 | 118 | // program counter logic 119 | if (pc >= 7) setDoneTill(2); 120 | if (pc >= 12) setDoneTill(3); 121 | if (pc >= 17) setDoneTill(4); 122 | 123 | // get tx data from rollup 124 | console.log(json.currentCount.transactions); 125 | const txArr = json.currentCount.transactions || []; 126 | console.log(txArr); 127 | setTransactionHashs(txArr); 128 | } catch (error) { 129 | console.error("Error fetching data:", error); 130 | } 131 | }, []); 132 | 133 | useEffect(() => { 134 | fetchStatusFromRollup(); 135 | fetchData(); 136 | 137 | const interval = setInterval(() => { 138 | fetchStatusFromRollup(); 139 | fetchData(); 140 | }, 2000); 141 | 142 | return () => clearInterval(interval); 143 | }, [fetchStatusFromRollup, fetchData]); 144 | 145 | const buyNft = async () => { 146 | setLoading(true); 147 | const data = { 148 | type: "add", // imp 149 | id: 1, 150 | byteCode: bytecode, // imp 151 | programCounter: 0, // imp 152 | transactionData: { 153 | id: 4, 154 | type: "swap", 155 | hashs: "swap", 156 | }, 157 | }; 158 | const message = ethers.utils.hexlify( 159 | ethers.utils.toUtf8Bytes("Your message here") 160 | ); 161 | const signature = await signMessageAsync({ message }); 162 | console.log(signature); 163 | 164 | const wallet = new ethers.Wallet( 165 | "c036423371f04df762d41da48e70072efd687496f6715ea2da6a668a6d34a9fa" 166 | ); 167 | const sign = await wallet._signTypedData( 168 | { 169 | name: "Stackr MVP v0", 170 | version: "1", 171 | chainId: 69420, 172 | verifyingContract: "0xe95157e7f6b65ccf3d7a2176d1162825a1436593", 173 | salt: "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 174 | }, 175 | { 176 | TransactionData: [ 177 | { 178 | name: "id", 179 | type: "uint256", 180 | }, 181 | { 182 | name: "type", 183 | type: "string", 184 | }, 185 | { 186 | name: "hashs", 187 | type: "string", 188 | }, 189 | ], 190 | "update-state": [ 191 | { 192 | name: "type", 193 | type: "string", 194 | }, 195 | { 196 | name: "id", 197 | type: "uint256", 198 | }, 199 | { 200 | name: "byteCode", 201 | type: "string", 202 | }, 203 | { 204 | name: "programCounter", 205 | type: "uint256", 206 | }, 207 | { 208 | name: "transactionData", 209 | type: "TransactionData", 210 | }, 211 | ], 212 | }, 213 | data 214 | ); 215 | 216 | const payload = JSON.stringify({ 217 | msgSender: wallet.address, 218 | signature: sign, 219 | payload: data, 220 | }); 221 | 222 | const res = await fetch("http://localhost:3000/", { 223 | method: "POST", 224 | body: payload, 225 | headers: { 226 | "Content-Type": "application/json", 227 | }, 228 | }); 229 | const json = await res.json(); 230 | 231 | await new Promise((resolve) => setTimeout(resolve, 2000)); 232 | setDoneTill(1); 233 | showSuccessMessage(json.ack._actionHash); 234 | setLoading(false); 235 | }; 236 | 237 | return ( 238 |
239 | 240 |
241 |
242 |
243 |
244 |
245 |
246 | NFT 251 |
252 | 258 |
259 | 260 |
261 |
262 | Intent_Bytecode: 263 |
264 |
265 | 266 | {bytecode.substring(0, pointerPosition + 1)} 267 | {/* {bytecode[pointerPosition]} */} 268 | {/*
272 | ↑ 273 |
*/} 274 |
275 | {bytecode.substring(pointerPosition + 1)} 276 |
277 |
278 |
279 | 280 |
281 | {chains.map((chain, chainIndex) => ( 282 |
283 |
284 | {`${chain.name} 289 | {chain.name} 290 |
291 |
292 |
293 | {chains.some((chain) => chain.tokens.length === 0) ? ( 294 |
Loading...
295 | ) : ( 296 | chain.tokens.map((token: any, tokenIndex: number) => ( 297 |
298 | {token.name} 299 | {/* 300 | {token.balance} 301 | */} 302 | 303 | {token.usdValue} 304 | 305 |
306 | )) 307 | )} 308 |
309 |
310 | ))} 311 |
312 |
313 |
314 |
    315 | {states.map((state, index) => ( 316 |
  • 321 |
    {state.title}
    322 |
    {state.description}
    323 |
  • 324 | ))} 325 | 326 |
    Transaction Hash
    327 |
    328 | {transactionHashs.map((txHashs) => { 329 | return txHashs.hashs 330 | .split(",") 331 | .map((txHash: string, index: number) => ( 332 |
    333 | -{" "} 334 | 335 | {txHash} 336 | 337 |
    338 | )); 339 | })} 340 |
    341 |
342 |
343 |
344 |
345 | 346 |
347 | ); 348 | }; 349 | 350 | const states = [ 351 | { 352 | title: "State 0: Intent Submission", 353 | description: 354 | "Your intent is submitted on the rollup. Solvers will start looking for transactions.", 355 | }, 356 | { 357 | title: "State 1: Consolidate Processing", 358 | description: 359 | "A solver picked up the consolidation transaction, gathering funds across various chains to a destination chain.", 360 | transactions: [], 361 | }, 362 | { 363 | title: "State 2: Swap Processing", 364 | description: 365 | "One solver processed your swaps, converting required asset to USDC.", 366 | }, 367 | // { 368 | // title: "State 3: Program counter updated", 369 | // description: 370 | // "After a solver picks and processes a transaction, updates are made on the rollup.", 371 | // }, 372 | { 373 | title: "State 3: NFT Purchase Execution", 374 | description: 375 | "This whole program is solved by the solver. It concludes with the successful purchase of an NFT or completion of a call operation.", 376 | }, 377 | ]; 378 | 379 | const useStyles = makeStyles(() => ({ 380 | bgCover: { 381 | fontFamily: "'Roboto', sans-serif", 382 | fontWeight: 500, 383 | backgroundColor: "#f6fefd", 384 | opacity: 0.9, 385 | background: "url(/img/background.svg) center 71px / auto repeat", 386 | // backgroundSize: "cover", 387 | }, 388 | btn: { 389 | margin: "30px auto 0 auto", 390 | background: "#88AB8E", 391 | cursor: "pointer", 392 | border: 0, 393 | outline: "none", 394 | borderRadius: 5, 395 | height: "36px", 396 | fontSize: 18, 397 | lineHeight: "36px", 398 | padding: "0 18px 0 18px", 399 | borderBottom: "1px solid #000", 400 | display: "flex", 401 | alignItems: "center", 402 | color: "white", 403 | width: "max-content", 404 | 405 | "@media (max-width:599px)": { 406 | padding: 0, 407 | }, 408 | 409 | "&:hover": { 410 | backgroundColor: "#6ba667", 411 | }, 412 | 413 | "& div": { 414 | "@media (max-width:599px)": { 415 | margin: 0, 416 | display: "none", 417 | }, 418 | }, 419 | }, 420 | bytecodeContainer: { 421 | textAlign: "center", 422 | margin: "20px 0", 423 | }, 424 | bytecode: { 425 | backgroundColor: "#f0f0f0", 426 | padding: "10px", 427 | borderRadius: "5px", 428 | margin: "auto", 429 | fontFamily: "monospace", 430 | fontSize: "0.9em", 431 | // height: 70, 432 | // overflowX: "auto", 433 | width: "100%", 434 | wordBreak: "break-all", 435 | }, 436 | programCounter: { 437 | margin: "10px 0", 438 | fontSize: "1.5em", 439 | position: "absolute", 440 | }, 441 | pointerIndicator: { 442 | color: "green", 443 | fontSize: "1em", 444 | fontWeight: "bold", 445 | position: "relative", 446 | }, 447 | market: { 448 | display: "flex", 449 | minHeight: "85vh", 450 | // margin: "0px auto", 451 | padding: "10px", 452 | }, 453 | leftSection: { 454 | flex: 0.65, 455 | display: "flex", 456 | flexDirection: "column", 457 | borderRight: "2px solid #282b4c", 458 | }, 459 | rightSection: { 460 | flex: 0.35, 461 | padding: 20, 462 | margin: "auto", 463 | }, 464 | upperLeft: { 465 | flex: 0.75, 466 | display: "flex", 467 | flexDirection: "column", 468 | borderBottom: "2px solid #282b4c", 469 | }, 470 | lowerLeft: { 471 | flex: 0.25, 472 | display: "flex", 473 | justifyContent: "space-around", 474 | alignItems: "center", 475 | padding: "10px", 476 | }, 477 | chainBox: { 478 | width: 250, 479 | height: "auto", 480 | minHeight: 150, 481 | border: "1px solid #ccc", 482 | borderRadius: "5px", 483 | padding: "10px", 484 | 485 | flexDirection: "column", 486 | justifyContent: "space-between", 487 | alignItems: "center", 488 | backgroundColor: "#f7f7f7", 489 | }, 490 | chainTitle: { 491 | fontWeight: "bold", 492 | marginBottom: 5, 493 | display: "flex", 494 | alignItems: "center", 495 | gap: "10px", 496 | }, 497 | 498 | chainLine: { 499 | width: "100%", 500 | height: "2px", 501 | backgroundColor: "#282b4c", 502 | marginBottom: "10px", 503 | }, 504 | chainBalance: { 505 | textAlign: "center", 506 | }, 507 | tokenItem: { 508 | display: "flex", 509 | justifyContent: "space-between", 510 | alignItems: "center", 511 | margin: "5px 0", 512 | }, 513 | tokenName: { 514 | fontWeight: "normal", 515 | fontSize: "0.9em", 516 | }, 517 | tokenDetails: { 518 | fontWeight: "normal", 519 | fontSize: "0.8em", 520 | }, 521 | frame2: { 522 | margin: "auto", 523 | }, 524 | // nft frame 525 | frame: { 526 | backgroundColor: "#ddc", 527 | border: "solid 1vmin #eee", 528 | borderBottomColor: "#fff", 529 | borderLeftColor: "#eee", 530 | borderRadius: "2px", 531 | borderRightColor: "#eee", 532 | borderTopColor: "#ddd", 533 | boxShadow: 534 | "0 0 2px 0 rgba(0,0,0,0.25) inset, 0 2px 4px 2px rgba(0,0,0,0.25)", 535 | boxSizing: "border-box", 536 | display: "inline-block", 537 | margin: "10px auto", 538 | // height: "calc(300px + 16vmin)", 539 | padding: "20px", 540 | position: "relative", 541 | textAlign: "center", 542 | }, 543 | nftImage: { 544 | width: 250, 545 | height: 250, 546 | border: "solid 2px", 547 | borderBottomColor: "#ffe", 548 | borderLeftColor: "#eed", 549 | borderRightColor: "#eed", 550 | borderTopColor: "#ccb", 551 | }, 552 | stateList: { 553 | listStyle: "none", 554 | padding: 0, 555 | "& li": { 556 | border: "1px solid #ccc", 557 | borderRadius: "5px", 558 | padding: "15px", 559 | marginBottom: "20px", 560 | backgroundColor: "#f7f7f7", 561 | position: "relative", 562 | "&:after": { 563 | content: '""', 564 | position: "absolute", 565 | left: "50%", 566 | transform: "translateX(-50%)", 567 | top: "100%", 568 | width: "2px", 569 | height: "20px", 570 | backgroundColor: "#ccc", 571 | }, 572 | "&.active": { 573 | backgroundColor: "#dff0d8", 574 | borderColor: "green", 575 | "&:after": { 576 | backgroundColor: "green", 577 | }, 578 | }, 579 | "&:last-child:after": { 580 | display: "none", 581 | }, 582 | }, 583 | "& .title": { 584 | fontWeight: "bold", 585 | marginBottom: "10px", 586 | }, 587 | "& .description": { 588 | fontSize: "0.9em", 589 | // lineHeight: "1.4", 590 | fontWeight: 400, 591 | }, 592 | }, 593 | txHashBox: { 594 | border: "1px solid #ccc", 595 | borderRadius: "5px", 596 | padding: "10px", 597 | fontSize: 14, 598 | marginTop: "10px", 599 | backgroundColor: "#f7f7f7", 600 | maxHeight: "200px", // Adjust as needed 601 | overflowY: "auto", // Allows scrolling if the content is too long 602 | }, 603 | txHash: { 604 | marginBottom: "10px", 605 | wordBreak: "break-all", // Ensures long hashes don't overflow 606 | }, 607 | txHashLink: { 608 | color: "#0645ad", // Link color, can be adjusted 609 | textDecoration: "none", 610 | }, 611 | lastListItem: { 612 | position: "relative", 613 | "&:after": { 614 | display: "none", 615 | }, 616 | }, 617 | })); 618 | 619 | export default Main; 620 | -------------------------------------------------------------------------------- /client/public/img/Base.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | --------------------------------------------------------------------------------