diff --git a/templates/frontend/components/next-app/package.json b/templates/frontend/components/next-app/package.json deleted file mode 100644 index 254dd48a8..000000000 --- a/templates/frontend/components/next-app/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "hello-near", - "version": "1.0.0", - "private": true, - "engines": { - "node": ">=18" - }, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@near-wallet-selector/core": "^8.9.7", - "@near-wallet-selector/here-wallet": "^8.9.7", - "@near-wallet-selector/modal-ui": "^8.9.7", - "@near-wallet-selector/my-near-wallet": "^8.9.7", - "@web3-onboard/core": "^2.21.5", - "@web3-onboard/injected-wallets": "^2.10.15", - "@web3-onboard/ledger": "^2.6.0", - "@web3-onboard/react": "^2.8.16", - "@web3-onboard/walletconnect": "^2.5.4", - "base64-js": "^1.5.1", - "bootstrap": "^5.3.3", - "bootstrap-icons": "^1.11.3", - "ieee754": "^1.2.1", - "near-api-js": "^3.0.4", - "near-social-vm": "github:gagdiez/VM", - "next": "14.2.0", - "pino-pretty": "^11.0.0", - "react": "^18", - "react-dom": "^18" - }, - "overrides": { - "near-api-js": "^3.0.4" - }, - "devDependencies": { - "eslint": "^8.57.0", - "eslint-config-next": "14.2.2" - } -} diff --git a/templates/frontend/components/next-app/src/app/hello-components/page.js b/templates/frontend/components/next-app/src/app/hello-components/page.js deleted file mode 100644 index ea70da643..000000000 --- a/templates/frontend/components/next-app/src/app/hello-components/page.js +++ /dev/null @@ -1,46 +0,0 @@ -import dynamic from 'next/dynamic'; - -import styles from '@/app/app.module.css'; -import { Cards } from '@/components/cards'; -import { Components } from '@/config'; - -const Component = dynamic(() => import('@/components/vm'), { - ssr: false, - loading: () =>

Loading Component...

