diff --git a/Connectors/Http/HttpJsonRpcConnectorAbstract.php b/Connectors/Http/HttpJsonRpcConnectorAbstract.php index 1bcc8e9..3991c43 100644 --- a/Connectors/Http/HttpJsonRpcConnectorAbstract.php +++ b/Connectors/Http/HttpJsonRpcConnectorAbstract.php @@ -22,7 +22,7 @@ abstract class HttpJsonRpcConnectorAbstract implements ConnectorInterface /** - * current node url, for example 'https://api.golos.io' + * current node url, for example 'https://golos.lexa.host' * * if you set several nodes urls, if with first node will be trouble * it will connect after $maxNumberOfTriesToCallApi tries to next node @@ -339,4 +339,4 @@ public function makeUrlFromArray($data) return $url; } -} \ No newline at end of file +} diff --git a/Connectors/WebSocket/WSConnectorAbstract.php b/Connectors/WebSocket/WSConnectorAbstract.php index 3c18317..d238c5c 100644 --- a/Connectors/WebSocket/WSConnectorAbstract.php +++ b/Connectors/WebSocket/WSConnectorAbstract.php @@ -22,7 +22,7 @@ abstract class WSConnectorAbstract implements ConnectorInterface protected static $nodeURL; /** - * current node url, for example 'wss://ws.golos.io' + * current node url, for example 'wss://golos.lexa.host/ws' * * @var string */ @@ -309,4 +309,4 @@ public function doRequest($apiName, array $data, $answerFormat = self::ANSWER_FO return $answer; } -} \ No newline at end of file +} diff --git a/README.md b/README.md index e273429..fe558c5 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,11 @@ namespace GrapheneNodeClient\Tools\ChainOperations - comment // steem or golos - content // only viz - witness_update +- transfer_to_vesting +- withdraw_vesting +- claim +- transfer_to_tip +- transfer_from_tip ```php 2, ChainOperations::OPERATION_CUSTOM_JSON => 18, ChainOperations::OPERATION_WITNESS_UPDATE => 11, + ChainOperations::OPERATION_TRANSFER_TO_VESTING => 3, + ChainOperations::OPERATION_WITHDRAW_VESTING => 4, + ChainOperations::OPERATION_CLAIM => 53, + ChainOperations::OPERATION_TRANSFER_TO_TIP => 55, + ChainOperations::OPERATION_TRANSFER_FROM_TIP => 56, + ]; const FIELDS_TYPES = [ @@ -64,6 +70,36 @@ class ChainOperationsGolos 'account_creation_fee' => OperationSerializer::TYPE_ASSET, 'maximum_block_size' => OperationSerializer::TYPE_INT32, 'sbd_interest_rate' => OperationSerializer::TYPE_INT16 + ], + ChainOperations::OPERATION_TRANSFER_TO_VESTING => [ + 'from' => OperationSerializer::TYPE_STRING, + 'to' => OperationSerializer::TYPE_STRING, + 'amount' => OperationSerializer::TYPE_ASSET + ], + ChainOperations::OPERATION_WITHDRAW_VESTING => [ + 'account' => OperationSerializer::TYPE_STRING, + 'vesting_shares' => OperationSerializer::TYPE_ASSET + ], + ChainOperations::OPERATION_CLAIM => [ + 'from' => OperationSerializer::TYPE_STRING, + 'to' => OperationSerializer::TYPE_STRING, + 'amount' => OperationSerializer::TYPE_ASSET, + 'to_vesting' => OperationSerializer::TYPE_BOOL, + 'extensions' => OperationSerializer::TYPE_SET_EXTENSIONS + ], + ChainOperations::OPERATION_TRANSFER_TO_TIP => [ + 'from' => OperationSerializer::TYPE_STRING, + 'to' => OperationSerializer::TYPE_STRING, + 'amount' => OperationSerializer::TYPE_ASSET, + 'memo' => OperationSerializer::TYPE_STRING, + 'extensions' => OperationSerializer::TYPE_SET_EXTENSIONS + ], + ChainOperations::OPERATION_TRANSFER_FROM_TIP => [ + 'from' => OperationSerializer::TYPE_STRING, + 'to' => OperationSerializer::TYPE_STRING, + 'amount' => OperationSerializer::TYPE_ASSET, + 'memo' => OperationSerializer::TYPE_STRING, + 'extensions' => OperationSerializer::TYPE_SET_EXTENSIONS ] ]; -} \ No newline at end of file +} diff --git a/Tools/ChainOperations/OperationSerializer.php b/Tools/ChainOperations/OperationSerializer.php index 72e746e..bf24952 100644 --- a/Tools/ChainOperations/OperationSerializer.php +++ b/Tools/ChainOperations/OperationSerializer.php @@ -3,24 +3,32 @@ namespace GrapheneNodeClient\Tools\ChainOperations; use GrapheneNodeClient\Connectors\ConnectorInterface; +use GrapheneNodeClient\Tools\ChainOperations\TypeSerializers\TypeSerializerInterface; use StephenHill\Base58; use StephenHill\GMPService; use t3ran13\ByteBuffer\ByteBuffer; class OperationSerializer { - const TYPE_CHAIN_PROPERTIES = 'chain_properties'; - const TYPE_SET_EXTENSIONS = 'set_extensions'; - const TYPE_SET_BENEFICIARIES = 'set_beneficiaries'; - const TYPE_BENEFICIARY = 'set_beneficiary'; - const TYPE_SET_STRING = 'set_string'; - const TYPE_PUBLIC_KEY = 'public_key'; - const TYPE_STRING = 'string'; - const TYPE_INT16 = 'int16'; - const TYPE_INT32 = 'int32'; - const TYPE_ASSET = 'asset'; - const TYPE_BOOL = 'bool'; - const TYPE_INT8 = 'int8'; + const TYPE_CHAIN_PROPERTIES = 'chainProperties'; + const TYPE_DONATE_MEMO = 'donateMemo'; + const TYPE_SET_EXTENSIONS = 'setExtensions'; + const TYPE_SET_BENEFICIARIES = 'setBeneficiaries'; + const TYPE_SET_FUTURE_EXTENSIONS = 'setFutureExtensions'; + const TYPE_SET_STRING = 'setString'; + const TYPE_BENEFICIARY = 'beneficiary'; + const TYPE_PUBLIC_KEY = 'publicKey'; + const TYPE_STRING = 'string'; + const TYPE_INT8 = 'int8'; + const TYPE_INT16 = 'int16'; + const TYPE_INT32 = 'int32'; + const TYPE_INT64 = 'int64'; + const TYPE_ASSET = 'asset'; + const TYPE_BOOL = 'bool'; + const TYPE_VARIANT_OBJECT = 'variantObject'; + const TYPE_OPTIONAL_STRING = 'optionalString'; + const TYPE_VOID = 'void'; + const TYPE_FUTURE_EXTENSIONS = 'futureExtensions'; /** @var array */ protected static $opFieldsMap = []; @@ -130,92 +138,322 @@ public static function getOpFieldsTypes($chainName, $operationName) * @param ByteBuffer $byteBuffer * @param string $chainName * - * @return mixed + * @return void * @throws \Exception */ - public static function serializeType($type, $value, $byteBuffer, $chainName) + public static function serializeType(string $type, $value, ByteBuffer $byteBuffer, string $chainName) { - if ($type === self::TYPE_STRING) { - //Writes a UTF8 encoded string prefixed 32bit base 128 variable-length integer. - $strLength = strlen($value); + $serializer = 'serialize' . ucfirst($type); + self::$serializer($value, $byteBuffer, $chainName); + } - if ($strLength <= 128) { - $byteBuffer->writeInt8($strLength); - } elseif ($strLength <= 16511) { - $strLength = ceil($strLength / 128) * 256 - + ($strLength - ceil($strLength / 128) * 128); - $byteBuffer->writeInt16LE($strLength); - } else { - $n3 = ceil($strLength / (128 * 128)); - $n2 = ceil(($strLength - $n3 * 128 * 128) / 128); - $strLength = $n3 * 256 * 256 - + $n2 * 256 - + ($strLength - $n3 * 128 * 128 - $n2 * 128); - $byteBuffer->writeInt32LE($strLength); - if ($strLength <= 16777215) { - $byteBuffer->setCurrentOffset($byteBuffer->getCurrentOffset() - 1); - } - } - $byteBuffer->writeVStringLE($value); - } elseif ($type === self::TYPE_SET_STRING) { - $byteBuffer->writeInt8(count($value)); - foreach ($value as $string) { - self::serializeType(self::TYPE_STRING, $string, $byteBuffer); + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + */ + public static function serializeString($value, ByteBuffer $byteBuffer, string $chainName) + { + //Writes a UTF8 encoded string prefixed 32bit base 128 variable-length integer. + $strLength = strlen($value); + + if ($strLength <= 128) { + $byteBuffer->writeInt8($strLength); + } elseif ($strLength <= 16511) { + $strLength = ceil($strLength / 128) * 256 + + ($strLength - ceil($strLength / 128) * 128); + $byteBuffer->writeInt16LE($strLength); + } else { + $n3 = ceil($strLength / (128 * 128)); + $n2 = ceil(($strLength - $n3 * 128 * 128) / 128); + $strLength = $n3 * 256 * 256 + + $n2 * 256 + + ($strLength - $n3 * 128 * 128 - $n2 * 128); + $byteBuffer->writeInt32LE($strLength); + if ($strLength <= 16777215) { + $byteBuffer->setCurrentOffset($byteBuffer->getCurrentOffset() - 1); } - } elseif ($type === self::TYPE_INT16) { - $byteBuffer->writeInt16LE($value); - } elseif ($type === self::TYPE_INT32) { - $byteBuffer->writeInt32LE($value); - } elseif ($type === self::TYPE_ASSET) { - list($amount, $symbol) = explode(' ', $value); - - $byteBuffer->writeInt64LE(str_replace('.', '', $amount)); - - $dot = strpos($amount, '.'); - $precision = $dot === false ? 0 : strlen($amount) - $dot - 1; - $byteBuffer->writeInt8($precision); - - $byteBuffer->writeVStringLE(strtoupper($symbol)); - for ($i = 0; $i < 7 - strlen($symbol); $i++) { - $byteBuffer->writeInt8(0); + } + $byteBuffer->writeVStringLE($value); + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + */ + public static function serializeInt8($value, ByteBuffer $byteBuffer, string $chainName) + { + $byteBuffer->writeInt8($value); + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + */ + public static function serializeInt16($value, ByteBuffer $byteBuffer, string $chainName) + { + $byteBuffer->writeInt16LE($value); + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + */ + public static function serializeInt32($value, ByteBuffer $byteBuffer, string $chainName) + { + $byteBuffer->writeInt32LE($value); + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + */ + public static function serializeInt64($value, ByteBuffer $byteBuffer, string $chainName) + { + $byteBuffer->writeInt64LE($value); + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + */ + public static function serializeAsset($value, ByteBuffer $byteBuffer, string $chainName) + { + list($amount, $symbol) = explode(' ', $value); + + $byteBuffer->writeInt64LE(str_replace('.', '', $amount)); + + $dot = strpos($amount, '.'); + $precision = $dot === false ? 0 : strlen($amount) - $dot - 1; + $byteBuffer->writeInt8($precision); + + $byteBuffer->writeVStringLE(strtoupper($symbol)); + for ($i = 0; $i < 7 - strlen($symbol); $i++) { + $byteBuffer->writeInt8(0); + } + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeSetString($value, ByteBuffer $byteBuffer, string $chainName) + { + $byteBuffer->writeInt8(count($value)); + foreach ($value as $string) { + self::serializeString($string, $byteBuffer, $chainName); + } + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeSetExtension($value, ByteBuffer $byteBuffer, string $chainName) + { + $byteBuffer->writeInt8(count($value)); + foreach ($value as $extension) { + $byteBuffer->writeInt8($extension[0]); + if ($extension[0] === 0) { + self::serializeSetBeneficiaries($extension[1], $byteBuffer, $chainName); + } else { + throw new \Exception("There is no serializer logic for '{$extension[0]}' extension"); } - } elseif ($type === self::TYPE_SET_EXTENSIONS) { - $byteBuffer->writeInt8(count($value)); - foreach ($value as $extension) { - $byteBuffer->writeInt8($extension[0]); - if ($extension[0] === 0) { - self::serializeType(self::TYPE_SET_BENEFICIARIES, $extension[1], $byteBuffer); - } else { - throw new \Exception("There is no serializer logic for '{$extension[0]}' extension"); - } + } + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeSetBeneficiaries($value, ByteBuffer $byteBuffer, string $chainName) + { + $byteBuffer->writeInt8(count($value['beneficiaries'])); + foreach ($value['beneficiaries'] as $beneficiary) { + self::serializeBeneficiary($beneficiary, $byteBuffer, $chainName); + } + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeBeneficiary($value, ByteBuffer $byteBuffer, string $chainName) + { + self::serializeString($value['account'], $byteBuffer, $chainName); + self::serializeInt16($value['weight'], $byteBuffer, $chainName); + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeBool($value, ByteBuffer $byteBuffer, string $chainName) + { + self::serializeInt8($value ? 1 : 0, $byteBuffer, $chainName); + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializePublicKey($value, ByteBuffer $byteBuffer, string $chainName) + { + $clearPubKey = substr($value, 3); + $base58 = new Base58(null, new GMPService()); //decode base 58 to str + $stringPubKey = substr($base58->decode($clearPubKey), 0, 33); + $byteBuffer->writeVStringLE($stringPubKey); + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeChainProperties($value, ByteBuffer $byteBuffer, string $chainName) + { + if (count($value) > 0) { + foreach (self::getOpFieldsTypes($chainName, self::TYPE_CHAIN_PROPERTIES) as $field => $type) { + self::serializeType($type, $value[$field], $byteBuffer, $chainName); } - } elseif ($type === self::TYPE_SET_BENEFICIARIES) { - $byteBuffer->writeInt8(count($value['beneficiaries'])); - foreach ($value['beneficiaries'] as $beneficiary) { - self::serializeType(self::TYPE_BENEFICIARY, $beneficiary, $byteBuffer); + } + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeSetFutureExtensions($value, ByteBuffer $byteBuffer, string $chainName) + { + $byteBuffer->writeInt8(count($value)); + foreach ($value as $extension) { + self::serializeFutureExtensions($extension, $byteBuffer, $chainName); + } + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeFutureExtensions($value, ByteBuffer $byteBuffer, string $chainName) + { + throw new \Exception('There is no serializer logic for ' . self::TYPE_FUTURE_EXTENSIONS); + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeDonateMemo($value, ByteBuffer $byteBuffer, string $chainName) + { + if (count($value) > 0) { + foreach (self::getOpFieldsTypes($chainName, self::TYPE_DONATE_MEMO) as $field => $type) { + self::serializeType($type, $value[$field] ?? null, $byteBuffer, $chainName); } - } elseif ($type === self::TYPE_BENEFICIARY) { - self::serializeType(self::TYPE_STRING, $value['account'], $byteBuffer); - self::serializeType(self::TYPE_INT16, $value['weight'], $byteBuffer); - } elseif ($type === self::TYPE_INT8) { - $byteBuffer->writeInt8($value); - } elseif ($type === self::TYPE_BOOL) { - self::serializeType(self::TYPE_INT8, $value ? 1 : 0, $byteBuffer); - } elseif ($type === self::TYPE_PUBLIC_KEY) { - $clearPubKey = substr($value, 3); - $base58 = new Base58(null, new GMPService()); //decode base 58 to str - $stringPubKey = substr($base58->decode($clearPubKey), 0, 33); - $byteBuffer->writeVStringLE($stringPubKey); - } elseif ($type === self::TYPE_CHAIN_PROPERTIES) { - if (count($value) > 0) { - foreach (self::getOpFieldsTypes($chainName, self::TYPE_CHAIN_PROPERTIES) as $field => $type) { - self::serializeType($type, $value[$field], $byteBuffer, $chainName); - } + } + } + + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeVariantObject($value, ByteBuffer $byteBuffer, string $chainName) + { + $byteBuffer->writeInt8(count($value)); + foreach ($value as $key => $val) { + self::serializeString($key, $byteBuffer, $chainName); + if (is_string($val)) { + $prefix = 5; + $type = self::TYPE_STRING; + } elseif (is_int($val)) { + $prefix = 2; + $type = self::TYPE_INT64; + } else { + throw new \Exception('Correct value for ' . self::TYPE_VARIANT_OBJECT . 'is array pf numbers or strings'); } + + self::serializeInt8($prefix, $byteBuffer, $chainName); + self::serializeType($type, $val, $byteBuffer, $chainName); } + } - return $byteBuffer; + /** + * @param mixed $value + * @param ByteBuffer $byteBuffer + * @param string $chainName + * + * @return void + * @throws \Exception + */ + public static function serializeOptionalString($value, ByteBuffer $byteBuffer, string $chainName) + { + if ($value === null) { + self::serializeInt8(0, $byteBuffer, $chainName); + } else { + self::serializeInt8(1, $byteBuffer, $chainName); + self::serializeString($value, $byteBuffer, $chainName); + } } -} \ No newline at end of file +} diff --git a/examples/Broadcast/GetTransactionHex.php b/examples/Broadcast/GetTransactionHex.php index 79854ed..cf4ff97 100644 --- a/examples/Broadcast/GetTransactionHex.php +++ b/examples/Broadcast/GetTransactionHex.php @@ -44,7 +44,7 @@ 'witness_update', [ 'owner' => 't3ran13-miner', - 'url' => 'https://golos.io/@t3ran13-miner', + 'url' => 'https://golos.id/@t3ran13-miner', 'block_signing_key' => 'GLS7eExwRw2Waqrq7DcC1553revU7MWvjHMqK8sbWGScaBfsThnzN', 'props' => [ diff --git a/examples/Broadcast/MoreTest.php b/examples/Broadcast/MoreTest.php new file mode 100644 index 0000000..987e1ce --- /dev/null +++ b/examples/Broadcast/MoreTest.php @@ -0,0 +1,203 @@ +getPlatform(); + +// аккаунт для тестов +$acc="jackvote"; + +// активный (все операции тестировались с ним, кроме donate) и постинг (для donate) ключи +$wif='5_active_key'; +$postingWif='5_posting_key'; + +$signKey=['active' => $wif]; + +/** @var CommandQueryData $tx */ +$tx = Transaction::init($connector); + +// ТЕСТОВЫЕ БЛОКИ: раскомментируйте только одну нужную операцию (или выполнится последняя) +//$oper="transfer"; +//$oper="transfer_to_vesting"; +//$oper="withdraw_vesting"; // для отмены вывода раскомментируйте в блоке $limit=0; +//$oper="claim"; +$oper="donate"; +//$oper="vote"; +//$oper="transfer_to_tip"; +//$oper="transfer_from_tip"; + +echo "
\n".$oper."
\n"; + +if ($oper=="transfer") { +// TRANSFER + $tx->setParamByKey( + '0:operations:0', + [ + 'transfer', + [ + 'from' => $acc, + 'to' => 'jackvote', + 'amount' => '1.000 GOLOS', + 'memo' => 'Successfully transfer' + ] + ] + ); +// END TRANSFER +} elseif ($oper=="transfer_to_vesting") { +// TRANSFER TO VESTING + $tx->setParamByKey( + '0:operations:0', + [ + 'transfer_to_vesting', + [ + 'from' => $acc, + 'to' => 'jackvote', + 'amount' => '1.000 GOLOS', + 'memo' => 'Successfully to vesting' + ] + ] + ); +// END TRANSFER TO VESTING +} elseif ($oper=="withdraw_vesting") { +// WITHDRAW VESTING +// Определяем доступную для вывода СГ + $command = new Commands($connector); + $command = $command->get_accounts(); + $commandQuery = new CommandQueryData(); + $commandQuery->setParamByKey('0', [$acc]); + $content = $command->execute($commandQuery); + $obj=$content['result'][0]; + $limit=preg_replace("/[^\d.]+/", "", $obj['vesting_shares'])-preg_replace("/[^\d.]+/", "", $obj['delegated_vesting_shares']); +// $limit=0; - для отмены вывода '0.000000 GESTS' + $limit=sprintf("%01.6f", $limit); + + $tx->setParamByKey( + '0:operations:0', + [ + 'withdraw_vesting', + [ + 'account' => $acc, + 'vesting_shares' => $limit.' GESTS' + ] + ] + ); +// END WITHDRAW VESTING +} elseif ($oper=="claim") { +// CLAIM + $tx->setParamByKey( + '0:operations:0', + [ + 'claim', + [ + 'from' => $acc, + 'to' => 'jackvote', + 'amount' => '1.000 GOLOS', + 'to_vesting' => true, // true - в СГ, false - в TIP + 'extensions' => [] + ] + ] + ); +// END CLAIM +} elseif ($oper=="donate") { +// DONATE + $signKey=['posting' => $postingWif]; + + $tx->setParamByKey( + '0:operations:0', + [ + 'donate', + [ + 'from' => $acc, + 'to' => 'tiptoken', + 'amount' => '1.000 GOLOS', + 'memo' => + [ + 'app' => "php-graphene-node-client", + 'version' => 1, + 'target' => + [ + 'account' => "tiptoken", + 'reason' => "test library" + ], + 'comment' => "Successfully donate" + ], + 'extensions' => [] + ] + ] + ); +// END CLAIM +} elseif ($oper=="vote") { +// VOTE + $signKey=['posting' => $postingWif]; + + $tx->setParamByKey( + '0:operations:0', + [ + 'vote', + [ + 'voter' => $acc, + 'author' => "jackvote", + 'permlink' => "anekdot-2-raza-vypusk-1250", + 'weight' => 1000 + ] + ] + ); +// END VOTE +} elseif ($oper=="transfer_to_tip") { +// TRANSFER TO TIP - с баланса GOLOS(!) + $tx->setParamByKey( + '0:operations:0', + [ + 'transfer_to_tip', + [ + 'from' => $acc, + 'to' => 'jackvote', + 'amount' => '1.000 GOLOS', + 'memo' => 'Successfully to tip', + 'extensions' => [] + ] + ] + ); +// END TRANSFER TO TIP +} elseif ($oper=="transfer_from_tip") { +// TRANSFER FROM TIP - в СГ (не на баланс!) + $tx->setParamByKey( + '0:operations:0', + [ + 'transfer_from_tip', + [ + 'from' => $acc, + 'to' => 'jackvote', + 'amount' => '1.000 GOLOS', + 'memo' => 'Successfully from tip', + 'extensions' => [] + ] + ] + ); +// END TRANSFER FROM TIP +} +// Общая часть для любой операции: подпись ключом и выполнение операции +echo "
";
+print_r($tx);
+echo "
"; + +Transaction::sign($chainName, $tx, $signKey); // подписываем операцию соответствующим ключом + +$command = new BroadcastTransactionSynchronousCommand($connector); + +$answer = $command->execute( + $tx +); + +echo "
\n
\n
\n";
+print_r($answer);
+echo "
"; +?> diff --git a/examples/Broadcast/WitnessUpdate.php b/examples/Broadcast/WitnessUpdate.php index 503f34f..e89c50d 100644 --- a/examples/Broadcast/WitnessUpdate.php +++ b/examples/Broadcast/WitnessUpdate.php @@ -44,7 +44,7 @@ 'witness_update', [ 'owner' => 'guest123', - 'url' => 'https://golos.io/@guest123', + 'url' => 'https://golos.id/@guest123', 'block_signing_key' => 'GLS7eExwRw2Waqrq7DcC1553revU7MWvjHMqK8sbWGScguest123', 'props' => [