Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge testnet > mainnet #266

Merged
merged 52 commits into from
Oct 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
9890e70
Amount validity check update
MightOfOaks Jun 20, 2022
88174cd
Merge pull request #218 from MightOfOaks/airdrop-csv-amount-validity-…
findolor Jun 20, 2022
0221c13
Airdrop fund and register subtitle fix (#219)
MightOfOaks Jun 21, 2022
6e63e76
Native token airdrop support (#220)
findolor Jun 24, 2022
7a54362
Sync development to testnet (#221)
findolor Jun 24, 2022
ac31572
Manage (burn or withdraw) remaining funds for an expired airdrop (#223)
MightOfOaks Jun 28, 2022
c94efb3
Feature: Terra airdrop support (#224)
findolor Jul 4, 2022
f370b81
Merge branch 'testnet' into development
findolor Jul 4, 2022
8e569e8
Revert "Merge branch 'testnet' into development"
findolor Jul 4, 2022
121b205
Remove txSigner from claim method in airdrop helpers
findolor Jul 4, 2022
5ba6a4c
Merge development to testnet (#226)
findolor Jul 4, 2022
4ac75c9
Get correct token balance based on token type (#233)
findolor Aug 19, 2022
73673c3
Custom decimal on denom conversion (#234)
findolor Aug 19, 2022
9104bdb
Change contract parameter to be recipient for cw20 execute send (#232)
findolor Aug 19, 2022
9a906ef
Sync development to testnet (#235)
findolor Aug 19, 2022
075fd62
Move airdrop acc limit to env file and remove duplicate check (#237)
findolor Aug 19, 2022
a458206
Merge development (#238)
findolor Aug 19, 2022
21b3dd2
Terra ledger support for airdrops (#241)
findolor Aug 22, 2022
18985fd
Remove unused depencencies
findolor Aug 22, 2022
bba03bc
Merge branch 'development' into merge-development
findolor Aug 22, 2022
24d98d8
Merge pull request #242 from CosmosContracts/merge-development
findolor Aug 22, 2022
b7e805a
Add wallet check on contract upload
findolor Aug 25, 2022
66f425e
Merge pull request #246 from CosmosContracts/upload-contract
findolor Aug 25, 2022
6e6e0b3
Add wallet check on contract upload (#247)
findolor Aug 26, 2022
13458fe
Compatibility for Loop airdrop (#250)
MightOfOaks Aug 30, 2022
df925ee
Fix airdrop contract claim message (#251)
findolor Aug 30, 2022
a409efa
Change code owners
findolor Sep 5, 2022
fc7afb8
Update testnet chain id (#259)
Sep 24, 2022
1bba8a0
Fix keplr wallet connection issue & update testnet chainId (#260)
MightOfOaks Sep 27, 2022
baa2a10
Merge branch 'testnet' into development
findolor Sep 27, 2022
a49d189
Merge development > testnet (#261)
MightOfOaks Sep 27, 2022
4712776
Query airdrop pause status on manage page
MightOfOaks Oct 16, 2022
7ca33c6
Add pause and resume buttons
MightOfOaks Oct 17, 2022
f1745b0
Check isAdmin for airdrops on AirdropsTable
MightOfOaks Oct 18, 2022
2b8d044
Add manage button for airdrops on AirdropsTable
MightOfOaks Oct 18, 2022
a98ce5b
Update manage page for airdrops
MightOfOaks Oct 19, 2022
117640d
Airdrop manage UI update
MightOfOaks Oct 19, 2022
0c6d2c6
Show pause status on airdrops table & modify expiration update logic
MightOfOaks Oct 19, 2022
1fb4a9d
Error message update for pause()
MightOfOaks Oct 20, 2022
c464224
Error message update for pause() - 2
MightOfOaks Oct 20, 2022
fc25327
Error message update for pause() - 3
MightOfOaks Oct 20, 2022
2538d4f
Merge pull request #263 from deus-labs/pause-airdrop
MightOfOaks Oct 21, 2022
613a6bd
Merge pull request #265 from CosmosContracts/testnet
MightOfOaks Oct 21, 2022
3dd0d7d
Merge pull request #264 from CosmosContracts/development
MightOfOaks Oct 21, 2022
209e7be
Address merge conflicts
MightOfOaks Oct 21, 2022
049e07c
Merge pull request #267 from CosmosContracts/address-merge-conflicts
MightOfOaks Oct 21, 2022
914431c
Remove legacy claim signature logic
MightOfOaks Oct 22, 2022
bdaac65
Remove fetch airdrop pause status error message
MightOfOaks Oct 22, 2022
bbe2694
Update migration error message on pause()
MightOfOaks Oct 22, 2022
0b03515
Merge pull request #268 from CosmosContracts/remove-legacy-claim-sign…
MightOfOaks Oct 22, 2022
db8c17b
Merge pull request #270 from CosmosContracts/testnet
MightOfOaks Oct 22, 2022
59758a9
Merge pull request #269 from CosmosContracts/development
MightOfOaks Oct 22, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
* @orkunkl @MightOfOaks

60 changes: 58 additions & 2 deletions components/AirdropsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import { AnchorButton } from 'components/AnchorButton'
import { Tooltip } from 'components/Tooltip'
import { useWallet } from 'contexts/wallet'
import type { ComponentProps } from 'react'
import { FaCopy } from 'react-icons/fa'
import { useEffect, useState } from 'react'
import { FaCopy, FaWrench } from 'react-icons/fa'
import { getAirdropDate } from 'utils/airdrop'
import { copy } from 'utils/clipboard'
import { truncateMiddle } from 'utils/text'

import { useContracts } from '../contexts/contracts'

export interface AirdropData {
name: string
contractAddress: string
Expand All @@ -29,6 +32,51 @@ export interface AirdropsTableProps extends ComponentProps<'table'> {
export const AirdropsTable = (props: AirdropsTableProps) => {
const { data, className, ...rest } = props
const wallet = useWallet()
const merkleAirdropContract = useContracts().cw20MerkleAirdrop
const [isOwner, setIsOwner] = useState<boolean[]>([])
const [isPaused, setIsPaused] = useState<boolean[]>([])
const getAirdropOwner = async (contractAddress: string) => {
const airdropConfig = await merkleAirdropContract?.use(contractAddress)?.getConfig()
return airdropConfig?.owner
}
const getAirdropPauseStatus = async (contractAddress: string) => {
const airdropPauseStatus = await merkleAirdropContract?.use(contractAddress)?.isPaused(1)
return airdropPauseStatus
}

useEffect(() => {
const tempArray: boolean[] = []
setIsOwner([])
data.map(async (airdrop, index) => {
await getAirdropOwner(airdrop.contractAddress)
.then((owner) => {
tempArray[index] = owner === wallet.address
})
.catch(() => {
tempArray[index] = false
})
})
setTimeout(() => {
setIsOwner(tempArray)
}, 500)
}, [data, wallet.address])

useEffect(() => {
const tempArray: boolean[] = []
setIsPaused([])
data.map(async (airdrop, index) => {
await getAirdropPauseStatus(airdrop.contractAddress)
.then((pauseStatus) => {
tempArray[index] = pauseStatus || false
})
.catch(() => {
tempArray[index] = false
})
})
setTimeout(() => {
setIsPaused(tempArray)
}, 500)
}, [data, wallet.address])

return (
<table className={clsx('min-w-full', className)} {...rest}>
Expand Down Expand Up @@ -76,7 +124,9 @@ export const AirdropsTable = (props: AirdropsTableProps) => {
<td className="p-4 text-right">{airdrop.claimed.toLocaleString('en')}</td>
<td className="p-4 text-right">{airdrop.allocation ? airdrop.allocation.toLocaleString('en') : '-'}</td>
<td className="p-4">{getAirdropDate(airdrop.start, airdrop.startType)}</td>
<td className="p-4">{getAirdropDate(airdrop.expiration, airdrop.expirationType)}</td>
<td className="p-4">
{isPaused[i] ? 'Paused' : getAirdropDate(airdrop.expiration, airdrop.expirationType)}
</td>
<td className="p-4">
<div className="flex">
<AnchorButton
Expand All @@ -88,6 +138,12 @@ export const AirdropsTable = (props: AirdropsTableProps) => {
>
CLAIM
</AnchorButton>
<AnchorButton
className={clsx('ml-2 border-none', { invisible: !isOwner[i] })}
href={`/airdrops/manage/?contractAddress=${airdrop.contractAddress}`}
leftIcon={<FaWrench className="ml-2" />}
variant="outline"
/>
</div>
</td>
</tr>
Expand Down
5 changes: 0 additions & 5 deletions config/keplr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ export const keplrConfig = (config: AppConfig): ChainInfo => ({
coinMinimalDenom: config.feeToken,
coinDecimals: config.coinMap[config.feeToken].fractionalDigits,
},
{
coinDenom: config.coinMap[config.stakingToken].denom,
coinMinimalDenom: config.stakingToken,
coinDecimals: config.coinMap[config.stakingToken].fractionalDigits,
},
],
feeCurrencies: [
{
Expand Down
2 changes: 1 addition & 1 deletion config/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const mainnetConfig: AppConfig = {
}

export const uniTestnetConfig: AppConfig = {
chainId: 'uni-3',
chainId: 'uni-5',
chainName: 'Uni',
addressPrefix: 'juno',
rpcUrl: 'https://rpc.uni.juno.deuslabs.fi',
Expand Down
81 changes: 81 additions & 0 deletions contracts/cw20/merkleAirdrop/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export interface CW20MerkleAirdropInstance {
getLatestStage: () => Promise<number>
isClaimed: (address: string, stage: number) => Promise<boolean>
totalClaimed: (stage: number) => Promise<string>
isPaused: (stage: number) => Promise<boolean>

// Execute
updateConfig: (txSigner: string, newOwner: string) => Promise<string>
Expand All @@ -67,6 +68,8 @@ export interface CW20MerkleAirdropInstance {
claim: (stage: number, amount: string, proof: string[], signedMessage?: SignedMessage) => Promise<string>
burn: (stage: number) => Promise<string>
withdraw: (stage: number, address: string) => Promise<string>
pause: (stage: number) => Promise<string>
resume: (stage: number, newExpiration?: Expiration) => Promise<string>
registerAndReleaseEscrow: (
merkleRoot: string,
start: Expiration,
Expand Down Expand Up @@ -101,6 +104,8 @@ export interface CW20MerkleAirdropMessages {
fundWithSend: (recipient: string, amount: string) => FundWithSendMessage
burn: (airdropAddress: string, stage: number) => BurnMessage
withdraw: (airdropAddress: string, stage: number, address: string) => WithdrawMessage
pause: (airdropAddress: string, stage: number) => PauseMessage
resume: (airdropAddress: string, stage: number, new_expiration?: Expiration) => ResumeMessage
}

export interface InstantiateMessage {
Expand Down Expand Up @@ -193,6 +198,28 @@ export interface WithdrawMessage {
funds: Coin[]
}

export interface PauseMessage {
sender: string
contract: string
msg: {
pause: {
stage: number
}
}
funds: Coin[]
}
export interface ResumeMessage {
sender: string
contract: string
msg: {
resume: {
stage: number
new_expiration?: Expiration
}
}
funds: Coin[]
}

export interface CW20MerkleAirdropContract {
instantiate: (
senderAddress: string,
Expand Down Expand Up @@ -237,6 +264,13 @@ export const CW20MerkleAirdrop = (client: SigningCosmWasmClient, txSigner: strin
return data.is_claimed
}

const isPaused = async (stage: number): Promise<boolean> => {
const data = await client.queryContractSmart(contractAddress, {
is_paused: { stage },
})
return data.is_paused
}

const totalClaimed = async (stage: number): Promise<string> => {
const data = await client.queryContractSmart(contractAddress, {
total_claimed: { stage },
Expand Down Expand Up @@ -302,6 +336,21 @@ export const CW20MerkleAirdrop = (client: SigningCosmWasmClient, txSigner: strin
return result.transactionHash
}

const pause = async (stage: number): Promise<string> => {
const result = await client.execute(txSigner, contractAddress, { pause: { stage } }, fee)
return result.transactionHash
}

const resume = async (stage: number, newExpiration?: Expiration): Promise<string> => {
const result = await client.execute(
txSigner,
contractAddress,
{ resume: { stage, new_expiration: newExpiration } },
fee,
)
return result.transactionHash
}

const registerAndReleaseEscrow = async (
merkleRoot: string,
start: Expiration,
Expand Down Expand Up @@ -444,12 +493,15 @@ export const CW20MerkleAirdrop = (client: SigningCosmWasmClient, txSigner: strin
getMerkleRoot,
getLatestStage,
isClaimed,
isPaused,
totalClaimed,
updateConfig,
registerMerkleRoot,
claim,
burn,
withdraw,
pause,
resume,
registerAndReleaseEscrow,
depositEscrow,
fundWithSend,
Expand Down Expand Up @@ -593,6 +645,33 @@ export const CW20MerkleAirdrop = (client: SigningCosmWasmClient, txSigner: strin
}
}

const pause = (airdropAddress: string, stage: number): PauseMessage => {
return {
sender: txSigner,
contract: airdropAddress,
msg: {
pause: {
stage,
},
},
funds: [],
}
}

const resume = (airdropAddress: string, stage: number, newExpiration?: Expiration): ResumeMessage => {
return {
sender: txSigner,
contract: airdropAddress,
msg: {
resume: {
stage,
new_expiration: newExpiration,
},
},
funds: [],
}
}

return {
instantiate,
registerAndReleaseEscrow,
Expand All @@ -601,6 +680,8 @@ export const CW20MerkleAirdrop = (client: SigningCosmWasmClient, txSigner: strin
fundWithSend,
burn,
withdraw,
pause,
resume,
}
}

Expand Down
57 changes: 9 additions & 48 deletions pages/airdrops/[address]/claim.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { CreateTxOptions, Msg, SignDoc } from '@terra-money/terra.js'
import { LCDClient, MsgSend } from '@terra-money/terra.js'
import { prepareSignBytes } from '@terra-money/terra.js/dist/util/json'
import type { SignBytesResult, SignResult } from '@terra-money/wallet-provider'
import type { SignResult } from '@terra-money/wallet-provider'
import {
ConnectType,
useConnectedWallet,
Expand Down Expand Up @@ -94,36 +94,10 @@ const ClaimAirdropPage: NextPage = () => {
}, [wallets[0]?.terraAddress])

useEffect(() => {
if (contractAddress === 'juno143rmxg4khjkxzk56pd3tru6wapenwls20y3shahlc5p9zgddyk8q27n0k4')
setSignedMessage({ claim_msg: { addr: wallet.address }, signature })
else setSignedMessage({ claim_msg: claimMsg, signature })
setSignedMessage({ claim_msg: claimMsg, signature })
}, [signature, claimMsg])

// TODO: Think about moving this to a service
const legacySignTerraClaimSignature = async (): Promise<string> => {
return new Promise((resolve, reject) => {
if (!connectedWallet) {
toast.error('Terra Station Wallet not connected!')
return
}

const junoAddressMsgByteArray = Buffer.from(JSON.stringify({ addr: wallet.address }))

connectedWallet
.signBytes(junoAddressMsgByteArray)
.then((nextSignBytesResult: SignBytesResult) => {
const signedJunoAddress = Buffer.from(nextSignBytesResult.result.signature).toString('base64')
const publickey = nextSignBytesResult.result.public_key?.toAmino().value
const sig = Buffer.from(JSON.stringify({ pub_key: publickey, signature: signedJunoAddress })).toString(
'base64',
)
setSignature(sig)
resolve(sig)
})
.catch(reject)
})
}

const signTerraClaimSignature = async (): Promise<Record<string, string>> => {
return new Promise((resolve, reject) => {
if (!connectedWallet) {
Expand Down Expand Up @@ -201,9 +175,7 @@ const ClaimAirdropPage: NextPage = () => {
setIsTerraAirdrop(airdrop.isTerraAirdrop)

if (airdrop.isTerraAirdrop) {
if (contractAddress === 'juno143rmxg4khjkxzk56pd3tru6wapenwls20y3shahlc5p9zgddyk8q27n0k4')
setSignedMessage({ claim_msg: { addr: wallet.address }, signature })
else setSignedMessage({ claim_msg: '', signature })
setSignedMessage({ claim_msg: '', signature })
}

if (isClaimed) setAirdropState('claimed')
Expand Down Expand Up @@ -269,21 +241,12 @@ const ClaimAirdropPage: NextPage = () => {

let signedMsg
if (isTerraAirdrop) {
if (contractAddress === 'juno143rmxg4khjkxzk56pd3tru6wapenwls20y3shahlc5p9zgddyk8q27n0k4') {
const data = await legacySignTerraClaimSignature()
signedMsg = {
claim_msg: { addr: wallet.address },
signature: data,
}
setSignedMessage(signedMessage)
} else {
const data = (await signTerraClaimSignature()) as { sig: string; claimMsg: string }
signedMsg = {
claim_msg: data.claimMsg,
signature: data.sig,
}
setSignedMessage(signedMessage)
const data = (await signTerraClaimSignature()) as { sig: string; claimMsg: string }
signedMsg = {
claim_msg: data.claimMsg,
signature: data.sig,
}
setSignedMessage(signedMessage)
}

await contractMessages?.claim(stage, amount, proofs, signedMsg)
Expand Down Expand Up @@ -384,9 +347,7 @@ const ClaimAirdropPage: NextPage = () => {
<JsonPreview content={transactionMessage} copyable isVisible={false} title="Show Transaction Message" />
</Conditional>

<Conditional
test={isTerraAirdrop && contractAddress !== 'juno143rmxg4khjkxzk56pd3tru6wapenwls20y3shahlc5p9zgddyk8q27n0k4'}
>
<Conditional test={isTerraAirdrop}>
<Alert type="warning">
A send message of 0,000001 LUNA will be signed for making sure the terra wallet signature is valid on the
airdrop contract.
Expand Down
Loading