Руководство по интеграции расширения Scaled UI Amount

Поддержка расширения Scaled UI Amount в Solana

Введение

Расширение Scaled UI Amount позволяет эмитентам токенов указывать множитель, который используется при вычислении UI-количества баланса токена пользователя. Это даёт возможность создавать ребейзинговые токены и реализовывать такие функции, как дробление акций. Это расширение, как и расширение для токенов с начислением процентов, предоставляет исключительно косметическое UI-значение, поэтому командам необходимо выполнить дополнительную работу для обеспечения качественного пользовательского опыта. Все базовые вычисления и переводы происходят с использованием необработанных значений в программе.

Ресурсы:

Кратко

  • Конечные пользователи должны взаимодействовать с UIAmount (необработанное значение * множитель) для цены токена, баланса токена и количества токенов, когда это возможно
  • dApp и сервис-провайдеры должны использовать необработанные значения и нескейленные цены для всех вычислений и преобразовывать их для пользователей на уровне интерфейса
  • Для облегчения интеграции необходимо предоставлять исторические ценовые данные как для скейленных, так и для нескейленных значений
  • Для точных исторических данных должен быть доступ к историческим значениям множителя

Определения терминов

  • Множитель: статический обновляемый множитель, используемый для вычисления UI Amount
  • UIAmount: множитель * необработанное значение (также: скейленное значение)
  • Необработанное значение: amount (также: нескейленное значение)

Текущий баланс

Текущее значение для отображения

  • Каждый раз, когда вы отображаете значения токенов с расширением scaled UI amount для конечных пользователей, используйте один из вариантов:
    • UIAmount/UIAmountString (рекомендуется)
    • Ручной расчёт: необработанное значение * множитель
    • Рекомендуем обрезать это значение в соответствии с количеством знаков после запятой у токена.
      • Например: если у yUSD 6 знаков после запятой, а у пользователя UIAmount 1.123456789, следует отображать «1.123456».

Где получить эти данные:

  • Чтобы узнать актуальный баланс пользователя, вы можете получить обновлённую информацию по вышеуказанным значениям, вызвав либо getTokenAccountBalance, либо getAccountInfo.
  • Если вам нужно узнать UI Amount для произвольного значения, вы можете получить этот расчёт, вызвав функцию 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 */
  • Приложения должны использовать общий исходный объем, когда пользователь запрашивает действие с “максимумом” или “всем” своего баланса. Это гарантирует, что не останется пыли.
    • Необязательно: вы можете рассмотреть возможность автоматического закрытия аккаунта, если используется “максимум” для возврата пользователю его депозита за хранение.

Цена токена

  • Цена токена всегда должна отображаться как масштабированная цена, где это возможно.
  • Если вы являетесь поставщиком ценовых данных, например, оракулом, вы должны предоставлять как масштабированную, так и немасштабированную цену.
    • По возможности предоставляйте SDK/API, который абстрагирует сложности расширения масштабированного UI-объема.

Текущий множитель

  • Текущий множитель можно получить из токен-минта в любой момент, вызвав 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 для переводов по мере обработки транзакций, чтобы избежать этого расчёта в будущем.

Обратная совместимость

  • По умолчанию кошельки и приложения, которые не поддерживают расширение масштабируемого UIAmount, будут показывать правильную итоговую цену операции, умножая немасштабированную цену на необработанную сумму.
  • Однако они будут отображать немасштабированную цену, что может вызвать путаницу у пользователей.
  • Мы надеемся, что это побудит команды обновить свои dapp для совместимости с токенами, использующими расширение масштабируемого UIAmount, и готовы оказать поддержку в этом процессе.

Рекомендуемые приоритеты интеграции по платформам

Общие требования

ТребованиеОписаниеПриоритет
Поддержка пользовательских действий с UiAmountВсе пользовательские действия должны вводиться в UiAmount, если UiAmount включён во всём приложении. Если UiAmount не отображается, следует использовать необработанные суммы до обновления приложения.P0

Кошельки

ТребованиеОписаниеПриоритет
Отображение масштабируемого балансаПоказывать масштабируемую сумму (uiAmount) как основной баланс.P0
Поддержка переводов токеновПользователи должны вводить суммы переводов, используя свои масштабируемые балансы (необработанная сумма * баланс).P0
Отображение спотовой ценыПоказывать масштабируемую спотовую цену для пользователейP0
Метаданные истории транзакцийПоказывать масштабируемую сумму (UIAmount) для каждого перевода, где это возможно.P1
Отображение обновлений множителя в историиПри обновлении множителя показывать это событие в истории транзакций пользователя, включая полученную суммуP2
Отображение графика истории ценОтражать масштабируемые цены на графике ценP1
Обучение/подсказкиПредлагать подсказки или обучение для пользователей о токенах с расширением масштабируемого uiAmountP2

