この記事は、以下に紹介したtsunagi-functionsのPHP実装版です。
トランザクション構築の内部処理やノードへの通知方法については以下の記事もご参考ください。
Symbolブロックチェーンをよく知らないという方はこちらで速習することができます。
リポジトリ
tsunagi-functions for PHP
関数群の提供のため、sdkという名称は今後functionsに変更予定です。
テスト
テストスクリプトを以下に置いています。実行することができればそのロジックをそのまま実装に利用することができます。
test_0_1.php
composer.json
{
"require": {
"christian-riesen/base32": "^1.6"
}
}
テスト実行
vendor/bin/phpunit test_0_1.php
実装例
まずは簡単な実装例を紹介します。
転送トランザクション
$private_key = "94ee0f4d7fe388ac4b04a6a6ae2ba969617879b83616e4d25710d688a89d80c75f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb";
$this->network = [
"version" => 1,
"network" => "TESTNET",
"generationHash" => "7fccd304802016bebbcd342a332f91ff1f3bb5e902988b352697be245f48e836",
"epochAdjustment" => 1637848847,
"catjasonBase" => "https://xembook.github.io/tsunagi-sdk/catjson/",
];
$now = $this->network["epochAdjustment"] * 1000;
$this->deadline_time = ((intval($now/1000) + 7200) - 1637848847) * 1000;
//$deadline_time = ((time() + 7200) - 1637848847) * 1000;
$tx1 = [
"type" => "TRANSFER",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"recipient_address" => generate_address_id("TCO7HLVDQUX6V7C737BCM3VYJ3MKP6REE2EKROA"),
"mosaics" => [
["mosaic_id" => 0x2A09B7F9097934C2, "amount" => 1],
["mosaic_id" => 0x3A8416DB2D53B6C8, "amount" => 100],
],
"message" => "Hello Tsunagi(Catjson) SDK!",
];
$catjson = load_catjson($tx1,$this->network);
$layout = load_layout($tx1,$catjson,false); //isEmbedded false
$prepared_tx = prepare_transaction($tx1,$layout,$this->network); //TX事前準備
$parsed_tx = parse_transaction($prepared_tx,$layout,$catjson,$this->network);
$built_tx = build_transaction($parsed_tx); //TX構築
$signature = sign_transaction($built_tx,$private_key,$this->network);
$built_tx = update_transaction($built_tx,"signature","value",$signature);
$tx_hash = hash_transaction($tx1["signer_public_key"],$signature,$built_tx,$this->network);
$payload = hexlify_transaction($built_tx);
通知
$node = "https://sym-test-01.opening-line.jp:3001";
$params = array(
"payload" => $payload
);
$params = json_encode($params); // json化
$header = array(
"Content-Type: application/json",
);
$context = array(
"http" => array(
"method" => 'PUT',
"header" => implode("\r\n", $header),
"content" => $params
)
);
$json_response = file_get_contents($node . "/transactions" ,false,stream_context_create($context));
echo $json_response . PHP_EOL;
echo $http_response_header . PHP_EOL;
連署
連署を必要とするトランザクションの場合は、$tx1 に加えて以下のような定義と署名の追加が必要になります。
$cosignature1 = [
"version" => 0,
"signer_public_key" =>"6199bae3b241df60418e258d046c22c8c1a5de2f4f325753554e7fd9c650afec",
"signature"=>"",
];
$cosignature2 = [
"version" => 0,
"signer_public_key" => "886adfbd4213576d63ea7e7a4bece61c6933c27cd2ff36f85155c8febfb6eb4e",
"signature" => "",
];
$agg_tx = [
"type" => 'AGGREGATE_COMPLETE',
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 1000000,
"deadline" => $this->deadline_time,
"transactions" => [$tx1,$tx2,$tx3],
"cosignatures" => [$cosignature1,$cosignature2]
];
$catjson = load_catjson($agg_tx,$this->network);
$layout = load_layout($agg_tx,$catjson,false); //isEmbedded false
$prepared_tx = prepare_transaction($agg_tx,$layout,$this->network); //TX事前準備
$parsed_tx = parse_transaction($prepared_tx,$layout,$catjson,$this->network);
$built_tx = build_transaction($parsed_tx); //TX構築
$private_key = "94ee0f4d7fe388ac4b04a6a6ae2ba969617879b83616e4d25710d688a89d80c75f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb";
$signature = sign_transaction($built_tx,$private_key,$this->network);
$built_tx = update_transaction($built_tx,"signature","value",$signature);
$tx_hash = hash_transaction($agg_tx["signer_public_key"],$signature,$built_tx,$this->network);
//連署
$bob_private_key = "fa6373f4f497773c5cc55c103e348b139461d61fd4b45387e69d08a68000e06b6199BAE3B241DF60418E258D046C22C8C1A5DE2F4F325753554E7FD9C650AFEC";
$carol_private_key = "1e090b2a266877a9f88a510af2eb0945a63dc69dbce674ccd83272717d4175cf886ADFBD4213576D63EA7E7A4BECE61C6933C27CD2FF36F85155C8FEBFB6EB4E";
$prepared_tx["cosignatures"][0]["signature"] = cosign_transaction($tx_hash,$bob_private_key);
$prepared_tx["cosignatures"][1]["signature"] = cosign_transaction($tx_hash,$carol_private_key);
$filter_layout = array_filter($layout,function($fl){
return $fl["name"] === "cosignatures";
});
$cosignatures_layout = array_values($filter_layout);
$parsed_cosignatures = parse_transaction($prepared_tx,$cosignatures_layout,$catjson,$this->network); //連署TXの構築
$built_tx = update_transaction($built_tx,"cosignatures","layout",$parsed_cosignatures[0]["layout"]);
$payload = hexlify_transaction($built_tx);
トランザクションタイプ別記述例
その他のトランザクションの記述方法について説明します。
アグリゲートボンデッドトランザクション
ハッシュロックトランザクション
$tx1 = [
"type" => "HASH_LOCK",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"mosaic" => [["mosaic_id" => 0x3A8416DB2D53B6C8, "amount" => 10000000]],
"duration" => 480,
"hash" => "a3ed27ee26592f6c501349a7de3427fc729e8d625ed214a6331c11b981f59f78"
];
ボンデッド
$agg_tx = [
"type" => 'AGGREGATE_BONDED',
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 1000000,
"deadline" => $this->deadline_time,
"transactions" => [$tx1,$tx2,$tx3],
];
モザイク生成
$tx1 = [
"type" => "MOSAIC_DEFINITION",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"duration" => 0,
"id" => generate_mosaic_id(generate_address_id("TBUXMJAYYW3EH3XHBZXSBVGVKXKZS4EH26TINKI"),$nonce),
"nonce" => $nonce,
"flags" => 'TRANSFERABLE RESTRICTABLE',
"divisibility" => 2,
];
$tx2 = [
"type" => "MOSAIC_SUPPLY_CHANGE",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"duration" => 0,
"mosaic_id" => generate_mosaic_id(generate_address_id("TBUXMJAYYW3EH3XHBZXSBVGVKXKZS4EH26TINKI"),$nonce),
"delta" => 1000 * 100,
"action" => 'INCREASE',
];
ネームスペース生成
ルートネームスペース
$tx1 = [
"type" => "NAMESPACE_REGISTRATION",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"duration" => 86400,
"registration_type" => "ROOT",
"name" => "xembook",
"id" => generate_namespace_id("xembook"),
];
サブネームスペース
$tx1 = [
"type" => "NAMESPACE_REGISTRATION",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"parent_id" => generate_namespace_id("xembook"),
"registration_type" => "CHILD",
"name" => "tomato",
"id" => generate_namespace_id("tomato",generate_namespace_id("xembook")),
];
アドレスへのリンク
$tx1 = [
"type" => "ADDRESS_ALIAS",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"namespace_id" => generate_namespace_id("xembook"),
"address" => generate_address_id("TBUXMJAYYW3EH3XHBZXSBVGVKXKZS4EH26TINKI"),
"alias_action" => "LINK"
];
モザイクへのリンク
$tx1 = [
"type" => "MOSAIC_ALIAS",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"namespace_id" => generate_namespace_id("tomato",generate_namespace_id("xembook")),
"mosaic_id" => 0x4DAFFBE5505DE676,
"alias_action" => "LINK"
];
メタデータ
モザイクへのメタデータ
$tx1 = [
"type" => "MOSAIC_METADATA",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"target_address" => generate_address_id("TBUXMJAYYW3EH3XHBZXSBVGVKXKZS4EH26TINKI"),
"target_mosaic_id" => 0x4DAFFBE5505DE676,
"scoped_metadata_key" => generate_key("key_mosaic"),
"value_size_delta" => 27,
"value" => "Hello Tsunagi(Catjson) SDK!",
];
$agg_tx = [
"type" => 'AGGREGATE_COMPLETE',
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 1000000,
"deadline" => $this->deadline_time,
"transactions" => [$tx1],
];
ネームスペースへのメタデータ
$tx1 = [
"type" => "NAMESPACE_METADATA",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"target_address" => generate_address_id("TBUXMJAYYW3EH3XHBZXSBVGVKXKZS4EH26TINKI"),
"target_namespace_id" => generate_namespace_id("xembook"),
"scoped_metadata_key" => generate_key("key_namespace"),
"value_size_delta" => 27,
"value" => "Hello Tsunagi(Catjson) SDK!",
];
$agg_tx = [
"type" => 'AGGREGATE_COMPLETE',
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 1000000,
"deadline" => $this->deadline_time,
"transactions" => [$tx1],
];
マルチシグ
$tx1 = [
"type" => "MULTISIG_ACCOUNT_MODIFICATION",
"signer_public_key" => "66adb706bc9a93e6e803b2b76a1341a8acd98690ef204b402643ae3d4701ee77",
"min_removal_delta" => 1,
"min_approval_delta" => 1,
"address_additions" => [
generate_address_id("TCO7HLVDQUX6V7C737BCM3VYJ3MKP6REE2EKROA"),
generate_address_id("TBUXMJAYYW3EH3XHBZXSBVGVKXKZS4EH26TINKI"),
],
"address_deletions" => [],
];
$cosignature1 = [
"version" => 0,
"signer_public_key" =>"5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"signature"=>"",
];
$cosignature2 = [
"version" => 0,
"signer_public_key" => "6199bae3b241df60418e258d046c22c8c1a5de2f4f325753554e7fd9c650afec",
"signature" => "",
];
$agg_tx = [
"type" => 'AGGREGATE_COMPLETE',
"signer_public_key" => "66adb706bc9a93e6e803b2b76a1341a8acd98690ef204b402643ae3d4701ee77",
"fee" => 1000000,
"deadline" => $this->deadline_time,
"transactions" => [$tx1],
"cosignatures" => [$cosignature1,$cosignature2]
];
制限
アカウントアドレス制限
$tx1 = [
"type" => "ACCOUNT_ADDRESS_RESTRICTION",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"restriction_flags" => "ADDRESS BLOCK OUTGOING",
"restriction_additions" => [
generate_address_id("TCO7HLVDQUX6V7C737BCM3VYJ3MKP6REE2EKROA"),
generate_address_id("TDZBCWHAVA62R4JFZJJUXQWXLIRTUK5KZHFR5AQ")
],
"restriction_deletions" => [],
];
アカウントモザイク制限
$tx1 = [
"type" => "ACCOUNT_MOSAIC_RESTRICTION",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"restriction_flags" => "MOSAIC_ID BLOCK",
"restriction_additions" => [0x4DAFFBE5505DE676,0x2A09B7F9097934C2],
"restriction_deletions" => [],
];
アカウント操作制限
$tx1 = [
"type" => "ACCOUNT_OPERATION_RESTRICTION",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"restriction_flags" => "TRANSACTION_TYPE BLOCK OUTGOING",
"restriction_additions" => ["TRANSFER","AGGREGATE_COMPLETE"],
"restriction_deletions" => [],
];
グローバルモザイク制限
モザイクグローバル制限
$tx1 = [
"type" => "MOSAIC_GLOBAL_RESTRICTION",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"mosaic_id" => 0x4DAFFBE5505DE676,
"reference_mosaic_id" => 0,
"restriction_key" => generate_key("key_account"),
"previous_restriction_value" => 0,
"new_restriction_value" => 0x1,
"previous_restriction_type" => "NONE",
"new_restriction_type" => "EQ"
];
モザイクアドレス制限
$tx1 = [
"type" => "MOSAIC_ADDRESS_RESTRICTION",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"mosaic_id" => 0x4DAFFBE5505DE676,
"restriction_key" => generate_key("key_account"),
"previous_restriction_value" => 0xFFFFFFFFFFFFFFFF,
"new_restriction_value" => 0x1,
"target_address" => generate_address_id("TBUXMJAYYW3EH3XHBZXSBVGVKXKZS4EH26TINKI"),
];
リボーカブルトランザクション
$tx1 = [
"type" => "MOSAIC_SUPPLY_REVOCATION",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"source_address" => generate_address_id("TBUXMJAYYW3EH3XHBZXSBVGVKXKZS4EH26TINKI"),
"mosaic" => [
["mosaic_id" => 0x0552BC5EF5BD589D, "amount" => 100],
],
];
シークレット
シークレットロック
$tx1 = [
"type" => "SECRET_LOCK",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"recipient_address" => generate_address_id("TBUXMJAYYW3EH3XHBZXSBVGVKXKZS4EH26TINKI"),
"secret" => "f260bfb53478f163ee61ee3e5fb7cfcaf7f0b663bc9dd4c537b958d4ce00e240",
"mosaic" => [
["mosaic_id" => 0x3A8416DB2D53B6C8, "amount" => 10000000],
],
"duration" => 480,
"hash_algorithm" => "SHA3_256",
];
シークレットプルーフ
$tx1 = [
"type" => "SECRET_PROOF",
"signer_public_key" => "5f594dfc018578662e0b5a2f5f83ecfb1cda2b32e29ff1d9b2c5e7325c4cf7cb",
"fee" => 25000,
"deadline" => $this->deadline_time,
"recipient_address" => generate_address_id("TBUXMJAYYW3EH3XHBZXSBVGVKXKZS4EH26TINKI"),
"secret" => "f260bfb53478f163ee61ee3e5fb7cfcaf7f0b663bc9dd4c537b958d4ce00e240",
"hash_algorithm" => "SHA3_256",
"proof" => "7944496ac0f572173c2549baf9ac18f893aab6d0",
];