mirror of
https://github.com/oceanprotocol/ocean.js.git
synced 2024-11-26 20:39:05 +01:00
add DataFarming contract support (#1596)
* add DataFarming contract support
This commit is contained in:
parent
647096a9af
commit
dd383ec365
106
src/contracts/df/DfRewards.ts
Normal file
106
src/contracts/df/DfRewards.ts
Normal file
@ -0,0 +1,106 @@
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import dfRewardsABI from '@oceanprotocol/contracts/artifacts/contracts/df/DFRewards.sol/DFRewards.json'
|
||||
import { calculateEstimatedGas, sendTx } from '../../utils'
|
||||
import { SmartContractWithAddress } from '../SmartContractWithAddress'
|
||||
import { ReceiptOrEstimate } from '../../@types'
|
||||
|
||||
/**
|
||||
* Provides an interface for DFRewards contract
|
||||
*/
|
||||
export class DfRewards extends SmartContractWithAddress {
|
||||
getDefaultAbi(): AbiItem | AbiItem[] {
|
||||
return dfRewardsABI.abi as AbiItem[]
|
||||
}
|
||||
|
||||
/** Get available DF Rewards for a token
|
||||
* @param {String} userAddress user address
|
||||
* @param {String} tokenAddress token address
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
public async getAvailableRewards(
|
||||
userAddress: string,
|
||||
tokenAddress: string
|
||||
): Promise<string> {
|
||||
const rewards = await this.contract.methods
|
||||
.claimable(userAddress, tokenAddress)
|
||||
.call()
|
||||
const rewardsFormated = await this.unitsToAmount(tokenAddress, rewards)
|
||||
|
||||
return rewardsFormated
|
||||
}
|
||||
|
||||
/**
|
||||
* claim rewards for any address
|
||||
* @param {String} fromUserAddress user that generates the tx
|
||||
* @param {String} userAddress user address to claim
|
||||
* @param {String} tokenAddress token address
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async claimRewards<G extends boolean = false>(
|
||||
fromUserAddress: string,
|
||||
userAddress: string,
|
||||
tokenAddress: string,
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const estGas = await calculateEstimatedGas(
|
||||
fromUserAddress,
|
||||
this.contract.methods.claimFor,
|
||||
userAddress,
|
||||
tokenAddress
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
fromUserAddress,
|
||||
estGas + 1,
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.claimFor,
|
||||
userAddress,
|
||||
tokenAddress
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
|
||||
/**
|
||||
* allocate rewards to address. An approve must exist before calling this function.
|
||||
* @param {String} fromUserAddress user that generates the tx
|
||||
* @param {String[]} userAddresses array of users that will receive rewards
|
||||
* @param {String[]} amounts array of amounts
|
||||
* @param {String} tokenAddress token address
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async allocateRewards<G extends boolean = false>(
|
||||
fromUserAddress: string,
|
||||
userAddresses: string[],
|
||||
amounts: string[],
|
||||
tokenAddress: string,
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
for (let i = 0; i < amounts.length; i++) {
|
||||
amounts[i] = await this.amountToUnits(tokenAddress, amounts[i])
|
||||
}
|
||||
const estGas = await calculateEstimatedGas(
|
||||
fromUserAddress,
|
||||
this.contract.methods.allocate,
|
||||
userAddresses,
|
||||
amounts,
|
||||
tokenAddress
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
fromUserAddress,
|
||||
estGas + 1,
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.allocate,
|
||||
userAddresses,
|
||||
amounts,
|
||||
tokenAddress
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
}
|
67
src/contracts/df/DfStrategyV1.ts
Normal file
67
src/contracts/df/DfStrategyV1.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import dfStrategyV1ABI from '@oceanprotocol/contracts/artifacts/contracts/df/DFStrategyV1.sol/DFStrategyV1.json'
|
||||
import { calculateEstimatedGas, sendTx } from '../../utils'
|
||||
import { SmartContractWithAddress } from '../SmartContractWithAddress'
|
||||
import { ReceiptOrEstimate } from '../../@types'
|
||||
|
||||
/**
|
||||
* Provides an interface for dfStrategyV1 contract
|
||||
*/
|
||||
export class DfStrategyV1 extends SmartContractWithAddress {
|
||||
getDefaultAbi(): AbiItem | AbiItem[] {
|
||||
return dfStrategyV1ABI.abi as AbiItem[]
|
||||
}
|
||||
|
||||
/** Get available DF Rewards for multiple tokens
|
||||
* @param {String} userAddress user address
|
||||
* @param {String} tokenAddresses array of tokens
|
||||
* @return {Promise<string[]>}
|
||||
*/
|
||||
public async getMultipleAvailableRewards(
|
||||
userAddress: string,
|
||||
tokenAddresses: string[]
|
||||
): Promise<string[]> {
|
||||
const rewards = await this.contract.methods
|
||||
.claimables(userAddress, tokenAddresses)
|
||||
.call()
|
||||
const rewardsFormated: string[] = []
|
||||
for (let i = 0; i < rewards.length; i++) {
|
||||
rewardsFormated.push(await this.unitsToAmount(tokenAddresses[i], rewards[i]))
|
||||
}
|
||||
return rewardsFormated
|
||||
}
|
||||
|
||||
/**
|
||||
* claim multiple token rewards for any address
|
||||
* @param {String} fromUserAddress user that generates the tx
|
||||
* @param {String} userAddress user address to claim
|
||||
* @param {String} tokenAddresses array of tokens
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async claimMultipleRewards<G extends boolean = false>(
|
||||
fromUserAddress: string,
|
||||
userAddress: string,
|
||||
tokenAddresses: string[],
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const estGas = await calculateEstimatedGas(
|
||||
fromUserAddress,
|
||||
this.contract.methods.claimMultiple,
|
||||
userAddress,
|
||||
tokenAddresses
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
fromUserAddress,
|
||||
estGas + 1,
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.claimMultiple,
|
||||
userAddress,
|
||||
tokenAddresses
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
}
|
@ -9,3 +9,5 @@ export * from './NFTFactory'
|
||||
export * from './ve/VeOcean'
|
||||
export * from './ve/VeFeeDistributor'
|
||||
export * from './ve/VeAllocate'
|
||||
export * from './df/DfRewards'
|
||||
export * from './df/DfStrategyV1'
|
||||
|
133
test/unit/DFRewards.test.ts
Normal file
133
test/unit/DFRewards.test.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import { assert } from 'chai'
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import { web3, getTestConfig, getAddresses } from '../config'
|
||||
import {
|
||||
Config,
|
||||
approve,
|
||||
DfRewards,
|
||||
DfStrategyV1,
|
||||
sendTx,
|
||||
calculateEstimatedGas
|
||||
} from '../../src'
|
||||
|
||||
describe('veOcean tests', async () => {
|
||||
let config: Config
|
||||
let addresses: any
|
||||
let nftFactory
|
||||
let dfRewards: DfRewards
|
||||
let dfStrategy: DfStrategyV1
|
||||
let ownerAccount: string
|
||||
let Alice: string
|
||||
let Bob: string
|
||||
let nft1, nft2, nft3
|
||||
let tokenContract
|
||||
let chainId
|
||||
|
||||
before(async () => {
|
||||
config = await getTestConfig(web3)
|
||||
})
|
||||
|
||||
it('initialize accounts', async () => {
|
||||
addresses = getAddresses()
|
||||
const accounts = await web3.eth.getAccounts()
|
||||
chainId = await web3.eth.getChainId()
|
||||
ownerAccount = accounts[0]
|
||||
Alice = accounts[1]
|
||||
Bob = accounts[2]
|
||||
const minAbi = [
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{ name: 'to', type: 'address' },
|
||||
{ name: 'value', type: 'uint256' }
|
||||
],
|
||||
name: 'mint',
|
||||
outputs: [{ name: '', type: 'bool' }],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [{ name: 'owner', type: 'address' }],
|
||||
name: 'balanceOf',
|
||||
outputs: [{ name: '', type: 'uint256' }],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
}
|
||||
] as AbiItem[]
|
||||
tokenContract = new web3.eth.Contract(minAbi, addresses.Ocean)
|
||||
const estGas = await calculateEstimatedGas(
|
||||
ownerAccount,
|
||||
tokenContract.methods.mint,
|
||||
ownerAccount,
|
||||
web3.utils.toWei('10000')
|
||||
)
|
||||
// mint some Oceans
|
||||
await sendTx(
|
||||
ownerAccount,
|
||||
estGas,
|
||||
web3,
|
||||
1,
|
||||
tokenContract.methods.mint,
|
||||
ownerAccount,
|
||||
web3.utils.toWei('1000')
|
||||
)
|
||||
dfRewards = new DfRewards(addresses.DFRewards, web3)
|
||||
dfStrategy = new DfStrategyV1(addresses.DFStrategyV1, web3)
|
||||
})
|
||||
|
||||
it('Generous owner should allocate some DF Rewards', async () => {
|
||||
const dfOceanBalance = web3.utils.fromWei(
|
||||
await tokenContract.methods.balanceOf(addresses.DFRewards).call()
|
||||
)
|
||||
// approve 500 tokens
|
||||
await approve(web3, config, ownerAccount, addresses.Ocean, addresses.DFRewards, '300')
|
||||
// fund DFRewards
|
||||
await dfRewards.allocateRewards(
|
||||
ownerAccount,
|
||||
[Alice, Bob],
|
||||
['100', '200'],
|
||||
addresses.Ocean
|
||||
)
|
||||
const newDfOceanBalance = web3.utils.fromWei(
|
||||
await tokenContract.methods.balanceOf(addresses.DFRewards).call()
|
||||
)
|
||||
const expected = parseInt(dfOceanBalance) + 300
|
||||
assert(parseInt(newDfOceanBalance) === expected, 'DFRewards allocate failed')
|
||||
})
|
||||
|
||||
it('Alice should check for rewards', async () => {
|
||||
const rewards = await dfRewards.getAvailableRewards(Alice, addresses.Ocean)
|
||||
assert(parseInt(rewards) >= 100, 'Alice reward missmatch, got only ' + rewards)
|
||||
const multipleRewards = await dfStrategy.getMultipleAvailableRewards(Alice, [
|
||||
addresses.Ocean
|
||||
])
|
||||
assert(parseInt(multipleRewards[0]) >= 100, 'Alice reward missmatch')
|
||||
})
|
||||
|
||||
it('Alice should claim the rewards using DFRewards claim', async () => {
|
||||
const aliceOceanBalance = web3.utils.fromWei(
|
||||
await tokenContract.methods.balanceOf(Alice).call()
|
||||
)
|
||||
await dfRewards.claimRewards(Alice, Alice, addresses.Ocean)
|
||||
const newAliceOceanBalance = web3.utils.fromWei(
|
||||
await tokenContract.methods.balanceOf(Alice).call()
|
||||
)
|
||||
const expected = parseInt(aliceOceanBalance) + 100
|
||||
assert(parseInt(newAliceOceanBalance) >= expected, 'Alice failed to claim')
|
||||
})
|
||||
|
||||
it('Bob should claim the rewards using DFStrategy claim', async () => {
|
||||
const bobOceanBalance = web3.utils.fromWei(
|
||||
await tokenContract.methods.balanceOf(Bob).call()
|
||||
)
|
||||
await dfStrategy.claimMultipleRewards(Bob, Bob, [addresses.Ocean])
|
||||
const newBobOceanBalance = web3.utils.fromWei(
|
||||
await tokenContract.methods.balanceOf(Bob).call()
|
||||
)
|
||||
const expected = parseInt(bobOceanBalance) + 200
|
||||
assert(parseInt(newBobOceanBalance) >= expected, 'Bob failed to claim')
|
||||
})
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user