Skip to content

Commit

Permalink
feat(transactions): add TransactionClient to support transaction methods
Browse files Browse the repository at this point in the history
  • Loading branch information
EdouardCourty committed Jan 8, 2025
1 parent 2e0e3a9 commit 690a0fc
Show file tree
Hide file tree
Showing 19 changed files with 285 additions and 123 deletions.
8 changes: 1 addition & 7 deletions src/Client/JsonRpcClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,6 @@ public function getResult(string $method, array $params = [], int $timeout = sel
return $response->result;
}

public function getJson(string $method, array $params = [], int $timeout = self::DEFAULT_TIMEOUT): array
{
$response = $this->getResult($method, $params, $timeout);

return json_decode(json_encode($response), true);
}

public function execute(JsonRpcRequest $request, int $timeout): RippledResponse
{
$response = $this->httpClient->request('POST', '/', [
Expand All @@ -71,6 +64,7 @@ public function execute(JsonRpcRequest $request, int $timeout): RippledResponse

if (isset($content['error'])) {
$error = $content['error'];

throw new JsonRpcException("RPC Error {$error['code']}: {$error['message']}", $response);
}

Expand Down
17 changes: 17 additions & 0 deletions src/Client/SubClient/AbstractClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace XRPL\Client\SubClient;

use XRPL\Client\JsonRpcClient;
use XRPL\Service\Serializer;

abstract readonly class AbstractClient
{
public function __construct(
protected Serializer $serializer,
protected JsonRpcClient $jsonRpcClient,
) {
}
}
29 changes: 4 additions & 25 deletions src/Client/SubClient/AccountClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace XRPL\Client\SubClient;

use XRPL\Client\JsonRpcClient;
use XRPL\Enum\AccountLedgerEntryEnum;
use XRPL\Model\Account\AccountChannels;
use XRPL\Model\Account\AccountCurrencies;
Expand All @@ -16,22 +15,9 @@
use XRPL\Model\Account\AccountTransactions;
use XRPL\Model\Account\GatewayBalances;
use XRPL\Model\Account\NoRippleCheck;
use XRPL\Model\Utility\Ping;
use XRPL\Model\Utility\Random;
use XRPL\Service\Denormalizer\TransactionDenormalizer;
use XRPL\Service\Serializer;

readonly class AccountClient
readonly class AccountClient extends AbstractClient
{
private TransactionDenormalizer $transactionDenormalizer;

public function __construct(
private Serializer $serializer,
private JsonRpcClient $jsonRpcClient,
) {
$this->transactionDenormalizer = new TransactionDenormalizer($this->serializer);
}

public function getAccountChannels(
string $address,
?string $destinationAccount = null,
Expand Down Expand Up @@ -186,8 +172,7 @@ public function getAccountTransactions(
bool $forward = false,
?int $limit = null,
mixed $marker = null,
): AccountTransactions
{
): AccountTransactions {
$providedParams = array_filter([
'ledger_index_min' => $ledgerIndexMin,
'ledger_index_max' => $ledgerIndexMax,
Expand Down Expand Up @@ -222,10 +207,7 @@ public function getAccountTransactions(

$response = $this->jsonRpcClient->getResult('account_tx', $params);

$accountTransaction = $this->serializer->deserialize(json_encode($response), AccountTransactions::class, 'json');
$accountTransaction->transactions = $this->transactionDenormalizer->deserializeListForAccount($response->transactions);

return $accountTransaction;
return $this->serializer->deserialize(json_encode($response), AccountTransactions::class, 'json');
}

public function getGatewayBalances(
Expand Down Expand Up @@ -271,9 +253,6 @@ public function getNoRippleCheck(

$response = $this->jsonRpcClient->getResult('noripple_check', $params);

$noRippleCheck = $this->serializer->deserialize(json_encode($response), NoRippleCheck::class, 'json');
$noRippleCheck->transactions = $this->transactionDenormalizer->deserializeList($response->transactions ?? []);

return $noRippleCheck;
return $this->serializer->deserialize(json_encode($response), NoRippleCheck::class, 'json');
}
}
29 changes: 7 additions & 22 deletions src/Client/SubClient/LedgerClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,15 @@

namespace XRPL\Client\SubClient;

use XRPL\Client\JsonRpcClient;
use XRPL\Enum\LedgerEntryEnum;
use XRPL\Model\Ledger\LedgerClosed;
use XRPL\Model\Ledger\LedgerCurrent;
use XRPL\Model\Ledger\LedgerData;
use XRPL\Model\Ledger\LedgerEntry;
use XRPL\Model\Ledger\LedgerResult;
use XRPL\Service\Denormalizer\TransactionDenormalizer;
use XRPL\Service\Serializer;

readonly class LedgerClient
readonly class LedgerClient extends AbstractClient
{
private TransactionDenormalizer $transactionDeserializer;

public function __construct(
private Serializer $serializer,
private JsonRpcClient $jsonRpcClient,
) {
$this->transactionDeserializer = new TransactionDenormalizer($this->serializer);
}

/**
* @note If `transactions` is set to true but `expand` is set to false, only the `transactionIds` field will be populated.
*/
Expand All @@ -45,20 +33,17 @@ public function getLedger(
'ledger_index' => $ledgerIndex,
];

$result = $this->jsonRpcClient->getResult('ledger', $payload);
$response = $this->jsonRpcClient->getResult('ledger', $payload);

/** @var LedgerResult $ledgerResponse */
$ledgerResponse = $this->serializer->deserialize(json_encode($result), LedgerResult::class, 'json');
/** @var LedgerResult $ledgerResult */
$ledgerResult = $this->serializer->deserialize(json_encode($response), LedgerResult::class, 'json');

if ($transactions === true && $expand === false) {
$ledgerResponse->ledger->transactionIds = $result->ledger->transactions;
}

if ($transactions === true && $expand === true) {
$ledgerResponse->ledger->transactions = $this->transactionDeserializer->deserializeList($result->ledger->transactions);
$ledgerResult->ledger->transactionIds = $response['ledger']['transactions'];
$ledgerResult->ledger->transactions = [];
}

return $ledgerResponse;
return $ledgerResult;
}

public function getLedgerClosed(): LedgerClosed
Expand Down
10 changes: 1 addition & 9 deletions src/Client/SubClient/PaymentChannelClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,11 @@

namespace XRPL\Client\SubClient;

use XRPL\Client\JsonRpcClient;
use XRPL\Model\PaymentChannel\ChannelAuthorize;
use XRPL\Model\PaymentChannel\ChannelVerify;
use XRPL\Service\Serializer;

readonly class PaymentChannelClient
readonly class PaymentChannelClient extends AbstractClient
{
public function __construct(
private Serializer $serializer,
private JsonRpcClient $jsonRpcClient,
) {
}

public function authorizeChannel(
string $channelId,
string $amount,
Expand Down
10 changes: 1 addition & 9 deletions src/Client/SubClient/ServerInfoClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,14 @@

namespace XRPL\Client\SubClient;

use XRPL\Client\JsonRpcClient;
use XRPL\Model\ServerInfo\Fee;
use XRPL\Model\ServerInfo\Manifest;
use XRPL\Model\ServerInfo\ServerDefinitions;
use XRPL\Model\ServerInfo\ServerState;
use XRPL\Model\ServerInfo\VersionResults;
use XRPL\Service\Serializer;

readonly class ServerInfoClient
readonly class ServerInfoClient extends AbstractClient
{
public function __construct(
private Serializer $serializer,
private JsonRpcClient $jsonRpcClient,
) {
}

public function getFee(): Fee
{
$response = $this->jsonRpcClient->getResult('fee');
Expand Down
129 changes: 129 additions & 0 deletions src/Client/SubClient/TransactionClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php

declare(strict_types=1);

namespace XRPL\Client\SubClient;

use XRPL\Model\AbstractTransaction;
use XRPL\Model\Transaction\MultiSignedSubmittedTransaction;
use XRPL\Model\Transaction\SubmittedTransaction;
use XRPL\Model\Transaction\TransactionEntry;

readonly class TransactionClient extends AbstractClient
{
public function submitOnly(
string $transactionBlob,
bool $failHard = false,
): SubmittedTransaction {
$params = [
'tx_blob' => $transactionBlob,
'fail_hard' => $failHard,
];

$response = $this->jsonRpcClient->getResult('submit', $params);

return $this->serializer->deserialize(json_encode($response), SubmittedTransaction::class, 'json');
}

public function signAndSubmit(
array $txJson,
?string $secret = null,
?string $seed = null,
?string $seedHex = null,
?string $passphrase = null,
?string $keyType = null,
bool $failHard = false,
bool $offline = false,
?bool $buildPath = null,
?int $feeMultMax = null,
?int $feeDivMax = null,
): SubmittedTransaction {
$params = [
'tx_json' => $txJson,
'secret' => $secret,
'seed' => $seed,
'seed_hex' => $seedHex,
'passphrase' => $passphrase,
'key_type' => $keyType,
'fail_hard' => $failHard,
'offline' => $offline,
'build_path' => $buildPath,
'fee_mult_max' => $feeMultMax,
'fee_div_max' => $feeDivMax,
];

$response = $this->jsonRpcClient->getResult('submit', $params);

return $this->serializer->deserialize(json_encode($response), SubmittedTransaction::class, 'json');
}

public function submitMultiSigned(
array $transaction,
bool $failHard = false,
): MultiSignedSubmittedTransaction {
$params = [
'tx_json' => $transaction,
'fail_hard' => $failHard,
];

$response = $this->jsonRpcClient->getResult('submit_multisigned', $params);

return $this->serializer->deserialize(json_encode($response), MultiSignedSubmittedTransaction::class, 'json');
}

public function getTransactionAtLedger(
string $transactionHash,
?string $ledgerHash = null,
string|int|null $ledgerIndex = null,
): TransactionEntry {
if ($ledgerHash === null && $ledgerIndex === null) {
throw new \InvalidArgumentException('Either ledgerHash or ledgerIndex must be provided.');
}

if ($ledgerHash !== null && $ledgerIndex !== null) {
throw new \InvalidArgumentException('Only one of ledgerHash or ledgerIndex can be provided.');
}

$params = [
'tx_hash' => $transactionHash,
'ledger_hash' => $ledgerHash,
'ledger_index' => $ledgerIndex,
];

$response = $this->jsonRpcClient->getResult('transaction_entry', $params);

$transactionEntry = $this->serializer->deserialize(json_encode($response), TransactionEntry::class, 'json');

if ($transactionEntry->transaction === null) {
throw new \RuntimeException('Transaction not found.');
}

return $transactionEntry;
}

public function getTransaction(
?string $transactionHash = null,
?string $compactTransactionId = null,
?int $minLedger = null,
?int $maxLedger = null,
): AbstractTransaction {
if (null === $transactionHash && null === $compactTransactionId) {
throw new \InvalidArgumentException('Either transactionHash or compactTransactionId must be provided.');
}

if (null !== $transactionHash && null !== $compactTransactionId) {
throw new \InvalidArgumentException('Only one of transactionHash or compactTransactionId can be provided.');
}

$params = [
'transaction' => $transactionHash,
'ctid' => $compactTransactionId,
'min_ledger' => $minLedger,
'max_ledger' => $maxLedger,
];

$response = $this->jsonRpcClient->getResult('tx', $params);

return $this->serializer->deserialize(json_encode($response), AbstractTransaction::class, 'json');
}
}
10 changes: 1 addition & 9 deletions src/Client/SubClient/UtilityClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,11 @@

namespace XRPL\Client\SubClient;

use XRPL\Client\JsonRpcClient;
use XRPL\Model\Utility\Ping;
use XRPL\Model\Utility\Random;
use XRPL\Service\Serializer;

readonly class UtilityClient
readonly class UtilityClient extends AbstractClient
{
public function __construct(
private Serializer $serializer,
private JsonRpcClient $jsonRpcClient,
) {
}

public function ping(): Ping
{
$response = $this->jsonRpcClient->getResult('ping');
Expand Down
7 changes: 5 additions & 2 deletions src/Client/XRPLClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use XRPL\Client\SubClient\LedgerClient;
use XRPL\Client\SubClient\PaymentChannelClient;
use XRPL\Client\SubClient\ServerInfoClient;
use XRPL\Client\SubClient\TransactionClient;
use XRPL\Client\SubClient\UtilityClient;
use XRPL\Service\Serializer;

Expand All @@ -21,7 +22,8 @@

public AccountClient $account;
public LedgerClient $ledger;
public PaymentChannelClient $paymentChannelClient;
public TransactionClient $transaction;
public PaymentChannelClient $paymentChannels;
public ServerInfoClient $serverInfo;
public UtilityClient $utility;

Expand All @@ -33,7 +35,8 @@ public function __construct(

$this->account = new AccountClient($this->serializer, $this->jsonRpcClient);
$this->ledger = new LedgerClient($this->serializer, $this->jsonRpcClient);
$this->paymentChannelClient = new PaymentChannelClient($this->serializer, $this->jsonRpcClient);
$this->transaction = new TransactionClient($this->serializer, $this->jsonRpcClient);
$this->paymentChannels = new PaymentChannelClient($this->serializer, $this->jsonRpcClient);
$this->serverInfo = new ServerInfoClient($this->serializer, $this->jsonRpcClient);
$this->utility = new UtilityClient($this->serializer, $this->jsonRpcClient);
}
Expand Down
Loading

0 comments on commit 690a0fc

Please sign in to comment.