Skip to content

Commit

Permalink
chore: multipayment setup
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsANameToo committed Dec 18, 2024
1 parent 20b4118 commit a49381e
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 2 deletions.
3 changes: 3 additions & 0 deletions src/Enums/AbiFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace ArkEcosystem\Crypto\Enums;

use ArkEcosystem\Crypto\Transactions\Types\Multipayment;
use ArkEcosystem\Crypto\Transactions\Types\Unvote;
use ArkEcosystem\Crypto\Transactions\Types\UsernameRegistration;
use ArkEcosystem\Crypto\Transactions\Types\UsernameResignation;
Expand All @@ -19,6 +20,7 @@ enum AbiFunction: string
case VALIDATOR_RESIGNATION = 'resignValidator';
case USERNAME_REGISTRATION = 'registerUsername';
case USERNAME_RESIGNATION = 'resignUsername';
case MULTIPAYMENT = 'pay';

public function transactionClass(): string
{
Expand All @@ -29,6 +31,7 @@ public function transactionClass(): string
self::VALIDATOR_RESIGNATION => ValidatorResignation::class,
self::USERNAME_REGISTRATION => UsernameRegistration::class,
self::USERNAME_RESIGNATION => UsernameResignation::class,
self::MULTIPAYMENT => Multipayment::class,
};
}
}
41 changes: 41 additions & 0 deletions src/Transactions/Builder/MultipaymentBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace ArkEcosystem\Crypto\Transactions\Builder;

use ArkEcosystem\Crypto\Enums\ContractAddresses;
use ArkEcosystem\Crypto\Transactions\Types\AbstractTransaction;
use ArkEcosystem\Crypto\Transactions\Types\Multipayment;
use Exception;

class MultipaymentBuilder extends AbstractTransactionBuilder
{
public function __construct(?array $data = null)
{
parent::__construct($data);

$this->recipientAddress(ContractAddresses::MULTIPAYMENT->value);

$this->transaction->data['pay'] = [[], []];
$this->transaction->refreshPayloadData();
}

public function pay(string $address, string $amount): self
{
// TODO: validate amount and address?
$this->transaction->data['pay'][0][] = $address;
$this->transaction->data['pay'][1][] = $amount;

$this->transaction->refreshPayloadData();

$this->transaction->data['value']+= $amount;

return $this;
}

protected function getTransactionInstance(?array $data = []): AbstractTransaction
{
return new Multipayment($data);
}
}
5 changes: 3 additions & 2 deletions src/Transactions/Types/AbstractTransaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace ArkEcosystem\Crypto\Transactions\Types;

use ArkEcosystem\Crypto\Configuration\Network;
use ArkEcosystem\Crypto\Enums\ContractAbiType;
use ArkEcosystem\Crypto\Identities\Address;
use ArkEcosystem\Crypto\Transactions\Serializer;
use ArkEcosystem\Crypto\Utils\AbiDecoder;
Expand Down Expand Up @@ -170,7 +171,7 @@ public function hash(bool $skipSignature): BufferInterface
return TransactionHasher::toHash($hashData, $skipSignature);
}

protected function decodePayload(array $data): ?array
protected function decodePayload(array $data, ContractAbiType $type = ContractAbiType::CONSENSUS): ?array
{
if (! isset($data['data'])) {
return null;
Expand All @@ -182,7 +183,7 @@ protected function decodePayload(array $data): ?array
return null;
}

return (new AbiDecoder())->decodeFunctionData($payload);
return (new AbiDecoder($type))->decodeFunctionData($payload);
}

private function getSignature(): CompactSignatureInterface
Expand Down
32 changes: 32 additions & 0 deletions src/Transactions/Types/Multipayment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace ArkEcosystem\Crypto\Transactions\Types;

use ArkEcosystem\Crypto\Enums\AbiFunction;
use ArkEcosystem\Crypto\Enums\ContractAbiType;
use ArkEcosystem\Crypto\Utils\AbiEncoder;

