Metaplex SDK, some minted NFTs are missing a name - solana

We're minting NFTs with Metaplex SDK, we found that at random, NFT name is missing in blockchain explorer and metadata storage. As a result, tokens aren't showing up in Phantom wallets.
https://explorer.solana.com/address/9SKg6LiT8suiyToATmQ6jjJxWqMcxcV7ALHcwmYSaoqY
Metadata:
Interestingly, running the following code returns the name ("The Wreath"), but only in a json object. In the root of the response that name is still empty.
const connection = new Connection(clusterApiUrl('mainnet-beta'));
const mx = Metaplex.make(connection);
const fetchNft = async () => {
const asset = await mx
.nfts()
.findByMint({
mintAddress: new PublicKey(
'9SKg6LiT8suiyToATmQ6jjJxWqMcxcV7ALHcwmYSaoqY'
),
})
.run();
console.log(asset);
};
Result:
For reference, some NFTs we minted in the same fashion do have names, eg: https://explorer.solana.com/address/F1qnUF2gPuf5FsD7whmacw1G7YFLaNHGYC48FAStmCjg
Does anyone have any idea how to go about debugging this?
Thanks in advance!

Related

How to make an auction with the new metaplex js sdk?

I am working on building a solana marketplace and trying to update from the old solana marketplace to auction house.
code:
const authority = metaplex.identity();
const auctionHouse = await metaplex
.auctions()
.createAuctionHouse({
sellerFeeBasisPoints: 200,
requiresSignOff: false,
treasuryMint: WRAPPED_SOL_MINT,
authority: authority.publicKey,
canChangeSalePrice: true,
feeWithdrawalDestination: publicKey,
treasuryWithdrawalDestinationOwner: publicKey,
})
.run();
const listNft = async () => {
try {
const NFTs = await metaplex.nfts().findAllByOwner(publicKey).run();
console.log(NFTs[4].mintAddress.toString(), " nft");
const auctionHouse = await metaplex
.auctions()
.findAuctionHouseByCreatorAndMint(publicKey, WRAPPED_SOL_MINT)
.run();
const listtx = metaplex
.auctions()
.builders()
.createListing({
mintAccount: NFTs[4].mintAddress,
price: lamports(1 * LAMPORTS_PER_SOL),
auctionHouse: auctionHouse,
});
var rpcClient = await metaplex.rpc().sendTransaction(listtx);
console.log(rpcClient, "listed nft");
} catch (error) {
console.log(error);
}
};
const getListing = async () => {
const NFTs = await metaplex.nfts().findAllByOwner(publicKey).run();
const retrievedAuctionHouse = await metaplex
.auctions()
.findAuctionHouseByCreatorAndMint(publicKey, WRAPPED_SOL_MINT)
.run();
console.log(retrievedAuctionHouse?.address?.toString(), "auction pubkey");
const retrieveListing = await metaplex
.auctions()
.for(retrievedAuctionHouse)
.findListingByAddress(NFTs[4].mintAddress)
.run();
console.log(retrieveListing, "retrieving listings");
};
const bidNft = async () => {
const NFTs = await metaplex.nfts().findAllByOwner(publicKey).run();
const auctionHouse = await metaplex
.auctions()
.findAuctionHouseByCreatorAndMint(publicKey, WRAPPED_SOL_MINT)
.run();
const { bid, buyerTradeState } = await metaplex
.auctions()
.for(auctionHouse)
.bid({
mintAccount: NFTs[5].mintAddress,
price: lamports(0.5 * LAMPORTS_PER_SOL),
});
console.log(bid, buyerTradeState, "bidding");
};
errors:
when trying to list nft:
MetaplexError: AuctionHouseProgram > Account is already initialized"
Source: Program > AuctionHouseProgram [hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk]
Problem: The program [AuctionHouseProgram] at address [hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk] raised an error of code [1] that translates to "Account is already initialized"".
Solution: Check the error message provided by the program.
Caused By: TokenLendingError#AlreadyInitialized: Account is already initialized"
at RpcClient.parseProgramError (RpcClient.mjs?e98e:206:1)
at RpcClient.sendTransaction (RpcClient.mjs?e98e:48:1)
When trying to fetch listings:
Account.mjs?9f45:47 Uncaught (in promise) MetaplexError: Account Not Found
Source: SDK
Problem: The account of type [ListingReceipt] was not found at the provided address [3m517hu6UuV5HjdLmb2GxZkttKTtQ8VseHRCPuUTDJmz].
Solution: Ensure the provided address is correct and that an account exists at this address.
at assertAccountExists (Account.mjs?9f45:47:1)
at eval (Account.mjs?9f45:39:1)
at Object.handle (findListingByAddress.mjs?1810:23:44)
at async eval (Task.mjs?1340:58:1)
at async Disposable.run (Disposable.mjs?b308:22:1)
Found a way around
Instead of using metaplex.auction().builder().createListing i used metaplex.auctions().for(auctionHouse).list().
Then funded the auction fee payer account which is a pda.
Finally in findListingByAddress i passed the sellerTradeState
const { listing, sellerTradeState } = await metaplex
.auctions()
.for(auctionHouse)
.list({
mintAccount: NFTs[1].mintAddress,
price: sol(1.5),
})
.run();
For fetching the listed nft
const retrieveListing = await metaplex
.auctions()
.for(retrievedAuctionHouse)
.findListingByAddress(
sellerTradeState
)
.run();
Just from the information provided above, there are two issues:
You might have run the createAuctionHouse instruction already once which created the Auction house and now that you are running the listNft function which also runs createAuctionHouse instruction, it throws an Account already exists error. You can see why this happens here: https://stackoverflow.com/a/72808405/19264629
You are using the NFTs mint address in findListingByAddress instruction, which is wrong. You have to create a ListingReceipt as stated here: https://docs.metaplex.com/guides/auction-house/#auction-house-receipts while creating the listing itself (this needs to be done in one single transaction). Once this is done, you need to plugin the receipt address in the findListingByAddress to fetch the listings.
Got it to work. The trick was to fund the auction house "Fee Account" as explained above and in Auction House CLI: I cannot execute the sale instruction to list my NFT
const ah = await mx
.auctionHouse()
.findByAddress({ address:ahKey })
.run();
const nft = await mx
.nfts()
.create({
name:"TESTNFT",
symbol: "TESTNFT",
uri: "https://blah.com",
sellerFeeBasisPoints : 100,
creators: [
{
address: wallet.publicKey,
share: 100,
}]
})
.run();
const price = sol(0.1);
const { listing, sellerTradeState } = await mx
.auctionHouse()
.list({
auctionHouse: ah,
mintAccount: nft.mintAddress,
price
})
.run()

