@xyo-network/crypto-nft-witness-wallet-plugin 2.77.19 → 2.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAqB1F"}
1
+ {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAwB1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAqB1F"}
1
+ {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAwB1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAqB1F"}
1
+ {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAwB1F"}
@@ -159,11 +159,15 @@ var CryptoWalletNftWitness = class extends import_abstract_witness.AbstractWitne
159
159
  ).toString();
160
160
  const chainId = (0, import_assert2.assertEx)(query?.chainId || this.config.chainId, "params.chainId is required");
161
161
  const maxNfts = query?.maxNfts || defaultMaxNfts;
162
- const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout);
163
- const observation = nfts.map((nft) => {
164
- return { ...nft, schema };
165
- });
166
- return observation;
162
+ try {
163
+ const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout);
164
+ const observation = nfts.map((nft) => {
165
+ return { ...nft, schema };
166
+ });
167
+ return observation;
168
+ } catch (error) {
169
+ throw new Error(`Failed to get nfts for address ${address} on chainId ${chainId}`);
170
+ }
167
171
  })
168
172
  );
169
173
  return observations.flat();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/getNftsOwnedByAddress.ts","../../src/lib/getInfuraProvider.ts"],"sourcesContent":["import { CryptoWalletNftWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoWalletNftWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoWalletNftWitnessPlugin\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoWalletNftWitness } from './Witness'\n\nexport const CryptoWalletNftWitnessPlugin = () =>\n createPayloadSetWitnessPlugin<CryptoWalletNftWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoWalletNftWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { AbstractWitness } from '@xyo-network/abstract-witness'\nimport {\n CryptoWalletNftWitnessConfig,\n isNftWitnessQuery,\n NftInfo,\n NftSchema,\n NftWitnessConfigSchema,\n NftWitnessQuery,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { WitnessParams } from '@xyo-network/witness-model'\n\nimport { getNftsOwnedByAddress } from './lib'\n\nexport type CryptoWalletNftWitnessParams = WitnessParams<AnyConfigSchema<CryptoWalletNftWitnessConfig>>\n\nconst schema = NftSchema\n\nconst defaultMaxNfts = 100\n\nexport class CryptoWalletNftWitness<TParams extends CryptoWalletNftWitnessParams = CryptoWalletNftWitnessParams> extends AbstractWitness<\n TParams,\n NftWitnessQuery,\n NftInfo\n> {\n static override configSchemas = [NftWitnessConfigSchema]\n\n get timeout() {\n return this.config.timeout ?? 2000\n }\n\n protected override async observeHandler(payloads?: NftWitnessQuery[]): Promise<NftInfo[]> {\n await this.started('throw')\n const queries = payloads?.filter(isNftWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map(async (query) => {\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout)\n const observation = nfts.map<NftInfo>((nft) => {\n return { ...nft, schema }\n })\n return observation\n }),\n )\n\n return observations.flat()\n }\n}\n","import { Auth, SDK } from '@infura/sdk'\nimport { AxiosJson } from '@xyo-network/axios'\nimport { NftInfoFields, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155__factory } from '@xyo-network/open-zeppelin-typechain'\n\nimport { getInfuraProvider } from './getInfuraProvider'\n\ntype PublicAddressOptions = {\n cursor?: string\n includeMetadata?: boolean\n publicAddress: string\n tokenAddresses?: string[]\n}\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\n/**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\nexport const checkIpfsUrl = (urlToCheck: string, ipfsGateway: string) => {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = ipfsGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n}\n\nexport const getErc721MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC721__factory.connect(address, getInfuraProvider())\n return [await contract.tokenURI(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getErc1155MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC1155__factory.connect(address, getInfuraProvider())\n return [await contract.uri(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getNftMetadataUri = async (address: string, tokenId: string) => {\n const results = await Promise.all([getErc721MetadataUri(address, tokenId), getErc1155MetadataUri(address, tokenId)])\n return results[0][0] ?? results[1][0]\n}\n\nexport const getNftsOwnedByAddress = async (\n /** @param publicAddress The address of the wallet to search for NFTs */\n publicAddress: string,\n /** @param chainId The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on */\n chainId: number,\n /** @param privateKey The private key of the wallet to use to search for NFTs */\n privateKey: string,\n /** @param maxNfts The maximum number of NFTs to return. Configurable to prevent large wallets from exhausting Infura API credits. */\n maxNfts = 1000,\n /** @param httpTimeout The connection timeout for http call to get metadata */\n timeout = 2000,\n): Promise<NftInfoFields[]> => {\n const sdk = new SDK(new Auth({ chainId, privateKey, projectId: process.env.INFURA_PROJECT_ID, secretId: process.env.INFURA_PROJECT_SECRET }))\n const nfts: NftInfoFields[] = []\n const axios = new AxiosJson()\n let cursor: string | undefined = undefined\n do {\n const opts: PublicAddressOptions = { cursor, includeMetadata: true, publicAddress }\n const { cursor: nextCursor, pageSize, total, assets } = await sdk.api.getNFTs(opts)\n const batch: NftInfoFields[] = assets.slice(0, Math.min(pageSize, total - nfts.length)).map((asset) => {\n const { contract: address, type: tokenType, ...rest } = asset\n const type = toTokenType(tokenType)\n return { address, chainId, type, ...rest }\n })\n nfts.push(...batch)\n cursor = nextCursor\n if (nfts.length >= total || !cursor) break\n } while (nfts.length < maxNfts)\n\n return await Promise.all(\n nfts.map(async (nft) => {\n const metaDataUri = await getNftMetadataUri(nft.address, nft.tokenId)\n if (metaDataUri) {\n nft.metaDataUri = metaDataUri\n const cookedUri = checkIpfsUrl(metaDataUri, ipfsGateway)\n try {\n nft.metadata = (await axios.get(cookedUri, { timeout }))?.data\n } catch (ex) {\n console.log(`failed to get NTF metadata [${cookedUri}] [${ex}]`)\n }\n } else {\n console.log('failed to get NTF metadata URI')\n }\n return nft\n }),\n )\n}\n","import { InfuraProvider, Provider } from '@ethersproject/providers'\nimport { assertEx } from '@xylabs/assert'\n\nexport interface InfuraProviderConfig {\n projectId: string\n projectSecret: string\n}\n\nlet instance: InfuraProvider | undefined = undefined\n\nexport const getInfuraProvider = (): Provider => {\n if (instance) return instance\n const config = getInfuraProviderConfig()\n instance = new InfuraProvider('homestead', config)\n return instance\n}\n\nexport const canUseInfuraProvider = (): boolean => {\n return !!process.env.INFURA_PROJECT_ID && !!process.env.INFURA_PROJECT_SECRET ? true : false\n}\n\nexport const getInfuraProviderConfig = (): InfuraProviderConfig => {\n const projectId = assertEx(process.env.INFURA_PROJECT_ID, 'Missing INFURA_PROJECT_ID ENV VAR')\n const projectSecret = assertEx(process.env.INFURA_PROJECT_SECRET, 'Missing INFURA_PROJECT_SECRET ENV VAR')\n return { projectId, projectSecret }\n}\n"],"mappings":"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","names":["import_crypto_nft_payload_plugin","import_assert","import_crypto_nft_payload_plugin","ipfsGateway"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/getNftsOwnedByAddress.ts","../../src/lib/getInfuraProvider.ts"],"sourcesContent":["import { CryptoWalletNftWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoWalletNftWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoWalletNftWitnessPlugin\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoWalletNftWitness } from './Witness'\n\nexport const CryptoWalletNftWitnessPlugin = () =>\n createPayloadSetWitnessPlugin<CryptoWalletNftWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoWalletNftWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { AbstractWitness } from '@xyo-network/abstract-witness'\nimport {\n CryptoWalletNftWitnessConfig,\n isNftWitnessQuery,\n NftInfo,\n NftSchema,\n NftWitnessConfigSchema,\n NftWitnessQuery,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { WitnessParams } from '@xyo-network/witness-model'\n\nimport { getNftsOwnedByAddress } from './lib'\n\nexport type CryptoWalletNftWitnessParams = WitnessParams<AnyConfigSchema<CryptoWalletNftWitnessConfig>>\n\nconst schema = NftSchema\n\nconst defaultMaxNfts = 100\n\nexport class CryptoWalletNftWitness<TParams extends CryptoWalletNftWitnessParams = CryptoWalletNftWitnessParams> extends AbstractWitness<\n TParams,\n NftWitnessQuery,\n NftInfo\n> {\n static override configSchemas = [NftWitnessConfigSchema]\n\n get timeout() {\n return this.config.timeout ?? 2000\n }\n\n protected override async observeHandler(payloads?: NftWitnessQuery[]): Promise<NftInfo[]> {\n await this.started('throw')\n const queries = payloads?.filter(isNftWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map(async (query) => {\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const maxNfts = query?.maxNfts || defaultMaxNfts\n try {\n const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout)\n const observation = nfts.map<NftInfo>((nft) => {\n return { ...nft, schema }\n })\n return observation\n } catch (error) {\n throw new Error(`Failed to get nfts for address ${address} on chainId ${chainId}`)\n }\n }),\n )\n return observations.flat()\n }\n}\n","import { Auth, SDK } from '@infura/sdk'\nimport { AxiosJson } from '@xyo-network/axios'\nimport { NftInfoFields, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155__factory } from '@xyo-network/open-zeppelin-typechain'\n\nimport { getInfuraProvider } from './getInfuraProvider'\n\ntype PublicAddressOptions = {\n cursor?: string\n includeMetadata?: boolean\n publicAddress: string\n tokenAddresses?: string[]\n}\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\n/**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\nexport const checkIpfsUrl = (urlToCheck: string, ipfsGateway: string) => {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = ipfsGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n}\n\nexport const getErc721MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC721__factory.connect(address, getInfuraProvider())\n return [await contract.tokenURI(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getErc1155MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC1155__factory.connect(address, getInfuraProvider())\n return [await contract.uri(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getNftMetadataUri = async (address: string, tokenId: string) => {\n const results = await Promise.all([getErc721MetadataUri(address, tokenId), getErc1155MetadataUri(address, tokenId)])\n return results[0][0] ?? results[1][0]\n}\n\nexport const getNftsOwnedByAddress = async (\n /** @param publicAddress The address of the wallet to search for NFTs */\n publicAddress: string,\n /** @param chainId The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on */\n chainId: number,\n /** @param privateKey The private key of the wallet to use to search for NFTs */\n privateKey: string,\n /** @param maxNfts The maximum number of NFTs to return. Configurable to prevent large wallets from exhausting Infura API credits. */\n maxNfts = 1000,\n /** @param httpTimeout The connection timeout for http call to get metadata */\n timeout = 2000,\n): Promise<NftInfoFields[]> => {\n const sdk = new SDK(new Auth({ chainId, privateKey, projectId: process.env.INFURA_PROJECT_ID, secretId: process.env.INFURA_PROJECT_SECRET }))\n const nfts: NftInfoFields[] = []\n const axios = new AxiosJson()\n let cursor: string | undefined = undefined\n do {\n const opts: PublicAddressOptions = { cursor, includeMetadata: true, publicAddress }\n const { cursor: nextCursor, pageSize, total, assets } = await sdk.api.getNFTs(opts)\n const batch: NftInfoFields[] = assets.slice(0, Math.min(pageSize, total - nfts.length)).map((asset) => {\n const { contract: address, type: tokenType, ...rest } = asset\n const type = toTokenType(tokenType)\n return { address, chainId, type, ...rest }\n })\n nfts.push(...batch)\n cursor = nextCursor\n if (nfts.length >= total || !cursor) break\n } while (nfts.length < maxNfts)\n\n return await Promise.all(\n nfts.map(async (nft) => {\n const metaDataUri = await getNftMetadataUri(nft.address, nft.tokenId)\n if (metaDataUri) {\n nft.metaDataUri = metaDataUri\n const cookedUri = checkIpfsUrl(metaDataUri, ipfsGateway)\n try {\n nft.metadata = (await axios.get(cookedUri, { timeout }))?.data\n } catch (ex) {\n console.log(`failed to get NTF metadata [${cookedUri}] [${ex}]`)\n }\n } else {\n console.log('failed to get NTF metadata URI')\n }\n return nft\n }),\n )\n}\n","import { InfuraProvider, Provider } from '@ethersproject/providers'\nimport { assertEx } from '@xylabs/assert'\n\nexport interface InfuraProviderConfig {\n projectId: string\n projectSecret: string\n}\n\nlet instance: InfuraProvider | undefined = undefined\n\nexport const getInfuraProvider = (): Provider => {\n if (instance) return instance\n const config = getInfuraProviderConfig()\n instance = new InfuraProvider('homestead', config)\n return instance\n}\n\nexport const canUseInfuraProvider = (): boolean => {\n return !!process.env.INFURA_PROJECT_ID && !!process.env.INFURA_PROJECT_SECRET ? true : false\n}\n\nexport const getInfuraProviderConfig = (): InfuraProviderConfig => {\n const projectId = assertEx(process.env.INFURA_PROJECT_ID, 'Missing INFURA_PROJECT_ID ENV VAR')\n const projectSecret = assertEx(process.env.INFURA_PROJECT_SECRET, 'Missing INFURA_PROJECT_SECRET ENV VAR')\n return { projectId, projectSecret }\n}\n"],"mappings":"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","names":["import_crypto_nft_payload_plugin","import_assert","import_crypto_nft_payload_plugin","ipfsGateway"]}
