An open API service indexing awesome lists of open source software.

https://github.com/creativechain/php-graphene-node-client


https://github.com/creativechain/php-graphene-node-client

Last synced: 5 months ago
JSON representation

Awesome Lists containing this project

README

          

# php-graphene-node-client
PHP client for connection to [CREA](https://gitlab.com/creativechain) node

## Install Via Composer
#### For readonly, without broadcast
```
composer require crea/php-graphene-node-client
```
#### with broadcast (sending transactions to blockchain)
\(details are [here](https://golos.io/ru--otkrytyij-kod/@php-node-client/podklyuchenie-secp256k1-php-k-php-dockerfile)\) and actual dockerfile and requests examples see in branch ["debug"](https://github.com/crea/php-graphene-node-client/tree/debug)

install components
- automake
- libtool
- libgmp-dev

install extensions
- Bit-Wasp/secp256k1-php v0.2.1 \(how to install [secp256k1-php](https://github.com/Bit-Wasp/secp256k1-php)\)
- gmp

## Basic Usage
```php
$limit,
'tag' => 'crea', // for CREA
]
];
$commandQuery->setParams($data);

//OR
$commandQuery = new CommandQueryData();
$commandQuery->setParamByKey('0:limit', $limit);
$commandQuery->setParamByKey('0:select_tags', [$tag]);
$commandQuery->setParamByKey('0:tag', $tag);

//and use single command
$command = new GetDiscussionsByCreatedCommand(new CreaWSConnector());
$golosPosts = $command->execute(
$commandQuery
);

//or commands aggregator class
$commands = new Commands(new CreaWSConnector());
$golosPosts = $commands->get_discussions_by_created()
->execute(
$commandQuery
);

// will return
// [
// "id" => 1,
// "result" => [
// [
// "id": 466628,
// "author": "piranya",
// "permlink": "devyatyi-krug",
// ...
// ],
// ...
// ]
// ]


//single command
$command = new GetDiscussionsByCreatedCommand(new CreaWSConnector());
$steemitPosts = $command->execute(
$commandQuery,
'result',
CreaWSConnector::ANSWER_FORMAT_ARRAY // or CreaWSConnector::ANSWER_FORMAT_OBJECT
);

//or commands aggregator class
$commands = new Commands(new CreaWSConnector());
$golosPosts = $commands->get_discussions_by_created()
->execute(
$commandQuery,
'result',
CreaWSConnector::ANSWER_FORMAT_ARRAY // or CreaWSConnector::ANSWER_FORMAT_OBJECT
);

// will return
// [
// [
// "id": 466628,
// "author": "piranya",
// "permlink": "devyatyi-krug",
// ...
// ],
// ...
// ]

```

## Implemented Commands List

### Single Commands
- BroadcastTransactionCommand
- BroadcastTransactionSynchronousCommand
- GetAccountCountCommand
- GetAccountHistoryCommand
- GetAccountsCommand
- GetAccountVotesCommand
- GetActiveWitnessesCommand
- GetApiByNameCommand //ONLY STEEM/whaleshares
- GetBlockCommand
- GetBlockHeaderCommand
- GetConfigCommand
- GetContentCommand
- GetContentRepliesCommand
- GetCurrentMedianHistoryPriceCommand //STEEM/GOLOS
- GetDiscussionsByAuthorBeforeDateCommand
- GetDiscussionsByBlogCommand
- GetDiscussionsByCreatedCommand
- GetDiscussionsByFeedCommand
- GetDiscussionsByTrendingCommand
- GetDynamicGlobalPropertiesCommand
- GetFollowersCommand
- GetOpsInBlock
- GetTrendingCategoriesCommand //only steem/whaleshares
- GetVersionCommand
- GetWitnessesByVoteCommand
- LoginCommand //ONLY for STEEM/whaleshares

All single commands can be called through Commands Class as methods (example: (new Commands)->get_block()->execute(...) )

### broadcast operations templates

namespace GrapheneNodeClient\Tools\ChainOperations

- vote
- transfer
- comment // crea

```php
5
// [result] => Array
// (
// [id] => a2c52988ea870e446480782ff046994de2666e0d
// [block_num] => 17852337
// [trx_num] => 1
// [expired] =>
// )
//
//)

```

## Implemented Connectors List

namespace: GrapheneNodeClient\Connectors\WebSocket OR GrapheneNodeClient\Connectors\Http;

- CreaWSConnector
- CreaHttpJsonRpcConnector

#### Switching between connectors
```php
setParamByKey('0', 'author');
$commandQuery->setParamByKey('1', 'permlink');

//OR
$commandQuery = new CommandQueryData();
$commandQuery->setParams(
[
0 => "author",
1 => "permlink"
]
);

$content = $command->execute(
$commandQuery
);
// will return
// [
// "id" => 1,
// "result" => [
// ...
// ]
// ]

```

## Creating Own Connector
```php
[ 'apiName' => 'api_name', 'fields'=>['массив с полями из команды']]];
protected static $map = [
//...
'broadcast_transaction' => [
'apiName' => 'network_broadcast_api',
'fields' => [
'0:ref_block_num' => ['integer'],
'0:ref_block_prefix' => ['integer'],
'0:expiration' => ['string'],
'0:operations:*:0' => ['string'],
'0:operations:*:1' => ['array'],
'0:extensions' => ['array'],
'0:signatures' => ['array']
]
],
//...
'broadcast_transaction' => [
'apiName' => 'your_method',
'fields' => [
//your fields
]
]
];
}

```

# Tools
## Transliterator

```php
setParamByKey(
'0:operations:0',
[
'vote',
[
'voter' => $voter,
'author' => $author,
'permlink' => $permlink,
'weight' => $weight
]
]
);
$command = new BroadcastTransactionSynchronousCommand($connector);
Transaction::sign($chainName, $tx, ['posting' => $publicWif]);

$trxString = mb_strlen(json_encode($tx->getParams()), '8bit');
if (Bandwidth::isEnough($connector, $voter, 'market', $trxString)) {
$answer = $command->execute(
$tx
);
}

//or other way

$bandwidth = Bandwidth::getBandwidthByAccountName($voter, 'market', $connector);

//Array
//(
// [used] => 3120016
// [available] => 148362781
//)

if ($trxString * 10 + $bandwidth['used'] < $bandwidth['available']) {
$answer = $command->execute(
$tx
);
}

//

```

## Transaction for blockchain (broadcast)

```php
setParamByKey(
'0:operations:0',
[
'vote',
[
'voter' => $voter,
'author' => $author,
'permlink' => $permlink,
'weight' => $weight
]
]
);

$command = new BroadcastTransactionSynchronousCommand($connector);
Transaction::sign($chainName, $tx, ['posting' => $publicWif]);

$answer = $command->execute(
$tx
);

```

** WARNING**

Transactions are signing with spec256k1-php with function secp256k1_ecdsa_sign_recoverable($context, $signatureRec, $msg32, $privateKey) and if it is not canonical from first time, you have to make transaction for other block. For searching canonical sign function have to implement two more parameters, but spec256k1-php library does not have it.
It is was solved with php-hack in Transaction::sign()
```php
...
//becouse spec256k1-php canonical sign trouble will use php hack.
//If sign is not canonical, we have to chang msg (we will add 1 sec to tx expiration time) and try to sign again
$nTries = 0;
while (true) {
$nTries++;
$msg = self::getTxMsg($chainName, $trxData);
echo '

' . print_r($trxData->getParams(), true) . '
'; //FIXME delete it

try {
foreach ($privateWIFs as $keyName => $privateWif) {
$index = count($trxData->getParams()[0]['signatures']);

/** @var CommandQueryData $trxData */
$trxData->setParamByKey('0:signatures:' . $index, self::signOperation($msg, $privateWif));
}
break;
} catch (TransactionSignException $e) {
if ($nTries > 200) {
//stop tries to find canonical sign
throw $e;
break;
} else {
/** @var CommandQueryData $trxData */
$params = $trxData->getParams();
foreach ($params as $key => $tx) {
$tx['expiration'] = (new \DateTime($tx['expiration']))
->add(new \DateInterval('PT0M1S'))
->format('Y-m-d\TH:i:s\.000');
$params[$key] = $tx;
}
$trxData->setParams($params);
}
}
...
```

## Tests
You need to install PhpUnit in your system (https://phpunit.de/manual/3.7/en/installation.html)
```
cd Tests
phpunit CommandsTest.php
phpunit CommandsTest.php --filter=testGetBlock // test only one command
```