Merge pull request #5 from status-im/deploy-example-to-gh

This commit is contained in:
F 2021-12-23 11:13:22 +11:00 committed by GitHub
commit 8f9322593c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 378 additions and 4 deletions

View File

@ -0,0 +1,5 @@
{
"extends": [
"../../.eslintrc.json"
]
}

View File

@ -0,0 +1,8 @@
{
"spec": "test/**/*.test.{ts,tsx}",
"require": "ts-node/register",
"watchExtensions": "ts",
"extension": "ts",
"timeout": 3000,
"file": "./test/setup.ts"
}

View File

@ -0,0 +1 @@
# Mainnet DappConnect Poll SDK Example

View File

@ -0,0 +1,47 @@
{
"name": "@dappconnect/mainnet-poll-sdk-example",
"version": "0.1.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"clean:all": "yarn clean && rimraf node_modules/",
"clean": "rimraf dist/",
"build": "rm -rf dist && webpack --mode=production --env ENV=production",
"start": "webpack serve --mode=development --env ENV=development --https --port 8181",
"test": "mocha -r jsdom-global/register",
"lint": "yarn lint:prettier --check && yarn lint:eslint",
"lint:fix": "yarn lint:prettier --write && yarn lint:eslint --fix",
"lint:eslint": "eslint './{src,test}/**/*.{ts,tsx}'",
"lint:prettier": "yarn prettier './{src,test}/**/*.{ts,tsx}'"
},
"dependencies": {
"@dappconnect/vote-poll-sdk-core": "^0.1.0",
"@dappconnect/poll-sdk-react-components": "^0.1.0",
"@dappconnect/poll-sdk-react-hooks": "^0.1.0",
"@dappconnect/vote-poll-sdk-react-components": "^0.1.0",
"@usedapp/core": "^0.4.7",
"ethers": "^5.4.4",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
"styled-components": "^5.3.0"
},
"devDependencies": {
"@types/chai": "^4.2.21",
"@types/mocha": "^9.0.0",
"@types/react": "^17.0.16",
"@types/styled-components": "^5.1.12",
"@typescript-eslint/eslint-plugin": "^4.29.0",
"@typescript-eslint/parser": "^4.29.0",
"chai": "^4.3.4",
"copyfiles": "^2.4.1",
"eslint": "^7.32.0",
"jsdom": "^16.7.0",
"jsdom-global": "^3.0.2",
"mocha": "^9.0.3",
"npm-watch": "^0.11.0",
"rimraf": "^3.0.2",
"ts-node": "^10.1.0",
"typescript": "^4.3.5"
}
}

View File

@ -0,0 +1 @@
module.exports = require('../../.prettierrc.json')

View File