Metamask is showing "invalid amount" in metamask mobile app during transfer with etherjs but works fine in web plugin

I am getting an invalid amount error while connecting to my dapp using the metamask mobile appilication. It works fine with the browser plugin but not on the mobile app. I am trying to transfer BUSD using etherJs. I already connected with the BUSD contract and abi, and like I mentioned it works fine on web but shows "invalid amount" on mobile app. I'd really appreciate the help.
Here's what my code looks like
const price_r = ethers.utils.parseUnits(price_, 18);
const {BUSDContract, signer} = await getContract();
const contract = BUSDContract.connect(signer)
m_response = await contract.transfer(
'0xf0e2fb4174A66dbD5A4B94B9D6331eA05460542d',
`${amount}`,
{
gasLimit: 3000000,
}
);
This works quite when with the metamask browser plugin. However, when I switch to the metamask mobile app it shows the invalid amount as shown below.
Metamask mobile invalid error image
Add gasLimit and gasPrice:
const gasLimit = await Contract.estimateGas.transfer(to, amount, {from: account });
const gasPrice = await library.getGasPrice();
const tx = await Contract.transfer(to, amount, {
from: account,
gasLimit: gasLimit,
gasPrice: gasPrice
});
const response = await tx.wait();
return response;
Just in case anyone comes into this issue, I was able to resolve it by switching from etherjs to web3.