@@ -130,11 +130,15 @@ var CryptoWalletNftWitness = class extends AbstractWitness {
130
130
  ).toString();
131
131
  const chainId = assertEx2(query?.chainId || this.config.chainId, "params.chainId is required");
132
132
  const maxNfts = query?.maxNfts || defaultMaxNfts;
133
- const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout);
134
- const observation = nfts.map((nft) => {
135
- return { ...nft, schema };
136
- });
137
- return observation;
133
+ try {
134
+ const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout);
135
+ const observation = nfts.map((nft) => {
136
+ return { ...nft, schema };
137
+ });
138
+ return observation;
139
+ } catch (error) {
140
+ throw new Error(`Failed to get nfts for address ${address} on chainId ${chainId}`);
141
+ }
138
142
  })
139
143
  );
140
144
  return observations.flat();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/getNftsOwnedByAddress.ts","../../src/lib/getInfuraProvider.ts","../../src/index.ts"],"sourcesContent":["import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoWalletNftWitness } from './Witness'\n\nexport const CryptoWalletNftWitnessPlugin = () =>\n createPayloadSetWitnessPlugin<CryptoWalletNftWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoWalletNftWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { AbstractWitness } from '@xyo-network/abstract-witness'\nimport {\n CryptoWalletNftWitnessConfig,\n isNftWitnessQuery,\n NftInfo,\n NftSchema,\n NftWitnessConfigSchema,\n NftWitnessQuery,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { WitnessParams } from '@xyo-network/witness-model'\n\nimport { getNftsOwnedByAddress } from './lib'\n\nexport type CryptoWalletNftWitnessParams = WitnessParams<AnyConfigSchema<CryptoWalletNftWitnessConfig>>\n\nconst schema = NftSchema\n\nconst defaultMaxNfts = 100\n\nexport class CryptoWalletNftWitness<TParams extends CryptoWalletNftWitnessParams = CryptoWalletNftWitnessParams> extends AbstractWitness<\n TParams,\n NftWitnessQuery,\n NftInfo\n> {\n static override configSchemas = [NftWitnessConfigSchema]\n\n get timeout() {\n return this.config.timeout ?? 2000\n }\n\n protected override async observeHandler(payloads?: NftWitnessQuery[]): Promise<NftInfo[]> {\n await this.started('throw')\n const queries = payloads?.filter(isNftWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map(async (query) => {\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout)\n const observation = nfts.map<NftInfo>((nft) => {\n return { ...nft, schema }\n })\n return observation\n }),\n )\n\n return observations.flat()\n }\n}\n","import { Auth, SDK } from '@infura/sdk'\nimport { AxiosJson } from '@xyo-network/axios'\nimport { NftInfoFields, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155__factory } from '@xyo-network/open-zeppelin-typechain'\n\nimport { getInfuraProvider } from './getInfuraProvider'\n\ntype PublicAddressOptions = {\n cursor?: string\n includeMetadata?: boolean\n publicAddress: string\n tokenAddresses?: string[]\n}\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\n/**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\nexport const checkIpfsUrl = (urlToCheck: string, ipfsGateway: string) => {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = ipfsGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n}\n\nexport const getErc721MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC721__factory.connect(address, getInfuraProvider())\n return [await contract.tokenURI(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getErc1155MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC1155__factory.connect(address, getInfuraProvider())\n return [await contract.uri(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getNftMetadataUri = async (address: string, tokenId: string) => {\n const results = await Promise.all([getErc721MetadataUri(address, tokenId), getErc1155MetadataUri(address, tokenId)])\n return results[0][0] ?? results[1][0]\n}\n\nexport const getNftsOwnedByAddress = async (\n /** @param publicAddress The address of the wallet to search for NFTs */\n publicAddress: string,\n /** @param chainId The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on */\n chainId: number,\n /** @param privateKey The private key of the wallet to use to search for NFTs */\n privateKey: string,\n /** @param maxNfts The maximum number of NFTs to return. Configurable to prevent large wallets from exhausting Infura API credits. */\n maxNfts = 1000,\n /** @param httpTimeout The connection timeout for http call to get metadata */\n timeout = 2000,\n): Promise<NftInfoFields[]> => {\n const sdk = new SDK(new Auth({ chainId, privateKey, projectId: process.env.INFURA_PROJECT_ID, secretId: process.env.INFURA_PROJECT_SECRET }))\n const nfts: NftInfoFields[] = []\n const axios = new AxiosJson()\n let cursor: string | undefined = undefined\n do {\n const opts: PublicAddressOptions = { cursor, includeMetadata: true, publicAddress }\n const { cursor: nextCursor, pageSize, total, assets } = await sdk.api.getNFTs(opts)\n const batch: NftInfoFields[] = assets.slice(0, Math.min(pageSize, total - nfts.length)).map((asset) => {\n const { contract: address, type: tokenType, ...rest } = asset\n const type = toTokenType(tokenType)\n return { address, chainId, type, ...rest }\n })\n nfts.push(...batch)\n cursor = nextCursor\n if (nfts.length >= total || !cursor) break\n } while (nfts.length < maxNfts)\n\n return await Promise.all(\n nfts.map(async (nft) => {\n const metaDataUri = await getNftMetadataUri(nft.address, nft.tokenId)\n if (metaDataUri) {\n nft.metaDataUri = metaDataUri\n const cookedUri = checkIpfsUrl(metaDataUri, ipfsGateway)\n try {\n nft.metadata = (await axios.get(cookedUri, { timeout }))?.data\n } catch (ex) {\n console.log(`failed to get NTF metadata [${cookedUri}] [${ex}]`)\n }\n } else {\n console.log('failed to get NTF metadata URI')\n }\n return nft\n }),\n )\n}\n","import { InfuraProvider, Provider } from '@ethersproject/providers'\nimport { assertEx } from '@xylabs/assert'\n\nexport interface InfuraProviderConfig {\n projectId: string\n projectSecret: string\n}\n\nlet instance: InfuraProvider | undefined = undefined\n\nexport const getInfuraProvider = (): Provider => {\n if (instance) return instance\n const config = getInfuraProviderConfig()\n instance = new InfuraProvider('homestead', config)\n return instance\n}\n\nexport const canUseInfuraProvider = (): boolean => {\n return !!process.env.INFURA_PROJECT_ID && !!process.env.INFURA_PROJECT_SECRET ? true : false\n}\n\nexport const getInfuraProviderConfig = (): InfuraProviderConfig => {\n const projectId = assertEx(process.env.INFURA_PROJECT_ID, 'Missing INFURA_PROJECT_ID ENV VAR')\n const projectSecret = assertEx(process.env.INFURA_PROJECT_SECRET, 'Missing INFURA_PROJECT_SECRET ENV VAR')\n return { projectId, projectSecret }\n}\n","import { CryptoWalletNftWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoWalletNftWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoWalletNftWitnessPlugin\n"],"mappings":"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","names":["NftSchema","assertEx","ipfsGateway","assertEx","NftSchema"]}
1
+ {"version":3,"sources":["../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/getNftsOwnedByAddress.ts","../../src/lib/getInfuraProvider.ts","../../src/index.ts"],"sourcesContent":["import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoWalletNftWitness } from './Witness'\n\nexport const CryptoWalletNftWitnessPlugin = () =>\n createPayloadSetWitnessPlugin<CryptoWalletNftWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoWalletNftWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { AbstractWitness } from '@xyo-network/abstract-witness'\nimport {\n CryptoWalletNftWitnessConfig,\n isNftWitnessQuery,\n NftInfo,\n NftSchema,\n NftWitnessConfigSchema,\n NftWitnessQuery,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { WitnessParams } from '@xyo-network/witness-model'\n\nimport { getNftsOwnedByAddress } from './lib'\n\nexport type CryptoWalletNftWitnessParams = WitnessParams<AnyConfigSchema<CryptoWalletNftWitnessConfig>>\n\nconst schema = NftSchema\n\nconst defaultMaxNfts = 100\n\nexport class CryptoWalletNftWitness<TParams extends CryptoWalletNftWitnessParams = CryptoWalletNftWitnessParams> extends AbstractWitness<\n TParams,\n NftWitnessQuery,\n NftInfo\n> {\n static override configSchemas = [NftWitnessConfigSchema]\n\n get timeout() {\n return this.config.timeout ?? 2000\n }\n\n protected override async observeHandler(payloads?: NftWitnessQuery[]): Promise<NftInfo[]> {\n await this.started('throw')\n const queries = payloads?.filter(isNftWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map(async (query) => {\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const maxNfts = query?.maxNfts || defaultMaxNfts\n try {\n const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout)\n const observation = nfts.map<NftInfo>((nft) => {\n return { ...nft, schema }\n })\n return observation\n } catch (error) {\n throw new Error(`Failed to get nfts for address ${address} on chainId ${chainId}`)\n }\n }),\n )\n return observations.flat()\n }\n}\n","import { Auth, SDK } from '@infura/sdk'\nimport { AxiosJson } from '@xyo-network/axios'\nimport { NftInfoFields, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155__factory } from '@xyo-network/open-zeppelin-typechain'\n\nimport { getInfuraProvider } from './getInfuraProvider'\n\ntype PublicAddressOptions = {\n cursor?: string\n includeMetadata?: boolean\n publicAddress: string\n tokenAddresses?: string[]\n}\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\n/**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\nexport const checkIpfsUrl = (urlToCheck: string, ipfsGateway: string) => {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = ipfsGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n}\n\nexport const getErc721MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC721__factory.connect(address, getInfuraProvider())\n return [await contract.tokenURI(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getErc1155MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC1155__factory.connect(address, getInfuraProvider())\n return [await contract.uri(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getNftMetadataUri = async (address: string, tokenId: string) => {\n const results = await Promise.all([getErc721MetadataUri(address, tokenId), getErc1155MetadataUri(address, tokenId)])\n return results[0][0] ?? results[1][0]\n}\n\nexport const getNftsOwnedByAddress = async (\n /** @param publicAddress The address of the wallet to search for NFTs */\n publicAddress: string,\n /** @param chainId The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on */\n chainId: number,\n /** @param privateKey The private key of the wallet to use to search for NFTs */\n privateKey: string,\n /** @param maxNfts The maximum number of NFTs to return. Configurable to prevent large wallets from exhausting Infura API credits. */\n maxNfts = 1000,\n /** @param httpTimeout The connection timeout for http call to get metadata */\n timeout = 2000,\n): Promise<NftInfoFields[]> => {\n const sdk = new SDK(new Auth({ chainId, privateKey, projectId: process.env.INFURA_PROJECT_ID, secretId: process.env.INFURA_PROJECT_SECRET }))\n const nfts: NftInfoFields[] = []\n const axios = new AxiosJson()\n let cursor: string | undefined = undefined\n do {\n const opts: PublicAddressOptions = { cursor, includeMetadata: true, publicAddress }\n const { cursor: nextCursor, pageSize, total, assets } = await sdk.api.getNFTs(opts)\n const batch: NftInfoFields[] = assets.slice(0, Math.min(pageSize, total - nfts.length)).map((asset) => {\n const { contract: address, type: tokenType, ...rest } = asset\n const type = toTokenType(tokenType)\n return { address, chainId, type, ...rest }\n })\n nfts.push(...batch)\n cursor = nextCursor\n if (nfts.length >= total || !cursor) break\n } while (nfts.length < maxNfts)\n\n return await Promise.all(\n nfts.map(async (nft) => {\n const metaDataUri = await getNftMetadataUri(nft.address, nft.tokenId)\n if (metaDataUri) {\n nft.metaDataUri = metaDataUri\n const cookedUri = checkIpfsUrl(metaDataUri, ipfsGateway)\n try {\n nft.metadata = (await axios.get(cookedUri, { timeout }))?.data\n } catch (ex) {\n console.log(`failed to get NTF metadata [${cookedUri}] [${ex}]`)\n }\n } else {\n console.log('failed to get NTF metadata URI')\n }\n return nft\n }),\n )\n}\n","import { InfuraProvider, Provider } from '@ethersproject/providers'\nimport { assertEx } from '@xylabs/assert'\n\nexport interface InfuraProviderConfig {\n projectId: string\n projectSecret: string\n}\n\nlet instance: InfuraProvider | undefined = undefined\n\nexport const getInfuraProvider = (): Provider => {\n if (instance) return instance\n const config = getInfuraProviderConfig()\n instance = new InfuraProvider('homestead', config)\n return instance\n}\n\nexport const canUseInfuraProvider = (): boolean => {\n return !!process.env.INFURA_PROJECT_ID && !!process.env.INFURA_PROJECT_SECRET ? true : false\n}\n\nexport const getInfuraProviderConfig = (): InfuraProviderConfig => {\n const projectId = assertEx(process.env.INFURA_PROJECT_ID, 'Missing INFURA_PROJECT_ID ENV VAR')\n const projectSecret = assertEx(process.env.INFURA_PROJECT_SECRET, 'Missing INFURA_PROJECT_SECRET ENV VAR')\n return { projectId, projectSecret }\n}\n","import { CryptoWalletNftWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoWalletNftWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoWalletNftWitnessPlugin\n"],"mappings":"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","names":["NftSchema","assertEx","ipfsGateway","assertEx","NftSchema"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAqB1F"}
1
+ {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAwB1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAqB1F"}
1
+ {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAwB1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAqB1F"}
1
+ {"version":3,"file":"Witness.d.ts","sourceRoot":"","sources":["../../src/Witness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EACL,4BAA4B,EAE5B,OAAO,EAGP,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAI1D,MAAM,MAAM,4BAA4B,GAAG,aAAa,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAA;AAMvG,qBAAa,sBAAsB,CAAC,OAAO,SAAS,4BAA4B,GAAG,4BAA4B,CAAE,SAAQ,eAAe,CACtI,OAAO,EACP,eAAe,EACf,OAAO,CACR;IACC,OAAgB,aAAa,4CAA2B;IAExD,IAAI,OAAO,WAEV;cAEwB,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAwB1F"}
@@ -160,11 +160,15 @@ var CryptoWalletNftWitness = class extends import_abstract_witness.AbstractWitne
160
160
  ).toString();
161
161
  const chainId = (0, import_assert2.assertEx)((query == null ? void 0 : query.chainId) || this.config.chainId, "params.chainId is required");
162
162
  const maxNfts = (query == null ? void 0 : query.maxNfts) || defaultMaxNfts;
163
- const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout);
164
- const observation = nfts.map((nft) => {
165
- return { ...nft, schema };
166
- });
167
- return observation;
163
+ try {
164
+ const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout);
165
+ const observation = nfts.map((nft) => {
166
+ return { ...nft, schema };
167
+ });
168
+ return observation;
169
+ } catch (error) {
170
+ throw new Error(`Failed to get nfts for address ${address} on chainId ${chainId}`);
171
+ }
168
172
  })
169
173
  );
