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
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-test-unit-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-test-unit-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||||
restore-keys: ${{ runner.os }}-test-unit-${{ env.cache-name }}-
|
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
|
- name: Checkout Barge
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
@ -57,6 +60,8 @@ jobs:
|
|||||||
working-directory: ${{ github.workspace }}/barge
|
working-directory: ${{ github.workspace }}/barge
|
||||||
run: |
|
run: |
|
||||||
bash -x start_ocean.sh --no-aquarius --no-elasticsearch --no-provider --no-dashboard 2>&1 > start_ocean.log &
|
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
|
- run: npm ci
|
||||||
- name: Wait for contracts deployment
|
- name: Wait for contracts deployment
|
||||||
working-directory: ${{ github.workspace }}/barge
|
working-directory: ${{ github.workspace }}/barge
|
||||||
|
14
package-lock.json
generated
14
package-lock.json
generated
@ -9,7 +9,7 @@
|
|||||||
"version": "1.1.8",
|
"version": "1.1.8",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oceanprotocol/contracts": "^1.0.0",
|
"@oceanprotocol/contracts": "^1.1.3",
|
||||||
"bignumber.js": "^9.0.2",
|
"bignumber.js": "^9.0.2",
|
||||||
"cross-fetch": "^3.1.5",
|
"cross-fetch": "^3.1.5",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
@ -2589,9 +2589,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@oceanprotocol/contracts": {
|
"node_modules/@oceanprotocol/contracts": {
|
||||||
"version": "1.0.0",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.1.3.tgz",
|
||||||
"integrity": "sha512-rDCIooe1WHipLejuGhx2Wv/88SB7bWrN3+XHCWxXyPKTmmSQsgxKZPPzbIVBQ0ESChQZqGSBBJyqErqwwW4eBw=="
|
"integrity": "sha512-pn0rm4QKF8sVfDeJVlt18TV4Qj5oGgR/qQNO7O0GO2DQ3q8KHXRS15uRjmLTr5wW1kGcCHcTqEndXEEC7Elzkw=="
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/auth-token": {
|
"node_modules/@octokit/auth-token": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@ -19327,9 +19327,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@oceanprotocol/contracts": {
|
"@oceanprotocol/contracts": {
|
||||||
"version": "1.0.0",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.1.3.tgz",
|
||||||
"integrity": "sha512-rDCIooe1WHipLejuGhx2Wv/88SB7bWrN3+XHCWxXyPKTmmSQsgxKZPPzbIVBQ0ESChQZqGSBBJyqErqwwW4eBw=="
|
"integrity": "sha512-pn0rm4QKF8sVfDeJVlt18TV4Qj5oGgR/qQNO7O0GO2DQ3q8KHXRS15uRjmLTr5wW1kGcCHcTqEndXEEC7Elzkw=="
|
||||||
},
|
},
|
||||||
"@octokit/auth-token": {
|
"@octokit/auth-token": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
"web3": "^1.7.4"
|
"web3": "^1.7.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oceanprotocol/contracts": "^1.0.0",
|
"@oceanprotocol/contracts": "^1.1.3",
|
||||||
"bignumber.js": "^9.0.2",
|
"bignumber.js": "^9.0.2",
|
||||||
"cross-fetch": "^3.1.5",
|
"cross-fetch": "^3.1.5",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
|
@ -6,3 +6,6 @@ export * from './Router'
|
|||||||
export * from './Datatoken'
|
export * from './Datatoken'
|
||||||
export * from './NFT'
|
export * from './NFT'
|
||||||
export * from './NFTFactory'
|
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',
|
image: 'ubuntu',
|
||||||
tag: 'latest',
|
tag: 'latest',
|
||||||
checksum:
|
checksum:
|
||||||
'sha256:42ba2dfce475de1113d55602d40af18415897167d47c2045ec7b6d9746ff148f'
|
'sha256:2d7ecc9c5e08953d586a6e50c29b91479a48f69ac1ba1f9dc0420d18a728dfc5'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -213,7 +213,7 @@ const algoDdoWith1mTimeout = {
|
|||||||
image: 'ubuntu',
|
image: 'ubuntu',
|
||||||
tag: 'latest',
|
tag: 'latest',
|
||||||
checksum:
|
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