forked from LaconicNetwork/icns-frontend
Fix some logic handling error
This commit is contained in:
parent
da01e40550
commit
d33788e2b1
@ -23,7 +23,8 @@ class ErrorBoundary extends Component<Props, State> {
|
||||
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
console.error("Uncaught error:", error, errorInfo);
|
||||
|
||||
captureException(error);
|
||||
const errorMessage = error.message || error;
|
||||
captureException(errorMessage);
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
@ -2,12 +2,11 @@
|
||||
const { withSentryConfig } = require("@sentry/nextjs");
|
||||
|
||||
const nextConfig = {
|
||||
sentry: {
|
||||
hideSourceMaps: true,
|
||||
},
|
||||
api: {
|
||||
externalResolver: true,
|
||||
},
|
||||
...(!!process.env.NEXT_PUBLIC_SENTRY_DSN && {
|
||||
sentry: {
|
||||
hideSourceMaps: true,
|
||||
},
|
||||
}),
|
||||
reactStrictMode: false,
|
||||
swcMinify: true,
|
||||
compiler: {
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { captureException } from "@sentry/nextjs";
|
||||
import { withIronSessionApiRoute } from "iron-session/next";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { ironOptions } from "../../iron.config";
|
||||
import { IcnsVerificationResponse } from "../../types";
|
||||
import { request } from "../../utils/url";
|
||||
|
||||
export default withIronSessionApiRoute(async function handler(
|
||||
req: NextApiRequest,
|
||||
@ -10,30 +9,42 @@ export default withIronSessionApiRoute(async function handler(
|
||||
) {
|
||||
try {
|
||||
if (!process.env.ICNS_VERIFIER_ORIGIN_LIST) {
|
||||
console.log(".env is not set");
|
||||
const errorMessage = ".env is not set";
|
||||
console.error(errorMessage);
|
||||
captureException(errorMessage);
|
||||
return res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
const verifierOriginList = process.env.ICNS_VERIFIER_ORIGIN_LIST.split(",");
|
||||
|
||||
const verificationList = await Promise.allSettled(
|
||||
verifierOriginList.map((verfierOrigin) =>
|
||||
request<IcnsVerificationResponse>(
|
||||
`${verfierOrigin}/api/verify_twitter`,
|
||||
{
|
||||
verifierOriginList.map(async (verfierOrigin) =>
|
||||
(
|
||||
await fetch(`${verfierOrigin}/api/verify_twitter`, {
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(req.body),
|
||||
},
|
||||
),
|
||||
})
|
||||
).json(),
|
||||
),
|
||||
);
|
||||
|
||||
const errorTrimmedVerificationList = verificationList.map(
|
||||
(verification) => ({
|
||||
...verification,
|
||||
...(verification.status === "rejected" && {
|
||||
reason: verification.reason.message || verification.reason,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
res.status(200).json({
|
||||
verificationList,
|
||||
verificationList: errorTrimmedVerificationList,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
captureException(error);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
},
|
||||
|
@ -1,8 +1,8 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { captureException } from "@sentry/nextjs";
|
||||
import { withIronSessionApiRoute } from "iron-session/next";
|
||||
import { request } from "../../utils/url";
|
||||
import { ironOptions } from "../../iron.config";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { twitterApiBaseUrl } from "../../constants/twitter";
|
||||
import { ironOptions } from "../../iron.config";
|
||||
|
||||
export default withIronSessionApiRoute(async function handler(
|
||||
req: NextApiRequest,
|
||||
@ -45,53 +45,60 @@ export default withIronSessionApiRoute(async function handler(
|
||||
params.append("code_verifier", req.session.code_verifier);
|
||||
}
|
||||
|
||||
const { access_token: accessToken, refresh_token } =
|
||||
await request<TwitterOAuth2TokenResponse>(
|
||||
`${twitterApiBaseUrl}/oauth2/token`,
|
||||
{
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
Authorization: `Basic ${Buffer.from(
|
||||
`${process.env.TWITTER_CLIENT_ID}:${process.env.TWITTER_CLIENT_SECRET}`,
|
||||
).toString("base64")}`,
|
||||
},
|
||||
body: params,
|
||||
const {
|
||||
access_token: accessToken,
|
||||
refresh_token,
|
||||
}: TwitterOAuth2TokenResponse = await (
|
||||
await fetch(`${twitterApiBaseUrl}/oauth2/token`, {
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
Authorization: `Basic ${Buffer.from(
|
||||
`${process.env.TWITTER_CLIENT_ID}:${process.env.TWITTER_CLIENT_SECRET}`,
|
||||
).toString("base64")}`,
|
||||
},
|
||||
);
|
||||
body: params,
|
||||
})
|
||||
).json();
|
||||
|
||||
req.session.refresh_token = refresh_token;
|
||||
await req.session.save();
|
||||
const {
|
||||
data: {
|
||||
id,
|
||||
username,
|
||||
name,
|
||||
profile_image_url,
|
||||
description,
|
||||
public_metrics,
|
||||
},
|
||||
} = await request<TwitterUsersMeResponse>(
|
||||
`${twitterApiBaseUrl}/users/me?user.fields=profile_image_url,public_metrics,description`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
const { data, title }: TwitterUsersMeResponse = await (
|
||||
await fetch(
|
||||
`${twitterApiBaseUrl}/users/me?user.fields=profile_image_url,public_metrics,description`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
)
|
||||
).json();
|
||||
const {
|
||||
id,
|
||||
username,
|
||||
name,
|
||||
profile_image_url,
|
||||
description,
|
||||
public_metrics,
|
||||
} = data || {};
|
||||
|
||||
res.status(200).json({
|
||||
accessToken,
|
||||
id,
|
||||
username,
|
||||
name,
|
||||
profile_image_url: profile_image_url.replace("normal.jpg", "400x400.jpg"),
|
||||
profile_image_url: profile_image_url?.replace(
|
||||
"normal.jpg",
|
||||
"400x400.jpg",
|
||||
),
|
||||
description,
|
||||
public_metrics,
|
||||
error: title,
|
||||
});
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
res.status(500).json({ error: "Internal server error " });
|
||||
captureException(error);
|
||||
res.status(500).json({ error: "Internal Server Error" });
|
||||
}
|
||||
},
|
||||
ironOptions);
|
||||
@ -105,7 +112,7 @@ interface TwitterOAuth2TokenResponse {
|
||||
}
|
||||
|
||||
interface TwitterUsersMeResponse {
|
||||
data: {
|
||||
data?: {
|
||||
id: string;
|
||||
username: string;
|
||||
name: string;
|
||||
@ -113,6 +120,11 @@ interface TwitterUsersMeResponse {
|
||||
description: string;
|
||||
public_metrics: TwitterPublicMetrics;
|
||||
};
|
||||
// Error data
|
||||
title?: string;
|
||||
detail?: string;
|
||||
type?: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export interface TwitterPublicMetrics {
|
||||
|
@ -1,13 +1,14 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { captureException } from "@sentry/nextjs";
|
||||
import crypto from "crypto";
|
||||
import { withIronSessionApiRoute } from "iron-session/next";
|
||||
import { base64URLEncode } from "../../utils/encoding";
|
||||
import { buildQueryString } from "../../utils/url";
|
||||
import { ironOptions } from "../../iron.config";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import {
|
||||
twitterOAuthBaseUrl,
|
||||
twitterOAuthScopes,
|
||||
} from "../../constants/twitter";
|
||||
import { ironOptions } from "../../iron.config";
|
||||
import { base64URLEncode } from "../../utils/encoding";
|
||||
import { buildQueryString } from "../../utils/url";
|
||||
|
||||
export default withIronSessionApiRoute(async function handler(
|
||||
req: NextApiRequest,
|
||||
@ -46,6 +47,7 @@ export default withIronSessionApiRoute(async function handler(
|
||||
res.status(200).json({ authUrl });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
captureException(error);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
},
|
||||
|
@ -239,13 +239,12 @@ export default function VerificationPage() {
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
if (error.message === TWITTER_LOGIN_ERROR) {
|
||||
setErrorMessage({ message: TWITTER_LOGIN_ERROR, path: "/" });
|
||||
setErrorModalOpen(true);
|
||||
}
|
||||
setErrorMessage({ message: error.message, path: "/" });
|
||||
setErrorModalOpen(true);
|
||||
}
|
||||
|
||||
console.error(error);
|
||||
captureException(error);
|
||||
} finally {
|
||||
setIsLoadingInit(false);
|
||||
}
|
||||
@ -404,8 +403,7 @@ export default function VerificationPage() {
|
||||
|
||||
if (verification.status === "rejected") {
|
||||
if (verification.reason) {
|
||||
const errorMessage =
|
||||
verification.reason.message || verification.reason;
|
||||
const errorMessage = verification.reason;
|
||||
captureException(errorMessage);
|
||||
}
|
||||
}
|
||||
@ -443,8 +441,6 @@ export default function VerificationPage() {
|
||||
rest: REST_URL,
|
||||
};
|
||||
|
||||
console.log(aminoMsgs);
|
||||
|
||||
const simulated = await simulateMsgs(
|
||||
chainInfo,
|
||||
walletKey.bech32Address,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {
|
||||
IcnsVerificationResponse,
|
||||
IcnsVerificationResponseOnFrontend,
|
||||
TwitterAuthInfoResponse,
|
||||
TwitterAuthUrlResponse,
|
||||
} from "../types";
|
||||
@ -27,15 +27,18 @@ export const verifyTwitterAccount = async (
|
||||
accessToken: string,
|
||||
) => {
|
||||
return (
|
||||
await request<IcnsVerificationResponse>("/api/icns-verification", {
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
await request<IcnsVerificationResponseOnFrontend>(
|
||||
"/api/icns-verification",
|
||||
{
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
claimer: claimer,
|
||||
authToken: accessToken,
|
||||
}),
|
||||
},
|
||||
body: JSON.stringify({
|
||||
claimer: claimer,
|
||||
authToken: accessToken,
|
||||
}),
|
||||
})
|
||||
)
|
||||
).verificationList;
|
||||
};
|
||||
|
@ -38,6 +38,30 @@ export interface IcnsVerificationResponse {
|
||||
)[];
|
||||
}
|
||||
|
||||
export interface IcnsVerificationResponseOnFrontend {
|
||||
verificationList: (
|
||||
| {
|
||||
status: "fulfilled";
|
||||
value: {
|
||||
errors: Error[];
|
||||
data: {
|
||||
// JSON string
|
||||
verifying_msg: string;
|
||||
// Base64 encoded
|
||||
public_key: string;
|
||||
// Base64 encoded
|
||||
signature: string;
|
||||
algorithm: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
| {
|
||||
status: "rejected";
|
||||
reason: string;
|
||||
}
|
||||
)[];
|
||||
}
|
||||
|
||||
export interface NameByTwitterIdQueryResponse {
|
||||
data: {
|
||||
name: string;
|
||||
|
31
utils/url.ts
31
utils/url.ts
@ -2,23 +2,32 @@ import { TwitterLoginSuccess } from "../types";
|
||||
import { TWITTER_LOGIN_ERROR } from "../constants/error-message";
|
||||
import { WALLET_INSTALL_URL } from "../constants/wallet";
|
||||
|
||||
export function request<TResponse>(
|
||||
export async function request<TResponse>(
|
||||
url: string,
|
||||
config: RequestInit = {},
|
||||
customConfig?: {
|
||||
isErrorIgnore?: boolean;
|
||||
},
|
||||
): Promise<TResponse> {
|
||||
return fetch(url, config)
|
||||
.then((response) => {
|
||||
if (!response.ok && !customConfig?.isErrorIgnore) {
|
||||
throw new Error(
|
||||
`This is an HTTP error: The status is ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((data) => data as TResponse);
|
||||
const response = await fetch(url, config);
|
||||
const data = await response.json();
|
||||
|
||||
if (
|
||||
(!response.ok || data.error || data.errors) &&
|
||||
!customConfig?.isErrorIgnore
|
||||
) {
|
||||
const { error, errors } = data;
|
||||
let errorMessage;
|
||||
if (error && error.error) {
|
||||
errorMessage = error.error_description;
|
||||
} else {
|
||||
errorMessage =
|
||||
(error && error.toString()) || (errors && errors.toString());
|
||||
}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export function buildQueryString(query: Record<string, any>): string {
|
||||
|
Loading…
Reference in New Issue
Block a user