5
1

More than 1 year has passed since last update.

symbol-sdk@3.0.7を試してみる

Last updated at Posted at 2023-07-05

はじめに

こんにちは。symbol-sdkの3系が手軽に利用できるようになりましたね。

npmでは、執筆時点で3.0.7が公開されています。

では、少し触ってみようと思います。

インストール

今回はブラウザではなくて、Node.jsの環境で実施します。

以下

npm i symbol-sdk

のコマンドで、

"symbol-sdk": "^3.0.7"

が入りました。rxjsはいらないみたいです。

また、REST Gatewayとの通信のためにaxiosをインストールしておきます。

npm i axios

Typescriptは使えない

最初Typescriptで始めようとしたら、コンパイルでこけました。どうやらTypescriptは対応していないようです。

> tsc

src/index.ts:1:23 - error TS7016: Could not find a declaration file for module 'symbol-sdk'. '/node_modules/symbol-sdk/src/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/symbol-sdk` if it exists or add a new declaration (.d.ts) file containing `declare module 'symbol-sdk';`

Typescriptについては詳しくはないのですが、型定義を作成すると使えるようになるのかな、と思います。

ですので、以下はJavaScriptで進めようと思います。

転送トランザクションサンプル

情報を収集する

epoch adjustmentやモザイクID、ネットワークIDを取得していきます。

const node = axios.create({
  baseURL: NODE_URL,
  timeout: 1000,
  headers: { 'Content-Type': 'application/json' }
});

const networkProperties = await node.get('/network/properties').then((res) => res.data);

const epochAdjustment = BigInt(networkProperties.network.epochAdjustment.slice(0, -1)) * 1000n;
// 1667250467000n

