Skip to content

Commit

Permalink
Merge branch '772-third-party-nfts-are-not-foud-when-metamaks-is-not-…
Browse files Browse the repository at this point in the history
…in-the-same-network' of https://github.com/telosnetwork/telos-wallet into 764-mp4-nft-artwork-not-showing-correctly
  • Loading branch information
Viterbo committed Feb 14, 2024
2 parents 8e41416 + 4324ff8 commit 9d4d615
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 31 deletions.
21 changes: 19 additions & 2 deletions src/antelope/chains/EVMChainSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { dateIsWithinXMinutes } from 'src/antelope/stores/utils/date-utils';
import { CURRENT_CONTEXT, getAntelope, useContractStore, useNftsStore } from 'src/antelope';
import { WEI_PRECISION, PRICE_UPDATE_INTERVAL_IN_MIN } from 'src/antelope/stores/utils';
import { BehaviorSubject, filter } from 'rxjs';
import { createTraceFunction } from 'src/antelope/config';


export default abstract class EVMChainSettings implements ChainSettings {
Expand Down Expand Up @@ -97,6 +98,9 @@ export default abstract class EVMChainSettings implements ChainSettings {
// This observable is used to check if the indexer health state was already checked
indexerChecked$ = new BehaviorSubject(false);

// This function is used to trace the execution of the code
trace = createTraceFunction('EVMChainSettings');

simulateIndexerDown(isBad: boolean) {
this.indexerBadHealthSimulated = isBad;
}
Expand Down Expand Up @@ -152,6 +156,7 @@ export default abstract class EVMChainSettings implements ChainSettings {
}

async init(): Promise<void> {
this.trace('init');
// this is called only when this chain is needed to avoid initialization of all chains
if (this.ready) {
return this.initPromise;
Expand Down Expand Up @@ -302,6 +307,7 @@ export default abstract class EVMChainSettings implements ChainSettings {
}

async getBalances(account: string): Promise<TokenBalance[]> {
this.trace('getBalances', account);
if (!this.hasIndexerSupport()) {
console.error('Indexer API not supported for this chain:', this.getNetwork());
return [];
Expand Down Expand Up @@ -366,6 +372,7 @@ export default abstract class EVMChainSettings implements ChainSettings {

// get the NFTs belonging to a particular contract (collection)
async getNftsForCollection(collection: string, params: IndexerCollectionNftsFilter): Promise<Collectible[]> {
this.trace('getNftsForCollection', collection, params);
if (!this.hasIndexerSupport()) {
console.error('Error fetching NFTs, Indexer API not supported for this chain:', this.getNetwork());
return [];
Expand All @@ -384,6 +391,7 @@ export default abstract class EVMChainSettings implements ChainSettings {
supply: nftResponse.supply,
owner: nftResponse.owner,
}));
this.trace('getNftsForCollection', { shapedIndexerNftData, response });

// we fix the supportedInterfaces property if it is undefined in the response but present in the request
Object.values(response.contracts).forEach((contract) => {
Expand All @@ -392,7 +400,10 @@ export default abstract class EVMChainSettings implements ChainSettings {

this.processNftContractsCalldata(response.contracts);
const shapedNftData = this.shapeNftRawData(shapedIndexerNftData, response.contracts);
return this.processNftRawData(shapedNftData);
this.trace('getNftsForCollection', { shapedNftData });
const finalNftData = this.processNftRawData(shapedNftData);
this.trace('getNftsForCollection', { finalNftData });
return finalNftData;
}

// get the NFTs belonging to a particular account
Expand Down Expand Up @@ -471,6 +482,7 @@ export default abstract class EVMChainSettings implements ChainSettings {

// process the shaped raw data into NFTs
async processNftRawData(shapedRawNfts: NftRawData[]): Promise<Collectible[]> {
this.trace('processNftRawData', shapedRawNfts);
const contractStore = useContractStore();
const nftsStore = useNftsStore();

Expand Down Expand Up @@ -502,6 +514,7 @@ export default abstract class EVMChainSettings implements ChainSettings {

return nft;
});
this.trace('processNftRawData', 'erc1155Nfts', erc1155Nfts);

const erc721RawData = shapedRawNfts.filter(({ contract }) => contract.supportedInterfaces.includes('erc721'));
const erc721Nfts = erc721RawData.map(async ({ data, contract }) => {
Expand All @@ -519,6 +532,7 @@ export default abstract class EVMChainSettings implements ChainSettings {

return nft;
});
this.trace('processNftRawData', 'erc721Nfts', erc721Nfts);

const settledPromises = await Promise.allSettled([...erc1155Nfts, ...erc721Nfts]);

Expand All @@ -529,7 +543,10 @@ export default abstract class EVMChainSettings implements ChainSettings {
console.error('Error constructing NFT', reason);
});

return fulfilledPromises.map(result => result.value as Collectible);
const nfts = fulfilledPromises.map(result => result.value as Collectible);
this.trace('processNftRawData', 'nfts', nfts);

return nfts;
}

constructTokenId(token: TokenSourceInfo): string {
Expand Down
2 changes: 1 addition & 1 deletion src/antelope/chains/evm/telos-evm-testnet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export default class TelosEVMTestnet extends EVMChainSettings {
}

getBuyMoreOfTokenLink(): string {
return 'https://telos.net/ecosystem?category=Exchanges';
return 'https://app.telos.net/testnet/evm-faucet';
}

getSystemTokens(): TokenClass[] {
Expand Down
2 changes: 1 addition & 1 deletion src/antelope/chains/evm/telos-evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export default class TelosEVMTestnet extends EVMChainSettings {
}

getBuyMoreOfTokenLink(): string {
return 'https://telos.net/ecosystem?category=Exchanges';
return 'https://www.telos.net/buy';
}

getSystemTokens(): TokenClass[] {
Expand Down
4 changes: 4 additions & 0 deletions src/antelope/stores/nfts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ export const useNftsStore = defineStore(store_name, {
tokenId,
type,
};
this.trace('fetchNftDetails', 'filter:', new_filter);

// If we already have a contract for that network and contract, we search for the NFT in that list first
this.__contracts[network] = this.__contracts[network] || {};
Expand All @@ -246,6 +247,7 @@ export const useNftsStore = defineStore(store_name, {
nft => nft.contractAddress.toLowerCase() === contract.toLowerCase() && nft.id === tokenId,
);
if (nft) {
this.trace('fetchNftDetails', 'found in cache:', nft);
return nft;
}
} else {
Expand All @@ -260,6 +262,7 @@ export const useNftsStore = defineStore(store_name, {
// we don't have the NFT on any cache, we fetch it from the indexer
useFeedbackStore().setLoading('updateNFTsForAccount');
if (chain.settings.isNative() || (chain.settings as EVMChainSettings).hasIndexerSupport()) {
this.trace('fetchNftDetails', 'fetching from indexer');
promise = chain.settings.getNftsForCollection(contract, new_filter).then((nfts) => {
const contractLower = contract.toLowerCase();

Expand All @@ -273,6 +276,7 @@ export const useNftsStore = defineStore(store_name, {
if (!chain.settings.isNative()) {
// this means we have the indexer down
// we have the contract and the address so we try to fetch the NFT from the contract
this.trace('fetchNftDetails', 'indexer down, fetching from contract');
useEVMStore().getNFT(
contract,
tokenId,
Expand Down
9 changes: 9 additions & 0 deletions src/antelope/types/NFTClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import { CURRENT_CONTEXT, useAccountStore, useChainStore } from 'src/antelope';
import { AxiosInstance } from 'axios';
import { Contract, ethers } from 'ethers';
import { AntelopeError } from 'src/antelope/types';
import { createTraceFunction } from 'src/antelope/config';

// This function is used to trace the execution of the code
const trace = createTraceFunction('NFTClass');

export interface NftAttribute {
label: string;
Expand Down Expand Up @@ -106,6 +110,7 @@ export async function constructNft(
contractStore: ReturnType<typeof useContractStore>,
nftStore: ReturnType<typeof useNftsStore>,
): Promise<Erc721Nft | Erc1155Nft> {
trace('constructNft', { contract, indexerData, chainSettings, contractStore, nftStore });
const network = chainSettings.getNetwork();

const isErc721 = contract.supportedInterfaces.includes('erc721');
Expand All @@ -118,6 +123,7 @@ export async function constructNft(
const cachedNft = nftStore.__contracts[network]?.[contract.address]?.list.find(nft => nft.id === indexerData.tokenId);

if (cachedNft) {
trace('constructNft', 'contract found in cache');
await cachedNft.updateOwnerData();
return cachedNft;
}
Expand Down Expand Up @@ -146,6 +152,7 @@ export async function constructNft(
indexerData.metadata.image = ((indexerData.metadata.image as string) ?? '').replace('ipfs://', IPFS_GATEWAY);

const { image, mediaType, mediaSource } = await extractNftMetadata(indexerData.imageCache ?? '', indexerData.tokenUri ?? '', indexerData.metadata ?? {});
trace('constructNft', 'extracted metadata:', { image, mediaType, mediaSource });
const commonData: NftPrecursorData = {
name: (indexerData.metadata?.name ?? '') as string,
id: indexerData.tokenId,
Expand All @@ -166,6 +173,7 @@ export async function constructNft(
const contractInstance = await (await contractStore.getContract(CURRENT_CONTEXT, contract.address, 'erc721'))?.getContractInstance();

if (!contractInstance) {
console.error('Error getting contract instance');
throw new AntelopeError('antelope.utils.error_contract_instance');
}

Expand Down Expand Up @@ -286,6 +294,7 @@ export class Erc721Nft extends NFT {
}

async updateOwnerData(): Promise<void> {
trace('Erc721Nft.updateOwnerData', { contract: this.contract, id: this.id });
const contract = await useContractStore().getContract(CURRENT_CONTEXT, this.contractAddress);
const contractInstance = await contract?.getContractInstance();

Expand Down
26 changes: 2 additions & 24 deletions src/antelope/wallets/AntelopeWallets.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { EVMAuthenticator } from 'src/antelope/wallets/authenticators/EVMAuthenticator';
import { useAccountStore } from 'src/antelope/stores/account';
import { CURRENT_CONTEXT, useChainStore } from 'src/antelope';
import { RpcEndpoint } from 'universal-authenticator-library';
import { ethers } from 'ethers';
Expand Down Expand Up @@ -35,31 +34,10 @@ export class AntelopeWallets {
return (useChainStore().getChain(label).settings as EVMChainSettings);
}

async getWeb3Provider(): Promise<ethers.providers.Web3Provider> {
async getWeb3Provider(label = CURRENT_CONTEXT): Promise<ethers.providers.Web3Provider> {
this.trace('getWeb3Provider');
const account = useAccountStore().getAccount(CURRENT_CONTEXT);
try {
// we try first the best solution which is taking the provider from the current authenticator
const authenticator = account.authenticator as EVMAuthenticator;
const provider = authenticator.web3Provider();
return provider;
} catch(e1) {
this.trace('getWeb3Provider authenticator.web3Provider() Failed!', e1);
}

// we try to build a web3 provider from a local injected provider it it exists
try {
if (window.ethereum) {
const web3Provider = new ethers.providers.Web3Provider(window.ethereum);
await web3Provider.ready;
return web3Provider;
}
} catch(e2) {
this.trace('getWeb3Provider authenticator.web3Provider() Failed!', e2);
}

try {
const p:RpcEndpoint = this.getChainSettings(CURRENT_CONTEXT).getRPCEndpoint();
const p:RpcEndpoint = this.getChainSettings(label).getRPCEndpoint();
const url = `${p.protocol}://${p.host}:${p.port}${p.path ?? ''}`;
const jsonRpcProvider = new ethers.providers.JsonRpcProvider(url);
await jsonRpcProvider.ready;
Expand Down
2 changes: 1 addition & 1 deletion src/pages/native/BalanceInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import WithdrawEVM from '~/pages/native/balance/WithdrawEVM';
import RexStaking from '~/pages/native/balance/RexStaking';
import { copyToClipboard } from 'quasar';
const GETTING_STARTED_URL = 'https://telos.net/ecosystem?category=Exchanges';
const GETTING_STARTED_URL = 'https://www.telos.net/buy';
export default {
props: ['loadedCoins', 'loadedNftTokens', 'balanceTab'],
Expand Down
2 changes: 1 addition & 1 deletion src/pages/native/balance/CoinHistory.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { mapGetters } from 'vuex';
import tokenAvatar from 'components/native/TokenAvatar.vue';
const GETTING_STARTED_URL = 'https://www.telos.net/#getting-started';
const GETTING_STARTED_URL = 'https://www.telos.net/buy';
export default {
components: {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/native/balance/CoinInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { mapGetters, mapActions } from 'vuex';
import tokenAvatar from 'components/native/TokenAvatar.vue';
const GETTING_STARTED_URL = 'https://www.telos.net/#getting-started';
const GETTING_STARTED_URL = 'https://www.telos.net/buy';
export default {
components: {
Expand Down

0 comments on commit 9d4d615

Please sign in to comment.