Typescript Hedera Mirror Node Rest API wrapper with complete declarative abstraction layer
- Typed Library
- Typed Responses
- Flexible with different http clients like axios, fetch etc
- No need to remember how and what params exist for different resources in raw form
- Easily maintainable
npm install @tikz/hedera-mirror-node-ts
yarn add @tikz/hedera-mirror-node-ts
Client needs to be initialized with base url depending upon network. BaseURL should not contain forward slashes at end
import { Client } from "@tikz/hedera-mirror-node-ts";
/**
* https://previewnet.mirrornode.hedera.com
* https://mainnet-public.mirrornode.hedera.com
*/
const client = new Client(baseURL)
import { Client, topicMessages, optionalFilters } from "@tikz/hedera-mirror-node-ts";
const client = new Client('https://testnet.mirrornode.hedera.com')
const msgCursor = topicMessages(client)
.setTopicId('0.0.16430')
.setLimit(10)
.order('asc')
.sequenceNumber(optionalFilters.greaterThan(20))
// get initial data
// -> 20 < sequenceNumber <= 30
const msgs = await msgCursor.get()
// get next set of data
// -> 30 < sequenceNumber <= 40
const msgs2 = await msgCursor.next()
// get next set of data
// -> 40 < sequenceNumber <= 50
const msgs3 = await msgCursor.next()
Refer TopicMessages for full api
import { accounts, optionalFilters } from "@tikz/hedera-mirror-node-ts";
const accountCursor = accounts(client)
.setAccountId(
optionalFilters.lessThan('0.0.15678177')
)
.setLimit(2)
const accounts1 = await accountCursor.get()
const accounts2 = await accountCursor.next()
Refer Accounts for full api
import { transactions, optionalFilters, TransactionType } from "@tikz/hedera-mirror-node-ts";
const transactionCursor = transactions(client)
.setAccountId('0.0.15678177')
.setLimit(2)
.setType('debit')
.setTransactionType(
TransactionType.CONSENSUSSUBMITMESSAGE
)
.setResult('success')
const txns = await transactionCursor.get()
// get next batch of transactions
const txns2 = await transactionCursor.next()
Refer Transactions for full api
import { networkSupply } from "@tikz/hedera-mirror-node-ts";
const supply = await networkSupply(client).get()
Refer NetworkSupply for full api
import { tokenUtils } from "@tikz/hedera-mirror-node-ts";
const tokenUtil = tokenUtils(client)
// don't destructure {TokensCursor, TokenInfoCursor, TokenBalances}
// token utils is a class
const tokenCursor = tokenUtil.Tokens
.setLimit(2)
.order("desc")
.setTokenType(TokenTypeFilter.NON_FUNGIBLE_UNIQUE);
const tokensUnique = await tokenCursor.get();
const tokensCommon = await tokenCursor
.setTokenType(TokenTypeFilter.FUNGIBLE_COMMON)
.get();
// token information
const tokenInfoCursor = tokenUtil.TokenInfo
.setTokenId('0.0....');
const tokenInfo = await tokenInfoCursor.get();
// get token balances
const tokenBalance = await tokenInfoCursor.TokenBalances
.get(); // no need to set token id
//or
const tokenBalance = await tokenUtil.TokenBalances
.setTokenId('0.0....')
.get();
Refer TokenUtils for full api
import { nftUtils } from "@tikz/hedera-mirror-node-ts";
const nftUtil = nftUtils(client)
// get nfts
const nftsCursors = nftUtil.NFTs
.setTokenId("0.0.....")
.order("asc");
const nfts = await nftsCursors.get();
// get nft info
const nftInfoCursor = nftUtil.NFTInfo
.setTokenId("0.0.....")
.setSerialNumber(1);
const nftInfo = await nftInfoCursor.get();
// get nft transaction history
const nftTxns = await nftInfo // no need to set token id
.getNFTTransactionHistory()
.get();
// or
const nftTxns = await nftUtil.NFTTransactionHistory
.setTokenId('0.0...')
.setSerialNumber(0)
.get();
Refer NFTUtils for full api
const contractCursor = smartContract(client);
const resp = await contractCursor
.setLimit(2)
.order("asc")
.get();
Refer SmartContracts for full api
By default axios is used to make requests which can be easily changed
import { BaseMirrorClient } from "@tikz/hedera-mirror-node-ts";
// Client.ts
class AxiosClient implements BaseMirrorClient{
public baseURL = 'https://mainnet-public.mirrornode.hedera.com'
public async fetch<D>(url:string,params:Params):Promise<D>{
const response = await axios.get(baseURL,{url:url,params:params})
return response.data
}
}
// index.ts
const client = new AxiosClient()
When /api/v1
gets deprecated then a more raw approach can be used till library gets updated
import { Client, TopicMessages,Transactions ,optionalFilters, TokenUtils, NFTUtils } from "@tikz/hedera-mirror-node-ts";
const client = new Client('https://testnet.mirrornode.hedera.com')
const msgCursor = new TopicMessages(client,'/api/v2/topics')
.setTopicId('0.0.16430')
.setLimit(10)
.order('asc')
.sequenceNumber(optionalFilters.greaterThan(20))
// similarly
const transactionCursor = new Transactions(client,'/api/v2/transactions')
const networkSupplyCursor = new NetworkSupply(client,'/api/v2/network/supply')
const tokenUtils = new TokenUtils(client,'/api/v2/token')
const nftUtils = new NFTUtils(client,'/api/v2/token')
Exists for all resource types that has next cursor link
order(order: "asc" | "desc")
setLimit(limit: number)
timestamp(timestamp: OptionalFilters)
// Methods
sequenceNumber(val: OptionalFilters): TopicMessages;
setTopicId(val: string): TopicMessages;
get(): Promise<MessagesResponse>;
next(): Promise<MessagesResponse>;
// Methods
setBalance(val: OptionalFilters): Accounts;
setAccountId(val: string): Accounts;
setPublicKey(val: OptionalFilters): Accounts;
setTransactionType(val: TransactionType): Accounts;
get(): Promise<AccountsResponse>;
next(): Promise<AccountsResponse>;
// Methods
setAccountId(val: OptionalFilters): Transaction;
setResult(val: 'fail' | 'success'): Transaction;
setType(val: 'credit' | 'debit'): Transaction;
setTransactionType(val: TransactionType): Transaction;
get(): Promise<TransactionsResponse>;
next(): Promise<TransactionsResponse>;
// Methods
get(): Promise<NetworkSupplyResponse>;
// Response
interface NetworkSupplyResponse {
released_supply: string;
timestamp: string;
total_supply: string;
}
// methods
setPublicKey(val: string): Tokens;
setTokenId(val: OptionalFilters): Tokens;
setTokenType(val: TokenTypeFilter): Tokens;
setAccountId(val: OptionalFilters): Tokens;
get(): Promise<TokensResponse>;
// methods
setTokenId(val: string): TokenInfo;
get(): Promise<TokenInfoResponse>;
TokenBalances: TokenBalances;
// methods
setPublicKey(val: string): this;
setAccountBalance(val: OptionalFilters): this;
setAccountId(val: OptionalFilters): this;
setTokenId(val: string): this;
get(): Promise<TokenBalanceResponse>;
// methods
setAccountId(val: OptionalFilters): NFTs;
setTokenId(val: string): NFTs;
get(): Promise<NFTsResponse>;
// methods
setTokenId(val: string): NFTInfo;
setSerialNumber(val: number): NFTInfo;
get(): Promise<NFTResponse>;
getNFTTransactionHistory: NFTTransactionHistory;
// methods
setTokenId(val: string): NFTTransactionHistory;
setSerialNumber(val: number): NFTTransactionHistory;
get(): Promise<NftTransactionHistoryResponse>;
// methods
setSmartContractId(val: OptionalFilters): SmartContracts;
get(): Promise<ContractResponse>;
type Order = "asc" | "desc"
enum TokenTypeFilter {
ALL = "all",
FUNGIBLE_COMMON = "fungible_common",
NON_FUNGIBLE_UNIQUE = "non_fungible_unique"
}
// optionalFilters is a helper provided in package for navigating cursors
type OptionalFilters = `gt:${string}` | `gte:${string}` | `lt:${string}` | `lte:${string}` | `ne:${string}` | string;
type optionalFilters: {
greaterThan(val: any): OptionalFilters;
greaterThanEqualTo(val: any): OptionalFilters;
lessThan(val: any): OptionalFilters;
lessThanEqualTo(val: any): OptionalFilters;
notEqualTo(val: any): OptionalFilters;
equalTo(val: any): OptionalFilters;
};
enum TransactionType {
CONSENSUSCREATETOPIC = "CONSENSUSCREATETOPIC",
CONSENSUSDELETETOPIC = "CONSENSUSDELETETOPIC",
CONSENSUSSUBMITMESSAGE = "CONSENSUSSUBMITMESSAGE",
CONSENSUSUPDATETOPIC = "CONSENSUSUPDATETOPIC",
CONTRACTCALL = "CONTRACTCALL",
CONTRACTCREATEINSTANCE = "CONTRACTCREATEINSTANCE",
CONTRACTDELETEINSTANCE = "CONTRACTDELETEINSTANCE",
CONTRACTUPDATEINSTANCE = "CONTRACTUPDATEINSTANCE",
CRYPTOADDLIVEHASH = "CRYPTOADDLIVEHASH",
CRYPTOCREATEACCOUNT = "CRYPTOCREATEACCOUNT",
CRYPTODELETE = "CRYPTODELETE",
CRYPTODELETELIVEHASH = "CRYPTODELETELIVEHASH",
CRYPTOTRANSFER = "CRYPTOTRANSFER",
CRYPTOUPDATEACCOUNT = "CRYPTOUPDATEACCOUNT",
FILEAPPEND = "FILEAPPEND",
FILECREATE = "FILECREATE",
FILEDELETE = "FILEDELETE",
FILEUPDATE = "FILEUPDATE",
FREEZE = "FREEZE",
SCHEDULECREATE = "SCHEDULECREATE",
SCHEDULEDELETE = "SCHEDULEDELETE",
SCHEDULESIGN = "SCHEDULESIGN",
SYSTEMDELETE = "SYSTEMDELETE",
SYSTEMUNDELETE = "SYSTEMUNDELETE",
TOKENASSOCIATE = "TOKENASSOCIATE",
TOKENBURN = "TOKENBURN",
TOKENCREATION = "TOKENCREATION",
TOKENDELETION = "TOKENDELETION",
TOKENDISSOCIATE = "TOKENDISSOCIATE",
TOKENFEESCHEDULEUPDATE = "TOKENFEESCHEDULEUPDATE",
TOKENFREEZE = "TOKENFREEZE",
TOKENGRANTKYC = "TOKENGRANTKYC",
TOKENMINT = "TOKENMINT",
TOKENPAUSE = "TOKENPAUSE",
TOKENREVOKEKYC = "TOKENREVOKEKYC",
TOKENUNFREEZE = "TOKENUNFREEZE",
TOKENUNPAUSE = "TOKENUNPAUSE",
TOKENUPDATE = "TOKENUPDATE",
TOKENWIPE = "TOKENWIPE",
UNCHECKEDSUBMIT = "UNCHECKEDSUBMIT"
}