mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
This reverts commit 81ea24f08a
.
This commit is contained in:
parent
0563c471a6
commit
3cff801b8e
@ -139,6 +139,9 @@
|
|||||||
"addNFT": {
|
"addNFT": {
|
||||||
"message": "Add NFT"
|
"message": "Add NFT"
|
||||||
},
|
},
|
||||||
|
"addNFTLowerCase": {
|
||||||
|
"message": "add NFT"
|
||||||
|
},
|
||||||
"addNetwork": {
|
"addNetwork": {
|
||||||
"message": "Add Network"
|
"message": "Add Network"
|
||||||
},
|
},
|
||||||
@ -562,9 +565,6 @@
|
|||||||
"contract": {
|
"contract": {
|
||||||
"message": "Contract"
|
"message": "Contract"
|
||||||
},
|
},
|
||||||
"contractAddress": {
|
|
||||||
"message": "Contract address"
|
|
||||||
},
|
|
||||||
"contractAddressError": {
|
"contractAddressError": {
|
||||||
"message": "You are sending tokens to the token's contract address. This may result in the loss of these tokens."
|
"message": "You are sending tokens to the token's contract address. This may result in the loss of these tokens."
|
||||||
},
|
},
|
||||||
@ -706,9 +706,6 @@
|
|||||||
"depositEther": {
|
"depositEther": {
|
||||||
"message": "Deposit Ether"
|
"message": "Deposit Ether"
|
||||||
},
|
},
|
||||||
"description": {
|
|
||||||
"message": "Description"
|
|
||||||
},
|
|
||||||
"details": {
|
"details": {
|
||||||
"message": "Details"
|
"message": "Details"
|
||||||
},
|
},
|
||||||
@ -875,9 +872,6 @@
|
|||||||
"editPermission": {
|
"editPermission": {
|
||||||
"message": "Edit Permission"
|
"message": "Edit Permission"
|
||||||
},
|
},
|
||||||
"enableAutoDetect": {
|
|
||||||
"message": " Enable Autodetect"
|
|
||||||
},
|
|
||||||
"enableFromSettings": {
|
"enableFromSettings": {
|
||||||
"message": " Enable it from Settings."
|
"message": " Enable it from Settings."
|
||||||
},
|
},
|
||||||
@ -1291,9 +1285,6 @@
|
|||||||
"importMyWallet": {
|
"importMyWallet": {
|
||||||
"message": "Import My Wallet"
|
"message": "Import My Wallet"
|
||||||
},
|
},
|
||||||
"importNFTs": {
|
|
||||||
"message": "Import NFTs"
|
|
||||||
},
|
|
||||||
"importTokenQuestion": {
|
"importTokenQuestion": {
|
||||||
"message": "Import token?"
|
"message": "Import token?"
|
||||||
},
|
},
|
||||||
@ -1486,9 +1477,6 @@
|
|||||||
"likeToImportTokens": {
|
"likeToImportTokens": {
|
||||||
"message": "Would you like to import these tokens?"
|
"message": "Would you like to import these tokens?"
|
||||||
},
|
},
|
||||||
"link": {
|
|
||||||
"message": "Link"
|
|
||||||
},
|
|
||||||
"links": {
|
"links": {
|
||||||
"message": "Links"
|
"message": "Links"
|
||||||
},
|
},
|
||||||
@ -2171,9 +2159,6 @@
|
|||||||
"removeAccountDescription": {
|
"removeAccountDescription": {
|
||||||
"message": "This account will be removed from your wallet. Please make sure you have the original Secret Recovery Phrase or private key for this imported account before continuing. You can import or create accounts again from the account drop-down. "
|
"message": "This account will be removed from your wallet. Please make sure you have the original Secret Recovery Phrase or private key for this imported account before continuing. You can import or create accounts again from the account drop-down. "
|
||||||
},
|
},
|
||||||
"removeNFT": {
|
|
||||||
"message": "Remove NFT"
|
|
||||||
},
|
|
||||||
"requestsAwaitingAcknowledgement": {
|
"requestsAwaitingAcknowledgement": {
|
||||||
"message": "requests waiting to be acknowledged"
|
"message": "requests waiting to be acknowledged"
|
||||||
},
|
},
|
||||||
@ -2492,9 +2477,6 @@
|
|||||||
"somethingWentWrong": {
|
"somethingWentWrong": {
|
||||||
"message": "Oops! Something went wrong."
|
"message": "Oops! Something went wrong."
|
||||||
},
|
},
|
||||||
"source": {
|
|
||||||
"message": "Source"
|
|
||||||
},
|
|
||||||
"speedUp": {
|
"speedUp": {
|
||||||
"message": "Speed Up"
|
"message": "Speed Up"
|
||||||
},
|
},
|
||||||
@ -3284,9 +3266,6 @@
|
|||||||
"message": "View $1 on Etherscan",
|
"message": "View $1 on Etherscan",
|
||||||
"description": "$1 is the action type. e.g (Account, Transaction, Swap)"
|
"description": "$1 is the action type. e.g (Account, Transaction, Swap)"
|
||||||
},
|
},
|
||||||
"viewOnOpensea": {
|
|
||||||
"message": "View on Opensea"
|
|
||||||
},
|
|
||||||
"viewinExplorer": {
|
"viewinExplorer": {
|
||||||
"message": "View $1 in Explorer",
|
"message": "View $1 in Explorer",
|
||||||
"description": "$1 is the action type. e.g (Account, Transaction, Swap)"
|
"description": "$1 is the action type. e.g (Account, Transaction, Swap)"
|
||||||
|
@ -61,7 +61,7 @@ export default class PreferencesController {
|
|||||||
hideZeroBalanceTokens: false,
|
hideZeroBalanceTokens: false,
|
||||||
},
|
},
|
||||||
// ENS decentralized website resolution
|
// ENS decentralized website resolution
|
||||||
ipfsGateway: 'https://cloudflare-ipfs.com/ipfs/',
|
ipfsGateway: 'dweb.link',
|
||||||
infuraBlocked: null,
|
infuraBlocked: null,
|
||||||
ledgerTransportType: window.navigator.hid
|
ledgerTransportType: window.navigator.hid
|
||||||
? LEDGER_TRANSPORT_TYPES.WEBHID
|
? LEDGER_TRANSPORT_TYPES.WEBHID
|
||||||
|
@ -50,8 +50,6 @@ export default function setupEnsIpfsResolver({
|
|||||||
|
|
||||||
async function attemptResolve({ tabId, name, pathname, search, fragment }) {
|
async function attemptResolve({ tabId, name, pathname, search, fragment }) {
|
||||||
const ipfsGateway = getIpfsGateway();
|
const ipfsGateway = getIpfsGateway();
|
||||||
const ipfsGatewayHost = new URL(ipfsGateway)?.host;
|
|
||||||
|
|
||||||
extension.tabs.update(tabId, { url: `loading.html` });
|
extension.tabs.update(tabId, { url: `loading.html` });
|
||||||
let url = `https://app.ens.domains/name/${name}`;
|
let url = `https://app.ens.domains/name/${name}`;
|
||||||
try {
|
try {
|
||||||
@ -63,7 +61,7 @@ export default function setupEnsIpfsResolver({
|
|||||||
const resolvedUrl = `https://${hash}.${type.slice(
|
const resolvedUrl = `https://${hash}.${type.slice(
|
||||||
0,
|
0,
|
||||||
4,
|
4,
|
||||||
)}.${ipfsGatewayHost}${pathname}${search || ''}${fragment || ''}`;
|
)}.${ipfsGateway}${pathname}${search || ''}${fragment || ''}`;
|
||||||
try {
|
try {
|
||||||
// check if ipfs gateway has result
|
// check if ipfs gateway has result
|
||||||
const response = await fetchWithTimeout(resolvedUrl, {
|
const response = await fetchWithTimeout(resolvedUrl, {
|
||||||
|
@ -41,10 +41,7 @@ import {
|
|||||||
GAS_DEV_API_BASE_URL,
|
GAS_DEV_API_BASE_URL,
|
||||||
SWAPS_CLIENT_ID,
|
SWAPS_CLIENT_ID,
|
||||||
} from '../../shared/constants/swaps';
|
} from '../../shared/constants/swaps';
|
||||||
import {
|
import { MAINNET_CHAIN_ID } from '../../shared/constants/network';
|
||||||
IPFS_DEFAULT_GATEWAY_URL,
|
|
||||||
MAINNET_CHAIN_ID,
|
|
||||||
} from '../../shared/constants/network';
|
|
||||||
import {
|
import {
|
||||||
DEVICE_NAMES,
|
DEVICE_NAMES,
|
||||||
KEYRING_TYPES,
|
KEYRING_TYPES,
|
||||||
@ -190,44 +187,32 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
provider: this.provider,
|
provider: this.provider,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.collectiblesController = new CollectiblesController(
|
this.collectiblesController = new CollectiblesController({
|
||||||
{
|
onPreferencesStateChange: this.preferencesController.store.subscribe.bind(
|
||||||
onPreferencesStateChange: (cb) =>
|
this.preferencesController.store,
|
||||||
this.preferencesController.store.subscribe((preferencesState) => {
|
),
|
||||||
const { ipfsGateway } = this.preferencesController.store.getState();
|
onNetworkStateChange: this.networkController.store.subscribe.bind(
|
||||||
const modifiedPreferencesState = {
|
this.networkController.store,
|
||||||
...preferencesState,
|
),
|
||||||
ipfsGateway: ipfsGateway.endsWith('/ipfs/')
|
getAssetName: this.assetsContractController.getAssetName.bind(
|
||||||
? ipfsGateway
|
this.assetsContractController,
|
||||||
: `${ipfsGateway}/ipfs/`,
|
),
|
||||||
};
|
getAssetSymbol: this.assetsContractController.getAssetSymbol.bind(
|
||||||
return cb(modifiedPreferencesState);
|
this.assetsContractController,
|
||||||
}),
|
),
|
||||||
onNetworkStateChange: this.networkController.store.subscribe.bind(
|
getCollectibleTokenURI: this.assetsContractController.getCollectibleTokenURI.bind(
|
||||||
this.networkController.store,
|
this.assetsContractController,
|
||||||
),
|
),
|
||||||
getAssetName: this.assetsContractController.getAssetName.bind(
|
getOwnerOf: this.assetsContractController.getOwnerOf.bind(
|
||||||
this.assetsContractController,
|
this.assetsContractController,
|
||||||
),
|
),
|
||||||
getAssetSymbol: this.assetsContractController.getAssetSymbol.bind(
|
balanceOfERC1155Collectible: this.assetsContractController.balanceOfERC1155Collectible.bind(
|
||||||
this.assetsContractController,
|
this.assetsContractController,
|
||||||
),
|
),
|
||||||
getCollectibleTokenURI: this.assetsContractController.getCollectibleTokenURI.bind(
|
uriERC1155Collectible: this.assetsContractController.uriERC1155Collectible.bind(
|
||||||
this.assetsContractController,
|
this.assetsContractController,
|
||||||
),
|
),
|
||||||
getOwnerOf: this.assetsContractController.getOwnerOf.bind(
|
});
|
||||||
this.assetsContractController,
|
|
||||||
),
|
|
||||||
balanceOfERC1155Collectible: this.assetsContractController.balanceOfERC1155Collectible.bind(
|
|
||||||
this.assetsContractController,
|
|
||||||
),
|
|
||||||
uriERC1155Collectible: this.assetsContractController.uriERC1155Collectible.bind(
|
|
||||||
this.assetsContractController,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{ ipfsGateway: `${IPFS_DEFAULT_GATEWAY_URL}/ipfs/` },
|
|
||||||
initState.CollectiblesController,
|
|
||||||
);
|
|
||||||
|
|
||||||
process.env.COLLECTIBLES_V1 &&
|
process.env.COLLECTIBLES_V1 &&
|
||||||
(this.collectibleDetectionController = new CollectibleDetectionController(
|
(this.collectibleDetectionController = new CollectibleDetectionController(
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
import { cloneDeep } from 'lodash';
|
|
||||||
import { IPFS_DEFAULT_GATEWAY_URL } from '../../../shared/constants/network';
|
|
||||||
|
|
||||||
const version = 68;
|
|
||||||
|
|
||||||
function addUrlProtocolPrefix(urlString) {
|
|
||||||
if (!urlString.match(/(^http:\/\/)|(^https:\/\/)/u)) {
|
|
||||||
return `https://${urlString}`;
|
|
||||||
}
|
|
||||||
return urlString;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
version,
|
|
||||||
|
|
||||||
async migrate(originalVersionedData) {
|
|
||||||
const versionedData = cloneDeep(originalVersionedData);
|
|
||||||
versionedData.meta.version = version;
|
|
||||||
const state = versionedData.data;
|
|
||||||
const newState = transformState(state);
|
|
||||||
versionedData.data = newState;
|
|
||||||
return versionedData;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function transformState(state) {
|
|
||||||
const PreferencesController = state?.PreferencesController || {};
|
|
||||||
const preferences = PreferencesController.preferences || {};
|
|
||||||
const oldIpfsGateWay = preferences.ipfsGateway;
|
|
||||||
|
|
||||||
let newState;
|
|
||||||
|
|
||||||
if (oldIpfsGateWay && oldIpfsGateWay !== 'dweb.link') {
|
|
||||||
const newIpfsGateway = new URL(
|
|
||||||
addUrlProtocolPrefix(oldIpfsGateWay),
|
|
||||||
).toString();
|
|
||||||
newState = {
|
|
||||||
...state,
|
|
||||||
PreferencesController: {
|
|
||||||
...PreferencesController,
|
|
||||||
preferences: {
|
|
||||||
...preferences,
|
|
||||||
ipfsGateway: newIpfsGateway,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
newState = {
|
|
||||||
...state,
|
|
||||||
PreferencesController: {
|
|
||||||
...PreferencesController,
|
|
||||||
preferences: {
|
|
||||||
...preferences,
|
|
||||||
ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return newState;
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
import { IPFS_DEFAULT_GATEWAY_URL } from '../../../shared/constants/network';
|
|
||||||
import migration68 from './068';
|
|
||||||
|
|
||||||
describe('migration #68', () => {
|
|
||||||
it('should update the version metadata', async () => {
|
|
||||||
const oldStorage = {
|
|
||||||
meta: {
|
|
||||||
version: 67,
|
|
||||||
},
|
|
||||||
data: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const newStorage = await migration68.migrate(oldStorage);
|
|
||||||
expect(newStorage.meta).toStrictEqual({
|
|
||||||
version: 68,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set preference ipfsGateway to "https://cloudflare-ipfs.com" if ipfsGateway is old default dweb.link', async () => {
|
|
||||||
const expectedValue = IPFS_DEFAULT_GATEWAY_URL; // = https://cloudflare-ipfs.com
|
|
||||||
const oldStorage = {
|
|
||||||
meta: {},
|
|
||||||
data: {
|
|
||||||
PreferencesController: {
|
|
||||||
preferences: {
|
|
||||||
ipfsGateway: 'dweb.link',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const newStorage = await migration68.migrate(oldStorage);
|
|
||||||
expect(newStorage.data.PreferencesController.preferences.ipfsGateway).toBe(
|
|
||||||
expectedValue,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update preference ipfsGateway to a full url version of user set ipfsGateway if ipfsGateway is not old default dweb.link', async () => {
|
|
||||||
const expectedValue = 'https://random.ipfs/';
|
|
||||||
const oldStorage = {
|
|
||||||
meta: {},
|
|
||||||
data: {
|
|
||||||
PreferencesController: {
|
|
||||||
preferences: {
|
|
||||||
ipfsGateway: 'random.ipfs',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const newStorage = await migration68.migrate(oldStorage);
|
|
||||||
expect(newStorage.data.PreferencesController.preferences.ipfsGateway).toBe(
|
|
||||||
expectedValue,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
@ -71,7 +71,6 @@ import m064 from './064';
|
|||||||
import m065 from './065';
|
import m065 from './065';
|
||||||
import m066 from './066';
|
import m066 from './066';
|
||||||
import m067 from './067';
|
import m067 from './067';
|
||||||
import m068 from './068';
|
|
||||||
|
|
||||||
const migrations = [
|
const migrations = [
|
||||||
m002,
|
m002,
|
||||||
@ -140,7 +139,6 @@ const migrations = [
|
|||||||
m065,
|
m065,
|
||||||
m066,
|
m066,
|
||||||
m067,
|
m067,
|
||||||
m068,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export default migrations;
|
export default migrations;
|
||||||
|
@ -111,7 +111,7 @@
|
|||||||
"@keystonehq/metamask-airgapped-keyring": "0.2.1",
|
"@keystonehq/metamask-airgapped-keyring": "0.2.1",
|
||||||
"@material-ui/core": "^4.11.0",
|
"@material-ui/core": "^4.11.0",
|
||||||
"@metamask/contract-metadata": "^1.28.0",
|
"@metamask/contract-metadata": "^1.28.0",
|
||||||
"@metamask/controllers": "^21.0.1",
|
"@metamask/controllers": "^20.1.0",
|
||||||
"@metamask/eth-ledger-bridge-keyring": "^0.10.0",
|
"@metamask/eth-ledger-bridge-keyring": "^0.10.0",
|
||||||
"@metamask/eth-token-tracker": "^3.0.1",
|
"@metamask/eth-token-tracker": "^3.0.1",
|
||||||
"@metamask/etherscan-link": "^2.1.0",
|
"@metamask/etherscan-link": "^2.1.0",
|
||||||
|
@ -171,5 +171,3 @@ export const UNSUPPORTED_RPC_METHODS = new Set([
|
|||||||
// eth-json-rpc-middleware – but our UI does not support it.
|
// eth-json-rpc-middleware – but our UI does not support it.
|
||||||
'eth_signTransaction',
|
'eth_signTransaction',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const IPFS_DEFAULT_GATEWAY_URL = 'https://cloudflare-ipfs.com';
|
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
@import 'app-header/index';
|
@import 'app-header/index';
|
||||||
@import 'asset-list-item/asset-list-item';
|
@import 'asset-list-item/asset-list-item';
|
||||||
@import 'confirm-page-container/index';
|
@import 'confirm-page-container/index';
|
||||||
@import 'collectibles-items/index';
|
|
||||||
@import 'collectible-details/index';
|
|
||||||
@import 'connected-accounts-list/index';
|
@import 'connected-accounts-list/index';
|
||||||
@import 'connected-accounts-permissions/index';
|
@import 'connected-accounts-permissions/index';
|
||||||
@import 'connected-sites-list/index';
|
@import 'connected-sites-list/index';
|
||||||
|
@ -1,212 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
|
||||||
import { getTokenTrackerLink } from '@metamask/etherscan-link';
|
|
||||||
import Box from '../../ui/box';
|
|
||||||
import Typography from '../../ui/typography/typography';
|
|
||||||
import {
|
|
||||||
COLORS,
|
|
||||||
TYPOGRAPHY,
|
|
||||||
BLOCK_SIZES,
|
|
||||||
FONT_WEIGHT,
|
|
||||||
JUSTIFY_CONTENT,
|
|
||||||
FLEX_DIRECTION,
|
|
||||||
OVERFLOW_WRAP,
|
|
||||||
DISPLAY,
|
|
||||||
} from '../../../helpers/constants/design-system';
|
|
||||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
|
||||||
import {
|
|
||||||
getAssetImageURL,
|
|
||||||
isEqualCaseInsensitive,
|
|
||||||
shortenAddress,
|
|
||||||
} from '../../../helpers/utils/util';
|
|
||||||
import {
|
|
||||||
getCurrentChainId,
|
|
||||||
getIpfsGateway,
|
|
||||||
getRpcPrefsForCurrentProvider,
|
|
||||||
getSelectedIdentity,
|
|
||||||
} from '../../../selectors';
|
|
||||||
import AssetNavigation from '../../../pages/asset/components/asset-navigation';
|
|
||||||
import { getCollectibleContracts } from '../../../ducks/metamask/metamask';
|
|
||||||
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
|
|
||||||
import { removeAndIgnoreCollectible } from '../../../store/actions';
|
|
||||||
import {
|
|
||||||
GOERLI_CHAIN_ID,
|
|
||||||
KOVAN_CHAIN_ID,
|
|
||||||
MAINNET_CHAIN_ID,
|
|
||||||
POLYGON_CHAIN_ID,
|
|
||||||
RINKEBY_CHAIN_ID,
|
|
||||||
ROPSTEN_CHAIN_ID,
|
|
||||||
} from '../../../../shared/constants/network';
|
|
||||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
|
|
||||||
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
|
|
||||||
import CollectibleOptions from './collectible-options';
|
|
||||||
|
|
||||||
export default function CollectibleDetails({ collectible }) {
|
|
||||||
const { image, name, description, address, tokenId } = collectible;
|
|
||||||
const t = useI18nContext();
|
|
||||||
const history = useHistory();
|
|
||||||
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider);
|
|
||||||
const ipfsGateway = useSelector(getIpfsGateway);
|
|
||||||
const collectibleContracts = useSelector(getCollectibleContracts);
|
|
||||||
const currentNetwork = useSelector(getCurrentChainId);
|
|
||||||
|
|
||||||
const collectibleContractName = collectibleContracts.find(
|
|
||||||
({ address: contractAddress }) =>
|
|
||||||
isEqualCaseInsensitive(contractAddress, address),
|
|
||||||
)?.name;
|
|
||||||
const selectedAccountName = useSelector(
|
|
||||||
(state) => getSelectedIdentity(state).name,
|
|
||||||
);
|
|
||||||
const collectibleImageURL = getAssetImageURL(image, ipfsGateway);
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
|
|
||||||
const onRemove = () => {
|
|
||||||
dispatch(removeAndIgnoreCollectible(address, tokenId));
|
|
||||||
history.push(DEFAULT_ROUTE);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getOpenSeaLink = () => {
|
|
||||||
switch (currentNetwork) {
|
|
||||||
case MAINNET_CHAIN_ID:
|
|
||||||
return `https://opensea.io/assets/${address}/${tokenId}`;
|
|
||||||
case POLYGON_CHAIN_ID:
|
|
||||||
return `https://opensea.io/assets/matic/${address}/${tokenId}`;
|
|
||||||
case GOERLI_CHAIN_ID:
|
|
||||||
case KOVAN_CHAIN_ID:
|
|
||||||
case ROPSTEN_CHAIN_ID:
|
|
||||||
case RINKEBY_CHAIN_ID:
|
|
||||||
return `https://testnets.opensea.io/assets/${address}/${tokenId}`;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const openSeaLink = getOpenSeaLink();
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AssetNavigation
|
|
||||||
accountName={selectedAccountName}
|
|
||||||
assetName={collectibleContractName}
|
|
||||||
onBack={() => history.push(DEFAULT_ROUTE)}
|
|
||||||
optionsButton={
|
|
||||||
<CollectibleOptions
|
|
||||||
onViewOnOpensea={
|
|
||||||
openSeaLink
|
|
||||||
? () => global.platform.openTab({ url: openSeaLink })
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
onRemove={onRemove}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Box padding={[4, 2, 4, 2]}>
|
|
||||||
<div className="collectible-details">
|
|
||||||
<Box margin={3} padding={2} justifyContent={JUSTIFY_CONTENT.CENTER}>
|
|
||||||
<img style={{ width: '14rem' }} src={collectibleImageURL} />
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
margin={3}
|
|
||||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
|
||||||
width={
|
|
||||||
getEnvironmentType() === ENVIRONMENT_TYPE_POPUP
|
|
||||||
? BLOCK_SIZES.THREE_FOURTHS
|
|
||||||
: BLOCK_SIZES.HALF
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
color={COLORS.BLACK}
|
|
||||||
variant={TYPOGRAPHY.H4}
|
|
||||||
fontWeight={FONT_WEIGHT.BOLD}
|
|
||||||
>
|
|
||||||
{name}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
color={COLORS.UI3}
|
|
||||||
variant={TYPOGRAPHY.H5}
|
|
||||||
boxProps={{ marginTop: 2, marginBottom: 3 }}
|
|
||||||
overflowWrap={OVERFLOW_WRAP.BREAK_WORD}
|
|
||||||
>
|
|
||||||
{`#${tokenId}`}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
color={COLORS.BLACK}
|
|
||||||
variant={TYPOGRAPHY.H6}
|
|
||||||
fontWeight={FONT_WEIGHT.BOLD}
|
|
||||||
className="collectible-details__description"
|
|
||||||
>
|
|
||||||
{t('description')}
|
|
||||||
</Typography>
|
|
||||||
<Typography color={COLORS.UI3} variant={TYPOGRAPHY.H6}>
|
|
||||||
{description}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</div>
|
|
||||||
<Box margin={4}>
|
|
||||||
<Box display={DISPLAY.FLEX} flexDirection={FLEX_DIRECTION.ROW}>
|
|
||||||
<Typography
|
|
||||||
color={COLORS.BLACK}
|
|
||||||
variant={TYPOGRAPHY.H6}
|
|
||||||
fontWeight={FONT_WEIGHT.BOLD}
|
|
||||||
boxProps={{ marginBottom: 3, width: BLOCK_SIZES.ONE_FOURTH }}
|
|
||||||
>
|
|
||||||
{t('source')}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
color={COLORS.PRIMARY1}
|
|
||||||
variant={TYPOGRAPHY.H6}
|
|
||||||
boxProps={{ marginBottom: 3, width: BLOCK_SIZES.THREE_FOURTHS }}
|
|
||||||
overflowWrap={OVERFLOW_WRAP.BREAK_WORD}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
href={collectibleImageURL}
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}
|
|
||||||
>
|
|
||||||
{image}
|
|
||||||
</a>
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<Box display={DISPLAY.FLEX} flexDirection={FLEX_DIRECTION.ROW}>
|
|
||||||
<Typography
|
|
||||||
color={COLORS.BLACK}
|
|
||||||
variant={TYPOGRAPHY.H6}
|
|
||||||
fontWeight={FONT_WEIGHT.BOLD}
|
|
||||||
boxProps={{ width: BLOCK_SIZES.ONE_FOURTH }}
|
|
||||||
>
|
|
||||||
{t('contractAddress')}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
color={COLORS.UI3}
|
|
||||||
variant={TYPOGRAPHY.H6}
|
|
||||||
overflowWrap={OVERFLOW_WRAP.BREAK_WORD}
|
|
||||||
boxProps={{ width: BLOCK_SIZES.THREE_FOURTHS }}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
href={getTokenTrackerLink(
|
|
||||||
address,
|
|
||||||
currentNetwork,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
rpcPrefs,
|
|
||||||
)}
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{getEnvironmentType() === ENVIRONMENT_TYPE_POPUP
|
|
||||||
? shortenAddress(address)
|
|
||||||
: address}
|
|
||||||
</a>
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
CollectibleDetails.propTypes = {
|
|
||||||
collectible: PropTypes.object,
|
|
||||||
};
|
|
@ -1,23 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import CollectibleDetails from './collectible-details';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: 'Collectibles Detail',
|
|
||||||
id: __filename,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const basic = () => {
|
|
||||||
const collectible = {
|
|
||||||
name: 'Catnip Spicywright',
|
|
||||||
tokenId: '1124157',
|
|
||||||
address: '0x06012c8cf97bead5deae237070f9587f8e7a266d',
|
|
||||||
image: './images/catnip-spicywright.png',
|
|
||||||
description:
|
|
||||||
"Good day. My name is Catnip Spicywight, which got me teased a lot in high school. If I want to put low fat mayo all over my hamburgers, I shouldn't have to answer to anyone about it, am I right? One time I beat Arlene in an arm wrestle.",
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div style={{ width: '420px' }}>
|
|
||||||
<CollectibleDetails collectible={collectible} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,61 +0,0 @@
|
|||||||
import React, { useContext, useState } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import { I18nContext } from '../../../contexts/i18n';
|
|
||||||
import { Menu, MenuItem } from '../../ui/menu';
|
|
||||||
|
|
||||||
const CollectibleOptions = ({ onRemove, onViewOnOpensea }) => {
|
|
||||||
const t = useContext(I18nContext);
|
|
||||||
const [
|
|
||||||
collectibleOptionsButtonElement,
|
|
||||||
setCollectibleOptionsButtonElement,
|
|
||||||
] = useState(null);
|
|
||||||
const [collectibleOptionsOpen, setCollectibleOptionsOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button
|
|
||||||
className="fas fa-ellipsis-v collectible-options__button"
|
|
||||||
data-testid="collectible-options__button"
|
|
||||||
onClick={() => setCollectibleOptionsOpen(true)}
|
|
||||||
ref={setCollectibleOptionsButtonElement}
|
|
||||||
/>
|
|
||||||
{collectibleOptionsOpen ? (
|
|
||||||
<Menu
|
|
||||||
anchorElement={collectibleOptionsButtonElement}
|
|
||||||
onHide={() => setCollectibleOptionsOpen(false)}
|
|
||||||
>
|
|
||||||
{onViewOnOpensea ? (
|
|
||||||
<MenuItem
|
|
||||||
iconClassName="fas fa-qrcode"
|
|
||||||
data-testid="collectible-options__view-on-opensea"
|
|
||||||
onClick={() => {
|
|
||||||
setCollectibleOptionsOpen(false);
|
|
||||||
onViewOnOpensea();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('viewOnOpensea')}
|
|
||||||
</MenuItem>
|
|
||||||
) : null}
|
|
||||||
<MenuItem
|
|
||||||
iconClassName="fas fa-trash-alt collectible-options__icon"
|
|
||||||
data-testid="collectible-options__hide"
|
|
||||||
onClick={() => {
|
|
||||||
setCollectibleOptionsOpen(false);
|
|
||||||
onRemove();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('removeNFT')}
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
CollectibleOptions.propTypes = {
|
|
||||||
onRemove: PropTypes.func.isRequired,
|
|
||||||
onViewOnOpensea: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CollectibleOptions;
|
|
@ -1,26 +0,0 @@
|
|||||||
.collectible-details {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
@media screen and (min-width: $break-large) {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__address {
|
|
||||||
overflow-wrap: break-word;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.collectible-options {
|
|
||||||
&__button {
|
|
||||||
font-size: $font-size-paragraph;
|
|
||||||
color: $Black-100;
|
|
||||||
background-color: inherit;
|
|
||||||
padding: 2px 0 2px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__icon {
|
|
||||||
font-weight: 900;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,5 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
|
||||||
import Box from '../../ui/box';
|
import Box from '../../ui/box';
|
||||||
import Button from '../../ui/button';
|
import Button from '../../ui/button';
|
||||||
import Typography from '../../ui/typography/typography';
|
import Typography from '../../ui/typography/typography';
|
||||||
@ -20,43 +18,29 @@ import {
|
|||||||
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
|
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
|
||||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
|
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
|
||||||
import { getIpfsGateway } from '../../../selectors';
|
|
||||||
import { ASSET_ROUTE } from '../../../helpers/constants/routes';
|
|
||||||
import { getAssetImageURL } from '../../../helpers/utils/util';
|
|
||||||
|
|
||||||
const width =
|
export default function CollectiblesItems({ onAddNFT, onRefreshList }) {
|
||||||
getEnvironmentType() === ENVIRONMENT_TYPE_POPUP
|
|
||||||
? BLOCK_SIZES.ONE_THIRD
|
|
||||||
: BLOCK_SIZES.ONE_SIXTH;
|
|
||||||
export default function CollectiblesItems({
|
|
||||||
onAddNFT,
|
|
||||||
onRefreshList,
|
|
||||||
collections,
|
|
||||||
useCollectibleDetection,
|
|
||||||
onEnableAutoDetect,
|
|
||||||
}) {
|
|
||||||
const t = useI18nContext();
|
const t = useI18nContext();
|
||||||
|
const collections = {};
|
||||||
const defaultDropdownState = {};
|
const defaultDropdownState = {};
|
||||||
const ipfsGateway = useSelector(getIpfsGateway);
|
|
||||||
|
|
||||||
Object.keys(collections).forEach((key) => {
|
Object.keys(collections).forEach((key) => {
|
||||||
defaultDropdownState[key] = true;
|
defaultDropdownState[key] = true;
|
||||||
});
|
});
|
||||||
const history = useHistory();
|
|
||||||
|
|
||||||
const [dropdownState, setDropdownState] = useState(defaultDropdownState);
|
const [dropdownState, setDropdownState] = useState(defaultDropdownState);
|
||||||
|
const width =
|
||||||
|
getEnvironmentType() === ENVIRONMENT_TYPE_POPUP
|
||||||
|
? BLOCK_SIZES.ONE_THIRD
|
||||||
|
: BLOCK_SIZES.ONE_SIXTH;
|
||||||
return (
|
return (
|
||||||
<div className="collectibles-items">
|
<div className="collectibles-items">
|
||||||
<Box padding={[4, 6, 4, 6]} flexDirection={FLEX_DIRECTION.COLUMN}>
|
<Box padding={[4, 6, 4, 6]} flexDirection={FLEX_DIRECTION.COLUMN}>
|
||||||
<>
|
<>
|
||||||
{Object.keys(collections).map((key, index) => {
|
{Object.keys(collections).map((key, index) => {
|
||||||
const {
|
const { icon, collectibles } = collections[key];
|
||||||
collectibles,
|
|
||||||
collectionName,
|
|
||||||
collectionImage,
|
|
||||||
} = collections[key];
|
|
||||||
|
|
||||||
const isExpanded = dropdownState[key];
|
const isExpanded = dropdownState[key];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={`collection-${index}`}>
|
<div key={`collection-${index}`}>
|
||||||
<Box
|
<Box
|
||||||
@ -67,20 +51,13 @@ export default function CollectiblesItems({
|
|||||||
justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN}
|
justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN}
|
||||||
>
|
>
|
||||||
<Box alignItems={ALIGN_ITEMS.CENTER}>
|
<Box alignItems={ALIGN_ITEMS.CENTER}>
|
||||||
{collectionImage ? (
|
<img width="28" src={icon} />
|
||||||
<img
|
|
||||||
style={{ width: '1.5rem', borderRadius: '50%' }}
|
|
||||||
src={collectionImage}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="collection-icon">{collectionName[0]}</div>
|
|
||||||
)}
|
|
||||||
<Typography
|
<Typography
|
||||||
color={COLORS.BLACK}
|
color={COLORS.BLACK}
|
||||||
variant={TYPOGRAPHY.H4}
|
variant={TYPOGRAPHY.H4}
|
||||||
margin={[0, 0, 0, 2]}
|
margin={[0, 0, 0, 2]}
|
||||||
>
|
>
|
||||||
{`${collectionName} (${collectibles.length})`}
|
{`${key} (${collectibles.length})`}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box alignItems={ALIGN_ITEMS.FLEX_END}>
|
<Box alignItems={ALIGN_ITEMS.FLEX_END}>
|
||||||
@ -100,30 +77,13 @@ export default function CollectiblesItems({
|
|||||||
{isExpanded ? (
|
{isExpanded ? (
|
||||||
<Box display={DISPLAY.FLEX} flexWrap={FLEX_WRAP.WRAP}>
|
<Box display={DISPLAY.FLEX} flexWrap={FLEX_WRAP.WRAP}>
|
||||||
{collectibles.map((collectible, i) => {
|
{collectibles.map((collectible, i) => {
|
||||||
const { image, address, tokenId } = collectible;
|
|
||||||
const collectibleImage = getAssetImageURL(
|
|
||||||
image,
|
|
||||||
ipfsGateway,
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<Box width={width} margin={1} key={`collectible-${i}`}>
|
<Box width={width} padding={2} key={`collectible-${i}`}>
|
||||||
<Box
|
<Box
|
||||||
borderRadius={SIZES.MD}
|
borderRadius={SIZES.MD}
|
||||||
backgroundColor={collectible.backgroundColor}
|
backgroundColor={collectible.backgroundColor}
|
||||||
display={DISPLAY.FLEX}
|
|
||||||
justifyContent={JUSTIFY_CONTENT.CENTER}
|
|
||||||
padding={2}
|
|
||||||
width={BLOCK_SIZES.FULL}
|
|
||||||
>
|
>
|
||||||
<img
|
<img src={collectible.icon} />
|
||||||
onClick={() =>
|
|
||||||
history.push(
|
|
||||||
`${ASSET_ROUTE}/${address}/${tokenId}`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="collectibles-items__image"
|
|
||||||
src={collectibleImage}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@ -149,28 +109,15 @@ export default function CollectiblesItems({
|
|||||||
alignItems={ALIGN_ITEMS.CENTER}
|
alignItems={ALIGN_ITEMS.CENTER}
|
||||||
justifyContent={JUSTIFY_CONTENT.CENTER}
|
justifyContent={JUSTIFY_CONTENT.CENTER}
|
||||||
>
|
>
|
||||||
{' '}
|
<Box justifyContent={JUSTIFY_CONTENT.FLEX_END}>
|
||||||
{useCollectibleDetection ? (
|
<Button
|
||||||
<Box justifyContent={JUSTIFY_CONTENT.FLEX_END}>
|
type="link"
|
||||||
<Button
|
onClick={onRefreshList}
|
||||||
type="link"
|
style={{ padding: '4px' }}
|
||||||
onClick={onRefreshList}
|
>
|
||||||
style={{ padding: '4px', fontSize: '16px' }}
|
{t('refreshList')}
|
||||||
>
|
</Button>
|
||||||
{t('refreshList')}
|
</Box>
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
) : (
|
|
||||||
<Box justifyContent={JUSTIFY_CONTENT.FLEX_END}>
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
onClick={onEnableAutoDetect}
|
|
||||||
style={{ padding: '4px', fontSize: '16px' }}
|
|
||||||
>
|
|
||||||
{t('enableAutoDetect')}
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
<Typography
|
<Typography
|
||||||
color={COLORS.UI3}
|
color={COLORS.UI3}
|
||||||
variant={TYPOGRAPHY.H4}
|
variant={TYPOGRAPHY.H4}
|
||||||
@ -182,9 +129,9 @@ export default function CollectiblesItems({
|
|||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
onClick={onAddNFT}
|
onClick={onAddNFT}
|
||||||
style={{ padding: '4px', fontSize: '16px' }}
|
style={{ padding: '4px' }}
|
||||||
>
|
>
|
||||||
{t('importNFTs')}
|
{t('addNFTLowerCase')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@ -198,7 +145,4 @@ export default function CollectiblesItems({
|
|||||||
CollectiblesItems.propTypes = {
|
CollectiblesItems.propTypes = {
|
||||||
onAddNFT: PropTypes.func.isRequired,
|
onAddNFT: PropTypes.func.isRequired,
|
||||||
onRefreshList: PropTypes.func.isRequired,
|
onRefreshList: PropTypes.func.isRequired,
|
||||||
collections: PropTypes.array,
|
|
||||||
useCollectibleDetection: PropTypes.bool.isRequired,
|
|
||||||
onEnableAutoDetect: PropTypes.func.isRequired,
|
|
||||||
};
|
};
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
.collectibles-items {
|
|
||||||
&__image {
|
|
||||||
border-radius: 0.625rem;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.collection-icon {
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 2rem;
|
|
||||||
height: 2rem;
|
|
||||||
padding: 0.5rem;
|
|
||||||
background: $ui-4;
|
|
||||||
color: $ui-white;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
@ -1,7 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
|
||||||
import Box from '../../ui/box';
|
import Box from '../../ui/box';
|
||||||
import Button from '../../ui/button';
|
import Button from '../../ui/button';
|
||||||
import Typography from '../../ui/typography/typography';
|
import Typography from '../../ui/typography/typography';
|
||||||
@ -16,49 +14,20 @@ import {
|
|||||||
FONT_WEIGHT,
|
FONT_WEIGHT,
|
||||||
} from '../../../helpers/constants/design-system';
|
} from '../../../helpers/constants/design-system';
|
||||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||||
import {
|
|
||||||
getCollectibles,
|
|
||||||
getCollectibleContracts,
|
|
||||||
} from '../../../ducks/metamask/metamask';
|
|
||||||
import { getUseCollectibleDetection } from '../../../selectors';
|
|
||||||
import { EXPERIMENTAL_ROUTE } from '../../../helpers/constants/routes';
|
|
||||||
import { detectCollectibles } from '../../../store/actions';
|
|
||||||
|
|
||||||
export default function CollectiblesTab({ onAddNFT }) {
|
export default function CollectiblesTab({ onAddNFT }) {
|
||||||
const collectibles = useSelector(getCollectibles);
|
const collectibles = [];
|
||||||
const collectibleContracts = useSelector(getCollectibleContracts);
|
|
||||||
const useCollectibleDetection = useSelector(getUseCollectibleDetection);
|
|
||||||
const history = useHistory();
|
|
||||||
const newNFTsDetected = false;
|
const newNFTsDetected = false;
|
||||||
const t = useI18nContext();
|
const t = useI18nContext();
|
||||||
const collections = {};
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
|
|
||||||
collectibles.forEach((collectible) => {
|
|
||||||
if (collections[collectible.address]) {
|
|
||||||
collections[collectible.address].collectibles.push(collectible);
|
|
||||||
} else {
|
|
||||||
const collectionContract = collectibleContracts.find(
|
|
||||||
({ address }) => address === collectible.address,
|
|
||||||
);
|
|
||||||
collections[collectible.address] = {
|
|
||||||
collectionName: collectionContract?.name || collectible.name,
|
|
||||||
collectionImage:
|
|
||||||
collectionContract?.logo || collectible.collectionImage,
|
|
||||||
collectibles: [collectible],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="collectibles-tab">
|
<div className="collectibles-tab">
|
||||||
{collectibles.length > 0 ? (
|
{collectibles.length > 0 ? (
|
||||||
<CollectiblesItems
|
<CollectiblesItems
|
||||||
collections={collections}
|
|
||||||
onAddNFT={onAddNFT}
|
onAddNFT={onAddNFT}
|
||||||
useCollectibleDetection={useCollectibleDetection}
|
onRefreshList={() => {
|
||||||
onRefreshList={() => dispatch(detectCollectibles())}
|
console.log('refreshing collectibles');
|
||||||
onEnableAutoDetect={() => history.push(EXPERIMENTAL_ROUTE)}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Box padding={[6, 12, 6, 12]}>
|
<Box padding={[6, 12, 6, 12]}>
|
||||||
|
@ -169,6 +169,6 @@ Box.propTypes = {
|
|||||||
display: PropTypes.oneOf(Object.values(DISPLAY)),
|
display: PropTypes.oneOf(Object.values(DISPLAY)),
|
||||||
width: PropTypes.oneOf(Object.values(BLOCK_SIZES)),
|
width: PropTypes.oneOf(Object.values(BLOCK_SIZES)),
|
||||||
height: PropTypes.oneOf(Object.values(BLOCK_SIZES)),
|
height: PropTypes.oneOf(Object.values(BLOCK_SIZES)),
|
||||||
backgroundColor: PropTypes.string,
|
backgroundColor: PropTypes.oneOf(Object.values(COLORS)),
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
FONT_STYLE,
|
FONT_STYLE,
|
||||||
TEXT_ALIGN,
|
TEXT_ALIGN,
|
||||||
TYPOGRAPHY,
|
TYPOGRAPHY,
|
||||||
OVERFLOW_WRAP,
|
|
||||||
} from '../../../helpers/constants/design-system';
|
} from '../../../helpers/constants/design-system';
|
||||||
import Box, { MultipleSizes } from '../box';
|
import Box, { MultipleSizes } from '../box';
|
||||||
|
|
||||||
@ -23,7 +22,6 @@ export default function Typography({
|
|||||||
fontStyle = 'normal',
|
fontStyle = 'normal',
|
||||||
fontSize,
|
fontSize,
|
||||||
align,
|
align,
|
||||||
overflowWrap,
|
|
||||||
boxProps = {},
|
boxProps = {},
|
||||||
margin = [1, 0],
|
margin = [1, 0],
|
||||||
}) {
|
}) {
|
||||||
@ -37,7 +35,6 @@ export default function Typography({
|
|||||||
[`typography--align-${align}`]: Boolean(align),
|
[`typography--align-${align}`]: Boolean(align),
|
||||||
[`typography--color-${color}`]: Boolean(color),
|
[`typography--color-${color}`]: Boolean(color),
|
||||||
[`typography--size-${fontSize}`]: Boolean(fontSize),
|
[`typography--size-${fontSize}`]: Boolean(fontSize),
|
||||||
[`typography--overflowwrap-${overflowWrap}`]: Boolean(overflowWrap),
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -72,7 +69,6 @@ Typography.propTypes = {
|
|||||||
margin: MultipleSizes,
|
margin: MultipleSizes,
|
||||||
fontWeight: PropTypes.oneOf(Object.values(FONT_WEIGHT)),
|
fontWeight: PropTypes.oneOf(Object.values(FONT_WEIGHT)),
|
||||||
fontStyle: PropTypes.oneOf(Object.values(FONT_STYLE)),
|
fontStyle: PropTypes.oneOf(Object.values(FONT_STYLE)),
|
||||||
overflowWrap: PropTypes.oneOf(Object.values(OVERFLOW_WRAP)),
|
|
||||||
fontSize: PropTypes.string,
|
fontSize: PropTypes.string,
|
||||||
tag: PropTypes.oneOf([
|
tag: PropTypes.oneOf([
|
||||||
'p',
|
'p',
|
||||||
|
@ -45,12 +45,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@each $overflow in design-system.$overflow-wrap {
|
|
||||||
&--overflowwrap-#{$overflow} {
|
|
||||||
overflow-wrap: $overflow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@for $i from 1 through 8 {
|
@for $i from 1 through 8 {
|
||||||
&--spacing-#{$i} {
|
&--spacing-#{$i} {
|
||||||
margin: #{$i * 4}px auto;
|
margin: #{$i * 4}px auto;
|
||||||
|
@ -80,7 +80,6 @@ $border-style: solid, double, none, dashed, dotted;
|
|||||||
$directions: top, right, bottom, left;
|
$directions: top, right, bottom, left;
|
||||||
$display: block, grid, flex, inline-block, inline-grid, inline-flex, list-item;
|
$display: block, grid, flex, inline-block, inline-grid, inline-flex, list-item;
|
||||||
$text-align: left, right, center, justify, end;
|
$text-align: left, right, center, justify, end;
|
||||||
$overflow-wrap: normal, break-word;
|
|
||||||
$font-weight: bold, normal, 100, 200, 300, 400, 500, 600, 700, 800, 900;
|
$font-weight: bold, normal, 100, 200, 300, 400, 500, 600, 700, 800, 900;
|
||||||
$font-style: normal, italic, oblique;
|
$font-style: normal, italic, oblique;
|
||||||
$font-size: 10px, 12px;
|
$font-size: 10px, 12px;
|
||||||
|
@ -256,45 +256,6 @@ export const getUnconnectedAccountAlertShown = (state) =>
|
|||||||
|
|
||||||
export const getTokens = (state) => state.metamask.tokens;
|
export const getTokens = (state) => state.metamask.tokens;
|
||||||
|
|
||||||
export const getCollectibles = (state) => {
|
|
||||||
const {
|
|
||||||
metamask: {
|
|
||||||
allCollectibles,
|
|
||||||
provider: { chainId },
|
|
||||||
selectedAddress,
|
|
||||||
},
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
let decFormattedChainId;
|
|
||||||
if (typeof chainId === 'string' && isHexString(chainId)) {
|
|
||||||
decFormattedChainId = `${parseInt(chainId, 16)}`;
|
|
||||||
} else if (typeof chainId === 'number') {
|
|
||||||
decFormattedChainId = `${chainId}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return allCollectibles?.[selectedAddress]?.[decFormattedChainId] || [];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getCollectibleContracts = (state) => {
|
|
||||||
const {
|
|
||||||
metamask: {
|
|
||||||
allCollectibleContracts,
|
|
||||||
provider: { chainId },
|
|
||||||
selectedAddress,
|
|
||||||
},
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
let decFormattedChainId;
|
|
||||||
if (typeof chainId === 'string' && isHexString(chainId)) {
|
|
||||||
decFormattedChainId = `${parseInt(chainId, 16)}`;
|
|
||||||
} else if (typeof chainId === 'number') {
|
|
||||||
decFormattedChainId = `${chainId}`;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
allCollectibleContracts?.[selectedAddress]?.[decFormattedChainId] || []
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export function getBlockGasLimit(state) {
|
export function getBlockGasLimit(state) {
|
||||||
return state.metamask.currentBlockGasLimit;
|
return state.metamask.currentBlockGasLimit;
|
||||||
}
|
}
|
||||||
|
@ -171,11 +171,6 @@ export const FONT_WEIGHT = {
|
|||||||
900: 900,
|
900: 900,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const OVERFLOW_WRAP = {
|
|
||||||
BREAK_WORD: 'break-word',
|
|
||||||
NORMAL: 'normal',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const FONT_STYLE = {
|
export const FONT_STYLE = {
|
||||||
ITALIC: 'italic',
|
ITALIC: 'italic',
|
||||||
NORMAL: 'normal',
|
NORMAL: 'normal',
|
||||||
|
@ -93,7 +93,7 @@ const PATH_NAME_MAP = {
|
|||||||
[DEFAULT_ROUTE]: 'Home',
|
[DEFAULT_ROUTE]: 'Home',
|
||||||
[UNLOCK_ROUTE]: 'Unlock Page',
|
[UNLOCK_ROUTE]: 'Unlock Page',
|
||||||
[LOCK_ROUTE]: 'Lock Page',
|
[LOCK_ROUTE]: 'Lock Page',
|
||||||
[`${ASSET_ROUTE}/:asset/:id`]: `Asset Page`,
|
[`${ASSET_ROUTE}/:asset`]: `Asset Page`,
|
||||||
[SETTINGS_ROUTE]: 'Settings Page',
|
[SETTINGS_ROUTE]: 'Settings Page',
|
||||||
[GENERAL_ROUTE]: 'General Settings Page',
|
[GENERAL_ROUTE]: 'General Settings Page',
|
||||||
[ADVANCED_ROUTE]: 'Advanced Settings Page',
|
[ADVANCED_ROUTE]: 'Advanced Settings Page',
|
||||||
|
@ -3,7 +3,6 @@ import abi from 'human-standard-token-abi';
|
|||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { util } from '@metamask/controllers';
|
|
||||||
import { addHexPrefix } from '../../../app/scripts/lib/util';
|
import { addHexPrefix } from '../../../app/scripts/lib/util';
|
||||||
import {
|
import {
|
||||||
GOERLI_CHAIN_ID,
|
GOERLI_CHAIN_ID,
|
||||||
@ -429,18 +428,3 @@ export const toHumanReadableTime = (t, milliseconds) => {
|
|||||||
export function clearClipboard() {
|
export function clearClipboard() {
|
||||||
window.navigator.clipboard.writeText('');
|
window.navigator.clipboard.writeText('');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAssetImageURL(image, ipfsGateway) {
|
|
||||||
let result = image;
|
|
||||||
if (!image || !ipfsGateway || typeof image !== 'string') {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image.startsWith('ipfs://')) {
|
|
||||||
const contentIdentifier = util.getIpfsUrlContentIdentifier(image);
|
|
||||||
result = ipfsGateway.endsWith('/')
|
|
||||||
? ipfsGateway + contentIdentifier
|
|
||||||
: `${ipfsGateway}/${contentIdentifier}`;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { isValidHexAddress } from '@metamask/controllers/dist/util';
|
|
||||||
import { useI18nContext } from '../../hooks/useI18nContext';
|
import { useI18nContext } from '../../hooks/useI18nContext';
|
||||||
import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
|
import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
|
||||||
|
|
||||||
@ -20,7 +19,6 @@ export default function AddCollectible() {
|
|||||||
|
|
||||||
const [address, setAddress] = useState('');
|
const [address, setAddress] = useState('');
|
||||||
const [tokenId, setTokenId] = useState('');
|
const [tokenId, setTokenId] = useState('');
|
||||||
const [disabled, setDisabled] = useState(true);
|
|
||||||
|
|
||||||
const handleAddCollectible = async () => {
|
const handleAddCollectible = async () => {
|
||||||
try {
|
try {
|
||||||
@ -35,16 +33,6 @@ export default function AddCollectible() {
|
|||||||
history.push(DEFAULT_ROUTE);
|
history.push(DEFAULT_ROUTE);
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateAndSetAddress = (val) => {
|
|
||||||
setDisabled(!isValidHexAddress(val) || !tokenId);
|
|
||||||
setAddress(val);
|
|
||||||
};
|
|
||||||
|
|
||||||
const validateAndSetTokenId = (val) => {
|
|
||||||
setDisabled(!isValidHexAddress(address) || !val);
|
|
||||||
setTokenId(val);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer
|
<PageContainer
|
||||||
title={t('addNFT')}
|
title={t('addNFT')}
|
||||||
@ -58,7 +46,7 @@ export default function AddCollectible() {
|
|||||||
onClose={() => {
|
onClose={() => {
|
||||||
history.push(DEFAULT_ROUTE);
|
history.push(DEFAULT_ROUTE);
|
||||||
}}
|
}}
|
||||||
disabled={disabled}
|
disabled={false}
|
||||||
contentComponent={
|
contentComponent={
|
||||||
<Box padding={4}>
|
<Box padding={4}>
|
||||||
<Box>
|
<Box>
|
||||||
@ -68,7 +56,7 @@ export default function AddCollectible() {
|
|||||||
placeholder="0x..."
|
placeholder="0x..."
|
||||||
type="text"
|
type="text"
|
||||||
value={address}
|
value={address}
|
||||||
onChange={(e) => validateAndSetAddress(e.target.value)}
|
onChange={(e) => setAddress(e.target.value)}
|
||||||
fullWidth
|
fullWidth
|
||||||
autoFocus
|
autoFocus
|
||||||
margin="normal"
|
margin="normal"
|
||||||
@ -81,7 +69,7 @@ export default function AddCollectible() {
|
|||||||
placeholder={t('nftTokenIdPlaceholder')}
|
placeholder={t('nftTokenIdPlaceholder')}
|
||||||
type="number"
|
type="number"
|
||||||
value={tokenId}
|
value={tokenId}
|
||||||
onChange={(e) => validateAndSetTokenId(e.target.value)}
|
onChange={(e) => setTokenId(e.target.value)}
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { Redirect, useParams } from 'react-router-dom';
|
import { Redirect, useParams } from 'react-router-dom';
|
||||||
import CollectibleDetails from '../../components/app/collectible-details/collectible-details';
|
import { getTokens } from '../../ducks/metamask/metamask';
|
||||||
import { getCollectibles, getTokens } from '../../ducks/metamask/metamask';
|
|
||||||
import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
|
import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
|
||||||
import { isEqualCaseInsensitive } from '../../helpers/utils/util';
|
import { isEqualCaseInsensitive } from '../../helpers/utils/util';
|
||||||
|
|
||||||
@ -12,18 +11,12 @@ import TokenAsset from './components/token-asset';
|
|||||||
const Asset = () => {
|
const Asset = () => {
|
||||||
const nativeCurrency = useSelector((state) => state.metamask.nativeCurrency);
|
const nativeCurrency = useSelector((state) => state.metamask.nativeCurrency);
|
||||||
const tokens = useSelector(getTokens);
|
const tokens = useSelector(getTokens);
|
||||||
const collectibles = useSelector(getCollectibles);
|
const { asset } = useParams();
|
||||||
const { asset, id } = useParams();
|
|
||||||
|
|
||||||
const token = tokens.find(({ address }) =>
|
const token = tokens.find(({ address }) =>
|
||||||
isEqualCaseInsensitive(address, asset),
|
isEqualCaseInsensitive(address, asset),
|
||||||
);
|
);
|
||||||
|
|
||||||
const collectible = collectibles.find(
|
|
||||||
({ address, tokenId }) =>
|
|
||||||
isEqualCaseInsensitive(address, asset) && id === tokenId,
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const el = document.querySelector('.app');
|
const el = document.querySelector('.app');
|
||||||
el.scroll(0, 0);
|
el.scroll(0, 0);
|
||||||
@ -32,8 +25,6 @@ const Asset = () => {
|
|||||||
let content;
|
let content;
|
||||||
if (token) {
|
if (token) {
|
||||||
content = <TokenAsset token={token} />;
|
content = <TokenAsset token={token} />;
|
||||||
} else if (collectible) {
|
|
||||||
content = <CollectibleDetails collectible={collectible} />;
|
|
||||||
} else if (asset === nativeCurrency) {
|
} else if (asset === nativeCurrency) {
|
||||||
content = <NativeAsset nativeCurrency={nativeCurrency} />;
|
content = <NativeAsset nativeCurrency={nativeCurrency} />;
|
||||||
} else {
|
} else {
|
||||||
|
@ -184,8 +184,7 @@ export default class Routes extends Component {
|
|||||||
path={`${CONNECT_ROUTE}/:id`}
|
path={`${CONNECT_ROUTE}/:id`}
|
||||||
component={PermissionsConnect}
|
component={PermissionsConnect}
|
||||||
/>
|
/>
|
||||||
<Authenticated path={`${ASSET_ROUTE}/:asset/:id`} component={Asset} />
|
<Authenticated path={`${ASSET_ROUTE}/:asset`} component={Asset} />
|
||||||
<Authenticated path={`${ASSET_ROUTE}/:asset/`} component={Asset} />
|
|
||||||
<Authenticated path={DEFAULT_ROUTE} component={Home} />
|
<Authenticated path={DEFAULT_ROUTE} component={Home} />
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
|
@ -566,7 +566,10 @@ export default class AdvancedTab extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleIpfsGatewaySave() {
|
handleIpfsGatewaySave() {
|
||||||
this.props.setIpfsGateway(this.state.ipfsGateway);
|
const url = new URL(addUrlProtocolPrefix(this.state.ipfsGateway));
|
||||||
|
const { host } = url;
|
||||||
|
|
||||||
|
this.props.setIpfsGateway(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderIpfsGatewayControl() {
|
renderIpfsGatewayControl() {
|
||||||
|
@ -2203,16 +2203,6 @@ export function setOpenSeaEnabled(val) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function detectCollectibles() {
|
|
||||||
return async (dispatch) => {
|
|
||||||
dispatch(showLoadingIndication());
|
|
||||||
log.debug(`background.detectCollectibles`);
|
|
||||||
await promisifiedBackground.detectCollectibles();
|
|
||||||
dispatch(hideLoadingIndication());
|
|
||||||
await forceUpdateMetamaskState(dispatch);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setAdvancedGasFee(val) {
|
export function setAdvancedGasFee(val) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(showLoadingIndication());
|
dispatch(showLoadingIndication());
|
||||||
|
28
yarn.lock
28
yarn.lock
@ -2601,19 +2601,19 @@
|
|||||||
semver "^7.3.5"
|
semver "^7.3.5"
|
||||||
yargs "^17.0.1"
|
yargs "^17.0.1"
|
||||||
|
|
||||||
"@metamask/contract-metadata@^1.19.0", "@metamask/contract-metadata@^1.28.0", "@metamask/contract-metadata@^1.31.0":
|
"@metamask/contract-metadata@^1.19.0", "@metamask/contract-metadata@^1.28.0", "@metamask/contract-metadata@^1.30.0":
|
||||||
version "1.31.0"
|
version "1.30.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.31.0.tgz#9e3e46de7a955ea1ca61f7db20d9a17b5e91d3d0"
|
resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.30.0.tgz#fa8e1b0c3e7aaa963986088f691fb553ffbe3904"
|
||||||
integrity sha512-4FBJkg/vDiYp/thIiZknxrJ0lfsj2eWIPenwlNZmoqOhoL4VqhK5eKWxi+EuGMvv9taP+QBRk6Key7wC1uL78A==
|
integrity sha512-b2usYW/ptQYnE6zhUmr4T+nvOAQJK5ABcpKudyQANpy4K099elpv4aN0WcrcOcwV99NHOdMzFP3ZuG0HoAyOBQ==
|
||||||
|
|
||||||
"@metamask/controllers@^21.0.1":
|
"@metamask/controllers@^20.1.0":
|
||||||
version "21.0.1"
|
version "20.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-21.0.1.tgz#f7776a448afd3869dce76ecb34549e867fa78ec4"
|
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-20.1.0.tgz#1d8386dc22d14f9fd9feb8b3cc8314d663587550"
|
||||||
integrity sha512-E8JLRlTC7jyUgJSaXgFYa3g5pt5NCtA87hyarZFoolNKL6yrQgLHxqRyfGV28TsNsawl1i++rxb/8rgAJSRPHw==
|
integrity sha512-Z/7uLGXZWbCBbtCybR3jo1bx3mcvZRUSm1i43od4dnJoQo2+Veq4ePrFVgPKS3WtLIM/hzZuI7UTAQ9HNX9aew==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@ethereumjs/common" "^2.3.1"
|
"@ethereumjs/common" "^2.3.1"
|
||||||
"@ethereumjs/tx" "^3.2.1"
|
"@ethereumjs/tx" "^3.2.1"
|
||||||
"@metamask/contract-metadata" "^1.31.0"
|
"@metamask/contract-metadata" "^1.30.0"
|
||||||
"@types/uuid" "^8.3.0"
|
"@types/uuid" "^8.3.0"
|
||||||
abort-controller "^3.0.0"
|
abort-controller "^3.0.0"
|
||||||
async-mutex "^0.2.6"
|
async-mutex "^0.2.6"
|
||||||
@ -2632,7 +2632,7 @@
|
|||||||
ethjs-unit "^0.1.6"
|
ethjs-unit "^0.1.6"
|
||||||
ethjs-util "^0.1.6"
|
ethjs-util "^0.1.6"
|
||||||
human-standard-collectible-abi "^1.0.2"
|
human-standard-collectible-abi "^1.0.2"
|
||||||
human-standard-multi-collectible-abi "^1.0.4"
|
human-standard-multi-collectible-abi "^1.0.2"
|
||||||
human-standard-token-abi "^2.0.0"
|
human-standard-token-abi "^2.0.0"
|
||||||
immer "^9.0.6"
|
immer "^9.0.6"
|
||||||
isomorphic-fetch "^3.0.0"
|
isomorphic-fetch "^3.0.0"
|
||||||
@ -14654,10 +14654,10 @@ human-standard-collectible-abi@^1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/human-standard-collectible-abi/-/human-standard-collectible-abi-1.0.2.tgz#077bae9ed1b0b0b82bc46932104b4b499c941aa0"
|
resolved "https://registry.yarnpkg.com/human-standard-collectible-abi/-/human-standard-collectible-abi-1.0.2.tgz#077bae9ed1b0b0b82bc46932104b4b499c941aa0"
|
||||||
integrity sha512-nD3ITUuSAIBgkaCm9J2BGwlHL8iEzFjJfTleDAC5Wi8RBJEXXhxV0JeJjd95o+rTwf98uTE5MW+VoBKOIYQh0g==
|
integrity sha512-nD3ITUuSAIBgkaCm9J2BGwlHL8iEzFjJfTleDAC5Wi8RBJEXXhxV0JeJjd95o+rTwf98uTE5MW+VoBKOIYQh0g==
|
||||||
|
|
||||||
human-standard-multi-collectible-abi@^1.0.4:
|
human-standard-multi-collectible-abi@^1.0.2:
|
||||||
version "1.0.4"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/human-standard-multi-collectible-abi/-/human-standard-multi-collectible-abi-1.0.4.tgz#981625bc1a6bea5fef90567f9e12c11581fac497"
|
resolved "https://registry.yarnpkg.com/human-standard-multi-collectible-abi/-/human-standard-multi-collectible-abi-1.0.3.tgz#be5896b13f8622289cff70040e478366931bf3d7"
|
||||||
integrity sha512-ylR9JDXClDJAxWD/QJxsjXJJdLTUmhipTquMAgrfybXL3qX3x3P/vmKg92A7qFu7SqVOf2hyv5dA8vX0j+0Thg==
|
integrity sha512-1VXqats7JQqDZozLKhpmFG0S33hVePrkLNRJNKfJTxewR0heYKjSoz72kqs+6O/Tywi0zW4fWe7dfTaPX4j7gQ==
|
||||||
|
|
||||||
human-standard-token-abi@^1.0.2:
|
human-standard-token-abi@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
|
Loading…
Reference in New Issue
Block a user