🔍

XRPレジャーのレジャーデータを取得する

2023/05/11に公開

XRPレジャー

パブリックな分散型のブロックチェーンであるXRPレジャーは2012年から7900万以上のレジャーをvalidateしてきました。

XRPLの各ノードはこれらのレジャーの一部またはほぼ全てを保持しており、APIメソッドを通じて取得することが可能です。

ledger_data

レジャーデータはledger_dataコマンドを利用して取得することができます。

取得するレジャーを指定するためにleder_hashまたはledger_indexを指定する必要があります。

ledger_hashにはそのレジャーを表すハッシュ値を指定します。

ledger_indexにはそのレジャーの番号を表すインデックス値を指定します。

ledger_indexは特殊な値として次の3つを指定することもできます。

  • validated: ネットワーク全体で検証された最新のレジャー
  • closed: 変更できないように閉鎖され、検証を提案されている最新のレジャー
  • current: サーバーで現在処理中のレジャーバージョン
コマンド例
{
  "command": "ledger_data",
  "ledger_index": 79657746,
  "limit": 10
}

このコマンドを利用し特定のレジャー番号のレジャーデータを取得することで、現在のアカウントの総数や、DEXへのオファーの状況などXRPレジャーの現在の情報全てを確認することができます。

ただし、レジャーデータ全体のサイズは1400オブジェクト/5000MB以上と非常に大きく、全データを取得するには独自ノードを利用したとしても数十分はかかると考えられます。また1リクエストで取得できるデータ数の制限もあるため公開ノードの利用は推奨されません。

独自ノードの建て方については以下の記事を参考にしてください。

https://qiita.com/tequ/items/2cde7d347e96280d49ae

マーカー(maker)

一部のメソッドではレスポンスデータが1レスポンスに納まらない場合があります。

そのような場合はレスポンスにmarkerフィールドが含まれ、次のレスポンス時にmakerを指定することでその続きからデータを取得できるようになります。

makerフィールドがレスポンスに含まれない場合は、以降のデータが存在しないことを表します。

コード例

今回はXRPレジャー向けのJavascriptライブラリであるxrpl.jsを使ってレジャーデータを取得します。

const { Client } = require("xrpl")

// メインネットノードに接続(今回はサンプルのため公開ノードを使用)
const client = new Client("wss://xrplcluster.com")

const main = async () => {

  await client.connect()

  let fetchsize = 0
  let response
  let ledger_index = "validated"
  let marker

  do {
    response = await client.request({
      command: "ledger_data",
      ledger_index,
      marker,
    })
    // "validated"で取得したレジャー番号を次の取得時に使用する
    ledger_index = response.result.ledger_index
    marker = response.result.marker
    // レジャーの内容を表示
    console.log(response.result)
    fetchsize =+ response.result.state.length
    if(fetchsize > 200) {
      // テストコードのため、200件以上取得したら終了とする
      break
    }
  } while (marker)

  client.disconnect()
}
main()

上記のコードを実行すると次のようなデータが得られます。

