Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: econia-labs/emojicoin-dot-fun
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c706c634eaef3f29936f20e4af4fe49605fe6fd2
Choose a base ref
..
head repository: econia-labs/emojicoin-dot-fun
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1465f603758b3cdb38cb49fdc6befef51e90676a
Choose a head ref
6 changes: 6 additions & 0 deletions src/cloud-formation/README.md
Original file line number Diff line number Diff line change
@@ -41,6 +41,10 @@ indexer deployments.

## Setup

1. Choose an [AWS region][aws regions] like `us-east-2` (Ohio) if you are going
to get indexer data from the [Aptos Labs gRPC endpoint], which is located in
[GCP region][gcp regions] `us-central1` (Iowa).

1. [Make Route 53 the DNS service for a domain you own], which will
automatically be configured with a subdomain for each deployment environment.

@@ -494,6 +498,7 @@ REST and WebSocket endpoints.
[auto-selection of aurora az]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbinstance.html#cfn-rds-dbinstance-availabilityzone
[availability zone]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-availability-zones
[aws cloudformation]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html
[aws regions]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions
[aws routes docs]: https://docs.aws.amazon.com/vpc/latest/userguide/subnet-route-tables.html#route-table-routes
[aws-recommended vpc cidr block]: https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html
[az-specific nat gateways]: https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-basics.html
@@ -513,6 +518,7 @@ REST and WebSocket endpoints.
[ecr pull through cache rule creation docs]: https://docs.aws.amazon.com/AmazonECR/latest/userguide/pull-through-cache-creating-rule.html
[ecs task execution iam role]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
[fault tolerant replica promotion]: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Concepts.AuroraHighAvailability.html#Aurora.Managing.FaultTolerance
[gcp regions]: https://cloud.google.com/compute/docs/regions-zones#available
[gitsync]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/git-sync.html
[gitsync event]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/git-sync-status.html#git-sync-status-sync-events
[gitsync iam role]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/git-sync-prereq.html#git-sync-prereq-iam
3 changes: 3 additions & 0 deletions src/cloud-formation/deploy-indexer-production.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
---
parameters:
BrokerCpu: 1024
BrokerImageVersion: '1.0.1'
BrokerMemory: 2048
DbMaxCapacity: 8
DeployAlb: 'true'
DeployAlbDnsRecord: 'true'
DeployBastionHost: 'true'
20 changes: 15 additions & 5 deletions src/cloud-formation/indexer.cfn.yaml
Original file line number Diff line number Diff line change
@@ -107,10 +107,16 @@ Parameters:
BastionHostAmiId:
Default: 'ami-030cb86c12b18e236'
Type: 'AWS::EC2::Image::Id'
BrokerCpu:
Default: 256
Type: 'Number'
BrokerImageVersion:
Type: 'String'
BrokerMemory:
Default: 512
Type: 'Number'
DbMaxCapacity:
Default: 16
Default: 1
Type: 'Number'
DbMinCapacity:
Default: 0.5
@@ -654,10 +660,10 @@ Resources:
- 'Constants'
- 'Networking'
- 'BrokerPort'
Cpu: '1024'
Cpu: !Ref 'BrokerCpu'
ExecutionRoleArn: !GetAtt 'ContainerRole.Arn'
Family: !Ref 'AWS::StackName'
Memory: '2048'
Memory: !Ref 'BrokerMemory'
NetworkMode: 'awsvpc'
RequiresCompatibilities:
- 'FARGATE'
@@ -676,6 +682,10 @@ Resources:
# Cluster for running ECS containers.
ContainerCluster:
Condition: 'DeployContainers'
Properties:
ClusterSettings:
- Name: 'containerInsights'
Value: 'enabled'
Type: 'AWS::ECS::Cluster'
# Log group for ECS task logging.
ContainerLogGroup:
@@ -1305,10 +1315,10 @@ Resources:
- 'Constants'
- 'Networking'
- 'PostgrestHealthCheckPort'
Cpu: '1024'
Cpu: '256'
ExecutionRoleArn: !GetAtt 'ContainerRole.Arn'
Family: !Ref 'AWS::StackName'
Memory: '2048'
Memory: '512'
NetworkMode: 'awsvpc'
RequiresCompatibilities:
- 'FARGATE'
1 change: 0 additions & 1 deletion src/typescript/frontend/src/configs/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export { default as LOCAL_STORAGE_KEYS } from "./local-storage-keys";
export { EN, languages, languageList } from "./languages";
export { default as REGEX } from "./regex";
42 changes: 41 additions & 1 deletion src/typescript/frontend/src/configs/local-storage-keys.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,48 @@
import { parseJSON, stringifyJSON } from "utils";
import packages from "../../package.json";

const LOCAL_STORAGE_KEYS = {
theme: `${packages.name}_theme`,
language: `${packages.name}_language`,
geoblocking: `${packages.name}_geoblocking`,
};

export default LOCAL_STORAGE_KEYS;
const LOCAL_STORAGE_CACHE_TIME = {
theme: Infinity,
language: Infinity,
geoblocking: 7 * 24 * 60 * 60 * 1000, // 7 days.
};

