Перейти к основному содержимому

Примеры API

Примеры

Все shell-примеры ниже работают на публичных FastNear API-хостах как есть. Если в shell задан FASTNEAR_API_KEY, они автоматически добавляют bearer header; если переменная не задана, они переходят на публичный неаутентифицированный путь.

Свести один аккаунт за один вызов

/v1/account/{id}/full — это агрегатор аккаунтов в FastNear API: один вызов собирает NEAR-состояние аккаунта, каждый FT-контракт, которого он касался, каждую NFT-коллекцию, которую он получил, и каждый валидаторский пул, в который делегировал. Если у вас уже есть account_id, это самый быстрый ответ на вопрос «что это за аккаунт?».

ACCOUNT_ID=root.near
AUTH_HEADER=()
if [ -n "${FASTNEAR_API_KEY:-}" ]; then AUTH_HEADER=(-H "Authorization: Bearer $FASTNEAR_API_KEY"); fi

curl -s "https://api.fastnear.com/v1/account/$ACCOUNT_ID/full" \
  "${AUTH_HEADER[@]}" \
  | jq '{
      account_id,
      near_balance_yocto: .state.balance,
      ft_contracts: (.tokens | length),
      nft_contracts: (.nfts | length),
      staking_pool_contracts: (.pools | length)
    }'

Для root.near: 150 FT-контрактов в списке, 102 NFT-коллекции, 2 валидаторских пула. Одни только счётчики контрактов говорят, что это оживлённый mainnet-аккаунт. Все примеры ниже погружаются в какую-то одну из этих поверхностей — начинайте отсюда, когда на руках только ID аккаунта.

Определить аккаунт по публичному ключу и сразу получить сводку

Найдите, какому аккаунту принадлежит ключ, и прочитайте его активы за один следующий запрос.

PUBLIC_KEY='ed25519:CCaThr3uokqnUs6Z5vVnaDcJdrfuTpYJHJWcAGubDjT'
AUTH_HEADER=()
if [ -n "${FASTNEAR_API_KEY:-}" ]; then AUTH_HEADER=(-H "Authorization: Bearer $FASTNEAR_API_KEY"); fi

LOOKUP="$(curl -s "https://api.fastnear.com/v1/public_key/$(jq -rn --arg k "$PUBLIC_KEY" '$k | @uri')" \
  "${AUTH_HEADER[@]}")"

echo "$LOOKUP" | jq '{matched: (.account_ids | length), account_ids}'

ACCOUNT_ID="$(echo "$LOOKUP" | jq -r '.account_ids[0]')"

curl -s "https://api.fastnear.com/v1/account/$ACCOUNT_ID/full" \
  "${AUTH_HEADER[@]}" \
  | jq '{account_id, state, tokens: (.tokens|length), nfts: (.nfts|length), pools: (.pools|length)}'

Если matched больше 1, переключайтесь на V1 Public Key Lookup All и пройдитесь по каждому найденному аккаунту.

Сколько NEAR на этом аккаунте реально доступно к переводу?

Состояние аккаунта NEAR делится на три ведра, которые UI кошельков обычно сливает в одно: balance — это свободная часть (не в стейкинге), locked — NEAR, привязанный к валидаторскому стейку или lockup-контракту, а storage_bytes подразумевает ещё отдельную долю, пришпиленную к trie по текущей ставке 10^19 yoctoNEAR за байт. Один pipeline над /full разводит их по полкам.

ACCOUNT_ID=root.near
AUTH_HEADER=()
if [ -n "${FASTNEAR_API_KEY:-}" ]; then AUTH_HEADER=(-H "Authorization: Bearer $FASTNEAR_API_KEY"); fi

curl -s "https://api.fastnear.com/v1/account/$ACCOUNT_ID/full" \
  "${AUTH_HEADER[@]}" \
  | jq '
      (.state.balance | tonumber) as $amount
      | (.state.locked  | tonumber) as $locked
      | (.state.storage_bytes * 10000000000000000000) as $pinned
      | 1e24 as $ynear
      | {
          account_id,
          near: {
            total_owned:       (($amount + $locked) / $ynear),
            unstaked:          ($amount / $ynear),
            stake_or_lockup:   ($locked / $ynear),
            pinned_to_storage: ($pinned / $ynear),
            spendable:         (($amount - $pinned) / $ynear)
          }
        }'

Для root.near: ~3914.67 NEAR всего, всё в свободной части, ~0.28677 NEAR закреплено за 28,677 байтами on-chain-состояния, ~3914.38 NEAR доступно к переводу. Новым аккаунтам это особенно заметно — свежесозданный именованный аккаунт ~182 байта «съедает» ~0.00182 NEAR под storage, и именно поэтому CLI-утилиты не дают отправить полный баланс.

Наведите тот же pipeline на валидаторский пул вроде astro-stakers.poolv1.near, и пропорции перевернутся: ~730 тыс. свободных, ~27.68 млн в locked. Этот locked — собственный протокольный валидаторский стейк пула, а не средства делегатов (те учитываются внутри состояния контракта пула). Одно и то же поле означает разное на разных типах аккаунтов.

jq считает в IEEE-754 double, поэтому NEAR-значения выше — только для отображения; для точной бухгалтерии сохраняйте сами yocto-строки.

Когда в этом аккаунте что-либо последний раз менялось?

У каждой записи в массивах tokens, nfts и pools внутри /full есть собственное last_update_block_height — блок, в котором индексер последний раз видел изменение этой строки для этого аккаунта. Максимум по всем трём массивам даёт дешёвый сигнал «последняя активность» без похода в Transactions API.

