Solana Dev 设置指南(第二部分:Node.js、Next.js、React)
本文是一篇关于如何在Solana Devnet上进行快速、低成本和有趣的项目开发的教程。
在 Solana 的 Devnet 上构建快速、廉价且有趣的项目,免费获取 devnet SOL,使用 Node.js、Typescript 和 Next.js 引导程序的设置
本指南将帮助你准备好使用 Node.js、Javascript 和 Typescript 实用程序脚本编写 Solana 交易代码,然后通过 React 和 Solana Next.js 引导程序模板进行前端集成。
为什么要这样做?我们正在为前端、后端和链上应用程序的发布 盛会 做准备,我们需要熟悉我们所有的工具。如果你没有看过 Solana 开发设置指南(第一部分:CLI) 这篇文章,请先阅读它!
这是“设置系列”的第二部分,是为那些想学习如何发布 Solana 应用程序的人准备的序幕。

在 Solana 上开发是多学科的,涵盖了广泛的技术,从 CLI,到像 Next.js 这样的前端,到链下 Node.js 或其他后端脚本,当然还有 Rust/Anchor 中的链上后端程序。
?♂️ 为什么要关注我的设置文章? 你也可以在 Solana 文档中找到设置信息,但是,我沿途添加了自己的技巧和窍门,并将其设计为适合 我们稍后将使用的有趣的应用程序和技术堆栈!
?️ 我们将从 Node.js 脚本开始,然后从那里开始! 使用 TypeScript 是一个最佳实践,所以我们将使用它,但是,由于这些是用于学习的基础脚本,所以没有很多需要担心的类型!
然后,我们将深入研究一个很棒的应用程序引导程序模板,它结合了 Next.js、React、TailwindCSS、ReactQuery 和大量的 Solana 交易 javascript。最好的部分是,我们公开了大量的 React Hooks,可以在你的应用程序中按原样使用。
在本教程中:
?️ Javascript、Typescript 配置
- 前言:安装 Typescript — 参考信息
- 开始:创建 Solana JS/TS 仓库
? Solana Node.js 和 Typescript 脚本
- 连接到 Solana Devnet 并检查集群状态
- 生成一个新的 Solana 密钥对
- 检查 Devnet 上的账户余额
- 在 Devnet 上请求 Airdrop
- 在账户之间转移 SOL
- 创建并资助一个新账户
⚡️ Solana 前端,Next.js 集成
-
Next.js 应用程序 — 基本应用程序设置
-
安装并设置 Solana “热”钱包(和安全)
-
获得免费的 Solana Devnet Airdrop
-
Next.js 应用程序。了解钱包集成。
11. 回顾 Next.js 中的 Solana 钱包代码
12. 快速的首次交易,React Hooks
- 其他 Solana 资源
? 感谢阅读!… ? 请鼓掌并分享这篇文章,谢谢!?
前言:安装 Typescript — 参考信息
我在这里放置了标准的 TypeScript 安装流程,但是,这也在下面创建你的仓库的说明中重复了。
你可以只阅读本节并用作参考, 因为我们将在下面开始我们的项目时再次输入。
我建议你现在做的唯一一件事是在全局安装 ts-node CLI:
npm install -g ts-node
标准 Typescript 安装流程:
1. 初始化一个 Node.js 项目
通常在你的空 git 初始化仓库文件夹中完成此操作。
npm init -y
2. 安装 TypeScript 和所需的 Solana 依赖项
还添加 dotenv 用于密钥并将它添加到 .gitignore。
npm install typescript @solana/web3.js @types/node --save
npm install dotenv --save
echo ".env" >> .gitignore
3. 初始化 TypeScript 配置
命令 npx tsc --init 创建一个名为 tsconfig.json 的文件。该文件包含诸如要输出的 JavaScript 版本、是否启用严格类型检查以及要包括或排除的文件或文件夹之类的设置。
tsc TypeScript CLI 命令未在本文中使用,但是你应该可以使用它来将 TS 从 TS 转换为 JS 在输出目录中,“outDir”: “./dist”,
npx tsc --init
tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"module": "CommonJS",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./"
},
"include": ["*.ts"],
"exclude": ["node_modules"]
}
4.1 运行 Node.js 脚本(选项 1:tsc)
本节假定你已准备好运行 Node.js 脚本/文件。
通常在普通的 node.js 中,你只需使用如下命令:
node my-script.ts
但是,运行 typescript 略有不同,你可以使用此处 4.1 或 4.2 中的任一选项。
tsc 只是将你的脚本从 .ts 文件编译为 .js,然后像以前一样(在上面)使用 node 运行它。注意: 我没有在本文的大部分示例中使用此选项。但是,稍后我将把它用于无服务器函数示例。
优点是,如果你要将其转换为 无服务器函数,则应该使用此选项。如果需要,你可以更改更多配置选项,并同时拥有未编译和已编译的版本。你还可以将此与其他依赖项一起压缩。
npx tsc
node dist/my-script.js
4.2 运行 Node.js 脚本(选项 2:ts-node)
你安装 ts-node 并只需运行 typescript。我在本文中大部分时间都使用此选项,除了稍后。
优点是你可以使用它而无需任何额外的编译步骤,并且文件更少(不会将其编译为 .js,只需将其作为 .ts 运行即可)。
现在让我们创建我们的目录和仓库。
npm install -g ts-node
ts-node connect-to-devnet.ts
开始:创建 Solana JS/TS 仓库
确保创建一个目录和 github 仓库,以便你可以保存你的工作并保持井井有条。
Github
- 转到 Github 仪表板 并在 Github 中创建一个项目,命名为:
solana-devnet-scripts - 将其克隆到你的计算机本地。
- 或者……只需从 github CLI 在本地执行
git init
git remote add origin https://github.com/YOUR_USERNAME/solana-devnet-scripts.git
cd solana-devnet-scripts(或你的目录名称)
设置一个基本的 Node.js 项目
npm init -y
注意:请确保你设置了本系列第一部分中所需的 Node.js 和 Solana 库。如果你没有这样做,请查看该文章。
如果没有,请添加一个 .gitignore
echo -e "node_modules\ndist\n.env*" > .gitignore
安装依赖项
npm install typescript @solana/web3.js @types/node --save-dev
npm install dotenv --save
确保你添加了用于密钥的 dotenv,并将 .env* 添加到 gitignore(应该在上一步中完成)
初始化 Typescript
我们正在安装两种 Typescript 选项,以便你可以学习如何使用任何一种。但是稍后我们主要使用 ts-node。
⚠️ 我需要使用 Typescript 吗? 不,但 这是一个最佳实践,因此即使在每个脚本中都不是必需的,我们也在使用它,以使其成为一种习惯。
npx tsc -init
npm install -g ts-node
创建、编辑:tsconfig.json 以包含以下设置:
{
"compilerOptions": {
"target": "ESNext",
"module": "CommonJS",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./"
},
"include": ["*.ts"],
"exclude": ["node_modules"]
}
创建 scripts/ 和 .env 文件。
让我们开始使用一些简单的使用 Solana 的 Node.js 脚本
创建一个 scripts/ 目录是个好主意。你可以随意调用它,但这是你在代码库中看到的典型名称。
还有 .env 文件,我们在其中保存密钥或常量,并且我们不希望将其检入 github(应该在你的 .gitignore 文件 .env* 中),并且永远不要检入或提交任何 .env 文件。
1. 连接到 Solana Devnet 并检查集群状态
建立与 Solana Devnet 的连接,这是一个供开发人员使用的测试网络,并检索有关区块链状态的基本信息。
它将 Solana 集群软件的版本和最新的 slot(区块高度)记录到控制台,从而提供了一种快速验证连接性和网络状态的方法。
connect-to-devnet.ts
import { Connection, clusterApiUrl } from '@solana/web3.js';
async function checkConnection(): Promise<void> {
// Connect to Devnet
const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
// Get the version of the Solana cluster
const version = await connection.getVersion();
console.log('Solana Cluster Version:', version);
// Get the latest block height
const slot = await connection.getSlot();
console.log('Current Slot:', slot);
}
checkConnection().catch((error: Error) => console.error(error));
- 导入 solana 工具:使用
@solana/web3.js中的 Connection 和 clusterApiUrl 与 Solana 区块链交互。 - 连接到 Devnet:创建一个链接到 Solana 的 Devnet 的 Connection 对象,承诺级别为“confirmed”,以确保可靠的数据。
- 获取集群信息:异步检索集群版本(软件版本)和当前 slot 号(衡量区块链进度的指标)。
- 错误处理:将异步调用包装在 try-catch 模式中,将任何错误(网络问题)记录到控制台以进行调试。
让我们从你的终端窗口运行它:
ts-node connect-to-devnet.ts
## 输出
Solana Cluster Version: { 'feature-set': 3294202862, 'solana-core': '2.2.3' }
Current Slot: 370732858
✅ 成功了!
? 我们获得了一些其他信息,因此让我们找出其含义。
feature-set:表示集群上启用的活动功能集的数字哈希。 随着 Solana 核心功能打开或关闭而变化。 当你想确认与链上程序或工具的兼容性时,它很有用。solana-core:这是 devnet 验证器当前正在运行的 Solana 核心软件版本,此处为版本2.2.3。- 在 Solana 中,slot 是验证器可以生成区块的时间单位。 它快速前进(每约 400 毫秒)。
- 因此
370,732,858只是你运行命令时的Current slot编号,本质上是网络的心跳。
? 2. 生成一个新的 Solana 密钥对
我们将创建一个钱包, 通常称为**“密钥对”(公钥和私钥)。** 尽管请记住,非钱包账户也需要“密钥对”,因此并非所有密钥对都是钱包!

