mirror of
https://github.com/oceanprotocol/ocean.js.git
synced 2024-11-26 20:39:05 +01:00
Feature/basic ve ocean (#1595)
* bump contracts to 1.1.3 * add basic veOcean support Co-authored-by: Bogdan Fazakas <bogdan.fazakas@gmail.com>
This commit is contained in:
parent
8a6f009290
commit
f8f4b48243
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@ -46,7 +46,10 @@ jobs:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-test-unit-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: ${{ runner.os }}-test-unit-${{ env.cache-name }}-
|
||||
|
||||
# Env var expansion workaround
|
||||
# https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
|
||||
- name: Set ADDRESS_FILE
|
||||
run: echo "ADDRESS_FILE=${HOME}/.ocean/ocean-contracts/artifacts/address.json" >> $GITHUB_ENV
|
||||
- name: Checkout Barge
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
@ -57,6 +60,8 @@ jobs:
|
||||
working-directory: ${{ github.workspace }}/barge
|
||||
run: |
|
||||
bash -x start_ocean.sh --no-aquarius --no-elasticsearch --no-provider --no-dashboard 2>&1 > start_ocean.log &
|
||||
env:
|
||||
CONTRACTS_VERSION: v1.1.3
|
||||
- run: npm ci
|
||||
- name: Wait for contracts deployment
|
||||
working-directory: ${{ github.workspace }}/barge
|
||||
|
14
package-lock.json
generated
14
package-lock.json
generated
@ -9,7 +9,7 @@
|
||||
"version": "1.1.8",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@oceanprotocol/contracts": "^1.0.0",
|
||||
"@oceanprotocol/contracts": "^1.1.3",
|
||||
"bignumber.js": "^9.0.2",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"crypto-js": "^4.1.1",
|
||||
@ -2589,9 +2589,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oceanprotocol/contracts": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.0.0.tgz",
|
||||
"integrity": "sha512-rDCIooe1WHipLejuGhx2Wv/88SB7bWrN3+XHCWxXyPKTmmSQsgxKZPPzbIVBQ0ESChQZqGSBBJyqErqwwW4eBw=="
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.1.3.tgz",
|
||||
"integrity": "sha512-pn0rm4QKF8sVfDeJVlt18TV4Qj5oGgR/qQNO7O0GO2DQ3q8KHXRS15uRjmLTr5wW1kGcCHcTqEndXEEC7Elzkw=="
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "3.0.1",
|
||||
@ -19327,9 +19327,9 @@
|
||||
}
|
||||
},
|
||||
"@oceanprotocol/contracts": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.0.0.tgz",
|
||||
"integrity": "sha512-rDCIooe1WHipLejuGhx2Wv/88SB7bWrN3+XHCWxXyPKTmmSQsgxKZPPzbIVBQ0ESChQZqGSBBJyqErqwwW4eBw=="
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.1.3.tgz",
|
||||
"integrity": "sha512-pn0rm4QKF8sVfDeJVlt18TV4Qj5oGgR/qQNO7O0GO2DQ3q8KHXRS15uRjmLTr5wW1kGcCHcTqEndXEEC7Elzkw=="
|
||||
},
|
||||
"@octokit/auth-token": {
|
||||
"version": "3.0.1",
|
||||
|
@ -49,7 +49,7 @@
|
||||
"web3": "^1.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@oceanprotocol/contracts": "^1.0.0",
|
||||
"@oceanprotocol/contracts": "^1.1.3",
|
||||
"bignumber.js": "^9.0.2",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"crypto-js": "^4.1.1",
|
||||
|
@ -6,3 +6,6 @@ export * from './Router'
|
||||
export * from './Datatoken'
|
||||
export * from './NFT'
|
||||
export * from './NFTFactory'
|
||||
export * from './ve/VeOcean'
|
||||
export * from './ve/VeFeeDistributor'
|
||||
export * from './ve/VeAllocate'
|
||||
|
117
src/contracts/ve/VeAllocate.ts
Normal file
117
src/contracts/ve/VeAllocate.ts
Normal file
@ -0,0 +1,117 @@
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import veAllocateABI from '@oceanprotocol/contracts/artifacts/contracts/ve/veAllocate.sol/veAllocate.json'
|
||||
import { calculateEstimatedGas, sendTx } from '../../utils'
|
||||
import { SmartContractWithAddress } from '../SmartContractWithAddress'
|
||||
import { ReceiptOrEstimate } from '../../@types'
|
||||
/**
|
||||
* Provides an interface for veOcean contract
|
||||
*/
|
||||
export class VeAllocate extends SmartContractWithAddress {
|
||||
getDefaultAbi(): AbiItem | AbiItem[] {
|
||||
return veAllocateABI.abi as AbiItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* set a specific percentage of veOcean to a specific nft
|
||||
* Maximum allocated percentage is 10000, so 1% is specified as 100
|
||||
* @param {String} userAddress user address
|
||||
* @param {String} amount Percentage used
|
||||
* @param {String} nft NFT address to allocate to
|
||||
* @param {String} chainId chainId of NFT
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async setAllocation<G extends boolean = false>(
|
||||
userAddress: string,
|
||||
amount: string,
|
||||
nft: string,
|
||||
chainId: number,
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const estGas = await calculateEstimatedGas(
|
||||
userAddress,
|
||||
this.contract.methods.setAllocation,
|
||||
amount,
|
||||
nft,
|
||||
chainId
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
userAddress,
|
||||
estGas + 1,
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.setAllocation,
|
||||
amount,
|
||||
nft,
|
||||
chainId
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
|
||||
/**
|
||||
* set specific percetage of veOcean to multiple nfts
|
||||
* Maximum allocated percentage is 10000, so 1% is specified as 100
|
||||
* @param {String} userAddress user address
|
||||
* @param {String[]} amount Array of percentages used
|
||||
* @param {String[]} nft Array of NFT addresses
|
||||
* @param {String[]} chainId Array of chainIds
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async setBatchAllocation<G extends boolean = false>(
|
||||
userAddress: string,
|
||||
amount: string[],
|
||||
nft: string[],
|
||||
chainId: number[],
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const estGas = await calculateEstimatedGas(
|
||||
userAddress,
|
||||
this.contract.methods.setBatchAllocation,
|
||||
amount,
|
||||
nft,
|
||||
chainId
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
userAddress,
|
||||
estGas + 1,
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.setBatchAllocation,
|
||||
amount,
|
||||
nft,
|
||||
chainId
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
|
||||
/** Get totalAllocation for address
|
||||
* @param {String} userAddress user address
|
||||
* @return {Promise<number>}
|
||||
*/
|
||||
public async getTotalAllocation(userAddress: string): Promise<number> {
|
||||
const allocation = await this.contract.methods.getTotalAllocation(userAddress).call()
|
||||
return allocation
|
||||
}
|
||||
|
||||
/** Get getveAllocation for address, nft, chainId
|
||||
* @param {String} userAddress user address
|
||||
* @param {String} nft NFT address to allocate to
|
||||
* @param {String} chainId chainId of NFT
|
||||
* @return {Promise<number>}
|
||||
*/
|
||||
public async getVeAllocation(
|
||||
userAddress: string,
|
||||
nft: string,
|
||||
chainId: string
|
||||
): Promise<number> {
|
||||
const allocation = await this.contract.methods
|
||||
.getveAllocation(userAddress, nft, chainId)
|
||||
.call()
|
||||
return allocation
|
||||
}
|
||||
}
|
74
src/contracts/ve/VeFeeDistributor.ts
Normal file
74
src/contracts/ve/VeFeeDistributor.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import veFeeABI from '@oceanprotocol/contracts/artifacts/contracts/ve/veFeeDistributor.vy/veFeeDistributor.json'
|
||||
import { calculateEstimatedGas, sendTx } from '../../utils'
|
||||
import { SmartContractWithAddress } from '../SmartContractWithAddress'
|
||||
import { ReceiptOrEstimate } from '../../@types'
|
||||
/**
|
||||
* Provides an interface for veOcean contract
|
||||
*/
|
||||
export class VeFeeDistributor extends SmartContractWithAddress {
|
||||
getDefaultAbi(): AbiItem | AbiItem[] {
|
||||
return veFeeABI.abi as AbiItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim fees for `userAddress`
|
||||
* Each call to claim look at a maximum of 50 user veOCEAN points.
|
||||
For accounts with many veOCEAN related actions, this function
|
||||
may need to be called more than once to claim all available
|
||||
fees. In the `Claimed` event that fires, if `claim_epoch` is
|
||||
less than `max_epoch`, the account may claim again
|
||||
* @param {String} userAddress user address
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async claim<G extends boolean = false>(
|
||||
userAddress: string,
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const estGas = await calculateEstimatedGas(userAddress, this.contract.methods.claim)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
userAddress,
|
||||
estGas + 20000,
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.claim
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
|
||||
/**
|
||||
* Make multiple fee claims in a single call
|
||||
Used to claim for many accounts at once, or to make
|
||||
multiple claims for the same address when that address
|
||||
has significant veOCEAN history
|
||||
* @param {String} fromUserAddress user address that sends the tx
|
||||
* @param {String} addresses array of addresses to claim
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async claimMany<G extends boolean = false>(
|
||||
fromUserAddress: string,
|
||||
addresses: string[],
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const estGas = await calculateEstimatedGas(
|
||||
fromUserAddress,
|
||||
this.contract.methods.claim_many,
|
||||
addresses
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
fromUserAddress,
|
||||
estGas + 20000,
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.claim_many,
|
||||
addresses
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
}
|
222
src/contracts/ve/VeOcean.ts
Normal file
222
src/contracts/ve/VeOcean.ts
Normal file
@ -0,0 +1,222 @@
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import veOceanABI from '@oceanprotocol/contracts/artifacts/contracts/ve/veOCEAN.vy/veOCEAN.json'
|
||||
import { calculateEstimatedGas, sendTx } from '../../utils'
|
||||
import { SmartContractWithAddress } from '../SmartContractWithAddress'
|
||||
import { ReceiptOrEstimate } from '../../@types'
|
||||
/**
|
||||
* Provides an interface for veOcean contract
|
||||
*/
|
||||
export class VeOcean extends SmartContractWithAddress {
|
||||
getDefaultAbi(): AbiItem | AbiItem[] {
|
||||
return veOceanABI.abi as AbiItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Deposit `amount` tokens for `userAddress` and lock until `unlockTime`
|
||||
* @param {String} userAddress user address
|
||||
* @param {String} amount Amount of tokens to be locked
|
||||
* @param {Number} unlockTime Timestamp for unlock
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async lockTokens<G extends boolean = false>(
|
||||
userAddress: string,
|
||||
amount: string,
|
||||
unlockTime: number,
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const amountFormatted = await this.amountToUnits(await this.getToken(), amount)
|
||||
const estGas = await calculateEstimatedGas(
|
||||
userAddress,
|
||||
this.contract.methods.create_lock,
|
||||
amountFormatted,
|
||||
unlockTime
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
userAddress,
|
||||
estGas + 20000, // sometimes, it's not enough
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.create_lock,
|
||||
amountFormatted,
|
||||
unlockTime
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
|
||||
/**
|
||||
* Deposit `amount` tokens for `toAddress` and add to the existing lock
|
||||
* Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new user
|
||||
* @param {String} fromUserAddress user address that sends the tx
|
||||
* @param {String} toAddress user address to deposit for
|
||||
* @param {String} amount Amount of tokens to be locked
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async depositFor<G extends boolean = false>(
|
||||
fromUserAddress: string,
|
||||
toAddress: string,
|
||||
amount: string,
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const amountFormatted = await this.amountToUnits(await this.getToken(), amount)
|
||||
const estGas = await calculateEstimatedGas(
|
||||
fromUserAddress,
|
||||
this.contract.methods.deposit_for,
|
||||
toAddress,
|
||||
amountFormatted
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
fromUserAddress,
|
||||
estGas + 20000, // sometimes, it's not enough
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.deposit_for,
|
||||
toAddress,
|
||||
amountFormatted
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
|
||||
/**
|
||||
* Deposit `amount` additional tokens for `userAddress` without modifying the unlock time
|
||||
* @param {String} userAddress user address that sends the tx
|
||||
* @param {String} amount Amount of tokens to be locked
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async increaseAmount<G extends boolean = false>(
|
||||
userAddress: string,
|
||||
amount: string,
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const amountFormatted = await this.amountToUnits(await this.getToken(), amount)
|
||||
const estGas = await calculateEstimatedGas(
|
||||
userAddress,
|
||||
this.contract.methods.increase_amount,
|
||||
amountFormatted
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
userAddress,
|
||||
estGas + 20000, // sometimes, it's not enough
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.increase_amount,
|
||||
amountFormatted
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the unlock time for `userAddress` to `unlockTime`
|
||||
* @param {String} userAddress user address that sends the tx
|
||||
* @param {Number} unlockTime Timestamp for new unlock time
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async increaseUnlockTime<G extends boolean = false>(
|
||||
userAddress: string,
|
||||
unlockTime: number,
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const estGas = await calculateEstimatedGas(
|
||||
userAddress,
|
||||
this.contract.methods.increase_unlock_time,
|
||||
unlockTime
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
userAddress,
|
||||
estGas + 20000, // sometimes, it's not enough
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.increase_unlock_time,
|
||||
unlockTime
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdraw all tokens for `userAddress`
|
||||
* @param {String} userAddress user address that sends the tx
|
||||
* @return {Promise<ReceiptOrEstimate>}
|
||||
*/
|
||||
public async withdraw<G extends boolean = false>(
|
||||
userAddress: string,
|
||||
estimateGas?: G
|
||||
): Promise<ReceiptOrEstimate<G>> {
|
||||
const estGas = await calculateEstimatedGas(
|
||||
userAddress,
|
||||
this.contract.methods.withdraw
|
||||
)
|
||||
if (estimateGas) return <ReceiptOrEstimate<G>>estGas
|
||||
|
||||
// Invoke function of the contract
|
||||
const trxReceipt = await sendTx(
|
||||
userAddress,
|
||||
estGas + 1,
|
||||
this.web3,
|
||||
this.config?.gasFeeMultiplier,
|
||||
this.contract.methods.withdraw
|
||||
)
|
||||
return <ReceiptOrEstimate<G>>trxReceipt
|
||||
}
|
||||
|
||||
/** Get voting power for address
|
||||
* @param {String} userAddress user address
|
||||
* @return {Promise<number>}
|
||||
*/
|
||||
public async getVotingPower(userAddress: string): Promise<number> {
|
||||
const balance = await this.contract.methods.balanceOf(userAddress).call()
|
||||
return balance
|
||||
}
|
||||
|
||||
/** Get locked balance
|
||||
* @param {String} userAddress user address
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
public async getLockedAmount(userAddress: string): Promise<string> {
|
||||
const balance = await this.contract.methods.locked(userAddress).call()
|
||||
const balanceFormated = await this.unitsToAmount(
|
||||
await this.getToken(),
|
||||
balance.amount
|
||||
)
|
||||
|
||||
return balanceFormated
|
||||
}
|
||||
|
||||
/** Get untilLock for address
|
||||
* @param {String} userAddress user address
|
||||
* @return {Promise<number>}
|
||||
*/
|
||||
public async lockEnd(userAddress: string): Promise<number> {
|
||||
const untilLock = await this.contract.methods.locked__end(userAddress).call()
|
||||
return untilLock
|
||||
}
|
||||
|
||||
/** Get total supply
|
||||
* @return {Promise<number>}
|
||||
*/
|
||||
public async totalSupply(): Promise<string> {
|
||||
const supplyFormated = await this.unitsToAmount(
|
||||
await this.getToken(),
|
||||
await this.contract.methods.totalSupply().call()
|
||||
)
|
||||
return supplyFormated
|
||||
}
|
||||
|
||||
/** Get token
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
public async getToken(): Promise<string> {
|
||||
const tokenAddress = await this.contract.methods.token().call()
|
||||
return tokenAddress
|
||||
}
|
||||
}
|
@ -171,7 +171,7 @@ const algoDdoWithNoTimeout = {
|
||||
image: 'ubuntu',
|
||||
tag: 'latest',
|
||||
checksum:
|
||||
'sha256:42ba2dfce475de1113d55602d40af18415897167d47c2045ec7b6d9746ff148f'
|
||||
'sha256:2d7ecc9c5e08953d586a6e50c29b91479a48f69ac1ba1f9dc0420d18a728dfc5'
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -213,7 +213,7 @@ const algoDdoWith1mTimeout = {
|
||||
image: 'ubuntu',
|
||||
tag: 'latest',
|
||||
checksum:
|
||||
'sha256:42ba2dfce475de1113d55602d40af18415897167d47c2045ec7b6d9746ff148f'
|
||||
'sha256:2d7ecc9c5e08953d586a6e50c29b91479a48f69ac1ba1f9dc0420d18a728dfc5'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
218
test/unit/veOcean.test.ts
Normal file
218
test/unit/veOcean.test.ts
Normal file
@ -0,0 +1,218 @@
|
||||
import { assert } from 'chai'
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import { web3, getTestConfig, getAddresses } from '../config'
|
||||
import {
|
||||
Config,
|
||||
approve,
|
||||
VeOcean,
|
||||
VeFeeDistributor,
|
||||
sendTx,
|
||||
calculateEstimatedGas,
|
||||
NftFactory,
|
||||
VeAllocate
|
||||
} from '../../src'
|
||||
|
||||
describe('veOcean tests', async () => {
|
||||
let config: Config
|
||||
let addresses: any
|
||||
let nftFactory
|
||||
let veOcean: VeOcean
|
||||
let veFeeDistributor: VeFeeDistributor
|
||||
let veAllocate: VeAllocate
|
||||
let ownerAccount: string
|
||||
let Alice: string
|
||||
let Bob: string
|
||||
let nft1, nft2, nft3
|
||||
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'
|
||||
}
|
||||
] as AbiItem[]
|
||||
const tokenContract = new web3.eth.Contract(minAbi, addresses.Ocean)
|
||||
const estGas = await calculateEstimatedGas(
|
||||
ownerAccount,
|
||||
tokenContract.methods.mint,
|
||||
Alice,
|
||||
web3.utils.toWei('1000')
|
||||
)
|
||||
await sendTx(
|
||||
ownerAccount,
|
||||
estGas,
|
||||
web3,
|
||||
1,
|
||||
tokenContract.methods.mint,
|
||||
Alice,
|
||||
web3.utils.toWei('1000')
|
||||
)
|
||||
await sendTx(
|
||||
ownerAccount,
|
||||
estGas,
|
||||
web3,
|
||||
1,
|
||||
tokenContract.methods.mint,
|
||||
Bob,
|
||||
web3.utils.toWei('1000')
|
||||
)
|
||||
veOcean = new VeOcean(addresses.veOCEAN, web3)
|
||||
veFeeDistributor = new VeFeeDistributor(addresses.veFeeDistributor, web3)
|
||||
veAllocate = new VeAllocate(addresses.veAllocate, web3)
|
||||
nftFactory = new NftFactory(addresses.ERC721Factory, web3)
|
||||
})
|
||||
|
||||
it('Alice should lock 100 Ocean', async () => {
|
||||
// since we can only lock once, we test if tx fails or not
|
||||
// so if there is already a lock, skip it
|
||||
const currentBalance = await veOcean.getLockedAmount(Alice)
|
||||
const currentLock = await veOcean.lockEnd(Alice)
|
||||
const amount = '100'
|
||||
await approve(web3, config, Alice, addresses.Ocean, addresses.veOCEAN, amount)
|
||||
const timestamp = Math.floor(Date.now() / 1000)
|
||||
const unlockTime = timestamp + 7 * 86400
|
||||
|
||||
if (parseInt(currentBalance) > 0 || currentLock > 0) {
|
||||
// we already have some locked tokens, so our transaction should fail
|
||||
try {
|
||||
await veOcean.lockTokens(Alice, amount, unlockTime)
|
||||
assert(false, 'This should fail!')
|
||||
} catch (e) {
|
||||
// do nothing
|
||||
}
|
||||
} else {
|
||||
const estGas = await veOcean.lockTokens(Alice, amount, unlockTime, true)
|
||||
console.log('Estimate gas for lockTokens:' + estGas)
|
||||
const tx = await veOcean.lockTokens(Alice, amount, unlockTime)
|
||||
// check events
|
||||
assert(tx.events.Deposit.returnValues[0] === Alice)
|
||||
assert(tx.events.Deposit.returnValues[1] === web3.utils.toWei(amount))
|
||||
assert(tx.events.Deposit.returnValues[2] > 0) // we cannot compare it to the actual untiLock, because contract will round it to weeks
|
||||
assert(tx.events.Supply.returnValues[1] > tx.events.Supply.returnValues[0]) // supply has increased
|
||||
}
|
||||
})
|
||||
|
||||
it('Alice should increase the lock time', async () => {
|
||||
const currentLock = await veOcean.lockEnd(Alice)
|
||||
const newLock = parseInt(String(currentLock)) + 7 * 86400
|
||||
await veOcean.increaseUnlockTime(Alice, newLock)
|
||||
const newCurrentLock = await veOcean.lockEnd(Alice)
|
||||
assert(newCurrentLock > currentLock, 'Lock time should change"')
|
||||
})
|
||||
|
||||
it('Alice should increase the locked amount', async () => {
|
||||
const currentBalance = await veOcean.getLockedAmount(Alice)
|
||||
const currentLock = await veOcean.lockEnd(Alice)
|
||||
const amount = '200'
|
||||
await approve(web3, config, Alice, addresses.Ocean, addresses.veOCEAN, amount)
|
||||
await veOcean.increaseAmount(Alice, amount)
|
||||
const newCurrentBalance = await veOcean.getLockedAmount(Alice)
|
||||
const newCurrentLock = await veOcean.lockEnd(Alice)
|
||||
assert(newCurrentLock === currentLock, 'Lock time should not change')
|
||||
assert(
|
||||
newCurrentBalance > currentBalance,
|
||||
'Amount error:' + newCurrentBalance + ' shoud be > than ' + currentBalance
|
||||
)
|
||||
})
|
||||
|
||||
it('Alice should publish 3 NFTs', async () => {
|
||||
// publish 3 nfts
|
||||
nft1 = await nftFactory.createNFT(Alice, {
|
||||
name: 'testNft1',
|
||||
symbol: 'TSTF1',
|
||||
templateIndex: 1,
|
||||
tokenURI: '',
|
||||
transferable: true,
|
||||
owner: Alice
|
||||
})
|
||||
nft2 = await nftFactory.createNFT(Alice, {
|
||||
name: 'testNft2',
|
||||
symbol: 'TSTF2',
|
||||
templateIndex: 1,
|
||||
tokenURI: '',
|
||||
transferable: true,
|
||||
owner: Alice
|
||||
})
|
||||
nft3 = await nftFactory.createNFT(Alice, {
|
||||
name: 'testNft3',
|
||||
symbol: 'TSTF3',
|
||||
templateIndex: 1,
|
||||
tokenURI: '',
|
||||
transferable: true,
|
||||
owner: Alice
|
||||
})
|
||||
})
|
||||
|
||||
it('Alice should allocate 10% to NFT1', async () => {
|
||||
const totalAllocation = await veAllocate.getTotalAllocation(Alice)
|
||||
const tx = await veAllocate.setAllocation(Alice, '1000', nft1, chainId)
|
||||
assert(tx.events.AllocationSet.returnValues[0] === Alice)
|
||||
assert(tx.events.AllocationSet.returnValues[1] === nft1)
|
||||
assert(parseInt(tx.events.AllocationSet.returnValues[2]) === parseInt(chainId))
|
||||
assert(tx.events.AllocationSet.returnValues[3] === '1000')
|
||||
const newTotalAllocation = await veAllocate.getTotalAllocation(Alice)
|
||||
const expectedAllocation = parseInt(String(totalAllocation)) + 1000
|
||||
assert(
|
||||
parseInt(String(newTotalAllocation)) === parseInt(String(expectedAllocation)),
|
||||
'NewAllocation (' + newTotalAllocation + ') should be ' + expectedAllocation
|
||||
)
|
||||
const nftAllocation = await veAllocate.getVeAllocation(Alice, nft1, chainId)
|
||||
assert(
|
||||
parseInt(String(nftAllocation)) === parseInt('1000'),
|
||||
nftAllocation + ' should be 1000'
|
||||
)
|
||||
})
|
||||
|
||||
it('Alice should allocate 10% to NFT2 and 20% to NFT3', async () => {
|
||||
const totalAllocation = await veAllocate.getTotalAllocation(Alice)
|
||||
const tx = await veAllocate.setBatchAllocation(
|
||||
Alice,
|
||||
['1000', '2000'],
|
||||
[nft2, nft3],
|
||||
[chainId, chainId]
|
||||
)
|
||||
assert(tx.events.AllocationSetMultiple.returnValues[0] === Alice)
|
||||
assert(tx.events.AllocationSetMultiple.returnValues[1][0] === nft2)
|
||||
assert(tx.events.AllocationSetMultiple.returnValues[1][1] === nft3)
|
||||
assert(
|
||||
parseInt(tx.events.AllocationSetMultiple.returnValues[2][0]) === parseInt(chainId)
|
||||
)
|
||||
assert(tx.events.AllocationSetMultiple.returnValues[3][0] === '1000')
|
||||
assert(tx.events.AllocationSetMultiple.returnValues[3][1] === '2000')
|
||||
const newTotalAllocation = await veAllocate.getTotalAllocation(Alice)
|
||||
const expectedAllocation = parseInt(String(totalAllocation)) + 3000
|
||||
assert(
|
||||
parseInt(String(newTotalAllocation)) === parseInt(String(expectedAllocation)),
|
||||
'NewAllocation (' + newTotalAllocation + ') should be ' + expectedAllocation
|
||||
)
|
||||
let nftAllocation = await veAllocate.getVeAllocation(Alice, nft2, chainId)
|
||||
assert(
|
||||
parseInt(String(nftAllocation)) === parseInt('1000'),
|
||||
nftAllocation + ' should be 1000'
|
||||
)
|
||||
nftAllocation = await veAllocate.getVeAllocation(Alice, nft3, chainId)
|
||||
assert(
|
||||
parseInt(String(nftAllocation)) === parseInt('2000'),
|
||||
nftAllocation + ' should be 2000'
|
||||
)
|
||||
})
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user