Skip to content

Commit

Permalink
Merge branch 'master' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardocustodio committed Nov 28, 2023
2 parents 081db96 + 99ac3b0 commit 70c3d75
Show file tree
Hide file tree
Showing 12 changed files with 424 additions and 40 deletions.
1 change: 1 addition & 0 deletions lang/en/query.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
'get_beams.description' => 'Get beams details.',
'get_single_use_codes.description' => 'Get single use codes.',
'get_claims.description' => 'Get the claims details.',
'get_pending_claims.description' => 'Get a list of pending claims for a Beam.',
];
80 changes: 80 additions & 0 deletions src/GraphQL/Queries/GetPendingClaimsQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace Enjin\Platform\Beam\GraphQL\Queries;

use Closure;
use Enjin\Platform\Beam\Models\BeamClaim;
use Enjin\Platform\GraphQL\Types\Pagination\ConnectionInput;
use Enjin\Platform\Interfaces\PlatformPublicGraphQlOperation;
use Enjin\Platform\Rules\ValidSubstrateAccount;
use Enjin\Platform\Support\SS58Address;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;
use Illuminate\Support\Arr;
use Rebing\GraphQL\Support\Facades\GraphQL;

class GetPendingClaimsQuery extends Query implements PlatformPublicGraphQlOperation
{
/**
* Get the query's attributes.
*/
public function attributes(): array
{
return [
'name' => 'GetPendingClaims',
'description' => __('enjin-platform-beam::query.get_pending_claims.description'),
];
}

/**
* Get the query's return type.
*/
public function type(): Type
{
return GraphQL::paginate('BeamClaim', 'BeamClaimConnection');
}

/**
* Get the query's arguments definition.
*/
public function args(): array
{
return ConnectionInput::args([
'code' => [
'type' => GraphQL::type('String!'),
'description' => __('enjin-platform-beam::mutation.claim_beam.args.code'),
],
'account' => [
'type' => GraphQL::type('String!'),
'description' => __('enjin-platform-beam::mutation.claim_beam.args.account'),
],
]);
}

/**
* Resolve the query's request.
*/
public function resolve(
$root,
array $args,
$context,
ResolveInfo $resolveInfo,
Closure $getSelectFields
) {
return BeamClaim::loadSelectFields($resolveInfo, $this->name)
->hasCode(Arr::get($args, 'code'))
->where('wallet_public_key', SS58Address::getPublicKey(Arr::get($args, 'account')))
->cursorPaginateWithTotalDesc('id', $args['first']);
}

/**
* Get the query's request validation rules.
*/
protected function rules(array $args = []): array
{
return [
'code' => ['filled', 'max:1024'],
'account' => ['filled', new ValidSubstrateAccount()],
];
}
}
13 changes: 11 additions & 2 deletions src/GraphQL/Types/BeamClaimType.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public function fields(): array
'type' => GraphQL::type('String!'),
'description' => __('enjin-platform-beam::type.beam_claim.field.code'),
'resolve' => fn ($claim) => $claim->code ? $claim->singleUseCode : '',
'excludeFrom' => ['GetBeam', 'GetBeams'],
'excludeFrom' => ['GetBeam', 'GetBeams', 'GetPendingClaims'],
],
'identifierCode' => [
'type' => GraphQL::type('String!'),
Expand All @@ -94,7 +94,16 @@ public function fields(): array
},
'selectable' => false,
'is_relation' => false,
'excludeFrom' => ['GetBeam', 'GetBeams'],
'excludeFrom' => ['GetBeam', 'GetBeams', 'GetPendingClaims'],
],
'attributes' => [
'type' => GraphQL::type('[AttributeType]'),
'description' => __('enjin-platform-beam::type.attribute.description'),
],
'transaction' => [
'type' => GraphQL::type('Transaction'),
'description' => __('enjin-platform::type.transaction.description'),
'is_relation' => true,
],
'attributes' => [
'type' => GraphQL::type('[AttributeType]'),
Expand Down
8 changes: 8 additions & 0 deletions src/Jobs/ClaimBeam.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Throwable;

class ClaimBeam implements ShouldQueue
Expand Down Expand Up @@ -56,10 +57,17 @@ public function handle(BatchService $batch, WalletService $wallet): void
BeamScan::firstWhere(['wallet_public_key' => $data['wallet_public_key'], 'beam_id' => $data['beam']['id']])?->delete();

DB::commit();

Log::info('Claim beam assigned.', $data);
} else {
Log::info('Claim beam cannot assign.', $data);
$this->release(1);
}
} catch (Throwable $e) {
DB::rollBack();

Log::error('Claim beam error, message:' . $e->getMessage(), $data);

throw $e;
}
}
Expand Down
17 changes: 17 additions & 0 deletions src/Models/Laravel/BeamClaim.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
use Enjin\Platform\Models\BaseModel;
use Enjin\Platform\Models\Laravel\Collection;
use Enjin\Platform\Models\Laravel\Token;
use Enjin\Platform\Models\Laravel\Transaction;
use Enjin\Platform\Models\Laravel\Wallet;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\MassPrunable;
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
Expand Down Expand Up @@ -194,6 +196,21 @@ public function prunable()
return static::where('id', 0);
}

/**
* The transaction relationship.
*/
public function transaction(): HasOneThrough
{
return $this->hasOneThrough(
Transaction::class,
BeamBatch::class,
'id',
'id',
'beam_batch_id',
'transaction_id'
);
}

/**
* This model's factory.
*/
Expand Down
2 changes: 2 additions & 0 deletions src/Models/Laravel/Traits/EagerLoadSelectFields.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public static function selectFields(ResolveInfo $resolveInfo, string $query): ar
);

