본문으로 건너뛰기

잔액 및 자산 쿼리

Permissioned Asset Standard (PAS)는 SDK에서 dedicated read API를 노출하지 않는다. 이는 의도된 설계다. PAS는 deterministic 주소가 있는 표준 Sui 객체에 자산을 저장하므로, 다른 주소 소유 data(예: 잔액 쿼리와 소유 객체 쿼리)에 사용하는 동일한 RPC method로 조회한다.

Sui의 지갑 주소는 두 종류의 잔액을 보유할 수 있다.

  • 일반 잔액: 지갑 주소가 직접 소유한다.

  • PAS 잔액: 지갑 주소를 대신해 PAS가 관리한다.

사용자 관점에서는 둘 다 같은 주소에 속한다. PAS 잔액은 derived Account 객체에 보관되지만, transfer는 항상 Account 주소가 아니라 지갑 주소를 대상으로 한다. SDK는 underlying Account를 투명하게 해결한다.

PAS 잔액 쿼리​

지갑의 PAS 잔액을 읽으려면 PAS SDK를 사용해 지갑 주소에서 internal Account 주소를 derive한 다음(derivation은 deterministic), core SDK 잔액 method로 쿼리한다.

다음 diagram은 derivation flow를 보여준다.

Wallet Address (for example, 0xAlice)
│
▼
┌──────────────────────────────┐
│ client.pas │
│ .deriveAccountAddress( │
│ '0xAlice' │
│ ) │
└──────────────────────────────┘
│
▼
Account Address (deterministic, same every time)

derived 주소는 network마다(Mainnet과 Testnet) 다르다. PAS namespace 객체가 각 network에서 다른 ID를 갖기 때문이다. SDK는 클라이언트 network configuration을 기반으로 이를 처리한다.

다음 예시는 일반 잔액과 PAS 관리 잔액을 모두 쿼리하는 방법을 보여준다.

import { SuiGrpcClient } from '@mysten/sui/grpc';
import { pas } from '@mysten/pas';
const client = new SuiGrpcClient({ network: 'testnet' }).$extend(pas());
const walletAddress = '0xAlice';
// Regular balances — query the wallet address directly
const regularBalances = await client.core.getAllBalances({
owner: walletAddress,
});
// PAS-managed balances — derive the Account address, then query it
const pasBalances = await client.core.getAllBalances({
owner: client.pas.deriveAccountAddress(walletAddress),
});
// Single asset type
const { balance } = await client.core.getBalance({
owner: client.pas.deriveAccountAddress(walletAddress),
coinType: '0xabc...::my_coin::MY_COIN',
});

지갑에 PAS Account가 있는지 확인​

derived 주소에 대해 getObject가 null을 반환하면 지갑에는 아직 PAS Account가 없다.

const { object } = await client.core.getObject({ objectId: accountAddress });
if (!object) {
// No PAS account
}

Account의 non-정책 자산​

Account는 PAS 정책이 관리하지 않는 자산 type도 보유할 수 있다. 예를 들어 direct Balance<SUI> call을 통해 balance::send_funds가 Account에 들어갈 수 있다. getAllBalances를 호출하면 이런 잔액은 정책-managed 자산과 함께 표시된다.

핵심 사항​

  • Wallet 중심: PAS 잔액은 지갑 주소에 속한다. Account는 SDK가 처리하는 내부 detail이다.
  • Deterministic: 같은 지갑 주소는 항상 같은 Account로 해결된다.
  • 표준 RPC: getBalance와 getAllBalances는 derived 주소에서 동작한다. custom endpoint가 필요하지 않다.
  • Indexing 불필요: derivation은 클라이언트-side에서 수행된다. event subscription이나 custom indexer가 필요하지 않다.