From 1484cd38f93468f17ada55daa6d4d8abdb1cd7ee Mon Sep 17 00:00:00 2001 From: Scott Herren Date: Wed, 22 Mar 2023 08:28:03 -0500 Subject: [PATCH 1/6] start wearable claim --- packages/app/features/closet/Closet.tsx | 18 + .../app/features/closet/useWearableClaim.ts | 90 ++ .../app/features/closet/useWearableClaims.ts | 44 + packages/app/features/closet/useWearables.ts | 85 ++ packages/app/features/closet/utils/nft.ts | 5 + .../features/closet/utils/nftGiveaway.json | 482 ++++++++++ .../features/closet/utils/nftWearables.json | 850 ++++++++++++++++++ .../app/features/closet/utils/tempType.ts | 33 + packages/app/features/rewards/useClaims.ts | 3 +- ...orRewards.tsx => useContributorRewards.ts} | 2 +- 10 files changed, 1610 insertions(+), 2 deletions(-) create mode 100644 packages/app/features/closet/Closet.tsx create mode 100644 packages/app/features/closet/useWearableClaim.ts create mode 100644 packages/app/features/closet/useWearableClaims.ts create mode 100644 packages/app/features/closet/useWearables.ts create mode 100644 packages/app/features/closet/utils/nft.ts create mode 100644 packages/app/features/closet/utils/nftGiveaway.json create mode 100644 packages/app/features/closet/utils/nftWearables.json create mode 100644 packages/app/features/closet/utils/tempType.ts rename packages/app/features/rewards/{useContributorRewards.tsx => useContributorRewards.ts} (97%) diff --git a/packages/app/features/closet/Closet.tsx b/packages/app/features/closet/Closet.tsx new file mode 100644 index 0000000..8e580a7 --- /dev/null +++ b/packages/app/features/closet/Closet.tsx @@ -0,0 +1,18 @@ +import { createParam } from 'solito'; +import { H3, TextLink } from 'app/ui/typography'; +import { Box } from 'app/ui/layout/Box'; + +export const { useParam } = createParam<{ username: string }>(); + +export function ClosetScreen() { + const [username] = useParam('username'); + + return ( + +

{`Username: ${username}`}

+ + 👈 Go Home + Go to Posts +
+ ); +} diff --git a/packages/app/features/closet/useWearableClaim.ts b/packages/app/features/closet/useWearableClaim.ts new file mode 100644 index 0000000..1f8f2da --- /dev/null +++ b/packages/app/features/closet/useWearableClaim.ts @@ -0,0 +1,90 @@ +import _ from 'lodash'; +import { + useContractReads, + usePrepareContractWrite, + useContractWrite, +} from 'wagmi'; +import useWearableClaims from './useWearableClaims'; +import nftGiveawayAbi from './utils/nftGiveaway.json'; +import { NftClaim } from './utils/tempType'; + +const useWearableClaim = ({ id, address }: { id: string; address: string }) => { + const { data: wearableClaims } = useWearableClaims(); + const rootHashes = _.map( + wearableClaims, + (nftClaim: NftClaim) => nftClaim.merkle_root_hash, + ); + const { data: claimedStatuses } = useContractReads({ + contracts: [ + { + abi: nftGiveawayAbi, + address, + functionName: 'getClaimedStatus', + args: [address, rootHashes], + }, + ], + }); + + // ? is this the right way to get claim count? + // const claim = _.find( + // wearableClaims, + // (claim) => claim.merkle_root_hash === id, + // ); + // const claimJson = _.get(claim, 'claim_json', {}); + // const claimCount = _.size(_.get(claimJson, 'erc1155[0].ids')); + + const unclaimedWearableClaims = _.reduce( + claimedStatuses as boolean[], + (sum: NftClaim[], currentValue: boolean, currentIndex: number) => { + if (currentValue === true) return sum; + + const unclaimedRootHash = rootHashes[currentIndex]; + const unclaimedNftClaim = _.find( + wearableClaims, + (claim: NftClaim) => claim.merkle_root_hash === unclaimedRootHash, + ); + + if (unclaimedNftClaim) sum.push(unclaimedNftClaim); + + return sum; + }, + [], + ); + + const claims = _.map(wearableClaims, (nftClaim: NftClaim) => ({ + to: nftClaim.claim_json.to, + erc1155: nftClaim.claim_json.erc1155, + erc721: nftClaim.claim_json.erc721, + erc20: nftClaim.claim_json.erc20, + salt: nftClaim.claim_json.salt, + })); + const merkleProofs = _.map(wearableClaims, (nftClaim: NftClaim) => + _.get(nftClaim, 'claim_json.proof'), + ); + + const { config } = usePrepareContractWrite({ + address: '0x', + abi: nftGiveawayAbi, + functionName: 'claimMultipleTokensFromMultipleMerkleTree', + args: [rootHashes, claims, merkleProofs], + }); + + const { writeAsync } = useContractWrite({ + ...config, + onSuccess: () => { + console.log('success'); + }, + onError: (error) => { + console.log('error', error); + }, + }); + + return { + writeAsync, + // claimCount, + unclaimedWearableClaims, + allIsClaimed: _.size(unclaimedWearableClaims), + }; +}; + +export default useWearableClaim; diff --git a/packages/app/features/closet/useWearableClaims.ts b/packages/app/features/closet/useWearableClaims.ts new file mode 100644 index 0000000..ee478a7 --- /dev/null +++ b/packages/app/features/closet/useWearableClaims.ts @@ -0,0 +1,44 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import _ from 'lodash'; +import { useQuery } from '@tanstack/react-query'; +import { hasuraClient } from 'services/graphql/client'; +import { NftClaim } from './utils/tempType'; + +// ? handle auth on hasura client? +const useWearableClaims = () => { + const { data, isLoading, error } = useQuery( + ['wearableClaims'], + async () => { + const data = await hasuraClient.query({ + robot_merkle_claims: [ + { where: { merkle_root: { network: { _eq: 'mainnet' } } } }, + { + claim_json: [{ path: 'erc1155' }, true], // ! guessed on this + merkle_root_hash: true, + }, + ], + }); + + const nftClaimArray: any[] = _.get(data, 'robot_merkle_claims', []); + const currentNftClaims = nftClaimArray.map((nftClaim: NftClaim) => { + const claim_count = _.size( + _.get(nftClaim, 'claim_json.erc1155[0].ids'), + ); + + return { + ...nftClaim, + claim_json: { + ...nftClaim.claim_json, + claim_count, + }, + }; + }); + + return currentNftClaims; + }, + { enabled: false }, + ); + return { data, isLoading, error }; +}; + +export default useWearableClaims; diff --git a/packages/app/features/closet/useWearables.ts b/packages/app/features/closet/useWearables.ts new file mode 100644 index 0000000..9567c1a --- /dev/null +++ b/packages/app/features/closet/useWearables.ts @@ -0,0 +1,85 @@ +import { useQuery } from '@tanstack/react-query'; +import { utils, BigNumberish } from 'ethers'; +import { useContractReads } from 'wagmi'; +import _ from 'lodash'; +import { NftItem } from './utils/tempType'; +import nftWearablesAbi from './utils/nftWearables.json'; +import { parseIds } from './utils/nft'; + +const useNfts = () => { + const fetchNfts = async () => { + return fetch('api/nfts') + .then((res) => res.json()) + .then((data) => { + const initialObject: { [key: number]: NftItem } = {}; + const nftListObject = _.reduce( + data, + (result: Record, nft: NftItem) => + (result[nft.nft_token_id] = nft), + initialObject, + ); + + return { nfts: nftListObject, nftIds: parseIds(nftListObject) }; + }) + .catch((err) => { + console.log(err); + return { nfts: {}, nftIds: [] }; + }); + }; + + const { data, isLoading, error } = useQuery< + { nfts: any; nftIds: any }, + Error + >(['nfts'], fetchNfts); + + const nfts = _.get(data, 'nfts', null); + const nftIds = _.get(data, 'nftIds', null); + + return { nfts, nftIds, isLoading, error }; +}; + +// useWearablesForAddress ? +/** + * Fetches the claimed wearables for a given address + * @param address address of the user + * @returns list of wearables `parsedBalances` or error + */ +const useWearables = ({ address }: { address: string }) => { + const { nfts, nftIds } = useNfts(); + const { data: rawWearables, error } = useContractReads({ + contracts: [ + { + // TODO replace address + address: '0x8e9a29e7e8e3dcd7ea31b1792a8078b5723ed4d8', + abi: nftWearablesAbi, + functionName: 'balanceOfBatch', + args: [Array(nftIds.length).fill(address), nftIds], + }, + ], + enabled: !!nfts && !!nftIds, + }); + + if (!nftIds || !rawWearables) return { wearables: [], parsedBalances: [] }; + + const parsedBalances = _.map(rawWearables, (balance: BigNumberish) => + utils.formatUnits(balance, 0), + ); + + // reduce to nft items only with existing balance + const wearables = parsedBalances.reduce( + (sum: NftItem[], currentValue: boolean | string, currentIndex: number) => { + if (currentValue === '0') return sum; + + const nftId = nftIds[currentIndex]; + const currentItem = nfts[nftId]; + sum.push(currentItem); + + return sum; + }, + [], + ); + + return { wearables, rawWearables, error }; +}; + +export default useWearables; diff --git a/packages/app/features/closet/utils/nft.ts b/packages/app/features/closet/utils/nft.ts new file mode 100644 index 0000000..595f5c0 --- /dev/null +++ b/packages/app/features/closet/utils/nft.ts @@ -0,0 +1,5 @@ +export const parseIds = (nfts: { [key: string]: any }) => { + if (!nfts) return []; + + return Object.keys(nfts).map((key: string) => nfts[key].nft_token_id); +}; diff --git a/packages/app/features/closet/utils/nftGiveaway.json b/packages/app/features/closet/utils/nftGiveaway.json new file mode 100644 index 0000000..bcdc663 --- /dev/null +++ b/packages/app/features/closet/utils/nftGiveaway.json @@ -0,0 +1,482 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "admin", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "components": [ + { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "indexed": false, + "internalType": "struct ClaimERC1155ERC721ERC20.ERC1155Claim[]", + "name": "erc1155", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "indexed": false, + "internalType": "struct ClaimERC1155ERC721ERC20.ERC721Claim[]", + "name": "erc721", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "contractAddresses", + "type": "address[]" + } + ], + "indexed": false, + "internalType": "struct ClaimERC1155ERC721ERC20.ERC20Claim", + "name": "erc20", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + } + ], + "name": "ClaimedMultipleTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "expiryTime", + "type": "uint256" + } + ], + "name": "NewGiveaway", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "merkleRoot", "type": "bytes32" }, + { "internalType": "uint256", "name": "expiryTime", "type": "uint256" } + ], + "name": "addNewGiveaway", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "merkleRoot", "type": "bytes32" }, + { + "components": [ + { "internalType": "address", "name": "to", "type": "address" }, + { + "components": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "internalType": "struct ClaimERC1155ERC721ERC20.ERC1155Claim[]", + "name": "erc1155", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "internalType": "struct ClaimERC1155ERC721ERC20.ERC721Claim[]", + "name": "erc721", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "contractAddresses", + "type": "address[]" + } + ], + "internalType": "struct ClaimERC1155ERC721ERC20.ERC20Claim", + "name": "erc20", + "type": "tuple" + }, + { "internalType": "bytes32", "name": "salt", "type": "bytes32" } + ], + "internalType": "struct ClaimERC1155ERC721ERC20.Claim", + "name": "claim", + "type": "tuple" + }, + { "internalType": "bytes32[]", "name": "proof", "type": "bytes32[]" } + ], + "name": "claimMultipleTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "rootHashes", + "type": "bytes32[]" + }, + { + "components": [ + { "internalType": "address", "name": "to", "type": "address" }, + { + "components": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "internalType": "struct ClaimERC1155ERC721ERC20.ERC1155Claim[]", + "name": "erc1155", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "internalType": "struct ClaimERC1155ERC721ERC20.ERC721Claim[]", + "name": "erc721", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "contractAddresses", + "type": "address[]" + } + ], + "internalType": "struct ClaimERC1155ERC721ERC20.ERC20Claim", + "name": "erc20", + "type": "tuple" + }, + { "internalType": "bytes32", "name": "salt", "type": "bytes32" } + ], + "internalType": "struct ClaimERC1155ERC721ERC20.Claim[]", + "name": "claims", + "type": "tuple[]" + }, + { "internalType": "bytes32[][]", "name": "proofs", "type": "bytes32[][]" } + ], + "name": "claimMultipleTokensFromMultipleMerkleTree", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "bytes32", "name": "", "type": "bytes32" } + ], + "name": "claimed", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "user", "type": "address" }, + { "internalType": "bytes32[]", "name": "rootHashes", "type": "bytes32[]" } + ], + "name": "getClaimedStatus", + "outputs": [{ "internalType": "bool[]", "name": "", "type": "bool[]" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" } + ], + "name": "getRoleAdmin", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "hasRole", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "bytes32", "name": "", "type": "bytes32" } + ], + "name": "leaves", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "uint256[]", "name": "", "type": "uint256[]" }, + { "internalType": "uint256[]", "name": "", "type": "uint256[]" }, + { "internalType": "bytes", "name": "", "type": "bytes" } + ], + "name": "onERC1155BatchReceived", + "outputs": [{ "internalType": "bytes4", "name": "", "type": "bytes4" }], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "bytes", "name": "", "type": "bytes" } + ], + "name": "onERC1155Received", + "outputs": [{ "internalType": "bytes4", "name": "", "type": "bytes4" }], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "uint256[]", "name": "", "type": "uint256[]" }, + { "internalType": "bytes", "name": "", "type": "bytes" } + ], + "name": "onERC721BatchReceived", + "outputs": [{ "internalType": "bytes4", "name": "", "type": "bytes4" }], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "bytes", "name": "", "type": "bytes" } + ], + "name": "onERC721Received", + "outputs": [{ "internalType": "bytes4", "name": "", "type": "bytes4" }], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } + ], + "name": "supportsInterface", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/app/features/closet/utils/nftWearables.json b/packages/app/features/closet/utils/nftWearables.json new file mode 100644 index 0000000..b693c21 --- /dev/null +++ b/packages/app/features/closet/utils/nftWearables.json @@ -0,0 +1,850 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "AdminApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "AdminRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address payable[]", + "name": "receivers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "basisPoints", + "type": "uint256[]" + } + ], + "name": "DefaultRoyaltiesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "extension", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "ExtensionApproveTransferUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "extension", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExtensionBlacklisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "extension", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExtensionRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "extension", + "type": "address" + }, + { + "indexed": false, + "internalType": "address payable[]", + "name": "receivers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "basisPoints", + "type": "uint256[]" + } + ], + "name": "ExtensionRoyaltiesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "extension", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExtensionUnregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "extension", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "permissions", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "MintPermissionsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address payable[]", + "name": "receivers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "basisPoints", + "type": "uint256[]" + } + ], + "name": "RoyaltiesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { "internalType": "address", "name": "admin", "type": "address" } + ], + "name": "approveAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" }, + { "internalType": "uint256", "name": "id", "type": "uint256" } + ], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address[]", "name": "accounts", "type": "address[]" }, + { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" } + ], + "name": "balanceOfBatch", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "extension", "type": "address" } + ], + "name": "blacklistExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" }, + { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }, + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAdmins", + "outputs": [ + { "internalType": "address[]", "name": "admins", "type": "address[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getExtensions", + "outputs": [ + { "internalType": "address[]", "name": "extensions", "type": "address[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "getFeeBps", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "getFeeRecipients", + "outputs": [ + { "internalType": "address payable[]", "name": "", "type": "address[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "getFees", + "outputs": [ + { "internalType": "address payable[]", "name": "", "type": "address[]" }, + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "getRoyalties", + "outputs": [ + { "internalType": "address payable[]", "name": "", "type": "address[]" }, + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "admin", "type": "address" } + ], + "name": "isAdmin", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" }, + { "internalType": "address", "name": "operator", "type": "address" } + ], + "name": "isApprovedForAll", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address[]", "name": "to", "type": "address[]" }, + { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }, + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "name": "mintBaseExisting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address[]", "name": "to", "type": "address[]" }, + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, + { "internalType": "string[]", "name": "uris", "type": "string[]" } + ], + "name": "mintBaseNew", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address[]", "name": "to", "type": "address[]" }, + { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }, + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "name": "mintExtensionExisting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address[]", "name": "to", "type": "address[]" }, + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, + { "internalType": "string[]", "name": "uris", "type": "string[]" } + ], + "name": "mintExtensionNew", + "outputs": [ + { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { "internalType": "string", "name": "_name", "type": "string" } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "extension", "type": "address" }, + { "internalType": "string", "name": "baseURI", "type": "string" } + ], + "name": "registerExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "extension", "type": "address" }, + { "internalType": "string", "name": "baseURI", "type": "string" }, + { "internalType": "bool", "name": "baseURIIdentical", "type": "bool" } + ], + "name": "registerExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "admin", "type": "address" } + ], + "name": "revokeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "royaltyInfo", + "outputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }, + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "id", "type": "uint256" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "operator", "type": "address" }, + { "internalType": "bool", "name": "approved", "type": "bool" } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "bool", "name": "enabled", "type": "bool" }], + "name": "setApproveTransferExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "string", "name": "uri_", "type": "string" }], + "name": "setBaseTokenURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "string", "name": "uri_", "type": "string" }], + "name": "setBaseTokenURIExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "string", "name": "uri_", "type": "string" }, + { "internalType": "bool", "name": "identical", "type": "bool" } + ], + "name": "setBaseTokenURIExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "extension", "type": "address" }, + { "internalType": "address", "name": "permissions", "type": "address" } + ], + "name": "setMintPermissions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { + "internalType": "address payable[]", + "name": "receivers", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "basisPoints", + "type": "uint256[]" + } + ], + "name": "setRoyalties", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable[]", + "name": "receivers", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "basisPoints", + "type": "uint256[]" + } + ], + "name": "setRoyalties", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "extension", "type": "address" }, + { + "internalType": "address payable[]", + "name": "receivers", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "basisPoints", + "type": "uint256[]" + } + ], + "name": "setRoyaltiesExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "string", "name": "uri_", "type": "string" } + ], + "name": "setTokenURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }, + { "internalType": "string[]", "name": "uris", "type": "string[]" } + ], + "name": "setTokenURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }, + { "internalType": "string[]", "name": "uris", "type": "string[]" } + ], + "name": "setTokenURIExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "string", "name": "uri_", "type": "string" } + ], + "name": "setTokenURIExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "string", "name": "prefix", "type": "string" } + ], + "name": "setTokenURIPrefix", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "string", "name": "prefix", "type": "string" } + ], + "name": "setTokenURIPrefixExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } + ], + "name": "supportsInterface", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { "internalType": "string", "name": "_symbol", "type": "string" } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "tokenExtension", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "extension", "type": "address" } + ], + "name": "unregisterExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "uri", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/app/features/closet/utils/tempType.ts b/packages/app/features/closet/utils/tempType.ts new file mode 100644 index 0000000..af37ab7 --- /dev/null +++ b/packages/app/features/closet/utils/tempType.ts @@ -0,0 +1,33 @@ +export type NftItem = { + nft_token_id: number; + id: number; + nft_metadata: { + name: string; + image: string; + files: { uri: string; mimeType: string }[]; + properties: { + brand: string; + images: string[]; + }; + }; +}; + +export type NftClaim = { + claim_json: { + to: string; + erc1155: { + contractAddress: string; + ids: string[]; + values: number[]; + }[]; + erc721: never[]; + erc20: { + contractAddresses: never[]; + amounts: never[]; + }; + salt: string; + proof: string[]; + claim_count: number; + }; + merkle_root_hash: string; +}; diff --git a/packages/app/features/rewards/useClaims.ts b/packages/app/features/rewards/useClaims.ts index 169fff4..a01cd1d 100644 --- a/packages/app/features/rewards/useClaims.ts +++ b/packages/app/features/rewards/useClaims.ts @@ -97,7 +97,7 @@ const useClaims = () => { }; }, [claimWeeksData, unclaimedWeeks, address]); - const { config, ...res } = usePrepareContractWrite({ + const { config, ...rest } = usePrepareContractWrite({ abi: MerkleRedeemABI, address: MerkleRedeemAddress.mainnet, functionName: 'claimWeeks', @@ -111,6 +111,7 @@ const useClaims = () => { claimedWeeksValues, unclaimedWeeksValues, claimRewardWrite, + ...rest, }; }; diff --git a/packages/app/features/rewards/useContributorRewards.tsx b/packages/app/features/rewards/useContributorRewards.ts similarity index 97% rename from packages/app/features/rewards/useContributorRewards.tsx rename to packages/app/features/rewards/useContributorRewards.ts index c9def66..6d7a3fc 100644 --- a/packages/app/features/rewards/useContributorRewards.tsx +++ b/packages/app/features/rewards/useContributorRewards.ts @@ -4,7 +4,7 @@ import { useQuery } from '@tanstack/react-query'; import { hasuraClient } from 'services/graphql/client'; import { order_by } from 'services/graphql/__generated__/zeus'; -import { formatNumber } from './utils/format'; +import { formatNumber } from 'shared/utils/numberHelpers'; export type DesignerReward = { robot_reward: number; From 5fba7581f693d13931cdefd5efb20d9c3073d63d Mon Sep 17 00:00:00 2001 From: Scott Herren Date: Wed, 22 Mar 2023 15:31:05 -0500 Subject: [PATCH 2/6] update --- packages/api/src/claims/router.ts | 69 ++ .../tempType.ts => api/src/claims/types.ts} | 0 packages/api/src/root.ts | 2 + packages/api/src/trpc.ts | 2 + packages/app/features/closet/Closet.tsx | 2 + .../app/features/closet/useWearableClaim.ts | 96 +- .../app/features/closet/useWearableClaims.ts | 44 - packages/app/features/closet/useWearables.ts | 31 +- .../features/closet/utils/nftGiveaway.json | 482 ---------- .../features/closet/utils/nftWearables.json | 850 ------------------ packages/contracts/abis/NftGiveaway.ts | 480 ++++++++++ packages/contracts/abis/NftWearables.ts | 810 +++++++++++++++++ 12 files changed, 1416 insertions(+), 1452 deletions(-) create mode 100644 packages/api/src/claims/router.ts rename packages/{app/features/closet/utils/tempType.ts => api/src/claims/types.ts} (100%) delete mode 100644 packages/app/features/closet/useWearableClaims.ts delete mode 100644 packages/app/features/closet/utils/nftGiveaway.json delete mode 100644 packages/app/features/closet/utils/nftWearables.json create mode 100644 packages/contracts/abis/NftGiveaway.ts create mode 100644 packages/contracts/abis/NftWearables.ts diff --git a/packages/api/src/claims/router.ts b/packages/api/src/claims/router.ts new file mode 100644 index 0000000..0cfc4f5 --- /dev/null +++ b/packages/api/src/claims/router.ts @@ -0,0 +1,69 @@ +import { createTRPCRouter, protectedProcedure, publicProcedure } from '../trpc'; +import { z } from 'zod'; +import { + baseProductsSelector, + contributorsSelector, +} from '../products/selectors'; +import { productsFilesSelector } from 'services/mfos/products/selectors'; +import { ResolverInputTypes } from 'services/mfos'; +import { + getProductTags, + getProgressFromTagsAndStage, +} from 'shared/utils/productHelpers'; +import { NftClaim } from './types'; + +export const claimsRouter = createTRPCRouter({ + wearableMerkleClaims: protectedProcedure + .input(z.string().optional().default('mainnet')) + .query(async ({ ctx, input }) => { + const network = input; + + const res = await ctx.hasuraClient.query({ + robot_merkle_claims: [ + { + where: { + merkle_root: { network: { _eq: network } }, + recipient_eth_address: { _eq: ctx.session.address }, + }, + }, + { + claim_json: [{ path: '' }, true], + merkle_root_hash: true, + }, + ], + }); + + const nftClaimArray = res.robot_merkle_claims as NftClaim[]; + const currentNftClaims = nftClaimArray.map((nftClaim) => { + const claim_count = nftClaim.claim_json.erc1155[0].ids.length; + + return { + ...nftClaim, + claim_json: { + ...nftClaim.claim_json, + claim_count, + }, + }; + }); + + return currentNftClaims; + }), + byId: publicProcedure + .input(z.string().optional()) + .query(async ({ ctx, input }) => { + if (!input) return null; + + const res = await ctx.mfosClient('query')({ + products_by_id: [ + { id: input }, + { + ...baseProductsSelector, + ...contributorsSelector, + ...productsFilesSelector, + }, + ], + }); + + return res.products_by_id; + }), +}); diff --git a/packages/app/features/closet/utils/tempType.ts b/packages/api/src/claims/types.ts similarity index 100% rename from packages/app/features/closet/utils/tempType.ts rename to packages/api/src/claims/types.ts diff --git a/packages/api/src/root.ts b/packages/api/src/root.ts index c0fcf0c..881bbb9 100644 --- a/packages/api/src/root.ts +++ b/packages/api/src/root.ts @@ -1,10 +1,12 @@ import { createTRPCRouter } from './trpc'; import { productRouter } from './products/router'; import { authRouter } from './auth/router'; +import { claimsRouter } from './claims/router'; export const appRouter = createTRPCRouter({ product: productRouter, auth: authRouter, + claims: claimsRouter, }); // export type definition of API diff --git a/packages/api/src/trpc.ts b/packages/api/src/trpc.ts index ff8020a..25ca1da 100644 --- a/packages/api/src/trpc.ts +++ b/packages/api/src/trpc.ts @@ -20,6 +20,7 @@ import { type CreateNextContextOptions } from '@trpc/server/adapters/next'; import { siwe, SiweSession } from 'shared/auth/siwe'; import { mfosClient } from 'services/mfos/client'; +import { hasuraClient } from 'services/graphql/client'; interface CreateInnerContextOptions { session: SiweSession | null; @@ -37,6 +38,7 @@ const createInnerTRPCContext = (opts: CreateInnerContextOptions) => { return { session: opts.session, mfosClient, + hasuraClient, }; }; diff --git a/packages/app/features/closet/Closet.tsx b/packages/app/features/closet/Closet.tsx index 8e580a7..5110269 100644 --- a/packages/app/features/closet/Closet.tsx +++ b/packages/app/features/closet/Closet.tsx @@ -1,11 +1,13 @@ import { createParam } from 'solito'; import { H3, TextLink } from 'app/ui/typography'; import { Box } from 'app/ui/layout/Box'; +import { api } from 'app/lib/api'; export const { useParam } = createParam<{ username: string }>(); export function ClosetScreen() { const [username] = useParam('username'); + const { data, isLoading } = api.claims.wearableMerkleClaims.useQuery(); return ( diff --git a/packages/app/features/closet/useWearableClaim.ts b/packages/app/features/closet/useWearableClaim.ts index 1f8f2da..2cf5277 100644 --- a/packages/app/features/closet/useWearableClaim.ts +++ b/packages/app/features/closet/useWearableClaim.ts @@ -1,89 +1,67 @@ import _ from 'lodash'; import { - useContractReads, + useContractRead, usePrepareContractWrite, useContractWrite, } from 'wagmi'; -import useWearableClaims from './useWearableClaims'; -import nftGiveawayAbi from './utils/nftGiveaway.json'; -import { NftClaim } from './utils/tempType'; +import { api } from 'app/lib/api'; +import { NftGiveawayAddress, NftGiveawayAbi } from 'contracts/abis/NftGiveaway'; -const useWearableClaim = ({ id, address }: { id: string; address: string }) => { - const { data: wearableClaims } = useWearableClaims(); - const rootHashes = _.map( - wearableClaims, - (nftClaim: NftClaim) => nftClaim.merkle_root_hash, - ); - const { data: claimedStatuses } = useContractReads({ - contracts: [ - { - abi: nftGiveawayAbi, - address, - functionName: 'getClaimedStatus', - args: [address, rootHashes], - }, - ], - }); +const useWearableClaim = ({ address }: { address: string }) => { + const { data: wearableClaims, isLoading: wearableClaimsLoading } = + api.claims.wearableMerkleClaims.useQuery(); - // ? is this the right way to get claim count? - // const claim = _.find( - // wearableClaims, - // (claim) => claim.merkle_root_hash === id, - // ); - // const claimJson = _.get(claim, 'claim_json', {}); - // const claimCount = _.size(_.get(claimJson, 'erc1155[0].ids')); + const rootHashes = wearableClaims?.map( + (nftClaim) => nftClaim.merkle_root_hash, + ); + const { data: claimedStatuses, isLoading: claimStatusLoading } = + useContractRead({ + abi: NftGiveawayAbi, + address: NftGiveawayAddress.mainnet, + functionName: 'getClaimedStatus', + args: [address, rootHashes], + enabled: !!address && !!rootHashes, + }); const unclaimedWearableClaims = _.reduce( claimedStatuses as boolean[], - (sum: NftClaim[], currentValue: boolean, currentIndex: number) => { - if (currentValue === true) return sum; + ( + unclaimed: NonNullable, + currentValue: boolean, + currentIndex: number, + ) => { + if (currentValue === true || !wearableClaims) return unclaimed; - const unclaimedRootHash = rootHashes[currentIndex]; - const unclaimedNftClaim = _.find( - wearableClaims, - (claim: NftClaim) => claim.merkle_root_hash === unclaimedRootHash, - ); + const unclaimedNftClaim = wearableClaims[currentIndex]; - if (unclaimedNftClaim) sum.push(unclaimedNftClaim); + if (unclaimedNftClaim) unclaimed.push(unclaimedNftClaim); - return sum; + return unclaimed; }, [], ); - const claims = _.map(wearableClaims, (nftClaim: NftClaim) => ({ - to: nftClaim.claim_json.to, - erc1155: nftClaim.claim_json.erc1155, - erc721: nftClaim.claim_json.erc721, - erc20: nftClaim.claim_json.erc20, - salt: nftClaim.claim_json.salt, - })); - const merkleProofs = _.map(wearableClaims, (nftClaim: NftClaim) => - _.get(nftClaim, 'claim_json.proof'), + const claims = _.map(wearableClaims, (nftClaim) => + _.omit(nftClaim.claim_json, ['claim_count']), + ); + const merkleProofs = _.map( + wearableClaims, + (nftClaim) => nftClaim.claim_json.proof, ); const { config } = usePrepareContractWrite({ - address: '0x', - abi: nftGiveawayAbi, + address: NftGiveawayAddress.mainnet, + abi: NftGiveawayAbi, functionName: 'claimMultipleTokensFromMultipleMerkleTree', args: [rootHashes, claims, merkleProofs], }); - const { writeAsync } = useContractWrite({ - ...config, - onSuccess: () => { - console.log('success'); - }, - onError: (error) => { - console.log('error', error); - }, - }); + const claimWearablesWrite = useContractWrite(config); return { - writeAsync, - // claimCount, + claimWearablesWrite, unclaimedWearableClaims, - allIsClaimed: _.size(unclaimedWearableClaims), + isLoading: claimStatusLoading || wearableClaimsLoading, }; }; diff --git a/packages/app/features/closet/useWearableClaims.ts b/packages/app/features/closet/useWearableClaims.ts deleted file mode 100644 index ee478a7..0000000 --- a/packages/app/features/closet/useWearableClaims.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import _ from 'lodash'; -import { useQuery } from '@tanstack/react-query'; -import { hasuraClient } from 'services/graphql/client'; -import { NftClaim } from './utils/tempType'; - -// ? handle auth on hasura client? -const useWearableClaims = () => { - const { data, isLoading, error } = useQuery( - ['wearableClaims'], - async () => { - const data = await hasuraClient.query({ - robot_merkle_claims: [ - { where: { merkle_root: { network: { _eq: 'mainnet' } } } }, - { - claim_json: [{ path: 'erc1155' }, true], // ! guessed on this - merkle_root_hash: true, - }, - ], - }); - - const nftClaimArray: any[] = _.get(data, 'robot_merkle_claims', []); - const currentNftClaims = nftClaimArray.map((nftClaim: NftClaim) => { - const claim_count = _.size( - _.get(nftClaim, 'claim_json.erc1155[0].ids'), - ); - - return { - ...nftClaim, - claim_json: { - ...nftClaim.claim_json, - claim_count, - }, - }; - }); - - return currentNftClaims; - }, - { enabled: false }, - ); - return { data, isLoading, error }; -}; - -export default useWearableClaims; diff --git a/packages/app/features/closet/useWearables.ts b/packages/app/features/closet/useWearables.ts index 9567c1a..bf6c648 100644 --- a/packages/app/features/closet/useWearables.ts +++ b/packages/app/features/closet/useWearables.ts @@ -1,20 +1,22 @@ import { useQuery } from '@tanstack/react-query'; import { utils, BigNumberish } from 'ethers'; -import { useContractReads } from 'wagmi'; +import { useContractRead } from 'wagmi'; import _ from 'lodash'; -import { NftItem } from './utils/tempType'; -import nftWearablesAbi from './utils/nftWearables.json'; +import { + NftWearablesAddress, + NftWearablesAbi, +} from 'contracts/abis/NftWearables'; import { parseIds } from './utils/nft'; const useNfts = () => { const fetchNfts = async () => { - return fetch('api/nfts') + return fetch('api/nftMetadata') .then((res) => res.json()) .then((data) => { - const initialObject: { [key: number]: NftItem } = {}; + const initialObject: { [key: number]: any } = {}; const nftListObject = _.reduce( data, - (result: Record, nft: NftItem) => + (result: Record, nft: any) => (result[nft.nft_token_id] = nft), initialObject, ); @@ -46,16 +48,11 @@ const useNfts = () => { */ const useWearables = ({ address }: { address: string }) => { const { nfts, nftIds } = useNfts(); - const { data: rawWearables, error } = useContractReads({ - contracts: [ - { - // TODO replace address - address: '0x8e9a29e7e8e3dcd7ea31b1792a8078b5723ed4d8', - abi: nftWearablesAbi, - functionName: 'balanceOfBatch', - args: [Array(nftIds.length).fill(address), nftIds], - }, - ], + const { data: rawWearables, error } = useContractRead({ + address: NftWearablesAddress.mainnet, + abi: NftWearablesAbi, + functionName: 'balanceOfBatch', + args: [Array(nftIds.length).fill(address), nftIds], enabled: !!nfts && !!nftIds, }); @@ -67,7 +64,7 @@ const useWearables = ({ address }: { address: string }) => { // reduce to nft items only with existing balance const wearables = parsedBalances.reduce( - (sum: NftItem[], currentValue: boolean | string, currentIndex: number) => { + (sum: any[], currentValue: boolean | string, currentIndex: number) => { if (currentValue === '0') return sum; const nftId = nftIds[currentIndex]; diff --git a/packages/app/features/closet/utils/nftGiveaway.json b/packages/app/features/closet/utils/nftGiveaway.json deleted file mode 100644 index bcdc663..0000000 --- a/packages/app/features/closet/utils/nftGiveaway.json +++ /dev/null @@ -1,482 +0,0 @@ -[ - { - "inputs": [ - { "internalType": "address", "name": "admin", "type": "address" } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "components": [ - { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - } - ], - "indexed": false, - "internalType": "struct ClaimERC1155ERC721ERC20.ERC1155Claim[]", - "name": "erc1155", - "type": "tuple[]" - }, - { - "components": [ - { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }, - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - } - ], - "indexed": false, - "internalType": "struct ClaimERC1155ERC721ERC20.ERC721Claim[]", - "name": "erc721", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "address[]", - "name": "contractAddresses", - "type": "address[]" - } - ], - "indexed": false, - "internalType": "struct ClaimERC1155ERC721ERC20.ERC20Claim", - "name": "erc20", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "merkleRoot", - "type": "bytes32" - } - ], - "name": "ClaimedMultipleTokens", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "merkleRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "expiryTime", - "type": "uint256" - } - ], - "name": "NewGiveaway", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "merkleRoot", "type": "bytes32" }, - { "internalType": "uint256", "name": "expiryTime", "type": "uint256" } - ], - "name": "addNewGiveaway", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "merkleRoot", "type": "bytes32" }, - { - "components": [ - { "internalType": "address", "name": "to", "type": "address" }, - { - "components": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - } - ], - "internalType": "struct ClaimERC1155ERC721ERC20.ERC1155Claim[]", - "name": "erc1155", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - } - ], - "internalType": "struct ClaimERC1155ERC721ERC20.ERC721Claim[]", - "name": "erc721", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "address[]", - "name": "contractAddresses", - "type": "address[]" - } - ], - "internalType": "struct ClaimERC1155ERC721ERC20.ERC20Claim", - "name": "erc20", - "type": "tuple" - }, - { "internalType": "bytes32", "name": "salt", "type": "bytes32" } - ], - "internalType": "struct ClaimERC1155ERC721ERC20.Claim", - "name": "claim", - "type": "tuple" - }, - { "internalType": "bytes32[]", "name": "proof", "type": "bytes32[]" } - ], - "name": "claimMultipleTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "rootHashes", - "type": "bytes32[]" - }, - { - "components": [ - { "internalType": "address", "name": "to", "type": "address" }, - { - "components": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - } - ], - "internalType": "struct ClaimERC1155ERC721ERC20.ERC1155Claim[]", - "name": "erc1155", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - } - ], - "internalType": "struct ClaimERC1155ERC721ERC20.ERC721Claim[]", - "name": "erc721", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "address[]", - "name": "contractAddresses", - "type": "address[]" - } - ], - "internalType": "struct ClaimERC1155ERC721ERC20.ERC20Claim", - "name": "erc20", - "type": "tuple" - }, - { "internalType": "bytes32", "name": "salt", "type": "bytes32" } - ], - "internalType": "struct ClaimERC1155ERC721ERC20.Claim[]", - "name": "claims", - "type": "tuple[]" - }, - { "internalType": "bytes32[][]", "name": "proofs", "type": "bytes32[][]" } - ], - "name": "claimMultipleTokensFromMultipleMerkleTree", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "bytes32", "name": "", "type": "bytes32" } - ], - "name": "claimed", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "user", "type": "address" }, - { "internalType": "bytes32[]", "name": "rootHashes", "type": "bytes32[]" } - ], - "name": "getClaimedStatus", - "outputs": [{ "internalType": "bool[]", "name": "", "type": "bool[]" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" } - ], - "name": "getRoleAdmin", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } - ], - "name": "hasRole", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "bytes32", "name": "", "type": "bytes32" } - ], - "name": "leaves", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "uint256[]", "name": "", "type": "uint256[]" }, - { "internalType": "uint256[]", "name": "", "type": "uint256[]" }, - { "internalType": "bytes", "name": "", "type": "bytes" } - ], - "name": "onERC1155BatchReceived", - "outputs": [{ "internalType": "bytes4", "name": "", "type": "bytes4" }], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "uint256", "name": "", "type": "uint256" }, - { "internalType": "uint256", "name": "", "type": "uint256" }, - { "internalType": "bytes", "name": "", "type": "bytes" } - ], - "name": "onERC1155Received", - "outputs": [{ "internalType": "bytes4", "name": "", "type": "bytes4" }], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "uint256[]", "name": "", "type": "uint256[]" }, - { "internalType": "bytes", "name": "", "type": "bytes" } - ], - "name": "onERC721BatchReceived", - "outputs": [{ "internalType": "bytes4", "name": "", "type": "bytes4" }], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "uint256", "name": "", "type": "uint256" }, - { "internalType": "bytes", "name": "", "type": "bytes" } - ], - "name": "onERC721Received", - "outputs": [{ "internalType": "bytes4", "name": "", "type": "bytes4" }], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } - ], - "name": "supportsInterface", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/app/features/closet/utils/nftWearables.json b/packages/app/features/closet/utils/nftWearables.json deleted file mode 100644 index b693c21..0000000 --- a/packages/app/features/closet/utils/nftWearables.json +++ /dev/null @@ -1,850 +0,0 @@ -[ - { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "AdminApproved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "AdminRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address payable[]", - "name": "receivers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "basisPoints", - "type": "uint256[]" - } - ], - "name": "DefaultRoyaltiesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "extension", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "name": "ExtensionApproveTransferUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "extension", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "ExtensionBlacklisted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "extension", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "ExtensionRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "extension", - "type": "address" - }, - { - "indexed": false, - "internalType": "address payable[]", - "name": "receivers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "basisPoints", - "type": "uint256[]" - } - ], - "name": "ExtensionRoyaltiesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "extension", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "ExtensionUnregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "extension", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "permissions", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "MintPermissionsUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address payable[]", - "name": "receivers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "basisPoints", - "type": "uint256[]" - } - ], - "name": "RoyaltiesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "TransferBatch", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TransferSingle", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "URI", - "type": "event" - }, - { - "inputs": [ - { "internalType": "address", "name": "admin", "type": "address" } - ], - "name": "approveAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "account", "type": "address" }, - { "internalType": "uint256", "name": "id", "type": "uint256" } - ], - "name": "balanceOf", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address[]", "name": "accounts", "type": "address[]" }, - { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" } - ], - "name": "balanceOfBatch", - "outputs": [ - { "internalType": "uint256[]", "name": "", "type": "uint256[]" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "extension", "type": "address" } - ], - "name": "blacklistExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "account", "type": "address" }, - { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }, - { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAdmins", - "outputs": [ - { "internalType": "address[]", "name": "admins", "type": "address[]" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getExtensions", - "outputs": [ - { "internalType": "address[]", "name": "extensions", "type": "address[]" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" } - ], - "name": "getFeeBps", - "outputs": [ - { "internalType": "uint256[]", "name": "", "type": "uint256[]" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" } - ], - "name": "getFeeRecipients", - "outputs": [ - { "internalType": "address payable[]", "name": "", "type": "address[]" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" } - ], - "name": "getFees", - "outputs": [ - { "internalType": "address payable[]", "name": "", "type": "address[]" }, - { "internalType": "uint256[]", "name": "", "type": "uint256[]" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" } - ], - "name": "getRoyalties", - "outputs": [ - { "internalType": "address payable[]", "name": "", "type": "address[]" }, - { "internalType": "uint256[]", "name": "", "type": "uint256[]" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "admin", "type": "address" } - ], - "name": "isAdmin", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "account", "type": "address" }, - { "internalType": "address", "name": "operator", "type": "address" } - ], - "name": "isApprovedForAll", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address[]", "name": "to", "type": "address[]" }, - { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }, - { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } - ], - "name": "mintBaseExisting", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address[]", "name": "to", "type": "address[]" }, - { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, - { "internalType": "string[]", "name": "uris", "type": "string[]" } - ], - "name": "mintBaseNew", - "outputs": [ - { "internalType": "uint256[]", "name": "", "type": "uint256[]" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address[]", "name": "to", "type": "address[]" }, - { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }, - { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } - ], - "name": "mintExtensionExisting", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address[]", "name": "to", "type": "address[]" }, - { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, - { "internalType": "string[]", "name": "uris", "type": "string[]" } - ], - "name": "mintExtensionNew", - "outputs": [ - { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { "internalType": "string", "name": "_name", "type": "string" } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "extension", "type": "address" }, - { "internalType": "string", "name": "baseURI", "type": "string" } - ], - "name": "registerExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "extension", "type": "address" }, - { "internalType": "string", "name": "baseURI", "type": "string" }, - { "internalType": "bool", "name": "baseURIIdentical", "type": "bool" } - ], - "name": "registerExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "admin", "type": "address" } - ], - "name": "revokeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, - { "internalType": "uint256", "name": "value", "type": "uint256" } - ], - "name": "royaltyInfo", - "outputs": [ - { "internalType": "address", "name": "", "type": "address" }, - { "internalType": "uint256", "name": "", "type": "uint256" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "from", "type": "address" }, - { "internalType": "address", "name": "to", "type": "address" }, - { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }, - { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, - { "internalType": "bytes", "name": "data", "type": "bytes" } - ], - "name": "safeBatchTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "from", "type": "address" }, - { "internalType": "address", "name": "to", "type": "address" }, - { "internalType": "uint256", "name": "id", "type": "uint256" }, - { "internalType": "uint256", "name": "amount", "type": "uint256" }, - { "internalType": "bytes", "name": "data", "type": "bytes" } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "operator", "type": "address" }, - { "internalType": "bool", "name": "approved", "type": "bool" } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [{ "internalType": "bool", "name": "enabled", "type": "bool" }], - "name": "setApproveTransferExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [{ "internalType": "string", "name": "uri_", "type": "string" }], - "name": "setBaseTokenURI", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [{ "internalType": "string", "name": "uri_", "type": "string" }], - "name": "setBaseTokenURIExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "string", "name": "uri_", "type": "string" }, - { "internalType": "bool", "name": "identical", "type": "bool" } - ], - "name": "setBaseTokenURIExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "extension", "type": "address" }, - { "internalType": "address", "name": "permissions", "type": "address" } - ], - "name": "setMintPermissions", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, - { - "internalType": "address payable[]", - "name": "receivers", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "basisPoints", - "type": "uint256[]" - } - ], - "name": "setRoyalties", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable[]", - "name": "receivers", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "basisPoints", - "type": "uint256[]" - } - ], - "name": "setRoyalties", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "extension", "type": "address" }, - { - "internalType": "address payable[]", - "name": "receivers", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "basisPoints", - "type": "uint256[]" - } - ], - "name": "setRoyaltiesExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, - { "internalType": "string", "name": "uri_", "type": "string" } - ], - "name": "setTokenURI", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }, - { "internalType": "string[]", "name": "uris", "type": "string[]" } - ], - "name": "setTokenURI", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }, - { "internalType": "string[]", "name": "uris", "type": "string[]" } - ], - "name": "setTokenURIExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, - { "internalType": "string", "name": "uri_", "type": "string" } - ], - "name": "setTokenURIExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "string", "name": "prefix", "type": "string" } - ], - "name": "setTokenURIPrefix", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "string", "name": "prefix", "type": "string" } - ], - "name": "setTokenURIPrefixExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } - ], - "name": "supportsInterface", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { "internalType": "string", "name": "_symbol", "type": "string" } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" } - ], - "name": "tokenExtension", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" } - ], - "name": "totalSupply", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "newOwner", "type": "address" } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "extension", "type": "address" } - ], - "name": "unregisterExtension", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "tokenId", "type": "uint256" } - ], - "name": "uri", - "outputs": [{ "internalType": "string", "name": "", "type": "string" }], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/contracts/abis/NftGiveaway.ts b/packages/contracts/abis/NftGiveaway.ts new file mode 100644 index 0000000..6561daf --- /dev/null +++ b/packages/contracts/abis/NftGiveaway.ts @@ -0,0 +1,480 @@ +export const NftGiveawayAddress = { + mainnet: '0x', +}; + +export const NftGiveawayAbi = [ + { + inputs: [{ internalType: 'address', name: 'admin', type: 'address' }], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'address', + name: 'to', + type: 'address', + }, + { + components: [ + { internalType: 'uint256[]', name: 'ids', type: 'uint256[]' }, + { + internalType: 'uint256[]', + name: 'values', + type: 'uint256[]', + }, + { + internalType: 'address', + name: 'contractAddress', + type: 'address', + }, + ], + indexed: false, + internalType: 'struct ClaimERC1155ERC721ERC20.ERC1155Claim[]', + name: 'erc1155', + type: 'tuple[]', + }, + { + components: [ + { internalType: 'uint256[]', name: 'ids', type: 'uint256[]' }, + { + internalType: 'address', + name: 'contractAddress', + type: 'address', + }, + ], + indexed: false, + internalType: 'struct ClaimERC1155ERC721ERC20.ERC721Claim[]', + name: 'erc721', + type: 'tuple[]', + }, + { + components: [ + { + internalType: 'uint256[]', + name: 'amounts', + type: 'uint256[]', + }, + { + internalType: 'address[]', + name: 'contractAddresses', + type: 'address[]', + }, + ], + indexed: false, + internalType: 'struct ClaimERC1155ERC721ERC20.ERC20Claim', + name: 'erc20', + type: 'tuple', + }, + { + indexed: false, + internalType: 'bytes32', + name: 'merkleRoot', + type: 'bytes32', + }, + ], + name: 'ClaimedMultipleTokens', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'bytes32', + name: 'merkleRoot', + type: 'bytes32', + }, + { + indexed: false, + internalType: 'uint256', + name: 'expiryTime', + type: 'uint256', + }, + ], + name: 'NewGiveaway', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'bytes32', + name: 'previousAdminRole', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'bytes32', + name: 'newAdminRole', + type: 'bytes32', + }, + ], + name: 'RoleAdminChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + ], + name: 'RoleGranted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + ], + name: 'RoleRevoked', + type: 'event', + }, + { + inputs: [], + name: 'DEFAULT_ADMIN_ROLE', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'merkleRoot', type: 'bytes32' }, + { internalType: 'uint256', name: 'expiryTime', type: 'uint256' }, + ], + name: 'addNewGiveaway', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'merkleRoot', type: 'bytes32' }, + { + components: [ + { internalType: 'address', name: 'to', type: 'address' }, + { + components: [ + { + internalType: 'uint256[]', + name: 'ids', + type: 'uint256[]', + }, + { + internalType: 'uint256[]', + name: 'values', + type: 'uint256[]', + }, + { + internalType: 'address', + name: 'contractAddress', + type: 'address', + }, + ], + internalType: 'struct ClaimERC1155ERC721ERC20.ERC1155Claim[]', + name: 'erc1155', + type: 'tuple[]', + }, + { + components: [ + { + internalType: 'uint256[]', + name: 'ids', + type: 'uint256[]', + }, + { + internalType: 'address', + name: 'contractAddress', + type: 'address', + }, + ], + internalType: 'struct ClaimERC1155ERC721ERC20.ERC721Claim[]', + name: 'erc721', + type: 'tuple[]', + }, + { + components: [ + { + internalType: 'uint256[]', + name: 'amounts', + type: 'uint256[]', + }, + { + internalType: 'address[]', + name: 'contractAddresses', + type: 'address[]', + }, + ], + internalType: 'struct ClaimERC1155ERC721ERC20.ERC20Claim', + name: 'erc20', + type: 'tuple', + }, + { internalType: 'bytes32', name: 'salt', type: 'bytes32' }, + ], + internalType: 'struct ClaimERC1155ERC721ERC20.Claim', + name: 'claim', + type: 'tuple', + }, + { internalType: 'bytes32[]', name: 'proof', type: 'bytes32[]' }, + ], + name: 'claimMultipleTokens', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32[]', + name: 'rootHashes', + type: 'bytes32[]', + }, + { + components: [ + { internalType: 'address', name: 'to', type: 'address' }, + { + components: [ + { + internalType: 'uint256[]', + name: 'ids', + type: 'uint256[]', + }, + { + internalType: 'uint256[]', + name: 'values', + type: 'uint256[]', + }, + { + internalType: 'address', + name: 'contractAddress', + type: 'address', + }, + ], + internalType: 'struct ClaimERC1155ERC721ERC20.ERC1155Claim[]', + name: 'erc1155', + type: 'tuple[]', + }, + { + components: [ + { + internalType: 'uint256[]', + name: 'ids', + type: 'uint256[]', + }, + { + internalType: 'address', + name: 'contractAddress', + type: 'address', + }, + ], + internalType: 'struct ClaimERC1155ERC721ERC20.ERC721Claim[]', + name: 'erc721', + type: 'tuple[]', + }, + { + components: [ + { + internalType: 'uint256[]', + name: 'amounts', + type: 'uint256[]', + }, + { + internalType: 'address[]', + name: 'contractAddresses', + type: 'address[]', + }, + ], + internalType: 'struct ClaimERC1155ERC721ERC20.ERC20Claim', + name: 'erc20', + type: 'tuple', + }, + { internalType: 'bytes32', name: 'salt', type: 'bytes32' }, + ], + internalType: 'struct ClaimERC1155ERC721ERC20.Claim[]', + name: 'claims', + type: 'tuple[]', + }, + { internalType: 'bytes32[][]', name: 'proofs', type: 'bytes32[][]' }, + ], + name: 'claimMultipleTokensFromMultipleMerkleTree', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'bytes32', name: '', type: 'bytes32' }, + ], + name: 'claimed', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'user', type: 'address' }, + { internalType: 'bytes32[]', name: 'rootHashes', type: 'bytes32[]' }, + ], + name: 'getClaimedStatus', + outputs: [{ internalType: 'bool[]', name: '', type: 'bool[]' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes32', name: 'role', type: 'bytes32' }], + name: 'getRoleAdmin', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'role', type: 'bytes32' }, + { internalType: 'address', name: 'account', type: 'address' }, + ], + name: 'grantRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'role', type: 'bytes32' }, + { internalType: 'address', name: 'account', type: 'address' }, + ], + name: 'hasRole', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'bytes32', name: '', type: 'bytes32' }, + ], + name: 'leaves', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'uint256[]', name: '', type: 'uint256[]' }, + { internalType: 'uint256[]', name: '', type: 'uint256[]' }, + { internalType: 'bytes', name: '', type: 'bytes' }, + ], + name: 'onERC1155BatchReceived', + outputs: [{ internalType: 'bytes4', name: '', type: 'bytes4' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'bytes', name: '', type: 'bytes' }, + ], + name: 'onERC1155Received', + outputs: [{ internalType: 'bytes4', name: '', type: 'bytes4' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'uint256[]', name: '', type: 'uint256[]' }, + { internalType: 'bytes', name: '', type: 'bytes' }, + ], + name: 'onERC721BatchReceived', + outputs: [{ internalType: 'bytes4', name: '', type: 'bytes4' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'bytes', name: '', type: 'bytes' }, + ], + name: 'onERC721Received', + outputs: [{ internalType: 'bytes4', name: '', type: 'bytes4' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'role', type: 'bytes32' }, + { internalType: 'address', name: 'account', type: 'address' }, + ], + name: 'renounceRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes32', name: 'role', type: 'bytes32' }, + { internalType: 'address', name: 'account', type: 'address' }, + ], + name: 'revokeRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes4', name: 'interfaceId', type: 'bytes4' }], + name: 'supportsInterface', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, +]; diff --git a/packages/contracts/abis/NftWearables.ts b/packages/contracts/abis/NftWearables.ts new file mode 100644 index 0000000..87ba06d --- /dev/null +++ b/packages/contracts/abis/NftWearables.ts @@ -0,0 +1,810 @@ +export const NftWearablesAddress = { + mainnet: '', +}; + +export const NftWearablesAbi = [ + { inputs: [], stateMutability: 'nonpayable', type: 'constructor' }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + ], + name: 'AdminApproved', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + ], + name: 'AdminRevoked', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: false, + internalType: 'bool', + name: 'approved', + type: 'bool', + }, + ], + name: 'ApprovalForAll', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'address payable[]', + name: 'receivers', + type: 'address[]', + }, + { + indexed: false, + internalType: 'uint256[]', + name: 'basisPoints', + type: 'uint256[]', + }, + ], + name: 'DefaultRoyaltiesUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'extension', + type: 'address', + }, + { + indexed: false, + internalType: 'bool', + name: 'enabled', + type: 'bool', + }, + ], + name: 'ExtensionApproveTransferUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'extension', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + ], + name: 'ExtensionBlacklisted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'extension', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + ], + name: 'ExtensionRegistered', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'extension', + type: 'address', + }, + { + indexed: false, + internalType: 'address payable[]', + name: 'receivers', + type: 'address[]', + }, + { + indexed: false, + internalType: 'uint256[]', + name: 'basisPoints', + type: 'uint256[]', + }, + ], + name: 'ExtensionRoyaltiesUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'extension', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + ], + name: 'ExtensionUnregistered', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'extension', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'permissions', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + ], + name: 'MintPermissionsUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'previousOwner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'newOwner', + type: 'address', + }, + ], + name: 'OwnershipTransferred', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'tokenId', + type: 'uint256', + }, + { + indexed: false, + internalType: 'address payable[]', + name: 'receivers', + type: 'address[]', + }, + { + indexed: false, + internalType: 'uint256[]', + name: 'basisPoints', + type: 'uint256[]', + }, + ], + name: 'RoyaltiesUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'from', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'to', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256[]', + name: 'ids', + type: 'uint256[]', + }, + { + indexed: false, + internalType: 'uint256[]', + name: 'values', + type: 'uint256[]', + }, + ], + name: 'TransferBatch', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'from', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'to', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'TransferSingle', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'string', + name: 'value', + type: 'string', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'URI', + type: 'event', + }, + { + inputs: [{ internalType: 'address', name: 'admin', type: 'address' }], + name: 'approveAdmin', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'account', type: 'address' }, + { internalType: 'uint256', name: 'id', type: 'uint256' }, + ], + name: 'balanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'accounts', type: 'address[]' }, + { internalType: 'uint256[]', name: 'ids', type: 'uint256[]' }, + ], + name: 'balanceOfBatch', + outputs: [{ internalType: 'uint256[]', name: '', type: 'uint256[]' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'extension', type: 'address' }], + name: 'blacklistExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'account', type: 'address' }, + { internalType: 'uint256[]', name: 'tokenIds', type: 'uint256[]' }, + { internalType: 'uint256[]', name: 'amounts', type: 'uint256[]' }, + ], + name: 'burn', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'getAdmins', + outputs: [{ internalType: 'address[]', name: 'admins', type: 'address[]' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getExtensions', + outputs: [ + { internalType: 'address[]', name: 'extensions', type: 'address[]' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'tokenId', type: 'uint256' }], + name: 'getFeeBps', + outputs: [{ internalType: 'uint256[]', name: '', type: 'uint256[]' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'tokenId', type: 'uint256' }], + name: 'getFeeRecipients', + outputs: [ + { internalType: 'address payable[]', name: '', type: 'address[]' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'tokenId', type: 'uint256' }], + name: 'getFees', + outputs: [ + { internalType: 'address payable[]', name: '', type: 'address[]' }, + { internalType: 'uint256[]', name: '', type: 'uint256[]' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'tokenId', type: 'uint256' }], + name: 'getRoyalties', + outputs: [ + { internalType: 'address payable[]', name: '', type: 'address[]' }, + { internalType: 'uint256[]', name: '', type: 'uint256[]' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'admin', type: 'address' }], + name: 'isAdmin', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'account', type: 'address' }, + { internalType: 'address', name: 'operator', type: 'address' }, + ], + name: 'isApprovedForAll', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'to', type: 'address[]' }, + { internalType: 'uint256[]', name: 'tokenIds', type: 'uint256[]' }, + { internalType: 'uint256[]', name: 'amounts', type: 'uint256[]' }, + ], + name: 'mintBaseExisting', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'to', type: 'address[]' }, + { internalType: 'uint256[]', name: 'amounts', type: 'uint256[]' }, + { internalType: 'string[]', name: 'uris', type: 'string[]' }, + ], + name: 'mintBaseNew', + outputs: [{ internalType: 'uint256[]', name: '', type: 'uint256[]' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'to', type: 'address[]' }, + { internalType: 'uint256[]', name: 'tokenIds', type: 'uint256[]' }, + { internalType: 'uint256[]', name: 'amounts', type: 'uint256[]' }, + ], + name: 'mintExtensionExisting', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'to', type: 'address[]' }, + { internalType: 'uint256[]', name: 'amounts', type: 'uint256[]' }, + { internalType: 'string[]', name: 'uris', type: 'string[]' }, + ], + name: 'mintExtensionNew', + outputs: [ + { internalType: 'uint256[]', name: 'tokenIds', type: 'uint256[]' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'name', + outputs: [{ internalType: 'string', name: '_name', type: 'string' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [], + name: 'owner', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'extension', type: 'address' }, + { internalType: 'string', name: 'baseURI', type: 'string' }, + ], + name: 'registerExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'extension', type: 'address' }, + { internalType: 'string', name: 'baseURI', type: 'string' }, + { internalType: 'bool', name: 'baseURIIdentical', type: 'bool' }, + ], + name: 'registerExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'renounceOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'admin', type: 'address' }], + name: 'revokeAdmin', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, + { internalType: 'uint256', name: 'value', type: 'uint256' }, + ], + name: 'royaltyInfo', + outputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'from', type: 'address' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256[]', name: 'ids', type: 'uint256[]' }, + { internalType: 'uint256[]', name: 'amounts', type: 'uint256[]' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'safeBatchTransferFrom', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'from', type: 'address' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'id', type: 'uint256' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'safeTransferFrom', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'operator', type: 'address' }, + { internalType: 'bool', name: 'approved', type: 'bool' }, + ], + name: 'setApprovalForAll', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bool', name: 'enabled', type: 'bool' }], + name: 'setApproveTransferExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'string', name: 'uri_', type: 'string' }], + name: 'setBaseTokenURI', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'string', name: 'uri_', type: 'string' }], + name: 'setBaseTokenURIExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'string', name: 'uri_', type: 'string' }, + { internalType: 'bool', name: 'identical', type: 'bool' }, + ], + name: 'setBaseTokenURIExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'extension', type: 'address' }, + { internalType: 'address', name: 'permissions', type: 'address' }, + ], + name: 'setMintPermissions', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, + { + internalType: 'address payable[]', + name: 'receivers', + type: 'address[]', + }, + { + internalType: 'uint256[]', + name: 'basisPoints', + type: 'uint256[]', + }, + ], + name: 'setRoyalties', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address payable[]', + name: 'receivers', + type: 'address[]', + }, + { + internalType: 'uint256[]', + name: 'basisPoints', + type: 'uint256[]', + }, + ], + name: 'setRoyalties', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'extension', type: 'address' }, + { + internalType: 'address payable[]', + name: 'receivers', + type: 'address[]', + }, + { + internalType: 'uint256[]', + name: 'basisPoints', + type: 'uint256[]', + }, + ], + name: 'setRoyaltiesExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, + { internalType: 'string', name: 'uri_', type: 'string' }, + ], + name: 'setTokenURI', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256[]', name: 'tokenIds', type: 'uint256[]' }, + { internalType: 'string[]', name: 'uris', type: 'string[]' }, + ], + name: 'setTokenURI', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256[]', name: 'tokenIds', type: 'uint256[]' }, + { internalType: 'string[]', name: 'uris', type: 'string[]' }, + ], + name: 'setTokenURIExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, + { internalType: 'string', name: 'uri_', type: 'string' }, + ], + name: 'setTokenURIExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'string', name: 'prefix', type: 'string' }], + name: 'setTokenURIPrefix', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'string', name: 'prefix', type: 'string' }], + name: 'setTokenURIPrefixExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes4', name: 'interfaceId', type: 'bytes4' }], + name: 'supportsInterface', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'symbol', + outputs: [{ internalType: 'string', name: '_symbol', type: 'string' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'tokenId', type: 'uint256' }], + name: 'tokenExtension', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'tokenId', type: 'uint256' }], + name: 'totalSupply', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'newOwner', type: 'address' }], + name: 'transferOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'extension', type: 'address' }], + name: 'unregisterExtension', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'tokenId', type: 'uint256' }], + name: 'uri', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, +]; From 4f9e4e42098e8bcb75e4a205b8f6c864b27ecfeb Mon Sep 17 00:00:00 2001 From: Scott Herren Date: Thu, 23 Mar 2023 08:12:30 -0500 Subject: [PATCH 3/6] prefer named exports --- packages/app/features/closet/useWearableClaim.ts | 4 +--- packages/app/features/closet/useWearables.ts | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/app/features/closet/useWearableClaim.ts b/packages/app/features/closet/useWearableClaim.ts index 2cf5277..42ef2f7 100644 --- a/packages/app/features/closet/useWearableClaim.ts +++ b/packages/app/features/closet/useWearableClaim.ts @@ -7,7 +7,7 @@ import { import { api } from 'app/lib/api'; import { NftGiveawayAddress, NftGiveawayAbi } from 'contracts/abis/NftGiveaway'; -const useWearableClaim = ({ address }: { address: string }) => { +export const useWearableClaim = ({ address }: { address: string }) => { const { data: wearableClaims, isLoading: wearableClaimsLoading } = api.claims.wearableMerkleClaims.useQuery(); @@ -64,5 +64,3 @@ const useWearableClaim = ({ address }: { address: string }) => { isLoading: claimStatusLoading || wearableClaimsLoading, }; }; - -export default useWearableClaim; diff --git a/packages/app/features/closet/useWearables.ts b/packages/app/features/closet/useWearables.ts index bf6c648..1594b3a 100644 --- a/packages/app/features/closet/useWearables.ts +++ b/packages/app/features/closet/useWearables.ts @@ -46,7 +46,7 @@ const useNfts = () => { * @param address address of the user * @returns list of wearables `parsedBalances` or error */ -const useWearables = ({ address }: { address: string }) => { +export const useWearables = ({ address }: { address: string }) => { const { nfts, nftIds } = useNfts(); const { data: rawWearables, error } = useContractRead({ address: NftWearablesAddress.mainnet, @@ -78,5 +78,3 @@ const useWearables = ({ address }: { address: string }) => { return { wearables, rawWearables, error }; }; - -export default useWearables; From 1188d9f379a4ce8686db8d76b242d04aab529653 Mon Sep 17 00:00:00 2001 From: META DREAMER Date: Wed, 5 Apr 2023 13:02:13 -0600 Subject: [PATCH 4/6] Implement wearable data fetching with trpc + basic inventory page --- apps/next/package.json | 2 +- apps/next/pages/api/siwe/[...route].ts | 4 +- apps/next/pages/inventory.tsx | 10 +- packages/api/package.json | 1 + packages/api/src/claims/router.ts | 69 - packages/api/src/root.ts | 4 +- packages/api/src/trpc.ts | 10 +- packages/api/src/utils/wagmiClient.ts | 7 + packages/api/src/wearables/router.ts | 94 ++ .../api/src/{claims => wearables}/types.ts | 13 +- packages/app/features/closet/Closet.tsx | 20 - packages/app/features/closet/useWearables.ts | 80 - packages/app/features/closet/utils/nft.ts | 5 - packages/app/features/inventory/Inventory.tsx | 42 + .../useClaimWearables.ts} | 33 +- packages/app/features/rewards/useClaims.ts | 5 +- .../app/lib/ConnectWalletButton.native.tsx | 46 - packages/app/package.json | 4 +- packages/app/provider/web3/chains.tsx | 37 - packages/app/provider/web3/connectKit.tsx | 8 +- packages/app/provider/web3/rainbowKit.tsx | 2 +- .../app/provider/web3/wagmiClient.native.tsx | 2 +- packages/app/provider/web3/wagmiClient.tsx | 2 +- packages/app/ui/components/WearableCard.tsx | 25 + packages/contracts/abis/MerkleRedeem.ts | 7 +- packages/contracts/abis/NftGiveaway.ts | 9 +- packages/contracts/abis/NftWearables.ts | 9 +- packages/contracts/abis/README.md | 13 + packages/shared/auth/siwe.ts | 14 - packages/shared/auth/siweClient.ts | 5 + packages/shared/auth/siweServer.ts | 11 + packages/shared/config/chains.ts | 15 + packages/shared/utils/stringHelpers.ts | 2 + packages/shared/utils/wearableMetadata.ts | 1 - yarn.lock | 1377 ++++++++++++++--- 35 files changed, 1447 insertions(+), 541 deletions(-) delete mode 100644 packages/api/src/claims/router.ts create mode 100644 packages/api/src/utils/wagmiClient.ts create mode 100644 packages/api/src/wearables/router.ts rename packages/api/src/{claims => wearables}/types.ts (70%) delete mode 100644 packages/app/features/closet/Closet.tsx delete mode 100644 packages/app/features/closet/useWearables.ts delete mode 100644 packages/app/features/closet/utils/nft.ts create mode 100644 packages/app/features/inventory/Inventory.tsx rename packages/app/features/{closet/useWearableClaim.ts => inventory/useClaimWearables.ts} (60%) delete mode 100644 packages/app/lib/ConnectWalletButton.native.tsx delete mode 100644 packages/app/provider/web3/chains.tsx create mode 100644 packages/app/ui/components/WearableCard.tsx create mode 100644 packages/contracts/abis/README.md delete mode 100644 packages/shared/auth/siwe.ts create mode 100644 packages/shared/auth/siweClient.ts create mode 100644 packages/shared/auth/siweServer.ts create mode 100644 packages/shared/config/chains.ts diff --git a/apps/next/package.json b/apps/next/package.json index 92b0ea4..e6d223e 100644 --- a/apps/next/package.json +++ b/apps/next/package.json @@ -15,7 +15,7 @@ "@expo/next-adapter": "^4.0.13", "@mf/api": "*", "app": "*", - "connectkit-next-siwe": "^0.0.2", + "connectkit-next-siwe": "0.1.0", "next": "^13.0.6", "next-auth": "^4.16.4", "raf": "^3.4.1", diff --git a/apps/next/pages/api/siwe/[...route].ts b/apps/next/pages/api/siwe/[...route].ts index 9a5c7d3..83202e1 100644 --- a/apps/next/pages/api/siwe/[...route].ts +++ b/apps/next/pages/api/siwe/[...route].ts @@ -1,2 +1,2 @@ -import { siwe } from 'shared/auth/siwe'; -export default siwe.apiRouteHandler; +import { siweServer } from 'shared/auth/siweServer'; +export default siweServer.apiRouteHandler; diff --git a/apps/next/pages/inventory.tsx b/apps/next/pages/inventory.tsx index 36720a3..56f9fc6 100644 --- a/apps/next/pages/inventory.tsx +++ b/apps/next/pages/inventory.tsx @@ -1,9 +1,9 @@ -import { NavLayout } from '../lib/NavLayout'; +import { NavLayout } from '~/lib/NavLayout'; import type { SolitoPage } from 'solito'; -import { SecondScreen } from 'app/features/home/SecondScreen'; +import { Inventory } from 'app/features/inventory/Inventory'; -const Settings: SolitoPage = () => ; +const InventoryPage: SolitoPage = () => ; -Settings.getLayout = (page) => {page}; +InventoryPage.getLayout = (page) => {page}; -export default Settings; +export default InventoryPage; diff --git a/packages/api/package.json b/packages/api/package.json index bccb0f6..c7cc149 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -12,6 +12,7 @@ "dependencies": { "@trpc/client": "10.8.2", "@trpc/server": "10.8.2", + "@wagmi/core": "0.10.8", "graphql-request": "^5.1.0", "services": "*", "shared": "*", diff --git a/packages/api/src/claims/router.ts b/packages/api/src/claims/router.ts deleted file mode 100644 index 0cfc4f5..0000000 --- a/packages/api/src/claims/router.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { createTRPCRouter, protectedProcedure, publicProcedure } from '../trpc'; -import { z } from 'zod'; -import { - baseProductsSelector, - contributorsSelector, -} from '../products/selectors'; -import { productsFilesSelector } from 'services/mfos/products/selectors'; -import { ResolverInputTypes } from 'services/mfos'; -import { - getProductTags, - getProgressFromTagsAndStage, -} from 'shared/utils/productHelpers'; -import { NftClaim } from './types'; - -export const claimsRouter = createTRPCRouter({ - wearableMerkleClaims: protectedProcedure - .input(z.string().optional().default('mainnet')) - .query(async ({ ctx, input }) => { - const network = input; - - const res = await ctx.hasuraClient.query({ - robot_merkle_claims: [ - { - where: { - merkle_root: { network: { _eq: network } }, - recipient_eth_address: { _eq: ctx.session.address }, - }, - }, - { - claim_json: [{ path: '' }, true], - merkle_root_hash: true, - }, - ], - }); - - const nftClaimArray = res.robot_merkle_claims as NftClaim[]; - const currentNftClaims = nftClaimArray.map((nftClaim) => { - const claim_count = nftClaim.claim_json.erc1155[0].ids.length; - - return { - ...nftClaim, - claim_json: { - ...nftClaim.claim_json, - claim_count, - }, - }; - }); - - return currentNftClaims; - }), - byId: publicProcedure - .input(z.string().optional()) - .query(async ({ ctx, input }) => { - if (!input) return null; - - const res = await ctx.mfosClient('query')({ - products_by_id: [ - { id: input }, - { - ...baseProductsSelector, - ...contributorsSelector, - ...productsFilesSelector, - }, - ], - }); - - return res.products_by_id; - }), -}); diff --git a/packages/api/src/root.ts b/packages/api/src/root.ts index 881bbb9..da5e50d 100644 --- a/packages/api/src/root.ts +++ b/packages/api/src/root.ts @@ -1,12 +1,12 @@ import { createTRPCRouter } from './trpc'; import { productRouter } from './products/router'; import { authRouter } from './auth/router'; -import { claimsRouter } from './claims/router'; +import { wearablesRouter } from './wearables/router'; export const appRouter = createTRPCRouter({ product: productRouter, auth: authRouter, - claims: claimsRouter, + wearables: wearablesRouter, }); // export type definition of API diff --git a/packages/api/src/trpc.ts b/packages/api/src/trpc.ts index 25ca1da..6abfd3a 100644 --- a/packages/api/src/trpc.ts +++ b/packages/api/src/trpc.ts @@ -17,13 +17,16 @@ * */ import { type CreateNextContextOptions } from '@trpc/server/adapters/next'; +import { Chain } from 'wagmi'; -import { siwe, SiweSession } from 'shared/auth/siwe'; +import { siweServer, SiweSession } from 'shared/auth/siweServer'; import { mfosClient } from 'services/mfos/client'; import { hasuraClient } from 'services/graphql/client'; +import { ChainsById } from 'shared/config/chains'; interface CreateInnerContextOptions { session: SiweSession | null; + chain: Chain; } /** * This helper generates the "internals" for a tRPC context. If you need to use @@ -37,6 +40,7 @@ interface CreateInnerContextOptions { const createInnerTRPCContext = (opts: CreateInnerContextOptions) => { return { session: opts.session, + chain: opts.chain, mfosClient, hasuraClient, }; @@ -50,11 +54,11 @@ const createInnerTRPCContext = (opts: CreateInnerContextOptions) => { export const createTRPCContext = async (opts: CreateNextContextOptions) => { const { req, res } = opts; - // Get the session from the server using the unstable_getServerSession wrapper function - const session = await siwe.getSession(req, res); + const session = await siweServer.getSession(req, res); return createInnerTRPCContext({ session, + chain: ChainsById[session?.chainId || 1], }); }; diff --git a/packages/api/src/utils/wagmiClient.ts b/packages/api/src/utils/wagmiClient.ts new file mode 100644 index 0000000..214a662 --- /dev/null +++ b/packages/api/src/utils/wagmiClient.ts @@ -0,0 +1,7 @@ +import { createClient } from '@wagmi/core'; +import { provider, webSocketProvider } from 'shared/config/chains'; + +export const wagmiCoreClient = createClient({ + provider, + webSocketProvider, +}); diff --git a/packages/api/src/wearables/router.ts b/packages/api/src/wearables/router.ts new file mode 100644 index 0000000..9313606 --- /dev/null +++ b/packages/api/src/wearables/router.ts @@ -0,0 +1,94 @@ +import { createTRPCRouter, protectedProcedure, publicProcedure } from '../trpc'; +import { z } from 'zod'; +import { readContract } from '@wagmi/core'; +import { BigNumber } from '@ethersproject/bignumber'; + +import { + NftWearablesAbi, + NftWearablesAddress, +} from 'contracts/abis/NftWearables'; +import { NftClaim } from './types'; +import { productNftMetadataSelector } from 'services/mfos/products/selectors'; +import { getMetadataForProduct } from 'shared/utils/wearableMetadata'; + +export const wearablesRouter = createTRPCRouter({ + merkleClaims: protectedProcedure.query(async ({ ctx }) => { + const res = await ctx.hasuraClient.query({ + robot_merkle_claims: [ + { + where: { + merkle_root: { network: { _eq: ctx.chain.network } }, + recipient_eth_address: { _eq: ctx.session.address }, + }, + }, + { + claim_json: [{}, true], + merkle_root_hash: true, + }, + ], + }); + + return res.robot_merkle_claims as NftClaim[]; + // return nftClaimArray.map((nftClaim) => { + // const claim_count = nftClaim.claim_json.erc1155[0].ids.length; + // + // return { + // ...nftClaim, + // claim_json: { + // ...nftClaim.claim_json, + // }, + // }; + // }); + }), + byAddress: publicProcedure + .input(z.string().optional()) + .query(async ({ ctx, input }) => { + const address = input || ctx.session?.address; + if (!address) return null; + + const tokenIdRes = await ctx.mfosClient('query')({ + products: [ + { filter: { nft_token_id: { _nnull: true } } }, + { nft_token_id: true, id: true }, + ], + }); + + const allTokenIds = tokenIdRes.products.map((p) => + // Query filters non nulls + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + BigNumber.from(p.nft_token_id!), + ); + + const balances = await readContract({ + address: NftWearablesAddress[ctx.chain.id], + abi: NftWearablesAbi, + functionName: 'balanceOfBatch', + args: [Array(allTokenIds.length).fill(address), allTokenIds], + chainId: ctx.chain.id, + }); + + const tokenIdsForUser = balances.reduce( + (ids: number[], balance, index) => { + if (balance.isZero()) return ids; + + const tokenId = allTokenIds[index].toNumber(); + return [...ids, tokenId]; + }, + [], + ); + + const nftMetadataRes = await ctx.mfosClient('query')({ + products: [ + { filter: { nft_token_id: { _in: tokenIdsForUser } } }, + productNftMetadataSelector, + ], + }); + + return (nftMetadataRes.products || []).map((p) => ({ + id: p.id, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + nft_token_id: p.nft_token_id!, + nft_metadata: getMetadataForProduct(p), + })); + }), +}); diff --git a/packages/api/src/claims/types.ts b/packages/api/src/wearables/types.ts similarity index 70% rename from packages/api/src/claims/types.ts rename to packages/api/src/wearables/types.ts index af37ab7..ec23a4c 100644 --- a/packages/api/src/claims/types.ts +++ b/packages/api/src/wearables/types.ts @@ -1,3 +1,5 @@ +import type { HexString } from 'shared/utils/stringHelpers'; + export type NftItem = { nft_token_id: number; id: number; @@ -14,9 +16,9 @@ export type NftItem = { export type NftClaim = { claim_json: { - to: string; + to: HexString; erc1155: { - contractAddress: string; + contractAddress: HexString; ids: string[]; values: number[]; }[]; @@ -25,9 +27,8 @@ export type NftClaim = { contractAddresses: never[]; amounts: never[]; }; - salt: string; - proof: string[]; - claim_count: number; + salt: HexString; + proof: HexString[]; }; - merkle_root_hash: string; + merkle_root_hash: HexString; }; diff --git a/packages/app/features/closet/Closet.tsx b/packages/app/features/closet/Closet.tsx deleted file mode 100644 index 5110269..0000000 --- a/packages/app/features/closet/Closet.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { createParam } from 'solito'; -import { H3, TextLink } from 'app/ui/typography'; -import { Box } from 'app/ui/layout/Box'; -import { api } from 'app/lib/api'; - -export const { useParam } = createParam<{ username: string }>(); - -export function ClosetScreen() { - const [username] = useParam('username'); - const { data, isLoading } = api.claims.wearableMerkleClaims.useQuery(); - - return ( - -

{`Username: ${username}`}

- - 👈 Go Home - Go to Posts -
- ); -} diff --git a/packages/app/features/closet/useWearables.ts b/packages/app/features/closet/useWearables.ts deleted file mode 100644 index 1594b3a..0000000 --- a/packages/app/features/closet/useWearables.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { useQuery } from '@tanstack/react-query'; -import { utils, BigNumberish } from 'ethers'; -import { useContractRead } from 'wagmi'; -import _ from 'lodash'; -import { - NftWearablesAddress, - NftWearablesAbi, -} from 'contracts/abis/NftWearables'; -import { parseIds } from './utils/nft'; - -const useNfts = () => { - const fetchNfts = async () => { - return fetch('api/nftMetadata') - .then((res) => res.json()) - .then((data) => { - const initialObject: { [key: number]: any } = {}; - const nftListObject = _.reduce( - data, - (result: Record, nft: any) => - (result[nft.nft_token_id] = nft), - initialObject, - ); - - return { nfts: nftListObject, nftIds: parseIds(nftListObject) }; - }) - .catch((err) => { - console.log(err); - return { nfts: {}, nftIds: [] }; - }); - }; - - const { data, isLoading, error } = useQuery< - { nfts: any; nftIds: any }, - Error - >(['nfts'], fetchNfts); - - const nfts = _.get(data, 'nfts', null); - const nftIds = _.get(data, 'nftIds', null); - - return { nfts, nftIds, isLoading, error }; -}; - -// useWearablesForAddress ? -/** - * Fetches the claimed wearables for a given address - * @param address address of the user - * @returns list of wearables `parsedBalances` or error - */ -export const useWearables = ({ address }: { address: string }) => { - const { nfts, nftIds } = useNfts(); - const { data: rawWearables, error } = useContractRead({ - address: NftWearablesAddress.mainnet, - abi: NftWearablesAbi, - functionName: 'balanceOfBatch', - args: [Array(nftIds.length).fill(address), nftIds], - enabled: !!nfts && !!nftIds, - }); - - if (!nftIds || !rawWearables) return { wearables: [], parsedBalances: [] }; - - const parsedBalances = _.map(rawWearables, (balance: BigNumberish) => - utils.formatUnits(balance, 0), - ); - - // reduce to nft items only with existing balance - const wearables = parsedBalances.reduce( - (sum: any[], currentValue: boolean | string, currentIndex: number) => { - if (currentValue === '0') return sum; - - const nftId = nftIds[currentIndex]; - const currentItem = nfts[nftId]; - sum.push(currentItem); - - return sum; - }, - [], - ); - - return { wearables, rawWearables, error }; -}; diff --git a/packages/app/features/closet/utils/nft.ts b/packages/app/features/closet/utils/nft.ts deleted file mode 100644 index 595f5c0..0000000 --- a/packages/app/features/closet/utils/nft.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const parseIds = (nfts: { [key: string]: any }) => { - if (!nfts) return []; - - return Object.keys(nfts).map((key: string) => nfts[key].nft_token_id); -}; diff --git a/packages/app/features/inventory/Inventory.tsx b/packages/app/features/inventory/Inventory.tsx new file mode 100644 index 0000000..54ec318 --- /dev/null +++ b/packages/app/features/inventory/Inventory.tsx @@ -0,0 +1,42 @@ +import { H3 } from 'app/ui/typography'; +import { Box } from 'app/ui/layout/Box'; +import { api } from 'app/lib/api'; +import { formatAddress } from 'shared/utils/addressHelpers'; +import { WearableCard } from 'app/ui/components/WearableCard'; +import { useAccount } from 'wagmi'; + +type InventoryProps = { + // address?: string; +}; + +export const Inventory: React.FC = () => { + const { address } = useAccount(); + const { data, isLoading } = api.wearables.byAddress.useQuery(address); + + const formattedAddress = formatAddress(address); + + return ( + +

