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

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

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

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

Ресурсы:

Кратко

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

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

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

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

Кошельки

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

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

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