Skip to content

Instantly share code, notes, and snippets.

@LanfordCai
Last active April 9, 2024 16:52
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save LanfordCai/324c7ea81530680972bcbfb54d7c56e5 to your computer and use it in GitHub Desktop.
Save LanfordCai/324c7ea81530680972bcbfb54d7c56e5 to your computer and use it in GitHub Desktop.
Solana Batch Transfer
'use strict'
const web3 = require('@solana/web3.js')
const splToken = require('@solana/spl-token')
const bs = require('bs58')
const connection = new web3.Connection(
web3.clusterApiUrl('devnet'),
'confirmed',
)
main()
async function main() {
let secret = 'YOUR_SECRET_KEY'
let sender = web3.Keypair.fromSecretKey(Uint8Array.from(bs.decode(secret)))
console.log(sender.publicKey.toBase58())
let transfers = [
{recipient: new web3.PublicKey('YOUR_RECIPIENT_1'), value: 0.1},
{recipient: new web3.PublicKey('YOUR_RECIPIENT_2'), value: 0.2}
]
let tx = await buildSolBatchTransferTx(sender, transfers)
let signature = await web3.sendAndConfirmTransaction(
connection,
tx,
[sender]
)
console.log('SIGNATURE', signature)
let tokenInfo = await getTokenInfo(connection, sender, 'YOUR_TOKEN_MINT')
let splTransfers = [
{recipient: new web3.PublicKey('YOUR_RECIPIENT_1'), value: 0.1},
{recipient: new web3.PublicKey('YOUR_RECIPIENT_1'), value: 0.2},
{recipient: new web3.PublicKey('YOUR_RECIPIENT_2'), value: 0.3}
]
let splTx = await buildSplTokenBatchTransferTx(connection, sender, tokenInfo, splTransfers)
let splSignature = await web3.sendAndConfirmTransaction(
connection,
splTx,
[sender]
)
console.log('SPL_SIGNATURE', splSignature)
}
async function buildSolBatchTransferTx(sender, transfers) {
let transaction = new web3.Transaction()
for (let i = 0; i < transfers.length; i++) {
let transfer = transfers[i]
transaction = transaction.add(
web3.SystemProgram.transfer({
fromPubkey: sender.publicKey,
toPubkey: transfer.recipient,
lamports: transfer.value * web3.LAMPORTS_PER_SOL,
})
)
}
return transaction
}
async function buildSplTokenBatchTransferTx(connection, sender, tokenInfo, transfers) {
let token = tokenInfo.token
let senderTokenAccount = await token.getOrCreateAssociatedAccountInfo(sender.publicKey)
let transferedRecipients = {}
let transaction = new web3.Transaction()
for (var i = 0; i < transfers.length; i++) {
let transfer = transfers[i]
let recipient = transfer.recipient
let amount = transfer.value * Math.pow(10, tokenInfo.decimals)
let aTokenAddress =
await getAssociatedTokenAddress(connection, recipient, token.publicKey) ||
transferedRecipients[recipient]
if (aTokenAddress) {
transaction = transaction.add(
splToken.Token.createTransferInstruction(
splToken.TOKEN_PROGRAM_ID,
senderTokenAccount.address,
aTokenAddress,
sender.publicKey,
[],
amount
)
)
} else {
aTokenAddress = await calcAssociatedTokenAddress(recipient, token.publicKey)
transaction = transaction.add(
splToken.Token.createAssociatedTokenAccountInstruction(
splToken.ASSOCIATED_TOKEN_PROGRAM_ID,
splToken.TOKEN_PROGRAM_ID,
token.publicKey,
aTokenAddress,
recipient,
sender.publicKey
),
splToken.Token.createTransferInstruction(
splToken.TOKEN_PROGRAM_ID,
senderTokenAccount.address,
aTokenAddress,
sender.publicKey,
[],
amount
)
)
}
transferedRecipients[recipient] = aTokenAddress
}
return transaction
}
// Helpers
async function getTokenInfo(connection, sender, tokenContractAddress) {
const tokenMint = new web3.PublicKey(tokenContractAddress)
const token = new splToken.Token(connection, tokenMint, splToken.TOKEN_PROGRAM_ID, sender)
const decimals = (await token.getMintInfo()).decimals
return {token: token, decimals: decimals}
}
async function getAssociatedTokenAddress(connection, address, tokenMint) {
const result = await connection.getTokenAccountsByOwner(address, {'mint': tokenMint}, {commitment: 'confirmed'})
if (result.value.length == 0) {
return null
}
return result.value[0].pubkey
}
async function calcAssociatedTokenAddress(address, tokenMint) {
return (await web3.PublicKey.findProgramAddress(
[
address.toBuffer(),
splToken.TOKEN_PROGRAM_ID.toBuffer(),
tokenMint.toBuffer()
],
splToken.ASSOCIATED_TOKEN_PROGRAM_ID
))[0]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment