5
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Firebase Cloud Functions を使って Catapult API を作る

どうも、shoheiです。

大阪在住のフリーランスエンジニアです。現在はFlutterを使ってプロダクト開発をしています。

今回はFirebase Cloud Functionsを使ってCatapult APIの作り方を紹介します。

・Github
https://github.com/hukusuke1007/nem2_api_server

準備

Firebaseの設定を行います。Firebaseコンソールより、プロジェクトを作成してください。

作成後、Cloud Functionを利用できるようにしてください。
https://firebase.google.com/products/functions/?hl=ja

なお、Cloud FunctionにDeployして外部APIを利用する場合は有料の利用プランでないと利用することができません。

今回はローカル上で立ち上げたCloud Functionから利用する想定で紹介します。

お手元のターミナルで firebase init で Cloud Function のテンプレートを作成します。

firebase init

? Which Firebase CLI features do you want to setup for this folder? Press Space to select features, then Enter to confirm your choi
ces. 
 ◯ Database: Deploy Firebase Realtime Database Rules
 ◯ Firestore: Deploy rules and create indexes for Firestore
❯◉ Functions: Configure and deploy Cloud Functions
 ◯ Hosting: Configure and deploy Firebase Hosting sites
 ◯ Storage: Deploy Cloud Storage security rules

A functions directory will be created in your project with a Node.js
package pre-configured. Functions can be deployed with firebase deploy.

? What language would you like to use to write Cloud Functions? TypeScript
? Do you want to use TSLint to catch probable bugs and enforce style? Yes
✔  Wrote functions/package.json
✔  Wrote functions/tslint.json
✔  Wrote functions/tsconfig.json
✔  Wrote functions/src/index.ts
✔  Wrote functions/.gitignore
? Do you want to install dependencies with npm now? Yes

構築が完了するとカレントディレクトリに functions ディレクトリが作成されます。

ディレクトリ構成は次の通りです。

.
├── package.json
├── src
│   └── index.ts
├── tsconfig.json
└── tslint.json

必要なライブラリをインストールします。

yarn add cors dotenv express inversify reflect-metadata nem2-sdk rxjs
yarn add --dev @types/cors @types/dotenv @types/express

package.json に node のバージョンを設定します。

  "engines": {
    "node": "10"
  },

tsconfig.json を変更します。

{
  "compilerOptions": {
    "target": "es2017",
    "lib": ["es2017", "dom"],
    "module": "commonjs",
    "noImplicitReturns": true,
    "outDir": "lib",
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "types": ["reflect-metadata"],
    "emitDecoratorMetadata": true,
    "sourceMap": true
  },
  "compileOnSave": true,
  "include": [
    "src"
  ]
}

次に tslint.json をダウンロードして上書きしてください。

https://github.com/hukusuke1007/nem2_api_server/blob/master/functions/tslint.json

実装

っと言いたいところでしたが、全て解説するとかなり長くなるので既に用意しているコードを利用します。

ここの src ディレクトリをダウンロードして上書きしてください。

https://github.com/hukusuke1007/nem2_api_server/tree/master/functions/src

src ディレクトリ内の構成は次の通りです。

.
├── common
│   ├── Config.ts
│   └── Utils.ts
├── domain
│   ├── dto
│   │   ├── FaucetDTO.ts
│   │   ├── SendMosaicDTO.ts
│   │   └── response
│   │       └── ResponseBody.ts
│   ├── model
│   │   └── TransactionResult.ts
│   ├── repository
│   │   ├── AggregateTransactionRepository.ts
│   │   ├── TransactionRepository.ts
│   │   └── WalletRepository.ts
│   ├── type
│   │   └── Types.ts
│   └── use_case
│       └── CatapultUseCase.ts
├── index.ts
├── infrastructure
│   ├── AggregateTransactionDataSource.ts
│   ├── TransactionDataSource.ts
│   ├── WalletDatasource.ts
│   └── helper
│       └── ListenerHelper.ts
├── inversify.config.ts
└── presentation
    └── v1
        ├── index.ts
        └── router
            ├── catapult.ts
            └── index.ts

src/presentation/v1/router/catapult.ts を見ると次のAPIを用意しています。

API 機能
wallet Catapultのウォレット作成
faucet Catapultコインを取得
sendMosaic Catapultコインを送信
sendMosaicNoFee Catapultコインを送信(手数料無料)

ノードの設定

dotenvsample から .env を作成します。

