小试牛刀-Solana合约账户详解

目录

一.Solana

三.账户详解

[3.1 程序账户](#3.1 程序账户)

[3.2 系统所有账户](#3.2 系统所有账户)

[3.3 程序派生账户(PDA)](#3.3 程序派生账户(PDA))

[3.4 Token账户](#3.4 Token账户)

四、相关学习文档

五、在线编辑器


Welcome to Code Block's blog

本篇文章主要介绍了

**Solana合约账户详解**

❤博主广交技术好友,喜欢文章的可以关注一下❤

注:该篇文章在测试环境下进行,使用测试账户进行。

一.合约账户类型

开发语言上,Solana合约使用Rust 为主要开发语言,其次是Solana合约并不像其它链那样将数据直接存到合约里,而是使用了更加独立的账户来代币转移和存储数据。按功能可以分为以下账户:

  • 程序账户
  • 系统所有账户
  • 程序派生账户(PDA)
  • Token账户

二.账户详解

2.1 程序账户

程序账户即为合约部署后生成的账户,这个账户用于存储和执行智能合约代码,即合约部署后生成的地址。这里部署地址是:Fckx9Sxf17hyauwe1nfxL9GtvruESb5kTrU2LCPLJpzm

测试截图:

2.2 系统所有账户

用户通过调用程序账户生成用于存储状态的数据的账户为系统所有账户,这个账户的所有者为当前合约。同时用户可以获得当前账户的公钥和私钥信息。使用TS创建的代码如下:

TypeScript 复制代码
    const greetingAccountKp = new web3.Keypair();
    const lamports = await pg.connection.getMinimumBalanceForRentExemption(
      GREETING_SIZE
    );
    console.log(GREETING_SIZE);
    const createGreetingAccountIx = web3.SystemProgram.createAccount({
      fromPubkey: pg.wallet.publicKey,
      lamports,
      newAccountPubkey: greetingAccountKp.publicKey,
      programId: pg.PROGRAM_ID,
      space: GREETING_SIZE,
    });
    const tx = new web3.Transaction();
    tx.add(createGreetingAccountIx);

    const txHash = await web3.sendAndConfirmTransaction(pg.connection, tx, [
      pg.wallet.keypair,
      greetingAccountKp,
    ]);
    console.log(`Use 'solana confirm -v ${txHash}' to see the logs`);

执行上述代码并成功后,这里的greetingAccountKp内的公钥和私钥即为创建账户的公钥和私钥。可以通过以下方式进行打印:

TypeScript 复制代码
    console.log("publicKey:" + greetingAccountKp.publicKey.toBase58());
    console.log("secretKey:" + greetingAccountKp.secretKey);

这个账户与普通账户的不同之处在于其用于存储数据,账户owner为当前程序账户,在合约内可以使用以下方式在合约内进行打印:

TypeScript 复制代码
    // 账户列表
    let accounts_iter = &mut accounts.iter();

    // 下一个账户
    let account = next_account_info(accounts_iter)?;
    // 打印账户拥有者
    msg!("account:{}", account.owner);

log截图:

测试截图:

2.3 程序派生账户(PDA)

在实际应用中,用户在创建账户后即需要存储账户信息,这显然是不符合实际需求的,首先这会生成大量账户浪费资源,并且不利于账户管理和维护。如实现用户锁仓功能:用户创建一个账户后,服务程序即需要存储这个钱包创建的对应账户地址。PDA账户很好的解决了这个问题。PDA的原理为让程序通过利用种子(方法名或其它)+用户钱包公钥+程序账户(合约地址),三者进行加密运算生成一个钱包地址,这个地址是唯一的,在后续运算中仍然会生成这个地址,这样即解决了账户存储和管理问题。TS代码PDA账户生成方式如下:

TypeScript 复制代码
async function getPda(programId, userPubkey) {
  const [pda, bump] = await web3.PublicKey.findProgramAddressSync(
    [Buffer.from("lock"), userPubkey.toBuffer()],
    programId
  );
  console.log("PDA:", pda.toBase58());
  return pda;
}

这里的lock为种子(种子是可变的,可使用对应合约方法名,便于管理),userPubkey为用户地址,programId为程序账户账户地址.使用如下方式进行调用(会发现每次生成地址结果为同一地址):

TypeScript 复制代码
    const pda = getPda(pg.PROGRAM_ID, greetingAccountKp.publicKey);
    console.log(pda);

测试截图:

通过截图可以看到运行多次生成的地址为相同的.

2.4 Token账户

SPL账户即为存储某个特定的代币创建的账户,该账户用于存储某个特定类型的代币,创建方式如下:

TypeScript 复制代码
async function createSPLAccount() {
    const mint = new web3.PublicKey('代币合约地址'); 
    const owner = payerAccount.publicKey; // 付款账户

    // 创建 SPL 账户
    const tokenAccount = await splToken.Token.createAccount(connection, {
        mint,
        owner,
    });

    console.log('SPL 账户创建成功:', tokenAccount.toBase58());
}

三、相关学习文档

1.Solana官方文档

2.Solana GitHub 仓库

四、在线编辑器

1.Solana IDE

声明:该文章只作为学习和使用相关,不涉及投资等其它建议.

相关推荐
Risk Actuary17 小时前
侧挂车(Sidecar)与巨灾债券(Cat Bond)
区块链
Css38RttP18 小时前
springMVC-RequestMapping注解
区块链
Amos_Web21 小时前
Solana开发(1)- 核心概念扫盲篇&&扫雷篇
前端·rust·区块链
OPHKVPS1 天前
GoBruteforcer(GoBrut)僵尸网络新攻势:AI 生成弱配置成“帮凶”,瞄准加密货币及区块链数据库
网络·人工智能·区块链
好家伙VCC2 天前
**发散创新:基于以太坊侧链的高性能去中心化应用部署实战**在区块链生态中,*
java·python·去中心化·区块链
Joy T3 天前
【Web3】深度解析 NFT 跨链智能合约开发:原生资产与衍生包装合约架构实战
git·架构·web3·区块链·node·智能合约·hardhat
普通网友4 天前
数据加密与零知识证明在区块链中的应用解析
区块链·零知识证明
御坂100574 天前
区块链智能合约AI化:链下计算+TensorRT验证
区块链· 智能合约· tensorrt
BlockChain8884 天前
区块链入门【一】:揭开“信任机器”的神秘面纱
区块链·ai编程
QQ5110082854 天前
基于区块链的个人医疗咨询挂号信息系统vue
前端·vue.js·区块链