Skip to content

Commit

Permalink
[PLA-1931] Add dispatch with require signature (#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardocustodio authored Dec 16, 2024
1 parent a044ac0 commit 2d1a4cc
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 14 deletions.
1 change: 1 addition & 0 deletions lang/en/deprecated.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
return [
'fuel_tank.field.reservesExistentialDeposit' => 'This field doesn\'t exist on-chain anymore',
'fuel_tank.field.providesDeposit' => 'This field has been replaced by the new CoveragePolicy',
'dispatch.args.paysRemainingFee' => 'This field has been replaced by the new DispatchSettings',
];
10 changes: 8 additions & 2 deletions lang/en/input_type.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
'dispatch.field.query' => "The GraphQL query. It's required to query the 'id' and 'encodedData' from the result.",
'dispatch.field.variables' => 'The GraphQL query variables.',
'permitted_extrinsics.description' => 'The list of permitted extrinsics in this ruleset.',
'require_signature.description' => 'The signature required in this ruleset.',
'require_signature.field.signature' => 'The signature.',
'require_signature.description' => 'The account that is required to sign the transaction.',
'require_signature.field.signature' => 'The wallet which we will require to sign the transaction.',
'dispatch_settings.description' => 'The dispatch settings.',
'dispatch_settings.field.paysRemainingFee' => 'The flag to pay the remaining fee.',
'dispatch_settings.field.signature' => 'The expirable signature to use for this dispatch.',
'expirable_signature.description' => 'The expirable signature.',
'expirable_signature.field.signature' => 'The signature.',
'expirable_signature.field.expiryBlock' => 'The expiry block.',
];
23 changes: 20 additions & 3 deletions src/GraphQL/Mutations/DispatchMutation.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Enjin\Platform\Models\Transaction;
use Enjin\Platform\Rules\MaxBigInt;
use Enjin\Platform\Rules\MinBigInt;
use Enjin\Platform\Rules\ValidHex;
use Enjin\Platform\Rules\ValidSubstrateAddress;
use Enjin\Platform\Facades\TransactionSerializer;
use Enjin\Platform\Support\Account;
Expand Down Expand Up @@ -80,6 +81,7 @@ public function args(): array
'paysRemainingFee' => [
'type' => GraphQL::type('Boolean'),
'description' => __('enjin-platform-fuel-tanks::mutation.dispatch.args.paysRemainingFee'),
'deprecationReason' => __('enjin-platform-fuel-tanks::deprecation.dispatch.args.paysRemainingFee'),
],
...$this->getSigningAccountField(),
...$this->getIdempotencyField(),
Expand Down Expand Up @@ -130,8 +132,8 @@ public static function getEncodedCall($args)

public static function getFuelTankCall($method, $args, ?string $rawCall = null): string
{
$paysRemainingFee = Arr::get($args, 'paysRemainingFee');

$paysRemainingFee = Arr::get($args, 'dispatch.settings.paysRemainingFee') ?? Arr::get($args, 'paysRemainingFee');
$signature = Arr::get($args, 'dispatch.settings.signature.signature');
$encodedCall = TransactionSerializer::encode($method, static::getEncodableParams(
tankId: $args['tankId'],
ruleSetId: $args['ruleSetId'],
Expand All @@ -145,7 +147,10 @@ public static function getFuelTankCall($method, $args, ?string $rawCall = null):
[
'useNoneOrigin' => false,
'paysRemainingFee' => $paysRemainingFee,
'signature' => null,
'signature' => $signature === null ? null : [
'signature' => HexConverter::hexToBytes($signature),
'expiryBlock' => Arr::get($args, 'dispatch.settings.signature.expiryBlock'),
],
],
],
);
Expand Down Expand Up @@ -190,6 +195,12 @@ protected function rulesWithValidation(array $args): array
'filled',
new ValidMutation(),
],
'dispatch.settings.signature.signature' => [
'bail', 'filled', new ValidHex(64),
],
'dispatch.settings.signature.expiryBlock' => [
'bail', 'integer', 'min:0',
],
];
}

