コンテンツにスキップ

サブネームスペースを登録する⚓︎

中級

サブネームスペース(「子」ネームスペースとも呼ばれます)は、ネームスペース の階層構造を拡張します。

このチュートリアルでは、既存の ルートネームスペース の下にサブネームスペースを登録する方法を説明します。

ルートネームスペースを登録する方法については、ルートネームスペースを登録する ガイドを参照してください。

前提条件⚓︎

始める前に、次の準備をしてください。

さらに、トランザクションのアナウンスと承認の方法を理解するため、XEM を送信する チュートリアルを確認してください。

完全なコード⚓︎

このチュートリアルの完全なコード一覧を以下に示します。 詳細な手順ごとの説明は次のセクションで行います。

import json
import os
import time
import urllib.request

from symbolchain.CryptoTypes import PrivateKey
from symbolchain.facade.NemFacade import NemFacade
from symbolchain.nc import Amount
from symbolchain.nem.FeeCalculator import (
    calculate_namespace_rental_fee,
    calculate_transaction_fee
)

NODE_URL = os.getenv('NODE_URL', 'http://libertalia.nemtest.net:7890')
print(f'Using node {NODE_URL}')


# Helper function to announce a transaction
def announce_transaction(payload, label):
    announce_path = '/transaction/announce'
    print(f'Announcing {label} to {announce_path}')
    request = urllib.request.Request(
        f'{NODE_URL}{announce_path}',
        data=payload.encode(),
        headers={'Content-Type': 'application/json'},
        method='POST'
    )
    with urllib.request.urlopen(request) as announce_response:
        result = json.loads(announce_response.read().decode())
    print(f'  Result: {result["message"]}')
    return result['message']


# Helper function to wait for transaction confirmation
def wait_for_confirmation(tx_hash, label):
    status_path = f'/transaction/get?hash={tx_hash}'
    print(f'Waiting for {label} confirmation from {status_path}')
    is_confirmed = False
    for _ in range(120):
        try:
            with urllib.request.urlopen(
                f'{NODE_URL}{status_path}'
            ) as status_response:
                confirmed = json.loads(status_response.read().decode())
                height = confirmed['meta']['height']
                print(f'{label} confirmed in block {height}')
                is_confirmed = True
                break
        except urllib.error.HTTPError:
            print('  Transaction status: pending')
        time.sleep(1)
    if not is_confirmed:
        print(f'{label} confirmation took too long.')


SIGNER_PRIVATE_KEY = os.getenv(
    'SIGNER_PRIVATE_KEY',
    '0000000000000000000000000000000000000000000000000000000000000000')
signer_key_pair = NemFacade.KeyPair(PrivateKey(SIGNER_PRIVATE_KEY))

facade = NemFacade('testnet')
signer_address = facade.network.public_key_to_address(
    signer_key_pair.public_key)
print(f'Signer address: {signer_address}')

