142 lines
7.4 KiB
PHP
142 lines
7.4 KiB
PHP
<?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";
|