This subgraph indexes events from the Strategy (MONSTR) smart contract on the Monad blockchain, enabling efficient querying of lottery prizes, auction results, transactions, and user activity.
New: Simple .env-based build process!
# 1. Create .env file
cp .env.example .env
# Edit .env with your ADDRESS and NETWORK
# 2. Build
npm install
npm run build
# 3. Deploy
npm run deploy # or npm run deploy:goldskySee QUICK_BUILD.md for details.
The Strategy contract is an ERC20 token with unique mechanics including:
- Daily lottery system for token holders
- Daily auction system using WMON
- Mint and redeem functionality with fees
- Prize claiming system with 7-day expiry
This subgraph tracks all these activities and makes them queryable via GraphQL.
- Node.js v16 or higher
- npm or yarn
- Graph CLI (
npm install -g @graphprotocol/graph-cli) - Access to a Graph node (local or The Graph Studio)
npm installEdit subgraph.yaml and update the following fields:
source:
address: "0x0000000000000000000000000000000000000000" # Replace with actual contract address
startBlock: 0 # Replace with deployment block numberYou can find the contract address in your .env file (VITE_CONTRACT_ADDRESS).
To find the deployment block number, use a block explorer or check the deployment transaction.
Generate TypeScript types from the GraphQL schema and ABI:
npm run codegenThis will create the generated/ directory with all necessary types.
Compile the subgraph:
npm run build- Create a subgraph on The Graph Studio
- Authenticate with your deploy key:
graph auth --studio <DEPLOY_KEY>
- Deploy:
npm run deploy
- Start a local Graph node (see Graph Node docs)
- Create the subgraph:
npm run create-local
- Deploy:
npm run deploy-local
Tracks lottery winners and their prizes:
id: Unique identifier (day-lottery)day: Day number when lottery was executedwinner: Winner's addressamount: Prize amount in MONSTR (wei)claimed: Whether prize was claimedexpired: Whether prize expired (sent to beneficiary)timestamp: Block timestamp of lottery execution
Tracks auction results:
id: Unique identifier (day-auction)day: Day number when auction concludedwinner: Winner's addressstratAmount: MONSTR amount wonmonPaid: MON/WMON paid by winnerclaimed: Whether prize was claimedexpired: Whether prize expiredbidCount: Number of bids placed
Tracks all mint and redeem transactions:
id: Unique identifier (txHash-logIndex)type: "MINT" or "REDEEM"user: User's addressmonAmount: MON amount (deposited or received)stratAmount: MONSTR amount (minted or burned)fee: Fee chargedtimestamp: Block timestamp
Aggregates user statistics:
id: User's addresslotteryWins: Array of lottery prizes wonauctionWins: Array of auction prizes wontotalLotteryWinnings: Sum of lottery prizestotalAuctionWinnings: Sum of auction prizestotalAuctionSpent: Total MON spent on auctionslotteryWinCount: Number of lotteries wonauctionWinCount: Number of auctions wontotalMinted: Total MONSTR mintedtotalRedeemed: Total MONSTR redeemedtransactionCount: Total transactions
Global protocol statistics:
totalLotteryPrizes: Total MONSTR distributed via lotterytotalAuctionPrizes: Total MONSTR distributed via auctionstotalLotteryClaimed: Total lottery prizes claimedtotalAuctionClaimed: Total auction prizes claimedtotalLotteryExpired: Total lottery prizes that expiredtotalAuctionExpired: Total auction prizes that expiredlotteryCount: Number of lotteries executedauctionCount: Number of auctions executed
{
lotteryPrizes(first: 7, orderBy: day, orderDirection: desc) {
day
winner
amount
claimed
expired
timestamp
txHash
}
}{
auctionPrizes(first: 7, orderBy: day, orderDirection: desc) {
day
winner
stratAmount
monPaid
claimed
expired
timestamp
bidCount
}
}{
user(id: "0x...") {
address
lotteryWinCount
auctionWinCount
totalLotteryWinnings
totalAuctionWinnings
totalAuctionSpent
lotteryWins(orderBy: day, orderDirection: desc) {
day
amount
claimed
expired
timestamp
}
auctionWins(orderBy: day, orderDirection: desc) {
day
stratAmount
monPaid
claimed
expired
timestamp
}
}
}{
transactions(
first: 10
orderBy: timestamp
orderDirection: desc
) {
id
type
user
monAmount
stratAmount
fee
timestamp
txHash
}
}{
protocolStats(id: "protocol-stats") {
totalLotteryPrizes
totalAuctionPrizes
totalLotteryClaimed
totalAuctionClaimed
lotteryCount
auctionCount
totalMinted
totalRedeemed
totalFees
totalTransactions
}
}{
lotteryPrizes(
where: {
winner: "0x...",
claimed: false,
expired: false
}
) {
day
amount
timestamp
}
auctionPrizes(
where: {
winner: "0x...",
claimed: false,
expired: false
}
) {
day
stratAmount
monPaid
timestamp
}
}After deploying the subgraph, add the subgraph URL to your .env file:
VITE_SUBGRAPH_URL=https://api.studio.thegraph.com/query/{SUBGRAPH_ID}/strategy-subgraph/version/latestInstall Apollo Client or similar:
npm install @apollo/client graphqlExample using Apollo Client:
import { ApolloClient, InMemoryCache, gql } from '@apollo/client';
const client = new ApolloClient({
uri: import.meta.env.VITE_SUBGRAPH_URL,
cache: new InMemoryCache()
});
// Query recent transactions
const { data } = await client.query({
query: gql`
{
transactions(first: 10, orderBy: timestamp, orderDirection: desc) {
id
type
user
monAmount
stratAmount
fee
timestamp
txHash
}
}
`
});For real-time updates on the landing page, you can:
Option A: Polling
const { data } = await client.query({
query: TRANSACTIONS_QUERY,
pollInterval: 5000 // Poll every 5 seconds
});Option B: Subscriptions (if supported)
const { data } = await client.subscribe({
query: gql`
subscription {
transactions(
first: 10
orderBy: timestamp
orderDirection: desc
) {
id
type
user
timestamp
}
}
`
});The subgraph automatically correlates PrizeClaimed events with their corresponding lottery or auction prizes by:
- Searching the last 30 prizes for matching winner address and amount
- Marking the prize as claimed with timestamp
- Updating protocol statistics
When a prize expires (after 7 days unclaimed), the BeneficiaryFunded event is emitted. The subgraph:
- Finds the prize by previous winner
- Marks it as expired
- Records the beneficiary who received the funds
- Updates protocol statistics
User entities automatically aggregate:
- All lottery and auction wins
- Total winnings and spending
- Complete transaction history
- Win counts
To test the subgraph locally:
- Start a local Graph node (with PostgreSQL and IPFS)
- Create and deploy:
npm run create-local npm run deploy-local
- Query at
http://localhost:8000/subgraphs/name/strategy-subgraph
If you make changes to the schema or mappings:
- Update the relevant files
- Run codegen:
npm run codegen
- Rebuild:
npm run build
- Redeploy:
npm run deploy
Check the Graph Node logs for errors. Common issues:
- Incorrect contract address or network
- Wrong start block (set to block before first transaction)
- ABI mismatch (ensure ABI is up to date)
If data is missing:
- Verify events are being emitted on-chain
- Check that the start block is correct
- Ensure the contract address matches
For large datasets:
- Use pagination with
firstandskip - Add appropriate
orderByandwherefilters - Consider using timestamps for time-based queries
MIT