JS Client Quickstart
This guide shows you how to quickly add the packages required to deposit into PoolTogether.
Basic knowledge of Javascript, Typescript, Ethereum and ethers.js is assumed.
💾 Installation
To interact with the latest PoolTogether V4 deployment you'll need to install 2 packages: v4-client-js and v4-pool-data.
v4-client-js
provides functionality for interacting with the deployment.
v4-pool-data
contains the latest contract addresses & ABIs of the PoolTogether Prize Pool Network.
yarn add @pooltogether/v4-client-js @pooltogether/v4-pool-data
🏎️ Getting Started
1. Prize Pool Networks
To begin, we'll create an instance of the deployed Prize Pool Network. The PrizePoolNetwork
class is the root of most interaction through the client library, so we'll begin by creating an instance of it.
You'll need to create instances of ethers Providers to read data from each blockchain the contract list contains deployments for. Default code is provided below but acquiring your own API keys for better performance is recommended.
NOTE: You can determine the chain ids needed dynamically by using
getContractListChainIds
fromv4-client-js
.
import { PrizePoolNetwork } from "@pooltogether/v4-client-js";
import { mainnet } from "@pooltogether/v4-pool-data";
import { ethers } from "ethers";
const providers = {
// Mainnet Ethereum
1: ethers.getDefaultProvider(1),
// Polygon
137: new ethers.providers.JsonRpcProvider(137, "https://polygon-rpc.com"),
// Avalanche
43114: new ethers.providers.JsonRpcProvider(
43114,
"https://api.avax.network/ext/bc/C/rpc"
),
};
const PrizePoolNetwork = new PrizePoolNetwork(providers, mainnet);
That's it! Now we're ready to start reading data from the PoolTogether Prize Pool Network!
2. Prize Pools
A PrizePool
is a representation of a Prize Pool deployment. The Prize Pool is responsible for managing deposits, withdrawals & delegation. PrizePool
is a read only object, for write capabilities see User
.
Our PrizePoolNetwork
is already populated with a PrizePool
instance for each deployment provided in the contract list. To interact with a specific one we can read it from the PrizePoolNetwork
with a combination of chain id and the addres of the YieldSourcePrizePool
contract. We'll use the Polygon USDC Prize Pool for this example, all deployments are available here.
const chainId = 137;
const prizePoolAddress = "0x19DE635fb3678D8B8154E37d8C9Cdf182Fe84E60";
const prizePool = PrizePoolNetwork.getPrizePool(chainId, prizePoolAddress);
3. Users
A User
is wrapper around PrizePool
with the ability to send transactions to manage deposits, withdrawals and delegation.
It is created by passing an instance of an ethers Signer and a PrizePool
. Depending on how your dApp is set up, acquiring a Signer
may vary.
const user = new User(prizePool.prizePoolMetadata, signer, prizePool);
4. How to Get Token Balances
A very basic action is just getting a users token balances. We want to know the amount of tokens a user has deposited, the amount of underlying token the user has, as well as other details about the token like it's decimals, name and symbol.
We can use getUsersPrizePoolBalances
to fetch a users token balances across all of the networks.
const usersAddress = "0x1D9312B477E38397c6A69A6bBA2A1AD009CcF685";
const balances = await PrizePoolNetwork.getUsersPrizePoolBalances(usersAddress);
Alternatively we can use getUsersDepositAllowance
to fetch a users token balances for a specific Prize Pool.
const usersAddress = "0x1D9312B477E38397c6A69A6bBA2A1AD009CcF685";
const balances = await PrizePool.getUsersDepositAllowance(usersAddress);
5. How to Deposit
Before we can make a deposit, we need to make sure hte user has approved the YieldSourcePrizePool
to use the users underlying token (USDC in this case).
NOTE: All of the read actions that are taking place through the User object can also be done with just a PrizePool.
const { allowanceUnformatted, isApproved } = await user.getDepositAllowance();
isApproved
is a boolean which is true
if the user has an approved depost allowance.
allowanceUnformatted
is a BigNumber
representing the amount the user has allowed the contract to spend. The Unformatted
suffix implies that the data has not been shifted to account for the decimals of the underlying token that was approved for use.
If isApproved
is false
, we will need to submit a transaction to update the amount the user has approved. Otherwise we can move forward.
NOTE:
decimals
can be found inusersTokenBalances
from above.
const txResponse: TransactionResponse = await user.approveDeposits(
ethers.utils.parseUnits(1000, decimals)
);
If isApproved
is true
and the amount the user wishes to deposit is less than the allowance, then we can simply submit a transaction to deposit.
const txResponse: TransactionResponse = await user.deposit(
ethers.utils.parseUnits(10, decimals)
);
6. How to Claim Prizes
Claiming a users prizes requires a few steps. To do this we need to:
6.1. First we need to determine which PrizeDistributor
we want to interact with. Lets stick with the Polygon USDC deployment for now. Again, all deployments are available here.
const chainId = 137;
const prizeDistributorAddress = "0x8141BcFBcEE654c5dE17C4e2B2AF26B67f9B9056";
const prizeDistributor = PrizePoolNetwork.getPrizeDistributor(
chainId,
prizeDistributorAddress
);
6.2. We need a valid Draw
and PrizeDistribution
to check prizes for. "Valid" meaning that the Draw is in the DrawBuffer
, the PrizeDistribution is in the PrizeDistributionBuffer
and the Draw is not expired. The buffers can store hundreds of their respective data types and the expiration date is dynamic and often on a scale of months.
import { msToS } from "@pooltogether/utilities";
const draw: Draw = await prizeDistributor.getNewestDraw();
const prizeDistribution: PrizeDistribution =
await prizeDistributor.getNewestDraw();
const currentTimestampSeconds = msToS(Date.now());
const drawTimestampSeconds = draw.timestamp.toNumber();
const drawExpirationTimestampSeconds =
prizeDistribution.expiryDuration + drawTimestampSeconds;
const isExpired: boolean =
drawExpirationTimestampSeconds <= currentTimestampSeconds;
6.3. Now that we have a Draw
and PrizeDistribution
we can check if a user won any prizes. Checking if a user has won a prize requires a lot of computations. To make this as simple as possible we provide several options for accessing the data; we recommend using the Prize API, a Prize API wrapper is available here.
const usersAddress = "0x1D9312B477E38397c6A69A6bBA2A1AD009CcF685";
const drawResults: DrawResults =
await prizeDistributor.getUsersDrawResultsForDrawId(
usersAddress,
draw.drawId,
prizeDistribution.maxPicksPerUser
);
6.4. Simply checking the draw results reveals if a user won any prizes.
const isUserAWinner = !drawResults.totalValue.isZero();
6.5. Now we can claim prizes! To do this, we need to encode the data and send it to the users wallet for a signature. The easiest way to do this is to instantiate a PrizeDistributor
with an ethers Signer instead of a Provider
. We can accomplish this using the PrizeDistributor
from step 1 and the Signer
from the User
section.
const signerPrizeDistributor = new PrizeDistributor(
prizeDistributor.prizeDistributorMetadata,
signer,
prizeDistributor.contractMetadataList
);
const txResponse: TransactionResponse =
await signerPrizeDistributor.claimPrizesByDrawResults(drawResults);
For more examples of the v4-client-js
library see here.