break;
case 'GetPendingClaims':
case 'GetClaims':
case 'GetSingleUseCodes':
[$select, $with, $withCount] = static::loadClaims(
Expand Down Expand Up @@ -128,6 +129,7 @@ public static function loadClaims(
'beam_id',
isset($fields['wallet']) ? 'wallet_public_key' : null,
isset($fields['collection']) ? 'collection_id' : null,
isset($fields['transaction']) ? 'beam_batch_id' : null,
...(isset($fields['qr']) ? ['code'] : []),
...(static::$query == 'GetSingleUseCodes' ? ['code', 'nonce'] : ['nonce']),
...BeamClaimType::getSelectFields($fieldKeys = array_keys($fields)),
Expand Down
2 changes: 2 additions & 0 deletions src/Services/BeamService.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Throwable;
Expand Down Expand Up @@ -213,6 +214,7 @@ public function claim(string $code, string $wallet): bool
ClaimBeam::dispatch($claim = $this->buildClaimBeamData($wallet, $beam, $singleUseCode));
event(new BeamClaimPending($claim));
Cache::decrement($key);
Log::info("Claim beam: {$code}, Remaining: " . Cache::get($key), $claim);
} catch (LockTimeoutException $e) {
throw new BeamException(__('enjin-platform-beam::error.unable_to_process'));
} finally {
Expand Down
109 changes: 89 additions & 20 deletions src/Support/ClaimProbabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@

namespace Enjin\Platform\Beam\Support;

use Closure;
use Enjin\Platform\Beam\Enums\PlatformBeamCache;
use Enjin\Platform\Beam\Models\Laravel\BeamClaim;
use Enjin\Platform\Beam\Rules\Traits\IntegerRange;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use stdClass;

class ClaimProbabilities
{
use IntegerRange;

public const FORMAT_VERSION = 'v2';

/**
* Create or update the probabilities for a claim.
*/
Expand All @@ -31,15 +36,57 @@ public function createOrUpdateProbabilities(string $code, array $claims): void
*/
public static function hasProbabilities(string $code): bool
{
return Cache::has(PlatformBeamCache::CLAIM_PROBABILITIES->key($code));
return Cache::has(static::getCacheKey($code));
}

/**
* Get the cache key for the code.
*/
public static function getCacheKey(string $code): string
{
return PlatformBeamCache::CLAIM_PROBABILITIES->key($code) . ':' . static::FORMAT_VERSION;
}

/**
* Get the probabilities for a code.
*/
public static function getProbabilities(string $code): array
{
return Cache::get(PlatformBeamCache::CLAIM_PROBABILITIES->key($code), []);
return Cache::get(
static::getCacheKey($code),
static::getProbabilitiesFromDB($code)
);
}

/**
* Get the probabilities from the database.
*/
public static function getProbabilitiesFromDB(string $code): Closure
{
return function () use ($code) {
$claims = BeamClaim::selectRaw('
token_chain_id,
quantity as tokenQuantityPerClaim,
count(*) as claimQuantity
')->hasCode($code)
->groupBy('token_chain_id', 'quantity')
->get()
->map(function ($claim) {
$claim->tokenIds = [$claim->token_chain_id];

return $claim;
})->toArray();

$instance = resolve(static::class);
$formatted = $instance->filterClaims($claims);
$instance->computeProbabilities(
$code,
$formatted['ft'],
$formatted['nft'],
);

return Cache::get(static::getCacheKey($code), []);
};
}

/**
Expand Down Expand Up @@ -68,6 +115,34 @@ public function removeTokens(string $code, array $tokenIds): void
}
}

/**
* Compute the probabilities for the items.
*/
public function computeProbabilities(string $code, array $fts, array $nfts): void
{
$total = collect($fts)->sum() + ($totalNft = collect($nfts)->sum());
if (!$total) {
return;
}

$probabilities = [
'ft' => collect($fts)->mapWithKeys(fn ($quantity, $key) => [$key => ($quantity / $total) * 100])->toArray() ?: new stdClass(),
'nft' => ($totalNft / $total) * 100,
'ftTokenIds' => $this->extractTokenIds($fts, $total) ?: new stdClass(),
'nftTokenIds' => $this->extractTokenIds($nfts, $total) ?: new stdClass(),
];

$data = [
'tokens' => ['ft' => $fts, 'nft' => $nfts],
'probabilities' => $probabilities,
];

Cache::forever(
static::getCacheKey($code),
$data
);
}

/**
* Merge the tokens into the current tokens.
*/
Expand Down Expand Up @@ -116,28 +191,22 @@ protected function filterClaims(array $claims): array
}

/**
* Compute the probabilities for the items.
* Extract the token ids from the array.
*/
protected function computeProbabilities(string $code, array $fts, array $nfts): void
protected function extractTokenIds(array $tokenIds, int $total): array
{
$totalNft = collect($nfts)->sum();
$total = collect($fts)->sum() + $totalNft;
$probabilities = [];
if ($total > 0) {
foreach ($fts as $key => $quantity) {
$probabilities['ft'][$key] = ($quantity / $total) * 100;
$tokens = [];
foreach ($tokenIds as $key => $quantity) {
if (($range = $this->integerRange($key)) !== false) {
$count = $quantity / (($range[1] - $range[0]) + 1);
for ($i = $range[0]; $i <= $range[1]; $i++) {
$tokens[$i] = ($count / $total) * 100;
}
} else {
$tokens[$key] = ($quantity / $total) * 100;
}
$probabilities['nft'] = ($totalNft / $total) * 100;
}

$data = [
'tokens' => ['ft' => $fts, 'nft' => $nfts],
'probabilities' => $probabilities,
];

Cache::forever(
PlatformBeamCache::CLAIM_PROBABILITIES->key($code),
$data
);
return $tokens;
}
}
Loading

0 comments on commit 70c3d75

Please sign in to comment.