ACCOUNT_ID=root.near
AUTH_HEADER=()
if [ -n "${FASTNEAR_API_KEY:-}" ]; then AUTH_HEADER=(-H "Authorization: Bearer $FASTNEAR_API_KEY"); fi

curl -s "https://api.fastnear.com/v1/account/$ACCOUNT_ID/full" \
  "${AUTH_HEADER[@]}" \
  | jq '
      [
        (.tokens // [])[].last_update_block_height,
        (.nfts   // [])[].last_update_block_height,
        (.pools  // [])[].last_update_block_height
      ] as $heights
      | ($heights | map(select(. != null))) as $tracked
      | {
          account_id,
          total_entries:        ($heights | length),
          tracked_entries:      ($tracked | length),
          most_recent_block:    ($tracked | max),
          oldest_tracked_block: ($tracked | min)
        }'

Для root.near это возвращает 254 записи по FT-, NFT- и pool-контрактам, 158 с отслеживаемым блоком и самый свежий блок 194301659. Этого уже достаточно, чтобы понять, что кошелёк живой, не заходя в историю транзакций.

Это правильный вопрос для «был ли этот кошелёк недавно активен?» или «двигалось ли что-то после блока X?» — дёшево, один запрос, без истории транзакций. Чтобы достать саму транзакцию, вызвавшую последнее изменение, расширяйте поверхность до Transactions API. Записи с last_update_block_height: null относятся ко времени до per-row-отслеживания индексером (обычно старые airdrops) и здесь игнорируются, а не считаются свежими.

Показать NFT-коллекции этого кошелька от конкретного издателя

Имена аккаунтов на NEAR кодируют иерархию: mint.sharddog.near — это подаккаунт sharddog.near, который, в свою очередь, — подаккаунт near. Издатели, выпускающие несколько NFT-коллекций, обычно разворачивают каждую как отдельный подаккаунт, поэтому один фильтр по суффиксу над NFT-списком аккаунта вытаскивает всё опубликованное под одним деревом — без внешнего реестра коллекций.

ACCOUNT_ID=root.near
PUBLISHER=sharddog.near
AUTH_HEADER=()
if [ -n "${FASTNEAR_API_KEY:-}" ]; then AUTH_HEADER=(-H "Authorization: Bearer $FASTNEAR_API_KEY"); fi

curl -s "https://api.fastnear.com/v1/account/$ACCOUNT_ID/nft" \
  "${AUTH_HEADER[@]}" \
  | jq --arg publisher "$PUBLISHER" '
      ("." + $publisher) as $suffix
      | {
          account_id: .account_id,
          publisher: $publisher,
          collections: [
            .tokens[]
            | select(.contract_id | endswith($suffix))
            | {
                contract_id,
                last_update_block_height,
                status: (if .last_update_block_height == null then "dormant" else "active" end)
              }
          ] | sort_by(.last_update_block_height // 0)
        }'

Для root.near и sharddog.near это возвращает четыре контракта-подаккаунта: ndcconstellationnft, mint, harvestmoon и claim. Только у claim есть ненулевой last_update_block_height (131402024), так что именно этот контракт явно менял позицию кошелька. Остальные — спящие, что типично для одноразовых drop-контрактов, в которые аккаунт что-то получил и больше не возвращался.

Поменяйте PUBLISHER на любой аккаунт, чтобы сфокусировать фильтр на другом дереве издателя.

Показывает ли кошелёк прямой стейкинг, liquid staking-токены или оба варианта?

Прямые позиции в пулах лежат на /staking; liquid staking-токены (stNEAR, LiNEAR и т. п.) лежат на /ft как обычные FT. Прочитайте оба эндпоинта и классифицируйте кошелёк — root.near оказывается mixed.

ACCOUNT_ID=root.near
LIQUID_PROVIDERS_JSON='["meta-pool.near","lst.rhealab.near","linear-protocol.near"]'
AUTH_HEADER=()
if [ -n "${FASTNEAR_API_KEY:-}" ]; then AUTH_HEADER=(-H "Authorization: Bearer $FASTNEAR_API_KEY"); fi

STAKING="$(curl -s "https://api.fastnear.com/v1/account/$ACCOUNT_ID/staking" \
  "${AUTH_HEADER[@]}")"
FT="$(curl -s "https://api.fastnear.com/v1/account/$ACCOUNT_ID/ft" \
  "${AUTH_HEADER[@]}")"

jq -n \
  --argjson staking "$STAKING" \
  --argjson ft "$FT" \
  --argjson providers "$LIQUID_PROVIDERS_JSON" '
  ($staking.pools // []) as $direct
  | (($ft.tokens // []) | map(select(.contract_id as $id | $providers | index($id)))) as $liquid
  | {
      classification: (
        if ($direct|length)>0 and ($liquid|length)>0 then "mixed"
        elif ($direct|length)>0 then "direct_only"
        elif ($liquid|length)>0 then "liquid_only"
        else "no_visible_staking_position" end
      ),
      direct_pools: ($direct | map(.pool_id)),
      liquid_tokens: ($liquid | map({contract_id, balance}))
    }'

Классификатор знает только то, чему вы его научили — расширяйте LIQUID_PROVIDERS_JSON по мере появления новых liquid staking-продуктов и рассматривайте результат как наблюдательный, а не исчерпывающий.

Частые ошибки

  • Сразу идти в широкий снимок аккаунта, когда пользователя интересует только одна категория активов.
  • Использовать FastNear API, хотя пользователю нужны точные поля RPC или права доступа.
  • Оставаться на страницах сводок по аккаунту, когда вопрос уже стал вопросом об истории транзакций.

Связанные страницы