1
0
mirror of https://github.com/oceanprotocol/ocean.js.git synced 2024-11-26 20:39:05 +01:00

added handlers for all methods in erc721 template contract

This commit is contained in:
Bogdan Fazakas 2021-10-20 17:24:07 +03:00
parent 252eca12e4
commit 1352a1c5d2
4 changed files with 552 additions and 1 deletions

111
src/datatokens/Datatoken.ts Normal file
View File

@ -0,0 +1,111 @@
import Web3 from 'web3'
import { AbiItem } from 'web3-utils'
import { TransactionReceipt } from 'web3-eth'
import defaultDatatokensABI from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json'
import Decimal from 'decimal.js'
import { Logger, getFairGasPrice } from '../utils'
/**
* ERC20 ROLES
*/
interface Roles {
minter: boolean
feeManager: boolean
}
export class Datatoken {
public GASLIMIT_DEFAULT = 1000000
public factoryAddress: string
public factoryABI: AbiItem | AbiItem[]
public datatokensABI: AbiItem | AbiItem[]
public web3: Web3
private logger: Logger
public startBlock: number
/**
* Instantiate ERC20 DataTokens (independently of Ocean).
* @param {AbiItem | AbiItem[]} datatokensABI
* @param {Web3} web3
*/
constructor(
web3: Web3,
logger: Logger,
datatokensABI?: AbiItem | AbiItem[],
startBlock?: number
) {
this.web3 = web3
this.logger = logger
this.datatokensABI = datatokensABI || (defaultDatatokensABI.abi as AbiItem[])
this.startBlock = startBlock || 0
}
/**
* Mint
* @param {String} dataTokenAddress
* @param {String} address
* @param {String} amount Number of datatokens, as number. Will be converted to wei
* @param {String} toAddress - only if toAddress is different from the minter
* @return {Promise<TransactionReceipt>} transactionId
*/
public async mint(
dataTokenAddress: string,
address: string,
amount: string,
toAddress?: string
): Promise<TransactionReceipt> {
const dtContract = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress)
if ((await this.getDTPermissions(dataTokenAddress, address)).minter != true) {
throw new Error(`Caller is not Minter`)
}
const capAvailble = await this.getCap(dataTokenAddress)
if (new Decimal(capAvailble).gte(amount)) {
// Estimate gas cost for mint method
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await dtContract.methods
.mint(toAddress || address, this.web3.utils.toWei(amount))
.estimateGas({ from: address }, (err, estGas) =>
err ? gasLimitDefault : estGas
)
} catch (e) {
estGas = gasLimitDefault
}
// Call mint contract method
const trxReceipt = await dtContract.methods
.mint(toAddress || address, this.web3.utils.toWei(amount))
.send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
} else {
throw new Error(`Mint amount exceeds cap available`)
}
}
/** Returns ERC20 user's permissions for a datatoken
* @param {String} dtAddress Datatoken adress
* @param {String} address user adress
* @return {Promise<Roles>}
*/
public async getDTPermissions(dtAddress: string, address: string): Promise<Roles> {
const dtContract = new this.web3.eth.Contract(this.datatokensABI, dtAddress)
const roles = await dtContract.methods.permissions(address).call()
return roles
}
/** Returns the DataToken capital
* @param {String} dtAddress Datatoken adress
* @return {Promise<string>}
*/
public async getCap(dtAddress: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dtAddress)
const cap = await datatoken.methods.cap().call()
return this.web3.utils.fromWei(cap)
}
}

View File

