diff --git a/src/datatokens/Datatoken.ts b/src/datatokens/Datatoken.ts index 5c7587e5..b0a48086 100644 --- a/src/datatokens/Datatoken.ts +++ b/src/datatokens/Datatoken.ts @@ -132,6 +132,197 @@ export class Datatoken { return estGas } + /** + * Estimate gas cost for createFixedRate method + * @param {String} dtAddress Datatoken address + * @param {String} address Caller address + * @param {String} fixedPriceAddress + * @param {String} baseTokenAddress + * @param {String} marketFeeCollector + * @param {String} baseTokenDecimals + * @param {String} dataTokenDecimals + * @param {String} fixedRate + * @param {String} marketFee + * @param {String} withMint + * @param {Contract} contractInstance optional contract instance + * @return {Promise} + */ + public async estGasCreateFixedRate( + dtAddress: string, + address: string, + fixedPriceAddress: string, + baseTokenAddress: string, + marketFeeCollector: string, + baseTokenDecimals: number, + dataTokenDecimals: number, + fixedRate: number, + marketFee: number, + withMint: number, + contractInstance?: Contract + ): Promise { + const dtContract = + contractInstance || new this.web3.eth.Contract(this.datatokensABI, dtAddress) + + const gasLimitDefault = this.GASLIMIT_DEFAULT + let estGas + try { + estGas = await dtContract.methods + .createFixedRate( + fixedPriceAddress, + [baseTokenAddress, address, marketFeeCollector], + [baseTokenDecimals, dataTokenDecimals, fixedRate, marketFee, withMint] + ) + .estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas)) + } catch (e) { + estGas = gasLimitDefault + } + + return estGas + } + + /** + * Creates a new FixedRateExchange setup. + * @param {String} dtAddress Datatoken address + * @param {String} address Caller address + * @param {String} fixedPriceAddress + * @param {String} baseTokenAddress + * @param {String} marketFeeCollector + * @param {String} baseTokenDecimals + * @param {String} dataTokenDecimals + * @param {String} fixedRate + * @param {String} marketFee + * @param {String} withMint + * @return {Promise} transactionId + */ + public async createFixedRate( + dtAddress: string, + address: string, + fixedPriceAddress: string, + baseTokenAddress: string, + marketFeeCollector: string, + baseTokenDecimals: number, + dataTokenDecimals: number, + fixedRate: number, + marketFee: number, + withMint: number + ): Promise { + const dtContract = new this.web3.eth.Contract(this.datatokensABI, dtAddress) + + // should check ERC20Deployer role using erc721 level .. + + const estGas = await this.estGasCreateFixedRate( + dtAddress, + address, + fixedPriceAddress, + baseTokenAddress, + marketFeeCollector, + baseTokenDecimals, + dataTokenDecimals, + fixedRate, + marketFee, + withMint, + dtContract + ) + + // Call createFixedRate contract method + const trxReceipt = await dtContract.methods + .createFixedRate( + fixedPriceAddress, + [baseTokenAddress, address, marketFeeCollector], + [baseTokenDecimals, dataTokenDecimals, fixedRate, marketFee, withMint] + ) + .send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3) + }) + return trxReceipt + } + + /** + * Estimate gas cost for createDispenser method + * @param {String} dtAddress Datatoken address + * @param {String} address Caller address + * @param {String} dispenser ispenser contract address + * @param {String} maxTokens max tokens to dispense + * @param {String} maxBalance max balance of requester + * @param {Boolean} withMint true if we want to allow the dispenser to be a minter + * @param {String} allowedSwapper only account that can ask tokens. set address(0) if not required + * @param {Contract} contractInstance optional contract instance + * @return {Promise} + */ + public async estGasCreateDispenser( + dtAddress: string, + address: string, + dispenser: string, + maxTokens: string, + maxBalance: string, + withMint: Boolean, + allowedSwapper: string, + contractInstance?: Contract + ): Promise { + const dtContract = + contractInstance || new this.web3.eth.Contract(this.datatokensABI, dtAddress) + + const gasLimitDefault = this.GASLIMIT_DEFAULT + let estGas + try { + estGas = await dtContract.methods + .createDispenser(dispenser, maxTokens, maxBalance, withMint, allowedSwapper) + .estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas)) + } catch (e) { + estGas = gasLimitDefault + } + + return estGas + } + + /** + * Creates a new Dispenser + * @param {String} dtAddress Datatoken address + * @param {String} address Caller address + * @param {String} dispenser ispenser contract address + * @param {String} maxTokens max tokens to dispense + * @param {String} maxBalance max balance of requester + * @param {Boolean} withMint true if we want to allow the dispenser to be a minter + * @param {String} allowedSwapper only account that can ask tokens. set address(0) if not required + * @return {Promise} transactionId + */ + public async createDispenser( + dtAddress: string, + address: string, + dispenser: string, + maxTokens: string, + maxBalance: string, + withMint: Boolean, + allowedSwapper: string + ): Promise { + const dtContract = new this.web3.eth.Contract(this.datatokensABI, dtAddress) + + // should check ERC20Deployer role using erc721 level .. + + const estGas = await this.estGasCreateDispenser( + dtAddress, + address, + dispenser, + maxTokens, + maxBalance, + withMint, + allowedSwapper, + dtContract + ) + + // Call createFixedRate contract method + const trxReceipt = await dtContract.methods + .createDispenser(dispenser, maxTokens, maxBalance, withMint, allowedSwapper) + .send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3) + }) + return trxReceipt + } + /** * Mint * @param {String} dtAddress Datatoken address @@ -816,6 +1007,16 @@ export class Datatoken { return this.web3.utils.fromWei(cap) } + /** It returns the token decimals, how many supported decimal points + * @param {String} dtAddress Datatoken adress + * @return {Promise} + */ + public async getDecimals(dtAddress: string): Promise { + const dtContract = new this.web3.eth.Contract(this.datatokensABI, dtAddress) + const decimals = await dtContract.methods.decimals().call() + return decimals + } + /** * Get Address Balance for datatoken * @param {String} dtAddress Datatoken adress diff --git a/src/datatokens/NFTDatatoken.ts b/src/datatokens/NFTDatatoken.ts index bdeb75a8..18ba374d 100644 --- a/src/datatokens/NFTDatatoken.ts +++ b/src/datatokens/NFTDatatoken.ts @@ -801,6 +801,184 @@ export class NFTDatatoken { return trxReceipt } + /** + * Estimate gas cost for safeTransfer NFT method + * @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 + * @param {Contract} nftContract optional contract instance + * @return {Promise} + */ + public async estGasSafeTransferNFT( + nftAddress: string, + nftOwner: string, + nftReceiver: string, + tokenId: number, + contractInstance?: Contract + ): Promise { + const nftContract = + contractInstance || new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress) + + const gasLimitDefault = this.GASLIMIT_DEFAULT + let estGas + try { + estGas = await nftContract.methods + .safeTransferFrom(nftOwner, nftReceiver, tokenId) + .estimateGas({ from: nftOwner }, (err, estGas) => + err ? gasLimitDefault : estGas + ) + } catch (e) { + estGas = gasLimitDefault + } + + return estGas + } + + /** + * safeTransferNFT Used for transferring the NFT, can be used by an approved relayer + * 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} trxReceipt + */ + public async safeTransferNFT( + nftAddress: string, + nftOwner: string, + nftReceiver: string, + tokenId?: number + ): Promise { + const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress) + + if ((await this.getNFTOwner(nftAddress)) !== nftOwner) { + throw new Error(`Caller is not NFT Owner`) + } + + const tokenIdentifier = tokenId || 1 + + const estGas = await this.estGasSafeTransferNFT( + nftAddress, + nftOwner, + nftReceiver, + tokenIdentifier, + nftContract + ) + + // Call transferFrom function of the contract + const trxReceipt = await nftContract.methods + .safeTransferFrom(nftOwner, nftReceiver, tokenIdentifier) + .send({ + from: nftOwner, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3) + }) + + return trxReceipt + } + + /** + * Estimate gas cost for setMetadata method + * @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 + * @param {Contract} nftContract optional contract instance + * @return {Promise} + */ + public async estGasSetMetadata( + nftAddress: string, + nftOwner: string, + metadataState: number, + metaDataDecryptorUrl: string, + metaDataDecryptorAddress: string, + flags: string, + data: string, + metadataHash: string, + contractInstance?: Contract + ): Promise { + const nftContract = + contractInstance || new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress) + + const gasLimitDefault = this.GASLIMIT_DEFAULT + let estGas + try { + estGas = await nftContract.methods + .setMetaData( + metadataState, + metaDataDecryptorUrl, + metaDataDecryptorAddress, + flags, + data, + metadataHash + ) + .estimateGas({ from: nftOwner }, (err, estGas) => + err ? gasLimitDefault : estGas + ) + } catch (e) { + estGas = gasLimitDefault + } + + return estGas + } + + /** + * safeTransferNFT Used for transferring the NFT, can be used by an approved relayer + * will clean all permissions both on erc721 and erc20 level. + * @param {String} nftAddress erc721 contract adress + * @param {String} address Caller address 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} trxReceipt + */ + public async setMetadata( + nftAddress: string, + address: string, + metadataState: number, + metaDataDecryptorUrl: string, + metaDataDecryptorAddress: string, + flags: string, + data: string, + metadataHash: string + ): Promise { + const nftContract = new this.web3.eth.Contract(this.nftDatatokenABI, nftAddress) + + if (!(await this.getNFTPermissions(nftAddress, address)).updateMetadata) { + throw new Error(`Caller is not NFT Owner`) + } + + const estGas = await this.estGasSetMetadata( + nftAddress, + address, + metadataState, + metaDataDecryptorUrl, + metaDataDecryptorAddress, + flags, + data, + metadataHash, + nftContract + ) + + // Call transferFrom function of the contract + const trxReceipt = await nftContract.methods + .setMetaData( + metadataState, + metaDataDecryptorUrl, + metaDataDecryptorAddress, + flags, + data, + metadataHash + ) + .send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3) + }) + + return trxReceipt + } + /** Get Owner * @param {String} nftAddress erc721 contract adress * @return {Promise} string