diff --git a/src/GraphQL/Mutations/CancelListingMutation.php b/src/GraphQL/Mutations/CancelListingMutation.php index bb73c43..f8eb8a5 100644 --- a/src/GraphQL/Mutations/CancelListingMutation.php +++ b/src/GraphQL/Mutations/CancelListingMutation.php @@ -6,6 +6,7 @@ use Enjin\BlockchainTools\HexConverter; use Enjin\Platform\Facades\TransactionSerializer; use Enjin\Platform\GraphQL\Schemas\Primary\Substrate\Traits\StoresTransactions; +use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasSkippableRules; use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasTransactionDeposit; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasIdempotencyField; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasSigningAccountField; @@ -13,6 +14,7 @@ use Enjin\Platform\Interfaces\PlatformBlockchainTransaction; use Enjin\Platform\Marketplace\Rules\ListingNotCancelled; use Enjin\Platform\Models\Transaction; +use Enjin\Platform\Rules\ValidHex; use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; use Illuminate\Support\Arr; @@ -24,6 +26,7 @@ class CancelListingMutation extends Mutation implements PlatformBlockchainTransa use HasIdempotencyField; use HasSigningAccountField; use HasSimulateField; + use HasSkippableRules; use HasTransactionDeposit; use StoresTransactions; @@ -59,6 +62,7 @@ public function args(): array ...$this->getSigningAccountField(), ...$this->getIdempotencyField(), ...$this->getSimulateField(), + ...$this->getSkipValidationField(), ]; } @@ -88,9 +92,9 @@ public static function getEncodableParams(...$params): array } /** - * Get the mutation's request validation rules. + * Get the mutation's validation rules. */ - protected function rules(array $args = []): array + protected function rulesWithValidation(array $args): array { return [ 'listingId' => [ @@ -101,4 +105,19 @@ protected function rules(array $args = []): array ], ]; } + + /** + * Get the mutation's validation rules without DB rules. + */ + protected function rulesWithoutValidation(array $args): array + { + return [ + 'listingId' => [ + 'bail', + 'filled', + 'max:255', + new ValidHex(32), + ], + ]; + } } diff --git a/src/GraphQL/Mutations/CreateListingMutation.php b/src/GraphQL/Mutations/CreateListingMutation.php index 8806fc4..da95b8d 100644 --- a/src/GraphQL/Mutations/CreateListingMutation.php +++ b/src/GraphQL/Mutations/CreateListingMutation.php @@ -6,6 +6,7 @@ use Enjin\BlockchainTools\HexConverter; use Enjin\Platform\Facades\TransactionSerializer; use Enjin\Platform\GraphQL\Schemas\Primary\Substrate\Traits\StoresTransactions; +use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasSkippableRules; use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasTokenIdFieldRules; use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasTransactionDeposit; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasIdempotencyField; @@ -34,6 +35,7 @@ class CreateListingMutation extends Mutation implements PlatformBlockchainTransa use HasIdempotencyField; use HasSigningAccountField; use HasSimulateField; + use HasSkippableRules; use HasTokenIdFieldRules; use HasTransactionDeposit; use StoresTransactions; @@ -90,6 +92,7 @@ public function args(): array ...$this->getSigningAccountField(), ...$this->getIdempotencyField(), ...$this->getSimulateField(), + ...$this->getSkipValidationField(), ]; } @@ -145,7 +148,7 @@ public static function getEncodableParams(...$params): array ]; } - protected function makeOrTakeRule(?string $collectionId = null, ?bool $isMake = true): array + protected function makeOrTakeRuleExist(?string $collectionId = null, ?bool $isMake = true): array { $makeOrTake = $isMake ? 'makeAssetId' : 'takeAssetId'; @@ -164,13 +167,49 @@ function (string $attribute, mixed $value, Closure $fail) { ]; } + protected function makeOrTakeRule(?string $collectionId = null, ?bool $isMake = true): array + { + $makeOrTake = $isMake ? 'makeAssetId' : 'takeAssetId'; + + return $collectionId === '0' ? [] : [ + $makeOrTake . '.collectionId' => [ + 'bail', + 'required_with:' . $makeOrTake . '.tokenId', + new MinBigInt(), + new MaxBigInt(Hex::MAX_UINT128), + ], + ]; + } + + /** + * Get the common rules. + */ + protected function rulesCommon(array $args): array + { + return [ + 'price' => [ + 'bail', + new MinBigInt(), + new MaxBigInt(), + ], + 'salt' => ['bail', 'filled', 'max:255'], + 'auctionData.endBlock' => [ + 'bail', + 'required_with:auctionData.startBlock', + new MinBigInt(), + new MaxBigInt(Hex::MAX_UINT32), + 'gt:auctionData.startBlock', + ], + ]; + } + /** - * Get the mutation's request validation rules. + * Get the mutation's validation rules. */ - protected function rules(array $args = []): array + protected function rulesWithValidation(array $args): array { - $makeRule = $this->makeOrTakeRule($makeCollection = Arr::get($args, 'makeAssetId.collectionId')); - $takeRule = $this->makeOrTakeRule($takeCollection = Arr::get($args, 'takeAssetId.collectionId'), false); + $makeRule = $this->makeOrTakeRuleExist($makeCollection = Arr::get($args, 'makeAssetId.collectionId')); + $takeRule = $this->makeOrTakeRuleExist($takeCollection = Arr::get($args, 'takeAssetId.collectionId'), false); return [ 'makeAssetId' => new TokenExistsInCollection($makeCollection), @@ -185,12 +224,6 @@ protected function rules(array $args = []): array new MaxBigInt(), new EnoughTokenSupply(), ], - 'price' => [ - 'bail', - new MinBigInt(), - new MaxBigInt(), - ], - 'salt' => ['bail', 'filled', 'max:255'], 'auctionData.startBlock' => [ 'bail', 'required_with:auctionData.endBlock', @@ -199,12 +232,33 @@ protected function rules(array $args = []): array new FutureBlock(), 'lte:auctionData.endBlock', ], - 'auctionData.endBlock' => [ + ]; + } + + /** + * Get the mutation's validation rules without DB rules. + */ + protected function rulesWithoutValidation(array $args): array + { + $makeRule = $this->makeOrTakeRule(Arr::get($args, 'makeAssetId.collectionId')); + $takeRule = $this->makeOrTakeRule(Arr::get($args, 'takeAssetId.collectionId'), false); + + return [ + ...$makeRule, + ...$this->getTokenFieldRules('makeAssetId'), + ...$takeRule, + ...$this->getTokenFieldRules('takeAssetId'), + 'amount' => [ 'bail', - 'required_with:auctionData.startBlock', + new MinBigInt(1), + new MaxBigInt(), + ], + 'auctionData.startBlock' => [ + 'bail', + 'required_with:auctionData.endBlock', new MinBigInt(), new MaxBigInt(Hex::MAX_UINT32), - 'gt:auctionData.startBlock', + 'lte:auctionData.endBlock', ], ]; } diff --git a/src/GraphQL/Mutations/FillListingMutation.php b/src/GraphQL/Mutations/FillListingMutation.php index 42b7827..c7852a5 100644 --- a/src/GraphQL/Mutations/FillListingMutation.php +++ b/src/GraphQL/Mutations/FillListingMutation.php @@ -6,6 +6,7 @@ use Enjin\BlockchainTools\HexConverter; use Enjin\Platform\Facades\TransactionSerializer; use Enjin\Platform\GraphQL\Schemas\Primary\Substrate\Traits\StoresTransactions; +use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasSkippableRules; use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasTransactionDeposit; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasIdempotencyField; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasSigningAccountField; @@ -15,6 +16,7 @@ use Enjin\Platform\Models\Transaction; use Enjin\Platform\Rules\MaxBigInt; use Enjin\Platform\Rules\MinBigInt; +use Enjin\Platform\Rules\ValidHex; use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; use Illuminate\Support\Arr; @@ -26,6 +28,7 @@ class FillListingMutation extends Mutation implements PlatformBlockchainTransact use HasIdempotencyField; use HasSigningAccountField; use HasSimulateField; + use HasSkippableRules; use HasTransactionDeposit; use StoresTransactions; @@ -65,6 +68,7 @@ public function args(): array ...$this->getSigningAccountField(), ...$this->getIdempotencyField(), ...$this->getSimulateField(), + ...$this->getSkipValidationField(), ]; } @@ -95,9 +99,23 @@ public static function getEncodableParams(...$params): array } /** - * Get the mutation's request validation rules. + * Get the common rules. */ - protected function rules(array $args = []): array + protected function rulesCommon(array $args): array + { + return [ + 'amount' => [ + 'bail', + new MinBigInt(1), + new MaxBigInt(), + ], + ]; + } + + /** + * Get the mutation's validation rules. + */ + protected function rulesWithValidation(array $args): array { return [ 'listingId' => [ @@ -106,10 +124,20 @@ protected function rules(array $args = []): array 'max:255', new ListingNotCancelled(), ], - 'amount' => [ + ]; + } + + /** + * Get the mutation's validation rules without DB rules. + */ + protected function rulesWithoutValidation(array $args): array + { + return [ + 'listingId' => [ 'bail', - new MinBigInt(1), - new MaxBigInt(), + 'filled', + 'max:255', + new ValidHex(32), ], ]; } diff --git a/src/GraphQL/Mutations/FinalizeAuctionMutation.php b/src/GraphQL/Mutations/FinalizeAuctionMutation.php index a7f6512..4c84697 100644 --- a/src/GraphQL/Mutations/FinalizeAuctionMutation.php +++ b/src/GraphQL/Mutations/FinalizeAuctionMutation.php @@ -6,6 +6,7 @@ use Enjin\BlockchainTools\HexConverter; use Enjin\Platform\Facades\TransactionSerializer; use Enjin\Platform\GraphQL\Schemas\Primary\Substrate\Traits\StoresTransactions; +use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasSkippableRules; use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasTransactionDeposit; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasIdempotencyField; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasSigningAccountField; @@ -13,6 +14,7 @@ use Enjin\Platform\Interfaces\PlatformBlockchainTransaction; use Enjin\Platform\Marketplace\Rules\ListingNotCancelled; use Enjin\Platform\Models\Transaction; +use Enjin\Platform\Rules\ValidHex; use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; use Illuminate\Support\Arr; @@ -24,6 +26,7 @@ class FinalizeAuctionMutation extends Mutation implements PlatformBlockchainTran use HasIdempotencyField; use HasSigningAccountField; use HasSimulateField; + use HasSkippableRules; use HasTransactionDeposit; use StoresTransactions; @@ -59,6 +62,7 @@ public function args(): array ...$this->getSigningAccountField(), ...$this->getIdempotencyField(), ...$this->getSimulateField(), + ...$this->getSkipValidationField(), ]; } @@ -88,9 +92,9 @@ public static function getEncodableParams(...$params): array } /** - * Get the mutation's request validation rules. + * Get the mutation's validation rules. */ - protected function rules(array $args = []): array + protected function rulesWithValidation(array $args): array { return [ 'listingId' => [ @@ -101,4 +105,19 @@ protected function rules(array $args = []): array ], ]; } + + /** + * Get the mutation's validation rules without DB rules. + */ + protected function rulesWithoutValidation(array $args): array + { + return [ + 'listingId' => [ + 'bail', + 'filled', + 'max:255', + new ValidHex(32), + ], + ]; + } } diff --git a/src/GraphQL/Mutations/PlaceBidMutation.php b/src/GraphQL/Mutations/PlaceBidMutation.php index 599fd15..fef4c7e 100644 --- a/src/GraphQL/Mutations/PlaceBidMutation.php +++ b/src/GraphQL/Mutations/PlaceBidMutation.php @@ -6,6 +6,7 @@ use Enjin\BlockchainTools\HexConverter; use Enjin\Platform\Facades\TransactionSerializer; use Enjin\Platform\GraphQL\Schemas\Primary\Substrate\Traits\StoresTransactions; +use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasSkippableRules; use Enjin\Platform\GraphQL\Schemas\Primary\Traits\HasTransactionDeposit; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasIdempotencyField; use Enjin\Platform\GraphQL\Types\Input\Substrate\Traits\HasSigningAccountField; @@ -16,6 +17,7 @@ use Enjin\Platform\Models\Transaction; use Enjin\Platform\Rules\MaxBigInt; use Enjin\Platform\Rules\MinBigInt; +use Enjin\Platform\Rules\ValidHex; use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; use Illuminate\Support\Arr; @@ -27,6 +29,7 @@ class PlaceBidMutation extends Mutation implements PlatformBlockchainTransaction use HasIdempotencyField; use HasSigningAccountField; use HasSimulateField; + use HasSkippableRules; use HasTransactionDeposit; use StoresTransactions; @@ -66,6 +69,7 @@ public function args(): array ...$this->getSigningAccountField(), ...$this->getIdempotencyField(), ...$this->getSimulateField(), + ...$this->getSkipValidationField(), ]; } @@ -96,9 +100,9 @@ public static function getEncodableParams(...$params): array } /** - * Get the mutation's request validation rules. + * Get the mutation's validation rules. */ - protected function rules(array $args = []): array + protected function rulesWithValidation(array $args): array { return [ 'listingId' => [ @@ -115,4 +119,24 @@ protected function rules(array $args = []): array ], ]; } + + /** + * Get the mutation's validation rules without DB rules. + */ + protected function rulesWithoutValidation(array $args): array + { + return [ + 'listingId' => [ + 'bail', + 'filled', + 'max:255', + new ValidHex(32), + ], + 'price' => [ + 'bail', + new MinBigInt(1), + new MaxBigInt(), + ], + ]; + } } diff --git a/tests/Feature/GraphQL/Mutations/CancelListingTest.php b/tests/Feature/GraphQL/Mutations/CancelListingTest.php index ad95d63..6f2b6cd 100644 --- a/tests/Feature/GraphQL/Mutations/CancelListingTest.php +++ b/tests/Feature/GraphQL/Mutations/CancelListingTest.php @@ -30,6 +30,18 @@ public function test_it_can_cancel_listing(): void ); } + public function test_it_can_skip_validation(): void + { + $response = $this->graphql( + $this->method, + $params = ['listingId' => '0x' . fake()->regexify('[a-f0-9]{64}'), 'skipValidation' => true] + ); + $this->assertEquals( + $response['encodedData'], + TransactionSerializer::encode($this->method, CancelListingMutation::getEncodableParams(...$params)) + ); + } + public function test_it_will_fail_with_invalid_parameter_listing_id(): void { $response = $this->graphql( diff --git a/tests/Feature/GraphQL/Mutations/CreateListingTest.php b/tests/Feature/GraphQL/Mutations/CreateListingTest.php index f8b8925..c410f67 100644 --- a/tests/Feature/GraphQL/Mutations/CreateListingTest.php +++ b/tests/Feature/GraphQL/Mutations/CreateListingTest.php @@ -47,7 +47,51 @@ public function test_it_can_create_listing(): void Arr::get($params, 'takeAssetId.collectionId'), $this->encodeTokenId(Arr::get($params, 'takeAssetId')) ); - $params['auctionData'] = ($data = Arr::get($params, 'auctionData')) + $params['auctionData'] = (Arr::get($params, 'auctionData')) + ? new AuctionDataParams(Arr::get($params, 'auctionData.startBlock'), Arr::get($params, 'auctionData.endBlock')) + : null; + + $this->assertEquals( + $response['encodedData'], + TransactionSerializer::encode($this->method, CreateListingMutation::getEncodableParams(...$params)) + ); + + $this->assertNull(Arr::get($response, 'wallet.account.publicKey')); + } + + public function test_it_can_skip_validation(): void + { + $response = $this->graphql( + $this->method, + $params = [ + 'makeAssetId' => [ + 'collectionId' => fake()->numberBetween(10000, 20000), + 'tokenId' => ['integer' => fake()->numberBetween(10000, 20000)], + ], + 'takeAssetId' => [ + 'collectionId' => fake()->numberBetween(10000, 20000), + 'tokenId' => ['integer' => fake()->numberBetween(10000, 20000)], + ], + 'amount' => fake()->numberBetween(1, 1000), + 'price' => fake()->numberBetween(1, 1000), + 'salt' => fake()->text(10), + 'auctionData' => [ + 'startBlock' => fake()->numberBetween(1011, 5000), + 'endBlock' => fake()->numberBetween(5001, 10000), + ], + 'skipValidation' => true, + ] + ); + + $params['makeAssetId'] = new MultiTokensTokenAssetIdParams( + Arr::get($params, 'makeAssetId.collectionId'), + $this->encodeTokenId(Arr::get($params, 'makeAssetId')) + ); + $params['takeAssetId'] = new MultiTokensTokenAssetIdParams( + Arr::get($params, 'takeAssetId.collectionId'), + $this->encodeTokenId(Arr::get($params, 'takeAssetId')) + ); + $params['auctionData'] = (Arr::get($params, 'auctionData')) ? new AuctionDataParams(Arr::get($params, 'auctionData.startBlock'), Arr::get($params, 'auctionData.endBlock')) : null; diff --git a/tests/Feature/GraphQL/Mutations/FillListingTest.php b/tests/Feature/GraphQL/Mutations/FillListingTest.php index 5e96f32..ad1edc3 100644 --- a/tests/Feature/GraphQL/Mutations/FillListingTest.php +++ b/tests/Feature/GraphQL/Mutations/FillListingTest.php @@ -31,6 +31,18 @@ public function test_it_can_fill_listing(): void ); } + public function test_it_can_skip_validation(): void + { + $response = $this->graphql( + $this->method, + $params = ['listingId' => '0x' . fake()->regexify('[a-f0-9]{64}'), 'amount' => fake()->numberBetween(1, 1000), 'skipValidation' => true] + ); + $this->assertEquals( + $response['encodedData'], + TransactionSerializer::encode($this->method, FillListingMutation::getEncodableParams(...$params)) + ); + } + public function test_it_will_fail_with_invalid_parameter_listing_id(): void { $listing = $this->createListing(); diff --git a/tests/Feature/GraphQL/Mutations/FinalizeAuctionTest.php b/tests/Feature/GraphQL/Mutations/FinalizeAuctionTest.php index 3a80c44..c8a3667 100644 --- a/tests/Feature/GraphQL/Mutations/FinalizeAuctionTest.php +++ b/tests/Feature/GraphQL/Mutations/FinalizeAuctionTest.php @@ -29,6 +29,18 @@ public function test_it_can_finalize_auction(): void ); } + public function test_it_can_skip_validation(): void + { + $response = $this->graphql( + $this->method, + $params = ['listingId' => '0x' . fake()->regexify('[a-f0-9]{64}'), 'skipValidation' => true] + ); + $this->assertEquals( + $response['encodedData'], + TransactionSerializer::encode($this->method, FinalizeAuctionMutation::getEncodableParams(...$params)) + ); + } + public function test_it_will_fail_with_invalid_parameter_listing_id(): void { $response = $this->graphql( diff --git a/tests/Feature/GraphQL/Mutations/PlaceBidTest.php b/tests/Feature/GraphQL/Mutations/PlaceBidTest.php index 40bf43a..a033883 100644 --- a/tests/Feature/GraphQL/Mutations/PlaceBidTest.php +++ b/tests/Feature/GraphQL/Mutations/PlaceBidTest.php @@ -33,6 +33,22 @@ public function test_it_can_place_bid(): void ); } + public function test_it_can_skip_validation(): void + { + $response = $this->graphql( + $this->method, + $params = [ + 'listingId' => '0x' . fake()->regexify('[a-f0-9]{64}'), + 'price' => fake()->numberBetween(1, 1000), + 'skipValidation' => true, + ] + ); + $this->assertEquals( + $response['encodedData'], + TransactionSerializer::encode($this->method, PlaceBidMutation::getEncodableParams(...$params)) + ); + } + public function test_it_will_fail_with_invalid_parameter_listing_id(): void { $listing = $this->createListing(); diff --git a/tests/Feature/GraphQL/Resources/CancelListing.graphql b/tests/Feature/GraphQL/Resources/CancelListing.graphql index 4193f61..6800368 100644 --- a/tests/Feature/GraphQL/Resources/CancelListing.graphql +++ b/tests/Feature/GraphQL/Resources/CancelListing.graphql @@ -1,5 +1,5 @@ -mutation CancelListing($listingId: String!) { - CancelListing(listingId: $listingId) { +mutation CancelListing($listingId: String!, $skipValidation: Boolean) { + CancelListing(listingId: $listingId, skipValidation: $skipValidation) { id transactionId transactionHash diff --git a/tests/Feature/GraphQL/Resources/CreateListing.graphql b/tests/Feature/GraphQL/Resources/CreateListing.graphql index e819d94..0a9d5a6 100644 --- a/tests/Feature/GraphQL/Resources/CreateListing.graphql +++ b/tests/Feature/GraphQL/Resources/CreateListing.graphql @@ -6,6 +6,7 @@ mutation CreateListing( $salt: String! $auctionData: AuctionDataInputType $signingAccount: String + $skipValidation: Boolean ) { CreateListing( makeAssetId: $makeAssetId @@ -15,6 +16,7 @@ mutation CreateListing( salt: $salt auctionData: $auctionData signingAccount: $signingAccount + skipValidation: $skipValidation ) { id transactionId diff --git a/tests/Feature/GraphQL/Resources/FillListing.graphql b/tests/Feature/GraphQL/Resources/FillListing.graphql index 945b1cf..d561a9e 100644 --- a/tests/Feature/GraphQL/Resources/FillListing.graphql +++ b/tests/Feature/GraphQL/Resources/FillListing.graphql @@ -1,5 +1,5 @@ -mutation FillListing($listingId: String!, $amount: BigInt!) { - FillListing(listingId: $listingId, amount: $amount) { +mutation FillListing($listingId: String!, $amount: BigInt!, $skipValidation: Boolean) { + FillListing(listingId: $listingId, amount: $amount, skipValidation: $skipValidation) { id transactionId transactionHash diff --git a/tests/Feature/GraphQL/Resources/FinalizeAuction.graphql b/tests/Feature/GraphQL/Resources/FinalizeAuction.graphql index 3512240..8bbbdc5 100644 --- a/tests/Feature/GraphQL/Resources/FinalizeAuction.graphql +++ b/tests/Feature/GraphQL/Resources/FinalizeAuction.graphql @@ -1,5 +1,5 @@ -mutation FinalizeAuction($listingId: String!) { - FinalizeAuction(listingId: $listingId) { +mutation FinalizeAuction($listingId: String!, $skipValidation: Boolean) { + FinalizeAuction(listingId: $listingId, skipValidation: $skipValidation) { id transactionId transactionHash diff --git a/tests/Feature/GraphQL/Resources/PlaceBid.graphql b/tests/Feature/GraphQL/Resources/PlaceBid.graphql index a355e09..4d575d3 100644 --- a/tests/Feature/GraphQL/Resources/PlaceBid.graphql +++ b/tests/Feature/GraphQL/Resources/PlaceBid.graphql @@ -1,5 +1,5 @@ -mutation PlaceBid($listingId: String!, $price: BigInt!) { - PlaceBid(listingId: $listingId, price: $price) { +mutation PlaceBid($listingId: String!, $price: BigInt!, $skipValidation: Boolean) { + PlaceBid(listingId: $listingId, price: $price, skipValidation: $skipValidation) { id transactionId transactionHash