Skip to content

Commit

Permalink
[PLA-1590] Add support for batch transactions with continueOnFailure. (
Browse files Browse the repository at this point in the history
  • Loading branch information
v16Studios authored Feb 22, 2024
1 parent 812f2e2 commit 195a017
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ public function args(): array
'type' => GraphQL::type('[MintRecipient!]!'),
'rules' => ['array', 'min:1', 'max:250'],
],
'continueOnFailure' => [
'type' => GraphQL::type('Boolean'),
'defaultValue' => false,
],
...$this->getSigningAccountField(),
...$this->getIdempotencyField(),
...$this->getSkipValidationField(),
Expand Down Expand Up @@ -126,7 +130,7 @@ function ($recipient) use ($blockchainService, $walletService) {
);

// Hard-coded to false until we add support for this feature back into the mutations.
$continueOnFailure = false;
$continueOnFailure = $args['continueOnFailure'];
$encodedData = $serializationService->encode($continueOnFailure ? 'Batch' : $this->getMutationName(), static::getEncodableParams(
collectionId: $args['collectionId'],
recipients: $recipients->toArray(),
Expand All @@ -147,7 +151,7 @@ public static function getEncodableParams(...$params): array
$recipients = Arr::get($params, 'recipients', []);

if ($continueOnFailure) {
$encodedData = $recipients->map(
$encodedData = collect($recipients)->map(
fn ($recipient) => $serializationService->encode('Mint', [
'collectionId' => gmp_init($collectionId),
'recipient' => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ public function args(): array
'recipients' => [
'type' => GraphQL::type('[TransferRecipient!]!'),
],
'continueOnFailure' => [
'type' => GraphQL::type('Boolean'),
'defaultValue' => false,
],
...$this->getSigningAccountField(),
...$this->getIdempotencyField(),
...$this->getSkipValidationField(),
Expand Down Expand Up @@ -115,7 +119,7 @@ function ($recipient) use ($blockchainService, $walletService) {
);

// Hard-coded to false until we add support for this feature back into the mutations.
$continueOnFailure = false;
$continueOnFailure = $args['continueOnFailure'];
$encodedData = $serializationService->encode($continueOnFailure ? 'Batch' : $this->getMutationName(), static::getEncodableParams(
collectionId: $args['collectionId'],
recipients: $recipients->toArray(),
Expand All @@ -136,7 +140,7 @@ public static function getEncodableParams(...$params): array
$recipients = Arr::get($params, 'recipients', []);

if ($continueOnFailure) {
$encodedData = $recipients->map(
$encodedData = collect($recipients)->map(
fn ($recipient) => $serializationService->encode('TransferToken', [
'recipient' => [
'Id' => HexConverter::unPrefix($recipient['accountId']),
Expand Down
53 changes: 53 additions & 0 deletions tests/Feature/GraphQL/Mutations/BatchMintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,59 @@ public function test_it_can_batch_mint_mint_multiple_tokens(): void
Event::assertDispatched(TransactionCreated::class);
}

public function test_it_can_batch_mint_mint_multiple_tokens_with_continue_on_failure(): void
{
Token::where('collection_id', '=', $this->collection->collection_id)?->delete();

$tokens = Token::factory([
'collection_id' => $this->collection,
'cap' => TokenMintCapType::INFINITE->name,
])->count(10)->create();

$recipients = $tokens->map(fn ($token) => [
'accountId' => Wallet::factory()->create()->public_key,
'params' => new MintParams(
tokenId: $this->tokenIdEncoder->encode($token->token_chain_id),
amount: fake()->numberBetween(1),
),
]);

$encodedData = TransactionSerializer::encode($this->method, BatchMintMutation::getEncodableParams(
collectionId: $collectionId = $this->collection->collection_chain_id,
recipients: $recipients->toArray()
));

$response = $this->graphql($this->method, [
'collectionId' => $collectionId,
'recipients' => $recipients->map(function ($recipient) {
$params = $recipient['params']->toArray()['Mint'];
$params['tokenId'] = $this->tokenIdEncoder->toEncodable($params['tokenId']);

return [
'account' => SS58Address::encode($recipient['accountId']),
'mintParams' => $params,
];
})->toArray(),
'continueOnFailure' => true,
]);

$this->assertArraySubset([
'method' => $this->method,
'state' => TransactionState::PENDING->name,
'encodedData' => $encodedData,
'wallet' => null,
], $response);

$this->assertDatabaseHas('transactions', [
'id' => $response['id'],
'method' => $this->method,
'state' => TransactionState::PENDING->name,
'encoded_data' => $encodedData,
]);

Event::assertDispatched(TransactionCreated::class);
}

public function test_it_can_batch_mint_mixed_tokens(): void
{
Token::where('collection_id', '=', $this->collection->collection_id)?->delete();
Expand Down
54 changes: 54 additions & 0 deletions tests/Feature/GraphQL/Mutations/BatchTransferTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,60 @@ public function test_it_can_batch_simple_multiple_transfers(): void
Event::assertDispatched(TransactionCreated::class);
}

public function test_it_can_batch_simple_multiple_transfers_with_continue_on_failure(): void
{
// TODO: We should validate if the sum of all amount doesn't exceed the total balance
// Will do that later

$recipients = collect(
range(
0,
($value = fake()->randomNumber(1, $this->tokenAccount->balance)) < 10 ? $value : 9
)
)->map(fn ($x) => [
'accountId' => Wallet::factory()->create()->public_key,
'params' => new SimpleTransferParams(
tokenId: $this->tokenIdEncoder->encode(),
amount: fake()->numberBetween(1, $this->tokenAccount->balance)
),
]);

$encodedData = TransactionSerializer::encode($this->method, BatchTransferMutation::getEncodableParams(
collectionId: $collectionId = $this->collection->collection_chain_id,
recipients: $recipients->toArray()
));

$response = $this->graphql($this->method, [
'collectionId' => $collectionId,
'recipients' => $recipients->map(function ($recipient) {
$simpleParams = $recipient['params']->toArray()['Simple'];
$simpleParams['tokenId'] = $this->tokenIdEncoder->toEncodable();

return [
'account' => SS58Address::encode($recipient['accountId']),
'simpleParams' => $simpleParams,
];
})->toArray(),
'continueOnFailure' => true,
]);

$this->assertArraySubset([
'method' => $this->method,
'state' => TransactionState::PENDING->name,
'encodedData' => $encodedData,
'wallet' => null,
], $response);

$this->assertDatabaseHas('transactions', [
'id' => $response['id'],
'method' => $this->method,
'state' => TransactionState::PENDING->name,
'encoded_data' => $encodedData,
]);

Event::assertDispatched(TransactionCreated::class);
}

public function test_it_can_batch_operator_multiple_transfers(): void
{
$recipients = collect(
Expand Down
29 changes: 28 additions & 1 deletion tests/Unit/EncodingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ public function test_it_can_encode_remove_all_attributes()
);
}

public function test_it_can_encode_efinity_utility_batch()
public function test_it_can_encode_matrix_utility_batch()
{
$call = TransactionSerializer::encode('Mint', CreateTokenMutation::getEncodableParams(
recipientAccount: '0x52e3c0eb993523286d19954c7e3ada6f791fa3f32764e44b9c1df0c2723bc15e',
Expand All @@ -1240,4 +1240,31 @@ public function test_it_can_encode_efinity_utility_batch()
$data
);
}

public function test_it_can_encode_matrix_utility_batch_with_continue_on_failure()
{
$call = TransactionSerializer::encode('Mint', CreateTokenMutation::getEncodableParams(
recipientAccount: '0x52e3c0eb993523286d19954c7e3ada6f791fa3f32764e44b9c1df0c2723bc15e',
collectionId: '1',
createTokenParams: new CreateTokenParams(
tokenId: '255',
initialSupply: '57005',
cap: TokenMintCapType::INFINITE,
unitPrice: '10000000000000',
behavior: null,
listingForbidden: null
)
));

$data = $this->codec->encoder()->batch(
calls: [$call, $call],
continueOnFailure: true,
);

$callIndex = $this->codec->encoder()->getCallIndex('MatrixUtility.batch', true);
$this->assertEquals(
"0x{$callIndex}0828040052e3c0eb993523286d19954c7e3ada6f791fa3f32764e44b9c1df0c2723bc15e0400fd03b67a0300000100a0724e18090000000000000000000000000000000028040052e3c0eb993523286d19954c7e3ada6f791fa3f32764e44b9c1df0c2723bc15e0400fd03b67a0300000100a0724e18090000000000000000000000000000000001",
$data
);
}
}

0 comments on commit 195a017

Please sign in to comment.