, -}); - - -export default function HelloComponents() { - return ( - <> -
-
-

- Loading components from:   - {Components.socialDB} -

-
-
-

- Multi-chain Components Made Simple -

-
-
-
- -

 

- -
-
- -
-
-
- -
- -
-
- - ); -} diff --git a/templates/frontend/components/next-app/src/components/cards.js b/templates/frontend/components/next-app/src/components/cards.js deleted file mode 100644 index e074338fa..000000000 --- a/templates/frontend/components/next-app/src/components/cards.js +++ /dev/null @@ -1,43 +0,0 @@ -import Link from 'next/link'; - -import styles from '@/app/app.module.css'; - -export const Cards = () => { - return ( -
- -

- Near Docs -> -

-

Learn how this application works, and what you can build on Near.

- - - -

- Near Integration -> -

-

Discover how simple it is to interact with a Near smart contract.

- - - -

- Web3 Components -> -

-

See how Web3 components can help you to create multi-chain apps.

- -
- ); -}; \ No newline at end of file diff --git a/templates/frontend/components/next-app/src/components/vm.js b/templates/frontend/components/next-app/src/components/vm.js deleted file mode 100644 index 4b5be8166..000000000 --- a/templates/frontend/components/next-app/src/components/vm.js +++ /dev/null @@ -1,31 +0,0 @@ -'use client'; - -import { useEffect, useContext } from 'react'; -import { useInitNear, Widget, EthersProviderContext } from 'near-social-vm'; - -import { NearContext } from '@/context'; -import { NetworkId } from '@/config'; -import { useEthersProviderContext } from '@/wallets/eth'; - -export default function Component({ src }) { - const ethersContext = useEthersProviderContext(); - const { wallet } = useContext(NearContext); - const { initNear } = useInitNear(); - - useEffect(() => { - wallet && initNear && initNear({ networkId: NetworkId, selector: wallet.selector, config: { allowOtherContracts: true } }); - }, [wallet, initNear]); - - const href = wallet.networkId === 'mainnet' ? - `https://near.social/mob.near/widget/WidgetSource?src=${src}` : - `https://test.near.social/eugenethedream/widget/WidgetSource?src=${src}`; - - return ( -
- - - -

Source: {src}

-
- ); -} diff --git a/templates/frontend/components/next-app/src/config.js b/templates/frontend/components/next-app/src/config.js deleted file mode 100644 index 35e2e86ce..000000000 --- a/templates/frontend/components/next-app/src/config.js +++ /dev/null @@ -1,23 +0,0 @@ -const contractPerNetwork = { - mainnet: 'hello.near-examples.near', - testnet: 'hello.near-examples.testnet', -}; - -const componentsPerNetwork = { - mainnet: { - socialDB: 'social.near', - Lido: 'zavodil.near/widget/Lido', - HelloNear: 'gagdiez.near/widget/HelloNear', - LoveNear: 'gagdiez.near/widget/LoveNear', - }, - testnet: { - socialDB: 'v1.social08.testnet', - Lido: 'influencer.testnet/widget/Lido', - HelloNear: 'influencer.testnet/widget/HelloNear', - LoveNear: 'influencer.testnet/widget/LoveNear', - } -}; - -export const NetworkId = 'testnet'; -export const HelloNearContract = contractPerNetwork[NetworkId]; -export const Components = componentsPerNetwork[NetworkId]; \ No newline at end of file diff --git a/templates/frontend/components/next-app/src/wallets/eth.ts b/templates/frontend/components/next-app/src/wallets/eth.ts deleted file mode 100644 index 091596e3c..000000000 --- a/templates/frontend/components/next-app/src/wallets/eth.ts +++ /dev/null @@ -1,289 +0,0 @@ -'use client'; -import type { EIP1193Provider } from '@web3-onboard/core'; -import injectedModule from '@web3-onboard/injected-wallets'; -import ledgerModule from '@web3-onboard/ledger'; -import { init, useConnectWallet } from '@web3-onboard/react'; -import walletConnectModule from '@web3-onboard/walletconnect'; -import { useEffect, useState } from 'react'; -import { singletonHook } from 'react-singleton-hook'; - -const web3onboardKey = 'web3-onboard:connectedWallets'; - -const wcV2InitOptions: any = { - version: 2, - projectId: '72b7b3359ab477e339a070f615806aa6', - requiredChains: [1, 56], -}; - -const walletConnect = walletConnectModule(wcV2InitOptions); -const ledger = ledgerModule(wcV2InitOptions); -const injected = injectedModule(); - -// initialize Onboard -export const onboard = init({ - wallets: [injected, walletConnect, ledger], - chains: [ - { - id: 1, - token: 'ETH', - label: 'Ethereum Mainnet', - rpcUrl: 'https://rpc.ankr.com/eth', - }, - { - id: 3, - token: 'ETH', - label: 'Ropsten - Ethereum Testnet', - rpcUrl: 'https://rpc.ankr.com/eth_ropsten', - }, - { - id: 5, - token: 'ETH', - label: 'Goerli - Ethereum Testnet', - rpcUrl: 'https://rpc.ankr.com/eth_goerli', - }, - { - id: 10, - token: 'ETH', - label: 'Optimism', - rpcUrl: 'https://rpc.ankr.com/optimism', - }, - { - id: 420, - token: 'ETH', - label: 'Optimism Goerli Testnet', - rpcUrl: 'https://optimism-goerli.publicnode.com', - }, - { - id: 56, - token: 'BNB', - label: 'Binance Smart Chain Mainnet', - rpcUrl: 'https://bsc.publicnode.com', - }, - { - id: 97, - token: 'tBNB', - label: 'Binance Smart Chain Testnet', - rpcUrl: 'https://bsc-testnet.publicnode.com', - }, - { - id: 1313161554, - token: 'ETH', - label: 'Aurora Mainnet', - rpcUrl: 'https://mainnet.aurora.dev', - }, - { - id: 1313161555, - token: 'ETH', - label: 'Aurora Testnet', - rpcUrl: 'https://testnet.aurora.dev', - }, - { - id: 137, - token: 'MATIC', - label: 'Polygon Mainnet', - rpcUrl: 'https://rpc.ankr.com/polygon', - }, - { - id: 80001, - token: 'MATIC', - label: 'Polygon Testnet Mumbai', - rpcUrl: 'https://rpc.ankr.com/polygon_mumbai', - }, - { - id: 280, - token: 'ETH', - label: 'zkSync Era Testnet', - rpcUrl: 'https://testnet.era.zksync.dev', - }, - { - id: 324, - token: 'ETH', - label: 'zkSync Era Mainnet', - rpcUrl: 'https://zksync2-mainnet.zksync.io', - }, - { - id: 1101, - token: 'ETH', - label: 'Polygon zkEVM', - rpcUrl: 'https://zkevm-rpc.com', - }, - { - id: 1442, - token: 'ETH', - label: 'Polygon zkEVM Testnet', - rpcUrl: 'https://rpc.public.zkevm-test.net', - }, - { - id: 42161, - token: 'ETH', - label: 'Arbitrum One Mainnet', - rpcUrl: 'https://arb1.arbitrum.io/rpc', - }, - { - id: 42170, - token: 'ETH', - label: 'Arbitrum Nova', - rpcUrl: 'https://nova.arbitrum.io/rpc', - }, - { - id: 421613, - token: 'AGOR', - label: 'Arbitrum Goerli', - rpcUrl: 'https://goerli-rollup.arbitrum.io/rpc', - }, - { - id: 25, - token: 'CRO', - label: 'Cronos Mainnet Beta', - rpcUrl: 'https://evm.cronos.org', - }, - { - id: 338, - token: 'TCRO', - label: 'Cronos Testnet', - rpcUrl: 'https://evm-t3.cronos.org', - }, - { - id: 100, - token: 'XDAI', - label: 'Gnosis', - rpcUrl: 'https://rpc.ankr.com/gnosis', - }, - { - id: 10200, - token: 'XDAI', - label: 'Gnosis Chiado Testnet', - rpcUrl: 'https://rpc.chiadochain.net', - }, - { - id: 42220, - token: 'CELO', - label: 'Celo Mainnet', - rpcUrl: 'https://rpc.ankr.com/celo', - }, - { - id: 44787, - token: 'CELO', - label: 'Celo Alfajores Testnet', - rpcUrl: 'https://alfajores-forno.celo-testnet.org', - }, - { - id: 43114, - token: 'AVAX', - label: 'Avalanche C-Chain', - rpcUrl: 'https://rpc.ankr.com/avalanche', - }, - { - id: 43113, - token: 'AVAX', - label: 'Avalanche Fuji Testnet', - rpcUrl: 'https://rpc.ankr.com/avalanche_fuji', - }, - { - id: 250, - token: 'FTM', - label: 'Fantom Opera', - rpcUrl: 'https://rpc.ankr.com/fantom', - }, - { - id: 4002, - token: 'FTM', - label: 'Fantom Testnet', - rpcUrl: 'https://rpc.ankr.com/fantom_testnet', - }, - { - id: 1284, - token: 'GLMR', - label: 'Moonbeam', - rpcUrl: 'https://rpc.ankr.com/moonbeam', - }, - { - id: 61, - token: 'ETC', - label: 'Ethereum Classic Mainnet', - rpcUrl: 'https://etc.rivet.link', - }, - { - id: 84531, - token: 'ETH', - label: 'Base Goerli Testnet', - rpcUrl: 'https://goerli.base.org', - }, - { - id: 8453, - token: 'ETH', - label: 'Base', - rpcUrl: 'https://mainnet.base.org', - }, - { - id: 5001, - token: 'MNT', - label: 'Mantle Testnet', - rpcUrl: 'https://rpc.testnet.mantle.xyz', - }, - { - id: 5000, - token: 'MNT', - label: 'Mantle', - rpcUrl: 'https://rpc.mantle.xyz', - }, - ], - appMetadata: { - name: 'NEAR', - icon: '/next.svg', - description: 'NEAR', - }, - theme: 'dark', - containerElements: { - // connectModal: '#near-social-navigation-bar', - // accountCenter: "#near-social-web3-account", - }, -}); - -type EthersProviderContext = { - provider?: EIP1193Provider; - useConnectWallet: typeof useConnectWallet; -}; - -const defaultEthersProviderContext: EthersProviderContext = { useConnectWallet }; - -export const useEthersProviderContext = singletonHook(defaultEthersProviderContext, () => { - const [{ wallet }] = useConnectWallet(); - const [ethersProvider, setEthersProvider] = useState(defaultEthersProviderContext); - - useEffect(() => { - (async () => { - if (typeof localStorage === 'undefined') return; - - const walletsSub = onboard.state.select('wallets'); - - walletsSub.subscribe((wallets) => { - const connectedWallets = wallets.map(({ label }) => label); - localStorage.setItem(web3onboardKey, JSON.stringify(connectedWallets)); - }); - - const previouslyConnectedWallets = JSON.parse(localStorage.getItem(web3onboardKey) || '[]'); - - if (previouslyConnectedWallets) { - // You can also auto connect "silently" and disable all onboard modals to avoid them flashing on page load - await onboard.connectWallet({ - autoSelect: { - label: previouslyConnectedWallets[0], - disableModals: true, - }, - }); - } - })(); - }, []); - - useEffect(() => { - if (!wallet) return; - - setEthersProvider({ - provider: wallet.provider, - useConnectWallet, - }); - }, [wallet]); - - return ethersProvider; -}); \ No newline at end of file diff --git a/templates/frontend/components/next-page/package.json b/templates/frontend/components/next-page/package.json deleted file mode 100644 index 254dd48a8..000000000 --- a/templates/frontend/components/next-page/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "hello-near", - "version": "1.0.0", - "private": true, - "engines": { - "node": ">=18" - }, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@near-wallet-selector/core": "^8.9.7", - "@near-wallet-selector/here-wallet": "^8.9.7", - "@near-wallet-selector/modal-ui": "^8.9.7", - "@near-wallet-selector/my-near-wallet": "^8.9.7", - "@web3-onboard/core": "^2.21.5", - "@web3-onboard/injected-wallets": "^2.10.15", - "@web3-onboard/ledger": "^2.6.0", - "@web3-onboard/react": "^2.8.16", - "@web3-onboard/walletconnect": "^2.5.4", - "base64-js": "^1.5.1", - "bootstrap": "^5.3.3", - "bootstrap-icons": "^1.11.3", - "ieee754": "^1.2.1", - "near-api-js": "^3.0.4", - "near-social-vm": "github:gagdiez/VM", - "next": "14.2.0", - "pino-pretty": "^11.0.0", - "react": "^18", - "react-dom": "^18" - }, - "overrides": { - "near-api-js": "^3.0.4" - }, - "devDependencies": { - "eslint": "^8.57.0", - "eslint-config-next": "14.2.2" - } -} diff --git a/templates/frontend/components/next-page/src/components/cards.js b/templates/frontend/components/next-page/src/components/cards.js deleted file mode 100644 index 44942c249..000000000 --- a/templates/frontend/components/next-page/src/components/cards.js +++ /dev/null @@ -1,43 +0,0 @@ -import Link from 'next/link'; - -import styles from '@/styles/app.module.css'; - -export const Cards = () => { - return ( -
- -

