React SDK for embedding Polypuls3 polls in decentralized applications on Polygon.
- 🎨 Pre-built UI Components - Ready-to-use React components with customizable theming
- 🎣 Headless Hooks - Build custom UIs with powerful React hooks
- ⚡ Wagmi Integration - Built on wagmi v2 for seamless Web3 interactions
- 🔗 Subgraph Support - Efficient data fetching via The Graph
- 🎯 TypeScript First - Fully typed for the best developer experience
- 🌈 Themeable - Customize colors and styles with CSS variables
- 📦 Tree-shakeable - Import only what you need
npm install @polypuls3/sdk wagmi viem @tanstack/react-queryimport { WagmiProvider, createConfig, http } from 'wagmi'
import { polygon, polygonAmoy } from 'wagmi/chains'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
const config = createConfig({
chains: [polygon, polygonAmoy],
transports: {
[polygon.id]: http(),
[polygonAmoy.id]: http(),
},
})
const queryClient = new QueryClient()
function App() {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
{/* Your app */}
</QueryClientProvider>
</WagmiProvider>
)
}import '@polypuls3/sdk/styles'import { PollWidget } from '@polypuls3/sdk/components'
function MyPoll() {
return <PollWidget pollId={1n} />
}Complete poll display with voting functionality.
import { PollWidget } from '@polypuls3/sdk/components'
<PollWidget
pollId={1n}
enableConfetti={true}
onVoteSuccess={() => console.log('Vote successful!')}
onVoteError={(error) => console.error(error)}
/>Form component for creating new polls.
import { CreatePollForm } from '@polypuls3/sdk/components'
<CreatePollForm
onSuccess={(pollId) => navigate(`/poll/${pollId}`)}
minOptions={2}
maxOptions={10}
/>Poll preview card component.
import { PollCard } from '@polypuls3/sdk/components'
<PollCard
poll={poll}
onClick={() => navigate(`/poll/${poll.id}`)}
/>Display poll results with visual bars.
import { PollResults } from '@polypuls3/sdk/components'
<PollResults
pollId={1n}
optionCount={3}
showVoteCount
showPercentage
/>Button component for voting on a specific option.
import { VoteButton } from '@polypuls3/sdk/components'
<VoteButton
pollId={1n}
optionId={0n}
onSuccess={() => alert('Voted!')}
>
Vote for this option
</VoteButton>Fetch a single poll by ID.
import { usePoll } from '@polypuls3/sdk/hooks'
const { poll, isLoading, isError } = usePoll({ pollId: 1n })Vote on a poll.
import { useVote } from '@polypuls3/sdk/hooks'
const { vote, isPending, isSuccess } = useVote()
vote({ pollId: 1n, optionId: 0n })Create a new poll.
import { useCreatePoll } from '@polypuls3/sdk/hooks'
const { createPoll, isPending, pollId } = useCreatePoll()
createPoll({
title: 'My Poll',
description: 'What do you think?',
options: ['Option 1', 'Option 2'],
duration: 86400n, // 1 day in seconds
})Fetch poll results with vote counts and percentages.
import { usePollResults } from '@polypuls3/sdk/hooks'
const { results, totalVotes, isLoading } = usePollResults({
pollId: 1n,
optionCount: 3,
})Check if a user has voted on a poll.
import { useHasVoted } from '@polypuls3/sdk/hooks'
const { hasVoted, userVote } = useHasVoted({ pollId: 1n })The SDK includes hooks for fetching data from The Graph subgraph.
import { useSubgraphPolls } from '@polypuls3/sdk'
const { polls, isLoading } = useSubgraphPolls({
status: 'active',
limit: 10,
})useSubgraphPoll(pollId)- Fetch a poll from subgraphuseSubgraphPolls(filters)- Fetch multiple pollsuseSubgraphUserVotes(voter)- Fetch user's vote history
Customize the SDK's appearance using CSS variables:
:root {
--polypuls3-primary: #8247e5;
--polypuls3-primary-foreground: #ffffff;
--polypuls3-background: #ffffff;
--polypuls3-foreground: #0f172a;
--polypuls3-border: #e2e8f0;
--polypuls3-radius: 0.5rem;
}
/* Dark mode */
.dark {
--polypuls3-primary: #a78bfa;
--polypuls3-background: #0f172a;
--polypuls3-foreground: #f1f5f9;
}Before using the SDK, update the following configuration files in your installation:
Update src/core/config/chains.ts with your deployed contract addresses:
export const POLYPULS3_ADDRESSES = {
[polygon.id]: '0xYourMainnetAddress',
[polygonAmoy.id]: '0xYourAmoyAddress',
}Replace the placeholder ABI in src/core/abis/polypuls3.ts with your actual contract ABI from your smart contract project.
Update src/subgraph/config.ts with your subgraph endpoints:
export const SUBGRAPH_URLS = {
137: 'https://api.studio.thegraph.com/query/your-id/polypuls3-polygon/version/latest',
80002: 'https://api.studio.thegraph.com/query/your-id/polypuls3-amoy/version/latest',
}The SDK includes built-in confetti celebration effects that can be triggered on successful votes.
Enable confetti on the PollWidget:
import { PollWidget } from '@polypuls3/sdk/components'
<PollWidget
pollId={1n}
enableConfetti={true} // Enable confetti on vote success
/>You can also trigger confetti programmatically:
import { celebrateVote } from '@polypuls3/sdk/core'
// Trigger with defaults
celebrateVote()
// Customize confetti
celebrateVote({
particleCount: 150,
spread: 90,
colors: ['#ff0000', '#00ff00', '#0000ff'],
origin: { x: 0.5, y: 0.5 }
})Limit confetti to widget boundaries instead of the full viewport:
import { celebrateVote } from '@polypuls3/sdk/core'
// With canvas element for constrained mode
celebrateVote({
constrained: true,
particleCount: 100,
spread: 70,
}, canvasElement)| Option | Type | Default | Description |
|---|---|---|---|
particleCount |
number |
100 |
Number of confetti particles |
spread |
number |
70 |
Spread angle in degrees |
colors |
string[] |
['#8247e5', '#a78bfa', '#22c55e'] |
Array of color hex codes |
constrained |
boolean |
false |
Constrain to widget boundaries |
origin |
{ x?: number; y?: number } |
{ y: 0.6 } |
Spawn point (0-1 range) |
Configure confetti globally through the theme system:
import { PolyPulse3Provider } from '@polypuls3/sdk'
<PolyPulse3Provider
config={{
themeConfig: {
effects: {
enableConfetti: true,
confettiConfig: {
particleCount: 150,
spread: 90,
colors: ['#8247e5', '#a78bfa', '#22c55e'],
constrained: false
}
}
}
}}
>
{/* Your app */}
</PolyPulse3Provider>The SDK includes helpful utility functions:
import {
getPollStatus,
isPollActive,
calculateVotePercentages,
formatDuration,
formatTimestamp,
getTimeRemaining,
truncateAddress,
toDuration,
celebrateVote,
createConfettiInstance,
} from '@polypuls3/sdk/core'Poll Utilities:
getPollStatus(poll)- Get current poll status (active, ended, not_started)isPollActive(poll)- Check if poll is currently activecalculateVotePercentages(options)- Calculate vote percentages for optionsformatDuration(seconds)- Format duration in human-readable stringformatTimestamp(timestamp)- Format Unix timestamp to date stringgetTimeRemaining(expiresAt)- Get time remaining for a polltruncateAddress(address)- Truncate Ethereum address for displaytoDuration(value, unit)- Convert value to duration in seconds
Confetti Utilities:
celebrateVote(config?, canvasElement?)- Trigger confetti celebrationcreateConfettiInstance(canvas)- Create constrained confetti instance for a specific canvas
The SDK provides multiple entry points for tree-shaking:
// Main entry - everything
import { PollWidget } from '@polypuls3/sdk'
// Hooks only
import { usePoll } from '@polypuls3/sdk/hooks'
// Components only
import { PollWidget } from '@polypuls3/sdk/components'
// Core utilities and types
import { Poll, getPollStatus } from '@polypuls3/sdk/core'The SDK is written in TypeScript and includes comprehensive type definitions.
import type { Poll, PollOption, CreatePollParams } from '@polypuls3/sdk'npm install
npm run buildnpm run typechecknpm run lintMIT
Contributions are welcome! Please open an issue or submit a pull request.
For issues and questions:
- GitHub Issues: Create an issue
- Documentation: See
/examplesdirectory for more examples