LoginSignup
4
1

More than 1 year has passed since last update.

JavaでもSymbolブロックチェーン~送金編~

Last updated at Posted at 2021-06-11

Symbol from NEMではエンタープライズ分野で人気のあるJava言語でも使用することができます。

今回はJavaでSymbol送金を体験してみましょう。

まず、公式の案内通りにGradleの準備をします(Gradle 7.0 以上)

ここで

dependencies {
    compile "io.nem:symbol-sdk-vertx-client"
}

とありますが、これでは動きません。
implementation 'io.nem:symbol-sdk-vertx-client:1.0.0'
と読み替えてください。

gradle run が実行できるようになったらApp.javaを書き換えていきます。

基本プログラム

package symbol_test;

public class App  {

    public static void main(String[] args) throws Exception {
        run();
    }

    public String getGreeting() {
        return "Hello Symbol!";
    }

    private static void run() throws Exception {
        Thread.sleep(1000);
        run();
    }
}

これが基本フォーマットになります。
public static void mainからプログラムが開始され runで強制終了されるまでループします。
送金プログラムだけの場合はループは必要ありませんが、着金を検知するためにループで待機しています。

import

今回使用するライブラリです。

import java.time.Duration;
import java.math.BigInteger;
import java.util.Collections;

import io.nem.symbol.sdk.api.Listener;
import io.nem.symbol.sdk.api.RepositoryFactory;
import io.nem.symbol.sdk.api.TransactionRepository;
import io.nem.symbol.sdk.model.account.Address;
import io.nem.symbol.sdk.model.account.Account;
import io.nem.symbol.sdk.model.mosaic.Mosaic;
import io.nem.symbol.sdk.model.mosaic.MosaicId;
import io.nem.symbol.sdk.model.message.PlainMessage;
import io.nem.symbol.sdk.model.network.NetworkType;
import io.nem.symbol.sdk.model.transaction.Deadline;
import io.nem.symbol.sdk.model.transaction.Transaction;
import io.nem.symbol.sdk.model.transaction.SignedTransaction;
import io.nem.symbol.sdk.model.transaction.TransferTransaction;
import io.nem.symbol.sdk.model.transaction.TransferTransactionFactory;
import io.nem.symbol.sdk.infrastructure.vertx.RepositoryFactoryVertxImpl;

python版では対話式に都度ライブラリを追加していきましたが、
Javaでは最初に宣言しておきます。

リポジトリ生成

RepositoryFactory repo = new RepositoryFactoryVertxImpl(
    "http://ngl-dual-101.testnet.symboldev.network:3000"
);

接続するノードを指定してレポジトリを生成します。

アカウント生成

Account alice = Account.createFromPrivateKey(
    "896E43895B908AF5847ECCB2645543751D94BD87E71058B003417FED512****", 
    NetworkType.TEST_NET
);
System.out.printf("Alice address is: %s \n",alice.getAddress().plain());

Account bob = Account.generateNewAccount(NetworkType.TEST_NET);
System.out.printf("Bob address is: %s \n",bob.getAddress().plain());

送金者Aliceと受信者Bobを生成します。送信者は残高を持つ秘密鍵から生成。Bobはランダムに生成しました。

トークン定義

BigInteger amount = BigInteger.valueOf(1);

Mosaic mosaic = new Mosaic(
    new MosaicId("091F837E059AE13C"),
    amount.multiply(
        BigInteger.valueOf(10).pow(6)
    )
);

送金するトークンを定義します。
テストネットのXYMはID:091F837E059AE13C 可分性:6で定義されています。
公式ドキュメントは古いテストネットのIDで解説されているのでご注意ください。

トランザクション生成

TransferTransaction tx = TransferTransactionFactory.create(
        NetworkType.TEST_NET,
        Deadline.create(repo.getEpochAdjustment().toFuture().get()),
        bob.getAddress(),
        Collections.singletonList(mosaic)
).message(
    PlainMessage.create("This is a test message")
).maxFee(BigInteger.valueOf(2000000)
).build();

送金トランザクションを生成します。
このあたりは公式ドキュメントの情報が古いので、少し変更が必要です。
- Deadlineを指定してください(引数にはネットワークのエポックタイムの指定が必要です)。
- メッセージはcreateの引数ではなく、メソッドチェーンで追加していきます。