@ -1,5 +1,6 @@
import Web3 from 'web3'
import { AbiItem } from 'web3-utils'
import { TransactionReceipt } from 'web3-eth'
import defaultNFTDatatokenABI from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC721Template.sol/ERC721Template.json'
import { Logger, getFairGasPrice, generateDtName } from '../utils'
@ -13,7 +14,7 @@ interface Roles {
store: boolean
}
export class NFTDataToken {
export class NFTDatatoken {
public GASLIMIT_DEFAULT = 1000000
public factory721Address: string
public factory721ABI: AbiItem | AbiItem[]
@ -104,4 +105,426 @@ export class NFTDataToken {
}
return tokenAddress
}
/**
* Add Manager for NFT Contract (only NFT Owner can succeed)
* @param {String} nftAddress erc721 contract adress
* @param {String} address NFT Owner adress
* @param {String} manager User adress which is going to be assing manager
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async addManager(nftAddress: string, address: string, manager: string) {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
if ((await this.getNFTOwner(nftAddress)) !== address) {
throw new Error(`Caller is not NFT Owner`)
}
// Estimate gas for add manager call
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await nftContract.methods
.addManager(manager)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) {
estGas = gasLimitDefault
}
// Invoke addManager function of the contract
const trxReceipt = await nftContract.methods.addManager(manager).send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
}
/**
* Removes a specific manager for NFT Contract (only NFT Owner can succeed)
* @param {String} nftAddress erc721 contract adress
* @param {String} address NFT Owner adress
* @param {String} manager User adress which is going to be removed as manager
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async removeManager(nftAddress: string, address: string, manager: string) {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
if ((await this.getNFTOwner(nftAddress)) !== address) {
throw new Error(`Caller is not NFT Owner`)
}
// Estimate gas for removeManager method
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await nftContract.methods
.removeManager(manager)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) {
estGas = gasLimitDefault
}
// Invoke removeManager function of the contract
const trxReceipt = await nftContract.methods.removeManager(manager).send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
}
/**
* Add ERC20Deployer permission - only Manager can succeed
* @param {String} nftAddress erc721 contract adress
* @param {String} address NFT Manager adress
* @param {String} erc20Deployer User adress which is going to have erc20Deployer permission
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async addERC20Deployer(
nftAddress: string,
address: string,
erc20Deployer: string
): Promise<TransactionReceipt> {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
if ((await this.getNFTPermissions(nftAddress, address)).manager !== true) {
throw new Error(`Caller is not Manager`)
}
// Estimate gas for addToCreateERC20List method
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await nftContract.methods
.addToCreateERC20List(erc20Deployer)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) {
estGas = gasLimitDefault
}
// Invoke addToCreateERC20List function of the contract
const trxReceipt = await nftContract.methods
.addToCreateERC20List(erc20Deployer)
.send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
}
/**
* Remove ERC20Deployer permission - only Manager can succeed
* @param {String} nftAddress erc721 contract adress
* @param {String} address NFT Manager adress
* @param {String} erc20Deployer Address of the user to be revoked ERC20Deployer Permission
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async removeERC20Deployer(
nftAddress: string,
address: string,
erc20Deployer: string
): Promise<TransactionReceipt> {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
if ((await this.getNFTPermissions(nftAddress, address)).manager !== true) {
throw new Error(`Caller is not Manager`)
}
//Estimate gas for removeFromCreateERC20List method
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await nftContract.methods
.removeFromCreateERC20List(erc20Deployer)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) {
estGas = gasLimitDefault
}
// Call removeFromCreateERC20List function of the contract
const trxReceipt = await nftContract.methods
.removeFromCreateERC20List(erc20Deployer)
.send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
}
/**
* Add Metadata Updater permission - only Manager can succeed
* @param {String} nftAddress erc721 contract adress
* @param {String} address NFT Manager adress
* @param {String} metadataUpdater User adress which is going to have Metadata Updater permission
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async addMetadataUpdater(
nftAddress: string,
address: string,
metadataUpdater: string
): Promise<TransactionReceipt> {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
if ((await this.getNFTPermissions(nftAddress, address)).manager != true) {
throw new Error(`Caller is not Manager`)
}
//Estimate gas cost for addToMetadataList method
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await nftContract.methods
.addToMetadataList(metadataUpdater)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) {
estGas = gasLimitDefault
}
// Call addToMetadataList function of the contract
const trxReceipt = await nftContract.methods.addToMetadataList(metadataUpdater).send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
}
/**
* Remove Metadata Updater permission - only Manager can succeed
* @param {String} nftAddress erc721 contract adress
* @param {String} address NFT Manager adress
* @param {String} metadataUpdater Address of the user to be revoked Metadata updater Permission
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async removeMetadataUpdater(
nftAddress: string,
address: string,
metadataUpdater: string
): Promise<TransactionReceipt> {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
if ((await this.getNFTPermissions(nftAddress, address)).manager != true) {
throw new Error(`Caller is not Manager`)
}
//Estimate gas cost for removeFromMetadataList method
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await nftContract.methods
.removeFromMetadataList(metadataUpdater)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) {
estGas = gasLimitDefault
}
// Call removeFromMetadataList function of the contract
const trxReceipt = await nftContract.methods
.removeFromMetadataList(metadataUpdater)
.send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
}
/**
* Add Store Updater permission - only Manager can succeed
* @param {String} nftAddress erc721 contract adress
* @param {String} address NFT Manager adress
* @param {String} storeUpdater User adress which is going to have Store Updater permission
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async addStoreUpdater(
nftAddress: string,
address: string,
storeUpdater: string
): Promise<TransactionReceipt> {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
if ((await this.getNFTPermissions(nftAddress, address)).manager != true) {
throw new Error(`Caller is not Manager`)
}
// Estimate gas cost for addTo725StoreList method
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await nftContract.methods
.addTo725StoreList(storeUpdater)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) {
estGas = gasLimitDefault
}
// Call addTo725StoreList function of the contract
const trxReceipt = await nftContract.methods.addTo725StoreList(storeUpdater).send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
}
/**
* Remove Store Updater permission - only Manager can succeed
* @param {String} nftAddress erc721 contract adress
* @param {String} address NFT Manager adress
* @param {String} storeUpdater Address of the user to be revoked Store Updater Permission
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async removeStoreUpdater(
nftAddress: string,
address: string,
storeUpdater: string
): Promise<TransactionReceipt> {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
if ((await this.getNFTPermissions(nftAddress, address)).manager != true) {
throw new Error(`Caller is not Manager`)
}
// Estimate gas cost for removeFrom725StoreList method
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await nftContract.methods
.removeFrom725StoreList(storeUpdater)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) {
estGas = gasLimitDefault
}
// Call removeFrom725StoreList function of the contract
const trxReceipt = await nftContract.methods
.removeFrom725StoreList(storeUpdater)
.send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
}
/**
* This function allows to remove all ROLES at erc721 level: Managers, ERC20Deployer, MetadataUpdater, StoreUpdater
* Even NFT Owner has to readd himself as Manager
* Permissions at erc20 level stay.
* Only NFT Owner can call it.
* @param {String} nftAddress erc721 contract adress
* @param {String} address NFT Owner adress
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async cleanPermissions(
nftAddress: string,
address: string
): Promise<TransactionReceipt> {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
if ((await this.getNFTOwner(nftAddress)) !== address) {
throw new Error(`Caller is not NFT Owner`)
}
// Estimate gas cost for cleanPermissions method
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await nftContract.methods
.cleanPermissions()
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) {
estGas = gasLimitDefault
}
// Call cleanPermissions function of the contract
const trxReceipt = await nftContract.methods.cleanPermissions().send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
}
/**
* Transfers the NFT
* will clean all permissions both on erc721 and erc20 level.
* @param {String} nftAddress erc721 contract adress
* @param {String} nftOwner Current NFT Owner adress
* @param {String} nftReceiver User which will receive the NFT, will also be set as Manager
* @param {Number} tokenId The id of the token to be transfered
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async transferNFT(
nftAddress: string,
nftOwner: string,
nftReceiver: string,
tokenId?: number
): Promise<TransactionReceipt> {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
if ((await this.getNFTOwner(nftAddress)) !== nftOwner) {
throw new Error(`Caller is not NFT Owner`)
}
let tokenIdentifier = tokenId || 1
// Estimate gas cost for transfer NFT method
const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas
try {
estGas = await nftContract.methods
.transferFrom(nftOwner, nftReceiver, tokenIdentifier)
.estimateGas({ from: nftOwner }, (err, estGas) =>
err ? gasLimitDefault : estGas
)
} catch (e) {
estGas = gasLimitDefault
}
// Call transferFrom function of the contract
const trxReceipt = await nftContract.methods
.transferFrom(nftOwner, nftReceiver, tokenIdentifier)
.send({
from: nftOwner,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
return trxReceipt
}
/** Get Owner
* @param {String} nftAddress erc721 contract adress
* @return {Promise<string>} string
*/
public async getNFTOwner(nftAddress: string): Promise<string> {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
const trxReceipt = await nftContract.methods.ownerOf(1).call()
return trxReceipt
}
/** Get users NFT Permissions
* @param {String} nftAddress erc721 contract adress
* @param {String} address user adress
* @return {Promise<Roles>}
*/
public async getNFTPermissions(nftAddress: string, address: string): Promise<Roles> {
const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
const roles = await nftContract.methods._getPermissions(address).call()
return roles
}
}

View File

@ -1 +1,2 @@
export * from './Datatoken'
export * from './NFTDatatoken'

View File

@ -0,0 +1,16 @@
// import { assert } from 'chai'
// import { LoggerInstance } from '../../../src/utils'
// const web3 = new Web3('http://127.0.0.1:8545')
// describe('NFTDatatoken', () => {
// let nftOwner: string
// let user1: string
// let user2: string
// let contracts: TestContractHandler
// let nftDatatoken: NFTDataToken
// let nftFactory: NFTFactory
// let erc20Factory: DT20Factory
// let nftAddress: string
// }