From d636ab5d1c5cbb08d9e233122825df36ef19de2d Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Wed, 25 Oct 2023 16:05:07 +0100 Subject: [PATCH 1/2] chore: refactor packages --- apps/sample-react-app/package.json | 6 +- apps/sample-react-app/src/App.tsx | 4 +- .../src/Components/AccountDetailBody.tsx | 2 +- .../src/Components/AccountDetailModal.tsx | 4 +- .../src/Components/ConnectWalletButton.tsx | 2 +- .../src/Components/ConnectWalletModal.tsx | 2 +- .../src/Components/WalletSourceRadio.tsx | 4 +- .../src/Components/layout/NavBar.tsx | 2 +- .../src/Constants/Constants.ts | 2 +- apps/sample-react-app/src/Hooks/useCounter.ts | 2 +- .../src/Screens/components/Counter.tsx | 2 +- apps/sample-react-app/src/index.tsx | 2 + package.json | 2 +- packages/eslint-config-custom/react.js | 1 + .../.eslintrc.js | 0 .../README.md | 0 .../package.json | 7 +- .../src/AccountReducer.ts | 3 +- .../src/ConnexProvider.tsx | 14 ++- .../src/index.tsx | 0 .../src/types.ts | 21 +--- .../tsconfig.json | 0 packages/wallet-connect/package.json | 2 +- packages/wallet-connect/tsconfig.json | 2 +- packages/wallet-kit/.eslintrc.js | 3 + packages/wallet-kit/README.md | 1 + packages/wallet-kit/package.json | 26 +++++ packages/wallet-kit/src/connex.ts | 67 +++++++++++ packages/wallet-kit/src/genesis.ts | 17 +++ packages/wallet-kit/src/index.ts | 2 + packages/wallet-kit/src/signer.ts | 79 +++++++++++++ packages/wallet-kit/src/thor-driver.ts | 27 +++++ packages/wallet-kit/src/types.d.ts | 12 ++ packages/wallet-kit/src/vendor-driver.ts | 22 ++++ packages/wallet-kit/src/wallet.ts | 31 ++++++ packages/wallet-kit/tsconfig.json | 5 + pnpm-lock.yaml | 105 ++++++++++++------ 37 files changed, 403 insertions(+), 80 deletions(-) rename packages/{react-vendor => react-wallet-kit}/.eslintrc.js (100%) rename packages/{react-vendor => react-wallet-kit}/README.md (100%) rename packages/{react-vendor => react-wallet-kit}/package.json (83%) rename packages/{react-vendor => react-wallet-kit}/src/AccountReducer.ts (92%) rename packages/{react-vendor => react-wallet-kit}/src/ConnexProvider.tsx (95%) rename packages/{react-vendor => react-wallet-kit}/src/index.tsx (100%) rename packages/{react-vendor => react-wallet-kit}/src/types.ts (81%) rename packages/{react-vendor => react-wallet-kit}/tsconfig.json (100%) create mode 100644 packages/wallet-kit/.eslintrc.js create mode 100644 packages/wallet-kit/README.md create mode 100644 packages/wallet-kit/package.json create mode 100644 packages/wallet-kit/src/connex.ts create mode 100644 packages/wallet-kit/src/genesis.ts create mode 100644 packages/wallet-kit/src/index.ts create mode 100644 packages/wallet-kit/src/signer.ts create mode 100644 packages/wallet-kit/src/thor-driver.ts create mode 100644 packages/wallet-kit/src/types.d.ts create mode 100644 packages/wallet-kit/src/vendor-driver.ts create mode 100644 packages/wallet-kit/src/wallet.ts create mode 100644 packages/wallet-kit/tsconfig.json diff --git a/apps/sample-react-app/package.json b/apps/sample-react-app/package.json index 87a369b0..bba1c11c 100644 --- a/apps/sample-react-app/package.json +++ b/apps/sample-react-app/package.json @@ -19,6 +19,9 @@ "@heroicons/react": "^2.0.18", "@vechain/connex": "2.1.0", "@vechain/picasso": "^2.1.1", + "@vechain/react-wallet-kit": "workspace:*", + "@vechain/wallet-connect": "workspace:*", + "@vechain/wallet-kit": "workspace:*", "buffer": "^6.0.3", "crypto-browserify": "^3.12.0", "https-browserify": "^1.0.0", @@ -28,11 +31,10 @@ "react-dom": "^18.2.0", "react-router-dom": "^6.4.2", "react-scripts": "5.0.1", - "react-vendor": "workspace:*", "stream-browserify": "^3.0.0", "stream-http": "^3.2.0", "thor-devkit": "^2.0.9", - "wallet-connect": "workspace:*", + "url": "^0.11.3", "web-vitals": "^2.1.2" }, "devDependencies": { diff --git a/apps/sample-react-app/src/App.tsx b/apps/sample-react-app/src/App.tsx index dd8ca265..75b7a5dd 100644 --- a/apps/sample-react-app/src/App.tsx +++ b/apps/sample-react-app/src/App.tsx @@ -1,8 +1,8 @@ import type { JSX } from "react"; import React from "react"; import type { Options } from "@vechain/connex"; -import type { WalletConnectOptions } from "wallet-connect"; -import { ConnexProvider } from "react-vendor"; +import type { WalletConnectOptions } from "@vechain/wallet-connect"; +import { ConnexProvider } from "@vechain/react-wallet-kit"; import { BrowserRouter, Route, Routes } from "react-router-dom"; import { ChakraProvider } from "@chakra-ui/react"; import { NavBar, StyledContainer } from "./Components/layout"; diff --git a/apps/sample-react-app/src/Components/AccountDetailBody.tsx b/apps/sample-react-app/src/Components/AccountDetailBody.tsx index 5a499602..d6611350 100644 --- a/apps/sample-react-app/src/Components/AccountDetailBody.tsx +++ b/apps/sample-react-app/src/Components/AccountDetailBody.tsx @@ -1,6 +1,6 @@ import { Button, HStack, Image, Text, VStack } from "@chakra-ui/react"; import React, { useMemo } from "react"; -import type { WalletSource } from "react-vendor"; +import type { WalletSource } from "@vechain/wallet-kit"; import { WalletSources } from "../Constants"; import { AddressButton } from "./AddressButton"; diff --git a/apps/sample-react-app/src/Components/AccountDetailModal.tsx b/apps/sample-react-app/src/Components/AccountDetailModal.tsx index 2e6fe428..464da6da 100644 --- a/apps/sample-react-app/src/Components/AccountDetailModal.tsx +++ b/apps/sample-react-app/src/Components/AccountDetailModal.tsx @@ -1,6 +1,6 @@ import { HStack, Text } from "@chakra-ui/react"; -import type { WalletSource } from "react-vendor"; -import { useWallet } from "react-vendor"; +import type { WalletSource } from "@vechain/wallet-kit"; +import { useWallet } from "@vechain/react-wallet-kit"; import React, { useCallback } from "react"; import { getPicassoImgSrc } from "../Utils/AccountUtils"; import { Dialog } from "./shared"; diff --git a/apps/sample-react-app/src/Components/ConnectWalletButton.tsx b/apps/sample-react-app/src/Components/ConnectWalletButton.tsx index 7ee62dc7..8115e6e4 100644 --- a/apps/sample-react-app/src/Components/ConnectWalletButton.tsx +++ b/apps/sample-react-app/src/Components/ConnectWalletButton.tsx @@ -2,7 +2,7 @@ import type { HTMLChakraProps } from "@chakra-ui/react"; import { Button, Icon, useDisclosure } from "@chakra-ui/react"; import { WalletIcon } from "@heroicons/react/24/solid"; import React from "react"; -import { useWallet } from "react-vendor"; +import { useWallet } from "@vechain/react-wallet-kit"; import { AccountDetailModal } from "./AccountDetailModal"; import { AddressButton } from "./AddressButton"; import { ConnectWalletModal } from "./ConnectWalletModal"; diff --git a/apps/sample-react-app/src/Components/ConnectWalletModal.tsx b/apps/sample-react-app/src/Components/ConnectWalletModal.tsx index f6e80802..fee3371b 100644 --- a/apps/sample-react-app/src/Components/ConnectWalletModal.tsx +++ b/apps/sample-react-app/src/Components/ConnectWalletModal.tsx @@ -14,7 +14,7 @@ import { import { LinkIcon, WalletIcon } from "@heroicons/react/24/solid"; import React, { useCallback, useState } from "react"; import { Certificate } from "thor-devkit"; -import { useConnex, useWallet } from "react-vendor"; +import { useConnex, useWallet } from "@vechain/react-wallet-kit"; import { Dialog } from "./shared"; import { WalletSourceRadio } from "./WalletSourceRadio"; diff --git a/apps/sample-react-app/src/Components/WalletSourceRadio.tsx b/apps/sample-react-app/src/Components/WalletSourceRadio.tsx index 3091c5e6..b7c9550f 100644 --- a/apps/sample-react-app/src/Components/WalletSourceRadio.tsx +++ b/apps/sample-react-app/src/Components/WalletSourceRadio.tsx @@ -10,8 +10,8 @@ import { } from "@chakra-ui/react"; import { ExclamationTriangleIcon } from "@heroicons/react/24/solid"; import React, { useCallback } from "react"; -import type { WalletSource } from "react-vendor"; -import { useWallet } from "react-vendor"; +import type { WalletSource } from "@vechain/wallet-kit"; +import { useWallet } from "@vechain/react-wallet-kit"; import { WalletSources } from "../Constants"; import { RadioCard } from "./shared"; diff --git a/apps/sample-react-app/src/Components/layout/NavBar.tsx b/apps/sample-react-app/src/Components/layout/NavBar.tsx index ca1c9497..bf14b534 100644 --- a/apps/sample-react-app/src/Components/layout/NavBar.tsx +++ b/apps/sample-react-app/src/Components/layout/NavBar.tsx @@ -17,7 +17,7 @@ import { import type { JSX } from "react"; import React from "react"; import { Bars3Icon } from "@heroicons/react/24/solid"; -import { useWallet } from "react-vendor"; +import { useWallet } from "@vechain/react-wallet-kit"; import { VechainLogo } from "../../Logos"; import { AccountDetailBody } from "../AccountDetailBody"; import { ConnectWalletButton } from "../ConnectWalletButton"; diff --git a/apps/sample-react-app/src/Constants/Constants.ts b/apps/sample-react-app/src/Constants/Constants.ts index 0ed62d94..0a178d49 100644 --- a/apps/sample-react-app/src/Constants/Constants.ts +++ b/apps/sample-react-app/src/Constants/Constants.ts @@ -1,4 +1,4 @@ -import { WalletSource } from "react-vendor"; +import { WalletSource } from "@vechain/wallet-kit"; export const NODE_URL = "https://testnet.vechain.org/"; export const NODE_NETWORK = "test"; diff --git a/apps/sample-react-app/src/Hooks/useCounter.ts b/apps/sample-react-app/src/Hooks/useCounter.ts index 0e4d6bf5..8bfe0d73 100644 --- a/apps/sample-react-app/src/Hooks/useCounter.ts +++ b/apps/sample-react-app/src/Hooks/useCounter.ts @@ -1,5 +1,5 @@ import { useCallback, useEffect, useMemo, useState } from "react"; -import { useConnex } from "react-vendor"; +import { useConnex } from "@vechain/react-wallet-kit"; import type { abi } from "thor-devkit"; const _counter: abi.Function.Definition = { diff --git a/apps/sample-react-app/src/Screens/components/Counter.tsx b/apps/sample-react-app/src/Screens/components/Counter.tsx index 3d91206b..a3a83969 100644 --- a/apps/sample-react-app/src/Screens/components/Counter.tsx +++ b/apps/sample-react-app/src/Screens/components/Counter.tsx @@ -12,7 +12,7 @@ import { import type { JSX } from "react"; import React, { useCallback, useMemo } from "react"; import { ArrowUpIcon } from "@heroicons/react/24/solid"; -import { useWallet } from "react-vendor"; +import { useWallet } from "@vechain/react-wallet-kit"; import { StyledCard } from "../../Components/shared"; import { useCounter } from "../../Hooks/useCounter"; import { AddressButton } from "../../Components"; diff --git a/apps/sample-react-app/src/index.tsx b/apps/sample-react-app/src/index.tsx index afcbbaa4..62cac8d1 100644 --- a/apps/sample-react-app/src/index.tsx +++ b/apps/sample-react-app/src/index.tsx @@ -4,6 +4,8 @@ import { App } from "./App"; import reportWebVitals from "./reportWebVitals"; import "./Styles/index.css"; +document.createElement("vechain-wallet-modal"); + const rootElement = document.getElementById("root"); if (rootElement) { diff --git a/package.json b/package.json index 820f18bc..cb462c0b 100755 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "private": true, "scripts": { "clean": "turbo run clean; rm -rf node_modules .turbo", - "build:deps": "turbo build --no-daemon --filter=react-vendor --filter=wallet-connect", + "build:deps": "turbo build --no-daemon --filter='@vechain/**'", "install:all": "pnpm i && pnpm run build:deps", "reinstall": "pnpm clean && pnpm i && pnpm run build:deps", "dev": "turbo run dev --no-daemon", diff --git a/packages/eslint-config-custom/react.js b/packages/eslint-config-custom/react.js index b1fd2ee7..b8dfb5b2 100644 --- a/packages/eslint-config-custom/react.js +++ b/packages/eslint-config-custom/react.js @@ -20,6 +20,7 @@ module.exports = { parserOptions: { project, }, + parser: "@typescript-eslint/parser", globals: { JSX: true, }, diff --git a/packages/react-vendor/.eslintrc.js b/packages/react-wallet-kit/.eslintrc.js similarity index 100% rename from packages/react-vendor/.eslintrc.js rename to packages/react-wallet-kit/.eslintrc.js diff --git a/packages/react-vendor/README.md b/packages/react-wallet-kit/README.md similarity index 100% rename from packages/react-vendor/README.md rename to packages/react-wallet-kit/README.md diff --git a/packages/react-vendor/package.json b/packages/react-wallet-kit/package.json similarity index 83% rename from packages/react-vendor/package.json rename to packages/react-wallet-kit/package.json index 24adaba1..9337b8c3 100644 --- a/packages/react-vendor/package.json +++ b/packages/react-wallet-kit/package.json @@ -1,5 +1,5 @@ { - "name": "react-vendor", + "name": "@vechain/react-wallet-kit", "version": "0.0.0", "private": true, "license": "MIT", @@ -15,8 +15,9 @@ "dependencies": { "@vechain/connex": "2.1.0", "@vechain/connex-framework": "2.1.0", - "thor-devkit": "^2.0.9", - "wallet-connect": "workspace:*" + "@vechain/wallet-connect": "workspace:*", + "@vechain/wallet-kit": "workspace:*", + "thor-devkit": "^2.0.9" }, "devDependencies": { "@types/react": "^18.2.28", diff --git a/packages/react-vendor/src/AccountReducer.ts b/packages/react-wallet-kit/src/AccountReducer.ts similarity index 92% rename from packages/react-vendor/src/AccountReducer.ts rename to packages/react-wallet-kit/src/AccountReducer.ts index 4190931f..b6ad8615 100644 --- a/packages/react-vendor/src/AccountReducer.ts +++ b/packages/react-wallet-kit/src/AccountReducer.ts @@ -1,4 +1,5 @@ -import type { AccountState, WalletSource } from "./types"; +import type { WalletSource } from "@vechain/wallet-kit"; +import type { AccountState } from "./types"; const ACCOUNT_KEY = "sample-app@account"; const WALLET_SOURCE_KEY = "sample-app@wallet-source"; diff --git a/packages/react-vendor/src/ConnexProvider.tsx b/packages/react-wallet-kit/src/ConnexProvider.tsx similarity index 95% rename from packages/react-vendor/src/ConnexProvider.tsx rename to packages/react-wallet-kit/src/ConnexProvider.tsx index 087fe0f2..55f238e0 100644 --- a/packages/react-vendor/src/ConnexProvider.tsx +++ b/packages/react-wallet-kit/src/ConnexProvider.tsx @@ -9,8 +9,13 @@ import React, { } from "react"; import { Connex } from "@vechain/connex"; import { newVendor } from "@vechain/connex-framework"; -import type { WalletConnectOptions, WCSigner } from "wallet-connect"; -import { newWcClient, newWcSigner, newWeb3Modal } from "wallet-connect"; +import type { WalletConnectOptions, WCSigner } from "@vechain/wallet-connect"; +import { + newWcClient, + newWcSigner, + newWeb3Modal, +} from "@vechain/wallet-connect"; +import { WalletSource } from "@vechain/wallet-kit"; import { accountReducer, defaultAccountState } from "./AccountReducer"; import type { ConnexContext, @@ -18,7 +23,6 @@ import type { SetAccount, SetSource, } from "./types"; -import { WalletSource } from "./types"; /** * Context @@ -160,9 +164,7 @@ export const ConnexProvider: React.FC = ({ } if (source === WalletSource.VeWorldExtension && window.vechain) { - const extensionSigner: Connex.Signer = window.vechain.newConnexSigner( - thor.genesis.id - ); + const extensionSigner = window.vechain.newConnexSigner(thor.genesis.id); return newVendor(extensionSigner); } diff --git a/packages/react-vendor/src/index.tsx b/packages/react-wallet-kit/src/index.tsx similarity index 100% rename from packages/react-vendor/src/index.tsx rename to packages/react-wallet-kit/src/index.tsx diff --git a/packages/react-vendor/src/types.ts b/packages/react-wallet-kit/src/types.ts similarity index 81% rename from packages/react-vendor/src/types.ts rename to packages/react-wallet-kit/src/types.ts index c44c852e..5d81496d 100644 --- a/packages/react-vendor/src/types.ts +++ b/packages/react-wallet-kit/src/types.ts @@ -1,30 +1,13 @@ import type { Options } from "@vechain/connex"; import type React from "react"; -import type { WalletConnectOptions } from "wallet-connect"; +import type { WalletConnectOptions } from "@vechain/wallet-connect"; +import type { WalletSource } from "@vechain/wallet-kit"; export interface AccountState { address: string | null; source: WalletSource | null; } -declare global { - interface Window { - vechain?: { - newConnexSigner: (genesisId: string) => Connex.Signer; - }; - } -} - -/** - * The wallet source - */ -export enum WalletSource { - WalletConnect = "wallet-connect", - VeWorldExtension = "veworld-extension", - Sync2 = "sync2", - Sync = "sync", -} - /** * Set the wallet account * @param account - account address diff --git a/packages/react-vendor/tsconfig.json b/packages/react-wallet-kit/tsconfig.json similarity index 100% rename from packages/react-vendor/tsconfig.json rename to packages/react-wallet-kit/tsconfig.json diff --git a/packages/wallet-connect/package.json b/packages/wallet-connect/package.json index 397e7588..e7b6c5cf 100644 --- a/packages/wallet-connect/package.json +++ b/packages/wallet-connect/package.json @@ -1,5 +1,5 @@ { - "name": "wallet-connect", + "name": "@vechain/wallet-connect", "version": "0.0.0", "private": true, "license": "MIT", diff --git a/packages/wallet-connect/tsconfig.json b/packages/wallet-connect/tsconfig.json index ad010d9a..127dc568 100644 --- a/packages/wallet-connect/tsconfig.json +++ b/packages/wallet-connect/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "tsconfig/react-library.json", + "extends": "tsconfig/base.json", "include": ["."], "exclude": ["dist", "node_modules"] } diff --git a/packages/wallet-kit/.eslintrc.js b/packages/wallet-kit/.eslintrc.js new file mode 100644 index 00000000..f8329c28 --- /dev/null +++ b/packages/wallet-kit/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ["custom/library"], +}; diff --git a/packages/wallet-kit/README.md b/packages/wallet-kit/README.md new file mode 100644 index 00000000..687a3faf --- /dev/null +++ b/packages/wallet-kit/README.md @@ -0,0 +1 @@ +# `wallet-helpers` diff --git a/packages/wallet-kit/package.json b/packages/wallet-kit/package.json new file mode 100644 index 00000000..d69b49c7 --- /dev/null +++ b/packages/wallet-kit/package.json @@ -0,0 +1,26 @@ +{ + "name": "@vechain/wallet-kit", + "version": "0.0.0", + "private": true, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "build": "tsup src/index.ts --format cjs --dts", + "clean": "rm -rf dist node_modules .turbo", + "dev": "tsup src/index.ts --format cjs --watch --dts", + "lint": "eslint src --ext .js,.jsx,.ts,.tsx" + }, + "dependencies": { + "@vechain/connex": "2.1.0", + "@vechain/connex-framework": "2.1.0", + "@vechain/connex-driver": "2.1.0", + "@vechain/wallet-connect": "workspace:*" + }, + "devDependencies": { + "eslint-config-custom": "workspace:*", + "tsconfig": "workspace:*", + "eslint": "^8.4.1", + "tsup": "^5.10.1", + "typescript": "4.9.5" + } +} diff --git a/packages/wallet-kit/src/connex.ts b/packages/wallet-kit/src/connex.ts new file mode 100644 index 00000000..3b60ba94 --- /dev/null +++ b/packages/wallet-kit/src/connex.ts @@ -0,0 +1,67 @@ +import { Framework } from "@vechain/connex-framework"; +import type { WalletConnectOptions } from "@vechain/wallet-connect"; +import type { Genesis } from "./types"; +import { WalletSource } from "./wallet"; +import { createSigner } from "./signer"; +import { normalizeGenesisBlock } from "./genesis"; +import { createVendorDriver } from "./vendor-driver"; +import { createDriverNoVendor } from "./thor-driver"; + +interface BaseConnexOptions { + nodeUrl: string; + genesis: Genesis; +} + +interface NoWalletConfigOptions extends BaseConnexOptions { + source: + | WalletSource.VeWorldExtension + | WalletSource.Sync + | WalletSource.Sync2; +} + +interface WalletConnectConfigOptions extends BaseConnexOptions { + source: WalletSource.WalletConnect; + options: WalletConnectOptions; + onDisconnected: () => void; +} + +type ConnexOptions = NoWalletConfigOptions | WalletConnectConfigOptions; + +const createConnexInstance = (options: ConnexOptions): Connex => { + const { source, genesis } = options; + + const genesisBlock = normalizeGenesisBlock(genesis); + + let signer: Promise; + + if (source === WalletSource.WalletConnect) { + signer = createSigner({ + source: options.source, + genesis: options.genesis, + options: options.options, + onDisconnected: options.onDisconnected, + }); + } else { + signer = createSigner({ + source: options.source, + genesis: options.genesis, + }); + } + + // This is cached, so the `DriverNoVendor` is shared between wallet sources + const driverNoVendor = createDriverNoVendor(options.nodeUrl, genesisBlock); + + // This is also cached based on the source + const vendorDriver = createVendorDriver(signer, source); + + vendorDriver.setNoVendor(driverNoVendor); + + const framework = new Framework(vendorDriver); + + return { + thor: framework.thor, + vendor: framework.vendor, + }; +}; + +export { createConnexInstance }; diff --git a/packages/wallet-kit/src/genesis.ts b/packages/wallet-kit/src/genesis.ts new file mode 100644 index 00000000..a6a86c09 --- /dev/null +++ b/packages/wallet-kit/src/genesis.ts @@ -0,0 +1,17 @@ +import { genesisBlocks } from "@vechain/connex/esm/config"; +import type { Genesis } from "./types"; + +const normalizeGenesisId = (genesis: Genesis): string => { + if (genesis === "main" || genesis === "test") + return genesisBlocks[genesis].id; + + return genesis.id; +}; + +const normalizeGenesisBlock = (genesis: Genesis): Connex.Thor.Block => { + if (genesis === "main" || genesis === "test") return genesisBlocks[genesis]; + + return genesis; +}; + +export { normalizeGenesisId, normalizeGenesisBlock }; diff --git a/packages/wallet-kit/src/index.ts b/packages/wallet-kit/src/index.ts new file mode 100644 index 00000000..3cbc415e --- /dev/null +++ b/packages/wallet-kit/src/index.ts @@ -0,0 +1,2 @@ +export * from "./connex"; +export * from "./wallet"; diff --git a/packages/wallet-kit/src/signer.ts b/packages/wallet-kit/src/signer.ts new file mode 100644 index 00000000..c9f6a09a --- /dev/null +++ b/packages/wallet-kit/src/signer.ts @@ -0,0 +1,79 @@ +import type { + WalletConnectOptions, + WCSigner, +} from "@vechain/wallet-connect/dist"; +import { + newWcClient, + newWcSigner, + newWeb3Modal, +} from "@vechain/wallet-connect/dist"; +import type { Connex } from "@vechain/connex"; +import { createSync, createSync2 } from "@vechain/connex/esm/signer"; +import { WalletSource } from "./wallet"; +import type { Genesis } from "./types"; +import { normalizeGenesisId } from "./genesis"; + +interface WCOptions { + source: WalletSource.WalletConnect; + genesis: Genesis; + options: WalletConnectOptions; + onDisconnected: () => void; +} + +interface DefaultOptions { + source: + | WalletSource.Sync + | WalletSource.Sync2 + | WalletSource.VeWorldExtension; + genesis: Genesis; +} + +type ICreateVendor = DefaultOptions | WCOptions; + +export const createSigner = (params: ICreateVendor): Promise => { + const { source, genesis } = params; + + const genesisId = normalizeGenesisId(genesis); + + if (source === WalletSource.VeWorldExtension) { + if (!window.vechain) { + throw new Error("VeWorld Extension is not installed"); + } + + const signer = window.vechain.newConnexSigner(genesisId); + + return Promise.resolve(signer); + } + + if (source === WalletSource.WalletConnect) { + const { onDisconnected, options } = params; + + const { projectId, metadata } = options; + + const wcClient = newWcClient({ + projectId, + metadata, + }); + + const web3Modal = newWeb3Modal(projectId); + + const wcSigner: WCSigner = newWcSigner({ + genesisId, + wcClient, + web3Modal, + onDisconnected, + }); + + return Promise.resolve(wcSigner); + } + + if (source === WalletSource.Sync) { + if (!window.connex) { + throw new Error("User is not in a Sync wallet"); + } + + return createSync(genesisId); + } + + return createSync2(genesisId); +}; diff --git a/packages/wallet-kit/src/thor-driver.ts b/packages/wallet-kit/src/thor-driver.ts new file mode 100644 index 00000000..0fe64b09 --- /dev/null +++ b/packages/wallet-kit/src/thor-driver.ts @@ -0,0 +1,27 @@ +import { DriverNoVendor } from "@vechain/connex-driver/dist/driver-no-vendor"; +import { SimpleNet } from "@vechain/connex-driver"; +import type { Genesis } from "./types"; +import { normalizeGenesisBlock } from "./genesis"; + +let previousDriver: DriverNoVendor | undefined; + +const createDriverNoVendor = ( + nodeUrl: string, + genesis: Genesis +): DriverNoVendor => { + const genesisBlock = normalizeGenesisBlock(genesis); + + if (previousDriver && previousDriver.genesis.id === genesisBlock.id) { + return previousDriver; + } + + const net = new SimpleNet(nodeUrl); + + const driver = new DriverNoVendor(net, genesisBlock); + + previousDriver = driver; + + return driver; +}; + +export { createDriverNoVendor }; diff --git a/packages/wallet-kit/src/types.d.ts b/packages/wallet-kit/src/types.d.ts new file mode 100644 index 00000000..78980676 --- /dev/null +++ b/packages/wallet-kit/src/types.d.ts @@ -0,0 +1,12 @@ +import type { Connex1 } from "@vechain/connex/esm/signer"; + +declare global { + interface Window { + vechain?: { + newConnexSigner: (genesisId: string) => Connex.Signer; + }; + connex?: Connex1; + } +} + +export type Genesis = "main" | "test" | Connex.Thor.Block; diff --git a/packages/wallet-kit/src/vendor-driver.ts b/packages/wallet-kit/src/vendor-driver.ts new file mode 100644 index 00000000..0b604a97 --- /dev/null +++ b/packages/wallet-kit/src/vendor-driver.ts @@ -0,0 +1,22 @@ +import { LazyDriver } from "@vechain/connex/esm/driver"; +import type { WalletSource } from "./wallet"; + +const _cachedDrivers: Record = {}; + +const createVendorDriver = ( + signer: Promise, + source: WalletSource +): LazyDriver => { + const cachedDriver = _cachedDrivers[source]; + + if (cachedDriver) { + return cachedDriver; + } + + const driver = new LazyDriver(signer); + _cachedDrivers[source] = driver; + + return driver; +}; + +export { createVendorDriver }; diff --git a/packages/wallet-kit/src/wallet.ts b/packages/wallet-kit/src/wallet.ts new file mode 100644 index 00000000..8cd229d2 --- /dev/null +++ b/packages/wallet-kit/src/wallet.ts @@ -0,0 +1,31 @@ +/** + * Wallet types + */ + +enum WalletSource { + WalletConnect = "wallet-connect", + VeWorldExtension = "veworld-extension", + Sync2 = "sync2", + Sync = "sync", +} + +interface WalletConfig { + requiresCertificate: boolean; +} + +const DEFAULT_CONFIG: WalletConfig = { + requiresCertificate: true, +}; + +const WalletMapping: Record = { + [WalletSource.WalletConnect]: { + requiresCertificate: false, + }, + [WalletSource.VeWorldExtension]: DEFAULT_CONFIG, + [WalletSource.Sync2]: DEFAULT_CONFIG, + [WalletSource.Sync]: DEFAULT_CONFIG, +}; + +export { WalletSource, WalletMapping }; + +export type { WalletConfig }; diff --git a/packages/wallet-kit/tsconfig.json b/packages/wallet-kit/tsconfig.json new file mode 100644 index 00000000..127dc568 --- /dev/null +++ b/packages/wallet-kit/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "tsconfig/base.json", + "include": ["."], + "exclude": ["dist", "node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1ecf3855..26ae9bc5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,6 +56,15 @@ importers: '@vechain/picasso': specifier: ^2.1.1 version: 2.1.1 + '@vechain/react-wallet-kit': + specifier: workspace:* + version: link:../../packages/react-wallet-kit + '@vechain/wallet-connect': + specifier: workspace:* + version: link:../../packages/wallet-connect + '@vechain/wallet-kit': + specifier: workspace:* + version: link:../../packages/wallet-kit buffer: specifier: ^6.0.3 version: 6.0.3 @@ -83,9 +92,6 @@ importers: react-scripts: specifier: 5.0.1 version: 5.0.1(@babel/plugin-syntax-flow@7.18.6)(@babel/plugin-transform-react-jsx@7.19.0)(eslint@8.28.0)(react@18.2.0)(ts-node@10.9.1)(typescript@4.9.5) - react-vendor: - specifier: workspace:* - version: link:../../packages/react-vendor stream-browserify: specifier: ^3.0.0 version: 3.0.0 @@ -95,9 +101,9 @@ importers: thor-devkit: specifier: ^2.0.9 version: 2.0.9 - wallet-connect: - specifier: workspace:* - version: link:../../packages/wallet-connect + url: + specifier: ^0.11.3 + version: 0.11.3 web-vitals: specifier: ^2.1.2 version: 2.1.4 @@ -169,7 +175,7 @@ importers: specifier: ^1.10.12 version: 1.10.12(eslint@8.28.0) - packages/react-vendor: + packages/react-wallet-kit: dependencies: '@vechain/connex': specifier: 2.1.0 @@ -177,12 +183,15 @@ importers: '@vechain/connex-framework': specifier: 2.1.0 version: 2.1.0 + '@vechain/wallet-connect': + specifier: workspace:* + version: link:../wallet-connect + '@vechain/wallet-kit': + specifier: workspace:* + version: link:../wallet-kit thor-devkit: specifier: ^2.0.9 version: 2.0.9 - wallet-connect: - specifier: workspace:* - version: link:../wallet-connect devDependencies: '@types/react': specifier: ^18.2.28 @@ -245,6 +254,37 @@ importers: specifier: 4.9.5 version: 4.9.5 + packages/wallet-kit: + dependencies: + '@vechain/connex': + specifier: 2.1.0 + version: 2.1.0 + '@vechain/connex-driver': + specifier: 2.1.0 + version: 2.1.0 + '@vechain/connex-framework': + specifier: 2.1.0 + version: 2.1.0 + '@vechain/wallet-connect': + specifier: workspace:* + version: link:../wallet-connect + devDependencies: + eslint: + specifier: ^8.4.1 + version: 8.28.0 + eslint-config-custom: + specifier: workspace:* + version: link:../eslint-config-custom + tsconfig: + specifier: workspace:* + version: link:../tsconfig + tsup: + specifier: ^5.10.1 + version: 5.12.9(ts-node@10.9.1)(typescript@4.9.5) + typescript: + specifier: 4.9.5 + version: 4.9.5 + packages: /@adobe/css-tools@4.0.1: @@ -7549,7 +7589,7 @@ packages: glob-parent: 6.0.2 globals: 13.18.0 grapheme-splitter: 1.0.4 - ignore: 5.2.0 + ignore: 5.2.4 import-fresh: 3.3.0 imurmurhash: 0.1.4 is-glob: 4.0.3 @@ -8488,10 +8528,6 @@ packages: /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - /ignore@5.2.0: - resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} - engines: {node: '>= 4'} - /ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} @@ -10233,7 +10269,7 @@ packages: levn: 0.3.0 prelude-ls: 1.1.2 type-check: 0.3.2 - word-wrap: 1.2.3 + word-wrap: 1.2.5 /optionator@0.9.1: resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} @@ -11297,6 +11333,10 @@ packages: safe-buffer: 5.2.1 dev: false + /punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + dev: false + /punycode@2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} @@ -11322,6 +11362,13 @@ packages: dependencies: side-channel: 1.0.4 + /qs@6.11.2: + resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + /query-string@7.1.3: resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} engines: {node: '>=6'} @@ -11961,6 +12008,7 @@ packages: /rollup@2.79.1: resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} engines: {node: '>=10.0.0'} + hasBin: true optionalDependencies: fsevents: 2.3.2 @@ -12572,18 +12620,6 @@ packages: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} dev: false - /sucrase@3.29.0: - resolution: {integrity: sha512-bZPAuGA5SdFHuzqIhTAqt9fvNEo9rESqXIG3oiKdF8K4UmkQxC4KlNL3lVyAErXp+mPvUqZ5l13qx6TrDIGf3A==} - engines: {node: '>=8'} - dependencies: - commander: 4.1.1 - glob: 7.1.6 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.5 - ts-interface-checker: 0.1.13 - dev: true - /sucrase@3.34.0: resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} engines: {node: '>=8'} @@ -13000,7 +13036,7 @@ packages: resolve-from: 5.0.0 rollup: 2.79.1 source-map: 0.8.0-beta.0 - sucrase: 3.29.0 + sucrase: 3.34.0 tree-kill: 1.2.2 typescript: 4.9.5 transitivePeerDependencies: @@ -13241,6 +13277,13 @@ packages: querystringify: 2.2.0 requires-port: 1.0.0 + /url@0.11.3: + resolution: {integrity: sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==} + dependencies: + punycode: 1.4.1 + qs: 6.11.2 + dev: false + /use-callback-ref@1.3.0(@types/react@18.2.28)(react@18.2.0): resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} engines: {node: '>=10'} @@ -13608,10 +13651,6 @@ packages: dependencies: isexe: 2.0.0 - /word-wrap@1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} - engines: {node: '>=0.10.0'} - /word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} From 5fb466965a042bd760ecdc15ceaba740fe7065bb Mon Sep 17 00:00:00 2001 From: Davide Carpini Date: Wed, 25 Oct 2023 17:33:34 +0200 Subject: [PATCH 2/2] fix: prettier and react/package.json --- .prettierrc | 5 + README.md | 16 +- apps/sample-react-app/hardhat.config.ts | 12 +- apps/sample-react-app/package.json | 201 ++++---- apps/sample-react-app/src/App.tsx | 84 ++-- .../src/Components/AccountDetailBody.tsx | 89 ++-- .../src/Components/AccountDetailModal.tsx | 92 ++-- .../src/Components/AddressButton.tsx | 100 ++-- .../src/Components/AddressIcon.tsx | 38 +- .../src/Components/ConnectWalletButton.tsx | 84 ++-- .../src/Components/ConnectWalletModal.tsx | 305 ++++++------ .../src/Components/WalletSourceRadio.tsx | 174 +++---- apps/sample-react-app/src/Components/index.ts | 14 +- .../src/Components/layout/NavBar.tsx | 196 ++++---- .../src/Components/layout/StyledContainer.tsx | 24 +- .../src/Components/layout/index.ts | 4 +- .../src/Components/shared/Dialog.tsx | 78 +-- .../src/Components/shared/RadioCard.tsx | 103 ++-- .../src/Components/shared/StyledCard.tsx | 26 +- .../src/Components/shared/index.ts | 6 +- .../src/Constants/Constants.ts | 42 +- apps/sample-react-app/src/Constants/index.ts | 2 +- apps/sample-react-app/src/Hooks/useCounter.ts | 104 ++-- apps/sample-react-app/src/Logos/Logo.tsx | 58 +-- apps/sample-react-app/src/Logos/index.ts | 2 +- .../sample-react-app/src/Screens/Homepage.tsx | 50 +- .../src/Screens/components/Counter.tsx | 183 +++---- .../src/Screens/components/MeetVeWorld.tsx | 48 +- .../src/Screens/components/Welcome.tsx | 59 +-- .../src/Screens/components/index.ts | 6 +- apps/sample-react-app/src/Styles/Fonts.tsx | 10 +- apps/sample-react-app/src/Styles/Theme.tsx | 10 +- apps/sample-react-app/src/Styles/index.ts | 4 +- .../src/Utils/AccountUtils.ts | 26 +- apps/sample-react-app/src/index.tsx | 26 +- apps/sample-react-app/src/reportWebVitals.ts | 30 +- apps/sample-react-app/src/setupTests.ts | 2 +- package.json | 86 ++-- .../react-wallet-kit/src/AccountReducer.ts | 66 +-- .../react-wallet-kit/src/ConnexProvider.tsx | 454 +++++++++--------- packages/react-wallet-kit/src/index.tsx | 6 +- packages/react-wallet-kit/src/types.ts | 38 +- packages/wallet-connect/src/client.ts | 54 ++- packages/wallet-connect/src/constants.ts | 4 +- packages/wallet-connect/src/index.ts | 18 +- packages/wallet-connect/src/signer.ts | 388 +++++++-------- packages/wallet-connect/src/types.d.ts | 42 +- packages/wallet-connect/src/web3-modal.ts | 52 +- packages/wallet-kit/src/connex.ts | 86 ++-- packages/wallet-kit/src/genesis.ts | 14 +- packages/wallet-kit/src/index.ts | 4 +- packages/wallet-kit/src/signer.ts | 106 ++-- packages/wallet-kit/src/thor-driver.ts | 28 +- packages/wallet-kit/src/types.d.ts | 16 +- packages/wallet-kit/src/vendor-driver.ts | 22 +- packages/wallet-kit/src/wallet.ts | 24 +- yarn.lock | 2 +- 57 files changed, 1933 insertions(+), 1890 deletions(-) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..cc8d72b8 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "singleQuote": true, + "trailingComma": "none", + "tabWidth": 4 +} \ No newline at end of file diff --git a/README.md b/README.md index 58478c4c..81d95be3 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ VeWorld WalletKit is a typescript library that facilitates seamless interaction ## Why ? -- Allow easy interaction with all wallets. -- Currently, connex only plays nice with Sync / Sync2 -- Enable a better UX for users +- Allow easy interaction with all wallets. +- Currently, connex only plays nice with Sync / Sync2 +- Enable a better UX for users ## Key features @@ -14,19 +14,19 @@ Key Features a.k.a scope 1. wallet connectivity - key components that handle interaction with veworld and sync 2 + key components that handle interaction with veworld and sync 2 2. customizable UI - ability to totally customize the UI of components + ability to totally customize the UI of components 3. User Experience - Consistent experience with Ethereum and other chains + Consistent experience with Ethereum and other chains 4. Developer friendly - Easy to adopt with proper documentation. + Easy to adopt with proper documentation. ## Setting up the project (Common flow) @@ -70,4 +70,4 @@ yarn build ### Future Work -- Create a Modal/ Library in React / Vue / Angular +- Create a Modal/ Library in React / Vue / Angular diff --git a/apps/sample-react-app/hardhat.config.ts b/apps/sample-react-app/hardhat.config.ts index 6c392940..1208d13b 100644 --- a/apps/sample-react-app/hardhat.config.ts +++ b/apps/sample-react-app/hardhat.config.ts @@ -1,11 +1,11 @@ -import { HardhatUserConfig } from "hardhat/config"; -import "@nomicfoundation/hardhat-toolbox"; +import { HardhatUserConfig } from 'hardhat/config'; +import '@nomicfoundation/hardhat-toolbox'; const config: HardhatUserConfig = { - solidity: "0.8.19", - typechain: { - outDir: "src/hardhat", - }, + solidity: '0.8.19', + typechain: { + outDir: 'src/hardhat' + } }; export default config; diff --git a/apps/sample-react-app/package.json b/apps/sample-react-app/package.json index e6d08c7a..ffb1515a 100644 --- a/apps/sample-react-app/package.json +++ b/apps/sample-react-app/package.json @@ -1,103 +1,102 @@ { - "name": "sample-app-react", - "version": "0.0.0", - "private": true, - "homepage": ".", - "main": "src/index.js", - "scripts": { - "build": "yarn compile && react-app-rewired build", - "clean": "rm -rf build node_modules .turbo cache artifacts src/hardhat", - "compile": "yarn hardhat compile", - "dev": "react-app-rewired start", - "eject": "react-app-rewired eject", - "postinstall": "yarn compile", - "lint": "eslint src --ext .js,.jsx,.ts,.tsx", - "start": "HTTPS=true react-app-rewired start", - "test": "echo 'Not yet testing'" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "dependencies": { - "@chakra-ui/react": "^2.8.1", - "@emotion/react": "^11.11.1", - "@emotion/styled": "^11.11.0", - "@heroicons/react": "^2.0.18", - "@vechain/connex": "2.1.0", - "@vechain/hardhat-vechain": "^0.1.4", - "@vechain/hardhat-web3": "^0.1.4", - "@vechain/picasso": "^2.1.1", - "@vechain/react-wallet-kit": "*", - "@vechain/wallet-connect": "*", - "@vechain/wallet-kit": "*", - "@vechain/web3-providers-connex": "^1.1.2", - "buffer": "^6.0.3", - "crypto-browserify": "^3.12.0", - "ethers": "^6.8.0", - "framer-motion": "3.10.6", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "process": "^0.11.10", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router-dom": "^6.4.2", - "react-scripts": "5.0.1", - "stream-browserify": "^3.0.0", - "stream-http": "^3.2.0", - "thor-devkit": "^2.0.9", - "url": "^0.11.3", - "web-vitals": "^2.1.2" - }, - "devDependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", - "@nomicfoundation/hardhat-ethers": "^3.0.0", - "@nomicfoundation/hardhat-network-helpers": "^1.0.0", - "@nomicfoundation/hardhat-toolbox": "^3.0.0", - "@nomicfoundation/hardhat-verify": "^1.0.0", - "@testing-library/jest-dom": "^5.16.1", - "@testing-library/react": "^12.1.2", - "@testing-library/user-event": "^13.5.0", - "@typechain/ethers-v6": "^0.4.0", - "@typechain/hardhat": "^8.0.0", - "@types/chai": "^4.2.0", - "@types/jest": "^27.0.3", - "@types/mocha": ">=9.1.0", - "@types/node": "^18.17.2", - "@types/react": "^18.2.28", - "@types/react-dom": "^18.2.13", - "@types/testing-library__jest-dom": "^5.14.5", - "chai": "^4.2.0", - "copy-webpack-plugin": "^11.0.0", - "customize-cra": "^1.0.0", - "eslint-config-custom": "*", - "ethers": "^6.4.0", - "filemanager-webpack-plugin": "^8.0.0", - "hardhat": "^2.18.2", - "hardhat-gas-reporter": "^1.0.8", - "mini-css-extract-plugin": "^2.7.6", - "react-app-rewired": "^2.2.1", - "solidity-coverage": "^0.8.1", - "ts-import-plugin": "^3.0.0", - "ts-loader": "^9.5.0", - "ts-node": "^10.9.1", - "tsconfig": "*", - "typechain": "^8.2.0", - "typescript": "4.9.5", - "webpack": "^5.88.2" - } + "name": "sample-app-react", + "version": "0.0.0", + "private": true, + "homepage": ".", + "main": "src/index.js", + "scripts": { + "build": "yarn compile && react-app-rewired build", + "clean": "rm -rf build node_modules .turbo cache artifacts src/hardhat", + "compile": "yarn hardhat compile", + "dev": "react-app-rewired start", + "eject": "react-app-rewired eject", + "postinstall": "yarn compile", + "lint": "eslint src --ext .js,.jsx,.ts,.tsx", + "start": "HTTPS=true react-app-rewired start", + "test": "echo 'Not yet testing'" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "dependencies": { + "@chakra-ui/react": "^2.8.1", + "@emotion/react": "^11.11.1", + "@emotion/styled": "^11.11.0", + "@heroicons/react": "^2.0.18", + "@vechain/connex": "2.1.0", + "@vechain/hardhat-vechain": "^0.1.4", + "@vechain/hardhat-web3": "^0.1.4", + "@vechain/picasso": "^2.1.1", + "@vechain/react-wallet-kit": "*", + "@vechain/wallet-connect": "*", + "@vechain/wallet-kit": "*", + "@vechain/web3-providers-connex": "^1.1.2", + "buffer": "^6.0.3", + "crypto-browserify": "^3.12.0", + "framer-motion": "3.10.6", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "process": "^0.11.10", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.4.2", + "react-scripts": "5.0.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "thor-devkit": "^2.0.9", + "url": "^0.11.3", + "web-vitals": "^2.1.2" + }, + "devDependencies": { + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomicfoundation/hardhat-toolbox": "^3.0.0", + "@nomicfoundation/hardhat-verify": "^1.0.0", + "@testing-library/jest-dom": "^5.16.1", + "@testing-library/react": "^12.1.2", + "@testing-library/user-event": "^13.5.0", + "@typechain/ethers-v6": "^0.4.0", + "@typechain/hardhat": "^8.0.0", + "@types/chai": "^4.2.0", + "@types/jest": "^27.0.3", + "@types/mocha": ">=9.1.0", + "@types/node": "^18.17.2", + "@types/react": "^18.2.28", + "@types/react-dom": "^18.2.13", + "@types/testing-library__jest-dom": "^5.14.5", + "chai": "^4.2.0", + "copy-webpack-plugin": "^11.0.0", + "customize-cra": "^1.0.0", + "eslint-config-custom": "*", + "ethers": "^6.4.0", + "filemanager-webpack-plugin": "^8.0.0", + "hardhat": "^2.18.2", + "hardhat-gas-reporter": "^1.0.8", + "mini-css-extract-plugin": "^2.7.6", + "react-app-rewired": "^2.2.1", + "solidity-coverage": "^0.8.1", + "ts-import-plugin": "^3.0.0", + "ts-loader": "^9.5.0", + "ts-node": "^10.9.1", + "tsconfig": "*", + "typechain": "^8.2.0", + "typescript": "4.9.5", + "webpack": "^5.88.2" + } } diff --git a/apps/sample-react-app/src/App.tsx b/apps/sample-react-app/src/App.tsx index 75b7a5dd..5771e94b 100644 --- a/apps/sample-react-app/src/App.tsx +++ b/apps/sample-react-app/src/App.tsx @@ -1,50 +1,50 @@ -import type { JSX } from "react"; -import React from "react"; -import type { Options } from "@vechain/connex"; -import type { WalletConnectOptions } from "@vechain/wallet-connect"; -import { ConnexProvider } from "@vechain/react-wallet-kit"; -import { BrowserRouter, Route, Routes } from "react-router-dom"; -import { ChakraProvider } from "@chakra-ui/react"; -import { NavBar, StyledContainer } from "./Components/layout"; -import { Homepage } from "./Screens/Homepage"; -import { Fonts, theme } from "./Styles"; +import type { JSX } from 'react'; +import React from 'react'; +import type { Options } from '@vechain/connex'; +import type { WalletConnectOptions } from '@vechain/wallet-connect'; +import { ConnexProvider } from '@vechain/react-wallet-kit'; +import { BrowserRouter, Route, Routes } from 'react-router-dom'; +import { ChakraProvider } from '@chakra-ui/react'; +import { NavBar, StyledContainer } from './Components/layout'; +import { Homepage } from './Screens/Homepage'; +import { Fonts, theme } from './Styles'; -const nodeOptions: Omit = { - node: "https://testnet.vechain.org/", - network: "test", +const nodeOptions: Omit = { + node: 'https://testnet.vechain.org/', + network: 'test' }; const walletConnectOptions: WalletConnectOptions = { - projectId: "8dfc5cac972ee656e6edeb8309ab30ec", - metadata: { - name: "Sample VeChain dApp", - description: "A sample VeChain dApp", - url: window.location.origin, - icons: [`${window.location.origin}/images/logo/my-dapp.png`], - }, + projectId: '8dfc5cac972ee656e6edeb8309ab30ec', + metadata: { + name: 'Sample VeChain dApp', + description: 'A sample VeChain dApp', + url: window.location.origin, + icons: [`${window.location.origin}/images/logo/my-dapp.png`] + } }; export const App = (): JSX.Element => { - return ( - <> - - - - - - - - } path="/" /> - - - - - - - ); + return ( + <> + + + + + + + + } path="/" /> + + + + + + + ); }; diff --git a/apps/sample-react-app/src/Components/AccountDetailBody.tsx b/apps/sample-react-app/src/Components/AccountDetailBody.tsx index d6611350..b3721bda 100644 --- a/apps/sample-react-app/src/Components/AccountDetailBody.tsx +++ b/apps/sample-react-app/src/Components/AccountDetailBody.tsx @@ -1,50 +1,55 @@ -import { Button, HStack, Image, Text, VStack } from "@chakra-ui/react"; -import React, { useMemo } from "react"; -import type { WalletSource } from "@vechain/wallet-kit"; -import { WalletSources } from "../Constants"; -import { AddressButton } from "./AddressButton"; +import { Button, HStack, Image, Text, VStack } from '@chakra-ui/react'; +import React, { useMemo } from 'react'; +import type { WalletSource } from '@vechain/wallet-kit'; +import { WalletSources } from '../Constants'; +import { AddressButton } from './AddressButton'; interface AccountDetailBodyProps { - accountAddress: string; - source: WalletSource; - disconnectWallet: () => void; + accountAddress: string; + source: WalletSource; + disconnectWallet: () => void; } export const AccountDetailBody: React.FC = ({ - accountAddress, - source, - disconnectWallet, + accountAddress, + source, + disconnectWallet }) => { - const sourceInfo = useMemo(() => WalletSources[source], [source]); + const sourceInfo = useMemo(() => WalletSources[source], [source]); - return ( - <> - - - - Account - - - - - - Source - - - {`${sourceInfo.name}-logo`} - {sourceInfo.name} - - - - - - ); + return ( + <> + + + + Account + + + + + + Source + + + {`${sourceInfo.name}-logo`} + {sourceInfo.name} + + + + + + ); }; diff --git a/apps/sample-react-app/src/Components/AccountDetailModal.tsx b/apps/sample-react-app/src/Components/AccountDetailModal.tsx index 464da6da..0af149ca 100644 --- a/apps/sample-react-app/src/Components/AccountDetailModal.tsx +++ b/apps/sample-react-app/src/Components/AccountDetailModal.tsx @@ -1,57 +1,57 @@ -import { HStack, Text } from "@chakra-ui/react"; -import type { WalletSource } from "@vechain/wallet-kit"; -import { useWallet } from "@vechain/react-wallet-kit"; -import React, { useCallback } from "react"; -import { getPicassoImgSrc } from "../Utils/AccountUtils"; -import { Dialog } from "./shared"; -import { AccountDetailBody } from "./AccountDetailBody"; +import { HStack, Text } from '@chakra-ui/react'; +import type { WalletSource } from '@vechain/wallet-kit'; +import { useWallet } from '@vechain/react-wallet-kit'; +import React, { useCallback } from 'react'; +import { getPicassoImgSrc } from '../Utils/AccountUtils'; +import { Dialog } from './shared'; +import { AccountDetailBody } from './AccountDetailBody'; interface AccountDetailModalProps { - isOpen: boolean; - onClose: () => void; - address: string; - source: WalletSource; + isOpen: boolean; + onClose: () => void; + address: string; + source: WalletSource; } export const AccountDetailModal: React.FC = ({ - isOpen, - onClose, - address, - source, + isOpen, + onClose, + address, + source }) => { - const { disconnect } = useWallet(); + const { disconnect } = useWallet(); - const disconnectWallet = useCallback((): void => { - disconnect(); - onClose(); - }, [disconnect, onClose]); + const disconnectWallet = useCallback((): void => { + disconnect(); + onClose(); + }, [disconnect, onClose]); - const header = ( - - Connected Wallet - - ); + const header = ( + + Connected Wallet + + ); - return ( - + } + closeButtonStyle={{ color: 'white' }} + header={header} + headerStyle={{ p: 0 }} + isOpen={isOpen} + onClose={onClose} /> - } - closeButtonStyle={{ color: "white" }} - header={header} - headerStyle={{ p: 0 }} - isOpen={isOpen} - onClose={onClose} - /> - ); + ); }; diff --git a/apps/sample-react-app/src/Components/AddressButton.tsx b/apps/sample-react-app/src/Components/AddressButton.tsx index d2f9089e..f0632a50 100644 --- a/apps/sample-react-app/src/Components/AddressButton.tsx +++ b/apps/sample-react-app/src/Components/AddressButton.tsx @@ -1,60 +1,60 @@ -import type { HTMLChakraProps } from "@chakra-ui/react"; -import { Button, HStack, Icon, Text, useClipboard } from "@chakra-ui/react"; -import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/solid"; -import React, { useCallback, useEffect } from "react"; -import { friendlyAddress } from "../Utils/AccountUtils"; -import { AddressIcon } from "./AddressIcon"; +import type { HTMLChakraProps } from '@chakra-ui/react'; +import { Button, HStack, Icon, Text, useClipboard } from '@chakra-ui/react'; +import { CheckIcon, DocumentDuplicateIcon } from '@heroicons/react/24/solid'; +import React, { useCallback, useEffect } from 'react'; +import { friendlyAddress } from '../Utils/AccountUtils'; +import { AddressIcon } from './AddressIcon'; -interface AddressButtonProps extends HTMLChakraProps<"button"> { - address: string; - showAddressIcon?: boolean; - showCopyIcon?: boolean; +interface AddressButtonProps extends HTMLChakraProps<'button'> { + address: string; + showAddressIcon?: boolean; + showCopyIcon?: boolean; } export const AddressButton: React.FC = ({ - address, - showAddressIcon = true, - showCopyIcon = true, - ...props + address, + showAddressIcon = true, + showCopyIcon = true, + ...props }) => { - const { onCopy, hasCopied, setValue } = useClipboard(address); + const { onCopy, hasCopied, setValue } = useClipboard(address); - const { onClick, ...otherProps } = props; + const { onClick, ...otherProps } = props; - const onClickHandler = useCallback( - (e: React.MouseEvent): void => { - // console.log(onClick) - if (onClick) onClick(e); - if (showCopyIcon) onCopy(); - }, - [onClick, showCopyIcon, onCopy] - ); + const onClickHandler = useCallback( + (e: React.MouseEvent): void => { + // console.log(onClick) + if (onClick) onClick(e); + if (showCopyIcon) onCopy(); + }, + [onClick, showCopyIcon, onCopy] + ); - useEffect(() => { - setValue(address); - }, [setValue, address]); + useEffect(() => { + setValue(address); + }, [setValue, address]); - return ( - - ); + return ( + + ); }; diff --git a/apps/sample-react-app/src/Components/AddressIcon.tsx b/apps/sample-react-app/src/Components/AddressIcon.tsx index 64d2a1a1..ff0eb489 100644 --- a/apps/sample-react-app/src/Components/AddressIcon.tsx +++ b/apps/sample-react-app/src/Components/AddressIcon.tsx @@ -1,30 +1,30 @@ -import React from "react"; -import type { HTMLChakraProps } from "@chakra-ui/react"; -import { Img } from "@chakra-ui/react"; -import { getPicassoImgSrc } from "../Utils/AccountUtils"; +import React from 'react'; +import type { HTMLChakraProps } from '@chakra-ui/react'; +import { Img } from '@chakra-ui/react'; +import { getPicassoImgSrc } from '../Utils/AccountUtils'; -interface AddressIconProps extends HTMLChakraProps<"img"> { - address: string; +interface AddressIconProps extends HTMLChakraProps<'img'> { + address: string; } export const AddressIcon: React.FC = ({ - address, - ...props + address, + ...props }) => { - return ; + return ; }; -interface PicassoProps extends HTMLChakraProps<"img"> { - address: string; +interface PicassoProps extends HTMLChakraProps<'img'> { + address: string; } const Picasso: React.FC = ({ address, ...props }) => { - return ( - - ); + return ( + + ); }; diff --git a/apps/sample-react-app/src/Components/ConnectWalletButton.tsx b/apps/sample-react-app/src/Components/ConnectWalletButton.tsx index 8115e6e4..469bbae4 100644 --- a/apps/sample-react-app/src/Components/ConnectWalletButton.tsx +++ b/apps/sample-react-app/src/Components/ConnectWalletButton.tsx @@ -1,53 +1,53 @@ -import type { HTMLChakraProps } from "@chakra-ui/react"; -import { Button, Icon, useDisclosure } from "@chakra-ui/react"; -import { WalletIcon } from "@heroicons/react/24/solid"; -import React from "react"; -import { useWallet } from "@vechain/react-wallet-kit"; -import { AccountDetailModal } from "./AccountDetailModal"; -import { AddressButton } from "./AddressButton"; -import { ConnectWalletModal } from "./ConnectWalletModal"; +import type { HTMLChakraProps } from '@chakra-ui/react'; +import { Button, Icon, useDisclosure } from '@chakra-ui/react'; +import { WalletIcon } from '@heroicons/react/24/solid'; +import React from 'react'; +import { useWallet } from '@vechain/react-wallet-kit'; +import { AccountDetailModal } from './AccountDetailModal'; +import { AddressButton } from './AddressButton'; +import { ConnectWalletModal } from './ConnectWalletModal'; interface ConnectWalletButtonProps { - buttonProps?: HTMLChakraProps<"button">; + buttonProps?: HTMLChakraProps<'button'>; } export const ConnectWalletButton: React.FC = ({ - buttonProps, + buttonProps }): React.ReactElement => { - const { isOpen, onOpen, onClose } = useDisclosure(); + const { isOpen, onOpen, onClose } = useDisclosure(); - const { - accountState: { address, source }, - } = useWallet(); + const { + accountState: { address, source } + } = useWallet(); + + if (address && source) + return ( + <> + + + + ); - if (address && source) return ( - <> - - - + <> + + + ); - - return ( - <> - - - - ); }; diff --git a/apps/sample-react-app/src/Components/ConnectWalletModal.tsx b/apps/sample-react-app/src/Components/ConnectWalletModal.tsx index fee3371b..a9e21066 100644 --- a/apps/sample-react-app/src/Components/ConnectWalletModal.tsx +++ b/apps/sample-react-app/src/Components/ConnectWalletModal.tsx @@ -1,166 +1,169 @@ import { - Alert, - AlertIcon, - Box, - Button, - Flex, - HStack, - Icon, - Spinner, - Text, - useToast, - VStack, -} from "@chakra-ui/react"; -import { LinkIcon, WalletIcon } from "@heroicons/react/24/solid"; -import React, { useCallback, useState } from "react"; -import { Certificate } from "thor-devkit"; -import { useConnex, useWallet } from "@vechain/react-wallet-kit"; -import { Dialog } from "./shared"; -import { WalletSourceRadio } from "./WalletSourceRadio"; + Alert, + AlertIcon, + Box, + Button, + Flex, + HStack, + Icon, + Spinner, + Text, + useToast, + VStack +} from '@chakra-ui/react'; +import { LinkIcon, WalletIcon } from '@heroicons/react/24/solid'; +import React, { useCallback, useState } from 'react'; +import { Certificate } from 'thor-devkit'; +import { useConnex, useWallet } from '@vechain/react-wallet-kit'; +import { Dialog } from './shared'; +import { WalletSourceRadio } from './WalletSourceRadio'; interface ConnectedWalletDialogProps { - isOpen: boolean; - onClose: () => void; + isOpen: boolean; + onClose: () => void; } export const ConnectWalletModal: React.FC = ({ - isOpen, - onClose, + isOpen, + onClose }) => { - const header = ( - - - Connect Wallet - - ); - - return ( - } - header={header} - isOpen={isOpen} - onClose={onClose} - /> - ); + const header = ( + + + Connect Wallet + + ); + + return ( + } + header={header} + isOpen={isOpen} + onClose={onClose} + /> + ); }; interface ConnectedWalletBodyProps { - onClose: () => void; + onClose: () => void; } const ConnectedWalletBody: React.FC = ({ - onClose, + onClose }) => { - const toast = useToast(); - const { setAccount } = useWallet(); - const { vendor } = useConnex(); - - const [connectionLoading, setConnectionLoading] = useState(false); - const [connectionError, setConnectionError] = useState(""); - - const connectToWalletHandler = useCallback(async (): Promise => { - const message: Connex.Vendor.CertMessage = { - purpose: "identification", - payload: { - type: "text", - content: "Sign a certificate to prove your identity", - }, - }; - - const certResponse = await vendor.sign("cert", message).request(); - - const cert: Certificate = { - purpose: message.purpose, - payload: message.payload, - domain: certResponse.annex.domain, - timestamp: certResponse.annex.timestamp, - signer: certResponse.annex.signer, - signature: certResponse.signature, - }; - - Certificate.verify(cert); - - return cert; - }, [vendor]); - - const onSuccessfullConnection = useCallback( - (cert: Certificate): void => { - setAccount(cert.signer); - onClose(); - toast({ - title: "Wallet connected.", - description: `You've succesfully connected with wallet ${cert.signer}`, - status: "success", - position: "bottom-left", - duration: 5000, - isClosable: true, - }); - }, - [toast, setAccount, onClose] - ); - - const connectHandler = useCallback(async () => { - try { - setConnectionError(""); - setConnectionLoading(true); - - const cert = await connectToWalletHandler(); - - onSuccessfullConnection(cert); - } catch (e) { - if (e instanceof Error) { - setConnectionError(e.message); - } else { - setConnectionError("Failed to connect to wallet"); - } - } finally { - setConnectionLoading(false); - } - }, [ - onSuccessfullConnection, - setConnectionError, - setConnectionLoading, - connectToWalletHandler, - ]); - - const connect = useCallback(() => { - connectHandler().catch((e) => { - throw e; - }); - }, [connectHandler]); - - return ( - <> - - - Wallet - - - - - {connectionLoading ? ( - - - Waiting for wallet approval... - - ) : null} - {connectionError ? ( - - - {connectionError} - - ) : null} - - - - - ); + const toast = useToast(); + const { setAccount } = useWallet(); + const { vendor } = useConnex(); + + const [connectionLoading, setConnectionLoading] = useState(false); + const [connectionError, setConnectionError] = useState(''); + + const connectToWalletHandler = + useCallback(async (): Promise => { + const message: Connex.Vendor.CertMessage = { + purpose: 'identification', + payload: { + type: 'text', + content: 'Sign a certificate to prove your identity' + } + }; + + const certResponse = await vendor.sign('cert', message).request(); + + const cert: Certificate = { + purpose: message.purpose, + payload: message.payload, + domain: certResponse.annex.domain, + timestamp: certResponse.annex.timestamp, + signer: certResponse.annex.signer, + signature: certResponse.signature + }; + + Certificate.verify(cert); + + return cert; + }, [vendor]); + + const onSuccessfullConnection = useCallback( + (cert: Certificate): void => { + setAccount(cert.signer); + onClose(); + toast({ + title: 'Wallet connected.', + description: `You've succesfully connected with wallet ${cert.signer}`, + status: 'success', + position: 'bottom-left', + duration: 5000, + isClosable: true + }); + }, + [toast, setAccount, onClose] + ); + + const connectHandler = useCallback(async () => { + try { + setConnectionError(''); + setConnectionLoading(true); + + const cert = await connectToWalletHandler(); + + onSuccessfullConnection(cert); + } catch (e) { + if (e instanceof Error) { + setConnectionError(e.message); + } else { + setConnectionError('Failed to connect to wallet'); + } + } finally { + setConnectionLoading(false); + } + }, [ + onSuccessfullConnection, + setConnectionError, + setConnectionLoading, + connectToWalletHandler + ]); + + const connect = useCallback(() => { + connectHandler().catch((e) => { + throw e; + }); + }, [connectHandler]); + + return ( + <> + + + Wallet + + + + + {connectionLoading ? ( + + + Waiting for wallet approval... + + ) : null} + {connectionError ? ( + + + {connectionError} + + ) : null} + + + + + ); }; diff --git a/apps/sample-react-app/src/Components/WalletSourceRadio.tsx b/apps/sample-react-app/src/Components/WalletSourceRadio.tsx index b7c9550f..54de45de 100644 --- a/apps/sample-react-app/src/Components/WalletSourceRadio.tsx +++ b/apps/sample-react-app/src/Components/WalletSourceRadio.tsx @@ -1,107 +1,111 @@ import { - Box, - Flex, - HStack, - Icon, - Image, - Text, - Tooltip, - VStack, -} from "@chakra-ui/react"; -import { ExclamationTriangleIcon } from "@heroicons/react/24/solid"; -import React, { useCallback } from "react"; -import type { WalletSource } from "@vechain/wallet-kit"; -import { useWallet } from "@vechain/react-wallet-kit"; -import { WalletSources } from "../Constants"; -import { RadioCard } from "./shared"; + Box, + Flex, + HStack, + Icon, + Image, + Text, + Tooltip, + VStack +} from '@chakra-ui/react'; +import { ExclamationTriangleIcon } from '@heroicons/react/24/solid'; +import React, { useCallback } from 'react'; +import type { WalletSource } from '@vechain/wallet-kit'; +import { useWallet } from '@vechain/react-wallet-kit'; +import { WalletSources } from '../Constants'; +import { RadioCard } from './shared'; export const WalletSourceRadio: React.FC = () => { - const { availableWallets, wallets, setSource, accountState } = useWallet(); + const { availableWallets, wallets, setSource, accountState } = useWallet(); - const handleSourceClick = useCallback( - (isDisabled: boolean, source: WalletSource) => () => { - if (!isDisabled) { - setSource(source); - } - }, - [setSource] - ); + const handleSourceClick = useCallback( + (isDisabled: boolean, source: WalletSource) => () => { + if (!isDisabled) { + setSource(source); + } + }, + [setSource] + ); - return ( - - {wallets.map((source: WalletSource) => { - const isDisabled = !availableWallets.includes(source); - const isSelected = source === accountState.source; + return ( + + {wallets.map((source: WalletSource) => { + const isDisabled = !availableWallets.includes(source); + const isSelected = source === accountState.source; - return ( - - ); - })} - - ); + return ( + + ); + })} + + ); }; interface WalletSourceButtonProps { - source: WalletSource; - isSelected: boolean; - isDisabled: boolean; - onClick: () => void; + source: WalletSource; + isSelected: boolean; + isDisabled: boolean; + onClick: () => void; } const WalletSourceButton: React.FC = ({ - source, - isSelected, - isDisabled, - onClick, + source, + isSelected, + isDisabled, + onClick }) => { - const sourceInfo = WalletSources[source]; - return ( - - - {`${sourceInfo.name}-logo`} - {sourceInfo.name} - - {isDisabled ? ( - - - - ) : null} - - ); + const sourceInfo = WalletSources[source]; + return ( + + + {`${sourceInfo.name}-logo`} + {sourceInfo.name} + + {isDisabled ? ( + + + + ) : null} + + ); }; interface SourceNotDetectedIconProps { - source: WalletSource; + source: WalletSource; } const SourceNotDetectedIcon: React.FC = ({ - source, + source }) => { - const sourceInfo = WalletSources[source]; + const sourceInfo = WalletSources[source]; - return ( - - - - - - ); + return ( + + + + + + ); }; diff --git a/apps/sample-react-app/src/Components/index.ts b/apps/sample-react-app/src/Components/index.ts index 0d3c1163..2c393926 100644 --- a/apps/sample-react-app/src/Components/index.ts +++ b/apps/sample-react-app/src/Components/index.ts @@ -1,7 +1,7 @@ -export * from "./AccountDetailBody"; -export * from "./AccountDetailModal"; -export * from "./AddressButton"; -export * from "./AddressIcon"; -export * from "./ConnectWalletButton"; -export * from "./ConnectWalletModal"; -export * from "./WalletSourceRadio"; +export * from './AccountDetailBody'; +export * from './AccountDetailModal'; +export * from './AddressButton'; +export * from './AddressIcon'; +export * from './ConnectWalletButton'; +export * from './ConnectWalletModal'; +export * from './WalletSourceRadio'; diff --git a/apps/sample-react-app/src/Components/layout/NavBar.tsx b/apps/sample-react-app/src/Components/layout/NavBar.tsx index bf14b534..678e15cb 100644 --- a/apps/sample-react-app/src/Components/layout/NavBar.tsx +++ b/apps/sample-react-app/src/Components/layout/NavBar.tsx @@ -1,120 +1,120 @@ import { - Box, - Drawer, - DrawerBody, - DrawerContent, - DrawerOverlay, - Flex, - HStack, - Icon, - IconButton, - Text, - useColorModeValue, - useDisclosure, - useMediaQuery, - VStack, -} from "@chakra-ui/react"; -import type { JSX } from "react"; -import React from "react"; -import { Bars3Icon } from "@heroicons/react/24/solid"; -import { useWallet } from "@vechain/react-wallet-kit"; -import { VechainLogo } from "../../Logos"; -import { AccountDetailBody } from "../AccountDetailBody"; -import { ConnectWalletButton } from "../ConnectWalletButton"; + Box, + Drawer, + DrawerBody, + DrawerContent, + DrawerOverlay, + Flex, + HStack, + Icon, + IconButton, + Text, + useColorModeValue, + useDisclosure, + useMediaQuery, + VStack +} from '@chakra-ui/react'; +import type { JSX } from 'react'; +import React from 'react'; +import { Bars3Icon } from '@heroicons/react/24/solid'; +import { useWallet } from '@vechain/react-wallet-kit'; +import { VechainLogo } from '../../Logos'; +import { AccountDetailBody } from '../AccountDetailBody'; +import { ConnectWalletButton } from '../ConnectWalletButton'; export const NavBar = (): JSX.Element => { - const bg = useColorModeValue("gray.50", "gray.900"); - const [isDesktop] = useMediaQuery("(min-width: 48em)"); + const bg = useColorModeValue('gray.50', 'gray.900'); + const [isDesktop] = useMediaQuery('(min-width: 48em)'); - return ( - - {isDesktop ? : } - - ); + return ( + + {isDesktop ? : } + + ); }; const DesktopNavBar = (): JSX.Element => { - return ( - <> - - - - - - ); + return ( + <> + + + + + + ); }; const MobileNavBar = (): JSX.Element => { - const { isOpen, onClose, onOpen } = useDisclosure(); - return ( - <> - - - - - } - onClick={onOpen} - /> - - ); + const { isOpen, onClose, onOpen } = useDisclosure(); + return ( + <> + + + + + } + onClick={onOpen} + /> + + ); }; interface MobileNavBarDrawerProps { - isOpen: boolean; - onClose: () => void; + isOpen: boolean; + onClose: () => void; } const MobileNavBarDrawer = ({ - isOpen, - onClose, + isOpen, + onClose }: MobileNavBarDrawerProps): JSX.Element => { - const { accountState, disconnect } = useWallet(); + const { accountState, disconnect } = useWallet(); - return ( - - - - - - - Connected Wallet - {accountState.address && accountState.source ? ( - - ) : ( - - )} - - - - - - ); + return ( + + + + + + + Connected Wallet + {accountState.address && accountState.source ? ( + + ) : ( + + )} + + + + + + ); }; const NavBarWalletConnect = (): JSX.Element => { - return ( - - - - ); + return ( + + + + ); }; diff --git a/apps/sample-react-app/src/Components/layout/StyledContainer.tsx b/apps/sample-react-app/src/Components/layout/StyledContainer.tsx index f1f8214a..f0f98395 100644 --- a/apps/sample-react-app/src/Components/layout/StyledContainer.tsx +++ b/apps/sample-react-app/src/Components/layout/StyledContainer.tsx @@ -1,20 +1,20 @@ -import { Box, Container, useColorModeValue } from "@chakra-ui/react"; -import React from "react"; +import { Box, Container, useColorModeValue } from '@chakra-ui/react'; +import React from 'react'; interface StyledContainerProps { - children: React.ReactNode; + children: React.ReactNode; } export const StyledContainer: React.FC = ({ - children, + children }) => { - const bodyBg = useColorModeValue("gray.50", "gray.900"); + const bodyBg = useColorModeValue('gray.50', 'gray.900'); - return ( - - - {children} - - - ); + return ( + + + {children} + + + ); }; diff --git a/apps/sample-react-app/src/Components/layout/index.ts b/apps/sample-react-app/src/Components/layout/index.ts index 65a8d02b..65237cdf 100644 --- a/apps/sample-react-app/src/Components/layout/index.ts +++ b/apps/sample-react-app/src/Components/layout/index.ts @@ -1,2 +1,2 @@ -export * from "./NavBar"; -export * from "./StyledContainer"; +export * from './NavBar'; +export * from './StyledContainer'; diff --git a/apps/sample-react-app/src/Components/shared/Dialog.tsx b/apps/sample-react-app/src/Components/shared/Dialog.tsx index 7945d113..3301dcde 100644 --- a/apps/sample-react-app/src/Components/shared/Dialog.tsx +++ b/apps/sample-react-app/src/Components/shared/Dialog.tsx @@ -1,45 +1,49 @@ -import type { HTMLChakraProps } from "@chakra-ui/react"; +import type { HTMLChakraProps } from '@chakra-ui/react'; import { - Modal, - ModalBody, - ModalCloseButton, - ModalContent, - ModalFooter, - ModalHeader, - ModalOverlay, -} from "@chakra-ui/react"; -import React from "react"; + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay +} from '@chakra-ui/react'; +import React from 'react'; interface DialogProps { - isOpen: boolean; - onClose: () => void; - header?: React.ReactNode; - headerStyle?: HTMLChakraProps<"header">; - body?: React.ReactNode; - footer?: React.ReactNode; - showCloseButton?: boolean; - closeButtonStyle?: HTMLChakraProps<"button">; + isOpen: boolean; + onClose: () => void; + header?: React.ReactNode; + headerStyle?: HTMLChakraProps<'header'>; + body?: React.ReactNode; + footer?: React.ReactNode; + showCloseButton?: boolean; + closeButtonStyle?: HTMLChakraProps<'button'>; } export const Dialog: React.FC = ({ - isOpen, - onClose, - header, - headerStyle = {}, - body, - footer, - showCloseButton = true, - closeButtonStyle = {}, + isOpen, + onClose, + header, + headerStyle = {}, + body, + footer, + showCloseButton = true, + closeButtonStyle = {} }) => { - return ( - - - - {header ? {header} : null} - {showCloseButton ? : null} - {body ? {body} : null} - {footer ? {footer} : null} - - - ); + return ( + + + + {header ? ( + {header} + ) : null} + {showCloseButton ? ( + + ) : null} + {body ? {body} : null} + {footer ? {footer} : null} + + + ); }; diff --git a/apps/sample-react-app/src/Components/shared/RadioCard.tsx b/apps/sample-react-app/src/Components/shared/RadioCard.tsx index a9427998..b0012f46 100644 --- a/apps/sample-react-app/src/Components/shared/RadioCard.tsx +++ b/apps/sample-react-app/src/Components/shared/RadioCard.tsx @@ -1,61 +1,66 @@ -import type { HTMLChakraProps } from "@chakra-ui/react"; -import { Box, Button, Flex, HStack } from "@chakra-ui/react"; -import React from "react"; +import type { HTMLChakraProps } from '@chakra-ui/react'; +import { Box, Button, Flex, HStack } from '@chakra-ui/react'; +import React from 'react'; -interface RadioCardProps extends HTMLChakraProps<"button"> { - children: React.ReactNode; - selected: boolean; - onClick: () => void; +interface RadioCardProps extends HTMLChakraProps<'button'> { + children: React.ReactNode; + selected: boolean; + onClick: () => void; } export const RadioCard: React.FC = ({ - children, - selected, - onClick, - ...props + children, + selected, + onClick, + ...props }) => { - return ( - - ); + return ( + + ); }; -interface RadioCircleProps extends HTMLChakraProps<"div"> { - filled?: boolean; +interface RadioCircleProps extends HTMLChakraProps<'div'> { + filled?: boolean; } const RadioCircle: React.FC = ({ - filled = false, - ...props + filled = false, + ...props }) => { - return ( - - - - ); + return ( + + + + ); }; diff --git a/apps/sample-react-app/src/Components/shared/StyledCard.tsx b/apps/sample-react-app/src/Components/shared/StyledCard.tsx index b5b0786b..f94282ef 100644 --- a/apps/sample-react-app/src/Components/shared/StyledCard.tsx +++ b/apps/sample-react-app/src/Components/shared/StyledCard.tsx @@ -1,19 +1,19 @@ -import type { HTMLChakraProps } from "@chakra-ui/react"; -import { Card, CardBody, useColorModeValue } from "@chakra-ui/react"; -import React from "react"; +import type { HTMLChakraProps } from '@chakra-ui/react'; +import { Card, CardBody, useColorModeValue } from '@chakra-ui/react'; +import React from 'react'; -interface StyledCardProps extends HTMLChakraProps<"div"> { - children: React.ReactNode; +interface StyledCardProps extends HTMLChakraProps<'div'> { + children: React.ReactNode; } export const StyledCard: React.FC = ({ - children, - ...props + children, + ...props }) => { - const cardBg = useColorModeValue("white", "gray.700"); - return ( - - {children} - - ); + const cardBg = useColorModeValue('white', 'gray.700'); + return ( + + {children} + + ); }; diff --git a/apps/sample-react-app/src/Components/shared/index.ts b/apps/sample-react-app/src/Components/shared/index.ts index 3991c962..f623ae48 100644 --- a/apps/sample-react-app/src/Components/shared/index.ts +++ b/apps/sample-react-app/src/Components/shared/index.ts @@ -1,3 +1,3 @@ -export * from "./Dialog"; -export * from "./RadioCard"; -export * from "./StyledCard"; +export * from './Dialog'; +export * from './RadioCard'; +export * from './StyledCard'; diff --git a/apps/sample-react-app/src/Constants/Constants.ts b/apps/sample-react-app/src/Constants/Constants.ts index 0a178d49..19cb0bed 100644 --- a/apps/sample-react-app/src/Constants/Constants.ts +++ b/apps/sample-react-app/src/Constants/Constants.ts @@ -1,30 +1,30 @@ -import { WalletSource } from "@vechain/wallet-kit"; +import { WalletSource } from '@vechain/wallet-kit'; -export const NODE_URL = "https://testnet.vechain.org/"; -export const NODE_NETWORK = "test"; +export const NODE_URL = 'https://testnet.vechain.org/'; +export const NODE_NETWORK = 'test'; interface SourceInfo { - name: string; - logo: string; + name: string; + logo: string; } const baseLogoUrl = `${process.env.PUBLIC_URL}/images/logo`; export const WalletSources: Record = { - [WalletSource.WalletConnect]: { - name: "Wallet Connect", - logo: `${baseLogoUrl}/wallet-connect-logo.png`, - }, - [WalletSource.VeWorldExtension]: { - name: "VeWorld Extension", - logo: `${baseLogoUrl}/veworld_black.png`, - }, - [WalletSource.Sync]: { - name: "Sync", - logo: `${baseLogoUrl}/sync.png`, - }, - [WalletSource.Sync2]: { - name: "Sync 2", - logo: `${baseLogoUrl}/sync2.png`, - }, + [WalletSource.WalletConnect]: { + name: 'Wallet Connect', + logo: `${baseLogoUrl}/wallet-connect-logo.png` + }, + [WalletSource.VeWorldExtension]: { + name: 'VeWorld Extension', + logo: `${baseLogoUrl}/veworld_black.png` + }, + [WalletSource.Sync]: { + name: 'Sync', + logo: `${baseLogoUrl}/sync.png` + }, + [WalletSource.Sync2]: { + name: 'Sync 2', + logo: `${baseLogoUrl}/sync2.png` + } }; diff --git a/apps/sample-react-app/src/Constants/index.ts b/apps/sample-react-app/src/Constants/index.ts index 86ad2cf4..a719bffa 100644 --- a/apps/sample-react-app/src/Constants/index.ts +++ b/apps/sample-react-app/src/Constants/index.ts @@ -1 +1 @@ -export * from "./Constants"; +export * from './Constants'; diff --git a/apps/sample-react-app/src/Hooks/useCounter.ts b/apps/sample-react-app/src/Hooks/useCounter.ts index 8bfe0d73..7dacfd80 100644 --- a/apps/sample-react-app/src/Hooks/useCounter.ts +++ b/apps/sample-react-app/src/Hooks/useCounter.ts @@ -1,77 +1,77 @@ -import { useCallback, useEffect, useMemo, useState } from "react"; -import { useConnex } from "@vechain/react-wallet-kit"; -import type { abi } from "thor-devkit"; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useConnex } from '@vechain/react-wallet-kit'; +import type { abi } from 'thor-devkit'; const _counter: abi.Function.Definition = { - inputs: [], - name: "counter", - outputs: [ - { - internalType: "uint256", - name: "count", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", + inputs: [], + name: 'counter', + outputs: [ + { + internalType: 'uint256', + name: 'count', + type: 'uint256' + } + ], + stateMutability: 'view', + type: 'function' }; const _increment: abi.Function.Definition = { - inputs: [], - name: "increment", - outputs: [], - stateMutability: "nonpayable", - type: "function", + inputs: [], + name: 'increment', + outputs: [], + stateMutability: 'nonpayable', + type: 'function' }; -type IncrementStatus = "idle" | "in-wallet" | "pending" | "error"; +type IncrementStatus = 'idle' | 'in-wallet' | 'pending' | 'error'; interface UseCounter { - count: number; - increment: () => Promise; - status: IncrementStatus; - address: string; + count: number; + increment: () => Promise; + status: IncrementStatus; + address: string; } export const useCounter = (): UseCounter => { - const { vendor, thor } = useConnex(); + const { vendor, thor } = useConnex(); - const [count, setCount] = useState(0); - const [status, setStatus] = useState("idle"); + const [count, setCount] = useState(0); + const [status, setStatus] = useState('idle'); - const contract = useMemo( - () => thor.account("0x8384738c995d49c5b692560ae688fc8b51af1059"), - [thor] - ); + const contract = useMemo( + () => thor.account('0x8384738c995d49c5b692560ae688fc8b51af1059'), + [thor] + ); - const setValue = useCallback(async () => { - const res = await contract.method(_counter).call(); + const setValue = useCallback(async () => { + const res = await contract.method(_counter).call(); - setCount(res.decoded.count as number); - }, [contract]); + setCount(res.decoded.count as number); + }, [contract]); - useEffect(() => { - setValue().catch(() => setStatus("error")); - }, [setValue]); + useEffect(() => { + setValue().catch(() => setStatus('error')); + }, [setValue]); - const increment = useCallback(async (): Promise => { - const clause = contract.method(_increment).asClause(); + const increment = useCallback(async (): Promise => { + const clause = contract.method(_increment).asClause(); - setStatus("in-wallet"); + setStatus('in-wallet'); - await vendor - .sign("tx", [clause]) - .delegate("https://sponsor-testnet.vechain.energy/by/90") - .request(); + await vendor + .sign('tx', [clause]) + .delegate('https://sponsor-testnet.vechain.energy/by/90') + .request(); - setStatus("pending"); + setStatus('pending'); - await thor.ticker().next(); + await thor.ticker().next(); - await setValue() - .then(() => setStatus("idle")) - .catch(() => setStatus("error")); - }, [thor, vendor, contract, setValue]); + await setValue() + .then(() => setStatus('idle')) + .catch(() => setStatus('error')); + }, [thor, vendor, contract, setValue]); - return { count, increment, status, address: contract.address }; + return { count, increment, status, address: contract.address }; }; diff --git a/apps/sample-react-app/src/Logos/Logo.tsx b/apps/sample-react-app/src/Logos/Logo.tsx index f821f81b..7e15008d 100644 --- a/apps/sample-react-app/src/Logos/Logo.tsx +++ b/apps/sample-react-app/src/Logos/Logo.tsx @@ -1,37 +1,37 @@ -import type { HTMLChakraProps } from "@chakra-ui/react"; -import { Image, useColorModeValue } from "@chakra-ui/react"; -import React from "react"; +import type { HTMLChakraProps } from '@chakra-ui/react'; +import { Image, useColorModeValue } from '@chakra-ui/react'; +import React from 'react'; -type IIMage = HTMLChakraProps<"img">; +type IIMage = HTMLChakraProps<'img'>; export const VechainLogo: React.FC = ({ - ...props + ...props }): React.ReactElement => { - const lightModeUrl = `${process.env.PUBLIC_URL}/images/logo/vechain.png`; - const darkModeUrl = `${process.env.PUBLIC_URL}/images/logo/vechain_white.png`; - const logoUrl = useColorModeValue(lightModeUrl, darkModeUrl); - return ( - Vechain logo - ); + const lightModeUrl = `${process.env.PUBLIC_URL}/images/logo/vechain.png`; + const darkModeUrl = `${process.env.PUBLIC_URL}/images/logo/vechain_white.png`; + const logoUrl = useColorModeValue(lightModeUrl, darkModeUrl); + return ( + Vechain logo + ); }; export const VeWorldLogo: React.FC = ({ ...props }) => { - const lightModeUrl = `${process.env.PUBLIC_URL}/images/logo/veWorld.png`; - const darkModeUrl = `${process.env.PUBLIC_URL}/images/logo/veworld_black.png`; - const logoUrl = useColorModeValue(lightModeUrl, darkModeUrl); - return ( - VeWorld logo - ); + const lightModeUrl = `${process.env.PUBLIC_URL}/images/logo/veWorld.png`; + const darkModeUrl = `${process.env.PUBLIC_URL}/images/logo/veworld_black.png`; + const logoUrl = useColorModeValue(lightModeUrl, darkModeUrl); + return ( + VeWorld logo + ); }; diff --git a/apps/sample-react-app/src/Logos/index.ts b/apps/sample-react-app/src/Logos/index.ts index bd3113fb..d97c6951 100644 --- a/apps/sample-react-app/src/Logos/index.ts +++ b/apps/sample-react-app/src/Logos/index.ts @@ -1 +1 @@ -export * from "./Logo"; +export * from './Logo'; diff --git a/apps/sample-react-app/src/Screens/Homepage.tsx b/apps/sample-react-app/src/Screens/Homepage.tsx index 23269a97..f2ad2069 100644 --- a/apps/sample-react-app/src/Screens/Homepage.tsx +++ b/apps/sample-react-app/src/Screens/Homepage.tsx @@ -1,28 +1,28 @@ -import React from "react"; -import { Box, Grid, GridItem, VStack } from "@chakra-ui/react"; -import { Counter, MeetVeWorld, Welcome } from "./components"; +import React from 'react'; +import { Box, Grid, GridItem, VStack } from '@chakra-ui/react'; +import { Counter, MeetVeWorld, Welcome } from './components'; export const Homepage: React.FC = () => { - return ( - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + ); }; diff --git a/apps/sample-react-app/src/Screens/components/Counter.tsx b/apps/sample-react-app/src/Screens/components/Counter.tsx index a3a83969..19c3d0a5 100644 --- a/apps/sample-react-app/src/Screens/components/Counter.tsx +++ b/apps/sample-react-app/src/Screens/components/Counter.tsx @@ -1,100 +1,105 @@ import { - Alert, - AlertIcon, - Button, - Heading, - HStack, - Icon, - Text, - useToast, - VStack, -} from "@chakra-ui/react"; -import type { JSX } from "react"; -import React, { useCallback, useMemo } from "react"; -import { ArrowUpIcon } from "@heroicons/react/24/solid"; -import { useWallet } from "@vechain/react-wallet-kit"; -import { StyledCard } from "../../Components/shared"; -import { useCounter } from "../../Hooks/useCounter"; -import { AddressButton } from "../../Components"; + Alert, + AlertIcon, + Button, + Heading, + HStack, + Icon, + Text, + useToast, + VStack +} from '@chakra-ui/react'; +import type { JSX } from 'react'; +import React, { useCallback, useMemo } from 'react'; +import { ArrowUpIcon } from '@heroicons/react/24/solid'; +import { useWallet } from '@vechain/react-wallet-kit'; +import { StyledCard } from '../../Components/shared'; +import { useCounter } from '../../Hooks/useCounter'; +import { AddressButton } from '../../Components'; export const Counter = (): JSX.Element => { - const { accountState } = useWallet(); - const { count, increment, status, address } = useCounter(); - const toast = useToast(); + const { accountState } = useWallet(); + const { count, increment, status, address } = useCounter(); + const toast = useToast(); - const incrementCounter = useCallback(() => { - increment() - .then(() => { - toast({ - title: "Counter incremented", - status: "success", - duration: 2000, - isClosable: true, - }); - }) - // eslint-disable-next-line no-console - .catch(console.error); - }, [increment, toast]); + const incrementCounter = useCallback(() => { + increment() + .then(() => { + toast({ + title: 'Counter incremented', + status: 'success', + duration: 2000, + isClosable: true + }); + }) + // eslint-disable-next-line no-console + .catch(console.error); + }, [increment, toast]); - const button = useMemo(() => { - return ( - - ); - }, [accountState.address, incrementCounter, status]); - - const message = useMemo(() => { - switch (status) { - case "in-wallet": - return ( - - - Waiting for wallet approval... - - ); - case "error": + const button = useMemo(() => { return ( - - - There was an unexpected error - + ); - case "pending": - return ( - - - Waiting for transaction confirmation... - - ); - case "idle": - return null; - } - }, [status]); + }, [accountState.address, incrementCounter, status]); + + const message = useMemo(() => { + switch (status) { + case 'in-wallet': + return ( + + + Waiting for wallet approval... + + ); + case 'error': + return ( + + + There was an unexpected error + + ); + case 'pending': + return ( + + + Waiting for transaction confirmation... + + ); + case 'idle': + return null; + } + }, [status]); - return ( - - - Counter + return ( + + + Counter - + - - Current count: {count} - - - {button} - {message} - - - - ); + + Current count: {count} + + + {button} + {message} + + + + ); }; diff --git a/apps/sample-react-app/src/Screens/components/MeetVeWorld.tsx b/apps/sample-react-app/src/Screens/components/MeetVeWorld.tsx index be9423a8..b753b16c 100644 --- a/apps/sample-react-app/src/Screens/components/MeetVeWorld.tsx +++ b/apps/sample-react-app/src/Screens/components/MeetVeWorld.tsx @@ -1,27 +1,27 @@ -import { Box, Button, Heading, HStack, Text, VStack } from "@chakra-ui/react"; -import type { JSX } from "react"; -import { VeWorldLogo } from "../../Logos"; -import { StyledCard } from "../../Components/shared"; +import { Box, Button, Heading, HStack, Text, VStack } from '@chakra-ui/react'; +import type { JSX } from 'react'; +import { VeWorldLogo } from '../../Logos'; +import { StyledCard } from '../../Components/shared'; export const MeetVeWorld = (): JSX.Element => { - return ( - - - - Meet VeWorld{" "} - - - - - - The new browser-based wallet coming straightly from the Vechain - Foundation. Built with state of the art technologies, security and - ease of use in mind. - - - - - ); + return ( + + + + Meet VeWorld{' '} + + + + + + The new browser-based wallet coming straightly from the + Vechain Foundation. Built with state of the art + technologies, security and ease of use in mind. + + + + + ); }; diff --git a/apps/sample-react-app/src/Screens/components/Welcome.tsx b/apps/sample-react-app/src/Screens/components/Welcome.tsx index 00cccd79..bfd1e88c 100644 --- a/apps/sample-react-app/src/Screens/components/Welcome.tsx +++ b/apps/sample-react-app/src/Screens/components/Welcome.tsx @@ -1,30 +1,35 @@ -import { Button, Heading, HStack, Link, Text, VStack } from "@chakra-ui/react"; -import type { JSX } from "react"; -import { StyledCard } from "../../Components/shared"; -import { ConnectWalletButton } from "../../Components"; +import { Button, Heading, HStack, Link, Text, VStack } from '@chakra-ui/react'; +import type { JSX } from 'react'; +import { StyledCard } from '../../Components/shared'; +import { ConnectWalletButton } from '../../Components'; export const Welcome = (): JSX.Element => { - return ( - - - Welcome to the Official VeWorld Demo Dapp - - You can use this dapp to familiarize and know more about creation on - VeChain - - - - - - - - - - ); + return ( + + + Welcome to the Official VeWorld Demo Dapp + + You can use this dapp to familiarize and know more about + creation on VeChain + + + + + + + + + + ); }; diff --git a/apps/sample-react-app/src/Screens/components/index.ts b/apps/sample-react-app/src/Screens/components/index.ts index 1a0266bb..8882b673 100644 --- a/apps/sample-react-app/src/Screens/components/index.ts +++ b/apps/sample-react-app/src/Screens/components/index.ts @@ -1,3 +1,3 @@ -export * from "./MeetVeWorld"; -export * from "./Welcome"; -export * from "./Counter"; +export * from './MeetVeWorld'; +export * from './Welcome'; +export * from './Counter'; diff --git a/apps/sample-react-app/src/Styles/Fonts.tsx b/apps/sample-react-app/src/Styles/Fonts.tsx index 64885238..7f830cf8 100644 --- a/apps/sample-react-app/src/Styles/Fonts.tsx +++ b/apps/sample-react-app/src/Styles/Fonts.tsx @@ -1,9 +1,9 @@ -import { Global } from "@emotion/react"; -import React from "react"; +import { Global } from '@emotion/react'; +import React from 'react'; export const Fonts = (): React.ReactElement => ( - ( font-style: normal; } `} - /> + /> ); diff --git a/apps/sample-react-app/src/Styles/Theme.tsx b/apps/sample-react-app/src/Styles/Theme.tsx index 3cc10ad2..caeced90 100644 --- a/apps/sample-react-app/src/Styles/Theme.tsx +++ b/apps/sample-react-app/src/Styles/Theme.tsx @@ -1,8 +1,8 @@ -import { extendTheme } from "@chakra-ui/react"; +import { extendTheme } from '@chakra-ui/react'; export const theme = extendTheme({ - fonts: { - heading: `'JetBrains Mono', sans-serif`, - body: `'Inter', sans-serif`, - }, + fonts: { + heading: `'JetBrains Mono', sans-serif`, + body: `'Inter', sans-serif` + } }); diff --git a/apps/sample-react-app/src/Styles/index.ts b/apps/sample-react-app/src/Styles/index.ts index 99c5763a..6e81efc6 100644 --- a/apps/sample-react-app/src/Styles/index.ts +++ b/apps/sample-react-app/src/Styles/index.ts @@ -1,2 +1,2 @@ -export * from "./Fonts"; -export * from "./Theme"; +export * from './Fonts'; +export * from './Theme'; diff --git a/apps/sample-react-app/src/Utils/AccountUtils.ts b/apps/sample-react-app/src/Utils/AccountUtils.ts index 76e235b5..0526249f 100644 --- a/apps/sample-react-app/src/Utils/AccountUtils.ts +++ b/apps/sample-react-app/src/Utils/AccountUtils.ts @@ -1,20 +1,20 @@ -import { picasso } from "@vechain/picasso"; +import { picasso } from '@vechain/picasso'; export const getPicassoImgSrc = (address: string, base64 = false): string => { - const image = picasso(address.toLowerCase()); - if (base64) { - const base64data = Buffer.from(image, "utf8").toString("base64"); - return `data:image/svg+xml;base64,${base64data}`; - } - return `data:image/svg+xml;utf8,${image}`; + const image = picasso(address.toLowerCase()); + if (base64) { + const base64data = Buffer.from(image, 'utf8').toString('base64'); + return `data:image/svg+xml;base64,${base64data}`; + } + return `data:image/svg+xml;utf8,${image}`; }; export const friendlyAddress = ( - address: string, - lengthBefore = 6, - lengthAfter = 4 + address: string, + lengthBefore = 6, + lengthAfter = 4 ): string => { - const before = address.substring(0, lengthBefore); - const after = address.substring(address.length - lengthAfter); - return `${before}…${after}`; + const before = address.substring(0, lengthBefore); + const after = address.substring(address.length - lengthAfter); + return `${before}…${after}`; }; diff --git a/apps/sample-react-app/src/index.tsx b/apps/sample-react-app/src/index.tsx index 62cac8d1..4c3a1658 100644 --- a/apps/sample-react-app/src/index.tsx +++ b/apps/sample-react-app/src/index.tsx @@ -1,20 +1,20 @@ -import React from "react"; -import { createRoot } from "react-dom/client"; -import { App } from "./App"; -import reportWebVitals from "./reportWebVitals"; -import "./Styles/index.css"; +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import { App } from './App'; +import reportWebVitals from './reportWebVitals'; +import './Styles/index.css'; -document.createElement("vechain-wallet-modal"); +document.createElement('vechain-wallet-modal'); -const rootElement = document.getElementById("root"); +const rootElement = document.getElementById('root'); if (rootElement) { - const root = createRoot(rootElement); - root.render( - - - - ); + const root = createRoot(rootElement); + root.render( + + + + ); } // If you want to start measuring performance in your app, pass a function diff --git a/apps/sample-react-app/src/reportWebVitals.ts b/apps/sample-react-app/src/reportWebVitals.ts index 9f98d7d9..fae17894 100644 --- a/apps/sample-react-app/src/reportWebVitals.ts +++ b/apps/sample-react-app/src/reportWebVitals.ts @@ -1,20 +1,20 @@ -import type { ReportHandler } from "web-vitals"; +import type { ReportHandler } from 'web-vitals'; const reportWebVitals = (onPerfEntry?: ReportHandler): void => { - if (onPerfEntry && onPerfEntry instanceof Function) { - import("web-vitals") - .then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }) - .catch((err) => { - // eslint-disable-next-line no-console - console.error('Failed to load "web-vitals"', err); - }); - } + if (onPerfEntry && onPerfEntry instanceof Function) { + import('web-vitals') + .then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + getCLS(onPerfEntry); + getFID(onPerfEntry); + getFCP(onPerfEntry); + getLCP(onPerfEntry); + getTTFB(onPerfEntry); + }) + .catch((err) => { + // eslint-disable-next-line no-console + console.error('Failed to load "web-vitals"', err); + }); + } }; export default reportWebVitals; diff --git a/apps/sample-react-app/src/setupTests.ts b/apps/sample-react-app/src/setupTests.ts index 1dd407a6..8f2609b7 100644 --- a/apps/sample-react-app/src/setupTests.ts +++ b/apps/sample-react-app/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import "@testing-library/jest-dom"; +import '@testing-library/jest-dom'; diff --git a/package.json b/package.json index 2aebe675..848a0e68 100755 --- a/package.json +++ b/package.json @@ -1,46 +1,46 @@ { - "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], - "scripts": { - "build": "turbo run build", - "build:deps": "turbo build --no-daemon --filter='@vechain/*'", - "clean": "npx turbo@latest run clean && rm -rf node_modules .turbo", - "dev": "turbo run dev --no-daemon", - "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "install:all": "yarn && yarn run build:deps", - "lint": "turbo run lint", - "prepare": "husky install", - "reinstall": "yarn clean && yarn && yarn run build:deps", - "test": "turbo run test" - }, - "husky": { - "hooks": { - "pre-commit": "lint-staged" - } - }, - "lint-staged": { - "*.{js,jsx,ts,tsx,json,md}": [ - "prettier --write", - "git add" + "private": true, + "workspaces": [ + "apps/*", + "packages/*" ], - "*.{js,jsx,ts,tsx}": [ - "eslint" - ] - }, - "devDependencies": { - "@commitlint/config-conventional": "^18.0.0", - "commitlint": "^18.0.0", - "eslint": "^8.4.1", - "eslint-config-custom": "*", - "eslint-plugin-prefer-arrow": "1.2.3", - "husky": "^8.0.0", - "lint-staged": "^15.0.2", - "prettier": "^2.5.1", - "tsconfig": "*", - "turbo": "latest" - }, - "packageManager": "yarn@1.22.19" + "scripts": { + "build": "turbo run build", + "build:deps": "turbo build --no-daemon --filter='@vechain/*'", + "clean": "npx turbo@latest run clean && rm -rf node_modules .turbo", + "dev": "turbo run dev --no-daemon", + "format": "prettier --write \"**/*.{ts,tsx,md}\"", + "install:all": "yarn && yarn run build:deps", + "lint": "turbo run lint", + "prepare": "husky install", + "reinstall": "yarn clean && yarn && yarn run build:deps", + "test": "turbo run test" + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "*.{js,jsx,ts,tsx,json,md}": [ + "prettier --write", + "git add" + ], + "*.{js,jsx,ts,tsx}": [ + "eslint" + ] + }, + "devDependencies": { + "@commitlint/config-conventional": "^18.0.0", + "commitlint": "^18.0.0", + "eslint": "^8.4.1", + "eslint-config-custom": "*", + "eslint-plugin-prefer-arrow": "1.2.3", + "husky": "^8.0.0", + "lint-staged": "^15.0.2", + "prettier": "^2.5.1", + "tsconfig": "*", + "turbo": "latest" + }, + "packageManager": "yarn@1.22.19" } diff --git a/packages/react-wallet-kit/src/AccountReducer.ts b/packages/react-wallet-kit/src/AccountReducer.ts index b6ad8615..54f75dd5 100644 --- a/packages/react-wallet-kit/src/AccountReducer.ts +++ b/packages/react-wallet-kit/src/AccountReducer.ts @@ -1,44 +1,44 @@ -import type { WalletSource } from "@vechain/wallet-kit"; -import type { AccountState } from "./types"; +import type { WalletSource } from '@vechain/wallet-kit'; +import type { AccountState } from './types'; -const ACCOUNT_KEY = "sample-app@account"; -const WALLET_SOURCE_KEY = "sample-app@wallet-source"; +const ACCOUNT_KEY = 'sample-app@account'; +const WALLET_SOURCE_KEY = 'sample-app@wallet-source'; export type AccountAction = - | { type: "set-address"; payload: { address: string; persist: boolean } } - | { - type: "set-wallet-source"; - payload: { source: WalletSource; persist: boolean }; - } - | { type: "clear" }; + | { type: 'set-address'; payload: { address: string; persist: boolean } } + | { + type: 'set-wallet-source'; + payload: { source: WalletSource; persist: boolean }; + } + | { type: 'clear' }; export const defaultAccountState: AccountState = { - address: localStorage.getItem(ACCOUNT_KEY), - source: localStorage.getItem(WALLET_SOURCE_KEY) as WalletSource, + address: localStorage.getItem(ACCOUNT_KEY), + source: localStorage.getItem(WALLET_SOURCE_KEY) as WalletSource }; export const accountReducer = ( - state: AccountState, - action: AccountAction + state: AccountState, + action: AccountAction ): AccountState => { - switch (action.type) { - case "set-address": { - const { address, persist } = action.payload; - if (persist) { - localStorage.setItem(ACCOUNT_KEY, address); - } - return { ...state, address }; - } - case "set-wallet-source": { - const { source, persist } = action.payload; - if (persist) { - localStorage.setItem(WALLET_SOURCE_KEY, source); - } - return { ...state, source }; + switch (action.type) { + case 'set-address': { + const { address, persist } = action.payload; + if (persist) { + localStorage.setItem(ACCOUNT_KEY, address); + } + return { ...state, address }; + } + case 'set-wallet-source': { + const { source, persist } = action.payload; + if (persist) { + localStorage.setItem(WALLET_SOURCE_KEY, source); + } + return { ...state, source }; + } + case 'clear': + localStorage.removeItem(ACCOUNT_KEY); + localStorage.removeItem(WALLET_SOURCE_KEY); + return { address: null, source: null }; } - case "clear": - localStorage.removeItem(ACCOUNT_KEY); - localStorage.removeItem(WALLET_SOURCE_KEY); - return { address: null, source: null }; - } }; diff --git a/packages/react-wallet-kit/src/ConnexProvider.tsx b/packages/react-wallet-kit/src/ConnexProvider.tsx index 55f238e0..aa2e563e 100644 --- a/packages/react-wallet-kit/src/ConnexProvider.tsx +++ b/packages/react-wallet-kit/src/ConnexProvider.tsx @@ -1,28 +1,28 @@ import React, { - createContext, - useCallback, - useContext, - useEffect, - useMemo, - useReducer, - useRef, -} from "react"; -import { Connex } from "@vechain/connex"; -import { newVendor } from "@vechain/connex-framework"; -import type { WalletConnectOptions, WCSigner } from "@vechain/wallet-connect"; + createContext, + useCallback, + useContext, + useEffect, + useMemo, + useReducer, + useRef +} from 'react'; +import { Connex } from '@vechain/connex'; +import { newVendor } from '@vechain/connex-framework'; +import type { WalletConnectOptions, WCSigner } from '@vechain/wallet-connect'; import { - newWcClient, - newWcSigner, - newWeb3Modal, -} from "@vechain/wallet-connect"; -import { WalletSource } from "@vechain/wallet-kit"; -import { accountReducer, defaultAccountState } from "./AccountReducer"; + newWcClient, + newWcSigner, + newWeb3Modal +} from '@vechain/wallet-connect'; +import { WalletSource } from '@vechain/wallet-kit'; +import { accountReducer, defaultAccountState } from './AccountReducer'; import type { - ConnexContext, - ConnexProviderOptions, - SetAccount, - SetSource, -} from "./types"; + ConnexContext, + ConnexProviderOptions, + SetAccount, + SetSource +} from './types'; /** * Context @@ -30,217 +30,221 @@ import type { const Context = createContext({} as ConnexContext); export const ConnexProvider: React.FC = ({ - children, - nodeOptions, - walletConnectOptions, - persistState = false, + children, + nodeOptions, + walletConnectOptions, + persistState = false }): React.ReactElement => { - const [accountState, dispatch] = useReducer( - accountReducer, - defaultAccountState - ); - - const wcSignerRef = useRef(); - - const disconnectMobile = useCallback(() => { - const client = wcSignerRef.current; - - if (client) { - client.disconnect().catch((err) => { - throw err; - }); - wcSignerRef.current = undefined; - } - }, []); - - const availableWallets = useMemo(() => { - const wallets: WalletSource[] = [WalletSource.Sync2]; - - if (window.vechain) { - wallets.push(WalletSource.VeWorldExtension); - } - - if (window.connex) { - wallets.push(WalletSource.Sync); - } - - if (walletConnectOptions) { - wallets.push(WalletSource.WalletConnect); - } - - return wallets; - }, [walletConnectOptions]); - - const onDisconnected = useCallback((): void => { - if (accountState.source === WalletSource.WalletConnect) { - disconnectMobile(); - } - - dispatch({ type: "clear" }); - }, [disconnectMobile, accountState]); - - useEffect(() => { - if ( - accountState.source === WalletSource.WalletConnect && - !walletConnectOptions - ) { - onDisconnected(); - } - - if ( - accountState.source === WalletSource.VeWorldExtension && - !window.vechain - ) { - onDisconnected(); - } - }, [accountState, walletConnectOptions, onDisconnected]); - - const updateSource: SetSource = useCallback( - (wallet: WalletSource): void => { - // We can't set VeWorld Mobile if there is no Wallet Connect config - if (wallet === WalletSource.WalletConnect && !walletConnectOptions) { - throw new Error("Wallet Connect config not found"); - } - - // We can't set VeWorld Extension if there is no VeChain extension - if (wallet === WalletSource.VeWorldExtension && !window.vechain) { - throw new Error("VeWorld extension not found"); - } - - dispatch({ - type: "set-wallet-source", - payload: { source: wallet, persist: persistState }, - }); - }, - [walletConnectOptions, persistState] - ); - - const thor: Connex.Thor = useMemo( - () => new Connex.Thor(nodeOptions), - [nodeOptions] - ); - - const createWalletConnectVendor = useCallback( - (options: WalletConnectOptions) => { - const { projectId, metadata } = options; - - const wcClient = newWcClient({ - projectId, - metadata, - }); - - const web3Modal = newWeb3Modal(projectId); - - const wcSigner: WCSigner = newWcSigner({ - genesisId: thor.genesis.id, - wcClient, - web3Modal, + const [accountState, dispatch] = useReducer( + accountReducer, + defaultAccountState + ); + + const wcSignerRef = useRef(); + + const disconnectMobile = useCallback(() => { + const client = wcSignerRef.current; + + if (client) { + client.disconnect().catch((err) => { + throw err; + }); + wcSignerRef.current = undefined; + } + }, []); + + const availableWallets = useMemo(() => { + const wallets: WalletSource[] = [WalletSource.Sync2]; + + if (window.vechain) { + wallets.push(WalletSource.VeWorldExtension); + } + + if (window.connex) { + wallets.push(WalletSource.Sync); + } + + if (walletConnectOptions) { + wallets.push(WalletSource.WalletConnect); + } + + return wallets; + }, [walletConnectOptions]); + + const onDisconnected = useCallback((): void => { + if (accountState.source === WalletSource.WalletConnect) { + disconnectMobile(); + } + + dispatch({ type: 'clear' }); + }, [disconnectMobile, accountState]); + + useEffect(() => { + if ( + accountState.source === WalletSource.WalletConnect && + !walletConnectOptions + ) { + onDisconnected(); + } + + if ( + accountState.source === WalletSource.VeWorldExtension && + !window.vechain + ) { + onDisconnected(); + } + }, [accountState, walletConnectOptions, onDisconnected]); + + const updateSource: SetSource = useCallback( + (wallet: WalletSource): void => { + // We can't set VeWorld Mobile if there is no Wallet Connect config + if ( + wallet === WalletSource.WalletConnect && + !walletConnectOptions + ) { + throw new Error('Wallet Connect config not found'); + } + + // We can't set VeWorld Extension if there is no VeChain extension + if (wallet === WalletSource.VeWorldExtension && !window.vechain) { + throw new Error('VeWorld extension not found'); + } + + dispatch({ + type: 'set-wallet-source', + payload: { source: wallet, persist: persistState } + }); + }, + [walletConnectOptions, persistState] + ); + + const thor: Connex.Thor = useMemo( + () => new Connex.Thor(nodeOptions), + [nodeOptions] + ); + + const createWalletConnectVendor = useCallback( + (options: WalletConnectOptions) => { + const { projectId, metadata } = options; + + const wcClient = newWcClient({ + projectId, + metadata + }); + + const web3Modal = newWeb3Modal(projectId); + + const wcSigner: WCSigner = newWcSigner({ + genesisId: thor.genesis.id, + wcClient, + web3Modal, + onDisconnected + }); + + wcSignerRef.current = wcSigner; + + return newVendor(wcSigner); + }, + [onDisconnected, thor.genesis.id] + ); + + /** + * Create the vendor + * Create a vendor for the provided options. If that vendor is not available, the priority is: + * 1. Wallet Connect - If the options are provided + * 2. VeWorld Extension - If the extension is available + * 3. Sync2 - As a fallback, as it is always available + */ + const vendor: Connex.Vendor = useMemo(() => { + const { source } = accountState; + + if (source === WalletSource.WalletConnect && walletConnectOptions) { + return createWalletConnectVendor(walletConnectOptions); + } + + if (source === WalletSource.Sync2 || source === WalletSource.Sync) { + return new Connex.Vendor(thor.genesis.id, source); + } + + if (source === WalletSource.VeWorldExtension && window.vechain) { + const extensionSigner = window.vechain.newConnexSigner( + thor.genesis.id + ); + + return newVendor(extensionSigner); + } + + // We've exhausted all options, so default to Wallet Connect if the options are provided + if (walletConnectOptions) { + return createWalletConnectVendor(walletConnectOptions); + } + + // No wallet connect options, so use the extension if it's available + if (window.vechain) { + const extensionSigner: Connex.Signer = + window.vechain.newConnexSigner(thor.genesis.id); + + return newVendor(extensionSigner); + } + + // Default to Sync2 + return new Connex.Vendor(thor.genesis.id, WalletSource.Sync2); + }, [ + createWalletConnectVendor, + thor.genesis.id, + walletConnectOptions, + accountState + ]); + + const updateAccount: SetAccount = useCallback( + (address: string) => { + dispatch({ + type: 'set-address', + payload: { address, persist: persistState } + }); + }, + [persistState] + ); + + const wallets: WalletSource[] = useMemo(() => { + return Object.values(WalletSource); + }, []); + + const context: ConnexContext = useMemo(() => { + return { + connex: { + thor, + vendor + }, + wallet: { + setSource: updateSource, + setAccount: updateAccount, + availableWallets, + wallets, + accountState, + disconnect: onDisconnected + } + }; + }, [ onDisconnected, - }); - - wcSignerRef.current = wcSigner; - - return newVendor(wcSigner); - }, - [onDisconnected, thor.genesis.id] - ); - - /** - * Create the vendor - * Create a vendor for the provided options. If that vendor is not available, the priority is: - * 1. Wallet Connect - If the options are provided - * 2. VeWorld Extension - If the extension is available - * 3. Sync2 - As a fallback, as it is always available - */ - const vendor: Connex.Vendor = useMemo(() => { - const { source } = accountState; - - if (source === WalletSource.WalletConnect && walletConnectOptions) { - return createWalletConnectVendor(walletConnectOptions); - } - - if (source === WalletSource.Sync2 || source === WalletSource.Sync) { - return new Connex.Vendor(thor.genesis.id, source); - } - - if (source === WalletSource.VeWorldExtension && window.vechain) { - const extensionSigner = window.vechain.newConnexSigner(thor.genesis.id); - - return newVendor(extensionSigner); - } - - // We've exhausted all options, so default to Wallet Connect if the options are provided - if (walletConnectOptions) { - return createWalletConnectVendor(walletConnectOptions); - } - - // No wallet connect options, so use the extension if it's available - if (window.vechain) { - const extensionSigner: Connex.Signer = window.vechain.newConnexSigner( - thor.genesis.id - ); - - return newVendor(extensionSigner); - } - - // Default to Sync2 - return new Connex.Vendor(thor.genesis.id, WalletSource.Sync2); - }, [ - createWalletConnectVendor, - thor.genesis.id, - walletConnectOptions, - accountState, - ]); - - const updateAccount: SetAccount = useCallback( - (address: string) => { - dispatch({ - type: "set-address", - payload: { address, persist: persistState }, - }); - }, - [persistState] - ); - - const wallets: WalletSource[] = useMemo(() => { - return Object.values(WalletSource); - }, []); - - const context: ConnexContext = useMemo(() => { - return { - connex: { + updateAccount, + accountState, thor, vendor, - }, - wallet: { - setSource: updateSource, - setAccount: updateAccount, - availableWallets, + updateSource, wallets, - accountState, - disconnect: onDisconnected, - }, - }; - }, [ - onDisconnected, - updateAccount, - accountState, - thor, - vendor, - updateSource, - wallets, - availableWallets, - ]); - - return {children}; + availableWallets + ]); + + return {children}; }; export const useConnex = (): Connex => { - const context = useContext(Context); - return context.connex; + const context = useContext(Context); + return context.connex; }; -export const useWallet = (): ConnexContext["wallet"] => { - const context = useContext(Context); - return context.wallet; +export const useWallet = (): ConnexContext['wallet'] => { + const context = useContext(Context); + return context.wallet; }; diff --git a/packages/react-wallet-kit/src/index.tsx b/packages/react-wallet-kit/src/index.tsx index b418b710..a9e4b854 100644 --- a/packages/react-wallet-kit/src/index.tsx +++ b/packages/react-wallet-kit/src/index.tsx @@ -1,5 +1,5 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars -import * as React from "react"; +import * as React from 'react'; -export * from "./ConnexProvider"; -export * from "./types"; +export * from './ConnexProvider'; +export * from './types'; diff --git a/packages/react-wallet-kit/src/types.ts b/packages/react-wallet-kit/src/types.ts index 5d81496d..dfa00253 100644 --- a/packages/react-wallet-kit/src/types.ts +++ b/packages/react-wallet-kit/src/types.ts @@ -1,11 +1,11 @@ -import type { Options } from "@vechain/connex"; -import type React from "react"; -import type { WalletConnectOptions } from "@vechain/wallet-connect"; -import type { WalletSource } from "@vechain/wallet-kit"; +import type { Options } from '@vechain/connex'; +import type React from 'react'; +import type { WalletConnectOptions } from '@vechain/wallet-connect'; +import type { WalletSource } from '@vechain/wallet-kit'; export interface AccountState { - address: string | null; - source: WalletSource | null; + address: string | null; + source: WalletSource | null; } /** @@ -28,10 +28,10 @@ export type SetSource = (wallet: WalletSource) => void; * @param persistState - An option to persist state. Defaults to false */ export interface ConnexProviderOptions { - children: React.ReactNode; - nodeOptions: Omit; - walletConnectOptions?: WalletConnectOptions; - persistState?: boolean; + children: React.ReactNode; + nodeOptions: Omit; + walletConnectOptions?: WalletConnectOptions; + persistState?: boolean; } /** @@ -48,13 +48,13 @@ export interface ConnexProviderOptions { */ export interface ConnexContext { - connex: Connex; - wallet: { - setSource: SetSource; - setAccount: SetAccount; - availableWallets: WalletSource[]; - wallets: WalletSource[]; - accountState: AccountState; - disconnect: () => void; - }; + connex: Connex; + wallet: { + setSource: SetSource; + setAccount: SetAccount; + availableWallets: WalletSource[]; + wallets: WalletSource[]; + accountState: AccountState; + disconnect: () => void; + }; } diff --git a/packages/wallet-connect/src/client.ts b/packages/wallet-connect/src/client.ts index bcf313b1..16b053b8 100644 --- a/packages/wallet-connect/src/client.ts +++ b/packages/wallet-connect/src/client.ts @@ -1,38 +1,40 @@ -import { SignClient } from "@walletconnect/sign-client"; +import { SignClient } from '@walletconnect/sign-client'; import type { - ResolvedSignClient, - WalletConnectOptions, - WCClient, -} from "./types"; + ResolvedSignClient, + WalletConnectOptions, + WCClient +} from './types'; const _cachedClients: Record = {}; export const newWcClient = ({ - projectId, - metadata, + projectId, + metadata }: WalletConnectOptions): WCClient => { - const cachedClient = _cachedClients[projectId]; + const cachedClient = _cachedClients[projectId]; - if (cachedClient) { - return cachedClient; - } + if (cachedClient) { + return cachedClient; + } - const _signClient = SignClient.init({ - projectId, - metadata, - }); + const _signClient = SignClient.init({ + projectId, + metadata + }); - const client: WCClient = { - get: async (): Promise => { - try { - return await _signClient; - } catch (e) { - throw new Error(`Failed to initialise the wallet connect sign client`); - } - }, - }; + const client: WCClient = { + get: async (): Promise => { + try { + return await _signClient; + } catch (e) { + throw new Error( + `Failed to initialise the wallet connect sign client` + ); + } + } + }; - _cachedClients[projectId] = client; + _cachedClients[projectId] = client; - return client; + return client; }; diff --git a/packages/wallet-connect/src/constants.ts b/packages/wallet-connect/src/constants.ts index a0c7589f..fc70546d 100644 --- a/packages/wallet-connect/src/constants.ts +++ b/packages/wallet-connect/src/constants.ts @@ -1,6 +1,6 @@ export enum DefaultMethods { - RequestTransaction = "thor_sendTransaction", - SignCertificate = "thor_signCertificate", + RequestTransaction = 'thor_sendTransaction', + SignCertificate = 'thor_signCertificate' } export enum DefaultEvents {} diff --git a/packages/wallet-connect/src/index.ts b/packages/wallet-connect/src/index.ts index 49e0ec14..ae707d36 100644 --- a/packages/wallet-connect/src/index.ts +++ b/packages/wallet-connect/src/index.ts @@ -1,13 +1,13 @@ -import { newWcSigner } from "./signer"; -import { newWeb3Modal } from "./web3-modal"; -import { newWcClient } from "./client"; +import { newWcSigner } from './signer'; +import { newWeb3Modal } from './web3-modal'; +import { newWcClient } from './client'; export type { - WCSigner, - WCSignerOptions, - WalletConnectOptions, - ResolvedSignClient, - WCClient, -} from "./types"; + WCSigner, + WCSignerOptions, + WalletConnectOptions, + ResolvedSignClient, + WCClient +} from './types'; export { newWcSigner, newWeb3Modal, newWcClient }; diff --git a/packages/wallet-connect/src/signer.ts b/packages/wallet-connect/src/signer.ts index 687aab0c..c24c39ee 100644 --- a/packages/wallet-connect/src/signer.ts +++ b/packages/wallet-connect/src/signer.ts @@ -1,214 +1,216 @@ /// -import type { SessionTypes } from "@walletconnect/types"; -import type { ProposalTypes } from "@walletconnect/types/dist/types/sign-client/proposal"; -import type { EngineTypes } from "@walletconnect/types/dist/types/sign-client/engine"; -import { getSdkError } from "@walletconnect/utils"; -import type { SignClient } from "@walletconnect/sign-client/dist/types/client"; -import type { WCSigner, WCSignerOptions } from "./types"; -import { DefaultEvents, DefaultMethods } from "./constants"; +import type { SessionTypes } from '@walletconnect/types'; +import type { ProposalTypes } from '@walletconnect/types/dist/types/sign-client/proposal'; +import type { EngineTypes } from '@walletconnect/types/dist/types/sign-client/engine'; +import { getSdkError } from '@walletconnect/utils'; +import type { SignClient } from '@walletconnect/sign-client/dist/types/client'; +import type { WCSigner, WCSignerOptions } from './types'; +import { DefaultEvents, DefaultMethods } from './constants'; interface SessionAccount { - networkIdentifier: string; - address: string; - topic: string; + networkIdentifier: string; + address: string; + topic: string; } export const newWcSigner = ({ - genesisId, - wcClient, - web3Modal, - onDisconnected, + genesisId, + wcClient, + web3Modal, + onDisconnected }: WCSignerOptions): WCSigner => { - const chainId = `vechain:${genesisId.slice(-32)}`; - let session: SessionTypes.Struct | undefined; - - wcClient - .get() - .then((clientInstance) => { - listenToEvents(clientInstance); - restoreSession(clientInstance); - }) - .catch(() => { - throw new Error(`Failed to initialise the wallet connect sign client`); - }); - - const makeRequest = async ( - params: EngineTypes.RequestParams["request"], - signer?: string - ): Promise => { - const sessionTopic = await getSessionTopic(signer); - - const signClient = await wcClient.get(); - - return signClient.request({ - topic: sessionTopic, - chainId, - request: params, - }); - }; - - const signTx = async ( - message: Connex.Vendor.TxMessage, - options: Connex.Signer.TxOptions - ): Promise => { - return makeRequest({ - method: DefaultMethods.RequestTransaction, - params: [{ message, options }], - }); - }; - - const signCert = async ( - message: Connex.Vendor.CertMessage, - options: Connex.Signer.CertOptions - ): Promise => { - return makeRequest({ - method: DefaultMethods.SignCertificate, - params: [{ message, options }], - }); - }; - - const disconnect = async (): Promise => { - if (!session) return; - - const topic = session.topic; - session = undefined; - - const signClient = await wcClient.get(); - - try { - await signClient.disconnect({ - topic, - reason: getSdkError("USER_DISCONNECTED"), - }); - } catch (e) { - throw new Error(`SignClient.disconnect failed`); - } - }; - - /** - * Validates the requested account and network against a request - * @param requestedAddress - The optional requested account address - */ - const validateSession = ( - requestedAddress?: string - ): SessionAccount | undefined => { - if (!session) return; - - const firstAccount = session.namespaces.vechain.accounts[0]; - - const address = firstAccount.split(":")[2]; - const networkIdentifier = firstAccount.split(":")[1]; - - // Return undefined if the network identifier doesn't match - if (networkIdentifier !== genesisId.slice(-32)) return; - - // Return undefined if the address doesn't match - if ( - requestedAddress && - requestedAddress.toLowerCase() !== address.toLowerCase() - ) - return; + const chainId = `vechain:${genesisId.slice(-32)}`; + let session: SessionTypes.Struct | undefined; + + wcClient + .get() + .then((clientInstance) => { + listenToEvents(clientInstance); + restoreSession(clientInstance); + }) + .catch(() => { + throw new Error( + `Failed to initialise the wallet connect sign client` + ); + }); - return { - address, - networkIdentifier, - topic: session.topic, + const makeRequest = async ( + params: EngineTypes.RequestParams['request'], + signer?: string + ): Promise => { + const sessionTopic = await getSessionTopic(signer); + + const signClient = await wcClient.get(); + + return signClient.request({ + topic: sessionTopic, + chainId, + request: params + }); + }; + + const signTx = async ( + message: Connex.Vendor.TxMessage, + options: Connex.Signer.TxOptions + ): Promise => { + return makeRequest({ + method: DefaultMethods.RequestTransaction, + params: [{ message, options }] + }); + }; + + const signCert = async ( + message: Connex.Vendor.CertMessage, + options: Connex.Signer.CertOptions + ): Promise => { + return makeRequest({ + method: DefaultMethods.SignCertificate, + params: [{ message, options }] + }); + }; + + const disconnect = async (): Promise => { + if (!session) return; + + const topic = session.topic; + session = undefined; + + const signClient = await wcClient.get(); + + try { + await signClient.disconnect({ + topic, + reason: getSdkError('USER_DISCONNECTED') + }); + } catch (e) { + throw new Error(`SignClient.disconnect failed`); + } }; - }; - const getSessionTopic = async ( - requestedAccount?: string - ): Promise => { - const validation = validateSession(requestedAccount); + /** + * Validates the requested account and network against a request + * @param requestedAddress - The optional requested account address + */ + const validateSession = ( + requestedAddress?: string + ): SessionAccount | undefined => { + if (!session) return; + + const firstAccount = session.namespaces.vechain.accounts[0]; + + const address = firstAccount.split(':')[2]; + const networkIdentifier = firstAccount.split(':')[1]; + + // Return undefined if the network identifier doesn't match + if (networkIdentifier !== genesisId.slice(-32)) return; + + // Return undefined if the address doesn't match + if ( + requestedAddress && + requestedAddress.toLowerCase() !== address.toLowerCase() + ) + return; + + return { + address, + networkIdentifier, + topic: session.topic + }; + }; - if (validation) return validation.topic; + const getSessionTopic = async ( + requestedAccount?: string + ): Promise => { + const validation = validateSession(requestedAccount); - const newSession = await connect(); + if (validation) return validation.topic; - return newSession.topic; - }; + const newSession = await connect(); - const connect = async (): Promise => { - const signClient = await wcClient.get(); + return newSession.topic; + }; - const namespace: ProposalTypes.RequiredNamespace = { - methods: Object.values(DefaultMethods), - chains: [chainId], - events: Object.values(DefaultEvents), + const connect = async (): Promise => { + const signClient = await wcClient.get(); + + const namespace: ProposalTypes.RequiredNamespace = { + methods: Object.values(DefaultMethods), + chains: [chainId], + events: Object.values(DefaultEvents) + }; + + try { + const requiredNamespaces: Record< + string, + ProposalTypes.RequiredNamespace + > = { + vechain: namespace + }; + + const { uri, approval } = await signClient.connect({ + requiredNamespaces + }); + + if (uri) { + await web3Modal.openModal({ uri, chains: namespace.chains }); + } + + return await new Promise((resolve, reject) => { + web3Modal.subscribeModal((ev: { open: boolean }) => { + if (!ev.open) { + reject(new Error('User closed modal')); + } + }); + + approval() + .then((newSession) => { + session = newSession; + resolve(newSession); + }) + .catch(reject); + }); + } finally { + web3Modal.closeModal(); + } }; - try { - const requiredNamespaces: Record< - string, - ProposalTypes.RequiredNamespace - > = { - vechain: namespace, - }; - - const { uri, approval } = await signClient.connect({ - requiredNamespaces, - }); - - if (uri) { - await web3Modal.openModal({ uri, chains: namespace.chains }); - } - - return await new Promise((resolve, reject) => { - web3Modal.subscribeModal((ev: { open: boolean }) => { - if (!ev.open) { - reject(new Error("User closed modal")); - } + const listenToEvents = (_client: SignClient): void => { + _client.on('session_update', ({ topic, params }) => { + const { namespaces } = params; + const _session = _client.session.get(topic); + session = { ..._session, namespaces }; + }); + + _client.on('session_delete', () => { + if (onDisconnected) onDisconnected(); + disconnect().catch(() => { + throw new Error('Failed to disconnect'); + }); }); + }; - approval() - .then((newSession) => { - session = newSession; - resolve(newSession); - }) - .catch(reject); - }); - } finally { - web3Modal.closeModal(); - } - }; - - const listenToEvents = (_client: SignClient): void => { - _client.on("session_update", ({ topic, params }) => { - const { namespaces } = params; - const _session = _client.session.get(topic); - session = { ..._session, namespaces }; - }); - - _client.on("session_delete", () => { - if (onDisconnected) onDisconnected(); - disconnect().catch(() => { - throw new Error("Failed to disconnect"); - }); - }); - }; - - const restoreSession = (_client: SignClient): void => { - if (typeof session !== "undefined") return; - - const sessionKeys = _client.session.keys; - - for (const key of sessionKeys) { - const _session = _client.session.get(key); - const accounts = _session.namespaces.vechain.accounts; - - for (const acc of accounts) { - if (acc.split(":")[1] === genesisId.slice(-32)) { - session = _session; - return; + const restoreSession = (_client: SignClient): void => { + if (typeof session !== 'undefined') return; + + const sessionKeys = _client.session.keys; + + for (const key of sessionKeys) { + const _session = _client.session.get(key); + const accounts = _session.namespaces.vechain.accounts; + + for (const acc of accounts) { + if (acc.split(':')[1] === genesisId.slice(-32)) { + session = _session; + return; + } + } } - } - } - }; - - return { - signTx, - signCert, - disconnect, - genesisId, - }; + }; + + return { + signTx, + signCert, + disconnect, + genesisId + }; }; diff --git a/packages/wallet-connect/src/types.d.ts b/packages/wallet-connect/src/types.d.ts index 090ab4be..c1e4deea 100644 --- a/packages/wallet-connect/src/types.d.ts +++ b/packages/wallet-connect/src/types.d.ts @@ -1,6 +1,6 @@ -import type { WalletConnectModal } from "@walletconnect/modal"; -import type { SignClientTypes } from "@walletconnect/types"; -import type { SignClient } from "@walletconnect/sign-client"; +import type { WalletConnectModal } from '@walletconnect/modal'; +import type { SignClientTypes } from '@walletconnect/types'; +import type { SignClient } from '@walletconnect/sign-client'; export type ResolvedSignClient = Awaited>; @@ -9,22 +9,22 @@ export type ResolvedSignClient = Awaited>; * */ export type WCSigner = Connex.Signer & { - /** - * Disconnects and cleans up the WalletConnect session - */ - disconnect: () => Promise; + /** + * Disconnects and cleans up the WalletConnect session + */ + disconnect: () => Promise; - /** - * The genesis ID of the current signer - */ - genesisId: string; + /** + * The genesis ID of the current signer + */ + genesisId: string; }; export interface WCClient { - /** - * Gets the initialized WalletConnect SignClient - */ - get: () => Promise; + /** + * Gets the initialized WalletConnect SignClient + */ + get: () => Promise; } /** @@ -35,8 +35,8 @@ export interface WCClient { * @param logger - The logger or log level to use */ export interface WalletConnectOptions { - projectId: string; - metadata: SignClientTypes.Options["metadata"]; + projectId: string; + metadata: SignClientTypes.Options['metadata']; } /** @@ -47,8 +47,8 @@ export interface WalletConnectOptions { * @param genesisId - The genesis ID of the VeChain network you want to connect to */ export interface WCSignerOptions { - wcClient: WCClient; - web3Modal: WalletConnectModal; - onDisconnected?: () => void; - genesisId: string; + wcClient: WCClient; + web3Modal: WalletConnectModal; + onDisconnected?: () => void; + genesisId: string; } diff --git a/packages/wallet-connect/src/web3-modal.ts b/packages/wallet-connect/src/web3-modal.ts index f0453585..1f5f571d 100644 --- a/packages/wallet-connect/src/web3-modal.ts +++ b/packages/wallet-connect/src/web3-modal.ts @@ -1,4 +1,4 @@ -import { WalletConnectModal } from "@walletconnect/modal"; +import { WalletConnectModal } from '@walletconnect/modal'; const _cachedModals: Record = {}; @@ -7,34 +7,34 @@ const _cachedModals: Record = {}; * @param projectId - Your WalletConnect project ID */ export const newWeb3Modal = (projectId: string): WalletConnectModal => { - const cached = _cachedModals[projectId]; + const cached = _cachedModals[projectId]; - if (cached) { - return cached; - } + if (cached) { + return cached; + } - const modal = new WalletConnectModal({ - projectId, - explorerRecommendedWalletIds: "NONE", - mobileWallets: [ - { - name: "VeWorld", - id: "veworld-mobile", - links: { - native: "veworld://org.vechain.veworld.app/", - universal: "https://veworld.com", + const modal = new WalletConnectModal({ + projectId, + explorerRecommendedWalletIds: 'NONE', + mobileWallets: [ + { + name: 'VeWorld', + id: 'veworld-mobile', + links: { + native: 'veworld://org.vechain.veworld.app/', + universal: 'https://veworld.com' + } + } + ], + themeVariables: { + '--wcm-z-index': '99999999' }, - }, - ], - themeVariables: { - "--wcm-z-index": "99999999", - }, - walletImages: { - "veworld-mobile": "https://www.veworld.net/assets/logo/logo.svg", - }, - }); + walletImages: { + 'veworld-mobile': 'https://www.veworld.net/assets/logo/logo.svg' + } + }); - _cachedModals[projectId] = modal; + _cachedModals[projectId] = modal; - return modal; + return modal; }; diff --git a/packages/wallet-kit/src/connex.ts b/packages/wallet-kit/src/connex.ts index 3b60ba94..13717cf2 100644 --- a/packages/wallet-kit/src/connex.ts +++ b/packages/wallet-kit/src/connex.ts @@ -1,67 +1,67 @@ -import { Framework } from "@vechain/connex-framework"; -import type { WalletConnectOptions } from "@vechain/wallet-connect"; -import type { Genesis } from "./types"; -import { WalletSource } from "./wallet"; -import { createSigner } from "./signer"; -import { normalizeGenesisBlock } from "./genesis"; -import { createVendorDriver } from "./vendor-driver"; -import { createDriverNoVendor } from "./thor-driver"; +import { Framework } from '@vechain/connex-framework'; +import type { WalletConnectOptions } from '@vechain/wallet-connect'; +import type { Genesis } from './types'; +import { WalletSource } from './wallet'; +import { createSigner } from './signer'; +import { normalizeGenesisBlock } from './genesis'; +import { createVendorDriver } from './vendor-driver'; +import { createDriverNoVendor } from './thor-driver'; interface BaseConnexOptions { - nodeUrl: string; - genesis: Genesis; + nodeUrl: string; + genesis: Genesis; } interface NoWalletConfigOptions extends BaseConnexOptions { - source: - | WalletSource.VeWorldExtension - | WalletSource.Sync - | WalletSource.Sync2; + source: + | WalletSource.VeWorldExtension + | WalletSource.Sync + | WalletSource.Sync2; } interface WalletConnectConfigOptions extends BaseConnexOptions { - source: WalletSource.WalletConnect; - options: WalletConnectOptions; - onDisconnected: () => void; + source: WalletSource.WalletConnect; + options: WalletConnectOptions; + onDisconnected: () => void; } type ConnexOptions = NoWalletConfigOptions | WalletConnectConfigOptions; const createConnexInstance = (options: ConnexOptions): Connex => { - const { source, genesis } = options; + const { source, genesis } = options; - const genesisBlock = normalizeGenesisBlock(genesis); + const genesisBlock = normalizeGenesisBlock(genesis); - let signer: Promise; + let signer: Promise; - if (source === WalletSource.WalletConnect) { - signer = createSigner({ - source: options.source, - genesis: options.genesis, - options: options.options, - onDisconnected: options.onDisconnected, - }); - } else { - signer = createSigner({ - source: options.source, - genesis: options.genesis, - }); - } + if (source === WalletSource.WalletConnect) { + signer = createSigner({ + source: options.source, + genesis: options.genesis, + options: options.options, + onDisconnected: options.onDisconnected + }); + } else { + signer = createSigner({ + source: options.source, + genesis: options.genesis + }); + } - // This is cached, so the `DriverNoVendor` is shared between wallet sources - const driverNoVendor = createDriverNoVendor(options.nodeUrl, genesisBlock); + // This is cached, so the `DriverNoVendor` is shared between wallet sources + const driverNoVendor = createDriverNoVendor(options.nodeUrl, genesisBlock); - // This is also cached based on the source - const vendorDriver = createVendorDriver(signer, source); + // This is also cached based on the source + const vendorDriver = createVendorDriver(signer, source); - vendorDriver.setNoVendor(driverNoVendor); + vendorDriver.setNoVendor(driverNoVendor); - const framework = new Framework(vendorDriver); + const framework = new Framework(vendorDriver); - return { - thor: framework.thor, - vendor: framework.vendor, - }; + return { + thor: framework.thor, + vendor: framework.vendor + }; }; export { createConnexInstance }; diff --git a/packages/wallet-kit/src/genesis.ts b/packages/wallet-kit/src/genesis.ts index a6a86c09..e50705a1 100644 --- a/packages/wallet-kit/src/genesis.ts +++ b/packages/wallet-kit/src/genesis.ts @@ -1,17 +1,17 @@ -import { genesisBlocks } from "@vechain/connex/esm/config"; -import type { Genesis } from "./types"; +import { genesisBlocks } from '@vechain/connex/esm/config'; +import type { Genesis } from './types'; const normalizeGenesisId = (genesis: Genesis): string => { - if (genesis === "main" || genesis === "test") - return genesisBlocks[genesis].id; + if (genesis === 'main' || genesis === 'test') + return genesisBlocks[genesis].id; - return genesis.id; + return genesis.id; }; const normalizeGenesisBlock = (genesis: Genesis): Connex.Thor.Block => { - if (genesis === "main" || genesis === "test") return genesisBlocks[genesis]; + if (genesis === 'main' || genesis === 'test') return genesisBlocks[genesis]; - return genesis; + return genesis; }; export { normalizeGenesisId, normalizeGenesisBlock }; diff --git a/packages/wallet-kit/src/index.ts b/packages/wallet-kit/src/index.ts index 3cbc415e..4684031f 100644 --- a/packages/wallet-kit/src/index.ts +++ b/packages/wallet-kit/src/index.ts @@ -1,2 +1,2 @@ -export * from "./connex"; -export * from "./wallet"; +export * from './connex'; +export * from './wallet'; diff --git a/packages/wallet-kit/src/signer.ts b/packages/wallet-kit/src/signer.ts index c9f6a09a..42a19854 100644 --- a/packages/wallet-kit/src/signer.ts +++ b/packages/wallet-kit/src/signer.ts @@ -1,79 +1,79 @@ import type { - WalletConnectOptions, - WCSigner, -} from "@vechain/wallet-connect/dist"; + WalletConnectOptions, + WCSigner +} from '@vechain/wallet-connect/dist'; import { - newWcClient, - newWcSigner, - newWeb3Modal, -} from "@vechain/wallet-connect/dist"; -import type { Connex } from "@vechain/connex"; -import { createSync, createSync2 } from "@vechain/connex/esm/signer"; -import { WalletSource } from "./wallet"; -import type { Genesis } from "./types"; -import { normalizeGenesisId } from "./genesis"; + newWcClient, + newWcSigner, + newWeb3Modal +} from '@vechain/wallet-connect/dist'; +import type { Connex } from '@vechain/connex'; +import { createSync, createSync2 } from '@vechain/connex/esm/signer'; +import { WalletSource } from './wallet'; +import type { Genesis } from './types'; +import { normalizeGenesisId } from './genesis'; interface WCOptions { - source: WalletSource.WalletConnect; - genesis: Genesis; - options: WalletConnectOptions; - onDisconnected: () => void; + source: WalletSource.WalletConnect; + genesis: Genesis; + options: WalletConnectOptions; + onDisconnected: () => void; } interface DefaultOptions { - source: - | WalletSource.Sync - | WalletSource.Sync2 - | WalletSource.VeWorldExtension; - genesis: Genesis; + source: + | WalletSource.Sync + | WalletSource.Sync2 + | WalletSource.VeWorldExtension; + genesis: Genesis; } type ICreateVendor = DefaultOptions | WCOptions; export const createSigner = (params: ICreateVendor): Promise => { - const { source, genesis } = params; + const { source, genesis } = params; - const genesisId = normalizeGenesisId(genesis); + const genesisId = normalizeGenesisId(genesis); - if (source === WalletSource.VeWorldExtension) { - if (!window.vechain) { - throw new Error("VeWorld Extension is not installed"); - } - - const signer = window.vechain.newConnexSigner(genesisId); + if (source === WalletSource.VeWorldExtension) { + if (!window.vechain) { + throw new Error('VeWorld Extension is not installed'); + } - return Promise.resolve(signer); - } + const signer = window.vechain.newConnexSigner(genesisId); - if (source === WalletSource.WalletConnect) { - const { onDisconnected, options } = params; + return Promise.resolve(signer); + } - const { projectId, metadata } = options; + if (source === WalletSource.WalletConnect) { + const { onDisconnected, options } = params; - const wcClient = newWcClient({ - projectId, - metadata, - }); + const { projectId, metadata } = options; - const web3Modal = newWeb3Modal(projectId); + const wcClient = newWcClient({ + projectId, + metadata + }); - const wcSigner: WCSigner = newWcSigner({ - genesisId, - wcClient, - web3Modal, - onDisconnected, - }); + const web3Modal = newWeb3Modal(projectId); - return Promise.resolve(wcSigner); - } + const wcSigner: WCSigner = newWcSigner({ + genesisId, + wcClient, + web3Modal, + onDisconnected + }); - if (source === WalletSource.Sync) { - if (!window.connex) { - throw new Error("User is not in a Sync wallet"); + return Promise.resolve(wcSigner); } - return createSync(genesisId); - } + if (source === WalletSource.Sync) { + if (!window.connex) { + throw new Error('User is not in a Sync wallet'); + } + + return createSync(genesisId); + } - return createSync2(genesisId); + return createSync2(genesisId); }; diff --git a/packages/wallet-kit/src/thor-driver.ts b/packages/wallet-kit/src/thor-driver.ts index 0fe64b09..258f48af 100644 --- a/packages/wallet-kit/src/thor-driver.ts +++ b/packages/wallet-kit/src/thor-driver.ts @@ -1,27 +1,27 @@ -import { DriverNoVendor } from "@vechain/connex-driver/dist/driver-no-vendor"; -import { SimpleNet } from "@vechain/connex-driver"; -import type { Genesis } from "./types"; -import { normalizeGenesisBlock } from "./genesis"; +import { DriverNoVendor } from '@vechain/connex-driver/dist/driver-no-vendor'; +import { SimpleNet } from '@vechain/connex-driver'; +import type { Genesis } from './types'; +import { normalizeGenesisBlock } from './genesis'; let previousDriver: DriverNoVendor | undefined; const createDriverNoVendor = ( - nodeUrl: string, - genesis: Genesis + nodeUrl: string, + genesis: Genesis ): DriverNoVendor => { - const genesisBlock = normalizeGenesisBlock(genesis); + const genesisBlock = normalizeGenesisBlock(genesis); - if (previousDriver && previousDriver.genesis.id === genesisBlock.id) { - return previousDriver; - } + if (previousDriver && previousDriver.genesis.id === genesisBlock.id) { + return previousDriver; + } - const net = new SimpleNet(nodeUrl); + const net = new SimpleNet(nodeUrl); - const driver = new DriverNoVendor(net, genesisBlock); + const driver = new DriverNoVendor(net, genesisBlock); - previousDriver = driver; + previousDriver = driver; - return driver; + return driver; }; export { createDriverNoVendor }; diff --git a/packages/wallet-kit/src/types.d.ts b/packages/wallet-kit/src/types.d.ts index 78980676..0f6e4507 100644 --- a/packages/wallet-kit/src/types.d.ts +++ b/packages/wallet-kit/src/types.d.ts @@ -1,12 +1,12 @@ -import type { Connex1 } from "@vechain/connex/esm/signer"; +import type { Connex1 } from '@vechain/connex/esm/signer'; declare global { - interface Window { - vechain?: { - newConnexSigner: (genesisId: string) => Connex.Signer; - }; - connex?: Connex1; - } + interface Window { + vechain?: { + newConnexSigner: (genesisId: string) => Connex.Signer; + }; + connex?: Connex1; + } } -export type Genesis = "main" | "test" | Connex.Thor.Block; +export type Genesis = 'main' | 'test' | Connex.Thor.Block; diff --git a/packages/wallet-kit/src/vendor-driver.ts b/packages/wallet-kit/src/vendor-driver.ts index 0b604a97..c02fb198 100644 --- a/packages/wallet-kit/src/vendor-driver.ts +++ b/packages/wallet-kit/src/vendor-driver.ts @@ -1,22 +1,22 @@ -import { LazyDriver } from "@vechain/connex/esm/driver"; -import type { WalletSource } from "./wallet"; +import { LazyDriver } from '@vechain/connex/esm/driver'; +import type { WalletSource } from './wallet'; const _cachedDrivers: Record = {}; const createVendorDriver = ( - signer: Promise, - source: WalletSource + signer: Promise, + source: WalletSource ): LazyDriver => { - const cachedDriver = _cachedDrivers[source]; + const cachedDriver = _cachedDrivers[source]; - if (cachedDriver) { - return cachedDriver; - } + if (cachedDriver) { + return cachedDriver; + } - const driver = new LazyDriver(signer); - _cachedDrivers[source] = driver; + const driver = new LazyDriver(signer); + _cachedDrivers[source] = driver; - return driver; + return driver; }; export { createVendorDriver }; diff --git a/packages/wallet-kit/src/wallet.ts b/packages/wallet-kit/src/wallet.ts index 8cd229d2..05c1405d 100644 --- a/packages/wallet-kit/src/wallet.ts +++ b/packages/wallet-kit/src/wallet.ts @@ -3,27 +3,27 @@ */ enum WalletSource { - WalletConnect = "wallet-connect", - VeWorldExtension = "veworld-extension", - Sync2 = "sync2", - Sync = "sync", + WalletConnect = 'wallet-connect', + VeWorldExtension = 'veworld-extension', + Sync2 = 'sync2', + Sync = 'sync' } interface WalletConfig { - requiresCertificate: boolean; + requiresCertificate: boolean; } const DEFAULT_CONFIG: WalletConfig = { - requiresCertificate: true, + requiresCertificate: true }; const WalletMapping: Record = { - [WalletSource.WalletConnect]: { - requiresCertificate: false, - }, - [WalletSource.VeWorldExtension]: DEFAULT_CONFIG, - [WalletSource.Sync2]: DEFAULT_CONFIG, - [WalletSource.Sync]: DEFAULT_CONFIG, + [WalletSource.WalletConnect]: { + requiresCertificate: false + }, + [WalletSource.VeWorldExtension]: DEFAULT_CONFIG, + [WalletSource.Sync2]: DEFAULT_CONFIG, + [WalletSource.Sync]: DEFAULT_CONFIG }; export { WalletSource, WalletMapping }; diff --git a/yarn.lock b/yarn.lock index 6c5d9884..cdafe691 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8574,7 +8574,7 @@ ethers@^5.7.1, ethers@^5.7.2: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" -ethers@^6.7.1, ethers@^6.8.0: +ethers@^6.4.0, ethers@^6.7.1: version "6.8.0" resolved "https://registry.npmjs.org/ethers/-/ethers-6.8.0.tgz" integrity sha512-zrFbmQRlraM+cU5mE4CZTLBurZTs2gdp2ld0nG/f3ecBK+x6lZ69KSxBqZ4NjclxwfTxl5LeNufcBbMsTdY53Q==