Обозреватели

ТребованиеОписаниеПриоритет
Улучшения страницы токенаОтображать метаданные, такие как общая масштабированная рыночная капитализация и текущий множительP0
Отображение масштабированного баланса для балансовПоказывать масштабированные балансы (UiAmount) для текущих балансов.P0
Отображение масштабированного баланса для транзакцийПоказывать масштабированные балансы (UiAmount) для сумм переводов в истории транзакций.P0
Отображение масштабированной цены для транзакцийПоказывать масштабированные цены для прошлых транзакцийP1
Корректный разбор и отображение обновлений множителяКорректно показывать детали об обновлении множителяP2

Агрегаторы рыночных данных (например, CoinGecko, Birdeye)

ТребованиеОписаниеПриоритет
Обновления API для масштабированных данныхРасширить функциональность API, чтобы включить изменения множителя во времени, а также масштабированную ценовую ленту.P0
Общий объем с учетом масштабированияПри отображении общего объема и общей рыночной капитализации учитывать масштабированные балансыP0
Историческое отслеживание ценПредоставлять исторический график цен с использованием масштабированной цены во времени.P1
Историческое отслеживание множителяПредоставлять исторические отметки обновлений множителя для токенов с начислением процентов. Обратите внимание, что обновления множителя могут содержать метку времени в прошлом. Рекомендуем использовать блоковую метку времени вместо указанной в обновлении множителя для исторических данных.P2
Обучающий контент или поясненияВключать краткие описания или подсказки, объясняющие, как работают масштабированные токены.P2

Поставщики ценовых данных

ТребованиеОписаниеПриоритет
Масштабируемые и немасштабируемые ценовые лентыПредоставлять ценовые ленты как для масштабируемых, так и для немасштабируемых цен.P0
Исторические данные множителяПредоставлять API с историей изменений множителя. Обратите внимание, что обновления множителя могут содержать метку времени из прошлого. Рекомендуем использовать блоковую метку времени вместо метки времени из обновления множителя для исторических данных.P0
Исторические ценовые данныеПредоставлять API с историческими ценами на основе как масштабируемых, так и немасштабируемых значений.P0

DEX

ТребованиеОписаниеПриоритет
Отображение балансов ребейз-токеновПоказывать масштабируемые балансы для торговли или предоставления ликвидности в интерфейсе. (бэкенд может использовать исходные значения)P0
Поддержка действий с токенамиПользователи должны вводить суммы действий с учетом их UiAmount балансов (множитель * исходное количество).P0
Адаптация ценовой лентыВезде, где используется ценовая лента для отображения текущей цены, предоставлять масштабируемую цену пользователям.P1
Отображение графика истории ценОтражать масштабируемые цены на графике ценP1

CEX

ТребованиеОписаниеПриоритет
Отслеживание обновлений множителяОтслеживать обновления множителя для токенов, использующих расширение масштабируемой UI суммы.P0
Отображение балансов ребейз-токеновПоказывать масштабируемые балансы для торговли или предоставления ликвидности в интерфейсе. (бэкенд может использовать исходные значения)P0
Поддержка действий с токенамиПользователи должны вводить суммы действий с учетом их UiAmount балансов (множитель * исходное количество).P0
Исторические действия не должны пересчитыватьсяИсторические действия, такие как сделки, должны отображаться с точными масштабируемыми суммой и ценой на момент действия.P1
Внутренний учет исходных балансовВести учет исходных балансов для ончейн-транзакций вместо масштабируемых балансов. Это будет точнее и проще для управления в долгосрочной перспективе.P1
Адаптация ценовой лентыВезде, где используется ценовая лента для отображения текущей цены, предоставлять масштабируемую цену пользователям.P1
Отображение графика истории ценОтражать масштабируемые цены на графике цен. Это включает пересчет исторических цен по текущему множителю.P1
Масштабирование себестоимостиСебестоимость за акцию должна быть масштабирована по текущему множителю.P1

Is this page helpful?

Управляется

© 2026 Фонд Solana.
Все права защищены.
Подключиться