class Multipayment extends AbstractTransaction
{
public function __construct(?array $data = [])
{
$payload = $this->decodePayload($data, ContractAbiType::MULTIPAYMENT);

if ($payload !== null) {
$data['pay'] = $payload['args'][0];
}

parent::__construct($data);
}

public function getPayload(): string
{
if (! array_key_exists('pay', $this->data)) {
return '';
}

return (new AbiEncoder(ContractAbiType::MULTIPAYMENT))->encodeFunctionCall(AbiFunction::MULTIPAYMENT->value, [$this->data['pay']]);
}
}
2 changes: 2 additions & 0 deletions src/Utils/AbiEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ private function getAbiItem(array $abi, string $name, array $args): array
}
}



throw new Exception("Function with matching arguments not found in ABI: $name");
}

Expand Down
80 changes: 80 additions & 0 deletions tests/Unit/Transactions/Builder/MultipaymentBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

declare(strict_types=1);

namespace ArkEcosystem\Tests\Crypto\Unit\Transactions\Builder;

use ArkEcosystem\Crypto\Exceptions\InvalidUsernameException;
use ArkEcosystem\Crypto\Transactions\Builder\MultipaymentBuilder;
use ArkEcosystem\Tests\Crypto\TestCase;

/**
* @covers \ArkEcosystem\Crypto\Transactions\Builder\MultipaymentBuilder
*/
class MultipaymentBuilderTest extends TestCase
{
// /** @test */
// public function it_should_sign_it_with_a_passphrase()
// {
// $fixture = $this->getTransactionFixture('evm_call', 'username-registration');

// $builder = UsernameRegistrationBuilder::new()
// ->gasPrice($fixture['data']['gasPrice'])
// ->nonce($fixture['data']['nonce'])
// ->network($fixture['data']['network'])
// ->gasLimit($fixture['data']['gasLimit'])
// ->username('php')
// ->sign($this->passphrase);

// $this->assertSame($fixture['serialized'], $builder->transaction->serialize()->getHex());

// $this->assertSame($fixture['data']['id'], $builder->transaction->data['id']);

// $this->assertTrue($builder->verify());
// }

/** @test */
public function it_should_handle_single_recipient()
{
$fixture = $this->getTransactionFixture('evm_call', 'multipayment-1');

$builder = MultipaymentBuilder::new()
->gasPrice($fixture['data']['gasPrice'])
->nonce($fixture['data']['nonce'])
->network($fixture['data']['network'])
->gasLimit($fixture['data']['gasLimit'])
->pay('0x8233F6Df6449D7655f4643D2E752DC8D2283fAd5', '1000000000000000000')
->sign($this->passphrase);

$this->assertSame($fixture['serialized'], $builder->transaction->serialize()->getHex());

$this->assertSame($fixture['data']['id'], $builder->transaction->data['id']);

$this->assertTrue($builder->verify());
}

// /** @test */
// public function it_should_handle_sending_to_self()
// {

// }

/** @test */
// public function it_should_handle_empty_payment()
// {
// $fixture = $this->getTransactionFixture('evm_call', 'multipayment-0');

// $builder = MultipaymentBuilder::new()
// ->gasPrice($fixture['data']['gasPrice'])
// ->nonce($fixture['data']['nonce'])
// ->network($fixture['data']['network'])
// ->gasLimit($fixture['data']['gasLimit'])
// ->sign($this->passphrase);

// $this->assertSame($fixture['serialized'], $builder->transaction->serialize()->getHex());

// $this->assertSame($fixture['data']['id'], $builder->transaction->data['id']);

// $this->assertTrue($builder->verify());
// }
}
16 changes: 16 additions & 0 deletions tests/fixtures/transactions/evm_call/multipayment-0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"data": {
"network": 30,
"nonce": "1",
"gasPrice": 5,
"gasLimit": 1000000,
"value": "0",
"recipientAddress": "0x83769BeEB7e5405ef0B7dc3C66C43E3a51A6d27f",
"data": "084ce7080000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"signature": "97e06c7c8c2d7d9409d0330113784126ff87e873f777864295c28403e2c8fc1d2bf455c94b8b72e70d6ac414aadbcc5c9a3c3cca82686587345346ec5554d09500",
"senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3",
"senderAddress": "0x6F0182a0cc707b055322CcF6d4CB6a5Aff1aEb22",
"id": "8cc750a6260fcf0a56e88a5c0e8e1b8f6edda3747b9517533e3081fa78735290"
},
"serialized": "1e01000000000000000500000040420f0000000000000000000000000000000000000000000000000000000000000000000183769beeb7e5405ef0b7dc3c66c43e3a51a6d27f84000000084ce708000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000097e06c7c8c2d7d9409d0330113784126ff87e873f777864295c28403e2c8fc1d2bf455c94b8b72e70d6ac414aadbcc5c9a3c3cca82686587345346ec5554d09500"
}
16 changes: 16 additions & 0 deletions tests/fixtures/transactions/evm_call/multipayment-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"data": {
"network": 30,
"nonce": "4",
"gasPrice": 5,
"gasLimit": 1000000,
"value": "1000000000000000000n",
"recipientAddress": "0x83769BeEB7e5405ef0B7dc3C66C43E3a51A6d27f",
"data": "084ce7080000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000008233f6df6449d7655f4643d2e752dc8d2283fad500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a7640000",
"signature": "4368a0aa9a9ae7931ef47709a0c727a21086eff3ae695948cfe57017c556cbb82d904197fbf6a1916bd6b8233f2ade4a42c5a296d9429c00148c609fafbb097100",
"senderPublicKey": "03f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabc",
"senderAddress": "0xfEAf2f24ba1205e9255d015DFaD8463c70D9A466",
"id": "abed9a416c3c4c5c503985b85ccf346560e4cc768c33233868c16cc3c7cefe8e"
},
"serialised": "1e04000000000000000500000040420f000000000000000000000000000000000000000000000000000de0b6b3a76400000183769beeb7e5405ef0b7dc3c66c43e3a51a6d27fc4000000084ce7080000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000008233f6df6449d7655f4643d2e752dc8d2283fad500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a76400004368a0aa9a9ae7931ef47709a0c727a21086eff3ae695948cfe57017c556cbb82d904197fbf6a1916bd6b8233f2ade4a42c5a296d9429c00148c609fafbb097100"
}
16 changes: 16 additions & 0 deletions tests/fixtures/transactions/evm_call/multipayment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"data": {
"network": 30,
"nonce": "0",
"gasPrice": 5,
"gasLimit": 1000000,
"value": "3000000000000000000",
"recipientAddress": "0x83769BeEB7e5405ef0B7dc3C66C43E3a51A6d27f",
"data": "084ce708000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000008233f6df6449d7655f4643d2e752dc8d2283fad50000000000000000000000006f0182a0cc707b055322ccf6d4cb6a5aff1aeb2200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000001bc16d674ec80000",
"signature": "b7073cf34ac3eb4e1429ac1ddc42603bda078e221cd3098fdc61edd162a2e03902068fc0c72d2b5dacc91c2ebd4c44f53287a5eb2ce8f888d0d0c9f3a72a600001",
"senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3",
"senderAddress": "0x6F0182a0cc707b055322CcF6d4CB6a5Aff1aEb22",
"id": "3dff56759f96969db1e9d04656646bdb78bf34452a83644cb994ca2bbc2d4a8d"
},
"serialised": "1e00000000000000000500000040420f0000000000000000000000000000000000000000000000000029a2241af62c00000183769beeb7e5405ef0b7dc3c66c43e3a51a6d27f04010000084ce708000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000008233f6df6449d7655f4643d2e752dc8d2283fad50000000000000000000000006f0182a0cc707b055322ccf6d4cb6a5aff1aeb2200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000001bc16d674ec80000b7073cf34ac3eb4e1429ac1ddc42603bda078e221cd3098fdc61edd162a2e03902068fc0c72d2b5dacc91c2ebd4c44f53287a5eb2ce8f888d0d0c9f3a72a600001"
}

0 comments on commit a49381e

Please sign in to comment.