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:
parent
d6f8d047c8
commit
fbee0945fd
|
|
@ -1,13 +1,27 @@
|
||||||
|
import {
|
||||||
|
ErrorDescription as InterfaceErrorDescription,
|
||||||
|
Result as InterfaceResult,
|
||||||
|
} from '@ethersproject/abi/lib/interface';
|
||||||
|
import { BytesLike } from 'ethers';
|
||||||
import { Ethereum } from '../ethereum';
|
import { Ethereum } from '../ethereum';
|
||||||
|
|
||||||
|
enum CollectionRoles {
|
||||||
|
Owner,
|
||||||
|
Verifier,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TokenRoles {
|
||||||
|
Controller,
|
||||||
|
}
|
||||||
|
|
||||||
export const FleekERC721 = {
|
export const FleekERC721 = {
|
||||||
|
contract: Ethereum.getContract('FleekERC721'),
|
||||||
|
|
||||||
async mint(
|
async mint(
|
||||||
params: FleekERC721.MintParams,
|
params: FleekERC721.MintParams,
|
||||||
provider: Ethereum.Providers
|
provider: Ethereum.Providers
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const contract = Ethereum.getContract('FleekERC721', provider);
|
const response = await this.contract.connect(provider).mint(
|
||||||
|
|
||||||
const response = await contract.mint(
|
|
||||||
params.owner,
|
params.owner,
|
||||||
params.name,
|
params.name,
|
||||||
params.description.replaceAll(/\n/g, '\\n'), //replace break lines with \\n so it doesn't break the json,
|
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
|
// TODO: fetch last token id
|
||||||
return 7;
|
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 {
|
export namespace FleekERC721 {
|
||||||
|
|
@ -61,4 +152,11 @@ export namespace FleekERC721 {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TransactionError = {
|
||||||
|
message: string;
|
||||||
|
description: InterfaceErrorDescription | null;
|
||||||
|
result: InterfaceResult | null;
|
||||||
|
isIdentified: boolean;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 { useState } from 'react';
|
||||||
|
|
||||||
|
import { ComboboxItem, DropdownItem } from '@/components';
|
||||||
|
import { Ethereum, EthereumHooks } from '@/integrations';
|
||||||
|
import { GithubState } from '@/store';
|
||||||
|
import { createContext } from '@/utils';
|
||||||
|
|
||||||
export type MintContext = {
|
export type MintContext = {
|
||||||
selectedUserOrg: ComboboxItem;
|
selectedUserOrg: ComboboxItem;
|
||||||
repositoryName: GithubState.Repository;
|
repositoryName: GithubState.Repository;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ type NftCardProps = {
|
||||||
message: string;
|
message: string;
|
||||||
buttonText: string;
|
buttonText: string;
|
||||||
leftIconButton?: React.ReactNode;
|
leftIconButton?: React.ReactNode;
|
||||||
onClick: () => void;
|
onClick?: () => void;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ export const NftCard: React.FC<NftCardProps> = ({
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
leftIcon={leftIconButton}
|
leftIcon={leftIconButton}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
isDisabled={isLoading}
|
isDisabled={isLoading || !onClick}
|
||||||
>
|
>
|
||||||
{buttonText}
|
{buttonText}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Icon, IconButton, Stepper } from '@/components';
|
import { Icon, IconButton, Stepper } from '@/components';
|
||||||
import { useTransactionCost } from '@/hooks';
|
import { useTransactionCost } from '@/hooks';
|
||||||
|
import { FleekERC721 } from '@/integrations';
|
||||||
import { Mint } from '@/views/mint/mint.context';
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
@ -8,7 +9,7 @@ import { NftCard } from '../nft-card';
|
||||||
export const MintPreview = () => {
|
export const MintPreview = () => {
|
||||||
const { prevStep } = Stepper.useContext();
|
const { prevStep } = Stepper.useContext();
|
||||||
const {
|
const {
|
||||||
prepare: { status: prepareStatus, data: prepareData },
|
prepare: { status: prepareStatus, data: prepareData, error: prepareError },
|
||||||
write: { status: writeStatus, write },
|
write: { status: writeStatus, write },
|
||||||
transaction: { status: transactionStatus },
|
transaction: { status: transactionStatus },
|
||||||
} = Mint.useTransactionContext();
|
} = Mint.useTransactionContext();
|
||||||
|
|
@ -24,6 +25,18 @@ export const MintPreview = () => {
|
||||||
if (isCostLoading || prepareStatus === 'loading')
|
if (isCostLoading || prepareStatus === 'loading')
|
||||||
return 'Calculating cost...';
|
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);
|
const formattedCost = ethers.utils.formatEther(cost).slice(0, 9);
|
||||||
return `Minting this NFA will cost ${formattedCost} ${currency}.`;
|
return `Minting this NFA will cost ${formattedCost} ${currency}.`;
|
||||||
}, [prepareData, isCostLoading, prepareStatus]);
|
}, [prepareData, isCostLoading, prepareStatus]);
|
||||||
|
|
@ -59,7 +72,7 @@ export const MintPreview = () => {
|
||||||
}
|
}
|
||||||
message={message}
|
message={message}
|
||||||
buttonText="Mint NFA"
|
buttonText="Mint NFA"
|
||||||
onClick={write!}
|
onClick={write}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue