Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add web3jsV2 examples #610

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions content/cookbook/accounts/get-account-balance.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,35 @@ description:
that account balance on Solana."
---

<Tabs groupId="language" items={['web3.js v2', 'web3.js v1']}>

<Tab value="web3.js v2">

```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} lamports`);
Woody4618 marked this conversation as resolved.
Show resolved Hide resolved
} catch (err) {
console.error("Error fetching balance:", err);
}
}

getBalance();
```

</Tab>

<Tab value="web3.js v1">

```typescript filename="get-account-balance.ts" {13}
import {
clusterApiUrl,
Expand All @@ -23,3 +52,7 @@ import {
);
})();
```

</Tab>

</Tabs>
95 changes: 95 additions & 0 deletions content/cookbook/development/load-keypair-from-file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
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<CryptoKeyPair> {
return await loadKeypairFromFile("~/.config/solana/id.json");
}

export async function loadDefaultKeypairWithAirdrop(
cluster: string,
): Promise<CryptoKeyPair> {
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<CryptoKeyPair> {
// 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;
}

async function logPublicKey(path: string) {
Woody4618 marked this conversation as resolved.
Show resolved Hide resolved
const keypair = await loadKeypairFromFile(path);
const publicAddress = await getAddressFromPublicKey(keypair.publicKey);

console.log(`Public key from bytes: ${publicAddress}`);
}

createKeypair();
logPublicKey("~/.config/solana/id.json");
```
127 changes: 124 additions & 3 deletions content/cookbook/transactions/add-memo.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

<Tabs groupId="language" items={['web3.js v2', 'web3.js v1']}>

<Tab value="web3.js v2">

```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!");
```

</Tab>

<Tab value="web3.js v1">

```typescript filename="add-memo.ts" {38-46}
import {
Expand Down Expand Up @@ -63,3 +180,7 @@ import {
]);
})();
```

</Tab>

</Tabs>
Loading
Loading