一个“钱包”:
- 可以持有 SOL,
- 控制账户,
- 进行交易并
- 授权交易。
我们将生成一个新的密码密钥对,供在 Solana 区块链上使用,包含一个公钥和一个秘密(私钥)。
⚠️ 小心:在任何地方记录 秘密 密钥都是很高的安全风险。 泄露可能导致钱包中所有资金的损失。 下面给出一个示例,仅用于学习(如果你取消注释日志记录)。
生成密钥对是一项非常基本的任务,但却是用于以下目的的常见例程:
- 在 devnet 上进行测试
- 为程序创建钱包、账户
- 模拟传输
- 签署交易
此脚本默认仅出于学习目的将 公钥 以 Base58 格式记录到屏幕上。 但是,你可以取消注释以在控制台中获取公钥和私钥,其中 公钥采用 Base58 格式,私钥采用十六进制格式,从而允许用户创建和管理 Solana 钱包。
示例(注意字符串的细微差别):
公钥,Base58: Fb8uPmkJzB6T4xJHFGgiU5hVzZEYQoWfbbKtTTfS98Xc
- 对 URL、QR 码和印刷格式安全。
- 在加密货币中很常见(也用于比特币地址)。
私钥,十六进制编码版本: 626gsjka7w73t763572ksdhj73gsj68adskhjh…
- 以可读的方式表示原始二进制数据。
- 每个字节 = 2 个十六进制字符 → 紧凑且人类可读。
⚠️ 永远不要共享密钥或让其他人看到它,例如在“屏幕共享”、屏幕截图时,并且永远不要在正常操作中登录。
- 公钥 就像一个地址,如果你愿意,可以将其公开,人们可以看到你的钱包内容,并且它是“只读的”。
- 如果某人拥有你的密钥,就好像你将房子的密码/钥匙、贵重物品保险箱和所有钱都交给了他们。 如果某人拥有你的密钥,他们可以拿走该钱包中的所有代币/钱,无论是 Dev 还是 Mainnet(真实的、实时的)。
⚠️ 不要 记录 密钥, 除非在此演示实例中用于本地学习。
generate-keypair.ts
import { Keypair } from '@solana/web3.js';
function generateKeypair(): void {
// Generate a new keypair
const keypair = Keypair.generate();
console.log('Public Key:', keypair.publicKey.toBase58());
// Secret key commented out for security. If you want to see what it looks like once uncomment below but never give it out. Security risk.
// console.log('Secret Key (DO NOT SHARE, SECRET, This is for local learning demo only):', Buffer.from(keypair.secretKey).toString('hex'));
}
generateKeypair();
⚠️你已经创建了一个“ 钱包”。 钱包持有 SOL,可以转移它并授权其他操作 — 但钱包未配置为存储额外的程序数据。稍后,我们将创建一个“ 账户”,该账户可以容纳任意额外数据。两者都有公钥,看起来相似,但配置_不同_,操作不同并且用于不同的用例。
- 导入 Keypair 类:从 @solana/web3.js 中引入 Keypair 实用程序以处理密钥生成。
- 创建密钥对:使用 Keypair.generate() 生成一个新的、随机的公私密钥对,用于 Solana 交易或账户。
- 显示密钥:将公钥输出为 Base58 编码的字符串,并将私钥输出为十六进制字符串,使其可用于进一步的区块链操作。
- 无返回值:定义为 : void,因为它执行一项操作(日志记录)而不返回数据,从而遵守 TypeScript 的类型系统。
? 3. 检查 Devnet 上的账户余额
查询指定公钥的余额,将结果从 lamports(Solana 的最小单位)转换为 SOL 以提高可读性。 它将余额记录到控制台,从而提供了一种简单的方法来检查 Devnet 账户中有多少测试 SOL 可用。
在 CLI 中它是:
solana balance <address>
你可以从 CLI 获取余额,但是此处的目的是学习如何在你在 Typescript 中编写的代码中执行此操作。
请注意脚本中的这一点,根据你的 .env 文件所在的位置更改为 dotenv.config({ path: ‘../.env’ }) 或 dotenv.config();:
// Load environment variables from .env file
dotenv.config({ path: '../.env' }); // If .env is in your app root directory
// dotenv.config(); // If .env is in your current working directory
check-balance.ts
import { Connection, PublicKey, clusterApiUrl, LAMPORTS_PER_SOL } from '@solana/web3.js';
import * as dotenv from 'dotenv';
// Load environment variables from .env file
dotenv.config({ path: '../.env' }); // location of your .env file, adjust as needed
// dotenv.config(); // If .env is in your current working directory
async function checkBalance() {
try {
const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
// Load and validate public key
const publicKeyString = process.env.PUBLIC_KEY;
if (!publicKeyString) {
throw new Error('PUBLIC_KEY not found in .env file. Check if .env is in the correct directory.');
}
// Validate the public key
let publicKey;
try {
publicKey = new PublicKey(publicKeyString);
} catch (err) {
throw new Error('Invalid PUBLIC_KEY in .env file');
}
// Get balance in lamports and convert to SOL
const balance = await connection.getBalance(publicKey);
console.log('Balance:', balance / LAMPORTS_PER_SOL, 'SOL');
} catch (error) {
console.error('Error:', (error as Error).message);
}
}
checkBalance();
- 导入 Solana 实用程序:使用 @solana/web3.js 中的 Connection、PublicKey 和 clusterApiUrl 与区块链交互。
- 建立 Devnet 连接:设置与 Solana 的 Devnet 的 Connection,承诺为“confirmed”,以获取可靠的余额数据。
- 确认有效的公钥,如果未找到则给出各种错误。 我使其比某些人更冗长一点,只是为了给出一些错误通知。
- 查询余额:获取用户提供的公钥,使用 getBalance() 获取其 lamports 余额,并将其转换为 SOL(1 SOL = LAMPORTS_PER_SOL = 10 亿 lamports)。
- 处理错误:将异步操作包装在 try-catch 块中,将任何错误(无效的公钥或网络问题)记录到控制台。
如果你想使用你当前设置的地址进行测试,或者使用其他地址:
solana address
## 输出
[你的地址]
检查是哪个钱包:
solana config get
将你正在检查的公钥添加到 .env 文件:
PUBLIC_KEY=YOUR_PUBLIC_KEY_HERE
运行:
ts-node check-balance.ts
## 输出(SOL 因你的钱包而异)
Balance: 5.239995 SOL
? 4. 在 Devnet 上请求 Airdrop
我们可以尝试获得 1 个 dev SOL 的空投。 你可以更改它,但从 devnet 获取少于 2 个 SOL,通常它不会给你超过这个数量。
⚠️ 正如我们的 CLI 教程(本设置系列的第 1 部分)中所述, 有时 devnet 会过载或受到速率限制,并且可能会给出错误。 建议从 Helius 或其他 RPC 提供商处获取 RPC devnet url/密钥,以获得更稳定、无错误的操作。 如果你想从 Helius 获取一个,请参阅我的文章:在 Solana 上构建:Helius RPC + 教程。
airdrop.ts
import { Connection, PublicKey, Keypair, clusterApiUrl, LAMPORTS_PER_SOL, VersionedTransaction } from '@solana/web3.js';
import * as dotenv from 'dotenv';
// Load environment variables from .env file
dotenv.config({ path: '../.env' }); // location of your .env file, adjust as needed
// dotenv.config(); // If .env is in your current working directory
async function requestAirdrop(): Promise<void> {
const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
// Load secret key from .env and create keypair
const secretKeyHex = process.env.PAYER_SECRET_KEY;
if (!secretKeyHex) {
throw new Error('PAYER_SECRET_KEY not found in .env file');
}
const payerKeypair = Keypair.fromSecretKey(Buffer.from(secretKeyHex, 'hex'));
const publicKey = payerKeypair.publicKey;
// Request 1 SOL airdrop
const signature = await connection.requestAirdrop(publicKey, 1_000_000_000); // 1 SOL in lamports
const latestBlockhash = await connection.getLatestBlockhash();
await connection.confirmTransaction({
signature,
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
});
console.log('Airdrop successful! Transaction signature:', signature);
// Check new balance
const balance = await connection.getBalance(publicKey);
console.log('New Balance:', balance / LAMPORTS_PER_SOL, 'SOL');
}
requestAirdrop().catch((error: Error) => console.error(error));
- 加载和配置环境变量: 该脚本使用
dotenv包从.env文件加载环境变量。 这允许代码访问敏感数据,例如 Solana 钱包的密钥,而无需对其进行硬编码。 - 建立与 Solana Devnet 的连接: 它使用
@solana/web3.js中的Connection类连接到 Solana Devnet 集群。 该连接用于在开发安全的环境中与区块链交互。 - 从密钥重建钱包: 从环境读取付款人的密钥,并重新生成关联的 Solana 密钥对。 此密钥对是验证交易和请求空投所必需的。
- 请求并确认 1 SOL 的空投: 该函数请求将 1 SOL(1,000,000,000 lamports)的空投到钱包的公钥。 然后,它使用最新的区块哈希确认交易并记录交易签名。
- 获取并显示更新的 SOL 余额: 空投之后,该脚本会获取新的钱包余额以验证是否已收到资金。 它将余额从 lamports 转换为 SOL,以提高可读性。
⚠️ 你的脚本需要一个密钥,因为它涉及在 Solana devnet 上请求空投,这是一种链上操作,需要签名者(付款人)启动和确认交易。
首先获取你的钱包路径:
solana config get
## 输出(示例,因你的配置而异)
...
Keypair Path: /Users/yourusername/wallets/wallet-dev.json
...
现在获取你的密钥,使用上面的完整钱包路径/文件输出:
cat put-your-full-wallet-path/file-here.json | jq -r '.[]' | xargs printf "%02x"
## 输出
jhe1nbc9v6yiok7jfdiohg88silhor ...etc.
将密钥完全按照输出添加到 .env 文件:
PAYER_SECRET_KEY=YOUR_SECRET_KEY_HERE
运行它:
ts-node airdrop.ts
## 输出
Airdrop successful! Transaction signature: 57bKTADsu6XkUZzGpEsJgU5mhEsp7x9JFiTAJsjij8dXRKiab1g7N1oaUavH57krdeDtifY2iKDFhNEnZ2m477hz
New Balance: 6.239995 SOL
你可以转到 Solscan.io (devnet) 或其他区块浏览器,并将交易签名放入搜索栏中(请确保在 Solana 徽标的右上角设置为 Devnet,否则它将找不到交易)。

