0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FCL SDK Reference

Last updated at Posted at 2024-12-16

Previous << FCL Reference
Next >> Authentication

Overview

このリファレンスでは、FCL経由でアクセスできるSDKで利用可能なメソッドを説明し、それらのメソッドの動作について詳しく説明しています。FCL/SDKはオープンソースであり、ライセンスに従ってご利用いただけます。

ライブラリクライアントの仕様は、こちらでご覧いただけます。

image.png

Getting Started

Installing

FCL経由でFlow SDKにアクセスしますのでFCLをインストールします。

NPM:

npm install --save @onflow/fcl @onflow/types

Yarn:

yarn add @onflow/fcl @onflow/types

Importing the Library

javascriptでインポートできます。

import * as fcl from "@onflow/fcl"
import * as types from "@onflow/types"

Connect

image.png

デフォルトでは、ライブラリはアクセスノードとの通信にHTTPを使用します。そして、正しいアクセスノードAPI URLで設定されていといけません。ホストに到達できない場合、エラーが返されます。

📖HTTP/REST APIの情報こちらでご確認いただけます。Flow HTTP/RESTのパブリックアクセスノードは、以下からアクセスできます。

  • Testnet https://rest-testnet.onflow.org
  • Mainnet https://rest-mainnet.onflow.org
  • Local Emulator 127.0.0.1:8888

Example:

import { config } from "@onflow/fcl"

config({
  "accessNode.api": "https://rest-testnet.onflow.org"
})

Querying the Flow Network

アクセスノードとの接続が確立されたら、Flowネットワークにqueryで問い合わせて、ブロック、アカウント、イベント、トランザクションに関するデータを取得することができます。以下では、これらのデータをそれぞれ取得する方法について説明していきます。

Get Blocks

image.png

ネットワークにIDと高さによるブロックをqueryします、または最新のブロックの取得します。

📖 ブロックIDは、ブロックペイロード全体のSHA3-256 hashです。このハッシュは、(GetLatestBlockからのレスポンスなど)ブロックレスポンスオブジェクトのIDとして保存されています。

📖 ブロック高さは、チェーン上のブロックの高さを表します。最新のブロック高さは、有効なブロックが生成されるごとに1ずつ増加します。

Examples
この例では、最新のブロックの取得方法と、高さまたはIDによるその他のブロックの取得方法を説明しています。

import * as fcl from "@onflow/fcl";

/* Get latest block */
const latestBlock = await fcl.latestBlock(true); // If true, get the latest sealed block

/* Get block by ID (uses builder function) */
await fcl.send([fcl.getBlock(), fcl.atBlockId("23232323232")]).then(fcl.decode);

/* Get block at height (uses builder function) */
await fcl.send([fcl.getBlock(), fcl.atBlockHeight(123)]).then(fcl.decode)

Result output: BlockObject

Get Account

image.png

任意のアカウントを、Flowネットワークの最新ブロックまたは指定したブロック高さから取得します。

📖 Account addressは、アカウントを一意に識別するものです。0xという接頭辞に注意してください。デフォルトの表現ではこの接頭辞を使うべきですが、ユーザーが入力する接頭辞がない表現については慎重に安全に処理してください。

アカウントには以下のデータが含まれます。

  • Address:アカウントのアドレス。
  • Balance:アカウントの残高。
  • Contracts:アカウントにデプロイされたコントラクトのリスト。
  • Keys:アカウントに関連付けられたキーのリスト。

Examples
最新のブロックからと、特定のブロック高さからアカウントを取得する方法を例示します。

import * as fcl from "@onflow/fcl";

/* Get account from latest block height */
const account = await fcl.account("0x1d007d755706c469");

/* Get account at a specific block height */
fcl.send([
  fcl.getAccount("0x1d007d755706c469"),
  fcl.atBlockHeight(123)
]);

Result output: AccountObject

Get Transactions

image.png

トランザクションIDを指定して、ネットワークからトランザクションを取得します。 トランザクションを送信した後、ステータスを確認するためにトランザクションの結果を取得することもできます。

