Solana钱包开发小记
Solana 钱包开发
这段时间,也不止Filecoin的钱包开发,还有Solana的钱包开发。
这里就不展开所有的代码讲了。有问题的可以自己联系我。
这里主要说一下功能的主要实现。
Solana根据助记词生成私钥和地址
一开始我也是看文档发现,生成私钥和地址,只需要
const bs58 = require("bs58")
const nacl = require("tweetnacl") // nacl
const bip39 = require('bip39');
const seed = bip39.mnemonicToSeedSync(mnemonic)
const keyPair = nacl.sign.keyPair.fromSeed(seed.slice(0, 32));
// 得到私钥和地址
// privateKey = bs58.encode(keyPair.secretKey)
// address = bs58.encode(keyPair.publicKey)
但是看过我上一篇filecoin文章的知道,一个助记词可以派生出很多的地址。有时候它的默认派生路径的地址不是我们想要的,这时候,我们就需要知道solana的具体network_path_code
的数字了,找到自己想要的path。example:"m/44'/501'/0'/0'"
,"m/44'/501'/0'/1'"
,甚至"m/44'/501'/0'/0'/0'"
。
const bs58 = require("bs58")
const bip39 = require('bip39');
const nacl = require("tweetnacl") // nacl
const ed25519 = require('ed25519-hd-key')
// 这里就直接取第一个地址,solana的network_path_code为501
// 举例,我们这边取的派生地址使用“m/44'/501'/0'/0'”,你也可以使用其他的派生路径
// phantom 默认就是使用的“m/44'/501'/0'/0'”
const derivePath = "m/44'/501'/0'/0'"
// 先根据助记词获取seed
const seed = bip39.mnemonicToSeedSync(mnemonic)
const derivedSeed = ed25519.derivePath(derivePath, seed.toString('hex')).key
// 得到私钥和地址
// privateKey = bs58.encode(nacl.sign.keyPair.fromSeed(derivedSeed).secretKey)
// address = bs58.encode(nacl.sign.keyPair.fromSeed(derivedSeed).publicKey)
solana的publicKey
与address
其实就是bs58
(base58)的decode
与encode
之间的转换,同理privateKey
与secretKey
也是一样的。
privateKey = bs58.encode(secretKey)
address = bs58.encode(publicKey)
Solana 发送交易
关于solana如何发送交易,这里主要还是使用了solana官方提供的js的sdk,这里仅供参考。因为自己实现的是插件钱包,所以并未对客户端发送交易这块进行实际测试。
npm install — save @solana/web3.js
然后我们建立于solana链的连接 和 Airdrop some tokens
const web3 = require('@solana/web3.js');
// 主网 mainnet-beta 测试网 devnet
const connection = new web3.Connection( web3.clusterApiUrl('devnet'), 'confirmed');
let balanace = await connection.getBalance(fromWallet.publicKey)
const fromAirdropSignature = await connection.requestAirdrop(
fromWallet.publicKey,
web3.LAMPORTS_PER_SOL, //A lamport has a value of 0.000000001 SOL.
);
// Wait for airdrop confirmation
await connection.confirmTransaction(fromAirdropSignature);
接下来,我们直接调用交易api
var transaction = new web3.Transaction().add(
web3.SystemProgram.transfer({
fromPubkey: fromWallet.publicKey,
toPubkey: toWallet.publicKey,
lamports: 1, // number of SOL to send
}),
)
// Sign transaction, broadcast, and confirm
transaction.feePayer = fromWallet.publicKey;
let blockhashObj = await connection.getRecentBlockhash();
transaction.recentBlockhash = await blockhashObj.blockhash;
// provider 其实就是我们作为钱包提供给客户端进行签名的
let signed = await provider.signTransaction(transaction)
let signature = await connection.sendRawTransaction(signed.serialize());
await connection.confirmTransaction(signature);
Solana 如何用私钥给交易签名
既然是钱包开发,我们肯定是要走完整个交易流程的,接下来,我们就来看看如何给sol的sdk提供交易签名服务。
由上文可知,我们需要提供一个provider.signTransaction
的一个方法,来给交易对象transaction
进行一个签名。
这里是如果密钥不在我们这,交给第三方进行签名的代码:
// 如果是交给第三方去签名,这里我们就需要对transaction 进行一个bs58的encode
// example
const signTransaction = (transaction) => {
const message = bs58.encode(transaction.serializeMessage())
/**
这里就是交给第三方对message进行签名,然后返回给我们
不理解signature内容的可以看下面我们自己签名的代码来查看具体的签名逻辑
return signature
**/
const signature = bs58.decode(signature);
const publicKey = fromWallet.publicKey; // 不是address,是publicKey
transaction.addSignature(publicKey, signature);
return transaction
}
但如果是我们有密钥,我们自己来签名:
const signMessage = (message) => {
const privateKey = '2m2VFti.......'
return bs58.encode(nacl.sign.detached(bs58.decode(message), bs58.decode(privateKey)))
}
const signTransaction = (transaction) => {
const message = bs58.encode(transaction.serializeMessage())
const signature = bs58.decode(signMessage(message));
/**
// 或者直接一点
// const signature = nacl.sign.detached(transaction.serializeMessage(), fromWallet.secretKey)
// 不知道secretKey 的可以看上文
**/
const publicKey = fromWallet.publicKey; // 不是address,是publicKey
transaction.addSignature(publicKey, signature);
return transaction
}
OK,这样我们就可以对transaction
签名并返回了。
其实不止signTransaction
,还有一个signAllTransactions
,参数是transactions
,是transaction
的一个数组形式。
同理,对每一个transaction进行签名,并返回一个数组。
结束,Over!
评论区