Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: index NFT burn events #454

Merged
merged 14 commits into from
Nov 20, 2023
20 changes: 9 additions & 11 deletions app/Data/Nfts/NftActivityData.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
use Spatie\TypeScriptTransformer\Attributes\LiteralTypeScriptType;
use Spatie\TypeScriptTransformer\Attributes\TypeScript;

#[TypeScript]
Expand All @@ -23,24 +22,23 @@ public function __construct(
public string $recipient,
public int $timestamp,
public CollectionNftData $nft,
#[LiteralTypeScriptType('App.Enums.NftTransferType')]
public NftTransferType $type,
public ?string $totalNative,
public ?string $totalUsd
) {
}

public static function fromModel(NftActivity $nftActivity): self
public static function fromModel(NftActivity $activity): self
{
return new self(
id: $nftActivity->tx_hash,
sender: $nftActivity->sender,
recipient: $nftActivity->recipient,
timestamp: (int) $nftActivity->timestamp->timestamp,
nft: CollectionNftData::fromModel($nftActivity->nft),
type: $nftActivity->type,
totalNative: $nftActivity->total_native ?? null,
totalUsd: $nftActivity->total_usd ?? null,
id: $activity->tx_hash,
sender: $activity->sender,
recipient: $activity->recipient,
timestamp: (int) $activity->timestamp->timestamp,
nft: CollectionNftData::fromModel($activity->nft),
type: $activity->type,
totalNative: $activity->total_native ?? null,
totalUsd: $activity->total_usd ?? null,
);
}
}
18 changes: 1 addition & 17 deletions app/Enums/NftTransferType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,13 @@

namespace App\Enums;

use InvalidArgumentException;
use Spatie\TypeScriptTransformer\Attributes\TypeScript;

/**
* @see https://docs.mnemonichq.com/references/uniform/rest/reference/#operation/FoundationalService_GetNftTransfers for
* type referecnes
*/
#[TypeScript]
enum NftTransferType: string
{
// Note: there are more labels but currently we only care about the following
// ones
case Mint = 'LABEL_MINT';
case Sale = 'LABEL_SALE';
case Transfer = 'LABEL_TRANSFER';

public static function getEnumFromValue(string $value): self
{
return match ($value) {
'LABEL_MINT' => self::Mint,
'LABEL_SALE' => self::Sale,
'LABEL_TRANSFER' => self::Transfer,
default => throw new InvalidArgumentException(sprintf('Invalid value: %s', $value)),
};
}
case Burn = 'LABEL_BURN';
}
25 changes: 14 additions & 11 deletions app/Http/Client/Mnemonic/MnemonicPendingRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ public function getCollectionActivity(Chain $chain, string $contractAddress, int
'LABEL_MINT',
'LABEL_SALE',
'LABEL_TRANSFER',
'LABEL_BURN',
]));

