Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 49 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Codec supports `PSR-4` autoloaders.

```php
<?php

# When installed via composer
require_once 'vendor/autoload.php';
```
Expand All @@ -44,7 +45,9 @@ require_once 'vendor/autoload.php';

```php
<?php

use Rpc\SubstrateRpc;

// http client
$httpClient = new SubstrateRpc("https://kusama-rpc.polkadot.io/");
// websocket client
Expand All @@ -56,17 +59,19 @@ $websocketClient->close(); // close websocket connection

```php
<?php

use Rpc\SubstrateRpc;

$client = new SubstrateRpc("wss://kusama-rpc.polkadot.io/");

// call any json rpc you can use $client->rpc->{$pallet_name}->{$method}, like
// call rpc system_health
$res = $client->rpc->system->health();
$res = $client->rpc->system->health();
var_dump($res); #{"peers": 31, "isSyncing": false, "shouldHavePeers": true}
// or call rpc chain_getFinalizedHead
$client->rpc->chain->getFinalizedHead();
$client->rpc->chain->getFinalizedHead();

$client->close(); // do not forget close websocket connection !
$client->close(); // close websocket connection
```

* Hasher
Expand All @@ -75,23 +80,24 @@ We currently support 6 hash methods, including Blake2_128,Blake2_256,Twox128

```php
<?php

use Rpc\Hasher\Hasher;

$hasher = new Hasher();
// Blake2_128
$hasher->ByHasherName("Blake2_128", "20be52a5a80cad065651ec35fcb1a212bc669aabb52d68d8780a41e29ec9c83e");
// Blake2_256
$hasher->ByHasherName("Blake2_256", "20be52a5a80cad065651ec35fcb1a212bc669aabb52d68d8780a41e29ec9c83e")
$hasher->ByHasherName("Blake2_256", "20be52a5a80cad065651ec35fcb1a212bc669aabb52d68d8780a41e29ec9c83e");
// Twox128
$hasher->TwoxHash("Key", 128)
// Twox128
$hasher->TwoxHash("Sudo", 256)
$hasher->TwoxHash("Key", 128);
// Twox256
$hasher->TwoxHash("Sudo", 256);
// XXHash64
$hasher->XXHash64(0, "test");
// Twox64Concat
$hasher->ByHasherName("Twox64Concat", "0xad2ecd66275a1ded")
$hasher->ByHasherName("Twox64Concat", "0xad2ecd66275a1ded");
// Blake2_128Concat
$hasher->ByHasherName("Blake2_128Concat", "20be")
$hasher->ByHasherName("Blake2_128Concat", "20be");
````

