Solana区块链,对接合约操作和转账
一、 转账操作 使用 solana-web3.js 转账sol币
1.引入库
代码如下(示例):
import bs58 from 'bs58'
import np from '@/utils/number-precision'
import * as BufferLayout from 'buffer-layout'
import { TokenListProvider } from '@solana/spl-token-registry'
import {
Program, AnchorProvider,
BN
} from '@project-serum/anchor'
import {
Connection,
PublicKey,
SystemProgram,
SYSVAR_CLOCK_PUBKEY,
SYSVAR_RENT_PUBKEY,
Transaction,
sendAndConfirmTransaction,
TransactionInstruction
// LAMPORTS_PER_SOL
} from '@solana/web3.js'
import {
Token, ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID
} from '@solana/spl-token'
2.创建钱包连接connection
代码如下(示例):
const netWork ="https://api.devnet.solana.com" //开发网
const netWork ="https://api.testnet.solana.com"//测试网
const netWork = "http://solscan.rpcpool.com" //主网
this.connection = new Connection(netWork , 'recent')
3.查询账户信息并且进行sol转账操作
代码如下(示例):
async toAccounts () {
try {
const rp = await this.connection.getAccountInfo(new PublicKey(钱包地址))
// 转账
const fromPubkey = new PublicKey(转出的钱包地址)
const toPubkey = new PublicKey(转入钱包地址)
const tx = new Transaction() // 建一个交易单
// 设置交易单数据
tx.add(
SystemProgram.transfer({
fromPubkey: fromPubkey,
toPubkey: toPubkey,
lamports: this.form.lamports * Math.pow(10, 9) // lamports 是看代币单位要*多少个0
})
)
// 查找最近的区块
tx.recentBlockhash = (
await this.connection.getLatestBlockhash('max')
).blockhash
tx.feePayer = fromPubkey// 付款人
// 调用slope钱包获取签名
const slope = new window.Slope()
const { msg, data } = await slope.signTransaction(
bs58.encode(tx.serializeMessage())
)
if (msg === 'ok') {
// 给交易设置slope钱包签名
tx.addSignature(pubkey, bs58.decode(data.signature))
const txid = await this.connection.sendRawTransaction(
tx.serialize(),
bs58.decode(data.signature),
{
skipPreflight: false,
preflightCommitment: 'recent'
}
)
console.log(txid)// 交易成功返回签名地址可在https://solscan.io/查询记录
let err = await this.confirmTx(txid)
err && (err = await this.confirmTx(txid))
if (err) {
this.$message.error('Transaction failed, please try again!')
this.loading = false
return
}
}
} catch (e) {
console.log(e)
}
},
// 交易确认
async confirmTx (txid) {
try {
const cfmRp = await this.connection.confirmTransaction(txid, 'recent')
if (cfmRp.value.err !== null) {
return cfmRp.value.err
}
} catch (error) {
console.log(error)
}
},
4.其他代币转账操作
export const toAccountss = async () => {
try {
// const rp = await this.connection.getAccountInfo(new PublicKey(钱包地址))
// balances代币数据 mintAddress
const decimals = 10000000
const mint = new PublicKey('aaaaaa')
const fromPubkey = new PublicKey('aaaaaa')// 转出的钱包地址
const toPubkey = new PublicKey('aaaaaa')// 转入钱包地址
// 获取代币地址
const destinationAssociatedTokenAddress = await Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID, // 导包
TOKEN_PROGRAM_ID, // 导包
mint, // 代币mint地址
fromPubkey, // 账户地址
true
)
// 查询代币,没有就创建代币 Token.createAssociatedTokenAccountInstruction
const destination = await connection.getAccountInfo(destinationAssociatedTokenAddress)
// console.log(destination, 'destination', destinationAssociatedTokenAddress)
const tx = new Transaction() // 建一个交易单
if (!destination) {
// 给转入地址创建一个代币token
const associatedTokenAccountIx = tx.add(
Token.createAssociatedTokenAccountInstruction(
destinationAssociatedTokenAddress,
new PublicKey(fromPubkey), // 付款账户地址
new PublicKey(toPubkey), // 转入地址
new PublicKey(mint)// 代币地址
)
)
tx.add(associatedTokenAccountIx) // 插入创建代币指令
console.log(tx, '创建token账户 ')
}
// 创建交易单采用底层逻辑
const splTransferIx = await createTransferInstruction({
programId: TOKEN_PROGRAM_ID,
source: new PublicKey('aaaaaa'), // 代币账户地址
destination: destinationAssociatedTokenAddress, // 查询的代币账户地址
owner: new PublicKey(fromPubkey), // 所属人new PublicKey(puk)发送方的钱包地址
amount: new BN(1 * decimals)
})
tx.add(splTransferIx)
// 查找最近的区块
tx.recentBlockhash = (
await this.connection.getLatestBlockhash('max')
).blockhash
tx.feePayer = fromPubkey// 付款人
// 调用slope钱包获取签名
const slope = new window.Slope()
const { msg, data } = await slope.signTransaction(
bs58.encode(tx.serializeMessage())
)
if (msg === 'ok') {
// 给交易设置slope钱包签名
tx.addSignature(fromPubkey, bs58.decode(data.signature))
const txid = await this.connection.sendRawTransaction(
tx.serialize(),
bs58.decode(data.signature),
{
skipPreflight: false,
preflightCommitment: 'recent'
}
)
console.log(txid)// 交易成功返回签名地址可在查询记录
let err = await this.confirmTx(txid)
err && (err = await this.confirmTx(txid))
if (err) {
this.$message.error('Transaction failed, please try again!')
this.loading = false
return
}
}
} catch (e) {
console.log(e)
}
}
5.创建token代币交易方法
// 创建token交易
export const createTransferInstruction = async ({
programId,
source,
destination,
owner,
amount
}) => {
const multiSigners = []
const dataLayout = BufferLayout.struct([
BufferLayout.u8('instruction'),
BufferLayout.blob(8, 'amount')
])
const data = Buffer.alloc(dataLayout.span)
dataLayout.encode(
{
instruction: 3, // Transfer instruction
amount: new U64(amount).toBuffer()
},
data
)
console.log(multiSigners, 'multiSigners1')
const keys = [
{ pubkey: source, isSigner: false, isWritable: true },
{ pubkey: destination, isSigner: false, isWritable: true }
]
if (multiSigners.length === 0) {
keys.push({
pubkey: owner,
isSigner: true,
isWritable: false
})
console.log(multiSigners, 'multiSigners2', keys)
} else {
console.log(multiSigners, 'multiSigners3')
keys.push({ pubkey: owner, isSigner: false, isWritable: false })
multiSigners.forEach(signer =>
keys.push({
pubkey: signer.publicKey,
isSigner: true,
isWritable: false
})
)
}
return new TransactionInstruction({
keys,
programId: programId,
data
})
}