hedera-token-service — скилл для Claude Code: токены Hedera на JS
Помогает агенту писать код для токенов и NFT на Hedera через Hiero JavaScript SDK. Пригодится, когда проект уже на этой сети.
npx skills add hedera-dev/hedera-skills --skill hedera-token-service -a claude-codeЧто делает hedera-token-service
Скилл описывает работу с Hedera Token Service на JavaScript и TypeScript: создание взаимозаменяемых токенов и NFT, минт, сжигание, переводы, ассоциация токенов со счетами, кастомные комиссии, а также операции KYC, freeze, wipe и pause. Всё это делается через @hiero-ledger/sdk, без смарт-контрактов — токены в HTS существуют как сущности сети.
Внутри — два шаблона настройки клиента: прямой через Client.forName(...).setOperator(...) и через Wallet с LocalProvider. Дальше идёт жизненный цикл транзакции: настроить, заморозить, подписать, выполнить, получить квитанцию. Если хватает ключа оператора, заморозку и подпись можно пропустить — execute(client) сделает это сам. Отдельно разобраны роли ключей: adminKey, supplyKey, freezeKey, kycKey, wipeKey, pauseKey, feeScheduleKey, metadataKey. Ключ, не заданный при создании токена, отключает соответствующую возможность навсегда — это повод проверить набор ключей до запуска в основной сети.
Для NFT нужен TokenType.NonFungibleUnique: без decimals и без начальной эмиссии, серийные номера появляются после минта. Переводы используют знаковые суммы — минус списывает, плюс зачисляет, и по каждому токену сумма должна сходиться к нулю. Чтобы счёт мог принять токен, его нужно ассоциировать, если только при создании счёта не выставлено setMaxAutomaticTokenAssociations.
Какие задачи решает
- создать взаимозаменяемый токен с treasury и supply-ключом
- выпустить NFT-коллекцию и наминтовать серийные номера
- перевести токены и NFT между счетами одной транзакцией
- настроить KYC, freeze, wipe и pause для токена
- ассоциировать токен со счётом получателя
Примеры запросов агенту
- Создай токен HTS с именем My Token, символом MTK и начальной эмиссией 10000 через @hiero-ledger/sdk
- Наминтуй NFT с метаданными ipfs://QmFirst... в существующую коллекцию
- Переведи 100 единиц токена со счёта отправителя получателю и покажи квитанцию
Как установить hedera-token-service
1Через Skills CLI (Vercel)
npx skills add hedera-dev/hedera-skills --skill hedera-token-service -a claude-code2Вручную: положить файлы
~/.claude/skills/hedera-token-service/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/hedera-token-service/
1Через Skills CLI (Vercel)
npx skills add hedera-dev/hedera-skills --skill hedera-token-service -a codex2Вручную: положить файлы
.agents/skills/hedera-token-service/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add hedera-dev/hedera-skills --skill hedera-token-service -a cursor2Вручную: положить файлы
.cursor/skills/hedera-token-service/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install hedera-dev/hedera-skills hedera-token-service2Вручную: положить файлы
.github/skills/hedera-token-service/SKILL.md1Через Skills CLI (Vercel)
npx skills add hedera-dev/hedera-skills --skill hedera-token-service -a gemini-cli2Командой платформы
gemini skills install https://github.com/hedera-dev/hedera-skills --path plugins/native-services-js/skills/hedera-token-serviceВручную: положить файлы
.devin/skills/hedera-token-service/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add hedera-dev/hedera-skills --skill hedera-token-service -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Из того же набора13
Похожие
Рядом в теме «Бэкенд и API»
Всё по теме «Бэкенд и API» →Вопросы о hedera-token-service
Как установить hedera-token-service в Claude?
Выполните npx skills add hedera-dev/hedera-skills --skill hedera-token-service -a claude-code. Скилл появится в ~/.claude/skills/hedera-token-service/SKILL.md.
Что делает hedera-token-service?
Даёт агенту справочник по операциям Hedera Token Service на JavaScript и TypeScript: создание токенов и NFT, минт, сжигание, переводы, ассоциация, кастомные комиссии и compliance-операции.
Какие ключи нужны токену на Hedera?
Роли распределены между adminKey, supplyKey, freezeKey, kycKey, wipeKey, pauseKey, feeScheduleKey и metadataKey. Если ключ не задать при создании, соответствующая операция станет недоступна навсегда.
Исходный текст
SKILL.md · Apache-2.0
---
name: hedera-token-service
description: "How to create, manage, and transfer tokens on Hedera using the Hiero JavaScript SDK (@hiero-ledger/sdk). Use this skill whenever the user wants to work with fungible tokens, NFTs, token creation, minting, burning, transfers, token association, custom fees (fixed, fractional, royalty), airdrops, KYC/freeze/wipe/pause operations, or any HTS (Hedera Token Service) operation in JavaScript or TypeScript. Also trigger when users mention @hashgraph/sdk token operations, ERC-20/ERC-721 equivalents on Hedera, or tokenization on the Hedera network."
---
# Hedera Token Service (HTS) — JavaScript SDK
HTS is Hedera's native token engine. It lets you create and manage fungible tokens and NFTs without writing smart contracts. Tokens created through HTS are first-class network entities with built-in compliance controls (KYC, freeze, wipe, pause) and custom fee schedules.
## Setup
All imports come from `@hiero-ledger/sdk`. Two setup patterns exist:
### Client + setOperator (direct)
```js
import { Client, AccountId, PrivateKey } from "@hiero-ledger/sdk";
const client = Client.forName(process.env.HEDERA_NETWORK)
.setOperator(
AccountId.fromString(process.env.OPERATOR_ID),
PrivateKey.fromStringECDSA(process.env.OPERATOR_KEY),
);
```
### Wallet + LocalProvider (signer-based)
```js
import { Wallet, LocalProvider } from "@hiero-ledger/sdk";
const provider = new LocalProvider();
const wallet = new Wallet(process.env.OPERATOR_ID, process.env.OPERATOR_KEY, provider);
```
With the signer pattern, use `freezeWithSigner(wallet)`, `signWithSigner(wallet)`, `executeWithSigner(wallet)`, and `getReceiptWithSigner(wallet)` instead of `freezeWith(client)` / `execute(client)`.
## Transaction Lifecycle
Every transaction follows this flow: **configure -> freeze -> sign -> execute -> receipt**.
```js
const tx = await new SomeTransaction()
.setSomeField(value)
.freezeWith(client); // locks the transaction body
await tx.sign(privateKey); // add signatures (call multiple times for multi-sig)
const response = await tx.execute(client);
const receipt = await response.getReceipt(client);
```
When only the operator key is needed, you can skip explicit freeze/sign — `execute(client)` handles it:
```js
const response = await new SomeTransaction()
.setSomeField(value)
.execute(client);
const receipt = await response.getReceipt(client);
```
## Creating Tokens
### Fungible Token
```js
import {
TokenCreateTransaction, TokenType, TokenSupplyType,
PrivateKey, Hbar,
} from "@hiero-ledger/sdk";
const supplyKey = PrivateKey.generateECDSA();
const { tokenId } = await (
await new TokenCreateTransaction()
.setTokenName("My Token")
.setTokenSymbol("MTK")
.setDecimals(2)
.setInitialSupply(10000)
.setTreasuryAccountId(operatorId)
.setAdminKey(operatorKey)
.setSupplyKey(supplyKey)
.execute(client)
).getReceipt(client);
```
### NFT (Non-Fungible Token)
NFTs require `TokenType.NonFungibleUnique`. They have **no decimals** and **no initial supply** — you mint individual serials after creation.
```js
const { tokenId: nftId } = await (
await new TokenCreateTransaction()
.setTokenName("My NFT Collection")
.setTokenSymbol("MNFT")
.setTokenType(TokenType.NonFungibleUnique)
.setSupplyType(TokenSupplyType.Finite)
.setMaxSupply(1000)
.setTreasuryAccountId(treasuryId)
.setAdminKey(adminKey)
.setSupplyKey(supplyKey)
.execute(client)
).getReceipt(client);
```
## Minting
```js
import { TokenMintTransaction } from "@hiero-ledger/sdk";
// Fungible — specify amount
await new TokenMintTransaction()
.setTokenId(tokenId)
.setAmount(500)
.execute(client);
// NFT — specify metadata per serial
const { serials } = await (
await new TokenMintTransaction()
.setTokenId(nftId)
.addMetadata(Buffer.from("ipfs://QmFirst..."))
.addMetadata(Buffer.from("ipfs://QmSecond..."))
.execute(client)
).getReceipt(client);
// serials = [Long(1), Long(2)]
```
## Token Association
Hedera accounts must **associate** with a token before they can receive it (unless the account has automatic token associations enabled via `setMaxAutomaticTokenAssociations`).
```js
import { TokenAssociateTransaction } from "@hiero-ledger/sdk";
await (
await (
await new TokenAssociateTransaction()
.setAccountId(recipientId)
.setTokenIds([tokenId])
.freezeWith(client)
).sign(recipientKey) // account owner must sign
).execute(client);
```
Alternatively, set `setMaxAutomaticTokenAssociations(-1)` on account creation to allow unlimited auto-association.
## Transfers
Use `TransferTransaction` for both fungible tokens and NFTs. Amounts are **signed**: negative debits, positive credits. They must net to zero per token.
```js
import { TransferTransaction } from "@hiero-ledger/sdk";
// Fungible transfer
await new TransferTransaction()
.addTokenTransfer(tokenId, senderId, -100)
.addTokenTransfer(tokenId, receiverId, 100)
.execute(client);
// NFT transfer (tokenId, serial, sender, receiver)
await new TransferTransaction()
.addNftTransfer(nftId, 1, senderId, receiverId)
.execute(client);
// Mix Hbar + token transfers in one transaction
await new TransferTransaction()
.addHbarTransfer(senderId, new Hbar(-5))
.addHbarTransfer(receiverId, new Hbar(5))
.addTokenTransfer(tokenId, senderId, -50)
.addTokenTransfer(tokenId, receiverId, 50)
.execute(client);
```
## Key Roles
Each key is optional. If omitted at creation, that capability is permanently disabled.
| Key | Purpose |
|-----|---------|
| `adminKey` | Update/delete the token; rotate other keys |
| `supplyKey` | Mint and burn |
| `freezeKey` | Freeze/unfreeze accounts from transferring this token |
| `kycKey` | Grant/revoke KYC status on accounts |
| `wipeKey` | Wipe token balance from an account |
| `pauseKey` | Pause/unpause all token operations globally |
| `feeScheduleKey` | Update the custom fee schedule |
| `metadataKey` | Update token or NFT metadata |
## Compliance Operations
```js
// Grant KYC (required when token has kycKey)
await new TokenGrantKycTransaction()
.setTokenId(tokenId).setAccountId(accountId).execute(client);
// Freeze an account
await new TokenFreezeTransaction()
.setTokenId(tokenId).setAccountId(accountId).execute(client);
// Unfreeze
await new TokenUnfreezeTransaction()
.setTokenId(tokenId).setAccountId(accountId).execute(client);
// Wipe tokens from an account
await new TokenWipeTransaction()
.setTokenId(tokenId).setAccountId(accountId).setAmount(10).execute(client);
// Pause all transfers
await new TokenPauseTransaction().setTokenId(tokenId).execute(client);
// Unpause
await new TokenUnpauseTransaction().setTokenId(tokenId).execute(client);
```
## Burning & Deleting
```js
import { TokenBurnTransaction, TokenDeleteTransaction } from "@hiero-ledger/sdk";
// Burn fungible
await new TokenBurnTransaction()
.setTokenId(tokenId).setAmount(100).execute(client);
// Burn NFT serials
await new TokenBurnTransaction()
.setTokenId(nftId).setSerials([1, 2]).execute(client);
// Delete entire token (requires adminKey)
await new TokenDeleteTransaction()
.setTokenId(tokenId).execute(client);
```
## Querying Token Info
```js
import { TokenInfoQuery, TokenNftInfoQuery, NftId } from "@hiero-ledger/sdk";
const info = await new TokenInfoQuery().setTokenId(tokenId).execute(client);
console.log(info.name, info.symbol, info.totalSupply.toString());
const nftInfo = await new TokenNftInfoQuery()
.setNftId(new NftId(nftId, 1))
.execute(client);
console.log(nftInfo.accountId.toString()); // current owner
```
## Airdrops
Airdrops distribute tokens to multiple recipients. If a recipient can't auto-associate, the airdrop becomes **pending** and must be claimed.
```js
import {
TokenAirdropTransaction, TokenClaimAirdropTransaction,
TokenCancelAirdropTransaction, TokenRejectTransaction, NftId,
} from "@hiero-ledger/sdk";
// Send airdrop
const record = await (
await (
await new TokenAirdropTransaction()
.addTokenTransfer(tokenId, treasuryId, -300)
.addTokenTransfer(tokenId, recipient1, 100)
.addTokenTransfer(tokenId, recipient2, 100)
.addTokenTransfer(tokenId, recipient3, 100)
.addNftTransfer(nftId, 1, treasuryId, recipient1)
.freezeWith(client)
.sign(treasuryKey)
).execute(client)
).getRecord(client);
// Check pending airdrops
const { newPendingAirdrops } = record;
// Recipient claims a pending airdrop
await (
await new TokenClaimAirdropTransaction()
.addPendingAirdropId(newPendingAirdrops[0].airdropId)
.freezeWith(client)
.sign(recipientKey)
).execute(client);
// Sender cancels a pending airdrop
await new TokenCancelAirdropTransaction()
.addPendingAirdropId(newPendingAirdrops[1].airdropId)
.execute(client);
// Recipient rejects tokens they already received
await (
await new TokenRejectTransaction()
.setOwnerId(recipientId)
.addTokenId(tokenId) // reject fungible
.addNftId(new NftId(nftId, 1)) // reject NFT
.freezeWith(client)
.sign(recipientKey)
).execute(client);
```
## Custom Fees
HTS supports three fee types. See `references/custom-fees.md` for full details.
```js
import {
CustomFixedFee, CustomFractionalFee, CustomRoyaltyFee, Hbar,
} from "@hiero-ledger/sdk";
const fixedFee = new CustomFixedFee()
.setFeeCollectorAccountId(collectorId)
.setHbarAmount(new Hbar(1));
const fractionalFee = new CustomFractionalFee()
.setFeeCollectorAccountId(collectorId)
.setNumerator(1).setDenominator(100) // 1%
.setMin(1).setMax(1000);
const royaltyFee = new CustomRoyaltyFee()
.setFeeCollectorAccountId(collectorId)
.setNumerator(5).setDenominator(100) // 5%
.setFallbackFee(
new CustomFixedFee().setHbarAmount(new Hbar(2))
);
await new TokenCreateTransaction()
.setCustomFees([fixedFee, fractionalFee])
// ... other fields
.execute(client);
```
## Common Gotchas
1. **Association before transfer**: Recipients must associate with the token or have auto-association slots. Without it, transfers fail with `TOKEN_NOT_ASSOCIATED_TO_ACCOUNT`.
2. **Signed amounts**: `addTokenTransfer` uses signed amounts. Sender gets negative, receiver gets positive. They must net to zero.
3. **NFTs have no decimals or initial supply**: Set `TokenType.NonFungibleUnique` and mint serials individually.
4. **Keys are permanent if no adminKey**: Without an admin key, you cannot update or delete the token, and cannot change any other keys.
5. **KYC gate**: If a token has a `kycKey`, accounts must receive KYC approval before they can transact with that token.
6. **Supply key for mint/burn**: You need a supply key set at creation to later mint or burn.
7. **Treasury auto-association**: The treasury account is automatically associated with the token.
8. **Freeze before multi-sig**: When multiple parties need to sign, call `freezeWith(client)` first, then chain `.sign(key)` calls.
## Reference Files
- `references/api-reference.md` — Complete list of all HTS transaction and query classes with their methods
- `references/custom-fees.md` — Detailed guide to fixed, fractional, and royalty fees
© hedera-dev · Apache-2.0 · hedera-dev/hedera-skills