Skip to content

Commit

Permalink
Merge branch 'solana-foundation:main' into aoc-ita
Browse files Browse the repository at this point in the history
  • Loading branch information
SAMAD101 authored Sep 5, 2024
2 parents b137b8c + 3c43753 commit b1d8695
Show file tree
Hide file tree
Showing 61 changed files with 2,632 additions and 1,363 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,7 @@ typings/
package-lock.json

# translations are stored in the `i18n` via crowdin
i18n
i18n

# vscode configuration
.vscode
44 changes: 44 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,50 @@ To embed a Whimsical diagram:
slightly deflated beach ball. **Do not draw a snake or some other kind or
curve!**

### Tabs

The Tabs component allows you to organize content into multiple tabbed sections,
enabling users to switch between content.

Wrap your content in <Tabs> and use <Tab> for each individual tab section.

```md
<!-- prettier-ignore -->
<Tabs groupId="language" items={['Rust', 'Typescript']}>
<Tab value="Rust">Rust 1</Tab>
<Tab value="Typescript">Typescript 1</Tab>
</Tabs>
```

### Accordion

The Accordion component allows you to create collapsible content sections. It's
useful for organizing and presenting information in a compact, expandable
format.

Wrap your content in <Accordion> and use <AccordionItem> for each collapsible
section.

<!-- prettier-ignore -->
```md
<Accordion>
<AccordionItem title="Hello">

```ts
console.log("hello");
```

</AccordionItem>
<AccordionItem title="World">

```rs
println!("world");
```

</AccordionItem>
</Accordion>
```
## Translations
Content translations are supported via the Crowdin platform.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ the Solana ecosystem and displayed on
There are a few primary types of Solana Developer content within this repo:

- [`courses`](#cources) - multiple lessons comprehensively covering a given
topic, with both a read session and and an interactive lab for each lesson
topic, with both a theory section and an interactive lab for each lesson
- [`docs`](#docs) - the [core documentation](https://solana.com/docs) for the
Solana blockchain
- [`guides`](#developer-guides) - long form tutorials focused on a specific
Expand Down
184 changes: 184 additions & 0 deletions content/cookbook/tokens/create-nft.md
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);
}
})();
```
50 changes: 50 additions & 0 deletions content/cookbook/tokens/fetch-all-nfts.md
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);
}
})();
```
59 changes: 59 additions & 0 deletions content/cookbook/tokens/fetch-nft-metadata.md
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);
}
})();
```
Loading

0 comments on commit b1d8695

Please sign in to comment.