UNPKG

nft-did-resolver

Version:
118 lines 4.21 kB
import fetch from 'cross-fetch'; import { jsonToGraphQLQuery } from 'json-to-graphql-query'; import BigNumber from 'bignumber.js'; export const fetchQueryData = async (queryUrl, query) => { const fetchOpts = { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ query: jsonToGraphQLQuery({ query }) }), }; const resp = await fetch(queryUrl, fetchOpts); if (resp.ok) { const { data, error } = await resp.json(); if (error) throw new Error(error.message); return data; } else { throw new Error('Received an invalid response from TheGraph API'); } }; /** * Queries TheGraph to find the latest block at the given time. * @param timestamp * @param blockQueryUrl - subgraph url for blocks * @returns {string} latest block num at timestamp */ export const blockAtTime = async (timestamp, blockQueryUrl) => { const query = { blocks: { __args: { first: 1, orderBy: 'timestamp', orderDirection: 'desc', where: { // we ask for lte because it is the last known block at the given time timestamp_lte: timestamp, }, }, number: true, }, }; const queryData = (await fetchQueryData(blockQueryUrl, query)); if (!queryData?.blocks) { throw new Error('Missing data from subgraph query'); } else if (queryData.blocks.length === 0) { throw new Error(`No blocks exist before timestamp: ${timestamp}`); } return parseInt(queryData.blocks[0].number); }; /** * Eth blocks are typically 13 seconds. We use this check so we don't have to * make an unneccessary call to the blocks subgraph if the did was just created. */ export const isWithinLastBlock = (timestamp, skew) => { return Date.now() - timestamp <= skew; }; export const erc721OwnerOf = async (asset, blockNum, queryUrl) => { const tokenId = `0x${new BigNumber(asset.tokenId).toString(16)}`; const query = { tokens: { __args: { where: { id: [asset.assetName.reference, tokenId].join('-'), }, first: 1, block: blockNum ? { number: blockNum } : null, }, owner: { id: true, }, }, }; const queryData = (await fetchQueryData(queryUrl, query)); if (!queryData?.tokens) { throw new Error('Missing data from subgraph query'); } else if (queryData.tokens.length === 0) { throw new Error(`No owner found for ERC721 NFT ID: ${asset.tokenId} for contract: ${asset.assetName.reference}`); } return queryData.tokens[0].owner.id; }; export const erc1155OwnersOf = async (asset, blockNum, queryUrl) => { const tokenId = `0x${new BigNumber(asset.tokenId).toString(16)}`; const query = { tokens: { __args: { where: { id: [asset.assetName.reference, tokenId].join('-'), }, first: 1, block: blockNum ? { number: blockNum } : null, }, balances: { __args: { where: { value_gt: 0, // we don't want to get an "owner" with a balance of zero }, }, account: { id: true, }, }, }, }; const queryData = (await fetchQueryData(queryUrl, query)); if (!queryData?.tokens[0]) { throw new Error(`No tokens with ERC1155 NFT ID: ${asset.tokenId} found for contract: ${asset.assetName.reference}`); } else if (!queryData.tokens[0].balances || queryData.tokens[0].balances.length === 0) { throw new Error(`No owner found for ERC1155 NFT ID: ${asset.tokenId} for contract: ${asset.assetName.reference}`); } return queryData.tokens[0].balances.slice().map((bal) => bal.account.id); }; //# sourceMappingURL=subgraph-utils.js.map