From 7485bc4bba65fbb430fb61ff286338f45a49e565 Mon Sep 17 00:00:00 2001 From: Abner Tudtud <114082473+enjinabner@users.noreply.github.com> Date: Wed, 26 Jul 2023 23:31:39 +0800 Subject: [PATCH] Add price validation (#7) --- lang/en/validation.php | 1 + src/GraphQL/Mutations/FillListingMutation.php | 4 +- .../Mutations/FinalizeAuctionMutation.php | 4 +- src/GraphQL/Mutations/PlaceBidMutation.php | 6 ++- src/Rules/MinimumPrice.php | 48 +++++++++++++++++++ .../GraphQL/Mutations/FillListingTest.php | 16 +++++++ .../GraphQL/Mutations/FinalizeAuctionTest.php | 17 +++++++ .../GraphQL/Mutations/PlaceBidTest.php | 28 ++++++++++- 8 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 src/Rules/MinimumPrice.php diff --git a/lang/en/validation.php b/lang/en/validation.php index 1811cf4..128ed38 100644 --- a/lang/en/validation.php +++ b/lang/en/validation.php @@ -4,4 +4,5 @@ 'future_block'=> 'The :attribute must be at least :block.', 'enough_token_supply' => 'The token supply is not enough.', 'listing_not_cancelled' => 'The listing is already cancelled.', + 'minimum_price' => 'The minimum bidding price is :price.', ]; diff --git a/src/GraphQL/Mutations/FillListingMutation.php b/src/GraphQL/Mutations/FillListingMutation.php index da5e53f..42e3459 100644 --- a/src/GraphQL/Mutations/FillListingMutation.php +++ b/src/GraphQL/Mutations/FillListingMutation.php @@ -5,6 +5,7 @@ use Closure; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasIdempotencyField; use Enjin\Platform\Interfaces\PlatformBlockchainTransaction; +use Enjin\Platform\Marketplace\Rules\ListingNotCancelled; use Enjin\Platform\Marketplace\Services\TransactionService; use Enjin\Platform\Models\Transaction; use Enjin\Platform\Rules\MaxBigInt; @@ -12,7 +13,6 @@ use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; use Illuminate\Support\Facades\DB; -use Illuminate\Validation\Rule; use Rebing\GraphQL\Support\Facades\GraphQL; class FillListingMutation extends Mutation implements PlatformBlockchainTransaction @@ -83,7 +83,7 @@ protected function rules(array $args = []): array 'bail', 'filled', 'max:255', - Rule::exists('marketplace_listings', 'listing_id'), + new ListingNotCancelled(), ], 'amount' => [ 'bail', diff --git a/src/GraphQL/Mutations/FinalizeAuctionMutation.php b/src/GraphQL/Mutations/FinalizeAuctionMutation.php index a7471ec..03d930c 100644 --- a/src/GraphQL/Mutations/FinalizeAuctionMutation.php +++ b/src/GraphQL/Mutations/FinalizeAuctionMutation.php @@ -5,12 +5,12 @@ use Closure; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasIdempotencyField; use Enjin\Platform\Interfaces\PlatformBlockchainTransaction; +use Enjin\Platform\Marketplace\Rules\ListingNotCancelled; use Enjin\Platform\Marketplace\Services\TransactionService; use Enjin\Platform\Models\Transaction; use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; use Illuminate\Support\Facades\DB; -use Illuminate\Validation\Rule; use Rebing\GraphQL\Support\Facades\GraphQL; class FinalizeAuctionMutation extends Mutation implements PlatformBlockchainTransaction @@ -77,7 +77,7 @@ protected function rules(array $args = []): array 'bail', 'filled', 'max:255', - Rule::exists('marketplace_listings', 'listing_id'), + new ListingNotCancelled(), ], ]; } diff --git a/src/GraphQL/Mutations/PlaceBidMutation.php b/src/GraphQL/Mutations/PlaceBidMutation.php index 6d9b04d..1ab5a97 100644 --- a/src/GraphQL/Mutations/PlaceBidMutation.php +++ b/src/GraphQL/Mutations/PlaceBidMutation.php @@ -5,6 +5,8 @@ use Closure; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasIdempotencyField; use Enjin\Platform\Interfaces\PlatformBlockchainTransaction; +use Enjin\Platform\Marketplace\Rules\ListingNotCancelled; +use Enjin\Platform\Marketplace\Rules\MinimumPrice; use Enjin\Platform\Marketplace\Services\TransactionService; use Enjin\Platform\Models\Transaction; use Enjin\Platform\Rules\MaxBigInt; @@ -12,7 +14,6 @@ use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; use Illuminate\Support\Facades\DB; -use Illuminate\Validation\Rule; use Rebing\GraphQL\Support\Facades\GraphQL; class PlaceBidMutation extends Mutation implements PlatformBlockchainTransaction @@ -83,12 +84,13 @@ protected function rules(array $args = []): array 'bail', 'filled', 'max:255', - Rule::exists('marketplace_listings', 'listing_id'), + new ListingNotCancelled(), ], 'price' => [ 'bail', new MinBigInt(1), new MaxBigInt(), + new MinimumPrice(), ], ]; } diff --git a/src/Rules/MinimumPrice.php b/src/Rules/MinimumPrice.php new file mode 100644 index 0000000..7ebf77c --- /dev/null +++ b/src/Rules/MinimumPrice.php @@ -0,0 +1,48 @@ +data = $data; + + return $this; + } + + /** + * Run the validation rule. + * + * @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail + */ + public function validate(string $attribute, mixed $value, Closure $fail): void + { + if ($listingId = Arr::get($this->data, 'listingId')) { + $listing = MarketplaceListing::where('listing_id', $listingId)->first(); + if ($listing && $value < $listing->price) { + $fail('enjin-platform-marketplace::validation.minimum_price')->translate(['price' => $listing->price]); + } + } + } +} diff --git a/tests/Feature/GraphQL/Mutations/FillListingTest.php b/tests/Feature/GraphQL/Mutations/FillListingTest.php index 202121b..64d05ef 100644 --- a/tests/Feature/GraphQL/Mutations/FillListingTest.php +++ b/tests/Feature/GraphQL/Mutations/FillListingTest.php @@ -2,6 +2,8 @@ namespace Enjin\Platform\Marketplace\Tests\Feature\GraphQL\Mutations; +use Enjin\Platform\Marketplace\Enums\ListingState; +use Enjin\Platform\Marketplace\Models\MarketplaceState; use Enjin\Platform\Marketplace\Tests\Feature\GraphQL\TestCaseGraphQL; use Enjin\Platform\Support\Hex; use Illuminate\Support\Str; @@ -69,6 +71,20 @@ public function test_it_will_fail_with_invalid_parameter_listing_id(): void ['listingId' => ['The selected listing id is invalid.']], $response['error'] ); + + MarketplaceState::create([ + 'state' => ListingState::CANCELLED->name, + 'marketplace_listing_id' => $listing->id, + ]); + $response = $this->graphql( + $this->method, + $data, + true + ); + $this->assertArraySubset( + ['listingId' => ['The listing is already cancelled.']], + $response['error'] + ); } public function test_it_will_fail_with_invalid_parameter_amount(): void diff --git a/tests/Feature/GraphQL/Mutations/FinalizeAuctionTest.php b/tests/Feature/GraphQL/Mutations/FinalizeAuctionTest.php index 5be6cf5..7fbc1c1 100644 --- a/tests/Feature/GraphQL/Mutations/FinalizeAuctionTest.php +++ b/tests/Feature/GraphQL/Mutations/FinalizeAuctionTest.php @@ -2,6 +2,8 @@ namespace Enjin\Platform\Marketplace\Tests\Feature\GraphQL\Mutations; +use Enjin\Platform\Marketplace\Enums\ListingState; +use Enjin\Platform\Marketplace\Models\MarketplaceState; use Enjin\Platform\Marketplace\Tests\Feature\GraphQL\TestCaseGraphQL; use Illuminate\Support\Str; @@ -66,5 +68,20 @@ public function test_it_will_fail_with_invalid_parameter_listing_id(): void ['listingId' => ['The selected listing id is invalid.']], $response['error'] ); + + $listing = $this->createListing(); + MarketplaceState::create([ + 'state' => ListingState::CANCELLED->name, + 'marketplace_listing_id' => $listing->id, + ]); + $response = $this->graphql( + $this->method, + ['listingId' => $listing->listing_id], + true + ); + $this->assertArraySubset( + ['listingId' => ['The listing is already cancelled.']], + $response['error'] + ); } } diff --git a/tests/Feature/GraphQL/Mutations/PlaceBidTest.php b/tests/Feature/GraphQL/Mutations/PlaceBidTest.php index 1526219..0800785 100644 --- a/tests/Feature/GraphQL/Mutations/PlaceBidTest.php +++ b/tests/Feature/GraphQL/Mutations/PlaceBidTest.php @@ -2,6 +2,8 @@ namespace Enjin\Platform\Marketplace\Tests\Feature\GraphQL\Mutations; +use Enjin\Platform\Marketplace\Enums\ListingState; +use Enjin\Platform\Marketplace\Models\MarketplaceState; use Enjin\Platform\Marketplace\Tests\Feature\GraphQL\TestCaseGraphQL; use Enjin\Platform\Support\Hex; use Illuminate\Support\Str; @@ -74,7 +76,7 @@ public function test_it_will_fail_with_invalid_parameter_listing_id(): void public function test_it_will_fail_with_invalid_parameter_price(): void { $listing = $this->createListing(); - $data = ['listingId' => $listing->listing_id, 'price' => fake()->numberBetween(1, 1000)]; + $data = ['listingId' => $listing->listing_id, 'price' => $price = fake()->numberBetween(1, 1000)]; $response = $this->graphql( $this->method, array_merge($data, ['price' => null]), @@ -104,5 +106,29 @@ public function test_it_will_fail_with_invalid_parameter_price(): void 'Cannot represent following value as uint256: 1.1579208923732E+77', $response['error'] ); + + $response = $this->graphql( + $this->method, + array_merge($data, ['price' => $listing->price - 1]), + true + ); + $this->assertArraySubset( + ['price' => ["The minimum bidding price is {$listing->price}."]], + $response['error'] + ); + + MarketplaceState::create([ + 'state' => ListingState::CANCELLED->name, + 'marketplace_listing_id' => $listing->id, + ]); + $response = $this->graphql( + $this->method, + $data, + true + ); + $this->assertArraySubset( + ['listingId' => ['The listing is already cancelled.']], + $response['error'] + ); } }