-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add DataFarming contract support (#1596)
* add DataFarming contract support
- Loading branch information
Showing
4 changed files
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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') | ||
}) | ||
}) |