Skip to content

Commit

Permalink
Offline metadata (rainbow-me#2057)
Browse files Browse the repository at this point in the history
* add offline metadata script

* consume offline metadata

* add migration to wipe metadata from localstorage

* clean up

* dont use metadata img for token family icon

* dont use metadata img for nfts previews

* Improve fallback coin icon colors

Co-authored-by: Christian Baroni <[email protected]>
  • Loading branch information
brunobar79 and christianbaroni authored May 31, 2021
1 parent 51a2a9b commit 9733ee5
Show file tree
Hide file tree
Showing 11 changed files with 16,313 additions and 738 deletions.
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"test": "jest test.js",
"update-env": "curl -H 'Authorization: token '$GITHUB_TOKEN -H 'Accept: application/vnd.github.v3.raw' -O -L https://api.github.com/repos/rainbow-me/rainbow-env/contents/dotenv && rm -f .env && mv dotenv .env",
"android-reverse-ports": "adb reverse tcp:8097 tcp:8097 && adb reverse tcp:8081 tcp:8081",
"update-token-list": "./scripts/update-token-list.sh"
"update-token-list": "./scripts/update-token-list.sh",
"update-token-metadata": "./scripts/update-token-metadata.sh"
},
"husky": {
"hooks": {
Expand Down Expand Up @@ -244,6 +245,8 @@
"@types/react-test-renderer": "^16.9.3",
"@types/styled-components": "^5.1.7",
"@types/url-parse": "^1.4.3",
"@typescript-eslint/eslint-plugin": "^4.24.0",
"@typescript-eslint/parser": "^4.24.0",
"ast-parser": "^0.0.5",
"audit-ci": "^3.1.1",
"babel-core": "7.0.0-bridge.0",
Expand All @@ -264,17 +267,17 @@
"eslint-plugin-jest": "^24.3.6",
"ganache-cli": "6.12.2",
"graphql": "^15.3.0",
"image-size": "^1.0.0",
"jest": "^26.6.3",
"jest-circus": "^26.6.3",
"metro-plugin-anisotropic-transform": "rainbow-me/metro-plugin-anisotropic-transform#463b4ca9f5631f9c5e6028d22a450f6f0e54214f",
"metro-react-native-babel-preset": "^0.64.0",
"node-vibrant": "^3.2.1-alpha.1",
"prettier": "^2.2.1",
"react-test-renderer": "17.0.1",
"rn-nodeify": "10.2.0",
"schedule": "0.5.0",
"typescript": "^3.9.7",
"@typescript-eslint/parser": "^4.24.0",
"@typescript-eslint/eslint-plugin": "^4.24.0"
"typescript": "^3.9.7"
},
"resolutions": {
"**/node-fetch": "2.6.1",
Expand Down
67 changes: 67 additions & 0 deletions scripts/extract-metadata.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* eslint-disable no-console */
/* eslint-disable import/no-commonjs */
const { readdirSync, writeFileSync } = require('fs');
const sizeOf = require('image-size');
const {
default: makeColorMoreChill,
isBlackOrWhite,
} = require('make-color-more-chill');
const Vibrant = require('node-vibrant');

const start = Date.now();

const args = process.argv.slice(2);
const assets_dir = args[0];
console.log('Extracting metadata...');

const getDirectories = source =>
readdirSync(source, { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name);

const tokenAddresses = getDirectories(assets_dir);
let allItems = {};
const init = async () => {
for (let i = 0; i < tokenAddresses.length; i++) {
const address = tokenAddresses[i];
const imageUrl = `https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/${address}/logo.png`;
let metadata = {};
try {
const filePath = `${assets_dir}/${address}/logo.png`;
const { width, height } = sizeOf(filePath);
metadata.dimensions = {
height,
isSquare: height === width,
width,
};

const palette = await Vibrant.from(filePath).getPalette();
const primaryColor = palette.Vibrant.hex;
const secondaryColor = palette.Muted.hex;
let color = makeColorMoreChill(primaryColor);
if (isBlackOrWhite(secondaryColor)) {
color = makeColorMoreChill(primaryColor);
}
if (isBlackOrWhite(primaryColor)) {
color = makeColorMoreChill(secondaryColor);
}
if (color) {
metadata.color = color;
}
// eslint-disable-next-line no-empty
} catch (e) {
} finally {
allItems[imageUrl] = metadata;
}
}

const data = JSON.stringify(allItems);
writeFileSync('tokens-metadata.json', data);

const end = Date.now();
const time = (end - start) / 1000;
console.log(`Processed ${tokenAddresses.length} images`);
console.log(`Took ${time} seconds`);
};

init();
4 changes: 4 additions & 0 deletions scripts/update-token-metadata.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
git clone https://github.com/trustwallet/assets assets-tmp
node ./scripts/extract-metadata.js assets-tmp/blockchains/ethereum/assets/
mv -f tokens-metadata.json ./src/references/meta/tokens-metadata.json
rm -rf assets-tmp
4 changes: 2 additions & 2 deletions src/components/token-family/TokenFamilyHeaderIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { FallbackIcon } from 'react-coin-icon';
import styled from 'styled-components';
import { initials } from '../../utils';
import { Emoji } from '../text';
import { ImageWithCachedMetadata } from '@rainbow-me/images';
import { ImgixImage } from '@rainbow-me/images';
import { borders } from '@rainbow-me/styles';
import ShadowStack from 'react-native-shadow-stack';

Expand Down Expand Up @@ -46,7 +46,7 @@ const TokenFamilyHeaderIcon = ({
style={style}
>
{familyImage ? (
<ImageWithCachedMetadata imageUrl={familyImage} style={circleStyle} />
<ImgixImage source={{ uri: familyImage }} style={circleStyle} />
) : (
<FallbackIcon {...circleStyle} symbol={initials(familyName)} />
)}
Expand Down
6 changes: 3 additions & 3 deletions src/components/unique-token/UniqueTokenImage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { buildUniqueTokenName } from '../../helpers/assets';
import { magicMemo } from '../../utils';
import { Centered } from '../layout';
import { Monospace } from '../text';
import { ImageWithCachedMetadata, ImgixImage } from '@rainbow-me/images';
import { ImgixImage } from '@rainbow-me/images';
import { position } from '@rainbow-me/styles';

const FallbackTextColorVariants = (darkMode, colors) => ({
Expand Down Expand Up @@ -33,10 +33,10 @@ const UniqueTokenImage = ({
return (
<Centered backgroundColor={backgroundColor} style={position.coverAsObject}>
{imageUrl && !error ? (
<ImageWithCachedMetadata
imageUrl={imageUrl}
<ImgixImage
onError={handleError}
resizeMode={ImgixImage.resizeMode[resizeMode]}
source={{ uri: imageUrl }}
style={position.coverAsObject}
/>
) : (
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/localstorage/globalSettings.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getGlobal, saveGlobal } from './common';
import networkTypes from '@rainbow-me/helpers/networkTypes';

const IMAGE_METADATA = 'imageMetadata';
export const IMAGE_METADATA = 'imageMetadata';
const KEYBOARD_HEIGHT = 'keyboardHeight';
const LANGUAGE = 'language';
const NATIVE_CURRENCY = 'nativeCurrency';
Expand Down
5 changes: 3 additions & 2 deletions src/hooks/useImageMetadata.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useCallback, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import OfflineMetadata from '../references/meta/tokens-metadata.json';
import useDimensions from './useDimensions';
import { updateImageMetadataCache } from '@rainbow-me/redux/imageMetadata';
import { position } from '@rainbow-me/styles';
Expand All @@ -14,7 +15,8 @@ export default function useImageMetadata(imageUrl) {
[imageUrl]
);

const metadata = useSelector(imageMetadataSelector);
const selectorMeta = useSelector(imageMetadataSelector);
const metadata = imageUrl ? OfflineMetadata[imageUrl] || selectorMeta : null;
const defaultMetadata = useMemo(
() => ({
dimensions: position.sizeAsObject(deviceWidth - 30),
Expand All @@ -26,7 +28,6 @@ export default function useImageMetadata(imageUrl) {
const onCacheImageMetadata = useCallback(
async ({ color, height, width }) => {
if (isCached || !imageUrl) return;

const colorFromImage = await getDominantColorFromImage(imageUrl);

dispatch(
Expand Down
9 changes: 9 additions & 0 deletions src/model/migrations.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { findKey, keys } from 'lodash';
import { removeLocal } from '../handlers/localstorage/common';
import { IMAGE_METADATA } from '../handlers/localstorage/globalSettings';
import {
getMigrationVersion,
setMigrationVersion,
Expand Down Expand Up @@ -273,6 +275,13 @@ export default async function runMigrations() {

migrations.push(v7);

const v8 = async () => {
logger.log('wiping old metadata');
await removeLocal(IMAGE_METADATA);
};

migrations.push(v8);

logger.sentry(
`Migrations: ready to run migrations starting on number ${currentVersion}`
);
Expand Down
1 change: 1 addition & 0 deletions src/references/meta/tokens-metadata.json

Large diffs are not rendered by default.

Loading

0 comments on commit 9733ee5

Please sign in to comment.