스케일드 UI 금액 통합 가이드

Solana에서 스케일드 UI 금액 확장 지원하기

배경

스케일드 UI 금액 확장은 토큰 발행자가 사용자의 토큰 잔액의 UI 금액을 계산할 때 사용할 승수를 지정할 수 있게 해줍니다. 이를 통해 발행자는 리베이싱 토큰을 생성하고 주식 분할과 같은 기능을 활성화할 수 있습니다. 이 확장 기능은 이자 발생 토큰 확장과 마찬가지로 순전히 시각적인 UI 금액을 제공하므로 팀은 좋은 사용자 경험을 제공하기 위해 추가 작업을 수행해야 합니다. 기본 계산 및 전송은 모두 프로그램에서 원시 금액을 사용하여 이루어집니다.

리소스:

요약

  • 최종 사용자는 가능한 한 토큰 가격, 토큰 잔액 및 토큰 금액에 대해 UIAmount(원시 금액 * 승수)와 상호 작용해야 합니다
  • dApp 및 서비스 제공업체는 모든 계산에 원시 금액과 스케일링되지 않은 가격을 사용하고 사용자 인터페이스에서 변환해야 합니다
  • 더 쉬운 통합을 위해 스케일링된 금액과 스케일링되지 않은 금액 모두에 대한 과거 가격 피드를 제공해야 합니다
  • 정확한 과거 데이터를 위해 과거 승수 값에 접근할 수 있어야 합니다

용어 정의

  • 승수: UI 금액 계산에 사용되는 정적 업데이트 가능한 승수
  • UIAmount: 승수 * 원시 금액 (일명: 스케일링된 금액)
  • 원시 금액: 금액 (일명: 스케일링되지 않은 금액)

현재 잔액

표시용 현재 금액

  • 스케일드 UI 금액 확장을 사용하는 토큰의 금액을 최종 사용자에게 표시할 때마다 다음 중 하나를 사용해야 합니다:
    • UIAmount/UIAmountString (권장)
    • 원시 금액 * 승수의 수동 계산
    • 토큰이 가진 소수점 자릿수에 따라 이 값을 잘라내는 것을 권장합니다.
      • 예: yUSD가 6자리 소수점을 가지고 있고 사용자의 UIAmount가 1.123456789인 경우 "1.123456"으로 표시해야 합니다

이 데이터를 얻을 수 있는 곳:

  • 사용자의 실시간 잔액에 대한 위 금액의 업데이트된 정보는 getTokenAccountBalance 또는 getAccountInfo를 호출하여 얻을 수 있습니다
  • 임의 금액에 대한 UI 금액을 알아야 하는 경우 amountToUiAmountForMintWithoutSimulation (web3.js v1) 함수를 호출하거나 amountToUiAmount를 사용하여 트랜잭션을 시뮬레이션하여 계산할 수 있습니다.
    • 참고: amountToUiAmount는 트랜잭션 시뮬레이션이 필요하며 이는 잔액이 있는 유효한 수수료 지불자도 필요함을 의미합니다. 이러한 이유로 이 방법은 잔액을 얻는 기본 방법이 되어서는 안 됩니다.

RPC 호출

  • getTokenAccountBalance
    • token account 잔액과 mint 정보를 반환합니다
$ curl http://localhost:8899 -s -X POST -H "Content-Type: application/json" -d '
{"jsonrpc": "2.0", "id": 1, "method": "getTokenAccountBalance", "params": ["2uuvxpnEKw52aTqNerHiQ3WeSqZriCMNVt8LhWfrkbPk"]}' | jq .
{
"jsonrpc": "2.0",
"result": {
"context": {
"apiVersion": "2.2.14",
"slot": 381130751
},
"value": {
"amount": "10000000",
"decimals": 6,
"uiAmount": 20.0,
"uiAmountString": "20"
}
},
"id": 1
}
  • getAccountInfo
    • 계정 정보와 mint 정보를 반환합니다
