Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.

Commit c9f6936

Browse files
authored
feat: use OpenSea for fetching NFTs (#331)
* feat: use OpenSea for fetching NFTs * feat: truncate long NFT names * test: update tests * feat: force same aspect for all NFTs
1 parent b89345d commit c9f6936

File tree

6 files changed

+42
-48
lines changed

6 files changed

+42
-48
lines changed

src/components/Block/NftPicker.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ const filteredNfts = computed(() =>
3838
class="block px-3 py-1 mb-3 hover:opacity-80 transition-opacity"
3939
@click="emit('pick', nft.id)"
4040
>
41-
<NftPreview :item="nft" class="aspect-square rounded" />
42-
<div class="mt-2 text-sm">{{ nft.displayTitle }}</div>
41+
<NftPreview :item="nft" class="aspect-square rounded w-full" />
42+
<div class="mt-2 text-sm truncate">{{ nft.displayTitle }}</div>
4343
</a>
4444
</div>
4545
</template>

src/components/Modal/SendNft.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ watch(
138138
class="mr-2"
139139
:size="20"
140140
/>
141-
{{ currentNft?.displayTitle || 'Select NFT' }}
141+
<div class="truncate">
142+
{{ currentNft?.displayTitle || 'Select NFT' }}
143+
</div>
142144
</div>
143145
</button>
144146
</div>

src/components/NftPreview.vue

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
<script setup>
2+
import { computed } from 'vue';
3+
24
const props = defineProps({
35
item: Object,
46
size: Number
57
});
68
7-
function handleError(e) {
8-
const size = props.size ? props.size * 2 : 256;
9+
const fallbackUrl = computed(
10+
() =>
11+
`https://cdn.stamp.fyi/token/${props.item.contractAddress}?s=${
12+
props.size ? props.size * 2 : 256
13+
}`
14+
);
15+
const url = computed(() => props.item.image || fallbackUrl.value);
916
10-
e.target.src = `https://cdn.stamp.fyi/token/${props.item.contract_address}?s=${size}`;
17+
function handleError(e) {
18+
e.target.src = fallbackUrl.value;
1119
}
1220
</script>
1321

1422
<template>
1523
<img
16-
:src="item.image"
24+
:src="url"
1725
class="aspect-square rounded"
1826
:style="
1927
size

src/composables/useNfts.ts

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ref, computed, Ref } from 'vue';
22
import snapshot from '@snapshot-labs/snapshot.js';
33

4-
const SUPPORTED_ABIS = ['erc721', 'erc1155'];
4+
const SUPPORTED_ABIS = ['ERC721', 'ERC1155'];
55

66
const nfts: Ref<any[]> = ref([]);
77
const loading = ref(true);
@@ -10,42 +10,32 @@ const loaded = ref(false);
1010
export function useNfts() {
1111
async function loadNfts(address) {
1212
loading.value = true;
13-
const key = 'ckey_2d082caf47f04a46947f4f212a8';
14-
const url = `https://api.covalenthq.com/v1/1/address/${address}/balances_v2/?quote-currency=USD&format=JSON&nft=true&key=${key}`;
15-
const results = await snapshot.utils.getJSON(url);
16-
nfts.value = results.data.items
17-
.filter(
18-
item =>
19-
item.type === 'nft' &&
20-
item.nft_data &&
21-
item.supports_erc?.some(itemErc => SUPPORTED_ABIS.includes(itemErc))
13+
14+
const url =
15+
'https://testnets-api.opensea.io/api/v1/assets?owner=0x0000000000000000000000000000000000000000&order_direction=desc&offset=0&limit=20&include_orders=false';
16+
const { assets } = await snapshot.utils.getJSON(url);
17+
18+
nfts.value = assets
19+
.filter(asset =>
20+
SUPPORTED_ABIS.includes(asset.asset_contract?.schema_name)
2221
)
23-
.map(item => {
24-
const type = item.supports_erc?.find(itemErc =>
25-
SUPPORTED_ABIS.includes(itemErc)
26-
);
27-
const tokenId = item.nft_data[0]?.token_id;
28-
const title =
29-
item.nft_data[0]?.external_data?.name ??
30-
item.contract_name ??
31-
'Untitled';
22+
.map(asset => {
23+
const tokenId = asset.token_id;
24+
const title = asset.name ?? 'Untitled';
3225
const displayTitle =
3326
title.match(/(#[0-9]+)$/) || !tokenId
3427
? title
3528
: `${title} #${tokenId}`;
3629

37-
const image =
38-
item?.nft_data[0]?.external_data.image ??
39-
`https://cdn.stamp.fyi/token/${item.contract_address}?s=256`;
40-
4130
return {
42-
...item,
43-
id: `${item.contract_address}:${tokenId || 0}`,
44-
type,
31+
...asset,
32+
type: asset.asset_contract.schema_name.toLowerCase(),
4533
tokenId,
4634
title,
4735
displayTitle,
48-
image
36+
image: asset.image_url,
37+
collectionName: asset.collection.name,
38+
contractAddress: asset.asset_contract.address
4939
};
5040
});
5141
loading.value = false;

src/helpers/__tests__/transactions.test.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,16 @@ describe('transactions', () => {
4444

4545
describe('createSendNftTransaction', () => {
4646
const erc721Nft = {
47-
contract_decimals: 0,
48-
contract_name: 'BekoNekoz VX',
49-
contract_address: '0x9ed9dc8af51d74e638528ececd510dca5fe2a539',
47+
collectionName: 'BekoNekoz VX',
48+
contractAddress: '0x9ed9dc8af51d74e638528ececd510dca5fe2a539',
5049
type: 'erc721',
5150
id: '0x9ed9dc8af51d74e638528ececd510dca5fe2a539:162',
5251
tokenId: '162'
5352
};
5453

5554
const erc1155Nft = {
56-
contract_decimals: 0,
57-
contract_name: 'OpenSea Shared Storefront',
58-
contract_ticker_symbol: 'OPENSTORE',
59-
contract_address: '0x495f947276749ce646f68ac8c248420045cb7b5e',
55+
collectionName: 'OpenSea Shared Storefront',
56+
contractAddress: '0x495f947276749ce646f68ac8c248420045cb7b5e',
6057
type: 'erc1155',
6158
id: '0x495f947276749ce646f68ac8c248420045cb7b5e:90408759670418442924295527194769699607350667425091321551161727238095924887553',
6259
tokenId:

src/helpers/transactions.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,7 @@ export function createSendNftTransaction({
5959
}): SendNftTransaction {
6060
let data = '';
6161

62-
const baseAmount = parseUnits(
63-
form.amount.toString() || '1',
64-
nft.contract_decimals
65-
);
62+
const baseAmount = parseUnits(form.amount.toString() || '1', 0);
6663

6764
if (nft.type === 'erc1155') {
6865
const iface = new Interface(abis.erc1155);
@@ -90,13 +87,13 @@ export function createSendNftTransaction({
9087
recipient: form.to,
9188
amount: baseAmount.toString(),
9289
nft: {
93-
address: nft.contract_address,
90+
address: nft.contractAddress,
9491
id: nft.tokenId,
9592
name: nft.title,
96-
collection: nft.contract_name
93+
collection: nft.collectionName
9794
}
9895
},
99-
to: nft.contract_address,
96+
to: nft.contractAddress,
10097
data,
10198
value: '0'
10299
};

0 commit comments

Comments
 (0)