@le7el/rewards_engine
Version:
Smart contracts that distribute reward tokens according to conditional oracle or a merkle root
136 lines (121 loc) • 3.96 kB
text/typescript
import contracts from "../contracts"
import oracle from "../../artifacts/contracts/condition_oracles/OneTimeOffchainTickets.sol/OneTimeOffchainTickets.json"
import {initContractByAbi} from "../utils"
import {BigNumber, utils, Wallet} from "ethers"
const ONE_TIME_TICKET_CONTRACT = 'one_time_offchain_tickets'
const abi = () => {
return oracle.abi
}
const bytecode = () => {
return oracle.bytecode
}
const deployedAddress = (network : string | number) => {
if (!contracts[`${network}`]) return null
return contracts[`${network}`][ONE_TIME_TICKET_CONTRACT]
}
const initContract = (contractKey : string, readOnly = true, web3Provider = null) => {
return initContractByAbi(oracle.abi, contractKey, readOnly, web3Provider)
}
const owner = (web3Provider = null, contractKey = ONE_TIME_TICKET_CONTRACT) => {
return initContract(contractKey, true, web3Provider)
.then(contract => contract.owner())
}
const getDomainSeparator = (web3Provider = null, contractKey = ONE_TIME_TICKET_CONTRACT) => {
return initContract(contractKey, true, web3Provider)
.then(contract => contract.getDomainSeparator())
}
const nextNonce = (account : string, web3Provider = null, contractKey = ONE_TIME_TICKET_CONTRACT) => {
return initContract(contractKey, true, web3Provider)
.then(contract => contract.nextNonce(account))
}
const claimedAmount = (account : string, web3Provider = null, contractKey = ONE_TIME_TICKET_CONTRACT) => {
return initContract(contractKey, true, web3Provider)
.then(contract => contract.claimedAmount(account))
}
const isAllowed = (
user : string,
amount : number | BigNumber,
claimedAmount : number | BigNumber,
nonce : number,
callData : string,
web3Provider = null,
contractKey = ONE_TIME_TICKET_CONTRACT
) => {
return initContract(contractKey, true, web3Provider)
.then(contract => contract.isAllowed(user, amount, claimedAmount, nonce, callData))
}
const hasClaim = (account : string, claim : string, web3Provider = null, contractKey = ONE_TIME_TICKET_CONTRACT) => {
return initContract(contractKey, true, web3Provider)
.then(contract => contract.hasClaim(account, claim))
}
const prepareOffchainClaim = (
claimInterface : string,
rewardToken : string,
rewardTokenId : number | BigNumber,
user : string,
amount : number | BigNumber,
claimedAmount : number | BigNumber,
nonce : number,
ticketSignature : string
) => {
const integrityHash = utils.solidityKeccak256(["address", "uint256", "bytes4"], [rewardToken, rewardTokenId, claimInterface])
const ticketData = utils.defaultAbiCoder.encode(
["address", "uint256", "uint256", "uint32", "bytes"],
[user, amount, claimedAmount, nonce, ticketSignature]
)
return utils.defaultAbiCoder.encode(["bytes32", "bytes"], [integrityHash, ticketData])
}
const signTicket = async function(
signer : Wallet,
domainSeparator : string,
user : string,
amount : number | BigNumber,
claimedAmount : number | BigNumber,
nonce : number
) {
const ticketMessage = utils.keccak256(
utils.defaultAbiCoder.encode(
["bytes32", "address", "uint256", "uint256", "uint32"], [
domainSeparator,
user,
amount,
claimedAmount,
nonce
],
),
)
const ticketSignature = await signer.signMessage(utils.arrayify(ticketMessage))
const sig = utils.splitSignature(
utils.arrayify(ticketSignature)
);
const ticketSignatureEncoded = utils.defaultAbiCoder.encode(
["uint8", "bytes32", "bytes32"], [sig.v, sig.r, sig.s],
)
return ticketSignatureEncoded
}
export {
abi,
bytecode,
deployedAddress,
owner,
getDomainSeparator,
nextNonce,
claimedAmount,
isAllowed,
hasClaim,
prepareOffchainClaim,
signTicket
}
export default {
abi,
bytecode,
deployedAddress,
owner,
getDomainSeparator,
nextNonce,
claimedAmount,
isAllowed,
hasClaim,
prepareOffchainClaim,
signTicket
}