try:
    # Choose the subnamespace name
    root_namespace_name = os.getenv('ROOT_NAMESPACE', 'ns_root')
    child_namespace_name = os.getenv(
        'SUBNAMESPACE', f'sub_{int(time.time())}')
    full_namespace_name = (
        f'{root_namespace_name}.{child_namespace_name}')
    print(f'Creating subnamespace: {full_namespace_name}')

    # Build the transaction
    rental_fee = calculate_namespace_rental_fee(False)
    print(f'  Namespace lease fee: {rental_fee / 1_000_000} XEM')

    transaction = facade.create_transaction_from_descriptor({
        'type': 'namespace_registration_transaction_v1',
        'rental_fee_sink': 'TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35',
        'rental_fee': rental_fee,
        'name': child_namespace_name,
        'parent_name': root_namespace_name
    }, signer_key_pair.public_key, 0, 2 * 60 * 60)

    fee = calculate_transaction_fee(transaction)
    transaction.fee = Amount(fee)
    print(f'  Transaction fee: {fee / 1_000_000} XEM')

    # Sign transaction and generate final payload
    signature = facade.sign_transaction(signer_key_pair, transaction)
    json_payload = facade.transaction_factory.attach_signature(
        transaction, signature)
    print('Built transaction:')
    print(json.dumps(transaction.to_json(), indent=2))
    transaction_hash = facade.hash_transaction(transaction)
    print(f'Transaction hash: {transaction_hash}')

    # Announce the transaction
    announce_result = announce_transaction(
        json_payload, 'namespace registration')

    # Wait for confirmation
    if 'SUCCESS' == announce_result:
        wait_for_confirmation(transaction_hash, 'namespace registration')
    else:
        print(f'Transaction rejected: {announce_result}')
    # Retrieve the namespace
    namespace_path = f'/namespace?namespace={full_namespace_name}'
    print(f'Fetching namespace information from {namespace_path}')
    with urllib.request.urlopen(
        f'{NODE_URL}{namespace_path}'
    ) as response:
        namespace_info = json.loads(response.read().decode())
        print('Namespace information:')
        print(f'  Name: {namespace_info["fqn"]}')
        print(f'  Owner: {namespace_info["owner"]}')
        print(f'  Registration height: {namespace_info["height"]}')

except Exception as error:
    print(error)

Download source

import { PrivateKey } from 'symbol-sdk';
import {
    Address,
    NemFacade,
    calculateNamespaceRentalFee,
    calculateTransactionFee,
    descriptors,
    models
} from 'symbol-sdk/nem';

const NODE_URL = process.env.NODE_URL ||
    'http://libertalia.nemtest.net:7890';
console.log('Using node', NODE_URL);