📖 トランザクションIDは、エンコードされたトランザクションペイロードのハッシュであり、ネットワークにトランザクションを送信する前に計算することができます。

⚠️ 提供するトランザクションIDは、直近のspork以降のものでなければなりません。

📖 トランザクションステータスは、ブロックチェーン上のトランザクションの状態を表します。ステータスは、sealedされるまでは変更される可能性があります。

Status Final Description
UNKNOWN The transaction has not yet been seen by the network
PENDING The transaction has not yet been included in a block
FINALIZED The transaction has been included in a block
EXECUTED The transaction has been executed but the result has not yet been sealed
SEALED The transaction has been executed and the result is sealed in a block
EXPIRED The transaction reference block is outdated before being executed
import * as fcl from "@onflow/fcl";

/* Snapshot the transaction at a point in time */
fcl.tx(transactionId).snapshot();

/* Subscribe to a transaction's updates */
fcl.tx(transactionId).subscribe(callback);

/* Provides the transaction once the status is finalized */
fcl.tx(transactionId).onceFinalized();

/* Provides the transaction once the status is executed */
fcl.tx(transactionId).onceExecuted();

/* Provides the transaction once the status is sealed */
fcl.tx(transactionId).onceSealed();

Result output: TransactionStatusObject

Get Events

image.png

指定されたブロックの高さの範囲内にある、またはブロックIDのリストから、指定された型のイベントを取得します。

📖 Event typeは、標準フォーマットに従った文字列です。

A.{contract address}.{contract name}.{event name}

イベントに関する詳細をドキュメントで確認してください。このスタンダードに対する例外はcore eventsであり、このドキュメントで詳細をご確認ください。

📖 Block height rangeは、チェーン内の開始ブロックと終了ブロックの高さを表します。

Examples

ブロックの範囲内および複数のブロックIDでイベントを取得する方法を示します。

import * as fcl from "@onflow/fcl";

/* Get events at block height range */
await fcl
  .send([
    fcl.getEventsAtBlockHeightRange(
      "A.7e60df042a9c0868.FlowToken.TokensWithdrawn", /* event name */
      35580624, /* block to start looking for events at */
      35580624
      /* block to stop looking for events at */
    ),
  ])
  .then(fcl.decode);

/* Get events from list of block ids */
await fcl
  .send([
    fcl.getEventsAtBlockIds("A.7e60df042a9c0868.FlowToken.TokensWithdrawn", [
      "c4f239d49e96d1e5fbcf1f31027a6e582e8c03fcd9954177b7723fdb03d938c7",
      "5dbaa85922eb194a3dc463c946cc01c866f2ff2b88f3e59e21c0d8d00113273f",
    ]),
  ])
  .then(fcl.decode);

Result output: EventObject

Get Collections

image.png

同じブロックに含まれているトランザクションの塊を取得します。これをcollectionsと呼びます。コレクションは、ブロックあたりのトランザクション数を増やすことで、コンセンサス処理のスループットを向上させるために使用され、それらはブロックとトランザクションの間のリンクとして働きます。

📖 コレクションIDは、collectionペイロードのSHA3-256ハッシュです。

コレクションの取得例:

import * as fcl from "@onflow/fcl";

const collection = await fcl
  .send([
    fcl.getCollection(
      "cccdb0c67d015dc7f6444e8f62a3244ed650215ed66b90603006c70c5ef1f6e5"
    ),
  ])
  .then(fcl.decode);

Result output: CollectionObject

Execute Scripts

image.png

スクリプトを使用すると、Flowブロックチェーン上で変更が発生しない任意のCadenceコードを書いて、そのデータを受け取ることができます。Cadenceはこちらにスクリプトについてはこちらで詳しく説明されていますが、現時点で私達はスクリプトコードの実行とデータの取得のみに興味を持ちます。

Flowブロックチェーンの最新の状態に対してスクリプトを実行することもできますし、ブロックの高さまたはブロックIDで定義されたヒストリーの特定の時点でスクリプトを実行することもできます。

