Skip to content

Commit

Permalink
refactor: do not use deprecated mnemonic APIs (#632)
Browse files Browse the repository at this point in the history
  • Loading branch information
crnkovic authored Jan 30, 2024
1 parent bb80962 commit 2b5d63b
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 75 deletions.
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

0 comments on commit 2b5d63b

Please sign in to comment.