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

Примеры API

Готовые сценарии

Читайте эту страницу как короткую лестницу: сначала определите, что это за аккаунт, затем классифицируйте форму кошелька, а потом переходите к более насыщенному сценарию происхождения, если хотите превратить живой BOS-артефакт в отчеканенную запись.

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

Используйте этот сценарий, когда у вас сначала есть только публичный ключ, а следующий практический вопрос пользователя звучит как «какому аккаунту он соответствует?» и сразу после этого «что сейчас видно по этому аккаунту?»

Стратегия

Сначала определите личность, а затем переиспользуйте тот же аккаунт для одной читаемой сводки по кошельку.

01GET /v1/public_key возвращает кандидатные значения account_id для этого ключа.

02jq поднимает тот аккаунт, который вы хотите смотреть дальше.

03GET /v1/account/.../full в одном ответе показывает балансы, NFT и стейкинг.

Что вы делаете

  • Ищете по публичному ключу один или несколько account_id.
  • Извлекаете первый найденный account_id через jq.
  • Переиспользуете это значение в широком эндпоинте полного снимка аккаунта.
API_BASE_URL=https://api.fastnear.com
PUBLIC_KEY='ed25519:YOUR_PUBLIC_KEY'
# Пример публичного ключа из модели страницы в документации:
# PUBLIC_KEY='ed25519:CCaThr3uokqnUs6Z5vVnaDcJdrfuTpYJHJWcAGubDjT'

ENCODED_PUBLIC_KEY="$(jq -rn --arg public_key "$PUBLIC_KEY" '$public_key | @uri')"

ACCOUNT_ID="$(
  curl -s "$API_BASE_URL/v1/public_key/$ENCODED_PUBLIC_KEY" \
    | tee /tmp/fastnear-public-key.json \
    | jq -r '.account_ids[0]'
)"

jq '{account_ids}' /tmp/fastnear-public-key.json

curl -s "$API_BASE_URL/v1/account/$ACCOUNT_ID/full" \
  | jq '{
      account_id,
      state,
      token_count: (.tokens | length),
      nft_count: (.nfts | length),
      pool_count: (.pools | length)
    }'

Зачем нужен следующий шаг?

Поиск по публичному ключу говорит, с каким аккаунтом вы имеете дело. Полный снимок аккаунта — естественный следующий запрос, если нужны балансы, NFT, стейкинг и пулы в одном ответе. Если ключ сопоставляется не с одним, а с несколькими аккаунтами, переходите к V1 Public Key Lookup All или пройдитесь по каждому найденному account_id.

У меня обычный стейкинг или liquid staking?

Используйте этот сценарий, когда история звучит так: «покажи, связан ли этот кошелёк с прямыми staking pool, liquid staking token или и с тем и с другим».

Стратегия

Сначала сравните staking-позиции и FT-балансы, а уже потом интерпретируйте кошелёк.

01GET /v1/account/.../staking находит прямую экспозицию через пулы.

02GET /v1/account/.../ft находит liquid staking token, которые лежат рядом с пулами или вместо них.

03jq превращает эти два индексированных чтения в direct_only, liquid_only или mixed.

Сеть

  • mainnet

Официальные ссылки

Этот пример намеренно остаётся наблюдательным. Он классифицирует то, что FastNear видит сейчас по staking-позициям и FT-балансам. Он не доказывает каждую возможную синтетическую или внешнюю форму стейкинг-экспозиции.

Что вы делаете

  • Читаете индексированные прямые staking-позиции через staking-эндпоинт аккаунта.
  • Читаете индексированные FT-балансы через FT-эндпоинт аккаунта.
  • Классифицируете аккаунт как direct_only, liquid_only, mixed или no_visible_staking_position.
  • Выводите список прямых пулов и список liquid staking-токенов, на которых основана эта классификация.
API_BASE_URL=https://api.fastnear.com
ACCOUNT_ID=YOUR_ACCOUNT_ID
LIQUID_PROVIDERS_JSON='["meta-pool.near","lst.rhealab.near","linear-protocol.near"]'
  1. Получите представление по прямому стейкингу.
curl -s "$API_BASE_URL/v1/account/$ACCOUNT_ID/staking" \
  | tee /tmp/account-staking.json \
  | jq '{account_id, pools}'
  1. Получите FT-балансы, чтобы увидеть liquid staking-позиции.