$ curl http://localhost:8899 -s -X POST -H "Content-Type: application/json" -d '
{"jsonrpc": "2.0", "id": 1, "method": "getAccountInfo", "params": ["2uuvxpnEKw52aTqNerHiQ3WeSqZriCMNVt8LhWfrkbPk", {"encoding": "jsonParsed"}]}' | jq .
{
"jsonrpc": "2.0",
"result": {
"context": {
"apiVersion": "2.2.14",
"slot": 381131001
},
"value": {
"data": {
"parsed": {
"info": {
"extensions": [
{
"extension": "immutableOwner"
},
{
"extension": "pausableAccount"
}
],
"isNative": false,
"mint": "BZCd6HfTbb5ZYJ8hQsm8282tG4QzLyeqFR6tdgQA9EAG",
"owner": "G7ARQSUCwNrfvTDUCZvM5xdiRdBJiN3qVw2PryD8Wnib",
"state": "initialized",
"tokenAmount": {
"amount": "10000000",
"decimals": 6,
"uiAmount": 20.0,
"uiAmountString": "20"
}
},
"type": "account"
},
"program": "spl-token-2022",
"space": 174
},
"executable": false,
"lamports": 2101920,
"owner": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
"rentEpoch": 18446744073709551615,
"space": 174
}
},
"id": 1
}

현재 금액 업데이트하기

발행자는 언제든지 승수를 업데이트할 수 있으므로 계정 잔액을 최신 상태로 유지하기 위해 주기적으로 폴링하는 것을 고려할 수 있습니다. 발행자는 하루에 한 번 이상 이 승수를 업데이트할 가능성이 낮습니다. 승수가 미래 날짜로 설정된 경우, 이 업데이트 시간에 자동으로 폴링할 수 있습니다

트랜잭션에서의 토큰 금액 (전송 / 스왑 등)

  • 사용자는 조정된 "UIAmount"로 해석될 금액을 입력해야 합니다. 이를 처리하는 앱은 트랜잭션을 위해 원시 토큰 금액으로 변환해야 합니다.
    • 반올림 문제가 있는 경우, 내림하여 트랜잭션 실패 위험보다는 약간의 먼지 금액을 남기는 것이 좋습니다
    • 이 변환을 수행하려면 uiAmountToAmountForMintWithoutSimulation (web3.js v1) 함수를 사용하거나 amountToUiAmount를 사용하여 트랜잭션을 시뮬레이션할 수 있습니다.
web3js-uiAmountToAmountForMintWithoutSimulation.ts
import { uiAmountToAmountForMintWithoutSimulation } from "@solana/web3.js";
import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js";
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
const mint = new PublicKey("BZCd6HfTbb5ZYJ8hQsm8282tG4QzLyeqFR6tdgQA9EAG");
const uiAmount = "20.2";
const rawAmount = await uiAmountToAmountForMintWithoutSimulation(
connection as unknown as Connection,
mint,
uiAmount
);
console.log("Raw Amount:", rawAmount);
/* Raw Amount: 20200000 */
  • 앱은 사용자가 "최대" 또는 "전체" 잔액으로 작업을 요청할 때 총 원시 금액을 사용해야 합니다. 이렇게 하면 잔여 먼지가 남지 않습니다.
    • 선택 사항: "최대"가 사용될 때 계정을 자동으로 닫아 사용자에게 저장소 보증금을 환불하는 것을 고려할 수 있습니다.

토큰 가격

  • 토큰 가격은 가능한 한 항상 스케일링된 가격으로 표시되어야 합니다.
  • 오라클과 같은 가격 피드 서비스 제공업체인 경우, 스케일링된 가격과 스케일링되지 않은 가격을 모두 제공해야 합니다.
    • 가능한 한 스케일링된 UI 금액 확장의 복잡성을 추상화하는 SDK/API를 제공하세요.

현재 승수

  • 현재 승수는 언제든지 getAccountInfo를 호출하여 토큰 민트에서 읽을 수 있습니다. 또한 미래 승수가 설정된 경우, 이 정보도 토큰 민트에서 확인할 수 있습니다. UX를 혼란스럽게 할 수 있으므로 이 승수를 표시하지 않는 것이 좋습니다.
