metaplex-foundation / js

A JavaScript SDK for interacting with Metaplex's programs
357 stars 182 forks source link

Adding metadata to a new fungible token. #295

Closed Bhaney44 closed 2 years ago

Bhaney44 commented 2 years ago

Overview

I've been working on finding a method for adding metadata to a new fungible token for a few days now. However, it appears there is a need for this as one does not currently exist. I've documented some troubles in this Issue.

Core Problem

With the change from Solana-Labs Token List to the MetaPlexToken MetaData Program, there is now no method for adding MetaData to a new asset on Solana. There is documentation for the MetaPlex JS-SDK, however it focuses only on the nfts() method.

The MetaPlex metadata instructions explain the metadata file, but they provide no explanation of how to actually add the metadata to a token. Thus, there is a need for a method to add metadata to new SPL tokens. This is important because without a method for adding metadata to assets, new SPL tokens cannot be launched on the Solana blockchain.

Solution Needed An ideal solution would be a directory, guide, or resource providing a step-by-step guide on how to add metadata to an SPL fungible token. Thanks in advance - I sincerely appreciate any suggestions or advice!

lorisleiva commented 2 years ago

Hi there πŸ‘‹

100% I wish I had more time to dedicate to documentation right now but I, unfortunately, don't.

In the meantime, you can use API references to explore what the SDK has to offer.

Here are the API references for the create SFT operation:

Notice the useExistingMint parameter that allows you to add Metadata to an existing mint account.

Bhaney44 commented 2 years ago

Hi @lorisleiva, thanks for the reply. Please open this Issue back up. It's an important problem and I'm working hard to solve it. When you close an issue without resolving it, it makes it difficult to continue working toward a solution. You provided two links, but neither satisfy the problem. For example, the first link you provided is for an NFT method, but my problem is focusing on fungible tokens.

const { uri } = await metaplex
  .nfts()
  .uploadMetadata({
    name: "My NFT",
    description: "My description",
    image: "https://arweave.net/123",
  })
  .run(); 

This function is dependent on the .nfts()method, which means it will likely fail for use with fungible tokens. Moreover, in the second link, there is no way to actually use the useExistingMint?: PublicKey function, nor instruction on how to use it.

I've been working hard on solving this problem for several days now. I know you are very busy, I am too, but I am willing to take the time to document this problem and develop a solution. Once, I've finished, I can make a PR with the documentation. The problem is I did not write this code and it is not at all documented, so I have no method to actually use it. It is very important that projects can add metadata to SPL tokens. For that reason, please re-open this issue, so we can continue working on a solution.

With thanks,

Brian Haney

lorisleiva commented 2 years ago

I have provided you with the solution.

SFT stands for Semi-Fungible Token which is what we call fungible tokens with a Metadata account which you are trying to achieve.

The first link even provide an code example on how to use it.

const { sft } = await metaplex
  .nfts()
  .createSft({
    name: 'My SFT',
    uri: 'https://example.com/my-sft',
    sellerFeeBasisPoints: 250, // 2.5%
  })
  .run();

Simply add the useExistingMint parameter I mentioned before and you will be able to transform a mint account into an SFT.

const { sft } = await metaplex
  .nfts()
  .createSft({
    name: 'My SFT',
    uri: 'https://example.com/my-sft',
    sellerFeeBasisPoints: 250, // 2.5%
    useExistingMint: new PublicKey('your-mint-account-address-here'),
  })
  .run();
Bhaney44 commented 2 years ago

My apologies @lorisleiva. This is not a solution to my problem. There is also no context for executing the function you provided.

I will simplify the problem. I have created both the TOKEN_URI.json and the Meta_Data.json files. I have also created a token account and token address.

The problem is there is currently no method on Solana to assign metadata to a fungible token. For example, Samoyed Coin is a fungible token with assigned metadata, including a name and an image. Ultimately, this is what I intend to accomplish, create a token with an associated name and image. However, there needs to be a method for accomplishing this task.

Bhaney44 commented 2 years ago

With the solution you provided there are still outstanding issues.

