Skip to content

Commit

Permalink
Basic PWA set up (#1)
Browse files Browse the repository at this point in the history
Co-authored-by: tokodev <pablo@asdloop.com>
Co-authored-by: Carlos Sánchez <oceanrdn@gmail.com>
  • Loading branch information
3 people authored Oct 4, 2023
1 parent b33b38c commit b17797c
Show file tree
Hide file tree
Showing 63 changed files with 4,847 additions and 578 deletions.
162 changes: 126 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,163 @@
# 🔥 Burner Wallet PWA 📱
⚠️ This is a work in progress.

🧪 An open-source, up-to-date toolkit for building decentralized applications (dapps) on the Ethereum blockchain. It's designed to make it easier for developers to create and deploy smart contracts and build user interfaces that interact with those contracts.
# 🏗 Scaffold-ETH 2 PWA 📱

⚙️ Built using NextJS, RainbowKit, Hardhat, Wagmi, and Typescript.
This **forkable** project provides the infraestructure to build a Progressive Web App (PWA) using Scaffold-ETH 2 base features, plus PWA oriented extra features, like Push Notifications and the capability to Install the PWA on your device.

-**Contract Hot Reload**: Your frontend auto-adapts to your smart contract as you edit it.
- 🔥 **Burner Wallet & Local Faucet**: Quickly test your application with a burner wallet and local faucet.
- 🔐 **Integration with Wallet Providers**: Connect to different wallet providers and interact with the Ethereum network.
To learn more about base Scaffold-ETH 2 features and development guide, check our [Docs](https://docs.scaffoldeth.io/) and [Website](https://scaffoldeth.io/).

![Debug Contracts tab](https://github.com/scaffold-eth/scaffold-eth-2/assets/55535804/1171422a-0ce4-4203-bcd4-d2d1941d198b)
## 🏃 Quick Start

## Requirements
To get started with Scaffold-ETH 2 PWA, follow the steps below:

Before you begin, you need to install the following tools:
### 1. Clone this repo & install dependencies

- [Node (v18 LTS)](https://nodejs.org/en/download/)
- Yarn ([v1](https://classic.yarnpkg.com/en/docs/install/) or [v2+](https://yarnpkg.com/getting-started/install))
- [Git](https://git-scm.com/downloads)
```bash
gh repo clone BuidlGuidl/PWA-burner-wallet
cd PWA-burner-wallet
yarn install
```

## Quickstart
### 2. Setting up Firebase

To get started with Scaffold-ETH 2, follow the steps below:
> Note : You can also use other database as well, we are using Firebase for this example checkout `packages/nextjs/database/firebase`.
1. Clone this repo & install dependencies
Create your [Firebase project](https://console.firebase.google.com/) and register a web app. It'll give you a config object that looks like this:

```js
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
};
```
git clone https://github.com/scaffold-eth/scaffold-eth-2.git
cd scaffold-eth-2
yarn install

Copy `packages/nextjs/.env.example` into `packages/nextjs/.env` file and fill in your Firebase credentials which starts with `FIREBASE_`.

The next step is to create your Firestore database from your [Firebase console](https://console.firebase.google.com/) (_sidebar menu > Build > Firestore Database_). You can start your database in **test mode**, and then change the [rules](https://console.firebase.google.com/project/_/firestore/rules?_gl=1*aqmcm*_ga*MTQxNzU0MTYyMi4xNjk0MTY1NjY2*_ga_CW55HF8NVT*MTY5NTc2ODQwNS4xNC4xLjE2OTU3NzE0MDAuMC4wLjA.) to the following:

```
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// This rule allows anyone with your Firestore database reference to view, edit,
// and delete all data in your Firestore subscriptions collection
match /subscriptions/{subscription} {
allow read, write: if true;
}
}
}
```

### 3. Setting VAPID Keys

VAPID keys are a public-private key pair used to securely identify the server sending web push notifications.

2. Run a local network in the first terminal:
Run the following command to generate Public and Private VAPID :

```bash
yarn web-push-generate
```

Set `NEXT_PUBLIC_PUBLIC_KEY_VAPID` and `PRIVATE_KEY_VAPID` variables in `packages/nextjs/.env.local` file.

### 4. Starting the PWA

To set up your local environment and start the PWA, run the following commands in different terminal windows:

1. In the first terminal, start your local network (a blockchain emulator in your computer):

```bash
yarn chain
```

This command starts a local Ethereum network using Hardhat. The network runs on your local machine and can be used for testing and development. You can customize the network configuration in `hardhat.config.ts`.
2. In a second terminal window, deploy your contract (locally):

```bash
yarn deploy
```

3. On a second terminal, deploy the test contract:
3. In a third terminal window, start your PWA:

```bash
yarn start
```
yarn deploy

Visit your web app on: `http://localhost:3000`.

> Note: You can disable dev server logs by uncommenting line `disable: process.env.NODE_ENV=== "development"` in `packages/nextjs/next.config.mjs` file.
### 5. Testing notification on local

1. Install the PWA from Chrome web browser.

2. Open the PWA, click _"Allow Notification"_ button => This will ask for permission & register the subscription in DB.

3. Once its successful you will see _"Notify All"_ button => This button makes "POST" request to `packages/nextjs/pages/api/push/notify-all.ts` which will send notification to all the subscribers

### 6. Deploying your contracts on a public network

1. Edit the `defaultNetwork` in `packages/hardhat/hardhat.config.ts` to [your choice of public EVM networks](https://ethereum.org/en/developers/docs/networks/)

2. You will need to generate a **deployer address** using `yarn generate`. This creates a mnemonic and saves it locally.

3. Run `yarn deploy` to deploy your smart contract to the public network selected in `packages/hardhat/hardhat.config.ts`

4. Edit your frontend config in `packages/nextjs/scaffold.config.ts` to change the `targetNetwork`.

> Hint: You will need to send ETH to your deployer address to deploy your contracts.
> Use `yarn account` to view your deployer account balances.
### 7. Deploying your PWA to Vercel

> Hint: We recommend connecting your GitHub repo to Vercel (through the Vercel UI) so it gets automatically deployed when pushing to main.
To deploy directly from the CLI, run this and follow the steps to deploy to Vercel:

```
yarn vercel
```

This command deploys a test smart contract to the local network. The contract is located in `packages/hardhat/contracts` and can be modified to suit your needs. The `yarn deploy` command uses the deploy script located in `packages/hardhat/deploy` to deploy the contract to the network. You can also customize the deploy script.
Once you log in (email, github, etc), the default options should work. It'll give you a public URL.

4. On a third terminal, start your NextJS app:
If you want to redeploy to the same production URL you can run:

```
yarn start
yarn vercel --prod
```

Visit your app on: `http://localhost:3000`. You can interact with your smart contract using the contract component or the example ui in the frontend. You can tweak the app config in `packages/nextjs/scaffold.config.ts`.
#### 7.1 Setting Environment Variables

When you deploy to Vercel you have to set all the environment variables from your `packages/nextjs/.env.local` file into your Vercel Environment Variables section.

You can do this in the Vercel Project dashboard under _"Settings > Environment Variables"_.

> Hint: You can mass copy all the config variables from your `packages/nextjs/.env.local` config files and paste them into the Vercel form.
## Development and References

### Important Development files

1. We have extended [`next-pwa`](https://github.com/shadowwalker/next-pwa) default service-worker at `packages/worker/index.ts`

Run smart contract test with `yarn hardhat:test`
2. Logic for subscription for push notification is present in `packages/nextjs/utils/service-workers/index.ts`

- Edit your smart contract `YourContract.sol` in `packages/hardhat/contracts`
- Edit your frontend in `packages/nextjs/pages`
- Edit your deployment scripts in `packages/hardhat/deploy`
3. All the push backend routes are present in `packages/nextjs/pages/api/push`

## Documentation
### Scaffold ETH 2 Documentation

Visit our [docs](https://docs.scaffoldeth.io) to learn how to start building with Scaffold-ETH 2.
To learn more about Scaffold-ETH 2 features and development guide, you can check out the [Scaffold-ETH 2 Docs](https://docs.scaffoldeth.io/).

To know more about its features, check out our [website](https://scaffoldeth.io).
### Extra Resources

## Contributing to Scaffold-ETH 2
1. [The service worker lifecycle](https://web.dev/service-worker-lifecycle/)

We welcome contributions to Scaffold-ETH 2!
2. [next-pwa](https://github.com/shadowwalker/next-pwa)

Please see [CONTRIBUTING.MD](https://github.com/scaffold-eth/scaffold-eth-2/blob/main/CONTRIBUTING.md) for more information and guidelines for contributing to Scaffold-ETH 2.
3. [Google's Push Notification's series](https://web.dev/push-notifications-overview/)
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"next:check-types": "yarn workspace @se-2/nextjs check-types",
"postinstall": "husky install",
"precommit": "lint-staged",
"web-push-generate": "yarn workspace @se-2/nextjs web-push generate-vapid-keys",
"vercel": "yarn workspace @se-2/nextjs vercel",
"vercel:yolo": "yarn workspace @se-2/nextjs vercel:yolo"
},
Expand Down
1 change: 1 addition & 0 deletions packages/hardhat/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const config: HardhatUserConfig = {
},
},
defaultNetwork: "localhost",

namedAccounts: {
deployer: {
// By default, it will take the first Hardhat account as the deployer
Expand Down
19 changes: 14 additions & 5 deletions packages/nextjs/.env.example
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
# Template for NextJS environment variables.

# For local development, copy this file, rename it to .env.local, and fill in the values.
# When deploying live, you'll need to store the vars in Vercel/System config.

# PWA environment variables.
FIREBASE_API_KEY=
FIREBASE_AUTH_DOMAIN=
FIREBASE_PROJECT_ID=
FIREBASE_STRG_BUCKET=
FIREBASE_MESSAGING_SENDER_ID=
FIREBASE_APP_ID=
NEXT_PUBLIC_PUBLIC_KEY_VAPID=
PRIVATE_KEY_VAPID=

# scaffold config environment variables.
# If not set, we provide default values (check `scaffold.config.ts`) so developers can start prototyping out of the box,
# but we recommend getting your own API Keys for Production Apps.
NEXT_PUBLIC_ALCHEMY_API_KEY=
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=

# To access the values stored in this env file you can use: process.env.VARIABLENAME
# You'll need to prefix the variables names with NEXT_PUBLIC_ if you want to access them on the client side.
# More info: https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables
NEXT_PUBLIC_ALCHEMY_API_KEY=
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=
# More info: https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables
14 changes: 13 additions & 1 deletion packages/nextjs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,21 @@ yarn-error.log*
.env.development.local
.env.test.local
.env.production.local
.env

# vercel
.vercel

# typescript
*.tsbuildinfo
*.tsbuildinfo

# PWA files
**/public/sw.js
**/public/workbox-*.js
**/public/worker-*.js
**/public/sw.js.map
**/public/workbox-*.js.map
**/public/worker-*.js.map

# fake db json
db.json
14 changes: 1 addition & 13 deletions packages/nextjs/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useCallback, useRef, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { Bars3Icon, BugAntIcon, MagnifyingGlassIcon, SparklesIcon } from "@heroicons/react/24/outline";
import { Bars3Icon, BugAntIcon } from "@heroicons/react/24/outline";
import { FaucetButton, RainbowKitCustomConnectButton } from "~~/components/scaffold-eth";
import { useOutsideClick } from "~~/hooks/scaffold-eth";

Expand Down Expand Up @@ -45,18 +45,6 @@ export const Header = () => {
Debug Contracts
</NavLink>
</li>
<li>
<NavLink href="/example-ui">
<SparklesIcon className="h-4 w-4" />
Example UI
</NavLink>
</li>
<li>
<NavLink href="/blockexplorer">
<MagnifyingGlassIcon className="h-4 w-4" />
Block Explorer
</NavLink>
</li>
</>
);

Expand Down
40 changes: 40 additions & 0 deletions packages/nextjs/components/PWANotificationHinter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useState } from "react";
import { useIsClient } from "usehooks-ts";
import { useGlobalState } from "~~/services/store/store";
import { notification } from "~~/utils/scaffold-eth";
import { notificationsSupported, subscribe } from "~~/utils/service-workers";

export const PWANotificationHinter = () => {
const [isLoading, setIsLoading] = useState(false);
const { setPushNotificationSubscription } = useGlobalState(state => state);
const isClient = useIsClient();

return isClient ? (
<button
className="btn btn-primary"
disabled={!notificationsSupported()}
onClick={async () => {
try {
setIsLoading(true);
const subscription = await subscribe();
setPushNotificationSubscription(subscription);
} catch (e) {
if (e instanceof Error) {
notification.error(e.message);
}
setPushNotificationSubscription(null);
} finally {
setIsLoading(false);
}
}}
>
{isLoading ? (
<span className="loading loading-dots loading-xs"></span>
) : notificationsSupported() ? (
"Allow Notifications"
) : (
"Please install PWA first"
)}
</button>
) : null;
};
18 changes: 18 additions & 0 deletions packages/nextjs/database/firebase/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";

// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STRG_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.FIREBASE_APP_ID,
};

const app = initializeApp(firebaseConfig);

export const firebaseDB = getFirestore(app);

export const COLLECTION_NAME = "subscriptions";
1 change: 1 addition & 0 deletions packages/nextjs/database/firebase/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./config";
Loading

0 comments on commit b17797c

Please sign in to comment.