@ -0,0 +1 @@
/* /index.html 200

View File

@ -0,0 +1,14 @@
declare module '*.svg' {
const url: string
export default url
}
declare module '*.jpg' {
const url: string
export default url
}
declare module '*.png' {
const url: string
export default url
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,74 @@
import React, { useState, useEffect } from 'react'
import { useConfig, useEthers } from '@usedapp/core'
import styled from 'styled-components'
import { PollList, PollCreation } from '@dappconnect/poll-sdk-react-components'
import { JsonRpcSigner } from '@ethersproject/providers'
import { useWakuPolling } from '@dappconnect/poll-sdk-react-hooks'
import { Modal, Networks, CreateButton } from '@dappconnect/vote-poll-sdk-react-components'
import { Theme } from '@dappconnect/vote-poll-sdk-react-components/dist/esm/src/style/themes'
type WakuPollingProps = {
appName: string
signer: JsonRpcSigner | undefined
theme: Theme
tokenAddress: string
}
export function WakuPolling({ appName, signer, theme, tokenAddress }: WakuPollingProps) {
const { activateBrowserWallet, account, library, chainId } = useEthers()
const config = useConfig()
const [showPollCreation, setShowPollCreation] = useState(false)
const [selectConnect, setSelectConnect] = useState(false)
const wakuPolling = useWakuPolling(appName, tokenAddress, library, config?.multicallAddresses?.[chainId ?? 1337])
return (
<Wrapper>
{showPollCreation && signer && (
<PollCreation wakuPolling={wakuPolling} setShowPollCreation={setShowPollCreation} theme={theme} />
)}
{account ? (
<CreateButton theme={theme} disabled={!signer} onClick={() => setShowPollCreation(true)}>
Create a poll
</CreateButton>
) : (
<CreateButton
theme={theme}
onClick={() => {
if ((window as any)?.ethereum) {
activateBrowserWallet()
} else setSelectConnect(true)
}}
>
Connect to vote
</CreateButton>
)}
{selectConnect && (
<Modal heading="Connect" theme={theme} setShowModal={setSelectConnect}>
<Networks />
</Modal>
)}
<PollList wakuPolling={wakuPolling} account={account} theme={theme} />
</Wrapper>
)
}
const Wrapper = styled.div`
display: flex;
flex-direction: column;
align-items: center;
max-width: 1146px;
position: relative;
margin: 0 auto;
padding: 150px 32px 50px;
width: 100%;
@media (max-width: 1146px) {
max-width: 780px;
}
@media (max-width: 600px) {
padding: 132px 16px 32px;
}
@media (max-width: 425px) {
padding: 96px 16px 84px;
}
`

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="icon" href="/favicon.ico" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1" />
<link rel="icon" type="image/svg+xml" sizes="any" href="../src/assets/images/pollingIcon.svg" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<title>Polling Dapp</title>
</head>
<body>
<div id="root"></div>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script type="module" src="/index.js"></script>
</body>
</html>

View File

@ -0,0 +1,91 @@
import React, { useEffect, useState } from 'react'
import styled from 'styled-components'
import { DAppProvider, ChainId, useEthers } from '@usedapp/core'
import { DEFAULT_CONFIG } from '@usedapp/core/dist/cjs/src/model/config/default'
import { WakuPolling } from './components/WakuPolling'
import { TopBar, GlobalStyle } from '@dappconnect/vote-poll-sdk-react-components'
import pollingIcon from './assets/images/pollingIcon.png'
import { JsonRpcSigner } from '@ethersproject/providers'
import { orangeTheme } from '@dappconnect/vote-poll-sdk-react-components/dist/esm/src/style/themes'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom'
import { Route, Switch } from 'react-router'
import { useLocation } from 'react-router-dom'
const sntTokenAddress = '0x744d70FDBE2Ba4CF95131626614a1763DF805B9E'
const config = {
readOnlyChainId: ChainId.Mainnet,
readOnlyUrls: {
[ChainId.Mainnet]: 'https://mainnet.infura.io/v3/b4451d780cc64a078ccf2181e872cfcf',
},
multicallAddresses: {
1: '0xeefba1e63905ef1d7acba5a8513c70307c1ce441',
3: '0x53c43764255c17bd724f74c4ef150724ac50a3ed',
1337: process.env.GANACHE_MULTICALL_CONTRACT ?? '0x0000000000000000000000000000000000000000',
},
supportedChains: [...DEFAULT_CONFIG.supportedChains, 1337],
notifications: {
checkInterval: 500,
expirationPeriod: 50000,
},
}
export function Polling({ tokenAddress }: { tokenAddress: string }) {
const { account, library, activateBrowserWallet, deactivate } = useEthers()
const [signer, setSigner] = useState<undefined | JsonRpcSigner>(undefined)
useEffect(() => {
setSigner(library?.getSigner())
}, [account])
return (
<Wrapper>
<TopBar
logo={pollingIcon}
logoWidth={84}
title={'WakuConnect Poll Demo'}
theme={orangeTheme}
activate={activateBrowserWallet}
account={account}
deactivate={deactivate}
/>
<WakuPolling theme={orangeTheme} appName={'testApp_'} signer={signer} tokenAddress={tokenAddress} />
</Wrapper>
)
}
export function PollingPage() {
const location = useLocation()
const tokenAddress = new URLSearchParams(location.search).get('token')
return (
<Page>
<GlobalStyle />
<DAppProvider config={config}>
<Polling tokenAddress={tokenAddress ?? sntTokenAddress} />
</DAppProvider>
</Page>
)
}
const Page = styled.div`
height: 100%;
width: 100%;
`
const Wrapper = styled.div`
height: 100%;
width: 100%;
`
ReactDOM.render(
<div style={{ height: '100%' }}>
<BrowserRouter>
<Switch>
<Route exact path="/" component={PollingPage} />
</Switch>
</BrowserRouter>
</div>,
document.getElementById('root')
)

View File

@ -0,0 +1,7 @@
import { expect } from 'chai'
describe('test react-components', () => {
it('foo', async () => {
expect('Hello world').to.eq('Hello world')
})
})

View File

@ -0,0 +1,25 @@
{
"compilerOptions": {
"outDir": "dist",
"jsx":"react",
"esModuleInterop": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"skipLibCheck": true,
"downlevelIteration": true,
"strict": true,
"composite": true,
"declaration": true,
"sourceMap": true,
"declarationMap": true,
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"target": "es6",
"typeRoots": [ "./types", "./node_modules/@types", "../../node_modules/@types"]
},
"include": [
"src",
"src/**/*.json",
"test"
]
}

