Contractless-PHP-RPC/src/Transaction/AgreementBuilder.php

110 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Contractless\Rpc\Transaction;
use Contractless\Rpc\Crypto\CryptoInterface;
use Contractless\Rpc\Exception\ProtocolException;
use Contractless\Rpc\Protocol\Address;
use Contractless\Rpc\Protocol\Binary;
use Contractless\Rpc\Wallet\Credentials;
final class AgreementBuilder
{
public function __construct(
private readonly CryptoInterface $crypto,
private readonly Credentials $credentials,
) {
}
public function swap(
int $expiration,
string $ticker1,
int $series1,
int $value1,
string $ticker2,
int $series2,
int $value2,
string $sender1,
string $sender2,
int $tip1,
int $tip2,
int $fee1,
int $fee2,
?int $timestamp = null,
): DualSignedTransaction {
$timestamp ??= time();
$ticker1 = Binary::fixedText($ticker1, 15, 'First swap asset');
$ticker2 = Binary::fixedText($ticker2, 15, 'Second swap asset');
$unsigned = [
'txtype' => 6, 'timestamp' => $timestamp, 'offer_expiration' => $expiration,
'ticker1' => $ticker1, 'nft_series1' => $series1, 'value1' => $value1,
'ticker2' => $ticker2, 'nft_series2' => $series2, 'value2' => $value2,
'sender1' => $sender1, 'sender2' => $sender2, 'tip1' => $tip1,
'tip2' => $tip2, 'txfee1' => $fee1, 'txfee2' => $fee2,
];
$json = $this->json($unsigned);
$hash = $this->crypto->skein256($json);
$bytes = Binary::u8(6) . Binary::u32($timestamp) . Binary::u32($expiration)
. $ticker1 . Binary::u32($series1) . Binary::u64($value1)
. $ticker2 . Binary::u32($series2) . Binary::u64($value2)
. Address::toBytes($sender1) . Address::toBytes($sender2)
. Binary::u64($tip1) . Binary::u64($tip2)
. Binary::u64($fee1) . Binary::u64($fee2);
return (new DualSignedTransaction($json, $bytes, $hash))
->signNext($this->crypto, $this->credentials);
}
public function loan(
string $loanCoin,
int $loanAmount,
string $lender,
string $collateral,
int $collateralAmount,
string $borrower,
string $paymentPeriod,
int $paymentNumber,
int $paymentAmount,
int $gracePeriod,
int $maxLateValue,
int $fee,
?int $timestamp = null,
): DualSignedTransaction {
$timestamp ??= time();
$loanCoin = Binary::fixedText($loanCoin, 15, 'Loan asset');
$collateral = Binary::fixedText($collateral, 21, 'Collateral asset');
if (strlen($paymentPeriod) !== 1) {
throw new ProtocolException('Payment period must be one byte: d, w, or m.');
}
$unsigned = [
'txtype' => 7, 'timestamp' => $timestamp, 'loan_coin' => $loanCoin,
'loan_amount' => $loanAmount, 'lender' => $lender,
'collateral' => $collateral, 'collateral_amount' => $collateralAmount,
'borrower' => $borrower, 'payment_period' => $paymentPeriod,
'payment_number' => $paymentNumber, 'payment_amount' => $paymentAmount,
'grace_period' => $gracePeriod, 'max_late_value' => $maxLateValue,
'txfee' => $fee,
];
$json = $this->json($unsigned);
$hash = $this->crypto->skein256($json);
$bytes = Binary::u8(7) . Binary::u32($timestamp) . $loanCoin
. Binary::u64($loanAmount) . Address::toBytes($lender)
. $collateral . Binary::u64($collateralAmount)
. Address::toBytes($borrower) . $paymentPeriod
. Binary::u8($paymentNumber) . Binary::u64($paymentAmount)
. Binary::u8($gracePeriod) . Binary::u64($maxLateValue)
. Binary::u64($fee);
return (new DualSignedTransaction($json, $bytes, $hash, storesHash: true))
->signNext($this->crypto, $this->credentials);
}
private function json(array $unsigned): string
{
return json_encode(
$unsigned,
JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION,
);
}
}