{`${formattedAddress}'s Inventory`}

+ + {data ? ( + data.map((wearable) => { + return ( + + ); + }) + ) : ( +

{isLoading ? 'Loading' : 'No Wearables'}

+ )} +
+
+ ); +}; diff --git a/packages/app/features/closet/useWearableClaim.ts b/packages/app/features/inventory/useClaimWearables.ts similarity index 60% rename from packages/app/features/closet/useWearableClaim.ts rename to packages/app/features/inventory/useClaimWearables.ts index 42ef2f7..56e44ce 100644 --- a/packages/app/features/closet/useWearableClaim.ts +++ b/packages/app/features/inventory/useClaimWearables.ts @@ -3,24 +3,25 @@ import { useContractRead, usePrepareContractWrite, useContractWrite, + mainnet, } from 'wagmi'; import { api } from 'app/lib/api'; import { NftGiveawayAddress, NftGiveawayAbi } from 'contracts/abis/NftGiveaway'; +import { BigNumber } from 'ethers'; -export const useWearableClaim = ({ address }: { address: string }) => { +export const useClaimWearables = ({ address }: { address: `0x${string}` }) => { const { data: wearableClaims, isLoading: wearableClaimsLoading } = - api.claims.wearableMerkleClaims.useQuery(); + api.wearables.merkleClaims.useQuery(); - const rootHashes = wearableClaims?.map( - (nftClaim) => nftClaim.merkle_root_hash, - ); + const rootHashes = + wearableClaims?.map((nftClaim) => nftClaim.merkle_root_hash) || []; const { data: claimedStatuses, isLoading: claimStatusLoading } = useContractRead({ abi: NftGiveawayAbi, - address: NftGiveawayAddress.mainnet, + address: NftGiveawayAddress[mainnet.id], functionName: 'getClaimedStatus', args: [address, rootHashes], - enabled: !!address && !!rootHashes, + enabled: Boolean(address && rootHashes.length), }); const unclaimedWearableClaims = _.reduce( @@ -30,7 +31,7 @@ export const useWearableClaim = ({ address }: { address: string }) => { currentValue: boolean, currentIndex: number, ) => { - if (currentValue === true || !wearableClaims) return unclaimed; + if (currentValue || !wearableClaims) return unclaimed; const unclaimedNftClaim = wearableClaims[currentIndex]; @@ -41,19 +42,25 @@ export const useWearableClaim = ({ address }: { address: string }) => { [], ); - const claims = _.map(wearableClaims, (nftClaim) => - _.omit(nftClaim.claim_json, ['claim_count']), - ); + const claimsJSON = _.map(wearableClaims, (nftClaim) => ({ + ...nftClaim.claim_json, + erc1155: nftClaim.claim_json.erc1155.map((nft) => ({ + ...nft, + // TODO: test if it works without converting to BigNumber + ids: nft.ids.map(BigNumber.from), + values: nft.values.map(BigNumber.from), + })), + })); const merkleProofs = _.map( wearableClaims, (nftClaim) => nftClaim.claim_json.proof, ); const { config } = usePrepareContractWrite({ - address: NftGiveawayAddress.mainnet, + address: NftGiveawayAddress[mainnet.id], abi: NftGiveawayAbi, functionName: 'claimMultipleTokensFromMultipleMerkleTree', - args: [rootHashes, claims, merkleProofs], + args: [rootHashes, claimsJSON, merkleProofs], }); const claimWearablesWrite = useContractWrite(config); diff --git a/packages/app/features/rewards/useClaims.ts b/packages/app/features/rewards/useClaims.ts index a01cd1d..6a427a7 100644 --- a/packages/app/features/rewards/useClaims.ts +++ b/packages/app/features/rewards/useClaims.ts @@ -12,6 +12,7 @@ import { useContractRead, usePrepareContractWrite, useContractWrite, + mainnet, } from 'wagmi'; import { BigNumber } from 'ethers'; import { @@ -37,7 +38,7 @@ const useClaims = () => { const { data: unclaimedWeeks } = useContractRead({ abi: MerkleRedeemABI, - address: MerkleRedeemAddress.mainnet, + address: MerkleRedeemAddress[mainnet.id], functionName: 'claimStatus', args: [ address || '0x', @@ -99,7 +100,7 @@ const useClaims = () => { const { config, ...rest } = usePrepareContractWrite({ abi: MerkleRedeemABI, - address: MerkleRedeemAddress.mainnet, + address: MerkleRedeemAddress[mainnet.id], functionName: 'claimWeeks', args: [address || '0x', claimWeeksProofs], }); diff --git a/packages/app/lib/ConnectWalletButton.native.tsx b/packages/app/lib/ConnectWalletButton.native.tsx deleted file mode 100644 index 67d24ff..0000000 --- a/packages/app/lib/ConnectWalletButton.native.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { useWalletConnect } from 'app/lib/walletconnect'; -import { useAccount, useBalance, useConnect, useDisconnect } from 'wagmi'; -import { useEffect } from 'react'; -import { WalletConnectConnector } from 'wagmi/connectors/walletConnect'; -import { Button } from 'app/ui/input/Button'; -import { Text } from 'app/ui/typography'; - -export const ConnectWalletButton = () => { - const connector = useWalletConnect(); - - const { connect } = useConnect({ - connector: new WalletConnectConnector({ - options: { - qrcode: false, - connector, - }, - }), - }); - const { disconnect } = useDisconnect(); - - const { address } = useAccount(); - const { data: balance } = useBalance({ address }); - - useEffect(() => { - if (connector?.accounts?.length && !address) { - connect(); - } else { - disconnect(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [connector]); - - if (address) { - return ( - <> -