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

Fix NFTs not being displayed in the APP #537

Merged
merged 2 commits into from
Oct 14, 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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ This document logs notable, developer-facing updates to the NEAR Mobile Wallet.
- Add `app version` in settings [feat/add-versions](https://github.com/Peersyst/near-mobile-wallet/pull/536)
- Add actions in main app menu in [feat/main-button](https://github.com/Peersyst/near-mobile-wallet/pull/535)
- Refactor explore dApps tab [refactor/explore-dapp](https://github.com/Peersyst/near-mobile-wallet/pull/533)

### 🐛 Bug Fixes

- Fix NFTs not being displayed in the APP [fix/nft-not-being-displayed](https://github.com/Peersyst/near-mobile-wallet/pull/537)
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const NFT_CARD_WIDTH = 112;

export const NftImageRoot = styled(Image)<NftImageProps>(({ theme: { palette: p, borderRadiusXs } }) => ({
borderRadius: borderRadiusXs,
backgroundColor: p.gray[300],
backgroundColor: p.gray[100],
width: NFT_CARD_WIDTH,
height: NFT_CARD_WIDTH,
objectFit: "cover",
Expand Down
118 changes: 94 additions & 24 deletions src/module/sdk/NearSdkService/NearSdkService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
CreateNearSdkWithMnemonicParams,
CreateNearSdkWithSecretKeyParams,
Action,
NftTokenMetadata,
} from "./NearSdkService.types";
import {
MINIMUM_UNSTAKED,
Expand Down Expand Up @@ -57,6 +58,8 @@ import {
NFT_OWNER_TOKENS_SET_METHOD,
STAKING_WITHDRAW_GAS,
STAKING_WITHDRAW_ALL_GAS,
NFT_GET_TOKENS_BY_OWNER,
GET_TOKEN_METADATA_METHOD,
} from "../utils/near.constants";
import {
addNearAmounts,
Expand Down Expand Up @@ -930,11 +933,31 @@ export class NearSDKService {
// User has nfts of contract
async getNftTokensAmount(contractId: string): Promise<number> {
const account = await this.getAccount();
return account.viewFunction({
contractId,
methodName: NFT_SUPPLY_METHOD,
args: { account_id: account.accountId },
});
try {
return await account.viewFunction({
contractId,
methodName: NFT_SUPPLY_METHOD,
args: { account_id: account.accountId },
});
} catch (err: any) {
if (!err.toString().includes("Contract method is not found")) {
throw err;
}
try {
// example contract: mintv2.sharddog.near
const nftsIds = await account.viewFunction({
contractId,
methodName: NFT_GET_TOKENS_BY_OWNER,
args: { account_id: account.accountId },
});

if (Array.isArray(nftsIds)) {
return nftsIds.length;
}
} catch {}

return 0;
}
}

async getNftMetadata(contractId: string): Promise<NftMetadata> {
Expand All @@ -947,18 +970,34 @@ export class NearSDKService {
}

// Mintbase non-standard method
private async getNftTokenMetadata(contractId: string, tokenId: string, baseUri: string): Promise<NftMetadata> {
private async getNftTokenMetadata(contractId: string, tokenId: string, baseUri: string): Promise<NftTokenMetadata> {
const account = await this.getAccount();
let metadata = await account.viewFunction({
contractId,
methodName: NFT_TOKEN_METADATA_METHOD,
args: { token_id: tokenId },
});
let metadata;

try {
metadata = await account.viewFunction({
contractId,
methodName: NFT_TOKEN_METADATA_METHOD,
args: { token_id: tokenId },
});

if (!metadata.media && metadata.reference) {
if (!(metadata as NftMetadata).media && (metadata as NftMetadata).reference) {
try {
metadata = await (await fetch(`${baseUri}/${(metadata as NftMetadata).reference}`)).json();
} catch {}
}
} catch (err: any) {
if (!err.toString().includes("Contract method is not found")) {
throw err;
}
try {
metadata = await (await fetch(`${baseUri}/${metadata.reference}`)).json();
} catch {}
// example contract: mintv2.sharddog.near
return await account.viewFunction({
contractId,
methodName: GET_TOKEN_METADATA_METHOD,
args: { token_id: Number(tokenId) }, // We need to cast toa number here to avoid smart contract type issues
});
} catch (e) {}
}

return metadata;
Expand All @@ -984,6 +1023,7 @@ export class NearSDKService {
}

const media = token.metadata.media;

if (media && media.includes("://")) {
token.metadata.media_url = media;
token.metadata.media = null;
Expand All @@ -994,6 +1034,22 @@ export class NearSDKService {
token.metadata.media = null;
}

if (!token.metadata.media_url) {
const reference = token.metadata.reference;

if (reference) {
if (reference.includes("://")) {
token.metadata.media_url = reference;
token.metadata.media = null;
}
if (!reference.includes("://") && !reference.startsWith("data:image")) {
const url = baseUri ? `${baseUri}/${reference}` : `https://cloudflare-ipfs.com/ipfs/${reference}`;
token.metadata.media_url = url;
token.metadata.media = null;
}
}
}

return token;
}

Expand All @@ -1016,11 +1072,24 @@ export class NearSDKService {
const account = await this.getAccount();
let tokens: NftToken[] = [];
try {
const tokenIds = await account.viewFunction({
contractId,
methodName: NFT_OWNER_TOKENS_SET_METHOD,
args: { account_id: account.accountId },
});
let tokenIds;
try {
tokenIds = await account.viewFunction({
contractId,
methodName: NFT_OWNER_TOKENS_SET_METHOD,
args: { account_id: account.accountId },
});
} catch (err: any) {
if (!err.toString().includes("Contract method is not found")) {
throw err;
}
tokenIds = await account.viewFunction({
contractId,
methodName: NFT_GET_TOKENS_BY_OWNER,
args: { account_id: account.accountId },
});
}

tokens = await Promise.all(
tokenIds.map(async (tokenId: number | string) => ({
token_id: tokenId.toString(),
Expand All @@ -1029,7 +1098,7 @@ export class NearSDKService {
})),
);
} catch (err: any) {
if (!err.toString().includes("MethodResolveError(MethodNotFound)")) {
if (!err.toString().includes("Contract method is not found")) {
throw err;
}
tokens = await account.viewFunction({
Expand All @@ -1038,6 +1107,7 @@ export class NearSDKService {
args: { account_id: account.accountId },
});
}

const parsedTokens = tokens.map((token: any) => this.parseNftToken(token, contractId, baseUri));
return Promise.all(parsedTokens);
}
Expand All @@ -1050,9 +1120,9 @@ export class NearSDKService {
let contractNfts = 0;
try {
contractNfts = await this.getNftTokensAmount(contractId);
} catch {
} catch (e) {
// eslint-disable-next-line no-console
console.warn("Error getting nft amount for contract", contractId);
console.warn("Error getting nft amount for contract " + contractId, e);
}

if (contractNfts > 0) {
Expand All @@ -1062,9 +1132,9 @@ export class NearSDKService {
nftTokens.push(
...newNftTokens.map((token: NftToken) => ({ ...token, collection_metadata: collectionMetadata, contractId })),
);
} catch {
} catch (e) {
// eslint-disable-next-line no-console
console.warn("Error getting nft tokens for contract", contractId);
console.warn("Error getting nft tokens for contract " + contractId, e);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/module/sdk/utils/near.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export const NFT_TRANSFER_METHOD = "nft_transfer";
export const NFT_METADATA_METHOD = "nft_metadata";
export const NFT_TOKEN_METHOD = "nft_token";
export const NFT_TOKEN_METADATA_METHOD = "nft_token_metadata";
export const GET_TOKEN_METADATA_METHOD = "get_token_metadata";
export const NFT_SUPPLY_METHOD = "nft_supply_for_owner";
export const NFT_GET_TOKENS_BY_OWNER = "get_tokens_by_owner";
export const NFT_OWNER_TOKENS_METHOD = "nft_tokens_for_owner";
export const NFT_OWNER_TOKENS_SET_METHOD = "nft_tokens_for_owner_set";
//Fungible token
Expand Down
Loading