- Near Docs -> -

-

Learn how this application works, and what you can build on Near.

- - - -

- Near Integration -> -

-

Discover how simple it is to interact with a Near smart contract.

- - - -

- Web3 Components -> -

-

See how Web3 components can help you to create multi-chain apps.

- -
- ); -}; \ No newline at end of file diff --git a/templates/frontend/components/next-page/src/components/vm.js b/templates/frontend/components/next-page/src/components/vm.js deleted file mode 100644 index 34f12d816..000000000 --- a/templates/frontend/components/next-page/src/components/vm.js +++ /dev/null @@ -1,29 +0,0 @@ -import { useEffect, useContext } from 'react'; -import { useInitNear, Widget, EthersProviderContext } from 'near-social-vm'; - -import { NearContext } from '@/context'; -import { NetworkId } from '@/config'; -import { useEthersProviderContext } from '@/wallets/eth'; - -export default function Component({ src }) { - const ethersContext = useEthersProviderContext(); - const { wallet } = useContext(NearContext); - const { initNear } = useInitNear(); - - useEffect(() => { - wallet && initNear && initNear({ networkId: NetworkId, selector: wallet.selector, config: { allowOtherContracts: true } }); - }, [wallet, initNear]); - - const href = wallet.networkId === 'mainnet' ? - `https://near.social/mob.near/widget/WidgetSource?src=${src}` : - `https://test.near.social/eugenethedream/widget/WidgetSource?src=${src}`; - - return ( -
- - - -

Source: {src}

-
- ); -} diff --git a/templates/frontend/components/next-page/src/config.js b/templates/frontend/components/next-page/src/config.js deleted file mode 100644 index 35e2e86ce..000000000 --- a/templates/frontend/components/next-page/src/config.js +++ /dev/null @@ -1,23 +0,0 @@ -const contractPerNetwork = { - mainnet: 'hello.near-examples.near', - testnet: 'hello.near-examples.testnet', -}; - -const componentsPerNetwork = { - mainnet: { - socialDB: 'social.near', - Lido: 'zavodil.near/widget/Lido', - HelloNear: 'gagdiez.near/widget/HelloNear', - LoveNear: 'gagdiez.near/widget/LoveNear', - }, - testnet: { - socialDB: 'v1.social08.testnet', - Lido: 'influencer.testnet/widget/Lido', - HelloNear: 'influencer.testnet/widget/HelloNear', - LoveNear: 'influencer.testnet/widget/LoveNear', - } -}; - -export const NetworkId = 'testnet'; -export const HelloNearContract = contractPerNetwork[NetworkId]; -export const Components = componentsPerNetwork[NetworkId]; \ No newline at end of file diff --git a/templates/frontend/components/next-page/src/pages/hello-components/index.js b/templates/frontend/components/next-page/src/pages/hello-components/index.js deleted file mode 100644 index 1d518ffcc..000000000 --- a/templates/frontend/components/next-page/src/pages/hello-components/index.js +++ /dev/null @@ -1,46 +0,0 @@ -import dynamic from 'next/dynamic'; - -import styles from '@/styles/app.module.css'; -import { Cards } from '@/components/cards'; -import { Components } from '@/config'; - -const Component = dynamic(() => import('@/components/vm'), { - ssr: false, - loading: () =>

Loading Component...

, -}); - - -export default function HelloComponents() { - return ( - <> -
-
-

- Loading components from:   - {Components.socialDB} -

-
-
-

- Multi-chain Components Made Simple -

-
-
-
- -

 

- -
-
- -
-
-
- -
- -
-
- - ); -} diff --git a/templates/frontend/components/next-page/src/wallets/eth.ts b/templates/frontend/components/next-page/src/wallets/eth.ts deleted file mode 100644 index 091596e3c..000000000 --- a/templates/frontend/components/next-page/src/wallets/eth.ts +++ /dev/null @@ -1,289 +0,0 @@ -'use client'; -import type { EIP1193Provider } from '@web3-onboard/core'; -import injectedModule from '@web3-onboard/injected-wallets'; -import ledgerModule from '@web3-onboard/ledger'; -import { init, useConnectWallet } from '@web3-onboard/react'; -import walletConnectModule from '@web3-onboard/walletconnect'; -import { useEffect, useState } from 'react'; -import { singletonHook } from 'react-singleton-hook'; - -const web3onboardKey = 'web3-onboard:connectedWallets'; - -const wcV2InitOptions: any = { - version: 2, - projectId: '72b7b3359ab477e339a070f615806aa6', - requiredChains: [1, 56], -}; - -const walletConnect = walletConnectModule(wcV2InitOptions); -const ledger = ledgerModule(wcV2InitOptions); -const injected = injectedModule(); - -// initialize Onboard -export const onboard = init({ - wallets: [injected, walletConnect, ledger], - chains: [ - { - id: 1, - token: 'ETH', - label: 'Ethereum Mainnet', - rpcUrl: 'https://rpc.ankr.com/eth', - }, - { - id: 3, - token: 'ETH', - label: 'Ropsten - Ethereum Testnet', - rpcUrl: 'https://rpc.ankr.com/eth_ropsten', - }, - { - id: 5, - token: 'ETH', - label: 'Goerli - Ethereum Testnet', - rpcUrl: 'https://rpc.ankr.com/eth_goerli', - }, - { - id: 10, - token: 'ETH', - label: 'Optimism', - rpcUrl: 'https://rpc.ankr.com/optimism', - }, - { - id: 420, - token: 'ETH', - label: 'Optimism Goerli Testnet', - rpcUrl: 'https://optimism-goerli.publicnode.com', - }, - { - id: 56, - token: 'BNB', - label: 'Binance Smart Chain Mainnet', - rpcUrl: 'https://bsc.publicnode.com', - }, - { - id: 97, - token: 'tBNB', - label: 'Binance Smart Chain Testnet', - rpcUrl: 'https://bsc-testnet.publicnode.com', - }, - { - id: 1313161554, - token: 'ETH', - label: 'Aurora Mainnet', - rpcUrl: 'https://mainnet.aurora.dev', - }, - { - id: 1313161555, - token: 'ETH', - label: 'Aurora Testnet', - rpcUrl: 'https://testnet.aurora.dev', - }, - { - id: 137, - token: 'MATIC', - label: 'Polygon Mainnet', - rpcUrl: 'https://rpc.ankr.com/polygon', - }, - { - id: 80001, - token: 'MATIC', - label: 'Polygon Testnet Mumbai', - rpcUrl: 'https://rpc.ankr.com/polygon_mumbai', - }, - { - id: 280, - token: 'ETH', - label: 'zkSync Era Testnet', - rpcUrl: 'https://testnet.era.zksync.dev', - }, - { - id: 324, - token: 'ETH', - label: 'zkSync Era Mainnet', - rpcUrl: 'https://zksync2-mainnet.zksync.io', - }, - { - id: 1101, - token: 'ETH', - label: 'Polygon zkEVM', - rpcUrl: 'https://zkevm-rpc.com', - }, - { - id: 1442, - token: 'ETH', - label: 'Polygon zkEVM Testnet', - rpcUrl: 'https://rpc.public.zkevm-test.net', - }, - { - id: 42161, - token: 'ETH', - label: 'Arbitrum One Mainnet', - rpcUrl: 'https://arb1.arbitrum.io/rpc', - }, - { - id: 42170, - token: 'ETH', - label: 'Arbitrum Nova', - rpcUrl: 'https://nova.arbitrum.io/rpc', - }, - { - id: 421613, - token: 'AGOR', - label: 'Arbitrum Goerli', - rpcUrl: 'https://goerli-rollup.arbitrum.io/rpc', - }, - { - id: 25, - token: 'CRO', - label: 'Cronos Mainnet Beta', - rpcUrl: 'https://evm.cronos.org', - }, - { - id: 338, - token: 'TCRO', - label: 'Cronos Testnet', - rpcUrl: 'https://evm-t3.cronos.org', - }, - { - id: 100, - token: 'XDAI', - label: 'Gnosis', - rpcUrl: 'https://rpc.ankr.com/gnosis', - }, - { - id: 10200, - token: 'XDAI', - label: 'Gnosis Chiado Testnet', - rpcUrl: 'https://rpc.chiadochain.net', - }, - { - id: 42220, - token: 'CELO', - label: 'Celo Mainnet', - rpcUrl: 'https://rpc.ankr.com/celo', - }, - { - id: 44787, - token: 'CELO', - label: 'Celo Alfajores Testnet', - rpcUrl: 'https://alfajores-forno.celo-testnet.org', - }, - { - id: 43114, - token: 'AVAX', - label: 'Avalanche C-Chain', - rpcUrl: 'https://rpc.ankr.com/avalanche', - }, - { - id: 43113, - token: 'AVAX', - label: 'Avalanche Fuji Testnet', - rpcUrl: 'https://rpc.ankr.com/avalanche_fuji', - }, - { - id: 250, - token: 'FTM', - label: 'Fantom Opera', - rpcUrl: 'https://rpc.ankr.com/fantom', - }, - { - id: 4002, - token: 'FTM', - label: 'Fantom Testnet', - rpcUrl: 'https://rpc.ankr.com/fantom_testnet', - }, - { - id: 1284, - token: 'GLMR', - label: 'Moonbeam', - rpcUrl: 'https://rpc.ankr.com/moonbeam', - }, - { - id: 61, - token: 'ETC', - label: 'Ethereum Classic Mainnet', - rpcUrl: 'https://etc.rivet.link', - }, - { - id: 84531, - token: 'ETH', - label: 'Base Goerli Testnet', - rpcUrl: 'https://goerli.base.org', - }, - { - id: 8453, - token: 'ETH', - label: 'Base', - rpcUrl: 'https://mainnet.base.org', - }, - { - id: 5001, - token: 'MNT', - label: 'Mantle Testnet', - rpcUrl: 'https://rpc.testnet.mantle.xyz', - }, - { - id: 5000, - token: 'MNT', - label: 'Mantle', - rpcUrl: 'https://rpc.mantle.xyz', - }, - ], - appMetadata: { - name: 'NEAR', - icon: '/next.svg', - description: 'NEAR', - }, - theme: 'dark', - containerElements: { - // connectModal: '#near-social-navigation-bar', - // accountCenter: "#near-social-web3-account", - }, -}); - -type EthersProviderContext = { - provider?: EIP1193Provider; - useConnectWallet: typeof useConnectWallet; -}; - -const defaultEthersProviderContext: EthersProviderContext = { useConnectWallet }; - -export const useEthersProviderContext = singletonHook(defaultEthersProviderContext, () => { - const [{ wallet }] = useConnectWallet(); - const [ethersProvider, setEthersProvider] = useState(defaultEthersProviderContext); - - useEffect(() => { - (async () => { - if (typeof localStorage === 'undefined') return; - - const walletsSub = onboard.state.select('wallets'); - - walletsSub.subscribe((wallets) => { - const connectedWallets = wallets.map(({ label }) => label); - localStorage.setItem(web3onboardKey, JSON.stringify(connectedWallets)); - }); - - const previouslyConnectedWallets = JSON.parse(localStorage.getItem(web3onboardKey) || '[]'); - - if (previouslyConnectedWallets) { - // You can also auto connect "silently" and disable all onboard modals to avoid them flashing on page load - await onboard.connectWallet({ - autoSelect: { - label: previouslyConnectedWallets[0], - disableModals: true, - }, - }); - } - })(); - }, []); - - useEffect(() => { - if (!wallet) return; - - setEthersProvider({ - provider: wallet.provider, - useConnectWallet, - }); - }, [wallet]); - - return ethersProvider; -}); \ No newline at end of file diff --git a/templates/frontend/next-app/package.json b/templates/frontend/next-app/package.json index 9d81fdc12..217f604f4 100644 --- a/templates/frontend/next-app/package.json +++ b/templates/frontend/next-app/package.json @@ -12,26 +12,34 @@ "lint": "next lint" }, "dependencies": { - "@near-wallet-selector/core": "^8.9.12", - "@near-wallet-selector/here-wallet": "^8.9.12", - "@near-wallet-selector/ledger": "^8.9.12", - "@near-wallet-selector/meteor-wallet": "^8.9.12", - "@near-wallet-selector/modal-ui": "^8.9.12", - "@near-wallet-selector/my-near-wallet": "^8.9.12", - "@near-wallet-selector/bitte-wallet": "^8.9.12", - "@near-wallet-selector/sender": "^8.9.12", + "@near-js/providers": "^1.0.0", + "@near-wallet-selector/bitte-wallet": "^8.9.13", + "@near-wallet-selector/core": "^8.9.13", + "@near-wallet-selector/ethereum-wallets": "^8.9.13", + "@near-wallet-selector/here-wallet": "^8.9.13", + "@near-wallet-selector/ledger": "^8.9.13", + "@near-wallet-selector/meteor-wallet": "^8.9.13", + "@near-wallet-selector/modal-ui": "^8.9.13", + "@near-wallet-selector/my-near-wallet": "^8.9.13", + "@near-wallet-selector/sender": "^8.9.13", + "@web3modal/wagmi": "^5.1.10", "bootstrap": "^5", "bootstrap-icons": "^1.11.3", "near-api-js": "^4.0.3", - "next": "14.2.3", + "next": "14.2.13", "react": "^18", - "react-dom": "^18" + "react-dom": "^18", + "wagmi": "^2.12.16" }, - "resolutions": { - "near-api-js": "4.0.4" + "overrides": { + "@near-wallet-selector/ethereum-wallets": { + "near-api-js": "4.0.3" + } }, "devDependencies": { + "encoding": "^0.1.13", "eslint": "^8", - "eslint-config-next": "14.2.3" + "eslint-config-next": "14.2.13", + "pino-pretty": "^11.2.2" } } diff --git a/templates/frontend/next-app/src/app/hello-near/page.js b/templates/frontend/next-app/src/app/hello-near/page.js index 6f746d44f..0222a262b 100644 --- a/templates/frontend/next-app/src/app/hello-near/page.js +++ b/templates/frontend/next-app/src/app/hello-near/page.js @@ -4,7 +4,7 @@ import { useState, useEffect, useContext } from 'react'; import styles from '@/app/app.module.css'; import { Cards } from '@/components/cards'; -import { NearContext } from '@/context'; +import { NearContext } from '@/wallets/near'; import { HelloNearContract } from '@/config'; // Contract that the app will interact with diff --git a/templates/frontend/next-app/src/app/layout.js b/templates/frontend/next-app/src/app/layout.js index ad700a456..a39e8cc7a 100644 --- a/templates/frontend/next-app/src/app/layout.js +++ b/templates/frontend/next-app/src/app/layout.js @@ -3,11 +3,10 @@ import { useEffect, useState } from 'react'; import '@/app/globals.css'; -import { NearContext } from '@/context'; import { Navigation } from '@/components/navigation'; import { NetworkId } from '@/config'; -import { Wallet } from '@/wallets/near'; +import { NearContext, Wallet } from '@/wallets/near'; const wallet = new Wallet({ networkId: NetworkId }); diff --git a/templates/frontend/next-app/src/components/navigation.js b/templates/frontend/next-app/src/components/navigation.js index 6849b8b66..5ac4c8be1 100644 --- a/templates/frontend/next-app/src/components/navigation.js +++ b/templates/frontend/next-app/src/components/navigation.js @@ -2,7 +2,7 @@ import Image from 'next/image'; import Link from 'next/link'; import { useEffect, useState, useContext } from 'react'; -import { NearContext } from '@/context'; +import { NearContext } from '@/wallets/near'; import NearLogo from '/public/near-logo.svg'; export const Navigation = () => { diff --git a/templates/frontend/next-app/src/config.js b/templates/frontend/next-app/src/config.js index c97f8cb0e..eb0ffd942 100644 --- a/templates/frontend/next-app/src/config.js +++ b/templates/frontend/next-app/src/config.js @@ -3,5 +3,22 @@ const contractPerNetwork = { testnet: 'hello.near-examples.testnet', }; +// Chains for EVM Wallets +const evmWalletChains = { + mainnet: { + chainId: 397, + name: "Near Mainnet", + explorer: "https://eth-explorer.near.org", + rpc: "https://eth-rpc.mainnet.near.org", + }, + testnet: { + chainId: 398, + name: "Near Testnet", + explorer: "https://eth-explorer-testnet.near.org", + rpc: "https://eth-rpc.testnet.near.org", + }, +} + export const NetworkId = 'testnet'; -export const HelloNearContract = contractPerNetwork[NetworkId]; \ No newline at end of file +export const HelloNearContract = contractPerNetwork[NetworkId]; +export const EVMWalletChain = evmWalletChains[NetworkId]; \ No newline at end of file diff --git a/templates/frontend/next-app/src/context.js b/templates/frontend/next-app/src/context.js deleted file mode 100644 index 74223096a..000000000 --- a/templates/frontend/next-app/src/context.js +++ /dev/null @@ -1,13 +0,0 @@ -import { createContext } from 'react'; - -/** - * @typedef NearContext - * @property {import('./wallets/near').Wallet} wallet Current wallet - * @property {string} signedAccountId The AccountId of the signed user - */ - -/** @type {import ('react').Context} */ -export const NearContext = createContext({ - wallet: undefined, - signedAccountId: '' -}); \ No newline at end of file diff --git a/templates/frontend/next-app/src/wallets/near.js b/templates/frontend/next-app/src/wallets/near.js index 61616ab79..0ec844a18 100644 --- a/templates/frontend/next-app/src/wallets/near.js +++ b/templates/frontend/next-app/src/wallets/near.js @@ -1,8 +1,7 @@ import { createContext } from 'react'; -import { distinctUntilChanged, map } from 'rxjs'; // near api js -import { providers } from 'near-api-js'; +import { providers, utils } from 'near-api-js'; // wallet selector import '@near-wallet-selector/modal-ui/styles.css'; @@ -15,6 +14,10 @@ import { setupMeteorWallet } from '@near-wallet-selector/meteor-wallet'; import { setupSender } from '@near-wallet-selector/sender'; import { setupBitteWallet } from '@near-wallet-selector/bitte-wallet'; +// ethereum wallets +import { wagmiConfig, web3Modal } from '@/wallets/web3modal'; +import { setupEthereumWallets } from "@near-wallet-selector/ethereum-wallets"; + const THIRTY_TGAS = '30000000000000'; const NO_DEPOSIT = '0'; @@ -48,6 +51,7 @@ export class Wallet { setupMeteorWallet(), setupSender(), setupBitteWallet(), + setupEthereumWallets({ wagmiConfig, web3Modal, alwaysOnboardDuringSignIn: true }), ], }); @@ -55,15 +59,10 @@ export class Wallet { const isSignedIn = walletSelector.isSignedIn(); const accountId = isSignedIn ? walletSelector.store.getState().accounts[0].accountId : ''; - walletSelector.store.observable - .pipe( - map(state => state.accounts), - distinctUntilChanged() - ) - .subscribe(accounts => { - const signedAccount = accounts.find((account) => account.active)?.accountId; - accountChangeHook(signedAccount); - }); + walletSelector.store.observable.subscribe(async (state) => { + const signedAccount = state?.accounts.find(account => account.active)?.accountId; + accountChangeHook(signedAccount || ''); + }); return accountId; }; @@ -152,6 +151,12 @@ export class Wallet { return providers.getTransactionLastResult(transaction); }; + /** + * Gets the balance of an account + * @param {string} accountId - the account id to get the balance of + * @returns {Promise} - the balance of the account + * + */ getBalance = async (accountId) => { const walletSelector = await this.selector; const { network } = walletSelector.options; @@ -167,12 +172,44 @@ export class Wallet { return account.amount ? Number(utils.format.formatNearAmount(account.amount)) : 0; }; + /** + * Signs and sends transactions + * @param {Object[]} transactions - the transactions to sign and send + * @returns {Promise} - the resulting transactions + * + */ signAndSendTransactions = async ({ transactions }) => { const selectedWallet = await (await this.selector).wallet(); return selectedWallet.signAndSendTransactions({ transactions }); }; + + /** + * + * @param {string} accountId + * @returns {Promise} - the access keys for the + */ + getAccessKeys = async (accountId) => { + const walletSelector = await this.selector; + const { network } = walletSelector.options; + const provider = new providers.JsonRpcProvider({ url: network.nodeUrl }); + + // Retrieve account state from the network + const keys = await provider.query({ + request_type: 'view_access_key_list', + account_id: accountId, + finality: 'final', + }); + return keys.keys; + }; } +/** + * @typedef NearContext + * @property {import('./wallets/near').Wallet} wallet Current wallet + * @property {string} signedAccountId The AccountId of the signed user + */ + +/** @type {import ('react').Context} */ export const NearContext = createContext({ wallet: undefined, signedAccountId: '', diff --git a/templates/frontend/next-app/src/wallets/web3modal.js b/templates/frontend/next-app/src/wallets/web3modal.js new file mode 100644 index 000000000..2ea9d91d0 --- /dev/null +++ b/templates/frontend/next-app/src/wallets/web3modal.js @@ -0,0 +1,44 @@ +import { NetworkId, EVMWalletChain } from '@/config'; +import { reconnect, http, createConfig } from "@wagmi/core"; +import { walletConnect, injected } from "@wagmi/connectors"; +import { createWeb3Modal } from "@web3modal/wagmi"; + +// Config +const near = { + id: EVMWalletChain.chainId, + name: EVMWalletChain.name, + nativeCurrency: { + decimals: 18, + name: "NEAR", + symbol: "NEAR", + }, + rpcUrls: { + default: { http: [EVMWalletChain.rpc] }, + public: { http: [EVMWalletChain.rpc] }, + }, + blockExplorers: { + default: { + name: "NEAR Explorer", + url: EVMWalletChain.explorer, + }, + }, + testnet: NetworkId === "testnet", +}; + +// Get your projectId at https://cloud.reown.com +const projectId = '5bb0fe33763b3bea40b8d69e4269b4ae'; + +export const wagmiConfig = createConfig({ + chains: [near], + transports: { [near.id]: http() }, + connectors: [ + walletConnect({ projectId, showQrModal: false }), + injected({ shimDisconnect: true }), + ], +}); + +// Preserve login state on page reload +reconnect(wagmiConfig); + +// Modal for login +export const web3Modal = createWeb3Modal({ wagmiConfig, projectId }); \ No newline at end of file diff --git a/templates/frontend/next-page/package.json b/templates/frontend/next-page/package.json index 9d81fdc12..217f604f4 100644 --- a/templates/frontend/next-page/package.json +++ b/templates/frontend/next-page/package.json @@ -12,26 +12,34 @@ "lint": "next lint" }, "dependencies": { - "@near-wallet-selector/core": "^8.9.12", - "@near-wallet-selector/here-wallet": "^8.9.12", - "@near-wallet-selector/ledger": "^8.9.12", - "@near-wallet-selector/meteor-wallet": "^8.9.12", - "@near-wallet-selector/modal-ui": "^8.9.12", - "@near-wallet-selector/my-near-wallet": "^8.9.12", - "@near-wallet-selector/bitte-wallet": "^8.9.12", - "@near-wallet-selector/sender": "^8.9.12", + "@near-js/providers": "^1.0.0", + "@near-wallet-selector/bitte-wallet": "^8.9.13", + "@near-wallet-selector/core": "^8.9.13", + "@near-wallet-selector/ethereum-wallets": "^8.9.13", + "@near-wallet-selector/here-wallet": "^8.9.13", + "@near-wallet-selector/ledger": "^8.9.13", + "@near-wallet-selector/meteor-wallet": "^8.9.13", + "@near-wallet-selector/modal-ui": "^8.9.13", + "@near-wallet-selector/my-near-wallet": "^8.9.13", + "@near-wallet-selector/sender": "^8.9.13", + "@web3modal/wagmi": "^5.1.10", "bootstrap": "^5", "bootstrap-icons": "^1.11.3", "near-api-js": "^4.0.3", - "next": "14.2.3", + "next": "14.2.13", "react": "^18", - "react-dom": "^18" + "react-dom": "^18", + "wagmi": "^2.12.16" }, - "resolutions": { - "near-api-js": "4.0.4" + "overrides": { + "@near-wallet-selector/ethereum-wallets": { + "near-api-js": "4.0.3" + } }, "devDependencies": { + "encoding": "^0.1.13", "eslint": "^8", - "eslint-config-next": "14.2.3" + "eslint-config-next": "14.2.13", + "pino-pretty": "^11.2.2" } } diff --git a/templates/frontend/next-page/src/components/navigation.js b/templates/frontend/next-page/src/components/navigation.js index 6849b8b66..5ac4c8be1 100644 --- a/templates/frontend/next-page/src/components/navigation.js +++ b/templates/frontend/next-page/src/components/navigation.js @@ -2,7 +2,7 @@ import Image from 'next/image'; import Link from 'next/link'; import { useEffect, useState, useContext } from 'react'; -import { NearContext } from '@/context'; +import { NearContext } from '@/wallets/near'; import NearLogo from '/public/near-logo.svg'; export const Navigation = () => { diff --git a/templates/frontend/next-page/src/config.js b/templates/frontend/next-page/src/config.js index c97f8cb0e..eb0ffd942 100644 --- a/templates/frontend/next-page/src/config.js +++ b/templates/frontend/next-page/src/config.js @@ -3,5 +3,22 @@ const contractPerNetwork = { testnet: 'hello.near-examples.testnet', }; +// Chains for EVM Wallets +const evmWalletChains = { + mainnet: { + chainId: 397, + name: "Near Mainnet", + explorer: "https://eth-explorer.near.org", + rpc: "https://eth-rpc.mainnet.near.org", + }, + testnet: { + chainId: 398, + name: "Near Testnet", + explorer: "https://eth-explorer-testnet.near.org", + rpc: "https://eth-rpc.testnet.near.org", + }, +} + export const NetworkId = 'testnet'; -export const HelloNearContract = contractPerNetwork[NetworkId]; \ No newline at end of file +export const HelloNearContract = contractPerNetwork[NetworkId]; +export const EVMWalletChain = evmWalletChains[NetworkId]; \ No newline at end of file diff --git a/templates/frontend/next-page/src/context.js b/templates/frontend/next-page/src/context.js deleted file mode 100644 index 74223096a..000000000 --- a/templates/frontend/next-page/src/context.js +++ /dev/null @@ -1,13 +0,0 @@ -import { createContext } from 'react'; - -/** - * @typedef NearContext - * @property {import('./wallets/near').Wallet} wallet Current wallet - * @property {string} signedAccountId The AccountId of the signed user - */ - -/** @type {import ('react').Context} */ -export const NearContext = createContext({ - wallet: undefined, - signedAccountId: '' -}); \ No newline at end of file diff --git a/templates/frontend/next-page/src/pages/_app.js b/templates/frontend/next-page/src/pages/_app.js index 62942588b..1cfa25a70 100644 --- a/templates/frontend/next-page/src/pages/_app.js +++ b/templates/frontend/next-page/src/pages/_app.js @@ -1,10 +1,9 @@ import { useEffect, useState } from 'react'; import '@/styles/globals.css'; -import { NearContext } from '@/context'; import { Navigation } from '@/components/navigation'; -import { Wallet } from '@/wallets/near'; +import { Wallet, NearContext } from '@/wallets/near'; import { NetworkId } from '@/config'; const wallet = new Wallet({ networkId: NetworkId }); diff --git a/templates/frontend/next-page/src/pages/hello-near/index.js b/templates/frontend/next-page/src/pages/hello-near/index.js index 03bf9dbbd..6f7e5b6c7 100644 --- a/templates/frontend/next-page/src/pages/hello-near/index.js +++ b/templates/frontend/next-page/src/pages/hello-near/index.js @@ -1,6 +1,6 @@ import { useState, useEffect, useContext } from 'react'; -import { NearContext } from '@/context'; +import { NearContext } from '@/wallets/near'; import styles from '@/styles/app.module.css'; import { HelloNearContract } from '../../config'; import { Cards } from '@/components/cards'; diff --git a/templates/frontend/next-page/src/wallets/near.js b/templates/frontend/next-page/src/wallets/near.js index 61616ab79..0ec844a18 100644 --- a/templates/frontend/next-page/src/wallets/near.js +++ b/templates/frontend/next-page/src/wallets/near.js @@ -1,8 +1,7 @@ import { createContext } from 'react'; -import { distinctUntilChanged, map } from 'rxjs'; // near api js -import { providers } from 'near-api-js'; +import { providers, utils } from 'near-api-js'; // wallet selector import '@near-wallet-selector/modal-ui/styles.css'; @@ -15,6 +14,10 @@ import { setupMeteorWallet } from '@near-wallet-selector/meteor-wallet'; import { setupSender } from '@near-wallet-selector/sender'; import { setupBitteWallet } from '@near-wallet-selector/bitte-wallet'; +// ethereum wallets +import { wagmiConfig, web3Modal } from '@/wallets/web3modal'; +import { setupEthereumWallets } from "@near-wallet-selector/ethereum-wallets"; + const THIRTY_TGAS = '30000000000000'; const NO_DEPOSIT = '0'; @@ -48,6 +51,7 @@ export class Wallet { setupMeteorWallet(), setupSender(), setupBitteWallet(), + setupEthereumWallets({ wagmiConfig, web3Modal, alwaysOnboardDuringSignIn: true }), ], }); @@ -55,15 +59,10 @@ export class Wallet { const isSignedIn = walletSelector.isSignedIn(); const accountId = isSignedIn ? walletSelector.store.getState().accounts[0].accountId : ''; - walletSelector.store.observable - .pipe( - map(state => state.accounts), - distinctUntilChanged() - ) - .subscribe(accounts => { - const signedAccount = accounts.find((account) => account.active)?.accountId; - accountChangeHook(signedAccount); - }); + walletSelector.store.observable.subscribe(async (state) => { + const signedAccount = state?.accounts.find(account => account.active)?.accountId; + accountChangeHook(signedAccount || ''); + }); return accountId; }; @@ -152,6 +151,12 @@ export class Wallet { return providers.getTransactionLastResult(transaction); }; + /** + * Gets the balance of an account + * @param {string} accountId - the account id to get the balance of + * @returns {Promise} - the balance of the account + * + */ getBalance = async (accountId) => { const walletSelector = await this.selector; const { network } = walletSelector.options; @@ -167,12 +172,44 @@ export class Wallet { return account.amount ? Number(utils.format.formatNearAmount(account.amount)) : 0; }; + /** + * Signs and sends transactions + * @param {Object[]} transactions - the transactions to sign and send + * @returns {Promise} - the resulting transactions + * + */ signAndSendTransactions = async ({ transactions }) => { const selectedWallet = await (await this.selector).wallet(); return selectedWallet.signAndSendTransactions({ transactions }); }; + + /** + * + * @param {string} accountId + * @returns {Promise} - the access keys for the + */ + getAccessKeys = async (accountId) => { + const walletSelector = await this.selector; + const { network } = walletSelector.options; + const provider = new providers.JsonRpcProvider({ url: network.nodeUrl }); + + // Retrieve account state from the network + const keys = await provider.query({ + request_type: 'view_access_key_list', + account_id: accountId, + finality: 'final', + }); + return keys.keys; + }; } +/** + * @typedef NearContext + * @property {import('./wallets/near').Wallet} wallet Current wallet + * @property {string} signedAccountId The AccountId of the signed user + */ + +/** @type {import ('react').Context} */ export const NearContext = createContext({ wallet: undefined, signedAccountId: '', diff --git a/templates/frontend/next-page/src/wallets/web3modal.js b/templates/frontend/next-page/src/wallets/web3modal.js new file mode 100644 index 000000000..2ea9d91d0 --- /dev/null +++ b/templates/frontend/next-page/src/wallets/web3modal.js @@ -0,0 +1,44 @@ +import { NetworkId, EVMWalletChain } from '@/config'; +import { reconnect, http, createConfig } from "@wagmi/core"; +import { walletConnect, injected } from "@wagmi/connectors"; +import { createWeb3Modal } from "@web3modal/wagmi"; + +// Config +const near = { + id: EVMWalletChain.chainId, + name: EVMWalletChain.name, + nativeCurrency: { + decimals: 18, + name: "NEAR", + symbol: "NEAR", + }, + rpcUrls: { + default: { http: [EVMWalletChain.rpc] }, + public: { http: [EVMWalletChain.rpc] }, + }, + blockExplorers: { + default: { + name: "NEAR Explorer", + url: EVMWalletChain.explorer, + }, + }, + testnet: NetworkId === "testnet", +}; + +// Get your projectId at https://cloud.reown.com +const projectId = '5bb0fe33763b3bea40b8d69e4269b4ae'; + +export const wagmiConfig = createConfig({ + chains: [near], + transports: { [near.id]: http() }, + connectors: [ + walletConnect({ projectId, showQrModal: false }), + injected({ shimDisconnect: true }), + ], +}); + +// Preserve login state on page reload +reconnect(wagmiConfig); + +// Modal for login +export const web3Modal = createWeb3Modal({ wagmiConfig, projectId }); \ No newline at end of file