forked from TrueFiEng/devcon-raffle
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: wslyvh <[email protected]> Co-authored-by: David Furlong <[email protected]>
- Loading branch information
1 parent
96b6f43
commit ca1d7f8
Showing
9 changed files
with
1,257 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
packages/frontend/src/pages/api/frames/images/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import { NextApiRequest, NextApiResponse } from 'next' | ||
import { ImageResponse } from '@vercel/og' | ||
import { formatDate } from '@/utils/formatters/formatDate' | ||
import { DotsIcon } from '@/components/icons' | ||
import { renderToStaticMarkup } from 'react-dom/server' | ||
import { formatTimeLeft } from '@/utils/formatters/formatTimeLeft' | ||
import moment from 'moment' | ||
import { frameConfig, getBids } from '../utils' | ||
|
||
export const runtime = 'edge' | ||
|
||
export default async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
const svg = encodeURIComponent(renderToStaticMarkup(<DotsIcon />)) | ||
const start = moment.utc(frameConfig.startDate) | ||
const end = moment.utc(frameConfig.endDate) | ||
const withdraw = moment.utc(frameConfig.withdrawDate) | ||
const timer = moment().isBefore(start) | ||
? `Till start ${formatTimeLeft(BigInt(start.unix()))}` | ||
: `Time left ${formatTimeLeft(BigInt(end.unix()))}` | ||
const imageOptions = { width: 1146, height: 600, headers: { 'Cache-Control': 'public, max-age=0' } } | ||
|
||
const bids = await getBids() | ||
|
||
const totalNrOfParticipants = bids.length | ||
const numberOfWinners = frameConfig.maxTickets | ||
const probability = | ||
bids.length < frameConfig.maxTickets | ||
? 100 | ||
: ((totalNrOfParticipants - numberOfWinners) / totalNrOfParticipants) * 100 | ||
|
||
// Withdrawal period ended | ||
if (moment().isAfter(withdraw)) { | ||
return new ImageResponse( | ||
( | ||
<div tw="flex flex-col justify-between w-full h-full justify-center items-center text-center bg-[#FADAFA]"> | ||
<p tw="text-8xl">Devcon Raffle</p> | ||
<p tw="text-6xl">has ended ⌛️</p> | ||
</div> | ||
), | ||
imageOptions, | ||
) | ||
} | ||
|
||
// Bidding ended | ||
if (moment().isAfter(end)) { | ||
return new ImageResponse( | ||
( | ||
<div | ||
tw="flex flex-col justify-between w-full h-full p-12 bg-center bg-no-repeat" | ||
style={{ backgroundImage: `url("data:image/svg+xml,${svg}")`, backgroundSize: '100% 100%' }} | ||
> | ||
<div tw="flex flex-col"> | ||
<p tw="p-0 m-0"> | ||
<h1 tw="bg-white text-9xl m-0 p-4">{frameConfig.title}</h1> | ||
</p> | ||
<p tw="p-0 m-0"> | ||
<h2 tw="bg-white text-6xl m-0 px-4 pt-0 pb-4">{frameConfig.description}</h2> | ||
</p> | ||
</div> | ||
|
||
<div tw="flex flex-col text-4xl"> | ||
<p tw="p-0 m-0"> | ||
<span tw="bg-white m-0 p-4">Raffle has ended ⌛️</span> | ||
</p> | ||
<p tw="p-0 m-0"> | ||
<span tw="bg-white m-0 p-2"> | ||
Claim ticket before {formatDate(BigInt(moment.utc(frameConfig.withdrawDate).unix()))} | ||
</span> | ||
</p> | ||
</div> | ||
</div> | ||
), | ||
imageOptions, | ||
) | ||
} | ||
|
||
return new ImageResponse( | ||
( | ||
<div | ||
tw="flex flex-col bg-white justify-between w-full h-full p-12" | ||
style={{ backgroundImage: `url("data:image/svg+xml,${svg}")`, backgroundSize: '100% 100%' }} | ||
> | ||
<div tw="flex flex-col"> | ||
<p tw="p-0 m-0"> | ||
<h1 tw="bg-white text-9xl m-0 p-4">{frameConfig.title}</h1> | ||
</p> | ||
<p tw="p-0 m-0"> | ||
<h2 tw="bg-white text-6xl m-0 px-4 pt-0 pb-4">{frameConfig.description}</h2> | ||
</p> | ||
</div> | ||
|
||
<div tw="flex flex-row justify-between text-4xl"> | ||
<div tw="flex flex-col"> | ||
<p tw="p-0 m-0"> | ||
<span tw="bg-white m-0 p-2">{timer}</span> | ||
</p> | ||
<p tw="p-0 m-0"> | ||
<span tw="bg-white m-0 p-2">Ends on {formatDate(BigInt(moment.utc(frameConfig.endDate).unix()))}</span> | ||
</p> | ||
</div> | ||
{moment().isAfter(start) && ( | ||
<div tw="flex flex-col"> | ||
<p tw="p-0 m-0 justify-end text-right"> | ||
<span tw="bg-white m-0 p-2"> | ||
{bids.length} Bids / {frameConfig.maxTickets} tickets | ||
</span> | ||
</p> | ||
<p tw="p-0 m-0 justify-end text-right"> | ||
<span tw="bg-white m-0 p-2">Current win chance {probability}%</span> | ||
</p> | ||
</div> | ||
)} | ||
</div> | ||
</div> | ||
), | ||
imageOptions, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* eslint-disable react/jsx-key */ | ||
import { createFrames, Button } from 'frames.js/next/pages-router/server' | ||
import moment from 'moment' | ||
import { frameConfig } from './utils' | ||
|
||
const frames = createFrames({ | ||
basePath: '/api/frames', | ||
}) | ||
|
||
const handleRequest = frames(async (req) => { | ||
// Withdrawal period ended | ||
if (moment().isAfter(frameConfig.withdrawDate)) { | ||
return { | ||
image: `/images`, | ||
buttons: [ | ||
<Button action="link" target={`${frameConfig.url}/bids`}> | ||
🏆 View Winners | ||
</Button>, | ||
<Button action="link" target={frameConfig.website}> | ||
🌐 Devcon.org | ||
</Button>, | ||
], | ||
} | ||
} | ||
|
||
// Bidding ended | ||
if (moment().isAfter(frameConfig.endDate)) { | ||
return { | ||
image: `/images`, | ||
buttons: [ | ||
<Button action="link" target={`${frameConfig.url}/bids`}> | ||
🏆 View Winners | ||
</Button>, | ||
<Button action="link" target={frameConfig.url}> | ||
🎟️ Claim Ticket | ||
</Button>, | ||
], | ||
} | ||
} | ||
|
||
return { | ||
image: `/images`, | ||
buttons: [ | ||
<Button action="link" target={`${frameConfig.url}/bids`}> | ||
🏆 View Bids | ||
</Button>, | ||
<Button action="link" target={frameConfig.url}> | ||
🎟️ Place Bid | ||
</Button>, | ||
], | ||
} | ||
}) | ||
|
||
export default handleRequest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { AUCTION_ABI } from '@/blockchain/abi/auction' | ||
import { AUCTION_ADDRESSES } from '@/blockchain/auctionAddresses' | ||
import { createPublicClient, http } from 'viem' | ||
import { readContract } from 'viem/actions' | ||
import { arbitrum } from 'viem/chains' | ||
|
||
export const frameConfig = { | ||
title: 'Devcon 7', | ||
description: 'Auction & Raffle Tickets', | ||
website: 'https://devcon.org/', | ||
startDate: 1718722800000, | ||
endDate: 1720569540000, | ||
withdrawDate: 1722470340000, | ||
url: process.env.SITE_URL ?? process.env.URL ?? 'http://localhost:3000', | ||
chain: arbitrum, | ||
maxTickets: 204, | ||
} | ||
|
||
export const client = createPublicClient({ | ||
chain: frameConfig.chain, | ||
transport: http(), | ||
}) | ||
|
||
export const getBids = async () => { | ||
return readContract(client, { | ||
abi: AUCTION_ABI, | ||
address: AUCTION_ADDRESSES[frameConfig.chain.id], | ||
functionName: 'getBidsWithAddresses', | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.