diff --git a/packages/mainnet-poll-example/.eslintrc.json b/packages/mainnet-poll-example/.eslintrc.json
new file mode 100644
index 0000000..128cd29
--- /dev/null
+++ b/packages/mainnet-poll-example/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+ "extends": [
+ "../../.eslintrc.json"
+ ]
+}
diff --git a/packages/mainnet-poll-example/.mocharc.json b/packages/mainnet-poll-example/.mocharc.json
new file mode 100644
index 0000000..59d511f
--- /dev/null
+++ b/packages/mainnet-poll-example/.mocharc.json
@@ -0,0 +1,8 @@
+{
+ "spec": "test/**/*.test.{ts,tsx}",
+ "require": "ts-node/register",
+ "watchExtensions": "ts",
+ "extension": "ts",
+ "timeout": 3000,
+ "file": "./test/setup.ts"
+}
diff --git a/packages/mainnet-poll-example/README.md b/packages/mainnet-poll-example/README.md
new file mode 100644
index 0000000..58e5604
--- /dev/null
+++ b/packages/mainnet-poll-example/README.md
@@ -0,0 +1 @@
+# Mainnet DappConnect Poll SDK Example
diff --git a/packages/mainnet-poll-example/package.json b/packages/mainnet-poll-example/package.json
new file mode 100644
index 0000000..080f09e
--- /dev/null
+++ b/packages/mainnet-poll-example/package.json
@@ -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"
+ }
+}
diff --git a/packages/mainnet-poll-example/prettier.config.js b/packages/mainnet-poll-example/prettier.config.js
new file mode 100644
index 0000000..3bcd29e
--- /dev/null
+++ b/packages/mainnet-poll-example/prettier.config.js
@@ -0,0 +1 @@
+module.exports = require('../../.prettierrc.json')
diff --git a/packages/mainnet-poll-example/src/_redirects b/packages/mainnet-poll-example/src/_redirects
new file mode 100644
index 0000000..ad37e2c
--- /dev/null
+++ b/packages/mainnet-poll-example/src/_redirects
@@ -0,0 +1 @@
+/* /index.html 200
diff --git a/packages/mainnet-poll-example/src/assets/assets.d.ts b/packages/mainnet-poll-example/src/assets/assets.d.ts
new file mode 100644
index 0000000..4ce4da1
--- /dev/null
+++ b/packages/mainnet-poll-example/src/assets/assets.d.ts
@@ -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
+}
diff --git a/packages/mainnet-poll-example/src/assets/images/pollingIcon.png b/packages/mainnet-poll-example/src/assets/images/pollingIcon.png
new file mode 100644
index 0000000..1534250
Binary files /dev/null and b/packages/mainnet-poll-example/src/assets/images/pollingIcon.png differ
diff --git a/packages/mainnet-poll-example/src/components/WakuPolling.tsx b/packages/mainnet-poll-example/src/components/WakuPolling.tsx
new file mode 100644
index 0000000..dcf8e8a
--- /dev/null
+++ b/packages/mainnet-poll-example/src/components/WakuPolling.tsx
@@ -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 (
+
+ {showPollCreation && signer && (
+
+ )}
+ {account ? (
+ setShowPollCreation(true)}>
+ Create a poll
+
+ ) : (
+ {
+ if ((window as any)?.ethereum) {
+ activateBrowserWallet()
+ } else setSelectConnect(true)
+ }}
+ >
+ Connect to vote
+
+ )}
+ {selectConnect && (
+
+
+
+ )}
+
+
+
+ )
+}
+
+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;
+ }
+`
diff --git a/packages/mainnet-poll-example/src/index.html b/packages/mainnet-poll-example/src/index.html
new file mode 100644
index 0000000..067de06
--- /dev/null
+++ b/packages/mainnet-poll-example/src/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+ Polling Dapp
+
+
+
+
+
+
+
diff --git a/packages/mainnet-poll-example/src/index.tsx b/packages/mainnet-poll-example/src/index.tsx
new file mode 100644
index 0000000..05a5004
--- /dev/null
+++ b/packages/mainnet-poll-example/src/index.tsx
@@ -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)
+
+ useEffect(() => {
+ setSigner(library?.getSigner())
+ }, [account])
+
+ return (
+
+
+
+
+ )
+}
+
+export function PollingPage() {
+ const location = useLocation()
+ const tokenAddress = new URLSearchParams(location.search).get('token')
+
+ return (
+
+
+
+
+
+
+ )
+}
+
+const Page = styled.div`
+ height: 100%;
+ width: 100%;
+`
+
+const Wrapper = styled.div`
+ height: 100%;
+ width: 100%;
+`
+
+ReactDOM.render(
+
+
+
+
+
+
+
,
+ document.getElementById('root')
+)
diff --git a/packages/mainnet-poll-example/test/index.test.ts b/packages/mainnet-poll-example/test/index.test.ts
new file mode 100644
index 0000000..1dba999
--- /dev/null
+++ b/packages/mainnet-poll-example/test/index.test.ts
@@ -0,0 +1,7 @@
+import { expect } from 'chai'
+
+describe('test react-components', () => {
+ it('foo', async () => {
+ expect('Hello world').to.eq('Hello world')
+ })
+})
diff --git a/packages/mainnet-poll-example/test/setup.ts b/packages/mainnet-poll-example/test/setup.ts
new file mode 100644
index 0000000..e69de29
diff --git a/packages/mainnet-poll-example/tsconfig.json b/packages/mainnet-poll-example/tsconfig.json
new file mode 100644
index 0000000..4bd6269
--- /dev/null
+++ b/packages/mainnet-poll-example/tsconfig.json
@@ -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"
+ ]
+}
diff --git a/packages/mainnet-poll-example/webpack.config.js b/packages/mainnet-poll-example/webpack.config.js
new file mode 100644
index 0000000..cc8a6a8
--- /dev/null
+++ b/packages/mainnet-poll-example/webpack.config.js
@@ -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'
+ }
+}
\ No newline at end of file
diff --git a/packages/poll-react-components/src/components/Poll.tsx b/packages/poll-react-components/src/components/Poll.tsx
index 3ad6c79..272c7d0 100644
--- a/packages/poll-react-components/src/components/Poll.tsx
+++ b/packages/poll-react-components/src/components/Poll.tsx
@@ -55,12 +55,12 @@ export function Poll({ poll, wakuPolling, theme, account }: PollProps) {
{userInVoters < 0 && (
{
- 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) {
diff --git a/packages/poll-react-components/src/components/PollCreation.tsx b/packages/poll-react-components/src/components/PollCreation.tsx
index b7bda20..35c7ce0 100644
--- a/packages/poll-react-components/src/components/PollCreation.tsx
+++ b/packages/poll-react-components/src/components/PollCreation.tsx
@@ -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 (