response.result
{
  ledger: {
    accepted: true,
    account_hash: '3554A209BD48F2CE1003E7EBC9FE6D12FC06365981FC0CF4A3D81238FD9AF14C',
    close_flags: 0,
    close_time: 737023651,
    close_time_human: '2023-May-10 08:47:31.000000000 UTC',
    close_time_resolution: 10,
    closed: true,
    hash: '7EBACBD6A3860FBC29CB3B5BAF776EE8645A6A514DCF0BB35BDE3B1FBDF439F7',
    ledger_hash: '7EBACBD6A3860FBC29CB3B5BAF776EE8645A6A514DCF0BB35BDE3B1FBDF439F7',
    ledger_index: '79677049',
    parent_close_time: 737023650,
    parent_hash: '1D688817199B62E3620CED9722C9292E69E9C2CDE12FCB52B4208564FF7E751B',
    seqNum: '79677049',
    totalCoins: '99988929567948054',
    total_coins: '99988929567948054',
    transaction_hash: '989B83E836B745B3CC96D0B46C1383DD21E1935E1E143059CFA9A7415A1AD094'
  },
  ledger_hash: '7EBACBD6A3860FBC29CB3B5BAF776EE8645A6A514DCF0BB35BDE3B1FBDF439F7',
  ledger_index: 79677049,
  marker: '0000072ABB2A5D985D088B0B8F7C912A3C46C3381B33ABC821A4456748EBB384|NONFH',
  state: [
    {
      Balance: [Object],
      Flags: 2228224,
      HighLimit: [Object],
      HighNode: '0',
      LedgerEntryType: 'RippleState',
      LowLimit: [Object],
      LowNode: '28',
      PreviousTxnID: '15092C52FEA9753B73E6BB5737CD358E3D2DBEC42E1E37568057A07D87EF853E',
      PreviousTxnLgrSeq: 71796374,
      index: '000000E42EDA8F440C16D376B5FC6DE1370CE38C8A5D2965107E8DDBEAF4B007'
    },
    {
      Account: 'rntkix7favBwHFeDPoM3kZXsz2n6a39v8B',
      Balance: '10000000',
      Flags: 0,
      LedgerEntryType: 'AccountRoot',
      OwnerCount: 0,
      PreviousTxnID: '9B24265EE9E55B97748F85B9C287C6B174F324506FDADCA94E8A68BA43DDFA7B',
      PreviousTxnLgrSeq: 67448711,
      Sequence: 67108556,
      index: '000000EE90D2501F2A95C89000CDA272490864234067E84EE5A79844922ACDF4'
    },
    {
      Flags: 0,
      IndexNext: '426',
      IndexPrevious: '424',
      Indexes: [Array],
      LedgerEntryType: 'DirectoryNode',
      Owner: 'rEMzCUeRZbx6ydthbi2RVNYdRbuqqsrYof',
      RootIndex: 'BADEFEDEA9826CDFBD479D5747E441220ADC501BB32C8FE5D88C6C3CB629F542',
      index: '00000203EA7B91B283192593F8847E6641930185B3689530AAE24A64A815FF58'
    },
    {
      Flags: 0,
      Indexes: [Array],
      LedgerEntryType: 'DirectoryNode',
      Owner: 'rNvL1QrLRirjCtJf4WWPRMzuxLmhNmmHs9',
      RootIndex: '00000299BD60630F6C37B91FB1FDA6979E59D19E9D42C2DBF39ABBEF66F6FBB8',
      index: '00000299BD60630F6C37B91FB1FDA6979E59D19E9D42C2DBF39ABBEF66F6FBB8'
    },
    {
      Account: 'rMj5DFATVxw91PDy3AM2wu7Uu1kgrhWypE',
      Balance: '20722989',
      Flags: 0,
      LedgerEntryType: 'AccountRoot',
      OwnerCount: 0,
      PreviousTxnID: '4C43C78081198AC96F6EC15315FDD16FC12458DC9A3F1B0BD0AA62F8D9F8FB51',
      PreviousTxnLgrSeq: 62869196,
      Sequence: 4,
      index: '000003E6AFED1AADCC39AAE0727B354C2286F1503274F345FE661748F24366CF'
    },
    {
      Balance: [Object],
      Flags: 2162688,
      HighLimit: [Object],
      HighNode: '283',
      LedgerEntryType: 'RippleState',
      LowLimit: [Object],
      LowNode: '0',
      PreviousTxnID: 'C0C37CE200B509E0A529880634F7841A9EF4CB65F03C12E6004CFAD9718D6694',
      PreviousTxnLgrSeq: 24695242,
      index: '0000041EFD027808D3F78C8352F97E324CB816318E00B977C74ECDDC7CD975B2'
    },
    {
      Account: 'rHeyw38ezc3LSLzYAYwaBci2KssDkYGVr9',
      Balance: '20000000',
      Flags: 0,
      LedgerEntryType: 'AccountRoot',
      OwnerCount: 0,
      PreviousTxnID: '7540CE04B966D67DBD39F3AA832274902B79AF4782F5AC9D4DC7CD18B1D9AE0D',
      PreviousTxnLgrSeq: 47846971,
      Sequence: 2,
      index: '000004D417A9CE049C9A71A62B004659B5F1AAAB1BEA1EFDE4E01EB3497FD999'
    },
    {
      Flags: 0,
      IndexNext: '538',
      IndexPrevious: '534',
      Indexes: [Array],
      LedgerEntryType: 'DirectoryNode',
      Owner: 'rPGxCzMicNJRe1U1CD5QyNjXdLUtdgSa7B',
      RootIndex: 'AA173EE344FF635D347172D9B32F7B485789176BDF514E94F2585C68DFB73D8B',
      index: '000004F84BC4FCD2C9BDF17030BEB7D83A16ABFEE3130D7DF60CDEC2A4F0EA90'
    },
    {
      Balance: [Object],
      Flags: 1114112,
      HighLimit: [Object],
      HighNode: '487',
      LedgerEntryType: 'RippleState',
      LowLimit: [Object],
      LowNode: '2',
      PreviousTxnID: '60A9DE6B251545C58E1D0F297975736C017D0137ABC80A4546271662D19C9CFF',
      PreviousTxnLgrSeq: 69804405,
      index: '00000531A591AC8084599C5BA12D98C31F645C7F3F1E60646E1D568C36A1CD8E'
    },
    {
      Balance: [Object],
      Flags: 2228224,
      HighLimit: [Object],
      HighNode: '0',
      LedgerEntryType: 'RippleState',
      LowLimit: [Object],
      LowNode: '290c',
      PreviousTxnID: '8BEC398CE93BBC4434B17C441A0C234DF5AD95757C0D78A3E192C8B2EB915267',
      PreviousTxnLgrSeq: 69257676,
      index: '000006B28A3C81594D6F69D107CA3647854CE925A8B30A2E2D345EC33C294C00'
    }
  ],
  validated: true,
  _nodepref: 'nonfh'
}

ledgerには取得したレジャーのメタ情報、stateにはレジャーデータ(の一部)が含まれています。

各レジャーデータはレジャーオブジェクトとも呼ばれ、いくつかのLedgerEntryTypeによって分類されます。
例えばAccountRootはアカウントの情報を表し、アカウントのXRP残高やアカウントに紐付くオブジェクト数、その他メタデータなどが含まれます。
他のLedgerEntryTypeについては以下の記事を参照してください。

https://note.com/tequ/n/nd82873e8f5dc

以下のサイトではこのledger_dataを利用しオブジェクト数やデータサイズを表示しています。

https://xrpl.services/xrpl-statistics

まとめ

ledger_dataコマンドを利用することでXRPレジャーの特定レジャー番号のレジャー情報を取得することができ、オンレジャー情報の分析にも利用することができます。
またmarkerを利用することでレジャー情報を分割して取得することも可能です。

今回使用したコードは以下のリポジトリからも参照できます。
https://github.com/develoQ/xrpl-sample/tree/main/samples/ledgerData

興味を持たれた方はXRP Ledger開発者のDiscordチャンネルへ是非お越しください!
日本語チャンネルもありますので、英語ができなくても大丈夫です!
https://xrpldevs.org

Discussion