📖 ブロックIDはブロックのペイロード全体の SHA3-256 ハッシュですが、ブロックのレスポンスのプロパティからその値を取得できます。

📖 ブロック高さはチェーン内のブロックの高さを表します。

import * as fcl from "@onflow/fcl";

const result = await fcl.query({
  cadence: `
    access(all) fun main(a: Int, b: Int, addr: Address): Int {
      log(addr)
      return a + b
    }
  `,
  args: (arg, t) => [
    arg(7, t.Int), // a: Int
    arg(6, t.Int), // b: Int
    arg("0xba1132bc08f82fe2", t.Address), /* addr: Address */
  ],
});

Example output:

console.log(result); /* 13 */

Mutate Flow Network

Flowは、他の多くのブロックチェーンと同じ様に、共有されたグローバルチェーンの状態を変化させるトランザクションを誰でも送信することができます。トランザクションは、状態の変化を記述したペイロードと、特定アカウントによる所有状態の変化を許可した1つ以上の承認、を含むオブジェクトです。

トランザクションデータは、SDKの助けを借りて、作成/署名されます。署名されたトランザクションのペイロードは、その後、アクセスノードAPIに送信されます。トランザクションが無効であった場合、または正しい数の承認署名が用意されていなかった場合、トランザクションは拒否されます。

Transactions

トランザクションとは署名済みのデータセットでしかなく、どのようにネットワークの状態を変化させるかと、その実行を定義したり制限したりするプロパティを指示したスクリプト・コードを含んでいます。これらのプロパティについては、以下で説明します。

📖 Scriptフィールドは、状態の変化のロジックを記述するトランザクションの一部です。Flowでは、トランザクションロジックはCadenceで書かれます。以下は、トランザクションのスクリプトの例です。

transaction(greeting: String) {
  execute {
    log(greeting.concat(", World!"))
  }
}

📖 Arguments: トランザクションは、Cadenceスクリプトに渡されるゼロ個以上の引数を受け入れることができます。トランザクションの引数は、Cadenceスクリプト内で宣言された数と順序と一致する必要があります。上記のサンプルスクリプトでは、単一のString引数を受け入れています。

📖 Proposal keyは、シーケンス番号として機能し、リプレイ攻撃やその他の潜在的な攻撃を防止するために、提供されなければなりません。

各アカウントのキーは別個のトランザクションのシーケンス番号を管理しています。トランザクションにそのシーケンス番号を付与するキーは、提案キー(proposal key)と呼ばれます。

提案キーは3つのフィールドを含みます。

  • Account address
  • Key index
  • Sequence number

トランザクションは、宣言されたシーケンス番号がそのキーの現在のチェーン上のシーケンス番号と一致する場合のみ有効です。トランザクションが実行された後、シーケンス番号は1つインクリメントされます。

📖 Payerは、トランザクションの料金を支払うアカウントです。トランザクションは、必ず1つのPayerを指定する必要があります。Payerは、ネットワーク料金とガス料金の支払いの責任を負うのみであり、トランザクションはPayerアカウントに保存されているリソースやコードにアクセスする権限はありません。

📖 Authorizersとは、トランザクションがリソースを読み取り、変更することを承認するアカウントです。トランザクションは、アクセスする必要のあるアカウントの数に応じて、authorizerをゼロまたは複数指定できます。

トランザクションの承認者の数は、Cadenceスクリプトのprepareステートメントで宣言された&Accountパラメータの数と一致する必要があります。

複数の承認者を含むトランザクションの例:

transaction {
  prepare(authorizer1: &Account, authorizer2: &Account) { }
}

📖 Gas limitとは、トランザクションに必要な計算量の制限値であり、ガスリミットを超えると処理が中断されます。Cadenceでは、トランザクションごとの操作数を計測によって測定しています。詳細は、Cadenceのドキュメントを参照してください。

ガスリミットは、トランザクションスクリプトの複雑さによって異なります。専用のガス測定ツールが利用可能になるまでは、エミュレータを使用して複雑なトランザクションをテストし、安全なリミットを決定することをお勧めします。

