-
Notifications
You must be signed in to change notification settings - Fork 256
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'solana-foundation:main' into aoc-ita
- Loading branch information
Showing
61 changed files
with
2,632 additions
and
1,363 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
--- | ||
title: How to create an NFT | ||
sidebarSortOrder: 15 | ||
description: "Learn how to create an NFT on Solana, using Arweave and Metaplex." | ||
--- | ||
|
||
To create an NFT you have to: | ||
|
||
1. Upload the image to IPFS like Arweave | ||
2. Upload the JSON metadata to Arweave or similar storage service. | ||
3. Call metaplex to create an account for the NFT | ||
|
||
### Upload to Arweave | ||
|
||
```typescript filename="upload-to-arweave.ts" | ||
import fs from "node:fs"; | ||
import Arweave from "arweave"; | ||
|
||
(async () => { | ||
const arweave = Arweave.init({ | ||
host: "localhost", | ||
port: 1984, | ||
protocol: "http", | ||
timeout: 20000, | ||
logging: false, | ||
}); | ||
|
||
const host = arweave.getConfig().api.host; | ||
const port = arweave.getConfig().api.port; | ||
const protocol = arweave.getConfig().api.protocol; | ||
|
||
// Upload image to Arweave | ||
const data = fs.readFileSync("./code/nfts/upload-arweave/lowres-dog.png"); | ||
|
||
const transaction = await arweave.createTransaction({ | ||
data: data, | ||
}); | ||
|
||
transaction.addTag("Content-Type", "image/png"); | ||
|
||
// Instead of generating a new wallet, you can use an existing one from your file system | ||
// useful in production environments | ||
// const wallet = JSON.parse(fs.readFileSync("./code/nfts/upload-arweave/wallet.json", "utf-8")) | ||
const wallet = await arweave.wallets.generate(); | ||
const address = await arweave.wallets.getAddress(wallet); | ||
console.log("address:, ", address); | ||
|
||
await arweave.api.get(`/mint/${encodeURI(addr)}/10000000000000000`); | ||
await arweave.transactions.sign(transaction, wallet); | ||
|
||
const response = await arweave.transactions.post(transaction); | ||
console.log(response); | ||
|
||
const id = transaction.id; | ||
const imageUrl = id ? `${protocol}://${host}:${port}/${id}` : null; | ||
console.log("imageUrl", imageUrl); | ||
|
||
// Upload metadata to Arweave | ||
|
||
const metadata = { | ||
name: "Custom NFT #1", | ||
symbol: "CNFT", | ||
description: "A description about my custom NFT #1", | ||
seller_fee_basis_points: 500, | ||
external_url: "https://www.customnft.com/", | ||
attributes: [ | ||
{ | ||
trait_type: "NFT type", | ||
value: "Custom", | ||
}, | ||
], | ||
collection: { | ||
name: "Test Collection", | ||
family: "Custom NFTs", | ||
}, | ||
properties: { | ||
files: [ | ||
{ | ||
uri: imageUrl, | ||
type: "image/png", | ||
}, | ||
], | ||
category: "image", | ||
maxSupply: 0, | ||
creators: [ | ||
{ | ||
address: "CBBUMHRmbVUck99mTCip5sHP16kzGj3QTYB8K3XxwmQx", | ||
share: 100, | ||
}, | ||
], | ||
}, | ||
image: imageUrl, | ||
}; | ||
|
||
const metadataString = JSON.stringify(metadata); | ||
|
||
const metadataTransaction = await arweave.createTransaction({ | ||
data: metadataString, | ||
}); | ||
|
||
metadataTransaction.addTag("Content-Type", "application/json"); | ||
|
||
await arweave.transactions.sign(metadataTransaction, wallet); | ||
|
||
console.log("metadata txid", metadataTransaction.id); | ||
|
||
const txnResult = await arweave.transactions.post(metadataTransaction); | ||
|
||
console.log(txnResult); | ||
})(); | ||
``` | ||
|
||
### Mint the NFT | ||
|
||
```typescript filename="mint-nft.ts" | ||
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; | ||
import { | ||
generateSigner, | ||
percentAmount, | ||
keypairIdentity, | ||
} from "@metaplex-foundation/umi"; | ||
import { clusterApiUrl } from "@solana/web3.js"; | ||
import { | ||
createNft, | ||
fetchDigitalAsset, | ||
mplTokenMetadata, | ||
} from "@metaplex-foundation/mpl-token-metadata"; | ||
import "dotenv/config"; | ||
|
||
(async () => { | ||
try { | ||
console.log("Loading keypair from environment..."); | ||
const privateKey = JSON.parse(process.env.SOLANA_PRIVATE_KEY || "[]"); | ||
if (privateKey.length === 0) { | ||
throw new Error("SOLANA_PRIVATE_KEY is not set in .env file"); | ||
} | ||
|
||
console.log("Creating Umi instance..."); | ||
const umi = createUmi(clusterApiUrl("devnet")); | ||
|
||
const keypair = umi.eddsa.createKeypairFromSecretKey( | ||
new Uint8Array(privateKey), | ||
); | ||
|
||
// Use keypairIdentity to set the keypair as the signer | ||
const signer = keypairIdentity(keypair); | ||
umi.use(signer); | ||
umi.use(mplTokenMetadata()); | ||
|
||
console.log("Keypair loaded. Public key:", keypair.publicKey); | ||
|
||
console.log("Generating new mint address..."); | ||
const mint = generateSigner(umi); | ||
|
||
console.log("Creating NFT..."); | ||
const { signature } = await createNft(umi, { | ||
mint, | ||
name: "My NFT", | ||
// Replace this with your Arweave metadata URI | ||
uri: "https://ffaaqinzhkt4ukhbohixfliubnvpjgyedi3f2iccrq4efh3s.arweave.net/KUAIIbk6p8oo4XHRcq0U__C2r0mwQaNl0gQow4Qp9yk", | ||
maxSupply: 1, | ||
sellerFeeBasisPoints: percentAmount(0), | ||
creators: [ | ||
{ | ||
address: keypair.publicKey, | ||
share: 100, | ||
verified: true, | ||
}, | ||
], | ||
}).sendAndConfirm(umi); | ||
|
||
console.log("NFT created successfully!"); | ||
console.log("Mint address:", mint.publicKey); | ||
console.log("Transaction signature:", signature); | ||
|
||
console.log("Fetching digital asset..."); | ||
const asset = await fetchDigitalAsset(umi, mint.publicKey); | ||
console.log("Digital Asset:", asset); | ||
} catch (error) { | ||
console.error("Error:", error); | ||
console.error("Stack trace:", error.stack); | ||
} | ||
})(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
--- | ||
title: How to get all NFTs from a wallet? | ||
sidebarSortOrder: 18 | ||
description: | ||
"Learn how to fetch all non-fungible tokens (NFTs) from a wallet on Solana." | ||
--- | ||
|
||
```typescript filename="get-nfts-by-wallet.ts" | ||
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; | ||
import { publicKey } from "@metaplex-foundation/umi"; | ||
import { fetchAllDigitalAssetWithTokenByOwner } from "@metaplex-foundation/mpl-token-metadata"; | ||
import { clusterApiUrl } from "@solana/web3.js"; | ||
|
||
BigInt.prototype.toJSON = function () { | ||
return this.toString(); | ||
}; | ||
|
||
(async () => { | ||
try { | ||
// Create a UMI instance | ||
const umi = createUmi(clusterApiUrl("devnet")); | ||
|
||
// The owner's public key | ||
const ownerPublicKey = publicKey( | ||
"2R4bHmSBHkHAskerTHE6GE1Fxbn31kaD5gHqpsPySVd7", | ||
); | ||
|
||
console.log("Fetching NFTs..."); | ||
const allNFTs = await fetchAllDigitalAssetWithTokenByOwner( | ||
umi, | ||
ownerPublicKey, | ||
); | ||
|
||
console.log(`Found ${allNFTs.length} NFTs for the owner:`); | ||
allNFTs.forEach((nft, index) => { | ||
console.log(`\nNFT #${index + 1}:`); | ||
console.log("Mint Address:", nft.publicKey); | ||
console.log("Name:", nft.metadata.name); | ||
console.log("Symbol:", nft.metadata.symbol); | ||
console.log("URI:", nft.metadata.uri); | ||
}); | ||
|
||
// If you need the full NFT data | ||
console.log("\nFull NFT data:"); | ||
console.log(JSON.stringify(allNFTs, null, 2)); | ||
} catch (error) { | ||
console.error("Error:", error); | ||
} | ||
})(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
--- | ||
title: How to Fetch the NFT Metadata | ||
sidebarSortOrder: 16 | ||
description: | ||
"Learn how to fetch the metadata of a non-fungible token (NFT) on Solana." | ||
--- | ||
|
||
```typescript filename="get-nft-metadata.ts" | ||
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"; | ||
import { | ||
createSignerFromKeypair, | ||
generateSigner, | ||
signerIdentity, | ||
} from "@metaplex-foundation/umi"; | ||
import { | ||
fetchDigitalAsset, | ||
mplTokenMetadata, | ||
} from "@metaplex-foundation/mpl-token-metadata"; | ||
import { PublicKey } from "@metaplex-foundation/js"; | ||
|
||
(async () => { | ||
try { | ||
// Create a UMI instance | ||
const umi = createUmi("https://api.mainnet-beta.solana.com"); | ||
|
||
// Use the mplTokenMetadata plugin | ||
umi.use(mplTokenMetadata()); | ||
|
||
// Generate a new keypair (you can replace this with your own keypair if needed) | ||
const keypair = generateSigner(umi); | ||
umi.use(signerIdentity(createSignerFromKeypair(umi, keypair))); | ||
|
||
// The mint address of the NFT you want to fetch | ||
const mintAddress = new PublicKey( | ||
"Ay1U9DWphDgc7hq58Yj1yHabt91zTzvV2YJbAWkPNbaK", | ||
); | ||
|
||
console.log("Fetching NFT metadata..."); | ||
const asset = await fetchDigitalAsset(umi, mintAddress); | ||
|
||
console.log("NFT Metadata:"); | ||
|
||
// If you want to access specific metadata fields: | ||
console.log("\nName:", asset.metadata.name); | ||
console.log("Symbol:", asset.metadata.symbol); | ||
console.log("URI:", asset.metadata.uri); | ||
|
||
// Fetch and log the JSON metadata | ||
if (asset.metadata.uri) { | ||
const response = await fetch(asset.metadata.uri); | ||
const jsonMetadata = await response.json(); | ||
console.log("\nJSON Metadata:"); | ||
console.log(JSON.stringify(jsonMetadata, null, 2)); | ||
} | ||
} catch (error) { | ||
console.error("Error:", error); | ||
} | ||
})(); | ||
``` |
Oops, something went wrong.