Receiving "Phantom - RPC Error: Transaction creation failed" while building solana escrow with #solana/web3.js

I am trying to replicate https://github.com/dboures/solana-random-number-betting-game
Although when I try to initiate my the Escrow I receive the following error:
Phantom - RPC Error: Transaction creation failed.
Uncaught (in promise) {code: -32003, message: 'Transaction creation failed.'}
I am using Phantom Wallet with Solana RPC.
const transaction = new Transaction({ feePayer: initializerKey })
let recentBlockHash = await connection.getLatestBlockhash();
transaction.recentBlockhash = await recentBlockHash.blockhash;
const tempTokenAccount = Keypair.generate();
// Create Temp Token X Account
transaction.add(
SystemProgram.createAccount({
programId: TOKEN_PROGRAM_ID,
fromPubkey: initializerKey,
newAccountPubkey: tempTokenAccount.publicKey,
space: AccountLayout.span,
lamports: await connection.getMinimumBalanceForRentExemption(AccountLayout.span )
})
);
const { signature } = await wallet.signAndSendTransaction(transaction);
let txid = await connection.confirmTransaction(signature);
console.log(txid);
You're trying to create an account without signing with the keypair of that account to prove ownership.
You have to add the keypair as a signer like such:
await wallet.signAndSendTransaction(transaction, {signers: [tempTokenAccount]})
I was able to solve my problem by using the following code:
const signed = await wallet.request({
method: "signTransaction",
params: {
message: bs58.encode(transaction.serializeMessage())
}
});
const signature = bs58.decode(signed.signature)
transaction.addSignature(initializerKey, signature);
transaction.partialSign(...[tempTokenAccount]);
await connection.sendRawTransaction(transaction.serialize())
instead of:
await wallet.signAndSendTransaction(transaction, {signers: [tempTokenAccount]})
Basically at first I was using one simple function to perform all the above steps, however, for some reason it was not working and throwing the subjected error. When I used this breakdown code it worked!. The cause of the error is still mysterious to me.
Thank you.

Getting address of a token account given a Solana wallet address