View File

@ -0,0 +1,82 @@
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
const webpack = require('webpack')
const { ESBuildMinifyPlugin } = require('esbuild-loader')
module.exports = (env) => {
let environment = 'development'
if (env.ENV) {
environment = env.ENV
}
return {
entry: './src/index.tsx',
output: {
filename: 'index.[fullhash].js',
path: path.join(__dirname, 'dist'),
publicPath: "/",
},
devtool: 'source-map',
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json'],
fallback: {
"buffer": require.resolve("buffer/"),
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"assert": require.resolve("assert")
}
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'esbuild-loader',
exclude: /node_modules/,
options: {
loader: 'tsx',
target: 'es2018',
},
},
{
enforce: 'pre',
test: /\.js$/,
exclude: /node_modules/,
loader: 'source-map-loader'
},
{
test: /\.(png|svg|jpg|gif|woff|woff2|eot|ttf|otf|ico)$/,
use: ['file-loader'],
},
],
},
optimization: {
minimizer: [
new ESBuildMinifyPlugin({
target: 'es2018',
}),
],
},
plugins: [
new ForkTsCheckerWebpackPlugin(),
new HtmlWebpackPlugin({
template: 'src/index.html',
}),
new webpack.DefinePlugin({
'process.env.ENV': JSON.stringify(environment),
}),
new webpack.ProvidePlugin({
process: 'process/browser.js',
Buffer: ['buffer', 'Buffer'],
}),
],
devServer: {
historyApiFallback: true,
host: '0.0.0.0',
stats: 'errors-only',
overlay: true,
hot: true,
},
stats: 'minimal'
}
}

View File

@ -55,12 +55,12 @@ export function Poll({ poll, wakuPolling, theme, account }: PollProps) {
</PollAnswersWrapper>
{userInVoters < 0 && (
<SmallButton
disabled={!account}
disabled={!account || selectedAnswer === undefined}
onClick={async () => {
if (wakuPolling && account) {
if (wakuPolling && account && selectedAnswer !== undefined) {
const result = await wakuPolling.sendTimedPollVote(
poll.poll.id,
selectedAnswer ?? 0,
selectedAnswer,
poll.poll.pollType === PollType.WEIGHTED ? BigNumber.from(tokenAmount) : undefined
)
if (result === 1) {

View File

@ -5,6 +5,8 @@ import { WakuPolling } from '@dappconnect/vote-poll-sdk-core'
import { Input, addIcon, SmallButton, Modal, Theme } from '@dappconnect/vote-poll-sdk-react-components'
import { MESSAGE_SENDING_RESULT } from '@dappconnect/vote-poll-sdk-core/dist/esm/src/classes/WakuPolling'
const defaultPollDuration = 7 * 24 * 60 * 60 * 1000 // One week in ms.
function getLocaleIsoTime(dateTime: Date) {
const MS_PER_MINUTE = 60000
const milliseconds = dateTime.getTime() - dateTime.getTimezoneOffset() * MS_PER_MINUTE
@ -45,7 +47,7 @@ export function PollCreation({ wakuPolling, theme, setShowPollCreation }: PollCr
const [showCreateConfirmation, setShowCreateConfirmation] = useState(false)
const [showNotEnoughTokens, setShowNotEnoughTokens] = useState(false)
const [selectedType, setSelectedType] = useState(PollType.NON_WEIGHTED)
const [endTimePicker, setEndTimePicker] = useState(new Date(new Date().getTime() + 10000000))
const [endTimePicker, setEndTimePicker] = useState(new Date(new Date().getTime() + defaultPollDuration))
return (
<Modal heading="Create a poll" setShowModal={setShowPollCreation} theme={theme}>