📖 Reference block(参照ブロック) は、ネットワークによってトランザクションが有効とみなされる、expiration window(有効期限の期間)(ブロック単位)を指定します。 トランザクションがexpiry block(有効期限ブロック)を過ぎて送信された場合、そのトランザクションは拒否されます。 Flowは、トランザクション上のReference block(参照ブロック) フィールドを使用してトランザクションの有効期限を計算します。 トランザクションは、600ブロックがReference block(参照ブロック)の上にコミットされると有効期限切れとなり、これは平均的なMainnetブロックレートでは約10分かかります。

Mutate

image.png

FCLの「mutate」は、トランザクションの構築、署名、送信(building, signing, and sending a transaction)を裏側で実行します。FCLを使用してブロックチェーンの状態を変更するには、以下を行います。

import * as fcl from "@onflow/fcl"

await fcl.mutate({
  cadence: `
    transaction(a: Int) {
      prepare(acct: &Account) {
        log(acct)
        log(a)
      }
    }
  `,
  args: (arg, t) => [
    arg(6, t.Int)
  ],
  limit: 50
})

Flowはトランザクションの署名に関しては、高い柔軟性をサポートしており、複数の承認者(マルチシグ取引)を定義したり、提案者とは異なる支払者アカウントを持つことができます。以下では、高度な署名シナリオについて説明します。

Single party, single signature

  • Proposer, payer and authorizer are the same account (0x01).
  • Only the envelope must be signed.
  • Proposal key must have full signing weight.
Account Key ID Weight
0x01 1 1000
/* There are multiple ways to acheive this */
import * as fcl from "@onflow/fcl"

/* FCL provides currentUser as an authorization function */
await fcl.mutate({
  cadence: `
    transaction {
      prepare(acct: &Account) {}
    }
  `,
  proposer: currentUser,
  payer: currentUser,
  authorizations: [currentUser],
  limit: 50,
})

/* Or, simplified */

mutate({
  cadence: `
    transaction {
      prepare(acct: &Account) {}
    }
  `,
  authz: currentUser, /* Optional. Will default to currentUser if not provided. */
  limit: 50,
})


/* Or, create a custom authorization function */
const authzFn = async (txAccount) => {
  return {
    ...txAccount,
    addr: "0x01",
    keyId: 0,
    signingFunction: async(signable) => {
      return {
        addr: "0x01",
        keyId: 0,
        signature
      }
    }
  }
}

mutate({
  cadence: `
    transaction {
      prepare(acct: &Account) {}
    }
  `,
  proposer: authzFn,
  payer: authzFn,
  authorizations: [authzFn],
  limit: 50,
})

Single party, multiple signatures

  • Proposer, payer and authorizer are the same account (0x01).
  • Only the envelope must be signed.
  • Each key has weight 500, so two signatures are required.
Account Key ID Weight
0x01 1 500
0x01 2 500
import * as fcl from "@onflow/fcl"

const authzFn = async (txAccount) => {
  return [
    {
      ...txAccount,
      addr: "0x01",
      keyId: 0,
      signingFunction: async(signable) => {
        return {
          addr: "0x01",
          keyId: 0,
          signature
        }
      }
    },
    {
      ...txAccount,
      addr: "0x01",
      keyId: 1,
      signingFunction: async(signable) => {
        return {
          addr: "0x01",
          keyId: 1,
          signature
        }
      }
    }
  ]
}

mutate({
  cadence: `
    transaction {
      prepare(acct: &Account) {}
    }
  `,
  proposer: authzFn,
  payer: authzFn,
  authorizations: [authzFn],
  limit: 50,
})

Multiple parties

  • Proposer and authorizer are the same account (0x01).
  • Payer is a separate account (0x02).
  • Account 0x01 signs the payload.
  • Account 0x02 signs the envelope.
    • Account 0x02 must sign last since it is the payer.
Account Key ID Weight
0x01 1 1000
0x02 3 1000
import * as fcl from "@onflow/fcl"

