mirror of
https://github.com/oceanprotocol/ocean.js.git
synced 2024-11-26 20:39:05 +01:00
wip v4 contract integration NFT creation flow
This commit is contained in:
parent
a6ce03439f
commit
252eca12e4
204
src/data/words.json
Normal file
204
src/data/words.json
Normal file
@ -0,0 +1,204 @@
|
||||
{
|
||||
"nouns": [
|
||||
"Crab",
|
||||
"Fish",
|
||||
"Seal",
|
||||
"Octopus",
|
||||
"Shark",
|
||||
"Seahorse",
|
||||
"Walrus",
|
||||
"Starfish",
|
||||
"Whale",
|
||||
"Orca",
|
||||
"Penguin",
|
||||
"Jellyfish",
|
||||
"Squid",
|
||||
"Lobster",
|
||||
"Pelican",
|
||||
"Shrimp",
|
||||
"Oyster",
|
||||
"Clam",
|
||||
"Seagull",
|
||||
"Dolphin",
|
||||
"Shell",
|
||||
"Cormorant",
|
||||
"Otter",
|
||||
"Anemone",
|
||||
"Turtle",
|
||||
"Coral",
|
||||
"Ray",
|
||||
"Barracuda",
|
||||
"Krill",
|
||||
"Anchovy",
|
||||
"Angelfish",
|
||||
"Barnacle",
|
||||
"Clownfish",
|
||||
"Cod",
|
||||
"Cuttlefish",
|
||||
"Eel",
|
||||
"Fugu",
|
||||
"Herring",
|
||||
"Haddock",
|
||||
"Ling",
|
||||
"Mackerel",
|
||||
"Manatee",
|
||||
"Narwhal",
|
||||
"Nautilus",
|
||||
"Plankton",
|
||||
"Porpoise",
|
||||
"Prawn",
|
||||
"Pufferfish",
|
||||
"Swordfish",
|
||||
"Tuna"
|
||||
],
|
||||
"adjectives": [
|
||||
"adamant",
|
||||
"adroit",
|
||||
"amatory",
|
||||
"ambitious",
|
||||
"amused",
|
||||
"animistic",
|
||||
"antic",
|
||||
"arcadian",
|
||||
"artistic",
|
||||
"astonishing",
|
||||
"astounding",
|
||||
"baleful",
|
||||
"bellicose",
|
||||
"bilious",
|
||||
"blissful",
|
||||
"boorish",
|
||||
"brave",
|
||||
"breathtaking",
|
||||
"brilliant",
|
||||
"calamitous",
|
||||
"caustic",
|
||||
"cerulean",
|
||||
"clever",
|
||||
"charming",
|
||||
"comely",
|
||||
"competent",
|
||||
"concomitant",
|
||||
"confident",
|
||||
"contumacious",
|
||||
"corpulent",
|
||||
"crapulous",
|
||||
"creative",
|
||||
"dazzling",
|
||||
"dedicated",
|
||||
"defamatory",
|
||||
"delighted",
|
||||
"delightful",
|
||||
"determined",
|
||||
"didactic",
|
||||
"dilatory",
|
||||
"dowdy",
|
||||
"efficacious",
|
||||
"effulgent",
|
||||
"egregious",
|
||||
"empowered",
|
||||
"endemic",
|
||||
"enthusiastic",
|
||||
"equanimous",
|
||||
"exceptional",
|
||||
"execrable",
|
||||
"fabulous",
|
||||
"fantastic",
|
||||
"fastidious",
|
||||
"feckless",
|
||||
"fecund",
|
||||
"friable",
|
||||
"fulsome",
|
||||
"garrulous",
|
||||
"generous",
|
||||
"gentle",
|
||||
"guileless",
|
||||
"gustatory",
|
||||
"heuristic",
|
||||
"histrionic",
|
||||
"hubristic",
|
||||
"incendiary",
|
||||
"incredible",
|
||||
"insidious",
|
||||
"insolent",
|
||||
"inspired",
|
||||
"intransigent",
|
||||
"inveterate",
|
||||
"invidious",
|
||||
"invigorated",
|
||||
"irksome",
|
||||
"jejune",
|
||||
"juicy",
|
||||
"jocular",
|
||||
"joyful",
|
||||
"judicious",
|
||||
"kind",
|
||||
"lachrymose",
|
||||
"limpid",
|
||||
"loquacious",
|
||||
"lovely",
|
||||
"luminous",
|
||||
"mannered",
|
||||
"marvelous",
|
||||
"mendacious",
|
||||
"meretricious",
|
||||
"minatory",
|
||||
"mordant",
|
||||
"motivated",
|
||||
"munificent",
|
||||
"nefarious",
|
||||
"noxious",
|
||||
"obtuse",
|
||||
"optimistic",
|
||||
"parsimonious",
|
||||
"pendulous",
|
||||
"pernicious",
|
||||
"pervasive",
|
||||
"petulant",
|
||||
"passionate",
|
||||
"phenomenal",
|
||||
"platitudinous",
|
||||
"pleasant",
|
||||
"powerful",
|
||||
"precipitate",
|
||||
"propitious",
|
||||
"puckish",
|
||||
"querulous",
|
||||
"quiescent",
|
||||
"rebarbative",
|
||||
"recalcitant",
|
||||
"redolent",
|
||||
"rhadamanthine",
|
||||
"risible",
|
||||
"ruminative",
|
||||
"sagacious",
|
||||
"salubrious",
|
||||
"sartorial",
|
||||
"sclerotic",
|
||||
"serpentine",
|
||||
"smart",
|
||||
"spasmodic",
|
||||
"strident",
|
||||
"stunning",
|
||||
"stupendous",
|
||||
"taciturn",
|
||||
"tactful",
|
||||
"tasty",
|
||||
"tenacious",
|
||||
"tremendous",
|
||||
"tremulous",
|
||||
"trenchant",
|
||||
"turbulent",
|
||||
"turgid",
|
||||
"ubiquitous",
|
||||
"uxorious",
|
||||
"verdant",
|
||||
"vibrant",
|
||||
"voluble",
|
||||
"voracious",
|
||||
"wheedling",
|
||||
"withering",
|
||||
"wonderful",
|
||||
"zealous"
|
||||
]
|
||||
}
|
107
src/datatokens/NFTDatatoken.ts
Normal file
107
src/datatokens/NFTDatatoken.ts
Normal file
@ -0,0 +1,107 @@
|
||||
import Web3 from 'web3'
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import defaultNFTDatatokenABI from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC721Template.sol/ERC721Template.json'
|
||||
import { Logger, getFairGasPrice, generateDtName } from '../utils'
|
||||
|
||||
/**
|
||||
* ERC721 ROLES
|
||||
*/
|
||||
interface Roles {
|
||||
manager: boolean
|
||||
deployERC20: boolean
|
||||
updateMetadata: boolean
|
||||
store: boolean
|
||||
}
|
||||
|
||||
export class NFTDataToken {
|
||||
public GASLIMIT_DEFAULT = 1000000
|
||||
public factory721Address: string
|
||||
public factory721ABI: AbiItem | AbiItem[]
|
||||
public nftDatatokenABI: AbiItem | AbiItem[]
|
||||
public web3: Web3
|
||||
private logger: Logger
|
||||
public startBlock: number
|
||||
|
||||
constructor(
|
||||
web3: Web3,
|
||||
logger: Logger,
|
||||
nftDatatokenABI?: AbiItem | AbiItem[],
|
||||
startBlock?: number
|
||||
) {
|
||||
this.nftDatatokenABI = nftDatatokenABI || (defaultNFTDatatokenABI.abi as AbiItem[])
|
||||
this.web3 = web3
|
||||
this.logger = logger
|
||||
this.startBlock = startBlock || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new ERC20 datatoken - only user with ERC20Deployer permission can succeed
|
||||
* @param {String} address
|
||||
* @param {String} nftAddress
|
||||
* @param {String} minter User set as initial minter for the ERC20
|
||||
* @param {String} name Token name
|
||||
* @param {String} symbol Token symbol
|
||||
* @param {String} cap Maximum cap (Number) - will be converted to wei
|
||||
* @param {Number} templateIndex NFT template index
|
||||
* @return {Promise<string>} ERC20 datatoken address
|
||||
*/
|
||||
public async createERC20(
|
||||
nftAddress: string,
|
||||
address: string,
|
||||
minter: string,
|
||||
cap: string,
|
||||
name?: string,
|
||||
symbol?: string,
|
||||
templateIndex?: number
|
||||
): Promise<string> {
|
||||
if (!templateIndex) templateIndex = 1
|
||||
|
||||
// Generate name & symbol if not present
|
||||
if (!name || !symbol) {
|
||||
;({ name, symbol } = generateDtName())
|
||||
}
|
||||
|
||||
// Create 721contract object
|
||||
const contract721 = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress)
|
||||
|
||||
// Estimate gas for ERC20 token creation
|
||||
const gasLimitDefault = this.GASLIMIT_DEFAULT
|
||||
let estGas
|
||||
try {
|
||||
estGas = await contract721.methods
|
||||
.createERC20(
|
||||
templateIndex,
|
||||
[name, symbol],
|
||||
[minter],
|
||||
[this.web3.utils.toWei(cap)],
|
||||
null
|
||||
)
|
||||
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
|
||||
} catch (e) {
|
||||
estGas = gasLimitDefault
|
||||
}
|
||||
|
||||
// Invoke createERC20 token function of the contract
|
||||
const trxReceipt = await contract721.methods
|
||||
.createERC20(
|
||||
templateIndex,
|
||||
[name, symbol],
|
||||
[minter],
|
||||
[this.web3.utils.toWei(cap)],
|
||||
null
|
||||
)
|
||||
.send({
|
||||
from: address,
|
||||
gas: estGas + 1,
|
||||
gasPrice: await getFairGasPrice(this.web3)
|
||||
})
|
||||
|
||||
let tokenAddress = null
|
||||
try {
|
||||
tokenAddress = trxReceipt.events.ERC20Created.returnValues[0]
|
||||
} catch (e) {
|
||||
this.logger.error(`ERROR: Failed to create datatoken : ${e.message}`)
|
||||
}
|
||||
return tokenAddress
|
||||
}
|
||||
}
|
1
src/datatokens/index.ts
Normal file
1
src/datatokens/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './NFTDatatoken'
|
91
src/factories/NFTFactory.ts
Normal file
91
src/factories/NFTFactory.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import { Contract } from 'web3-eth-contract'
|
||||
import Web3 from 'web3'
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import defaultFactory721ABI from '@oceanprotocol/contracts/artifacts/contracts/ERC721Factory.sol/ERC721Factory.json'
|
||||
import { Logger, getFairGasPrice, generateDtName } from '../utils'
|
||||
|
||||
/**
|
||||
* Provides an interface for NFT DataTokens
|
||||
*/
|
||||
export class NFTFactory {
|
||||
public GASLIMIT_DEFAULT = 1000000
|
||||
public factory721Address: string
|
||||
public factory721ABI: AbiItem | AbiItem[]
|
||||
public web3: Web3
|
||||
private logger: Logger
|
||||
public startBlock: number
|
||||
public factory721: Contract
|
||||
|
||||
/**
|
||||
* Instantiate DataTokens.
|
||||
* @param {String} factory721Address
|
||||
* @param {AbiItem | AbiItem[]} factory721ABI
|
||||
* @param {Web3} web3
|
||||
*/
|
||||
constructor(
|
||||
factory721Address: string,
|
||||
web3: Web3,
|
||||
logger: Logger,
|
||||
factory721ABI?: AbiItem | AbiItem[],
|
||||
startBlock?: number
|
||||
) {
|
||||
this.factory721Address = factory721Address
|
||||
this.factory721ABI = factory721ABI || (defaultFactory721ABI.abi as AbiItem[])
|
||||
this.web3 = web3
|
||||
this.logger = logger
|
||||
this.startBlock = startBlock || 0
|
||||
this.factory721 = new this.web3.eth.Contract(
|
||||
this.factory721ABI,
|
||||
this.factory721Address
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new NFT
|
||||
* @param {String} address
|
||||
* @param {String} name Token name
|
||||
* @param {String} symbol Token symbol
|
||||
* @param {Number} templateIndex NFT template index
|
||||
* @return {Promise<string>} NFT datatoken address
|
||||
*/
|
||||
public async createNFT(
|
||||
address: string,
|
||||
name?: string,
|
||||
symbol?: string,
|
||||
templateIndex?: number
|
||||
): Promise<string> {
|
||||
if (!templateIndex) templateIndex = 1
|
||||
// Generate name & symbol if not present
|
||||
if (!name || !symbol) {
|
||||
;({ name, symbol } = generateDtName())
|
||||
}
|
||||
|
||||
// Get estimated gas value
|
||||
const gasLimitDefault = this.GASLIMIT_DEFAULT
|
||||
let estGas
|
||||
try {
|
||||
estGas = await this.factory721.methods
|
||||
.deployERC721Contract(name, symbol, templateIndex, null)
|
||||
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
|
||||
} catch (e) {
|
||||
estGas = gasLimitDefault
|
||||
}
|
||||
|
||||
// Invoke createToken function of the contract
|
||||
const trxReceipt = await this.factory721.methods
|
||||
.deployERC721Contract(name, symbol, templateIndex, null)
|
||||
.send({
|
||||
from: address,
|
||||
gas: estGas + 1,
|
||||
gasPrice: await getFairGasPrice(this.web3)
|
||||
})
|
||||
|
||||
let tokenAddress = null
|
||||
try {
|
||||
tokenAddress = trxReceipt.events.TokenCreated.returnValues[0]
|
||||
} catch (e) {
|
||||
this.logger.error(`ERROR: Failed to create datatoken : ${e.message}`)
|
||||
}
|
||||
return tokenAddress
|
||||
}
|
||||
}
|
1
src/factories/index.ts
Normal file
1
src/factories/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './NFTFactory'
|
38
src/pools/balancer/OceanPool.ts
Normal file
38
src/pools/balancer/OceanPool.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import Web3 from 'web3'
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import { Contract } from 'web3-eth-contract'
|
||||
import defaultPoolABI from '@oceanprotocol/contracts/artifacts/contracts/interfaces/IPool.sol/IPool.json'
|
||||
import defaultERC20ABI from '@oceanprotocol/contracts/artifacts/contracts/interfaces/IERC20.sol/IERC20.json'
|
||||
import { PoolFactory } from './PoolFactory'
|
||||
import { Logger } from '../../utils'
|
||||
|
||||
export class OceanPoolV4 extends PoolFactory {
|
||||
public oceanAddress: string = null
|
||||
public dtAddress: string = null
|
||||
public startBlock: number
|
||||
public vaultABI: AbiItem | AbiItem[]
|
||||
public vaultAddress: string
|
||||
public vault: Contract
|
||||
public poolABI: AbiItem | AbiItem[]
|
||||
public erc20ABI: AbiItem | AbiItem[]
|
||||
|
||||
constructor(
|
||||
web3: Web3,
|
||||
logger: Logger,
|
||||
routerAddress: string = null,
|
||||
oceanAddress: string = null,
|
||||
startBlock?: number
|
||||
) {
|
||||
super(web3, logger, routerAddress)
|
||||
|
||||
this.poolABI = defaultPoolABI.abi as AbiItem[]
|
||||
this.erc20ABI = defaultERC20ABI.abi as AbiItem[]
|
||||
this.vault = new this.web3.eth.Contract(this.vaultABI, this.vaultAddress)
|
||||
|
||||
// if (oceanAddress) {
|
||||
// this.oceanAddress = oceanAddress
|
||||
// }
|
||||
if (startBlock) this.startBlock = startBlock
|
||||
else this.startBlock = 0
|
||||
}
|
||||
}
|
57
src/pools/balancer/PoolFactory.ts
Normal file
57
src/pools/balancer/PoolFactory.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import Web3 from 'web3'
|
||||
import { AbiItem } from 'web3-utils'
|
||||
import { Contract } from 'web3-eth-contract'
|
||||
import defaultRouterABI from '@oceanprotocol/contracts/artifacts/contracts/interfaces/IFactoryRouter.sol/IFactoryRouter.json'
|
||||
import { Logger } from '../../utils'
|
||||
import { TransactionReceipt } from 'web3-eth'
|
||||
|
||||
export class PoolFactory {
|
||||
public GASLIMIT_DEFAULT = 1000000
|
||||
public web3: Web3 = null
|
||||
public routerABI: AbiItem | AbiItem[]
|
||||
|
||||
public routerAddress: string
|
||||
|
||||
public logger: Logger
|
||||
public router: Contract
|
||||
|
||||
/**
|
||||
* Instantiate PoolFactory.
|
||||
* @param {String} routerAddress
|
||||
* @param {AbiItem | AbiItem[]} routerABI
|
||||
* @param {Web3} web3
|
||||
*/
|
||||
constructor(
|
||||
web3: Web3,
|
||||
logger: Logger,
|
||||
routerAddress: string,
|
||||
routerABI?: AbiItem | AbiItem[]
|
||||
) {
|
||||
this.web3 = web3
|
||||
this.routerAddress = routerAddress
|
||||
this.routerABI = routerABI || (defaultRouterABI.abi as AbiItem[])
|
||||
this.logger = logger
|
||||
this.router = new this.web3.eth.Contract(this.routerABI, this.routerAddress)
|
||||
}
|
||||
|
||||
public async deployPool(
|
||||
account: string,
|
||||
tokens: string[],
|
||||
weights: string[],
|
||||
swapFeePercentage: number,
|
||||
swapMarketFee: number,
|
||||
owner: string
|
||||
): Promise<TransactionReceipt> {
|
||||
const gasLimitDefault = this.GASLIMIT_DEFAULT
|
||||
let estGas
|
||||
try {
|
||||
estGas = await this.router.methods
|
||||
.deployPool(tokens, weightsInWei, swapFeePercentage, swapMarketFee, owner)
|
||||
.estimateGas({ from: account }, (err, estGas) => (err ? gasLimitDefault : estGas))
|
||||
} catch (e) {
|
||||
this.logger.log('Error estimate gas deployPool')
|
||||
this.logger.log(e)
|
||||
estGas = gasLimitDefault
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
export * from './PoolFactory'
|
||||
export * from './OceanPool'
|
27
src/utils/DatatokenName.ts
Normal file
27
src/utils/DatatokenName.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import wordListDefault from '../data/words.json'
|
||||
|
||||
/**
|
||||
* Generate new datatoken name & symbol from a word list
|
||||
* @return {<{ name: String; symbol: String }>} datatoken name & symbol. Produces e.g. "Endemic Jellyfish Token" & "ENDJEL-45"
|
||||
*/
|
||||
export function generateDtName(wordList?: { nouns: string[]; adjectives: string[] }): {
|
||||
name: string
|
||||
symbol: string
|
||||
} {
|
||||
const list = wordList || wordListDefault
|
||||
const random1 = Math.floor(Math.random() * list.adjectives.length)
|
||||
const random2 = Math.floor(Math.random() * list.nouns.length)
|
||||
const indexNumber = Math.floor(Math.random() * 100)
|
||||
|
||||
// Capitalized adjective & noun
|
||||
const adjective = list.adjectives[random1].replace(/^\w/, (c) => c.toUpperCase())
|
||||
const noun = list.nouns[random2].replace(/^\w/, (c) => c.toUpperCase())
|
||||
|
||||
const name = `${adjective} ${noun} Token`
|
||||
// use first 3 letters of name, uppercase it, and add random number
|
||||
const symbol = `${(
|
||||
adjective.substring(0, 3) + noun.substring(0, 3)
|
||||
).toUpperCase()}-${indexNumber}`
|
||||
|
||||
return { name, symbol }
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
export * from './Logger'
|
||||
export * from './GasUtils'
|
||||
export * from './Logger'
|
||||
export * from './DatatokenName'
|
||||
|
Loading…
x
Reference in New Issue
Block a user