diff --git a/src/@types/Datatoken.ts b/src/@types/Datatoken.ts index 31c8b09f..063d3b21 100644 --- a/src/@types/Datatoken.ts +++ b/src/@types/Datatoken.ts @@ -10,6 +10,7 @@ export interface DatatokenCreateParams { cap: string name?: string symbol?: string + fileObject?: any // file object for template 4 } export interface ConsumeMarketFee { diff --git a/src/utils/Assets.ts b/src/utils/Assets.ts new file mode 100644 index 00000000..42c91496 --- /dev/null +++ b/src/utils/Assets.ts @@ -0,0 +1,184 @@ +import { SHA256 } from 'crypto-js' +import { ethers, Signer } from 'ethers' +import { + Aquarius, + DatatokenCreateParams, + Nft, + NftCreateData, + NftFactory, + ProviderInstance, + ZERO_ADDRESS, + // approveWei, + // ProviderComputeInitialize, + // ConsumeMarketFee, + // Datatoken, + // Config, + // DDO, + // ProviderFees, + getEventFromTx, + DispenserCreationParams, + FreCreationParams +} from '../../src' +import { hexlify } from 'ethers/lib/utils' +import { createHash } from 'crypto' + +const VALID_TEMPLATE_INDEXES = [1, 2, 4] +/** + * + * @param name asset name + * @param symbol asse symbol + * @param owner owner address + * @param assetUrl asset url + * @param templateIndex 1,2 or 4 + * @param ddo ddo + * @param encryptDDO encrypt or not? + * @param providerUrl the provider URL + * @param providerFeeToken the provider fee token + * @param nftContractAddress the nft contract address + * @param aquariusInstance aquarius, could be node instance url + * @param dispenserAddress dispenser address + * @param fixedRateAddress fixed rate exchange address + * @param baseTokenAddress base token address (ocean) + * @returns ddo id as string + */ +export async function createAsset( + name: string, + symbol: string, + owner: Signer, + assetUrl: any, + templateIndex: number, + ddo: any, + encryptDDO: boolean = true, // default is true + providerUrl: string, + providerFeeToken: string, + nftContractAddress: string, // addresses.ERC721Factory, + aquariusInstance: Aquarius, + filesObject: any, + // fixed rate + dispenserAddress?: string, + fixedRateAddress?: string, + baseTokenAddress? +): Promise { + if (!VALID_TEMPLATE_INDEXES.includes(templateIndex)) { + throw new Error('Invalid template index: ' + templateIndex) + } + + const chain = (await owner.provider.getNetwork()).chainId + + const nft = new Nft(owner, chain) + + const nftFactory = new NftFactory(nftContractAddress, owner) + + const account = await owner.getAddress() + + ddo.chainId = parseInt(chain.toString(10)) + const nftParamsAsset: NftCreateData = { + name, + symbol, + templateIndex, + tokenURI: 'aaa', + transferable: true, + owner: account + } + const datatokenParams: DatatokenCreateParams = { + templateIndex, + cap: '100000', + feeAmount: '0', + paymentCollector: account, + feeToken: providerFeeToken, + minter: account, + mpFeeAddress: ZERO_ADDRESS + } + + // include fileObject in the DT constructor + if (templateIndex === 4) { + datatokenParams.fileObject = filesObject + } + + let bundleNFT + + if (!ddo.stats?.price?.value) { + bundleNFT = await nftFactory.createNftWithDatatoken(nftParamsAsset, datatokenParams) + } else if (ddo.stats?.price?.value === '0') { + const dispenserParams: DispenserCreationParams = { + dispenserAddress, + maxTokens: '1', + maxBalance: '100000000', + withMint: true, + allowedSwapper: ZERO_ADDRESS + } + bundleNFT = await nftFactory.createNftWithDatatokenWithDispenser( + nftParamsAsset, + datatokenParams, + dispenserParams + ) + } else { + // fixed price + const fixedPriceParams: FreCreationParams = { + fixedRateAddress, + baseTokenAddress, + owner: account, + marketFeeCollector: account, + baseTokenDecimals: 18, + datatokenDecimals: 18, + fixedRate: ddo.stats.price.value, + marketFee: '0', + allowedConsumer: account, + withMint: true + } + bundleNFT = await nftFactory.createNftWithDatatokenWithFixedRate( + nftParamsAsset, + datatokenParams, + fixedPriceParams + ) + } + + const trxReceipt = await bundleNFT.wait() + // events have been emitted + const nftCreatedEvent = getEventFromTx(trxReceipt, 'NFTCreated') + const tokenCreatedEvent = getEventFromTx(trxReceipt, 'TokenCreated') + + const nftAddress = nftCreatedEvent.args.newTokenAddress + const datatokenAddressAsset = tokenCreatedEvent.args.newTokenAddress + // create the files encrypted string + assetUrl.datatokenAddress = datatokenAddressAsset + assetUrl.nftAddress = nftAddress + // TODO if template 4?? + if (templateIndex !== 4) { + ddo.services[0].files = await ProviderInstance.encrypt(assetUrl, chain, providerUrl) + } + + ddo.services[0].datatokenAddress = datatokenAddressAsset + ddo.services[0].serviceEndpoint = providerUrl + + ddo.nftAddress = nftAddress + ddo.id = 'did:op:' + SHA256(ethers.utils.getAddress(nftAddress) + chain.toString(10)) + + let metadata + let metadataHash + let flags + if (encryptDDO) { + metadata = await ProviderInstance.encrypt(ddo, chain, providerUrl) + const validateResult = await aquariusInstance.validate(ddo) + metadataHash = validateResult.hash + flags = 2 + } else { + const stringDDO = JSON.stringify(ddo) + const bytes = Buffer.from(stringDDO) + metadata = hexlify(bytes) + metadataHash = '0x' + createHash('sha256').update(metadata).digest('hex') + flags = 0 + } + + await nft.setMetadata( + nftAddress, + await owner.getAddress(), + 0, + providerUrl, + '', + ethers.utils.hexlify(flags), + metadata, + metadataHash + ) + return ddo.id +}