import { address, createSolanaRpc } from "@solana/kit";
const rpc_url = "https://api.devnet.solana.com";
const rpc = createSolanaRpc(rpc_url);
const publicKey = address("BZCd6HfTbb5ZYJ8hQsm8282tG4QzLyeqFR6tdgQA9EAG");
const accountInfo = await rpc
.getAccountInfo(publicKey, { encoding: "jsonParsed" })
.send();
const mintData = accountInfo.value?.data as Readonly<{
parsed: {
info?: {
extensions: {
extension: string;
state: object;
}[];
};
type: string;
};
program: string;
space: bigint;
}>;
const scaledUiAmountConfig = mintData.parsed.info?.extensions?.find(
(extension) => extension.extension === "scaledUiAmountConfig"
) as Readonly<{
state: {
newMultiplierEffectiveTimestamp: number;
newMultiplier: number;
multiplier: number;
};
}>;
const currentMultiplier =
scaledUiAmountConfig?.state &&
Date.now() / 1000 >=
scaledUiAmountConfig.state.newMultiplierEffectiveTimestamp
? scaledUiAmountConfig.state.newMultiplier
: scaledUiAmountConfig.state.multiplier;
console.log("Scaled UI Amount Config:", scaledUiAmountConfig);
console.log("Current Multiplier:", currentMultiplier);
/*
Scaled UI Amount Config: {
extension: 'scaledUiAmountConfig',
state: {
authority: 'G7ARQSUCwNrfvTDUCZvM5xdiRdBJiN3qVw2PryD8Wnib',
multiplier: '2',
newMultiplier: '2',
newMultiplierEffectiveTimestamp: 1743000000n
}
}
Current Multiplier: 2
*/

과거 데이터

가격 피드의 과거 데이터

  • 과거 데이터를 제공하는 서비스는 스케일링된 UI 금액 확장에 대해 스케일링된 가격과 스케일링되지 않은 가격을 모두 저장하고 표시해야 합니다.
  • 스케일링된 금액이 가장 자주 사용될 것으로 예상됩니다. 이는 전통적인 금융 세계에서 주식 분할이 있는 토큰 관련 차트를 다루는 방식과 일치합니다.
  • 승수 업데이트에는 과거의 타임스탬프가 포함될 수 있습니다. 과거 데이터에는 블록 타임스탬프를 사용하는 것이 좋습니다.
  • 현재 타임스탬프와 새 승수가 활성화되도록 설정된 시점에 따라 활성 승수는 "multiplier" 또는 "newMultiplier"일 수 있습니다.

금액에 대한 과거 데이터

  • 과거에 전송된 잔액을 표시하려면 해당 slot에서의 승수에 접근해야 합니다. 또한 트랜잭션을 처리할 때 전송에 대한 UiAmount를 저장하여 향후 이 계산을 피할 수 있습니다.

이전 버전과의 호환성

  • 기본적으로 스케일링된 UI 금액 확장을 이해하지 못하는 지갑과 애플리케이션은 비스케일링된 가격 × 원시 금액을 곱하여 활동의 총 가격을 올바르게 표시합니다.
  • 그러나 비스케일링된 가격을 표시하여 사용자에게 혼란을 줄 수 있습니다.
  • 이를 통해 팀들이 스케일링된 UI 금액 확장을 사용하는 토큰과 호환되도록 dapp을 업데이트하도록 장려하고, 이 과정에서 기꺼이 지원을 제공하고자 합니다.

플랫폼별 권장 통합 우선순위

일반 요구사항

요구사항설명우선순위
UiAmount를 사용한 사용자 작업 지원모든 사용자 작업은 앱 전체에서 UiAmount가 활성화된 경우 UiAmount로 입력해야 합니다. 앱에서 UiAmount가 표시되지 않는 경우, 앱이 업데이트될 때까지 원시 금액을 사용해야 합니다.P0

지갑

요구사항설명우선순위
스케일링된 잔액 표시주요 잔액으로 스케일링된 금액(uiAmount)을 표시합니다.P0
토큰 전송 지원최종 사용자는 스케일링된 잔액(원시 금액 × 잔액)으로 전송 금액을 입력해야 합니다.P0
현물 가격 표시사용자에게 스케일링된 현물 가격을 표시합니다.P0
거래 내역 메타데이터가능한 모든 전송에 대해 스케일링된 금액(UIAmount)을 표시합니다.P1
거래 내역에 승수 업데이트 표시승수 업데이트가 발생하면 획득한 금액을 포함하여 사용자의 거래 내역에 이벤트로 표시합니다.P2
가격 내역 그래프 표시가격 그래프에 스케일링된 가격을 반영합니다.P1
온보딩/툴팁스케일링된 UI 금액 확장을 사용하는 토큰에 대해 사용자를 교육하기 위한 툴팁 또는 온보딩을 제공합니다.P2

탐색기

