Skip to content

Commit

Permalink
feat: use batch rpc provider and enumerate tokens in custody
Browse files Browse the repository at this point in the history
  • Loading branch information
aramalipoor committed Oct 28, 2022
1 parent 5da7051 commit 8ef20e9
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 16 deletions.
65 changes: 54 additions & 11 deletions packages/react-token-streams/src/hooks/useStreamTokensInCustody.ts
Expand Up @@ -4,6 +4,7 @@ import {
PredefinedReadContractConfig,
useHasAnyOfFeatures,
} from '@0xflair/react-common';
import { useNftTokensByWallet } from '@0xflair/react-data-query';
import { useERC721TotalSupply } from '@0xflair/react-openzeppelin';
import { BytesLike } from '@ethersproject/bytes';
import { BigNumber, BigNumberish } from 'ethers';
Expand Down Expand Up @@ -43,6 +44,17 @@ export const useStreamTokensInCustody = (config: Config) => {
],
});

const {
data: allTokensInCustody,
error: allTokensInCustodyError,
isLoading: allTokensInCustodyLoading,
} = useNftTokensByWallet({
env: config.env,
chainId: config.chainId,
collectionAddress: config.ticketTokenAddress?.toString(),
walletAddress: config.contractAddress,
});

const { data: totalSupply } = useERC721TotalSupply({
chainId: config.chainId,
contractAddress: config.ticketTokenAddress?.toString() as string,
Expand Down Expand Up @@ -72,7 +84,7 @@ export const useStreamTokensInCustody = (config: Config) => {
finalWalletAddress,
startTokenId,
endTokenId,
)) as any[];
)) as boolean[];

return result.reduce<BigNumberish[]>(
(list, inCustody, tokenIdMinusStartTokenId) =>
Expand All @@ -93,21 +105,49 @@ export const useStreamTokensInCustody = (config: Config) => {
return;
}

if (supportsTokensInCustody) {
if (supportsTokensInCustody && contract && finalWalletAddress) {
try {
setError(undefined);
setIsLoading(true);
const finalData: BigNumberish[] = [];

for (
let i = 0, l = Number(totalSupply?.toString() || 20000);
i <= l;
i = i + 500
) {
const tokens = await fetchTokensInCustodyInRange(i, i + 500);
// Enumerate allTokensInCustody first
if (allTokensInCustody && allTokensInCustody.length < 1000) {
const custodyStatuses = await Promise.all(
allTokensInCustody.map((token) =>
contract.tokensInCustody(
finalWalletAddress,
token.tokenId,
token.tokenId,
),
),
);

for (let i = 0; i < custodyStatuses.length; i++) {
const [inCustody] = custodyStatuses[i];

if (inCustody) {
finalData.push(allTokensInCustody[i].tokenId);
}
}
} else {
// Otherwise enumerate to 20,000
const custodyStatusesPromises = [];

for (
let i = 0, l = Number(totalSupply?.toString() || 20000);
i <= l;
i = i + 500
) {
custodyStatusesPromises.push(
fetchTokensInCustodyInRange(i, i + 500),
);
}

if (tokens && tokens.length) {
finalData.push(...tokens);
for (const tokens of await Promise.all(custodyStatusesPromises)) {
if (tokens && tokens.length) {
finalData.push(...tokens);
}
}
}

Expand All @@ -120,7 +160,10 @@ export const useStreamTokensInCustody = (config: Config) => {
setIsLoading(false);
}
}, [
allTokensInCustody,
contract,
fetchTokensInCustodyInRange,
finalWalletAddress,
isLoading,
supportsTokensInCustody,
totalSupply,
Expand All @@ -133,7 +176,7 @@ export const useStreamTokensInCustody = (config: Config) => {

refetchTokensInCustody();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [supportsTokensInCustody, finalWalletAddress]);
}, [supportsTokensInCustody, finalWalletAddress, allTokensInCustody]);

return {
data,
Expand Down
2 changes: 1 addition & 1 deletion packages/react-wallet/src/constants/index.ts
@@ -1,3 +1,3 @@
export * from './infura';
export * from './providers';
export * from './backend';
export * from './login';
@@ -1 +1,2 @@
export const FLAIR_INFURA_PROJECT_ID = '21891c5f45de4147900a7539f5948dbf';
export const FLAIR_ALCHEMY_API_KEY = '5tDx1qwZ7sjP-_IxzVhV03PYx5pIbDov';
22 changes: 18 additions & 4 deletions packages/react-wallet/src/providers/wallet.tsx
@@ -1,5 +1,6 @@
import { MagicLinkConnector, SafeConnector } from '@0xflair/common';
import { FLAIR_CHAINS, FLAIR_DEFAULT_CHAIN } from '@0xflair/react-common';
import { AlchemyProvider } from '@ethersproject/providers';
import { providers } from 'ethers';
import {
PropsWithChildren,
Expand All @@ -13,14 +14,15 @@ import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet';
import { InjectedConnector } from 'wagmi/connectors/injected';
import { WalletConnectConnector } from 'wagmi/connectors/walletConnect';

import { FLAIR_INFURA_PROJECT_ID } from '../constants';
import { FLAIR_ALCHEMY_API_KEY, FLAIR_INFURA_PROJECT_ID } from '../constants';
import { useAutoConnect } from '../hooks/useAutoConnect';
import stylesheet from '../index.css';

export type WalletProviderProps = {
children?: ReactNode;
appName?: string;
infuraId?: string;
alchemyKey?: string;
custodialWallet?: boolean;
injectStyles?: boolean;
wagmiOverrides?: Record<string, any>;
Expand All @@ -38,22 +40,34 @@ export const WalletProvider = ({
children,
appName = 'Flair',
infuraId = FLAIR_INFURA_PROJECT_ID,
alchemyKey = FLAIR_ALCHEMY_API_KEY,
custodialWallet = false,
injectStyles = true,
wagmiOverrides,
}: WalletProviderProps) => {
const provider = useCallback(
(config: { chainId?: number }) => {
try {
const prv = new providers.InfuraProvider(config.chainId, infuraId);
if (!config.chainId) {
throw new Error('Chain ID is required');
}

const network = AlchemyProvider.getNetwork(config.chainId);
const prv = new providers.JsonRpcBatchProvider(
AlchemyProvider.getUrl(network, alchemyKey),
config.chainId,
);
prv.pollingInterval = 20_000;
return prv;
} catch (e) {
try {
const rpcUrl = FLAIR_CHAINS.find((x) => x.id === config.chainId)
?.rpcUrls.default;
if (rpcUrl) {
const prv = new providers.JsonRpcProvider(rpcUrl, config.chainId);
const prv = new providers.JsonRpcBatchProvider(
rpcUrl,
config.chainId,
);
prv.pollingInterval = 20_000;
return prv;
} else {
Expand Down Expand Up @@ -83,7 +97,7 @@ export const WalletProvider = ({
}
}
},
[infuraId],
[alchemyKey],
);

const connectors = useCallback(
Expand Down

0 comments on commit 8ef20e9

Please sign in to comment.