Previous << Day3 - 基礎編Part3
Next >> Day5 - 所持金表示
Why Flow
FLOW(または$FLOW)トークンは、Flowネットワークのネイティブ通貨です。開発者およびユーザーは、FLOWを使用してネットワーク上で取引(transact)を行うことができます。開発者は、ピアツーピア決済(他人同士の決済)、サービス料金徴収、または消費者向け特典(rewards)のために、FLOWを直接アプリに統合することができます。
ということでやっていきます、猿でも分かるP2P(ピアツーピア)決済アプリ開発!
💡もし、エミュレータの起動方法やスマートコントラクトのデプロイについて操作に自信がない場合はこちらを参照してください。
承認者、支払者 そして 提案者
Flowには3種類の承認関数をトランザクションでセットする必要があり、それぞれ、アカウントの変更権限を持つ承認者、トランザクションフィーを支払う支払者、Dos攻撃に対応するための提案者です。Dos攻撃に対応するための提案者アドレスは、短期間にトランザクションを繰り返す場合、トランザクションの度にキーIDを変更してローテーションさせる必要があります。
これらの承認関数はブラウザでトランザクション実行に使用する場合はウォレットが処理を引き継いで行う専用のメソッドがありますが、バックエンドでトランザクション実行に使用する場合は自分たちで作成する必要があります。
Non-Custodial Account
バックエンドでトランザクションを行うとき、それは専らAdmin処理ということになります。代表的なAdmin処理としてここではFLOWトークン送金をバックエンドで行います。バックエンドで行う場合、ウォレットを使わずに秘密鍵を使ってトランザクションを実施します。この方法をNon-Custodial
方式といいます。バックエンドでは秘密鍵を堅牢に管理できるためです。
バックエンドでトランザクションを実行するときは秘密鍵(private key)を必要としますが、絶対にGithubに保存しないでください。.gitignoreなどのファイルを使用して秘密鍵が漏洩しないように注意してください。
バックエンドでトランザクションを実行する手順は:
- FCLをnpmでインストール
- sha3とellipticをnpmでインストール(Flowで使われるハッシュ関数や署名関数に必要)
npm install @onflow/fcl --save-dev
npm install elliptic sha3 --save-dev
- FlowTokenを送金するプログラムを書きます。(
5.01FLOW
送金します、Mainnet)
const fcl = require("@onflow/fcl");
const { SHA3 } = require("sha3");
var EC = require("elliptic").ec;
var ec = new EC("p256");
require("dotenv").config();
fcl
.config()
.put("flow.network", "mainnet")
.put("accessNode.api", "https://rest-mainnet.onflow.org");
// CHANGE THESE THINGS FOR YOU
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const ADDRESS = process.env.ADDRESS;
const KEY_ID = parseInt(process.env.KEY_ID);
const hash = (message) => {
const sha = new SHA3(256);
sha.update(Buffer.from(message, "hex"));
return sha.digest();
};
const sign = (message) => {
const key = ec.keyFromPrivate(Buffer.from(PRIVATE_KEY, "hex"));
const sig = key.sign(hash(message)); // hashMsgHex -> hash
const n = 32;
const r = sig.r.toArrayLike(Buffer, "be", n);
const s = sig.s.toArrayLike(Buffer, "be", n);
return Buffer.concat([r, s]).toString("hex");
};
async function authorizationFunction(account) {
return {
...account,
tempId: `${ADDRESS}-${KEY_ID}`,
addr: fcl.sansPrefix(ADDRESS),
keyId: Number(KEY_ID),
signingFunction: async (signable) => {
return {
addr: fcl.withPrefix(ADDRESS),
keyId: Number(KEY_ID),
signature: sign(signable.message),
};
},
};
}
async function sendTx() {
const addr = process.env.RECIPIENT_ADDRESS;
const transactionId = await fcl.mutate({
cadence: `
import FungibleToken from 0xf233dcee88fe0abe
import FlowToken from 0x1654653399040a61
transaction(amount: UFix64, to: Address) {
let vault: @FlowToken.Vault
prepare(signer: auth(BorrowValue) &Account) {
self.vault <- signer.storage
.borrow<auth(FungibleToken.Withdraw) &{FungibleToken.Provider}>(from: /storage/flowTokenVault)!
.withdraw(amount: amount) as! @FlowToken.Vault
}
execute {
getAccount(to)
.capabilities
.get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)
.borrow()!
.deposit(from: <-self.vault)
}
}
`,
args: (arg, t) => [arg(5.01, t.UFix64), arg(addr, t.Address)],
payer: authorizationFunction,
proposer: authorizationFunction,
authorizations: [authorizationFunction],
limit: 999,
});
console.log({ transactionId });
fcl.tx(transactionId).subscribe((res) => {
console.log(res);
});
}
sendTx();
(ハッシュ関数や署名関数の詳細についてはこちらやこちら、およびこちらをご確認ください。)
- Node.jsで送金を実行します。
node sendFlow.js
Deprecation メッセージが出ていますが、このようにSEALEDとなったら送金は成功しています。Bloctoウォレットなど確認してみましょう。
この記事のソースコードはこちらにあります。