import { ErrorDescription as InterfaceErrorDescription, Result as InterfaceResult, } from '@ethersproject/abi/lib/interface'; import { BytesLike } from 'ethers'; import { Ethereum } from '../ethereum'; enum Billing { Mint, AddAccessPoint, } enum CollectionRoles { Owner, Verifier, } enum TokenRoles { Controller, } export const FleekERC721 = { contract: Ethereum.getContract('FleekERC721'), Enums: { Billing, CollectionRoles, TokenRoles, }, async mint( params: FleekERC721.MintParams, provider: Ethereum.Providers ): Promise { const response = await this.contract.connect(provider).mint( params.owner, params.name, params.description.replaceAll(/\n/g, '\\n'), //replace break lines with \\n so it doesn't break the json, params.image, params.externalUrl, params.ens, params.commitHash, params.repo ); return response; }, async tokenMetadata(tokenId: number): Promise { const response = await this.contract.tokenURI(Number(tokenId)); const parsed = JSON.parse( Buffer.from(response.slice(29), 'base64') .toString('utf-8') .replaceAll(/\n/g, '\\n') // replace escaped newlines ); return parsed; }, async lastTokenId(): Promise { const contract = Ethereum.getContract('FleekERC721'); return contract.getLastTokenId(); }, async getBilling(key: keyof typeof Billing): Promise { const contract = Ethereum.getContract('FleekERC721'); return (await contract.getBilling(this.Enums.Billing[key])).toString(); }, parseError(error: BytesLike): FleekERC721.TransactionError { try { if (!error) throw new Error('Empty error'); const description = this.contract.interface.parseError(error); const result = this.contract.interface.decodeErrorResult( description.signature, error ); let message: string; switch (description.signature) { case 'ContractIsNotPausable()': message = 'This contract is not pausable'; break; case 'ContractIsNotPaused()': message = 'This contract is not paused'; break; case 'ContractIsPaused()': message = 'This contract is paused'; break; case 'MustBeTokenOwner(uint256)': message = `You must be the token #${result.tokenId} owner`; break; case 'MustHaveAtLeastOneOwner()': message = 'You must have at least one owner'; break; case 'MustHaveCollectionRole(uint8)': message = `You must have a collection role "${ CollectionRoles[result.role] }" to mint`; break; case 'MustHaveTokenRole(uint256,uint8)': message = `You must have a token role "${ TokenRoles[result.role] }" on token #${result.tokenId}`; break; case 'PausableIsSetTo(bool)': message = `Pausable is set to "${result.isPausable}"`; break; case 'RoleAlreadySet()': message = `Role is already set`; break; case 'ThereIsNoTokenMinted()': message = `There is no token minted`; break; default: message = 'Unknown error'; } return { message, description, result, isIdentified: true, }; } catch { return { message: 'Unknown error', description: null, result: null, isIdentified: false, }; } }, }; export namespace FleekERC721 { export type MintParams = { name: string; description: string; owner: string; externalUrl: string; image: string; ens?: string; commitHash: string; repo: string; }; export type Metadata = Omit & { attributes: [ { trait_type: string; value: string; } ]; }; export type TransactionError = { message: string; description: InterfaceErrorDescription | null; result: InterfaceResult | null; isIdentified: boolean; }; }