트랜잭션 구성 및 전송
TransactionBuilder는 Savitri Network에 트랜잭션을 구성, 서명, 전송하기 위한 플루언트 API를 제공합니다.
단순 전송
use savitri_sdk::{Wallet, TransactionBuilder, RpcClient};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = RpcClient::from_url("http://localhost:8545")?;
let wallet = Wallet::from_private_key_hex("your_private_key_hex")?;
// Get current nonce
let nonce = client.get_nonce(wallet.address()).await?;
// Build and sign
let signed_tx = TransactionBuilder::new()
.to("recipient_address_64hex")
.value(1_000_000_000_000_000_000) // 1 SAVT (18 decimals)
.nonce(nonce)
.fee(1_000_000_000_000_000) // 0.001 SAVT fee
.build_and_sign(&wallet)?;
// Submit
let result = client.send_raw_transaction(&serialize_tx(&signed_tx)).await?;
println!("TX hash: {}", result.tx_hash);
Ok(())
}
빌더 API
필수 필드
| 메서드 | 유형 | 설명 |
|---|---|---|
.from(address) | String | 발신자 주소 (생략 시 wallet에서 자동 설정) |
.to(address) | String | 수신자 주소 |
.value(amount) | u128 | 최소 단위 전송 금액 |
선택적 필드
| 메서드 | 유형 | 기본값 | 설명 |
|---|---|---|---|
.nonce(n) | u64 | 0 | 트랜잭션 논스 (get_nonce()로 조회) |
.fee(f) | u128 | 없음 | 트랜잭션 수수료 |
.data(bytes) | Vec<u8> | 없음 | 컨트랙트 호출을 위한 페이로드 |
서명 없이 구성
let unsigned = TransactionBuilder::new()
.from("sender_address")
.to("recipient_address")
.value(1000)
.nonce(5)
.build()?;
// unsigned.from, unsigned.to, unsigned.value, unsigned.nonce, unsigned.fee, unsigned.data
구성 및 서명
let signed = TransactionBuilder::new()
.to("recipient_address")
.value(1000)
.nonce(5)
.fee(100)
.build_and_sign(&wallet)?;
// signed.transaction -- the UnsignedTransaction
// signed.public_key -- 32-byte ed25519 public key
// signed.signature -- 64-byte ed25519 signature
.from()을 호출하지 않으면 wallet 주소가 자동으로 사용됩니다.
오라클 호출
let signed = TransactionBuilder::new()
.oracle_call(
"oracle_contract_address",
"request_data",
b"temperature_sensor_01",
)
.value(0)
.nonce(nonce)
.build_and_sign(&wallet)?;
거버넌스 호출
제안에 투표
use savitri_sdk::GovernanceAction;
let signed = TransactionBuilder::new()
.governance_call(
"governance_contract_address",
proposal_id, // u64
GovernanceAction::Vote(true), // true = support, false = oppose
)
.nonce(nonce)
.build_and_sign(&wallet)?;
승인된 제안 실행
let signed = TransactionBuilder::new()
.governance_call(
"governance_contract_address",
proposal_id,
GovernanceAction::Execute,
)
.nonce(nonce)
.build_and_sign(&wallet)?;
FL 제안 생성
let signed = TransactionBuilder::new()
.create_fl_proposal(
"governance_contract_address",
"Upgrade model v2", // title
"Replace BERT with GPT-4", // description
604800, // voting period in seconds (7 days)
)
.nonce(nonce)
.build_and_sign(&wallet)?;
트랜잭션 서명 형식
서명 메시지는 다음과 같이 구성됩니다:
from_hex_bytes || to_hex_bytes || amount_le_u64 || nonce_le_u64 || fee_le_u128
이후 SHA-256으로 해시되고, 해시값이 Ed25519로 서명됩니다.
이 형식은 savitri-rpc의 서버측 검증과 일치합니다.
금액 및 소수점
모든 금액은 18 소수점을 사용합니다:
| 표시 금액 | 원시 값 |
|---|---|
| 1 SAVT | 1_000_000_000_000_000_000 |
| 0.1 SAVT | 100_000_000_000_000_000 |
| 0.001 SAVT | 1_000_000_000_000_000 |
| 0.00001 SAVT | 10_000_000_000_000 |
수수료 참조
| 트랜잭션 유형 | 수수료 (SAVT) | 원시 값 |
|---|---|---|
| 일반 전송 | 0.001 | 1_000_000_000_000_000 |
| 컨트랙트 호출 | 0.005 | 5_000_000_000_000_000 |
| IoT 데이터 | 0.00005 | 50_000_000_000_000 |