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: do not use deprecated mnemonic APIs #632

Merged
merged 8 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 21 additions & 38 deletions app/Http/Client/Mnemonic/MnemonicPendingRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,56 +180,39 @@ public function getCollectionFloorPrice(Chain $chain, string $contractAddress):
}
}

// https://docs.mnemonichq.com/reference/collectionsservice_getmetadata
/**
* Fetch the banner image for the collection.
*
* @see https://docs.mnemonichq.com/reference/foundationalservice_getnftcontracts
*/
public function getCollectionBanner(Chain $chain, string $contractAddress): ?string
{
$this->chain = MnemonicChain::fromChain($chain);

/** @var array<string, mixed> $data */
$data = self::get(sprintf('/collections/v1beta2/%s/metadata', $contractAddress), [])->json('metadata');

$metadata = collect($data)->mapWithKeys(fn ($item) => [$item['type'] => $item['value']]);

// *Note:* The API also returns an image for `TYPE_BANNER_IMAGE_URL`,
// however, I noticed that, (at least with the collections we have for
// testing), all images that return a value for
// `TYPE_ORIGINAL_BANNER_IMAGE_URL` also return a value for
// `TYPE_BANNER_IMAGE_URL`. On the other hand, images that don't return
// anything for `TYPE_ORIGINAL_BANNER_IMAGE_URL` do return a
// `TYPE_BANNER_IMAGE_URL` URL, but that URL shows an
// "Image metadata not found" message. Additionally, the image that
// comes from TYPE_BANNER_IMAGE_URL is too small to display in the header.
// In addition to that the image that comes from
// TYPE_ORIGINAL_BANNER_IMAGE_URL are urls from the OpenSea CDN,which
// seems to use the `imgix.com` API (or something similar).
// This means we can use GET attributes to resize the image to a more
// appropriate size for our banners.
$image = $metadata->get('TYPE_ORIGINAL_BANNER_IMAGE_URL');

if ($image === null) {
$url = $this->get('/foundational/v1beta2/nft_contracts', [
'contractAddresses' => $contractAddress,
])->json('nftContracts.0.bannerImageUrl');

if ($url === null || $url === '') {
return null;
}

// The image from `TYPE_ORIGINAL_BANNER_IMAGE_URL` includes a w= parameter
// that we can use to store a bigger image in our db.
return NftImageUrl::get($image, ImageSize::Banner);
// The URL includes a w= parameter. We want to normalize it, so that we can store a higher resolution image...
return NftImageUrl::get($url, ImageSize::Banner);
}

// https://docs.mnemonichq.com/reference/collectionsservice_getownerscount
public function getCollectionOwners(Chain $chain, string $contractAddress): ?int
/**
* Retrieve the number of owners of the collection.
*
* @see https://docs.mnemonichq.com/reference/collectionsservice_gettotals
*/
public function getCollectionOwners(Chain $chain, string $contractAddress): int
{
$this->chain = MnemonicChain::fromChain($chain);

/** @var array<string, mixed> $data */
$data = self::get(sprintf('/collections/v1beta2/%s/metadata', $contractAddress), [
'includeStats' => true,
])->json();

if (! is_numeric($data['ownersCount'])) {
return null;
}

return intval($data['ownersCount']);
return (int) $this->get(
'/collections/v1beta2/'.$contractAddress.'/totals'
)->json('ownersCount');
}

/**
Expand Down
10 changes: 0 additions & 10 deletions app/Jobs/FetchCollectionOwners.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

class FetchCollectionOwners implements ShouldQueue
{
Expand All @@ -35,10 +34,6 @@ public function __construct(
*/
public function handle(): void
{
Log::info('FetchCollectionOwners Job: Processing', [
'collection' => $this->collection->address,
]);

$owners = Mnemonic::getCollectionOwners(
chain: $this->collection->network->chain(),
contractAddress: $this->collection->address
Expand All @@ -47,11 +42,6 @@ public function handle(): void
$this->collection->update([
'owners' => $owners,
]);

Log::info('FetchCollectionOwners Job: Handled', [
'collection' => $this->collection->address,
'owners' => $owners,
]);
}

public function uniqueId(): string
Expand Down
2 changes: 1 addition & 1 deletion app/Support/Facades/Mnemonic.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* @method static string getNativeBalance(Wallet $wallet, Network $network)
* @method static Web3CollectionFloorPrice | null getCollectionFloorPrice(Chain $chain, string $contractAddress)
* @method static string | null getCollectionBanner(Chain $chain, string $contractAddress)
* @method static int | null getCollectionOwners(Chain $chain, string $contractAddress)
* @method static int getCollectionOwners(Chain $chain, string $contractAddress)
* @method static Web3Volume getLatestCollectionVolume(Chain $chain, string $contractAddress)
* @method static Collection<int, Web3Volume> getCollectionVolumeHistory(Chain $chain, string $address)
* @method static Collection<int, Web3CollectionTrait> getCollectionTraits(Chain $chain, string $contractAddress)
Expand Down
51 changes: 49 additions & 2 deletions tests/App/Http/Client/Mnemonic/MnemonicPendingRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@

it('should get owners', function () {
Mnemonic::fake([
'https://polygon-rest.api.mnemonichq.com/collections/v1beta2/*/metadata?includeStats=1' => Http::sequence()
->push(['ownersCount' => '789'], 200),
'https://polygon-rest.api.mnemonichq.com/collections/v1beta2/*/totals' => Http::response(['ownersCount' => '789']),
]);

$network = Network::polygon();
Expand All @@ -103,6 +102,54 @@
expect($data)->toBe(789);
});

it('should get banner URL for the collection', function () {
Mnemonic::fake([
'https://polygon-rest.api.mnemonichq.com/foundational/v1beta2/nft_contracts?contractAddresses=*' => Http::response([
'nftContracts' => [[
'bannerImageUrl' => 'https://example.com',
]],
]),
]);

$network = Network::polygon();

$collection = Collection::factory()->create([
'network_id' => $network->id,
]);

$banner = Mnemonic::getCollectionBanner(Chain::Polygon, $collection->address);

expect($banner)->toBe('https://example.com');
});

it('should normalize the banner URL for the collection', function () {
Mnemonic::fake([
'https://polygon-rest.api.mnemonichq.com/foundational/v1beta2/nft_contracts?contractAddresses=*' => Http::response([
'nftContracts' => [[
'bannerImageUrl' => 'https://i.seadn.io/gae/test?w=150&auto=format',
]],
]),
]);

$banner = Mnemonic::getCollectionBanner(Chain::Polygon, '0x123');

expect($banner)->toBe('https://i.seadn.io/gae/test?w=1378&auto=format');
});

it('can handle empty banner URLs', function () {
Mnemonic::fake([
'https://polygon-rest.api.mnemonichq.com/foundational/v1beta2/nft_contracts?contractAddresses=*' => Http::response([
'nftContracts' => [[
'bannerImageUrl' => '',
]],
]),
]);

$banner = Mnemonic::getCollectionBanner(Chain::Polygon, '0x123');

expect($banner)->toBeNull();
});

it('should get volume', function () {
Mnemonic::fake([
'https://polygon-rest.api.mnemonichq.com/collections/v1beta2/*/sales_volume/DURATION_1_DAY/GROUP_BY_PERIOD_1_DAY' => Http::sequence()
Expand Down
16 changes: 4 additions & 12 deletions tests/App/Jobs/FetchCollectionBannerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@
use App\Models\Collection;
use App\Models\Network;
use App\Support\Facades\Mnemonic;
use Illuminate\Support\Facades\Http;

it('should fetch nft collection banner', function () {
Mnemonic::fake([
'https://polygon-rest.api.mnemonichq.com/collections/v1beta2/*/metadata' => Http::response(fixtureData('mnemonic.nft_metadata'), 200),
]);
Mnemonic::shouldReceive('getCollectionBanner')->andReturn('https://i.seadn.io/gcs/files/f0d3006fb5a1f09d1619a024762f5aee.png?w=1378&auto=format');

$network = Network::polygon();

Expand All @@ -31,17 +28,12 @@

$collection->refresh();

expect($collection->banner())->toBe('https://i.seadn.io/gcs/files/f0d3006fb5a1f09d1619a024762f5aee.png?w=1378&auto=format')
->and($collection->image())->toBe('image-url');
expect($collection->banner())->toBe('https://i.seadn.io/gcs/files/f0d3006fb5a1f09d1619a024762f5aee.png?w=1378&auto=format');
expect($collection->image())->toBe('image-url');
});

it('should fetch nft collection banner in case no image', function () {
$response = fixtureData('mnemonic.nft_metadata');
$response['metadata'] = [];

Mnemonic::fake([
'https://polygon-rest.api.mnemonichq.com/collections/v1beta2/*/metadata' => Http::response($response, 200),
]);
Mnemonic::shouldReceive('getCollectionBanner')->andReturn(null);

$network = Network::polygon();

Expand Down
15 changes: 3 additions & 12 deletions tests/App/Jobs/FetchCollectionOwnersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@
use App\Models\Collection;
use App\Models\Network;
use App\Support\Facades\Mnemonic;
use Illuminate\Support\Facades\Http;

it('should fetch nft collection owners', function () {
Mnemonic::fake([
'https://polygon-rest.api.mnemonichq.com/collections/v1beta2/*/metadata?includeStats=1' => Http::response([
'ownersCount' => '789',
], 200),
]);
Mnemonic::shouldReceive('getCollectionOwners')->andReturn(789);

$network = Network::polygon();

Expand All @@ -34,11 +29,7 @@
});

it('should handle null owner count', function () {
Mnemonic::fake([
'https://polygon-rest.api.mnemonichq.com/collections/v1beta2/*/metadata?includeStats=1' => Http::response([
'ownersCount' => null,
], 200),
]);
Mnemonic::shouldReceive('getCollectionOwners')->andReturn(0);

$network = Network::polygon();

Expand All @@ -55,7 +46,7 @@

$collection->refresh();

expect($collection->owners)->toBeNull();
expect($collection->owners)->toBe(0);
});

it('has a unique ID', function () {
Expand Down
Loading