bug: mint button not triggering in dev hosted (#170)

* feat: parse error code using abi

* feat: add prepare error treatment on mint flow
This commit is contained in:
Felipe Mendes 2023-03-13 10:22:58 -03:00 committed by GitHub
parent d6f8d047c8
commit fbee0945fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 123 additions and 11 deletions

View File

@ -1,13 +1,27 @@
import {
ErrorDescription as InterfaceErrorDescription,
Result as InterfaceResult,
} from '@ethersproject/abi/lib/interface';
import { BytesLike } from 'ethers';
import { Ethereum } from '../ethereum';
enum CollectionRoles {
Owner,
Verifier,
}
enum TokenRoles {
Controller,
}
export const FleekERC721 = {
contract: Ethereum.getContract('FleekERC721'),
async mint(
params: FleekERC721.MintParams,
provider: Ethereum.Providers
): Promise<void> {
const contract = Ethereum.getContract('FleekERC721', provider);
const response = await contract.mint(
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,
@ -39,6 +53,83 @@ export const FleekERC721 = {
// TODO: fetch last token id
return 7;
},
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 {
@ -61,4 +152,11 @@ export namespace FleekERC721 {
}
];
};
export type TransactionError = {
message: string;
description: InterfaceErrorDescription | null;
result: InterfaceResult | null;
isIdentified: boolean;
};
}

View File

@ -1,9 +1,10 @@
import { ComboboxItem, DropdownItem } from '@/components';
import { GithubState } from '@/store';
import { EthereumHooks } from '@/integrations';
import { createContext } from '@/utils';
import { useState } from 'react';
import { ComboboxItem, DropdownItem } from '@/components';
import { Ethereum, EthereumHooks } from '@/integrations';
import { GithubState } from '@/store';
import { createContext } from '@/utils';
export type MintContext = {
selectedUserOrg: ComboboxItem;
repositoryName: GithubState.Repository;

View File

@ -9,7 +9,7 @@ type NftCardProps = {
message: string;
buttonText: string;
leftIconButton?: React.ReactNode;
onClick: () => void;
onClick?: () => void;
isLoading: boolean;
};
@ -53,7 +53,7 @@ export const NftCard: React.FC<NftCardProps> = ({
onClick={onClick}
leftIcon={leftIconButton}
isLoading={isLoading}
isDisabled={isLoading}
isDisabled={isLoading || !onClick}
>
{buttonText}
</Button>

View File

@ -1,5 +1,6 @@
import { Icon, IconButton, Stepper } from '@/components';
import { useTransactionCost } from '@/hooks';
import { FleekERC721 } from '@/integrations';
import { Mint } from '@/views/mint/mint.context';
import { ethers } from 'ethers';
import { useMemo } from 'react';
@ -8,7 +9,7 @@ import { NftCard } from '../nft-card';
export const MintPreview = () => {
const { prevStep } = Stepper.useContext();
const {
prepare: { status: prepareStatus, data: prepareData },
prepare: { status: prepareStatus, data: prepareData, error: prepareError },
write: { status: writeStatus, write },
transaction: { status: transactionStatus },
} = Mint.useTransactionContext();
@ -24,6 +25,18 @@ export const MintPreview = () => {
if (isCostLoading || prepareStatus === 'loading')
return 'Calculating cost...';
// TODO: better UI for prepare errors
if (prepareError) {
const parsedError = FleekERC721.parseError(
(prepareError as any).error?.data.data
);
if (parsedError.isIdentified) {
return parsedError.message;
}
return 'An error occurred while preparing the transaction';
}
const formattedCost = ethers.utils.formatEther(cost).slice(0, 9);
return `Minting this NFA will cost ${formattedCost} ${currency}.`;
}, [prepareData, isCostLoading, prepareStatus]);
@ -59,7 +72,7 @@ export const MintPreview = () => {
}
message={message}
buttonText="Mint NFA"
onClick={write!}
onClick={write}
isLoading={isLoading}
/>
);