diff --git a/.i18n-codegen.json b/.i18n-codegen.json index ded70c3006bd..fcf48baa424b 100644 --- a/.i18n-codegen.json +++ b/.i18n-codegen.json @@ -229,6 +229,18 @@ "trans": "Translate", "sourceMap": "inline" } + }, + { + "input": "./packages/plugins/Traderxyz/src/locales/en-US.json", + "output": "./packages/plugins/Traderxyz/src/locales/i18n_generated", + "parser": "i18next", + "generator": { + "type": "i18next/react-hooks", + "hooks": "useI18N", + "namespace": "io.mask.traderxyz", + "trans": "Translate", + "sourceMap": "inline" + } } ] } diff --git a/cspell.json b/cspell.json index 9e1391ac7183..d4f5bdc4a0a9 100644 --- a/cspell.json +++ b/cspell.json @@ -122,6 +122,7 @@ "newsfeed", "nftrss", "nftscan", + "nftswap", "nums", "openswap", "openx", @@ -179,6 +180,7 @@ "tokenid", "topbar", "traderjoe", + "traderxyz", "transak", "trisolaris", "twimg", @@ -257,6 +259,7 @@ "ifrandom", "iife", "inpage", + "itemavatar", "koda", "kodav", "lngs", @@ -267,6 +270,7 @@ "metaplex", "metaswap", "nftred", + "nftswap", "nftx", "nonfungiblefriends", "northcutt", @@ -292,6 +296,7 @@ "tinycolor", "tipable", "traderjoexyz", + "traderxyz", "treeshake", "txes", "txreceipt", diff --git a/packages/mask/package.json b/packages/mask/package.json index 25d28a0b9d5a..823e99f5727d 100644 --- a/packages/mask/package.json +++ b/packages/mask/package.json @@ -32,6 +32,7 @@ "@masknet/plugin-infra": "workspace:*", "@masknet/plugin-rss3": "workspace:*", "@masknet/plugin-solana": "workspace:*", + "@masknet/plugin-traderxyz": "workspace:*", "@masknet/plugin-wallet": "workspace:*", "@masknet/public-api": "workspace:*", "@masknet/sdk": "workspace:*", diff --git a/packages/mask/src/plugin-infra/register.js b/packages/mask/src/plugin-infra/register.js index 2c38073d8643..be52095423a6 100644 --- a/packages/mask/src/plugin-infra/register.js +++ b/packages/mask/src/plugin-infra/register.js @@ -12,6 +12,7 @@ import '@masknet/plugin-solana' import '@masknet/plugin-cyberconnect' import '@masknet/plugin-go-plus-security' import '@masknet/plugin-cross-chain-bridge' +import '@masknet/plugin-traderxyz' import '../plugins/Wallet' import '../plugins/EVM' import '../plugins/RedPacket' diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index 99697cefb7ed..36463a14544e 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -731,6 +731,7 @@ export enum PluginId { CyberConnect = 'me.cyberconnect.app', GoPlusSecurity = 'io.gopluslabs.security', CrossChainBridge = 'io.mask.cross-chain-bridge', + Traderxyz = 'io.mask.traderxyz', // @masknet/scripts: insert-here } /** diff --git a/packages/plugins/Traderxyz/README.md b/packages/plugins/Traderxyz/README.md new file mode 100644 index 000000000000..d2cf1381312f --- /dev/null +++ b/packages/plugins/Traderxyz/README.md @@ -0,0 +1,43 @@ +# Traderyx Plugin + +Buy and Sell NFT through social media platform in few clicks faster and chaper. + +## Features + +- [x] Create orders (Sell NFT) +- [x] Post orders (View NFT) +- [x] Fulfill orders (Buy NFT) + +## Pull requests + +- + +## Referenced resources + +NFRSWAP SDK: + +## Screenshots + +### Order compose + +#### Step 1 (Select the NFT) + + image + +#### Step 2 (Select the Receiving Currency) + + image + +#### Step 3 (Review and post) + + image + +### POST preview + +#### Twitter preview + + image + +## Authors + +- [@vaimeo](https://www.github.com/vaimeo) diff --git a/packages/plugins/Traderxyz/package.json b/packages/plugins/Traderxyz/package.json new file mode 100644 index 000000000000..04515fd08134 --- /dev/null +++ b/packages/plugins/Traderxyz/package.json @@ -0,0 +1,31 @@ +{ + "name": "@masknet/plugin-traderxyz", + "private": true, + "exports": { + ".": { + "webpack": "./src/index.ts", + "default": "./dist/index.js" + } + }, + "types": "./dist/index.d.ts", + "dependencies": { + "@ethersproject/providers": "5.6.4", + "@masknet/icons": "workspace:*", + "@masknet/plugin-infra": "workspace:*", + "@masknet/plugin-wallet": "workspace:*", + "@masknet/shared": "workspace:*", + "@masknet/shared-base": "workspace:*", + "@masknet/shared-base-ui": "workspace:*", + "@masknet/theme": "workspace:*", + "@masknet/typed-message": "workspace:*", + "@masknet/web3-providers": "workspace:*", + "@masknet/web3-shared-base": "workspace:*", + "@masknet/web3-shared-evm": "workspace:*", + "@traderxyz/nft-swap-sdk": "^0.22.1", + "bignumber.js": "^9.0.2", + "react-use": "^17.3.2", + "urlcat": "^2.0.4", + "use-subscription": "^1.7.0", + "web3": "1.7.3" + } +} diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/PostPreview.tsx b/packages/plugins/Traderxyz/src/SNSAdaptor/PostPreview.tsx new file mode 100644 index 000000000000..5a01f3c5393d --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/PostPreview.tsx @@ -0,0 +1,301 @@ +import { Box, Chip, Grid, Typography, useTheme } from '@mui/material' +import { makeStyles, useCustomSnackbar } from '@masknet/theme' +import { useI18N } from '../locales/i18n_generated' +import { usePluginWrapper } from '@masknet/plugin-infra/content-script' +import { useAccount, useChainId } from '@masknet/web3-shared-evm' +import { useTraderApi } from '../apis/nftSwap' +import type { TradeMetaData, NFTData } from '../types' +import type { SwappableAsset } from '@traderxyz/nft-swap-sdk' +import { ActionButtonPromise } from '../../../../mask/src/extension/options-page/DashboardComponents/ActionButton' +import { useCallback, useMemo } from 'react' + +const useStyles = makeStyles()((theme, props) => ({ + actions: { + alignSelf: 'center', + }, + mainWrapper: { + height: 400, + borderRadius: 10, + border: 1, + borderColor: ' blue !important', + }, + + bodyContent: { + height: 400, + background: '#cddc39', + color: '#000000', + borderRadius: 10, + }, + + button: { + borderRadius: 99, + marginTop: 0, + fontSize: 14, + fontWeight: 400, + lineHeight: 19.6, + height: 40, + paddingTop: 8, + paddingLeft: 16, + paddingBottom: 8, + paddingRight: 16, + backgroundColor: theme.palette.mode === 'dark' ? '#EFF3F4' : '#111418', + color: theme.palette.mode === 'dark' ? '#0F1419' : '#FFFFFF', + }, + buttonWrapper: { + marginTop: 10, + marginBottom: 10, + }, + img: { + borderRadius: 10, + }, + previewBoxOuter: { + boxShadow: 'rgb(0 0 0 / 4%) 0px 6px 40px, rgb(0 0 0 / 2%) 0px 3px 6px', + background: theme.palette.mode === 'dark' ? '#1D2933' : 'rgb(255, 255, 255)', + width: '100%', + border: '0px solid blue', + borderRadius: 16, + height: '310px', + }, + + previewBoxInner: { + background: theme.palette.mode === 'dark' ? '#000000' : 'rgb(245, 245, 247)', + width: '100%', + border: '0px solid blue', + borderRadius: 10, + height: '190px', + }, + + previewBoxInnerGridContainer: { + display: 'flex', + borderCollapse: 'collapse', + width: '100%', + border: '0px solid green', + alignItems: 'center', + justifyContent: 'space-evenly', + borderRadius: 15, + }, + + previewBoxInnerGridContainerItem: { + display: 'table-cell', + height: '190px', + border: '0px solid green', + }, + previewBoxInnerGridContainerItemImg: { + height: '100%', + maxWidth: '100%', + objectFit: 'cover', + borderRadius: '10px', + userSelect: 'none', + }, + previewBoxInnerGridContainerChip: { + position: 'relative', + left: '65%', + top: '-35px', + background: theme.palette.mode === 'dark' ? '#1D2933' : 'rgb(23, 23, 23)', + color: 'white', + fontSize: '18px', + border: '1px solid rgb(0, 0, 0)', + padding: '10px 5px 10px', + }, + previewBoxInnerGridFooterTitle1: { + fontWeight: 500, + fontSize: '18px', + color: theme.palette.mode === 'dark' ? '#ffffff' : '#000000', + }, + previewBoxInnerGridFooterTitle2: { + fontWeight: 'normal', + fontSize: '14px', + color: theme.palette.mode === 'dark' ? '#ffffff' : '#000000', + }, +})) + +/** + * This page we use to full fill order + */ + +export function PostPreview({ info }: { info: TradeMetaData }) { + const selectedChainId = useChainId() + const nftSwapSdk = useTraderApi(selectedChainId) + const account = useAccount() + const { classes } = useStyles() + const t = useI18N() + const theme = useTheme() + const { showSnackbar } = useCustomSnackbar() + + const signOrder = useCallback(async () => { + const normalizeSignedOrder = nftSwapSdk.normalizeSignedOrder(info.signedOrder) + const walletAddressUserA = account + const assetsToSwapUserA = [info.assetsInfo.receiving_token, ...info.assetsInfo.nfts] + + /// Check order status + + // Invalid = 0, + // InvalidMakerAssetAmount = 1, + // InvalidTakerAssetAmount = 2, + // Fillable = 3, + // Expired = 4, + // FullyFilled = 5, + // Cancelled = 6 + + const orderStatus = await nftSwapSdk.getOrderStatus(normalizeSignedOrder) + + if (orderStatus === 3) { + // Fillable + // Check if we need to approve the NFT for swapping + const approvalStatusForUserA = await nftSwapSdk.loadApprovalStatus( + assetsToSwapUserA[0] as SwappableAsset, + walletAddressUserA, + ) + + // Check if buyer needs to approve the sell token contract or no + if (!approvalStatusForUserA.contractApproved) { + // If not approved + const approvalTx = await nftSwapSdk.approveTokenOrNftByAsset( + assetsToSwapUserA[0] as SwappableAsset, + walletAddressUserA, + ) + + await approvalTx.wait().then( + (msg) => { + const message = `Approved ${assetsToSwapUserA[0]?.tokenAddress} contract to swap with 0x (txHash: ${msg.transactionHash})` + showSnackbar(message, { variant: 'success' }) + }, + (error) => showSnackbar(t.submit_order_submit_error_message() + error, { variant: 'error' }), + ) + } + // fill order + const fillTx = await nftSwapSdk.fillSignedOrder(normalizeSignedOrder).then( + async (fillTx) => { + const fillTxReceipt = await nftSwapSdk.awaitTransactionHash(fillTx?.hash).then( + (fillTxReceipt) => { + if (fillTxReceipt.status !== 0) { + const message = `\u{1F389} \u{1F973} ${t.submit_order_filled_message()} ${ + fillTxReceipt?.transactionHash + }` + showSnackbar(message, { variant: 'success' }) + } else { + showSnackbar( + t.submit_order_submit_error_message() + fillTxReceipt?.transactionHash + ' failed', + { variant: 'error' }, + ) + } + }, + (error) => + showSnackbar(t.submit_order_submit_error_message() + ' fillTxReceipt error :' + error, { + variant: 'error', + }), + ) + }, + (error) => showSnackbar(t.submit_order_submit_error_message() + error, { variant: 'error' }), + ) + } + + if (orderStatus === 5) { + // FullyFilled + showSnackbar(t.order_filled(), { variant: 'error' }) + } + + if (orderStatus === 4) { + // Expired + showSnackbar(t.order_expired(), { variant: 'error' }) + } + + if (orderStatus === 6) { + // Cancelled + showSnackbar(t.order_cancelled(), { variant: 'error' }) + } + + if (orderStatus === 6) { + // Cancelled + showSnackbar(t.order_cancelled(), { variant: 'error' }) + } + + if (orderStatus === 0) { + // Cancelled + showSnackbar(t.order_invalid(), { variant: 'error' }) + } + + if (orderStatus === 1) { + // Invalid + showSnackbar(t.order_invalid_maker(), { variant: 'error' }) + } + + if (orderStatus === 2) { + // Invalid + showSnackbar(t.order_invalid_taker(), { variant: 'error' }) + } + }, []) + + const nftList = info.assetsInfo.preview_info.nftMediaUrls + const previewImages = nftList.map((item: NFTData, index: number) => { + return ( + + {item.nft_name} + + ) + }) + + const chipTitle = + info.assetsInfo.preview_info.receivingSymbol.amount + ' ' + info.assetsInfo.preview_info.receivingSymbol.symbol + + const labelString = useMemo(() => { + let labelString = '' + const n = nftList + + if (n && n.length > 0) { + labelString = `${t.preview_order_label_title1()} ${n[0]?.nft_name} (#${n[0]?.nft_id})` + + if (n.length > 1) { + labelString += ` ${t.preview_order_label_title2()} ${n[1]?.nft_name} (#${n[1]?.nft_id})` + } + + if (n.length > 2) { + labelString += ` ${t.preview_order_label_title3()}` + } + + labelString += ` ${t.preview_order_label_title4()} ` + chipTitle + } + + return labelString + }, [nftList]) + + usePluginWrapper(true) + return ( + + + + {previewImages} + + + + + + + {labelString} + + + + + + + + + + ) +} diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/PreviewOrderView.tsx b/packages/plugins/Traderxyz/src/SNSAdaptor/PreviewOrderView.tsx new file mode 100644 index 000000000000..c2d45d5dbf02 --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/PreviewOrderView.tsx @@ -0,0 +1,107 @@ +import { Box, Chip, Grid, IconButton, Typography, Avatar } from '@mui/material' +import { ArrowBack } from '@mui/icons-material' +import type { NFTData } from '../types' +import { useI18N } from '../locales/i18n_generated' +import { useMemo } from 'react' + +export const PreviewOrderView = (props: { + nftList: NFTData[] | undefined + setDisplaySection: Function + classes: Record + amountLabel: string +}): JSX.Element => { + const t = useI18N() + const { nftList, classes, amountLabel } = props + const child = ( + no-image + ) + + const previewImages = nftList?.map((item: NFTData, index: number) => { + return ( + + + + ) + }) + + const labelString = useMemo(() => { + let labelString = '' + + const n = nftList + if (n && n.length > 0) { + labelString = `${t.preview_order_label_title1()} ${n[0]?.nft_name} (#${n[0]?.nft_id})` + + if (n.length > 1) { + labelString += ` ${t.preview_order_label_title2()} ${n[1]?.nft_name} (#${n[1]?.nft_id})` + } + if (n.length > 2) { + labelString += ` ${t.preview_order_label_title3()}` + } + } + return labelString + }, [nftList]) + + return ( +
+ + + + { + props.setDisplaySection(false, true, false) + }}> + + + + + + {t.preview_order_heading()} + + + + + {t.preview_order_subheading()} + + + + + + + + + {previewImages} + + + + + + + {labelString} + + + {t.preview_order_confirmation_title()} + + + + + +
+ ) +} diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/SelectTokenView.tsx b/packages/plugins/Traderxyz/src/SNSAdaptor/SelectTokenView.tsx new file mode 100644 index 000000000000..a45378970a7b --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/SelectTokenView.tsx @@ -0,0 +1,113 @@ +import { useI18N } from '../locales/i18n_generated' +import { InputTokenPanel } from '../../../../../packages/mask/src/plugins/Trader/SNSAdaptor/trader/InputTokenPanel' +import { TokenPanelType } from '../../../../../packages/mask/src/plugins/Trader/types' + +import { noop } from 'lodash-unified' +import { DropIcon } from '../../../../icons/general' +import { useCallback, useState } from 'react' +import { usePickToken } from '@masknet/shared' +import { + type FungibleTokenDetailed, + ChainId, + useFungibleTokenBalance, + isSameAddress, + EthereumTokenType, + useTokenConstants, +} from '@masknet/web3-shared-evm' +import { Grid, IconButton, Typography } from '@mui/material' +import { ArrowBack } from '@mui/icons-material' + +interface SelectTokenViewProps { + chainId: ChainId + onAmountChange: Function + setDisplaySection: Function + classes: Record + inputToken: FungibleTokenDetailed | null | undefined + inputTokenAmount: string +} + +export const SelectTokenView = (props: SelectTokenViewProps): JSX.Element => { + const t = useI18N() + + const { chainId, inputToken } = props + + const [inputTokenBalance, setInputTokenBalance] = useState('0') + + const { NATIVE_TOKEN_ADDRESS } = useTokenConstants() + + const excludeTokens = inputToken ? [inputToken.address] : [] + + // #region update balance + const { value: inputTokenBalance_, loading: loadingInputTokenBalance } = useFungibleTokenBalance( + isSameAddress(inputToken?.address, NATIVE_TOKEN_ADDRESS) + ? EthereumTokenType.Native + : inputToken?.type ?? EthereumTokenType.Native, + inputToken?.address ?? '', + chainId, + ) + + const pickToken = usePickToken() + const onTokenChipClick = useCallback( + async (panelType: TokenPanelType) => { + const picked = await pickToken({ + chainId, + disableNativeToken: false, + selectedTokens: excludeTokens, + }) + if (picked) { + props.onAmountChange(picked, props.inputTokenAmount) + } + }, + [excludeTokens.join(), chainId], + ) + + return ( +
+ + + + { + props.setDisplaySection(true, false, false) + }}> + + + + + + {t.select_nft_heading()} + + + + + + { + props.onAmountChange(inputToken, a) + }} + SelectTokenChip={{ + ChipProps: { + onClick: () => onTokenChipClick(TokenPanelType.Input), + deleteIcon: ( + + ), + onDelete: noop, + }, + }} + /> + +
+ ) +} diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/TradeComposeDialog.tsx b/packages/plugins/Traderxyz/src/SNSAdaptor/TradeComposeDialog.tsx new file mode 100644 index 000000000000..7e0ff21f1f73 --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/TradeComposeDialog.tsx @@ -0,0 +1,528 @@ +import { Button, DialogActions, DialogContent, Grid, Typography } from '@mui/material' +import { makeStyles, MaskDialog, useCustomSnackbar } from '@masknet/theme' +import { useRemoteControlledDialog } from '@masknet/shared-base-ui' +import { WalletMessages } from '@masknet/plugin-wallet' +import { META_KEY } from '../constants' +import { useCompositionContext } from '@masknet/plugin-infra/content-script' +import { useChainId, useAccount } from '@masknet/plugin-infra/web3' +import { type FungibleTokenDetailed, ChainId } from '@masknet/web3-shared-evm' +import { useState } from 'react' +import { useAsync } from 'react-use' +import { amountToWei } from '../helpers' +import { useTraderApi } from '../apis/nftSwap' +import { SelectTokenView } from './SelectTokenView' +import { PreviewOrderView } from './PreviewOrderView' +import NftListView from './components/NftListView' +import { useI18N } from '../locales/i18n_generated' +import urlcat from 'urlcat' +import { OPENSEA_API_KEY, isProxyENV } from '@masknet/web3-providers' +import type { SwappableAsset } from '@traderxyz/nft-swap-sdk' + +import type { OpenSeaToken, OpenSeaCollection, Token, AssetContract, PreviewNFTList, NFTData } from '../types' + +import { isDashboardPage, isPopupPage } from '@masknet/shared-base' + +interface nfts { + tokenAddress: string + tokenId: string + type: string +} +interface orderInfo { + nfts: nfts[] | undefined | null + receiving_token: { + tokenAddress: string | undefined + amount: string + type: string + } + preview_info: { + nftMediaUrls: NFTData[] | undefined + receivingSymbol: { + symbol: string | undefined + amount: string + } + } +} + +interface Props { + onClose: () => void + open: boolean +} + +const useStyles = makeStyles<{ isDashboard: boolean; isPopup: boolean }>()((theme, { isDashboard, isPopup }) => { + return { + mainTitle: { + color: theme.palette.mode === 'dark' ? '#ffffff' : '#000000', + }, + dropIcon: { + width: 20, + height: 24, + fill: isDashboard ? theme.palette.text.primary : theme.palette.text.secondary, + }, + button: { + borderRadius: 26, + background: theme.palette.mode === 'dark' ? '##D9D9D9' : '0F1419', + marginTop: 24, + fontSize: 14, + fontWeight: 400, + lineHeight: 2.5, + paddingLeft: 35, + color: theme.palette.mode === 'dark' ? '#0F1419' : '#ffffff', + paddingRight: 35, + width: '100%', + }, + disabledButton: { + borderRadius: 26, + width: '563px', + background: '#D9D9D9', + color: '#0F1419', + opacity: '0.5', + marginTop: 24, + fontSize: 14, + fontWeight: 400, + lineHeight: 2.5, + paddingLeft: 35, + paddingRight: 35, + }, + backBtn: { + borderRadius: 99, + }, + previewBoxOuter: { + boxShadow: 'rgb(0 0 0 / 4%) 0px 6px 40px, rgb(0 0 0 / 2%) 0px 3px 6px', + background: theme.palette.mode === 'dark' ? '#1D2933' : 'rgb(255, 255, 255)', + width: '100%', + border: '0px solid blue', + borderRadius: 16, + height: '250px', + }, + + previewBoxInner: { + background: theme.palette.mode === 'dark' ? '#000000' : 'rgb(245, 245, 247)', + width: '100%', + border: '0px solid blue', + borderRadius: 10, + height: '190px', + }, + + previewBoxInnerGridContainer: { + display: 'flex', + borderCollapse: 'collapse', + width: '100%', + border: '0px solid green', + alignItems: 'center', + justifyContent: 'space-evenly', + borderRadius: 15, + }, + + previewBoxInnerGridContainerItem: { + display: 'table-cell', + height: '172px', + border: '0px solid green', + background: 'transparent', + borderRadius: '10px', + width: 'inherit', + }, + previewBoxInnerGridContainerItemImg: { + height: '100%', + maxWidth: '100%', + objectFit: 'cover', + borderRadius: '10px', + userSelect: 'none', + }, + previewBoxInnerGridContainerChip: { + position: 'relative', + left: '74%', + top: '-35px', + background: theme.palette.mode === 'dark' ? '#1D2933' : 'rgb(23, 23, 23)', + color: 'white', + fontSize: '18px', + border: '1px solid rgb(0, 0, 0)', + padding: '10px 5px 10px', + }, + previewBoxInnerGridFooterTitle1: { + fontWeight: 500, + fontSize: '18px', + color: theme.palette.mode === 'dark' ? '#ffffff' : '#000000', + }, + previewBoxInnerGridFooterTitle2: { + fontWeight: 'normal', + fontSize: '14px', + color: theme.palette.mode === 'dark' ? '#ffffff' : '#000000', + }, + paper: { + width: '600px !important', + maxWidth: 'none', + boxShadow: 'none', + backgroundImage: 'none', + [`@media (max-width: ${theme.breakpoints.values.sm}px)`]: { + display: 'block !important', + margin: 12, + }, + }, + } +}) + +const TradeComposeDialog: React.FC = ({ onClose, open }) => { + const t = useI18N() + + // APP BASE VARS + const isDashboard = isDashboardPage() + const isPopup = isPopupPage() + const { classes } = useStyles({ isDashboard, isPopup }) + const { showSnackbar } = useCustomSnackbar() + + /// SET PREVIEW STATES + const [step1, setState1] = useState(true) + const [step2, setState2] = useState(false) + const [step3, setState3] = useState(false) + const [previewNftList, setPreviewNftList] = useState() + const [count, setCount] = useState(0) + const [openBd, setBdOpen] = useState(false) + + const selectedChainId = useChainId() + const [token, setToken] = useState() + const [inputAmount, setInputAmount] = useState('0') + const [orderInfo, setOrderInfo] = useState() + const nftSwapSdk = useTraderApi(selectedChainId) + const account = useAccount() + const { attachMetadata, dropMetadata } = useCompositionContext() + const { closeDialog: closeApplicationBoardDialog } = useRemoteControlledDialog( + WalletMessages.events.ApplicationDialogUpdated, + ) + // #endregion + + useAsync(async () => { + // declare the data fetching function + const fetchNftData = async () => { + const headers: HeadersInit = + ChainId.Rinkeby === selectedChainId + ? { Accept: 'application/json' } + : { 'x-api-key': OPENSEA_API_KEY, Accept: 'application/json' } + + const url = urlcat( + `https://${selectedChainId === ChainId.Rinkeby ? 'testnets-' : ''}api.opensea.io/api/v1/assets`, + { + format: 'json', + limit: '50', + offset: 0, + owner: account, + }, + ) + + return fetch(url, { + method: 'GET', + headers, + ...(!isProxyENV() && { mode: 'cors' }), + }) + } + + // call the function + fetchNftData() + .then(async (response) => { + if (response.ok) { + const result = await response.json() + + const asset_contract = [ + ...new Set( + result.assets.map((ele: { asset_contract: AssetContract }) => ele.asset_contract.address), + ), + ] + + const final = asset_contract.map((filteredAddress) => { + const t = result.assets + .filter((ele1: OpenSeaToken) => ele1.asset_contract.address === filteredAddress) + .map(function (ele2: Token) { + return { + id: ele2.id, + token_id: ele2.token_id, + name: ele2.name, + image_preview_url: ele2.image_preview_url, + image_thumbnail_url: ele2.image_thumbnail_url, + is_selected: false, + asset_contract: ele2.asset_contract, + } + }) + + const r = result.assets + .filter( + (ele1: { asset_contract: AssetContract }) => + ele1.asset_contract.address === filteredAddress, + ) + .map(function (ele2: { collection: OpenSeaCollection; asset_contract: AssetContract }) { + return { + collection_name: ele2.collection.name, + contract_address: ele2.asset_contract.address, + } + }) + + const rBoj: PreviewNFTList = { + ...r[0], + tokens: t, + } + return rBoj + }) + + setPreviewNftList(final) + } + return true + }) + .catch(console.error) + }, [selectedChainId, account]) + + // on amount change in select token area + const onAmountChange = (token: FungibleTokenDetailed, amount: string) => { + setToken(token) + setInputAmount(amount) + } + + // on NFT image click to select + const handleSelection = (collection_index: number, item_index: number, type: string) => { + const p = previewNftList + p + ? (p[collection_index].tokens[item_index].is_selected = !p[collection_index].tokens[item_index].is_selected) + : p + setPreviewNftList(p) + setCount(count + 1) // This is the heck to re-render the whole view + } + + // Enable dynamic view section + const setDisplaySection = (step1: boolean, step2: boolean, step3: boolean) => { + setState1(step1) + setState2(step2) + setState3(step3) + } + + // Submit order to traderXYZ sdk + const submitOrder = async () => { + const assetsToSwapUserA = [orderInfo?.nfts, orderInfo?.receiving_token].flat(1) + + // Check if we need to approve the NFT for swapping + const approvalStatusForUserA = await nftSwapSdk + .loadApprovalStatus(assetsToSwapUserA[0] as SwappableAsset, account) + .then( + async (result) => { + if (!result.contractApproved) { + const approvalTx = await nftSwapSdk.approveTokenOrNftByAsset( + assetsToSwapUserA[0] as SwappableAsset, + account, + ) + const approvalTxReceipt = await approvalTx.wait() + showSnackbar( + `Approved ${assetsToSwapUserA[0]?.tokenAddress} contract to swap with 0x (txHash: ${approvalTxReceipt?.transactionHash})`, + { variant: 'success' }, + ) + } + if (result.contractApproved) { + const order = nftSwapSdk.buildOrder( + orderInfo?.nfts as SwappableAsset[], + [orderInfo?.receiving_token] as SwappableAsset[], + account, + ) + + setBdOpen(true) + const signedOrder = await nftSwapSdk.signOrder(order, account).then( + (result) => { + setBdOpen(false) + showSnackbar(t.submit_order_signed_message(), { variant: 'success' }) + const d = { + assetsInfo: orderInfo, + signedOrder: result, + } + attachMetadata(META_KEY, d) + closeApplicationBoardDialog() + onClose() + }, + function (error) { + setBdOpen(false) + showSnackbar(t.submit_order_submit_error_message() + ' on signOrder:' + error, { + variant: 'error', + }) + }, + ) + } + }, + function (error) { + showSnackbar(t.submit_order_submit_error_message() + error, { variant: 'error' }) + }, + ) + } + + const setPreviewOrderData = () => { + // IN PREVIEW WE WILL GET LIST OF ALL SELECTED ASSETS AND SET THE FINAL ARRAY FOR SELL + + const selectedTokens = previewNftList + ?.map((x) => x.tokens) + .flat() + .filter((p) => p?.is_selected) + + const nfts = selectedTokens?.map((y) => { + return { + tokenAddress: y?.asset_contract.address, + tokenId: y?.token_id, + type: y?.asset_contract.schema_name, + } + }) + + const nftMediaInfo = selectedTokens?.map((y) => { + return { + image_preview_url: y?.image_preview_url, + image_thumbnail_url: y?.image_thumbnail_url, + nft_name: y?.name, + nft_id: y?.token_id, + } + }) + + const am = amountToWei(inputAmount, token ? token.decimals : 0) + + const previewInfo = { + nftMediaUrls: nftMediaInfo, + receivingSymbol: { + symbol: token?.symbol, + amount: inputAmount, + }, + } + + const receivingToken = { + tokenAddress: token?.address.toLowerCase(), // WETH contract address + amount: am, // 0.0001 WETH (WETH is 6 digits) + type: 'ERC20', + } + + const orderInfo = { + nfts, + receiving_token: receivingToken, + preview_info: previewInfo, + } + + setOrderInfo(orderInfo) + } + + const nextButtonSection = () => { + /// fist we show continue section on step1 + + if (step1) { + const c = previewNftList + ?.map((x) => x.tokens) + .flat() + .filter((p) => p?.is_selected).length + + return ( + + ) + } + + if (step2) { + return ( + + ) + } + + if (step3) { + return ( + + ) + } + + return '' + } + + const selectNftSection = () => { + if (!step1) return + return ( + + + + {t.select_nft_heading()} + + + + {/*
{JSON.stringify(previewNftList, null, 2)}
*/} + +
+
+ ) + } + + const selectTokenSection = () => { + if (!step2) return + return ( + + + + + + ) + } + + const previewOrderSection = () => { + if (!step3) return + const amountLabel = + orderInfo?.preview_info?.receivingSymbol?.amount + ' ' + orderInfo?.preview_info?.receivingSymbol?.symbol + const m = orderInfo?.preview_info?.nftMediaUrls + return ( + + + + + + ) + } + + const onDecline = () => { + dropMetadata(META_KEY) + onClose() + } + + return ( + + + {selectNftSection()} + {selectTokenSection()} + {previewOrderSection()} + + {nextButtonSection()} + + ) +} + +export default TradeComposeDialog diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/assets/missing-img.png b/packages/plugins/Traderxyz/src/SNSAdaptor/assets/missing-img.png new file mode 100644 index 000000000000..ff45c8940112 Binary files /dev/null and b/packages/plugins/Traderxyz/src/SNSAdaptor/assets/missing-img.png differ diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/assets/traderxyz.png b/packages/plugins/Traderxyz/src/SNSAdaptor/assets/traderxyz.png new file mode 100644 index 000000000000..7f682e00a4c0 Binary files /dev/null and b/packages/plugins/Traderxyz/src/SNSAdaptor/assets/traderxyz.png differ diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/components/NftListView.tsx b/packages/plugins/Traderxyz/src/SNSAdaptor/components/NftListView.tsx new file mode 100644 index 000000000000..0e368b9f2c7d --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/components/NftListView.tsx @@ -0,0 +1,150 @@ +import { makeStyles } from '@masknet/theme' +import TreeView from '@mui/lab/TreeView' +import { AddCircle, RemoveCircle } from '@mui/icons-material' +import type { TreeNftData, PreviewNFTList } from '../../types' + +import TreeParentContent from './TreeParentContent' +import TreeChildContent from './TreeChildContent' +import TreeChildItemContent from './TreeChildItemContent' + +import TreeItem, { TreeItemProps, treeItemClasses } from '@mui/lab/TreeItem' +import { alpha, styled } from '@mui/material/styles' +import { useI18N } from '../../locales/i18n_generated' +import { useMemo } from 'react' + +const useStyles = makeStyles()((theme) => { + return { + label: { + color: theme.palette.mode === 'dark' ? '#ffffff' : '#000000', + paddingLeft: '20px !important', + }, + } +}) + +const NftListView = (props: { + nftList: PreviewNFTList[] | null | undefined + handleSelection(collection_index: number, item_index: number, type: string): void +}): JSX.Element => { + const { classes } = useStyles() + const t = useI18N() + + const CustomTreeParent = styled( + (props: TreeItemProps & { ContentProps?: { previewImages: string[] | null | undefined } }) => ( + + ), + )(({ theme }) => ({ + [`& .${treeItemClasses.label}`]: { + paddingLeft: 15, + }, + [`& .${treeItemClasses.iconContainer}`]: { + '& .close': { + opacity: 0.3, + }, + }, + [`& .${treeItemClasses.group}`]: { + marginLeft: 15, + paddingLeft: 18, + borderLeft: `1px solid ${alpha(theme.palette.text.primary, 0.4)}`, + }, + })) + + const CustomTreeChild = styled( + (props: TreeItemProps & { ContentProps?: { collectionImage: string | undefined } }) => ( + + ), + )(({ theme }) => ({ + [`& .${treeItemClasses.iconContainer}`]: { + '& .close': { + opacity: 0.3, + }, + }, + [`& .${treeItemClasses.group}`]: { + marginLeft: 15, + paddingLeft: 18, + borderLeft: `1px solid ${alpha(theme.palette.text.primary, 0.4)}`, + }, + })) + + const CustomTreeChildItem = styled( + ( + props: TreeItemProps & { + ContentProps?: { + nftData?: TreeNftData | undefined + onSelected?(collectionIndex: number, itemIndex: number, type?: string): void + } + }, + ) => , + )(({ theme }) => ({ + [`& .${treeItemClasses.iconContainer}`]: { + '& .close': { + opacity: 0.3, + }, + }, + [`& .${treeItemClasses.group}`]: { + marginLeft: 15, + paddingLeft: 18, + borderLeft: `1px solid ${alpha(theme.palette.text.primary, 0.4)}`, + }, + })) + + const collectionItemList = props?.nftList?.map((item, index) => { + const collectionImage = item.tokens[0].image_preview_url + return ( + + {item?.tokens?.map((item, i) => ( + + ))} + + ) + }) + + const nftList = props?.nftList + const previewImages1 = useMemo(() => { + return nftList + ?.map((x) => x?.tokens) + .flat() + .slice(0, 3) + .map((y) => { + return y?.image_preview_url + }) + }, [nftList]) + + return ( + } + defaultExpandIcon={} + multiSelect + sx={{ height: 'auto', flexGrow: 1, maxWidth: '100%' }}> + + {collectionItemList} + + + ) +} + +export default NftListView diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/components/SvgIcons.tsx b/packages/plugins/Traderxyz/src/SNSAdaptor/components/SvgIcons.tsx new file mode 100644 index 000000000000..616a02424ebd --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/components/SvgIcons.tsx @@ -0,0 +1,35 @@ +export const CheckIcon = (): JSX.Element => { + return ( + + + + + ) +} diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/components/TreeChildContent.tsx b/packages/plugins/Traderxyz/src/SNSAdaptor/components/TreeChildContent.tsx new file mode 100644 index 000000000000..abba98f8add4 --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/components/TreeChildContent.tsx @@ -0,0 +1,73 @@ +import { TreeItemContentProps, useTreeItem } from '@mui/lab/TreeItem' +import { Typography, Avatar } from '@mui/material' +import * as React from 'react' +import { makeStyles } from '@masknet/theme' + +const useStyles = makeStyles()((theme) => { + return { + itemAvatar: { + position: 'relative', + right: '0px', + }, + } +}) + +const TreeChildContent = React.forwardRef(function CustomContent( + props: TreeItemContentProps & { + collectionImage?: string + }, + ref, +) { + const customClasses = useStyles().classes + + const { cx } = useStyles() + + const { classes, className, label, nodeId, icon: iconProp, expansionIcon, displayIcon, collectionImage } = props + + const { disabled, expanded, selected, focused, handleExpansion, handleSelection, preventSelection } = + useTreeItem(nodeId) + + const icon = iconProp || expansionIcon || displayIcon + + const handleMouseDown = (event: React.MouseEvent) => { + preventSelection(event) + } + + const handleExpansionClick = (event: React.MouseEvent) => { + handleExpansion(event) + } + + const handleSelectionClick = (event: React.MouseEvent) => { + handleSelection(event) + } + const child = ( + no-image + ) + return ( +
}> +
+ +
+ + {label} + +
+ ) +}) + +export default TreeChildContent diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/components/TreeChildItemContent.tsx b/packages/plugins/Traderxyz/src/SNSAdaptor/components/TreeChildItemContent.tsx new file mode 100644 index 000000000000..1c22ffa3e29d --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/components/TreeChildItemContent.tsx @@ -0,0 +1,111 @@ +import { TreeItemContentProps, useTreeItem } from '@mui/lab/TreeItem' +import { Fade, Grid, Typography, Avatar } from '@mui/material' +import * as React from 'react' +import type { TreeNftData } from '../../types' +import { makeStyles } from '@masknet/theme' +import { CheckIcon } from './SvgIcons' + +const useStyles = makeStyles()((theme) => { + return { + itemWrapper: { + color: theme.palette.mode === 'dark' ? '#ffffff' : '#000000', + height: 128, + margin: 10, + width: 'auto', + float: 'left', + }, + itemLabel: { + width: 100, + border: '0px solid red', + float: 'left', + display: 'block', + color: theme.palette.mode === 'dark' ? '#ffffff' : '#000000', + paddingLeft: '0px !important', + }, + itemAvatar: { + width: 100, + height: 100, + float: 'left', + display: 'block', + borderRadius: 10, + color: theme.palette.mode === 'dark' ? '#ffffff' : '#000000', + paddingLeft: '0px !important', + }, + checkBoxContainer: { + position: 'relative', + display: 'block', + right: -65, + top: 0, + height: theme.spacing(4), + width: theme.spacing(4), + }, + } +}) + +const TreeChildItemContent = React.forwardRef(function CustomContent( + props: TreeItemContentProps & { + nftData?: TreeNftData + onSelected?(collectionIndex?: number, itemIndex?: number): void + }, + ref, +) { + const customClasses = useStyles().classes + + const { cx } = useStyles() + + const { classes, label, nodeId, icon: iconProp, expansionIcon, displayIcon, onSelected } = props + + const nftData = props.nftData + + const { disabled, expanded, selected, focused } = useTreeItem(nodeId) + + const icon = iconProp || expansionIcon || displayIcon + + const handleClick = (event: React.MouseEvent) => { + onSelected?.(nftData?.collection_index, nftData?.item_index) + } + const child = ( + no-image + ) + + return ( + +
}> + + + + {nftData?.is_selected === true && ( +
+ +
+ )} +
+ + + {label} + + +
+
+
+ ) +}) + +export default TreeChildItemContent diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/components/TreeParentContent.tsx b/packages/plugins/Traderxyz/src/SNSAdaptor/components/TreeParentContent.tsx new file mode 100644 index 000000000000..ea93dfe2ccfd --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/components/TreeParentContent.tsx @@ -0,0 +1,69 @@ +import { TreeItemContentProps, useTreeItem } from '@mui/lab/TreeItem' +import { Avatar, Fade, Typography, AvatarGroup } from '@mui/material' +import * as React from 'react' +import { makeStyles } from '@masknet/theme' + +const useStyles = makeStyles()((theme) => { + return { + itemAvatar: { + width: 150, + border: '0px solid black', + }, + } +}) +const TreeParentContent = React.forwardRef(function CustomContent( + props: TreeItemContentProps & { + previewImages?: string[] + }, + ref, +) { + const customClasses = useStyles().classes + + const { cx } = useStyles() + + const { classes, className, label, nodeId, icon: iconProp, expansionIcon, displayIcon, previewImages } = props + + const { disabled, expanded, selected, focused, handleExpansion } = useTreeItem(nodeId) + + const icon = iconProp || expansionIcon || displayIcon + + const handleExpansionClick = (event: React.MouseEvent) => { + handleExpansion(event) + } + + const child = ( + no-image + ) + const ShowNft = previewImages?.map((item, index) => { + return + }) + + return ( +
}> +
{icon}
+ + {label} + + + + {ShowNft} + + +
+ ) +}) + +export default TreeParentContent diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/context.ts b/packages/plugins/Traderxyz/src/SNSAdaptor/context.ts new file mode 100644 index 000000000000..a328cf1c47ae --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/context.ts @@ -0,0 +1,5 @@ +import type { Plugin } from '@masknet/plugin-infra' +export let context: Plugin.SNSAdaptor.SNSAdaptorContext +export function setupContext(x: typeof context) { + context = x +} diff --git a/packages/plugins/Traderxyz/src/SNSAdaptor/index.tsx b/packages/plugins/Traderxyz/src/SNSAdaptor/index.tsx new file mode 100644 index 000000000000..be51c65e7034 --- /dev/null +++ b/packages/plugins/Traderxyz/src/SNSAdaptor/index.tsx @@ -0,0 +1,76 @@ +import type { Plugin } from '@masknet/plugin-infra' +import { base } from '../base' +import { setupContext } from './context' +import { CrossIsolationMessages } from '@masknet/shared-base' +import { ApplicationEntry } from '@masknet/shared' +import { SwapIcon } from '@masknet/icons' +import TradeComposeDialog from './TradeComposeDialog' +import { TradeMetadataReader } from '../helpers' +import { PostPreview } from './PostPreview' +import { META_KEY } from '../constants' +import { useI18N } from '../locales/i18n_generated' + +const sns: Plugin.SNSAdaptor.Definition = { + ...base, + init(signal, context) { + setupContext(context) + }, + DecryptedInspector: function Component(props) { + const metadata = TradeMetadataReader(props.message.meta) + if (!metadata.ok) return null + return + }, + CompositionDialogEntry: { + label: ( + <> + + Traderxyz + + ), + dialog: TradeComposeDialog, + }, + CompositionDialogMetadataBadgeRender: new Map([[META_KEY, onAttachedFile]]), + ApplicationEntries: [ + (() => { + const icon = + const name = { i18nKey: '__plugin_name', fallback: 'Traderxyz' } + return { + ApplicationEntryID: base.ID, + RenderEntryComponent({ disabled }) { + const t = useI18N() + return ( + + CrossIsolationMessages.events.requestComposition.sendToLocal({ + reason: 'timeline', + open: true, + options: { + startupPlugin: base.ID, + }, + }) + } + /> + ) + }, + appBoardSortingDefaultPriority: 2, + marketListSortingPriority: 2, + icon, + category: 'dapp', + description: { + i18nKey: '__plugin_description', + fallback: 'Buy and Sell NFT through social media platform in few clicks faster and chaper.', + }, + name, + } + })(), + ], +} + +export default sns + +function onAttachedFile() { + return 'Trader XYZ NFT Attached' +} diff --git a/packages/plugins/Traderxyz/src/apis/nftSwap.tsx b/packages/plugins/Traderxyz/src/apis/nftSwap.tsx new file mode 100644 index 000000000000..d76fd33031d9 --- /dev/null +++ b/packages/plugins/Traderxyz/src/apis/nftSwap.tsx @@ -0,0 +1,18 @@ +import { NftSwap } from '@traderxyz/nft-swap-sdk' +import { ExternalProvider, Web3Provider } from '@ethersproject/providers' +import { useWeb3Provider, ChainId } from '@masknet/web3-shared-evm' +import { memoize } from 'lodash-unified' + +const useTraderApi_ = memoize( + (chainId: ChainId) => { + const p = useWeb3Provider() + const provider = new Web3Provider(p as unknown as ExternalProvider, chainId) + const signer = provider.getSigner(0) + return new NftSwap(provider, signer, chainId) + }, + (chainId: ChainId) => String(chainId), +) + +export function useTraderApi(chainId: number) { + return useTraderApi_(chainId) +} diff --git a/packages/plugins/Traderxyz/src/base.ts b/packages/plugins/Traderxyz/src/base.ts new file mode 100644 index 000000000000..790a217a8f6e --- /dev/null +++ b/packages/plugins/Traderxyz/src/base.ts @@ -0,0 +1,17 @@ +import type { Plugin } from '@masknet/plugin-infra' +import { PLUGIN_DESCRIPTION, PLUGIN_ID, PLUGIN_NAME } from './constants' +import { languages } from './locales/languages' + +export const base: Plugin.Shared.Definition = { + ID: PLUGIN_ID, + name: { fallback: PLUGIN_NAME }, + description: { fallback: PLUGIN_DESCRIPTION }, + publisher: { name: { fallback: '' }, link: '' }, + enableRequirement: { + architecture: { app: false, web: true }, + networks: { type: 'opt-out', networks: {} }, + target: 'beta', + }, + experimentalMark: true, + i18n: languages, +} diff --git a/packages/plugins/Traderxyz/src/constants.ts b/packages/plugins/Traderxyz/src/constants.ts new file mode 100644 index 000000000000..b09eacd05560 --- /dev/null +++ b/packages/plugins/Traderxyz/src/constants.ts @@ -0,0 +1,7 @@ +import { PluginId } from '@masknet/plugin-infra' + +export const PLUGIN_ID = PluginId.Traderxyz +export const PLUGIN_DESCRIPTION = 'Traderxyz plugin enable you to sell your nft in most convenient way.' +export const PLUGIN_NAME = 'Traderxyz' +export const META_KEY = 'io.mask.traderxyz:1' +export const DEFAULT_IMAGE = 'assets/missing-img.png' diff --git a/packages/plugins/Traderxyz/src/env.d.ts b/packages/plugins/Traderxyz/src/env.d.ts new file mode 100644 index 000000000000..868322d5ff30 --- /dev/null +++ b/packages/plugins/Traderxyz/src/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/plugins/Traderxyz/src/helpers.ts b/packages/plugins/Traderxyz/src/helpers.ts new file mode 100644 index 000000000000..aefb67b18ffa --- /dev/null +++ b/packages/plugins/Traderxyz/src/helpers.ts @@ -0,0 +1,16 @@ +import { type TypedMessage, createTypedMessageMetadataReader } from '@masknet/typed-message' +import type { TradeMetaData } from './types' +import { META_KEY } from './constants' +import schema from './schema.json' +import type { Result } from 'ts-results' +import BigNumber from 'bignumber.js' + +const reader_v2 = createTypedMessageMetadataReader(META_KEY, schema) + +export function TradeMetadataReader(meta: TypedMessage['meta']): Result { + return reader_v2(meta) +} + +export function amountToWei(amount: BigNumber.Value, decimals: number) { + return new BigNumber(amount).shiftedBy(decimals).toString() +} diff --git a/packages/plugins/Traderxyz/src/index.ts b/packages/plugins/Traderxyz/src/index.ts new file mode 100644 index 000000000000..3720b837f2bc --- /dev/null +++ b/packages/plugins/Traderxyz/src/index.ts @@ -0,0 +1,13 @@ +import { registerPlugin } from '@masknet/plugin-infra' +import { base } from './base' + +export * from './constants' + +registerPlugin({ + ...base, + SNSAdaptor: { + load: () => import('./SNSAdaptor'), + hotModuleReload: (hot) => + import.meta.webpackHot && import.meta.webpackHot.accept('./SNSAdaptor', () => hot(import('./SNSAdaptor'))), + }, +}) diff --git a/packages/plugins/Traderxyz/src/locales/en-US.json b/packages/plugins/Traderxyz/src/locales/en-US.json new file mode 100644 index 000000000000..8b7db530a4d4 --- /dev/null +++ b/packages/plugins/Traderxyz/src/locales/en-US.json @@ -0,0 +1,31 @@ +{ + "name": "Traderxyz", + "display_name": "Traderxyz", + "select_nft_heading": "What do you want to sell?", + "select_token_heading": "What do you want to receive?", + "preview_order_heading": "Confirm and Share", + "preview_order_subheading": " Ready to checkout! Take a final look to confirm your order?", + "preview_order_confirmation_title": "Waiting for your confirmation", + "preview_order_label_title1": "Buy", + "preview_order_label_title2": "and", + "preview_order_label_title3": "and Others", + "preview_order_label_title4": "For", + "nft_tree_parent_title": "Collectibles & NFT", + "submit_order_signed_message": "Order is Signed", + "submit_order_submit_error_message": "Order has error", + "submit_order_filled_message": " Order filled. TxHash: ", + "meta_attach_message": "Traderxyz NFT Attached", + "__plugin_name": "Traderxyz", + "__plugin_description": "Buy and Sell NFT through social media platform in few clicks faster and chaper", + "__entry__": "Traderxyz", + "order_filled": "Order is filled already", + "order_expired": "Order is Expired", + "order_cancelled": "Order is Cancelled", + "order_invalid": "Invalid Order", + "order_invalid_maker": "Invalid Maker Asset Amount", + "order_invalid_taker": "Invalid Taker Asset Amount", + "post_preview_swap_btn": "Swap", + "continue_btn": "Continue", + "preview_btn": "Preview", + "approve_nft_btn": "Approve your NFT" +} diff --git a/packages/plugins/Traderxyz/src/locales/index.ts b/packages/plugins/Traderxyz/src/locales/index.ts new file mode 100644 index 000000000000..d6ead60252e4 --- /dev/null +++ b/packages/plugins/Traderxyz/src/locales/index.ts @@ -0,0 +1,6 @@ +// This file is auto generated. DO NOT EDIT +// Run `npx gulp sync-languages` to regenerate. +// Default fallback language in a family of languages are chosen by the alphabet order +// To overwrite this, please overwrite packages/scripts/src/locale-kit-next/index.ts + +export * from './i18n_generated' diff --git a/packages/plugins/Traderxyz/src/locales/ja-JP.json b/packages/plugins/Traderxyz/src/locales/ja-JP.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/plugins/Traderxyz/src/locales/ja-JP.json @@ -0,0 +1 @@ +{} diff --git a/packages/plugins/Traderxyz/src/locales/ko-KR.json b/packages/plugins/Traderxyz/src/locales/ko-KR.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/plugins/Traderxyz/src/locales/ko-KR.json @@ -0,0 +1 @@ +{} diff --git a/packages/plugins/Traderxyz/src/locales/languages.ts b/packages/plugins/Traderxyz/src/locales/languages.ts new file mode 100644 index 000000000000..ad05218c975a --- /dev/null +++ b/packages/plugins/Traderxyz/src/locales/languages.ts @@ -0,0 +1,34 @@ +// This file is auto generated. DO NOT EDIT +// Run `npx gulp sync-languages` to regenerate. +// Default fallback language in a family of languages are chosen by the alphabet order +// To overwrite this, please overwrite packages/scripts/src/locale-kit-next/index.ts +import en_US from './en-US.json' +import ja_JP from './ja-JP.json' +import ko_KR from './ko-KR.json' +import qya_AA from './qya-AA.json' +import zh_CN from './zh-CN.json' +import zh_TW from './zh-TW.json' +export const languages = { + en: en_US, + ja: ja_JP, + ko: ko_KR, + qy: qya_AA, + 'zh-CN': zh_CN, + zh: zh_TW, +} +// @ts-ignore +if (import.meta.webpackHot) { + // @ts-ignore + import.meta.webpackHot.accept( + ['./en-US.json', './ja-JP.json', './ko-KR.json', './qya-AA.json', './zh-CN.json', './zh-TW.json'], + () => + globalThis.dispatchEvent?.( + new CustomEvent('MASK_I18N_HMR', { + detail: [ + 'io.mask.traderxyz', + { en: en_US, ja: ja_JP, ko: ko_KR, qy: qya_AA, 'zh-CN': zh_CN, zh: zh_TW }, + ], + }), + ), + ) +} diff --git a/packages/plugins/Traderxyz/src/locales/qya-AA.json b/packages/plugins/Traderxyz/src/locales/qya-AA.json new file mode 100644 index 000000000000..439535f8dd96 --- /dev/null +++ b/packages/plugins/Traderxyz/src/locales/qya-AA.json @@ -0,0 +1,4 @@ +{ + "name": "crwdns13280:0crwdne13280:0", + "__entry__": "crwdns13282:0crwdne13282:0" +} diff --git a/packages/plugins/Traderxyz/src/locales/zh-CN.json b/packages/plugins/Traderxyz/src/locales/zh-CN.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/plugins/Traderxyz/src/locales/zh-CN.json @@ -0,0 +1 @@ +{} diff --git a/packages/plugins/Traderxyz/src/locales/zh-TW.json b/packages/plugins/Traderxyz/src/locales/zh-TW.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/plugins/Traderxyz/src/locales/zh-TW.json @@ -0,0 +1 @@ +{} diff --git a/packages/plugins/Traderxyz/src/schema.json b/packages/plugins/Traderxyz/src/schema.json new file mode 100644 index 000000000000..c34b1eebb39f --- /dev/null +++ b/packages/plugins/Traderxyz/src/schema.json @@ -0,0 +1,157 @@ +{ + "type": "object", + "additionalProperties": true, + "properties": { + "assetsInfo": { + "type": "object", + "title": "assetsInfo", + "properties": { + "nfts": { + "type": "array", + "title": "nfts", + "properties": { + "tokenAddress": { + "type": "string", + "title": "tokenAddress" + }, + "tokenId": { + "type": "string", + "title": "type" + }, + "type": { + "type": "string", + "title": "type" + } + } + }, + "receiving_token": { + "type": "object", + "title": "receiving_token", + "properties": { + "tokenAddress": { + "type": "string", + "title": "tokenAddress" + }, + "type": { + "type": "string", + "title": "type" + }, + "amount": { + "type": "string", + "title": "amount" + } + } + }, + "preview_info": { + "type": "object", + "title": "preview_info", + "properties": { + "nftMediaUrls": { + "type": "array", + "title": "nftMediaUrls", + "properties": { + "image_preview_url": { + "type": "string", + "title": "image_preview_url" + }, + "image_thumbnail_url": { + "type": "string", + "title": "image_thumbnail_url" + }, + "nft_name": { + "type": "string", + "title": "nft_name" + }, + "nft_id": { + "type": "number", + "title": "nft_id" + } + } + }, + "receivingSymbol": { + "type": "object", + "title": "receivingSymbol", + "properties": { + "symbol": { + "type": "string", + "title": "symbol" + }, + "amount": { + "type": "string", + "title": "amount" + } + } + } + } + } + } + }, + "signedOrder": { + "type": "object", + "title": "signedOrder", + "properties": { + "makerAddress": { + "type": "string", + "title": "makerAddress" + }, + "makerAssetAmount": { + "type": "string", + "title": "makerAssetAmount" + }, + "makerAssetData": { + "type": "string", + "title": "makerAssetData" + }, + "takerAddress": { + "type": "string", + "title": "takerAddress" + }, + "takerAssetAmount": { + "type": "string", + "title": "takerAssetAmount" + }, + "takerAssetData": { + "type": "string", + "title": "takerAssetData" + }, + "expirationTimeSeconds": { + "type": "string", + "title": "expirationTimeSeconds" + }, + "senderAddress": { + "type": "string", + "title": "senderAddress" + }, + "feeRecipientAddress": { + "type": "string", + "title": "feeRecipientAddress" + }, + "salt": { + "type": "string", + "title": "salt" + }, + "makerFeeAssetData": { + "type": "string", + "title": "makerFeeAssetData" + }, + "takerFeeAssetData": { + "type": "string", + "title": "takerFeeAssetData" + }, + "makerFee": { + "type": "string", + "title": "makerFee" + }, + "takerFee": { + "type": "string", + "title": "takerFee" + }, + "signature": { + "type": "string", + "title": "signature" + } + } + } + }, + "required": ["signedOrder", "assetsInfo"] +} diff --git a/packages/plugins/Traderxyz/src/types.ts b/packages/plugins/Traderxyz/src/types.ts new file mode 100644 index 000000000000..0a3cfe3c4eab --- /dev/null +++ b/packages/plugins/Traderxyz/src/types.ts @@ -0,0 +1,89 @@ +export interface NFTData { + image_preview_url?: string + image_thumbnail_url?: string + nft_name?: string + nft_id?: string +} + +export interface TreeNftData { + id: number + token_id: string + image_preview_url?: string + is_selected: boolean + collection_index: number + item_index: number +} + +export interface TradeMetaData { + assetsInfo: { + nfts: [ + { + tokenAddress: string + tokenId: string + type: string + }, + ] + preview_info: { + nftMediaUrls: NFTData[] + receivingSymbol: { + symbol: string + amount: number + } + } + receiving_token: { + tokenAddress: string + type: string + amount: number + } + } + signedOrder: { + makerAddress: string + makerAssetAmount: string + makerAssetData: string + takerAddress: string + takerAssetAmount: string + takerAssetData: string + expirationTimeSeconds: string + senderAddress: string + feeRecipientAddress: string + salt: string + makerFeeAssetData: string + takerFeeAssetData: string + makerFee: string + takerFee: string + signature: string + } +} + +export interface AssetContract { + schema_name: string + address: string +} + +export interface Token { + id: number + token_id: string + name?: string + image_preview_url: string + image_thumbnail_url?: string + is_selected: boolean + asset_contract: AssetContract +} + +export type PreviewNFTList = { + collection_name?: string + contract_address?: string + tokens: Token[] +} + +export interface OpenSeaAssetContract { + address: string +} + +export interface OpenSeaCollection { + name: string +} + +export interface OpenSeaToken { + asset_contract: OpenSeaAssetContract +} diff --git a/packages/plugins/Traderxyz/tsconfig.json b/packages/plugins/Traderxyz/tsconfig.json new file mode 100644 index 000000000000..2c82b040e035 --- /dev/null +++ b/packages/plugins/Traderxyz/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist", + "tsBuildInfoFile": "dist/.tsbuildinfo" + }, + "include": ["src", "src/**/*.json"], + "references": [ + { "path": "../../theme" }, + { "path": "../../mask/src" }, + { "path": "../../plugin-infra" }, + { "path": "../../shared-base" }, + { "path": "../../shared-base-ui" }, + { "path": "../../typed-message/base" }, + { "path": "../../shared" }, + { "path": "../../icons" }, + { "path": "../Wallet" } + ] +} diff --git a/packages/plugins/tsconfig.json b/packages/plugins/tsconfig.json index 56c3716dd4f8..9b1a5b00b587 100644 --- a/packages/plugins/tsconfig.json +++ b/packages/plugins/tsconfig.json @@ -10,6 +10,7 @@ { "path": "./RSS3/" }, { "path": "./DAO/" }, { "path": "./CyberConnect/" }, - { "path": "./CrossChainBridge/" } + { "path": "./CrossChainBridge/" }, + { "path": "./Traderxyz/" } ] } diff --git a/packages/web3-providers/src/index.ts b/packages/web3-providers/src/index.ts index 319cb457e9eb..3c2f96e7f918 100644 --- a/packages/web3-providers/src/index.ts +++ b/packages/web3-providers/src/index.ts @@ -17,6 +17,8 @@ export * from './types' export * from './hooks' export * from './opensea/utils' export * from './NextID' +export * from './helpers' +export * from './opensea/constants' export const OpenSea = new OpenSeaAPI() export const Rarible = new RaribleAPI() diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aa9db6a7ad7b..e9204eb3058f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -347,6 +347,7 @@ importers: '@masknet/plugin-infra': workspace:* '@masknet/plugin-rss3': workspace:* '@masknet/plugin-solana': workspace:* + '@masknet/plugin-traderxyz': workspace:* '@masknet/plugin-wallet': workspace:* '@masknet/public-api': workspace:* '@masknet/sdk': workspace:* @@ -491,6 +492,7 @@ importers: '@masknet/plugin-infra': link:../plugin-infra '@masknet/plugin-rss3': link:../plugins/RSS3 '@masknet/plugin-solana': link:../plugins/Solana + '@masknet/plugin-traderxyz': link:../plugins/Traderxyz '@masknet/plugin-wallet': link:../plugins/Wallet '@masknet/public-api': link:../public-api '@masknet/sdk': link:../mask-sdk @@ -918,6 +920,46 @@ importers: buffer: 6.0.3 react-use: 17.3.2 + packages/plugins/Traderxyz: + specifiers: + '@ethersproject/providers': 5.6.4 + '@masknet/icons': workspace:* + '@masknet/plugin-infra': workspace:* + '@masknet/plugin-wallet': workspace:* + '@masknet/shared': workspace:* + '@masknet/shared-base': workspace:* + '@masknet/shared-base-ui': workspace:* + '@masknet/theme': workspace:* + '@masknet/typed-message': workspace:* + '@masknet/web3-providers': workspace:* + '@masknet/web3-shared-base': workspace:* + '@masknet/web3-shared-evm': workspace:* + '@traderxyz/nft-swap-sdk': ^0.22.1 + bignumber.js: ^9.0.2 + react-use: ^17.3.2 + urlcat: ^2.0.4 + use-subscription: ^1.7.0 + web3: 1.7.3 + dependencies: + '@ethersproject/providers': 5.6.4 + '@masknet/icons': link:../../icons + '@masknet/plugin-infra': link:../../plugin-infra + '@masknet/plugin-wallet': link:../Wallet + '@masknet/shared': link:../../shared + '@masknet/shared-base': link:../../shared-base + '@masknet/shared-base-ui': link:../../shared-base-ui + '@masknet/theme': link:../../theme + '@masknet/typed-message': link:../../typed-message + '@masknet/web3-providers': link:../../web3-providers + '@masknet/web3-shared-base': link:../../web3-shared/base + '@masknet/web3-shared-evm': link:../../web3-shared/evm + '@traderxyz/nft-swap-sdk': 0.22.1 + bignumber.js: 9.0.2 + react-use: 17.3.2 + urlcat: 2.0.4 + use-subscription: 1.7.0 + web3: 1.7.3 + packages/plugins/Wallet: specifiers: '@masknet/plugin-infra': workspace:* @@ -6131,6 +6173,20 @@ packages: '@ethersproject/strings': 5.4.0 dev: false + /@ethersproject/abi/5.6.1: + resolution: {integrity: sha512-0cqssYh6FXjlwKWBmLm3+zH2BNARoS5u/hxbz+LpQmcDB3w0W553h2btWui1/uZp2GBM/SI3KniTuMcYyHpA5w==} + dependencies: + '@ethersproject/address': 5.6.0 + '@ethersproject/bignumber': 5.6.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.0 + '@ethersproject/hash': 5.6.0 + '@ethersproject/keccak256': 5.6.0 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/strings': 5.6.0 + dev: false + /@ethersproject/abstract-provider/5.4.0: resolution: {integrity: sha512-vPBR7HKUBY0lpdllIn7tLIzNN7DrVnhCLKSzY0l8WAwxz686m/aL7ASDzrVxV93GJtIub6N2t4dfZ29CkPOxgA==} dependencies: @@ -6219,6 +6275,13 @@ packages: '@ethersproject/properties': 5.4.0 dev: false + /@ethersproject/basex/5.6.0: + resolution: {integrity: sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ==} + dependencies: + '@ethersproject/bytes': 5.6.1 + '@ethersproject/properties': 5.6.0 + dev: false + /@ethersproject/bignumber/5.4.0: resolution: {integrity: sha512-OXUu9f9hO3vGRIPxU40cignXZVaYyfx6j9NNMjebKdnaCL3anCLSSy8/b8d03vY6dh7duCC0kW72GEC4tZer2w==} dependencies: @@ -6297,6 +6360,21 @@ packages: '@ethersproject/transactions': 5.4.0 dev: false + /@ethersproject/contracts/5.6.0: + resolution: {integrity: sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw==} + dependencies: + '@ethersproject/abi': 5.6.1 + '@ethersproject/abstract-provider': 5.6.0 + '@ethersproject/abstract-signer': 5.6.0 + '@ethersproject/address': 5.6.0 + '@ethersproject/bignumber': 5.6.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.0 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/transactions': 5.6.0 + dev: false + /@ethersproject/hash/5.4.0: resolution: {integrity: sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA==} dependencies: @@ -6339,6 +6417,23 @@ packages: '@ethersproject/wordlists': 5.4.0 dev: false + /@ethersproject/hdnode/5.6.0: + resolution: {integrity: sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw==} + dependencies: + '@ethersproject/abstract-signer': 5.6.0 + '@ethersproject/basex': 5.6.0 + '@ethersproject/bignumber': 5.6.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/pbkdf2': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/sha2': 5.6.0 + '@ethersproject/signing-key': 5.6.1 + '@ethersproject/strings': 5.6.0 + '@ethersproject/transactions': 5.6.0 + '@ethersproject/wordlists': 5.6.0 + dev: false + /@ethersproject/json-wallets/5.4.0: resolution: {integrity: sha512-igWcu3fx4aiczrzEHwG1xJZo9l1cFfQOWzTqwRw/xcvxTk58q4f9M7cjh51EKphMHvrJtcezJ1gf1q1AUOfEQQ==} dependencies: @@ -6357,6 +6452,24 @@ packages: scrypt-js: 3.0.1 dev: false + /@ethersproject/json-wallets/5.6.0: + resolution: {integrity: sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ==} + dependencies: + '@ethersproject/abstract-signer': 5.6.0 + '@ethersproject/address': 5.6.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/hdnode': 5.6.0 + '@ethersproject/keccak256': 5.6.0 + '@ethersproject/logger': 5.6.0 + '@ethersproject/pbkdf2': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/random': 5.6.0 + '@ethersproject/strings': 5.6.0 + '@ethersproject/transactions': 5.6.0 + aes-js: 3.0.0 + scrypt-js: 3.0.1 + dev: false + /@ethersproject/keccak256/5.4.0: resolution: {integrity: sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A==} dependencies: @@ -6395,6 +6508,12 @@ packages: dependencies: '@ethersproject/logger': 5.6.0 + /@ethersproject/networks/5.6.2: + resolution: {integrity: sha512-9uEzaJY7j5wpYGTojGp8U89mSsgQLc40PCMJLMCnFXTs7nhBveZ0t7dbqWUNrepWTszDbFkYD6WlL8DKx5huHA==} + dependencies: + '@ethersproject/logger': 5.6.0 + dev: false + /@ethersproject/pbkdf2/5.4.0: resolution: {integrity: sha512-x94aIv6tiA04g6BnazZSLoRXqyusawRyZWlUhKip2jvoLpzJuLb//KtMM6PEovE47pMbW+Qe1uw+68ameJjB7g==} dependencies: @@ -6402,6 +6521,13 @@ packages: '@ethersproject/sha2': 5.4.0 dev: false + /@ethersproject/pbkdf2/5.6.0: + resolution: {integrity: sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ==} + dependencies: + '@ethersproject/bytes': 5.6.1 + '@ethersproject/sha2': 5.6.0 + dev: false + /@ethersproject/properties/5.4.0: resolution: {integrity: sha512-7jczalGVRAJ+XSRvNA6D5sAwT4gavLq3OXPuV/74o3Rd2wuzSL035IMpIMgei4CYyBdialJMrTqkOnzccLHn4A==} dependencies: @@ -6521,6 +6647,60 @@ packages: - utf-8-validate dev: false + /@ethersproject/providers/5.6.4: + resolution: {integrity: sha512-WAdknnaZ52hpHV3qPiJmKx401BLpup47h36Axxgre9zT+doa/4GC/Ne48ICPxTm0BqndpToHjpLP1ZnaxyE+vw==} + dependencies: + '@ethersproject/abstract-provider': 5.6.0 + '@ethersproject/abstract-signer': 5.6.0 + '@ethersproject/address': 5.6.0 + '@ethersproject/basex': 5.6.0 + '@ethersproject/bignumber': 5.6.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.0 + '@ethersproject/hash': 5.6.0 + '@ethersproject/logger': 5.6.0 + '@ethersproject/networks': 5.6.1 + '@ethersproject/properties': 5.6.0 + '@ethersproject/random': 5.6.0 + '@ethersproject/rlp': 5.6.0 + '@ethersproject/sha2': 5.6.0 + '@ethersproject/strings': 5.6.0 + '@ethersproject/transactions': 5.6.0 + '@ethersproject/web': 5.6.0 + bech32: 1.1.4 + ws: 7.4.6 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@ethersproject/providers/5.6.5: + resolution: {integrity: sha512-TRS+c2Ud+cMpWodmGAc9xbnYRPWzRNYt2zkCSnj58nJoamBQ6x4cUbBeo0lTC3y+6RDVIBeJv18OqsDbSktLVg==} + dependencies: + '@ethersproject/abstract-provider': 5.6.0 + '@ethersproject/abstract-signer': 5.6.0 + '@ethersproject/address': 5.6.0 + '@ethersproject/basex': 5.6.0 + '@ethersproject/bignumber': 5.6.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.0 + '@ethersproject/hash': 5.6.0 + '@ethersproject/logger': 5.6.0 + '@ethersproject/networks': 5.6.2 + '@ethersproject/properties': 5.6.0 + '@ethersproject/random': 5.6.0 + '@ethersproject/rlp': 5.6.0 + '@ethersproject/sha2': 5.6.0 + '@ethersproject/strings': 5.6.0 + '@ethersproject/transactions': 5.6.0 + '@ethersproject/web': 5.6.0 + bech32: 1.1.4 + ws: 7.4.6 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + /@ethersproject/random/5.4.0: resolution: {integrity: sha512-pnpWNQlf0VAZDEOVp1rsYQosmv2o0ITS/PecNw+mS2/btF8eYdspkN0vIXrCMtkX09EAh9bdk8GoXmFXM1eAKw==} dependencies: @@ -6528,6 +6708,13 @@ packages: '@ethersproject/logger': 5.4.0 dev: false + /@ethersproject/random/5.6.0: + resolution: {integrity: sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw==} + dependencies: + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 + dev: false + /@ethersproject/rlp/5.4.0: resolution: {integrity: sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg==} dependencies: @@ -6556,6 +6743,14 @@ packages: hash.js: 1.1.7 dev: false + /@ethersproject/sha2/5.6.0: + resolution: {integrity: sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA==} + dependencies: + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 + hash.js: 1.1.7 + dev: false + /@ethersproject/signing-key/5.4.0: resolution: {integrity: sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A==} dependencies: @@ -6577,6 +6772,17 @@ packages: elliptic: 6.5.4 hash.js: 1.1.7 + /@ethersproject/signing-key/5.6.1: + resolution: {integrity: sha512-XvqQ20DH0D+bS3qlrrgh+axRMth5kD1xuvqUQUTeezxUTXBOeR6hWz2/C6FBEu39FRytyybIWrYf7YLSAKr1LQ==} + dependencies: + '@ethersproject/bytes': 5.6.1 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + bn.js: 4.12.0 + elliptic: 6.5.4 + hash.js: 1.1.7 + dev: false + /@ethersproject/solidity/5.4.0: resolution: {integrity: sha512-XFQTZ7wFSHOhHcV1DpcWj7VXECEiSrBuv7JErJvB9Uo+KfCdc3QtUZV+Vjh/AAaYgezUEKbCtE6Khjm44seevQ==} dependencies: @@ -6587,6 +6793,17 @@ packages: '@ethersproject/strings': 5.4.0 dev: false + /@ethersproject/solidity/5.6.0: + resolution: {integrity: sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww==} + dependencies: + '@ethersproject/bignumber': 5.6.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/keccak256': 5.6.0 + '@ethersproject/logger': 5.6.0 + '@ethersproject/sha2': 5.6.0 + '@ethersproject/strings': 5.6.0 + dev: false + /@ethersproject/strings/5.4.0: resolution: {integrity: sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA==} dependencies: @@ -6637,6 +6854,14 @@ packages: '@ethersproject/logger': 5.4.0 dev: false + /@ethersproject/units/5.6.0: + resolution: {integrity: sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw==} + dependencies: + '@ethersproject/bignumber': 5.6.0 + '@ethersproject/constants': 5.6.0 + '@ethersproject/logger': 5.6.0 + dev: false + /@ethersproject/wallet/5.4.0: resolution: {integrity: sha512-wU29majLjM6AjCjpat21mPPviG+EpK7wY1+jzKD0fg3ui5fgedf2zEu1RDgpfIMsfn8fJHJuzM4zXZ2+hSHaSQ==} dependencies: @@ -6657,6 +6882,26 @@ packages: '@ethersproject/wordlists': 5.4.0 dev: false + /@ethersproject/wallet/5.6.0: + resolution: {integrity: sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg==} + dependencies: + '@ethersproject/abstract-provider': 5.6.0 + '@ethersproject/abstract-signer': 5.6.0 + '@ethersproject/address': 5.6.0 + '@ethersproject/bignumber': 5.6.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/hash': 5.6.0 + '@ethersproject/hdnode': 5.6.0 + '@ethersproject/json-wallets': 5.6.0 + '@ethersproject/keccak256': 5.6.0 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/random': 5.6.0 + '@ethersproject/signing-key': 5.6.0 + '@ethersproject/transactions': 5.6.0 + '@ethersproject/wordlists': 5.6.0 + dev: false + /@ethersproject/web/5.4.0: resolution: {integrity: sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og==} dependencies: @@ -6686,6 +6931,16 @@ packages: '@ethersproject/strings': 5.4.0 dev: false + /@ethersproject/wordlists/5.6.0: + resolution: {integrity: sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q==} + dependencies: + '@ethersproject/bytes': 5.6.1 + '@ethersproject/hash': 5.6.0 + '@ethersproject/logger': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/strings': 5.6.0 + dev: false + /@gar/promisify/1.1.3: resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} dev: true @@ -10321,6 +10576,31 @@ packages: engines: {node: '>= 10'} dev: false + /@traderxyz/nft-swap-sdk/0.22.1: + resolution: {integrity: sha512-mJY8TATcN/aaUjPHzCxaXVT8YzecepOXnXjW/Wk/4OevQdgC6uLFYumA6ZkJjRdw4OnHIOoHpZNCTJ13A9AeKQ==} + engines: {node: '>=10'} + dependencies: + '@ethersproject/abi': 5.6.1 + '@ethersproject/abstract-signer': 5.6.0 + '@ethersproject/bignumber': 5.6.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/hash': 5.6.0 + '@ethersproject/providers': 5.6.4 + '@ethersproject/wallet': 5.6.0 + date-fns: 2.28.0 + ethers: 5.6.5 + isomorphic-unfetch: 3.1.0 + lodash: 4.17.21 + lodash-es: 4.17.21 + tiny-invariant: 1.2.0 + tiny-warning: 1.0.3 + uuid: 8.3.2 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + /@tsconfig/node10/1.0.8: resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==} dev: true @@ -16502,17 +16782,10 @@ packages: u3: 0.1.1 dev: false - /error-stack-parser/2.0.6: - resolution: {integrity: sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==} - dependencies: - stackframe: 1.2.0 - dev: false - /error-stack-parser/2.0.7: resolution: {integrity: sha512-chLOW0ZGRf4s8raLrDxa5sdkvPec5YdvwbFnqJme4rk0rFajP8mPtrDL1+I+CwrQDCjswDA5sREX7jYQDQs9vA==} dependencies: stackframe: 1.2.1 - dev: true /errors-utils/0.1.0: resolution: {integrity: sha512-BcAD40AzRrcoNJZRGFRZdGp1tvRsv0k9W3TZY1coOXIwKUb8/eRWFmhSM2kemgH6+1iwUtgC8sJJOJpGolqUCg==} @@ -17310,6 +17583,44 @@ packages: - utf-8-validate dev: false + /ethers/5.6.5: + resolution: {integrity: sha512-9CTmplO9bv0s/aPw3HB3txGzKz3tUSI2EfO4dJo0W2WvaEq1ArgsEX6obV+bj5X3yY+Zgb1kAux8TDtJKe1FaA==} + dependencies: + '@ethersproject/abi': 5.6.1 + '@ethersproject/abstract-provider': 5.6.0 + '@ethersproject/abstract-signer': 5.6.0 + '@ethersproject/address': 5.6.0 + '@ethersproject/base64': 5.6.0 + '@ethersproject/basex': 5.6.0 + '@ethersproject/bignumber': 5.6.0 + '@ethersproject/bytes': 5.6.1 + '@ethersproject/constants': 5.6.0 + '@ethersproject/contracts': 5.6.0 + '@ethersproject/hash': 5.6.0 + '@ethersproject/hdnode': 5.6.0 + '@ethersproject/json-wallets': 5.6.0 + '@ethersproject/keccak256': 5.6.0 + '@ethersproject/logger': 5.6.0 + '@ethersproject/networks': 5.6.2 + '@ethersproject/pbkdf2': 5.6.0 + '@ethersproject/properties': 5.6.0 + '@ethersproject/providers': 5.6.5 + '@ethersproject/random': 5.6.0 + '@ethersproject/rlp': 5.6.0 + '@ethersproject/sha2': 5.6.0 + '@ethersproject/signing-key': 5.6.1 + '@ethersproject/solidity': 5.6.0 + '@ethersproject/strings': 5.6.0 + '@ethersproject/transactions': 5.6.0 + '@ethersproject/units': 5.6.0 + '@ethersproject/wallet': 5.6.0 + '@ethersproject/web': 5.6.0 + '@ethersproject/wordlists': 5.6.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + /ethjs-abi/0.2.0: resolution: {integrity: sha1-0+LCIQEVIPxJm3FoIDbBT8wvWyU=} engines: {node: '>=6.5.0', npm: '>=3'} @@ -20264,6 +20575,15 @@ packages: unfetch: 3.1.2 dev: false + /isomorphic-unfetch/3.1.0: + resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} + dependencies: + node-fetch: 2.6.7 + unfetch: 4.2.0 + transitivePeerDependencies: + - encoding + dev: false + /isomorphic-ws/4.0.1_ws@7.5.7: resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} peerDependencies: @@ -24681,7 +25001,7 @@ packages: react-dom: 18.1.0_react@18.1.0 dev: false - /react-universal-interface/0.6.2_tslib@2.3.1: + /react-universal-interface/0.6.2_tslib@2.4.0: resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} peerDependencies: react: '*' @@ -24690,7 +25010,7 @@ packages: react: optional: true dependencies: - tslib: 2.3.1 + tslib: 2.4.0 dev: false /react-use/17.3.2: @@ -24711,13 +25031,13 @@ packages: fast-shallow-equal: 1.0.0 js-cookie: 2.2.1 nano-css: 5.3.4 - react-universal-interface: 0.6.2_tslib@2.3.1 + react-universal-interface: 0.6.2_tslib@2.4.0 resize-observer-polyfill: 1.5.1 screenfull: 5.2.0 set-harmonic-interval: 1.0.1 throttle-debounce: 3.0.1 ts-easing: 0.2.0 - tslib: 2.3.1 + tslib: 2.4.0 dev: false /react-virtualized-auto-sizer/1.0.6: @@ -26288,7 +26608,7 @@ packages: /stack-generator/2.0.5: resolution: {integrity: sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q==} dependencies: - stackframe: 1.2.0 + stackframe: 1.2.1 dev: false /stack-trace/0.0.10: @@ -26302,25 +26622,20 @@ packages: escape-string-regexp: 2.0.0 dev: true - /stackframe/1.2.0: - resolution: {integrity: sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==} - dev: false - /stackframe/1.2.1: resolution: {integrity: sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg==} - dev: true /stacktrace-gps/3.0.4: resolution: {integrity: sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg==} dependencies: source-map: 0.5.6 - stackframe: 1.2.0 + stackframe: 1.2.1 dev: false /stacktrace-js/2.0.2: resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} dependencies: - error-stack-parser: 2.0.6 + error-stack-parser: 2.0.7 stack-generator: 2.0.5 stacktrace-gps: 3.0.4 dev: false @@ -27129,6 +27444,10 @@ packages: resolution: {integrity: sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==} dev: false + /tiny-invariant/1.2.0: + resolution: {integrity: sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==} + dev: false + /tiny-secp256k1/1.1.6: resolution: {integrity: sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==} engines: {node: '>=6.0.0'} @@ -27919,7 +28238,6 @@ packages: /unfetch/4.2.0: resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} - dev: true /unherit/1.1.3: resolution: {integrity: sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==} @@ -28183,12 +28501,24 @@ packages: optional: true dev: false - /use-subscription/1.6.0_react@packages+empty: - resolution: {integrity: sha512-0Y/cTLlZfw547tJhJMoRA16OUbVqRm6DmvGpiGbmLST6BIA5KU5cKlvlz8DVMrACnWpyEjCkgmhLatthP4jUbA==} + /use-subscription/1.7.0: + resolution: {integrity: sha512-87x6MjiIVE/BWqtxfiRvM6jfvGudN+UeVOnWi7qKYp2c0YJn5+Z5Jt0kZw6Tt+8hs7kw/BWo2WBhizJSAZsQJA==} peerDependencies: - react: ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || 18 + peerDependenciesMeta: + react: + optional: true dependencies: - react: link:packages/empty + use-sync-external-store: 1.1.0 + dev: false + + /use-sync-external-store/1.1.0: + resolution: {integrity: sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || 18 + peerDependenciesMeta: + react: + optional: true dev: false /use/3.1.1: diff --git a/tsconfig.json b/tsconfig.json index a01cc8449468..fca565fe4460 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -101,6 +101,7 @@ "@masknet/plugin-cyberconnect": ["./packages/plugins/CyberConnect/src"], "@masknet/plugin-go-plus-security": ["./packages/plugins/GoPlusSecurity/src"], "@masknet/plugin-cross-chain-bridge": ["./packages/plugins/CrossChainBridge/src"], + "@masknet/plugin-traderxyz": ["./packages/plugins/Traderxyz/src"], // @masknet/scripts: insert-here 3 "@masknet/plugin-wallet": ["./packages/plugins/Wallet/src"] },