Skip to content

Commit 9cbd90f

Browse files
amilzcatmcgeeZYJLiu
authored
docs(cookbook): upgrade kit examples to plugin client (#1469)
* docs(cookbook): upgrade kit examples to plugin client Refactor 8 cookbook kit examples to use the @solana/kit-plugin-rpc + @solana/kit-plugin-signer client pattern introduced in #1465. Replaces manual pipe() / createTransactionMessage / blockhash / sendAndConfirm wiring with createClient().use(payer).use(solanaLocalRpc()).use(airdropPayer()) and client.sendTransaction([...]). - send-sol, add-memo, create-account: full plugin refactor - add-priority-fees: priority fees configured via solanaLocalRpc transactionConfig; planner/executor auto-handle CU price + limit - fee-sponsorship: uses tokenProgram() plugin (createMint, mintToATA, transferToATA) instead of manual ATA derivation - create-token-with-metadata: plugin client for setup, single Metaplex createV1 instruction - calculate-cost: plugin for setup/airdrop, kept manual pipe + getFeeForMessage since fee calculation is the recipe's whole point - mev-protection: plugin for setup, kept manual build + base64 + Jito POST 438 -> 153 lines (~65% reduction). #region markers preserved so MDX includes are unchanged. All 61 docs-examples tests pass. * fix highlight ranges past the new kit.ts line counts The plugin-client refactor shortened the kit examples — old highlight= directives pointed past the new file ends and codehike crashed the async cookbook compile with "Cannot read properties of undefined (reading 'range')". Repoint each at the new plugin .use() chain and the simplified client.sendTransaction call. * docs(cookbook): use explicit solanaRpc URLs in kit examples Replace solanaLocalRpc() with solanaRpc({ rpcUrl, rpcSubscriptionsUrl }) + rpcAirdrop() across all 8 cookbook kit examples so readers can swap the localhost URL for a surfnet (or any other endpoint) without changing imports or call shape. * remove highlight, line numbers incorrect --------- Co-authored-by: catmcgee <helloworld@mcgee.cat> Co-authored-by: John <75003086+ZYJLiu@users.noreply.github.com>
1 parent 53217b7 commit 9cbd90f

12 files changed

Lines changed: 202 additions & 442 deletions

File tree

apps/docs/content/cookbook/accounts/create-account.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ can then initialize the account data through its own instructions.
2424

2525
<CodeTabs storage="cookbook" flags="r">
2626

27-
```ts !! title="Kit" file=packages/docs-examples/cookbook/accounts/create-account/kit.ts#region=create highlight=38-44
27+
```ts !! title="Kit" file=packages/docs-examples/cookbook/accounts/create-account/kit.ts#region=create
2828

2929
```
3030

apps/docs/content/cookbook/transactions/add-memo.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Any transaction can add a message making use of the SPL memo program.
99

1010
<CodeTabs storage="cookbook" flags="r">
1111

12-
```ts !! title="Kit" file=packages/docs-examples/cookbook/transactions/add-memo/kit.ts#region=memo highlight=30-32
12+
```ts !! title="Kit" file=packages/docs-examples/cookbook/transactions/add-memo/kit.ts#region=memo
1313

1414
```
1515

apps/docs/content/cookbook/transactions/add-priority-fees.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ To add a priority fee to a transaction, invoke instructions from the
1212

1313
<CodeTabs storage="cookbook" flags="r">
1414

15-
```ts !! title="Kit" file=packages/docs-examples/cookbook/transactions/add-priority-fees/kit.ts#region=priority highlight=57,72
15+
```ts !! title="Kit" file=packages/docs-examples/cookbook/transactions/add-priority-fees/kit.ts#region=priority
1616

1717
```
1818

apps/docs/content/cookbook/transactions/send-sol.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ instruction.
1111

1212
<CodeTabs storage="cookbook" flags="r">
1313

14-
```ts !! title="Kit" file=packages/docs-examples/cookbook/transactions/send-sol/kit.ts#region=transfer highlight=34-38
14+
```ts !! title="Kit" file=packages/docs-examples/cookbook/transactions/send-sol/kit.ts#region=transfer
1515

1616
```
1717

Lines changed: 19 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,38 @@
11
// #region create
2-
import {
3-
airdropFactory,
4-
appendTransactionMessageInstructions,
5-
assertIsTransactionWithBlockhashLifetime,
6-
createSolanaRpc,
7-
createSolanaRpcSubscriptions,
8-
createTransactionMessage,
9-
generateKeyPairSigner,
10-
getSignatureFromTransaction,
11-
lamports,
12-
pipe,
13-
sendAndConfirmTransactionFactory,
14-
setTransactionMessageFeePayerSigner,
15-
setTransactionMessageLifetimeUsingBlockhash,
16-
signTransactionMessageWithSigners,
17-
} from "@solana/kit";
2+
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
3+
import { rpcAirdrop, solanaRpc } from "@solana/kit-plugin-rpc";
4+
import { airdropPayer, payer } from "@solana/kit-plugin-signer";
185
import {
196
getCreateAccountInstruction,
207
SYSTEM_PROGRAM_ADDRESS,
218
} from "@solana-program/system";
229

23-
const rpc = createSolanaRpc("http://localhost:8899");
24-
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");
25-
2610
const sender = await generateKeyPairSigner();
2711
const LAMPORTS_PER_SOL = 1_000_000_000n;
28-
await airdropFactory({ rpc, rpcSubscriptions })({
29-
recipientAddress: sender.address,
30-
lamports: lamports(LAMPORTS_PER_SOL), // 1 SOL
31-
commitment: "confirmed",
32-
});
3312

34-
const newAccount = await generateKeyPairSigner();
13+
const client = await createClient()
14+
.use(payer(sender))
15+
.use(
16+
solanaRpc({
17+
rpcUrl: "http://localhost:8899",
18+
rpcSubscriptionsUrl: "ws://localhost:8900",
19+
}),
20+
)
21+
.use(rpcAirdrop())
22+
.use(airdropPayer(lamports(LAMPORTS_PER_SOL)));
3523

36-
const space = 0n;
37-
const rentLamports = await rpc.getMinimumBalanceForRentExemption(space).send();
24+
const newAccount = await generateKeyPairSigner();
25+
const space = 0;
26+
const rentLamports = await client.getMinimumBalance(space);
3827

3928
const createAccountInstruction = getCreateAccountInstruction({
4029
payer: sender,
41-
newAccount: newAccount,
30+
newAccount,
4231
lamports: rentLamports,
4332
programAddress: SYSTEM_PROGRAM_ADDRESS,
4433
space,
4534
});
4635

47-
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
48-
const transactionMessage = pipe(
49-
createTransactionMessage({ version: 0 }),
50-
(tx) => setTransactionMessageFeePayerSigner(sender, tx),
51-
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
52-
(tx) => appendTransactionMessageInstructions([createAccountInstruction], tx),
53-
);
54-
55-
const signedTransaction =
56-
await signTransactionMessageWithSigners(transactionMessage);
57-
assertIsTransactionWithBlockhashLifetime(signedTransaction);
58-
await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(
59-
signedTransaction,
60-
{ commitment: "confirmed" },
61-
);
62-
const transactionSignature = getSignatureFromTransaction(signedTransaction);
63-
console.log("Transaction Signature for create account:", transactionSignature);
36+
const { context } = await client.sendTransaction([createAccountInstruction]);
37+
console.log("Transaction Signature for create account:", context.signature);
6438
// #endregion create

packages/docs-examples/cookbook/tokens/create-token-with-metadata/kit.ts

Lines changed: 18 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,26 @@
11
// #region create
2-
import {
3-
airdropFactory,
4-
appendTransactionMessageInstructions,
5-
assertIsTransactionWithBlockhashLifetime,
6-
createSolanaRpc,
7-
createSolanaRpcSubscriptions,
8-
createTransactionMessage,
9-
generateKeyPairSigner,
10-
lamports,
11-
pipe,
12-
sendAndConfirmTransactionFactory,
13-
setTransactionMessageFeePayerSigner,
14-
setTransactionMessageLifetimeUsingBlockhash,
15-
signTransactionMessageWithSigners,
16-
} from "@solana/kit";
2+
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
3+
import { rpcAirdrop, solanaRpc } from "@solana/kit-plugin-rpc";
4+
import { airdropPayer, payer as kitPayer } from "@solana/kit-plugin-signer";
175
import {
186
getCreateV1InstructionAsync,
197
fetchMetadataFromSeeds,
208
TokenStandard,
219
} from "@metaplex-foundation/mpl-token-metadata-kit";
2210

23-
// Create connection to local validator
24-
const rpc = createSolanaRpc("http://127.0.0.1:8899");
25-
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://127.0.0.1:8900");
26-
27-
// Generate keypairs
2811
const payer = await generateKeyPairSigner();
2912
const mint = await generateKeyPairSigner();
3013

31-
// Airdrop SOL to payer
32-
const airdrop = airdropFactory({ rpc, rpcSubscriptions });
33-
await airdrop({
34-
recipientAddress: payer.address,
35-
lamports: lamports(1_000_000_000n),
36-
commitment: "confirmed",
37-
});
14+
const client = await createClient()
15+
.use(kitPayer(payer))
16+
.use(
17+
solanaRpc({
18+
rpcUrl: "http://localhost:8899",
19+
rpcSubscriptionsUrl: "ws://localhost:8900",
20+
}),
21+
)
22+
.use(rpcAirdrop())
23+
.use(airdropPayer(lamports(1_000_000_000n)));
3824

3925
// Create token with metadata
4026
const createInstruction = await getCreateV1InstructionAsync({
@@ -48,27 +34,13 @@ const createInstruction = await getCreateV1InstructionAsync({
4834
tokenStandard: TokenStandard.Fungible,
4935
});
5036

51-
// Build and send transaction
52-
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
53-
54-
const transactionMessage = pipe(
55-
createTransactionMessage({ version: 0 }),
56-
(tx) => setTransactionMessageFeePayerSigner(payer, tx),
57-
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
58-
(tx) => appendTransactionMessageInstructions([createInstruction], tx),
59-
);
60-
61-
const signedTransaction =
62-
await signTransactionMessageWithSigners(transactionMessage);
63-
assertIsTransactionWithBlockhashLifetime(signedTransaction);
64-
65-
await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(
66-
signedTransaction,
67-
{ commitment: "confirmed" },
68-
);
37+
const { context } = await client.sendTransaction([createInstruction]);
38+
console.log("Transaction Signature:", context.signature);
6939

7040
// Verify metadata was created
71-
const metadata = await fetchMetadataFromSeeds(rpc, { mint: mint.address });
41+
const metadata = await fetchMetadataFromSeeds(client.rpc, {
42+
mint: mint.address,
43+
});
7244

7345
console.log("Mint Address:", mint.address);
7446
console.log("Token Name:", metadata.data.name);
Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,27 @@
11
// #region memo
2-
import {
3-
airdropFactory,
4-
appendTransactionMessageInstructions,
5-
assertIsTransactionWithBlockhashLifetime,
6-
createSolanaRpc,
7-
createSolanaRpcSubscriptions,
8-
createTransactionMessage,
9-
generateKeyPairSigner,
10-
getSignatureFromTransaction,
11-
lamports,
12-
pipe,
13-
sendAndConfirmTransactionFactory,
14-
setTransactionMessageFeePayerSigner,
15-
setTransactionMessageLifetimeUsingBlockhash,
16-
signTransactionMessageWithSigners,
17-
} from "@solana/kit";
2+
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
3+
import { rpcAirdrop, solanaRpc } from "@solana/kit-plugin-rpc";
4+
import { airdropPayer, payer } from "@solana/kit-plugin-signer";
185
import { getAddMemoInstruction } from "@solana-program/memo";
196

20-
const rpc = createSolanaRpc("http://localhost:8899");
21-
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");
22-
237
const sender = await generateKeyPairSigner();
248
const LAMPORTS_PER_SOL = 1_000_000_000n;
25-
await airdropFactory({ rpc, rpcSubscriptions })({
26-
recipientAddress: sender.address,
27-
lamports: lamports(LAMPORTS_PER_SOL), // 1 SOL
28-
commitment: "confirmed",
29-
});
9+
10+
const client = await createClient()
11+
.use(payer(sender))
12+
.use(
13+
solanaRpc({
14+
rpcUrl: "http://localhost:8899",
15+
rpcSubscriptionsUrl: "ws://localhost:8900",
16+
}),
17+
)
18+
.use(rpcAirdrop())
19+
.use(airdropPayer(lamports(LAMPORTS_PER_SOL)));
3020

3121
const memoInstruction = getAddMemoInstruction({
3222
memo: "Hello, world!",
3323
});
3424

35-
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
36-
const transactionMessage = pipe(
37-
createTransactionMessage({ version: 0 }),
38-
(tx) => setTransactionMessageFeePayerSigner(sender, tx),
39-
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
40-
(tx) => appendTransactionMessageInstructions([memoInstruction], tx),
41-
);
42-
43-
const signedTransaction =
44-
await signTransactionMessageWithSigners(transactionMessage);
45-
assertIsTransactionWithBlockhashLifetime(signedTransaction);
46-
await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(
47-
signedTransaction,
48-
{ commitment: "confirmed" },
49-
);
50-
const transactionSignature = getSignatureFromTransaction(signedTransaction);
51-
console.log("Transaction Signature:", transactionSignature);
25+
const { context } = await client.sendTransaction([memoInstruction]);
26+
console.log("Transaction Signature:", context.signature);
5227
// #endregion memo
Lines changed: 26 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,37 @@
11
// #region priority
22
import {
3-
airdropFactory,
4-
appendTransactionMessageInstructions,
5-
assertIsTransactionWithBlockhashLifetime,
6-
createSolanaRpc,
7-
createSolanaRpcSubscriptions,
8-
createTransactionMessage,
3+
createClient,
94
generateKeyPairSigner,
10-
estimateComputeUnitLimitFactory,
11-
getSignatureFromTransaction,
125
lamports,
13-
pipe,
14-
prependTransactionMessageInstructions,
15-
sendAndConfirmTransactionFactory,
16-
setTransactionMessageFeePayerSigner,
17-
setTransactionMessageLifetimeUsingBlockhash,
18-
signTransactionMessageWithSigners,
6+
type MicroLamports,
197
} from "@solana/kit";
20-
import {
21-
getSetComputeUnitLimitInstruction,
22-
getSetComputeUnitPriceInstruction,
23-
} from "@solana-program/compute-budget";
24-
8+
import { rpcAirdrop, solanaRpc } from "@solana/kit-plugin-rpc";
9+
import { airdropPayer, payer } from "@solana/kit-plugin-signer";
2510
import { getAddMemoInstruction } from "@solana-program/memo";
2611

27-
// Create an RPC
28-
const rpc = createSolanaRpc("http://localhost:8899");
29-
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");
30-
31-
// Create utility functions
32-
const airdrop = airdropFactory({ rpc, rpcSubscriptions });
33-
const getComputeUnitEstimate = estimateComputeUnitLimitFactory({ rpc });
34-
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
35-
rpc,
36-
rpcSubscriptions,
37-
});
38-
3912
// Create and fund an account
4013
const keypairSigner = await generateKeyPairSigner();
4114

42-
await airdrop({
43-
commitment: "confirmed",
44-
lamports: lamports(1_000_000n),
45-
recipientAddress: keypairSigner.address,
46-
});
47-
48-
// Create a memo transaction
49-
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
50-
const transactionMessage = pipe(
51-
createTransactionMessage({ version: "legacy" }),
52-
(m) => setTransactionMessageFeePayerSigner(keypairSigner, m),
53-
(m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
54-
(m) =>
55-
appendTransactionMessageInstructions(
56-
[
57-
getSetComputeUnitPriceInstruction({ microLamports: 5000n }),
58-
getAddMemoInstruction({ memo: "Hello, world!" }),
59-
],
60-
m,
61-
),
62-
);
63-
64-
// Estimate compute units for this transaction
65-
const estimatedComputeUnits = await getComputeUnitEstimate(transactionMessage);
66-
console.log(
67-
`Transaction is estimated to consume ${estimatedComputeUnits} compute units`,
68-
);
69-
70-
// Add compute unit limit instruction to the transaction
71-
const budgetedTransactionMessage = prependTransactionMessageInstructions(
72-
[getSetComputeUnitLimitInstruction({ units: estimatedComputeUnits })],
73-
transactionMessage,
74-
);
75-
76-
// Sign and send the transaction
77-
const signedTx = await signTransactionMessageWithSigners(
78-
budgetedTransactionMessage,
79-
);
80-
assertIsTransactionWithBlockhashLifetime(signedTx);
81-
const transactionSignature = getSignatureFromTransaction(signedTx);
82-
await sendAndConfirmTransaction(signedTx, { commitment: "confirmed" });
83-
console.log(`Transaction Signature: ${transactionSignature}`);
15+
// Configure priority fees on the client. The transaction planner will add a
16+
// SetComputeUnitPrice instruction, and the executor will simulate the
17+
// transaction to estimate compute units and add a SetComputeUnitLimit.
18+
const client = await createClient()
19+
.use(payer(keypairSigner))
20+
.use(
21+
solanaRpc({
22+
rpcUrl: "http://localhost:8899",
23+
rpcSubscriptionsUrl: "ws://localhost:8900",
24+
transactionConfig: {
25+
microLamportsPerComputeUnit: 5000n as MicroLamports,
26+
version: "legacy",
27+
},
28+
}),
29+
)
30+
.use(rpcAirdrop())
31+
.use(airdropPayer(lamports(1_000_000_000n)));
32+
33+
const memoInstruction = getAddMemoInstruction({ memo: "Hello, world!" });
34+
35+
const { context } = await client.sendTransaction([memoInstruction]);
36+
console.log(`Transaction Signature: ${context.signature}`);
8437
// #endregion priority

0 commit comments

Comments
 (0)