diff --git a/airdrops/app/campaigns/[campaign]/page.tsx b/airdrops/app/campaigns/[campaign]/page.tsx
index fbac828783e..b39283350a4 100644
--- a/airdrops/app/campaigns/[campaign]/page.tsx
+++ b/airdrops/app/campaigns/[campaign]/page.tsx
@@ -22,15 +22,15 @@ export async function generateMetadata({
}
return {
- title: `${campaign.title} | Airdrops`,
+ title: `${campaign.name} | Airdrops`,
description: campaign.description,
openGraph: {
- title: `${campaign.title} | Airdrops`,
+ title: `${campaign.name} | Airdrops`,
description: campaign.description,
},
twitter: {
card: 'summary',
- title: `${campaign.title} | Airdrops`,
+ title: `${campaign.name} | Airdrops`,
description: campaign.description,
},
}
diff --git a/airdrops/components/CampaignCard.tsx b/airdrops/components/CampaignCard.tsx
index 5f9a2d47b5c..bcb643f6823 100644
--- a/airdrops/components/CampaignCard.tsx
+++ b/airdrops/components/CampaignCard.tsx
@@ -8,15 +8,15 @@ interface CampaignCardProps {
}
const CampaignCardInternal = ({
- airdrop: { title, description, eligible },
+ airdrop: { name, description, eligible, contractAddress, url },
authenticated,
}: CampaignCardProps) => {
return (
-
{title}
+
{name}
{description}
- {authenticated && (
+ {authenticated && contractAddress && (
<>
>
)}
+ {url && (
+
+ More info
+
+ )}
)
diff --git a/airdrops/components/CampaignDetailContent.tsx b/airdrops/components/CampaignDetailContent.tsx
index 94303de7c43..c2e79755659 100644
--- a/airdrops/components/CampaignDetailContent.tsx
+++ b/airdrops/components/CampaignDetailContent.tsx
@@ -1,4 +1,5 @@
'use client'
+import { StandardMerkleTree } from '@openzeppelin/merkle-tree'
import { ethers } from 'ethers'
import { usePrivy, useWallets } from '@privy-io/react-auth'
import { Container } from './layout/Container'
@@ -9,6 +10,9 @@ import { BsArrowLeft as ArrowBackIcon } from 'react-icons/bs'
import { ConnectButton } from './auth/ConnectButton'
import { isEligible } from '../src/utils/eligibility'
import { AirdropData } from './Campaigns'
+import ReactMarkdown from 'react-markdown'
+import { terms } from '../src/utils/terms'
+import { UPAirdrops } from '@unlock-protocol/contracts'
interface CampaignDetailContentProps {
airdrop: AirdropData
@@ -16,6 +20,25 @@ interface CampaignDetailContentProps {
const timestamp = new Date().getTime()
+const getContract = async (address: string, network: number) => {
+ const provider = new ethers.JsonRpcProvider(
+ `https://rpc.unlock-protocol.com/${network}`
+ )
+ return new ethers.Contract(address, UPAirdrops.abi, provider)
+}
+
+const getProof = async (address: string, airdrop: AirdropData) => {
+ const request = await fetch(airdrop.recipientsFile)
+ const tree = StandardMerkleTree.load(await request.json())
+ for (const [i, leaf] of tree.entries()) {
+ if (leaf[0].toLowerCase() === address.toLowerCase()) {
+ const proof = tree.getProof(i)
+ return { leaf, proof }
+ }
+ }
+ return { leaf: null, proof: null }
+}
+
export default function CampaignDetailContent({
airdrop,
}: CampaignDetailContentProps) {
@@ -25,11 +48,10 @@ export default function CampaignDetailContent({
useEffect(() => {
const run = async () => {
- const amount = await isEligible(
- wallets[0].address,
- airdrop.recipientsFile
- )
- airdrop.eligible = amount || 0
+ if (wallets[0]) {
+ const amount = await isEligible(wallets[0].address, airdrop)
+ airdrop.eligible = amount || 0
+ }
}
run()
}, [authenticated, wallets, airdrop])
@@ -40,13 +62,17 @@ export default function CampaignDetailContent({
const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()
- await wallets[0].switchChain(8453)
+ await wallets[0].switchChain(airdrop.chainId)
+ const contract = await getContract(
+ airdrop.contractAddress,
+ airdrop.chainId
+ )
const domain = {
- name: 'Airdrops', // await airdrops.EIP712Name(),
- version: '1', // await airdrops.EIP712Version(),
- chainId: 8453,
- verifyingContract: '0x4200000000000000000000000000000000000011', // replace me
+ name: await contract.EIP712Name(),
+ version: await contract.EIP712Version(),
+ chainId: airdrop.chainId,
+ verifyingContract: airdrop.contractAddress,
}
const types = {
@@ -59,7 +85,7 @@ export default function CampaignDetailContent({
const value = {
signer: signer.address,
- campaignName: airdrop.title,
+ campaignName: airdrop.name,
timestamp,
}
@@ -70,6 +96,34 @@ export default function CampaignDetailContent({
}
}
+ const onClaim = async () => {
+ const provider = await wallets[0].getEthereumProvider()
+ const ethersProvider = new ethers.BrowserProvider(provider)
+ const signer = await ethersProvider.getSigner()
+
+ const airdropContract = await getContract(
+ airdrop.contractAddress,
+ airdrop.chainId
+ )
+
+ // Get the proof!
+ const { proof } = await getProof(wallets[0].address, airdrop)
+ console.log(proof)
+
+ const tx = await airdropContract
+ .connect(signer)
+ // @ts-expect-error Property 'claim' does not exist on type 'BaseContract'.ts(2339)
+ .claim(
+ airdrop.name,
+ timestamp,
+ wallets[0].address,
+ airdrop.eligible,
+ proof,
+ termsOfServiceSignature
+ )
+ await tx.wait()
+ }
+
return (