Can I do solana spl-token authorize mint --disable but from javascript? - solana

I am trying create an NFT mint, I know how to do it from CLI, but I need to do it from JS, I am looking at the code of #solana/spl-token package, but cannot find API analogous to
spl-token authorize <TOKEN_ID> mint --disable
Does anyone know how to do it?

You certainly can! Here's some code that doesn't compile to get you started:
import { Connection, PublicKey, Keypair } from '#solana/web3.js';
import { AuthorityType, setAuthority } from '#solana/spl-token';
const mint = new PublicKey("mint in base 58");
const payer = new Keypair(...);
const mintAuthority = new Keypair(...);
const connection = new Connection
await setAuthority(
connection,
payer,
mint,
mintAuthority,
AuthorityType.MintTokens,
null, // this sets the mint authority to null
);
Adapted from https://github.com/solana-labs/solana-program-library/blob/7c7507f4ec1f320bbc33af459d4d8b5573a6a906/token/js/test/e2e/setAuthority.test.ts#L88

Related

Metaplex SDK, some minted NFTs are missing a name

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!

Transaction with "SystemProgram.createAccount" results in "Error: Signature verification failed at Transaction.serialize"

What I'm tryding to achieve is a webpage on which the user connects its phantom wallet and then by a simple press of a button creates a token.
In order to achieve that, I created a simple transaction for now which creates an account for the future token (based on https://www.programcreek.com/typescript/?api=#solana/spl-token.createInitializeMintInstruction)
this is the function which is called when the user press the button:
const onClickCreate = useCallback( async () => {
const lamports = await getMinimumBalanceForRentExemptMint(connection)
const mint = Keypair.generate()
console.log(mint.publicKey.toBase58())
const transaction = new Transaction({feePayer: publicKey})
transaction.add(
SystemProgram.createAccount({
fromPubkey: publicKey,
newAccountPubkey: mint.publicKey,
space: MINT_SIZE,
lamports,
programId: TOKEN_PROGRAM_ID
}),
)
const signature = await sendTransaction(transaction, connection);
await connection.confirmTransaction(signature, 'processed');
}, [publicKey, signTransaction, sendTransaction, connection]);
Executing the code results in the error saying that the signature failed.
I use wallet-adapter to connect the user's wallet (which gives me access to the variable publicKey)
If I replace the createAccount function by SystemProgram.transfer everything works ok :
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: publicKey,
toPubkey: Keypair.generate().publicKey,
lamports: lamportsI,
})
);
Thank you for your time
Ok so I checked a little bit more and found someone on the solana forums in Feb 2022 who had kind of the same problem I have : https://forums.solana.com/t/signature-error-when-create-a-new-account/5348/2
the answer by #zicklag worked out for me.
for short, you simply have to make the mint keypair sign the transaction (which seems logic after you think about it)
final code (inside the function called by pressing the button):
if (!publicKey) throw new WalletNotConnectedError();
const lamports = await getMinimumBalanceForRentExemptMint(connection)
const mint = Keypair.generate()
const transaction = new Transaction({ feePayer: publicKey, recentBlockhash: (await connection.getLatestBlockhash()).blockhash });
transaction.add(
SystemProgram.createAccount({
fromPubkey: publicKey,
newAccountPubkey: mint.publicKey,
space: MINT_SIZE,
lamports,
programId: TOKEN_PROGRAM_ID
})
)
transaction.sign(mint)
const txID = await sendTransaction(transaction, connection)

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.

How to get "ownerof" token on Solana

I'm trying to see how you can get the "ownerof" token like on Ethereum but on the Solana blockchain instead.
For example, I want a user to access a certain part of the website only if they have x token on their phantom wallet (or other Solana wallet).
If you want to understand if a user owns a specific token, you'll have to check if they current own that specific mint's token account and have a balance > 0.
Code would be as follows checking amount that address GKNcUmNacSJo4S2Kq3DuYRYRGw3sNUfJ4tyqd198t6vQ owns of USDC:
import {clusterApiUrl, Connection, Keypair, LAMPORTS_PER_SOL, ParsedAccountData, PublicKey} from '#solana/web3.js';
import {ASSOCIATED_TOKEN_PROGRAM_ID, Token, TOKEN_PROGRAM_ID} from "#solana/spl-token";
const publicKey = new PublicKey("GKNcUmNacSJo4S2Kq3DuYRYRGw3sNUfJ4tyqd198t6vQ");
const mint = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
const connection = new Connection(clusterApiUrl('mainnet-beta'));
const associatedAddress = await Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
mint,
publicKey
);
console.log(associatedAddress.toBase58());
const tokenAccountInfo = await connection.getParsedAccountInfo(associatedAddress);
console.log((tokenAccountInfo.value?.data as ParsedAccountData).parsed.info.tokenAmount.amount);

How to revoke a function-call access key?

"Access keys are stored as account_id,public_key in a trie state."
how do I revoke an function-call access key from the blockchain?
You can remove an access key by sending a DeleteKey transaction. For more details on transactions, please checkout this page.
Here is how you would delete an access key for example.testnet:
const { KeyPair, keyStore, connect } = require("near-api-js");
const CREDENTIALS_DIR = "~/.near-credentials";
const ACCOUNT_ID = "example.testnet";
const PUBLIC_KEY = "8hSHprDq2StXwMtNd43wDTXQYsjXcD4MJTXQYsjXcc";
const keyStore = new keyStores.UnencryptedFileSystemKeyStore(CREDENTIALS_DIR);
const config = {
keyStore,
networkId: "testnet",
nodeUrl: "https://rpc.testnet.near.org",
};
deleteAccessKey(ACCOUNT_ID, PUBLIC_KEY);
async function deleteAccessKey(accountId, publicKey) {
const near = await connect(config);
const account = await near.account(accountId);
await account.deleteKey(publicKey);
}
You will need to make sure you have credentials for your account stored locally to complete this function. Do this by running the following near-cli command:
near login
For more info on rotating access keys, check out this doc:
https://docs.near.org/docs/api/naj-cookbook#access-key-rotation

Resources