在本节中,您将学习如何构建基本的 Create, Read, Update, Delete (CRUD) 程序。
书接上文,区块链日记6 - Solana入门 - PDA增删改查数据1-优快云博客 ,这节我们来操作部署、调用、测试。
目录
6.部署程序
您现在已经完成了基本的 CRUD 计划。通过运行 deploy
在 Playground 终端中。
确保您的 Playground 钱包具有 devnet SOL。可以从 水龙头 获取。
deploy
7.设置测试文件
起始代码还包括一个 anchor.test.ts
格式的测试文件。
import { PublicKey } from "@solana/web3.js";
describe("pda", () => {
it("Create Message Account", async () => {});
it("Update Message Account", async () => {});
it("Delete Message Account", async () => {});
});
在 describe()
中,但在 it()
部分之前添加以下代码。
const program = pg.program;
const wallet = pg.wallet;
const [messagePda, messageBump] = PublicKey.findProgramAddressSync(
[Buffer.from("message"), wallet.publicKey.toBuffer()],
program.programId,
);
汇总后为:
import { PublicKey } from "@solana/web3.js";
describe("pda", () => {
const program = pg.program;
const wallet = pg.wallet;
const [messagePda, messageBump] = PublicKey.findProgramAddressSync(
[Buffer.from("message"), wallet.publicKey.toBuffer()],
program.programId
);
it("Create Message Account", async () => {});
it("Update Message Account", async () => {});
it("Delete Message Account", async () => {});
});
解释:
PublicKey.findProgramAddressSync
:这是一个同步方法,用于生成 PDA 和对应的 bump 种子。
输入参数:
第一个参数是一个种子数组,用于生成 PDA。种子可以是任意的字节序列,通常包括一些标识符和用户的公钥。
Buffer.from("message")
:一个固定的种子,用于标识 PDA 的用途(例如,用于存储消息)。
wallet.publicKey.toBuffer()
:用户钱包的公钥,用于将 PDA 与特定用户关联。第二个参数是程序的 ID(
program.programId
),这是当前智能合约的唯一标识。返回值:
messagePda
:生成的 PDA 地址。
messageBump
:生成 PDA 时使用的 bump 种子。bump 种子是一个小的整数,用于确保 PDA 地址的唯一性。
通过在 Playground 终端中运行 test
来运行测试文件,以检查它是否按预期运行。后续步骤将添加实际测试。
test
8.调用 Create 指令
使用以下内容更新第一个测试:
it("Create Message Account", async () => {
const message = "Hello, World!";
const transactionSignature = await program.methods
.create(message)
.accounts({
messageAccount: messagePda,
})
.rpc({ commitment: "confirmed" });
const messageAccount = await program.account.messageAccount.fetch(
messagePda,
"confirmed",
);
console.log(JSON.stringify(messageAccount, null, 2));
console.log(
"Transaction Signature:",
`https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`,
);
});
首先,测试文件发送一个调用 create
指令的事务,并将 “Hello, World!” 作为消息传递。
发送交易并创建账户后,测试文件使用其地址 (messagePda
) 获取账户。
最后,测试文件会记录账户数据和交易详细信息的链接。
剩下的几个和Create类似。
9.调用 Update 指令
it("Update Message Account", async () => {
const message = "Hello, Solana!";
const transactionSignature = await program.methods
.update(message)
.accounts({
messageAccount: messagePda,
})
.rpc({ commitment: "confirmed" });
const messageAccount = await program.account.messageAccount.fetch(
messagePda,
"confirmed",
);
console.log(JSON.stringify(messageAccount, null, 2));
console.log(
"Transaction Signature:",
`https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`,
);
});
10.调用 Delete 指令
it("Delete Message Account", async () => {
const transactionSignature = await program.methods
.delete()
.accounts({
messageAccount: messagePda,
})
.rpc({ commitment: "confirmed" });
const messageAccount = await program.account.messageAccount.fetchNullable(
messagePda,
"confirmed",
);
console.log("Expect Null:", JSON.stringify(messageAccount, null, 2));
console.log(
"Transaction Signature:",
`https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`,
);
});
11.运行测试
test
检查 SolanaFM 链接以查看交易详细信息。
(可以发现和预期一致!)
完整代码
import { PublicKey } from "@solana/web3.js";
describe("pda", () => {
const program = pg.program;
const wallet = pg.wallet;
const [messagePda, messageBump] = PublicKey.findProgramAddressSync(
[Buffer.from("message"), wallet.publicKey.toBuffer()],
program.programId
);
it("Create Message Account", async () => {
const message = "Hello, World!";
const transactionSignature = await program.methods
.create(message)
.accounts({
messageAccount: messagePda,
})
.rpc({
commitment: "confirmed",
});
const messageAccount = await program.account.messageAccount.fetch(
messagePda,
"confirmed"
);
console.log(JSON.stringify(messageAccount, null, 2));
console.log(
"Transaction Signature:",
`http://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`
);
});
it("Update Message Account", async () => {
const message = "Hello, Solana!";
const transactionSignature = await program.methods
.update(message)
.accounts({
messageAccount: messagePda,
})
.rpc({
commitment: "confirmed",
});
const messageAccount = await program.account.messageAccount.fetch(
messagePda,
"confirmed"
);
console.log(JSON.stringify(messageAccount, null, 2));
console.log(
"Transaction Signature:",
`https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`
);
});
it("Delete Message Account", async () => {
const transactionSignature = await program.methods
.delete()
.accounts({
messageAccount: messagePda,
})
.rpc({
commitment: "confirmed",
});
const messageAccount = await program.account.messageAccount.fetchNullable(
messagePda,
"confirmed"
);
console.log("Expect Null:", JSON.stringify(messageAccount, null, 2));
console.log(
"Transaction Signature:",
`https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`
);
});
});
参考:链接