cp dotenvsample .env

それぞれの環境変数にノード情報を設定してください。

※ノードの情報はNEM2 Slackまで

# Blockchain network type
#  MAIN_NET = 104
#  TEST_NET = 152
#  MIJIN = 96
#  MIJIN_TEST = 144
NODE_NETWORK = 144

# Blockchain server URL
NODE_URL_SCHEME = 'https'
NODE_WS_SCHEME = 'https'
NODE_DOMAIN = ''
NODE_PORT = '3001'

# Blockchain generation hash
# curl https://XXXXX:3001/block/1
# is meta.generationHash
NODE_GENERATION_HASH = ''
FAUCET_PRIVATE_KEY = ''

次に動作確認用のshellを取り入れます。以下のディレクトリをダウンロードして functions ディレクトリ直下に保存してください。

https://github.com/hukusuke1007/nem2_api_server/tree/master/functions/request

全ての準備が整えば次のような構成になります。

├── .env
├── package-lock.json
├── package.json
├── node_modules
├── request
│   ├── address.sh
│   ├── faucet.sh
│   ├── sendMosaic.sh
│   ├── sendMosaicNoFee.sh
│   └── wallet.sh
├── src
│   ├── common
│   │   ├── Config.ts
│   │   └── Utils.ts
│   ├── domain
│   │   ├── dto
│   │   │   ├── FaucetDTO.ts
│   │   │   ├── SendMosaicDTO.ts
│   │   │   └── response
│   │   │       └── ResponseBody.ts
│   │   ├── model
│   │   │   └── TransactionResult.ts
│   │   ├── repository
│   │   │   ├── AggregateTransactionRepository.ts
│   │   │   ├── TransactionRepository.ts
│   │   │   └── WalletRepository.ts
│   │   ├── type
│   │   │   └── Types.ts
│   │   └── use_case
│   │       └── CatapultUseCase.ts
│   ├── index.ts
│   ├── infrastructure
│   │   ├── AggregateTransactionDataSource.ts
│   │   ├── TransactionDataSource.ts
│   │   ├── WalletDatasource.ts
│   │   └── helper
│   │       └── ListenerHelper.ts
│   ├── inversify.config.ts
│   └── presentation
│       └── v1
│           ├── index.ts
│           └── router
│               ├── catapult.ts
│               └── index.ts
├── tsconfig.json
├── tslint.json
└── yarn.lock

動作確認

ターミナルを二つ立ち上げます。

1つ目のターミナルでは次のコマンドで実行して Cloud Functions を起動します。

yarn serve