Expand All @@ -214,6 +225,12 @@ protected function rulesWithoutValidation(array $args): array
'filled',
new ValidMutation(),
],
'dispatch.settings.signature.signature' => [
'bail', 'filled', new ValidHex(64),
],
'dispatch.settings.signature.expiryBlock' => [
'bail', 'integer', 'min:0',
],
];
}
}
2 changes: 2 additions & 0 deletions src/GraphQL/Traits/HasFuelTankValidationRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ protected function commonRulesExist(string $attribute, array $args = []): array
],
],
default => [
"{$attribute}.requireSignature" => ['nullable', new ValidSubstrateAddress()],
"{$attribute}.whitelistedCallers.*" => ['bail', 'distinct', 'max:255', 'filled', new ValidSubstrateAddress()],
"{$attribute}.whitelistedCallers" => ['nullable', 'array', 'min:1'],
"{$attribute}.requireToken.collectionId" => $isArray
Expand Down Expand Up @@ -80,6 +81,7 @@ protected function commonRules(string $attribute, array $args = []): array
],
],
default => [
"{$attribute}.requireSignature" => ['nullable', new ValidSubstrateAddress()],
"{$attribute}.whitelistedCallers.*" => ['bail', 'distinct', 'max:255', 'filled', new ValidSubstrateAddress()],
"{$attribute}.whitelistedCallers" => ['nullable', 'array', 'min:1'],
"{$attribute}.requireToken.collectionId" => $isArray
Expand Down
4 changes: 4 additions & 0 deletions src/GraphQL/Types/Input/DispatchInputType.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public function fields(): array
'type' => GraphQL::type('Object'),
'description' => __('enjin-platform-fuel-tanks::input_type.dispatch.field.variables'),
],
'settings' => [
'type' => GraphQL::type('DispatchSettingsInputType'),
'description' => __('enjin-platform-fuel-tanks::input_type.dispatch.field.settings'),
],
];
}
}
2 changes: 1 addition & 1 deletion src/GraphQL/Types/Input/DispatchRuleInputType.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function fields(): array
'description' => __('enjin-platform-fuel-tanks::input_type.permitted_extrinsics.description'),
],
'requireSignature' => [
'type' => GraphQL::type('RequireSignatureInputType'),
'type' => GraphQL::type('String'),
'description' => __('enjin-platform-fuel-tanks::input_type.require_signature.description'),
],
];
Expand Down
36 changes: 36 additions & 0 deletions src/GraphQL/Types/Input/DispatchSettingsInputType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Enjin\Platform\FuelTanks\GraphQL\Types\Input;

use Rebing\GraphQL\Support\Facades\GraphQL;

