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

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

Общая информация

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

Ресурсы:

Краткий обзор

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

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

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

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

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

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

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

  • Для получения актуального баланса пользователя вы можете получить обновленную информацию о вышеуказанных суммах, вызвав либо getTokenAccountBalance, либо getAccountInfo.
  • Если вам нужно узнать UI Amount для произвольной суммы, вы можете выполнить этот расчет, вызвав функцию amountToUiAmountForMintWithoutSimulation (web3.js v1) или симулируя транзакцию с использованием amountToUiAmount.
    • Примечание: amountToUiAmount требует симуляции транзакции, что означает, что также необходим действительный плательщик комиссии с балансом. Поэтому это не должно быть основным способом получения баланса.

RPC вызовы

  • getTokenAccountBalance
    • Возвращает баланс токен-аккаунта и информацию о выпуске (mint info)
import { address, createSolanaRpc } from "@solana/kit";
const rpc_url = "https://api.devnet.solana.com";
const rpc = createSolanaRpc(rpc_url);
let tokenAddress = address("2uuvxpnEKw52aTqNerHiQ3WeSqZriCMNVt8LhWfrkbPk");
let tokenBalance = await rpc.getTokenAccountBalance(tokenAddress).send();
console.log("Token Balance:", tokenBalance);
/* Token Balance: {
context: { apiVersion: '2.2.14', slot: 381132711n },
value: {
amount: '10000000',
decimals: 6,
uiAmount: 20,
uiAmountString: '20'
}
} */
  • getAccountInfo
    • Возвращает информацию об аккаунте и информацию о выпуске (mint info)
import { address, createSolanaRpc } from "@solana/kit";
const rpc_url = "https://api.devnet.solana.com";
const rpc = createSolanaRpc(rpc_url);
const publicKey = address("2uuvxpnEKw52aTqNerHiQ3WeSqZriCMNVt8LhWfrkbPk");
const accountInfo = await rpc.getAccountInfo(publicKey).send();
console.log(
"Account Info:",
JSON.stringify(
accountInfo,
(key, value) => (typeof value === "bigint" ? value.toString() : value),
2
)
);
/* Account Info: {
"context": {
"apiVersion": "2.2.14",
"slot": "381133640"
},
"value": {
"data": {
"parsed": {
"info": {
"extensions": [
{
"extension": "immutableOwner"
},
{
"extension": "pausableAccount"
}
],
"isNative": false,
"mint": "BZCd6HfTbb5ZYJ8hQsm8282tG4QzLyeqFR6tdgQA9EAG",
"owner": "G7ARQSUCwNrfvTDUCZvM5xdiRdBJiN3qVw2PryD8Wnib",
"state": "initialized",
"tokenAmount": {
"amount": "10000000",
"decimals": 6,
"uiAmount": 20,
"uiAmountString": "20"
}
},
"type": "account"
},
"program": "spl-token-2022",
"space": "174"
},
"executable": false,
"lamports": "2101920",
"owner": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
"rentEpoch": "18446744073709551615",
"space": "174"
}
} */

Обновление текущей суммы

Поскольку эмитенты могут обновлять множитель в любое время, вы можете периодически выполнять опрос, чтобы поддерживать актуальность баланса аккаунта. Эмитенты вряд ли будут обновлять этот множитель чаще одного раза в день. Если множитель установлен на будущую дату, вы можете автоматически выполнять опрос в это время обновления.

Суммы токенов в транзакциях (переводы / обмены и т. д.)

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

Исторические данные для количеств

  • Если вы хотите показать баланс, переведенный в прошлом, вам нужен доступ к множителю на данном слоте. Вы также можете сохранить UiAmount для переводов, обрабатывая транзакции, чтобы избежать выполнения этого расчета в будущем.

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

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

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

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

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

Кошельки

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

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

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

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

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

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

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

DEXы

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

Is this page helpful?