✔  functions: Using node@10 from host.
✔  functions: Emulator started at http://localhost:5000
i  functions: Watching "/Users/hukusuke/Desktop/Start/Development/mokumoku/nem2_api_server/functions" for Cloud Functions...
✔  functions[v1-router-catapult-api]: http function initialized (http://localhost:5000/nem2-wallet-d3f63/asia-northeast1/v1-router-catapult-api).

2つ目のターミナルではCatapult APIに対してリクエストを送ります。

ウォレット作成

それでは、ウォレットを作成します。

先ほどダウンロードした request ディレクトリの wallet.sh を使います。

wallet.sh の API を利用するURLに書き換えてください。

API="http://localhost:5000/nem2-wallet-d3f63/asia-northeast1/v1-router-catapult-api" # ローカルで立ち上げたCloud FunctionのAPI

echo "--- Request ---"
curl -w '\n' -X GET $API/wallet

実行すると、ウォレットの情報が取れるのでメモします。

./request/wallet.sh

--- Request ---
{"status":200,"data":{"address":"SCG2E4AHU4NTL7EU2HY6ZY7PWMGLR462KQT6O5CV","privateKey":"E3413B6DD4E904A37BCC2F42A6A97094425E3BD918BCC3F49E3EBD66A2EED270","publicKey":"74ED318D28DFF3B7D63C6C24E297BE5AA2D28DD4C1352ED92FFE88E8FECFB48A","network":144}}

Catapultコイン獲得

次に faucet.sh を使ってCatapultコインを獲得します。

address に先ほど作成したウォレットアドレスに書き換えてください。

API="http://localhost:5000/nem2-wallet-d3f63/asia-northeast1/v1-router-catapult-api"

echo "--- Request ---"
curl -w '\n' -X POST $API/faucet \
  -H "Content-Type: application/json" \
  -d '
{
  "address": "SADMO4S3Q7MN44YZFVQBU75ILFMRE2PDBE3WUXAE",
  "amount": 70
}
'

実行するとコインを獲得できます。

./request/faucet.sh

--- Request ---
{"status":200,"data":{"message":"success","data":{"hash":"2A26241FC314F4C94CCA8B1B9709F149066BE69CC5F511C95522916B6161773B","isConfirmed":false,"data":{"transaction":{"type":16724,"network":144,"version":36865,"maxFee":"20000","deadline":"116260150514","signature":"BC1E649433C1CD4FFDB9DF9129E597DEC85D461D83FC1D52A1ACD420309EFE9A888A991344B3F14F0048919BB90E6CB9096ED8FC04BED3BEA52331EA55332C09","signerPublicKey":"9C7A61893BB7D8A39457D69C489F77B304F263A3BD927AF058432FCA65EA774D","recipientAddress":{"address":"SADMO4S3Q7MN44YZFVQBU75ILFMRE2PDBE3WUXAE","networkType":144},"mosaics":[{"amount":"20000000","id":"85BBEA6CC462B244"}],"message":{"type":0,"payload":""}}}}}}

残高確認

address.sh を使って残高を確認します。蛇口から取得後、トランザクションが承認させるまで少しだけ時間をあけてから確認してください。

ENDPOINT と TO_ADDRESS を書き換えて実行してください。

ENDPOINT="https://fushicho2-fee.opening-line.jp:3001"
TO_ADDRESS="SADMO4S3Q7MN44YZFVQBU75ILFMRE2PDBE3WUXAE"

echo "-- Address balance ---"
curl -w '\n' -X GET $ENDPOINT/account/$TO_ADDRESS

実行すると、amount で残高を確認できます。 

 ./request/address.sh

-- Address balance ---
{"account":{"address":"9006C7725B87D8DE73192D601A7FA859591269E309376A5C04","addressHeight":"26135","publicKey":"0000000000000000000000000000000000000000000000000000000000000000","publicKeyHeight":"0","accountType":0,"linkedAccountKey":"0000000000000000000000000000000000000000000000000000000000000000","activityBuckets":[],"mosaics":[{"id":"59CFA2FBA9A4E6CD","amount":"70000000"}],"importance":"0","importanceHeight":"0"}}

Catapultコインを送信

sendMosaic.sh を使います。予め送信先のアカウントを wallet.sh から作成して準備してください。

fromPrivateKey, toAddress, amount を書き換えてください。

API="http://localhost:5000/nem2-wallet-d3f63/asia-northeast1/v1-router-catapult-api"

echo "--- Request ---"
curl -w '\n' -X POST $API/sendMosaic \
  -H "Content-Type: application/json" \
  -d '
{
  "fromPrivateKey": "C8F8CAF55CA1796AAC31D552BFAF26948B3EE731237695B97DD5D34AC57BCFB3",
  "toAddress": "SADMO4S3Q7MN44YZFVQBU75ILFMRE2PDBE3WUXAE",
  "amount": 10
}
'

実行すると、送金できます。

./request/sendMosaic.sh 

--- Request ---
{"status":200,"data":{"message":"success","data":{"hash":"C22A31BE67834D7990EC5261482298D96099D1AFA223430FB41A7DBF07AC8AD3","isConfirmed":false,"data":{"transaction":{"type":16724,"network":144,"version":36865,"maxFee":"20000","deadline":"116260910379","signature":"379939BD48DA8A4F2B66D2CF599F2C56F65F64EF504EB940337A646BB6E05114446B6B68074C4788ED9CAF59C3B726C00BB00417EBD8D0773A39350F2CCD990B","signerPublicKey":"2DD7E62D59564E3A2B04213BFDA532813BAF235A7D4959F4306BF24A5A37CE45","recipientAddress":{"address":"SADMO4S3Q7MN44YZFVQBU75ILFMRE2PDBE3WUXAE","networkType":144},"mosaics":[{"amount":"10000000","id":"85BBEA6CC462B244"}],"message":{"type":0,"payload":""}}}}}}

デプロイ

次のコマンドでCloud Functionsへデプロイできます。

yarn deploy

終わりに

Catapultノードがはやく安定してほしい(切実

本当はAggregateTransactionで手数料なくてもトランザクション発行できるよ〜っていうのを詳細に書きたかった。

Reference

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
5
Help us understand the problem. What are the problem?