署名とアナウンス

String generationHash = repo.getGenerationHash().toFuture().get();
SignedTransaction signedTx = alice.sign(tx, generationHash);

System.out.printf("SignedTransaction is: %s ",signedTx.getHash());

TransactionRepository txRepo = repo.createTransactionRepository();
txRepo.announce(signedTx).toFuture().get();

作成したトランザクションをAliceで署名してネットワークにアナウンスします。

着金検知

Listener listener = repo.createListener();
listener.open().get();

listener.confirmed(bob.getAddress())
.subscribe(
    (notice) -> { System.out.println(notice.getType().toString());},
    (e) -> { System.out.println(e);}
);

リスナークラスを利用してBobへの着金を検知します。
Listener.confirmedで承認されたトランザクションが検知できます。

この書き方はVistiel Archさんの記事を参考にさせていただきました。

また、nabe3さんがJava版マイクラでXYMを送金するプラグインを実装した記事を公開されています。

最後に全ソースコードを載せておきます。
ぜひみなさん、お試しください!

package symbol_test;

import java.time.Duration;
import java.math.BigInteger;
import java.util.Collections;

import io.nem.symbol.sdk.api.Listener;
import io.nem.symbol.sdk.api.RepositoryFactory;
import io.nem.symbol.sdk.api.TransactionRepository;
import io.nem.symbol.sdk.model.account.Address;
import io.nem.symbol.sdk.model.account.Account;
import io.nem.symbol.sdk.model.mosaic.Mosaic;
import io.nem.symbol.sdk.model.mosaic.MosaicId;
import io.nem.symbol.sdk.model.message.PlainMessage;
import io.nem.symbol.sdk.model.network.NetworkType;
import io.nem.symbol.sdk.model.transaction.Deadline;
import io.nem.symbol.sdk.model.transaction.Transaction;
import io.nem.symbol.sdk.model.transaction.SignedTransaction;
import io.nem.symbol.sdk.model.transaction.TransferTransaction;
import io.nem.symbol.sdk.model.transaction.TransferTransactionFactory;
import io.nem.symbol.sdk.infrastructure.vertx.RepositoryFactoryVertxImpl;


public class App  {

    public static void main(String[] args) throws Exception {

        RepositoryFactory repo = new RepositoryFactoryVertxImpl(
            "http://ngl-dual-101.testnet.symboldev.network:3000"
        );

        Account alice = Account.createFromPrivateKey(
            "896E43895B908AF5847ECCB2645543751D94BD87E71058B003417FED512314AE", 
            NetworkType.TEST_NET
        );

        System.out.printf("Alice address is: %s \n",alice.getAddress().plain());

        Account bob = Account.generateNewAccount(NetworkType.TEST_NET);
        System.out.printf("Bob address is: %s \n",bob.getAddress().plain());

        BigInteger amount = BigInteger.valueOf(1);

        Mosaic mosaic = new Mosaic(
            new MosaicId("091F837E059AE13C"),
            amount.multiply(
                BigInteger.valueOf(10).pow(6)
            )
        );

        TransferTransaction tx = TransferTransactionFactory.create(
                NetworkType.TEST_NET,
                Deadline.create(repo.getEpochAdjustment().toFuture().get()),
                bob.getAddress(),
                Collections.singletonList(mosaic)
            ).message(
                PlainMessage.create("This is a test message")
            ).maxFee(BigInteger.valueOf(2000000)
            ).build();

        String generationHash = repo.getGenerationHash().toFuture().get();
        SignedTransaction signedTx = alice.sign(tx, generationHash);

        System.out.printf("SignedTransaction is: %s ",signedTx.getHash());

        TransactionRepository txRepo = repo.createTransactionRepository();
        txRepo.announce(signedTx).toFuture().get();

        Listener listener = repo.createListener();
        listener.open().get();

        listener.confirmed(bob.getAddress())
        .subscribe(
            (notice) -> { System.out.println(notice.getType().toString());},
            (e) -> { System.out.println(e);}
        );

        run();
    }

    public String getGreeting() {
        return "Hello Symbol!";
    }

    private static void run() throws Exception {
        Thread.sleep(1000);
        run();
    }
}


4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1