I have following account Solana Explorer Account
And i can see there is a Mint account ( Account that store my tokens ) how i can get the mint account having my public key is there any relation or how this thing is working in general
Some terminology to be sure we're on the same page:
the "wallet" is the system account that owns other accounts, your linked "Solana Explorer Account" of CGP6sKHyrZGPJRoUAy8XbyzmX7YD4tVBQG9SEe9ekZM6
the mint account defines the token, and does not hold any tokens, is Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr
the account that holds your tokens is actually G6ogFW6YzBpYKhwZrckZJa4yejcjNTfHLE2mUAQFv3ic: https://explorer.solana.com/address/G6ogFW6YzBpYKhwZrckZJa4yejcjNTfHLE2mUAQFv3ic?cluster=devnet -- this is an "associated token account", whose address is derived from your wallet. The tools and explorer default to using that account when dealing with the Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr token. To get this account, you can use getAssociatedTokenAccount, which boils down to:
import { PublicKey } from '#solana/web3.js';
const TOKEN_PROGRAM_ID = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
const ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
const owner = new PublicKey('CGP6sKHyrZGPJRoUAy8XbyzmX7YD4tVBQG9SEe9ekZM6');
const mint = new PublicKey('Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr');
const [address] = await PublicKey.findProgramAddress(
[owner.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mint.toBuffer()],
ASSOCIATED_TOKEN_PROGRAM_ID
);
The real code is at: https://github.com/solana-labs/solana-program-library/blob/5611ad8bd595d9e3666f8b115cd28f8116038645/token/js/src/state/mint.ts#L146
const connection = new Connection("https://api.devnet.solana.com");
let response = await connection.getTokenAccountsByOwner(
new PublicKey("27kVX7JpPZ1bsrSckbR76mV6GeRqtrjoddubfg2zBpHZ"), // owner here
{
programId: TOKEN_PROGRAM_ID,
}
);
This is to get all token account owned by specific wallet address. Dont forget to adjust connection url if you are using mainnet or testnet or localhost. You also can filter it to a specific mint address as well.
Related
Does the minted NFT from Metaplex(candy machine) automatically generate the Token Account (as I am planning to transfer it to other owner via Javascript). Also, i am using the function getOrCreateAssociatedTokenAccount to create a token account but my problem is it needs keypair and I dont know where to locate if I a only have a wallet address? Here is my code:
// wallet address of the owner of NFT but I want to get the keypair here since it is the one that is required for getOrCreateAssociatedTokenAccount
const fromWallet = owner_wallet;
// Public Key of buyer
const toWallet = buyer_wallet;
// NFT mint address
let mint = mint_address;
//connection
const connection = use_connection;
// Get the token account of the toWallet address, and if it does not exist, create it
const toTokenAccount = await getOrCreateAssociatedTokenAccount(connection, fromWallet, mint, toWallet);
// Get the token account of the fromWallet address, and if it does not exist, create it (my problem here is 2nd parameter is looking for keypair but i can only provide a wallet address
const fromTokenAccount = await getOrCreateAssociatedTokenAccount(
connection,
fromWallet,
mint,
fromWallet.publicKey
);
const signature = await transfer(
connection,
fromWallet,
fromTokenAccount.address,
toTokenAccount.address,
fromWallet.publicKey,
0
);
console.log(`finished transfer with ${signature}`);
Does the minted NFT from Metaplex(candy machine) automatically generate the Token Account --> Yes
(as I am planning to transfer it to other owner via Javascript) --> you need / should create a new token account and not just transfer the ownership of the token account
Also, i am using the function getOrCreateAssociatedTokenAccount to create a token account but my problem is it needs keypair and I dont know where to locate if I a only have a wallet address? --> You need to use the wallet / keypair of the wallet that is the current holder of the NFT.
This question is not related to candy machine but to transferring NFTs. Have a look here to learn how to transfer tokens: https://solanacookbook.com/references/basic-transactions.html#how-to-send-spl-tokens
Noticed this code comment in an Anchor test:
What's the ATA stand for there and why does it matter for DAO controlled authorities?
ATA is an associated token address.
Associated token addresses can be derived from another public key using findProgramAddress.
function getAssociatedTokenAddress(
mint: PublicKey,
owner: PublicKey,
allowOwnerOffCurve = false,
programId = TOKEN_PROGRAM_ID,
associatedTokenProgramId = ASSOCIATED_TOKEN_PROGRAM_ID
): Promise<PublicKey> {
if (!allowOwnerOffCurve && !PublicKey.isOnCurve(owner.toBuffer())) throw new TokenOwnerOffCurveError();
const [address] = await PublicKey.findProgramAddress(
[owner.toBuffer(), programId.toBuffer(), mint.toBuffer()],
associatedTokenProgramId
);
return address;
}
There is another type of token account that predates the associated token account, an ancillary token account. These legacy accounts still exist and can be created today.
The reason that the code says it can be either ATA or something else is because it is validating that the account is a token account that it expects.
After a user mints an nft, I want to get the token address or metadata and display it.
I'm using the Candy machine's ui from Metaplex
They're using the mintOneToken function and it only returns a confirmation code, and that's not helpful.
const mintTxId = (
await mintOneToken(candyMachine, wallet.publicKey)
);
Response
confirmationStatus: "confirmed"
I tried calling another function I got from Solana's cookbook , to get all the nfts minted by the current users wallet address.
But I think it fetches the data before the wallet gets updated and it doesn't retrieve the latest NFT minted
const updateNfts = async () => {
if (wallet.connected) {
const ownerPublickey = wallet.publicKey;
const nftsmetadata = await Metadata.findDataByOwner(connection, ownerPublickey);
if(nftsmetadata.length>0){
const amountOfNFT = nftsmetadata.length;
console.log(nftsmetadata[amountOfNFT - 1]);
}
}
}
How can I get the latest metadata to display it for the users? Should i set a timeout ?
I'm using Next.js, web3-react, ethers.js, MetaMask and Ganache to run a local blockchain.
What I'm trying to do: when the user clicks a button on the front-end, that button opens MetaMask where some tokens (I "minted/created" these tokens) are sent from the smart contract/smart contract creator to the user upon user consent.
The problem is: when the user clicks the button, the MetaMask pop-up appears, but the sender/recipient addresses are the same.
What I want is for the sender address to be the same as the smart contract/smart contract creator and this transaction should be done by MetaMask.
The following code is what I've done so far:
import { ethers, Contract } from 'ethers'
import { useWeb3React } from '#web3-react/core'
import HRC20 from '../../assets/HRC20.json'
const { account: userAccountAddress, library } = useWeb3React()
const provider = new ethers.providers.Web3Provider(
library.provider // this is the same as `window.ethereum.provider` injected by MetaMask
)
const signer = provider.getSigner()
const tokenContract = new ethers.Contract(
'0x4feEc53a54e36C80A2F0a47454Ab285B99A1a240',
HRC20.abi,
provider
)
const tokenContractWithSigner = contract.connect(signer)
const tx = tokenContractWithSigner.transfer(
userAccountAddress,
10000000000
)
My guess is that I need to specify the sender address when creating the provider or signer or something.
Based on calling tokenContractWithSigner.transfer, you have 2 args
function transfer(address _to, uint _value) public returns (bool success){
// make sure callee has enough balance
require(balanceOf[msg.sender]>=_value);
// ... more logic
to=payable(_to)
to.transfer(value);
}
Or:
function transfer(address _to, uint _value) public returns (bool success){
// make sure callee has enough balance
require(balanceOf[msg.sender]>=_value);
// ... more logic
to=payable(_to)
(bool success,)=to.call{value:_value}("");
require(success,"Transfer failed!");
}
When you call this:
tokenContractWithSigner.transfer(
userAccountAddress,
10000000000
).send({from:getAccount})
According to the ERC20 standart, the transfer method of an ERC20 contract is used to transfer tokens from the sender of the transaction, to the address specified. Because it is the same address that is sent the transaction and is given to the transfer method, the contract thinks you want to transfer tokens from an address to the same address.
To mint new tokens you need to add a mint method to your ERC20 contract.
I did find a solution to my problem: first, I can only make a transaction using MetaMask when the sender is me. I cannot send tokens on behalf of another wallet, even if I own it.
My approach was to create an endpoint on the backend that would receive the user's wallet address; then I connect to the wallet that holds the funds (usually the wallet that deployed the token) using its private key and that wallet signs the transaction. On the front end, I listen for a Transfer event so I can notify the user when their transactions are mined/confirmed.
Reference: https://ethereum.org/en/developers/tutorials/send-token-etherjs/#send-token-method
I have connected my Visual studio to Azure Active Directory by setting and manually entering pass/email.
This credential shows when I go to Azure Serice Authenticator in Visual Studio under tools.
I want to access the ID associated.
I came across this doc , and I want the AZURE_USERNAME , which must be associated with the id logged in.
I am unable to get a way by which I can access this value.
Does it mean that I can only access it if I explicitly set such value ?
--
Alternatively , is there any way by which I can access the Email ID of user signed in to Visual studio / or signed into Windows and not just User name
Yes of course we should preset environment variables.
Then we can use them for EnvironmentCredential authentication. The reverse will not work.
You can call Microsoft Graph API to get the user information.
Sample reference here.
You can implement the graphServiceClient like this:
var credential = new DefaultAzureCredential();
var token = credential.GetToken(
new Azure.Core.TokenRequestContext(
new[] { "https://graph.microsoft.com/.default" }));
var accessToken = token.Token;
var graphServiceClient = new GraphServiceClient(
new DelegateAuthenticationProvider((requestMessage) =>
{
requestMessage
.Headers
.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
return Task.CompletedTask;
}));
A blog for your reference.