Поддержка расширения 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.
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 |
| Обучение/подсказки | Предлагать подсказки или обучение для пользователей о токенах с расширением масштабируемого uiAmount | P2 |
Обозреватели
| Требование | Описание | Приоритет |
|---|---|---|
| Улучшения страницы токена | Отображать метаданные, такие как общая масштабированная рыночная капитализация и текущий множитель | 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?