export type LocalStorageCache<T> = {
expiry: number;
data: T | null;
};

/**
* Note that this data is not validated and any change in data type returned from this function
* should be validated to ensure that persisted cache data between multiple builds can cause errors
* with unexpected data types.
*/
export function readLocalStorageCache<T>(key: keyof typeof LOCAL_STORAGE_KEYS): T | null {
const str = localStorage.getItem(key);
if (str === null) {
return null;
}
const cache = parseJSON<LocalStorageCache<T>>(str);
try {
if (new Date(cache.expiry) > new Date()) {
return cache.data;
}
} catch (e) {
return null;
}
return null;
}

export function writeLocalStorageCache<T>(key: keyof typeof LOCAL_STORAGE_KEYS, data: T) {
const cache: LocalStorageCache<T> = {
expiry: new Date().getTime() + LOCAL_STORAGE_CACHE_TIME[key],
data,
};
localStorage.setItem(key, stringifyJSON<LocalStorageCache<T>>(cache));
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { EN, LOCAL_STORAGE_KEYS, REGEX } from "configs";
import { EN, REGEX } from "configs";
import { readLocalStorageCache } from "configs/local-storage-keys";

export const getLanguageCodeFromLocalStorage = () => {
if (typeof window === "undefined") {
return EN.locale;
}
return localStorage.getItem(LOCAL_STORAGE_KEYS.language) ?? EN.locale;
return readLocalStorageCache<string>("language") ?? EN.locale;
};

export const translatedTextIncludesVariable = (translatedText: string) => {
8 changes: 4 additions & 4 deletions src/typescript/frontend/src/context/theme-context/index.tsx
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ import { type DefaultTheme } from "styled-components";
import dark from "theme/dark";
import light from "theme/light";

import { LOCAL_STORAGE_KEYS } from "configs";
import { readLocalStorageCache, writeLocalStorageCache } from "configs/local-storage-keys";

type ContextType = {
theme: DefaultTheme;
@@ -28,7 +28,7 @@ const ThemeContextProvider: React.FC<PropsWithChildren<{}>> = ({ children }) =>
const [theme, setTheme] = useState(() => {
const themeFromStorage = getThemeValueFromLS();

localStorage.setItem(LOCAL_STORAGE_KEYS.theme, themeFromStorage);
writeLocalStorageCache("theme", themeFromStorage);
return { theme: themeValues[themeFromStorage], key: themeFromStorage };
});

@@ -42,12 +42,12 @@ const ThemeContextProvider: React.FC<PropsWithChildren<{}>> = ({ children }) =>
const themeFromStorage = getThemeValueFromLS();
const newValue = themeFromStorage === LIGHT ? DARK : LIGHT;

localStorage.setItem(LOCAL_STORAGE_KEYS.theme, newValue);
writeLocalStorageCache("theme", newValue);
setTheme({ theme: themeValues[newValue], key: newValue });
}

function getThemeValueFromLS() {
let themeFromStorage = localStorage.getItem(LOCAL_STORAGE_KEYS.theme) ?? LIGHT;
let themeFromStorage = readLocalStorageCache<string>("theme") ?? LIGHT;

if (!(themeFromStorage in themeValues)) {
themeFromStorage = LIGHT;
12 changes: 11 additions & 1 deletion src/typescript/frontend/src/hooks/use-is-user-geoblocked.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useQuery } from "@tanstack/react-query";
import { MS_IN_ONE_DAY } from "components/charts/const";
import { readLocalStorageCache, writeLocalStorageCache } from "configs/local-storage-keys";
import { isUserGeoblocked } from "utils/geolocation";

const SEVEN_DAYS_MS = 7 * MS_IN_ONE_DAY;
@@ -9,7 +10,16 @@ const useIsUserGeoblocked = (args?: { explicitlyGeoblocked: boolean }) => {
const { explicitlyGeoblocked = false } = args ?? {};
const { data } = useQuery({
queryKey: ["geoblocked"],
queryFn: () => isUserGeoblocked(),
queryFn: async () => {
let geoblocked = readLocalStorageCache<boolean>("geoblocking");

if (geoblocked === null) {
geoblocked = await isUserGeoblocked();
writeLocalStorageCache("geoblocking", geoblocked);
}

return geoblocked;
},
staleTime: SEVEN_DAYS_MS,
placeholderData: (prev) => prev,
});
5 changes: 3 additions & 2 deletions src/typescript/frontend/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -12,11 +12,12 @@ export { getStylesFromResponsiveValue } from "./styled-components-helpers";
export { isDisallowedEventKey } from "./check-is-disallowed-event-key";
export { getEmptyListTr } from "./get-empty-list-tr";

export const stringifyJSON = (data: object) =>
JSON.stringify(data, (_, value) => {
export function stringifyJSON<T>(data: T) {
return JSON.stringify(data, (_, value) => {
if (typeof value === "bigint") return value.toString() + "n";
return value;
});
}

export const parseJSON = <T>(json: string): T =>
JSON.parse(json, (_, value) => {