モザイク情報を取得する
初級
NEM のすべての モザイク には、供給量、可分性、転送ルールなど、オンチェーンのプロパティがあります。
このチュートリアルでは、モザイクのプロパティと現在の供給量を取得する方法を説明します。
前提条件
このチュートリアルではネットワークからデータを読み取るだけです。アカウント は必要ありません。
始める前に、開発環境をセットアップ してください。
完全なコード
このチュートリアルの完全なコード一覧を以下に示します。
詳細な手順ごとの説明は次のセクションで行います。
import json
import os
import urllib.request
NODE_URL = os . getenv ( 'NODE_URL' , 'http://libertalia.nemtest.net:7890' )
print ( f 'Using node { NODE_URL } ' )
MOSAIC_ID = os . getenv ( 'MOSAIC_ID' , 'nem:xem' )
print ( f 'Mosaic ID: { MOSAIC_ID } ' )
try :
# Fetch mosaic information
mosaic_path = f '/mosaic/definition?mosaicId= { MOSAIC_ID } '
print ( f 'Fetching mosaic information from { mosaic_path } ' )
with urllib . request . urlopen ( f ' { NODE_URL }{ mosaic_path } ' ) as response :
response_json = json . loads ( response . read () . decode ())
mosaic_id = response_json [ 'id' ]
full_name = f ' { mosaic_id [ "namespaceId" ] } : { mosaic_id [ "name" ] } '
print ( 'Mosaic information:' )
print ( f ' Mosaic ID: { full_name } ' )
print ( f ' Description: { response_json [ "description" ] } ' )
print ( f ' Creator: { response_json [ "creator" ] } ' )
properties = {
prop [ 'name' ]: prop [ 'value' ]
for prop in response_json [ 'properties' ]
}
divisibility = int ( properties [ 'divisibility' ])
print ( f ' Divisibility: { divisibility } ' )
print ( f ' Initial supply: { properties [ "initialSupply" ] } ' )
print ( f ' Supply mutable: { properties [ "supplyMutable" ] } ' )
print ( f ' Transferable: { properties [ "transferable" ] } ' )
levy = response_json [ 'levy' ]
print ( f ' Levy: { levy if levy else "none" } ' )
# Fetch the current supply
supply_path = f '/mosaic/supply?mosaicId= { MOSAIC_ID } '
print ( f ' \n Fetching current supply from { supply_path } ' )
with urllib . request . urlopen ( f ' { NODE_URL }{ supply_path } ' ) as response :
supply_info = json . loads ( response . read () . decode ())
supply = supply_info [ 'supply' ]
print ( f ' Current supply: { supply } ' )
# Convert the supply to atomic units
atomic = supply * 10 ** divisibility
print ( f ' \n Supply in atomic units: { atomic } ' )
except Exception as error :
print ( error )
Download source
const NODE_URL = process . env . NODE_URL ||
'http://libertalia.nemtest.net:7890' ;
console . log ( 'Using node' , NODE_URL );
const MOSAIC_ID = process . env . MOSAIC_ID || 'nem:xem' ;
console . log ( 'Mosaic ID:' , MOSAIC_ID );
try {
// Fetch mosaic information
const mosaicPath = `/mosaic/definition?mosaicId= ${ MOSAIC_ID } ` ;
console . log ( 'Fetching mosaic information from' , mosaicPath );
const mosaicResponse = await fetch ( ` ${ NODE_URL }${ mosaicPath } ` );
if ( ! mosaicResponse . ok )
throw new Error ( `HTTP error! status: ${ mosaicResponse . status } ` );
const mosaicJSON = await mosaicResponse . json ();
const fullName = ` ${ mosaicJSON . id . namespaceId } : ${ mosaicJSON . id . name } ` ;
console . log ( 'Mosaic information:' );
console . log ( ` Mosaic ID: ${ fullName } ` );
console . log ( ' Description:' , mosaicJSON . description );
console . log ( ' Creator:' , mosaicJSON . creator );
const properties = Object . fromEntries ( mosaicJSON . properties
. map ( property => [ property . name , property . value ]));
const divisibility = parseInt ( properties . divisibility , 10 );
console . log ( ' Divisibility:' , divisibility );
console . log ( ' Initial supply:' , properties . initialSupply );
console . log ( ' Supply mutable:' , properties . supplyMutable );
console . log ( ' Transferable:' , properties . transferable );
const hasLevy = 0 !== Object . keys ( mosaicJSON . levy ). length ;
console . log ( ' Levy:' , hasLevy ? mosaicJSON . levy : 'none' );
// Fetch the current supply
const supplyPath = `/mosaic/supply?mosaicId= ${ MOSAIC_ID } ` ;
console . log ( '\nFetching current supply from' , supplyPath );
const supplyResponse = await fetch ( ` ${ NODE_URL }${ supplyPath } ` );
const supplyInfo = await supplyResponse . json ();
const supply = supplyInfo . supply ;
console . log ( ' Current supply:' , supply );
// Convert the supply to atomic units
const atomic = BigInt ( supply ) * ( 10n ** BigInt ( divisibility ));
console . log ( `\nSupply in atomic units: ${ atomic } ` );
} catch ( e ) {
console . error ( e . message );
}
Download source
//JAVA 21+
//DEPS org.symbol:symbol-sdk:3.3.3
import java.io.IOException ;
import java.math.BigInteger ;
import java.net.URI ;
import java.net.http.HttpClient ;
import java.net.http.HttpRequest ;
import java.net.http.HttpResponse ;
import java.net.http.HttpResponse.BodyHandlers ;
import java.util.HashMap ;
import java.util.Map ;
import com.fasterxml.jackson.databind.JsonNode ;
import com.fasterxml.jackson.databind.ObjectMapper ;
public final class GetMosaicInfo {
private static final ObjectMapper JSON_MAPPER = new ObjectMapper ();
private static final HttpClient HTTP_CLIENT =
HttpClient . newHttpClient ();
private static final String NODE_URL = System . getenv (). getOrDefault (
"NODE_URL" , "http://libertalia.nemtest.net:7890" );
public static void main ( final String [] args ) {
try {
new GetMosaicInfo (). run ();
} catch ( final Exception ex ) {
System . out . println ( null == ex . getMessage ()
? ex . toString ()
: ex . getMessage ());
}
}
private void run () throws IOException , InterruptedException {
System . out . printf ( "Using node %s%n" , NODE_URL );
final String mosaicId = System . getenv (). getOrDefault (
"MOSAIC_ID" , "nem:xem" );
System . out . printf ( "Mosaic ID: %s%n" , mosaicId );
// Fetch mosaic information
final String mosaicPath = String . format (
"/mosaic/definition?mosaicId=%s" , mosaicId );
System . out . printf ( "Fetching mosaic information from %s%n" ,
mosaicPath );
final HttpRequest mosaicRequest = HttpRequest . newBuilder (
URI . create ( NODE_URL + mosaicPath )). GET (). build ();
final HttpResponse < String > mosaicResponse = HTTP_CLIENT . send (
mosaicRequest , BodyHandlers . ofString ());
if ( 2 != mosaicResponse . statusCode () / 100 )
throw new IOException ( "HTTP error! status: "
+ mosaicResponse . statusCode ());
final JsonNode mosaicJson = JSON_MAPPER . readTree (
mosaicResponse . body ());
final JsonNode id = mosaicJson . get ( "id" );
final String fullName = String . format ( "%s:%s" ,
id . get ( "namespaceId" ). asText (), id . get ( "name" ). asText ());
System . out . println ( "Mosaic information:" );
System . out . printf ( " Mosaic ID: %s%n" , fullName );
System . out . printf ( " Description: %s%n" ,
mosaicJson . get ( "description" ). asText ());
System . out . printf ( " Creator: %s%n" ,
mosaicJson . get ( "creator" ). asText ());
final Map < String , String > properties = new HashMap <> ();
for ( final JsonNode property : mosaicJson . get ( "properties" )) {
properties . put ( property . get ( "name" ). asText (),
property . get ( "value" ). asText ());
}
final int divisibility = Integer . parseInt (
properties . get ( "divisibility" ));
System . out . printf ( " Divisibility: %d%n" , divisibility );
System . out . printf ( " Initial supply: %s%n" ,
properties . get ( "initialSupply" ));
System . out . printf ( " Supply mutable: %s%n" ,
properties . get ( "supplyMutable" ));
System . out . printf ( " Transferable: %s%n" ,
properties . get ( "transferable" ));
final JsonNode levy = mosaicJson . get ( "levy" );
System . out . printf ( " Levy: %s%n" ,
levy . isEmpty () ? "none" : levy . toString ());
// Fetch the current supply
final String supplyPath = String . format (
"/mosaic/supply?mosaicId=%s" , mosaicId );
System . out . printf ( "%nFetching current supply from %s%n" ,
supplyPath );
final HttpRequest supplyRequest = HttpRequest . newBuilder (
URI . create ( NODE_URL + supplyPath )). GET (). build ();
final HttpResponse < String > supplyResponse = HTTP_CLIENT . send (
supplyRequest , BodyHandlers . ofString ());
final BigInteger supply = new BigInteger (
JSON_MAPPER . readTree ( supplyResponse . body ())
. get ( "supply" ). asText ());
System . out . printf ( " Current supply: %s%n" , supply );
// Convert the supply to atomic units
final BigInteger atomic = supply . multiply (
BigInteger . TEN . pow ( divisibility ));
System . out . printf ( "%nSupply in atomic units: %s%n" , atomic );
}
}
Download source
スニペットでは、NODE_URL 環境変数を使って NEM API ノードを指定します。
値が指定されていない場合は、デフォルトの テストネット ノードを使用します。
MOSAIC_ID 環境変数では、完全修飾名 で照会するモザイクを指定します。
設定されていない場合は、XEM モザイク(nem:xem)をデフォルト値として使用します。
コードの説明
# Fetch mosaic information
mosaic_path = f '/mosaic/definition?mosaicId= { MOSAIC_ID } '
print ( f 'Fetching mosaic information from { mosaic_path } ' )
with urllib . request . urlopen ( f ' { NODE_URL }{ mosaic_path } ' ) as response :
response_json = json . loads ( response . read () . decode ())
mosaic_id = response_json [ 'id' ]
full_name = f ' { mosaic_id [ "namespaceId" ] } : { mosaic_id [ "name" ] } '
print ( 'Mosaic information:' )
print ( f ' Mosaic ID: { full_name } ' )
print ( f ' Description: { response_json [ "description" ] } ' )
print ( f ' Creator: { response_json [ "creator" ] } ' )
properties = {
prop [ 'name' ]: prop [ 'value' ]
for prop in response_json [ 'properties' ]
}
divisibility = int ( properties [ 'divisibility' ])
print ( f ' Divisibility: { divisibility } ' )
print ( f ' Initial supply: { properties [ "initialSupply" ] } ' )
print ( f ' Supply mutable: { properties [ "supplyMutable" ] } ' )
print ( f ' Transferable: { properties [ "transferable" ] } ' )
levy = response_json [ 'levy' ]
print ( f ' Levy: { levy if levy else "none" } ' )
// Fetch mosaic information
const mosaicPath = `/mosaic/definition?mosaicId= ${ MOSAIC_ID } ` ;
console . log ( 'Fetching mosaic information from' , mosaicPath );
const mosaicResponse = await fetch ( ` ${ NODE_URL }${ mosaicPath } ` );
if ( ! mosaicResponse . ok )
throw new Error ( `HTTP error! status: ${ mosaicResponse . status } ` );
const mosaicJSON = await mosaicResponse . json ();
const fullName = ` ${ mosaicJSON . id . namespaceId } : ${ mosaicJSON . id . name } ` ;
console . log ( 'Mosaic information:' );
console . log ( ` Mosaic ID: ${ fullName } ` );
console . log ( ' Description:' , mosaicJSON . description );
console . log ( ' Creator:' , mosaicJSON . creator );
const properties = Object . fromEntries ( mosaicJSON . properties
. map ( property => [ property . name , property . value ]));
const divisibility = parseInt ( properties . divisibility , 10 );
console . log ( ' Divisibility:' , divisibility );
console . log ( ' Initial supply:' , properties . initialSupply );
console . log ( ' Supply mutable:' , properties . supplyMutable );
console . log ( ' Transferable:' , properties . transferable );
const hasLevy = 0 !== Object . keys ( mosaicJSON . levy ). length ;
console . log ( ' Levy:' , hasLevy ? mosaicJSON . levy : 'none' );
// Fetch mosaic information
final String mosaicPath = String . format (
"/mosaic/definition?mosaicId=%s" , mosaicId );
System . out . printf ( "Fetching mosaic information from %s%n" ,
mosaicPath );
final HttpRequest mosaicRequest = HttpRequest . newBuilder (
URI . create ( NODE_URL + mosaicPath )). GET (). build ();
final HttpResponse < String > mosaicResponse = HTTP_CLIENT . send (
mosaicRequest , BodyHandlers . ofString ());
if ( 2 != mosaicResponse . statusCode () / 100 )
throw new IOException ( "HTTP error! status: "
+ mosaicResponse . statusCode ());
final JsonNode mosaicJson = JSON_MAPPER . readTree (
mosaicResponse . body ());
final JsonNode id = mosaicJson . get ( "id" );
final String fullName = String . format ( "%s:%s" ,
id . get ( "namespaceId" ). asText (), id . get ( "name" ). asText ());
System . out . println ( "Mosaic information:" );
System . out . printf ( " Mosaic ID: %s%n" , fullName );
System . out . printf ( " Description: %s%n" ,
mosaicJson . get ( "description" ). asText ());
System . out . printf ( " Creator: %s%n" ,
mosaicJson . get ( "creator" ). asText ());
final Map < String , String > properties = new HashMap <> ();
for ( final JsonNode property : mosaicJson . get ( "properties" )) {
properties . put ( property . get ( "name" ). asText (),
property . get ( "value" ). asText ());
}
final int divisibility = Integer . parseInt (
properties . get ( "divisibility" ));
System . out . printf ( " Divisibility: %d%n" , divisibility );
System . out . printf ( " Initial supply: %s%n" ,
properties . get ( "initialSupply" ));
System . out . printf ( " Supply mutable: %s%n" ,
properties . get ( "supplyMutable" ));
System . out . printf ( " Transferable: %s%n" ,
properties . get ( "transferable" ));
final JsonNode levy = mosaicJson . get ( "levy" );
System . out . printf ( " Levy: %s%n" ,
levy . isEmpty () ? "none" : levy . toString ());
/mosaic/definition GET エンドポイントは、次の内容を含むモザイク定義を取得します。
説明: モザイクを 説明する テキスト。
作成者: モザイクを作成したアカウントの 公開鍵 。
プロパティ: モザイクの 動作プロパティ 。
可分性 : モザイクがサポートする小数桁数。
例えば、XEM の可分性は 6 なので、1 XEM は 1'000'000 原子単位に相当します。
初期供給量 : 作成時の供給量で、全体単位で表されます。
供給量の可変性 : 作成後に作成者が供給量を変更できるかどうか。
転送可能性 : モザイクをアカウント間で自由に送信できるか、作成者との間でのみ送信できるか。
徴収手数料(levy): モザイクを転送するたびに 3 つ目のアカウントへ支払われる、オプションの 徴収手数料 。
現在の供給量を取得する
定義に記録されるのは 初期 供給量だけです。
供給量が可変なモザイクでは現在値が異なる可能性があるため、/mosaic/supply GET エンドポイントは、現在流通している供給量を 全体単位 で返します。
原子単位に変換する
エンドポイントは供給量を全体単位で返しますが、トランザクションの数量は 原子単位 で表されます。
全体単位から原子単位に変換するには、コードで供給量に 10 のモザイクの可分性乗を掛けます。
XEM(可分性 6)では、8'999'999'999 全体単位の供給量は 8'999'999'999'000'000 原子単位に相当します。
出力
以下の出力は、テストネットの XEM モザイクを照会した場合の実行例です。
Using node http://libertalia.nemtest.net:7890
Mosaic ID: nem:xem
Fetching mosaic information from /mosaic/definition?mosaicId=nem:xem
Mosaic information:
Mosaic ID: nem:xem
Description: reserved xem mosaic
Creator: 3e82e1c1e4a75adaa3cba8c101c3cd31d9817a2eb966eb3b511fb2ed45b8e262
Divisibility: 6
Initial supply: 8999999999
Supply mutable: false
Transferable: true
Levy: none
Fetching current supply from /mosaic/supply?mosaicId=nem:xem
Current supply: 8999999999
Supply in atomic units: 8999999999000000
出力の要点は次のとおりです。
モザイク ID (5 行目): XEM モザイクの識別子である完全修飾名 nem:xem。
説明 (6 行目): 作成者が設定した、モザイクを説明するテキスト。
作成者 (7 行目): モザイクを作成したアカウントの公開鍵。
可分性 (8 行目): 6 は、1 XEM が 1'000'000(106 )原子単位であることを意味します。
初期供給量 (9 行目): 作成時の供給量で、全体単位で表されます。
供給量の可変性 (10 行目): false は、XEM の供給量が決して変更できないことを意味します。
転送可能性 (11 行目): true は、XEM をアカウント間で自由に送信できることを意味します。
徴収手数料(levy) (12 行目): XEM の転送に追加のモザイク手数料はかかりません。
現在の供給量 (15 行目): 現在流通している供給量。XEM は可変ではないため初期供給量と同じです。
原子単位の供給量 (17 行目): モザイクの可分性を使って、全体単位から変換した供給量。
まとめ
このチュートリアルでは、次の方法を説明しました。
次のステップ