Packages
signet
1.6.1
1.6.1
1.6.0
1.5.0
1.4.2
1.4.1
1.4.0
1.3.12
1.3.11
1.3.10
1.3.9
1.3.8
1.3.7
1.3.6
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.2
1.1.1
1.1.0
1.0.0-echo8
1.0.0-echo7
1.0.0-echo6
1.0.0-echo5
1.0.0-echo4
1.0.0-echo3
1.0.0-echo2
1.0.0-echo1
1.0.0-delta8
1.0.0-delta7
1.0.0-delta6
1.0.0-delta5
1.0.0-delta4
1.0.0-delta3
1.0.0-delta2
1.0.0-delta1
1.0.0-charlie9
1.0.0-charlie8
1.0.0-charlie7
1.0.0-charlie6
1.0.0-charlie5
1.0.0-charlie4
1.0.0-charlie3
1.0.0-charlie2
1.0.0-charlie1
1.0.0-beta9
1.0.0-beta8
1.0.0-beta7
1.0.0-beta6
1.0.0-beta5
1.0.0-beta4
1.0.0-beta3
1.0.0-beta2
1.0.0-beta1
1.0.0-alpha9
1.0.0-alpha8
1.0.0-alpha7
1.0.0-alpha6
1.0.0-alpha5
1.0.0-alpha4
1.0.0-alpha3
1.0.0-alpha2
1.0.0-alpha10
1.0.0-alpha1
0.2.0-alpha6
0.2.0-alpha5
0.2.0-alpha4
0.2.0-alpha1
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
0.1.0-rc7
0.1.0-rc6
0.1.0-rc5
0.1.0-rc4
0.1.0-rc3
0.1.0-rc2
0.1.0-rc1
0.1.0-rc0
Lightweight Ethereum and Solana RPC client for Elixir
Current section
Files
Jump to
Current section
Files
lib/signet/solana/ata.ex
defmodule Signet.Solana.ATA do
@moduledoc """
Associated Token Account (ATA) utilities for Solana.
An ATA is the canonical token account for a (wallet, mint) pair. It is
a PDA derived with seeds `[wallet, token_program_id, mint]` under the
Associated Token Account Program.
## Examples
iex> {pub, _} = Signet.Solana.Keys.from_seed(<<1::256>>)
iex> mint = Signet.Solana.Programs.wrapped_sol_mint()
iex> {ata, bump} = Signet.Solana.ATA.find_address(pub, mint)
iex> byte_size(ata) == 32 and bump >= 0 and bump <= 255
true
"""
alias Signet.Solana.{PDA, Programs}
alias Signet.Solana.Transaction.{Instruction, AccountMeta}
@doc """
Derive the associated token account address for a wallet + mint.
Pure computation (no RPC call). Returns `{ata_address, bump_seed}`.
## Options
- `:token_program` - Override the token program (default: SPL Token Program).
Pass `Programs.token_2022_program()` for Token-2022 mints.
"""
@spec find_address(<<_::256>>, <<_::256>>, keyword()) :: {<<_::256>>, non_neg_integer()}
def find_address(<<wallet::binary-32>>, <<mint::binary-32>>, opts \\ []) do
token_program = Keyword.get(opts, :token_program, Programs.token_program())
PDA.find_program_address!(
[wallet, token_program, mint],
Programs.ata_program()
)
end
@doc """
Build an instruction to create an ATA. Fails if it already exists.
## Options
- `:token_program` - Override the token program (default: SPL Token Program).
"""
@spec create(<<_::256>>, <<_::256>>, <<_::256>>, keyword()) :: Instruction.t()
def create(<<payer::binary-32>>, <<wallet::binary-32>>, <<mint::binary-32>>, opts \\ []) do
build_create_instruction(payer, wallet, mint, <<0>>, opts)
end
@doc """
Build an instruction to create an ATA, succeeding even if it already exists.
This is the preferred variant for most use cases - it is a no-op if the
ATA already exists.
## Options
- `:token_program` - Override the token program (default: SPL Token Program).
"""
@spec create_idempotent(<<_::256>>, <<_::256>>, <<_::256>>, keyword()) :: Instruction.t()
def create_idempotent(
<<payer::binary-32>>,
<<wallet::binary-32>>,
<<mint::binary-32>>,
opts \\ []
) do
build_create_instruction(payer, wallet, mint, <<1>>, opts)
end
# data is the ATA program instruction index:
# <<0>> = Create (fails if ATA already exists)
# <<1>> = CreateIdempotent (no-op if ATA already exists)
defp build_create_instruction(payer, wallet, mint, data, opts) do
token_program = Keyword.get(opts, :token_program, Programs.token_program())
{ata, _bump} = find_address(wallet, mint, opts)
%Instruction{
program_id: Programs.ata_program(),
accounts: [
%AccountMeta{pubkey: payer, is_signer: true, is_writable: true},
%AccountMeta{pubkey: ata, is_signer: false, is_writable: true},
%AccountMeta{pubkey: wallet, is_signer: false, is_writable: false},
%AccountMeta{pubkey: mint, is_signer: false, is_writable: false},
%AccountMeta{pubkey: Programs.system_program(), is_signer: false, is_writable: false},
%AccountMeta{pubkey: token_program, is_signer: false, is_writable: false}
],
data: data
}
end
end