@wavesenterprise/we-vote-api
v0.1.1
Published
Rest and Websocket integration API for https://we.vote public polls.
Downloads
4
Keywords
Readme
We Vote api
Rest and Websocket integration API for https://we.vote public polls.
Peer dependencies
axios, qs - for http requests
@wavesenterprise/api-token-refresher - auto token refresh on api request
@wavesenterprise/voting-blockchain-tools - to create and sign transaction
@wavesenterprise/voting-contract-api - vote transaction wrapper
@wavesenterprise/voting-crypto - to encrypt bulletin
socket.io-client - for websocket api
Initialization
import { WeVoteApi } from '@wavesenterprise/we-vote-api'
import { WebsocketWeVoteApi } from '@wavesenterprise/we-vote-api/websocketApi'
// default config
const config = {
backendAddress: 'https://client.we.vote/backendAddress',
nodeAddress: 'https://client.we.vote/nodeAddress',
authServiceAddress: 'https://client.we.vote/votingAuthService',
keysServiceAddress: 'https://client.we.vote/keysAddress',
transactionFeeAssetId: '5EQ4iE4j4gRT4RvTBEHpkPoDfaeDq277aatEe4LS1Hnv',
}
const weVoteApi = new WeVoteApi(config)
const websocketApi = new WebsocketWeVoteApi(config)
Api
Get poll info
const pollData = await weVoteApi.polls.find(pollId)
// {
// "result": {
// "id": 163,
// "title": "Публичное 1",
// "dateFrom": "2022-10-20T09:48:58.177Z",
// "dateTo": "2022-11-19T09:47:23.123Z",
// "status": "active",
// "type": "dynamicParticipants",
// "contractId": "63iKW75Wf5AkpQ1poLr8MuaUy65VGBWXbiFUj4QoU2w1",
// "mainKey": "033b4bb3e36ac6fce756edbf2ba73d7a002acbcb88b78d1258b7a3bc37bc8f25c8",
// "isOpenVote": false,
// "createdAt": "2022-10-20T09:46:55.175Z",
// "updatedAt": "2022-10-20T09:49:01.114Z",
// "publishDate": "2022-10-20T09:47:23.123Z",
// "votersCount": 1,
// "votedCount": 1,
// "questions": [
// {
// "title": "Новый вопрос",
// "options": [
// {
// "title": "За",
// "result": 0,
// },
// {
// "title": "Против",
// "result": 0,
// },
// {
// "title": "Воздержаться",
// "result": 0,
// },
// ],
// },
// ],
// "votingEnabled": true,
// "votes": [],
// "isParticipant": false,
// "votesLeft": 3,
// "voted": false,
// "hasMinedVotes": false,
// "hasPendingVotes": false
// },
// }
Listen poll updates through websocket
// be sure to connect to websocket during the page load
websocketWeVoteApi.connect()
// in component
useEffect(() => {
const handler = (data: PollDTO) => {
if (data.id === pollId) {
setPollData(data)
}
}
websocketWeVoteApi.subscribeOnPollUpdate(pollId, handler)
return () => websocketWeVoteApi.unsubscribeFromPollUpdate(pollId, handler)
}, [pollId])
Telegram login
// telegramData - response from success telegram login e.g
// {
// id: number,
// hash: string,
// auth_date: number,
// first_name: string,
// last_name: string,
// photo_url?: string,
// username: string,
// }
const response = await weVoteApi.auth.loginTelegram(telegramData, 'ru')
// {
// "result": {
// "accessToken": "jwt str",
// "refreshToken": "jwt str"
// }
// }
// to make authorized requests and receive personal updates
weVoteApi.authorize(response)
websocketWeVoteApi.connect(response)
// it's better to call weVoteApi.polls.find(pollId) again to get personalized data.
Vote sending
// ensure that poll status is "active"
const bulletin = [
[ // first qustion
1, // vote for the first option in the first question
0,
0,
],
[
0,
1, // vote for the second option in the second question
]
]
const nodeConfig = await weVoteApi.node.getNodeConfig()
await weVoteApi.polls.vote({
pollData,
nodeConfig,
bulletin,
hasRemoteSeed: true,
})
// void. Vote info can be received through weVoteApi.polls.find(pollId). Also you will get poll websocket update.
Integration example
import React, { useEffect, useState } from 'react'
import ReactDOM from 'react-dom'
import TelegramLoginButton from 'react-telegram-login'
import type { PollDTO, TelegramLoginRO } from '@wavesenterprise/we-vote-api/types/api'
import { WeVoteApi } from '@wavesenterprise/we-vote-api'
import { WebsocketWeVoteApi } from '@wavesenterprise/we-vote-api/websocketApi'
const pollId = 163
const telegramBotName = 'we_vote_dev_bot'
type AppContainerProps = {
weVoteApi: WeVoteApi,
websocketWeVoteApi: WebsocketWeVoteApi,
}
const AppContainer: React.FC<AppContainerProps> = ({ weVoteApi, websocketWeVoteApi }) => {
const [pollData, setPollData] = useState<PollDTO | null>(null)
useEffect(() => {
weVoteApi.polls.find(pollId)
.then((setPollData))
const handler = (data: PollDTO) => {
if (data.id === pollId) {
setPollData(data)
}
}
websocketWeVoteApi.subscribeOnPollUpdate(pollId, handler)
return () => websocketWeVoteApi.unsubscribeFromPollUpdate(pollId, handler)
},[pollId, weVoteApi.polls.find])
if (!pollData) {
return (<div>Poll {pollId} loading</div>)
}
return (
<div>
<div>Poll id: {pollData.id}</div>
<div>Poll title: {pollData.title}</div>
<div>Poll status: {pollData.status}</div>
{pollData.questions.map((q,i) => {
return (
<div key={i}>
<div>Question {i + 1}: {q.title}</div>
{q.options.map((o, j) => {
return (
<div key={j}>
<div>{o.title}: {o.result ?? 0} </div>
</div>
)
})}
</div>
)
})}
<div>Voted: {pollData.voted ? 'true' : 'false'}</div>
<div>Votes: {JSON.stringify(pollData.votes, null, 2)}</div>
<VoteButton
pollData={pollData}
telegramBotName={telegramBotName}
weVoteApi={weVoteApi}
websocketWeVoteApi={websocketWeVoteApi}
setPollData={setPollData}
/>
</div>
)
}
type VoteButtonProps = {
weVoteApi: WeVoteApi,
websocketWeVoteApi: WebsocketWeVoteApi,
pollData: PollDTO,
telegramBotName: string,
setPollData: (PollDTO) => void,
}
const VoteButton: React.FC<VoteButtonProps> = ({
pollData,
weVoteApi,
websocketWeVoteApi,
telegramBotName,
setPollData,
}) => {
const [isAuthorized, setAuthorized] = useState(false)
const [isVoteSent, setVoteSent] = useState(false)
const onAuth = async (user: TelegramLoginRO) => {
const response = await weVoteApi.auth.loginTelegram(user, 'ru')
weVoteApi.authorize(response)
websocketWeVoteApi.connect(response)
setAuthorized(true)
weVoteApi.polls.find(pollId)
.then((setPollData))
}
const onVote = async () => {
const nodeConfig = await weVoteApi.node.getNodeConfig()
await weVoteApi.polls.vote({
pollData,
nodeConfig,
bulletin: [[1,0,0]],
hasRemoteSeed: true,
})
setVoteSent(true)
}
if (!isAuthorized) {
return (
<TelegramLoginButton
botName={telegramBotName}
buttonSize={'large'}
cornerRadius={0}
lang={'ru'}
usePic={false}
dataOnauth={onAuth}
/>
)
}
return (
<div>
<button onClick={onVote}>
Vote For first option
</button>
{isVoteSent && (
<div>Vote sent </div>
)}
</div>
)
How to create public poll
- Go to
https://client.we.vote/
website and create an account. - Contact us to grant your account access to public polls. You can write to
[email protected]
. - When access granted create public poll on the website interface.
- Be sure to set option
Open vote
totrue
if you want to check results during voting stage. Otherwise, all votes will be encrypted and results will be published only after poll finish. - Get poll id from the url of the poll page. E.g
https://client.we.vote/main/polls/1000
. Here poll id is1000
. - Be also sure to start poll from the website interface before sending votes.
How to setup environment
- Pick a library to complete telegram oauth. For example
react-telegram-login
. - Configure your dev webpack configuration according telegram demands. You should setup local domain and certs for https. Local certs can be made via
mkcert
util. We have telegram bot configured for dev purposes. You should specify your local domain ashttps://voting.local.com/
and telegram bot namewe_vote_dev_bot
. - When you are ready to deploy your production vote form, contract us to setup special telegram bot for your website domain.