forked from Frankencoin-ZCHF/frankencoin-dapp
-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathapp.config.ts
More file actions
198 lines (171 loc) · 5.97 KB
/
app.config.ts
File metadata and controls
198 lines (171 loc) · 5.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
"use client";
import { ApolloClient, InMemoryCache, createHttpLink, from } from "@apollo/client";
import { onError } from "@apollo/client/link/error";
import { cookieStorage, createConfig, createStorage, http } from "@wagmi/core";
import { injected, coinbaseWallet, walletConnect } from "@wagmi/connectors";
import { mainnet, polygon, Chain } from "@wagmi/core/chains";
import axios from "axios";
import { Address, zeroAddress } from "viem";
import { getAppAddresses, isDeployed } from "@contracts";
export type ConfigEnv = {
landing: string;
app: string;
api: string;
ponder: string;
ponderFallback: string;
wagmiId: string;
alchemyApiKey: string;
chain: string;
network: {
mainnet: string;
polygon: string;
};
};
// DEV: Loaded with defaults, not needed for now.
// if (!process.env.NEXT_PUBLIC_WAGMI_ID) throw new Error("Project ID is not defined");
// if (!process.env.NEXT_PUBLIC_RPC_URL_MAINNET) throw new Error("RPC URL for at least mainnet, not available");
// if (process.env.NEXT_PUBLIC_CHAIN_NAME == "polygon" && !process.env.NEXT_PUBLIC_RPC_URL_POLYGON)
// throw new Error("RPC URL for polygon (testnet), not available");
// Config
export const CONFIG: ConfigEnv = {
landing: process.env.NEXT_PUBLIC_LANDINGPAGE_URL ?? "https://deuro.com",
app: process.env.NEXT_PUBLIC_APP_URL ?? "https://app.deuro.com",
api: process.env.NEXT_PUBLIC_API_URL ?? "https://api.deuro.com",
ponder: process.env.NEXT_PUBLIC_PONDER_URL ?? "https://ponder.deuro.com",
ponderFallback: process.env.NEXT_PUBLIC_PONDER_FALLBACK_URL ?? "https://dev.ponder.deuro.com/",
wagmiId: "e915436dd22f9ebb227b553076924700",
alchemyApiKey: process.env.NEXT_PUBLIC_ALCHEMY_API_KEY ?? "",
chain: process.env.NEXT_PUBLIC_CHAIN_NAME ?? "mainnet",
network: {
mainnet: process.env.NEXT_PUBLIC_RPC_URL_MAINNET ?? "https://eth-mainnet.g.alchemy.com/v2",
polygon: process.env.NEXT_PUBLIC_RPC_URL_POLYGON ?? "https://polygon-mainnet.g.alchemy.com/v2",
},
};
const PRINT_CONFIG = (): ConfigEnv => {
const printConfig = { ...CONFIG };
printConfig.wagmiId = TRUNCATE_STRING(printConfig.wagmiId, 5, 5);
printConfig.alchemyApiKey = TRUNCATE_STRING(printConfig.alchemyApiKey, 5, 5);
return printConfig;
};
const TRUNCATE_STRING = (text: string, startCount: number, endCount: number): string => {
if (text.length <= startCount + endCount) return text;
const first = text.slice(0, startCount);
const last = text.slice(-endCount);
return `${first}...${last}`;
};
// PRINT CONFIGURATION PROFILE
console.log("YOU ARE USING THIS CONFIG PROFILE:");
console.log(PRINT_CONFIG());
// CONFIG CHAIN
export const CONFIG_CHAIN = (): Chain => {
return CONFIG.chain === "polygon" ? polygon : mainnet;
};
// CONFIG RPC
export const CONFIG_RPC = (): string => {
return CONFIG.chain === "polygon"
? `${CONFIG.network.polygon}/${CONFIG.alchemyApiKey}`
: `${CONFIG.network.mainnet}/${CONFIG.alchemyApiKey}`;
};
// Ponder fallback mechanism
let fallbackUntil: number | null = null;
function getPonderUrl(): string {
return fallbackUntil && Date.now() < fallbackUntil
? CONFIG.ponderFallback
: CONFIG.ponder;
}
function activateFallback(): void {
if (!fallbackUntil) {
fallbackUntil = Date.now() + 10 * 60 * 1000; // 10 minutes
console.log("[Ponder] Switching to fallback for 10min:", CONFIG.ponderFallback);
}
}
// PONDER CLIENT
const errorLink = onError(({ graphQLErrors, networkError, operation, forward }) => {
// Log GraphQL errors for better debugging
if (graphQLErrors) {
graphQLErrors.forEach((error) => {
console.error(`[GraphQL error in operation: ${operation?.operationName || 'unknown'}]`, {
message: error.message,
locations: error.locations,
path: error.path,
});
});
}
if (!networkError || getPonderUrl() !== CONFIG.ponder) return;
const is503 =
(networkError as any)?.response?.status === 503 ||
(networkError as any)?.statusCode === 503 ||
(networkError as any)?.result?.status === 503;
// Handle 503 Service Unavailable (Ponder syncing)
if (is503) {
console.log("[Ponder] 503 Service Unavailable - Ponder is syncing, switching to fallback");
activateFallback();
return forward(operation);
}
// Handle other network errors
console.error(`[Network error in operation: ${operation?.operationName || 'unknown'}]`, {
message: (networkError as any).message,
name: (networkError as any).name,
});
console.log("[Ponder] Network error detected, activating fallback");
activateFallback();
return forward(operation);
});
const httpLink = createHttpLink({
uri: () => getPonderUrl(),
// Add timeout protection for hanging requests
fetchOptions: {
timeout: 10000, // 10 second timeout
},
});
export const PONDER_CLIENT = new ApolloClient({
link: from([errorLink, httpLink]),
cache: new InMemoryCache(),
});
// DEURO API CLIENT
export const DEURO_API_CLIENT = axios.create({
baseURL: CONFIG.api,
});
// WAGMI CONFIG
export const WAGMI_CHAIN = CONFIG_CHAIN();
export const WAGMI_METADATA = {
name: "dEURO",
description: "dEURO Frontend Application",
url: CONFIG.landing,
icons: ["https://avatars.githubusercontent.com/u/37784886"],
};
export const WAGMI_CONFIG = createConfig({
chains: [WAGMI_CHAIN],
transports: {
[WAGMI_CHAIN.id]: http(CONFIG_RPC()),
},
batch: {
multicall: {
wait: 200,
},
},
connectors: [
walletConnect({ projectId: CONFIG.wagmiId, metadata: WAGMI_METADATA, showQrModal: false }),
injected({ shimDisconnect: true }),
coinbaseWallet({
appName: WAGMI_METADATA.name,
appLogoUrl: WAGMI_METADATA.icons[0],
}),
],
ssr: true,
storage: createStorage({
storage: cookieStorage,
}),
});
// MINT POSITION BLACKLIST
export const MINT_POSITION_BLACKLIST: Address[] = ["0x98725eE62833096C1c9bE26001F3cDA9a6241EF3"];
export const POSITION_NOT_BLACKLISTED = (addr: Address): boolean => {
const r = MINT_POSITION_BLACKLIST.filter((p) => {
return p.toLowerCase() === addr.toLowerCase();
});
return r.length == 0;
};
export const GET_SAVINGS_V3_ADDRESS = (chainId: number): Address => {
const address = getAppAddresses(chainId).savings;
return isDeployed(address) ? address : zeroAddress;
};