curl -s "$API_BASE_URL/v1/account/$ACCOUNT_ID/ft" \
  | tee /tmp/account-ft.json >/dev/null
  1. Классифицируйте аккаунт на основе этих двух индексированных представлений.
jq -n \
  --slurpfile staking /tmp/account-staking.json \
  --slurpfile ft /tmp/account-ft.json \
  --argjson providers "$LIQUID_PROVIDERS_JSON" '
  ($staking[0].pools // []) as $direct_pools
  | ($ft[0].tokens // []) as $tokens
  | ($tokens | map(select(.contract_id as $id | $providers | index($id)))) as $liquid_tokens
  | {
      classification:
        if (($direct_pools | length) > 0 and ($liquid_tokens | length) > 0) then "mixed"
        elif (($direct_pools | length) > 0) then "direct_only"
        elif (($liquid_tokens | length) > 0) then "liquid_only"
        else "no_visible_staking_position"
        end,
      direct_pools: ($direct_pools | map(.pool_id)),
      liquid_tokens: (
        $liquid_tokens
        | map({
            contract_id,
            balance,
            last_update_block_height
          })
      )
    }'

Зачем нужен следующий шаг?

Если классификация показывает direct_only, следующий практический вопрос обычно касается сроков unstake и withdraw. Если она показывает liquid_only, следующий вопрос обычно про redeem, swap или провайдерский путь выхода. Если результат mixed, эти пути лучше рассматривать раздельно, а не пытаться свести их к одному сценарию.

Заархивировать версию BOS-виджета как provenance NFT

Используйте этот сценарий, когда история звучит так: «этот BOS-виджет — реальный on-chain-артефакт. Хочу выпустить NFT, который фиксирует, какую именно версию я заархивировал».

Стратегия

Сначала прочитайте точный виджет, а mint делайте только тогда, когда provenance-поля уже детерминированы.

01GET /v1/account/.../nft проверяет, есть ли у получателя уже архивные NFT из этой коллекции.

02RPC call_function get на social.near читает точный исходник виджета и блок его записи в SocialDB.

03Захешируйте исходник, выполните nft_mint в testnet, а потом проверьте provenance-поля через nft_tokens_for_owner.

Сети

  • mainnet для чтения виджета из social.near
  • testnet для безопасного mint provenance NFT в nft.examples.testnet

Официальные ссылки

Что вы делаете

  • Через FastNear API проверяете, есть ли у получателя NFT из архивной коллекции.
  • Читаете один точный BOS-виджет из social.near, включая SocialDB-блок именно этого виджета.
  • Хешируете исходник виджета и превращаете его в provenance-метаданные.
  • Выпускаете NFT в testnet, чьи метаданные фиксируют автора, widget-path, SocialDB-блок и хеш исходника.
  • Подтверждаете, что выпущенный токен действительно несёт эти provenance-поля.

Зафиксированный исходный виджет:

  • аккаунт автора: mob.near
  • путь виджета: mob.near/widget/Profile
  • SocialDB-блок уровня виджета: 86494825
API_BASE_URL=https://test.api.fastnear.com
MAINNET_RPC_URL=https://rpc.mainnet.fastnear.com
TESTNET_RPC_URL=https://rpc.testnet.fastnear.com
AUTHOR_ACCOUNT_ID=mob.near
WIDGET_NAME=Profile
DESTINATION_COLLECTION_ID=nft.examples.testnet
RECEIVER_ACCOUNT_ID=YOUR_ACCOUNT_ID.testnet
SIGNER_ACCOUNT_ID="$RECEIVER_ACCOUNT_ID"
  1. Через FastNear API посмотрите, держит ли получатель уже какие-то NFT из архивной коллекции.
curl -s "$API_BASE_URL/v1/account/$RECEIVER_ACCOUNT_ID/nft" \
  | tee /tmp/provenance-account-nfts.json >/dev/null

jq --arg destination_collection_id "$DESTINATION_COLLECTION_ID" '{
  existing_archive_tokens: [
    .tokens[]?
    | select(.contract_id == $destination_collection_id)
    | {
        contract_id,
        token_id,
        last_update_block_height
      }
  ]
}' /tmp/provenance-account-nfts.json
  1. Прочитайте точное тело виджета и widget-level SocialDB-блок из mainnet.
WIDGET_ARGS_BASE64="$(
  jq -nc --arg author_account_id "$AUTHOR_ACCOUNT_ID" --arg widget_name "$WIDGET_NAME" '{
    keys: [($author_account_id + "/widget/" + $widget_name)],
    options: {with_block_height: true}
  }' | base64 | tr -d '\n'
)"

