@le7el/rewards_engine
Version:
Smart contracts that distribute reward tokens according to conditional oracle or a merkle root
175 lines (146 loc) • 6.09 kB
text/typescript
import BalanceTree from './balance-tree'
import { BigNumber, ethers } from 'ethers'
import { getWeb3Provider, ERC721Holder, ConditionalDistributor, Le7elEvents } from './lib'
const Buffer = require('buffer/').Buffer
declare global {
interface Window {
Le7elEvents: any;
ethereum: ethers.providers.ExternalProvider | ethers.providers.JsonRpcFetchFunc | undefined;
}
}
let balance : BalanceTree | null
balance = null
function parseProof(str : string) {
return Buffer.from(str.slice('0x'.length), 'hex')
}
window.Le7elEvents = Le7elEvents
document.getElementById('js-distributions')?.addEventListener('submit', (event) => {
event.preventDefault()
const input = document.getElementById('js-json_distributions') as HTMLInputElement | null
const json_distributions = input?.value
if (!json_distributions || json_distributions.length < 1) return
const data = JSON.parse(json_distributions)
balance = new BalanceTree(data)
const root = document.getElementById('js-merkle_root') as HTMLInputElement | null
if (root) root.value = balance.getHexRoot()
const verify = document.getElementById('js-root-verify') as HTMLInputElement | null
if (verify) verify.value = balance.getHexRoot()
const proofBlock = document.getElementById('js-proofs') as HTMLElement | null
if (proofBlock) proofBlock.style.display = 'block'
return false
})
document.getElementById('js-proofs')?.addEventListener('submit', (event) => {
event.preventDefault()
if (!balance) return
if (!event.target) return
const formData = new FormData(event.target as HTMLFormElement)
const index = BigNumber.from(formData.get("index"))
const account = formData.get("account")?.toString()
const amount = BigNumber.from(formData.get("amount"))
if (!account) return
const proof = JSON.stringify(balance.getProof(index, account, amount))
const proofInput = document.getElementById('js-proof') as HTMLInputElement | null
if (proofInput) proofInput.value = proof
const verify = document.getElementById('js-proof-verify') as HTMLInputElement | null
if (verify) verify.value = proof
return false
})
document.getElementById('js-proof-verification')?.addEventListener('submit', (event) => {
event.preventDefault()
if (!balance) return
if (!event.target) return
const verificationResult = document.getElementById('js-verification') as HTMLElement | null
if (!verificationResult) return
verificationResult.innerHTML = 'verifing...'
const formData = new FormData(event.target as HTMLFormElement)
const index = BigNumber.from(formData.get("index"))
const account = formData.get("account")?.toString()
const amount = BigNumber.from(formData.get("amount"))
const root = formData.get("root")?.toString()
const claimProof = formData.get("proof")?.toString()
if (!account || !root || !claimProof) return
const claimProofs = JSON.parse(claimProof).map((v : string) => parseProof(v))
const result = BalanceTree.verifyProof(index, account, amount, claimProofs, parseProof(root))
if (result) {
verificationResult.innerHTML = 'VALID PROOF'
} else {
verificationResult.innerHTML = 'INVALID PROOF'
}
return false
})
document.getElementById('js-conditional-proof')?.addEventListener('submit', (event) => {
event.preventDefault()
if (!event.target) return
const formData = new FormData(event.target as HTMLFormElement)
const account = formData.get("account")?.toString()
const id = BigNumber.from(formData.get("id"))
const token = formData.get("token")?.toString()
const tokenId = BigNumber.from(formData.get("token_id"))
const claimInterface = formData.get("claim_interface")?.toString()
if (!id || !token || !tokenId || !claimInterface) return
const claimResult = document.getElementById('js-conditional-claim-progress') as HTMLElement | null
if (event.submitter?.getAttribute('name') === 'check_reward') {
const claim = formData.get("claim")?.toString()
if (!account || !claim) return
if (!claimResult) return
claimResult.innerHTML = 'checking reward...'
Promise.all([ERC721Holder.getReward(id), ERC721Holder.hasClaim(account, claim)])
.then(([reward, valid]) => {
if (!valid) {
claimResult.innerHTML = 'invalid claim'
} else if (reward.eq(BigNumber.from(0))) {
claimResult.innerHTML = 'no reward'
} else {
claimResult.innerHTML = reward.toString()
}
})
.catch((error) => {
console.log(error)
claimResult.innerHTML = error.reason
})
}
if (event.submitter?.getAttribute('name') === 'execute_claim') {
const claim = formData.get("claim")?.toString()
if (!account || !claim) return
if (!claimResult) return
claimResult.innerHTML = 'claiming reward...'
getWeb3Provider()
.then((provider) => {
if (!(provider instanceof ethers.providers.Web3Provider)) return
return provider.send("eth_requestAccounts", [])
.then(() => {
ConditionalDistributor.claim(
account,
ERC721Holder.deployedAddress(4) || "",
claimInterface,
token,
tokenId,
claim
)
.then((tr) => provider.waitForTransaction(tr.hash))
.then(() => {
claimResult.innerHTML = 'reward claimed!'
})
.catch((error) => {
console.log(error)
claimResult.innerHTML = error.reason
})
})
})
}
if (event.submitter?.getAttribute('name') === 'generate_claim') {
if (!claimResult) return
claimResult.innerHTML = 'generating...'
ERC721Holder.prepareClaim(claimInterface, token, tokenId, id)
.then((claim) => {
const proofInput = document.getElementById('js-conditional-claim') as HTMLInputElement | null
if (proofInput) proofInput.value = claim
claimResult.innerHTML = 'ready'
})
.catch((error) => {
console.log(error)
claimResult.innerHTML = error.reason
})
}
return false
})