170
174
  return observations.flat();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/getNftsOwnedByAddress.ts","../../src/lib/getInfuraProvider.ts"],"sourcesContent":["import { CryptoWalletNftWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoWalletNftWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoWalletNftWitnessPlugin\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoWalletNftWitness } from './Witness'\n\nexport const CryptoWalletNftWitnessPlugin = () =>\n createPayloadSetWitnessPlugin<CryptoWalletNftWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoWalletNftWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { AbstractWitness } from '@xyo-network/abstract-witness'\nimport {\n CryptoWalletNftWitnessConfig,\n isNftWitnessQuery,\n NftInfo,\n NftSchema,\n NftWitnessConfigSchema,\n NftWitnessQuery,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { WitnessParams } from '@xyo-network/witness-model'\n\nimport { getNftsOwnedByAddress } from './lib'\n\nexport type CryptoWalletNftWitnessParams = WitnessParams<AnyConfigSchema<CryptoWalletNftWitnessConfig>>\n\nconst schema = NftSchema\n\nconst defaultMaxNfts = 100\n\nexport class CryptoWalletNftWitness<TParams extends CryptoWalletNftWitnessParams = CryptoWalletNftWitnessParams> extends AbstractWitness<\n TParams,\n NftWitnessQuery,\n NftInfo\n> {\n static override configSchemas = [NftWitnessConfigSchema]\n\n get timeout() {\n return this.config.timeout ?? 2000\n }\n\n protected override async observeHandler(payloads?: NftWitnessQuery[]): Promise<NftInfo[]> {\n await this.started('throw')\n const queries = payloads?.filter(isNftWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map(async (query) => {\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout)\n const observation = nfts.map<NftInfo>((nft) => {\n return { ...nft, schema }\n })\n return observation\n }),\n )\n\n return observations.flat()\n }\n}\n","import { Auth, SDK } from '@infura/sdk'\nimport { AxiosJson } from '@xyo-network/axios'\nimport { NftInfoFields, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155__factory } from '@xyo-network/open-zeppelin-typechain'\n\nimport { getInfuraProvider } from './getInfuraProvider'\n\ntype PublicAddressOptions = {\n cursor?: string\n includeMetadata?: boolean\n publicAddress: string\n tokenAddresses?: string[]\n}\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\n/**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\nexport const checkIpfsUrl = (urlToCheck: string, ipfsGateway: string) => {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = ipfsGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n}\n\nexport const getErc721MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC721__factory.connect(address, getInfuraProvider())\n return [await contract.tokenURI(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getErc1155MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC1155__factory.connect(address, getInfuraProvider())\n return [await contract.uri(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getNftMetadataUri = async (address: string, tokenId: string) => {\n const results = await Promise.all([getErc721MetadataUri(address, tokenId), getErc1155MetadataUri(address, tokenId)])\n return results[0][0] ?? results[1][0]\n}\n\nexport const getNftsOwnedByAddress = async (\n /** @param publicAddress The address of the wallet to search for NFTs */\n publicAddress: string,\n /** @param chainId The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on */\n chainId: number,\n /** @param privateKey The private key of the wallet to use to search for NFTs */\n privateKey: string,\n /** @param maxNfts The maximum number of NFTs to return. Configurable to prevent large wallets from exhausting Infura API credits. */\n maxNfts = 1000,\n /** @param httpTimeout The connection timeout for http call to get metadata */\n timeout = 2000,\n): Promise<NftInfoFields[]> => {\n const sdk = new SDK(new Auth({ chainId, privateKey, projectId: process.env.INFURA_PROJECT_ID, secretId: process.env.INFURA_PROJECT_SECRET }))\n const nfts: NftInfoFields[] = []\n const axios = new AxiosJson()\n let cursor: string | undefined = undefined\n do {\n const opts: PublicAddressOptions = { cursor, includeMetadata: true, publicAddress }\n const { cursor: nextCursor, pageSize, total, assets } = await sdk.api.getNFTs(opts)\n const batch: NftInfoFields[] = assets.slice(0, Math.min(pageSize, total - nfts.length)).map((asset) => {\n const { contract: address, type: tokenType, ...rest } = asset\n const type = toTokenType(tokenType)\n return { address, chainId, type, ...rest }\n })\n nfts.push(...batch)\n cursor = nextCursor\n if (nfts.length >= total || !cursor) break\n } while (nfts.length < maxNfts)\n\n return await Promise.all(\n nfts.map(async (nft) => {\n const metaDataUri = await getNftMetadataUri(nft.address, nft.tokenId)\n if (metaDataUri) {\n nft.metaDataUri = metaDataUri\n const cookedUri = checkIpfsUrl(metaDataUri, ipfsGateway)\n try {\n nft.metadata = (await axios.get(cookedUri, { timeout }))?.data\n } catch (ex) {\n console.log(`failed to get NTF metadata [${cookedUri}] [${ex}]`)\n }\n } else {\n console.log('failed to get NTF metadata URI')\n }\n return nft\n }),\n )\n}\n","import { InfuraProvider, Provider } from '@ethersproject/providers'\nimport { assertEx } from '@xylabs/assert'\n\nexport interface InfuraProviderConfig {\n projectId: string\n projectSecret: string\n}\n\nlet instance: InfuraProvider | undefined = undefined\n\nexport const getInfuraProvider = (): Provider => {\n if (instance) return instance\n const config = getInfuraProviderConfig()\n instance = new InfuraProvider('homestead', config)\n return instance\n}\n\nexport const canUseInfuraProvider = (): boolean => {\n return !!process.env.INFURA_PROJECT_ID && !!process.env.INFURA_PROJECT_SECRET ? true : false\n}\n\nexport const getInfuraProviderConfig = (): InfuraProviderConfig => {\n const projectId = assertEx(process.env.INFURA_PROJECT_ID, 'Missing INFURA_PROJECT_ID ENV VAR')\n const projectSecret = assertEx(process.env.INFURA_PROJECT_SECRET, 'Missing INFURA_PROJECT_SECRET ENV VAR')\n return { projectId, projectSecret }\n}\n"],"mappings":"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","names":["import_crypto_nft_payload_plugin","import_assert","import_crypto_nft_payload_plugin","ipfsGateway"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/getNftsOwnedByAddress.ts","../../src/lib/getInfuraProvider.ts"],"sourcesContent":["import { CryptoWalletNftWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoWalletNftWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoWalletNftWitnessPlugin\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoWalletNftWitness } from './Witness'\n\nexport const CryptoWalletNftWitnessPlugin = () =>\n createPayloadSetWitnessPlugin<CryptoWalletNftWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoWalletNftWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { AbstractWitness } from '@xyo-network/abstract-witness'\nimport {\n CryptoWalletNftWitnessConfig,\n isNftWitnessQuery,\n NftInfo,\n NftSchema,\n NftWitnessConfigSchema,\n NftWitnessQuery,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { WitnessParams } from '@xyo-network/witness-model'\n\nimport { getNftsOwnedByAddress } from './lib'\n\nexport type CryptoWalletNftWitnessParams = WitnessParams<AnyConfigSchema<CryptoWalletNftWitnessConfig>>\n\nconst schema = NftSchema\n\nconst defaultMaxNfts = 100\n\nexport class CryptoWalletNftWitness<TParams extends CryptoWalletNftWitnessParams = CryptoWalletNftWitnessParams> extends AbstractWitness<\n TParams,\n NftWitnessQuery,\n NftInfo\n> {\n static override configSchemas = [NftWitnessConfigSchema]\n\n get timeout() {\n return this.config.timeout ?? 2000\n }\n\n protected override async observeHandler(payloads?: NftWitnessQuery[]): Promise<NftInfo[]> {\n await this.started('throw')\n const queries = payloads?.filter(isNftWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map(async (query) => {\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const maxNfts = query?.maxNfts || defaultMaxNfts\n try {\n const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout)\n const observation = nfts.map<NftInfo>((nft) => {\n return { ...nft, schema }\n })\n return observation\n } catch (error) {\n throw new Error(`Failed to get nfts for address ${address} on chainId ${chainId}`)\n }\n }),\n )\n return observations.flat()\n }\n}\n","import { Auth, SDK } from '@infura/sdk'\nimport { AxiosJson } from '@xyo-network/axios'\nimport { NftInfoFields, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155__factory } from '@xyo-network/open-zeppelin-typechain'\n\nimport { getInfuraProvider } from './getInfuraProvider'\n\ntype PublicAddressOptions = {\n cursor?: string\n includeMetadata?: boolean\n publicAddress: string\n tokenAddresses?: string[]\n}\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\n/**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\nexport const checkIpfsUrl = (urlToCheck: string, ipfsGateway: string) => {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = ipfsGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n}\n\nexport const getErc721MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC721__factory.connect(address, getInfuraProvider())\n return [await contract.tokenURI(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getErc1155MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC1155__factory.connect(address, getInfuraProvider())\n return [await contract.uri(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getNftMetadataUri = async (address: string, tokenId: string) => {\n const results = await Promise.all([getErc721MetadataUri(address, tokenId), getErc1155MetadataUri(address, tokenId)])\n return results[0][0] ?? results[1][0]\n}\n\nexport const getNftsOwnedByAddress = async (\n /** @param publicAddress The address of the wallet to search for NFTs */\n publicAddress: string,\n /** @param chainId The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on */\n chainId: number,\n /** @param privateKey The private key of the wallet to use to search for NFTs */\n privateKey: string,\n /** @param maxNfts The maximum number of NFTs to return. Configurable to prevent large wallets from exhausting Infura API credits. */\n maxNfts = 1000,\n /** @param httpTimeout The connection timeout for http call to get metadata */\n timeout = 2000,\n): Promise<NftInfoFields[]> => {\n const sdk = new SDK(new Auth({ chainId, privateKey, projectId: process.env.INFURA_PROJECT_ID, secretId: process.env.INFURA_PROJECT_SECRET }))\n const nfts: NftInfoFields[] = []\n const axios = new AxiosJson()\n let cursor: string | undefined = undefined\n do {\n const opts: PublicAddressOptions = { cursor, includeMetadata: true, publicAddress }\n const { cursor: nextCursor, pageSize, total, assets } = await sdk.api.getNFTs(opts)\n const batch: NftInfoFields[] = assets.slice(0, Math.min(pageSize, total - nfts.length)).map((asset) => {\n const { contract: address, type: tokenType, ...rest } = asset\n const type = toTokenType(tokenType)\n return { address, chainId, type, ...rest }\n })\n nfts.push(...batch)\n cursor = nextCursor\n if (nfts.length >= total || !cursor) break\n } while (nfts.length < maxNfts)\n\n return await Promise.all(\n nfts.map(async (nft) => {\n const metaDataUri = await getNftMetadataUri(nft.address, nft.tokenId)\n if (metaDataUri) {\n nft.metaDataUri = metaDataUri\n const cookedUri = checkIpfsUrl(metaDataUri, ipfsGateway)\n try {\n nft.metadata = (await axios.get(cookedUri, { timeout }))?.data\n } catch (ex) {\n console.log(`failed to get NTF metadata [${cookedUri}] [${ex}]`)\n }\n } else {\n console.log('failed to get NTF metadata URI')\n }\n return nft\n }),\n )\n}\n","import { InfuraProvider, Provider } from '@ethersproject/providers'\nimport { assertEx } from '@xylabs/assert'\n\nexport interface InfuraProviderConfig {\n projectId: string\n projectSecret: string\n}\n\nlet instance: InfuraProvider | undefined = undefined\n\nexport const getInfuraProvider = (): Provider => {\n if (instance) return instance\n const config = getInfuraProviderConfig()\n instance = new InfuraProvider('homestead', config)\n return instance\n}\n\nexport const canUseInfuraProvider = (): boolean => {\n return !!process.env.INFURA_PROJECT_ID && !!process.env.INFURA_PROJECT_SECRET ? true : false\n}\n\nexport const getInfuraProviderConfig = (): InfuraProviderConfig => {\n const projectId = assertEx(process.env.INFURA_PROJECT_ID, 'Missing INFURA_PROJECT_ID ENV VAR')\n const projectSecret = assertEx(process.env.INFURA_PROJECT_SECRET, 'Missing INFURA_PROJECT_SECRET ENV VAR')\n return { projectId, projectSecret }\n}\n"],"mappings":"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","names":["import_crypto_nft_payload_plugin","import_assert","import_crypto_nft_payload_plugin","ipfsGateway"]}
