Skip to content

Commit

Permalink
Merge pull request #4 from avianlabs/token2022
Browse files Browse the repository at this point in the history
token2022 support
  • Loading branch information
wiyarmir authored Feb 12, 2024
2 parents 055ef05 + c579383 commit bc4fc49
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package net.avianlabs.solana.domain.core
import net.avianlabs.solana.domain.program.AssociatedTokenProgram
import net.avianlabs.solana.domain.program.SystemProgram
import net.avianlabs.solana.domain.program.TokenProgram
import net.avianlabs.solana.domain.program.TokenProgramBase
import net.avianlabs.solana.methods.TransactionResponse
import net.avianlabs.solana.vendor.decodeBase58
import net.avianlabs.solana.vendor.encodeToBase58String
Expand Down Expand Up @@ -66,7 +67,8 @@ public sealed class DecodedInstruction(
val destination: PublicKey,
val owner: PublicKey,
val amount: Long,
) : TokenProgram(net.avianlabs.solana.domain.program.TokenProgram.Instruction.Transfer.index)
) :
TokenProgram(net.avianlabs.solana.domain.program.TokenProgramBase.Instruction.Transfer.index)

public data class TransferChecked(
val source: PublicKey,
Expand All @@ -76,7 +78,7 @@ public sealed class DecodedInstruction(
val amount: Long,
val decimals: UByte,
) :
TokenProgram(net.avianlabs.solana.domain.program.TokenProgram.Instruction.TransferChecked.index)
TokenProgram(net.avianlabs.solana.domain.program.TokenProgramBase.Instruction.TransferChecked.index)
}

