Contractless-PHP-RPC/tests/run.php

142 lines
7.4 KiB
PHP
Raw Normal View History

2026-07-25 21:23:28 +00:00
<?php
declare(strict_types=1);
spl_autoload_register(static function (string $class): void {
$prefix = 'Contractless\\Rpc\\';
if (!str_starts_with($class, $prefix)) {
return;
}
$path = dirname(__DIR__) . '/src/'
. str_replace('\\', '/', substr($class, strlen($prefix)))
. '.php';
if (is_file($path)) {
require $path;
}
});
use Contractless\Rpc\Client;
use Contractless\Rpc\Crypto\CallbackCrypto;
use Contractless\Rpc\Protocol\Address;
use Contractless\Rpc\Protocol\Command;
use Contractless\Rpc\Transport\TransportInterface;
use Contractless\Rpc\Transaction\TransferBuilder;
use Contractless\Rpc\Transaction\AssetBuilder;
use Contractless\Rpc\Transaction\GovernanceBuilder;
use Contractless\Rpc\Transaction\StorageBuilder;
use Contractless\Rpc\Transaction\MiscellaneousBuilder;
use Contractless\Rpc\Transaction\AgreementBuilder;
use Contractless\Rpc\Transaction\DualSignedTransaction;
use Contractless\Rpc\Wallet\Credentials;
function expect(bool $condition, string $message): void
{
if (!$condition) {
throw new RuntimeException($message);
}
}
expect(
Address::toBytes(str_repeat('ab', 20) . '.cltc')
=== str_repeat("\xab", 20) . ".\x02",
'Short-address encoding differs from the Rust wallet format.',
);
$transport = new class implements TransportInterface {
public string $handshake = '';
public string $request = '';
public function exchange(
string $handshake,
string $request,
string $uid,
Closure $validateHandshake,
): string {
$this->handshake = $handshake;
$this->request = $request;
return 'ok';
}
};
$crypto = new CallbackCrypto(
fn (string $message): string => str_repeat("\x11", 32),
fn (string $message, string $privateKey, string $publicKey): string => str_repeat("\x22", 666),
fn (string $message, string $signature, string $publicKey): bool => true,
);
$credentials = new Credentials(str_repeat("\x33", 897), str_repeat("\x44", 1281));
$client = new Client($transport, $crypto, $credentials);
expect($client->blockByHeight(42) === 'ok', 'Client did not return the RPC payload.');
expect(strlen($transport->handshake) === 1587, 'Handshake request has the wrong size.');
expect(substr($transport->handshake, 0, 2) === "\xac\xed", 'Handshake marker is wrong.');
expect(ord($transport->request[0]) === Command::BLOCK_BY_HEIGHT, 'RPC command is wrong.');
expect(unpack('Vheight', substr($transport->request, 4, 4))['height'] === 42, 'Height encoding is wrong.');
$client->storageLookupCost(str_repeat('01', 32), 'all', str_repeat('ab', 20) . '.cltc');
expect(ord($transport->request[0]) === Command::STORAGE_LOOKUP_COST, 'Storage command is wrong.');
expect(strlen($transport->request) === 4 + 32 + 50 + 22, 'Storage cost payload has the wrong size.');
$client->registerOwnedWallet(str_repeat('ab', 20) . '.cltc');
expect(ord($transport->request[0]) === Command::REGISTER_WALLET, 'Wallet registration command is wrong.');
expect(strlen($transport->request) === 4 + 22 + 897 + 666, 'Wallet registration payload has the wrong size.');
$transfer = (new TransferBuilder($crypto, $credentials))->create(
str_repeat('ab', 20) . '.cltc',
str_repeat('cd', 20) . '.cltc',
'CLTC',
2_500_000,
2_500,
timestamp: 1_700_000_000,
);
expect(strlen($transfer->bytes) === 750, 'Transfer transaction has the wrong byte size.');
expect(
$transfer->unsignedJson
=== '{"txtype":2,"time":1700000000,"value":2500000,"coin":"CLTC ","nft_series":0,"sender":"'
. str_repeat('ab', 20)
. '.cltc","receiver":"'
. str_repeat('cd', 20)
. '.cltc","txfee":2500}',
'Transfer signing JSON does not match Rust struct serialization.',
);
$address = str_repeat('ab', 20) . '.cltc';
$assets = new AssetBuilder($crypto, $credentials);
expect(strlen($assets->createToken($address, 'TEST', 1000, true, 100, 1)->bytes) === 725, 'Token size is wrong.');
expect(strlen($assets->issueToken($address, 'TEST', 1000, 100, 1)->bytes) === 724, 'Token issue size is wrong.');
expect(strlen($assets->createNft($address, false, false, 'ART', 'cid', 1, 'description', 100, 1)->bytes) === 922, 'NFT size is wrong.');
expect(strlen($assets->burn($address, 'TEST', 0, 1, 100, 1)->bytes) === 728, 'Burn size is wrong.');
expect(strlen($assets->vanity($address, str_repeat('a', 20) . '.cltc', 100, 1)->bytes) === 723, 'Vanity size is wrong.');
$governance = new GovernanceBuilder($crypto, $credentials);
expect(strlen($governance->proposal(str_repeat('01', 32), $address, 100, 1)->bytes) === 733, 'Proposal size is wrong.');
expect(strlen($governance->proposalVote(str_repeat('01', 32), $address, true, 100, 1)->bytes) === 734, 'Proposal vote size is wrong.');
expect(strlen($governance->activationVote(str_repeat('01', 32), str_repeat('02', 32), 'CLP-0001.md', $address, true, 100, 1)->bytes) === 866, 'Activation vote size is wrong.');
$storage = new StorageBuilder($crypto, $credentials);
expect(strlen($storage->createKey($address, 100, 1)->bytes) === 701, 'Storage key size is wrong.');
expect(strlen($storage->boolean(str_repeat('01', 32), 'active', true, $address, 100, 1)->bytes) === 784, 'Storage bool size is wrong.');
expect(strlen($storage->u32(str_repeat('01', 32), 'count', 42, $address, 100, 1)->bytes) === 787, 'Storage u32 size is wrong.');
expect(strlen($storage->i64(str_repeat('01', 32), 'balance', -42, $address, 100, 1)->bytes) === 791, 'Storage i64 size is wrong.');
expect(strlen($storage->u128(str_repeat('01', 32), 'large', '340282366920938463463374607431768211455', $address, 100, 1)->bytes) === 799, 'Storage u128 size is wrong.');
expect(strlen($storage->i128(str_repeat('01', 32), 'negative', '-170141183460469231731687303715884105728', $address, 100, 1)->bytes) === 799, 'Storage i128 size is wrong.');
expect(bin2hex(substr($storage->u128(str_repeat('01', 32), 'large', '340282366920938463463374607431768211455', $address, 100, 1)->bytes, 87, 16)) === str_repeat('ff', 16), 'u128 maximum encoding is wrong.');
expect(strlen($storage->string(str_repeat('01', 32), 'bio', 'hello', $address, str_repeat('0', 64), 100, 1)->bytes) === 995, 'Storage string size is wrong.');
expect(strlen($storage->delete(str_repeat('01', 32), 'bio', $address, 100, 1)->bytes) === 783, 'Storage delete size is wrong.');
$misc = new MiscellaneousBuilder($crypto, $credentials);
expect(strlen($misc->marketing(1, 'banner', 'keyword', 'website', 1, 1, 100, 100, $address, 100, 1)->bytes) === 861, 'Marketing size is wrong.');
expect(strlen($misc->collateralClaim(str_repeat('01', 32), $address, 100, 1)->bytes) === 733, 'Collateral claim size is wrong.');
expect(strlen($misc->loanPayment(1000, str_repeat('01', 32), $address, 100, 100, 1)->bytes) === 781, 'Loan payment size is wrong.');
$agreements = new AgreementBuilder($crypto, $credentials);
$swap = $agreements->swap(1000, 'CLTC', 0, 100, 'TEST', 0, 200, $address, str_repeat('cd', 20) . '.cltc', 1, 2, 3, 4, 1);
$swap = $swap->signNext($crypto, $credentials);
expect(strlen($swap->toSignedTransaction()->bytes) === 1471, 'Swap size is wrong.');
expect(DualSignedTransaction::import($swap->export())->isComplete(), 'Swap export/import lost signatures.');
$loan = $agreements->loan('CLTC', 1000, $address, 'TEST', 2000, str_repeat('cd', 20) . '.cltc', 'm', 12, 100, 2, 300, 100, 1);
$loan = $loan->signNext($crypto, $credentials);
expect(strlen($loan->toSignedTransaction()->bytes) === 1492, 'Loan size is wrong.');
echo "All protocol tests passed.\n";