diff --git a/content/cookbook/accounts/get-account-balance.md b/content/cookbook/accounts/get-account-balance.md
index 98a077947..5ef4b2853 100644
--- a/content/cookbook/accounts/get-account-balance.md
+++ b/content/cookbook/accounts/get-account-balance.md
@@ -6,6 +6,35 @@ description:
that account balance on Solana."
---
+
+
+
+
+```typescript filename="get-account-balance.ts" {13}
+import { address, createSolanaRpc } from "@solana/web3.js";
+const LAMPORTS_PER_SOL = 1000000000;
+
+async function getBalance() {
+ const rpc = createSolanaRpc("https://api.devnet.solana.com");
+ const addressToRequest = address(
+ "web3Qm5PuFapMJqe6PWRWfRBarkeqE2ZC8Eew3zwHH2",
+ );
+
+ try {
+ const result = await rpc.getBalance(addressToRequest).send();
+ console.log(`Balance: ${Number(result.value) / LAMPORTS_PER_SOL} sol.`);
+ } catch (err) {
+ console.error("Error fetching balance:", err);
+ }
+}
+
+getBalance();
+```
+
+
+
+
+
```typescript filename="get-account-balance.ts" {13}
import {
clusterApiUrl,
@@ -23,3 +52,7 @@ import {
);
})();
```
+
+
+
+
diff --git a/content/cookbook/development/load-keypair-from-file.md b/content/cookbook/development/load-keypair-from-file.md
new file mode 100644
index 000000000..b7ada9236
--- /dev/null
+++ b/content/cookbook/development/load-keypair-from-file.md
@@ -0,0 +1,87 @@
+---
+title: Load a local json file keypair
+sidebarSortOrder: 6
+description: "Learn how to load a keypair from file."
+---
+
+When running your local project you probably want to use a file json keypair.
+This can be very useful for all the cookbook examples as well. You can grind
+yourself a keypair using `solana-keygen grind --starts-with a23:1` and then load
+and use this one for your projects using the `loadKeypairFromFile` function.
+
+```typescript filename="load-keypair-from-file.ts"
+import {
+ airdropFactory,
+ createKeyPairFromBytes,
+ createSolanaRpc,
+ createSolanaRpcSubscriptions,
+ devnet,
+ generateKeyPair,
+ getAddressFromPublicKey,
+ lamports,
+} from "@solana/web3.js";
+import fs from "fs";
+import path from "path";
+import os from "os";
+
+// The new library takes a brand-new approach to Solana key pairs and addresses,
+// which will feel quite different from the classes PublicKey and Keypair from version 1.x.
+// All key operations now use the native Ed25519 implementation in JavaScript’s
+// Web Crypto API.
+async function createKeypair() {
+ const newKeypair: CryptoKeyPair = await generateKeyPair();
+ const publicAddress = await getAddressFromPublicKey(newKeypair.publicKey);
+
+ console.log(`Public key: ${publicAddress}`);
+}
+
+export async function loadDefaultKeypair(): Promise {
+ return await loadKeypairFromFile("~/.config/solana/id.json");
+}
+
+export async function loadDefaultKeypairWithAirdrop(
+ cluster: string,
+): Promise {
+ const keypair = await loadDefaultKeypair();
+ const rpc = createSolanaRpc(devnet(`https://api.${cluster}.solana.com`));
+ const rpcSubscriptions = createSolanaRpcSubscriptions(
+ devnet(`wss://api.${cluster}.solana.com`),
+ );
+ try {
+ const result = await rpc
+ .getBalance(await getAddressFromPublicKey(keypair.publicKey))
+ .send();
+
+ console.log(`Balance: ${result.value} lamports`);
+ if (result.value < lamports(500_000n)) {
+ console.log(`Balance low requesting airdrop`);
+ const airdrop = airdropFactory({ rpc, rpcSubscriptions });
+ await airdrop({
+ commitment: "confirmed",
+ lamports: lamports(1000_000n),
+ recipientAddress: await getAddressFromPublicKey(keypair.publicKey),
+ });
+ }
+ } catch (err) {
+ console.error("Error fetching balance:", err);
+ }
+ return keypair;
+}
+
+export async function loadKeypairFromFile(
+ filePath: string,
+): Promise {
+ // This is here so you can also load the default keypair from the file system.
+ const resolvedPath = path.resolve(
+ filePath.startsWith("~") ? filePath.replace("~", os.homedir()) : filePath,
+ );
+ const loadedKeyBytes = Uint8Array.from(
+ JSON.parse(fs.readFileSync(resolvedPath, "utf8")),
+ );
+ // Here you can also set the second parameter to true in case you need to extract your private key.
+ const keypair = await createKeyPairFromBytes(loadedKeyBytes);
+ return keypair;
+}
+
+createKeypair();
+```
diff --git a/content/cookbook/transactions/add-memo.md b/content/cookbook/transactions/add-memo.md
index 93deb235e..490566307 100644
--- a/content/cookbook/transactions/add-memo.md
+++ b/content/cookbook/transactions/add-memo.md
@@ -6,9 +6,126 @@ description:
how to add a memo to your transactions on Solana."
---
-Any transaction can add a message making use of the memo program. Currently the
-programID from the Memo Program has to be added manually
-`MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr`.
+Any transaction can add a message making use of the memo program. In web3.js@1
+the programID from the Memo Program has to be added manually
+`MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr` in V2 you can use
+`getAddMemoInstruction`.
+
+
+
+
+
+```typescript filename="add-memo.ts" {61-72}
+import {
+ airdropFactory,
+ appendTransactionMessageInstructions,
+ createSolanaRpc,
+ createSolanaRpcSubscriptions,
+ createTransactionMessage,
+ devnet,
+ generateKeyPairSigner,
+ getComputeUnitEstimateForTransactionMessageFactory,
+ getSignatureFromTransaction,
+ lamports,
+ pipe,
+ prependTransactionMessageInstructions,
+ sendAndConfirmTransactionFactory,
+ setTransactionMessageFeePayerSigner,
+ setTransactionMessageLifetimeUsingBlockhash,
+ signTransactionMessageWithSigners,
+ type Transaction,
+} from "@solana/web3.js";
+import {
+ getSetComputeUnitLimitInstruction,
+ getSetComputeUnitPriceInstruction,
+} from "@solana-program/compute-budget";
+import { getAddMemoInstruction } from "@solana-program/memo";
+
+async function writeMemo(message: string) {
+ // Create an RPC.
+ const CLUSTER = "devnet";
+ const rpc = createSolanaRpc(devnet(`https://api.${CLUSTER}.solana.com`));
+ const rpcSubscriptions = createSolanaRpcSubscriptions(
+ devnet(`wss://api.${CLUSTER}.solana.com`),
+ );
+
+ // Create an airdrop function.
+ const airdrop = airdropFactory({ rpc, rpcSubscriptions });
+
+ // Create a utility that estimates a transaction message's compute consumption.
+ const getComputeUnitEstimate =
+ getComputeUnitEstimateForTransactionMessageFactory({ rpc });
+
+ // Create a transaction sending function.
+ const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
+ rpc,
+ rpcSubscriptions,
+ });
+
+ // Create and fund an account.
+ const keypairSigner = await generateKeyPairSigner();
+ console.log("Created an account with address", keypairSigner.address);
+ console.log("Requesting airdrop");
+ await airdrop({
+ commitment: "confirmed",
+ lamports: lamports(1000_000n),
+ recipientAddress: keypairSigner.address,
+ });
+ console.log("Airdrop confirmed");
+
+ // Create a memo transaction.
+ console.log("Creating a memo transaction");
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
+ const transactionMessage = pipe(
+ createTransactionMessage({ version: "legacy" }),
+ m => setTransactionMessageFeePayerSigner(keypairSigner, m),
+ m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
+ m =>
+ appendTransactionMessageInstructions(
+ [
+ getSetComputeUnitPriceInstruction({ microLamports: 5000n }),
+ getAddMemoInstruction({ memo: message }),
+ ],
+ m,
+ ),
+ );
+
+ // Figure out how many compute units to budget for this transaction
+ // so that you can right-size the compute budget to maximize the
+ // chance that it will be selected for inclusion into a block.
+ console.log("Estimating the compute consumption of the transaction");
+ const estimatedComputeUnits =
+ await getComputeUnitEstimate(transactionMessage);
+ console.log(
+ `Transaction is estimated to consume ${estimatedComputeUnits} compute units`,
+ );
+ const budgetedTransactionMessage = prependTransactionMessageInstructions(
+ [getSetComputeUnitLimitInstruction({ units: estimatedComputeUnits })],
+ transactionMessage,
+ );
+
+ // Sign and send the transaction.
+ console.log("Signing and sending the transaction");
+ const signedTx = await signTransactionMessageWithSigners(
+ budgetedTransactionMessage,
+ );
+ const signature = getSignatureFromTransaction(signedTx);
+ console.log(
+ "Sending transaction https://explorer.solana.com/tx/" +
+ signature +
+ "/?cluster=" +
+ CLUSTER,
+ );
+ await sendAndConfirmTransaction(signedTx, { commitment: "confirmed" });
+ console.log("Transaction confirmed");
+}
+
+writeMemo("Hello, Solana!");
+```
+
+
+
+
```typescript filename="add-memo.ts" {38-46}
import {
@@ -63,3 +180,7 @@ import {
]);
})();
```
+
+
+
+
diff --git a/content/cookbook/transactions/add-priority-fees.md b/content/cookbook/transactions/add-priority-fees.md
index a10b49b42..ea02cb42f 100644
--- a/content/cookbook/transactions/add-priority-fees.md
+++ b/content/cookbook/transactions/add-priority-fees.md
@@ -29,6 +29,128 @@ compute budget. The value provided will replace the default value. Transactions
should request the minimum amount of CU required for execution to maximize
throughput, or minimize fees.
+
+
+
+
+```typescript filename="add-priority-fees.ts" {61-72} {37-38} {77-87}
+import {
+ airdropFactory,
+ appendTransactionMessageInstructions,
+ createSolanaRpc,
+ createSolanaRpcSubscriptions,
+ createTransactionMessage,
+ devnet,
+ generateKeyPairSigner,
+ getComputeUnitEstimateForTransactionMessageFactory,
+ getSignatureFromTransaction,
+ lamports,
+ pipe,
+ prependTransactionMessageInstructions,
+ sendAndConfirmTransactionFactory,
+ setTransactionMessageFeePayerSigner,
+ setTransactionMessageLifetimeUsingBlockhash,
+ signTransactionMessageWithSigners,
+} from "@solana/web3.js";
+import {
+ getSetComputeUnitLimitInstruction,
+ getSetComputeUnitPriceInstruction,
+} from "@solana-program/compute-budget";
+import { getAddMemoInstruction } from "@solana-program/memo";
+
+async function writeMemoWithPriorityFees(message: string) {
+ // Create an RPC.
+ const CLUSTER = "devnet";
+ const rpc = createSolanaRpc(devnet(`https://api.${CLUSTER}.solana.com`));
+ const rpcSubscriptions = createSolanaRpcSubscriptions(
+ devnet(`wss://api.${CLUSTER}.solana.com`),
+ );
+
+ // Create an airdrop function.
+ const airdrop = airdropFactory({ rpc, rpcSubscriptions });
+
+ // Create a utility that estimates a transaction message's compute consumption.
+ const getComputeUnitEstimate =
+ getComputeUnitEstimateForTransactionMessageFactory({ rpc });
+
+ // Create a transaction sending function.
+ const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
+ rpc,
+ rpcSubscriptions,
+ });
+
+ // Create and fund an account.
+ const keypairSigner = await generateKeyPairSigner();
+ console.log("Created an account with address", keypairSigner.address);
+ console.log("Requesting airdrop");
+ await airdrop({
+ commitment: "confirmed",
+ lamports: lamports(1000_000n),
+ recipientAddress: keypairSigner.address,
+ });
+ console.log("Airdrop confirmed");
+
+ // Create a memo transaction.
+ console.log("Creating a memo transaction");
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
+ const transactionMessage = pipe(
+ createTransactionMessage({ version: "legacy" }),
+ m => setTransactionMessageFeePayerSigner(keypairSigner, m),
+ m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
+ m =>
+ appendTransactionMessageInstructions(
+ [
+ getSetComputeUnitPriceInstruction({ microLamports: 5000n }),
+ getAddMemoInstruction({ memo: message }),
+ ],
+ m,
+ ),
+ );
+
+ // Figure out how many compute units to budget for this transaction
+ // so that you can right-size the compute budget to maximize the
+ // chance that it will be selected for inclusion into a block.
+ console.log("Estimating the compute consumption of the transaction");
+ var estimatedComputeUnits = await getComputeUnitEstimate(transactionMessage);
+ // While these estimates are quite accurate they are not perfect. So you may want to add a
+ // buffer if you expect that the transaction may consume more compute units than estimated.
+ // Its not possible to exactly know what the transaction will consume when
+ // you send it in the future. The state may change. You can add a buffer to the estimate to account for this.
+ // estimatedComputeUnits += 1000;
+ // estimatedComputeUnits *= 1.1;
+ // You can read more about the issue here: https://github.com/solana-labs/solana-web3.js/tree/master/packages/library#getcomputeunitestimatefortransactionmessagefactoryrpc
+
+ console.log(
+ `Transaction is estimated to consume ${estimatedComputeUnits} compute units`,
+ );
+ const budgetedTransactionMessage = prependTransactionMessageInstructions(
+ [getSetComputeUnitLimitInstruction({ units: estimatedComputeUnits })],
+ transactionMessage,
+ );
+
+ // Sign and send the transaction.
+ console.log("Signing and sending the transaction");
+ const signedTx = await signTransactionMessageWithSigners(
+ budgetedTransactionMessage,
+ );
+ const signature = getSignatureFromTransaction(signedTx);
+ console.log(
+ "Sending transaction https://explorer.solana.com/tx/" +
+ signature +
+ "/?cluster=" +
+ CLUSTER,
+ );
+ await sendAndConfirmTransaction(signedTx, { commitment: "confirmed" });
+ console.log("Transaction confirmed");
+}
+
+writeMemoWithPriorityFees("Hello, priority fees!");
+```
+
+
+
+
+
```typescript filename="add-priority-fees.ts" {25-28, 30-33}
import { BN } from "@coral-xyz/anchor";
import {
@@ -85,3 +207,7 @@ import {
console.log(result);
})();
```
+
+
+
+
diff --git a/content/cookbook/transactions/calculate-cost.md b/content/cookbook/transactions/calculate-cost.md
index 015a5824e..9bf42df2f 100644
--- a/content/cookbook/transactions/calculate-cost.md
+++ b/content/cookbook/transactions/calculate-cost.md
@@ -11,7 +11,152 @@ transaction cost. As long as you are not creating an account, this will be the
base transaction cost. To find out more about costs to create an account, check
out [calculating rent costs](/content/cookbook/accounts/calculate-rent.md).
-```typescript filename="calculate-cost.ts"
+
+
+
+
+```typescript filename="calculate-cost.ts" {101-118}
+import {
+ airdropFactory,
+ appendTransactionMessageInstructions,
+ compileTransactionMessage,
+ createSignerFromKeyPair,
+ createSolanaRpc,
+ createSolanaRpcSubscriptions,
+ createTransactionMessage,
+ devnet,
+ generateKeyPairSigner,
+ getBase64Decoder,
+ getCompiledTransactionMessageEncoder,
+ getComputeUnitEstimateForTransactionMessageFactory,
+ getSignatureFromTransaction,
+ lamports,
+ pipe,
+ prependTransactionMessageInstructions,
+ sendAndConfirmTransactionFactory,
+ setTransactionMessageFeePayerSigner,
+ setTransactionMessageLifetimeUsingBlockhash,
+ signTransactionMessageWithSigners,
+ type TransactionMessageBytesBase64,
+} from "@solana/web3.js";
+import {
+ getSetComputeUnitLimitInstruction,
+ getSetComputeUnitPriceInstruction,
+} from "@solana-program/compute-budget";
+import { getAddMemoInstruction } from "@solana-program/memo";
+import { loadDefaultKeypairWithAirdrop } from "./CreateKeypair";
+
+async function calculateCost(message: string) {
+ // Create an RPC.
+ const CLUSTER = "devnet";
+ const rpc = createSolanaRpc(devnet(`https://api.${CLUSTER}.solana.com`));
+ const rpcSubscriptions = createSolanaRpcSubscriptions(
+ devnet(`wss://api.${CLUSTER}.solana.com`),
+ );
+
+ // Create a utility that estimates a transaction message's compute consumption.
+ const getComputeUnitEstimate =
+ getComputeUnitEstimateForTransactionMessageFactory({ rpc });
+
+ // Create a transaction sending function.
+ const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
+ rpc,
+ rpcSubscriptions,
+ });
+
+ // Create an airdrop function.
+ const airdrop = airdropFactory({ rpc, rpcSubscriptions });
+
+ // Create and fund an account.
+ const signer = await generateKeyPairSigner();
+ console.log("Created an account with address", signer.address);
+ console.log("Requesting airdrop");
+ await airdrop({
+ commitment: "confirmed",
+ lamports: lamports(1000_000n),
+ recipientAddress: signer.address,
+ });
+ console.log("Airdrop confirmed");
+
+ // Create a memo transaction.
+ console.log("Creating a memo transaction");
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
+ const transactionMessage = pipe(
+ createTransactionMessage({ version: "legacy" }),
+ m => setTransactionMessageFeePayerSigner(signer, m),
+ m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
+ m =>
+ appendTransactionMessageInstructions(
+ [
+ getSetComputeUnitPriceInstruction({ microLamports: 5000n }),
+ getAddMemoInstruction({ memo: message }),
+ ],
+ m,
+ ),
+ );
+
+ // Figure out how many compute units to budget for this transaction
+ // so that you can right-size the compute budget to maximize the
+ // chance that it will be selected for inclusion into a block.
+ console.log("Estimating the compute consumption of the transaction");
+ const estimatedComputeUnits =
+ await getComputeUnitEstimate(transactionMessage);
+ console.log(
+ `Transaction is estimated to consume ${estimatedComputeUnits} compute units`,
+ );
+
+ const budgetedTransactionMessage = prependTransactionMessageInstructions(
+ [getSetComputeUnitLimitInstruction({ units: estimatedComputeUnits })],
+ transactionMessage,
+ );
+
+ const base64EncodedMessage = pipe(
+ // Start with the message you want the fee for.
+ budgetedTransactionMessage,
+
+ // Compile it.
+ compileTransactionMessage,
+
+ // Convert the compiled message into a byte array.
+ getCompiledTransactionMessageEncoder().encode,
+
+ // Encode that byte array as a base64 string.
+ getBase64Decoder().decode,
+ ) as TransactionMessageBytesBase64;
+
+ const transactionCost = await rpc
+ .getFeeForMessage(base64EncodedMessage)
+ .send();
+
+ console.log(
+ "Transaction is estimated to cost " + transactionCost.value + " lamports",
+ );
+
+ // Sign and send the transaction.
+ console.log("Signing and sending the transaction");
+ const signedTx = await signTransactionMessageWithSigners(
+ budgetedTransactionMessage,
+ );
+ const signature = getSignatureFromTransaction(signedTx);
+ console.log(
+ "Sending transaction https://explorer.solana.com/tx/" +
+ signature +
+ "/?cluster=" +
+ CLUSTER,
+ );
+ await sendAndConfirmTransaction(signedTx, { commitment: "confirmed" });
+ console.log("Transaction confirmed");
+ // Transaction is estimated to consume 6236 compute units
+ // Transaction is estimated to cost 5032 lamports
+}
+
+calculateCost("Hello, Fees!");
+```
+
+
+
+
+```typescript filename="calculate-cost.ts {108-111}"
import {
clusterApiUrl,
Connection,
@@ -65,3 +210,7 @@ import bs58 from "bs58";
// Estimated SOL transfer cost: 5000 lamports
})();
```
+
+
+
+
diff --git a/content/cookbook/transactions/send-sol.md b/content/cookbook/transactions/send-sol.md
index 5cfe36ee0..67003ef34 100644
--- a/content/cookbook/transactions/send-sol.md
+++ b/content/cookbook/transactions/send-sol.md
@@ -8,6 +8,127 @@ description:
To send SOL, you will need to interact with the [SystemProgram][1].
+
+
+
+
+```typescript filename="send-sol.ts" {70-74}
+import {
+ address,
+ airdropFactory,
+ appendTransactionMessageInstructions,
+ createSolanaRpc,
+ createSolanaRpcSubscriptions,
+ createTransactionMessage,
+ devnet,
+ generateKeyPairSigner,
+ getComputeUnitEstimateForTransactionMessageFactory,
+ getSignatureFromTransaction,
+ lamports,
+ pipe,
+ prependTransactionMessageInstructions,
+ sendAndConfirmTransactionFactory,
+ setTransactionMessageFeePayerSigner,
+ setTransactionMessageLifetimeUsingBlockhash,
+ signTransactionMessageWithSigners,
+} from "@solana/web3.js";
+import {
+ getSetComputeUnitLimitInstruction,
+ getSetComputeUnitPriceInstruction,
+} from "@solana-program/compute-budget";
+import { getAddMemoInstruction } from "@solana-program/memo";
+import { getTransferSolInstruction } from "@solana-program/system";
+
+async function transferSol() {
+ // Create an RPC. Use localnet for solana-test-validator. This will get you easier airdrops.
+ const CLUSTER = "devnet";
+ const rpc = createSolanaRpc(devnet(`https://api.${CLUSTER}.solana.com`));
+ const rpcSubscriptions = createSolanaRpcSubscriptions(
+ devnet(`wss://api.${CLUSTER}.solana.com`),
+ );
+
+ // Create an airdrop function.
+ const airdrop = airdropFactory({ rpc, rpcSubscriptions });
+
+ // Create a utility that estimates a transaction message's compute consumption.
+ const getComputeUnitEstimate =
+ getComputeUnitEstimateForTransactionMessageFactory({ rpc });
+
+ // Create a transaction sending function.
+ const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
+ rpc,
+ rpcSubscriptions,
+ });
+
+ // Create and fund an account.
+ const keypairSigner = await generateKeyPairSigner();
+ console.log("Created an account with address", keypairSigner.address);
+ console.log("Requesting airdrop");
+ await airdrop({
+ commitment: "confirmed",
+ lamports: lamports(1000_000n),
+ recipientAddress: keypairSigner.address,
+ });
+ console.log("Airdrop confirmed");
+
+ // Create a memo transaction.
+ console.log("Creating a memo transaction");
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
+ const transactionMessage = pipe(
+ createTransactionMessage({ version: "legacy" }),
+ m => setTransactionMessageFeePayerSigner(keypairSigner, m),
+ m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
+ m =>
+ appendTransactionMessageInstructions(
+ [
+ getSetComputeUnitPriceInstruction({ microLamports: 5000n }),
+ getTransferSolInstruction({
+ source: keypairSigner,
+ destination: address("web3Qm5PuFapMJqe6PWRWfRBarkeqE2ZC8Eew3zwHH2"),
+ amount: lamports(1_000n),
+ }),
+ ],
+ m,
+ ),
+ );
+
+ // Figure out how many compute units to budget for this transaction
+ // so that you can right-size the compute budget to maximize the
+ // chance that it will be selected for inclusion into a block.
+ console.log("Estimating the compute consumption of the transaction");
+ const estimatedComputeUnits =
+ await getComputeUnitEstimate(transactionMessage);
+ console.log(
+ `Transaction is estimated to consume ${estimatedComputeUnits} compute units`,
+ );
+ const budgetedTransactionMessage = prependTransactionMessageInstructions(
+ [getSetComputeUnitLimitInstruction({ units: estimatedComputeUnits })],
+ transactionMessage,
+ );
+
+ // Sign and send the transaction.
+ console.log("Signing and sending the transaction");
+ const signedTx = await signTransactionMessageWithSigners(
+ budgetedTransactionMessage,
+ );
+ const signature = getSignatureFromTransaction(signedTx);
+ console.log(
+ "Sending transaction https://explorer.solana.com/tx/" +
+ signature +
+ "/?cluster=" +
+ CLUSTER,
+ );
+ await sendAndConfirmTransaction(signedTx, { commitment: "confirmed" });
+ console.log("Transaction confirmed");
+}
+
+transferSol();
+```
+
+
+
+
+
```typescript filename="send-sol.ts" {28-38}
import {
Connection,
@@ -50,4 +171,8 @@ import {
})();
```
+
+
+
+
[1]: https://docs.solanalabs.com/runtime/programs#system-program
diff --git a/content/courses/tokens-and-nfts/nfts-with-metaplex.md b/content/courses/tokens-and-nfts/nfts-with-metaplex.md
index be6ce5a75..f5b929b5c 100644
--- a/content/courses/tokens-and-nfts/nfts-with-metaplex.md
+++ b/content/courses/tokens-and-nfts/nfts-with-metaplex.md
@@ -348,7 +348,8 @@ To begin, make a new folder and install the relevant dependencies:
npm i @solana/web3.js@1 @solana-developers/helpers@2 @metaplex-foundation/mpl-token-metadata @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/umi-uploader-irys esrun
```
-Then create a file called `create-metaplex-nft-collection.ts`, and add our imports:
+Then create a file called `create-metaplex-nft-collection.ts`, and add our
+imports:
```typescript
import {
diff --git a/docs/core/clusters.md b/docs/core/clusters.md
index 100f5a489..c7b59ee60 100644
--- a/docs/core/clusters.md
+++ b/docs/core/clusters.md
@@ -42,17 +42,18 @@ An example of some of these Solana blockchain explorers include:
## On a high level
- Mainnet: Live production environment for deployed applications.
-- Devnet: Testing with public accessibility for developers experimenting with their applications.
+- Devnet: Testing with public accessibility for developers experimenting with
+ their applications.
- Testnet: Stress-testing for network upgrades and validator performance.
-**Example use cases**: You may want to debug a new program on Devnet or verify performance metrics on Testnet before Mainnet deployment.
-
-| **Cluster** | **Endpoint** | **Purpose** | **Notes** |
-|---------------|----------------------------------|---------------------------------------------|-------------------------------------|
-| Mainnet | `https://api.mainnet-beta.solana.com` | Live production environment | Requires SOL for transactions |
-| Devnet | `https://api.devnet.solana.com` | Public testing and development | Free SOL airdrop for testing |
-| Testnet | `https://api.testnet.solana.com` | Validator and stress testing | May have intermittent downtime |
+**Example use cases**: You may want to debug a new program on Devnet or verify
+performance metrics on Testnet before Mainnet deployment.
+| **Cluster** | **Endpoint** | **Purpose** | **Notes** |
+| ----------- | ------------------------------------- | ------------------------------ | ------------------------------ |
+| Mainnet | `https://api.mainnet-beta.solana.com` | Live production environment | Requires SOL for transactions |
+| Devnet | `https://api.devnet.solana.com` | Public testing and development | Free SOL airdrop for testing |
+| Testnet | `https://api.testnet.solana.com` | Validator and stress testing | May have intermittent downtime |
## Devnet