public sealed class AssociatedTokenProgram :
Expand Down Expand Up @@ -173,7 +175,7 @@ public fun TransactionResponse.decode(): DecodedTransaction? {
TokenProgram.programId -> {
val programIndex = buffer.readByte().toUByte()
when (programIndex) {
TokenProgram.Instruction.Transfer.index -> {
TokenProgramBase.Instruction.Transfer.index -> {
val (source, destination, owner) = accountsMeta!!
DecodedInstruction.TokenProgram.Transfer(
source = source.publicKey,
Expand All @@ -183,7 +185,7 @@ public fun TransactionResponse.decode(): DecodedTransaction? {
)
}

TokenProgram.Instruction.TransferChecked.index -> {
TokenProgramBase.Instruction.TransferChecked.index -> {
val (source, mint, destination, owner) = accountsMeta!!
DecodedInstruction.TokenProgram.TransferChecked(
source = source.publicKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,47 @@ public object AssociatedTokenProgram : Program(

public fun createAssociatedTokenAccountInstruction(
associatedProgramId: PublicKey = ASSOCIATED_TOKEN_PROGRAM_PROGRAM_ID,
programId: PublicKey = TokenProgram.programId,
programId: PublicKey,
mint: PublicKey,
associatedAccount: PublicKey,
owner: PublicKey,
payer: PublicKey,
): TransactionInstruction {
): TransactionInstruction = buildCreateAssociatedTokenAccountInstruction(
payer = payer,
associatedAccount = associatedAccount,
owner = owner,
mint = mint,
programId = programId,
associatedProgramId = associatedProgramId,
bytes = byteArrayOf(),
)

public fun createAssociatedTokenAccountInstructionIdempotent(
associatedProgramId: PublicKey = ASSOCIATED_TOKEN_PROGRAM_PROGRAM_ID,
programId: PublicKey,
mint: PublicKey,
associatedAccount: PublicKey,
owner: PublicKey,
payer: PublicKey,
): TransactionInstruction = buildCreateAssociatedTokenAccountInstruction(
payer = payer,
associatedAccount = associatedAccount,
owner = owner,
mint = mint,
programId = programId,
associatedProgramId = associatedProgramId,
bytes = byteArrayOf(1),
)

private fun buildCreateAssociatedTokenAccountInstruction(
payer: PublicKey,
associatedAccount: PublicKey,
owner: PublicKey,
mint: PublicKey,
programId: PublicKey,
associatedProgramId: PublicKey,
bytes: ByteArray,
): TransactionInstruction {
val keys = listOf(
AccountMeta(payer, isSigner = true, isWritable = true),
AccountMeta(associatedAccount, isSigner = false, isWritable = true),
Expand All @@ -33,7 +67,7 @@ public object AssociatedTokenProgram : Program(
return TransactionInstruction(
keys = keys,
programId = associatedProgramId,
data = byteArrayOf(),
data = bytes,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import net.avianlabs.solana.domain.core.PublicKey
import net.avianlabs.solana.domain.core.TransactionInstruction
import okio.Buffer

private val TOKEN_PROGRAM_ID = PublicKey.fromBase58("ComputeBudget111111111111111111111111111111")
private val COMPUTE_BUDGET_PROGRAM_ID =
PublicKey.fromBase58("ComputeBudget111111111111111111111111111111")

public object ComputeBudgetProgram : Program(
programId = TOKEN_PROGRAM_ID,
programId = COMPUTE_BUDGET_PROGRAM_ID,
) {

public enum class Instruction(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package net.avianlabs.solana.domain.program

import net.avianlabs.solana.domain.core.PublicKey
import net.avianlabs.solana.domain.core.TransactionInstruction

private val TOKEN_2022_PROGRAM_ID =
PublicKey.fromBase58("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb")

public object Token2022Program : TokenProgramBase(TOKEN_2022_PROGRAM_ID) {

public enum class Extensions(
public val index: UByte,
) {
TransferFeeExtension(26u),
ConfidentialTransferExtension(27u),
DefaultAccountStateExtension(28u),
Reallocate(29u),
MemoTransferExtension(30u),
CreateNativeMint(31u),
InitializeNonTransferableMint(32u),
InterestBearingMintExtension(33u),
CpiGuardExtension(34u),
InitializePermanentDelegate(35u),
TransferHookExtension(36u),
ConfidentialTransferFeeExtension(37u),
WithdrawalExcessLamports(38u),
MetadataPointerExtension(39u),
}

public fun createAssociatedTokenAccountInstruction(
mint: PublicKey,
associatedAccount: PublicKey,
owner: PublicKey,
payer: PublicKey,
): TransactionInstruction = AssociatedTokenProgram.createAssociatedTokenAccountInstruction(
programId = programId,
mint = mint,
associatedAccount = associatedAccount,
owner = owner,
payer = payer,
)
}
Original file line number Diff line number Diff line change
@@ -1,72 +1,22 @@
package net.avianlabs.solana.domain.program

import net.avianlabs.solana.domain.core.AccountMeta
import net.avianlabs.solana.domain.core.PublicKey
import net.avianlabs.solana.domain.core.TransactionInstruction
import okio.Buffer

private val TOKEN_PROGRAM_ID = PublicKey.fromBase58("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")

public object TokenProgram : Program(
programId = TOKEN_PROGRAM_ID
) {
public object TokenProgram : TokenProgramBase(TOKEN_PROGRAM_ID) {

public enum class Instruction(
public val index: UByte,
) {
InitializeMint(0u),
InitializeAccount(1u),
InitializeMultisig(2u),
Transfer(3u),
Approve(4u),
Revoke(5u),
SetAuthority(6u),
MintTo(7u),
Burn(8u),
CloseAccount(9u),
FreezeAccount(10u),
ThawAccount(11u),
TransferChecked(12u),
ApproveChecked(13u),
MintToChecked(14u),
BurnChecked(15u),
InitializeAccount2(16u),
SyncNative(17u),
InitializeAccount3(18u),
;
}

public fun transfer(
source: PublicKey,
destination: PublicKey,
owner: PublicKey,
amount: ULong,
): TransactionInstruction = createTransactionInstruction(
programId = programId,
keys = listOf(
AccountMeta(source, isSigner = false, isWritable = true),
AccountMeta(destination, isSigner = false, isWritable = true),
AccountMeta(owner, isSigner = true, isWritable = false),
),
data = Buffer()
.writeByte(Instruction.Transfer.index.toInt())
.writeLongLe(amount.toLong())
.readByteArray(),
)

public fun closeAccount(
account: PublicKey,
destination: PublicKey,
public fun createAssociatedTokenAccountInstruction(
mint: PublicKey,
associatedAccount: PublicKey,
owner: PublicKey,
): TransactionInstruction = createTransactionInstruction(
payer: PublicKey,
): TransactionInstruction = AssociatedTokenProgram.createAssociatedTokenAccountInstruction(
programId = programId,
keys = listOf(
AccountMeta(account, isSigner = false, isWritable = true),
AccountMeta(destination, isSigner = false, isWritable = true),
AccountMeta(owner, isSigner = false, isWritable = false),
),
data = Buffer()
.writeByte(Instruction.CloseAccount.index.toInt())
.readByteArray(),
mint = mint,
associatedAccount = associatedAccount,
owner = owner,
payer = payer,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package net.avianlabs.solana.domain.program

import net.avianlabs.solana.domain.core.AccountMeta
import net.avianlabs.solana.domain.core.PublicKey
import net.avianlabs.solana.domain.core.TransactionInstruction
import okio.Buffer

public abstract class TokenProgramBase internal constructor(
programId: PublicKey,
) : Program(
programId = programId,
) {

public enum class Instruction(
public val index: UByte,
) {
InitializeAccount(1u),
InitializeMultisig(2u),
Transfer(3u),
Approve(4u),
Revoke(5u),
SetAuthority(6u),
MintTo(7u),
Burn(8u),
CloseAccount(9u),
FreezeAccount(10u),
ThawAccount(11u),
TransferChecked(12u),
ApproveChecked(13u),
MintToChecked(14u),
BurnChecked(15u),
InitializeAccount2(16u),
SyncNative(17u),
InitializeAccount3(18u),
InitializeMultisig2(19u),
InitializeMint2(20u),
GetAccountDataSize(21u),
InitializeImmutableOwner(22u),
AmountToUiAmount(23u),
UiAmountToAmount(24u),
InitializeMintCloseAuthority(25u),
;
}

public fun transfer(
source: PublicKey,
destination: PublicKey,
owner: PublicKey,
amount: ULong,
): TransactionInstruction = createTransactionInstruction(
programId = programId,
keys = listOf(
AccountMeta(source, isSigner = false, isWritable = true),
AccountMeta(destination, isSigner = false, isWritable = true),
AccountMeta(owner, isSigner = true, isWritable = false),
),
data = Buffer()
.writeByte(Instruction.Transfer.index.toInt())
.writeLongLe(amount.toLong())
.readByteArray(),
)

public fun closeAccount(
account: PublicKey,
destination: PublicKey,
owner: PublicKey,
): TransactionInstruction = createTransactionInstruction(
programId = programId,
keys = listOf(
AccountMeta(account, isSigner = false, isWritable = true),
AccountMeta(destination, isSigner = false, isWritable = true),
AccountMeta(owner, isSigner = false, isWritable = false),
),
data = Buffer()
.writeByte(Instruction.CloseAccount.index.toInt())
.readByteArray(),
)

public fun transferChecked(
source: PublicKey,
mint: PublicKey,
destination: PublicKey,
owner: PublicKey,
amount: ULong,
decimals: UByte,
): TransactionInstruction = createTransactionInstruction(
programId = programId,
keys = listOf(
AccountMeta(source, isSigner = false, isWritable = true),
AccountMeta(mint, isSigner = false, isWritable = false),
AccountMeta(destination, isSigner = false, isWritable = true),
AccountMeta(owner, isSigner = true, isWritable = false),
),
data = Buffer()
.writeByte(Instruction.TransferChecked.index.toInt())
.writeLongLe(amount.toLong())
.writeByte(decimals.toInt())
.readByteArray(),
)
}

0 comments on commit bc4fc49

Please sign in to comment.