const { sft } = await metaplex
  .nfts()
  .createSft({
    name: 'My SFT',
    uri: 'https://example.com/my-sft',
    sellerFeeBasisPoints: 250, // 2.5%
    useExistingMint: new PublicKey('your-mint-account-address-here'),
  })
  .run();
  1. How is the URI data validated and attached? Is a TOKEN_URI.json file sufficient if stored on GitHub? if so, is a link in the URI category sufficient to satisfy this constraint?
  2. What are the necessary dependencies for running this script? Would there need to be a package.json file to run a script with this function? What are the required imports?

Thanks in advance for your help @lorisleiva - I sincerely appreciate your time.

lorisleiva commented 2 years ago

Hi there πŸ‘‹

I have carefully read your problem and I can assure you that this piece of code is the solution to your problem.

Adding a Metadata account to a fungible token is what this function does when you provide the address of the Mint account as the useExistingMint parameter.

Regarding this uri parameter, it should point to your JSON file. Whether this is on-chain or off-chain is up to you. You can use other SDK methods to upload that JSON file on-chain if necessary. These are documented in the readme.

I recommend you look at all the parameters available in the URL I provided in my initial response to see what else is available in that operation.

Regarding setting up a JavaScript script to execute this, there are plenty of tutorials out there to set this up. I assume users of a JavaScript SDK are at least familiar with JavaScript.

Bhaney44 commented 2 years ago

Hi there πŸ‘‹

I have carefully read your problem and I can assure you that this piece of code is the solution to your problem.

Adding a Metadata account to a fungible token is what this function does when you provide the address of the Mint account as the useExistingMint parameter.

Regarding this uri parameter, it should point to your JSON file. Whether this is on-chain or off-chain is up to you. You can use other SDK methods to upload that JSON file on-chain if necessary. These are documented in the readme.

I recommend you look at all the parameters available in the URL I provided in my initial response to see what else is available in that operation.

Regarding setting up a JavaScript script to execute this, there are plenty of tutorials out there to set this up. I assume users of a JavaScript SDK are at least familiar with JavaScript.

Alright, thanks anyway @lorisleiva.

Bhaney44 commented 2 years ago

Hi there πŸ‘‹

I have carefully read your problem and I can assure you that this piece of code is the solution to your problem.

Adding a Metadata account to a fungible token is what this function does when you provide the address of the Mint account as the useExistingMint parameter.

Regarding this uri parameter, it should point to your JSON file. Whether this is on-chain or off-chain is up to you. You can use other SDK methods to upload that JSON file on-chain if necessary. These are documented in the readme.

I recommend you look at all the parameters available in the URL I provided in my initial response to see what else is available in that operation.

Regarding setting up a JavaScript script to execute this, there are plenty of tutorials out there to set this up. I assume users of a JavaScript SDK are at least familiar with JavaScript.

The problem with the useExistingMint parameter is there is no context for how the transaction to update the metadata is signed. This is a problem because the variables necessary to actually sign the transaction updating the metadata are missing. I'm getting consistent errors running the code you proposed would sole the problem.

useExistingMint: new PublicKey(''),

returns

ReferenceError: PublicKey is not defined

Bhaney44 commented 2 years ago

useExistingMint: new PublicKey('your-mint-account-address-here'),

useExistingMint: new PublicKey('your-mint-account-address-here'),

This line here is wrong. There is no definition for the PublicKey function. Additionally, your code does not make sense conceptually because according to the docs, the code should require some signature authority from the mint address or token account. Another problem is there is no explanation for this in the documentation.

lorisleiva commented 2 years ago

Hey πŸ‘‹ Yes, sadly the documentation does not cover everything that the SDK has to offer just yet and I'm sorry that you've not had a great experience with the SDK so far.

Unfortunately, for the same reasons that I can't dedicate much time to the documentation right now, I cannot provide a detailed tutorial to every single request I get on GitHub, Twitter, Discord, Email, etc.

The problem you're facing right now is that you need to import PublicKey from Solana's web3.js library. This library is part of the installation code written in the documentation of the SDK.

I cannot assist you much more than that but, that being said, there is a test on the SDK that you might benefit from reading as its goal is to add metadata to an existing token. Click here to read the test on GitHub.

Also, feel free to join our Metaplex Discord server where community developers can assist you when you have specific questions.

