Coin에서 Address Balances로 마이그레이션하기
Address Balances는 Sui 주소에 직접 연결된 대체 가능 자산을 위한 canonical balance system을 도입한다. 이는 Coin<T> 모델에 직접 주소 소유 잔액을 더해 트랜잭션 구성을 단순화하고 코인 선택 복잡성을 없앤다.
전체 사양은 SIP-58: Sui Address Balances를 참조한다. Address Balances로 자금을 보내고 인출하며 가스를 지불하는 구현 세부 사항은 Address Balances 사용하기를 참조한다.
먼저 읽기
초기 롤아웃의 영향 범위는 매우 제한적이다.
- 폐기되거나 제거되는 것은 없다. 현재 유효한 모든 트랜잭션은 계속 유효하다. 코인 객체는 Address Balances로 강제 마이그 레이션되지 않는다.
- 컨트랙트를 다시 작성할 필요가 없다. 컨트랙트는 이전처럼
Coin<T>와&mut Coin<T>를 계속 받을 수 있다. - 코인은
transfer::public_transfer또는TransferObjects명령으로 여전히 보낼 수 있다.
지갑, 거래소, 수탁 제공자에 미치는 영향
지갑(커스터디, 비커스터디 또는 거래소 지갑)을 운영하는 모든 주체는 이 변경의 영향을 받을 수 있다. 사용자는 이제 코인 객체를 전송하는 대신 send_funds()로 해당 주소에 자금을 보낼 수 있다. 지갑이 이 방식으로 자금을 받았지만 주소 잔액을 제대로 지원하지 않으면 사용자는 자금을 보거나 접근할 수 없다. 그러면 사용자는 자금이 손실되었다고 생각할 수 있다. 실제로 자금이 사라지는 것은 아니지만 영향을 받는 사용자에게 혼란을 줄 수 있다.
처음에는 생태계 대부분이 코인 객체 전송을 계속 사용할 것이므로 이런 일이 자주 발생하지는 않을 것이다. 하지만 주소 잔액 전송으로 특정 지갑에 자금이 도착하는 것을 막을 방법은 없으므로 지갑 구현자는 이에 대비하는 것이 좋다.
사용자 자금은 코인과 주소 잔액 양쪽에 나뉘어 있을 수도 있다. 잔액 쿼리(JSON-RPC, gRPC, GraphQL)는 합산 총액을 표시한다. 주소 잔액 부분이 포함된 자금을 보내려면 다음 중 하나를 사용해야 한다.
- TypeScript SDK(v2+)의
coinWithBalance를 사용한다. 이 방식은 양쪽에서 자동으로 인출한다. - Address Balances 사용하기에 설명된 수동 인출 로직을 구현한다.
잔액 쿼리 변경 사항
잔액 쿼리 응답에는 이제 코인 객체 총액과 함께 주소 잔액 정보가 포함된다.
JSON-RPC
suix_getBalance와 suix_getAllBalances 메서드는 이제 fundsInAddressBalance 필드를 반환한다. totalBalance 필드에는 코인 객체와 주소 잔액 자금이 모두 포함된다.
{
"coinType": "0x2::sui::SUI",
"coinObjectCount": 2,
"totalBalance": "99998990120",
"lockedBalance": {},
"fundsInAddressBalance": "5000000"
}
코인 기반 잔액만 얻으려면 fundsInAddressBalance에서 totalBalance를 뺀다.
gRPC
GetBalance의 ListBalances와 StateService 메서드는 이제 코인 잔액과 주소 잔액을 별도 필드로 반환한다.
coinBalance: 코인 객체에 보관된 총액.addressBalance: 주소 잔액에 보관된 금액.balance: 두 값의 합계.
{
"balance": {
"coinType": "0x2::sui::SUI",
"balance": "99998990120",
"addressBalance": "5000000",
"coinBalance": "99993990120"
}
}
GraphQL
주소 타입의 balance와 balances 필드는 이제 addressBalance, coinBalance, totalBalance 필드를 포함한다. 전체 스키마는 GraphQL Reference - IAddressable.balance를 참조한다.
체크포인트 데이터에서 잔액 계산 변경 사항
JSON-RPC 또는 gRPC가 제공하는 잔액 변경 내역을 사용하는 것이 권장된다.
체크포인트 데이터에서 잔액 변경 내역을 계산한다면 이제 코인 객체 변경분 외에도 TransactionEffects의 accumulator 이벤트를 처리해야 한다.
Sui framework는 이 과정을 위한 헬퍼를 제공한다.
use sui_types::balance_change::{derive_balance_changes, BalanceChange};
let balance_changes: Vec<BalanceChange> = derive_balance_changes(
&effects,
&input_objects,
&output_objects,
);
각 BalanceChange는 주소, 코인 타입, 부호 있는 금액(지출이면 음수, 수령이면 양수)을 포함한다.
전체 알고리즘은 참조 구현을 참조한다.
accumulator 이벤트 접근
Accumulator 이벤트는 TransactionEffects에 포함되어 있다. TransactionEffectsAPI trait로 접근한다.
use sui_types::effects::TransactionEffectsAPI;
let events = effects.accumulator_events();
각 이벤트는 대상 주소, 잔액 타입, 작업(Split은 인출, Merge는 예치), 금액을 포함한다. 전체 API는 sui-types/src/effects/mod.rs를 참조한다.
이전 버전과의 호환성
기존 컨트랙트
Coin<T> 또는 Balance<T>를 받는 컨트랙트는 변경 없이 계속 호출할 수 있다. redeem_funds 함수(sui::coin 및 sui::balance 모듈 각각)는 PTB 안에서 인출을 예상 타입으로 변환한다. 예:
inputs: [withdrawal<0x2::sui::SUI>(100)]
commands:
0: 0x2::coin::redeem_funds(inputs(0))
1: 0x2::transfer::public_transfer(result(0))
레거시 클라이언트
JSON-RPC 호환성 계층은 주소 잔액 예약을 나타내는 합성 코인 객체를 제공한다. 이 계층은 업그레이드할 수 없는 클라이언트를 위한 기본 기능을 보존하지만, 새 개발에서는 의존해서는 안 된다.
기존 코인을 Address Balances로 변환
마이그레이션은 선택 사항이다. SDK는 필요에 따라 코인 또는 주소 잔액을 자동으로 선택한다. 기존 코인 객체를 주소 잔액으로 통합하려면 사용 가이드의 기존 코인을 Address Balances로 변환을 참조한다.