mirror of
https://github.com/penxio/penx.git
synced 2026-04-19 03:03:06 -04:00
feat: can claim daily
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { Airdrop } from '@/components/Airdrop/Airdrop'
|
||||
import { ModeToggle } from '@/components/ModeToggle'
|
||||
import { Profile } from '@/components/Profile/Profile'
|
||||
import { getSite } from '@/lib/fetchers'
|
||||
@@ -11,7 +12,6 @@ export default async function RootLayout({
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
|
||||
const site = await getSite()
|
||||
const { SiteLayout } = await loadTheme()
|
||||
|
||||
@@ -22,6 +22,7 @@ export default async function RootLayout({
|
||||
ModeToggle={ModeToggle}
|
||||
MobileNav={null}
|
||||
ConnectButton={Profile}
|
||||
Airdrop={Airdrop}
|
||||
>
|
||||
{children}
|
||||
</SiteLayout>
|
||||
|
||||
@@ -74,7 +74,10 @@ export const BuyBtn = ({
|
||||
|
||||
if (!address)
|
||||
return (
|
||||
<WalletConnectButton className="h-[50px] w-full rounded-xl">
|
||||
<WalletConnectButton
|
||||
variant="brand"
|
||||
className="h-[50px] w-full rounded-xl"
|
||||
>
|
||||
Connect wallet
|
||||
</WalletConnectButton>
|
||||
)
|
||||
|
||||
@@ -97,7 +97,10 @@ export const SellBtn = ({
|
||||
)}
|
||||
</Button>
|
||||
) : (
|
||||
<WalletConnectButton className="h-[50px] w-full rounded-full">
|
||||
<WalletConnectButton
|
||||
variant="brand"
|
||||
className="h-[50px] w-full rounded-full"
|
||||
>
|
||||
Connect wallet
|
||||
</WalletConnectButton>
|
||||
)}
|
||||
|
||||
12
components/Airdrop/Airdrop.tsx
Normal file
12
components/Airdrop/Airdrop.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import * as React from 'react'
|
||||
import { AirdropButton } from './AirdropButton'
|
||||
import { AirdropDialog } from './AirdropDialog'
|
||||
|
||||
export function Airdrop() {
|
||||
return (
|
||||
<>
|
||||
{/* <AirdropButton /> */}
|
||||
<AirdropDialog />
|
||||
</>
|
||||
)
|
||||
}
|
||||
13
components/Airdrop/AirdropButton.tsx
Normal file
13
components/Airdrop/AirdropButton.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import { Rocket } from 'lucide-react'
|
||||
|
||||
export function AirdropButton() {
|
||||
return (
|
||||
<div className="flex items-center gap-1 text-xs rounded-full px-2 py-1 text-foreground/50 font-medium cursor-pointer hover:text-foreground/80 h-8 transition-colors">
|
||||
<Rocket size={12} />
|
||||
<div>Airdrop</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
163
components/Airdrop/AirdropDialog.tsx
Normal file
163
components/Airdrop/AirdropDialog.tsx
Normal file
@@ -0,0 +1,163 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@/components/ui/dialog'
|
||||
import { useDailyClaimCap } from '@/hooks/useDailyClaimCap'
|
||||
import { useWagmiConfig } from '@/hooks/useWagmiConfig'
|
||||
import { dailyClaimAbi } from '@/lib/abi'
|
||||
import { addressMap } from '@/lib/address'
|
||||
import { extractErrorMessage } from '@/lib/extractErrorMessage'
|
||||
import { readContract, waitForTransactionReceipt } from '@wagmi/core'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import pRetry, { AbortError } from 'p-retry'
|
||||
import { toast } from 'sonner'
|
||||
import { useAccount, useReadContract, useWriteContract } from 'wagmi'
|
||||
import LoadingDots from '../icons/loading-dots'
|
||||
import { Button } from '../ui/button'
|
||||
import { Skeleton } from '../ui/skeleton'
|
||||
import { WalletConnectButton } from '../WalletConnectButton'
|
||||
import { AirdropButton } from './AirdropButton'
|
||||
|
||||
interface Props {}
|
||||
|
||||
export function AirdropDialog({}: Props) {
|
||||
const { data } = useSession()
|
||||
return (
|
||||
<>
|
||||
<Dialog>
|
||||
<DialogTrigger>
|
||||
<AirdropButton />
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[400px] min-h-96 flex flex-col gap-6">
|
||||
<DialogHeader className="text-center">
|
||||
<DialogTitle className="text-center">
|
||||
Claim $PEN everyday!
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
{data && <AuthenticatedContent />}
|
||||
{!data && <UnauthenticatedContent />}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function UnauthenticatedContent() {
|
||||
return (
|
||||
<>
|
||||
<div className="w-11/12 text-foreground/60 text-center mx-auto">
|
||||
ou can claim some $PEN every day. Connect your wallet to see how much
|
||||
$PEN you’re eligible to claim.
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<div className="text-3xl font-bold text-center">*** $PEN</div>
|
||||
<div className="text-foreground/50">claimable</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-center flex-1 -mt-10">
|
||||
<WalletConnectButton size="lg">
|
||||
Connect wallet to Claim $PEN
|
||||
</WalletConnectButton>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function AuthenticatedContent() {
|
||||
const [isClaiming, setIsClaiming] = useState(false)
|
||||
const { data, isLoading } = useDailyClaimCap()
|
||||
const { writeContractAsync } = useWriteContract()
|
||||
const { address } = useAccount()
|
||||
const wagmiConfig = useWagmiConfig()
|
||||
let { data: executionFee, error } = useReadContract({
|
||||
address: addressMap.DailyClaim,
|
||||
abi: dailyClaimAbi,
|
||||
functionName: 'executionFee',
|
||||
})
|
||||
|
||||
async function checkClaimSuccess() {
|
||||
const requests = await readContract(wagmiConfig, {
|
||||
address: addressMap.DailyClaim,
|
||||
abi: dailyClaimAbi,
|
||||
functionName: 'getPendingRequests',
|
||||
})
|
||||
|
||||
const userRequests = requests.filter((req) => req.user === address) || []
|
||||
|
||||
// Abort retrying if the resource doesn't exist
|
||||
if (userRequests.length > 0) {
|
||||
// throw new AbortError('Not success')
|
||||
throw new Error('Not success')
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async function claim() {
|
||||
setIsClaiming(true)
|
||||
try {
|
||||
const hash = await writeContractAsync({
|
||||
abi: dailyClaimAbi,
|
||||
address: addressMap.DailyClaim,
|
||||
functionName: 'createClaimRequest',
|
||||
value: executionFee,
|
||||
})
|
||||
|
||||
await waitForTransactionReceipt(wagmiConfig, { hash })
|
||||
|
||||
await pRetry(checkClaimSuccess, {
|
||||
retries: 20,
|
||||
minTimeout: 1000,
|
||||
onFailedAttempt(error) {
|
||||
console.log('=====error:', error.attemptNumber, error.name)
|
||||
},
|
||||
})
|
||||
|
||||
toast.success('Claim $PEN successfully')
|
||||
} catch (error) {
|
||||
console.log('======error:', error)
|
||||
const msg = extractErrorMessage(error)
|
||||
toast.error(msg)
|
||||
}
|
||||
setIsClaiming(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="w-11/12 text-foreground/60 text-center mx-auto">
|
||||
You can claim $PEN every day. Don’t miss out, claim today’s $PEN airdrop
|
||||
now.
|
||||
</div>
|
||||
{isLoading && <Skeleton className="h-9 w-32 mx-auto" />}
|
||||
{data && (
|
||||
<div className="flex items-center justify-center gap-2 h-9">
|
||||
<div className="text-3xl font-bold text-center">{data.cap} $PEN</div>
|
||||
<div className="text-foreground/50">claimable</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center justify-center flex-1 -mt-10">
|
||||
<Button
|
||||
disabled={isClaiming}
|
||||
size="lg"
|
||||
className="w-40 flex gap-2"
|
||||
onClick={claim}
|
||||
>
|
||||
{isClaiming ? (
|
||||
<>
|
||||
<div>Claiming</div>
|
||||
<LoadingDots />
|
||||
</>
|
||||
) : (
|
||||
'Claim $PEN'
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -17,7 +17,7 @@ export function ModeToggle() {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="flex-shrink-0">
|
||||
<Button variant="ghost" size="icon" className="flex-shrink-0 h-8 w-8">
|
||||
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
|
||||
@@ -60,7 +60,7 @@ export function TipTokenDialog({
|
||||
})
|
||||
|
||||
const { refetch: refetchTipStats } = useTipStats(receivers)
|
||||
const { refetch: refetchTipInfo } = useTipInfo(post.id)
|
||||
const { refetch: refetchTipInfo } = useTipInfo(post.id, !!params.slug)
|
||||
const { data: data, isLoading: isLoadingCap, refetch } = useAllocationCap()
|
||||
|
||||
const { writeContractAsync } = useWriteContract()
|
||||
|
||||
@@ -26,7 +26,8 @@ export function TippedAmount(props: Props) {
|
||||
}
|
||||
|
||||
export function TippedAmountInPostDetail({ post, setIsOpen }: Props) {
|
||||
const { data, isLoading } = useTipInfo(post.id)
|
||||
const { data, isLoading } = useTipInfo(post.id, true)
|
||||
|
||||
if (isLoading) return <Skeleton className="h-6 w-12" />
|
||||
return (
|
||||
<div
|
||||
|
||||
20
hooks/useDailyClaimCap.ts
Normal file
20
hooks/useDailyClaimCap.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { DAILY_CLAIM_CAP_URL } from '@/lib/constants'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import ky from 'ky'
|
||||
import { useAccount } from 'wagmi'
|
||||
|
||||
export function useDailyClaimCap() {
|
||||
const { address } = useAccount()
|
||||
|
||||
const { data, ...rest } = useQuery({
|
||||
queryKey: ['DailyClaimCap', address!],
|
||||
async queryFn() {
|
||||
return ky
|
||||
.get(DAILY_CLAIM_CAP_URL + `?address=${address}`)
|
||||
.json<{ cap: number }>()
|
||||
},
|
||||
enabled: !!address,
|
||||
})
|
||||
|
||||
return { data, ...rest }
|
||||
}
|
||||
@@ -8,7 +8,7 @@ type TipInfo = {
|
||||
uri: string
|
||||
}
|
||||
|
||||
export function useTipInfo(postId: string) {
|
||||
export function useTipInfo(postId: string, enabled: boolean) {
|
||||
const query = gql`
|
||||
query geTip($postId: String!) {
|
||||
tip(id: $postId) {
|
||||
@@ -30,7 +30,7 @@ export function useTipInfo(postId: string) {
|
||||
},
|
||||
})
|
||||
},
|
||||
enabled: !!postId,
|
||||
enabled: !!postId && enabled,
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from './space'
|
||||
export { penTokenAbi, tipAbi, creationFactoryAbi } from './penx'
|
||||
export { penTokenAbi, tipAbi, dailyClaimAbi, creationFactoryAbi } from './penx'
|
||||
|
||||
241
lib/abi/penx.ts
241
lib/abi/penx.ts
@@ -637,6 +637,247 @@ export const creationFactoryAbi = [
|
||||
{ type: 'receive', stateMutability: 'payable' },
|
||||
] as const
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DailyClaim
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export const dailyClaimAbi = [
|
||||
{
|
||||
type: 'constructor',
|
||||
inputs: [
|
||||
{ name: '_keeper', internalType: 'address', type: 'address' },
|
||||
{ name: '_pen', internalType: 'contract PenToken', type: 'address' },
|
||||
],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'error',
|
||||
inputs: [{ name: 'value', internalType: 'uint256', type: 'uint256' }],
|
||||
name: 'ExecutionFeeNotEnough',
|
||||
},
|
||||
{
|
||||
type: 'error',
|
||||
inputs: [{ name: 'requestId', internalType: 'uint256', type: 'uint256' }],
|
||||
name: 'InvalidRequestId',
|
||||
},
|
||||
{ type: 'error', inputs: [], name: 'OnlyKeeper' },
|
||||
{
|
||||
type: 'error',
|
||||
inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],
|
||||
name: 'OwnableInvalidOwner',
|
||||
},
|
||||
{
|
||||
type: 'error',
|
||||
inputs: [{ name: 'account', internalType: 'address', type: 'address' }],
|
||||
name: 'OwnableUnauthorizedAccount',
|
||||
},
|
||||
{ type: 'error', inputs: [], name: 'ReentrancyGuardReentrantCall' },
|
||||
{ type: 'error', inputs: [], name: 'TodayIsClaimed' },
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'requestId',
|
||||
internalType: 'uint256',
|
||||
type: 'uint256',
|
||||
indexed: false,
|
||||
},
|
||||
{
|
||||
name: 'account',
|
||||
internalType: 'address',
|
||||
type: 'address',
|
||||
indexed: true,
|
||||
},
|
||||
],
|
||||
name: 'ClaimRequestCreated',
|
||||
},
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'requestId',
|
||||
internalType: 'uint256',
|
||||
type: 'uint256',
|
||||
indexed: false,
|
||||
},
|
||||
{
|
||||
name: 'account',
|
||||
internalType: 'address',
|
||||
type: 'address',
|
||||
indexed: true,
|
||||
},
|
||||
{
|
||||
name: 'amount',
|
||||
internalType: 'uint256',
|
||||
type: 'uint256',
|
||||
indexed: false,
|
||||
},
|
||||
],
|
||||
name: 'ClaimRequestExecuted',
|
||||
},
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'newExecutionFee',
|
||||
internalType: 'uint256',
|
||||
type: 'uint256',
|
||||
indexed: false,
|
||||
},
|
||||
],
|
||||
name: 'ExecutionFeeUpdated',
|
||||
},
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'newKeeper',
|
||||
internalType: 'address',
|
||||
type: 'address',
|
||||
indexed: false,
|
||||
},
|
||||
],
|
||||
name: 'KeeperUpdated',
|
||||
},
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'previousOwner',
|
||||
internalType: 'address',
|
||||
type: 'address',
|
||||
indexed: true,
|
||||
},
|
||||
{
|
||||
name: 'newOwner',
|
||||
internalType: 'address',
|
||||
type: 'address',
|
||||
indexed: true,
|
||||
},
|
||||
],
|
||||
name: 'OwnershipTransferred',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: '', internalType: 'address', type: 'address' }],
|
||||
name: 'claimedTimes',
|
||||
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'createClaimRequest',
|
||||
outputs: [{ name: 'requestId', internalType: 'uint256', type: 'uint256' }],
|
||||
stateMutability: 'payable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [
|
||||
{ name: 'requestId', internalType: 'uint256', type: 'uint256' },
|
||||
{ name: 'amount', internalType: 'uint256', type: 'uint256' },
|
||||
],
|
||||
name: 'executeClaimRequest',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'executionFee',
|
||||
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'getPendingRequests',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
internalType: 'struct DailyClaim.RequestInfo[]',
|
||||
type: 'tuple[]',
|
||||
components: [
|
||||
{ name: 'requestId', internalType: 'uint256', type: 'uint256' },
|
||||
{ name: 'user', internalType: 'address', type: 'address' },
|
||||
],
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: 'requestId', internalType: 'uint256', type: 'uint256' }],
|
||||
name: 'getRequest',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
internalType: 'struct DailyClaim.Request',
|
||||
type: 'tuple',
|
||||
components: [
|
||||
{ name: 'user', internalType: 'address', type: 'address' },
|
||||
],
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'keeper',
|
||||
outputs: [{ name: '', internalType: 'address', type: 'address' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'owner',
|
||||
outputs: [{ name: '', internalType: 'address', type: 'address' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'renounceOwnership',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'requestIndex',
|
||||
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: 'value', internalType: 'uint256', type: 'uint256' }],
|
||||
name: 'setExecutionFee',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: '_keeper', internalType: 'address', type: 'address' }],
|
||||
name: 'setKeeper',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }],
|
||||
name: 'transferOwnership',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{ type: 'receive', stateMutability: 'payable' },
|
||||
] as const
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ECDSA
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -5,6 +5,7 @@ const baseSepoliaAddress = {
|
||||
CreationFactory: '0xB2ebC5f85E0DA834CB71884150d2Fd738fEf918B',
|
||||
PenToken: '0xd8501D1063Db721512572738e53775F11C05Df10',
|
||||
Tip: '0xe31E51b20C1a054Fa46Dacd31C8a45ce3C97C834',
|
||||
DailyClaim: '0xfa68A007EF07d55218d4d1f5910A3A526850d001',
|
||||
}
|
||||
|
||||
const baseAddress = {
|
||||
@@ -12,6 +13,7 @@ const baseAddress = {
|
||||
CreationFactory: '0xB9563EBeDE644956FB4d8EFE40440bAeA8da342D',
|
||||
PenToken: '0xadA2eA2D7e2AbB724F860ED8d08F85B25a4cB90d',
|
||||
Tip: '0xD1B9751cdb3A6599f47eb3581446750c949c5f51',
|
||||
DailyClaim: '0x7BdD1C56363B5D2480f3CC1Cd3b0A250d07DB288',
|
||||
}
|
||||
|
||||
export const addressMap: Record<keyof typeof baseSepoliaAddress, any> =
|
||||
|
||||
@@ -12,7 +12,6 @@ export const IPFS_ADD_URL = 'https://penx.io/api/ipfs-add'
|
||||
// export const IPFS_ADD_URL = 'http://localhost:4000/api/ipfs-add'
|
||||
export const IPFS_GATEWAY = 'https://ipfs-gateway.spaceprotocol.xyz'
|
||||
|
||||
|
||||
export const ELECTRIC_BASE_URL = 'http://43.154.135.183:3000'
|
||||
|
||||
export const GOOGLE_DRIVE_OAUTH_REDIRECT_URI =
|
||||
@@ -98,5 +97,12 @@ export const DATABASE_TOOLBAR_HEIGHT = 42
|
||||
|
||||
export const SIDEBAR_WIDTH = 240
|
||||
|
||||
export const ALLOCATION_CAP_URL =
|
||||
NETWORK === NetworkNames.BASE
|
||||
? 'https://penx.io/api/allocation-cap'
|
||||
: 'https://sepolia.penx.io/api/allocation-cap'
|
||||
|
||||
export const ALLOCATION_CAP_URL = NETWORK === NetworkNames.BASE? 'https://penx.io/api/allocation-cap': 'https://sepolia.penx.io/api/allocation-cap'
|
||||
export const DAILY_CLAIM_CAP_URL =
|
||||
NETWORK === NetworkNames.BASE
|
||||
? 'https://penx.io/api/daily-claim-cap'
|
||||
: 'https://sepolia.penx.io/api/daily-claim-cap'
|
||||
|
||||
14
package.json
14
package.json
@@ -29,7 +29,7 @@
|
||||
"@fower/utils": "^2.1.1",
|
||||
"@glideapps/glide-data-grid": "^6.0.3",
|
||||
"@hookform/resolvers": "^3.9.0",
|
||||
"@penxio/types": "^0.0.3",
|
||||
"@penxio/types": "^0.0.4",
|
||||
"@prisma/client": "^5.21.1",
|
||||
"@privy-io/server-auth": "^1.15.0",
|
||||
"@radix-ui/react-accordion": "^1.2.1",
|
||||
@@ -137,7 +137,7 @@
|
||||
"ky": "^1.5.0",
|
||||
"lightweight-charts": "^4.2.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lucide-react": "^0.454.0",
|
||||
"lucide-react": "^0.456.0",
|
||||
"mime": "^4.0.4",
|
||||
"mitt": "^3.0.1",
|
||||
"nanoid": "^5.0.8",
|
||||
@@ -150,11 +150,11 @@
|
||||
"octokit": "^4.0.2",
|
||||
"openai-edge": "^1.2.2",
|
||||
"p-retry": "^6.2.0",
|
||||
"penx-theme-card": "^0.0.3",
|
||||
"penx-theme-photo": "^0.0.3",
|
||||
"penx-theme-micro": "^0.0.3",
|
||||
"penx-theme-minimal": "^0.0.3",
|
||||
"penx-theme-garden": "^0.0.3",
|
||||
"penx-theme-card": "^0.0.4",
|
||||
"penx-theme-photo": "^0.0.4",
|
||||
"penx-theme-micro": "^0.0.4",
|
||||
"penx-theme-minimal": "^0.0.4",
|
||||
"penx-theme-garden": "^0.0.4",
|
||||
"prisma-extension-pagination": "^0.7.4",
|
||||
"prismjs": "^1.29.0",
|
||||
"rc-table": "^7.48.1",
|
||||
|
||||
96
pnpm-lock.yaml
generated
96
pnpm-lock.yaml
generated
@@ -57,8 +57,8 @@ importers:
|
||||
specifier: ^3.9.0
|
||||
version: 3.9.0(react-hook-form@7.53.1(react@18.2.0))
|
||||
'@penxio/types':
|
||||
specifier: ^0.0.3
|
||||
version: 0.0.3
|
||||
specifier: ^0.0.4
|
||||
version: 0.0.4
|
||||
'@prisma/client':
|
||||
specifier: ^5.21.1
|
||||
version: 5.21.1(prisma@5.21.1)
|
||||
@@ -381,8 +381,8 @@ importers:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
lucide-react:
|
||||
specifier: ^0.454.0
|
||||
version: 0.454.0(react@18.2.0)
|
||||
specifier: ^0.456.0
|
||||
version: 0.456.0(react@18.2.0)
|
||||
mime:
|
||||
specifier: ^4.0.4
|
||||
version: 4.0.4
|
||||
@@ -420,20 +420,20 @@ importers:
|
||||
specifier: ^6.2.0
|
||||
version: 6.2.0
|
||||
penx-theme-card:
|
||||
specifier: ^0.0.3
|
||||
version: 0.0.3
|
||||
specifier: ^0.0.4
|
||||
version: 0.0.4
|
||||
penx-theme-garden:
|
||||
specifier: ^0.0.3
|
||||
version: 0.0.3
|
||||
specifier: ^0.0.4
|
||||
version: 0.0.4
|
||||
penx-theme-micro:
|
||||
specifier: ^0.0.3
|
||||
version: 0.0.3
|
||||
specifier: ^0.0.4
|
||||
version: 0.0.4
|
||||
penx-theme-minimal:
|
||||
specifier: ^0.0.3
|
||||
version: 0.0.3
|
||||
specifier: ^0.0.4
|
||||
version: 0.0.4
|
||||
penx-theme-photo:
|
||||
specifier: ^0.0.3
|
||||
version: 0.0.3
|
||||
specifier: ^0.0.4
|
||||
version: 0.0.4
|
||||
prisma-extension-pagination:
|
||||
specifier: ^0.7.4
|
||||
version: 0.7.4(@prisma/client@5.21.1(prisma@5.21.1))
|
||||
@@ -2234,11 +2234,11 @@ packages:
|
||||
resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
||||
'@penxio/types@0.0.3':
|
||||
resolution: {integrity: sha512-utn5+iu8mnXVWk3XA3GlBY1e+knU9WF2PMIv+hbwvQgO3mI+ExogJ2rZV6OXgkxxRDzSwyL2Vib/WBNos5+AUw==}
|
||||
'@penxio/types@0.0.4':
|
||||
resolution: {integrity: sha512-E+T58oPqDmiMt4G7ivnt1ngWzeGhgOF87OD06QVQgz7B28hMcJChDRzvF01LkejUiVViBm8CfnvN5zroehmwtg==}
|
||||
|
||||
'@penxio/utils@0.0.3':
|
||||
resolution: {integrity: sha512-pMrg6omLLk5rifQjkSJuCraiTd8TGDTL2W1y08GhPYQ0EB68dtTXm/d3KIvQmpoclSYZ7cWKUgkDUL+Onr+APg==}
|
||||
'@penxio/utils@0.0.4':
|
||||
resolution: {integrity: sha512-qD33j/si8KMFDeUaw4OURKi6wQcoX0uKKPaRqlWF+UOe8zoNyWiUXZRPHMhgcuHk1dlXas0jRXmr/pt5aTVeOA==}
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
@@ -6605,8 +6605,8 @@ packages:
|
||||
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
lucide-react@0.454.0:
|
||||
resolution: {integrity: sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ==}
|
||||
lucide-react@0.456.0:
|
||||
resolution: {integrity: sha512-DIIGJqTT5X05sbAsQ+OhA8OtJYyD4NsEMCA/HQW/Y6ToPQ7gwbtujIoeAaup4HpHzV35SQOarKAWH8LYglB6eA==}
|
||||
peerDependencies:
|
||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc
|
||||
|
||||
@@ -7417,20 +7417,20 @@ packages:
|
||||
pathe@1.1.2:
|
||||
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
|
||||
|
||||
penx-theme-card@0.0.3:
|
||||
resolution: {integrity: sha512-UCua5ivXEudqAX0B9UZTlgXGDv1XkWByuNV27LkR6QQECzVR/aqRrk0CQEicKvRDq8uzknZojhMtklv/fPsXxA==}
|
||||
penx-theme-card@0.0.4:
|
||||
resolution: {integrity: sha512-MOHrV0oZlNC5YJBhK7ocrldLfpDmiFEJkQ5zNyPb14pgwPt4YaxDsmyhuVElvP1BK7owYPHh0E2MkTvWmGAwBA==}
|
||||
|
||||
penx-theme-garden@0.0.3:
|
||||
resolution: {integrity: sha512-G/ouvhuoHRzUoULKBqKeHfy+ChfHMJlwzewdpyCbXairX1vEdeccCue7fdbbnUG+uiKpmc4nI6KRG/OmOdJT6g==}
|
||||
penx-theme-garden@0.0.4:
|
||||
resolution: {integrity: sha512-pUIoOZiIzrCb0iE5QUy6968piJHpfRcLr/UvT4QvHc7tFqNkfLaZO5ZwzMtskhT0i73oQFPn7VcRF0iCGkOjIg==}
|
||||
|
||||
penx-theme-micro@0.0.3:
|
||||
resolution: {integrity: sha512-pVAUdkajMNh1jyhfr5Y3BdV5iKU1e7l6OiuCG5oWyY2oGyRpdLfkLoCca0kfsPJoh1oAjCP1Xm6YiXEYE/Jr5w==}
|
||||
penx-theme-micro@0.0.4:
|
||||
resolution: {integrity: sha512-HFGc6f0dumWcNIMPDGZWJWmZGfSz7BhYd7FgZm0LUui+1j0P+/w2w0VR0WBH0iEmP9+7bhnVgYTwDeGaZvhyKg==}
|
||||
|
||||
penx-theme-minimal@0.0.3:
|
||||
resolution: {integrity: sha512-JXVd8aeAtOpQcrlFQ5sKQ9L191BxTZUF4kR1wIVSfUEvVJkeGkxFG2uZ8y5WG6fk1sm/Pv28juFnG4Gz0hqN1Q==}
|
||||
penx-theme-minimal@0.0.4:
|
||||
resolution: {integrity: sha512-6D6GYUN8Vdnll7iSuCKozRlOJWghCE5wCzuhJuh50GvPD9xVOxRzYUAqGjpH/FLdkFdUqlC2z0Vm1xWMGSWWOg==}
|
||||
|
||||
penx-theme-photo@0.0.3:
|
||||
resolution: {integrity: sha512-yiQTxS5idyxhwzeR2EylGISULM6MQjPzE4X5IDZCRIRAg9N200TaD75d42htEbokM/ck32zoyOAv27y+/NZRJw==}
|
||||
penx-theme-photo@0.0.4:
|
||||
resolution: {integrity: sha512-Cvh5vtFPRmQsM0IfpU5LhQ3nA0MixEiFwyXPFdNxvjH3pmhwla0connGtICfAZE/1QURKp+KyJwuRShazRNaxw==}
|
||||
|
||||
performance-now@2.1.0:
|
||||
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
|
||||
@@ -11489,9 +11489,9 @@ snapshots:
|
||||
'@parcel/watcher-win32-ia32': 2.4.1
|
||||
'@parcel/watcher-win32-x64': 2.4.1
|
||||
|
||||
'@penxio/types@0.0.3': {}
|
||||
'@penxio/types@0.0.4': {}
|
||||
|
||||
'@penxio/utils@0.0.3':
|
||||
'@penxio/utils@0.0.4':
|
||||
dependencies:
|
||||
clsx: 2.1.1
|
||||
tailwind-merge: 2.5.4
|
||||
@@ -16815,7 +16815,7 @@ snapshots:
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
|
||||
lucide-react@0.454.0(react@18.2.0):
|
||||
lucide-react@0.456.0(react@18.2.0):
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
|
||||
@@ -17994,42 +17994,42 @@ snapshots:
|
||||
|
||||
pathe@1.1.2: {}
|
||||
|
||||
penx-theme-card@0.0.3:
|
||||
penx-theme-card@0.0.4:
|
||||
dependencies:
|
||||
'@penxio/types': 0.0.3
|
||||
'@penxio/utils': 0.0.3
|
||||
'@penxio/types': 0.0.4
|
||||
'@penxio/utils': 0.0.4
|
||||
clsx: 2.1.1
|
||||
github-slugger: 2.0.0
|
||||
tailwind-merge: 2.5.4
|
||||
|
||||
penx-theme-garden@0.0.3:
|
||||
penx-theme-garden@0.0.4:
|
||||
dependencies:
|
||||
'@penxio/types': 0.0.3
|
||||
'@penxio/utils': 0.0.3
|
||||
'@penxio/types': 0.0.4
|
||||
'@penxio/utils': 0.0.4
|
||||
clsx: 2.1.1
|
||||
github-slugger: 2.0.0
|
||||
tailwind-merge: 2.5.4
|
||||
|
||||
penx-theme-micro@0.0.3:
|
||||
penx-theme-micro@0.0.4:
|
||||
dependencies:
|
||||
'@penxio/types': 0.0.3
|
||||
'@penxio/utils': 0.0.3
|
||||
'@penxio/types': 0.0.4
|
||||
'@penxio/utils': 0.0.4
|
||||
clsx: 2.1.1
|
||||
github-slugger: 2.0.0
|
||||
tailwind-merge: 2.5.4
|
||||
|
||||
penx-theme-minimal@0.0.3:
|
||||
penx-theme-minimal@0.0.4:
|
||||
dependencies:
|
||||
'@penxio/types': 0.0.3
|
||||
'@penxio/utils': 0.0.3
|
||||
'@penxio/types': 0.0.4
|
||||
'@penxio/utils': 0.0.4
|
||||
clsx: 2.1.1
|
||||
github-slugger: 2.0.0
|
||||
tailwind-merge: 2.5.4
|
||||
|
||||
penx-theme-photo@0.0.3:
|
||||
penx-theme-photo@0.0.4:
|
||||
dependencies:
|
||||
'@penxio/types': 0.0.3
|
||||
'@penxio/utils': 0.0.3
|
||||
'@penxio/types': 0.0.4
|
||||
'@penxio/utils': 0.0.4
|
||||
clsx: 2.1.1
|
||||
github-slugger: 2.0.0
|
||||
tailwind-merge: 2.5.4
|
||||
|
||||
@@ -178,7 +178,7 @@ model Comment {
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String @db.Uuid
|
||||
|
||||
@@unique([userId, postId])
|
||||
@@index([userId, postId])
|
||||
@@index([postId])
|
||||
@@index([userId])
|
||||
@@map("comment")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const { PrismaClient } = require('@prisma/client')
|
||||
const prisma = new PrismaClient()
|
||||
const crypto = require('crypto');
|
||||
|
||||
function genSecret(size = 32) {
|
||||
const bytes = crypto.getRandomValues(new Uint8Array(size))
|
||||
|
||||
Reference in New Issue
Block a user