class DispatchSettingsInputType extends InputType
{
/**
* Get the input type's attributes.
*/
public function attributes(): array
{
return [
'name' => 'DispatchSettingsInputType',
'description' => __('enjin-platform-fuel-tanks::input_type.dispatch_settings.description'),
];
}

/**
* Get the input type's fields.
*/
public function fields(): array
{
return [
'paysRemainingFee' => [
'type' => GraphQL::type('Boolean!'),
'description' => __('enjin-platform-fuel-tanks::input_type.dispatch_settings.field.paysRemainingFee'),
],
'signature' => [
'type' => GraphQL::type('ExpirableSignatureInputType'),
'description' => __('enjin-platform-fuel-tanks::input_type.dispatch_settings.field.signature'),
],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@

namespace Enjin\Platform\FuelTanks\GraphQL\Types\Input;

use Enjin\Platform\Rules\ValidHex;
use Rebing\GraphQL\Support\Facades\GraphQL;

class RequireSignatureInputType extends InputType
class ExpirableSignatureInputType extends InputType
{
/**
* Get the input type's attributes.
*/
public function attributes(): array
{
return [
'name' => 'RequireSignatureInputType',
'description' => __('enjin-platform-fuel-tanks::input_type.require_signature.description'),
'name' => 'ExpirableSignatureInputType',
'description' => __('enjin-platform-fuel-tanks::input_type.expirable_signature.description'),
];
}

Expand All @@ -26,8 +25,11 @@ public function fields(): array
return [
'signature' => [
'type' => GraphQL::type('String!'),
'description' => __('enjin-platform-fuel-tanks::input_type.require_signature.field.signature'),
'rules' => ['sometimes', new ValidHex(16)],
'description' => __('enjin-platform-fuel-tanks::input_type.expirable_signature.field.signature'),
],
'expiryBlock' => [
'type' => GraphQL::type('Int!'),
'description' => __('enjin-platform-fuel-tanks::input_type.expirable_signature.field.expiryBlock'),
],
];
}
Expand Down
3 changes: 2 additions & 1 deletion src/Models/Substrate/RequireSignatureParams.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Enjin\Platform\FuelTanks\Models\Substrate;

use Enjin\BlockchainTools\HexConverter;
use Enjin\Platform\Support\SS58Address;

class RequireSignatureParams extends FuelTankRules
{
Expand All @@ -28,7 +29,7 @@ public static function fromEncodable(array $params): self
*/
public function toEncodable(): array
{
return ['RequireSignature' => $this->signature];
return ['RequireSignature' => SS58Address::getPublicKey($this->signature)];
}

public function toArray(): array
Expand Down
2 changes: 1 addition & 1 deletion src/Services/Blockchain/Implemetations/Substrate.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public function getDispatchRulesParams(array $args): DispatchRulesParams
($pallets = Arr::get($args, 'whitelistedPallets'))
? new WhitelistedPalletsParams($pallets)
: null,
($requireSignature = Arr::get($args, 'requireSignature.signature'))
($requireSignature = Arr::get($args, 'requireSignature'))
? new RequireSignatureParams($requireSignature)
: null,
);
Expand Down
1 change: 1 addition & 0 deletions tests/Feature/GraphQL/Mutations/CreateFuelTankTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public function test_it_can_skip_validation(): void
'userFuelBudget' => ['amount' => $value ?? fake()->numberBetween(1, 1000), 'resetPeriod' => fake()->numberBetween(1, 1000)],
'tankFuelBudget' => ['amount' => $value ?? fake()->numberBetween(1, 1000), 'resetPeriod' => fake()->numberBetween(1, 1000)],
'permittedExtrinsics' => ['CreateCollection', 'ApproveCollection', 'SimpleTransferToken', 'OperatorTransferToken'],
'requireSignature' => resolve(SubstrateProvider::class)->public_key(),
]],
'requireAccount' => true,
'skipValidation' => true,
Expand Down
37 changes: 37 additions & 0 deletions tests/Feature/GraphQL/Mutations/DispatchTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,43 @@ public function test_it_can_dispatch_multi_token(): void
$this->assertEquals($response['encodedData'], $encodedCall);
}

public function test_it_can_dispatch_with_deprecated_pays_remaining_fee(): void
{
$response = $this->graphql(
$this->method,
$params = [
...$this->generateParams(),
'paysRemainingFee' => true,
],
);

$encodedCall = DispatchMutation::getFuelTankCall($this->method, $params);
$this->assertEquals($response['encodedData'], $encodedCall);
}

public function test_it_can_dispatch_with_pays_remaining_fee(): void
{
$params = $this->generateParams();
$params['dispatch']['settings']['paysRemainingFee'] = true;
$response = $this->graphql($this->method, $params);

$encodedCall = DispatchMutation::getFuelTankCall($this->method, $params);
$this->assertEquals($response['encodedData'], $encodedCall);
}

public function test_it_can_dispatch_with_required_signature(): void
{
$params = $this->generateParams();
$params['dispatch']['settings']['paysRemainingFee'] = true;
$params['dispatch']['settings']['signature']['signature'] = resolve(SubstrateProvider::class)->signature();
$params['dispatch']['settings']['signature']['expiryBlock'] = fake()->numberBetween(1, 1000);

$response = $this->graphql($this->method, $params);

$encodedCall = DispatchMutation::getFuelTankCall($this->method, $params);
$this->assertEquals($response['encodedData'], $encodedCall);
}

public function test_it_can_skip_validation(): void
{
$response = $this->graphql(
Expand Down
1 change: 1 addition & 0 deletions tests/Feature/GraphQL/Traits/GenerateFuelTankData.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ protected function generateData($isArray = true, $value = null): array
'userFuelBudget' => ['amount' => $value ?? fake()->numberBetween(1, 1000), 'resetPeriod' => fake()->numberBetween(1, 1000)],
'tankFuelBudget' => ['amount' => $value ?? fake()->numberBetween(1, 1000), 'resetPeriod' => fake()->numberBetween(1, 1000)],
'permittedExtrinsics' => ['CreateCollection', 'ApproveCollection', 'SimpleTransferToken', 'OperatorTransferToken'],
'requireSignature' => $provider->public_key(),
];

return [
Expand Down

0 comments on commit 2d1a4cc

Please sign in to comment.