npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@wavesenterprise/we-vote-api

v0.1.1

Published

Rest and Websocket integration API for https://we.vote public polls.

Downloads

4

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

  1. Go to https://client.we.vote/ website and create an account.
  2. Contact us to grant your account access to public polls. You can write to [email protected].
  3. When access granted create public poll on the website interface.
  4. Be sure to set option Open vote to true if you want to check results during voting stage. Otherwise, all votes will be encrypted and results will be published only after poll finish.
  5. Get poll id from the url of the poll page. E.g https://client.we.vote/main/polls/1000. Here poll id is 1000.
  6. Be also sure to start poll from the website interface before sending votes.

How to setup environment

  1. Pick a library to complete telegram oauth. For example react-telegram-login.
  2. 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 as https://voting.local.com/ and telegram bot name we_vote_dev_bot.
  3. When you are ready to deploy your production vote form, contract us to setup special telegram bot for your website domain.