if ($from !== null) {
Expand Down Expand Up @@ -455,19 +456,21 @@ private function getActivityNativePrice(

/**
* @param string[] $labels
*
* @see https://docs.mnemonichq.com/references/uniform/rest/reference/#operation/FoundationalService_GetNftTransfers
*/
private function extractNftTransferType(array $labels): ?NftTransferType
{
$validLabels = ['LABEL_MINT', 'LABEL_TRANSFER', 'LABEL_SALE'];

$label = collect($validLabels)->first(function ($label) use ($labels) {
return in_array($label, $labels);
});

if ($label === null) {
return null;
}

return NftTransferType::getEnumFromValue($label);
$label = collect($labels)->intersect([
'LABEL_MINT', 'LABEL_BURN', 'LABEL_TRANSFER', 'LABEL_SALE',
])->first();

return match ($label) {
'LABEL_MINT' => NftTransferType::Mint,
'LABEL_SALE' => NftTransferType::Sale,
'LABEL_TRANSFER' => NftTransferType::Transfer,
'LABEL_BURN' => NftTransferType::Burn,
default => null,
};
}
}
1 change: 1 addition & 0 deletions lang/en/pages.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
'LABEL_MINT' => 'Mint',
'LABEL_TRANSFER' => 'Transfer',
'LABEL_SALE' => 'Sale',
'LABEL_BURN' => 'Burn',
],
],
'articles' => [
Expand Down
1 change: 1 addition & 0 deletions resources/icons/fire.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,10 @@ export const Type = ({
};

const icons: Record<App.Enums.NftTransferType, IconName> = {
// @TODO: define the icon for mint
LABEL_MINT: "LayeredCards",
LABEL_TRANSFER: "ArrowUpArrowDown",
LABEL_SALE: "Cart",
LABEL_BURN: "Fire",
};

// This will need to be adjusted if more types are added
Expand Down
2 changes: 1 addition & 1 deletion resources/js/I18n/Locales/en.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion resources/js/Tests/Factories/Nfts/NFTActivityFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default class NFTActivityFactory extends ModelFactory<App.Data.Nfts.NftAc
recipient: this.generateAddress(),
timestamp: faker.date.past().getTime(),
nft: new CollectionNftDataFactory().create(),
type: faker.helpers.arrayElement(["LABEL_MINT", "LABEL_SALE", "LABEL_TRANSFER"]),
type: faker.helpers.arrayElement(["LABEL_MINT", "LABEL_SALE", "LABEL_TRANSFER", "LABEL_BURN"]),
totalUsd: faker.datatype.number().toString(),
totalNative: faker.datatype.number().toString(),
};
Expand Down
2 changes: 2 additions & 0 deletions resources/js/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import { ReactComponent as FatDoubleCheck } from "@icons/fat-double-check.svg";
import { ReactComponent as FatPlus } from "@icons/fat-plus.svg";
import { ReactComponent as FatXInCircle } from "@icons/fat-x-in-circle.svg";
import { ReactComponent as FingerTap } from "@icons/finger-tap.svg";
import { ReactComponent as Fire } from "@icons/fire.svg";
import { ReactComponent as Flag } from "@icons/flag.svg";
import { ReactComponent as FunnelBars } from "@icons/funnel-bars.svg";
import { ReactComponent as Funnel } from "@icons/funnel.svg";
Expand Down Expand Up @@ -161,6 +162,7 @@ export const SvgCollection = {
FatArrowDown,
FatArrowUp,
FingerTap,
Fire,
Flag,
FunnelBars,
Funnel,
Expand Down
2 changes: 1 addition & 1 deletion resources/types/generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -509,5 +509,5 @@ declare namespace App.Data.Wallet {
}
declare namespace App.Enums {
export type Chain = 1 | 5 | 137 | 80001;
export type NftTransferType = "LABEL_MINT" | "LABEL_SALE" | "LABEL_TRANSFER";
export type NftTransferType = "LABEL_MINT" | "LABEL_SALE" | "LABEL_TRANSFER" | "LABEL_BURN";
}
17 changes: 0 additions & 17 deletions tests/App/Enums/NftTransferTypeTest.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@
it('should ignore activity with unexpected label', function () {
$response = fixtureData('mnemonic.nft_transfers');

$response['nftTransfers'][1]['labels'] = ['LABEL_BURN'];
$response['nftTransfers'][1]['labels'] = ['LABEL_TEST'];

Mnemonic::fake([
'https://*-rest.api.mnemonichq.com/foundational/v1beta2/transfers/nft?*' => Http::response($response, 200),
Expand All @@ -391,9 +391,6 @@
$data = Mnemonic::getCollectionActivity(Chain::Polygon, $collection->address, 100);

expect($data)->toHaveCount(18);

expect($data->contains(fn ($activity) => $activity->type?->value === 'LABEL_BURN'))->toBeFalse();
expect($data->contains(fn ($activity) => $activity->type === null))->toBeTrue();
});

it('should fetch activity from date', function () {
Expand Down
Loading