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

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

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

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

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

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

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

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

Кошельки

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

CEXы

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

Is this page helpful?