Skip to content

Commit

Permalink
feat: update nft subvariant to support drawer and send to another wallet
Browse files Browse the repository at this point in the history
  • Loading branch information
chybisov committed Jun 14, 2023
1 parent a3e8deb commit 87d8927
Show file tree
Hide file tree
Showing 36 changed files with 511 additions and 480 deletions.
26 changes: 12 additions & 14 deletions packages/widget-embedded/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { LiFiWidget } from '@lifi/widget';
import { Box, CssBaseline } from '@mui/material';
import { useState } from 'react';
import type { NFTNetwork } from './components/NFTOpenSea';
import { NFTOpenSea, openSeaContractTool } from './components/NFTOpenSea';
import {
NFTOpenSea,
NFTOpenSeaSecondary,
openSeaContractTool,
} from './components/NFTOpenSea';
import { WidgetEvents } from './components/WidgetEvents';
import { widgetConfig } from './config';
import './index.css';
Expand All @@ -12,19 +16,6 @@ export const App = () => {
Object.fromEntries(new URLSearchParams(window?.location.search)),
);
const pathnameParams = window.location.pathname.substring(1).split('/');
// const {
// isLoading,
// imageUrl,
// collectonName,
// assetName,
// owner,
// token,
// contract,
// } = useNFTOpenSea({
// network: pathnameParams[0] as NFTNetwork,
// contractAddress: pathnameParams[1],
// tokenId: pathnameParams[2],
// });