const authzFn = async (txAccount) => {
  return {
    ...txAccount,
    addr: "0x01",
    keyId: 0,
    signingFunction: async(signable) => {
      return {
        addr: "0x01",
        keyId: 0,
        signature
      }
    }
  }
}

const authzTwoFn = async (txAccount) => {
  return {
    ...txAccount,
    addr: "0x02",
    keyId: 0,
    signingFunction: async(signable) => {
      return {
        addr: "0x02",
        keyId: 0,
        signature
      }
    }
  }
}

mutate({
  cadence: `
    transaction {
      prepare(acct: &Account) {}
    }
  `,
  proposer: authzFn,
  payer: authzTwoFn,
  authorizations: [authzFn],
  limit: 50,
})

Multiple parties, two authorizers

  • Proposer and authorizer are the same account (0x01).
  • Payer is a separate account (0x02).
  • Account 0x01 signs the payload.
  • Account 0x02 signs the envelope.
    • Account 0x02 must sign last since it is the payer.
  • Account 0x02 is also an authorizer to show how to include two &Account objects into an transaction
Account Key ID Weight
0x01 1 1000
0x02 3 1000
import * as fcl from "@onflow/fcl"

const authzFn = async (txAccount) => {
  return {
    ...txAccount,
    addr: "0x01",
    keyId: 0,
    signingFunction: async(signable) => {
      return {
        addr: "0x01",
        keyId: 0,
        signature
      }
    }
  }
}

const authzTwoFn = async (txAccount) => {
  return {
    ...txAccount,
    addr: "0x02",
    keyId: 0,
    signingFunction: async(signable) => {
      return {
        addr: "0x02",
        keyId: 0,
        signature
      }
    }
  }
}

mutate({
  cadence: `
    transaction {
      prepare(acct: &Account, acct2: &Account) {}
    }
  `,
  proposer: authzFn,
  payer: authzTwoFn,
  authorizations: [authzFn, authzTwoFn],
  limit: 50,
})

Multiple parties, multiple signatures

  • Proposer and authorizer are the same account (0x01).
  • Payer is a separate account (0x02).
  • Account 0x01 signs the payload.
  • Account 0x02 signs the envelope.
    • Account 0x02 must sign last since it is the payer.
  • Both accounts must sign twice (once with each of their keys).
Account Key ID Weight
0x01 1 500
0x01 2 500
0x02 3 500
0x02 4 500
import * as fcl from "@onflow/fcl"

const authzFn = async (txAccount) => {
  return [
    {
      ...txAccount,
      addr: "0x01",
      keyId: 0,
      signingFunction: async(signable) => {
        return {
          addr: "0x01",
          keyId: 0,
          signature
        }
      }
    },
    {
      ...txAccount,
      addr: "0x01",
      keyId: 1,
      signingFunction: async(signable) => {
        return {
          addr: "0x01",
          keyId: 1,
          signature
        }
      }
    }
  ]
}

const authzTwoFn = async (txAccount) => {
  return [
    {
      ...txAccount,
      addr: "0x02",
      keyId: 0,
      signingFunction: async(signable) => {
        return {
          addr: "0x02",
          keyId: 0,
          signature
        }
      }
    },
    {
      ...txAccount,
      addr: "0x02",
      keyId: 1,
      signingFunction: async(signable) => {
        return {
          addr: "0x02",
          keyId: 1,
          signature
        }
      }
    }
  ]
}

mutate({
  cadence: `
    transaction {
      prepare(acct: &Account) {}
    }
  `,
  proposer: authzFn,
  payer: authzTwoFn,
  authorizations: [authzFn],
  limit: 50,
})

トランザクションが構築され署名されると、Flowブロックチェーンに送信され、そこで実行されます。送信が成功した場合、トランザクションの結果を取得できます。

Last updated on Dec 11, 2024 by Chase Fleming

翻訳元


Flow BlockchainのCadence version1.0ドキュメント (FCL SDK Reference)


Previous << FCL Reference

Flow BlockchainのCadence version1.0ドキュメント (FCL SDK Reference)

Next >> Authentication

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?