💹

AlgorandでSDKを使って送金する

2024/01/26に公開

この記事は 株式会社Gincoのテックブログ として書いています。

概要

弊社が提供している Ginco Enterprise Wallet では、新たに Algorand に対応しました。

https://prtimes.jp/main/html/rd/p/000000128.000031033.html

Algorand (アルゴランド) は、コンセンサスアルゴリズムに PPoS を採用し取引速度や承認のスピードが速く、フォークが発生しない特徴もあり、金融機関の未来のプラットフォームになりうる環境の提供を目指しているブロックチェーンで、そのネイティブトークンが ALGO になります。

この記事では、go 言語で Algorand の SDK を用いて、SingleSig アカウントから ALGO を送金する方法をサンプルコードで紹介します。

参考リンク

サンプルコード

要点を絞って解説していきます。コード全文は最後に載せています。

初期設定

const (
	// ネットワークのバージョン
	genesisId = "testnet-v1.0"
	// ネットワークの固有識別子 (Base64)
	genesisHash = "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="

	// 開始ラウンド(開始ブロックナンバー)
	startRound = 34866953
	// 最低手数料 1000 MicroAlgos (0.001 ALGO)
	minFee = 1000

	// 送金額 1,000,000 MicroAlgos (1 ALGO)
	amount = 1000000
)
  • 送金額以外のパラメータは Rest API の /v2/transactions/params から得られますが、分かりやすくするため直接指定します。
  • 開始ラウンドは、Tx (トランザクション) が有効な期間を設定するために使います。ラウンド = ブロックナンバーで、通常は最新のブロック数を設定。
  • 最低手数料は 2023/11 時点 で 0.001 ALGO (約 0.02 円) であり、これをTxの手数料として設定します。手数料は Tx のバイトサイズによって増減しますが、バイト辺りの単価相場は非常に安価で、殆どの場合この最低手数料より安くなるため、最低手数料で十分です。

送金元、送金先のアカウント作成

// 1. 送金元のアカウント作成
FromAccount := crypto.GenerateAccount()
fmt.Println("Algorand FromAddress", FromAccount.Address.String())
fmt.Println("Algorand FromAddress PrivateKey",
hex.EncodeToString(FromAccount.PrivateKey))
fmt.Println("Algorand FromAddress PublicKey",
hex.EncodeToString(FromAccount.PublicKey))

// 2. 送金先のアカウント作成
ToAccount := crypto.GenerateAccount()
fmt.Println("Algorand ToAddress", ToAccount.Address.String())

送金元、送金先のアカウントを作成します。crypto.GenerateAccount を使うと、ランダムなシードから Ed25519 (EdDSA) の公開鍵と秘密鍵のペアを作り、Algorand アドレスまで含めた Address 構造体を返してくれます。

署名前のトランザクションデータ作成

// 3. 署名前のトランザクション作成
unSignedTx := types.Transaction{
	Type: "pay",
	Header: types.Header{
		Sender:      FromAccount.Address,
		FirstValid:  types.Round(startRound),
		LastValid:   types.Round(startRound + 1000),
		Note:        nil,
		GenesisID:   genesisId,
		GenesisHash: ghDigest,
	},
	PaymentTxnFields: types.PaymentTxnFields{
		Receiver:         ToAccount.Address,
		Amount:           types.MicroAlgos(amount),
		CloseRemainderTo: types.Address{},
	},
}
unSignedTx.Fee = types.MicroAlgos(minFee) // 最低手数料を設定
  • Algorand には TxType が 7 種類ありますが、 pay を設定します。
  • FirstValid と LastValid で Tx の有効期間を設定します。有効期間の最大値は 1000 なのでstartRound に加算しているだけです。
  • CloseRemainderTo は通常の送金では使わず、 残高を 0 にしたい場合 に設定します。 Algorandの 最小残高は 0.1 ALGO であり、通常これを下回る残高になる送金は許可されません。その制約を超えて「全額引き出したい」といった場合に送金先のアドレスを設定すると、ここにAmount を差し引いた全残額が送金されて残高 0 になり、アカウントはクローズ状態になります。
// Encode the transaction as msgpack
encodedTx := msgpack.Encode(unSignedTx)

// Prepend the hashable prefix
msgParts := [][]byte{[]byte("TX"), encodedTx}
toBeSigned := bytes.Join(msgParts, nil)

署名前 Tx を SDK の msgpack パッケージを使ってエンコードし、Tx の種別を示す Prefix を付与しています。

署名の作成

// 4. 署名の作成
signature := ed25519.Sign(FromAccount.PrivateKey, toBeSigned)

Ed25519 の署名を作成します。引数は、送金元アカウントの秘密鍵と署名前トランザクションのバイナリ (toBeSigned) です。

署名済みトランザクションの作成

// 5. 署名済みトランザクションの作成
stx := types.SignedTxn{
	Sig: algoSignature,
	Txn: unSignedTx,
}

署名前トランザクションと署名結果を入れた署名済み構造体を作成します。

トランザクションIDが確定

// 6. TxIDの確認
txid := txIDFromRawTxnBytesToSign(toBeSigned)
fmt.Println("Transaction ID", txid)

署名前トランザクション(メッセージ)から TxID が確定します。

Testnetのノードに送信

署名済トランザクションをノードに送信します。

pendingTxID, err := sendTransaction(stxBytes)
if err != nil {
	log.Fatalf("Failed to send transaction: %s\n", err)
}

func sendTransaction(stxBytes []byte) (string, error) {
	algodAddress := "https://testnet-api.algonode.cloud"
	algodToken := strings.Repeat("a", 64)
	algodClient, _ := algod.MakeClient(
		algodAddress,
		algodToken,
	)

	pendingTxID, err := algodClient.SendRawTransaction(stxBytes).Do(context.Background())
	if err != nil {
		return "", err
	}

	return pendingTxID, nil
}

SDK には容易にネットワークに送信できる algod パッケージがあるので、これを使います。

Public Node の Rest API /v2/transactions に向けて、HTTP Header を Content-Type: application/x-binary にし、 Body に署名済みトランザクションデータのバイナリを入れて、POST メソッドで送信します。成功すれば TxID が返却され、失敗であれば多くは 400 Bad Request になり詳しいエラー内容が返ってきます。

Algorand は承認までが速く数秒のため、TxID を Explorer で確認する頃には完了しているでしょう。手数料も 0.001 ALGO と非常に安いのが良いところです。

サンプルコード全文

こちらのリポジトリで公開しています。

https://github.com/skport/go-algo-payment-example

サンプルコードでは、Txを送信する前に確認メッセージが表示されます。実行する度に新しいアカウントを作っているため、送金元のアドレスを確認して Faucet で入金し残高を確保してから(最小残高より多く入金)、Txを送信するようにしてください。

最後に

MultiSig アカウントからの送金についてはリクエストがあれば書こうかと思います。

株式会社Ginco ではブロックチェーンを学びたい方、ウォレットについて詳しくなりたい方を募集していますので下記リンクから是非ご応募ください。

株式会社Ginco の求人一覧

Discussion