Add detailed minting progress indicator (#536)
This commit is contained in:
parent
afa73822d8
commit
3e8bda0a20
|
@ -16,7 +16,7 @@ import {
|
||||||
WalletSigner,
|
WalletSigner,
|
||||||
Attribute,
|
Attribute,
|
||||||
} from '@oyster/common';
|
} from '@oyster/common';
|
||||||
import React from 'react';
|
import React, { Dispatch, SetStateAction } from 'react';
|
||||||
import { MintLayout, Token } from '@solana/spl-token';
|
import { MintLayout, Token } from '@solana/spl-token';
|
||||||
import {
|
import {
|
||||||
Keypair,
|
Keypair,
|
||||||
|
@ -86,6 +86,7 @@ export const mintNFT = async (
|
||||||
creators: Creator[] | null;
|
creators: Creator[] | null;
|
||||||
sellerFeeBasisPoints: number;
|
sellerFeeBasisPoints: number;
|
||||||
},
|
},
|
||||||
|
progressCallback: Dispatch<SetStateAction<number>>,
|
||||||
maxSupply?: number,
|
maxSupply?: number,
|
||||||
): Promise<{
|
): Promise<{
|
||||||
metadataAccount: StringPublicKey;
|
metadataAccount: StringPublicKey;
|
||||||
|
@ -120,6 +121,8 @@ export const mintNFT = async (
|
||||||
const { instructions: pushInstructions, signers: pushSigners } =
|
const { instructions: pushInstructions, signers: pushSigners } =
|
||||||
await prepPayForFilesTxn(wallet, realFiles, metadata);
|
await prepPayForFilesTxn(wallet, realFiles, metadata);
|
||||||
|
|
||||||
|
progressCallback(1)
|
||||||
|
|
||||||
const TOKEN_PROGRAM_ID = programIds().token;
|
const TOKEN_PROGRAM_ID = programIds().token;
|
||||||
|
|
||||||
// Allocate memory for the account
|
// Allocate memory for the account
|
||||||
|
@ -183,6 +186,7 @@ export const mintNFT = async (
|
||||||
instructions,
|
instructions,
|
||||||
wallet.publicKey.toBase58(),
|
wallet.publicKey.toBase58(),
|
||||||
);
|
);
|
||||||
|
progressCallback(2)
|
||||||
|
|
||||||
// TODO: enable when using payer account to avoid 2nd popup
|
// TODO: enable when using payer account to avoid 2nd popup
|
||||||
// const block = await connection.getRecentBlockhash('singleGossip');
|
// const block = await connection.getRecentBlockhash('singleGossip');
|
||||||
|
@ -194,6 +198,7 @@ export const mintNFT = async (
|
||||||
// }),
|
// }),
|
||||||
// );
|
// );
|
||||||
|
|
||||||
|
|
||||||
const { txid } = await sendTransactionWithRetry(
|
const { txid } = await sendTransactionWithRetry(
|
||||||
connection,
|
connection,
|
||||||
wallet,
|
wallet,
|
||||||
|
@ -201,9 +206,11 @@ export const mintNFT = async (
|
||||||
signers,
|
signers,
|
||||||
'single',
|
'single',
|
||||||
);
|
);
|
||||||
|
progressCallback(3)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await connection.confirmTransaction(txid, 'max');
|
await connection.confirmTransaction(txid, 'max');
|
||||||
|
progressCallback(4)
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
@ -212,6 +219,8 @@ export const mintNFT = async (
|
||||||
// await connection.confirmTransaction(txid, 'max');
|
// await connection.confirmTransaction(txid, 'max');
|
||||||
await connection.getParsedConfirmedTransaction(txid, 'confirmed');
|
await connection.getParsedConfirmedTransaction(txid, 'confirmed');
|
||||||
|
|
||||||
|
progressCallback(5)
|
||||||
|
|
||||||
// this means we're done getting AR txn setup. Ship it off to ARWeave!
|
// this means we're done getting AR txn setup. Ship it off to ARWeave!
|
||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
data.append('transaction', txid);
|
data.append('transaction', txid);
|
||||||
|
@ -228,7 +237,9 @@ export const mintNFT = async (
|
||||||
realFiles.map(f => data.append('file[]', f));
|
realFiles.map(f => data.append('file[]', f));
|
||||||
|
|
||||||
// TODO: convert to absolute file name for image
|
// TODO: convert to absolute file name for image
|
||||||
|
|
||||||
const result: IArweaveResult = await uploadToArweave(data);
|
const result: IArweaveResult = await uploadToArweave(data);
|
||||||
|
progressCallback(6)
|
||||||
|
|
||||||
const metadataFile = result.messages?.find(
|
const metadataFile = result.messages?.find(
|
||||||
m => m.filename === RESERVED_TXN_MANIFEST,
|
m => m.filename === RESERVED_TXN_MANIFEST,
|
||||||
|
@ -265,6 +276,8 @@ export const mintNFT = async (
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
progressCallback(7)
|
||||||
// // In this instruction, mint authority will be removed from the main mint, while
|
// // In this instruction, mint authority will be removed from the main mint, while
|
||||||
// // minting authority will be maintained for the Printing mint (which we want.)
|
// // minting authority will be maintained for the Printing mint (which we want.)
|
||||||
await createMasterEdition(
|
await createMasterEdition(
|
||||||
|
@ -296,6 +309,8 @@ export const mintNFT = async (
|
||||||
// updateInstructions,
|
// updateInstructions,
|
||||||
// );
|
// );
|
||||||
|
|
||||||
|
progressCallback(8)
|
||||||
|
|
||||||
const txid = await sendTransactionWithRetry(
|
const txid = await sendTransactionWithRetry(
|
||||||
connection,
|
connection,
|
||||||
wallet,
|
wallet,
|
||||||
|
|
|
@ -8,12 +8,12 @@ import {
|
||||||
Input,
|
Input,
|
||||||
Statistic,
|
Statistic,
|
||||||
Slider,
|
Slider,
|
||||||
Progress,
|
|
||||||
Spin,
|
Spin,
|
||||||
InputNumber,
|
InputNumber,
|
||||||
Form,
|
Form,
|
||||||
Typography,
|
Typography,
|
||||||
Space,
|
Space,
|
||||||
|
Card,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { ArtCard } from './../../components/ArtCard';
|
import { ArtCard } from './../../components/ArtCard';
|
||||||
import { UserSearch, UserValue } from './../../components/UserSearch';
|
import { UserSearch, UserValue } from './../../components/UserSearch';
|
||||||
|
@ -41,7 +41,7 @@ import { useHistory, useParams } from 'react-router-dom';
|
||||||
import { cleanName, getLast } from '../../utils/utils';
|
import { cleanName, getLast } from '../../utils/utils';
|
||||||
import { AmountLabel } from '../../components/AmountLabel';
|
import { AmountLabel } from '../../components/AmountLabel';
|
||||||
import useWindowDimensions from '../../utils/layout';
|
import useWindowDimensions from '../../utils/layout';
|
||||||
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
import { LoadingOutlined, MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
const { Step } = Steps;
|
const { Step } = Steps;
|
||||||
const { Dragger } = Upload;
|
const { Dragger } = Upload;
|
||||||
|
@ -55,6 +55,7 @@ export const ArtCreateView = () => {
|
||||||
const { step_param }: { step_param: string } = useParams();
|
const { step_param }: { step_param: string } = useParams();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { width } = useWindowDimensions();
|
const { width } = useWindowDimensions();
|
||||||
|
const [nftCreateProgress, setNFTcreateProgress] = useState<number>(0)
|
||||||
|
|
||||||
const [step, setStep] = useState<number>(0);
|
const [step, setStep] = useState<number>(0);
|
||||||
const [stepsVisible, setStepsVisible] = useState<boolean>(true);
|
const [stepsVisible, setStepsVisible] = useState<boolean>(true);
|
||||||
|
@ -118,6 +119,7 @@ export const ArtCreateView = () => {
|
||||||
env,
|
env,
|
||||||
files,
|
files,
|
||||||
metadata,
|
metadata,
|
||||||
|
setNFTcreateProgress,
|
||||||
attributes.properties?.maxSupply,
|
attributes.properties?.maxSupply,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -205,6 +207,7 @@ export const ArtCreateView = () => {
|
||||||
<WaitingStep
|
<WaitingStep
|
||||||
mint={mint}
|
mint={mint}
|
||||||
minting={isMinting}
|
minting={isMinting}
|
||||||
|
step={nftCreateProgress}
|
||||||
confirm={() => gotoStep(6)}
|
confirm={() => gotoStep(6)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -1139,6 +1142,7 @@ const WaitingStep = (props: {
|
||||||
mint: Function;
|
mint: Function;
|
||||||
minting: boolean;
|
minting: boolean;
|
||||||
confirm: Function;
|
confirm: Function;
|
||||||
|
step: number;
|
||||||
}) => {
|
}) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const func = async () => {
|
const func = async () => {
|
||||||
|
@ -1148,6 +1152,13 @@ const WaitingStep = (props: {
|
||||||
func();
|
func();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const setIconForStep = (currentStep: number, componentStep) => {
|
||||||
|
if (currentStep === componentStep) {
|
||||||
|
return <LoadingOutlined />
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
@ -1158,10 +1169,19 @@ const WaitingStep = (props: {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Spin size="large" />
|
<Spin size="large" />
|
||||||
<div className="waiting-title">
|
<Card>
|
||||||
Your creation is being uploaded to the decentralized web...
|
<Steps direction="vertical" current={props.step}>
|
||||||
</div>
|
<Step title="Minting" description="Starting Mint Process" icon={setIconForStep(props.step, 0)} />
|
||||||
<div className="waiting-subtitle">This can take up to 1 minute.</div>
|
<Step title="Preparing Assets" icon={setIconForStep(props.step, 1)} />
|
||||||
|
<Step title="Signing Metadata Transaction" description="Approve the transaction from your wallet" icon={setIconForStep(props.step, 2)} />
|
||||||
|
<Step title="Sending Transaction to Solana" description="This will take a few seconds." icon={setIconForStep(props.step, 3)} />
|
||||||
|
<Step title="Waiting for Initial Confirmation" icon={setIconForStep(props.step, 4)} />
|
||||||
|
<Step title="Waiting for Final Confirmation" icon={setIconForStep(props.step, 5)} />
|
||||||
|
<Step title="Uploading to Arweave" icon={setIconForStep(props.step, 6)} />
|
||||||
|
<Step title="Updating Metadata" icon={setIconForStep(props.step, 7)} />
|
||||||
|
<Step title="Signing Token Transaction" description="Approve the final transaction from your wallet" icon={setIconForStep(props.step, 8)} />
|
||||||
|
</Steps>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1188,6 +1208,7 @@ const Congrats = (props: {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (props.alert) {
|
if (props.alert) {
|
||||||
|
// TODO - properly reset this components state on error
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="waiting-title">Sorry, there was an error!</div>
|
<div className="waiting-title">Sorry, there was an error!</div>
|
||||||
|
|
Loading…
Reference in New Issue