curl -s "$MAINNET_RPC_URL" \
  -H 'content-type: application/json' \
  --data "$(jq -nc --arg args_base64 "$WIDGET_ARGS_BASE64" '{
    jsonrpc: "2.0",
    id: "fastnear",
    method: "query",
    params: {
      request_type: "call_function",
      account_id: "social.near",
      method_name: "get",
      args_base64: $args_base64,
      finality: "final"
    }
  }')" \
  | jq '.result.result | implode | fromjson' \
  | tee /tmp/bos-widget.json >/dev/null

jq --arg author_account_id "$AUTHOR_ACCOUNT_ID" --arg widget_name "$WIDGET_NAME" '{
  widget_path: ($author_account_id + "/widget/" + $widget_name),
  socialdb_block_height: .[$author_account_id].widget[$widget_name][":block"],
  source_preview: (
    .[$author_account_id].widget[$widget_name][""]
    | split("\n")[0:8]
  )
}' /tmp/bos-widget.json
  1. Захешируйте исходник виджета и постройте детерминированные provenance-метаданные.
jq -r --arg author_account_id "$AUTHOR_ACCOUNT_ID" --arg widget_name "$WIDGET_NAME" '
  .[$author_account_id].widget[$widget_name][""]
' /tmp/bos-widget.json > /tmp/bos-widget-source.jsx

WIDGET_BLOCK_HEIGHT="$(
  jq -r --arg author_account_id "$AUTHOR_ACCOUNT_ID" --arg widget_name "$WIDGET_NAME" '
    .[$author_account_id].widget[$widget_name][":block"]
  ' /tmp/bos-widget.json
)"

SOURCE_SHA256="$(shasum -a 256 /tmp/bos-widget-source.jsx | awk '{print $1}')"
SOURCE_HASH_SHORT="$(printf '%s' "$SOURCE_SHA256" | cut -c1-12)"
TOKEN_ID="bos-widget-$SOURCE_HASH_SHORT"

PROVENANCE_METADATA_JSON="$(
  jq -nc \
    --arg author_account_id "$AUTHOR_ACCOUNT_ID" \
    --arg widget_name "$WIDGET_NAME" \
    --arg widget_path "$AUTHOR_ACCOUNT_ID/widget/$WIDGET_NAME" \
    --arg block_height "$WIDGET_BLOCK_HEIGHT" \
    --arg source_sha256 "$SOURCE_SHA256" '{
      title: ("BOS widget archive: " + $widget_path),
      description: ("Archived from social.near on mainnet at block " + $block_height),
      copies: 1,
      extra: ({
        author_account_id: $author_account_id,
        widget_name: $widget_name,
        widget_path: $widget_path,
        source_contract_id: "social.near",
        source_network: "mainnet",
        socialdb_block_height: ($block_height | tonumber),
        source_sha256: $source_sha256
      } | @json)
    }'
)"

printf '%s\n' "$PROVENANCE_METADATA_JSON" | jq '.'
  1. Выпустите provenance NFT в testnet.
near call "$DESTINATION_COLLECTION_ID" nft_mint "$(jq -nc \
  --arg token_id "$TOKEN_ID" \
  --arg receiver_id "$RECEIVER_ACCOUNT_ID" \
  --argjson metadata "$PROVENANCE_METADATA_JSON" '{
    token_id: $token_id,
    receiver_id: $receiver_id,
    metadata: $metadata
  }')" \
  --accountId "$SIGNER_ACCOUNT_ID" \
  --deposit 0.1 \
  --networkId testnet
  1. Подтвердите, что выпущенный NFT действительно несёт ожидаемые provenance-поля.

Не считайте отсутствие токена ошибкой мгновенно: после mint-транзакции опросите view-метод несколько раз.

