Skip to content

Commit ca0027b

Browse files
committed
fix: casper v2 compatibility + php 8.4 deprecations
1 parent 5e986d8 commit ca0027b

16 files changed

+208
-88
lines changed

src/Rpc/HttpHandler.php

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ public function processCall(RpcRequest $params): RpcResponse
1818
{
1919
$curl = curl_init($this->url);
2020

21+
if ($curl === false) {
22+
throw new \RuntimeException('Failed to initialize cURL');
23+
}
24+
2125
$headers = [
2226
'Accept: application/json',
2327
'Content-type: application/json'
@@ -34,8 +38,29 @@ public function processCall(RpcRequest $params): RpcResponse
3438
curl_setopt($curl, CURLOPT_POSTFIELDS, $params->toJson());
3539

3640
$rawResponse = curl_exec($curl);
37-
curl_close($curl);
3841

39-
return RpcResponse::fromArray(json_decode($rawResponse, true));
42+
// Handle cURL errors
43+
if ($rawResponse === false) {
44+
$error = curl_error($curl);
45+
throw new \RuntimeException('cURL request failed: ' . $error);
46+
}
47+
48+
// Note: curl_close() is deprecated in PHP 8.0+ and no longer necessary
49+
// CurlHandle objects are automatically garbage collected
50+
51+
// Ensure we have a valid string response
52+
if (!is_string($rawResponse)) {
53+
throw new \RuntimeException('Unexpected response type from cURL');
54+
}
55+
56+
// Decode JSON response
57+
$decoded = json_decode($rawResponse, true);
58+
59+
// Handle JSON decode errors or empty responses
60+
if (!is_array($decoded)) {
61+
throw new \RuntimeException('Invalid JSON response from RPC server: ' . $rawResponse);
62+
}
63+
64+
return RpcResponse::fromArray($decoded);
4065
}
4166
}

src/Rpc/ResultTypes/InfoGetStatusResult.php

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class InfoGetStatusResult extends AbstractResult
1717

1818
private string $chainSpecName;
1919

20-
private MinimalBlockInfo $lastAddedBlockInfo;
20+
private ?MinimalBlockInfo $lastAddedBlockInfo;
2121

2222
private ?NextUpgrade $nextUpgrade;
2323

@@ -46,23 +46,28 @@ class InfoGetStatusResult extends AbstractResult
4646

4747
public static function fromJSON(array $json): self
4848
{
49+
// Handle optional last_added_block_info (may be null in some node states)
50+
$lastAddedBlockInfo = isset($json['last_added_block_info'])
51+
? MinimalBlockInfoSerializer::fromJSON($json['last_added_block_info'])
52+
: null;
53+
4954
return new self(
5055
$json,
51-
$json['protocol_version'],
52-
$json['build_version'],
53-
$json['chainspec_name'],
54-
MinimalBlockInfoSerializer::fromJSON($json['last_added_block_info']),
55-
$json['next_upgrade'] ? NextUpgradeSerializer::fromJSON($json['next_upgrade']) : null,
56-
$json['our_public_signing_key'],
57-
PeerSerializer::fromJsonArray($json['peers']),
58-
$json['round_length'],
59-
$json['starting_state_root_hash'],
60-
$json['uptime'],
61-
$json['reactor_state'],
62-
new \DateTime($json['last_progress']),
63-
$json['latest_switch_block_hash'],
64-
$json['available_block_ranges'],
65-
$json['block_sync']
56+
$json['protocol_version'] ?? $json['api_version'] ?? '',
57+
$json['build_version'] ?? '',
58+
$json['chainspec_name'] ?? '',
59+
$lastAddedBlockInfo,
60+
isset($json['next_upgrade']) ? NextUpgradeSerializer::fromJSON($json['next_upgrade']) : null,
61+
$json['our_public_signing_key'] ?? '',
62+
isset($json['peers']) ? PeerSerializer::fromJsonArray($json['peers']) : [],
63+
$json['round_length'] ?? '',
64+
$json['starting_state_root_hash'] ?? '',
65+
$json['uptime'] ?? '',
66+
$json['reactor_state'] ?? '',
67+
isset($json['last_progress']) ? new \DateTime($json['last_progress']) : new \DateTime(),
68+
$json['latest_switch_block_hash'] ?? '',
69+
$json['available_block_ranges'] ?? $json['available_block_range'] ?? null,
70+
$json['block_sync'] ?? []
6671
);
6772
}
6873

@@ -71,7 +76,7 @@ public function __construct(
7176
string $protocolVersion,
7277
string $buildVersion,
7378
string $chainSpecName,
74-
MinimalBlockInfo $lastAddedBlockInfo,
79+
?MinimalBlockInfo $lastAddedBlockInfo,
7580
?NextUpgrade $nextUpgrade,
7681
string $outPublicSigningKey,
7782
array $peers,
@@ -118,7 +123,7 @@ public function getChainSpecName(): string
118123
return $this->chainSpecName;
119124
}
120125