Bhaney44 commented 2 years ago

Hey πŸ‘‹ Yes, sadly the documentation does not cover everything that the SDK has to offer just yet and I'm sorry that you've not had a great experience with the SDK so far.

Unfortunately, for the same reasons that I can't dedicate much time to the documentation right now, I cannot provide a detailed tutorial to every single request I get on GitHub, Twitter, Discord, Email, etc.

The problem you're facing right now is that you need to import PublicKey from Solana's web3.js library. This library is part of the installation code written in the documentation of the SDK.

I cannot assist you much more than that but, that being said, there is a test on the SDK that you might benefit from reading as its goal is to add metadata to an existing token. Click here to read the test on GitHub.

Also, feel free to join our Metaplex Discord server where community developers can assist you when you have specific questions.

So, how do I import PublicKey? Here are the imports from the code you sent:

import { Sft, SftWithToken, token, toMetaplexFile } from '@/index';
import { UseMethod } from '@metaplex-foundation/mpl-token-metadata';
import { Keypair } from '@solana/web3.js';
import spok, { Specifications } from 'spok';
import test, { Test } from 'tape';
import {
  createWallet,
  killStuckProcess,
  metaplex,
  spokSameAmount,
  spokSameBignum,
  spokSamePubkey,
} from '../../helpers';

But PublicKey isn't one of them. I don't see where it is part of the installation code. I ran the installation:

npm install @metaplex-foundation/js @solana/web3.js

But, I am still getting the error.

I get you're busy, but MetaPlex needs to provide sufficient documentation for developers to be able to add metadata. I'd be happy to help provide more detailed documentation on this as I work through this problem. Does MetaPlex offer grants for developers? I think this is an important problem that needs solved because it prevents the development of new assets on Solana.

Thanks again for your help.

Brian

Bhaney44 commented 2 years ago

Ok - I re-ran the installation in the local directory and it solved the PublicKey issue. I am now getting a new bug.

(base) fortiorb@FortiorBs-MacBook-Pro SPL_Token % node metadata.js
file:///Users/fortiorb/Desktop/Programming/SPL_Token/node_modules/@metaplex-foundation/js/dist/esm/plugins/nftModule/pdas.mjs:9
  return Pda.find(programId, [Buffer.from('metadata', 'utf8'), programId.toBuffer(), mint.toBuffer()]);
                                                                                          ^

TypeError: mint.toBuffer is not a function
    at findMetadataPda (file:///Users/fortiorb/Desktop/Programming/SPL_Token/node_modules/@metaplex-foundation/js/dist/esm/plugins/nftModule/pdas.mjs:9:91)
    at createSftBuilder (file:///Users/fortiorb/Desktop/Programming/SPL_Token/node_modules/@metaplex-foundation/js/dist/esm/plugins/nftModule/operations/createSft.mjs:97:23)
    at async Object.handle (file:///Users/fortiorb/Desktop/Programming/SPL_Token/node_modules/@metaplex-foundation/js/dist/esm/plugins/nftModule/operations/createSft.mjs:53:21)
    at async file:///Users/fortiorb/Desktop/Programming/SPL_Token/node_modules/@metaplex-foundation/js/dist/esm/utils/Task.mjs:58:23
    at async Disposable.run (file:///Users/fortiorb/Desktop/Programming/SPL_Token/node_modules/@metaplex-foundation/js/dist/esm/utils/Disposable.mjs:22:14)

It looks a bug in the nftModule/pdas.mjs:9module.

Bhaney44 commented 2 years ago

I really think this Issue should be opened @lorisleiva. The decision to close it was pre-mature because there is no existing solution. I am still hacking through the issue and debugging the code in #Issue748. All else being peripheral, there currently is no method for adding token metadata to a non-fungible token on Solana and there needs to be documentation for this so people are able to add metadata to new assets.

There must be some sort of agreement between @solana-labs and @metaplex-foundation that provided for the financial support of the token metadata program. Given the clear need, I'm wondering how I can apply to get support from MetaPlex to continue working on this problem and ultimately contribute to the documentation. Or, whether I would need to apply for funding from the Solana Foundation directly. Thanks!