return (
<Box display="flex" height="100vh">
Expand All @@ -39,6 +30,13 @@ export const App = () => {
tokenId={pathnameParams[2]}
/>
}
contractSecondaryComponent={
<NFTOpenSeaSecondary
network={pathnameParams[0] as NFTNetwork}
contractAddress={pathnameParams[1]}
tokenId={pathnameParams[2]}
/>
}
contractTool={openSeaContractTool}
config={widgetConfig}
integrator={widgetConfig.integrator}
Expand Down
141 changes: 9 additions & 132 deletions packages/widget-embedded/src/components/NFTOpenSea/NFTOpenSea.tsx
Original file line number Diff line number Diff line change
@@ -1,143 +1,20 @@
import type { ChainId, TokenAmount } from '@lifi/sdk';
import type { WidgetContract } from '@lifi/widget';
import { NFT, useWallet } from '@lifi/widget';
import { NFT } from '@lifi/widget';
import { Box, Typography } from '@mui/material';
import { Seaport } from '@opensea/seaport-js';
import { useQuery } from '@tanstack/react-query';
import { useState } from 'react';
import type {
FulfillmentDataResponse,
NFTNetwork,
NFTOpenSeaProps,
OrdersQueryResponse,
} from './types';
import { ChainId as OpenSeaChainId } from './types';
import { deserializeOrder } from './utils';
import type { NFTOpenSeaProps } from './types';
import { useOpenSeaFulfillment } from './useOpenSeaFulfillment';

export const NFTOpenSea: React.FC<NFTOpenSeaProps> = ({
network,
contractAddress,
tokenId,
}) => {
const { account, switchChain } = useWallet();
const [contract, setContract] = useState<WidgetContract>();
const { data, isLoading } = useQuery(
['nft', network, contractAddress, tokenId, account.address],
async ({
queryKey: [, network, contractAddress, tokenId, accountAddress],
}) => {
const ordersQueryResponse: OrdersQueryResponse = await fetch(
`https://api.opensea.io/v2/orders/${network}/seaport/listings?asset_contract_address=${contractAddress}&token_ids=${tokenId}&order_by=created_date&order_direction=desc`,
{
method: 'GET',
headers: {
accept: 'application/json',
'X-API-KEY': import.meta.env.VITE_OPENSEA_API_KEY,
},
},
).then((response) => response.json());

if (!ordersQueryResponse.orders[0]) {
return;
}

const fulfillmentDataResponse: FulfillmentDataResponse = await fetch(
`https://api.opensea.io/v2/listings/fulfillment_data`,
{
method: 'POST',
headers: {
'content-type': 'application/json',
'X-API-KEY': import.meta.env.VITE_OPENSEA_API_KEY,
},
body: JSON.stringify({
listing: {
hash: ordersQueryResponse.orders[0].order_hash,
chain: network,
protocol_address: ordersQueryResponse.orders[0].protocol_address,
},
fulfiller: {
address: accountAddress,
},
}),
},
).then((response) => response.json());

const order = deserializeOrder(ordersQueryResponse.orders[0]);
order.protocolData = fulfillmentDataResponse.fulfillment_data.orders[0];

const fulfillOrder = async () => {
try {
const seaport = new Seaport(account.signer as any, {
seaportVersion: '1.5',
});

const { actions } = await seaport.fulfillOrder({
order: order.protocolData,
accountAddress: account.address,
recipientAddress: account.address,
});

const transaction =
await actions[0].transactionMethods.buildTransaction();
const estimatedGas =
await actions[0].transactionMethods.estimateGas();

setContract({
address: transaction.to,
callData: transaction.data,
gasLimit: estimatedGas.toString(),
});
} catch (error: any) {
if (error.code === 'CALL_EXCEPTION') {
const switched = await switchChain(
OpenSeaChainId[network as NFTNetwork],
);
if (switched) {
await fulfillOrder();
} else {
throw error;
}
} else {
throw error;
}
}
};
await fulfillOrder();

const asset = order?.makerAssetBundle.assets[0];
const owner = {
name:
order?.maker.user?.username ||
order?.maker.address.substring(2, 8).toUpperCase(),
url: `https://opensea.io/${
order?.maker.user?.username || order?.maker.address
}`,
};
const token: TokenAmount = {
symbol: order?.takerAssetBundle.assets[0]?.assetContract?.tokenSymbol!,
amount: order?.currentPrice!,
decimals: order?.takerAssetBundle.assets[0].decimals!,
address: order?.takerAssetBundle.assets[0].tokenAddress!,
chainId: OpenSeaChainId[network as NFTNetwork] as number as ChainId,
name: order?.takerAssetBundle.assets[0]?.assetContract.tokenSymbol!,
priceUSD: '',
};

return {
imageUrl: asset?.imageUrl,
collectionName: asset?.collection.name,
assetName: asset?.name,
owner: owner,
token: token,
contract: contract,
};
},
{
enabled: Boolean(account.address),
},
const { data, order, isLoading, isOrderLoading } = useOpenSeaFulfillment(
network,
contractAddress,
tokenId,
);

return !data && !isLoading ? (
return !data && !order && !isLoading && !isOrderLoading ? (
<Box
p={2}
sx={{
Expand All @@ -164,7 +41,7 @@ export const NFTOpenSea: React.FC<NFTOpenSeaProps> = ({
assetName={data?.assetName}
owner={data?.owner}
token={data?.token}
contract={contract}
contract={data?.contract}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { ChainId, TokenAmount } from '@lifi/sdk';
import { NFTBase } from '@lifi/widget';
import type { NFTNetwork, NFTOpenSeaProps } from './types';
import { ChainId as OpenSeaChainId } from './types';
import { useOpenSeaOrder } from './useOpenSeaOrder';

export const NFTOpenSeaSecondary: React.FC<NFTOpenSeaProps> = ({
network,
contractAddress,
tokenId,
}) => {
const { data: order, isLoading: isOrderLoading } = useOpenSeaOrder(
network,
contractAddress,
tokenId,
);

const asset = order?.makerAssetBundle.assets[0];
const owner = {
name:
order?.maker.user?.username ||
order?.maker.address.substring(2, 8).toUpperCase(),
url: `https://opensea.io/${
order?.maker.user?.username || order?.maker.address
}`,
};
const token: TokenAmount = {
symbol: order?.takerAssetBundle.assets[0]?.assetContract?.tokenSymbol!,
amount: order?.currentPrice!,
decimals: order?.takerAssetBundle.assets[0].decimals!,
address: order?.takerAssetBundle.assets[0].tokenAddress!,
chainId: OpenSeaChainId[network as NFTNetwork] as number as ChainId,
name: order?.takerAssetBundle.assets[0]?.assetContract.tokenSymbol!,
priceUSD: '',
};

return (
<NFTBase
isLoading={isOrderLoading}
imageUrl={asset?.imageUrl}
collectionName={asset?.collection.name}
assetName={asset?.name}
owner={owner}
token={token}
/>
);
};
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './NFTOpenSea';
export * from './NFTOpenSeaSecondary';
export * from './types';
export * from './useNFTOpenSea';
135 changes: 0 additions & 135 deletions packages/widget-embedded/src/components/NFTOpenSea/useNFTOpenSea.tsx

This file was deleted.

Loading

0 comments on commit 87d8927

Please sign in to comment.