메인 콘텐츠로 건너뛰기

튜토리얼: 첫 번째 SAVITRI-20 토큰 배포

이 튜토리얼은 SDK를 사용하여 Savitri Network에 대체 가능 토큰을 배포하는 과정을 안내합니다.

사전 요구사항

  • 실행 중인 Savitri lightnode (자세한 내용은 빠른 시작 참조)
  • Rust 툴체인 설치
  • 자금이 있는 wallet (테스트넷 파우셋 사용)

1. 프로젝트 설정

새 Rust 프로젝트 생성:

cargo new my-savitri-token
cd my-savitri-token

Cargo.toml에 의존성 추가:

[dependencies]
savitri-sdk = { path = "../savitri-sdk" }
tokio = { version = "1", features = ["full"] }
anyhow = "1"
hex = "0.4"

2. Wallet 생성

use savitri_sdk::{Wallet, RpcClient};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Wallet 생성 또는 가져오기
let wallet = Wallet::new();
println!("Your address: {}", wallet.address());

// 로컬 노드에 연결
let client = RpcClient::from_url("http://localhost:8545")?;

// 노드 실행 확인
let health = client.health().await?;
println!("Connected to {} ({})", health.service, health.mode);

Ok(())
}

3. Wallet에 자금 충전

파우셋을 통해 테스트넷 토큰 요청:

let claim = client.faucet_claim(wallet.address()).await?;
println!("Received {} SAVT (tx: {})", claim.amount, claim.tx_hash);

// 확인 대기
tokio::time::sleep(std::time::Duration::from_secs(10)).await;

// 잔액 확인
let account = client.get_account(wallet.address()).await?;
println!("Balance: {} (nonce: {})", account.balance, account.nonce);

4. 토큰 컨트랙트 배포

토큰 배포는 to = None이고 data에 초기화 데이터가 있는 트랜잭션입니다:

use savitri_sdk::TransactionBuilder;

// 토큰 초기화 매개변수 인코딩
fn encode_token_init(name: &str, symbol: &str, initial_supply: u128) -> Vec<u8> {
let mut data = b"initialize_savitri20".to_vec();
data.push(0); // separator

// Name (length-prefixed)
data.extend_from_slice(&(name.len() as u32).to_le_bytes());
data.extend_from_slice(name.as_bytes());

// Symbol (length-prefixed)
data.extend_from_slice(&(symbol.len() as u32).to_le_bytes());
data.extend_from_slice(symbol.as_bytes());

// Initial supply (u128 LE)
data.extend_from_slice(&initial_supply.to_le_bytes());

data
}

// 배포 트랜잭션 구성
let nonce = client.get_nonce(wallet.address()).await?;

let deploy_data = encode_token_init(
"My Token", // name
"MTK", // symbol
1_000_000_000_000_000_000_000_000, // 1M tokens (18 decimals)
);

let deploy_tx = TransactionBuilder::new()
// .to() 없음 — 컨트랙트 배포를 나타냄
.data(deploy_data)
.value(0)
.nonce(nonce)
.fee(5_000_000_000_000_000) // 0.005 SAVT contract fee
.build_and_sign(&wallet)?;

println!("배포 TX 구성 완료. 컨트랙트가 파생된 주소에 생성됩니다.");

5. 토큰과 상호작용

배포 후 ContractClient를 사용하여 상호작용합니다:

use savitri_sdk::ContractClient;

let contract = ContractClient::from_url_and_wallet(
"http://localhost:8545",
wallet.clone(),
)?;

// 토큰 전송
let tx_hash = contract.call_contract(
&token_contract_address,
b"transfer",
&encode_transfer(&recipient_address, 1000_000_000_000_000_000), // 1000 tokens
Some(0),
).await?;
println!("Transfer TX: {}", tx_hash);

6. 토큰 잔액 확인

// RPC를 통해
let balance = client.call_raw(
"account_getTokenBalance",
serde_json::json!([wallet.address(), token_contract_address]),
).await?;
println!("Token balance: {}", balance);

토큰 표준 빠른 참조

표준사용 사례주요 함수
SAVITRI-20대체 가능 토큰transfer, approve, transferFrom
SAVITRI-721NFTmint, transferFrom, tokenURI
SAVITRI-1155멀티 에셋safeTransferFrom, balanceOfBatch

수수료 참조

작업수수료 (SAVT)
토큰 배포0.005
토큰 전송0.005
토큰 승인0.005
NFT 민트0.005
배치 전송0.005

금액 및 소수점

모든 Savitri 토큰은 18 소수점을 사용합니다:

1 token     = 1_000_000_000_000_000_000  (10^18)
0.001 token = 1_000_000_000_000_000 (10^15)
1M tokens = 1_000_000_000_000_000_000_000_000 (10^24)

다음 단계