* Storage key
Expand All @@ -102,22 +108,21 @@ rpc [state_getStorage](https://polkadot.js.org/docs/substrate/rpc#getstoragechil

```php
<?php
use Rpc\StorageKey;

use Rpc\StorageKey;
use Codec\Base;
use Codec\ScaleBytes;
use Codec\Types\ScaleInstance;
use Rpc\StorageKey;

$codec = new ScaleInstance(Base::create());
$metadataV14RawValue = "...." // from json rpc state_getMetadata
$metadataV14RawValue = "...."; // from json rpc state_getMetadata
$metadata = $codec->process("metadata", new ScaleBytes($metadataV14RawValue))["metadata"];
// Timestamp.now storage key
$hasher = new Hasher();
print_r(StorageKey::encode($hasher,"Timestamp", "now", $metadata, []));
print_r(StorageKey::encode($hasher, "Timestamp", "now", $metadata, []));
// Staking.Bonded storage key with param accountId
print_r(StorageKey::encode($hasher,"System", "Account", $metadata, ["0x1c79a5ada2ff0d55aaa65dfeaf0cba667babf312f9bf100444279b34cd769e49"]))

print_r(StorageKey::encode($hasher, "System", "Account", $metadata, ["0x1c79a5ada2ff0d55aaa65dfeaf0cba667babf312f9bf100444279b34cd769e49"]));
```

* Json RPC
Expand All @@ -142,35 +147,37 @@ Below is a simple example of sending a token, you can use tx.<module>.<method> t

```php
<?php

use Rpc\KeyPair\KeyPair;
use Rpc\SubstrateRpc;

$AliceSeed = "0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a";
$BobId = ["Id" => "8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48"];
$wsClient = new SubstrateRpc($endpoint);
$hasher = new Hasher();
$wsClient->setSigner(KeyPair::initKeyPair("sr25519", $AliceSeed, $hasher),$hasher);
$wsClient->setSigner(KeyPair::initKeyPair("sr25519", $AliceSeed, $hasher), $hasher);
$tx = $wsClient->tx;
$result = $tx->Balances->transfer($BobId, 12345);
var_dump($result); // transaction hash

// if you want waiting transaction exec, you can set tx with option
// If you want to wait for the transaction to be executed, you can set tx with the option
$tx->withOpt(["subscribe" => true]);
$result = $tx->Balances->transfer($BobId, 12345);
var_dump($result); // Will not return until execution is complete
$wsClient->close()
var_dump($result); // will not return until execution is complete
$wsClient->close();
````

### Keyring

The Keyring allows you to perform operations on these keys (such as sign/verify) and never exposes the secretKey

to the outside world. Support ed25519(Edwards https://ed25519.cr.yp.to/) or sr25519(
schnorrkel https://github.com/w3f/schnorrkel)
The Keyring allows you to perform operations on these keys (such as sign/verify) and never exposes the secretKey to the outside world.
Support [ed25519](https://ed25519.cr.yp.to/) or [sr25519](https://github.com/w3f/schnorrkel).

```php
<?php

use Rpc\KeyPair\KeyPair;
$keyPair = KeyPair::initKeyPair("sr25519|ed25519", {$secretKey}, new Hasher());

$keyPair = KeyPair::initKeyPair("sr25519|ed25519", $secretKey, new Hasher());
// signed msg
$signature = $keyPair->sign("msg");
// verify this message
Expand All @@ -188,9 +195,11 @@ We currently support ink metadata v0,v1,v2,v3,v4.

```php
<?php

use Rpc\Contract\Abi\Convert;
use Codec\Base;
use Codec\Types\ScaleInstance;

$content = json_decode(file_get_contents(__DIR__ . '/ink/ink_v0.json'), true);
$metadata = Convert::toLatest($content); // convert metadata to latest version
// reg metadata types
Expand All @@ -209,30 +218,32 @@ Below is an example.

```php
<?php

use Rpc\KeyPair\KeyPair;
use Rpc\SubstrateRpc;
use Rpc\Contract;

$wsClient = new SubstrateRpc($endpoint);
// set deployer keyring
$hasher = new Hasher();
$wsClient->setSigner(KeyPair::initKeyPair("sr25519",$seed, $hasher),$hasher);
$wsClient->setSigner(KeyPair::initKeyPair("sr25519", $seed, $hasher), $hasher);
$contract = new Contract($wsClient->tx);
// $inputData = constructor_selector + encode(args...)
$result = $contract->new($contract_code, $inputData); // with default option

# If you need to additionally set the gas limit and storageDepositLimit, you can set it like this
$result = $contract->new($contract_code, $inputData,[], ["gasLimit"=>100000,"storageDepositLimit"=>50000]); // with default option
$result = $contract->new($contract_code, $inputData, [], ["gasLimit" => 100000, "storageDepositLimit" => 50000]); // with default option
```

#### Read Contract state

Reading the storage on the contract does not consume any gas, so anyone can read the contract.

You can simply read the contract through ```$contract->state->{$method}($param1,$param2)```
You can simply read the contract through ```$contract->state->{$method}($param1, $param2);```

```php
<?php

use Rpc\KeyPair\KeyPair;
use Rpc\SubstrateRpc;
use Rpc\Contract;
Expand All @@ -241,7 +252,7 @@ use Rpc\Contract\ContractExecResult;
$wsClient = new SubstrateRpc($endpoint);
// set signer
$hasher = new Hasher();
$wsClient->setSigner(KeyPair::initKeyPair("sr25519", $seed, $hash),$hash);
$wsClient->setSigner(KeyPair::initKeyPair("sr25519", $seed, $hash), $hash);
// get abi
$v4 = ContractMetadataV4::to_obj(json_decode(file_get_contents(__DIR__ . '/ink/ink_v4.json'), true));
// register contract type
Expand All @@ -252,24 +263,26 @@ $contract = new Contract($wsClient->tx, $contractAddress, $v4);
// call get method
$execResult = $contract->state->get();
// parse exec Result
$result =ContractExecResult::getDecodeResult($execResult, $wsClient->tx->codec)
$result = ContractExecResult::getDecodeResult($execResult, $wsClient->tx->codec);
print_r($result);
```

#### Send Contract transaction

Sending contract transactions is very similar to executing extrinsic. You can simply exec the contract through
```$contract->call->{$method}($param1,$param2,$option=[])```
```$contract->call->{$method}($param1, $param2, $option = []);```

```php
<?php

use Rpc\KeyPair\KeyPair;
use Rpc\SubstrateRpc;
use Rpc\Contract;

$wsClient = new SubstrateRpc($endpoint);
// set signer
$hasher = new Hasher();
$wsClient->setSigner(KeyPair::initKeyPair("sr25519", $this->AliceSeed, $hasher),$hasher);
$wsClient->setSigner(KeyPair::initKeyPair("sr25519", $this->AliceSeed, $hasher), $hasher);

// register contract type
$v4 = ContractMetadataV4::to_obj(json_decode(file_get_contents(__DIR__ . '/ink/ink_v4.json'), true));
Expand All @@ -280,8 +293,8 @@ $contract = new Contract($wsClient->tx, $contractAddress, $v4);
$result = $contract->call->flip([]); // with default option

// If you need to additionally set the gas limit and storageDepositLimit, you can set it like this
$result = $contract->call->flip(["storageDepositLimit"=>$limit,["gasLimit"=>["refTime"=>$refTime,"proofSize"=>$proofSize]] ]);
print_r($result);// extrinsic_hash
$result = $contract->call->flip(["storageDepositLimit" => $limit, ["gasLimit" => ["refTime" => $refTime, "proofSize" => $proofSize]]]);
print_r($result); // extrinsic_hash
```

#### Generate contract address
Expand All @@ -290,15 +303,16 @@ Since the address algorithm of the contract is fixed, it is easy to calculate th

```php
<?php

use Rpc\Hasher\Hasher;
use Rpc\Contract\Address;
use Codec\Base;
use Codec\Types\ScaleInstance;

$hasher = new Hasher();
$codec = new ScaleInstance(Base::create());
$bytes = $codec->createTypeByTypeString("bytes");
Address::GenerateAddress($hasher, $deployer, $codeHash, $bytes->encode($inputData), $bytes->encode($salt)));

Address::GenerateAddress($hasher, $deployer, $codeHash, $bytes->encode($inputData), $bytes->encode($salt));
```

### Example
Expand Down Expand Up @@ -349,4 +363,4 @@ You need set [minimum-stability](https://getcomposer.org/doc/04-schema.md#minimu

## License

The package is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT)
The package is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT)