diff --git a/CHANGELOG.md b/CHANGELOG.md index a32413b..860c8a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +# v5.0.0 (Mon Jul 29 2024) + +#### 💥 Breaking Change + +- Removes Universal support with associated flags, prompts, and templates +- Adds architectural updates to EVM templates + +#### Authors: 1 + +- pbillingsby ([@PBillingsby](https://github.com/PBillingsby)) + # v4.13.0 (Fri Apr 12 2024) #### 🚀 Enhancement diff --git a/core/create-app.tsx b/core/create-app.tsx index b8db908..7296f53 100644 --- a/core/create-app.tsx +++ b/core/create-app.tsx @@ -84,7 +84,6 @@ export async function createApp(config: CreateMagicAppConfig) { ...(await buildTemplate({ ...config, chain: undefined, - product: undefined, configuration: undefined, isChosenTemplateValid: false, isQuickstart: false, diff --git a/core/utils/templateMappings.ts b/core/utils/templateMappings.ts index a339886..4127482 100644 --- a/core/utils/templateMappings.ts +++ b/core/utils/templateMappings.ts @@ -3,7 +3,6 @@ import { AuthTypePrompt, BlockchainNetworkPrompt, ConfigurationPrompt, - ProductPrompt, ProjectNamePrompt, PublishableApiKeyPrompt, } from 'scaffolds/prompts'; @@ -14,27 +13,16 @@ import DedicatedScaffold, { flags as dedicatedFlags } from '../../scaffolds/next import FlowDedicatedScaffold, { flags as flowDedicatedFlags, } from '../../scaffolds/nextjs-flow-dedicated-wallet/scaffold'; -import FlowUniversalScaffold, { - flags as flowUniversalFlags, -} from '../../scaffolds/nextjs-flow-universal-wallet/scaffold'; import SolanaDedicatedScaffold, { flags as solanaDedicatedFlags, } from '../../scaffolds/nextjs-solana-dedicated-wallet/scaffold'; -import UniversalScaffold, { flags as universalFlags } from '../../scaffolds/nextjs-universal-wallet/scaffold'; import { Timer } from './timer'; export type Chain = 'evm' | 'solana' | 'flow'; -export type Template = - | 'nextjs-dedicated-wallet' - | 'nextjs-universal-wallet' - | 'nextjs-solana-dedicated-wallet' - | 'nextjs-flow-universal-wallet' - | 'nextjs-flow-dedicated-wallet'; - -export type Product = 'universal' | 'dedicated'; +export type Template = 'nextjs-dedicated-wallet' | 'nextjs-solana-dedicated-wallet' | 'nextjs-flow-dedicated-wallet'; + type ConfigType = CreateMagicAppConfig & { chain: Chain | undefined; - product: Product | undefined; configuration: string | undefined; isChosenTemplateValid: boolean; isQuickstart: boolean; @@ -43,11 +31,9 @@ type ConfigType = CreateMagicAppConfig & { function mapTemplateToChain(template: string): Chain | undefined { switch (template) { case 'nextjs-dedicated-wallet': - case 'nextjs-universal-wallet': return 'evm'; case 'nextjs-solana-dedicated-wallet': return 'solana'; - case 'nextjs-flow-universal-wallet': case 'nextjs-flow-dedicated-wallet': return 'flow'; default: @@ -55,20 +41,6 @@ function mapTemplateToChain(template: string): Chain | undefined { } } -function mapTemplateToProduct(template: string): Product | undefined { - switch (template) { - case 'nextjs-dedicated-wallet': - case 'nextjs-solana-dedicated-wallet': - case 'nextjs-flow-dedicated-wallet': - return 'dedicated'; - case 'nextjs-universal-wallet': - case 'nextjs-flow-universal-wallet': - return 'universal'; - default: - return undefined; - } -} - export async function mapTemplateToScaffold( template: string, appData: any, @@ -93,11 +65,6 @@ export async function mapTemplateToScaffold( data.loginMethods = await AuthTypePrompt.loginMethodsPrompt(); } return new DedicatedScaffold(data); - case 'nextjs-universal-wallet': - if (!data.network) { - data.network = await BlockchainNetworkPrompt.evmNetworkPrompt(); - } - return new UniversalScaffold(data); case 'nextjs-solana-dedicated-wallet': if (!data.network) { data.network = await BlockchainNetworkPrompt.solanaNetworkPrompt(); @@ -106,11 +73,6 @@ export async function mapTemplateToScaffold( data.loginMethods = await AuthTypePrompt.loginMethodsPrompt(); } return new SolanaDedicatedScaffold(data); - case 'nextjs-flow-universal-wallet': - if (!data.network) { - data.network = await BlockchainNetworkPrompt.flowNetworkPrompt(); - } - return new FlowUniversalScaffold(data); case 'nextjs-flow-dedicated-wallet': if (!data.network) { data.network = await BlockchainNetworkPrompt.flowNetworkPrompt(); @@ -128,12 +90,8 @@ export function mapTemplateToFlags(template: string): any { switch (template) { case 'nextjs-dedicated-wallet': return dedicatedFlags; - case 'nextjs-universal-wallet': - return universalFlags; case 'nextjs-solana-dedicated-wallet': return solanaDedicatedFlags; - case 'nextjs-flow-universal-wallet': - return flowUniversalFlags; case 'nextjs-flow-dedicated-wallet': return flowDedicatedFlags; default: @@ -145,7 +103,6 @@ const quickstartConfig = (config: ConfigType): ConfigType => ({ ...config, template: 'nextjs-dedicated-wallet', network: 'polygon-amoy', - product: 'dedicated', chain: 'evm', isChosenTemplateValid: true, isQuickstart: true, @@ -155,14 +112,14 @@ const solanaConfig = async (config: ConfigType): Promise => ({ ...config, template: 'nextjs-solana-dedicated-wallet', network: await BlockchainNetworkPrompt.solanaNetworkPrompt(), - product: 'dedicated', chain: 'solana', isChosenTemplateValid: true, isQuickstart: false, }); export const buildTemplate = async (appConfig: ConfigType): Promise => { - let config = appConfig; + let config = { ...appConfig }; + if (!config.projectName) { config.projectName = await ProjectNamePrompt.askProjectName(); } @@ -171,59 +128,54 @@ export const buildTemplate = async (appConfig: ConfigType): Promise config.configuration = await ConfigurationPrompt.askConfiguration(); if (config.configuration === 'quickstart') { - config = quickstartConfig(config); - return config; + return quickstartConfig(config); } } else { - config = { - ...config, - product: mapTemplateToProduct(config.template), - chain: mapTemplateToChain(config.template), - }; + config.chain = mapTemplateToChain(config.template); } - if (!config.chain && !config.network) { + if (!config.chain) { config.chain = await BlockchainNetworkPrompt.chainPrompt(); } if (!config.network) { - if (config.chain === 'solana') { - config = await solanaConfig(config); - } else if (config.chain === 'flow') { - config.network = await BlockchainNetworkPrompt.flowNetworkPrompt(); - } else if (config.chain === 'evm') { - config.network = await BlockchainNetworkPrompt.evmNetworkPrompt(); + switch (config.chain) { + case 'solana': + config = await solanaConfig(config); + break; + case 'flow': + config.network = await BlockchainNetworkPrompt.flowNetworkPrompt(); + break; + case 'evm': + config.network = await BlockchainNetworkPrompt.evmNetworkPrompt(); + break; + default: + config.network = await BlockchainNetworkPrompt.evmNetworkPrompt(); + break; } - } else if ( - config.network === 'ethereum' || - config.network === 'ethereum-sepolia' || - config.network === 'polygon' || - config.network === 'polygon-amoy' || - config.network === 'etherlink-testnet' - ) { - config.chain = 'evm'; - } else if (config.network === 'solana-devnet' || config.network === 'solana-mainnet') { - config.chain = 'solana'; } else { - config.chain = 'flow'; - } - - if (!config.product) { - config.product = await ProductPrompt.askProduct(); - - if (config.product === 'universal') { - if (config.chain === 'flow') { - config.template = 'nextjs-flow-universal-wallet'; - } else { - config.template = 'nextjs-universal-wallet'; - } - } else if (config.chain === 'flow') { - config.template = 'nextjs-flow-dedicated-wallet'; + const evmNetworks = [ + 'ethereum', + 'ethereum-sepolia', + 'polygon', + 'polygon-amoy', + 'etherlink-testnet', + 'zksync', + 'zksync-sepolia', + ]; + const solanaNetworks = ['solana-devnet', 'solana-mainnet']; + + if (evmNetworks.includes(config.network)) { + config.chain = 'evm'; + } else if (solanaNetworks.includes(config.network)) { + config.chain = 'solana'; } else { - config.template = 'nextjs-dedicated-wallet'; + config.chain = 'flow'; } - config.isChosenTemplateValid = true; } + config.template = config.chain === 'flow' ? 'nextjs-flow-dedicated-wallet' : 'nextjs-dedicated-wallet'; + config.isChosenTemplateValid = true; + return config; }; diff --git a/package.json b/package.json index 9927d05..d3fdd3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "make-magic", - "version": "4.13.0", + "version": "5.0.0", "description": "A tool for quickly scaffolding an app with Magic authentication baked-in!", "repository": "magiclabs/create-magic-app", "license": "MIT", @@ -81,11 +81,17 @@ "dependencies": { "@segment/analytics-node": "^1.1.0", "binaryextensions": "^4.18.0", - "ejs": "^3.1.9", + "ejs": "^3.1.10", "enquirer": "^2.4.0", "fs-extra": "^11.1.1", "ora": "^5.1.0", "pretty-time": "^1.1.0", "textextensions": "^5.16.0" + }, + "resolutions": { + "ejs": "^3.1.10", + "tar": "^6.2.1", + "braces": "^3.0.3", + "merge": "^2.1.1" } -} +} \ No newline at end of file diff --git a/scaffolds/dev-data.ts b/scaffolds/dev-data.ts index d2da63e..255b341 100644 --- a/scaffolds/dev-data.ts +++ b/scaffolds/dev-data.ts @@ -11,20 +11,10 @@ export const templateDevData = { loginMethods: ['EmailOTP', 'SMSOTP'], projectName: 'My Flow Dedicated Wallet', }, - 'nextjs-flow-universal-wallet': { - network: 'flow-testnet', - publishableApiKey: 'pk_live_8D6C562ABCA3140A', - projectName: 'My Flow Universal Wallet', - }, 'nextjs-solana-dedicated-wallet': { network: 'solana-devnet', publishableApiKey: 'pk_live_FD2D70B32ABE11BD', loginMethods: ['EmailOTP', 'SMSOTP'], projectName: 'My Solana Dedicated Wallet', }, - 'nextjs-universal-wallet': { - network: 'ethereum-sepolia', - publishableApiKey: 'pk_live_8D6C562ABCA3140A', - projectName: 'My Universal Wallet', - }, }; diff --git a/scaffolds/nextjs-dedicated-wallet/scaffold.ts b/scaffolds/nextjs-dedicated-wallet/scaffold.ts index 44b17a4..7ca8365 100644 --- a/scaffolds/nextjs-dedicated-wallet/scaffold.ts +++ b/scaffolds/nextjs-dedicated-wallet/scaffold.ts @@ -1,6 +1,6 @@ import { Flags } from '../../core/flags'; import BaseScaffold, { ExecaCommand } from '../../core/types/BaseScaffold'; -import { AuthTypePrompt, BlockchainNetworkPrompt, PublishableApiKeyPrompt } from '../../scaffolds/prompts'; +import { AuthTypePrompt, BlockchainNetworkPrompt, PublishableApiKeyPrompt } from '../prompts'; export type Data = BlockchainNetworkPrompt.Data & PublishableApiKeyPrompt.Data & AuthTypePrompt.Data; @@ -41,12 +41,13 @@ export default class DedicatedScaffold extends BaseScaffold { './src/components/magic/wallet-methods/Disconnect.tsx', './src/components/magic/wallet-methods/GetIdToken.tsx', './src/components/magic/wallet-methods/GetMetadata.tsx', - './src/components/magic/Dashboard.tsx', - './src/components/magic/DevLinks.tsx', - './src/components/magic/Header.tsx', + './src/components/ui/Dashboard.tsx', + './src/components/ui/DevLinks.tsx', + './src/components/ui/Header.tsx', './src/components/magic/Login.tsx', - './src/components/magic/MagicProvider.tsx', - './src/components/magic/MagicDashboardRedirect.tsx', + './src/hooks/MagicProvider.tsx', + './src/hooks/Web3.tsx', + './src/components/ui/MagicDashboardRedirect.tsx', './src/pages', './src/styles', './src/utils', diff --git a/scaffolds/nextjs-dedicated-wallet/template/README.md b/scaffolds/nextjs-dedicated-wallet/template/README.md index 8525350..ed7bca5 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/README.md +++ b/scaffolds/nextjs-dedicated-wallet/template/README.md @@ -2,6 +2,53 @@ This scaffold is meant to help you bootstrap your own projects with Magic's [Ded The folder structure of this scaffold is designed to encapsulate all things Magic into one place so you can easily add or remove components and functionality. For example, all Magic-specific components are in the `src/components/magic` directory while generic UI components are in the `src/components/ui` directory. +## Usage + +This project uses Next.js but relies on fairly standard React components and hooks. Magic-related components are in the `/src/components/magic` directory, all other UI components are in the `/src/components/ui` directory, utility functions are in `/src/utils` and hooks are in the `/src/hooks` directory. + +Use this project as a reference for how to use this template or implement Magic in your own project. Key areas to look at include: + +### Custom Hooks +In the `/src/hooks` directory, the `MagicProvider` hook sets up and provides a Magic instance for using the Magic SDK and OAuth extension. Additionally, the `Web3.tsx` hook initializes and provides a Web3 instance using the Magic provider. + +### Login Functionality +The `Login.tsx` component, located in `/src/components/magic`, manages the display and functionality of various login methods on the login page. It is a central piece for handling user authentication. + +One thing to note is that whenever `getInfo` is called from any of the authentication providers, the user session is rehydrated. + +Here is a list of the available authentication methods: +- `Discord.tsx` - Handles authentication using Discord OAuth. +- `Facebook.tsx` - Handles authentication using Facebook OAuth. +- `Google.tsx` - Handles authentication using Google OAuth. +- `Twitch.tsx` - Handles authentication using Twitch OAuth. +- `EmailOTP.tsx` - Handles authentication using email one-time password (OTP). +- `Github.tsx` - Handles authentication using GitHub OAuth. +- `SMSOTP.tsx` - Handles authentication using SMS one-time password (OTP). +- `Twitter.tsx` - Handles authentication using Twitter OAuth. + +### User Interaction Components + +- `/src/components/magic/auth`: This contains all of the authentication methods. + +- `/src/components/magic/cards`: The `SendTransactionCard.tsx` component facilitate transaction processes, `UserInfoCard.tsx` displays user information, `WalletMethodsCard.tsx` manages authentication tokens and user metadata and `SmartContract.tsx` interacts with a basic storage contract. + +- `/src/components/magic/wallet-methods`: This directory includes several components that provide specific functionalities: + - `Disconnect.tsx` handles the disconnection of the user's session from the application. + - `GetIdToken.tsx` retrieves the ID token for the authenticated user. + - `GetMetadata.tsx` retrieves metadata information about the authenticated user. This will rehydrate the user session every time it is rendered. It does this when calling the `getInfo` function. The user session is rehydrated whenever `getInfo` is invoked + - `UpdateEmail.tsx` allows the user to update their email address. + +### Utility Functions +The `/src/utils` directory includes utility files that support various aspects of the application: +- `common.ts` manages user authentication processes. The `logout` function handle the process of logging out a user and clearing their authentication data, while `saveUserInfo` saves the user's token, login method, and address to local storage. +- `network.ts` defines network configurations and utilities, such as URLs, chain IDs, tokens, and block explorer links. +- `showToast.ts` handles customizable toast notifications. +- `smartContract.ts` contains functions and configurations for interacting with smart contracts, such as retrieving contract IDs, determining testnet status, generating hash links, and defining contract ABIs. + +These utilities are essential for supporting various aspects of the application. + +### UI Components +The `/src/components/ui` directory contains reusable UI components for building the user interface. This includes components for creating and styling cards (`Card`, `CardHeader`, `CardLabel`), layout elements for the dashboard (`Dashboard`), separators (`Divider`), error messages (`ErrorText`), form elements (`FormButton`, `FormInput`), redirection handling within the Magic dashboard (`MagicDashboardRedirect`), spacing elements (`Spacer`), loading indicators (`Spinner`), and displaying transaction history (`TransactionHistory`). ## Next.js This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). diff --git a/scaffolds/nextjs-dedicated-wallet/template/package.json b/scaffolds/nextjs-dedicated-wallet/template/package.json index e3a5b59..383805c 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/package.json +++ b/scaffolds/nextjs-dedicated-wallet/template/package.json @@ -9,13 +9,13 @@ "lint": "next lint --fix" }, "dependencies": { - "@magic-ext/oauth": "^15.0.0", + "@magic-ext/oauth": "^22.0.7", "@types/node": "20.3.3", "@types/react": "18.2.14", "@types/react-dom": "18.2.6", "autoprefixer": "10.4.14", "classnames": "^2.3.2", - "magic-sdk": "^21.5.0", + "magic-sdk": "^28.0.7", "next": "13.4.7", "postcss": "8.4.24", "react": "18.2.0", @@ -29,4 +29,4 @@ "eslint": "^8.45.0", "eslint-config-next": "13.4.10" } -} +} \ No newline at end of file diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Login.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Login.tsx index 9cac8d6..11f47ee 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Login.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Login.tsx @@ -1,8 +1,8 @@ import { LoginProps } from '@/utils/types' -import Header from './Header' +import Header from '@/components/ui/Header' <% loginMethods.forEach(authType => { %> -<%-`import ${authType.replaceAll(' ', '')} from './auth/${authType.replaceAll(' ', '')}';`-%> -<% }) %> + <%-`import ${authType.replaceAll(' ', '')} from './auth/${authType.replaceAll(' ', '')}';`-%> + <% }) %> const Login = ({ token, setToken }: LoginProps) => { return ( diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Discord.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Discord.tsx index 65a8718..e25d35a 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Discord.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Discord.tsx @@ -1,5 +1,5 @@ import { LoginProps } from '@/utils/types'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import { useEffect, useState } from 'react'; import { saveUserInfo } from '@/utils/common'; import Spinner from '@/components/ui/Spinner'; @@ -21,7 +21,7 @@ const Discord = ({ token, setToken }: LoginProps) => { try { if (magic) { const result = await magic?.oauth.getRedirectResult(); - const metadata = await magic?.user.getMetadata(); + const metadata = await magic?.user.getInfo(); if (!metadata?.publicAddress) return; setToken(result.magic.idToken); saveUserInfo(result.magic.idToken, 'SOCIAL', metadata?.publicAddress); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx index 152156e..e49eeec 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/EmailOTP.tsx @@ -1,4 +1,4 @@ -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import showToast from '@/utils/showToast'; import Spinner from '../../ui/Spinner'; import { RPCError, RPCErrorCode } from 'magic-sdk'; @@ -23,8 +23,8 @@ const EmailOTP = ({ token, setToken }: LoginProps) => { setLoginInProgress(true); setEmailError(false); const token = await magic?.auth.loginWithEmailOTP({ email }); - - const metadata = await magic?.user.getMetadata(); + // Rehydrates the user session whenever getInfo is invoked + const metadata = await magic?.user.getInfo(); if (!token || !metadata?.publicAddress) { throw new Error('Magic login failed'); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx index 6b33d7e..676553b 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Facebook.tsx @@ -1,5 +1,5 @@ import { LoginProps } from '@/utils/types'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import { useEffect, useState } from 'react'; import { saveUserInfo } from '@/utils/common'; import Spinner from '../../ui/Spinner'; @@ -21,7 +21,8 @@ const Facebook = ({ token, setToken }: LoginProps) => { try { if (magic) { const result = await magic?.oauth.getRedirectResult(); - const metadata = await magic?.user.getMetadata(); + // Rehydrates the user session whenever getInfo is invoked + const metadata = await magic?.user.getInfo(); if (!metadata?.publicAddress) return; setToken(result.magic.idToken); saveUserInfo(result.magic.idToken, 'SOCIAL', metadata?.publicAddress); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Github.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Github.tsx index 23ba301..e5eacf9 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Github.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Github.tsx @@ -1,5 +1,5 @@ import { LoginProps } from '@/utils/types'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import { useEffect, useState } from 'react'; import { saveUserInfo } from '@/utils/common'; import Spinner from '../../ui/Spinner'; @@ -21,7 +21,8 @@ const Github = ({ token, setToken }: LoginProps) => { try { if (magic) { const result = await magic?.oauth.getRedirectResult(); - const metadata = await magic?.user.getMetadata(); + // Rehydrates the user session whenever getInfo is invoked + const metadata = await magic?.user.getInfo(); if (!metadata?.publicAddress) return; setToken(result.magic.idToken); saveUserInfo(result.magic.idToken, 'SOCIAL', metadata?.publicAddress); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Google.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Google.tsx index b2b0079..e683ba2 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Google.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Google.tsx @@ -1,5 +1,5 @@ import { LoginProps } from '@/utils/types'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import { useEffect, useState } from 'react'; import { saveUserInfo } from '@/utils/common'; import Spinner from '../../ui/Spinner'; @@ -21,7 +21,8 @@ const Google = ({ token, setToken }: LoginProps) => { try { if (magic) { const result = await magic?.oauth.getRedirectResult(); - const metadata = await magic?.user.getMetadata(); + // Rehydrates the user session whenever getInfo is invoked + const metadata = await magic?.user.getInfo(); if (!metadata?.publicAddress) return; setToken(result.magic.idToken); saveUserInfo(result.magic.idToken, 'SOCIAL', metadata?.publicAddress); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx index fa075de..703e830 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/SMSOTP.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import showToast from '@/utils/showToast'; import Spinner from '../../ui/Spinner'; import { RPCError, RPCErrorCode } from 'magic-sdk'; @@ -25,7 +25,8 @@ const SMSOTP = ({ token, setToken }: LoginProps) => { const token = await magic?.auth.loginWithSMS({ phoneNumber: phone, }); - const metadata = await magic?.user.getMetadata(); + // Rehydrates the user session whenever getInfo is invoked + const metadata = await magic?.user.getInfo(); if (!token || !metadata?.publicAddress) { throw new Error('Magic login failed'); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx index 0747e80..19a186a 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitch.tsx @@ -1,5 +1,5 @@ import { LoginProps } from '@/utils/types'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import { useEffect, useState } from 'react'; import { saveUserInfo } from '@/utils/common'; import Spinner from '../../ui/Spinner'; @@ -21,7 +21,8 @@ const Twitch = ({ token, setToken }: LoginProps) => { try { if (magic) { const result = await magic?.oauth.getRedirectResult(); - const metadata = await magic?.user.getMetadata(); + // Rehydrates the user session whenever getInfo is invoked + const metadata = await magic?.user.getInfo(); if (!metadata?.publicAddress) return; setToken(result.magic.idToken); saveUserInfo(result.magic.idToken, 'SOCIAL', metadata?.publicAddress); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx index 39a1180..a00dc55 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/auth/Twitter.tsx @@ -1,5 +1,5 @@ import { LoginProps } from '@/utils/types'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import { useEffect, useState } from 'react'; import { saveUserInfo } from '@/utils/common'; import Spinner from '../../ui/Spinner'; @@ -21,7 +21,8 @@ const Twitter = ({ token, setToken }: LoginProps) => { try { if (magic) { const result = await magic?.oauth.getRedirectResult(); - const metadata = await magic?.user.getMetadata(); + // Rehydrates the user session whenever getInfo is invoked + const metadata = await magic?.user.getInfo(); if (!metadata?.publicAddress) return; setToken(result.magic.idToken); saveUserInfo(result.magic.idToken, 'SOCIAL', metadata?.publicAddress); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/SendTransactionCard.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/SendTransactionCard.tsx index e4155c6..80fe44d 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/SendTransactionCard.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/SendTransactionCard.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useState } from 'react'; import Divider from '@/components/ui/Divider'; -import { useMagic } from '../MagicProvider'; +import useWeb3 from '@/hooks/Web3'; import FormButton from '@/components/ui/FormButton'; import FormInput from '@/components/ui/FormInput'; import ErrorText from '@/components/ui/ErrorText'; @@ -12,9 +12,10 @@ import Spacer from '@/components/ui/Spacer'; import TransactionHistory from '@/components/ui/TransactionHistory'; import Image from 'next/image'; import Link from 'public/link.svg'; +import { TxnParams } from '@/utils/types'; const SendTransaction = () => { - const { web3 } = useMagic(); + const web3 = useWeb3(); const [toAddress, setToAddress] = useState(''); const [amount, setAmount] = useState(''); const [disabled, setDisabled] = useState(!toAddress || !amount); @@ -37,13 +38,21 @@ const SendTransaction = () => { return setAmountError(true); } setDisabled(true); - const txnParams = { + + const txnParams: TxnParams = { from: publicAddress, to: toAddress, value: web3.utils.toWei(amount, 'ether'), - // Specify `gasPrice` if network doesn't support EIP-1559 - ...(!isEip1559Supported() && { gasPrice: await web3.eth.getGasPrice() }), }; + + if (isEip1559Supported()) { + const feeData = await web3.eth.calculateFeeData(); + txnParams.maxFeePerGas = BigInt(feeData.maxFeePerGas); + txnParams.maxPriorityFeePerGas = BigInt(feeData.maxPriorityFeePerGas); + } else { + txnParams.gasPrice = await web3.eth.getGasPrice(); + } + web3.eth .sendTransaction(txnParams as any) .on('transactionHash', (txHash) => { @@ -60,9 +69,14 @@ const SendTransaction = () => { console.log('Transaction receipt:', receipt); }) .catch((error) => { - console.error(error); + console.error('Transaction error:', error); setDisabled(false); + showToast({ + message: 'Transaction Failed: ' + error.message, + type: 'error', + }); }); + }, [web3, amount, publicAddress, toAddress]); return ( diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/SmartContract.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/SmartContract.tsx new file mode 100644 index 0000000..8046abb --- /dev/null +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/SmartContract.tsx @@ -0,0 +1,141 @@ +import { useCallback, useEffect, useState } from 'react'; +import Divider from '@/components/ui/Divider'; +import Card from '@/components/ui/Card'; +import CardHeader from '@/components/ui/CardHeader'; +import CardLabel from '@/components/ui/CardLabel'; +import Spinner from '@/components/ui/Spinner'; +import { getContractId, abi } from '@/utils/smartContract'; +import { useMagic } from '@/hooks/MagicProvider'; +import useWeb3 from '@/hooks/Web3'; +import FormInput from '@/components/ui/FormInput'; +import FormButton from '@/components/ui/FormButton'; +import showToast from '@/utils/showToast'; +import Spacer from '@/components/ui/Spacer'; + +const SmartContract = () => { + const { magic } = useMagic(); + const web3 = useWeb3(); + const [contractAddress, setContractAddress] = useState(undefined); + const [value, setValue] = useState(undefined); + const [newValue, setNewValue] = useState(''); + const [copied, setCopied] = useState('Copy'); + const [updating, setUpdating] = useState(false); + const [hash, setHash] = useState(""); + + useEffect(() => { + const initialize = async () => { + const address = getContractId(); + setContractAddress(address); + + if (web3 && address) { + const contract = new web3.eth.Contract(abi, address); + + try { + const value = await contract.methods.retrieve().call(); + setValue(value); + } catch (error) { + console.error('Error retrieving value:', error); + } + } + }; + + initialize(); + }, [web3, updating]); + + const submit = async () => { + if (web3 && contractAddress) { + const contract = new web3.eth.Contract(abi, contractAddress); + setUpdating(true); + + try { + if (!newValue) { + throw new Error('No value entered'); + } + + const accounts = await web3.eth.getAccounts(); + const accountBalance = await web3.eth.getBalance(accounts[0]); + + const gasPrice = await web3.eth.getGasPrice(); + console.log(`Current gas price: ${gasPrice}`); + + // Estimate gas limit + const gasLimit = await contract.methods.store(Number(newValue)).estimateGas({ + from: accounts[0] + }); + console.log(`Estimated gas limit: ${gasLimit}`); + + // Check if account balance is sufficient + const transactionCost = BigInt(gasPrice) * BigInt(gasLimit); + if (BigInt(accountBalance) < transactionCost) { + throw new Error(`Insufficient funds for gas * price + value: have ${accountBalance}, need ${transactionCost}`); + } + + // Send the transaction + await contract.methods.store(Number(newValue)).send({ + from: accounts[0], + gasPrice: gasPrice, + gas: gasLimit + }) + .on('transactionHash', (txHash) => { + setHash(txHash); + console.log('Transaction hash:', txHash); + }) + .then((receipt) => { + showToast({ message: 'Value updated!', type: 'success' }); + console.log('Transaction receipt:', receipt); + setNewValue(''); + }) + .catch((error) => { + console.error('Error submitting value:', error); + showToast({ message: error.message, type: 'error' }); + }); + + setUpdating(false); + setValue(await contract.methods.retrieve().call()); + } catch (error: any) { + showToast({ message: error.message, type: 'error' }); + console.error('Error submitting value:', error); + setUpdating(false); + } + } + }; + + const copy = useCallback(() => { + if (contractAddress && copied === 'Copy') { + setCopied('Copied!'); + navigator.clipboard.writeText(contractAddress); + setTimeout(() => { + setCopied('Copy'); + }, 1000); + } + }, [copied, contractAddress]); + + return ( + + Smart Contract + :
{copied}
} + /> +
{contractAddress}
+ +
+
+ Stored Value: {value !== undefined ? value.toString() : "...loading"} +
+ + ) => setNewValue(e.target.value)} + placeholder="Enter new value" + /> + + {updating ? "Updating value" : "Submit"} + +
+
+ ); +}; + +export default SmartContract; diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/UserInfoCard.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/UserInfoCard.tsx index 1f6003f..2fcfe57 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/UserInfoCard.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/cards/UserInfoCard.tsx @@ -2,7 +2,8 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import Divider from '@/components/ui/Divider'; import { LoginProps } from '@/utils/types'; import { logout } from '@/utils/common'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; +import useWeb3 from '@/hooks/Web3'; import Card from '@/components/ui/Card'; import CardHeader from '@/components/ui/CardHeader'; import CardLabel from '@/components/ui/CardLabel'; @@ -10,7 +11,8 @@ import Spinner from '@/components/ui/Spinner'; import { getNetworkName, getNetworkToken } from '@/utils/network'; const UserInfo = ({ token, setToken }: LoginProps) => { - const { magic, web3 } = useMagic(); + const { magic } = useMagic(); + const web3 = useWeb3(); const [balance, setBalance] = useState('...'); const [copied, setCopied] = useState('Copy'); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/Disconnect.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/Disconnect.tsx index 3b11b01..a59f497 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/Disconnect.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/Disconnect.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useState } from 'react'; import { logout } from '@/utils/common'; import { LoginProps } from '@/utils/types'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import Spinner from '@/components/ui/Spinner'; const Disconnect = ({ setToken }: LoginProps) => { diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/GetIdToken.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/GetIdToken.tsx index 0c60adc..af0f7e5 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/GetIdToken.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/GetIdToken.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useState } from 'react'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import showToast from '@/utils/showToast'; import Spinner from '@/components/ui/Spinner'; diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/GetMetadata.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/GetMetadata.tsx index 39fb080..437e513 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/GetMetadata.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/GetMetadata.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useState } from 'react'; import showToast from '@/utils/showToast'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import Spinner from '@/components/ui/Spinner'; const GetMetadata = () => { @@ -11,6 +11,7 @@ const GetMetadata = () => { if (!magic) return; try { setDisabled(true); + // Rehydrates the user session whenever getInfo is invoked const userInfo = await magic.user.getInfo(); setDisabled(false); showToast({ diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/UpdateEmail.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/UpdateEmail.tsx index 68b8de8..7e49618 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/UpdateEmail.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/wallet-methods/UpdateEmail.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useState } from 'react'; import ErrorText from '@/components/ui/ErrorText'; import Spacer from '@/components/ui/Spacer'; -import { useMagic } from '../MagicProvider'; +import { useMagic } from '@/hooks/MagicProvider'; import Spinner from '@/components/ui/Spinner'; import FormInput from '@/components/ui/FormInput'; import showToast from '@/utils/showToast'; diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Dashboard.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/ui/Dashboard.tsx similarity index 65% rename from scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Dashboard.tsx rename to scaffolds/nextjs-dedicated-wallet/template/src/components/ui/Dashboard.tsx index 4e02d36..6abe866 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/Dashboard.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/ui/Dashboard.tsx @@ -1,11 +1,13 @@ import React from 'react'; -import WalletMethods from './cards/WalletMethodsCard'; -import SendTransaction from './cards/SendTransactionCard'; +import WalletMethods from '../magic/cards/WalletMethodsCard'; +import SendTransaction from '../magic/cards/SendTransactionCard'; import Spacer from '@/components/ui/Spacer'; import { LoginProps } from '@/utils/types'; -import UserInfo from './cards/UserInfoCard'; +import UserInfo from '@/components/magic/cards/UserInfoCard'; import DevLinks from './DevLinks'; import Header from './Header'; +import SmartContract from '../magic/cards/SmartContract'; +import { isTestnet } from '@/utils/smartContract'; export default function Dashboard({ token, setToken }: LoginProps) { return ( @@ -18,6 +20,7 @@ export default function Dashboard({ token, setToken }: LoginProps) { + {isTestnet() && } diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/DevLinks.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/ui/DevLinks.tsx similarity index 100% rename from scaffolds/nextjs-dedicated-wallet/template/src/components/magic/DevLinks.tsx rename to scaffolds/nextjs-dedicated-wallet/template/src/components/ui/DevLinks.tsx diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/ui/FormInput.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/ui/FormInput.tsx index c15afa6..5cd9c6a 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/ui/FormInput.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/components/ui/FormInput.tsx @@ -1,14 +1,16 @@ import React from 'react' interface Props { - value: string - onChange: (e: any) => void - placeholder: string + value?: string + type?: string + onChange: (e: any) => void + placeholder: string } -const FormInput = ({value, onChange, placeholder}: Props) => { +const FormInput = ({ value, type, onChange, placeholder }: Props) => { return ( { +

Take a look at our developer guide to learn more about this template

); }; diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/components/ui/MagicDashboardRedirect.tsx similarity index 100% rename from scaffolds/nextjs-dedicated-wallet/template/src/components/magic/MagicDashboardRedirect.tsx rename to scaffolds/nextjs-dedicated-wallet/template/src/components/ui/MagicDashboardRedirect.tsx diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/MagicProvider.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/hooks/MagicProvider.tsx similarity index 81% rename from scaffolds/nextjs-dedicated-wallet/template/src/components/magic/MagicProvider.tsx rename to scaffolds/nextjs-dedicated-wallet/template/src/hooks/MagicProvider.tsx index 2a1f37d..b3f2f64 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/components/magic/MagicProvider.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/hooks/MagicProvider.tsx @@ -2,25 +2,21 @@ import { getChainId, getNetworkUrl } from '@/utils/network'; import { OAuthExtension } from '@magic-ext/oauth'; import { Magic as MagicBase } from 'magic-sdk'; import { ReactNode, createContext, useContext, useEffect, useMemo, useState } from 'react'; -const { Web3 } = require('web3'); export type Magic = MagicBase; type MagicContextType = { magic: Magic | null; - web3: typeof Web3 | null; }; const MagicContext = createContext({ magic: null, - web3: null, }); export const useMagic = () => useContext(MagicContext); const MagicProvider = ({ children }: { children: ReactNode }) => { const [magic, setMagic] = useState(null); - const [web3, setWeb3] = useState(null); useEffect(() => { if (process.env.NEXT_PUBLIC_MAGIC_API_KEY) { @@ -33,18 +29,16 @@ const MagicProvider = ({ children }: { children: ReactNode }) => { }); setMagic(magic); - setWeb3(new Web3((magic as any).rpcProvider)); } }, []); const value = useMemo(() => { return { magic, - web3, }; - }, [magic, web3]); + }, [magic]); return {children}; }; -export default MagicProvider; +export default MagicProvider; \ No newline at end of file diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/hooks/Web3.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/hooks/Web3.tsx new file mode 100644 index 0000000..2ee403b --- /dev/null +++ b/scaffolds/nextjs-dedicated-wallet/template/src/hooks/Web3.tsx @@ -0,0 +1,20 @@ +import { Web3 } from 'web3'; +import { useEffect, useState } from 'react'; +import { useMagic } from './MagicProvider'; + +const useWeb3 = () => { + const { magic } = useMagic(); + const [web3, setWeb3] = useState(null); + + useEffect(() => { + if (magic) { + setWeb3(new Web3((magic as any).rpcProvider)); + } else { + console.log('Magic is not initialized'); + } + }, [magic]); + + return web3; +}; + +export default useWeb3; \ No newline at end of file diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/pages/index.tsx b/scaffolds/nextjs-dedicated-wallet/template/src/pages/index.tsx index f25df02..7be42b1 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/pages/index.tsx +++ b/scaffolds/nextjs-dedicated-wallet/template/src/pages/index.tsx @@ -1,10 +1,11 @@ -import MagicProvider from '../components/magic/MagicProvider'; +import MagicProvider from '@/hooks/MagicProvider'; + import { useEffect, useState } from 'react'; import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import Login from '@/components/magic/Login'; -import Dashboard from '@/components/magic/Dashboard'; -import MagicDashboardRedirect from '@/components/magic/MagicDashboardRedirect'; +import Dashboard from '@/components/ui/Dashboard'; +import MagicDashboardRedirect from '@/components/ui/MagicDashboardRedirect'; export default function Home() { const [token, setToken] = useState(''); diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/utils/network.ts b/scaffolds/nextjs-dedicated-wallet/template/src/utils/network.ts index fe95287..240a5bc 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/utils/network.ts +++ b/scaffolds/nextjs-dedicated-wallet/template/src/utils/network.ts @@ -23,7 +23,7 @@ export const getNetworkUrl = () => { case Network.ZKSYNC: return 'https://mainnet.era.zksync.io'; case Network.ZKSYNC_SEPOLIA: - return 'https://sepolia.era.zksync.dev'; + return 'https://zksync-era-sepolia.blockpi.network/v1/rpc/public'; default: throw new Error('Network not supported'); } @@ -116,13 +116,13 @@ export const getBlockExplorer = (address: string) => { export const isEip1559Supported = () => { switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.POLYGON: - case Network.POLYGON_AMOY: case Network.ETHEREUM_SEPOLIA: case Network.ETHEREUM: + return true; case Network.ZKSYNC: case Network.ZKSYNC_SEPOLIA: - return true; + case Network.POLYGON: + case Network.POLYGON_AMOY: case Network.ETHERLINK_TESTNET: return false; } diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/utils/smartContract.ts b/scaffolds/nextjs-dedicated-wallet/template/src/utils/smartContract.ts new file mode 100644 index 0000000..6101e39 --- /dev/null +++ b/scaffolds/nextjs-dedicated-wallet/template/src/utils/smartContract.ts @@ -0,0 +1,62 @@ +import { Network } from "./network"; + +export const getContractId = () => { + switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { + case Network.POLYGON_AMOY: + return '0xabBb65DD49c18e1ee504C92a83f8f60eC0726e1b'; + case Network.ETHEREUM_SEPOLIA: + return '0xa5bf55cC9afF6E0Ab59D8Fdd835c63983F124d03'; + case Network.ZKSYNC_SEPOLIA: + return '0xDA39B00b285B6344E420Fe6F4FC0Aa4Ee5A4312d'; + } +}; + +export const isTestnet = (): boolean => { + const testnets: Network[] = [Network.POLYGON_AMOY, Network.ETHEREUM_SEPOLIA, Network.ZKSYNC_SEPOLIA]; + const currentNetwork = process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK as Network | undefined; + + if (currentNetwork && testnets.includes(currentNetwork)) { + return true; + } + return false; +}; + +export const getHashLink = (hash: string) => { + switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { + case Network.POLYGON_AMOY: + return `https://www.oklink.com/amoy/tx/${hash}`; + case Network.ETHEREUM_SEPOLIA: + return `https://sepolia.etherscan.io/tx/${hash}`; + case Network.ZKSYNC_SEPOLIA: + return `https://sepolia.explorer.zksync.io/tx/${hash}`; + } +}; + +export const abi = [ + { + "inputs": [], + "name": "retrieve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "num", + "type": "uint256" + } + ], + "name": "store", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +]; \ No newline at end of file diff --git a/scaffolds/nextjs-dedicated-wallet/template/src/utils/types.ts b/scaffolds/nextjs-dedicated-wallet/template/src/utils/types.ts index a23936b..cb6d12f 100644 --- a/scaffolds/nextjs-dedicated-wallet/template/src/utils/types.ts +++ b/scaffolds/nextjs-dedicated-wallet/template/src/utils/types.ts @@ -5,4 +5,15 @@ export type LoginProps = { setToken: Dispatch> } +export type TxnParams = { + from: string | null; + to: string | null; + value: string; + maxFeePerGas?: bigint; + maxPriorityFeePerGas?: bigint; + gasPrice?: string; +}; + + + export type { Magic } from '../components/magic/MagicProvider' diff --git a/scaffolds/nextjs-flow-dedicated-wallet/scaffold.ts b/scaffolds/nextjs-flow-dedicated-wallet/scaffold.ts index 2cf5614..3422379 100644 --- a/scaffolds/nextjs-flow-dedicated-wallet/scaffold.ts +++ b/scaffolds/nextjs-flow-dedicated-wallet/scaffold.ts @@ -1,6 +1,6 @@ import { Flags } from '../../core/flags'; import BaseScaffold, { ExecaCommand } from '../../core/types/BaseScaffold'; -import { AuthTypePrompt, NpmClientPrompt, PublishableApiKeyPrompt } from '../../scaffolds/prompts'; +import { AuthTypePrompt, NpmClientPrompt, PublishableApiKeyPrompt } from '../prompts'; export type Data = NpmClientPrompt.Data & PublishableApiKeyPrompt.Data & AuthTypePrompt.Data; diff --git a/scaffolds/nextjs-flow-universal-wallet/scaffold.ts b/scaffolds/nextjs-flow-universal-wallet/scaffold.ts deleted file mode 100644 index 78a458f..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/scaffold.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Flags } from '../../core/flags'; -import BaseScaffold, { ExecaCommand } from '../../core/types/BaseScaffold'; -import { NpmClientPrompt, PublishableApiKeyPrompt } from '../../scaffolds/prompts'; - -export type Data = NpmClientPrompt.Data & PublishableApiKeyPrompt.Data; - -export const flags: Flags> = { - ...NpmClientPrompt.flags, - ...PublishableApiKeyPrompt.flags, -}; - -export const definition = { - shortDescription: 'A universal wallet scaffold for Next.js using Flow', - featured: true, -}; - -export default class FlowUniversalScaffold extends BaseScaffold { - public templateName = 'nextjs-flow-universal-wallet'; - private data: Data; - public installationCommand: ExecaCommand = { command: 'npm', args: ['install'] }; - public startCommand: ExecaCommand = { command: 'npm', args: ['run', 'dev'] }; - public source: string | string[] = './'; - - constructor(data: Data) { - super(); - this.data = data; - } -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/.env.example b/scaffolds/nextjs-flow-universal-wallet/template/.env.example deleted file mode 100644 index f1ef940..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -NEXT_PUBLIC_BLOCKCHAIN_NETWORK=<%= network %> -NEXT_PUBLIC_MAGIC_API_KEY=<%= publishableApiKey %> diff --git a/scaffolds/nextjs-flow-universal-wallet/template/.eslintrc.json b/scaffolds/nextjs-flow-universal-wallet/template/.eslintrc.json deleted file mode 100644 index bffb357..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/.gitignore b/scaffolds/nextjs-flow-universal-wallet/template/.gitignore deleted file mode 100644 index 7bba8aa..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/.gitignore +++ /dev/null @@ -1,39 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local -.env - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts - -#environment -.env diff --git a/scaffolds/nextjs-flow-universal-wallet/template/README.md b/scaffolds/nextjs-flow-universal-wallet/template/README.md deleted file mode 100644 index 016ad82..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/README.md +++ /dev/null @@ -1,44 +0,0 @@ -This scaffold is meant to help you bootstrap your own projects with Magic's [Universal Wallet](https://magic.link/docs/connect/overview). Magic is a developer SDK that integrates with your application to enable passwordless Web3 onboarding. - -The folder structure of this scaffold is designed to encapsulate all things Magic into one place so you can easily add or remove components and functionality. For example, all Magic-specific components are in the `src/components/magic` directory while generic UI components are in the `src/components/ui` directory. - -## Next.js - -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). - -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. - -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. - -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/scaffolds/nextjs-flow-universal-wallet/template/next.config.js b/scaffolds/nextjs-flow-universal-wallet/template/next.config.js deleted file mode 100644 index a843cbe..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/next.config.js +++ /dev/null @@ -1,6 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - reactStrictMode: true, -} - -module.exports = nextConfig diff --git a/scaffolds/nextjs-flow-universal-wallet/template/package.json b/scaffolds/nextjs-flow-universal-wallet/template/package.json deleted file mode 100644 index 44ab278..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "<%= projectName %>", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint --fix" - }, - "dependencies": { - "@magic-ext/flow": "^16.0.0", - "@onflow/fcl": "^1.6.0", - "@onflow/types": "^1.1.0", - "@types/node": "18.15.11", - "@types/react": "18.0.35", - "@types/react-dom": "18.0.11", - "eslint-config-next": "13.3.0", - "magic-sdk": "^21.0.0", - "next": "13.3.0", - "react": "18.2.0", - "react-dom": "18.2.0", - "typescript": "5.0.4" - }, - "devDependencies": { - "autoprefixer": "^10.4.15", - "eslint": "^8.45.0", - "postcss": "^8.4.28", - "tailwindcss": "^3.3.3" - } -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/postcss.config.js b/scaffolds/nextjs-flow-universal-wallet/template/postcss.config.js deleted file mode 100644 index 1b69d43..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/check.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/check.svg deleted file mode 100644 index a92ed0c..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/check.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/down-arrow.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/down-arrow.svg deleted file mode 100644 index 7bee9e0..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/down-arrow.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/favicon.ico b/scaffolds/nextjs-flow-universal-wallet/template/public/favicon.ico deleted file mode 100644 index 718d6fe..0000000 Binary files a/scaffolds/nextjs-flow-universal-wallet/template/public/favicon.ico and /dev/null differ diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/info.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/info.svg deleted file mode 100644 index df6edb9..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/info.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/link.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/link.svg deleted file mode 100644 index 09c4941..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/link.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/link_white.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/link_white.svg deleted file mode 100644 index c87852b..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/link_white.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/loading.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/loading.svg deleted file mode 100644 index c76c84b..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/loading.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/login.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/login.svg deleted file mode 100644 index 71a173d..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/login.svg +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/login_bg.png b/scaffolds/nextjs-flow-universal-wallet/template/public/login_bg.png deleted file mode 100644 index a4021c4..0000000 Binary files a/scaffolds/nextjs-flow-universal-wallet/template/public/login_bg.png and /dev/null differ diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/logo.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/logo.svg deleted file mode 100644 index e13da68..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/logo.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/magic.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/magic.svg deleted file mode 100644 index a769b49..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/magic.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/main.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/main.svg deleted file mode 100644 index ae112a2..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/main.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/nft-one.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/nft-one.svg deleted file mode 100644 index 34c5d9b..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/nft-one.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/nft-three.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/nft-three.svg deleted file mode 100644 index 96766f0..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/nft-three.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/nft-two.svg b/scaffolds/nextjs-flow-universal-wallet/template/public/nft-two.svg deleted file mode 100644 index bd602b4..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/public/nft-two.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/scaffolds/nextjs-flow-universal-wallet/template/public/redirect_bg.png b/scaffolds/nextjs-flow-universal-wallet/template/public/redirect_bg.png deleted file mode 100644 index aa322ee..0000000 Binary files a/scaffolds/nextjs-flow-universal-wallet/template/public/redirect_bg.png and /dev/null differ diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/DevLinks.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/DevLinks.tsx deleted file mode 100644 index 41f7d2f..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/DevLinks.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react' - -interface Props { - dark?: boolean - footer?: boolean -} - -const Links = ({dark, footer}: Props) => { - return ( -
- -
- - - ) -} - -export default Links diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Home.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Home.tsx deleted file mode 100644 index 5099438..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Home.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import TableOfContents from '../ui/TableOfContents'; -import AppHeader from '../ui/AppHeader'; -import Wallet from './cards/UserInfoCard'; -import WalletMethods from './cards/WalletMethodsCard'; -import SendTransaction from './cards/SendTransactionsCard'; -import Links from './DevLinks'; -import Spacer from '../ui/Spacer'; - -interface Props { - setAccount: React.Dispatch>; -} - -export default function Home({ setAccount }: Props) { - return ( -
- - - - - -
- - - - - - -
-
- ); -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Login.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Login.tsx deleted file mode 100644 index bec6b20..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/Login.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useState, useCallback } from 'react'; -import AppHeader from '../ui/AppHeader'; -import Links from './DevLinks'; -import ConnectButton from '../ui/ConnectButton'; -import Spacer from '../ui/Spacer'; -import { useMagicContext } from '@/components/magic/MagicProvider'; - -interface Props { - setAccount: React.Dispatch>; -} - -const Login = ({ setAccount }: Props) => { - const [disabled, setDisabled] = useState(false); - const { magic } = useMagicContext(); - - const connect = useCallback(async () => { - if (!magic) return; - try { - setDisabled(true); - const token = await magic.flow.getAccount(); - setDisabled(false); - console.log('Logged in user:', token); - localStorage.setItem('user', token); - setAccount(token); - } catch (error) { - setDisabled(false); - console.error(error); - } - }, [magic, setAccount]); - - return ( -
- - - - - -
- ); -}; - -export default Login; diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx deleted file mode 100644 index 2478f09..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React, { useCallback } from 'react'; -import Image from 'next/image'; -import Info from 'public/info.svg'; -import Link from 'public/link_white.svg'; -import Logo from 'public/logo.svg'; -import DevLinks from './DevLinks'; - -const MagicDashboardRedirect = () => { - const onClick = useCallback(() => { - window.open('https://dashboard.magic.link/signup', '_blank'); - }, []); - - return ( -
-
- logo -
Magic
-
- Demo -
-
-
-
-
- logo -

- Please set your NEXT_PUBLIC_MAGIC_API_KEY environment variable in .env. You can - get your Magic API key from the Magic Dashboard. -

-
-
- - -
- -
- ); -}; - -export default MagicDashboardRedirect; diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/MagicProvider.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/MagicProvider.tsx deleted file mode 100644 index 3c5424d..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/MagicProvider.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import {createContext, useContext, useEffect, useMemo, useState} from 'react' -import {Magic as MagicBase} from 'magic-sdk' -import {getNetwork, getNetworkUrl} from '../../utils/networks' -import {FlowExtension} from '@magic-ext/flow' -import * as fcl from '@onflow/fcl' - -export type Magic = MagicBase - -export type MagicContextType = { - magic: Magic | null -} - -const MagicContext = createContext({ - magic: null, -}) - -export const useMagicContext = () => useContext(MagicContext) - -const MagicProvider = ({children}: {children: React.ReactNode}) => { - const [magicInstance, setMagicInstance] = useState(null) - - useEffect(() => { - if (process.env.NEXT_PUBLIC_MAGIC_API_KEY) { - const magic = new MagicBase( - process.env.NEXT_PUBLIC_MAGIC_API_KEY as string, - { - extensions: [ - new FlowExtension({ - rpcUrl: getNetworkUrl(), - network: getNetwork() as string, - }), - ], - } - ) - setMagicInstance(magic) - fcl.config().put('accessNode.api', getNetworkUrl()) - } - }, []) - - const value = useMemo( - () => ({ - magic: magicInstance, - }), - [magicInstance] - ) - - return ( - {children} - ) -} - -export default MagicProvider diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/cards/SendTransactionsCard.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/cards/SendTransactionsCard.tsx deleted file mode 100644 index 9803a2d..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/cards/SendTransactionsCard.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React, { useCallback, useEffect, useState } from 'react'; -import Image from 'next/image'; -import Divider from '../../ui/Divider'; -import FormButton from '../../ui/FormButton'; -import Link from 'public/link.svg'; -import FormInput from '../../ui/FormInput'; -import Card from '../../ui/Card'; -import CardHeader from '../../ui/CardHeader'; -import ErrorText from '../../ui/Error'; -import { useMagicContext } from '@/components/magic/MagicProvider'; -import { getFaucetUrl, getNetwork } from '@/utils/networks'; -import * as fcl from '@onflow/fcl'; -import Loading from 'public/loading.svg'; -import Spacer from '@/components/ui/Spacer'; -import TransactionHistory from '@/components/ui/TransactionHistory'; - -const SendTransaction = () => { - const { magic } = useMagicContext(); - const [toAddress, setToAddress] = useState(''); - const [amount, setAmount] = useState(''); - const [disabled, setDisabled] = useState(!toAddress || !amount); - const [transactionLoading, setTransactionLoading] = useState(false); - const [hash, setHash] = useState(''); - const [amountError, setAmountError] = useState(false); - const publicAddress = localStorage.getItem('user'); - - useEffect(() => { - setDisabled(!toAddress || !amount); - setAmountError(false); - }, [amount, toAddress]); - - const sendTransaction = useCallback(async () => { - if (!magic) { - return; - } - try { - setTransactionLoading(true); - - const response = await fcl.mutate({ - //cadence: transaction, - template: 'https://flix.flow.com/v1/templates?name=transfer-flow', - args: (arg, t) => [arg(Number(amount).toFixed(2), t.UFix64), arg(toAddress, t.Address)], - proposer: magic.flow.authorization, - authorizations: [magic.flow.authorization], - payer: magic.flow.authorization, - limit: 999, - }); - console.log('response: ', JSON.stringify(response)); - setHash(response); - console.log('Waiting for transaction to be sealed'); - var data = await fcl.tx(response).onceSealed(); - console.log('sealed: ', JSON.stringify(data)); - - if (data.status === 4 && data.statusCode === 0) { - alert('Transaction successful'); - } else { - alert('Transaction Failed! Check console for more details'); - console.log('transaction error: ' + data.errorMessage); - } - setTransactionLoading(false); - setToAddress(''); - setAmount(''); - } catch (e) { - setTransactionLoading(false); - alert('Transaction Failed! Check console for more details'); - console.log(e); - } - }, [magic, amount, publicAddress, toAddress]); - - return ( - - Send Transaction - {getNetwork() == 'testnet' && ( - - null} disabled={false}> - Get Test FLOW - link-icon - - - )} - - setToAddress(e.target.value)} - placeholder="Receiving Address" - /> - setAmount(e.target.value)} placeholder={`Amount (FLOW)`} /> - {amountError ? Invalid amount : null} - - {transactionLoading ? ( -
- loading -
- ) : ( - 'Send Transaction' - )} -
- {hash ? ( - <> - - - - ) : null} -
- ); -}; - -export default SendTransaction; diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/cards/UserInfoCard.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/cards/UserInfoCard.tsx deleted file mode 100644 index 34a4c29..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/cards/UserInfoCard.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import {useCallback, useEffect, useState} from 'react' -import Image from 'next/image' -import Divider from '../../ui/Divider' -import Loading from 'public/loading.svg' -import CardLabel from '../../ui/CardLabel' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' -import {useMagicContext} from '@/components/magic/MagicProvider' -import {getNetworkName} from '@/utils/networks' -import * as fcl from '@onflow/fcl' -import {convertAccountBalance} from '@/utils/flowUtils' - -interface Props { - setAccount: React.Dispatch> -} - -const UserInfo = ({setAccount}: Props) => { - const {magic} = useMagicContext() - - const [balance, setBalance] = useState('...') - const [copied, setCopied] = useState('Copy') - const [isRefreshing, setIsRefreshing] = useState(false) - - const publicAddress = localStorage.getItem('user') - - const getBalance = useCallback(async () => { - if (publicAddress) { - const account = await fcl.account(publicAddress) - setBalance(convertAccountBalance(account.balance)) - } - }, [magic, publicAddress]) - - const refresh = useCallback(async () => { - setIsRefreshing(true) - await getBalance() - setTimeout(() => { - setIsRefreshing(false) - }, 500) - }, [getBalance]) - - useEffect(() => { - if (magic) { - refresh() - } - }, [magic, refresh]) - - useEffect(() => { - setBalance('...') - }, [magic]) - - const disconnect = useCallback(async () => { - if (magic) { - await magic.wallet.disconnect() - localStorage.removeItem('user') - setAccount(null) - } - }, [magic, setAccount]) - - const copy = useCallback(() => { - if (publicAddress && copied === 'Copy') { - setCopied('Copied!') - navigator.clipboard.writeText(publicAddress) - setTimeout(() => { - setCopied('Copy') - }, 1000) - } - }, [copied, publicAddress]) - - return ( - - Wallet - Disconnect
} - isDisconnect - /> -
-
-
Connected to {getNetworkName()}
-
- - {copied}
} - /> -
{publicAddress}
- - - loading -
- ) : ( -
Refresh
- ) - } - /> -
{balance} FLOW
- - ) -} - -export default UserInfo diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/cards/WalletMethodsCard.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/cards/WalletMethodsCard.tsx deleted file mode 100644 index c5133b3..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/cards/WalletMethodsCard.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react' -import Disconnect from '../wallet-methods/Disconnect' -import GetWalletInfo from '../wallet-methods/GetWalletInfo' -import RequestUserInfo from '../wallet-methods/RequestUserInfo' -import ShowUI from '../wallet-methods/ShowUi' -import Divider from '../../ui/Divider' -import Card from '../../ui/Card' -import CardHeader from '../../ui/CardHeader' - -interface Props { - setAccount: React.Dispatch> -} - -const WalletMethods = ({setAccount}: Props) => { - return ( - - Wallet Methods - - - - - - - - - ) -} - -export default WalletMethods diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/Disconnect.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/Disconnect.tsx deleted file mode 100644 index 029717b..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/Disconnect.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React, {useCallback, useState} from 'react' -import Loading from 'public/loading.svg' -import {useMagicContext} from '@/components/magic/MagicProvider' -import Image from 'next/image' - -interface Props { - setAccount: React.Dispatch> -} - -const Disconnect = ({setAccount}: Props) => { - const {magic} = useMagicContext() - const [disabled, setDisabled] = useState(false) - - const disconnect = useCallback(async () => { - if (!magic) return - try { - setDisabled(true) - await magic.wallet.disconnect() - localStorage.removeItem('user') - setDisabled(false) - setAccount(null) - } catch (error) { - setDisabled(false) - console.error(error) - } - }, [magic, setAccount]) - - return ( -
- -
- Disconnects user from dApp. -
-
- ) -} - -export default Disconnect diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/GetWalletInfo.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/GetWalletInfo.tsx deleted file mode 100644 index f8cde39..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/GetWalletInfo.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import React, {useCallback, useState} from 'react' -import Loading from 'public/loading.svg' -import Toast from '../../ui/Toast' -import {useMagicContext} from '@/components/magic/MagicProvider' -import Image from 'next/image' - -const GetWalletInfo = () => { - const {magic} = useMagicContext() - const [disabled, setDisabled] = useState(false) - const [showToast, setShowToast] = useState(false) - const [walletType, setWalletType] = useState('') - - const getWalletType = useCallback(async () => { - if (!magic) return - try { - setDisabled(true) - const walletInfo = await magic.wallet.getInfo() - setDisabled(false) - setWalletType(walletInfo.walletType) - setShowToast(true) - setTimeout(() => { - setShowToast(false) - }, 3000) - } catch (error) { - setDisabled(false) - console.error(error) - } - }, [magic]) - - return ( -
- -
- Returns information about the logged in user's wallet. -
- {showToast ? Wallet type: {walletType} : null} -
- ) -} - -export default GetWalletInfo diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/RequestUserInfo.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/RequestUserInfo.tsx deleted file mode 100644 index 6407167..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/RequestUserInfo.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React, {useCallback, useState} from 'react' -import Loading from 'public/loading.svg' -import Toast from '../../ui/Toast' -import {useMagicContext} from '@/components/magic/MagicProvider' -import Image from 'next/image' - -const RequestUserInfo = () => { - const {magic} = useMagicContext() - const [disabled, setDisabled] = useState(false) - const [showToast, setShowToast] = useState(false) - const [email, setEmail] = useState('') - - const requestUserInfo = useCallback(async () => { - if (!magic) return - try { - setDisabled(true) - const userInfo = await magic.wallet.requestUserInfoWithUI() - setDisabled(false) - setEmail(userInfo.email) - setShowToast(true) - setTimeout(() => { - setShowToast(false) - }, 3000) - } catch (error) { - setDisabled(false) - console.error(error) - } - }, [magic]) - - return ( -
- -
- Prompts the user to consent to sharing information with the - requesting dApp. -
- {showToast ? Email: {email} : null} -
- ) -} - -export default RequestUserInfo diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/ShowUi.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/ShowUi.tsx deleted file mode 100644 index 54858e1..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/magic/wallet-methods/ShowUi.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React, {useCallback, useState} from 'react' -import Loading from 'public/loading.svg' -import ErrorText from '../../ui/Error' -import Spacer from '../../ui/Spacer' -import {useMagicContext} from '@/components/magic/MagicProvider' -import Image from 'next/image' - -const ShowUI = () => { - const {magic} = useMagicContext() - const [disabled, setDisabled] = useState(false) - const [showUIError, setShowUIError] = useState(false) - - const showUI = useCallback(async () => { - if (!magic) return - try { - setShowUIError(false) - const {walletType} = await magic.wallet.getInfo() - if (walletType !== 'magic') { - return setShowUIError(true) - } - setDisabled(true) - await magic.wallet.showUI() - setDisabled(false) - } catch (error) { - setDisabled(false) - console.error(error) - } - }, [magic]) - - return ( -
- -
- Opens wallet view to manage assets, purchase/send/receive - crypto, and access recovery phrase. -
- {showUIError ? ( -
- - - Method not supported for third party wallets. - -
- ) : null} -
- ) -} - -export default ShowUI diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/AppHeader.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/AppHeader.tsx deleted file mode 100644 index eddd75c..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/AppHeader.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react' -import MagicLogo from 'public/magic.svg' -import Image from 'next/image' - -const AppHeader = () => { - return ( -
- magic-logo -