5. 在账户之间转移 SOL
在下一个 Solana 实用程序脚本中,我们将组合一些操作。 我们这样做是为了举例说明,以便你可以看到如何组合多个操作来完成任务。 在现实生活中,它可能略有不同,但这取决于你的场景。
为了使其工作,我们将需要一个 ✅ 具有公钥/密钥的“from”钱包和一个 ✅ 仅具有公钥的“to”钱包。 如果没有“from”钱包或密钥,我们将创建一个新钱包并尝试获得空投来资助它。
一旦我们有一个带有资金的“from”钱包,我们将执行转移指令。
import {
Connection,
PublicKey,
Keypair,
Transaction,
SystemProgram,
clusterApiUrl,
LAMPORTS_PER_SOL,
} from '@solana/web3.js';
import * as dotenv from 'dotenv';
dotenv.config({ path: '../.env' }); // location of your .env file, adjust as needed
function getOrCreateKeypair(): Keypair {
const secretKeyHex = process.env.PAYER_SECRET_KEY;
// this returns a key pair (public & secret key)
if (secretKeyHex) {
console.log('Using existing payer key from .env');
const secretKey = Buffer.from(secretKeyHex, 'hex');
return Keypair.fromSecretKey(secretKey);
} else {
console.log('No secret key found. Generating new payer key...');
const newKeypair = Keypair.generate();
console.log('Generated Public Key:', newKeypair.publicKey.toBase58());
return newKeypair;
}
}
async function transferSOL(): Promise<void> {
const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
const fromKeypair = getOrCreateKeypair();
let balance = await connection.getBalance(fromKeypair.publicKey);
if (balance < 0.02 * LAMPORTS_PER_SOL) {
console.log('Insufficient funds, requesting airdrop...');
const airdropSignature = await connection.requestAirdrop(
fromKeypair.publicKey,
LAMPORTS_PER_SOL
);
const latestBlockhash = await connection.getLatestBlockhash();
await connection.confirmTransaction({
signature: airdropSignature,
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
});
balance = await connection.getBalance(fromKeypair.publicKey);
console.log(`New balance after airdrop: ${balance / LAMPORTS_PER_SOL} SOL`);
} else {
console.log('Sufficient funds available, skipping airdrop.');
}
const toPublicKey = new PublicKey(process.env.RECIPIENT_PUBLIC_KEY || '');
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: fromKeypair.publicKey,
toPubkey: toPublicKey,
lamports: 0.01 * LAMPORTS_PER_SOL,
})
);
const signature = await connection.sendTransaction(transaction, [fromKeypair]);
const latestBlockhash = await connection.getLatestBlockhash();
await connection.confirmTransaction({
signature,
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
});
console.log('Transfer successful! Transaction signature:', signature);
balance = await connection.getBalance(fromKeypair.publicKey);
console.log('New Balance:', balance / LAMPORTS_PER_SOL, 'SOL');
}
transferSOL().catch(console.error);
在此脚本中,你需要:
- RECIPIENT_PUBLIC_KEY(接收转移的“to”地址)。
- 可选,PAYER_SECRET_KEY:如果你想使用特定的钱包作为“from”地址,请在 .env 文件中使用其密钥。 该脚本检查此密钥是否可用,如果不可用,则创建一个新密钥并尝试获得空投。
⚠️ 注意: 如果我们有钱包的密钥,我们也可以从中获取公钥! 因此,我们不需要将 PAYER 的公钥放入 .env 文件中!
.env 文件,你应该这样写(使用完整密钥,示例密钥已缩短):
PAYER_SECRET_KEY=ce3146a9...50f2bea68a2637
RECIPIENT_PUBLIC_KEY=9sLg...ktjA9WfkQPE
如果你也具有先前的 PUBLIC_KEY=GtYM8…P9zcXQ,则可以将其保留在其中,但我们不需要它。
ts-node transfer-sol.ts
## 输出
Using existing payer key from .env
Sufficient funds available, skipping airdrop.
Transfer successful! Transaction signature: 2r4qu6LX...NZaBjG
New Balance: 6.22999 SOL
回顾一下我们所做的事情:
- 创建连接。 建立与 Solana Devnet 的链接,承诺级别为“confirmed”,以实现可靠的交易跟踪。
new Connection(clusterApiUrl(‘devnet’), ‘confirmed’) - 从密钥重建密钥对。
Keypair.fromSecretKey(…)从以十六进制格式提供的 64 字节密钥加载现有钱包。 - 生成新的密钥对。
Keypair.generate()创建一个全新的随机钱包,除非显式导出或写入文件,否则不会保存该钱包。 当没有可用的钱包时,这很有用。 但是,除非你保留密钥对,否则退出脚本后将失去访问权限。 - ? 检查钱包余额。
connection.getBalance(publicKey)查询钱包中 lamports 的当前余额,可以将其转换为 SOL 以提高可读性。 - ? 请求空投。
connection.requestAirdrop(publicKey, lamports)请求 Devnet 水龙头将测试 SOL 发送到钱包以用于开发目的。 - 确认交易。
connection.confirmTransaction(signature)等待已提交的交易被网络确认并包含在一个区块中。 - 创建转移交易。
new Transaction().add(SystemProgram.transfer({…}))使用SystemProgram.transfer构建一个新交易,以将 SOL 从一个地址转移到另一个地址。 - 发送交易。 将已签名的交易提交到区块链并等待确认。
connection.sendTransaction(transaction, [signer])
有关交易设置的更多信息:
const signature = await connection.sendTransaction(transaction, [fromKeypair]);
将交易发送到 Solana 网络,并使用 fromKeypair 对其进行签名。 返回的 signature 是一个唯一 ID,你可以使用它来跟踪链上的交易状态。
const latestBlockhash = await connection.getLatestBlockhash();
获取最新的区块哈希和关联的 lastValidBlockHeight。 需要这些值来确认交易尚未过期(必需)。
await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight });
使用签名和区块数据确认交易,以在已知的区块范围内验证它。 此方法可以防止确认过时的交易并提高可靠性。
? 感谢阅读!… ? 请鼓掌并分享这篇文章,谢谢!?
6. 创建和资助一个新账户
- 此脚本在 Devnet 上创建一个新的 Solana 账户,并为其提供足够的 lamports 以满足租金豁免要求,外加额外的 0.1 SOL。
- 它使用从环境变量加载的付款人密钥对 来支付费用,为账户生成一个新的密钥对,并使用 SystemProgram 的 createAccount 指令构造一个交易。
- 然后,它确认交易并记录新账户的公钥和余额,从而确保该账户已准备好在进一步的区块链操作中使用。
用例: 你可能会创建并资助一个新账户,以初始化你的去中心化应用程序的全新钱包或状态账户,从而确保它可以免除租金并为交易做好准备。 它还有助于通过隔离账户余额和操作来安全地管理资金。
⚠️ 我们不是已经用钱包做过这件事了吗? 没有。 创建账户与创建钱包不同。
- 钱包 = 密钥对。 钱包不能执行其他账户可以执行的所有操作,但它是一种专门账户,可以签署交易、持有 SOL、授权程序交互
- 账户 = 链上存储。 你的钱包(是的,它是一种账户)、代币账户(用于 SPL 代币)、程序账户
仅创建钱包密钥对(示例):
const myWallet = Keypair.generate();
创建保存数据的账户(示例):
const accountKeypair = Keypair.generate();
const tx = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: myWallet.publicKey,
newAccountPubkey: accountKeypair.publicKey,
lamports: rentExemption,
space: 100,
programId: myProgramId
})
);
create-account.ts
import { Connection, PublicKey, Keypair, Transaction, SystemProgram, clusterApiUrl, LAMPORTS_PER_SOL } from '@solana/web3.js';
import * as dotenv from 'dotenv';
// Load environment variables from .env file
dotenv.config({ path: '../.env' }); // location of your .env file
async function createNewAccount(): Promise<void> {
const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
// Load secret key from .env and create keypair
const payerSecretKeyHex = process.env.PAYER_SECRET_KEY;
if (!payerSecretKeyHex) {
throw new Error('PAYER_SECRET_KEY not found in .env file');
}
const payerKeypair = Keypair.fromSecretKey(Buffer.from(payerSecretKeyHex, 'hex'));
// Generate a new account to create
const newAccountKeypair = Keypair.generate();
// Minimum balance for rent exemption (approx. 0.002 SOL)
const rentExemptionAmount = await connection.getMinimumBalanceForRentExemption(0);
// Create transaction to make the new account and fund it with 0.1 SOL
const transaction = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: payerKeypair.publicKey,
newAccountPubkey: newAccountKeypair.publicKey,
lamports: rentExemptionAmount + 100_000_000, // Rent + 0.1 SOL
space: 0, // No additional space needed for this example
programId: SystemProgram.programId,
})
);
// Sign and send the transaction
const signature = await connection.sendTransaction(transaction, [payerKeypair, newAccountKeypair]); const latestBlockhash = await connection.getLatestBlockhash();
await connection.confirmTransaction({
signature,
blockhash: latestBlockhash.```
createNewAccount().catch((error: Error) => console.error(error));
⚠️ 请确保你的 .env 文件中仍然有 PAYER_SECRET_KEY。
让我们运行它,然后讨论发生了什么:
ts-node create-account.ts
## 输出 (因情况而异)
New Account Created! Public Key: 7mBp...wv4bSanp6QXkK9
Transaction signature: 3KB66jvhcAu19UDH...RFnk7YaP9
New Account Balance: 0.10089088 SO
和之前一样,你可以将这个放入 Solscan.io devnet 搜索中并查看交易。
- 创建一个连接。
new Connection(clusterApiUrl('devnet'), 'confirmed')连接到 Solana Devnet 集群,用于发送和确认交易。 - 重建 payer 密钥对。
Keypair.fromSecretKey(...) 从存储在 .env 文件中的密钥中恢复 payer 钱包。
- 生成一个新的账户密钥对。
Keypair.generate()创建一个新的密钥对,它将成为新创建的链上账户。 - 计算租金豁免。
connection.getMinimumBalanceForRentExemption(0) 确定所需的 lamports 数量,以防止新账户因不活动而被清除。
- 创建一个系统账户创建指令。
SystemProgram.createAccount(...)准备一个指令,用于在链上创建一个新账户,并用租金 + SOL 为其提供资金。 - 发送带有签名的交易
connection.sendTransaction(transaction, [payerKeypair, newAccountKeypair])发送交易,交易由 payer 和新账户签名。 - 获取最新的区块哈希。
connection.getLatestBlockhash()获取最新的区块信息,以确保交易确认的安全。 - 确认交易。
connection.confirmTransaction({...})使用签名和区块信息等待交易在链上最终完成。 - 检查新账户余额。
connection.getBalance(newAccountKeypair.publicKey)检索新创建账户的 SOL 余额。

我们有很多基本的 Node.js TypeScript 示例,所以希望你对我们正在做的事情感到更舒服。
现在让我们用 React 和 Next.js 做一个快速的前端钱包集成。
7. 设置 Solana 模板 (Next.js + TypeScript + React Solana 钱包集成)
我们将设置一个简单的 Solana 模板安装。
- 这在 Solana Developer 仓库中维护 (由 Solana 基金会推广) beeman 在 X 上。截至本文发布,上次更新是 2 周前……但使用的是 Next.js 14。
- 还有另一个 Solana dAPP scaffold,但它已被存档,并且没有被更新。如果你搜索 Github,你可能会找到其他的。
注意: 我们不会总是使用这个。但这是一个很好的学习引导。
- 虽然它现在对学习很有用,但在早期阶段,从一个 从零开始的 Next.js 安装和添加我们自己的 Solana 库有一些优势。这取决于项目。
- 这对一个简单的项目来说很好, 但是随着你有了更多高级的想法和更大的应用程序,你可能会觉得它不够用。
从命令行,我运行了:
npx create-solana-dapp solana-dapp-tutorial
你可以更改 solana-dapp-tutorial 的名称——这就是我命名我的学习应用程序的名称。
npx create-solana-dapp solana-dapp-tutorial
## 输出
create-solana-dapp 4.2.7
│
◆ Project name: solana-dapp-tutorial
│
◇ Select a framework
│ Next.js
│
◆ Select a template
│ ● next-tailwind-counter (Next.js + Tailwind CSS + Anchor Counter Example)
│ ○ next-tailwind-basic
│ ○ next-tailwind
Cloning...
Installing...
◇ Installed via npm
│
◇ Executed init script
│
◇ Initialized git repo
│
◇ Installation successful ────────────────────────────╮
│ │
│ That's it! │
│ │
│ Change to your new directory and start developing: │
│ │
│ cd ./solana-dapp-tutorial │
│ │
│ Start the app: │
│ │
│ npm run dev │
│ │
│ Run Anchor commands: │
│ │
│ npm run anchor build | test | localnet | deploy │
│ │
├──────────────────────────────────────────────────────╯
│
└ Good luck with your project!
暂时忽略 Anchor 的内容。
现在我将运行它,看看会发生什么。
npm run dev
## 输出:
> legacy-next-tailwind-counter@0.1.0 dev
> next dev
▲ Next.js 14.2.24
- Local: http://localhost:3000
✓ Starting...
✓ Ready in 3.6s
一个问题,立即注意到的,是 Next.js 14。这需要升级到 Next.js 15。
现在,为了学习,我们将坚持使用这个。
我去了 http://localhost:3000 (如果你的 3000 端口正在运行其他东西,你的端口可能会不同,使用它在输出中给你的端口)

让我们快速地从顶部看一下这个。
- 你必须安装一个钱包,它会显示公钥的一些字符。
- 确保网络设置为 devnet。
- 下面是额外的 Solana 文档和资源。
8. 安装和设置一个 Solana “热”钱包
这被称为热钱包,因为它不如其他类型的钱包安全,但经常用于持有相对少量的 SOL 的一些应用程序和演示/学习。热钱包被使用是因为它们对于在线应用程序/任务来说很方便,尽管不如 Ledger (你连接的硬件钱包设备) 和冷钱包 (离线持有) 安全。
我们正在 devnet 上进行实验,所以这没问题。但如果可能,不要使用你的 mainnet Solana 钱包。
- 在你的 Chrome 浏览器中安装 Phantom 或 Backpack 钱包扩展。还有其他的,比如 Solflare。你也可以下载移动钱包应用程序。下载 URL 和文档如下。
- Backpack 钱包经常用于开发,因为它更容易切换自定义 RPC url (用于有效地连接到 Solana)。此外,出于安全原因,我保留了一个完全隔离的、独立的 Backpack 开发钱包!我不喜欢在真实的钱包上测试应用程序,因为存在安全问题,所以它是沙盒化的。此外,作为额外的预防措施,不要在上面持有产品的 mainnet SOL。
- 如果这对你来说更容易,你可以创建一个新的 Chrome 配置文件,使用不同的钱包,或者,如果可能,在你的操作系统上启动一个新的用户帐户,该帐户只有你开发所需的最低权限,或者使用 Docker 容器或 VM。
- Phantom 也是一个非常可靠的钱包,有些人更喜欢它。如果你使用默认的 devnet 选项,没有自定义的 dev RPC,那么你可能会遇到更多的网络超时。如果你正在进行大量的开发,这可能会很烦人——但对于只是尝试这些教程来说,可能不是问题。
- 小心良好的钱包安全、钱包卫生,并确保你知道你正在使用 devnet,不要与真实的 mainnet 实时 SOL 相混淆!永远不要出于任何理由透露或记录密钥。 你可能会被编码之神“击倒”,从而接受一个严厉的教训。
- ⚠️ 安全意识: 请阅读像这篇文章一样的文档,并为你自身的安全意识进行研究。“安全最佳实践和潜在风险”,“常见的加密货币诈骗以及如何避免它们” 和 “ 什么是私钥? ”
“想象一下,你的数字资产是存储在个人金库中的贵重物品。正如你不会让你的家的门不上锁,或者随意分享你的金库密码一样,采取严格的安全措施来保护你的加密货币持有是至关重要的。”
- ⚠️ 这很重要,不要忽略它。 我不想听到我的朋友在这里把它搞砸。你自己的钱包中的加密货币是“自我托管”,这意味着你对保护你的钱包负有 100% 的责任。
先决条件
- 安装一个 Solana 兼容的钱包:
- Phantom:从 phantom.app 下载(浏览器扩展或移动应用程序)。阅读 Phantom 文档。
- Backpack 钱包:从 backpack.app 下载(浏览器扩展)。阅读 Backpack 钱包文档。
- Solflare 和其他的也存在,例如 Jupiter Mobile。
9. 获取免费的 Solana Devnet 空投
免费的 Solana 空投:用测试 SOL 为你的钱包提供资金
- 在 Devnet 上,SOL 可以免费用于测试。通常一次 1-2 个或更少。
- ⚠️ 一个常见的问题是 devnet 在空投时超时。如果发生这种情况,请尝试以下各种选项,或者只是等待几分钟。
- ⚠️ 当你确实获得了 devnet SOL 时,尝试获得更多,不要浪费它。 有时很难再次获得 (超时)
现在我们需要免费的 devnet SOL。
有很多方法可以做到这一点,包括从 CLI(但这有时会超时并且受到速率限制),也可以通过我们正在使用的 javascript 脚本……
一个简单且相对可靠的空投是如果你使用 Github 登录 Solana 的 faucet:https://faucet.solana.com/
有关空投的更多方法,请参见 devnet SOL Solana 文档:https://solana.com/developers/guides/getstarted/solana-token-airdrop-and-faucets
10. 在 Next.js 中加载你的钱包
正如你在上面看到的,它显示了我在 devnet 上的 dev Backpack 钱包。
如果你以前没有连接过你的浏览器钱包,你可能会看到不同的东西。



按照说明操作。
接下来,我们将看看产生这个的代码。
11. Next.js 中 Solana 钱包代码的回顾
让我们看看产生钱包的代码。
首先,让我们回顾一下用于这个前端,React/Next.js 钱包集成的关键库。
Solana 钱包集成前端库
不是一个库,而是使用了许多库 (注意:最后一个是非 Solana 的,你可以根据需要替换它):
- solana/web3.js: 提供与 Solana 区块链交互的工具 (例如 Connection, PublicKey)。用于连接到集群并获取帐户数据。
- solana/wallet-adapter-react: 提供 React hooks 和实用程序 (useConnection, useWallet) 用于钱包连接。简化钱包状态管理和交易签名。
- solana/wallet-adapter-react-ui: 提供预构建的 UI 组件,例如用于钱包连接的 WalletMultiButton。
- coral-xyz/anchor (本教程中未使用): 集成 Anchor 框架,用于与 Solana 链上程序交互。用于此应用程序中的程序交互。我们将在以后介绍这个,而不是在本教程中。
- tanstack/react-query: 这不是 Solana 特有的,但如果你是新手,或者只是想知道堆栈中使用了什么,那么了解它会很好。这用于管理数据获取和 mutations (获取帐户数据,发送交易)。
它是如何工作的 (摘要)
- 设置: SolanaProvider 包装应用程序,提供钱包和连接上下文。
- 连接: 该应用程序使用 @solana/web3.js 连接到 Solana 集群(例如,devnet)。
- 钱包集成: 用户通过 WalletMultiButton 连接他们的钱包(例如 Phantom, Backpack, Solflare 等)。
- 程序交互 (可选,本教程中未使用): useAnchorProvider hook 组合了钱包和连接,用于基于 Anchor 的程序调用。
- 交易: Mutations (例如 initialize) 使用钱包来签名并将交易发送到区块链。
关键前端代码片段
以下是此模板中使其工作的关键代码片段。
- Solana Provider 设置: 此组件为应用程序设置 Solana 钱包和连接上下文。你可以用这个包装应用程序。
(src/components/solana/solana-provider.tsx)
'use client'
import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react'
import { WalletModalProvider, WalletMultiButton } from '@solana/wallet-adapter-react-ui'
import { useCluster } from '../cluster/cluster-data-access'
import { ReactNode, useCallback, useMemo } from 'react'
import dynamic from 'next/dynamic'
// Dynamically import WalletMultiButton to avoid SSR issues
export const WalletButton = dynamic(
async () => (await import('@solana/wallet-adapter-react-ui')).WalletMultiButton,
{ ssr: false }
)
export function SolanaProvider({ children }: { children: ReactNode }) {
const { cluster } = useCluster() // Custom hook to get cluster config
const endpoint = useMemo(() => cluster.endpoint, [cluster]) // Cluster endpoint (e.g., devnet)
const onError = useCallback((error: WalletError) => {
console.error(error) // Handle wallet errors
}, [])
return (
<ConnectionProvider endpoint={endpoint}>
<WalletProvider wallets={[]} onError={onError} autoConnect={true}>
<WalletModalProvider>{children}</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
)
}
- 使用 Solana 连接和钱包 providers 包装应用程序,启用钱包连接和集群选择。
- ConnectionProvider: 建立与 Solana 集群的连接。
- WalletProvider: 管理钱包状态并在之前获得授权时自动连接。
- WalletModalProvider: 添加一个用于钱包选择的 modal。
这是一个需要记住的关键部分:
// Dynamically import WalletMultiButton to avoid SSR issues
export const WalletButton = dynamic(
async () => (await import('@solana/wallet-adapter-react-ui')).WalletMultiButton,
{ ssr: false }
)
- 钱包按钮用法
src/components/ui/ui-layout.tsx
import { WalletButton } from '../solana/solana-provider'
export function UiLayout({ children, links }: { children: ReactNode; links: { label: string; path: string }[] }) {
return (
<div className="h-full flex flex-col">
<div className="navbar bg-base-300">
<div className="flex-1">
{/* Navigation links */}
</div>
<div className="flex-none space-x-2">
<WalletButton /> {/* Connects/disconnects wallet */}
<ClusterUiSelect /> {/* Cluster selection */}
</div>
</div>
{children}
</div>
)
}
12. 快速的首次交易,React Hooks
我们将回顾这个应用程序和一些代码。
通常,当我们从头开始时,我们必须开始创建实用程序来执行基本的 Solana 交易。
但是,这个 dAPP 模板已经有了!?
所以,我们不用尝试从头开始做所有这些,我们就在这里试验,学习如何在应用程序中完成它!? 也少了打字!
启动此应用程序的本地实例:
npm run dev
应该能够从以下位置访问 Account 页面:

这是我最初得到的。

你可以在这里看到,我们应该深入研究代码的几个项目……
- 显示我当前钱包中的 SOL。
- 显示我拥有的 token 帐户 (换句话说,非 SOL token)。 我为另一个项目做了一些,包括 dev USDC 和一些我从头开始制作的。
- 交易历史, 交易签名列表。
- 空投更多的 dev SOL。
考虑一下……这是开始一个很棒的 Solana 学习和诊断仪表板!我们可能会在另一个教程中在这个基础上构建更多的东西。我们可以做什么?添加并集成大约 10 个更多的 Solana React hooks?所有这些都可以在我们未来的所有项目中使用。那太棒了!
我从 1.17 SOL 开始,并在空投按钮上添加了 2 个。?
但是,当我试图再次这样做时,我得到了一个错误!这是预期的,因为通常你一次只能做 2 个,具体取决于它的限制方式,可能需要等待一段时间才能再次尝试。
在此之后,我确实尝试了几次,发现在 5-10 分钟后它再次工作了。但是当你使用它时,这可能会有所不同,它会根据当前的使用情况而变化。

在我写这篇文章的时候,我做了几次空投,所以我的总 SOL 上升了(该死,如果它是真正的 SOL 就好了!真是个吊人胃口的人!)。然后,在最初写完这篇文章的第二天,我又做了更多的空投,现在是 23+。
高达 3 个是好的,但 1-2 个更可靠,并且无法使其更高。

回顾这背后的代码。
真正有用的是,有一个文件通过 React hooks 控制着许多“Solana actions”,称为: account-data-access.tsx
我查看了它,并折叠了 React hook 函数名称,这样我们就可以概述一下这个文件是做什么的。
现在你知道我为什么想从这个开始了……当我们深入研究代码以了解是如何完成的时,大量的有用开发编码信息。

- useGetBalance: 获取指定帐户的 SOL 余额。
- useGetSignatures: 检索给定帐户的交易签名列表。
- useGetTokenAccounts: 收集指定地址拥有的 token 帐户。它查询标准 token 程序和新的 TOKEN 2022 程序,合并它们的结果。
- useTransferSol: 从用户的钱包发起 SOL 到目标地址的转移交易。
- useRequestAirdrop: 调用 Solana 连接的空投方法,将 SOL 数量转换为 lamports 并确认交易。在成功的空投之后,它使与帐户余额和签名相关的缓存查询无效,因此 UI 反映了更新的状态,同时还显示了一个交易 toast。
其他说明:
- 所有这些的输入只是一个公钥地址 (钱包地址)。
- 这些作为 React hooks 导出,因此可以在整个应用程序中重复使用……或者如果你集成它们,可以在任何其他 React 应用程序中重复使用!这不是很棒吗?
你可以自己查看这些函数,但我们只看一个,以确保我们理解基本模式。
这些中的每一个都在使用非 Solana 库 tanstack/react-query 进行提取,你可以用你喜欢的 fetch、axios 或其他库替换它。
每个 useQuery 都在那里,因为它正在使用 tanstack/react-query 进行提取并获取响应。
useGetTokenAccounts:用于获取钱包中有哪些 token。
// 这行代码声明并导出一个名为 useGetTokenAccounts 的自定义 hook。
// 它接受一个带有单个属性 address 的对象,该属性是 Solana 的
export function useGetTokenAccounts({ address }: { address: PublicKey }) {
// 检索当前的 Solana 连接。
const { connection } = useConnection()
// useQuery 负责处理异步数据获取、缓存和自动更新。
return useQuery({
// 这为查询设置了一个唯一的标识符。
// 这是一个数组,包括一个静态字符串和一个包含连接的 rpcEndpoint 和地址的对象。
queryKey: ['get-token-accounts', { endpoint: connection.rpcEndpoint, address }],
//异步函数,将在执行查询时获取 token 帐户数据。
queryFn: async () => {
// 使用 Promise.all 执行两个异步操作。
// 这两个操作的结果被解构为 tokenAccounts 和 token2022Accounts。
const [tokenAccounts, token2022Accounts] = await Promise.all([\
// 调用以使用标准 token 程序获取 address 拥有的 token 帐户\
connection.getParsedTokenAccountsByOwner(address, {\
programId: TOKEN_PROGRAM_ID,\
}),\
\
// // 调用以使用 Token 2022 (更新的,带有扩展) 获取 address 拥有的 token 帐户\
connection.getParsedTokenAccountsByOwner(address, {\
programId: TOKEN_2022_PROGRAM_ID,\
}),\
\
])
// 返回合并后的结果。
return [...tokenAccounts.value, ...token2022Accounts.value]
},
})
}
- 这次我把笔记放在代码的注释里了。
- 在其他 hooks 中,这是一个类似的模式
?️ 团队,我们在这篇文章中做了很多,我将在这里结束这篇文章。
我们将在下一个第 3 部分中再写一篇关于 Anchor 和 Rust 的设置文章, 这是创建链上程序所必需的。
在那之后……我们将开始比赛,并准备好制作应用程序 ?
其他 Solana 资源:
我可能会更新这些以进行更改/新资源。
Solana 文档 : 用于学习和使用 Solana 区块链的官方文档,包括设置指南、API 和协议详细信息。
Solana Faucet : 一个 Web 工具,可让你免费获得 Devnet SOL,用于测试 Solana 应用程序,而无需花费真正的 token。
Solana Cookbook : 一个开发者友好的指南,其中包含以代码为中心的实用方法,用于在 Solana 上构建应用程序和智能合约。
Solana Stack Overflow : 一个社区问答网站,开发者可以在这里提问和回答与 Solana 开发相关的技术问题。
Solana Developers GitHub : Solana 核心和社区开发者协作、共享工具和维护开源 Solana 项目的 GitHub 组织。
Awesome Solana : 我最初的 repo。很大,有几年历史了,并且有一些链接已损坏,我将尽快更新。如果最近没有更新,请再次查看。
? 感谢阅读!… ? 请鼓掌并分享这篇文章,谢谢!?
促销:我的云电子书商店——超值的云架构师和工程师书籍,“Cloud Metrics”(800 多页)和“Cloud Audit”(800 多页)等——https://store.systemsarchitect.io
结账时享受 35% 折扣 折扣码:35BLOG2025
https://store.systemsarchitect.io
关于我
我是一位云架构师、高级开发人员和技术负责人,喜欢通过创新的解决方案解决高价值的挑战。
我总是乐于讨论项目。如果你在项目上需要帮助、有一个机会,或者只是想聊聊云问题,你可以通过 csjcode at gmail 与我联系。
我在 Medium 上的最新文章: https://medium.com/@csjcode
Cloud Cost Saving: https://medium.com/cloud-cost-savings
Cloud Architect Review: https://medium.com/cloud-architect-review
AI Dev Tips: https://medium.com/ai-dev-tips
API Dev Tips: https://medium.com/api-dev-tips
Solana Dev Tips: https://medium.com/solana-dev-tips
我在软件开发领域工作了 20 多年, 既有像 NIKE 和最初的 MP3.com 这样的 企业 环境,也有像 FreshPatents, SystemsArchitect.io, API.cc, 和 Instantiate.io 这样的 初创企业。
我的经验范围从 云电子商务, API 设计/实现, serverless, AI 集成 用于开发、内容管理、前端 UI/UX 架构 和 登录/身份验证。我为架构软件提供技术讲座、教程和分享文档。之前也持有 AWS Solutions Architect 认证。
促销:我的云电子书商店——超值的云架构师和工程师书籍,“Cloud Metrics”(800 多页)和“Cloud Audit”(800 多页)等——https://store.systemsarchitect.io
结账时享受 35% 折扣 折扣码:35BLOG2025
- 原文链接: medium.com/solana-dev-ti...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~