I've been trying the code below to get the spl-token account address for a specific token in a Solana wallet from the Solana wallet address, but I am having issues getting the result I am looking for. I run:
const web3 = require('#solana/web3.js');
(async () => {
const solana = new web3.Connection("https://api.mainnet-beta.solana.com");
//the public solana address
const accountPublicKey = new web3.PublicKey(
"2B1Uy1UTnsaN1rBNJLrvk8rzTf5V187wkhouWJSApvGT"
);
//mintAccount = the token mint address
const mintAccount = new web3.PublicKey(
"GLmaRDRmYd4u3YLfnj9eq1mrwxa1YfSweZYYZXZLTRdK"
);
console.log(
await solana.getTokenAccountsByOwner(accountPublicKey, {
mint: mintAccount,
})
);
})();
I'm looking for the token account address in the return, 6kRT2kAVsBThd5cz6gaQtomaBwLxSp672RoRPGizikH4. I get:
{ context: { slot: 116402202 }, value: [ { account: [Object],
pubkey: [PublicKey] } ] }
I can drill down through this a bit using .value[0].pubkey or .value[0].account but ultimately can't get to the information i'm looking for, which is a return of 6kRT2kAVsBThd5cz6gaQtomaBwLxSp672RoRPGizikH4
Does anyone know what is going wrong?
(Note I do not want to use the getOrCreateAssociatedAccountInfo() method, i'm trying to get the token account address without handling the wallets keypair)
ISSUE SOLVED:
I needed to grab the correct _BN data and convert, solution below.
const web3 = require('#solana/web3.js');
(async () => {
const solana = new web3.Connection("https://api.mainnet-beta.solana.com");
//the public solana address
const accountPublicKey = new web3.PublicKey(
"2B1Uy1UTnsaN1rBNJLrvk8rzTf5V187wkhouWJSApvGT"
);
//mintAccount = the token mint address
const mintAccount = new web3.PublicKey(
"GLmaRDRmYd4u3YLfnj9eq1mrwxa1YfSweZYYZXZLTRdK"
);
const account = await solana.getTokenAccountsByOwner(accountPublicKey, {
mint: mintAccount});
console.log(account.value[0].pubkey.toString());
})();
That will certainly work as a heavy-handed approach. As an alternative, you can try to just search for the associated token account owned by that wallet without creating it if it doesn't exist.
You would essentially follow the logic at https://github.com/solana-labs/solana-program-library/blob/0a61bc4ea30f818d4c86f4fe1863100ed261c64d/token/js/client/token.js#L539
except without the whole catch block.

Stripe returns a "No such token" error (Plaid Integration)

I am getting this error from Stripe when I try to create a new source for the selected bank account. I am using the new (beta) version of the Plaid Node SDK. Here is my code:
let user;
const mode = "sandbox";
const dsService = new CaspioDsService();
// Load the user if not already loaded by cognitoAuth
if (!req.user) {
user = new User(
dsService,
new CaspioRefDataService(),
new AuthUserService({
organizationId: res.locals.organization.Organization_ID,
isAuthenticated: res.locals.isAuthenticated,
})
);
await user.load(req.params.userId);
} else {
user = req.user.userObject;
}
const configuration = new Configuration({
basePath: PlaidEnvironments[mode],
baseOptions: {
headers: {
"PLAID-CLIENT-ID": config.plaid.clientId,
"PLAID-SECRET": mode === "sandbox" ? config.plaid.secretSandbox : config.plaid.secretProduction,
"Plaid-Version": "2020-09-14",
},
},
});
const plaidClient = new PlaidApi(configuration);
console.log(configuration.basePath); // https://sandbox.plaid.com
// Exchange the public token for the Plaid access token
const plaidTokenRes = await plaidClient.itemPublicTokenExchange({
public_token: req.body.publicToken,
});
const accessToken = plaidTokenRes.data.access_token;
console.log(accessToken); // access-sandbox-d92396c2-1f49-4780-9ae9-23d50645f364
// Get the Stripe bank account token from Plaid
const stripeTokenRes = await plaidClient.processorStripeBankAccountTokenCreate({
access_token: accessToken,
account_id: req.body.accountId
});
const bankAccountToken = stripeTokenRes.data.stripe_bank_account_token;
console.log(bankAccountToken); // btok_1JFMGwGq7ejZoSiwGmM8WSSm
let stripeCustomerId = user.getStripeToken();
const stripeClient = await StripeHelper.getStripeClient(mode); // Get Stripe client in sandbox mode
console.log(stripeCustomerId); // cus_Jt7AWZjC8rHPzt
// Add the source to the Stripe customer and get the bank account info
const bankAccount = await stripeClient.customers.createSource(stripeCustomerId, {
source: bankAccountToken,
}); // Error: No such token: 'btok_1JFMGwGq7ejZoSiwGmM8WSSm'
Any ideas what I might be doing wrong? I expect the issue is with my code, or possibly Plaid (I don't think it is a Stripe problem).
It sounds like you're getting a token from Plaid, but Stripe is rejecting it, which suggests a problem with the relationship between your Plaid and Stripe setups. Are you sure that you enabled the Plaid/Stripe integration in the Plaid dashboard and that the client id / secret you're using matches the Plaid account where the integration is enabled? The Plaid docs also suggest that this error can be caused by using a mismatched set of environments (e.g. using Production with Stripe but Sandbox with Plaid).
The problem was that we had the wrong Stripe account connected. Silly one, but I'm posting this in case anyone else makes the same mistake.

Resources