火币是世界领先的数字货币交易平台,你可以买卖交易BTC/ETH/HT 等数字货币,投资现货和合约市场,或质押代币获得收益。立即注册HTX,开始加密货币交易之旅!


Web3新手系列:探索使用Solana Token登录

NFT (non-fungible token) 作为一个正如其名字所指的“不可替代”的代币,非常适合用于作为一种身份认证工具。

接下来,让我们通过一个简单的例子,来探索一下使用 NFT 作为注册凭证的可行性。

SPL Token

我们可以自己从零开始编写新的 Solana 合约,不过对于我们目前想要达到的目的来说,可以直接使用 Solana 提供的通用实现:Token Program。

Token Program 属于 Solana Program Library(SPL,https://spl.solana.com/)的一部分,SPL 中提供了包括 Token、Swap、Memo 的多个常用程序实现,并且提供了完善的客户端库、CLI 等工具,极大的方便了 Solana 开发者。

Token Program 的项目源码位于:https://github.com/solana-labs/solana-program-library/tree/master/token/program

Web3新手系列:探索使用Solana Token登录

会输出下面的日志:

Web3新手系列:探索使用Solana Token登录

其中的 69yXraTu3FqXZkATg6MiRnWT2qHd4tRzWsfCHHE9j2XE 经常会被称作 Mint Address,也是我们所创建的 Token 的 ID。

Token 地址为:

https://solscan.io/token/69yXraTu3FqXZkATg6MiRnWT2qHd4tRzWsfCHHE9j2XE?cluster=devnet

Web3新手系列:探索使用Solana Token登录

Web3新手系列:探索使用Solana Token登录

会输出下面的日志:

Web3新手系列:探索使用Solana Token登录

或者也可以:

Web3新手系列:探索使用Solana Token登录

也可以尝试一下 mint 其他数值,例如 1.9 :

Web3新手系列:探索使用Solana Token登录

查看交易详情,会发现:由于我们在第一步创建 Token 时指定「 –decimals 」为 0 ,所以实际执行 mint 时,会舍去小数部分,于是 mint 的量将依然是 1 。

也可以尝试一下直接给一个钱包地址 mint token,这里使用 4wztJ4CAH4GbAUopZrVk7nLvoAC3KAF6ttMMWfnBRG1t 来演示:

Web3新手系列:探索使用Solana Token登录

  • Token 我们直接使用上面的 69yXraTu3FqXZkATg6MiRnWT2qHd4tRzWsfCHHE9j2XE

  • Wallet Address:使用 4wztJ4CAH4GbAUopZrVk7nLvoAC3KAF6ttMMWfnBRG1t

  • 但我们直接简单的替换参数的时,却会得到意外的结果:

    Web3新手系列:探索使用Solana Token登录

    地址是存在的,只是 Mint 所需要的地址并不是原始的钱包地址,而是需要与之关联的 Token Account。

    我们需要进行与上面相同的流程:给钱包地址创建 Token Account,然后使用创建出的 Token Account mint 新的 Token unit。

    换句话说,如果我们想要为某个钱包地址铸造一个 Token unit,那么我们就必须先为这个钱包地址创建一个 Token Account。至于为什么需要这样做,其中一个原因是我们并没有权限直接修改某个地址的数据。

    在 Solana 的文档中,有时候你会分别看到两个相似的概念:代币账户(Token Account)和 关联代币账户(Associated Token Account,ATA)。文档中看起来两者似乎有些关联,但是却并没有说明这一点,这非常让人困惑。

    不过如果你查看 Metaplex 的文档,就会发现它很明确的指出:“关联代币账户,有时会被简称为代币账户”。

    我们这里不对这两者进行深入研究,只需要想象代币账户是代币和钱包地址之间的媒介。

    我们使用下面的命令,为钱包地址创建一个 Token Account:

    Web3新手系列:探索使用Solana Token登录

    重复创建将会报错:

    Web3新手系列:探索使用Solana Token登录

    在日志中也能看出,由确定的 Mint Account 和 钱包地址派生出的 Token Account 是确定的(3JocyxV4LX4VbNU248CvNozZphgRW5JTyxn7FPWrF8bx),只是由于已经存在了,所以才打印了错误信息。

    Web3新手系列:探索使用Solana Token登录

    你需要将「 _YOUR_RPC_PROVIDER_ 」替换为你自己选择的 RPC 供应商提供的地址。

    可以使用 Solana 官方提供的地址,或者,可以在这里找到公共的免费 RPC 网络:https://zan.top/service/public-rpc/solana

    注意:公共地址可能不稳定,如果需要稳定的 RPC 服务,建议创建自己的 API Key。

    对于上面的钱包地址来说,具体就是这样:

    Web3新手系列:探索使用Solana Token登录

    除了通过代码手动填充请求参数之外,也可以使用 @solana/web3.js 中提供的 Connection 上的「 getParsedTokenAccountsByOwner 」方法,其内部实际上就是通过创建 Connection 时提供的 RPC 接口调用了「 getParsedTokenAccountsByOwner 」method。

    如果是一个已经创建过 Account Token 的钱包,则会返回:

    Web3新手系列:探索使用Solana Token登录

    删掉了对我们无用的数据

    实现

    通过上面的尝试,可知我们能够使用现有的能力实现我们想要的功能。那么接下来,就开始编写客户端代码。

    以下代码都在 https://github.com/gin-lsl/my-sol-token-auth-example

    可以在这里预览:https://my-sol-token-auth-example.vercel.app/

    我会通过创建一个简单的 Nextjs 项目来实现它,使用 Ant Design Web3 来 Connect Wallet:

    初始化 Nextjs 项目

    Web3新手系列:探索使用Solana Token登录

    所有选项均使用默认值:

    Web3新手系列:探索使用Solana Token登录

    为了快速开始,我们直接使用 @ant-design/web3-solana 来连接钱包,使用 @solana/spl-token 和 Token Program 交互。

    添加相关的依赖:

    Web3新手系列:探索使用Solana Token登录

    我们需要包括首页的 3 个页面,创建 app/sign-in/page.tsx 和 app/sign-on/page.tsx。它们分别用于连接钱包并检查用户是否已经注册(是否 mint NFT),以及让用户进行注册流程(mint NFT)。

    打开演示页面后,首先看到的是欢迎语,以及前往 Sign in 页面的链接:

    Web3新手系列:探索使用Solana Token登录

    进入页面后,您需要先去 Sign in:

    点击「Continue with Solana」,将会唤起钱包

    Web3新手系列:探索使用Solana Token登录

    而如果你之前并没有注册,则会提示你先去注册:

    Web3新手系列:探索使用Solana Token登录

    这是因为在 /api/sign-in 的逻辑中,会根据连接的钱包地址查找关联的 Token Account。由于我们之前并没有使用过,所以自然找不到数据,于是系统就会认为这个钱包地址并没有注册过。

    然后我们按照提示,来到 Sign on 页面,注册页面与登录页面大体上类似,只是在服务端的处理逻辑不同:

    其实可以将两个逻辑合并,这里分开只是为了便于演示。

    Web3新手系列:探索使用Solana Token登录

    无论如何,让我们点击「Start with Solana」,连接钱包。然后,如果顺利的话,会看到成功的提示:

    Web3新手系列:探索使用Solana Token登录

    让我们来到 Solscan 中,看看发生了什么。进入 https://solscan.io/?cluster=devnet,查询你的钱包地址。或者,也可以查看这个地址:79reVF46NyuuH7PADR3i6RpQ7hmBZgYkiieXNYPM1oLF

    有一条交易数据:

    Web3新手系列:探索使用Solana Token登录

    注意在 Instructions 中,能看出交易内部执行了 CreateAccount 指令,点击链接进入详情,会发现它所创建的就是一个 TokenAccount:EXfDYkHw3UQw2VqiSLsRAfLMsxkgqnd3nhxbB4V5HAvA。其中的 isOnCurve 值为 False,表明是一个没有私钥的关联账户。

    回到之前的页面,转到 Portfolio -> NFTs,就能看到我们刚才在 sign-on 内部所做的 Mint 操作,以及 Mint 的那个 NFT:

    @zan_team)的 gin-lsl 撰写。