요구사항설명우선순위
토큰 상세 페이지 개선총 스케일링된 시가총액 및 현재 승수와 같은 메타데이터 표시P0
잔액에 대한 스케일링된 잔액 표시현재 잔액에 대한 스케일링된 잔액(UiAmount) 표시P0
거래에 대한 스케일링된 잔액 표시과거 거래의 전송 금액에 대한 스케일링된 잔액(UiAmount) 표시P0
거래에 대한 스케일링된 가격 표시이전 거래에 대한 스케일링된 가격 표시P1
승수 업데이트 거래의 적절한 파싱 및 표시승수 업데이트에 대한 세부 정보를 적절히 표시P2

시장 데이터 집계자(예: CoinGecko, Birdeye)

요구사항설명우선순위
스케일링된 데이터를 위한 API 업데이트시간 경과에 따른 승수 변경과 스케일링된 가격 피드를 포함하도록 API 기능을 확장합니다.P0
스케일링 조정이 포함된 총 공급량총 공급량과 총 시가총액을 표시할 때 스케일링된 잔액을 고려합니다P0
과거 가격 추적시간 경과에 따른 스케일링된 가격을 사용하여 과거 가격 차트를 제공합니다.P1
과거 승수 추적이자 발생 토큰에 대한 승수 업데이트의 과거 마커를 제공합니다. 승수 업데이트에는 과거의 타임스탬프가 포함될 수 있습니다. 과거 데이터의 경우 승수 업데이트에 표시된 타임스탬프 대신 블록 타임스탬프를 사용하는 것이 좋습니다.P2
교육 콘텐츠 또는 설명스케일링된 토큰의 작동 방식을 설명하는 간단한 설명이나 툴팁을 포함합니다.P2

가격 피드 제공업체

요구사항설명우선순위
스케일링된 및 스케일링되지 않은 가격 피드스케일링된 가격과 스케일링되지 않은 가격 모두에 대한 가격 피드를 제공합니다.P0
과거 승수 데이터과거 승수 변경 사항이 포함된 API를 제공합니다. 승수 업데이트에는 과거 시점의 타임스탬프가 포함될 수 있습니다. 과거 데이터의 경우 승수 업데이트에 표시된 타임스탬프 대신 블록 타임스탬프를 사용하는 것이 좋습니다.P0
과거 가격 데이터스케일링된 금액과 스케일링되지 않은 금액 모두에 기반한 과거 가격이 포함된 API를 제공합니다.P0

DEX

요구사항설명우선순위
리베이스된 토큰 잔액 표시UI에서 거래 또는 유동성 제공을 위한 조정된 잔액을 표시합니다. (백엔드는 여전히 원시 금액을 사용할 수 있음)P0
토큰 작업 지원최종 사용자는 UiAmount 잔액(승수 * 원시 금액)으로 작업 금액을 입력해야 합니다.P0
가격 피드 적응현재 가격을 표시하기 위해 가격 피드가 사용되는 모든 곳에서 최종 사용자에게 조정된 가격을 제공합니다.P1
가격 기록 그래프 표시가격 그래프에 조정된 가격을 반영합니다P1

CEX

요구사항설명우선순위
승수 업데이트 추적조정된 UI 금액 확장을 사용하는 토큰의 승수 업데이트를 추적합니다.P0
리베이스된 토큰 잔액 표시UI에서 거래 또는 유동성 제공을 위한 조정된 잔액을 표시합니다. (백엔드는 여전히 원시 금액을 사용할 수 있음)P0
토큰 작업 지원최종 사용자는 UiAmount 잔액(승수 * 원시 금액)으로 작업 금액을 입력해야 합니다.P0
과거 작업은 재조정되지 않아야 함거래와 같은 과거 작업은 작업 시점의 정확한 조정된 금액과 가격을 사용하여 표시해야 합니다.P1
내부적으로 원시 잔액 추적조정된 잔액 대신 온체인 트랜잭션에 대한 원시 잔액을 추적합니다. 이는 장기적으로 더 정확하고 관리하기 쉬울 것입니다.P1
가격 피드 적응현재 가격을 표시하기 위해 가격 피드가 사용되는 모든 곳에서 최종 사용자에게 조정된 가격을 제공합니다.P1
가격 기록 그래프 표시가격 그래프에 조정된 가격을 반영합니다. 여기에는 과거 가격을 현재 승수로 재조정하는 것이 포함됩니다.P1
원가 기준 조정주당 비용은 현재 승수에 맞게 조정되어야 합니다.P1

Is this page helpful?