NFT_TOKEN_ARGS_BASE64="$(
  jq -nc --arg token_id "$TOKEN_ID" '{token_id: $token_id}' \
    | base64 | tr -d '\n'
)"

for attempt in 1 2 3 4 5; do
  curl -s "$TESTNET_RPC_URL" \
    -H 'content-type: application/json' \
    --data "$(jq -nc \
      --arg account_id "$DESTINATION_COLLECTION_ID" \
      --arg args_base64 "$NFT_TOKEN_ARGS_BASE64" '{
        jsonrpc: "2.0",
        id: "fastnear",
        method: "query",
        params: {
          request_type: "call_function",
          account_id: $account_id,
          method_name: "nft_token",
          args_base64: $args_base64,
          finality: "final"
        }
      }')" \
    | jq '.result.result | implode | fromjson' \
    | tee /tmp/bos-widget-provenance-token.json >/dev/null

  if jq -e '. != null' /tmp/bos-widget-provenance-token.json >/dev/null; then
    break
  fi

  sleep 1
done

jq '{
  token_id,
  owner_id,
  title: .metadata.title,
  provenance: (.metadata.extra | fromjson)
}' /tmp/bos-widget-provenance-token.json

Зачем нужен следующий шаг?

FastNear API даёт быстрый чек со стороны получателя. Mainnet RPC даёт точное тело виджета и его SocialDB-блок. После этого mint в testnet превращает чтение в долговечную NFT-запись. Если позже понадобится доказать, какая именно историческая транзакция записала этот виджет, переходите к NEAR Social proof-расследованиям в Transactions API examples.

Частые задачи

Что этот аккаунт вообще держит прямо сейчас?

Начните здесь

  • V1 Full Account View, когда нужен самый быстрый понятный ответ на вопрос «что сейчас лежит в этом аккаунте?»

Следующая страница при необходимости

  • V1 Account FT, V1 Account NFT или V1 Account Staking, если широкая сводка уже помогла, но дальше хочется остаться только в одной категории активов.
  • Transactions API account history, если следующий вопрос звучит как «как аккаунт пришёл к такому состоянию?», а не «что он держит сейчас?»

Остановитесь, когда

  • Сводка уже отвечает на вопрос по активам в одной выдаче.

Переходите дальше, когда

  • Пользователь спрашивает о точном состоянии аккаунта, о семантике ключей доступа или о протокольных полях. Переходите к RPC Reference.
  • Пользователя интересует история активности или исполнения, а не текущий набор активов. Переходите к Transactions API.

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

Начните здесь

  • V1 Public Key Lookup, когда нужен основной аккаунт для ключа.
  • V1 Public Key Lookup All, когда нужен более полный список связанных аккаунтов.

Следующая страница при необходимости

  • V1 Full Account View после поиска, если сразу нужна сводка по балансам или активам найденных аккаунтов.

Остановитесь, когда

  • Уже определён аккаунт или набор аккаунтов, которым принадлежит ключ.

Переходите дальше, когда

  • Пользователь спрашивает о точных правах ключа, nonce или текущем состоянии access key. Переходите к View Access Key или View Access Key List.
  • Пользователя интересует недавняя активность найденных аккаунтов, а не только их идентификация. Переходите к Transactions API.

Есть ли у этого аккаунта FT, NFT или стейкинг-позиции?

Начните здесь

  • V1 Account FT, когда вопрос относится только к балансам FT-токенов.
  • V1 Account NFT, когда вопрос конкретно про владение NFT.
  • V1 Account Staking, когда пользователя интересуют именно стейкинг-позиции, а не вся картина по аккаунту.

Следующая страница при необходимости

  • V1 Full Account View, если после одной категории активов позже понадобится вся картина по аккаунту.
  • Transactions API account history, если вопрос уже меняется с «чем аккаунт владеет?» на «как он к этому пришёл?»

Остановитесь, когда

  • Эндпоинт по конкретной категории активов уже отвечает на вопрос о владении без пересборки всей картины аккаунта.

Переходите дальше, когда

  • Индексированного представления недостаточно и нужна точная семантика состояния в цепочке. Переходите к RPC Reference.
  • Вопрос становится историческим или связанным с исполнением вместо «чем этот аккаунт владеет сейчас?». Переходите к Transactions API.

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

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

Полезные связанные страницы