@@ -131,11 +131,15 @@ var CryptoWalletNftWitness = class extends AbstractWitness {
131
131
  ).toString();
132
132
  const chainId = assertEx2((query == null ? void 0 : query.chainId) || this.config.chainId, "params.chainId is required");
133
133
  const maxNfts = (query == null ? void 0 : query.maxNfts) || defaultMaxNfts;
134
- const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout);
135
- const observation = nfts.map((nft) => {
136
- return { ...nft, schema };
137
- });
138
- return observation;
134
+ try {
135
+ const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout);
136
+ const observation = nfts.map((nft) => {
137
+ return { ...nft, schema };
138
+ });
139
+ return observation;
140
+ } catch (error) {
141
+ throw new Error(`Failed to get nfts for address ${address} on chainId ${chainId}`);
142
+ }
139
143
  })
140
144
  );
141
145
  return observations.flat();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/getNftsOwnedByAddress.ts","../../src/lib/getInfuraProvider.ts","../../src/index.ts"],"sourcesContent":["import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoWalletNftWitness } from './Witness'\n\nexport const CryptoWalletNftWitnessPlugin = () =>\n createPayloadSetWitnessPlugin<CryptoWalletNftWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoWalletNftWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { AbstractWitness } from '@xyo-network/abstract-witness'\nimport {\n CryptoWalletNftWitnessConfig,\n isNftWitnessQuery,\n NftInfo,\n NftSchema,\n NftWitnessConfigSchema,\n NftWitnessQuery,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { WitnessParams } from '@xyo-network/witness-model'\n\nimport { getNftsOwnedByAddress } from './lib'\n\nexport type CryptoWalletNftWitnessParams = WitnessParams<AnyConfigSchema<CryptoWalletNftWitnessConfig>>\n\nconst schema = NftSchema\n\nconst defaultMaxNfts = 100\n\nexport class CryptoWalletNftWitness<TParams extends CryptoWalletNftWitnessParams = CryptoWalletNftWitnessParams> extends AbstractWitness<\n TParams,\n NftWitnessQuery,\n NftInfo\n> {\n static override configSchemas = [NftWitnessConfigSchema]\n\n get timeout() {\n return this.config.timeout ?? 2000\n }\n\n protected override async observeHandler(payloads?: NftWitnessQuery[]): Promise<NftInfo[]> {\n await this.started('throw')\n const queries = payloads?.filter(isNftWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map(async (query) => {\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout)\n const observation = nfts.map<NftInfo>((nft) => {\n return { ...nft, schema }\n })\n return observation\n }),\n )\n\n return observations.flat()\n }\n}\n","import { Auth, SDK } from '@infura/sdk'\nimport { AxiosJson } from '@xyo-network/axios'\nimport { NftInfoFields, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155__factory } from '@xyo-network/open-zeppelin-typechain'\n\nimport { getInfuraProvider } from './getInfuraProvider'\n\ntype PublicAddressOptions = {\n cursor?: string\n includeMetadata?: boolean\n publicAddress: string\n tokenAddresses?: string[]\n}\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\n/**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\nexport const checkIpfsUrl = (urlToCheck: string, ipfsGateway: string) => {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = ipfsGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n}\n\nexport const getErc721MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC721__factory.connect(address, getInfuraProvider())\n return [await contract.tokenURI(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getErc1155MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC1155__factory.connect(address, getInfuraProvider())\n return [await contract.uri(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getNftMetadataUri = async (address: string, tokenId: string) => {\n const results = await Promise.all([getErc721MetadataUri(address, tokenId), getErc1155MetadataUri(address, tokenId)])\n return results[0][0] ?? results[1][0]\n}\n\nexport const getNftsOwnedByAddress = async (\n /** @param publicAddress The address of the wallet to search for NFTs */\n publicAddress: string,\n /** @param chainId The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on */\n chainId: number,\n /** @param privateKey The private key of the wallet to use to search for NFTs */\n privateKey: string,\n /** @param maxNfts The maximum number of NFTs to return. Configurable to prevent large wallets from exhausting Infura API credits. */\n maxNfts = 1000,\n /** @param httpTimeout The connection timeout for http call to get metadata */\n timeout = 2000,\n): Promise<NftInfoFields[]> => {\n const sdk = new SDK(new Auth({ chainId, privateKey, projectId: process.env.INFURA_PROJECT_ID, secretId: process.env.INFURA_PROJECT_SECRET }))\n const nfts: NftInfoFields[] = []\n const axios = new AxiosJson()\n let cursor: string | undefined = undefined\n do {\n const opts: PublicAddressOptions = { cursor, includeMetadata: true, publicAddress }\n const { cursor: nextCursor, pageSize, total, assets } = await sdk.api.getNFTs(opts)\n const batch: NftInfoFields[] = assets.slice(0, Math.min(pageSize, total - nfts.length)).map((asset) => {\n const { contract: address, type: tokenType, ...rest } = asset\n const type = toTokenType(tokenType)\n return { address, chainId, type, ...rest }\n })\n nfts.push(...batch)\n cursor = nextCursor\n if (nfts.length >= total || !cursor) break\n } while (nfts.length < maxNfts)\n\n return await Promise.all(\n nfts.map(async (nft) => {\n const metaDataUri = await getNftMetadataUri(nft.address, nft.tokenId)\n if (metaDataUri) {\n nft.metaDataUri = metaDataUri\n const cookedUri = checkIpfsUrl(metaDataUri, ipfsGateway)\n try {\n nft.metadata = (await axios.get(cookedUri, { timeout }))?.data\n } catch (ex) {\n console.log(`failed to get NTF metadata [${cookedUri}] [${ex}]`)\n }\n } else {\n console.log('failed to get NTF metadata URI')\n }\n return nft\n }),\n )\n}\n","import { InfuraProvider, Provider } from '@ethersproject/providers'\nimport { assertEx } from '@xylabs/assert'\n\nexport interface InfuraProviderConfig {\n projectId: string\n projectSecret: string\n}\n\nlet instance: InfuraProvider | undefined = undefined\n\nexport const getInfuraProvider = (): Provider => {\n if (instance) return instance\n const config = getInfuraProviderConfig()\n instance = new InfuraProvider('homestead', config)\n return instance\n}\n\nexport const canUseInfuraProvider = (): boolean => {\n return !!process.env.INFURA_PROJECT_ID && !!process.env.INFURA_PROJECT_SECRET ? true : false\n}\n\nexport const getInfuraProviderConfig = (): InfuraProviderConfig => {\n const projectId = assertEx(process.env.INFURA_PROJECT_ID, 'Missing INFURA_PROJECT_ID ENV VAR')\n const projectSecret = assertEx(process.env.INFURA_PROJECT_SECRET, 'Missing INFURA_PROJECT_SECRET ENV VAR')\n return { projectId, projectSecret }\n}\n","import { CryptoWalletNftWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoWalletNftWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoWalletNftWitnessPlugin\n"],"mappings":"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","names":["NftSchema","assertEx","ipfsGateway","assertEx","NftSchema"]}
1
+ {"version":3,"sources":["../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/getNftsOwnedByAddress.ts","../../src/lib/getInfuraProvider.ts","../../src/index.ts"],"sourcesContent":["import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoWalletNftWitness } from './Witness'\n\nexport const CryptoWalletNftWitnessPlugin = () =>\n createPayloadSetWitnessPlugin<CryptoWalletNftWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoWalletNftWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { AbstractWitness } from '@xyo-network/abstract-witness'\nimport {\n CryptoWalletNftWitnessConfig,\n isNftWitnessQuery,\n NftInfo,\n NftSchema,\n NftWitnessConfigSchema,\n NftWitnessQuery,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { WitnessParams } from '@xyo-network/witness-model'\n\nimport { getNftsOwnedByAddress } from './lib'\n\nexport type CryptoWalletNftWitnessParams = WitnessParams<AnyConfigSchema<CryptoWalletNftWitnessConfig>>\n\nconst schema = NftSchema\n\nconst defaultMaxNfts = 100\n\nexport class CryptoWalletNftWitness<TParams extends CryptoWalletNftWitnessParams = CryptoWalletNftWitnessParams> extends AbstractWitness<\n TParams,\n NftWitnessQuery,\n NftInfo\n> {\n static override configSchemas = [NftWitnessConfigSchema]\n\n get timeout() {\n return this.config.timeout ?? 2000\n }\n\n protected override async observeHandler(payloads?: NftWitnessQuery[]): Promise<NftInfo[]> {\n await this.started('throw')\n const queries = payloads?.filter(isNftWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map(async (query) => {\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const maxNfts = query?.maxNfts || defaultMaxNfts\n try {\n const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout)\n const observation = nfts.map<NftInfo>((nft) => {\n return { ...nft, schema }\n })\n return observation\n } catch (error) {\n throw new Error(`Failed to get nfts for address ${address} on chainId ${chainId}`)\n }\n }),\n )\n return observations.flat()\n }\n}\n","import { Auth, SDK } from '@infura/sdk'\nimport { AxiosJson } from '@xyo-network/axios'\nimport { NftInfoFields, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155__factory } from '@xyo-network/open-zeppelin-typechain'\n\nimport { getInfuraProvider } from './getInfuraProvider'\n\ntype PublicAddressOptions = {\n cursor?: string\n includeMetadata?: boolean\n publicAddress: string\n tokenAddresses?: string[]\n}\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\n/**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\nexport const checkIpfsUrl = (urlToCheck: string, ipfsGateway: string) => {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = ipfsGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n}\n\nexport const getErc721MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC721__factory.connect(address, getInfuraProvider())\n return [await contract.tokenURI(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getErc1155MetadataUri = async (address: string, tokenId: string): Promise<[string | undefined, Error | undefined]> => {\n try {\n const contract = ERC1155__factory.connect(address, getInfuraProvider())\n return [await contract.uri(tokenId), undefined]\n } catch (ex) {\n return [undefined, ex as Error]\n }\n}\n\nexport const getNftMetadataUri = async (address: string, tokenId: string) => {\n const results = await Promise.all([getErc721MetadataUri(address, tokenId), getErc1155MetadataUri(address, tokenId)])\n return results[0][0] ?? results[1][0]\n}\n\nexport const getNftsOwnedByAddress = async (\n /** @param publicAddress The address of the wallet to search for NFTs */\n publicAddress: string,\n /** @param chainId The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on */\n chainId: number,\n /** @param privateKey The private key of the wallet to use to search for NFTs */\n privateKey: string,\n /** @param maxNfts The maximum number of NFTs to return. Configurable to prevent large wallets from exhausting Infura API credits. */\n maxNfts = 1000,\n /** @param httpTimeout The connection timeout for http call to get metadata */\n timeout = 2000,\n): Promise<NftInfoFields[]> => {\n const sdk = new SDK(new Auth({ chainId, privateKey, projectId: process.env.INFURA_PROJECT_ID, secretId: process.env.INFURA_PROJECT_SECRET }))\n const nfts: NftInfoFields[] = []\n const axios = new AxiosJson()\n let cursor: string | undefined = undefined\n do {\n const opts: PublicAddressOptions = { cursor, includeMetadata: true, publicAddress }\n const { cursor: nextCursor, pageSize, total, assets } = await sdk.api.getNFTs(opts)\n const batch: NftInfoFields[] = assets.slice(0, Math.min(pageSize, total - nfts.length)).map((asset) => {\n const { contract: address, type: tokenType, ...rest } = asset\n const type = toTokenType(tokenType)\n return { address, chainId, type, ...rest }\n })\n nfts.push(...batch)\n cursor = nextCursor\n if (nfts.length >= total || !cursor) break\n } while (nfts.length < maxNfts)\n\n return await Promise.all(\n nfts.map(async (nft) => {\n const metaDataUri = await getNftMetadataUri(nft.address, nft.tokenId)\n if (metaDataUri) {\n nft.metaDataUri = metaDataUri\n const cookedUri = checkIpfsUrl(metaDataUri, ipfsGateway)\n try {\n nft.metadata = (await axios.get(cookedUri, { timeout }))?.data\n } catch (ex) {\n console.log(`failed to get NTF metadata [${cookedUri}] [${ex}]`)\n }\n } else {\n console.log('failed to get NTF metadata URI')\n }\n return nft\n }),\n )\n}\n","import { InfuraProvider, Provider } from '@ethersproject/providers'\nimport { assertEx } from '@xylabs/assert'\n\nexport interface InfuraProviderConfig {\n projectId: string\n projectSecret: string\n}\n\nlet instance: InfuraProvider | undefined = undefined\n\nexport const getInfuraProvider = (): Provider => {\n if (instance) return instance\n const config = getInfuraProviderConfig()\n instance = new InfuraProvider('homestead', config)\n return instance\n}\n\nexport const canUseInfuraProvider = (): boolean => {\n return !!process.env.INFURA_PROJECT_ID && !!process.env.INFURA_PROJECT_SECRET ? true : false\n}\n\nexport const getInfuraProviderConfig = (): InfuraProviderConfig => {\n const projectId = assertEx(process.env.INFURA_PROJECT_ID, 'Missing INFURA_PROJECT_ID ENV VAR')\n const projectSecret = assertEx(process.env.INFURA_PROJECT_SECRET, 'Missing INFURA_PROJECT_SECRET ENV VAR')\n return { projectId, projectSecret }\n}\n","import { CryptoWalletNftWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoWalletNftWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoWalletNftWitnessPlugin\n"],"mappings":"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","names":["NftSchema","assertEx","ipfsGateway","assertEx","NftSchema"]}
package/package.json CHANGED
@@ -14,21 +14,21 @@
14
14
  "@infura/sdk": "^2.4.3",
15
15
  "@xylabs/assert": "^2.13.3",
16
16
  "@xylabs/eth-address": "^2.13.3",
17
- "@xyo-network/abstract-witness": "~2.77.19",
18
- "@xyo-network/axios": "^2.77.19",
19
- "@xyo-network/crypto-nft-payload-plugin": "~2.77.19",
20
- "@xyo-network/module-model": "~2.77.19",
17
+ "@xyo-network/abstract-witness": "~2.78.0",
18
+ "@xyo-network/axios": "^2.78.0",
19
+ "@xyo-network/crypto-nft-payload-plugin": "~2.78.0",
20
+ "@xyo-network/module-model": "~2.78.0",
21
21
  "@xyo-network/open-zeppelin-typechain": "^2.2.11",
22
- "@xyo-network/payload-model": "~2.77.19",
23
- "@xyo-network/payloadset-plugin": "~2.77.19",
24
- "@xyo-network/witness-model": "~2.77.19"
22
+ "@xyo-network/payload-model": "~2.78.0",
23
+ "@xyo-network/payloadset-plugin": "~2.78.0",
24
+ "@xyo-network/witness-model": "~2.78.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@xylabs/jest-helpers": "^2.13.3",
28
28
  "@xylabs/ts-scripts-yarn3": "^3.1.13",
29
29
  "@xylabs/tsconfig": "^3.1.13",
30
- "@xyo-network/account": "~2.77.19",
31
- "@xyo-network/payload-wrapper": "~2.77.19",
30
+ "@xyo-network/account": "~2.78.0",
31
+ "@xyo-network/payload-wrapper": "~2.78.0",
32
32
  "ethers": "^5.7.2",
33
33
  "jest": "^29.7.0",
34
34
  "typescript": "^5.2.2"
@@ -73,5 +73,5 @@
73
73
  "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
74
74
  },
75
75
  "sideEffects": false,
76
- "version": "2.77.19"
76
+ "version": "2.78.0"
77
77
  }
package/src/Witness.ts CHANGED
@@ -42,14 +42,17 @@ export class CryptoWalletNftWitness<TParams extends CryptoWalletNftWitnessParams
42
42
  ).toString()
43
43
  const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')
44
44
  const maxNfts = query?.maxNfts || defaultMaxNfts
45
- const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout)
46
- const observation = nfts.map<NftInfo>((nft) => {
47
- return { ...nft, schema }
48
- })
49
- return observation
45
+ try {
46
+ const nfts = await getNftsOwnedByAddress(address, chainId, this.account.private.hex, maxNfts, this.timeout)
47
+ const observation = nfts.map<NftInfo>((nft) => {
48
+ return { ...nft, schema }
49
+ })
50
+ return observation
51
+ } catch (error) {
52
+ throw new Error(`Failed to get nfts for address ${address} on chainId ${chainId}`)
53
+ }
50
54
  }),
51
55
  )
52
-
53
56
  return observations.flat()
54
57
  }
55
58
  }