121-
public function getLastAddedBlockInfo(): MinimalBlockInfo
126+
public function getLastAddedBlockInfo(): ?MinimalBlockInfo
122127
{
123128
return $this->lastAddedBlockInfo;
124129
}
@@ -133,6 +138,11 @@ public function getOutPublicSigningKey(): string
133138
return $this->outPublicSigningKey;
134139
}
135140

141+
public function getOurPublicSigningKey(): string
142+
{
143+
return $this->outPublicSigningKey;
144+
}
145+
136146
public function getPeers(): array
137147
{
138148
return $this->peers;

src/Rpc/RpcClient.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ public function getLatestBlockTransfers(): ChainGetBlockTransfersResult
628628
/**
629629
* @throws RpcError
630630
*/
631-
public function getBlockTransfersByHash(string $blockHash = null): ChainGetBlockTransfersResult
631+
public function getBlockTransfersByHash(?string $blockHash = null): ChainGetBlockTransfersResult
632632
{
633633
$result = $this->processRequest(
634634
self::RPC_METHOD_CHAIN_GET_BLOCK_TRANSFERS,
@@ -645,7 +645,7 @@ public function getBlockTransfersByHash(string $blockHash = null): ChainGetBlock
645645
/**
646646
* @throws RpcError
647647
*/
648-
public function getBlockTransfersByHeight(int $blockHeight = null): ChainGetBlockTransfersResult
648+
public function getBlockTransfersByHeight(?int $blockHeight = null): ChainGetBlockTransfersResult
649649
{
650650
$result = $this->processRequest(
651651
self::RPC_METHOD_CHAIN_GET_BLOCK_TRANSFERS,

src/Rpc/RpcError.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
class RpcError extends \Exception
88
{
9-
public function __construct($message = "", $code = 0, Throwable $previous = null)
9+
public function __construct($message = "", $code = 0, ?Throwable $previous = null)
1010
{
1111
parent::__construct($message, $code, $previous);
1212
}

src/Rpc/RpcResponse.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,19 @@ public static function fromArray(array $data): self
2222
$response->result = $data['result'] ?? null;
2323

2424
if ($response->result === null || isset($data['error'])) {
25-
$response->error = new RpcError(
26-
$data['error']['message'] ?? $data['message'] ?? 'Empty response',
27-
$data['error']['code'] ?? 0
28-
);
25+
$errorMessage = $data['error']['message'] ?? $data['message'] ?? 'Empty response';
26+
$errorCode = $data['error']['code'] ?? 0;
27+
28+
// Include detailed data if available (patched by AI)
29+
if (isset($data['error']['data'])) {
30+
$errorData = $data['error']['data'];
31+
if (is_array($errorData) || is_object($errorData)) {
32+
$errorData = json_encode($errorData);
33+
}
34+
$errorMessage .= '. Data: ' . $errorData;
35+
}
36+
37+
$response->error = new RpcError($errorMessage, $errorCode);
2938
}
3039

3140
return $response;

src/Rpc/SpeculativeClient.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public function __construct(Handler $handler)
1919
/**
2020
* @throws RpcError
2121
*/
22-
public function speculativeExecByBlockHash(Deploy $signedDeploy, string $blockHash = null): SpeculativeExecResult
22+
public function speculativeExecByBlockHash(Deploy $signedDeploy, ?string $blockHash = null): SpeculativeExecResult
2323
{
2424
$params = array(
2525
'deploy' => DeploySerializer::toJson($signedDeploy)
@@ -39,7 +39,7 @@ public function speculativeExecByBlockHash(Deploy $signedDeploy, string $blockHa
3939
/**
4040
* @throws RpcError
4141
*/
42-
public function speculativeExecByBlockHeight(Deploy $signedDeploy, int $blockHeight = null): SpeculativeExecResult
42+
public function speculativeExecByBlockHeight(Deploy $signedDeploy, ?int $blockHeight = null): SpeculativeExecResult
4343
{
4444
$params = array(
4545
'deploy' => DeploySerializer::toJson($signedDeploy)

src/Types/CLValue/CLPublicKey.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,15 @@ final class CLPublicKey extends CLValue
2424
/**
2525
* @throws \Exception
2626
*/
27-
public function __construct(array $rawPublicKey, CLPublicKeyTag $tag)
27+
public function __construct(array $rawPublicKey, $tag)
2828
{
29+
if (is_int($tag)) {
30+
$tag = new CLPublicKeyTag($tag);
31+
}
32+
if (!$tag instanceof CLPublicKeyTag) {
33+
throw new \InvalidArgumentException('Invalid public key tag type');
34+
}
35+
2936
$this->assertRawPublicKeyLengthIsValid($rawPublicKey, $tag);
3037
$this->data = $rawPublicKey;
3138
$this->tag = $tag;

src/Types/DeployExecutable.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public static function newStandardPayment($amount): DeployExecutableModuleBytes
1515
return self::newModuleBytes('', [new NamedArg('amount', new CLU512($amount))]);
1616
}
1717

18-
public static function newTransfer($id, $amount, $target, CLURef $sourcePurse = null): DeployExecutableTransfer
18+
public static function newTransfer($id, $amount, $target, ?CLURef $sourcePurse = null): DeployExecutableTransfer
1919
{
2020
if (!in_array(get_class($target), [CLURef::class, CLPublicKey::class])) {
2121
throw new \Exception('Please specify target');
@@ -63,7 +63,7 @@ public static function newStoredContractPackageByHash(
6363
string $entrypoint,
6464
array $args,
6565
string $hexContractPackageHash,
66-
int $version = null
66+
?int $version = null
6767
): DeployExecutableStoredVersionedContractByHash {
6868
return (new DeployExecutableStoredVersionedContractByHash($hexContractPackageHash, $entrypoint, $version))
6969
->setArgs($args);
@@ -73,7 +73,7 @@ public static function newStoredContractPackageByName(
7373
string $entrypoint,
7474
array $args,
7575
string $contractPackageAlias,
76-
int $version = null
76+
?int $version = null
7777
): DeployExecutableStoredVersionedContractByName {
7878
return (new DeployExecutableStoredVersionedContractByName($contractPackageAlias, $entrypoint, $version))
7979
->setArgs($args);

src/Types/DeployParams.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public function __construct(
4747
int $gasPrice = self::DEFAULT_GAS_PRICE,
4848
int $ttl = self::DEFAULT_TTL,
4949
array $dependencies = [],
50-
int $timestamp = null
50+
?int $timestamp = null
5151
)
5252
{
5353
$this->accountPublicKey = $accountPublicKey;

src/Types/Serializer/DelegatorSerializer.php

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@
88

99
class DelegatorSerializer extends JsonSerializer
1010
{
11+
private static function normalizePublicKey($value): ?string
12+
{
13+
if (is_string($value)) {
14+
return $value;
15+
}
16+
if (is_array($value)) {
17+
return $value['PublicKey'] ?? $value['public_key'] ?? null;
18+
}
19+
20+
return null;
21+
}
22+
1123
/**
1224
* @param Delegator $delegator
1325
*/
@@ -23,11 +35,43 @@ public static function toJson($delegator): array
2335

2436
public static function fromJson(array $json): Delegator
2537
{
38+
$publicKeyHex = self::normalizePublicKey($json['public_key'] ?? $json['delegator_public_key'] ?? $json['delegator'] ?? null);
39+
$delegateeHex = self::normalizePublicKey($json['delegatee'] ?? $json['validator_public_key'] ?? $json['validator'] ?? null);
40+
$stakedAmount = $json['staked_amount'] ?? $json['bonding_amount'] ?? '0';
41+
$bondingPurse = $json['bonding_purse'] ?? $json['bonding_purse_uref'] ?? null;
42+
43+
if (is_array($bondingPurse)) {
44+
$bondingPurse = $bondingPurse['URef'] ?? $bondingPurse['uref'] ?? null;
45+
}
46+
47+
if (null === $publicKeyHex || null === $delegateeHex || '' === $bondingPurse) {
48+
throw new \RuntimeException('Invalid delegator data: missing required fields');
49+
}
50+
2651
return new Delegator(
27-
CLPublicKey::fromHex($json['public_key']),
28-
gmp_init($json['staked_amount']),
29-
CLURef::fromString($json['bonding_purse']),
30-
CLPublicKey::fromHex($json['delegatee'])
52+
CLPublicKey::fromHex($publicKeyHex),
53+
gmp_init($stakedAmount),
54+
CLURef::fromString($bondingPurse),
55+
CLPublicKey::fromHex($delegateeHex)
3156
);
3257
}
58+
59+
public static function fromJsonArray(array $array): array
60+
{
61+
$result = [];
62+
63+
foreach ($array as $item) {
64+
if (!is_array($item)) {
65+
continue;
66+
}
67+
try {
68+
$result[] = self::fromJson($item);
69+
} catch (\RuntimeException $e) {
70+
// Skip invalid delegator entries
71+
continue;
72+
}
73+
}
74+
75+
return $result;
76+
}
3377
}

0 commit comments

Comments
 (0)