// Helper function to announce a transaction
async function announceTransaction(payload, label) {
    const announcePath = '/transaction/announce';
    console.log(`Announcing ${label} to ${announcePath}`);
    const response = await fetch(`${NODE_URL}${announcePath}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: payload
    });
    if (!response.ok)
        throw new Error(`HTTP ${response.status}`);
    const result = await response.json();
    console.log('  Result:', result.message);
    return result.message;
}

// Helper function to wait for transaction confirmation
async function waitForConfirmation(transactionHash, label) {
    const statusPath = `/transaction/get?hash=${transactionHash}`;
    console.log(`Waiting for ${label} confirmation from`, statusPath);
    let isConfirmed = false;
    for (let attempt = 1; 120 >= attempt; ++attempt) {
        const response = await fetch(`${NODE_URL}${statusPath}`);
        if (!response.ok) {
            console.log('  Transaction status: pending');
            await new Promise(resolve => { setTimeout(resolve, 1000); });
        } else {
            const confirmed = await response.json();
            console.log(`${label} confirmed in block`,
                confirmed.meta.height);
            isConfirmed = true;
            break;
        }
    }
    if (!isConfirmed)
        console.warn(`${label} confirmation took too long.`);
}

const SIGNER_PRIVATE_KEY = process.env.SIGNER_PRIVATE_KEY ||
    '0000000000000000000000000000000000000000000000000000000000000000';
const signerKeyPair = new NemFacade.KeyPair(
    new PrivateKey(SIGNER_PRIVATE_KEY));

const facade = new NemFacade('testnet');
const signerAddress = facade.network.publicKeyToAddress(
    signerKeyPair.publicKey);
console.log('Signer address:', signerAddress.toString());

try {
    // Choose the subnamespace name
    const rootNamespaceName = process.env.ROOT_NAMESPACE || 'ns_root';
    const childNamespaceName = process.env.SUBNAMESPACE ||
        `sub_${Math.floor(Date.now() / 1000)}`;
    const fullNamespaceName =
        `${rootNamespaceName}.${childNamespaceName}`;
    console.log('Creating subnamespace:', fullNamespaceName);

    // Build the transaction
    const rentalFee = calculateNamespaceRentalFee(false);
    console.log('  Namespace lease fee:',
        `${Number(rentalFee) / 1_000_000} XEM`);

    const transaction = facade.createTransactionFromTypedDescriptor(
        new descriptors.NamespaceRegistrationTransactionV1Descriptor(
            new Address('TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35'),
            new models.Amount(rentalFee),
            childNamespaceName,
            rootNamespaceName),
        signerKeyPair.publicKey,
        0n,
        2 * 60 * 60);

    const fee = calculateTransactionFee(transaction);
    transaction.fee = new models.Amount(fee);
    console.log(`  Transaction fee: ${Number(fee) / 1_000_000} XEM`);

    // Sign transaction and generate final payload
    const signature = facade.signTransaction(signerKeyPair, transaction);
    const jsonPayload = facade.transactionFactory.static.attachSignature(
        transaction, signature);
    console.log('Built transaction:');
    console.dir(transaction.toJson(), { colors: true });
    const transactionHash = facade.hashTransaction(transaction).toString();
    console.log('Transaction hash:', transactionHash);

    // Announce the transaction
    const announceResult = await announceTransaction(
        jsonPayload, 'namespace registration');

    // Wait for confirmation
    if ('SUCCESS' === announceResult)
        await waitForConfirmation(transactionHash, 'namespace registration');
    else
        console.log('Transaction rejected:', announceResult);
    // Retrieve the namespace
    const namespacePath = `/namespace?namespace=${fullNamespaceName}`;
    console.log('Fetching namespace information from', namespacePath);
    const namespaceResponse = await fetch(`${NODE_URL}${namespacePath}`);
    const namespaceInfo = await namespaceResponse.json();
    console.log('Namespace information:');
    console.log('  Name:', namespaceInfo.fqn);
    console.log('  Owner:', namespaceInfo.owner);
    console.log('  Registration height:', namespaceInfo.height);

} catch (e) {
    console.error(e.message, '| Cause:', e.cause?.code ?? 'unknown');
}

Download source

//JAVA 21+
//DEPS org.symbol:symbol-sdk:3.3.3

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.IOException;
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 com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.symbol.sdk.CryptoTypes;
import org.symbol.sdk.facade.NemFacade;
import org.symbol.sdk.nem.Address;
import org.symbol.sdk.nem.FeeCalculator;
import org.symbol.sdk.nem.KeyPair;
import org.symbol.sdk.nem.NemTransactionFactory;
import org.symbol.sdk.nem.descriptors.*;
import org.symbol.sdk.nem.models.Amount;
import org.symbol.sdk.nem.models.Transaction;

public final class RegisterSubnamespace {
    private static final ObjectMapper JSON_MAPPER = new ObjectMapper();

    private static final HttpClient HTTP_CLIENT =
        HttpClient.newHttpClient();

    private final String nodeUrl = System.getenv().getOrDefault(
        "NODE_URL", "http://libertalia.nemtest.net:7890");

    private final NemFacade facade = new NemFacade("testnet");

    private String announceTransaction(
        final String payload,
        final String label
    ) throws IOException, InterruptedException {
        final String announcePath = "/transaction/announce";
        System.out.printf("Announcing %s to %s%n", label, announcePath);
        final HttpRequest request = HttpRequest.newBuilder(
            URI.create(nodeUrl + announcePath))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(payload))
            .build();
        final HttpResponse<String> response = HTTP_CLIENT.send(
            request, BodyHandlers.ofString());
        if (2 != response.statusCode() / 100)
            throw new IOException("HTTP " + response.statusCode());
        final String result = JSON_MAPPER.readTree(response.body())
            .get("message").asText();
        System.out.printf("  Result: %s%n", result);
        return result;
    }

    private void waitForConfirmation(
        final String transactionHash,
        final String label
    ) throws IOException, InterruptedException {
        final String statusPath = String.format(
            "/transaction/get?hash=%s", transactionHash);
        System.out.printf("Waiting for %s confirmation from %s%n",
            label, statusPath);
        boolean isConfirmed = false;
        for (int attempt = 1; 120 >= attempt; ++attempt) {
            final HttpRequest request = HttpRequest.newBuilder(
                URI.create(nodeUrl + statusPath)).GET().build();
            final HttpResponse<String> response = HTTP_CLIENT.send(
                request, BodyHandlers.ofString());
            if (2 != response.statusCode() / 100) {
                System.out.println("  Transaction status: pending");
                Thread.sleep(1000);
            } else {
                final JsonNode confirmed = JSON_MAPPER.readTree(
                    response.body());
                System.out.printf("%s confirmed in block %s%n", label,
                    confirmed.get("meta").get("height").asText());
                isConfirmed = true;
                break;
            }
        }
        if (!isConfirmed)
            System.out.printf("%s confirmation took too long.%n", label);
    }

    public static void main(final String[] args) {
        try {
            new RegisterSubnamespace().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", nodeUrl);

        final String privateKey = System.getenv().getOrDefault(
            "SIGNER_PRIVATE_KEY", "0".repeat(64));
        final KeyPair signerKeyPair = new KeyPair(
            new CryptoTypes.PrivateKey(privateKey));
        System.out.printf("Signer address: %s%n",
            facade.network.publicKeyToAddress(
                signerKeyPair.getPublicKey()));

        // Choose the subnamespace name
        final String rootNamespaceName = System.getenv().getOrDefault(
            "ROOT_NAMESPACE",
            "ns_root");
        final String childNamespaceName = System.getenv().getOrDefault(
            "SUBNAMESPACE",
            "sub_" + System.currentTimeMillis() / 1000);
        final String fullNamespaceName =
            rootNamespaceName + "." + childNamespaceName;
        System.out.printf("Creating subnamespace: %s%n",
            fullNamespaceName);

        // Build the transaction
        final long rentalFee = FeeCalculator.calculateNamespaceRentalFee(
            false);
        System.out.printf("  Namespace lease fee: %s XEM%n",
            (double) rentalFee / 1_000_000);
        final Transaction transaction =
            facade.createTransactionFromTypedDescriptor(
                new NamespaceRegistrationTransactionV1Descriptor(
                    new Address(
                        "TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35"),
                    new Amount(rentalFee),
                    childNamespaceName.getBytes(UTF_8),
                    rootNamespaceName.getBytes(UTF_8)),
                signerKeyPair.getPublicKey(), 0, 2 * 60 * 60);

        final long fee = FeeCalculator.calculateTransactionFee(
            transaction);
        transaction.setFee(new Amount(fee));
        System.out.printf("  Transaction fee: %s XEM%n",
            (double) fee / 1_000_000);

        // Sign transaction and generate final payload
        final CryptoTypes.Signature signature = facade.signTransaction(
            signerKeyPair, transaction);
        final String payload = NemTransactionFactory.attachSignature(
            transaction, signature);
        System.out.println("Built transaction:");
        System.out.println(JSON_MAPPER.writerWithDefaultPrettyPrinter()
            .writeValueAsString(transaction.toJson()));
        final String transactionHash = facade.hashTransaction(transaction)
            .toString();
        System.out.printf("Transaction hash: %s%n", transactionHash);
        final String result = announceTransaction(
            payload, "namespace registration");
        // Wait for confirmation
        if ("SUCCESS".equals(result))
            waitForConfirmation(
                transactionHash, "namespace registration");
        else
            System.out.printf("Transaction rejected: %s%n", result);
        // Retrieve the namespace
        final String path = "/namespace?namespace=" + fullNamespaceName;
        System.out.printf(
            "Fetching namespace information from %s%n", path);
        final HttpRequest request = HttpRequest.newBuilder(
            URI.create(nodeUrl + path)).GET().build();
        final HttpResponse<String> response = HTTP_CLIENT.send(
            request, BodyHandlers.ofString());
        final JsonNode info = JSON_MAPPER.readTree(response.body());
        System.out.println("Namespace information:");
        System.out.printf("  Name: %s%n", info.get("fqn").asText());
        System.out.printf("  Owner: %s%n", info.get("owner").asText());
        System.out.printf("  Registration height: %s%n",
            info.get("height").asText());

    }
}

Download source

コードの説明⚓︎

コードは ルートネームスペースを登録する チュートリアルと同じパターンに従います。 このセクションでは、主な違いだけに焦点を当てます。

共通手順(アカウントのセットアップ、トランザクションの作成、アナウンス)とルートネームスペースで共有されるトランザクションディスクリプタフィールドの詳細な説明については、ルートネームスペースを登録する を参照してください。

サブネームスペース名を設定する⚓︎

    # Choose the subnamespace name
    root_namespace_name = os.getenv('ROOT_NAMESPACE', 'ns_root')
    child_namespace_name = os.getenv(
        'SUBNAMESPACE', f'sub_{int(time.time())}')
    full_namespace_name = (
        f'{root_namespace_name}.{child_namespace_name}')
    print(f'Creating subnamespace: {full_namespace_name}')
    // Choose the subnamespace name
    const rootNamespaceName = process.env.ROOT_NAMESPACE || 'ns_root';
    const childNamespaceName = process.env.SUBNAMESPACE ||
        `sub_${Math.floor(Date.now() / 1000)}`;
    const fullNamespaceName =
        `${rootNamespaceName}.${childNamespaceName}`;
    console.log('Creating subnamespace:', fullNamespaceName);
        // Choose the subnamespace name
        final String rootNamespaceName = System.getenv().getOrDefault(
            "ROOT_NAMESPACE",
            "ns_root");
        final String childNamespaceName = System.getenv().getOrDefault(
            "SUBNAMESPACE",
            "sub_" + System.currentTimeMillis() / 1000);
        final String fullNamespaceName =
            rootNamespaceName + "." + childNamespaceName;
        System.out.printf("Creating subnamespace: %s%n",
            fullNamespaceName);

サブネームスペースは、親ネームスペース名と子名をドットでつないだ完全な名前で識別します(ns_root.product など)。 命名規則については、テキストブックの 名前 を参照してください。

チュートリアルを複数回実行したときの衝突を避けるため、子名にタイムスタンプを追加します。 ただし、実際のプログラムでは、サブネームスペースに固定名を使用します。 ROOT_NAMESPACE と SUBNAMESPACE 環境変数を使うと、チュートリアルで固定名を使用できます。

署名者が所有する親ネームスペースを使用してください

デフォルトでは、コードは SIGNER_PRIVATE_KEY が参照するテストアカウントと、ns_root という親ネームスペースを使用します。

ルートネームスペースを登録する チュートリアルから続けている場合は、SIGNER_PRIVATE_KEY と ROOT_NAMESPACE 環境変数を、そこで作成したアカウントとネームスペース、または署名者が所有する別のネームスペースに合わせて設定してください。

トランザクションを構築する⚓︎

    # Build the transaction
    rental_fee = calculate_namespace_rental_fee(False)
    print(f'  Namespace lease fee: {rental_fee / 1_000_000} XEM')

    transaction = facade.create_transaction_from_descriptor({
        'type': 'namespace_registration_transaction_v1',
        'rental_fee_sink': 'TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35',
        'rental_fee': rental_fee,
        'name': child_namespace_name,
        'parent_name': root_namespace_name
    }, signer_key_pair.public_key, 0, 2 * 60 * 60)

    fee = calculate_transaction_fee(transaction)
    transaction.fee = Amount(fee)
    print(f'  Transaction fee: {fee / 1_000_000} XEM')
    // Build the transaction
    const rentalFee = calculateNamespaceRentalFee(false);
    console.log('  Namespace lease fee:',
        `${Number(rentalFee) / 1_000_000} XEM`);

    const transaction = facade.createTransactionFromTypedDescriptor(
        new descriptors.NamespaceRegistrationTransactionV1Descriptor(
            new Address('TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35'),
            new models.Amount(rentalFee),
            childNamespaceName,
            rootNamespaceName),
        signerKeyPair.publicKey,
        0n,
        2 * 60 * 60);

    const fee = calculateTransactionFee(transaction);
    transaction.fee = new models.Amount(fee);
    console.log(`  Transaction fee: ${Number(fee) / 1_000_000} XEM`);
        // Build the transaction
        final long rentalFee = FeeCalculator.calculateNamespaceRentalFee(
            false);
        System.out.printf("  Namespace lease fee: %s XEM%n",
            (double) rentalFee / 1_000_000);
        final Transaction transaction =
            facade.createTransactionFromTypedDescriptor(
                new NamespaceRegistrationTransactionV1Descriptor(
                    new Address(
                        "TAMESPACEWH4MKFMBCVFERDPOOP4FK7MTDJEYP35"),
                    new Amount(rentalFee),
                    childNamespaceName.getBytes(UTF_8),
                    rootNamespaceName.getBytes(UTF_8)),
                signerKeyPair.getPublicKey(), 0, 2 * 60 * 60);

        final long fee = FeeCalculator.calculateTransactionFee(
            transaction);
        transaction.setFee(new Amount(fee));
        System.out.printf("  Transaction fee: %s XEM%n",
            (double) fee / 1_000_000);

サブネームスペースを登録する場合の主な違いは、トランザクションディスクリプタにあります。

  • : 前の手順で設定したサブネームスペースの名前。

    これはサブネームスペースの名前だけで、完全なパスではないことに注意してください。 例えば、ルートが company の company.product を作成する場合は、 と を設定します。

  • : 前の手順で定義した親ネームスペースの名前。 ルートネームスペースでも、別のサブネームスペースでも構いません。

  • : サブネームスペースのレンタル手数料である 10 XEM。ルートネームスペースと同じ シンクアカウント に支払います。

    SDK の ヘルパーは、必要な金額を返します。 引数は、サブネームスペースの手数料を要求します。

その後、ルートネームスペースを登録する チュートリアルと同じ手順で、トランザクションに署名し、アナウンスして、承認を待ちます。 ファサードは署名者を追加し、2 時間のデッドライン期間からタイムスタンプとデッドラインを導出します。

サブネームスペースを取得する⚓︎

    # Retrieve the namespace
    namespace_path = f'/namespace?namespace={full_namespace_name}'
    print(f'Fetching namespace information from {namespace_path}')
    with urllib.request.urlopen(
        f'{NODE_URL}{namespace_path}'
    ) as response:
        namespace_info = json.loads(response.read().decode())
        print('Namespace information:')
        print(f'  Name: {namespace_info["fqn"]}')
        print(f'  Owner: {namespace_info["owner"]}')
        print(f'  Registration height: {namespace_info["height"]}')
    // Retrieve the namespace
    const namespacePath = `/namespace?namespace=${fullNamespaceName}`;
    console.log('Fetching namespace information from', namespacePath);
    const namespaceResponse = await fetch(`${NODE_URL}${namespacePath}`);
    const namespaceInfo = await namespaceResponse.json();
    console.log('Namespace information:');
    console.log('  Name:', namespaceInfo.fqn);
    console.log('  Owner:', namespaceInfo.owner);
    console.log('  Registration height:', namespaceInfo.height);
        // Retrieve the namespace
        final String path = "/namespace?namespace=" + fullNamespaceName;
        System.out.printf(
            "Fetching namespace information from %s%n", path);
        final HttpRequest request = HttpRequest.newBuilder(
            URI.create(nodeUrl + path)).GET().build();
        final HttpResponse<String> response = HTTP_CLIENT.send(
            request, BodyHandlers.ofString());
        final JsonNode info = JSON_MAPPER.readTree(response.body());
        System.out.println("Namespace information:");
        System.out.printf("  Name: %s%n", info.get("fqn").asText());
        System.out.printf("  Owner: %s%n", info.get("owner").asText());
        System.out.printf("  Registration height: %s%n",
            info.get("height").asText());

サブネームスペースが登録されたことを確認するため、コードは /namespace GET エンドポイントを使ってネットワークから取得し、そのプロパティを表示します。

サブネームスペースは、親名と子名をドットでつないだ完全な名前で照会します(例: ns_root.sub_1783411728)。

成功したレスポンスは、サブネームスペースが登録されてアクティブになったことを確認します。

レスポンスには登録時の高さも表示されます。サブネームスペースはルートネームスペースの リース を継承するため、これはルートネームスペースが登録されたブロックの高さです。

サブネームスペースの期間

サブネームスペースはルートネームスペースの期限切れと同時に期限切れになり、単独で更新することはできません。 ルートネームスペースを更新する と、サブネームスペースも更新されます。

出力⚓︎

以下は、プログラムの実行時の出力例です。

Using node http://libertalia.nemtest.net:7890
Signer address: TBONKWCOWBZYZB2I5JD3LSDBQVBYHB757VN3SKPP
Creating subnamespace: ns_root.sub_1783411728
  Namespace lease fee: 10.0 XEM
  Transaction fee: 0.15 XEM
Built transaction:
{
  "type": 8193,
  "version": 1,
  "network": 152,
  "timestamp": 355824143,
  "signer_public_key": "462EE976890916E54FA825D26BDD0235F5EB5B6A143C199AB0AE5EE9328E08CE",
  "signature": "EB8065E0D51173189950A7F28863135AA2E308B1F9A32840BCF48E85F15E0DD0AC48D8B6999D2BEDDC4B934842F93C9C4B4AFF28820CFA3B7EE73FE09B3D2303",
  "fee": "150000",
  "deadline": 355831343,
  "rental_fee_sink": "54414D4553504143455748344D4B464D42435646455244504F4F5034464B374D54444A4559503335",
  "rental_fee": "10000000",
  "name": "7375625f31373833343131373238",
  "parent_name": "6e735f726f6f74"
}
Transaction hash: 79C4412BC6A9AA73DB37AD01ECDC84A17926FB5E152979FFDCCFE567EC4F63ED
Announcing namespace registration to /transaction/announce
  Result: SUCCESS
Waiting for namespace registration confirmation from /transaction/get?hash=79C4412BC6A9AA73DB37AD01ECDC84A17926FB5E152979FFDCCFE567EC4F63ED
  Transaction status: pending
  Transaction status: pending
  Transaction status: pending
namespace registration confirmed in block 690650
Fetching namespace information from /namespace?namespace=ns_root.sub_1783411728
Namespace information:
  Name: ns_root.sub_1783411728
  Owner: TBONKWCOWBZYZB2I5JD3LSDBQVBYHB757VN3SKPP
  Registration height: 690649

出力の要点は次のとおりです。

  • 完全なネームスペースパス(3 行目): ns_root.sub_1783411728 は、親ネームスペース ns_root とトランザクションで設定したサブネームスペース名を組み合わせたものです。

  • レンタル手数料とトランザクション手数料(4~5 行目): サブネームスペースなのでレンタル手数料は 10 XEM です(ルートネームスペースは代わりに 100 XEM を支払います)。トランザクション手数料は 0.15 XEM です。

  • ネームスペース情報(31~33 行目): 登録されたサブネームスペース、その所有者(署名者のアドレス)、登録時の高さ。ルートネームスペースのリースが開始したブロックの高さをサブネームスペースが継承しています。

まとめ⚓︎

このチュートリアルでは、次の方法を説明しました。

手順 関連ドキュメント
サブネームスペース登録トランザクションを構築する 、NamespaceRegistrationTransactionV1
レンタル手数料を計算する
サブネームスペースを取得する /namespace GET

次のステップ⚓︎

サブネームスペースを取得できたので、次のことを行えます。

  • 追加のサブネームスペースを登録して、階層構造を拡張する
  • モザイクを定義する ことで、サブネームスペースの下にカスタム資産を作成する