const currencyMosaicId = BigInt(networkProperties.chain.currencyMosaicId.replace(/'/g, ''));
// 0x72C0212E67A08BCEn

const symbolNetwork = networkProperties.network.identifier;
// 'testnet'

Facadeを生成する

symbol用のfacadeを生成します。このfacadeを使ってsymbol固有の処理を実行していきます。

const facade = new symbolSdk.facade.SymbolFacade(symbolNetwork);

トランザクションを作成する

ここは2系のものと大きくは変わっていません。

const privateKey = new symbolSdk.PrivateKey(PRIVATE_KEY);
const keyPair = new facade.constructor.KeyPair(privateKey);

const transaction = facade.transactionFactory.create({
  type: 'transfer_transaction_v1',
  signerPublicKey: keyPair.publicKey.toString(),
  fee: 1000000n,
  deadline: BigInt(Date.now()) - epochAdjustment + 7200000n,
  recipientAddress: ADDRESS_RECEIVER_1,
  mosaics: [
    { mosaicId: currencyMosaicId, amount: 1000000n }
  ]
});

署名してハッシュを計算する

この辺りも2系のものと大きくは変わっていませんが、少し難しくなりましたかね。

jsonPayloadには、トランザクションのバイト列が入っています。これをそのままの形でREST Gatewayに送信することになります。

const signature = facade.signTransaction(keyPair, transaction);

const jsonPayload = facade.transactionFactory.constructor.attachSignature(transaction, signature);

const hash = facade.hashTransaction(transaction).toString();

console.log(jsonPayload);
// '{ "payload": "B000000000000000F514132000..." }'

console.log(hash);
// "D9140C1F85150ED9A0BE92DB18BBA02401AC6788B0D11DA190C50011FBD09C14"

ここでジェネレーションハッシュを入力していませんが、SDKの中に直に書かれていました。

送信する

REST Gatewayのエンドポイントへ送信します。

const response = await node.put("/transactions", jsonPayload).then((res) => res.data);

console.log(response);
// { message: 'packet 9 was pushed to the network via /transactions' }

確認する

SDKでは、情報を取得するためのものが無いため、自らREST Gatewayに問い合わせる必要があります。

トランザクションステータス

const statusRes = await node.get("/transactionStatus/" + hash).then((res) => res.data);

console.log(statusRes);

このようなデータが返ってきます。

{
  group: 'unconfirmed',
  code: 'Success',
  hash: 'F80F27E817288971AB533EAA9EF6DD846DECD0305734E047C04FC6BFEFCAE327',
  deadline: '16032354275',
  height: '0'
}

承認されていたら、こうなります。

{
  group: 'confirmed',
  code: 'Success',
  hash: 'F80F27E817288971AB533EAA9EF6DD846DECD0305734E047C04FC6BFEFCAE327',
  deadline: '16032354275',
  height: '436904'
}

トランザクション詳細

また、トランザクション承認後は、以下のエンドポイントが利用可能になりますね。

const hash = "F80F27E817288971AB533EAA9EF6DD846DECD0305734E047C04FC6BFEFCAE327"

const confirmedRes = await node.get("/transactions/confirmed/" + hash).then((res) => res.data);
console.log(confirmedRes);

コード全体

  • 全体のコードです。
import symbolSdk from 'symbol-sdk';
import axios from 'axios';
import {
  NODE_URL,
  ADDRESS_RECEIVER_1,
  PRIVATE_KEY,
} from './env.js';

const node = axios.create({
  baseURL: NODE_URL,
  timeout: 1000,
  headers: { 'Content-Type': 'application/json' }
});

const networkProperties = await node.get('/network/properties').then((res) => res.data);

const epochAdjustment = BigInt(networkProperties.network.epochAdjustment.slice(0, -1)) * 1000n;
const currencyMosaicId = BigInt(networkProperties.chain.currencyMosaicId.replace(/'/g, ''));
const symbolNetwork = networkProperties.network.identifier;

const facade = new symbolSdk.facade.SymbolFacade(symbolNetwork);

const privateKey = new symbolSdk.PrivateKey(PRIVATE_KEY);
const keyPair = new facade.constructor.KeyPair(privateKey);

const transaction = facade.transactionFactory.create({
  type: 'transfer_transaction_v1',
  signerPublicKey: keyPair.publicKey.toString(),
  fee: 1000000n,
  deadline: BigInt(Date.now()) - epochAdjustment + 7200000n,
  recipientAddress: ADDRESS_RECEIVER_1,
  mosaics: [
    { mosaicId: currencyMosaicId, amount: 1000000n }
  ]
});

const signature = facade.signTransaction(keyPair, transaction);
const jsonPayload = facade.transactionFactory.constructor.attachSignature(transaction, signature);
const hash = facade.hashTransaction(transaction).toString();

console.log(jsonPayload);
console.log(hash);

const sendRes = await node.put("/transactions", jsonPayload).then((res) => res.data);
console.log(sendRes);

await new Promise((resolve) => setTimeout(resolve, 1000));

const statusRes = await node.get("/transactionStatus/" + hash).then((res) => res.data);
console.log(statusRes);

補足

ネットワーク情報やデッドラインの作成方法がいくつかあるみたいでした。

import symbolSdk from 'symbol-sdk';

const network = symbolSdk.symbol.Network.TESTNET;

とすることで、Symbolテストネットのネットネット情報にアクセスできるようです。

const network = symbolSdk.symbol.Network.MAINNET;

とすれば、メインネット。

他には、このような方法も見つかりました。

const network = symbolSdk.NetworkLocator.findByName(symbolSdk.symbol.Network.NETWORKS, 'testnet');

これを使って、2時間のデッドラインを計算するには、以下のようにします。

const deadline = network.fromDatetime(new Date(Date.now() + 7200000)).timestamp;
// 16034333219n

7200000は、2時間をミリ秒に直した数値です。

おわりに

新しくなったsymbol-sdkにて、転送トランザクションを送信することをやってみました。少し難しくなった印象がありますね。その分、SDK自体は軽くなっているような気がします。

5
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
5
1