Last active
June 12, 2022 06:16
-
-
Save 0xMukesh/3f6c2450803588adcf6ffc2d15a6f356 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as anchor from "@project-serum/anchor"; | |
import { MintLayout, TOKEN_PROGRAM_ID, Token } from "@solana/spl-token"; | |
import { | |
SystemProgram, | |
SYSVAR_SLOT_HASHES_PUBKEY, | |
Keypair, | |
} from "@solana/web3.js"; | |
import { sendTransactions, SequenceType } from "./transaction"; | |
import { | |
CANDY_MACHINE_PROGRAM, | |
TOKEN_METADATA_PROGRAM_ID, | |
CIVIC, | |
SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID, | |
} from "../constants/constants"; | |
import { CandyMachineAccount } from "../types/getCandyMachineState"; | |
import { SetupState } from "../types/candyMachine/setupState"; | |
import { MintResult } from "../types/mintResult"; | |
export const awaitTransactionSignatureConfirmation = async ( | |
txid: anchor.web3.TransactionSignature, | |
timeout: number, | |
connection: anchor.web3.Connection, | |
queryStatus = false | |
): Promise<anchor.web3.SignatureStatus | null | void> => { | |
let done = false; | |
let status: anchor.web3.SignatureStatus | null | void = { | |
slot: 0, | |
confirmations: 0, | |
err: null, | |
}; | |
let subId = 0; | |
status = await new Promise(async (resolve, reject) => { | |
setTimeout(() => { | |
if (done) { | |
return; | |
} | |
done = true; | |
console.log("Rejecting for timeout..."); | |
reject({ timeout: true }); | |
}, timeout); | |
while (!done && queryStatus) { | |
(async () => { | |
try { | |
const signatureStatuses = await connection.getSignatureStatuses([ | |
txid, | |
]); | |
status = signatureStatuses && signatureStatuses.value[0]; | |
if (!done) { | |
if (!status) { | |
console.log("REST null result for", txid, status); | |
} else if (status.err) { | |
console.log("REST error for", txid, status); | |
done = true; | |
reject(status.err); | |
} else if (!status.confirmations) { | |
console.log("REST no confirmations for", txid, status); | |
} else { | |
console.log("REST confirmation for", txid, status); | |
done = true; | |
resolve(status); | |
} | |
} | |
} catch (e) { | |
if (!done) { | |
console.log("REST connection error: txid", txid, e); | |
} | |
} | |
})(); | |
} | |
}); | |
//@ts-ignore | |
if (connection._signatureSubscriptions[subId]) { | |
connection.removeSignatureListener(subId); | |
} | |
done = true; | |
console.log("Returning status", status); | |
return status; | |
}; | |
export const createAccountsForMint = async ( | |
candyMachine: CandyMachineAccount, | |
payer: anchor.web3.PublicKey | |
): Promise<SetupState> => { | |
const mint = anchor.web3.Keypair.generate(); | |
const userTokenAccountAddress = ( | |
await getAtaForMint(mint.publicKey, payer) | |
)[0]; | |
const signers: anchor.web3.Keypair[] = [mint]; | |
const instructions = [ | |
anchor.web3.SystemProgram.createAccount({ | |
fromPubkey: payer, | |
newAccountPubkey: mint.publicKey, | |
space: MintLayout.span, | |
lamports: | |
await candyMachine.program.provider.connection.getMinimumBalanceForRentExemption( | |
MintLayout.span | |
), | |
programId: TOKEN_PROGRAM_ID, | |
}), | |
Token.createInitMintInstruction( | |
TOKEN_PROGRAM_ID, | |
mint.publicKey, | |
0, | |
payer, | |
payer | |
), | |
createAssociatedTokenAccountInstruction( | |
userTokenAccountAddress, | |
payer, | |
payer, | |
mint.publicKey | |
), | |
Token.createMintToInstruction( | |
TOKEN_PROGRAM_ID, | |
mint.publicKey, | |
userTokenAccountAddress, | |
payer, | |
[], | |
1 | |
), | |
]; | |
return { | |
mint: mint, | |
userTokenAccount: userTokenAccountAddress, | |
transaction: ( | |
await sendTransactions( | |
candyMachine.program.provider.connection, | |
candyMachine.program.provider.wallet, | |
[instructions], | |
[signers], | |
SequenceType.StopOnFailure, | |
"singleGossip", | |
() => {}, | |
() => false, | |
undefined, | |
[], | |
[] | |
) | |
).txs[0].txid, | |
}; | |
}; | |
export const getAtaForMint = async ( | |
mint: anchor.web3.PublicKey, | |
buyer: anchor.web3.PublicKey | |
): Promise<[anchor.web3.PublicKey, number]> => { | |
return await anchor.web3.PublicKey.findProgramAddress( | |
[buyer.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mint.toBuffer()], | |
SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID | |
); | |
}; | |
export const createAssociatedTokenAccountInstruction = ( | |
associatedTokenAddress: anchor.web3.PublicKey, | |
payer: anchor.web3.PublicKey, | |
walletAddress: anchor.web3.PublicKey, | |
splTokenMintAddress: anchor.web3.PublicKey | |
) => { | |
const keys = [ | |
{ pubkey: payer, isSigner: true, isWritable: true }, | |
{ pubkey: associatedTokenAddress, isSigner: false, isWritable: true }, | |
{ pubkey: walletAddress, isSigner: false, isWritable: false }, | |
{ pubkey: splTokenMintAddress, isSigner: false, isWritable: false }, | |
{ | |
pubkey: anchor.web3.SystemProgram.programId, | |
isSigner: false, | |
isWritable: false, | |
}, | |
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, | |
{ | |
pubkey: anchor.web3.SYSVAR_RENT_PUBKEY, | |
isSigner: false, | |
isWritable: false, | |
}, | |
]; | |
return new anchor.web3.TransactionInstruction({ | |
keys, | |
programId: SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID, | |
data: Buffer.from([]), | |
}); | |
}; | |
export const getNetworkToken = async ( | |
wallet: anchor.web3.PublicKey, | |
gatekeeperNetwork: anchor.web3.PublicKey | |
): Promise<[anchor.web3.PublicKey, number]> => { | |
return await anchor.web3.PublicKey.findProgramAddress( | |
[ | |
wallet.toBuffer(), | |
Buffer.from("gateway"), | |
Buffer.from([0, 0, 0, 0, 0, 0, 0, 0]), | |
gatekeeperNetwork.toBuffer(), | |
], | |
CIVIC | |
); | |
}; | |
export const getNetworkExpire = async ( | |
gatekeeperNetwork: anchor.web3.PublicKey | |
): Promise<[anchor.web3.PublicKey, number]> => { | |
return await anchor.web3.PublicKey.findProgramAddress( | |
[gatekeeperNetwork.toBuffer(), Buffer.from("expire")], | |
CIVIC | |
); | |
}; | |
export const getCandyMachineState = async ( | |
anchorWallet: anchor.Wallet, | |
candyMachineId: anchor.web3.PublicKey, | |
connection: anchor.web3.Connection | |
): Promise<CandyMachineAccount> => { | |
const provider = new anchor.Provider(connection, anchorWallet, { | |
preflightCommitment: "processed", | |
}); | |
const idl = await anchor.Program.fetchIdl(CANDY_MACHINE_PROGRAM, provider); | |
const program = new anchor.Program(idl!, CANDY_MACHINE_PROGRAM, provider); | |
const state: any = await program.account.candyMachine.fetch(candyMachineId); | |
const itemsAvailable = state.data.itemsAvailable.toNumber(); | |
const itemsRedeemed = state.itemsRedeemed.toNumber(); | |
const itemsRemaining = itemsAvailable - itemsRedeemed; | |
return { | |
id: candyMachineId, | |
program, | |
state: { | |
authority: state.authority, | |
itemsAvailable, | |
itemsRedeemed, | |
itemsRemaining, | |
isSoldOut: itemsRemaining === 0, | |
isActive: false, | |
isPresale: false, | |
isWhitelistOnly: false, | |
goLiveDate: state.data.goLiveDate, | |
treasury: state.wallet, | |
tokenMint: state.tokenMint, | |
gatekeeper: state.data.gatekeeper, | |
endSettings: state.data.endSettings, | |
whitelistMintSettings: state.data.whitelistMintSettings, | |
hiddenSettings: state.data.hiddenSettings, | |
price: state.data.price, | |
retainAuthority: state.data.retainAuthority, | |
}, | |
}; | |
}; | |
export const getMasterEdition = async ( | |
mint: anchor.web3.PublicKey | |
): Promise<anchor.web3.PublicKey> => { | |
return ( | |
await anchor.web3.PublicKey.findProgramAddress( | |
[ | |
Buffer.from("metadata"), | |
TOKEN_METADATA_PROGRAM_ID.toBuffer(), | |
mint.toBuffer(), | |
Buffer.from("edition"), | |
], | |
TOKEN_METADATA_PROGRAM_ID | |
) | |
)[0]; | |
}; | |
export const getMetadata = async ( | |
mint: anchor.web3.PublicKey | |
): Promise<anchor.web3.PublicKey> => { | |
return ( | |
await anchor.web3.PublicKey.findProgramAddress( | |
[ | |
Buffer.from("metadata"), | |
TOKEN_METADATA_PROGRAM_ID.toBuffer(), | |
mint.toBuffer(), | |
], | |
TOKEN_METADATA_PROGRAM_ID | |
) | |
)[0]; | |
}; | |
export const getCandyMachineCreator = async ( | |
candyMachine: anchor.web3.PublicKey | |
): Promise<[anchor.web3.PublicKey, number]> => { | |
return await anchor.web3.PublicKey.findProgramAddress( | |
[Buffer.from("candy_machine"), candyMachine.toBuffer()], | |
CANDY_MACHINE_PROGRAM | |
); | |
}; | |
export const getCollectionPDA = async ( | |
candyMachineAddress: anchor.web3.PublicKey | |
): Promise<[anchor.web3.PublicKey, number]> => { | |
return await anchor.web3.PublicKey.findProgramAddress( | |
[Buffer.from("collection"), candyMachineAddress.toBuffer()], | |
CANDY_MACHINE_PROGRAM | |
); | |
}; | |
export interface CollectionData { | |
mint: anchor.web3.PublicKey; | |
candyMachine: anchor.web3.PublicKey; | |
} | |
export const getCollectionAuthorityRecordPDA = async ( | |
mint: anchor.web3.PublicKey, | |
newAuthority: anchor.web3.PublicKey | |
): Promise<anchor.web3.PublicKey> => { | |
return ( | |
await anchor.web3.PublicKey.findProgramAddress( | |
[ | |
Buffer.from("metadata"), | |
TOKEN_METADATA_PROGRAM_ID.toBuffer(), | |
mint.toBuffer(), | |
Buffer.from("collection_authority"), | |
newAuthority.toBuffer(), | |
], | |
TOKEN_METADATA_PROGRAM_ID | |
) | |
)[0]; | |
}; | |
export const mintOneToken = async ( | |
candyMachine: CandyMachineAccount, | |
payer: anchor.web3.PublicKey, | |
setupState?: SetupState | |
): Promise<MintResult | null> => { | |
const mint = setupState?.mint ?? anchor.web3.Keypair.generate(); | |
const userTokenAccountAddress = ( | |
await getAtaForMint(mint.publicKey, payer) | |
)[0]; | |
const userPayingAccountAddress = candyMachine.state.tokenMint | |
? (await getAtaForMint(candyMachine.state.tokenMint, payer))[0] | |
: payer; | |
const candyMachineAddress = candyMachine.id; | |
const remainingAccounts = []; | |
const instructions = []; | |
const signers: anchor.web3.Keypair[] = []; | |
console.log("SetupState: ", setupState); | |
if (!setupState) { | |
signers.push(mint); | |
instructions.push( | |
...[ | |
anchor.web3.SystemProgram.createAccount({ | |
fromPubkey: payer, | |
newAccountPubkey: mint.publicKey, | |
space: MintLayout.span, | |
lamports: | |
await candyMachine.program.provider.connection.getMinimumBalanceForRentExemption( | |
MintLayout.span | |
), | |
programId: TOKEN_PROGRAM_ID, | |
}), | |
Token.createInitMintInstruction( | |
TOKEN_PROGRAM_ID, | |
mint.publicKey, | |
0, | |
payer, | |
payer | |
), | |
createAssociatedTokenAccountInstruction( | |
userTokenAccountAddress, | |
payer, | |
payer, | |
mint.publicKey | |
), | |
Token.createMintToInstruction( | |
TOKEN_PROGRAM_ID, | |
mint.publicKey, | |
userTokenAccountAddress, | |
payer, | |
[], | |
1 | |
), | |
] | |
); | |
} | |
if (candyMachine.state.gatekeeper) { | |
remainingAccounts.push({ | |
pubkey: ( | |
await getNetworkToken( | |
payer, | |
candyMachine.state.gatekeeper.gatekeeperNetwork | |
) | |
)[0], | |
isWritable: true, | |
isSigner: false, | |
}); | |
if (candyMachine.state.gatekeeper.expireOnUse) { | |
remainingAccounts.push({ | |
pubkey: CIVIC, | |
isWritable: false, | |
isSigner: false, | |
}); | |
remainingAccounts.push({ | |
pubkey: ( | |
await getNetworkExpire( | |
candyMachine.state.gatekeeper.gatekeeperNetwork | |
) | |
)[0], | |
isWritable: false, | |
isSigner: false, | |
}); | |
} | |
} | |
if (candyMachine.state.whitelistMintSettings) { | |
const mint = new anchor.web3.PublicKey( | |
candyMachine.state.whitelistMintSettings.mint | |
); | |
const whitelistToken = (await getAtaForMint(mint, payer))[0]; | |
remainingAccounts.push({ | |
pubkey: whitelistToken, | |
isWritable: true, | |
isSigner: false, | |
}); | |
if (candyMachine.state.whitelistMintSettings.mode.burnEveryTime) { | |
remainingAccounts.push({ | |
pubkey: mint, | |
isWritable: true, | |
isSigner: false, | |
}); | |
remainingAccounts.push({ | |
pubkey: payer, | |
isWritable: false, | |
isSigner: true, | |
}); | |
} | |
} | |
if (candyMachine.state.tokenMint) { | |
remainingAccounts.push({ | |
pubkey: userPayingAccountAddress, | |
isWritable: true, | |
isSigner: false, | |
}); | |
remainingAccounts.push({ | |
pubkey: payer, | |
isWritable: false, | |
isSigner: true, | |
}); | |
} | |
const metadataAddress = await getMetadata(mint.publicKey); | |
const masterEdition = await getMasterEdition(mint.publicKey); | |
const [candyMachineCreator, creatorBump] = await getCandyMachineCreator( | |
candyMachineAddress | |
); | |
console.log(remainingAccounts.map((rm) => rm.pubkey.toBase58())); | |
instructions.push( | |
await candyMachine.program.instruction.mintNft(creatorBump, { | |
accounts: { | |
candyMachine: candyMachineAddress, | |
candyMachineCreator, | |
payer: payer, | |
wallet: candyMachine.state.treasury, | |
mint: mint.publicKey, | |
metadata: metadataAddress, | |
masterEdition, | |
mintAuthority: payer, | |
updateAuthority: payer, | |
tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, | |
tokenProgram: TOKEN_PROGRAM_ID, | |
systemProgram: SystemProgram.programId, | |
rent: anchor.web3.SYSVAR_RENT_PUBKEY, | |
clock: anchor.web3.SYSVAR_CLOCK_PUBKEY, | |
recentBlockhashes: SYSVAR_SLOT_HASHES_PUBKEY, | |
instructionSysvarAccount: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY, | |
}, | |
remainingAccounts: | |
remainingAccounts.length > 0 ? remainingAccounts : undefined, | |
}) | |
); | |
const [collectionPDA] = await getCollectionPDA(candyMachineAddress); | |
const collectionPDAAccount = | |
await candyMachine.program.provider.connection.getAccountInfo( | |
collectionPDA | |
); | |
if (collectionPDAAccount && candyMachine.state.retainAuthority) { | |
try { | |
const collectionData = | |
(await candyMachine.program.account.collectionPda.fetch( | |
collectionPDA | |
)) as CollectionData; | |
console.log(collectionData); | |
const collectionMint = collectionData.mint; | |
const collectionAuthorityRecord = await getCollectionAuthorityRecordPDA( | |
collectionMint, | |
collectionPDA | |
); | |
console.log(collectionMint); | |
if (collectionMint) { | |
const collectionMetadata = await getMetadata(collectionMint); | |
const collectionMasterEdition = await getMasterEdition(collectionMint); | |
console.log("Collection PDA: ", collectionPDA.toBase58()); | |
console.log("Authority: ", candyMachine.state.authority.toBase58()); | |
instructions.push( | |
await candyMachine.program.instruction.setCollectionDuringMint({ | |
accounts: { | |
candyMachine: candyMachineAddress, | |
metadata: metadataAddress, | |
payer: payer, | |
collectionPda: collectionPDA, | |
tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, | |
instructions: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY, | |
collectionMint, | |
collectionMetadata, | |
collectionMasterEdition, | |
authority: candyMachine.state.authority, | |
collectionAuthorityRecord, | |
}, | |
}) | |
); | |
} | |
} catch (error) { | |
console.error(error); | |
} | |
} | |
const instructionsMatrix = [instructions]; | |
const signersMatrix = [signers]; | |
try { | |
const txns = ( | |
await sendTransactions( | |
candyMachine.program.provider.connection, | |
candyMachine.program.provider.wallet, | |
instructionsMatrix, | |
signersMatrix, | |
SequenceType.StopOnFailure, | |
"singleGossip", | |
() => {}, | |
() => false, | |
undefined | |
) | |
).txs.map((t) => t.txid); | |
const mintTxn = txns[0]; | |
return { | |
mintTxId: mintTxn, | |
metadataKey: metadataAddress, | |
}; | |
} catch (e) { | |
console.log(e); | |
} | |
return null; | |
}; | |
export async function loadCandyProgramV2( | |
walletKeyPair: Keypair, | |
env: string, | |
customRpcUrl?: string | |
) { | |
if (customRpcUrl) console.log("USING CUSTOM URL", customRpcUrl); | |
// @ts-ignore | |
const solConnection = new anchor.web3.Connection( | |
//@ts-ignore | |
customRpcUrl || getCluster(env) | |
); | |
const walletWrapper = new anchor.Wallet(walletKeyPair); | |
const provider = new anchor.Provider(solConnection, walletWrapper, { | |
preflightCommitment: "recent", | |
}); | |
const idl = await anchor.Program.fetchIdl(CANDY_MACHINE_PROGRAM, provider); | |
const program = new anchor.Program(idl, CANDY_MACHINE_PROGRAM, provider); | |
console.log("Program ID from anchor", program.programId.toBase58()); | |
return program; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Request, Response } from "express"; | |
import * as anchor from "@project-serum/anchor"; | |
import { | |
PublicKey, | |
Connection, | |
Transaction, | |
TransactionInstruction, | |
SYSVAR_SLOT_HASHES_PUBKEY, | |
SystemProgram, | |
Keypair, | |
} from "@solana/web3.js"; | |
import { MintLayout, TOKEN_PROGRAM_ID, Token } from "@solana/spl-token"; | |
import fetchData from "../utils/fetchData"; | |
import { | |
getAtaForMint, | |
createAssociatedTokenAccountInstruction, | |
getNetworkToken, | |
getNetworkExpire, | |
getMetadata, | |
getMasterEdition, | |
getCandyMachineCreator, | |
getCollectionPDA, | |
CollectionData, | |
getCollectionAuthorityRecordPDA, | |
getCandyMachineState, | |
} from "../utils/candyMachine"; | |
import Scans from "../models/scans"; | |
import { CIVIC, TOKEN_METADATA_PROGRAM_ID } from "../constants/constants"; | |
import { MakeTransactionInputData } from "../types/makeTxn"; | |
const mint = async (req: Request, res: Response) => { | |
const qrCodeId = req.query.id; | |
if (!qrCodeId) { | |
return res.status(400).json({ | |
error: "ERR-MISSING-QR-CODE-ID", | |
message: | |
"Missing qrCodeId parameter. The qrCodeId is a required parameter", | |
}); | |
} | |
if (req.method === "GET") { | |
return res.status(200).json({ | |
label: (await fetchData(qrCodeId as string)).label, | |
icon: (await fetchData(qrCodeId as string)).icon, | |
}); | |
} | |
if (req.method === "POST") { | |
try { | |
const reference = Keypair.generate().publicKey; | |
const qrCodeId = req.query.id; | |
const { account } = req.body as MakeTransactionInputData; | |
if (!account) { | |
return res.status(400).json({ error: "No account provided" }); | |
} | |
const dummy_key_pair = new anchor.web3.Keypair(); | |
const walletWrapper = new anchor.Wallet(dummy_key_pair); | |
const candyMachine = await getCandyMachineState( | |
walletWrapper, | |
new anchor.web3.PublicKey( | |
( | |
await fetchData(qrCodeId as string) | |
).candyMachineId | |
), | |
new anchor.web3.Connection((await fetchData(qrCodeId as string)).rpcUrl) | |
); | |
const candyMachineAddress = candyMachine.id; | |
const payer = new PublicKey(account); | |
const mint = anchor.web3.Keypair.generate(); | |
const platformAddress = new anchor.web3.PublicKey(process.env.SHOP!); | |
console.log("Platform address: ", platformAddress.toString()); | |
const mintPrice = candyMachine.state.price.toNumber(); | |
console.log("Mint price: ", mintPrice); | |
const serviceFee = mintPrice / 100; | |
console.log("Service fee: ", serviceFee); | |
const userTokenAccountAddress = ( | |
await getAtaForMint(mint.publicKey, payer) | |
)[0]; | |
const transferIx = SystemProgram.transfer({ | |
fromPubkey: payer, | |
toPubkey: platformAddress, | |
lamports: serviceFee, | |
}); | |
const userPayingAccountAddress = payer; | |
const instructions: TransactionInstruction[] = []; | |
const remainingAccounts = []; | |
const signers: anchor.web3.Keypair[] = []; | |
instructions.push(transferIx); | |
if (mint) { | |
signers.push(mint); | |
instructions.push( | |
...[ | |
anchor.web3.SystemProgram.createAccount({ | |
fromPubkey: payer, | |
newAccountPubkey: mint.publicKey, | |
space: MintLayout.span, | |
lamports: | |
await candyMachine.program.provider.connection.getMinimumBalanceForRentExemption( | |
MintLayout.span | |
), | |
programId: TOKEN_PROGRAM_ID, | |
}), | |
Token.createInitMintInstruction( | |
TOKEN_PROGRAM_ID, | |
mint.publicKey, | |
0, | |
payer, | |
payer | |
), | |
createAssociatedTokenAccountInstruction( | |
userTokenAccountAddress, | |
payer, | |
payer, | |
mint.publicKey | |
), | |
Token.createMintToInstruction( | |
TOKEN_PROGRAM_ID, | |
mint.publicKey, | |
userTokenAccountAddress, | |
payer, | |
[], | |
1 | |
), | |
] | |
); | |
} | |
if (candyMachine.state.gatekeeper) { | |
remainingAccounts.push({ | |
pubkey: ( | |
await getNetworkToken( | |
payer, | |
candyMachine.state.gatekeeper.gatekeeperNetwork | |
) | |
)[0], | |
isWritable: true, | |
isSigner: false, | |
}); | |
if (candyMachine.state.gatekeeper.expireOnUse) { | |
remainingAccounts.push({ | |
pubkey: CIVIC, | |
isWritable: false, | |
isSigner: false, | |
}); | |
remainingAccounts.push({ | |
pubkey: ( | |
await getNetworkExpire( | |
candyMachine.state.gatekeeper.gatekeeperNetwork | |
) | |
)[0], | |
isWritable: false, | |
isSigner: false, | |
}); | |
} | |
} | |
if (candyMachine.state.whitelistMintSettings) { | |
const mint = new anchor.web3.PublicKey( | |
candyMachine.state.whitelistMintSettings.mint | |
); | |
const whitelistToken = (await getAtaForMint(mint, payer))[0]; | |
remainingAccounts.push({ | |
pubkey: whitelistToken, | |
isWritable: true, | |
isSigner: false, | |
}); | |
if (candyMachine.state.whitelistMintSettings.mode.burnEveryTime) { | |
remainingAccounts.push({ | |
pubkey: mint, | |
isWritable: true, | |
isSigner: false, | |
}); | |
remainingAccounts.push({ | |
pubkey: payer, | |
isWritable: false, | |
isSigner: true, | |
}); | |
} | |
} | |
if (candyMachine.state.tokenMint) { | |
remainingAccounts.push({ | |
pubkey: userPayingAccountAddress, | |
isWritable: true, | |
isSigner: false, | |
}); | |
remainingAccounts.push({ | |
pubkey: payer, | |
isWritable: false, | |
isSigner: true, | |
}); | |
} | |
const metadataAddress = await getMetadata(mint.publicKey); | |
const masterEdition = await getMasterEdition(mint.publicKey); | |
const [candyMachineCreator, creatorBump] = await getCandyMachineCreator( | |
candyMachineAddress | |
); | |
console.log(remainingAccounts.map((rm) => rm.pubkey.toBase58())); | |
instructions.push( | |
await candyMachine.program.instruction.mintNft(creatorBump, { | |
accounts: { | |
candyMachine: candyMachineAddress, | |
candyMachineCreator, | |
payer: payer, | |
wallet: candyMachine.state.treasury, | |
mint: mint.publicKey, | |
metadata: metadataAddress, | |
masterEdition, | |
mintAuthority: payer, | |
updateAuthority: payer, | |
tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, | |
tokenProgram: TOKEN_PROGRAM_ID, | |
systemProgram: SystemProgram.programId, | |
rent: anchor.web3.SYSVAR_RENT_PUBKEY, | |
clock: anchor.web3.SYSVAR_CLOCK_PUBKEY, | |
recentBlockhashes: SYSVAR_SLOT_HASHES_PUBKEY, | |
instructionSysvarAccount: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY, | |
}, | |
remainingAccounts: | |
remainingAccounts.length > 0 ? remainingAccounts : undefined, | |
}) | |
); | |
const [collectionPDA] = await getCollectionPDA(candyMachineAddress); | |
const collectionPDAAccount = | |
await candyMachine.program.provider.connection.getAccountInfo( | |
collectionPDA | |
); | |
if (collectionPDAAccount && candyMachine.state.retainAuthority) { | |
try { | |
const collectionData = | |
(await candyMachine.program.account.collectionPda.fetch( | |
collectionPDA | |
)) as CollectionData; | |
console.log(collectionData); | |
const collectionMint = collectionData.mint; | |
const collectionAuthorityRecord = | |
await getCollectionAuthorityRecordPDA( | |
collectionMint, | |
collectionPDA | |
); | |
console.log(collectionMint); | |
if (collectionMint) { | |
const collectionMetadata = await getMetadata(collectionMint); | |
const collectionMasterEdition = await getMasterEdition( | |
collectionMint | |
); | |
console.log("Collection PDA: ", collectionPDA.toBase58()); | |
console.log("Authority: ", candyMachine.state.authority.toBase58()); | |
const setCollectionInst = | |
await candyMachine.program.instruction.setCollectionDuringMint({ | |
accounts: { | |
candyMachine: candyMachineAddress, | |
metadata: metadataAddress, | |
payer: payer, | |
collectionPda: collectionPDA, | |
tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, | |
instructions: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY, | |
collectionMint, | |
collectionMetadata, | |
collectionMasterEdition, | |
authority: candyMachine.state.authority, | |
collectionAuthorityRecord, | |
}, | |
}); | |
setCollectionInst.keys.push({ | |
pubkey: new PublicKey(reference), | |
isSigner: false, | |
isWritable: false, | |
}); | |
instructions.push(setCollectionInst); | |
} | |
} catch (error) { | |
console.error(error); | |
} | |
} | |
const connection = new Connection( | |
(await fetchData(qrCodeId as string)).rpcUrl | |
); | |
const { blockhash } = await connection.getLatestBlockhash("finalized"); | |
const transaction = new Transaction({ | |
recentBlockhash: blockhash, | |
feePayer: payer, | |
}); | |
console.log("INX", instructions); | |
transaction.add(...instructions); | |
transaction.partialSign(mint); | |
console.log("Transaction Before Serialize", transaction); | |
const serializedTransaction = transaction.serialize({ | |
requireAllSignatures: false, | |
}); | |
const base64 = serializedTransaction.toString("base64"); | |
console.log("Serialized Transaction: ", base64); | |
const message = "Thanks for minting NFTs!"; | |
const scan = new Scans({ | |
user: account, | |
qrCodeId: qrCodeId, | |
candyMachineId: (await fetchData(qrCodeId as string)).candyMachineId, | |
reference: reference, | |
serviceFee: serviceFee / 1e9, | |
candyMachinePrice: mintPrice / 1e9, | |
}); | |
await scan.save(); | |
return res.status(200).json({ | |
transaction: base64, | |
message, | |
}); | |
} catch (err) { | |
console.error(err); | |
return res.status(500).json({ | |
message: "Error while creating the txn", | |
}); | |
} | |
} | |
}; | |
export default mint; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment