Does anyone know how I can add a max supply to a Metaplex fungible asset ?
const metadata = await Metadata.getPDA(mint.publicKey);
const createMetadataTx = new CreateMetadataV2(
{ feePayer: mint_authority.publicKey },
{
metadata,
metadataData: new DataV2({
uri :'https://xxxx-88-81-106-161.ngrok.io/sample-uri',
name: 'ttt',
symbol: 'ttt',
sellerFeeBasisPoints: 100,
creators: null,
collection: null,
uses: null,
tokenStandard: TokenStandard.Fungible
}),
updateAuthority: mint_authority.publicKey,
mint: mint.publicKey,
mintAuthority: mint_authority.publicKey,
},
);
const sig = await connection.sendTransaction(createMetadataTx, [mint_authority],{
skipPreflight: false,
} )
const txRpcResponse = await connection.confirmTransaction(sig)
According to the current Metadata Struct, there is no such field as max supply you can look more into the SPL token program it contains a field called supply to know more about it you can look here or checkout the Solana Program Library Repo
Related
I am attempting to call the increment in the counter contract here, which is deployed to my account on testnet, using the following script:
const nearAPI = require("near-api-js");
require("dotenv").config();
const {parseSeedPhrase} = require("near-seed-phrase");
async function call() {
const mneumonic = process.env.nearmneumonic0?.trim() || "";
const ACCOUNT_ID = process.env.nearacct0?.trim() || "";
const keyStores = nearAPI.keyStores;
const keyPair = nearAPI.KeyPair;
const connect = nearAPI.connect;
const keyStore = new keyStores.InMemoryKeyStore();
const PRIVATE_KEY = parseSeedPhrase(mneumonic);
const keyPair_ = keyPair.fromString(PRIVATE_KEY.secretKey);
await keyStore.setKey("testnet", ACCOUNT_ID, keyPair_);
const config = {
keyStore,
networkId: "testnet",
nodeUrl: "https://rpc.testnet.near.org",
};
const near = await connect(config);
const account = await near.account(ACCOUNT_ID);
const contract = new nearAPI.Contract(
account,
ACCOUNT_ID,
{
changeMethods: ["increment", "decrement", "reset"],
viewMethods: ["get_num"],
sender: account,
}
);
let response = await contract.increment(
{
args: {
//arg_name: "value"
},
gas: 300000000000000
}
);
console.log(response);
}
call();
However, the response thrown is al followed:
Failure [acct.testnet]: Error: Contract method is not found
...
ServerTransactionError: Contract method is not found
I have looked through some of the docs, which mention to add changeMethod/viewMethod, however it seems there is still errors thrown.
Any help much appreciated!
I need to unwrap some SOL using the web3 sdk. I'm wondering, Is it just a simple transfer from the wrapped account into SOL account or is it more complicated than that? Below Is just some sample code I've setup.
const emptyWSolAccount = async (amount:any) => {
const wsolAddress = await Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
new PublicKey("So11111111111111111111111111111111111111112"),
wallet.publicKey
);
const wsolAccount = await connection.getAccountInfo(wsolAddress);
if (wsolAccount) {
const transaction = new Transaction({
feePayer: wallet.publicKey,
});
const instructions = [];
const lamports = amount * LAMPORTS_PER_SOL;
instructions.push(
SystemProgram.transfer({
fromPubkey: wsolAddress,
toPubkey: wallet.publicKey,
lamports: lamports, // 1 sol
})
);
transaction.add(...instructions);
transaction.recentBlockhash = await (
await connection.getRecentBlockhash()
).blockhash;
transaction.partialSign(wallet.payer);
const result = await connection.sendTransaction(transaction, [
wallet.payer,
]);
console.log({ result });
return { result };
}
return ;
};
This is not really explained anywhere, but unwrapping SOL actually means closing the wrapped SOL account.
So instead of using a SystemProgram.transfer instruction, you'll do:
instructions.push(
splToken.instructions.createCloseAccountInstruction(
wsolAddress,
wallet.publicKey,
wallet.publicKey,
)
);
This closes wsolAddress and sends the contents to wallet, assuming that wallet is the owner.
You can see the CLI implementation at https://github.com/solana-labs/solana-program-library/blob/3db53e278b543a040d3c970797b6be6f9ea5aef9/token/cli/src/main.rs#L1139-L1194
At https://github.com/NEAR-Edu/near-certification-tools/blob/ba220aa6d13b9d8e1996526c796aec203a2853d3/data-contract/src/contract/mint.rs#L41 I call self.tokens.internal_mint(token_id, to_account_id, Some(combined_metadata)) which calls NftMint { owner_id: &token.owner_id, token_ids: &[&token.token_id], memo: None }.emit();
But when I mint an NFT, I never see the nft_mint event in the testnet Explorer.
What am I doing wrong, or how can I step through a debug to narrow down to the general area where something is wrong?
The NFT does successfully get minted, in the sense that my TypeScript const response = await (contract as NFT).nft_tokens_for_owner({ account_id: accountId }); finds it.
Running the TypeScript integration-tests in https://github.com/near-examples/NFT with worskpaces version 3.2.2 will print the smart contract logs, so the standard contract will emit the events with emit().
As for this contract, you can create an integration-tests folder in the project root. Here you can make use of the workspaces library to run a local version of NEAR Blockchain and upload your smart contract code to it, and run the nft_mint function as follows:
import { Worker, NearAccount, tGas, NEAR, BN } from 'near-workspaces';
import anyTest, { TestFn } from 'ava';
import { mint_more, nft_total_supply } from './utils';
const test = anyTest as TestFn<{
worker: Worker;
accounts: Record<string, NearAccount>;
}>;
test.beforeEach(async t => {
const worker = await Worker.init();
const root = worker.rootAccount;
const nft = await root.devDeploy(
'../data-contract/target/wasm32-unknown-unknown/release/near_certification_tools.wasm',
{
initialBalance: NEAR.parse('100 N').toJSON(),
method: "new",
args: {
owner_id: root.accountId,
metadata: {
spec: "nft-1.0.0",
name: "Certification Tools",
symbol: "CT",
icon: null,
base_uri: null,
reference: null,
reference_hash: null,
},
options: {
can_transfer: true,
can_invalidate: true
}
}
},
);
const alice = await root.createSubAccount('alice', { initialBalance: NEAR.parse('100 N').toJSON() });
t.context.worker = worker;
t.context.accounts = { root, alice, nft };
});
test.afterEach.always(async t => {
await t.context.worker.tearDown().catch(error => {
console.log('Failed to tear down the worker:', error);
});
});
test('Simple mint', async test => {
const { root, alice, nft } = test.context.accounts;
await root.call(
nft,
"add_issuer",
{ account_id: root.accountId },
);
test.log('Issuer set');
await root.call(
nft,
"nft_mint",
{
token_id: "0",
receiver_account_id: alice.accountId,
token_metadata: {
title: "Olympus Mons",
description: "The tallest mountain in the charted solar system",
media: null,
media_hash: null,
copies: 10000,
issued_at: null,
expires_at: null,
starts_at: null,
updated_at: null,
extra: null,
reference: null,
reference_hash: null,
},
certification_metadata: {
authority_name: "NASA",
authority_id: null,
program: "Mars 2020",
program_name: null,
program_link: null,
program_start_date: null,
program_end_date: null,
original_recipient_id: null,
original_recipient_name: null,
valid: true,
memo: null
}
},
{ attachedDeposit: '8540000000000000000000' }
);
test.pass();
});
This generates the following output, whereby EVENT_LOG is sent to the logs of contract:
I have some problem in updating Metaplex NFT Metadata.
I used #metaplex/js and this is my code.
import { programs } from '#metaplex/js';
export const updateMetadataV1 = async () => {
let { metadata : {Metadata, UpdateMetadata, MetadataDataData, Creator} } = programs;
let signer = loadWalletKey(keyfile);
let nftMintAccount = new PublicKey("EC8gGdtVFDoTf3vEGbLvPp7SVWta2xQrs99iWMbaFrdE");
let metadataAccount = await Metadata.getPDA(nftMintAccount);
const metadat = await Metadata.load(solConnection, metadataAccount);
let newUri = "https://arweave.net/my arweave address";
if (metadat.data.data.creators != null) {
const creators = metadat.data.data.creators.map(
(el) =>
new Creator({
...el,
}),
);
let newMetadataData = new MetadataDataData({
name: metadat.data.data.name,
symbol: metadat.data.data.symbol,
uri: newUri,
creators: [...creators],
sellerFeeBasisPoints: metadat.data.data.sellerFeeBasisPoints,
})
const updateTx = new UpdateMetadata(
{ feePayer: signer.publicKey },
{
metadata: metadataAccount,
updateAuthority: signer.publicKey,
metadataData: newMetadataData,
newUpdateAuthority: signer.publicKey,
primarySaleHappened: metadat.data.primarySaleHappened,
},
);
let result = await sendAndConfirmTransaction(solConnection, updateTx, [signer]);
console.log("result =", result);
}
}
The transaction result has no error, it means transaction success.
I checked it on Solana Explorer.
But the metadata doesn't change. What's the matter?
To Solve this issue this code can be used, This is a low-level code that uses the mpl-token-metadata npm package to call the on-chain updateMetadata Function.
import { Wallet } from "#project-serum/anchor";
import * as anchor from "#project-serum/anchor";
import {createUpdateMetadataAccountV2Instruction,DataV2,UpdateMetadataAccountV2InstructionArgs,UpdateMetadataAccountV2InstructionAccounts} from "#metaplex-foundation/mpl-token-metadata"
const fs = require("fs");
(async() => {
// This is the Update Authority Secret Key
const secretKey = fs.readFileSync(
"/Users/pratiksaria/.config/solana/id.json",
"utf8"
);
const keypair = anchor.web3.Keypair.fromSecretKey(
Buffer.from(JSON.parse(secretKey))
);
const endpoint = "https://metaplex.devnet.rpcpool.com/";
const connection = new anchor.web3.Connection(endpoint);
const wallet = new Wallet(keypair);
console.log("Connected Wallet", wallet.publicKey.toString());
const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey(
"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
);
// You have to enter your NFT Mint address Over Here
const mintKey = new anchor.web3.PublicKey("5iSxT33FyHWsnb8NYSytY17TTXfkFn62FiCyFVFxYhqY");
const [metadatakey] = await anchor.web3.PublicKey.findProgramAddress(
[
Buffer.from("metadata"),
TOKEN_METADATA_PROGRAM_ID.toBuffer(),
mintKey.toBuffer(),
],
TOKEN_METADATA_PROGRAM_ID
);
// BTW DeGods is my FAV collection although i cant afford one 🥲
const updated_data: DataV2 = {
name: "DeGods",
symbol: "DG",
uri: "https://metadata.degods.com/g/4924.json",
sellerFeeBasisPoints: 1000,
creators: [
{
address: new anchor.web3.PublicKey(
"CsEYyFxVtXxezfLTUWYwpj4ia5oCAsBKznJBWiNKLyxK"
),
verified: false,
share: 0,
},
{
address: wallet.publicKey,
verified: false,
share: 100,
},
],
collection: null,
uses: null,
};
const accounts:UpdateMetadataAccountV2InstructionAccounts = {
metadata: metadatakey,
updateAuthority: wallet.publicKey,
}
const args:UpdateMetadataAccountV2InstructionArgs = {
updateMetadataAccountArgsV2: {
data: updated_data,
updateAuthority: wallet.publicKey,
primarySaleHappened: true,
isMutable: true,
}
}
const updateMetadataAccount = createUpdateMetadataAccountV2Instruction(
accounts,
args
);
const transaction = new anchor.web3.Transaction()
transaction.add(updateMetadataAccount);
const {blockhash} = await connection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = wallet.publicKey;
const signedTx = await wallet.signTransaction(transaction);
const txid = await connection.sendRawTransaction(signedTx.serialize());
console.log("Transaction ID --",txid);
})()
let blockhashObj = await solConnection.getLatestBlockhash();
updateTx.recentBlockhash = blockhashObj.blockhash;
updateTx.sign(alice);
let endocdeTransction = updateTx.serialize({
requireAllSignatures: false,
verifySignatures: false,
});
var signature = await solConnection.sendRawTransaction(endocdeTransction, {
skipPreflight: false,
});
Trying to follow the samples from https://github.com/Azure/ms-rest-nodeauth
When passing authresponse to a client to generate a client to ping resources, I end up getting:
Error: credentials argument needs to implement signRequest method
I am trying to read through the documents to see if I need to sign the token's I am getting back from the SDK/Azure AD, but the documentation for the new SDK doesnt show anything
Figured it out, have to call .credentials on the authresponse
Adding the code, using #azure/arm-billing, in case the full code file is helpful.
// auth.json
// Create auth file with Azure CLI:`az ad sp create-for-rbac --sdk-auth > auth.json`
{
"clientId": "",
"clientSecret": "",
"subscriptionId": "",
"tenantId": "",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}
// index.js
const msRest = require("#azure/ms-rest-js");
const msRestAzure = require("#azure/ms-rest-azure-js");
const msRestNodeAuth = require("#azure/ms-rest-nodeauth");
const armBilling = require("#azure/arm-billing");
const path = require('path');
// list billing information
const lists = async (client) => {
try {
let lists = [];
const enrollmentAccounts = await client.enrollmentAccounts.list();
lists.push(enrollmentAccounts);
const billingPeriods = await client.billingPeriods.list();
lists.push(billingPeriods);
const invoices = await client.invoices.list();
lists.push(invoices);
return lists;
} catch (err) {
console.log(err);
throw (err);
}
}
// sample auth file created from Azure CLI - removed PII
const authenticationFile = path.join(__dirname, "./auth.json");
const options = {
filePath: authenticationFile
};
// get subscriptionId from auth file
const subscriptionIdFromAuthFile = require('./auth.json').subscriptionId;
// authenticate and getting billing information
msRestNodeAuth.loginWithAuthFileWithAuthResponse(options).then(async (response) => {
console.log("authenticated");
// --- CHANGE response parameter to -> response.credentials
const client = new armBilling.BillingManagementClient(response.credentials, subscriptionIdFromAuthFile);
console.log("client created");
const results = await lists(client);
console.log(`The result is:${JSON.stringify(results)}`);
}).catch((err) => {
console.error(err);
});