Demo

-
- ) -} - -export default AppHeader diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Card.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Card.tsx deleted file mode 100644 index 22c54c4..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Card.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' - -interface Props { - children: React.ReactNode -} - -const Card = ({children}: Props) => { - return
{children}
-} - -export default Card diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/CardHeader.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/CardHeader.tsx deleted file mode 100644 index d464970..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/CardHeader.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react' - -interface Props { - children: React.ReactNode - id: string -} - -const CardHeader = ({children, id}: Props) => { - return ( -

- {children} -

- ) -} - -export default CardHeader diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/CardLabel.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/CardLabel.tsx deleted file mode 100644 index f4402f8..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/CardLabel.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react' - -interface Props { - leftHeader?: React.ReactNode - rightAction?: React.ReactNode - isDisconnect?: boolean - [rest: string]: any -} - -const CardLabel = ({leftHeader, rightAction, isDisconnect, ...rest}: Props) => { - return ( -
-
{leftHeader}
- {rightAction ? ( -
- {rightAction} -
- ) : null} -
- ) -} - -export default CardLabel diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/ConnectButton.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/ConnectButton.tsx deleted file mode 100644 index 4b8b98f..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/ConnectButton.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react' -import Loading from 'public/loading.svg' -import Image from 'next/image' -interface Props { - onClick: () => void - disabled: boolean -} - -const ConnectButton = ({onClick, disabled}: Props) => { - return ( -
- -
- ) -} - -export default ConnectButton diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Divider.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Divider.tsx deleted file mode 100644 index 337c77c..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Divider.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const Divider = () => { - return
-} - -export default Divider diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Error.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Error.tsx deleted file mode 100644 index 97a17cf..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Error.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const ErrorText = ({children}: any) => { - return
{children}
-} - -export default ErrorText diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/FormButton.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/FormButton.tsx deleted file mode 100644 index 2e18776..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/FormButton.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react' - -interface Props { - children: React.ReactNode - onClick: () => void - disabled: boolean -} - -const FormButton = ({children, onClick, disabled}: Props) => { - return ( - - ) -} - -export default FormButton diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/FormInput.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/FormInput.tsx deleted file mode 100644 index ca0be19..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/FormInput.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react' - -interface Props { - value: string - onChange: (e: any) => void - placeholder: string -} - -const FormInput = ({value, onChange, placeholder}: Props) => { - return ( - - ) -} - -export default FormInput diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Spacer.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Spacer.tsx deleted file mode 100644 index 61e246b..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Spacer.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const Spacer = ({size}: {size: number}) => { - return
-} - -export default Spacer diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/TableOfContents.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/TableOfContents.tsx deleted file mode 100644 index b5cd52b..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/TableOfContents.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, {useCallback, useEffect, useRef, useState} from 'react' - -function useHeadingObserver() { - const observer = useRef() - const [activeId, setActiveId] = useState('') - - useEffect(() => { - const handleObserver = (entries: any) => { - entries.forEach((entry: any) => { - if (entry?.isIntersecting) { - setActiveId(entry.target.id) - } - }) - } - ;(observer as any).current = new IntersectionObserver(handleObserver, { - rootMargin: '0px 0px -82% 0px', - }) - const elements = document.querySelectorAll('h1') - elements.forEach((elem) => (observer as any).current.observe(elem)) - // eslint-disable-next-line react-hooks/exhaustive-deps - return () => (observer.current as any).disconnect() - }, []) - return {activeId} -} - -const TableOfContents = () => { - const [isBottomOfPage, setIsBottomOfPage] = useState(false) - const [headings, setHeadings] = useState([]) - const {activeId} = useHeadingObserver() - - const handleScroll = useCallback(() => { - const bottom = - Math.ceil(window.innerHeight + window.scrollY) >= - document.documentElement.scrollHeight - setIsBottomOfPage(bottom) - }, []) - - useEffect(() => { - const elements = Array.from(document.querySelectorAll('h1')).map( - (elem) => ({ - id: elem.id, - text: elem.innerText, - level: Number(elem.nodeName.charAt(1)), - }) - ) - setHeadings(elements) - - window.addEventListener('scroll', handleScroll, { - passive: true, - }) - return () => { - window.removeEventListener('scroll', handleScroll) - } - }, [handleScroll]) - - return ( - - ) -} - -export default TableOfContents diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Toast.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Toast.tsx deleted file mode 100644 index 49a9d7a..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/Toast.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const Toast = ({children}: any) => { - return
{children}
-} - -export default Toast diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/TransactionHistory.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/TransactionHistory.tsx deleted file mode 100644 index c3354f1..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/components/ui/TransactionHistory.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import Image from 'next/image'; -import Link from 'public/link.svg'; -import { getBlockExplorer } from '@/utils/networks'; - -const TransactionHistory = () => { - const publicAddress = localStorage.getItem('user'); - - return ( - -
- Transaction History link-icon -
-
- ); -}; - -export default TransactionHistory; diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/pages/_app.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/pages/_app.tsx deleted file mode 100644 index c1eb79d..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/pages/_app.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import '@/styles/globals.css' -import type {AppProps} from 'next/app' -import MagicProvider from '@/components/magic/MagicProvider' - -export default function App({Component, pageProps}: AppProps) { - return ( - - - - ) -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/pages/_document.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/pages/_document.tsx deleted file mode 100644 index af84485..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/pages/_document.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import {Html, Head, Main, NextScript} from 'next/document' - -export default function Document() { - return ( - - - -
- - - - ) -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/pages/index.tsx b/scaffolds/nextjs-flow-universal-wallet/template/src/pages/index.tsx deleted file mode 100644 index 8ec66bc..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/pages/index.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, {useState, useEffect} from 'react' -import Login from '../components/magic/Login' -import Home from '../components/magic/Home' -import MagicDashboardRedirect from '@/components/magic/MagicDashboardRedirect' - -export default function App() { - const [account, setAccount] = useState(null) - - useEffect(() => { - const user = localStorage.getItem('user') - setAccount(user) - }, []) - - /** - * If no Magic API key is set, instruct user to go to Magic Dashboard. - * Otherwise, if user is not logged in, show the Login component. - * Otherwise, show the Home component. - */ - return process.env.NEXT_PUBLIC_MAGIC_API_KEY ? ( - !account ? ( - - ) : ( - - ) - ) : ( - - ) -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/styles/globals.css b/scaffolds/nextjs-flow-universal-wallet/template/src/styles/globals.css deleted file mode 100644 index 65dde2b..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/styles/globals.css +++ /dev/null @@ -1,289 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap'); -@tailwind base; -@tailwind components; -@tailwind utilities; - -html, -body { - @apply m-0 p-0 bg-[#f8f8fa] scroll-pt-12; - font-family: 'Inter', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.table-of-contents { - @apply w-[220px] min-w-[220px] self-start sticky max-h-[calc(100vh_-_70px)] overflow-auto mt-0 px-0 py-6 top-0; - position: -webkit-sticky; -} - -nav > ul > li { - @apply text-left list-none text-[#777679] cursor-pointer mb-[15px]; -} - -ul { - @apply w-fit m-0 pl-[30px] pr-0 py-0; -} - -.active { - @apply text-[#6851ff] font-semibold; -} - -.active::before { - @apply content-['\2022'] text-[#6851ff] font-[bold] inline-block w-[1em] ml-[-1em]; -} - -.nft { - @apply text-[#777679]; -} - -.nft-name { - @apply text-black font-semibold; - font-family: 'Inter'; -} - -.nft-list { - @apply overflow-auto max-h-[270px]; -} - -.nft:not(:last-child) { - @apply mb-2.5; -} - -.cards-container { - @apply mt-[-260px]; -} - -@media only screen and (max-width: 767px) { - .table-of-contents { - @apply hidden; - } - .cards-container { - @apply mt-[-89px]; - } -} - -.network-dropdown { - @apply w-fit m-auto rounded-xl; -} - -.active-network { - @apply border w-[264px] flex items-center cursor-pointer justify-between m-auto px-4 py-3 rounded-xl border-solid border-[#dddbe0] bg-[#fff]; -} - -.active-network::selection { - @apply bg-transparent; -} - -.rotate { - @apply rotate-180; -} - -.network-options { - @apply overflow-hidden w-fit border mx-auto my-[5px] px-0 py-[5px] rounded-xl border-solid border-[#dddbe0] bg-[#fff]; -} - -.network-dropdown-option { - @apply w-[264px] flex items-center justify-start transition-[0.1s] m-auto px-4 py-3 bg-[#fff]; -} - -.network-dropdown-option:hover { - @apply text-white cursor-pointer bg-[#6851ff]; -} - -.network-dropdown-option:active { - @apply opacity-50; -} -.magic-logo { - @apply mb-[15px] mx-0 text-center; -} -.demo-sub-header { - @apply text-[rgba(255,255,255,0.5)] text-xl font-normal m-0; - font-family: monospace; -} - -.home-page { - @apply flex flex-col justify-center items-center min-h-screen relative bg-[length:100vw_320px] bg-[url('/login_bg.png')] bg-no-repeat; -} - -.login-page { - @apply min-h-screen bg-[length:100%_auto] bg-[url('/login.svg')]; -} -.connect-button { - @apply w-[296px] h-12 text-white font-semibold text-base leading-6 text-center transition-[0.1s] m-auto px-6 py-3 rounded-[300px] border-[none]; - background: rgba(255, 255, 255, 0.1); -} - -.connect-button:hover:enabled { - @apply cursor-pointer; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), rgba(255, 255, 255, 0.1); -} -.connect-button:active:enabled { - @apply opacity-50 cursor-pointer scale-[0.99]; - background: rgba(255, 255, 255, 0.1); -} - -.links { - @apply flex justify-center text-white font-semibold mt-5 mb-3 mx-auto; -} -.link { - @apply transition-[0.1s] px-[30px] py-0; -} - -@media only screen and (max-width: 420px) { - .link { - @apply px-[15px] py-0; - } -} -@media only screen and (max-width: 320px) { - .link { - @apply px-[5px] py-0; - } -} - -.link > a { - @apply cursor-pointer; -} -.link-divider { - @apply h-5 w-px; -} - -.footer-links { - @apply flex items-center absolute w-full mt-[30px] mb-0 mx-auto bottom-10; -} -.wallet-method-container { - @apply text-left; -} - -.wallet-method { - @apply w-fit text-[#522fd4] bg-[#edebff] text-base cursor-pointer font-medium transition-[0.1s] h-8 px-3 py-1.5 rounded-[32px] border-[none]; - font-family: monospace; -} - -.wallet-method:hover:enabled { - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; - background-blend-mode: color-burn, normal; -} - -.wallet-method:active:enabled { - @apply opacity-50 scale-[0.99]; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; -} -.wallet-method-desc { - @apply text-[#77767a] text-left text-sm mt-2.5; -} - -.form-input { - @apply box-border flex flex-row items-center w-full h-12 border text-base leading-6 text-[#18171a] mb-[15px] px-4 py-3 rounded-[10px] border-solid border-[#dddbe0]; - background: #ffffff; -} - -.form-input::placeholder { - color: #77767a; -} - -.form-button { - @apply flex flex-row justify-center items-center w-full h-12 text-[#522fd4] font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none] bg-[#edebff]; -} - -.form-button:disabled { - @apply opacity-50; -} - -.form-button:hover:enabled { - @apply cursor-pointer; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; -} -.form-button:active:enabled { - @apply opacity-50 scale-[0.99]; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; -} - -.loading-container { - @apply w-[50px] text-center flex items-center justify-center cursor-default; -} -.loading { - @apply animate-spin cursor-default; -} - -@keyframes rotation { - 0% { - transform: rotate(0); - } - 100% { - transform: rotate(360deg); - } -} - -.card { - @apply w-[300px] flex flex-col shadow-[0px_4px_24px_rgba(49,49,49,0.1)] mt-0 mb-[27px] mx-auto px-6 py-8 rounded-2xl bg-[#ffffff]; -} - -.card-header { - @apply text-xl font-semibold text-left mt-0 mb-[25px]; -} -.card-label-container { - @apply flex justify-between items-center mb-3; -} - -.card-label { - @apply text-sm font-medium cursor-pointer; -} -.toast { - @apply fixed w-fit text-white font-medium shadow-[4px_8px_20px_rgba(0,0,0,0.15)] mx-auto my-0 px-4 py-2 rounded-[10px] top-[30px] inset-x-0 bg-[#00875f]; -} - -.action-button { - @apply font-semibold text-[#6851ff] cursor-pointer transition-[0.1s]; -} -.disconnect-button { - @apply font-semibold text-[#d43100] cursor-pointer transition-[0.1s]; -} -.action-button:hover, -.disconnect-button:hover { - @apply opacity-70; -} -.action-button:active, -.disconnect-button:active { - @apply scale-[0.98]; -} -.code { - @apply text-base text-left p-2.5 rounded-[10px]; - font-family: monospace; - background: #f8f8fa; - word-wrap: break-word; -} -.error { - @apply text-[#d43100] text-xs text-left -mt-2.5 mb-2.5 mx-0; -} -.divider { - @apply mx-0 my-[15px] border-b-[#ededf3] border-b border-solid; -} -.flex-row { - @apply flex items-center; -} -.green-dot { - @apply h-1.5 w-1.5 bg-[#00cc8f] mr-2.5 rounded-[50%]; -} -.connected { - @apply text-base mx-0 my-[5px]; -} -a { - all: unset; -} - -.app-header-container { - @apply block pt-4; - text-align: -webkit-center; -} - -.redirect-container { - @apply flex flex-col items-center min-h-screen bg-['100%_auto'] bg-[url('/login.svg')]; -} - -.redirect-card { - @apply bg-[#F8F8FA] rounded-[10px] shadow-[0px_4px_24px_rgba(49,49,49,0.1)] p-2 m-12; -} - -.api-button { - @apply bg-[#6844bc] text-[#FFFFFF] flex w-[280px] justify-center items-center h-12 font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none]; -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/utils/flowUtils.ts b/scaffolds/nextjs-flow-universal-wallet/template/src/utils/flowUtils.ts deleted file mode 100644 index 4a1d3d6..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/utils/flowUtils.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const convertAccountBalance = (amount: number) => { - return (amount / 10 ** 8).toString() -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/src/utils/networks.ts b/scaffolds/nextjs-flow-universal-wallet/template/src/utils/networks.ts deleted file mode 100644 index d046298..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/src/utils/networks.ts +++ /dev/null @@ -1,49 +0,0 @@ -export enum Network { - FLOW_MAINNET = 'flow-mainnet', - FLOW_TESTNET = 'flow-testnet', -} - -export const getNetworkUrl = () => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.FLOW_MAINNET: - return 'https://rest-mainnet.onflow.org'; - case Network.FLOW_TESTNET: - return 'https://rest-testnet.onflow.org'; - default: - throw new Error('Network not supported'); - } -}; - -export const getNetwork = () => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.FLOW_MAINNET: - return 'mainnet'; - case Network.FLOW_TESTNET: - return 'testnet'; - } -}; - -export const getFaucetUrl = () => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.FLOW_TESTNET: - return 'https://testnet-faucet.onflow.org/fund-account/'; - } -}; - -export const getNetworkName = () => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.FLOW_MAINNET: - return 'Flow (Mainnet)'; - case Network.FLOW_TESTNET: - return 'Flow (Testnet)'; - } -}; - -export const getBlockExplorer = (address: string) => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.FLOW_MAINNET: - return `https://flowscan.org/account/${address}`; - case Network.FLOW_TESTNET: - return `https://testnet.flowscan.org/account/${address}`; - } -}; diff --git a/scaffolds/nextjs-flow-universal-wallet/template/tailwind.config.js b/scaffolds/nextjs-flow-universal-wallet/template/tailwind.config.js deleted file mode 100644 index 7b961b3..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/tailwind.config.js +++ /dev/null @@ -1,15 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - './app/**/*.{js,ts,jsx,tsx,mdx}', - './pages/**/*.{js,ts,jsx,tsx,mdx}', - './components/**/*.{js,ts,jsx,tsx,mdx}', - - // Or if using `src` directory: - './src/**/*.{js,ts,jsx,tsx,mdx}', - ], - theme: { - extend: {}, - }, - plugins: [], -} diff --git a/scaffolds/nextjs-flow-universal-wallet/template/tsconfig.json b/scaffolds/nextjs-flow-universal-wallet/template/tsconfig.json deleted file mode 100644 index 61c19ab..0000000 --- a/scaffolds/nextjs-flow-universal-wallet/template/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] -} diff --git a/scaffolds/nextjs-solana-dedicated-wallet/scaffold.ts b/scaffolds/nextjs-solana-dedicated-wallet/scaffold.ts index 91daf9e..b9423db 100644 --- a/scaffolds/nextjs-solana-dedicated-wallet/scaffold.ts +++ b/scaffolds/nextjs-solana-dedicated-wallet/scaffold.ts @@ -1,6 +1,6 @@ import { Flags } from '../../core/flags'; import BaseScaffold, { ExecaCommand } from '../../core/types/BaseScaffold'; -import { AuthTypePrompt, NpmClientPrompt, PublishableApiKeyPrompt } from '../../scaffolds/prompts'; +import { AuthTypePrompt, NpmClientPrompt, PublishableApiKeyPrompt } from '../prompts'; export type Data = NpmClientPrompt.Data & PublishableApiKeyPrompt.Data & AuthTypePrompt.Data; diff --git a/scaffolds/nextjs-universal-wallet/scaffold.ts b/scaffolds/nextjs-universal-wallet/scaffold.ts deleted file mode 100644 index f28385c..0000000 --- a/scaffolds/nextjs-universal-wallet/scaffold.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Prompt } from 'enquirer'; -import { Flags } from '../../core/flags'; -import BaseScaffold, { ExecaCommand } from '../../core/types/BaseScaffold'; -import { BlockchainNetworkPrompt, PublishableApiKeyPrompt } from '../../scaffolds/prompts'; - -export type Data = BlockchainNetworkPrompt.Data & PublishableApiKeyPrompt.Data; - -export const flags: Flags> = { ...BlockchainNetworkPrompt.flags, ...PublishableApiKeyPrompt.flags }; - -export const definition = { - shortDescription: 'A Universal Wallet scaffold for Next.js', - featured: true, -}; - -export default class UniversalScaffold extends BaseScaffold { - public templateName = 'nextjs-universal-wallet'; - private data: Data; - public installationCommand: ExecaCommand = { command: 'npm', args: ['install'] }; - public startCommand: ExecaCommand = { command: 'npm', args: ['run', 'dev'] }; - public source: string | string[] = './'; - - constructor(data: Data) { - super(); - this.data = data; - } -} diff --git a/scaffolds/nextjs-universal-wallet/template/.env.example b/scaffolds/nextjs-universal-wallet/template/.env.example deleted file mode 100644 index 4b4c3b1..0000000 --- a/scaffolds/nextjs-universal-wallet/template/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -NEXT_PUBLIC_BLOCKCHAIN_NETWORK=<%= network %> -NEXT_PUBLIC_MAGIC_API_KEY=<%= publishableApiKey %> \ No newline at end of file diff --git a/scaffolds/nextjs-universal-wallet/template/.eslintrc.json b/scaffolds/nextjs-universal-wallet/template/.eslintrc.json deleted file mode 100644 index bffb357..0000000 --- a/scaffolds/nextjs-universal-wallet/template/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/scaffolds/nextjs-universal-wallet/template/.gitignore b/scaffolds/nextjs-universal-wallet/template/.gitignore deleted file mode 100644 index c98ad77..0000000 --- a/scaffolds/nextjs-universal-wallet/template/.gitignore +++ /dev/null @@ -1,39 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local -.env - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts - -#environment -.env \ No newline at end of file diff --git a/scaffolds/nextjs-universal-wallet/template/README.md b/scaffolds/nextjs-universal-wallet/template/README.md deleted file mode 100644 index 68281ea..0000000 --- a/scaffolds/nextjs-universal-wallet/template/README.md +++ /dev/null @@ -1,44 +0,0 @@ -This scaffold is meant to help you bootstrap your own projects with Magic's [Universal Wallet](https://magic.link/docs/connect/overview). Magic is a developer SDK that integrates with your application to enable passwordless Web3 onboarding. - -The folder structure of this scaffold is designed to encapsulate all things Magic into one place so you can easily add or remove components and functionality. For example, all Magic-specific components are in the `src/components/magic` directory while generic UI components are in the `src/components/ui` directory. - -## Next.js - -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). - -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. - -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. - -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/scaffolds/nextjs-universal-wallet/template/next.config.js b/scaffolds/nextjs-universal-wallet/template/next.config.js deleted file mode 100644 index 91ef62f..0000000 --- a/scaffolds/nextjs-universal-wallet/template/next.config.js +++ /dev/null @@ -1,6 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - reactStrictMode: true, -}; - -module.exports = nextConfig; diff --git a/scaffolds/nextjs-universal-wallet/template/package.json b/scaffolds/nextjs-universal-wallet/template/package.json deleted file mode 100644 index bfbd8bb..0000000 --- a/scaffolds/nextjs-universal-wallet/template/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "<%= projectName %>", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint --fix" - }, - "dependencies": { - "@types/node": "18.15.11", - "@types/react": "18.0.35", - "@types/react-dom": "18.0.11", - "eslint-config-next": "13.3.0", - "magic-sdk": "^21.0.0", - "next": "13.3.0", - "react": "18.2.0", - "react-dom": "18.2.0", - "typescript": "5.0.4", - "web3": "^4.0.2" - }, - "devDependencies": { - "autoprefixer": "^10.4.15", - "eslint": "^8.45.0", - "postcss": "^8.4.28", - "tailwindcss": "^3.3.3" - } -} diff --git a/scaffolds/nextjs-universal-wallet/template/postcss.config.js b/scaffolds/nextjs-universal-wallet/template/postcss.config.js deleted file mode 100644 index 12a703d..0000000 --- a/scaffolds/nextjs-universal-wallet/template/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/scaffolds/nextjs-universal-wallet/template/public/check.svg b/scaffolds/nextjs-universal-wallet/template/public/check.svg deleted file mode 100644 index a92ed0c..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/check.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/scaffolds/nextjs-universal-wallet/template/public/down-arrow.svg b/scaffolds/nextjs-universal-wallet/template/public/down-arrow.svg deleted file mode 100644 index 7bee9e0..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/down-arrow.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/scaffolds/nextjs-universal-wallet/template/public/favicon.ico b/scaffolds/nextjs-universal-wallet/template/public/favicon.ico deleted file mode 100644 index 718d6fe..0000000 Binary files a/scaffolds/nextjs-universal-wallet/template/public/favicon.ico and /dev/null differ diff --git a/scaffolds/nextjs-universal-wallet/template/public/info.svg b/scaffolds/nextjs-universal-wallet/template/public/info.svg deleted file mode 100644 index df6edb9..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/info.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/scaffolds/nextjs-universal-wallet/template/public/link.svg b/scaffolds/nextjs-universal-wallet/template/public/link.svg deleted file mode 100644 index 09c4941..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/link.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/scaffolds/nextjs-universal-wallet/template/public/link_white.svg b/scaffolds/nextjs-universal-wallet/template/public/link_white.svg deleted file mode 100644 index c87852b..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/link_white.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/scaffolds/nextjs-universal-wallet/template/public/loading.svg b/scaffolds/nextjs-universal-wallet/template/public/loading.svg deleted file mode 100644 index c76c84b..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/loading.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/scaffolds/nextjs-universal-wallet/template/public/login.svg b/scaffolds/nextjs-universal-wallet/template/public/login.svg deleted file mode 100644 index 71a173d..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/login.svg +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scaffolds/nextjs-universal-wallet/template/public/login_bg.png b/scaffolds/nextjs-universal-wallet/template/public/login_bg.png deleted file mode 100644 index a4021c4..0000000 Binary files a/scaffolds/nextjs-universal-wallet/template/public/login_bg.png and /dev/null differ diff --git a/scaffolds/nextjs-universal-wallet/template/public/logo.svg b/scaffolds/nextjs-universal-wallet/template/public/logo.svg deleted file mode 100644 index e13da68..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/logo.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/scaffolds/nextjs-universal-wallet/template/public/magic.svg b/scaffolds/nextjs-universal-wallet/template/public/magic.svg deleted file mode 100644 index a769b49..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/magic.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/scaffolds/nextjs-universal-wallet/template/public/main.svg b/scaffolds/nextjs-universal-wallet/template/public/main.svg deleted file mode 100644 index ae112a2..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/main.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scaffolds/nextjs-universal-wallet/template/public/nft-one.svg b/scaffolds/nextjs-universal-wallet/template/public/nft-one.svg deleted file mode 100644 index 34c5d9b..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/nft-one.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/scaffolds/nextjs-universal-wallet/template/public/nft-three.svg b/scaffolds/nextjs-universal-wallet/template/public/nft-three.svg deleted file mode 100644 index 96766f0..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/nft-three.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/scaffolds/nextjs-universal-wallet/template/public/nft-two.svg b/scaffolds/nextjs-universal-wallet/template/public/nft-two.svg deleted file mode 100644 index bd602b4..0000000 --- a/scaffolds/nextjs-universal-wallet/template/public/nft-two.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/scaffolds/nextjs-universal-wallet/template/public/redirect_bg.png b/scaffolds/nextjs-universal-wallet/template/public/redirect_bg.png deleted file mode 100644 index aa322ee..0000000 Binary files a/scaffolds/nextjs-universal-wallet/template/public/redirect_bg.png and /dev/null differ diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/DevLinks.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/DevLinks.tsx deleted file mode 100644 index 97fc67c..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/DevLinks.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; - -interface Props { - dark?: boolean; - footer?: boolean; -} - -const Links = ({ dark, footer }: Props) => { - return ( -
- -
- - - ); -}; - -export default Links; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/Home.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/Home.tsx deleted file mode 100644 index cf49a0f..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/Home.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import TableOfContents from '../ui/TableOfContents'; -import AppHeader from '../ui/AppHeader'; -import Wallet from './cards/UserInfoCard'; -import WalletMethods from './cards/WalletMethodsCard'; -import SendTransaction from './cards/SendTransactionsCard'; -import Links from './DevLinks'; -import Spacer from '../ui/Spacer'; -interface Props { - setAccount: React.Dispatch>; -} - -export default function Home({ setAccount }: Props) { - return ( -
- - - - - -
- - - - - - -
-
- ); -} diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/Login.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/Login.tsx deleted file mode 100644 index ad9f7bc..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/Login.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React, { useState, useCallback } from 'react'; -import AppHeader from '../ui/AppHeader'; -import Links from './DevLinks'; -import ConnectButton from '../ui/ConnectButton'; -import Spacer from '../ui/Spacer'; -import LoginPageBackground from 'public/login.svg'; -import { useMagicContext } from '@/components/magic/MagicProvider'; - -interface Props { - setAccount: React.Dispatch>; -} - -const Login = ({ setAccount }: Props) => { - const [disabled, setDisabled] = useState(false); - const { magic } = useMagicContext(); - - const connect = useCallback(async () => { - if (!magic) return; - try { - setDisabled(true); - const accounts = await magic.wallet.connectWithUI(); - setDisabled(false); - console.log('Logged in user:', accounts[0]); - localStorage.setItem('user', accounts[0]); - setAccount(accounts[0]); - } catch (error) { - setDisabled(false); - console.error(error); - } - }, [magic, setAccount]); - - return ( -
- - - - - -
- ); -}; - -export default Login; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx deleted file mode 100644 index 2478f09..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/MagicDashboardRedirect.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React, { useCallback } from 'react'; -import Image from 'next/image'; -import Info from 'public/info.svg'; -import Link from 'public/link_white.svg'; -import Logo from 'public/logo.svg'; -import DevLinks from './DevLinks'; - -const MagicDashboardRedirect = () => { - const onClick = useCallback(() => { - window.open('https://dashboard.magic.link/signup', '_blank'); - }, []); - - return ( -
-
- logo -
Magic
-
- Demo -
-
-
-
-
- logo -

- Please set your NEXT_PUBLIC_MAGIC_API_KEY environment variable in .env. You can - get your Magic API key from the Magic Dashboard. -

-
-
- - -
- -
- ); -}; - -export default MagicDashboardRedirect; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/MagicProvider.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/MagicProvider.tsx deleted file mode 100644 index 7c31223..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/MagicProvider.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { createContext, useContext, useEffect, useState } from 'react'; -import { Magic } from 'magic-sdk'; -import { getChainId, getNetworkUrl } from '../../utils/networks'; -const { Web3 } = require('web3'); - -export type MagicContextType = { - magic: Magic | null; - web3: typeof Web3 | null; -}; - -const MagicContext = createContext({ - magic: null, - web3: null, -}); - -export const useMagicContext = () => useContext(MagicContext); - -const MagicProvider = ({ children }: { children: React.ReactNode }) => { - const [magicInstance, setMagicInstance] = useState(null); - const [web3Instance, setWeb3Instance] = useState(null); - - useEffect(() => { - if (process.env.NEXT_PUBLIC_MAGIC_API_KEY) { - const magic = new Magic(process.env.NEXT_PUBLIC_MAGIC_API_KEY as string, { - network: { - rpcUrl: getNetworkUrl(), - chainId: getChainId(), - }, - }); - - setMagicInstance(magic); - setWeb3Instance(new Web3((magic as any).rpcProvider)); - } - }, []); - - return ( - - {children} - - ); -}; - -export default MagicProvider; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/cards/SendTransactionsCard.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/cards/SendTransactionsCard.tsx deleted file mode 100644 index bf23288..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/cards/SendTransactionsCard.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React, { useCallback, useEffect, useState } from 'react'; -import Image from 'next/image'; -import Divider from '../../ui/Divider'; -import FormButton from '../../ui/FormButton'; -import Link from 'public/link.svg'; -import Spacer from '../../ui/Spacer'; -import FormInput from '../../ui/FormInput'; -import Card from '../../ui/Card'; -import CardHeader from '../../ui/CardHeader'; -import TransactionHistory from '../../ui/TransactionHistory'; -import ErrorText from '../../ui/Error'; -import { useMagicContext } from '@/components/magic/MagicProvider'; -import { getFaucetUrl, getNetworkToken, isEip1559Supported } from '@/utils/networks'; - -const SendTransaction = () => { - const { web3 } = useMagicContext(); - const [toAddress, setToAddress] = useState(''); - const [amount, setAmount] = useState(''); - const [disabled, setDisabled] = useState(!toAddress || !amount); - const [hash, setHash] = useState(''); - const [toAddressError, setToAddressError] = useState(false); - const [amountError, setAmountError] = useState(false); - const publicAddress = localStorage.getItem('user'); - const network = localStorage.getItem('network'); - const tokenSymbol = getNetworkToken(); - - useEffect(() => { - setDisabled(!toAddress || !amount); - setAmountError(false); - setToAddressError(false); - }, [amount, toAddress]); - - const sendTransaction = useCallback(async () => { - if (!web3?.utils.isAddress(toAddress)) { - return setToAddressError(true); - } - if (isNaN(Number(amount))) { - return setAmountError(true); - } - setDisabled(true); - const txnParams = { - from: publicAddress, - to: toAddress, - value: web3.utils.toWei(amount, 'ether'), - // Specify `gasPrice` if network doesn't support EIP-1559 - ...(!isEip1559Supported() && { gasPrice: await web3.eth.getGasPrice() }), - }; - web3.eth - .sendTransaction(txnParams as any) - .on('transactionHash', (txHash) => { - setHash(txHash); - console.log('Transaction hash:', txHash); - }) - .then((receipt) => { - setToAddress(''); - setAmount(''); - console.log('Transaction receipt:', receipt); - }) - .catch((error) => { - console.error(error); - setDisabled(false); - }); - }, [web3, amount, publicAddress, toAddress]); - - return ( - - Send Transaction - - null} disabled={false}> - Get Test {tokenSymbol} link-icon - - - - setToAddress(e.target.value)} - placeholder="Receiving Address" - /> - {toAddressError ? Invalid address : null} - setAmount(e.target.value)} - placeholder={`Amount (${tokenSymbol})`} - /> - {amountError ? Invalid amount : null} - - Send Transaction - - - {hash ? ( - <> - - - - ) : null} - - ); -}; - -export default SendTransaction; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/cards/UserInfoCard.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/cards/UserInfoCard.tsx deleted file mode 100644 index 48960a9..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/cards/UserInfoCard.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { useCallback, useEffect, useState } from 'react'; -import Image from 'next/image'; -import Divider from '../../ui/Divider'; -import Loading from 'public/loading.svg'; -import CardLabel from '../../ui/CardLabel'; -import Card from '../../ui/Card'; -import CardHeader from '../../ui/CardHeader'; -import { useMagicContext } from '@/components/magic/MagicProvider'; -import { getNetworkName, getNetworkToken } from '@/utils/networks'; - -interface Props { - setAccount: React.Dispatch>; -} - -const UserInfo = ({ setAccount }: Props) => { - const { magic, web3 } = useMagicContext(); - - const [balance, setBalance] = useState('...'); - const [copied, setCopied] = useState('Copy'); - const [isRefreshing, setIsRefreshing] = useState(false); - - const publicAddress = localStorage.getItem('user'); - const network = localStorage.getItem('network'); - const tokenSymbol = getNetworkToken(); - - const getBalance = useCallback(async () => { - if (publicAddress && web3) { - const balance = await web3.eth.getBalance(publicAddress); - setBalance(web3.utils.fromWei(balance, 'ether')); - console.log('BALANCE: ', balance); - } - }, [web3, publicAddress]); - - const refresh = useCallback(async () => { - setIsRefreshing(true); - await getBalance(); - setTimeout(() => { - setIsRefreshing(false); - }, 500); - }, [getBalance]); - - useEffect(() => { - if (web3) { - refresh(); - } - }, [web3, refresh]); - - useEffect(() => { - setBalance('...'); - }, [magic]); - - const disconnect = useCallback(async () => { - if (magic) { - await magic.wallet.disconnect(); - localStorage.removeItem('user'); - setAccount(null); - } - }, [magic, setAccount]); - - const copy = useCallback(() => { - if (publicAddress && copied === 'Copy') { - setCopied('Copied!'); - navigator.clipboard.writeText(publicAddress); - setTimeout(() => { - setCopied('Copy'); - }, 1000); - } - }, [copied, publicAddress]); - - return ( - - Wallet - Disconnect
} isDisconnect /> -
-
-
Connected to {getNetworkName()}
-
- - {copied}
} /> -
{publicAddress}
- - - loading -
- ) : ( -
Refresh
- ) - } - /> -
- {balance.substring(0, 7)} {tokenSymbol} -
- - ); -}; - -export default UserInfo; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/cards/WalletMethodsCard.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/cards/WalletMethodsCard.tsx deleted file mode 100644 index c0222b0..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/cards/WalletMethodsCard.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import Disconnect from '../wallet-methods/Disconnect'; -import GetWalletInfo from '../wallet-methods/GetWalletInfo'; -import RequestUserInfo from '../wallet-methods/RequestUserInfo'; -import ShowUI from '../wallet-methods/ShowUi'; -import Divider from '../../ui/Divider'; -import Card from '../../ui/Card'; -import CardHeader from '../../ui/CardHeader'; - -interface Props { - setAccount: React.Dispatch>; -} - -const WalletMethods = ({ setAccount }: Props) => { - return ( - - Wallet Methods - - - - - - - - - ); -}; - -export default WalletMethods; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/Disconnect.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/Disconnect.tsx deleted file mode 100644 index 23fc9ca..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/Disconnect.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React, { useCallback, useState } from 'react'; -import Loading from 'public/loading.svg'; -import { useMagicContext } from '@/components/magic/MagicProvider'; -import Image from 'next/image'; - -interface Props { - setAccount: React.Dispatch>; -} - -const Disconnect = ({ setAccount }: Props) => { - const { magic } = useMagicContext(); - const [disabled, setDisabled] = useState(false); - - const disconnect = useCallback(async () => { - if (!magic) return; - try { - setDisabled(true); - await magic.wallet.disconnect(); - localStorage.removeItem('user'); - setDisabled(false); - setAccount(null); - } catch (error) { - setDisabled(false); - console.error(error); - } - }, [magic, setAccount]); - - return ( -
- -
Disconnects user from dApp.
-
- ); -}; - -export default Disconnect; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/GetWalletInfo.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/GetWalletInfo.tsx deleted file mode 100644 index 18c2072..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/GetWalletInfo.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React, { useCallback, useState } from 'react'; -import Loading from 'public/loading.svg'; -import Toast from '../../ui/Toast'; -import { useMagicContext } from '@/components/magic/MagicProvider'; -import Image from 'next/image'; - -const GetWalletInfo = () => { - const { magic } = useMagicContext(); - const [disabled, setDisabled] = useState(false); - const [showToast, setShowToast] = useState(false); - const [walletType, setWalletType] = useState(''); - - const getWalletType = useCallback(async () => { - if (!magic) return; - try { - setDisabled(true); - const walletInfo = await magic.wallet.getInfo(); - setDisabled(false); - setWalletType(walletInfo.walletType); - setShowToast(true); - setTimeout(() => { - setShowToast(false); - }, 3000); - } catch (error) { - setDisabled(false); - console.error(error); - } - }, [magic]); - - return ( -
- -
Returns information about the logged in user's wallet.
- {showToast ? Wallet type: {walletType} : null} -
- ); -}; - -export default GetWalletInfo; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/RequestUserInfo.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/RequestUserInfo.tsx deleted file mode 100644 index 4a68ce9..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/RequestUserInfo.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React, { useCallback, useState } from 'react'; -import Loading from 'public/loading.svg'; -import Toast from '../../ui/Toast'; -import { useMagicContext } from '@/components/magic/MagicProvider'; -import Image from 'next/image'; - -const RequestUserInfo = () => { - const { magic } = useMagicContext(); - const [disabled, setDisabled] = useState(false); - const [showToast, setShowToast] = useState(false); - const [email, setEmail] = useState(''); - - const requestUserInfo = useCallback(async () => { - if (!magic) return; - try { - setDisabled(true); - const userInfo = await magic.wallet.requestUserInfoWithUI(); - setDisabled(false); - setEmail(userInfo.email); - setShowToast(true); - setTimeout(() => { - setShowToast(false); - }, 3000); - } catch (error) { - setDisabled(false); - console.error(error); - } - }, [magic]); - - return ( -
- -
- Prompts the user to consent to sharing information with the requesting dApp. -
- {showToast ? Email: {email} : null} -
- ); -}; - -export default RequestUserInfo; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/ShowUi.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/ShowUi.tsx deleted file mode 100644 index a00c8ee..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/magic/wallet-methods/ShowUi.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { useCallback, useState } from 'react'; -import Loading from 'public/loading.svg'; -import ErrorText from '../../ui/Error'; -import Spacer from '../../ui/Spacer'; -import { useMagicContext } from '@/components/magic/MagicProvider'; -import Image from 'next/image'; - -const ShowUI = () => { - const { magic } = useMagicContext(); - const [disabled, setDisabled] = useState(false); - const [showUIError, setShowUIError] = useState(false); - - const showUI = useCallback(async () => { - if (!magic) return; - try { - setShowUIError(false); - const { walletType } = await magic.wallet.getInfo(); - if (walletType !== 'magic') { - return setShowUIError(true); - } - setDisabled(true); - await magic.wallet.showUI(); - setDisabled(false); - } catch (error) { - setDisabled(false); - console.error(error); - } - }, [magic]); - - return ( -
- -
- Opens wallet view to manage assets, purchase/send/receive crypto, and access recovery phrase. -
- {showUIError ? ( -
- - Method not supported for third party wallets. -
- ) : null} -
- ); -}; - -export default ShowUI; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/AppHeader.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/AppHeader.tsx deleted file mode 100644 index e9c7cf6..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/AppHeader.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import MagicLogo from 'public/magic.svg'; -import Image from 'next/image'; - -const AppHeader = () => { - return ( -
- magic-logo -

Demo

-
- ); -}; - -export default AppHeader; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/CardHeader.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/CardHeader.tsx deleted file mode 100644 index d464970..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/CardHeader.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react' - -interface Props { - children: React.ReactNode - id: string -} - -const CardHeader = ({children, id}: Props) => { - return ( -

- {children} -

- ) -} - -export default CardHeader diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/CardLabel.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/CardLabel.tsx deleted file mode 100644 index 67cb6a7..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/CardLabel.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react' - -interface Props { - leftHeader?: React.ReactNode - rightAction?: React.ReactNode - isDisconnect?: boolean - [rest: string]: any -} - -const CardLabel = ({leftHeader, rightAction, isDisconnect, ...rest}: Props) => { - return ( -
-
{leftHeader}
- {rightAction ? ( -
- {rightAction} -
- ) : null} -
- ) -} - -export default CardLabel diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/ConnectButton.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/ConnectButton.tsx deleted file mode 100644 index e902d6c..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/ConnectButton.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import Loading from 'public/loading.svg'; -import Image from 'next/image'; -interface Props { - onClick: () => void; - disabled: boolean; -} - -const ConnectButton = ({ onClick, disabled }: Props) => { - return ( -
- -
- ); -}; - -export default ConnectButton; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/FormButton.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/FormButton.tsx deleted file mode 100644 index 4afbcb9..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/FormButton.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react' - -interface Props { - children: React.ReactNode - onClick: () => void - disabled: boolean -} - -const FormButton = ({children, onClick, disabled}: Props) => { - return ( - - ) -} - -export default FormButton diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/FormInput.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/FormInput.tsx deleted file mode 100644 index ca0be19..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/FormInput.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react' - -interface Props { - value: string - onChange: (e: any) => void - placeholder: string -} - -const FormInput = ({value, onChange, placeholder}: Props) => { - return ( - - ) -} - -export default FormInput diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/TableOfContents.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/TableOfContents.tsx deleted file mode 100644 index b5cd52b..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/TableOfContents.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, {useCallback, useEffect, useRef, useState} from 'react' - -function useHeadingObserver() { - const observer = useRef() - const [activeId, setActiveId] = useState('') - - useEffect(() => { - const handleObserver = (entries: any) => { - entries.forEach((entry: any) => { - if (entry?.isIntersecting) { - setActiveId(entry.target.id) - } - }) - } - ;(observer as any).current = new IntersectionObserver(handleObserver, { - rootMargin: '0px 0px -82% 0px', - }) - const elements = document.querySelectorAll('h1') - elements.forEach((elem) => (observer as any).current.observe(elem)) - // eslint-disable-next-line react-hooks/exhaustive-deps - return () => (observer.current as any).disconnect() - }, []) - return {activeId} -} - -const TableOfContents = () => { - const [isBottomOfPage, setIsBottomOfPage] = useState(false) - const [headings, setHeadings] = useState([]) - const {activeId} = useHeadingObserver() - - const handleScroll = useCallback(() => { - const bottom = - Math.ceil(window.innerHeight + window.scrollY) >= - document.documentElement.scrollHeight - setIsBottomOfPage(bottom) - }, []) - - useEffect(() => { - const elements = Array.from(document.querySelectorAll('h1')).map( - (elem) => ({ - id: elem.id, - text: elem.innerText, - level: Number(elem.nodeName.charAt(1)), - }) - ) - setHeadings(elements) - - window.addEventListener('scroll', handleScroll, { - passive: true, - }) - return () => { - window.removeEventListener('scroll', handleScroll) - } - }, [handleScroll]) - - return ( - - ) -} - -export default TableOfContents diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/TransactionHistory.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/TransactionHistory.tsx deleted file mode 100644 index c3354f1..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/TransactionHistory.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import Image from 'next/image'; -import Link from 'public/link.svg'; -import { getBlockExplorer } from '@/utils/networks'; - -const TransactionHistory = () => { - const publicAddress = localStorage.getItem('user'); - - return ( - -
- Transaction History link-icon -
-
- ); -}; - -export default TransactionHistory; diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/card.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/card.tsx deleted file mode 100644 index 22c54c4..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/card.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' - -interface Props { - children: React.ReactNode -} - -const Card = ({children}: Props) => { - return
{children}
-} - -export default Card diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/divider.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/divider.tsx deleted file mode 100644 index 337c77c..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/divider.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const Divider = () => { - return
-} - -export default Divider diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/error.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/error.tsx deleted file mode 100644 index 97a17cf..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/error.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const ErrorText = ({children}: any) => { - return
{children}
-} - -export default ErrorText diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/spacer.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/spacer.tsx deleted file mode 100644 index 61e246b..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/spacer.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const Spacer = ({size}: {size: number}) => { - return
-} - -export default Spacer diff --git a/scaffolds/nextjs-universal-wallet/template/src/components/ui/toast.tsx b/scaffolds/nextjs-universal-wallet/template/src/components/ui/toast.tsx deleted file mode 100644 index 49a9d7a..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/components/ui/toast.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const Toast = ({children}: any) => { - return
{children}
-} - -export default Toast diff --git a/scaffolds/nextjs-universal-wallet/template/src/pages/_app.tsx b/scaffolds/nextjs-universal-wallet/template/src/pages/_app.tsx deleted file mode 100644 index c1eb79d..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/pages/_app.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import '@/styles/globals.css' -import type {AppProps} from 'next/app' -import MagicProvider from '@/components/magic/MagicProvider' - -export default function App({Component, pageProps}: AppProps) { - return ( - - - - ) -} diff --git a/scaffolds/nextjs-universal-wallet/template/src/pages/_document.tsx b/scaffolds/nextjs-universal-wallet/template/src/pages/_document.tsx deleted file mode 100644 index af84485..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/pages/_document.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import {Html, Head, Main, NextScript} from 'next/document' - -export default function Document() { - return ( - - - -
- - - - ) -} diff --git a/scaffolds/nextjs-universal-wallet/template/src/pages/index.tsx b/scaffolds/nextjs-universal-wallet/template/src/pages/index.tsx deleted file mode 100644 index 611899c..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/pages/index.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import Login from '../components/magic/Login'; -import Home from '../components/magic/Home'; -import MagicDashboardRedirect from '@/components/magic/MagicDashboardRedirect'; - -export default function App() { - const [account, setAccount] = useState(null); - - useEffect(() => { - const user = localStorage.getItem('user'); - setAccount(user); - }, []); - - /** - * If no Magic API key is set, instruct user to go to Magic Dashboard. - * Otherwise, if user is not logged in, show the Login component. - * Otherwise, show the Home component. - */ - return process.env.NEXT_PUBLIC_MAGIC_API_KEY ? ( - !account ? ( - - ) : ( - - ) - ) : ( - - ); -} diff --git a/scaffolds/nextjs-universal-wallet/template/src/styles/globals.css b/scaffolds/nextjs-universal-wallet/template/src/styles/globals.css deleted file mode 100644 index aeda631..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/styles/globals.css +++ /dev/null @@ -1,290 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap'); -@tailwind base; -@tailwind components; -@tailwind utilities; - -html, -body { - @apply m-0 p-0 bg-[#f8f8fa] scroll-pt-12; - font-family: 'Inter', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.table-of-contents { - @apply w-[220px] min-w-[220px] self-start sticky max-h-[calc(100vh_-_70px)] overflow-auto mt-0 px-0 py-6 top-0; - position: -webkit-sticky; -} - -nav > ul > li { - @apply text-left list-none text-[#777679] cursor-pointer mb-[15px]; -} - -ul { - @apply w-fit m-0 pl-[30px] pr-0 py-0; -} - -.active { - @apply text-[#6851ff] font-semibold; -} - -.active::before { - @apply content-['\2022'] text-[#6851ff] font-[bold] inline-block w-[1em] ml-[-1em]; -} - -.nft { - @apply text-[#777679]; -} - -.nft-name { - @apply font-semibold text-black; - font-family: 'Inter'; -} - -.nft-list { - @apply overflow-auto max-h-[270px]; -} - -.nft:not(:last-child) { - @apply mb-2.5; -} - -.cards-container { - @apply mt-[-260px]; -} - -@media only screen and (max-width: 767px) { - .table-of-contents { - @apply hidden; - } - .cards-container { - @apply mt-[-89px]; - } -} - -.network-dropdown { - @apply m-auto w-fit rounded-xl; -} - -.active-network { - @apply border w-[264px] flex items-center cursor-pointer justify-between m-auto px-4 py-3 rounded-xl border-solid border-[#dddbe0] bg-[#fff]; -} - -.active-network::selection { - @apply bg-transparent; -} - -.rotate { - @apply rotate-180; -} - -.network-options { - @apply overflow-hidden w-fit border mx-auto my-[5px] px-0 py-[5px] rounded-xl border-solid border-[#dddbe0] bg-[#fff]; -} - -.network-dropdown-option { - @apply w-[264px] flex items-center justify-start transition-[0.1s] m-auto px-4 py-3 bg-[#fff]; -} - -.network-dropdown-option:hover { - @apply text-white cursor-pointer bg-[#6851ff]; -} - -.network-dropdown-option:active { - @apply opacity-50; -} -.magic-logo { - @apply mb-[15px] mx-0 text-center; -} -.demo-sub-header { - @apply text-[rgba(255,255,255,0.5)] text-xl font-normal m-0; - font-family: monospace; -} - -.home-page { - @apply flex flex-col justify-center items-center min-h-screen relative bg-[length:100vw_320px] bg-[url('/login_bg.png')] bg-no-repeat; -} - -.login-page { - @apply min-h-screen bg-[length:100%_auto] bg-[url('/login.svg')]; -} -.connect-button { - @apply w-[296px] h-12 text-white font-semibold text-base leading-6 transition-[0.1s] text-center transition-[0.1s] m-auto px-6 py-3 rounded-[300px] border-[none]; - background: rgba(255, 255, 255, 0.1); -} - -.connect-button:hover:enabled { - @apply cursor-pointer; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), rgba(255, 255, 255, 0.1); -} -.connect-button:active:enabled { - @apply opacity-50 cursor-pointer scale-[0.99]; - background: rgba(255, 255, 255, 0.1); -} - -.links { - @apply flex justify-center mx-auto mt-5 mb-3 font-semibold text-white; -} -.link { - @apply transition-[0.1s] px-[30px] py-0; -} - -@media only screen and (max-width: 420px) { - .link { - @apply px-[15px] py-0; - } -} -@media only screen and (max-width: 320px) { - .link { - @apply px-[5px] py-0; - } -} - -.link > a { - @apply cursor-pointer; -} -.link-divider { - @apply w-px h-5; -} - -.footer-links { - @apply flex items-center absolute w-full mt-[30px] mb-0 mx-auto bottom-10; -} -.wallet-method-container { - @apply text-left; -} - -.wallet-method { - @apply w-fit text-[#522fd4] bg-[#edebff] text-base cursor-pointer font-medium transition-[0.1s] h-8 px-3 py-1.5 rounded-[32px] border-[none]; - font-family: monospace; -} - -.wallet-method:hover:enabled { - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; - background-blend-mode: color-burn, normal; -} - -.wallet-method:active:enabled { - @apply opacity-50 scale-[0.99]; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; -} -.wallet-method-desc { - @apply text-[#77767a] text-left text-sm mt-2.5; -} - -.form-input { - @apply box-border flex flex-row items-center w-full h-12 border text-base leading-6 text-[#18171a] mb-[15px] px-4 py-3 rounded-[10px] border-solid border-[#dddbe0]; - background: #ffffff; -} - -.form-input::placeholder { - color: #77767a; -} - -.form-button { - @apply flex flex-row justify-center items-center w-full h-12 text-[#522fd4] font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none] bg-[#edebff]; -} - -.form-button:disabled { - @apply opacity-50; -} - -.form-button:hover:enabled { - @apply cursor-pointer; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; -} -.form-button:active:enabled { - @apply opacity-50 scale-[0.99]; - background: linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)), #edebff; -} - -.loading-container { - @apply w-[50px] text-center flex items-center justify-center cursor-default; -} -.loading { - @apply cursor-default animate-spin; -} - -@keyframes rotation { - 0% { - transform: rotate(0); - } - 100% { - transform: rotate(360deg); - } -} - -.card { - @apply w-[300px] flex flex-col shadow-[0px_4px_24px_rgba(49,49,49,0.1)] mt-0 mb-[27px] mx-auto px-6 py-8 rounded-2xl bg-[#ffffff]; -} - -.card-header { - @apply text-xl font-semibold text-left mt-0 mb-[25px]; -} -.card-label-container { - @apply flex items-center justify-between mb-3; -} - -.card-label { - @apply text-sm font-medium cursor-pointer; -} -.toast { - @apply fixed w-fit text-white font-medium shadow-[4px_8px_20px_rgba(0,0,0,0.15)] mx-auto my-0 px-4 py-2 rounded-[10px] top-[30px] inset-x-0 bg-[#00875f]; -} - -.action-button { - @apply font-semibold text-[#6851ff] cursor-pointer transition-[0.1s]; -} -.disconnect-button { - @apply font-semibold text-[#d43100] cursor-pointer transition-[0.1s]; -} -.action-button:hover, -.disconnect-button:hover { - @apply opacity-70; -} -.action-button:active, -.disconnect-button:active { - @apply scale-[0.98]; -} -.code { - @apply text-base text-left p-2.5 rounded-[10px]; - font-family: monospace; - background: #f8f8fa; - word-wrap: break-word; -} -.error { - @apply text-[#d43100] text-xs text-left -mt-2.5 mb-2.5 mx-0; -} -.divider { - @apply mx-0 my-[15px] border-b-[#ededf3] border-b border-solid; -} -.flex-row { - @apply flex items-center; -} -.green-dot { - @apply h-1.5 w-1.5 bg-[#00cc8f] mr-2.5 rounded-[50%]; -} -.connected { - @apply text-base mx-0 my-[5px]; -} -a { - all: unset; -} - -.app-header-container { - @apply block; - @apply p-6; - text-align: -webkit-center; -} - -.redirect-container { - @apply flex flex-col items-center min-h-screen bg-['100%_auto'] bg-[url('/login.svg')]; -} - -.redirect-card { - @apply bg-[#F8F8FA] rounded-[10px] shadow-[0px_4px_24px_rgba(49,49,49,0.1)] p-2 m-12; -} - -.api-button { - @apply bg-[#6844bc] text-[#FFFFFF] flex w-[280px] justify-center items-center h-12 font-semibold text-base leading-6 transition-[0.1s] px-6 py-3 rounded-[300px] border-[none]; -} diff --git a/scaffolds/nextjs-universal-wallet/template/src/utils/networks.ts b/scaffolds/nextjs-universal-wallet/template/src/utils/networks.ts deleted file mode 100644 index 1d812a8..0000000 --- a/scaffolds/nextjs-universal-wallet/template/src/utils/networks.ts +++ /dev/null @@ -1,129 +0,0 @@ -export enum Network { - POLYGON_AMOY = 'polygon-amoy', - POLYGON = 'polygon', - ETHEREUM_SEPOLIA = 'ethereum-sepolia', - ETHEREUM = 'ethereum', - ETHERLINK_TESTNET = 'etherlink-testnet', - ZKSYNC = 'zksync', - ZKSYNC_SEPOLIA = 'zksync-sepolia', -} - -export const getNetworkUrl = () => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.POLYGON: - return 'https://polygon-rpc.com/'; - case Network.POLYGON_AMOY: - return 'https://rpc-amoy.polygon.technology/'; - case Network.ETHEREUM_SEPOLIA: - return 'https://eth-sepolia.g.alchemy.com/v2/3jKhhva6zBqwp_dnwPlF4d0rFZhu2pjD'; - case Network.ETHEREUM: - return 'https://eth-mainnet.g.alchemy.com/v2/3jKhhva6zBqwp_dnwPlF4d0rFZhu2pjD'; - case Network.ETHERLINK_TESTNET: - return 'https://node.ghostnet.etherlink.com'; - case Network.ZKSYNC: - return 'https://mainnet.era.zksync.io'; - case Network.ZKSYNC_SEPOLIA: - return 'https://sepolia.era.zksync.dev'; - default: - throw new Error('Network not supported'); - } -}; - -export const getChainId = () => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.POLYGON: - return 137; - case Network.POLYGON_AMOY: - return 80002; - case Network.ETHEREUM_SEPOLIA: - return 11155111; - case Network.ZKSYNC: - return 324; - case Network.ZKSYNC_SEPOLIA: - return 300; - case Network.ETHEREUM: - return 1; - case Network.ETHERLINK_TESTNET: - return 128123; - } -}; - -export const getNetworkToken = () => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.POLYGON_AMOY: - case Network.POLYGON: - return 'MATIC'; - case Network.ETHEREUM: - case Network.ETHEREUM_SEPOLIA: - case Network.ZKSYNC: - case Network.ZKSYNC_SEPOLIA: - return 'ETH'; - case Network.ETHERLINK_TESTNET: - return 'XTZ'; - } -}; - -export const getFaucetUrl = () => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.POLYGON_AMOY: - return 'https://faucet.polygon.technology/'; - case Network.ETHEREUM_SEPOLIA: - return 'https://sepoliafaucet.com/'; - case Network.ETHERLINK_TESTNET: - return 'https://faucet.etherlink.com/'; - case Network.ZKSYNC_SEPOLIA: - return 'https://faucet.quicknode.com/ethereum/sepolia'; - } -}; - -export const getNetworkName = () => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.POLYGON: - return 'Polygon (Mainnet)'; - case Network.POLYGON_AMOY: - return 'Polygon (Amoy)'; - case Network.ETHEREUM_SEPOLIA: - return 'Ethereum (Sepolia)'; - case Network.ETHEREUM: - return 'Ethereum (Mainnet)'; - case Network.ETHERLINK_TESTNET: - return 'Etherlink (Testnet)'; - case Network.ZKSYNC: - return 'zkSync (Mainnet)'; - case Network.ZKSYNC_SEPOLIA: - return 'zkSync (Sepolia)'; - } -}; - -export const getBlockExplorer = (address: string) => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.POLYGON: - return `https://polygonscan.com/address/${address}`; - case Network.POLYGON_AMOY: - return `https://www.oklink.com/amoy/address/${address}`; - case Network.ETHEREUM: - return `https://etherscan.io/address/${address}`; - case Network.ETHEREUM_SEPOLIA: - return `https://sepolia.etherscan.io/address/${address}`; - case Network.ETHERLINK_TESTNET: - return `https://testnet-explorer.etherlink.com//address/${address}`; - case Network.ZKSYNC: - return `https://explorer.zksync.io/address/${address}`; - case Network.ZKSYNC_SEPOLIA: - return `https://sepolia.explorer.zksync.io/address/${address}`; - } -}; - -export const isEip1559Supported = () => { - switch (process.env.NEXT_PUBLIC_BLOCKCHAIN_NETWORK) { - case Network.POLYGON: - case Network.POLYGON_AMOY: - case Network.ETHEREUM_SEPOLIA: - case Network.ETHEREUM: - case Network.ZKSYNC: - case Network.ZKSYNC_SEPOLIA: - return true; - case Network.ETHERLINK_TESTNET: - return false; - } -}; diff --git a/scaffolds/nextjs-universal-wallet/template/tailwind.config.js b/scaffolds/nextjs-universal-wallet/template/tailwind.config.js deleted file mode 100644 index 84ecf21..0000000 --- a/scaffolds/nextjs-universal-wallet/template/tailwind.config.js +++ /dev/null @@ -1,15 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - './app/**/*.{js,ts,jsx,tsx,mdx}', - './pages/**/*.{js,ts,jsx,tsx,mdx}', - './components/**/*.{js,ts,jsx,tsx,mdx}', - - // Or if using `src` directory: - './src/**/*.{js,ts,jsx,tsx,mdx}', - ], - theme: { - extend: {}, - }, - plugins: [], -}; diff --git a/scaffolds/nextjs-universal-wallet/template/tsconfig.json b/scaffolds/nextjs-universal-wallet/template/tsconfig.json deleted file mode 100644 index 61c19ab..0000000 --- a/scaffolds/nextjs-universal-wallet/template/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] -} diff --git a/scaffolds/prompts.ts b/scaffolds/prompts.ts index 115b54e..9484d80 100644 --- a/scaffolds/prompts.ts +++ b/scaffolds/prompts.ts @@ -55,16 +55,6 @@ export namespace ProductPrompt { product: string; }; - export const askProduct = async () => - new Select({ - name: 'product', - message: 'Choose your wallet type', - choices: [ - { name: 'universal', message: 'Universal' }, - { name: 'dedicated', message: 'Dedicated' }, - ], - }).run(); - export const flags: Flags> = { product: { type: String, diff --git a/yarn.lock b/yarn.lock index 8808a73..e5d0181 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1043,12 +1043,12 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^3.0.2, braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" buffer-from@^1.0.0: version "1.1.2" @@ -1447,10 +1447,10 @@ duplexer@~0.1.1: resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== -ejs@^3.1.9: - version "3.1.9" - resolved "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz" - integrity sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ== +ejs@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" + integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== dependencies: jake "^10.8.5" @@ -1955,10 +1955,10 @@ filelist@^1.0.4: dependencies: minimatch "^5.0.1" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -2828,10 +2828,10 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -merge@^1.2.0: - version "1.2.1" - resolved "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz" - integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== +merge@^1.2.0, merge@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/merge/-/merge-2.1.1.tgz#59ef4bf7e0b3e879186436e8481c06a6c162ca98" + integrity sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w== micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.5" @@ -3855,6 +3855,18 @@ tar@^6.1.0: mkdirp "^1.0.3" yallist "^4.0.0" +tar@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + terminal-link@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz"