카테고리 없음

Solana SPL Token

https.. 2026. 1. 16. 15:44

Solana SPL Token

SPL Token: Solana 블록체인에서 사용되는 표준 토큰 프로그램(Token Program)

이더리움의 ERC-20과 유사하지만, Solana는 컨트랙트가 아닌 Program + Account 모델을 사용한다.

 

Solana의 계정 모델

Solan에서 Walle은 토큰 잔액을 직접 저장하지 않는다.

Solana의 모든 상태(state) Account에 저장되며, Account는 항상 특정 Program(owner) 에 의해 관리된다. SPL Token의 잔액은 (wallet, mint) 쌍에 대해 1개만 존재하는Associated Token Account(ATA)에 저장된다.

 

ATA(Associated Token Account) – SPL Token의 실제 잔액을 저장하는 계정

-      PDA(Program Derived Address)의 한 종류이다.

-      Token programAccount.owner이다.

-      ATAdata에는 토큰 소유자 주소(wallet), mint 주소, 잔액(amount)가 포함된다.

-      (wallet, mint) 기준으로 1개만 존재한다.

 

PDA(Program Derived Address)

-      개인키가 없는 주소이다.

-      사용자가 직접 서명할 수 없다.

-      Program만이 seed + bump를 통해 권한을 행사한다.

-      프로그램 전용 계정에 사용된다.

 

PA(Program-owned Account)

-      특정 Programowner로 설정된 계정

-      Program이 해당 accountdata를 수정할 수 있다.

-      SPL TokenMint, Token Account 모두 해당된다.

 

Mint 계정(토큰 자체): 토큰의 종류를 정의하는 계정

-      개별 사용자 잔액을 저장하지 않는다.

-      Mint 계정이 관리하는 것

n   총 발행량(supply)

n   소수점 자리수(decimals)

n   발행 권한(Mint Authority)

n   동결 권한(Freeze Authority)

 

토큰 전송 구조

SPL Token 전송은 ATA – ATA 사이에서만 발생한다.

수신자의 ATA가 없으면 --fund-recipient를 통한 자동 생성 또는 실패한다.

 

Solana SPL Token 발행, 지갑 간 전송 실습

1. Solana CLI 설치

# 설치
curl -LO https://github.com/solana-labs/solana/releases/latest/download/solana-release-aarch64-apple-darwin.tar.bz2
 
# 압축 해제
tar -xjf solana-release-*.tar.bz2
 
# Solana CLI 실행 파일 경로를 PATH에 추가
echo 'export PATH="$PWD/solana-release/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

 

2. Rust 설치 (SPL Token CLI 빌드용)

# Rust 설치
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
 
# 환경 변수 설정
source "$HOME/.cargo/env"

 

3. SPL Token CLI 설치

cargo install spl-token-cli

 

4. Solana 네트워크를 Devnet으로 설정

# 테스트용 Devnet 사용
solana config set --url https://api.devnet.solana.com
 
# 설정 확인
solana config get

 

# 결과
Config File: /Users/user/.config/solana/cli/config.yml
RPC URL: https://api.devnet.solana.com
WebSocket URL: wss://api.devnet.solana.com/ (computed)
Keypair Path: /Users/user/.config/solana/id.json
Commitment: confirmed

 

5. 지갑 A 생성(발행자/최초 보유자)

solana-keygen new -o ~/walletA.json

 

# 결과
Wrote new keypair to /Users/user/walletA.json
==================================================================================
pubkey: AttaoJLVRvFVRnAuncKUFSnfJuSvTrxMBYACeLkUfHCx
==================================================================================
Save this seed phrase and your BIP39 passphrase to recover your new keypair:
ivory curve protect rabbit wreck fashion photo until cousin punch blanket describe
==================================================================================

 

# 지갑 A의 주소 확인
solana address -k ~/walletA.json

 

# 결과

AttaoJLVRvFVRnAuncKUFSnfJuSvTrxMBYACeLkUfHCx

 

# 지갑 A를 CLI 기본 지갑으로 설정
solana config set --keypair ~/walletA.json

 

# 결과
Config File: /Users/user/.config/solana/cli/config.yml
RPC URL: https://api.devnet.solana.com
WebSocket URL: wss://api.devnet.solana.com/ (computed)
Keypair Path: /Users/user/walletA.json
Commitment: confirmed

 

 

# 지갑 A에 SOL 에어드롭
solana airdrop 2
 
# 확인
solana balance

 

 

 

6. SPL 토큰(Mint) 주소 생성 – 1번만 수행

spl-token create-token

 

# 결과
Creating token CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT under program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
 
Address:  CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT
Decimals:  9
 
Signature: 3mBHvLYeCb3gyG6paFHBYtFBwQB56eVgcQwtert8W49fVhfBK2KaEs1xSe386DRD5uqY9jxtjTUAzQoz33pcrX1X
 

 

 

7. 지갑 A의 토큰 계정 주소 ATA 생성(Mint 1개 생성)

# 지갑 A의 ATA 계정 생성
spl-token create-account CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT

 

# 결과
Creating account 8x5LQQraaQKagEZ6SWU5c9SNB6aDv4khLUM1jxPuQBgA
 
Signature: 4remehCPutZD7gzmvmKYzb5qxhHMCYSDkNxd82nr4RPX94gm62FtCProYU8NSQK73ub84dtaJejWvtyfhHzpcZ3A

 

 

8. 지갑 A에게 토큰 민트

spl-token mint \
CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT \
100

 

# 결과
Minting 100 tokens
  Token: CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT
  Recipient: 8x5LQQraaQKagEZ6SWU5c9SNB6aDv4khLUM1jxPuQBgA
 
Signature: 3SuVSz72Em4TFbcth9NYLz3dVydpn39QgqosURyjfqR7VDtPDH74GbR2qZBKi7hxokGSDAZSKE64RKRbsLyaWu76

 

 

9. 토큰 민트 잔액 확인

# 지갑 A가 가진 토큰
spl-token balance CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT
 
# 전체 발행량
spl-token supply CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT

 

10. 지갑 B 생성(받는 사람)

# 지갑 생성
solana-keygen new -o ~/walletB.json

 

# 결과
Wrote new keypair to /Users/user/walletB.json
========================================================================
pubkey: 4iFQvwMyaMdhfzD64jufDPMW58ofHr69MGzBJuFZdVxy
========================================================================
Save this seed phrase and your BIP39 passphrase to recover your new keypair:
enrich ice news asthma inner various top recipe guard diamond ahead idle
========================================================================

 

# 지갑 B 주소 확인
solana address -k ~/walletB.json
 
# 지갑 B도 SOL 받음
solana airdrop 1 $(solana address -k ~/walletB.json)

 

>> 지갑 B SOL airdrop 되지 않는 경우

#1 https://faucet.solana.com/ 에서 SOL 받기
 
#2 https://solfaucet.com/ 에서 SOL 받기
 
#3 지갑 A에서 지갑 B에 SOL 보내기
solana transfer \
  $(solana address -k ~/walletB.json) \
  0.05 \
  --from ~/walletA.json \
--allow-unfunded-recipient
 
# 지갑 B의 SOL 잔액 확인
solana balance $(solana address -k ~/walletB.json)

 

 

11. 지갑 A → 지갑 B 토큰 23개 전송 (ATA 자동 생성)

# 지갑 B ATA 자동 생성과 토큰 23 전송
spl-token transfer \
 CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT \
 23 \
 $(solana address -k ~/walletB.json) \
 --owner ~/walletA.json \
 --fund-recipient

 

# 결과
Transfer 23 tokens
  Sender: 8x5LQQraaQKagEZ6SWU5c9SNB6aDv4khLUM1jxPuQBgA
  Recipient: 4iFQvwMyaMdhfzD64jufDPMW58ofHr69MGzBJuFZdVxy
  Recipient associated token account: 5AkJxpQFPX5G8mB4T1dnrLowsNzSSLuGBqxiNUM5CcKX
  Funding recipient: 5AkJxpQFPX5G8mB4T1dnrLowsNzSSLuGBqxiNUM5CcKX
 
Signature: sthsJufFDrTBY3i1PnYNgrkGvZbf7cVDVTyFZgR6ztqobwUizqbk1cBXQG3BapxsZUs2sDikRL1FVdW2cGrwoG5

 

12. 지갑 B → 지갑 A로 토큰 6개 전송

spl-token transfer \
 CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT \
 6 \
 $(solana address -k ~/walletA.json) \
 --owner ~/walletB.json

 

# 결과
Transfer 6 tokens
  Sender: 5AkJxpQFPX5G8mB4T1dnrLowsNzSSLuGBqxiNUM5CcKX
  Recipient: AttaoJLVRvFVRnAuncKUFSnfJuSvTrxMBYACeLkUfHCx
  Recipient associated token account: 8x5LQQraaQKagEZ6SWU5c9SNB6aDv4khLUM1jxPuQBgA
 
Signature: 2FYFXiGU1E2rLaw5RwDLRRfviSZ3yhDuoLa6r8k8vxL4TVSNRmwMa15vVb1YjGNeGoPdAPtZ9z82H9rwfiwkiKZa

 

13. 각 지갑의 토큰 계정 확인

# 지갑 A
spl-token accounts --owner $(solana address -k ~/walletA.json)
 
# 지갑 B
spl-token accounts --owner $(solana address -k ~/walletB.json)

 

# 지갑 A 결과
Token                                         Balance
-----------------------------------------------------
CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT  83
 
# 지갑 B 결과
Token                                         Balance
-----------------------------------------------------
CfjWNEwbscKUNusDtvphhgEx34NyRtEUc2QnVguS9rRT  17

 

 

 

Phantom에 지갑 가져오기(import)

Phantom CLI에서 만든 keypair(json) 을 그대로 가져올 수 있다.

Phantom 열기 > 설정 > 계정 관리 > 계정 추가 > 비공개 가져오기

cat ~/walletA.json

 

# 결과[227,193,251,43,42,184,107,31,120,202,131,234,78,51,247,6,93,4,71,68,136,254,32,142,16,106,182,190,162,145,254,111,147,4,32,221,82,218,169,191,255,247,171,176,77,237,223,208,85,248,111,118,248,97,185,238,181,178,239,72,78,146,53,181]

 

cat ~/walletB.json

 

# 결과
[119,176,24,129,248,16,85,85,183,231,143,250,249,47,251,104,96,176,15,18,155,129,59,31,240,155,162,39,12,249,206,240,55,36,43,153,168,152,236,172,74,45,132,222,74,44,12,68,65,117,243,240,64,85,94,238,252,239,113,208,136,2,98,126]

 

>> 숫자 배열 전체를 복사하여 비공개 입력칸에 붙여넣기