Compare commits
44
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3fb440fb5 | ||
|
|
2307f11ab3 | ||
|
|
d8d48a9516 | ||
|
|
5ffbcfc302 | ||
|
|
d27a3dee83 | ||
|
|
7080ff29fc | ||
|
|
638afd8e08 | ||
|
|
947e3345ef | ||
|
|
ea51a50bfc | ||
|
|
c6f59e1b01 | ||
|
|
6d1eabe9f9 | ||
|
|
c238fde877 | ||
|
|
548601981f | ||
|
|
05481aa8c0 | ||
|
|
1cc26e43e5 | ||
|
|
99d7ec06ec | ||
|
|
ff996646b2 | ||
|
|
01260009be | ||
|
|
7dea0975ec | ||
|
|
a63f5dc7cb | ||
|
|
fd7a9f0998 | ||
|
|
246b0d4aac | ||
|
|
42ba15f2c0 | ||
|
|
aa9f48d136 | ||
|
|
64138642e8 | ||
|
|
223008b1f7 | ||
|
|
cbfd445ae7 | ||
|
|
137f46a547 | ||
|
|
1b8accde30 | ||
|
|
07544252b4 | ||
|
|
8708519cad | ||
|
|
6c30b7efc7 | ||
|
|
8b5e344f72 | ||
|
|
010955ff5c | ||
|
|
956b5645e4 | ||
|
|
068db44603 | ||
|
|
dd7d0fca2d | ||
|
|
526176c471 | ||
|
|
09120c923c | ||
|
|
d1f8e95162 | ||
|
|
6573556d0e | ||
|
|
fc62b91ee5 | ||
|
|
08e9cd206b | ||
|
|
fb0f12ae28 |
+3
-1
@@ -20,4 +20,6 @@ playwright-report/
|
||||
.env/
|
||||
|
||||
# Artifacts
|
||||
packages/cli/artifacts/
|
||||
packages/cli/artifacts/
|
||||
|
||||
typedoc
|
||||
@@ -1,5 +1,57 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 4.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1801](https://github.com/thirdweb-dev/js/pull/1801) [`99d7ec06`](https://github.com/thirdweb-dev/js/commit/99d7ec06ec4f31308627edc87d3122c21a884b5a) Thanks [@adam-maj](https://github.com/adam-maj)! - Add support for fastify
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1812](https://github.com/thirdweb-dev/js/pull/1812) [`c238fde8`](https://github.com/thirdweb-dev/js/commit/c238fde8777fd14b39837117e2d3fda1dd301029) Thanks [@adam-maj](https://github.com/adam-maj)! - Update to call uuidv4 to generate jti
|
||||
|
||||
- [#1811](https://github.com/thirdweb-dev/js/pull/1811) [`54860198`](https://github.com/thirdweb-dev/js/commit/548601981f6dd8706d7a9bd4ca48e4abc7723a1d) Thanks [@adam-maj](https://github.com/adam-maj)! - Expose buildJWT function
|
||||
|
||||
- [#1812](https://github.com/thirdweb-dev/js/pull/1812) [`c238fde8`](https://github.com/thirdweb-dev/js/commit/c238fde8777fd14b39837117e2d3fda1dd301029) Thanks [@adam-maj](https://github.com/adam-maj)! - Update to use uuidv4 for default jti
|
||||
|
||||
- Updated dependencies [[`5ffbcfc3`](https://github.com/thirdweb-dev/js/commit/5ffbcfc302f74167768b196d93a328f979344036), [`d27a3dee`](https://github.com/thirdweb-dev/js/commit/d27a3dee8398d5707d2d1343c428abf8e03f67e3), [`ff996646`](https://github.com/thirdweb-dev/js/commit/ff996646b228d4d095eea04b05004dd26fc7e522), [`aa9f48d1`](https://github.com/thirdweb-dev/js/commit/aa9f48d1361194fc81146da530c95a3409bd0799), [`fd7a9f09`](https://github.com/thirdweb-dev/js/commit/fd7a9f09989e39b02a93d9dfd01cc7378e6ead53), [`2307f11a`](https://github.com/thirdweb-dev/js/commit/2307f11ab311aa4a775edd23e777d10f8015ce86), [`64138642`](https://github.com/thirdweb-dev/js/commit/64138642e84d8b56b254762eca613d443cca292b)]:
|
||||
- @thirdweb-dev/wallets@2.0.8
|
||||
|
||||
## 4.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@2.0.7
|
||||
|
||||
## 4.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@2.0.6
|
||||
|
||||
## 4.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@2.0.5
|
||||
|
||||
## 4.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@2.0.4
|
||||
|
||||
## 4.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@2.0.3
|
||||
|
||||
## 4.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-auth-fastify.cjs.js",
|
||||
"module": "dist/thirdweb-dev-auth-fastify.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-auth-fastify.esm.js": "./dist/thirdweb-dev-auth-fastify.browser.esm.js"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "4.0.2",
|
||||
"version": "4.1.0",
|
||||
"main": "dist/thirdweb-dev-auth.cjs.js",
|
||||
"module": "dist/thirdweb-dev-auth.esm.js",
|
||||
"browser": {
|
||||
@@ -35,6 +35,13 @@
|
||||
},
|
||||
"default": "./express/dist/thirdweb-dev-auth-express.cjs.js"
|
||||
},
|
||||
"./fastify": {
|
||||
"module": {
|
||||
"browser": "./fastify/dist/thirdweb-dev-auth-fastify.browser.esm.js",
|
||||
"default": "./fastify/dist/thirdweb-dev-auth-fastify.esm.js"
|
||||
},
|
||||
"default": "./fastify/dist/thirdweb-dev-auth-fastify.cjs.js"
|
||||
},
|
||||
"./next-auth": {
|
||||
"module": {
|
||||
"browser": "./next-auth/dist/thirdweb-dev-auth-next-auth.browser.esm.js",
|
||||
@@ -63,6 +70,7 @@
|
||||
"express/index.ts",
|
||||
"next/index.ts",
|
||||
"next-auth/index.ts",
|
||||
"fastify/index.ts",
|
||||
"evm/index.ts"
|
||||
],
|
||||
"exports": {
|
||||
@@ -101,6 +109,7 @@
|
||||
"eslint-plugin-tsdoc": "^0.2.16",
|
||||
"ethers": "^5.7.2",
|
||||
"express": "^4.18.1",
|
||||
"fastify": "^4.24.2",
|
||||
"mocha": "^10.2.0",
|
||||
"next": "^12.3.4",
|
||||
"next-auth": "^4.22.3",
|
||||
@@ -111,6 +120,7 @@
|
||||
"cookie-parser": "^1.4.6",
|
||||
"ethers": "^5",
|
||||
"express": "^4",
|
||||
"fastify": "^4.24.2",
|
||||
"next": "^12 || ^13",
|
||||
"next-auth": "^4"
|
||||
},
|
||||
@@ -124,6 +134,9 @@
|
||||
"express": {
|
||||
"optional": true
|
||||
},
|
||||
"fastify": {
|
||||
"optional": true
|
||||
},
|
||||
"next": {
|
||||
"optional": true
|
||||
},
|
||||
@@ -132,8 +145,10 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/cookie": "^9.1.0",
|
||||
"@thirdweb-dev/wallets": "workspace:*",
|
||||
"cookie": "^0.5.0",
|
||||
"fastify-type-provider-zod": "^1.1.9",
|
||||
"uuid": "^9.0.1",
|
||||
"zod": "^3.22.3"
|
||||
}
|
||||
|
||||
@@ -38,7 +38,10 @@ function base64decode(data: string): string {
|
||||
/**
|
||||
* Build JWT token based on the authentication payload
|
||||
*/
|
||||
async function buildJWT({ wallet, payload }: BuildJwtParams): Promise<string> {
|
||||
export async function buildJWT({
|
||||
wallet,
|
||||
payload,
|
||||
}: BuildJwtParams): Promise<string> {
|
||||
const payloadData = AuthenticationPayloadDataSchema.parse(payload);
|
||||
|
||||
const message = JSON.stringify(payloadData);
|
||||
|
||||
@@ -3,6 +3,7 @@ export { ThirdwebAuth } from "./auth";
|
||||
|
||||
// Export individual auth functions
|
||||
export {
|
||||
buildJWT,
|
||||
generateJWT,
|
||||
parseJWT,
|
||||
refreshJWT,
|
||||
|
||||
@@ -9,7 +9,7 @@ export const AuthenticationPayloadDataSchema = z.object({
|
||||
exp: RawDateSchema,
|
||||
nbf: RawDateSchema,
|
||||
iat: RawDateSchema,
|
||||
jti: z.string().default(uuidv4()),
|
||||
jti: z.string().default(() => uuidv4()),
|
||||
ctx: JsonSchema.optional(),
|
||||
});
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export const LoginPayloadDataSchema = z.object({
|
||||
uri: z.string().optional(),
|
||||
version: z.string().default("1"),
|
||||
chain_id: z.string().optional(),
|
||||
nonce: z.string().default(uuidv4()),
|
||||
nonce: z.string().default(() => uuidv4()),
|
||||
issued_at: z
|
||||
.date()
|
||||
.default(new Date())
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE,
|
||||
THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX,
|
||||
} from "../../constants";
|
||||
import { Json } from "../../core/schema";
|
||||
import { Json } from "../../core";
|
||||
import { ThirdwebAuthContext, ThirdwebAuthUser } from "../types";
|
||||
import { Request } from "express";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE,
|
||||
THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX,
|
||||
} from "../../constants";
|
||||
import { GenerateOptions } from "../../core";
|
||||
import { GenerateOptionsWithOptionalDomain } from "../../core";
|
||||
import { LoginPayloadBodySchema, ThirdwebAuthContext } from "../types";
|
||||
import { serialize } from "cookie";
|
||||
import { Request, Response } from "express";
|
||||
@@ -41,7 +41,7 @@ export default async function handler(
|
||||
? new Date(Date.now() + 1000 * ctx.authOptions.tokenDurationInSeconds)
|
||||
: undefined;
|
||||
|
||||
const generateOptions: GenerateOptions = {
|
||||
const generateOptions: GenerateOptionsWithOptionalDomain = {
|
||||
verifyOptions: {
|
||||
statement: ctx.authOptions?.statement,
|
||||
uri: ctx.authOptions?.uri,
|
||||
@@ -68,6 +68,10 @@ export default async function handler(
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.callbacks?.onToken) {
|
||||
await ctx.callbacks.onToken(token, req);
|
||||
}
|
||||
|
||||
const {
|
||||
payload: { exp },
|
||||
} = ctx.auth.parseToken(token);
|
||||
@@ -84,7 +88,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
},
|
||||
),
|
||||
serialize(THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE, payload.payload.address, {
|
||||
@@ -93,7 +97,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(Date.now() + 5 * 1000),
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: cookieExpiration,
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(refreshedPayload.payload.exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
},
|
||||
),
|
||||
serialize(THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE, user.address, {
|
||||
@@ -62,7 +62,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(refreshedPayload.payload.exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -52,17 +52,21 @@ export type ThirdwebAuthConfig<
|
||||
domain?: string;
|
||||
path?: string;
|
||||
sameSite?: "lax" | "strict" | "none";
|
||||
secure?: boolean;
|
||||
};
|
||||
callbacks?: {
|
||||
onLogin?:
|
||||
| ((address: string, req?: Request) => void | TSession)
|
||||
| ((address: string, req?: Request) => Promise<void | TSession>);
|
||||
| ((address: string, req: Request) => void | TSession)
|
||||
| ((address: string, req: Request) => Promise<void | TSession>);
|
||||
onToken?:
|
||||
| ((token: string, req: Request) => void)
|
||||
| ((token: string, req: Request) => Promise<void>);
|
||||
onUser?:
|
||||
| ((user: User<TSession>, req?: Request) => void | TData)
|
||||
| ((user: User<TSession>, req?: Request) => Promise<void | TData>);
|
||||
| ((user: User<TSession>, req: Request) => void | TData)
|
||||
| ((user: User<TSession>, req: Request) => Promise<void | TData>);
|
||||
onLogout?:
|
||||
| ((user: User, req?: Request) => void)
|
||||
| ((user: User, req?: Request) => Promise<void>);
|
||||
| ((user: User, req: Request) => void)
|
||||
| ((user: User, req: Request) => Promise<void>);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
import {
|
||||
THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE,
|
||||
THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX,
|
||||
} from "../../constants";
|
||||
import { Json } from "../../core";
|
||||
import { ThirdwebAuthContext, ThirdwebAuthUser } from "../types";
|
||||
import { FastifyRequest } from "fastify";
|
||||
|
||||
export function getCookie(
|
||||
req: FastifyRequest,
|
||||
cookie: string,
|
||||
): string | undefined {
|
||||
return req.cookies[cookie];
|
||||
}
|
||||
|
||||
export function getActiveCookie(req: FastifyRequest): string | undefined {
|
||||
if (!req.cookies) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const activeAccount = getCookie(req, THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE);
|
||||
if (activeAccount) {
|
||||
return `${THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX}_${activeAccount}`;
|
||||
}
|
||||
|
||||
// If active account is not present, then use the old default
|
||||
return THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param req
|
||||
* @returns
|
||||
*/
|
||||
export function getToken(req: FastifyRequest): string | undefined {
|
||||
if (req.headers.authorization) {
|
||||
const authorizationHeader = req.headers.authorization.split(" ");
|
||||
if (authorizationHeader?.length === 2) {
|
||||
return authorizationHeader[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (!req.cookies) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const activeCookie = getActiveCookie(req);
|
||||
if (!activeCookie) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return getCookie(req, activeCookie);
|
||||
}
|
||||
|
||||
export async function getUser<
|
||||
TData extends Json = Json,
|
||||
TSession extends Json = Json,
|
||||
>(
|
||||
req: FastifyRequest,
|
||||
ctx: ThirdwebAuthContext<TData, TSession>,
|
||||
): Promise<ThirdwebAuthUser<TData, TSession> | null> {
|
||||
const token = getToken(req);
|
||||
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let authenticatedUser: ThirdwebAuthUser<TData, TSession>;
|
||||
try {
|
||||
authenticatedUser = await ctx.auth.authenticate<TSession>(token, {
|
||||
validateTokenId: async (tokenId: string) => {
|
||||
if (ctx.authOptions?.validateTokenId) {
|
||||
await ctx.authOptions?.validateTokenId(tokenId);
|
||||
}
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!ctx.callbacks?.onUser) {
|
||||
return authenticatedUser;
|
||||
}
|
||||
|
||||
const data = await ctx.callbacks.onUser(authenticatedUser, req);
|
||||
if (!data) {
|
||||
return authenticatedUser;
|
||||
}
|
||||
|
||||
return { ...authenticatedUser, data: data };
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { FastifyInstance, FastifyPluginOptions, FastifyRequest } from "fastify";
|
||||
import { Json, ThirdwebAuth as ThirdwebAuthSDK } from "../core";
|
||||
import fastifyCookie, { FastifyCookie } from "@fastify/cookie";
|
||||
import { payloadHandler } from "./routes/payload";
|
||||
import { loginHandler } from "./routes/login";
|
||||
import { userHandler } from "./routes/user";
|
||||
import { logoutHandler } from "./routes/logout";
|
||||
import { switchAccountHandler } from "./routes/switch-account";
|
||||
import {
|
||||
ZodTypeProvider,
|
||||
serializerCompiler,
|
||||
validatorCompiler,
|
||||
} from "fastify-type-provider-zod";
|
||||
import { getUser } from "./helpers/user";
|
||||
import {
|
||||
ThirdwebAuthConfig,
|
||||
ThirdwebAuthContext,
|
||||
ThirdwebAuthUser,
|
||||
} from "./types";
|
||||
|
||||
export * from "./types";
|
||||
export { getToken } from "./helpers/user";
|
||||
|
||||
type ThirdwebAuthReturnType<
|
||||
TData extends Json = Json,
|
||||
TSession extends Json = Json,
|
||||
> = {
|
||||
authRouter: (
|
||||
fastify: FastifyInstance,
|
||||
opts: FastifyPluginOptions,
|
||||
done: (err?: Error | undefined) => void,
|
||||
) => void;
|
||||
authMiddleware: FastifyCookie;
|
||||
getUser: (
|
||||
req: FastifyRequest,
|
||||
) => Promise<ThirdwebAuthUser<TData, TSession> | null>;
|
||||
};
|
||||
|
||||
export function ThirdwebAuth<
|
||||
TData extends Json = Json,
|
||||
TSession extends Json = Json,
|
||||
>(
|
||||
cfg: ThirdwebAuthConfig<TData, TSession>,
|
||||
): ThirdwebAuthReturnType<TData, TSession> {
|
||||
const ctx = {
|
||||
...cfg,
|
||||
auth: new ThirdwebAuthSDK(cfg.wallet, cfg.domain),
|
||||
};
|
||||
|
||||
const authRouter = async (
|
||||
fastify: FastifyInstance,
|
||||
_opts: FastifyPluginOptions,
|
||||
done: (err?: Error | undefined) => void,
|
||||
) => {
|
||||
// Setup plugin to use zod as a type provider
|
||||
fastify.setValidatorCompiler(validatorCompiler);
|
||||
fastify.setSerializerCompiler(serializerCompiler);
|
||||
const plugin = fastify.withTypeProvider<ZodTypeProvider>();
|
||||
|
||||
// Register the fastify cookie middleware with this plugin
|
||||
await plugin.register(fastifyCookie);
|
||||
|
||||
// Register individual auth endpoints
|
||||
payloadHandler(plugin, ctx as ThirdwebAuthContext);
|
||||
loginHandler(plugin, ctx as ThirdwebAuthContext);
|
||||
logoutHandler(plugin, ctx as ThirdwebAuthContext);
|
||||
userHandler(plugin, ctx as ThirdwebAuthContext);
|
||||
switchAccountHandler(plugin, ctx as ThirdwebAuthContext);
|
||||
|
||||
// Mark plugin creation as complete
|
||||
done();
|
||||
};
|
||||
|
||||
return {
|
||||
authRouter,
|
||||
authMiddleware: fastifyCookie,
|
||||
getUser: (req: FastifyRequest) => {
|
||||
return getUser<TData, TSession>(req, ctx);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
import {
|
||||
FastifyInstanceWithZod,
|
||||
LoginPayloadBodySchema,
|
||||
ThirdwebAuthContext,
|
||||
} from "../types";
|
||||
import { GenerateOptionsWithOptionalDomain } from "../../core";
|
||||
import {
|
||||
THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE,
|
||||
THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX,
|
||||
} from "../../constants";
|
||||
import { z } from "zod";
|
||||
|
||||
export const loginHandler = (
|
||||
fastify: FastifyInstanceWithZod,
|
||||
ctx: ThirdwebAuthContext,
|
||||
) => {
|
||||
fastify.route<{
|
||||
Body: z.infer<typeof LoginPayloadBodySchema>;
|
||||
}>({
|
||||
method: "POST",
|
||||
url: "/login",
|
||||
schema: {
|
||||
body: LoginPayloadBodySchema,
|
||||
response: {
|
||||
200: z.any(),
|
||||
},
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
const validateNonce = async (nonce: string) => {
|
||||
if (ctx.authOptions?.validateNonce) {
|
||||
await ctx.authOptions?.validateNonce(nonce);
|
||||
}
|
||||
};
|
||||
|
||||
const getSession = async (address: string) => {
|
||||
if (ctx.callbacks?.onLogin) {
|
||||
return ctx.callbacks.onLogin(address, req);
|
||||
}
|
||||
};
|
||||
|
||||
const expirationTime = ctx.authOptions?.tokenDurationInSeconds
|
||||
? new Date(Date.now() + 1000 * ctx.authOptions.tokenDurationInSeconds)
|
||||
: undefined;
|
||||
|
||||
const generateOptions: GenerateOptionsWithOptionalDomain = {
|
||||
verifyOptions: {
|
||||
statement: ctx.authOptions?.statement,
|
||||
uri: ctx.authOptions?.uri,
|
||||
version: ctx.authOptions?.version,
|
||||
chainId: ctx.authOptions?.chainId,
|
||||
validateNonce,
|
||||
resources: ctx.authOptions?.resources,
|
||||
},
|
||||
expirationTime,
|
||||
session: getSession,
|
||||
};
|
||||
|
||||
let token: string;
|
||||
try {
|
||||
// Generate an access token with the SDK using the signed payload
|
||||
token = await ctx.auth.generate(req.body.payload, generateOptions);
|
||||
} catch (err: any) {
|
||||
if (err.message) {
|
||||
return res.status(400).send({ error: err.message });
|
||||
} else if (typeof err === "string") {
|
||||
return res.status(400).send({ error: err });
|
||||
} else {
|
||||
return res.status(400).send({ error: "Invalid login payload" });
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.callbacks?.onToken) {
|
||||
await ctx.callbacks.onToken(token, req);
|
||||
}
|
||||
|
||||
const {
|
||||
payload: { exp },
|
||||
} = ctx.auth.parseToken(token);
|
||||
|
||||
// Securely set httpOnly cookie on request to prevent XSS on frontend
|
||||
// And set path to / to enable thirdweb_auth_token usage on all endpoints
|
||||
res.setCookie(
|
||||
`${THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX}_${req.body.payload.payload.address}`,
|
||||
token,
|
||||
{
|
||||
domain: ctx.cookieOptions?.domain,
|
||||
path: ctx.cookieOptions?.path || "/",
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
},
|
||||
);
|
||||
res.setCookie(
|
||||
THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE,
|
||||
req.body.payload.payload.address,
|
||||
{
|
||||
domain: ctx.cookieOptions?.domain,
|
||||
path: ctx.cookieOptions?.path || "/",
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
},
|
||||
);
|
||||
|
||||
return res.status(200).send({ success: true });
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
import { z } from "zod";
|
||||
import { getActiveCookie, getUser } from "../helpers/user";
|
||||
import {
|
||||
ErrorResponseSchema,
|
||||
FastifyInstanceWithZod,
|
||||
ThirdwebAuthContext,
|
||||
} from "../types";
|
||||
|
||||
export const logoutHandler = (
|
||||
fastify: FastifyInstanceWithZod,
|
||||
ctx: ThirdwebAuthContext,
|
||||
) => {
|
||||
fastify.route({
|
||||
method: "POST",
|
||||
url: "/logout",
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
message: z.string(),
|
||||
}),
|
||||
400: ErrorResponseSchema,
|
||||
},
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
const activeCookie = getActiveCookie(req);
|
||||
if (!activeCookie) {
|
||||
return res.status(400).send({
|
||||
error: "No logged in user to logout.",
|
||||
});
|
||||
}
|
||||
|
||||
if (ctx.callbacks?.onLogout) {
|
||||
const user = await getUser(req, ctx);
|
||||
if (user) {
|
||||
await ctx.callbacks.onLogout(user, req);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the access token to 'none' and expire in 5 seconds
|
||||
res.setCookie(activeCookie, "", {
|
||||
domain: ctx.cookieOptions?.domain,
|
||||
path: ctx.cookieOptions?.path || "/",
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(Date.now() + 5 * 1000),
|
||||
httpOnly: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
});
|
||||
|
||||
return res.status(200).send({ message: "Successfully logged out" });
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
FastifyInstanceWithZod,
|
||||
PayloadBodySchema,
|
||||
ThirdwebAuthContext,
|
||||
} from "../types";
|
||||
import { z } from "zod";
|
||||
|
||||
export const payloadHandler = (
|
||||
fastify: FastifyInstanceWithZod,
|
||||
ctx: ThirdwebAuthContext,
|
||||
) => {
|
||||
fastify.route<{
|
||||
Body: z.infer<typeof PayloadBodySchema>;
|
||||
}>({
|
||||
method: "POST",
|
||||
url: "/payload",
|
||||
schema: {
|
||||
body: PayloadBodySchema,
|
||||
response: {
|
||||
200: z.any(),
|
||||
},
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
const payload = await ctx.auth.payload({
|
||||
address: req.body.address,
|
||||
statement: ctx.authOptions?.statement,
|
||||
uri: ctx.authOptions?.uri,
|
||||
version: ctx.authOptions?.version,
|
||||
chainId: req.body.chainId || ctx.authOptions?.chainId,
|
||||
resources: ctx.authOptions?.resources,
|
||||
expirationTime: ctx.authOptions?.loginPayloadDurationInSeconds
|
||||
? new Date(
|
||||
Date.now() + 1000 * ctx.authOptions.loginPayloadDurationInSeconds,
|
||||
)
|
||||
: undefined,
|
||||
});
|
||||
|
||||
return res.status(200).send({ payload });
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
import {
|
||||
ActiveBodySchema,
|
||||
ErrorResponseSchema,
|
||||
FastifyInstanceWithZod,
|
||||
ThirdwebAuthContext,
|
||||
} from "../types";
|
||||
import {
|
||||
THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE,
|
||||
THIRDWEB_AUTH_DEFAULT_TOKEN_DURATION_IN_SECONDS,
|
||||
THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX,
|
||||
} from "../../constants";
|
||||
import { getCookie } from "../helpers/user";
|
||||
import { z } from "zod";
|
||||
|
||||
export const switchAccountHandler = (
|
||||
fastify: FastifyInstanceWithZod,
|
||||
ctx: ThirdwebAuthContext,
|
||||
) => {
|
||||
fastify.route<{
|
||||
Body: z.infer<typeof ActiveBodySchema>;
|
||||
}>({
|
||||
method: "POST",
|
||||
url: "/switch-account",
|
||||
schema: {
|
||||
body: ActiveBodySchema,
|
||||
response: {
|
||||
200: z.any(),
|
||||
400: ErrorResponseSchema,
|
||||
},
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
let cookieExpiration: Date;
|
||||
const cookie = getCookie(
|
||||
req,
|
||||
`${THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX}_${req.body.address}`,
|
||||
);
|
||||
|
||||
if (cookie) {
|
||||
// If the new account is already logged in, get the expiration time from the cookie
|
||||
const {
|
||||
payload: { exp },
|
||||
} = ctx.auth.parseToken(cookie);
|
||||
cookieExpiration = new Date(exp * 1000);
|
||||
} else if (ctx.authOptions?.tokenDurationInSeconds) {
|
||||
// Otherwise, if we have a token duration in seconds, set it to that
|
||||
cookieExpiration = new Date(
|
||||
Date.now() + 1000 * ctx.authOptions.tokenDurationInSeconds,
|
||||
);
|
||||
} else {
|
||||
// Otherwise, just default to 24 hours
|
||||
cookieExpiration = new Date(
|
||||
Date.now() + 1000 * THIRDWEB_AUTH_DEFAULT_TOKEN_DURATION_IN_SECONDS,
|
||||
);
|
||||
}
|
||||
|
||||
res.setCookie(THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE, req.body.address, {
|
||||
domain: ctx.cookieOptions?.domain,
|
||||
path: ctx.cookieOptions?.path || "/",
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: cookieExpiration,
|
||||
httpOnly: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
});
|
||||
|
||||
return res.status(200).send();
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
import { getToken, getUser } from "../helpers/user";
|
||||
import { FastifyInstanceWithZod, ThirdwebAuthContext } from "../types";
|
||||
import {
|
||||
THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE,
|
||||
THIRDWEB_AUTH_DEFAULT_REFRESH_INTERVAL_IN_SECONDS,
|
||||
THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX,
|
||||
} from "../../constants";
|
||||
import { z } from "zod";
|
||||
|
||||
export const userHandler = (
|
||||
fastify: FastifyInstanceWithZod,
|
||||
ctx: ThirdwebAuthContext,
|
||||
) => {
|
||||
fastify.route({
|
||||
method: "GET",
|
||||
url: "/user",
|
||||
schema: {
|
||||
response: {
|
||||
200: z.any(),
|
||||
},
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
const user = await getUser(req, ctx);
|
||||
|
||||
// Importantly, make sure the user was actually logged in before refreshing
|
||||
if (user) {
|
||||
const token = getToken(req);
|
||||
if (token) {
|
||||
const payload = ctx.auth.parseToken(token);
|
||||
|
||||
const refreshDate = ctx.authOptions?.refreshIntervalInSeconds
|
||||
? new Date(
|
||||
payload.payload.iat * 1000 +
|
||||
ctx.authOptions.refreshIntervalInSeconds * 1000,
|
||||
)
|
||||
: new Date(
|
||||
payload.payload.iat * 1000 +
|
||||
THIRDWEB_AUTH_DEFAULT_REFRESH_INTERVAL_IN_SECONDS * 1000,
|
||||
);
|
||||
|
||||
if (new Date() > refreshDate) {
|
||||
const expirationTime = ctx.authOptions?.tokenDurationInSeconds
|
||||
? new Date(
|
||||
Date.now() + 1000 * ctx.authOptions.tokenDurationInSeconds,
|
||||
)
|
||||
: undefined;
|
||||
const refreshedToken = await ctx.auth.refresh(
|
||||
token,
|
||||
expirationTime,
|
||||
);
|
||||
const refreshedPayload = ctx.auth.parseToken(refreshedToken);
|
||||
|
||||
res.setCookie(
|
||||
`${THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX}_${user.address}`,
|
||||
refreshedToken,
|
||||
{
|
||||
domain: ctx.cookieOptions?.domain,
|
||||
path: ctx.cookieOptions?.path || "/",
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(refreshedPayload.payload.exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
},
|
||||
);
|
||||
res.setCookie(THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE, user.address, {
|
||||
domain: ctx.cookieOptions?.domain,
|
||||
path: ctx.cookieOptions?.path || "/",
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(refreshedPayload.payload.exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res.status(200).send(user);
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
import { GenericAuthWallet } from "@thirdweb-dev/wallets";
|
||||
import { Json, LoginPayloadOutputSchema, ThirdwebAuth, User } from "../../core";
|
||||
import {
|
||||
FastifyBaseLogger,
|
||||
FastifyInstance,
|
||||
FastifyRequest,
|
||||
RawServerDefault,
|
||||
} from "fastify";
|
||||
import { z } from "zod";
|
||||
import { IncomingMessage, ServerResponse } from "http";
|
||||
import { ZodTypeProvider } from "fastify-type-provider-zod";
|
||||
|
||||
export const PayloadBodySchema = z.object({
|
||||
address: z.string(),
|
||||
chainId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const ActiveBodySchema = z.object({
|
||||
address: z.string(),
|
||||
});
|
||||
|
||||
export const LoginPayloadBodySchema = z.object({
|
||||
payload: LoginPayloadOutputSchema,
|
||||
});
|
||||
|
||||
export const ErrorResponseSchema = z.object({
|
||||
error: z.string(),
|
||||
});
|
||||
|
||||
export type ThirdwebAuthUser<
|
||||
TData extends Json = Json,
|
||||
TSession extends Json = Json,
|
||||
> = User<TSession> & {
|
||||
data?: TData;
|
||||
};
|
||||
|
||||
export type ThirdwebAuthConfig<
|
||||
TData extends Json = Json,
|
||||
TSession extends Json = Json,
|
||||
> = {
|
||||
domain: string;
|
||||
wallet: GenericAuthWallet;
|
||||
authOptions?: {
|
||||
statement?: string;
|
||||
uri?: string;
|
||||
version?: string;
|
||||
chainId?: string;
|
||||
resources?: string[];
|
||||
validateNonce?:
|
||||
| ((nonce: string) => void)
|
||||
| ((nonce: string) => Promise<void>);
|
||||
validateTokenId?:
|
||||
| ((tokenId: string) => void)
|
||||
| ((tokenId: string) => Promise<void>);
|
||||
loginPayloadDurationInSeconds?: number;
|
||||
tokenDurationInSeconds?: number;
|
||||
refreshIntervalInSeconds?: number;
|
||||
};
|
||||
cookieOptions?: {
|
||||
domain?: string;
|
||||
path?: string;
|
||||
sameSite?: "lax" | "strict" | "none";
|
||||
secure?: boolean;
|
||||
};
|
||||
callbacks?: {
|
||||
onLogin?:
|
||||
| ((address: string, req: FastifyRequest) => void | TSession)
|
||||
| ((address: string, req: FastifyRequest) => Promise<void | TSession>);
|
||||
onToken?:
|
||||
| ((token: string, req: FastifyRequest) => void)
|
||||
| ((token: string, req: FastifyRequest) => Promise<void>);
|
||||
onUser?:
|
||||
| ((user: User<TSession>, req: FastifyRequest) => void | TData)
|
||||
| ((user: User<TSession>, req: FastifyRequest) => Promise<void | TData>);
|
||||
onLogout?:
|
||||
| ((user: User, req: FastifyRequest) => void)
|
||||
| ((user: User, req: FastifyRequest) => Promise<void>);
|
||||
};
|
||||
};
|
||||
|
||||
export type ThirdwebAuthContext<
|
||||
TData extends Json = Json,
|
||||
TSession extends Json = Json,
|
||||
> = Omit<Omit<ThirdwebAuthConfig<TData, TSession>, "wallet">, "domain"> & {
|
||||
auth: ThirdwebAuth;
|
||||
};
|
||||
|
||||
export type FastifyInstanceWithZod = FastifyInstance<
|
||||
RawServerDefault,
|
||||
IncomingMessage,
|
||||
ServerResponse<IncomingMessage>,
|
||||
FastifyBaseLogger,
|
||||
ZodTypeProvider
|
||||
>;
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE,
|
||||
THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX,
|
||||
} from "../../constants";
|
||||
import { Json } from "../../core/schema";
|
||||
import { Json } from "../../core";
|
||||
import { ThirdwebAuthContext, ThirdwebAuthUser } from "../types";
|
||||
import { GetServerSidePropsContext, NextApiRequest } from "next";
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE,
|
||||
THIRDWEB_AUTH_TOKEN_COOKIE_PREFIX,
|
||||
} from "../../constants";
|
||||
import { GenerateOptions } from "../../core";
|
||||
import { GenerateOptionsWithOptionalDomain } from "../../core";
|
||||
import { LoginPayloadBodySchema, ThirdwebAuthContext } from "../types";
|
||||
import { serialize } from "cookie";
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
@@ -41,7 +41,7 @@ export default async function handler(
|
||||
? new Date(Date.now() + 1000 * ctx.authOptions.tokenDurationInSeconds)
|
||||
: undefined;
|
||||
|
||||
const generateOptions: GenerateOptions = {
|
||||
const generateOptions: GenerateOptionsWithOptionalDomain = {
|
||||
verifyOptions: {
|
||||
statement: ctx.authOptions?.statement,
|
||||
uri: ctx.authOptions?.uri,
|
||||
@@ -68,6 +68,10 @@ export default async function handler(
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.callbacks?.onToken) {
|
||||
await ctx.callbacks.onToken(token, req);
|
||||
}
|
||||
|
||||
const {
|
||||
payload: { exp },
|
||||
} = ctx.auth.parseToken(token);
|
||||
@@ -84,7 +88,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
},
|
||||
),
|
||||
serialize(THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE, payload.payload.address, {
|
||||
@@ -93,7 +97,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(Date.now() + 5 * 1000),
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: cookieExpiration,
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(refreshedPayload.payload.exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
},
|
||||
),
|
||||
serialize(THIRDWEB_AUTH_ACTIVE_ACCOUNT_COOKIE, user.address, {
|
||||
@@ -62,7 +62,7 @@ export default async function handler(
|
||||
sameSite: ctx.cookieOptions?.sameSite || "none",
|
||||
expires: new Date(refreshedPayload.payload.exp * 1000),
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
secure: ctx.cookieOptions?.secure || true,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -62,23 +62,27 @@ export type ThirdwebAuthConfig<
|
||||
domain?: string;
|
||||
path?: string;
|
||||
sameSite?: "lax" | "strict" | "none";
|
||||
secure?: boolean;
|
||||
};
|
||||
callbacks?: {
|
||||
onLogin?:
|
||||
| ((address: string, req?: NextApiRequest) => void | TSession)
|
||||
| ((address: string, req?: NextApiRequest) => Promise<void | TSession>);
|
||||
| ((address: string, req: NextApiRequest) => void | TSession)
|
||||
| ((address: string, req: NextApiRequest) => Promise<void | TSession>);
|
||||
onToken?:
|
||||
| ((token: string, req: NextApiRequest) => void)
|
||||
| ((token: string, req: NextApiRequest) => Promise<void>);
|
||||
onUser?:
|
||||
| (<TRequestType extends RequestType = RequestType>(
|
||||
user: User<TSession>,
|
||||
req?: TRequestType,
|
||||
req: TRequestType,
|
||||
) => void | TData)
|
||||
| (<TRequestType extends RequestType = RequestType>(
|
||||
user: User<TSession>,
|
||||
req?: TRequestType,
|
||||
req: TRequestType,
|
||||
) => Promise<void | TData>);
|
||||
onLogout?:
|
||||
| ((user: User, req?: NextApiRequest) => void)
|
||||
| ((user: User, req?: NextApiRequest) => Promise<void>);
|
||||
| ((user: User, req: NextApiRequest) => void)
|
||||
| ((user: User, req: NextApiRequest) => Promise<void>);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @thirdweb-dev/chains
|
||||
|
||||
## 0.1.55
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1783](https://github.com/thirdweb-dev/js/pull/1783) [`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64) Thanks [@jnsdls](https://github.com/jnsdls)! - sync chains
|
||||
|
||||
## 0.1.54
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -4,13 +4,13 @@ export default {
|
||||
"chainId": 100,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "gnosisscan",
|
||||
"url": "https://gnosisscan.io",
|
||||
"name": "blockscout",
|
||||
"url": "https://gnosis.blockscout.com",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://gnosis.blockscout.com",
|
||||
"name": "gnosisscan",
|
||||
"url": "https://gnosisscan.io",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,13 +4,13 @@ export default {
|
||||
"chainId": 11110,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Astra PingPub Explorer",
|
||||
"url": "https://ping.astranaut.io/astra",
|
||||
"name": "Astra EVM Explorer (Blockscout)",
|
||||
"url": "https://explorer.astranaut.io",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "Astra EVM Explorer (Blockscout)",
|
||||
"url": "https://explorer.astranaut.io",
|
||||
"name": "Astra PingPub Explorer",
|
||||
"url": "https://ping.astranaut.io/astra",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -3,15 +3,15 @@ export default {
|
||||
"chain": "Astra",
|
||||
"chainId": 11115,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Astra PingPub Explorer",
|
||||
"url": "https://ping.astranaut.dev/astra",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "Astra EVM Explorer",
|
||||
"url": "https://explorer.astranaut.dev",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "Astra PingPub Explorer",
|
||||
"url": "https://ping.astranaut.dev/astra",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"faucets": [
|
||||
|
||||
@@ -19,7 +19,6 @@ export default {
|
||||
},
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://localhost.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"http://localhost:8545"
|
||||
],
|
||||
"shortName": "local",
|
||||
|
||||
@@ -4,13 +4,13 @@ export default {
|
||||
"chainId": 2023,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Taycan Cosmos Explorer",
|
||||
"url": "https://cosmoscan-test.hupayx.io",
|
||||
"name": "Taycan Explorer(Blockscout)",
|
||||
"url": "https://evmscan-test.hupayx.io",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "Taycan Explorer(Blockscout)",
|
||||
"url": "https://evmscan-test.hupayx.io",
|
||||
"name": "Taycan Cosmos Explorer",
|
||||
"url": "https://cosmoscan-test.hupayx.io",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -30,7 +30,6 @@ export default {
|
||||
"rpc": [
|
||||
"https://kava-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://evm.testnet.kava.io",
|
||||
"https://kava-evm-testnet.rpc.thirdweb.com",
|
||||
"wss://wevm.testnet.kava.io"
|
||||
],
|
||||
"shortName": "tkava",
|
||||
|
||||
@@ -30,7 +30,6 @@ export default {
|
||||
"https://evm.kava.io",
|
||||
"https://evm2.kava.io",
|
||||
"https://kava-rpc.gateway.pokt.network",
|
||||
"https://kava-evm.rpc.thirdweb.com",
|
||||
"wss://wevm.kava.io",
|
||||
"wss://wevm2.kava.io",
|
||||
"https://kava-evm.publicnode.com",
|
||||
|
||||
@@ -4,13 +4,13 @@ export default {
|
||||
"chainId": 30,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Rootstock Explorer",
|
||||
"url": "https://explorer.rsk.co",
|
||||
"name": "blockscout",
|
||||
"url": "https://rootstock.blockscout.com",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://rootstock.blockscout.com",
|
||||
"name": "Rootstock Explorer",
|
||||
"url": "https://explorer.rsk.co",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -3,15 +3,15 @@ export default {
|
||||
"chain": "SDN",
|
||||
"chainId": 336,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "subscan",
|
||||
"url": "https://shiden.subscan.io",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://blockscout.com/shiden",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "subscan",
|
||||
"url": "https://shiden.subscan.io",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
|
||||
@@ -4,13 +4,13 @@ export default {
|
||||
"chainId": 369,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "otterscan",
|
||||
"url": "https://otter.pulsechain.com",
|
||||
"name": "blockscout",
|
||||
"url": "https://scan.pulsechain.com",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://scan.pulsechain.com",
|
||||
"name": "otterscan",
|
||||
"url": "https://otter.pulsechain.com",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -18,7 +18,7 @@ export default {
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "http://doschain.io/",
|
||||
"name": "DOS Tesnet",
|
||||
"name": "DOS Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "DOS",
|
||||
"symbol": "DOS",
|
||||
@@ -26,10 +26,10 @@ export default {
|
||||
},
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://dos-tesnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://dos-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://test.doschain.com"
|
||||
],
|
||||
"shortName": "dost",
|
||||
"slug": "dos-tesnet",
|
||||
"slug": "dos-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -27,8 +27,7 @@ export default {
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://wireshape-floripa-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc-floripa.wireshape.org",
|
||||
"https://wireshape-floripa-testnet.rpc.thirdweb.com"
|
||||
"https://rpc-floripa.wireshape.org"
|
||||
],
|
||||
"shortName": "floripa",
|
||||
"slug": "wireshape-floripa-testnet",
|
||||
|
||||
@@ -4,13 +4,13 @@ export default {
|
||||
"chainId": 50,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blocksscan",
|
||||
"url": "https://xdc.blocksscan.io",
|
||||
"name": "xdcscan",
|
||||
"url": "https://xdcscan.io",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "xdcscan",
|
||||
"url": "https://xdcscan.io",
|
||||
"name": "blocksscan",
|
||||
"url": "https://xdc.blocksscan.io",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,13 +4,13 @@ export default {
|
||||
"chainId": 51,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blocksscan",
|
||||
"url": "https://apothem.blocksscan.io",
|
||||
"name": "xdcscan",
|
||||
"url": "https://apothem.xinfinscan.com",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "xdcscan",
|
||||
"url": "https://apothem.xinfinscan.com",
|
||||
"name": "blocksscan",
|
||||
"url": "https://apothem.blocksscan.io",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -3,15 +3,15 @@ export default {
|
||||
"chain": "Imversed",
|
||||
"chainId": 5555555,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Imversed Cosmos Explorer (Big Dipper)",
|
||||
"url": "https://tex-c.imversed.com",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "Imversed EVM explorer (Blockscout)",
|
||||
"url": "https://txe.imversed.network",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "Imversed Cosmos Explorer (Big Dipper)",
|
||||
"url": "https://tex-c.imversed.com",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
|
||||
@@ -3,15 +3,15 @@ export default {
|
||||
"chain": "Imversed",
|
||||
"chainId": 5555558,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Imversed Cosmos Explorer (Big Dipper)",
|
||||
"url": "https://tex-t.imversed.com",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "Imversed EVM Explorer (Blockscout)",
|
||||
"url": "https://txe-test.imversed.network",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "Imversed Cosmos Explorer (Big Dipper)",
|
||||
"url": "https://tex-t.imversed.com",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
|
||||
@@ -4,13 +4,13 @@ export default {
|
||||
"chainId": 59140,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Blockscout",
|
||||
"url": "https://explorer.goerli.linea.build",
|
||||
"name": "Etherscan",
|
||||
"url": "https://goerli.lineascan.build",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "Etherscan",
|
||||
"url": "https://goerli.lineascan.build",
|
||||
"name": "Blockscout",
|
||||
"url": "https://explorer.goerli.linea.build",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -7,11 +7,6 @@ export default {
|
||||
"name": "lineascan",
|
||||
"url": "https://lineascan.build",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "Linea Scan",
|
||||
"url": "https://lineascan.build",
|
||||
"standard": ""
|
||||
}
|
||||
],
|
||||
"faucets": [
|
||||
|
||||
@@ -3,15 +3,15 @@ export default {
|
||||
"chain": "ASTR",
|
||||
"chainId": 592,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "subscan",
|
||||
"url": "https://astar.subscan.io",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://blockscout.com/astar",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "subscan",
|
||||
"url": "https://astar.subscan.io",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
|
||||
@@ -4,13 +4,13 @@ export default {
|
||||
"chainId": 8000,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Teleport Cosmos Explorer (Big Dipper)",
|
||||
"url": "https://explorer.teleport.network",
|
||||
"name": "Teleport EVM Explorer (Blockscout)",
|
||||
"url": "https://evm-explorer.teleport.network",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "Teleport EVM Explorer (Blockscout)",
|
||||
"url": "https://evm-explorer.teleport.network",
|
||||
"name": "Teleport Cosmos Explorer (Big Dipper)",
|
||||
"url": "https://explorer.teleport.network",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,13 +4,13 @@ export default {
|
||||
"chainId": 8001,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Teleport Cosmos Explorer (Big Dipper)",
|
||||
"url": "https://explorer.testnet.teleport.network",
|
||||
"name": "Teleport EVM Explorer (Blockscout)",
|
||||
"url": "https://evm-explorer.testnet.teleport.network",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "Teleport EVM Explorer (Blockscout)",
|
||||
"url": "https://evm-explorer.testnet.teleport.network",
|
||||
"name": "Teleport Cosmos Explorer (Big Dipper)",
|
||||
"url": "https://explorer.testnet.teleport.network",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -3,15 +3,15 @@ export default {
|
||||
"chain": "ETH",
|
||||
"chainId": 8453,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "basescan",
|
||||
"url": "https://basescan.org",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "basescout",
|
||||
"url": "https://base.blockscout.com",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "basescan",
|
||||
"url": "https://basescan.org",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
|
||||
@@ -3,15 +3,15 @@ export default {
|
||||
"chain": "ETH",
|
||||
"chainId": 84531,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "basescan",
|
||||
"url": "https://goerli.basescan.org",
|
||||
"standard": "none"
|
||||
},
|
||||
{
|
||||
"name": "basescout",
|
||||
"url": "https://base-goerli.blockscout.com",
|
||||
"standard": "EIP3091"
|
||||
},
|
||||
{
|
||||
"name": "basescan",
|
||||
"url": "https://goerli.basescan.org",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"faucets": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/chains",
|
||||
"version": "0.1.54",
|
||||
"version": "0.1.55",
|
||||
"main": "dist/thirdweb-dev-chains.cjs.js",
|
||||
"module": "dist/thirdweb-dev-chains.esm.js",
|
||||
"browser": {
|
||||
|
||||
@@ -6,7 +6,7 @@ const BASE_URI = (process.env.BASE_URI as string) || "https://api.thirdweb.com";
|
||||
|
||||
async function getAllPaginatedChains(
|
||||
chains: any[] = [],
|
||||
pathname = "/v1/chains",
|
||||
pathname = "/v1/chains?limit=100",
|
||||
) {
|
||||
const url = new URL(BASE_URI);
|
||||
url.pathname = pathname;
|
||||
@@ -33,31 +33,37 @@ async function sync() {
|
||||
|
||||
const results = await Promise.all(
|
||||
allChainsInDB.map(async (chain) => {
|
||||
let chainId = chain.chainId;
|
||||
// try to convert to number for legacy reasons
|
||||
try {
|
||||
chainId = Number(chainId);
|
||||
} catch {
|
||||
// if we fail here then we cannot use this chain in the chains package for now, so we skip it
|
||||
return null;
|
||||
}
|
||||
|
||||
const pkgChain: Chain = {
|
||||
...chain,
|
||||
chainId: Number(chain.chainId),
|
||||
// assing back the chainId
|
||||
chainId,
|
||||
// map the features to the legacy format
|
||||
features: chain.features?.map((feature) => ({ name: feature })),
|
||||
};
|
||||
// remove all null values
|
||||
Object.keys(pkgChain).forEach((key) => {
|
||||
// @ts-ignore
|
||||
if (pkgChain[key] === null || pkgChain[key] === undefined) {
|
||||
// @ts-ignore
|
||||
delete pkgChain[key];
|
||||
}
|
||||
});
|
||||
|
||||
// sort top level keys alphabetically
|
||||
// @ts-ignore
|
||||
const sortedChain: Chain = {};
|
||||
const sortedChain = {} as Chain;
|
||||
Object.keys(pkgChain)
|
||||
.sort()
|
||||
.forEach((key) => {
|
||||
// @ts-ignore
|
||||
sortedChain[key] = pkgChain[key];
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
await fs.writeFile(
|
||||
`${chainsDir}/${sortedChain.chainId}.ts`,
|
||||
`import type { Chain } from "../src/types";
|
||||
@@ -78,17 +84,8 @@ export default ${JSON.stringify(
|
||||
exportName = `_${exportName}`;
|
||||
}
|
||||
|
||||
// imports.push(`import c${chain.chainId} from "../chains/${chain.chainId}";`);
|
||||
|
||||
// exports.push(
|
||||
// `export { default as ${exportName} } from "../chains/${chain.chainId}"`,
|
||||
// );
|
||||
|
||||
const key = `c${sortedChain.chainId}`;
|
||||
|
||||
// exportNames.push(key);
|
||||
// exportNameToChain[key] = chain;
|
||||
|
||||
return {
|
||||
imp: `import c${sortedChain.chainId} from "../chains/${sortedChain.chainId}";`,
|
||||
exp: `export { default as ${exportName} } from "../chains/${sortedChain.chainId}"`,
|
||||
@@ -101,20 +98,21 @@ export default ${JSON.stringify(
|
||||
|
||||
const { imports, exports, exportNames, exportNameToChain } = results.reduce(
|
||||
(acc, result) => {
|
||||
// @ts-ignore
|
||||
// if it's a null result skip it (can happen when we skip chains above because their chainID is out of bounds)
|
||||
if (result === null) {
|
||||
return acc;
|
||||
}
|
||||
acc.imports.push(result.imp);
|
||||
// @ts-ignore
|
||||
acc.exports.push(result.exp);
|
||||
// @ts-ignore
|
||||
acc.exportNames.push(result.key);
|
||||
acc.exportNameToChain[result.key] = result.chain;
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
imports: [],
|
||||
exports: [],
|
||||
exportNames: [],
|
||||
exportNameToChain: {},
|
||||
imports: [] as string[],
|
||||
exports: [] as string[],
|
||||
exportNames: [] as string[],
|
||||
exportNameToChain: {} as Record<string, Chain>,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -1587,7 +1587,7 @@ export { default as Alveychain } from "../chains/3797"
|
||||
export { default as Kalychain } from "../chains/3888"
|
||||
export { default as KalychainTestnet } from "../chains/3889"
|
||||
export { default as DracNetwork } from "../chains/3912"
|
||||
export { default as DosTesnet } from "../chains/3939"
|
||||
export { default as DosTestnet } from "../chains/3939"
|
||||
export { default as Dyno } from "../chains/3966"
|
||||
export { default as DynoTestnet } from "../chains/3967"
|
||||
export { default as Yuanchain } from "../chains/3999"
|
||||
@@ -3727,7 +3727,7 @@ type ChainIdsBySlug = {
|
||||
"kalychain": 3888,
|
||||
"kalychain-testnet": 3889,
|
||||
"drac-network": 3912,
|
||||
"dos-tesnet": 3939,
|
||||
"dos-testnet": 3939,
|
||||
"dyno": 3966,
|
||||
"dyno-testnet": 3967,
|
||||
"yuanchain": 3999,
|
||||
|
||||
@@ -1,5 +1,61 @@
|
||||
# thirdweb
|
||||
|
||||
## 0.13.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`5ffbcfc3`](https://github.com/thirdweb-dev/js/commit/5ffbcfc302f74167768b196d93a328f979344036), [`42ba15f2`](https://github.com/thirdweb-dev/js/commit/42ba15f2c0e77e23e62650119dfaaa5c0dbe4481), [`d27a3dee`](https://github.com/thirdweb-dev/js/commit/d27a3dee8398d5707d2d1343c428abf8e03f67e3), [`c238fde8`](https://github.com/thirdweb-dev/js/commit/c238fde8777fd14b39837117e2d3fda1dd301029), [`99d7ec06`](https://github.com/thirdweb-dev/js/commit/99d7ec06ec4f31308627edc87d3122c21a884b5a), [`ff996646`](https://github.com/thirdweb-dev/js/commit/ff996646b228d4d095eea04b05004dd26fc7e522), [`d8d48a95`](https://github.com/thirdweb-dev/js/commit/d8d48a9516fc8fdd173fbb91a858fe7ec0725ddd), [`aa9f48d1`](https://github.com/thirdweb-dev/js/commit/aa9f48d1361194fc81146da530c95a3409bd0799), [`fd7a9f09`](https://github.com/thirdweb-dev/js/commit/fd7a9f09989e39b02a93d9dfd01cc7378e6ead53), [`fd7a9f09`](https://github.com/thirdweb-dev/js/commit/fd7a9f09989e39b02a93d9dfd01cc7378e6ead53), [`2307f11a`](https://github.com/thirdweb-dev/js/commit/2307f11ab311aa4a775edd23e777d10f8015ce86), [`54860198`](https://github.com/thirdweb-dev/js/commit/548601981f6dd8706d7a9bd4ca48e4abc7723a1d), [`64138642`](https://github.com/thirdweb-dev/js/commit/64138642e84d8b56b254762eca613d443cca292b), [`6d1eabe9`](https://github.com/thirdweb-dev/js/commit/6d1eabe9f9818ee2a79ce5bf6aa74417dbfd0558), [`c238fde8`](https://github.com/thirdweb-dev/js/commit/c238fde8777fd14b39837117e2d3fda1dd301029)]:
|
||||
- @thirdweb-dev/wallets@2.0.8
|
||||
- @thirdweb-dev/sdk@4.0.7
|
||||
- @thirdweb-dev/auth@4.1.0
|
||||
- @thirdweb-dev/storage@2.0.1
|
||||
|
||||
## 0.13.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64)]:
|
||||
- @thirdweb-dev/chains@0.1.55
|
||||
- @thirdweb-dev/sdk@4.0.6
|
||||
- @thirdweb-dev/wallets@2.0.7
|
||||
- @thirdweb-dev/auth@4.0.7
|
||||
|
||||
## 0.13.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`07544252`](https://github.com/thirdweb-dev/js/commit/07544252b49163e1ae84ba2cc76b99597a1c4553)]:
|
||||
- @thirdweb-dev/sdk@4.0.5
|
||||
- @thirdweb-dev/wallets@2.0.6
|
||||
- @thirdweb-dev/auth@4.0.6
|
||||
|
||||
## 0.13.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/sdk@4.0.4
|
||||
- @thirdweb-dev/wallets@2.0.5
|
||||
- @thirdweb-dev/auth@4.0.5
|
||||
|
||||
## 0.13.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177)]:
|
||||
- @thirdweb-dev/sdk@4.0.3
|
||||
- @thirdweb-dev/wallets@2.0.4
|
||||
- @thirdweb-dev/auth@4.0.4
|
||||
|
||||
## 0.13.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`526176c4`](https://github.com/thirdweb-dev/js/commit/526176c47108c91d83bcfc5f0ca556274e6462d6), [`d1f8e951`](https://github.com/thirdweb-dev/js/commit/d1f8e951623f1691fdfe3d1e8645970d0a52eb06), [`09120c92`](https://github.com/thirdweb-dev/js/commit/09120c923cca804b9d4f5f779e5a53c97ecc8223), [`6573556d`](https://github.com/thirdweb-dev/js/commit/6573556d0e03efa0d6a157fccb0a1c08dd22d7cd)]:
|
||||
- @thirdweb-dev/sdk@4.0.2
|
||||
- @thirdweb-dev/wallets@2.0.3
|
||||
- @thirdweb-dev/auth@4.0.3
|
||||
|
||||
## 0.13.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.13.2",
|
||||
"version": "0.13.8",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @thirdweb-dev/contracts-js
|
||||
|
||||
## 1.3.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1771](https://github.com/thirdweb-dev/js/pull/1771) [`6c30b7ef`](https://github.com/thirdweb-dev/js/commit/6c30b7efc708e1244f3be3e10eac8f3b8b14a8c3) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Updated to latest contracts package
|
||||
|
||||
## 1.3.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1756](https://github.com/thirdweb-dev/js/pull/1756) [`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Enable adding smart wallet admins via bundler for new account contracts
|
||||
|
||||
## 1.3.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/contracts-js",
|
||||
"version": "1.3.14",
|
||||
"version": "1.3.16",
|
||||
"main": "dist/thirdweb-dev-contracts-js.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js.esm.js",
|
||||
"browser": {
|
||||
@@ -10,7 +10,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/contracts-js",
|
||||
"dependencies": {
|
||||
"@thirdweb-dev/contracts": "3.10.2-3"
|
||||
"@thirdweb-dev/contracts": "3.10.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.22.9",
|
||||
|
||||
@@ -1,5 +1,65 @@
|
||||
# @thirdweb-dev/react-core
|
||||
|
||||
## 4.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1787](https://github.com/thirdweb-dev/js/pull/1787) [`ff996646`](https://github.com/thirdweb-dev/js/commit/ff996646b228d4d095eea04b05004dd26fc7e522) Thanks [@MananTank](https://github.com/MananTank)! - Enable typedoc for packages
|
||||
|
||||
- Updated dependencies [[`5ffbcfc3`](https://github.com/thirdweb-dev/js/commit/5ffbcfc302f74167768b196d93a328f979344036), [`42ba15f2`](https://github.com/thirdweb-dev/js/commit/42ba15f2c0e77e23e62650119dfaaa5c0dbe4481), [`d27a3dee`](https://github.com/thirdweb-dev/js/commit/d27a3dee8398d5707d2d1343c428abf8e03f67e3), [`c238fde8`](https://github.com/thirdweb-dev/js/commit/c238fde8777fd14b39837117e2d3fda1dd301029), [`99d7ec06`](https://github.com/thirdweb-dev/js/commit/99d7ec06ec4f31308627edc87d3122c21a884b5a), [`ff996646`](https://github.com/thirdweb-dev/js/commit/ff996646b228d4d095eea04b05004dd26fc7e522), [`d8d48a95`](https://github.com/thirdweb-dev/js/commit/d8d48a9516fc8fdd173fbb91a858fe7ec0725ddd), [`aa9f48d1`](https://github.com/thirdweb-dev/js/commit/aa9f48d1361194fc81146da530c95a3409bd0799), [`fd7a9f09`](https://github.com/thirdweb-dev/js/commit/fd7a9f09989e39b02a93d9dfd01cc7378e6ead53), [`fd7a9f09`](https://github.com/thirdweb-dev/js/commit/fd7a9f09989e39b02a93d9dfd01cc7378e6ead53), [`2307f11a`](https://github.com/thirdweb-dev/js/commit/2307f11ab311aa4a775edd23e777d10f8015ce86), [`54860198`](https://github.com/thirdweb-dev/js/commit/548601981f6dd8706d7a9bd4ca48e4abc7723a1d), [`64138642`](https://github.com/thirdweb-dev/js/commit/64138642e84d8b56b254762eca613d443cca292b), [`6d1eabe9`](https://github.com/thirdweb-dev/js/commit/6d1eabe9f9818ee2a79ce5bf6aa74417dbfd0558), [`c238fde8`](https://github.com/thirdweb-dev/js/commit/c238fde8777fd14b39837117e2d3fda1dd301029)]:
|
||||
- @thirdweb-dev/wallets@2.0.8
|
||||
- @thirdweb-dev/sdk@4.0.7
|
||||
- @thirdweb-dev/auth@4.1.0
|
||||
- @thirdweb-dev/storage@2.0.1
|
||||
|
||||
## 4.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64)]:
|
||||
- @thirdweb-dev/chains@0.1.55
|
||||
- @thirdweb-dev/sdk@4.0.6
|
||||
- @thirdweb-dev/wallets@2.0.7
|
||||
- @thirdweb-dev/auth@4.0.7
|
||||
|
||||
## 4.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`07544252`](https://github.com/thirdweb-dev/js/commit/07544252b49163e1ae84ba2cc76b99597a1c4553)]:
|
||||
- @thirdweb-dev/sdk@4.0.5
|
||||
- @thirdweb-dev/wallets@2.0.6
|
||||
- @thirdweb-dev/auth@4.0.6
|
||||
|
||||
## 4.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/sdk@4.0.4
|
||||
- @thirdweb-dev/wallets@2.0.5
|
||||
- @thirdweb-dev/auth@4.0.5
|
||||
|
||||
## 4.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177)]:
|
||||
- @thirdweb-dev/sdk@4.0.3
|
||||
- @thirdweb-dev/wallets@2.0.4
|
||||
- @thirdweb-dev/auth@4.0.4
|
||||
|
||||
## 4.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1758](https://github.com/thirdweb-dev/js/pull/1758) [`08e9cd20`](https://github.com/thirdweb-dev/js/commit/08e9cd206bcc37cf1e84a878dc78bc4f38e5092c) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Add pagination to useOwnedNFTs
|
||||
|
||||
- Updated dependencies [[`526176c4`](https://github.com/thirdweb-dev/js/commit/526176c47108c91d83bcfc5f0ca556274e6462d6), [`d1f8e951`](https://github.com/thirdweb-dev/js/commit/d1f8e951623f1691fdfe3d1e8645970d0a52eb06), [`09120c92`](https://github.com/thirdweb-dev/js/commit/09120c923cca804b9d4f5f779e5a53c97ecc8223), [`6573556d`](https://github.com/thirdweb-dev/js/commit/6573556d0e03efa0d6a157fccb0a1c08dd22d7cd)]:
|
||||
- @thirdweb-dev/sdk@4.0.2
|
||||
- @thirdweb-dev/wallets@2.0.3
|
||||
- @thirdweb-dev/auth@4.0.3
|
||||
|
||||
## 4.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-core",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.8",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
/** @internal */
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars, better-tree-shaking/no-top-level-side-effects
|
||||
export const __DEV__ = process.env.NODE_ENV !== "production";
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
LocalWallet,
|
||||
MagicLink,
|
||||
MetaMaskWallet,
|
||||
OKXWallet,
|
||||
PaperWallet,
|
||||
PhantomWallet,
|
||||
RainbowWallet,
|
||||
@@ -37,6 +38,7 @@ type WalletIdToWalletTypeMap = {
|
||||
walletConnect: WalletConnect;
|
||||
phantom: PhantomWallet;
|
||||
walletConnectV1: WalletConnect;
|
||||
okx: OKXWallet;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -225,11 +225,12 @@ export function useTotalCirculatingSupply(
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: ownedNFTs, isLoading, error } = useOwnedNFTs(contract, "{{wallet_address}}");
|
||||
* const { data: ownedNFTs, isLoading, error } = useOwnedNFTs(contract, "{{wallet_address}}", { start: 0, count: 100 });
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a {@link NFTContract}
|
||||
* @param ownerWalletAddress - the wallet address to get owned tokens for
|
||||
* @param queryParams - query params to pass to the query for pagination
|
||||
* @returns a response object that includes the list of owned tokens
|
||||
* @beta
|
||||
* @twfeature ERC721Enumerable | ERC1155Enumerable | ERC721Supply
|
||||
@@ -238,6 +239,7 @@ export function useTotalCirculatingSupply(
|
||||
export function useOwnedNFTs<TContract extends NFTContract>(
|
||||
contract: RequiredParam<TContract>,
|
||||
ownerWalletAddress: RequiredParam<WalletAddress>,
|
||||
queryParams?: QueryAllParams,
|
||||
) {
|
||||
const contractAddress = contract?.getAddress();
|
||||
const { erc721, erc1155 } = getErcs(contract);
|
||||
@@ -248,10 +250,10 @@ export function useOwnedNFTs<TContract extends NFTContract>(
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
invariant(ownerWalletAddress, "No wallet address provided");
|
||||
if (erc721) {
|
||||
return await erc721.getOwned(ownerWalletAddress);
|
||||
return await erc721.getOwned(ownerWalletAddress, queryParams);
|
||||
}
|
||||
if (erc1155) {
|
||||
return await erc1155.getOwned(ownerWalletAddress);
|
||||
return await erc1155.getOwned(ownerWalletAddress, queryParams);
|
||||
}
|
||||
invariant(false, "Unknown NFT type");
|
||||
},
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @thirdweb-dev/react-native-compat
|
||||
|
||||
## 0.3.13
|
||||
|
||||
## 0.3.12
|
||||
|
||||
## 0.3.11
|
||||
|
||||
## 0.3.10
|
||||
|
||||
## 0.3.9
|
||||
|
||||
## 0.3.8
|
||||
|
||||
## 0.3.7
|
||||
|
||||
## 0.3.6
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native-compat",
|
||||
"description": "Shims for Thirdweb in React Native Projects",
|
||||
"version": "0.3.7",
|
||||
"version": "0.3.13",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native-compat",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ["thirdweb"],
|
||||
plugins: ["i18next"],
|
||||
rules: {
|
||||
"i18next/no-literal-string": 2,
|
||||
},
|
||||
settings: {
|
||||
// https://github.com/facebook/react-native/issues/28549
|
||||
"import/ignore": ["react-native"],
|
||||
|
||||
@@ -1,5 +1,103 @@
|
||||
# @thirdweb-dev/react-native
|
||||
|
||||
## 0.3.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1803](https://github.com/thirdweb-dev/js/pull/1803) [`a63f5dc7`](https://github.com/thirdweb-dev/js/commit/a63f5dc7cb173bcb4dc5d17ccb0936411f9973e6) Thanks [@iketw](https://github.com/iketw)! - React Native UI/theme improvements
|
||||
|
||||
- [#1787](https://github.com/thirdweb-dev/js/pull/1787) [`ff996646`](https://github.com/thirdweb-dev/js/commit/ff996646b228d4d095eea04b05004dd26fc7e522) Thanks [@MananTank](https://github.com/MananTank)! - Enable typedoc for packages
|
||||
|
||||
- [#1799](https://github.com/thirdweb-dev/js/pull/1799) [`1cc26e43`](https://github.com/thirdweb-dev/js/commit/1cc26e43e533440abdb5c9df24ccd2ace671f413) Thanks [@iketw](https://github.com/iketw)! - Adds localization for the React Native SDK
|
||||
|
||||
You can now pass a Locale object to the ThirdwebProvider with your translations:
|
||||
|
||||
```javascript
|
||||
import { ThirdwebProvicer, en } from @thirdweb-dev/react-native;
|
||||
|
||||
<ThirdwebProvider locale={{
|
||||
...your-translated-strings
|
||||
}}>
|
||||
<App />
|
||||
</ThirdwebProvider>
|
||||
```
|
||||
|
||||
- Updated dependencies [[`5ffbcfc3`](https://github.com/thirdweb-dev/js/commit/5ffbcfc302f74167768b196d93a328f979344036), [`42ba15f2`](https://github.com/thirdweb-dev/js/commit/42ba15f2c0e77e23e62650119dfaaa5c0dbe4481), [`d27a3dee`](https://github.com/thirdweb-dev/js/commit/d27a3dee8398d5707d2d1343c428abf8e03f67e3), [`ff996646`](https://github.com/thirdweb-dev/js/commit/ff996646b228d4d095eea04b05004dd26fc7e522), [`d8d48a95`](https://github.com/thirdweb-dev/js/commit/d8d48a9516fc8fdd173fbb91a858fe7ec0725ddd), [`aa9f48d1`](https://github.com/thirdweb-dev/js/commit/aa9f48d1361194fc81146da530c95a3409bd0799), [`fd7a9f09`](https://github.com/thirdweb-dev/js/commit/fd7a9f09989e39b02a93d9dfd01cc7378e6ead53), [`fd7a9f09`](https://github.com/thirdweb-dev/js/commit/fd7a9f09989e39b02a93d9dfd01cc7378e6ead53), [`2307f11a`](https://github.com/thirdweb-dev/js/commit/2307f11ab311aa4a775edd23e777d10f8015ce86), [`64138642`](https://github.com/thirdweb-dev/js/commit/64138642e84d8b56b254762eca613d443cca292b), [`6d1eabe9`](https://github.com/thirdweb-dev/js/commit/6d1eabe9f9818ee2a79ce5bf6aa74417dbfd0558)]:
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
|
||||
## 0.3.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64)]:
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
|
||||
## 0.3.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`07544252`](https://github.com/thirdweb-dev/js/commit/07544252b49163e1ae84ba2cc76b99597a1c4553)]:
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
|
||||
## 0.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
|
||||
## 0.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177)]:
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
|
||||
## 0.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1724](https://github.com/thirdweb-dev/js/pull/1724) [`fc62b91e`](https://github.com/thirdweb-dev/js/commit/fc62b91ee55b0adba01298f33b21352004d1b71d) Thanks [@iketw](https://github.com/iketw)! - Adds Google sign in to embeddedWallet in React Native
|
||||
|
||||
You need to add the `react-native-inappbrowser-reborn` package to your app, then you can do:
|
||||
|
||||
```javascript
|
||||
<ThirdwebProvider
|
||||
activeChain={activeChain}
|
||||
clientId={"your-client-id"}
|
||||
supportedWallets={[
|
||||
embeddedWallet({
|
||||
// if this is true AND oauthOptions is not set we set it to false internally
|
||||
email: true,
|
||||
// if this is set we enable Sign in with Google
|
||||
oauthOptions: {
|
||||
redirectUrl: "test15app://",
|
||||
providers: ["google"],
|
||||
},
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<App />
|
||||
</ThirdwebProvider>
|
||||
```
|
||||
|
||||
- Updated dependencies [[`526176c4`](https://github.com/thirdweb-dev/js/commit/526176c47108c91d83bcfc5f0ca556274e6462d6), [`d1f8e951`](https://github.com/thirdweb-dev/js/commit/d1f8e951623f1691fdfe3d1e8645970d0a52eb06), [`09120c92`](https://github.com/thirdweb-dev/js/commit/09120c923cca804b9d4f5f779e5a53c97ecc8223), [`08e9cd20`](https://github.com/thirdweb-dev/js/commit/08e9cd206bcc37cf1e84a878dc78bc4f38e5092c), [`6573556d`](https://github.com/thirdweb-dev/js/commit/6573556d0e03efa0d6a157fccb0a1c08dd22d7cd)]:
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
|
||||
## 0.3.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -10,13 +10,16 @@
|
||||
<a href="https://discord.gg/thirdweb"><img alt="Join our Discord!" src="https://img.shields.io/discord/834227967404146718.svg?color=7289da&label=discord&logo=discord&style=flat"/></a>
|
||||
|
||||
</p>
|
||||
<p align="center"><strong>Powering react-native dapps.</strong></p>
|
||||
<br />
|
||||
<p><strong>Powering react-native dapps.</strong></p>
|
||||
|
||||
## 👷🚧 Alpha 🚧👷
|
||||
The go to librarly for seamless Web3 integration in React Native apps.
|
||||
|
||||
<br />
|
||||
|
||||
## Getting Started
|
||||
|
||||
Head over to the [documentation](https://portal.thirdweb.com/react-native) to learn more
|
||||
Try it out by running:
|
||||
|
||||
`npx thirdweb create --template react-native-typescript-starter`
|
||||
|
||||
or head over to the [documentation](https://portal.thirdweb.com/react-native) to learn more
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native",
|
||||
"version": "0.3.7",
|
||||
"version": "0.3.13",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -16,7 +16,8 @@
|
||||
"fix": "eslint src/ --fix",
|
||||
"clean": "rm -rf dist/",
|
||||
"build": "tsc",
|
||||
"push": "yalc push"
|
||||
"push": "yalc push",
|
||||
"typedoc": "rimraf typedoc && node ./scripts/typedoc.js"
|
||||
},
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -65,6 +66,7 @@
|
||||
"eslint": "^8.45.0",
|
||||
"eslint-config-prettier": "^8.9.0",
|
||||
"eslint-config-thirdweb": "workspace:*",
|
||||
"eslint-plugin-i18next": "^6.0.3",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-inclusive-language": "^2.2.0",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
@@ -79,17 +81,20 @@
|
||||
"react-native-mmkv": "2.5.1",
|
||||
"react-native-safe-area-context": "4.5.3",
|
||||
"react-native-webview": "12.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"typedoc": "^0.25.2",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"amazon-cognito-identity-js": "^6.3.3",
|
||||
"react-native-aes-gcm-crypto": "^0.2.2",
|
||||
"react-native-camera": "^4.2.1",
|
||||
"react-native-device-info": "10.6.0",
|
||||
"react-native-safe-area-context": "4.5.3",
|
||||
"react-native-webview": "12.1.0",
|
||||
"amazon-cognito-identity-js": "^6.3.3",
|
||||
"react-native-inappbrowser-reborn": "^3.7.0",
|
||||
"react-native-quick-base64": "^2.0.7",
|
||||
"react-native-quick-crypto": "^0.6.1",
|
||||
"react-native-aes-gcm-crypto": "^0.2.2"
|
||||
"react-native-safe-area-context": "4.5.3",
|
||||
"react-native-webview": "12.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"ethers": ">=5.5.1 <6",
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const TypeDoc = require("typedoc");
|
||||
|
||||
async function main() {
|
||||
// Application.bootstrap also exists, which will not load plugins
|
||||
// Also accepts an array of option readers if you want to disable
|
||||
// TypeDoc's tsconfig.json/package.json/typedoc.json option readers
|
||||
const app = await TypeDoc.Application.bootstrapWithPlugins({
|
||||
entryPoints: ["src/index.ts"],
|
||||
excludeInternal: true,
|
||||
externalPattern: [
|
||||
"**/node_modules/**",
|
||||
"**/packages/sdk/**",
|
||||
"**/packages/wallets/**",
|
||||
"**/packages/chains/**",
|
||||
],
|
||||
exclude: [
|
||||
"**/node_modules/**",
|
||||
"**/packages/sdk/**",
|
||||
"**/packages/wallets/**",
|
||||
"**/packages/chains/**",
|
||||
],
|
||||
});
|
||||
|
||||
const project = await app.convert();
|
||||
|
||||
if (project) {
|
||||
// Project may not have converted correctly
|
||||
const outputDir = "typedoc/";
|
||||
|
||||
// Rendered docs
|
||||
await app.generateDocs(project, outputDir);
|
||||
// Alternatively generate JSON output
|
||||
await app.generateJson(project, outputDir + "/documentation.json");
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -1,12 +1,12 @@
|
||||
import Svg, { Path } from "react-native-svg";
|
||||
import { IconStyleProp } from "./types";
|
||||
|
||||
const CloseIcon = ({ width, height }: IconStyleProp) => {
|
||||
const CloseIcon = ({ width, height, color }: IconStyleProp) => {
|
||||
return (
|
||||
<Svg width={width} height={height} viewBox="0 0 14 14" fill="none">
|
||||
<Path
|
||||
d="M13.3002 0.70998C13.2077 0.617276 13.0978 0.543728 12.9768 0.493547C12.8559 0.443366 12.7262 0.417535 12.5952 0.417535C12.4643 0.417535 12.3346 0.443366 12.2136 0.493547C12.0926 0.543728 11.9827 0.617276 11.8902 0.70998L7.00022 5.58998L2.11022 0.699979C2.01764 0.607397 1.90773 0.533957 1.78677 0.483852C1.6658 0.433747 1.53615 0.407959 1.40522 0.407959C1.27429 0.407959 1.14464 0.433747 1.02368 0.483852C0.902716 0.533957 0.792805 0.607397 0.700223 0.699979C0.607642 0.792561 0.534202 0.902472 0.484097 1.02344C0.433992 1.1444 0.408203 1.27405 0.408203 1.40498C0.408203 1.53591 0.433992 1.66556 0.484097 1.78652C0.534202 1.90749 0.607642 2.0174 0.700223 2.10998L5.59022 6.99998L0.700223 11.89C0.607642 11.9826 0.534202 12.0925 0.484097 12.2134C0.433992 12.3344 0.408203 12.464 0.408203 12.595C0.408203 12.7259 0.433992 12.8556 0.484097 12.9765C0.534202 13.0975 0.607642 13.2074 0.700223 13.3C0.792805 13.3926 0.902716 13.466 1.02368 13.5161C1.14464 13.5662 1.27429 13.592 1.40522 13.592C1.53615 13.592 1.6658 13.5662 1.78677 13.5161C1.90773 13.466 2.01764 13.3926 2.11022 13.3L7.00022 8.40998L11.8902 13.3C11.9828 13.3926 12.0927 13.466 12.2137 13.5161C12.3346 13.5662 12.4643 13.592 12.5952 13.592C12.7262 13.592 12.8558 13.5662 12.9768 13.5161C13.0977 13.466 13.2076 13.3926 13.3002 13.3C13.3928 13.2074 13.4662 13.0975 13.5163 12.9765C13.5665 12.8556 13.5922 12.7259 13.5922 12.595C13.5922 12.464 13.5665 12.3344 13.5163 12.2134C13.4662 12.0925 13.3928 11.9826 13.3002 11.89L8.41022 6.99998L13.3002 2.10998C13.6802 1.72998 13.6802 1.08998 13.3002 0.70998Z"
|
||||
fill="#646D7A"
|
||||
fill={color}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
|
||||
@@ -10,3 +10,4 @@ export * from "./right-arrow";
|
||||
export * from "./wallet";
|
||||
export * from "./money";
|
||||
export * from "./switch";
|
||||
export * from "./svgs";
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
export const GOOGLE_ICON = `<svg height={height} viewBox="0 0 24 24" width={width}>
|
||||
<path
|
||||
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
|
||||
fill="#4285F4"
|
||||
/>
|
||||
<path
|
||||
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
|
||||
fill="#34A853"
|
||||
/>
|
||||
<path
|
||||
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
|
||||
fill="#FBBC05"
|
||||
/>
|
||||
<path
|
||||
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
|
||||
fill="#EA4335"
|
||||
/>
|
||||
<path d="M1 1h22v22H1z" fill="none" />
|
||||
</svg>`;
|
||||
|
||||
export const EMAIL_WALLET_ICON = `<svg width="48" height="48" viewBox="0 0 48 48" fill="none">
|
||||
<g clip-path="url(#clip0_3589_8649)">
|
||||
<rect width="48" height="48" rx="8" fill="url(#paint0_linear_3589_8649)"/>
|
||||
|
||||
@@ -14,7 +14,7 @@ import { ConnectWalletButton } from "./ConnectWalletFlow/ConnectWalletButton";
|
||||
import { ConnectWalletButtonProps } from "./ConnectWalletFlow/ConnectWalletButton";
|
||||
import BaseButton from "./base/BaseButton";
|
||||
import Text from "./base/Text";
|
||||
import { useUIContext } from "../providers/ui-context-provider";
|
||||
import { useLocale, useUIContext } from "../providers/ui-context-provider";
|
||||
import { ThemeProvider } from "../styles/ThemeProvider";
|
||||
import { SupportedTokens, defaultTokens } from "./SendFunds/defaultTokens";
|
||||
|
||||
@@ -81,6 +81,7 @@ export const ConnectWallet = ({
|
||||
privacyPolicyUrl,
|
||||
supportedTokens,
|
||||
}: ConnectWalletProps) => {
|
||||
const l = useLocale();
|
||||
const fadeAnim = useRef(new Animated.Value(0)).current;
|
||||
const address = useAddress();
|
||||
const isNetworkMismatch = useNetworkMismatch();
|
||||
@@ -142,7 +143,7 @@ export const ConnectWallet = ({
|
||||
<ActivityIndicator size="small" color="buttonTextColor" />
|
||||
) : (
|
||||
<Text variant="bodyLarge" color="buttonTextColor">
|
||||
Switch Network
|
||||
{l.common.switch_network}
|
||||
</Text>
|
||||
)}
|
||||
</BaseButton>
|
||||
|
||||
@@ -13,9 +13,11 @@ import { WalletIcon } from "../base/WalletIcon";
|
||||
import WalletConnectIcon from "../../assets/wallet-connect";
|
||||
import QrCodeIcon from "../../assets/qr-code";
|
||||
import { QRCodeScan } from "./QRCodeScan";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
const ConnectAppField = () => {
|
||||
const theme = useTheme();
|
||||
const l = useLocale();
|
||||
const [showWCInput, setShowWCInput] = useState(false);
|
||||
const [wcUri, setWCUri] = useState<string | undefined>();
|
||||
const [appMeta, setAppMeta] = useState<{ name: string; iconUrl: string }>();
|
||||
@@ -130,6 +132,10 @@ const ConnectAppField = () => {
|
||||
placeholder: "wc://...",
|
||||
placeholderTextColor: theme.colors.textSecondary,
|
||||
numberOfLines: 1,
|
||||
style: {
|
||||
color: theme.colors.textPrimary,
|
||||
fontFamily: theme.textVariants.defaults.fontFamily,
|
||||
},
|
||||
}}
|
||||
containerProps={{
|
||||
flex: 1,
|
||||
@@ -177,7 +183,7 @@ const ConnectAppField = () => {
|
||||
)}
|
||||
<View style={styles.exportWalletInfo}>
|
||||
<Text variant="bodySmall" numberOfLines={1}>
|
||||
{appMeta ? appMeta.name : "Connect app"}
|
||||
{appMeta ? appMeta.name : l.common.connect_app}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
|
||||
+31
-15
@@ -29,6 +29,7 @@ import { SendButton } from "../SendFunds/SendButton";
|
||||
import { SupportedTokens } from "../SendFunds/defaultTokens";
|
||||
import { ActiveDot } from "../base";
|
||||
import { EmbeddedWallet } from "../../wallets/wallets/embedded/EmbeddedWallet";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
const MODAL_HEIGHT = Dimensions.get("window").height * 0.7;
|
||||
const DEVICE_WIDTH = Dimensions.get("window").width;
|
||||
@@ -50,6 +51,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
supportedTokens: SupportedTokens;
|
||||
displayBalanceToken?: Record<number, string>;
|
||||
}) => {
|
||||
const l = useLocale();
|
||||
const [isExportModalVisible, setIsExportModalVisible] = useState(false);
|
||||
const activeWallet = useWallet();
|
||||
const chain = useChain();
|
||||
@@ -137,11 +139,15 @@ export const ConnectWalletDetailsModal = ({
|
||||
return (
|
||||
<>
|
||||
<View style={styles.currentNetwork}>
|
||||
<Text variant="bodySmallSecondary">Additional Actions</Text>
|
||||
<Text variant="bodySmallSecondary">
|
||||
{l.connect_wallet_details.additional_actions}
|
||||
</Text>
|
||||
</View>
|
||||
<BaseButton
|
||||
backgroundColor="background"
|
||||
borderColor="border"
|
||||
borderRadius="lg"
|
||||
borderWidth={0.5}
|
||||
mb="sm"
|
||||
justifyContent="space-between"
|
||||
style={styles.exportWallet}
|
||||
@@ -150,7 +156,9 @@ export const ConnectWalletDetailsModal = ({
|
||||
<>
|
||||
<PocketWalletIcon width={16} height={16} />
|
||||
<View style={styles.exportWalletInfo}>
|
||||
<Text variant="bodySmall">Backup wallet</Text>
|
||||
<Text variant="bodySmall">
|
||||
{l.connect_wallet_details.backup_wallet}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
<RightArrowIcon height={10} width={10} />
|
||||
@@ -159,6 +167,8 @@ export const ConnectWalletDetailsModal = ({
|
||||
<BaseButton
|
||||
backgroundColor="background"
|
||||
borderColor="border"
|
||||
borderRadius="lg"
|
||||
borderWidth={0.5}
|
||||
mb="sm"
|
||||
justifyContent="space-between"
|
||||
style={styles.exportWallet}
|
||||
@@ -167,7 +177,9 @@ export const ConnectWalletDetailsModal = ({
|
||||
<>
|
||||
<PocketWalletIcon width={16} height={16} />
|
||||
<View style={styles.exportWalletInfo}>
|
||||
<Text variant="bodySmall">Import wallet</Text>
|
||||
<Text variant="bodySmall">
|
||||
{l.connect_wallet_details.import_wallet}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
<RightArrowIcon height={10} width={10} />
|
||||
@@ -181,9 +193,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
|
||||
{activeWallet?.walletId === LocalWallet.id ? (
|
||||
<Text variant="error" textAlign="left" mb="sm">
|
||||
{
|
||||
"This is a temporary guest wallet. Download a backup if you don't want to lose access to it."
|
||||
}
|
||||
{l.local_wallet.this_is_a_temporary_wallet}
|
||||
</Text>
|
||||
) : null}
|
||||
</>
|
||||
@@ -197,6 +207,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
onExportLocalWalletPress,
|
||||
onWalletImported,
|
||||
smartWallet,
|
||||
l,
|
||||
]);
|
||||
|
||||
return (
|
||||
@@ -230,7 +241,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
<Box flexDirection="row" alignItems="center">
|
||||
<ActiveDot width={10} height={10} />
|
||||
<Text variant="bodySmallSecondary" ml="xxs">
|
||||
Connected to a Smart Wallet
|
||||
{l.connect_wallet_details.connected_to_smart_wallet}
|
||||
</Text>
|
||||
</Box>
|
||||
{isSmartWalletDeployed ? (
|
||||
@@ -238,7 +249,8 @@ export const ConnectWalletDetailsModal = ({
|
||||
) : null}
|
||||
</BaseButton>
|
||||
) : null}
|
||||
{activeWallet?.walletId === EmbeddedWallet.id ? (
|
||||
{activeWallet?.walletId === EmbeddedWallet.id &&
|
||||
(activeWallet as EmbeddedWallet).getEmail() ? (
|
||||
<Box flexDirection="row" alignItems="center" mt="md">
|
||||
<ActiveDot width={10} height={10} />
|
||||
<Text variant="bodySmallSecondary" ml="xxs">
|
||||
@@ -246,18 +258,24 @@ export const ConnectWalletDetailsModal = ({
|
||||
</Text>
|
||||
</Box>
|
||||
) : null}
|
||||
<Box flexDirection="row" justifyContent="space-evenly" mt="md">
|
||||
<Box
|
||||
flexDirection="row"
|
||||
justifyContent="space-evenly"
|
||||
marginVertical="md"
|
||||
>
|
||||
<SendButton supportedTokens={supportedTokens} />
|
||||
<ReceiveButton />
|
||||
</Box>
|
||||
<View style={styles.currentNetwork}>
|
||||
<Text variant="bodySmallSecondary">Current Network</Text>
|
||||
<Text variant="bodySmallSecondary">
|
||||
{l.connect_wallet_details.current_network}
|
||||
</Text>
|
||||
</View>
|
||||
<NetworkButton chain={chain} enableSwitchModal={true} />
|
||||
{!hideTestnetFaucet && chain?.testnet && chain?.faucets?.length ? (
|
||||
<IconTextButton
|
||||
mt="xs"
|
||||
text="Request Testnet Funds"
|
||||
text={l.connect_wallet_details.request_testnet_funds}
|
||||
icon={<MoneyIcon height={16} width={16} />}
|
||||
onPress={() => {
|
||||
if (chain?.faucets?.[0]) {
|
||||
@@ -269,7 +287,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
{chain?.explorers && chain?.explorers?.[0] && (
|
||||
<IconTextButton
|
||||
mt="xs"
|
||||
text="View Transaction History"
|
||||
text={l.connect_wallet_details.view_transaction_history}
|
||||
icon={<TransactionIcon height={16} width={16} />}
|
||||
onPress={() => {
|
||||
Linking.openURL(
|
||||
@@ -318,8 +336,6 @@ const styles = StyleSheet.create({
|
||||
alignContent: "center",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
borderRadius: 12,
|
||||
borderWidth: 0.5,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 12,
|
||||
minWidth: 200,
|
||||
@@ -330,7 +346,7 @@ const styles = StyleSheet.create({
|
||||
alignContent: "flex-start",
|
||||
alignItems: "flex-start",
|
||||
justifyContent: "flex-start",
|
||||
marginTop: 24,
|
||||
marginBottom: 8,
|
||||
marginTop: 12,
|
||||
},
|
||||
});
|
||||
|
||||
+7
-7
@@ -18,6 +18,7 @@ import { usePersonalWalletAddress } from "../../wallets/hooks/usePersonalWalletA
|
||||
import { shortenWalletAddress } from "../../utils/addresses";
|
||||
import { LocalWallet } from "../../wallets/wallets/LocalWallet";
|
||||
import { TWModal } from "../base/modal/TWModal";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
export type ExportLocalWalletModalProps = {
|
||||
isVisible: boolean;
|
||||
@@ -28,6 +29,7 @@ export const ExportLocalWalletModal = ({
|
||||
isVisible,
|
||||
onClose,
|
||||
}: ExportLocalWalletModalProps) => {
|
||||
const l = useLocale();
|
||||
const [password, setPassword] = useState<string | undefined>();
|
||||
const [error, setError] = useState<string | undefined>();
|
||||
const [isExporting, setIsExporting] = useState<boolean>(false);
|
||||
@@ -151,15 +153,13 @@ export const ExportLocalWalletModal = ({
|
||||
>
|
||||
<ModalHeaderTextClose
|
||||
onClose={onCloseInternal}
|
||||
headerText="Backup your Wallet"
|
||||
headerText={l.local_wallet.backup_your_wallet}
|
||||
/>
|
||||
<Text variant="subHeader" mt="md" textAlign="left">
|
||||
{
|
||||
"This will download a JSON file containing your wallet information onto your device encrypted with the password."
|
||||
}
|
||||
{l.local_wallet.this_will_download_json}
|
||||
</Text>
|
||||
<Text variant="bodySmall" textAlign="left" mt="lg" mb="xxs">
|
||||
Wallet Address
|
||||
{l.local_wallet.wallet_address}
|
||||
</Text>
|
||||
<Text variant="bodySmallSecondary">
|
||||
{shortenWalletAddress(
|
||||
@@ -167,7 +167,7 @@ export const ExportLocalWalletModal = ({
|
||||
)}
|
||||
</Text>
|
||||
<Text variant="bodySmall" textAlign="left" mt="lg" mb="xxs">
|
||||
Password
|
||||
{l.common.password}
|
||||
</Text>
|
||||
<PasswordInput onChangeText={onChangeText} />
|
||||
<Text variant="bodySmall" color="red" mt="xs" textAlign="left">
|
||||
@@ -183,7 +183,7 @@ export const ExportLocalWalletModal = ({
|
||||
<ActivityIndicator size="small" color="buttonTextColor" />
|
||||
) : (
|
||||
<Text variant="bodySmall" color="black">
|
||||
Backup
|
||||
{l.connect_wallet_details.backup}
|
||||
</Text>
|
||||
)}
|
||||
</BaseButton>
|
||||
|
||||
+5
-4
@@ -7,9 +7,10 @@ import {
|
||||
CLOSE_MODAL_STATE,
|
||||
WalletConnectSessionProposalModal,
|
||||
} from "../../utils/modalTypes";
|
||||
import { useModalState } from "../../providers/ui-context-provider";
|
||||
import { useLocale, useModalState } from "../../providers/ui-context-provider";
|
||||
|
||||
export const SessionProposalModal = () => {
|
||||
const l = useLocale();
|
||||
const { modalState, setModalState } = useModalState();
|
||||
const { data: proposalData } =
|
||||
modalState as WalletConnectSessionProposalModal;
|
||||
@@ -27,7 +28,7 @@ export const SessionProposalModal = () => {
|
||||
borderRadius="md"
|
||||
p="lg"
|
||||
>
|
||||
<Text variant="bodyLarge">Connect to App</Text>
|
||||
<Text variant="bodyLarge">{l.connect_wallet_details.connect_to_app}</Text>
|
||||
<Text variant="bodyLarge">{proposalData.proposer.metadata.name}</Text>
|
||||
<Box flexDirection="row" justifyContent="space-evenly" mt="lg">
|
||||
<BaseButton
|
||||
@@ -44,7 +45,7 @@ export const SessionProposalModal = () => {
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<Text variant="bodySmall">Reject</Text>
|
||||
<Text variant="bodySmall">{l.common.reject}</Text>
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
alignContent="center"
|
||||
@@ -67,7 +68,7 @@ export const SessionProposalModal = () => {
|
||||
}}
|
||||
>
|
||||
<Text variant="bodySmall" color="black">
|
||||
Approve
|
||||
{l.common.approve}
|
||||
</Text>
|
||||
</BaseButton>
|
||||
</Box>
|
||||
|
||||
+8
-7
@@ -6,7 +6,7 @@ import {
|
||||
EIP155_SIGNING_METHODS,
|
||||
IWalletConnectReceiver,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import { useModalState } from "../../providers/ui-context-provider";
|
||||
import { useLocale, useModalState } from "../../providers/ui-context-provider";
|
||||
import {
|
||||
CLOSE_MODAL_STATE,
|
||||
WalletConnectSessionRequestModal,
|
||||
@@ -30,6 +30,7 @@ const getTitle = (method: string) => {
|
||||
const MODAL_HEIGHT = Dimensions.get("window").height * 0.7;
|
||||
|
||||
export const SessionRequestModal = () => {
|
||||
const l = useLocale();
|
||||
const { modalState, setModalState } = useModalState();
|
||||
const { data: requestData } = modalState as WalletConnectSessionRequestModal;
|
||||
const [approvingRequest, setApprovingRequest] = useState(false);
|
||||
@@ -60,7 +61,7 @@ export const SessionRequestModal = () => {
|
||||
case EIP155_SIGNING_METHODS.SWITCH_CHAIN:
|
||||
return (
|
||||
<Text variant="bodySmall" textAlign="left">
|
||||
{`Switch to ${
|
||||
{`${l.connect_wallet_details.switch_to} ${
|
||||
requestData.params[0].chainId === chain?.chainId
|
||||
? chain?.slug
|
||||
: requestData.params[0].chainId
|
||||
@@ -85,17 +86,17 @@ export const SessionRequestModal = () => {
|
||||
return (
|
||||
<Box>
|
||||
<Text variant="bodySmall" textAlign="left">
|
||||
{`from: ${shortenWalletAddress(from)}`}
|
||||
{`${l.common.from}: ${shortenWalletAddress(from)}`}
|
||||
</Text>
|
||||
<Text variant="bodySmall" textAlign="left" mt="sm">
|
||||
{`to: ${shortenWalletAddress(to)}`}
|
||||
{`${l.common.to}: ${shortenWalletAddress(to)}`}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
default:
|
||||
throw new Error(`Method not implemented: ${requestData.method}`);
|
||||
}
|
||||
}, [chain?.chainId, chain?.slug, requestData]);
|
||||
}, [chain?.chainId, chain?.slug, requestData, l]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -129,7 +130,7 @@ export const SessionRequestModal = () => {
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<Text variant="bodySmall">Reject</Text>
|
||||
<Text variant="bodySmall">{l.common.reject}</Text>
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
alignContent="center"
|
||||
@@ -148,7 +149,7 @@ export const SessionRequestModal = () => {
|
||||
<ActivityIndicator size="small" />
|
||||
) : (
|
||||
<Text variant="bodySmall" color="black">
|
||||
Approve
|
||||
{l.common.approve}
|
||||
</Text>
|
||||
)}
|
||||
</BaseButton>
|
||||
|
||||
+9
-10
@@ -14,13 +14,14 @@ import RightArrowIcon from "../../assets/right-arrow";
|
||||
import ConnectAppField from "./ConnectAppField";
|
||||
import DisconnectIcon from "../../assets/disconnect";
|
||||
import { IconTextButton } from "../base/IconTextButton";
|
||||
import { useGlobalTheme } from "../../providers/ui-context-provider";
|
||||
import { useGlobalTheme, useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
export const SmartWalletAdditionalActions = ({
|
||||
onExportPress,
|
||||
}: {
|
||||
onExportPress: () => void;
|
||||
}) => {
|
||||
const l = useLocale();
|
||||
const { setConnectedWallet } = useWalletContext();
|
||||
const [smartWallet, setSmartWallet] = useSmartWallet();
|
||||
const [smartWalletAddress, setSmartWalletAddress] = useState<string>("");
|
||||
@@ -64,8 +65,8 @@ export const SmartWalletAdditionalActions = ({
|
||||
mt="xs"
|
||||
text={
|
||||
showSmartWallet
|
||||
? "Switch to Smart Wallet"
|
||||
: "Switch to Personal Wallet"
|
||||
? l.smart_wallet.switch_to_smart
|
||||
: l.smart_wallet.switch_to_personal
|
||||
}
|
||||
icon={
|
||||
<DisconnectIcon
|
||||
@@ -85,6 +86,8 @@ export const SmartWalletAdditionalActions = ({
|
||||
<BaseButton
|
||||
backgroundColor="background"
|
||||
borderColor="border"
|
||||
borderRadius="lg"
|
||||
borderWidth={0.5}
|
||||
mb="sm"
|
||||
mt="xs"
|
||||
justifyContent="space-between"
|
||||
@@ -96,8 +99,8 @@ export const SmartWalletAdditionalActions = ({
|
||||
<View style={styles.exportWalletInfo}>
|
||||
<Text variant="bodySmall">
|
||||
{wallet?.walletId === walletIds.localWallet
|
||||
? "Backup personal wallet"
|
||||
: "Backup wallet"}
|
||||
? l.connect_wallet_details.backup_personal_wallet
|
||||
: l.connect_wallet_details.backup_wallet}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
@@ -108,9 +111,7 @@ export const SmartWalletAdditionalActions = ({
|
||||
/>
|
||||
</BaseButton>
|
||||
<Text variant="error" textAlign="left" mb="sm">
|
||||
{
|
||||
"This is a temporary guest wallet. Download a backup if you don't want to loose access to it."
|
||||
}
|
||||
{l.local_wallet.this_is_a_temporary_wallet}
|
||||
</Text>
|
||||
</>
|
||||
) : null}
|
||||
@@ -141,8 +142,6 @@ const styles = StyleSheet.create({
|
||||
alignContent: "center",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
borderRadius: 12,
|
||||
borderWidth: 0.5,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 12,
|
||||
minWidth: 200,
|
||||
|
||||
+11
-3
@@ -1,7 +1,6 @@
|
||||
import { AddressDisplay } from "../base/AddressDisplay";
|
||||
import BaseButton from "../base/BaseButton";
|
||||
import Text from "../base/Text";
|
||||
import { WalletIcon } from "../base/WalletIcon";
|
||||
import { useENS, useWallet } from "@thirdweb-dev/react-core";
|
||||
import { StyleSheet } from "react-native";
|
||||
import { LocalWallet, walletIds } from "@thirdweb-dev/wallets";
|
||||
@@ -11,6 +10,8 @@ import { useMemo, useState } from "react";
|
||||
import { TextBalance } from "../base/TextBalance";
|
||||
import { SupportedTokens } from "../SendFunds/defaultTokens";
|
||||
import { SMART_WALLET_ICON } from "../../assets/svgs";
|
||||
import { ImageSvgUri } from "../base";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
export type ConnectWalletDetailsProps = {
|
||||
address?: string;
|
||||
@@ -45,6 +46,7 @@ export const WalletDetailsButton = ({
|
||||
supportedTokens,
|
||||
displayBalanceToken,
|
||||
}: ConnectWalletDetailsProps) => {
|
||||
const l = useLocale();
|
||||
const activeWallet = useWallet();
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const ensQuery = useENS();
|
||||
@@ -90,11 +92,17 @@ export const WalletDetailsButton = ({
|
||||
alignContent="center"
|
||||
justifyContent="flex-start"
|
||||
>
|
||||
<WalletIcon size={32} iconUri={avatarUrl || walletIconUrl} />
|
||||
<Box borderRadius="lg" overflow="hidden">
|
||||
<ImageSvgUri
|
||||
width={32}
|
||||
height={32}
|
||||
imageUrl={avatarUrl || walletIconUrl}
|
||||
/>
|
||||
</Box>
|
||||
<Box ml="md" justifyContent="center" alignItems="flex-start">
|
||||
{activeWallet?.walletId === LocalWallet.id ? (
|
||||
<Text variant="bodySmall" color="red">
|
||||
Guest
|
||||
{l.connect_wallet_details.guest}
|
||||
</Text>
|
||||
) : ens ? (
|
||||
<Text variant="bodySmall">{ens}</Text>
|
||||
|
||||
+22
-24
@@ -9,7 +9,10 @@ import { ChooseWalletContent } from "./ChooseWalletContent";
|
||||
import { BaseButton, ImageSvgUri, WalletButton } from "../../base";
|
||||
import { ActivityIndicator, Linking } from "react-native";
|
||||
import { useTheme } from "@shopify/restyle";
|
||||
import { useGlobalTheme } from "../../../providers/ui-context-provider";
|
||||
import {
|
||||
useGlobalTheme,
|
||||
useLocale,
|
||||
} from "../../../providers/ui-context-provider";
|
||||
|
||||
export type ChooseWalletProps = {
|
||||
headerText?: ReactNode | string;
|
||||
@@ -34,6 +37,7 @@ export function ChooseWallet({
|
||||
termsOfServiceUrl,
|
||||
privacyPolicyUrl,
|
||||
}: ChooseWalletProps) {
|
||||
const l = useLocale();
|
||||
const theme = useGlobalTheme();
|
||||
const themeLightDark = useTheme();
|
||||
const [isConnecting, setIsConnecting] = useState(false);
|
||||
@@ -122,14 +126,8 @@ export function ChooseWallet({
|
||||
color={theme.colors.backgroundInverted}
|
||||
/>
|
||||
)}
|
||||
<Text
|
||||
variant="header"
|
||||
ml="xxs"
|
||||
fontWeight="700"
|
||||
fontSize={20}
|
||||
lineHeight={24}
|
||||
>
|
||||
Connect
|
||||
<Text variant="headerBold" ml="xxs" fontSize={20} lineHeight={24}>
|
||||
{l.connect_wallet_details.connect}
|
||||
</Text>
|
||||
</Box>
|
||||
)
|
||||
@@ -159,9 +157,11 @@ export function ChooseWallet({
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
>
|
||||
<Text variant="bodySmall">New to wallets?</Text>
|
||||
<Text variant="bodySmall">
|
||||
{l.connect_wallet_details.new_to_wallets}
|
||||
</Text>
|
||||
<BaseButton onPress={onGetStartedPress}>
|
||||
<Text variant="link">Get started</Text>
|
||||
<Text variant="link">{l.connect_wallet_details.get_started}</Text>
|
||||
</BaseButton>
|
||||
</Box>
|
||||
</>
|
||||
@@ -180,7 +180,6 @@ export function ChooseWallet({
|
||||
!isConnectAWalletEnabled &&
|
||||
(guestWallet || connectionWallets.length > 0) ? (
|
||||
<Box
|
||||
mb="md"
|
||||
mt="md"
|
||||
marginHorizontal="xl"
|
||||
flexDirection="row"
|
||||
@@ -189,7 +188,7 @@ export function ChooseWallet({
|
||||
>
|
||||
<Box height={1} flex={1} backgroundColor="border" />
|
||||
<Text variant="subHeader" textAlign="center" marginHorizontal="xxs">
|
||||
OR
|
||||
{l.common.or}
|
||||
</Text>
|
||||
<Box height={1} flex={1} backgroundColor="border" />
|
||||
</Box>
|
||||
@@ -202,7 +201,7 @@ export function ChooseWallet({
|
||||
marginHorizontal="xl"
|
||||
paddingHorizontal="none"
|
||||
paddingVertical="none"
|
||||
mb="md"
|
||||
mt="md"
|
||||
walletIconUrl={connectionWallets[0].meta.iconURL}
|
||||
name={connectionWallets[0].meta.name}
|
||||
onPress={onSingleWalletPress}
|
||||
@@ -212,6 +211,7 @@ export function ChooseWallet({
|
||||
marginHorizontal="xl"
|
||||
justifyContent="center"
|
||||
borderRadius="lg"
|
||||
mt="md"
|
||||
paddingVertical="md"
|
||||
borderColor="border"
|
||||
flexDirection="row"
|
||||
@@ -230,8 +230,8 @@ export function ChooseWallet({
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
<Text variant="bodySmall" fontWeight="700">
|
||||
Connect a wallet
|
||||
<Text variant="bodySmallBold">
|
||||
{l.connect_wallet_details.connect_a_wallet}
|
||||
</Text>
|
||||
</BaseButton>
|
||||
)
|
||||
@@ -253,22 +253,20 @@ export function ChooseWallet({
|
||||
color={theme.colors.textPrimary}
|
||||
/>
|
||||
) : (
|
||||
<Text variant="bodySmall" fontWeight="700">
|
||||
Continue as guest
|
||||
<Text variant="bodySmallBold">
|
||||
{l.connect_wallet_details.continue_as_guest}
|
||||
</Text>
|
||||
)}
|
||||
</BaseButton>
|
||||
) : null}
|
||||
{showToSPrivacyPolicy ? (
|
||||
<Box
|
||||
mt="md"
|
||||
pt="md"
|
||||
height={50}
|
||||
mt="sm"
|
||||
marginHorizontal={!isConnectAWalletEnabled ? "xl" : "none"}
|
||||
alignItems="center"
|
||||
>
|
||||
<Text variant="bodySmallSecondary" fontSize={10} lineHeight={14}>
|
||||
By connecting, you agree to the
|
||||
{l.connect_wallet_details.by_connecting_you_agree}
|
||||
</Text>
|
||||
<Box flexDirection="row" alignItems="center" justifyContent="center">
|
||||
{termsOfServiceUrl ? (
|
||||
@@ -283,7 +281,7 @@ export function ChooseWallet({
|
||||
padding="none"
|
||||
lineHeight={14}
|
||||
>
|
||||
Terms of Service
|
||||
{l.connect_wallet_details.tos}
|
||||
</Text>
|
||||
</BaseButton>
|
||||
) : null}
|
||||
@@ -309,7 +307,7 @@ export function ChooseWallet({
|
||||
padding="none"
|
||||
lineHeight={14}
|
||||
>
|
||||
Privacy Policy
|
||||
{l.connect_wallet_details.privacy_policy}
|
||||
</Text>
|
||||
</BaseButton>
|
||||
) : null}
|
||||
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
import { useMemo } from "react";
|
||||
import type { WalletConfig } from "@thirdweb-dev/react-core";
|
||||
import { FlatList, Dimensions } from "react-native";
|
||||
import Box from "../../base/Box";
|
||||
import { useTheme } from "@shopify/restyle";
|
||||
import { WalletButtonSquare } from "../../base/WalletButtonSquare";
|
||||
import Text from "../../base/Text";
|
||||
|
||||
const SCREEN_WIDTH = Dimensions.get("screen").width;
|
||||
const SCREEN_HEIGHT = Dimensions.get("screen").height;
|
||||
const MAX_HEIGHT = SCREEN_HEIGHT * 0.4;
|
||||
const NUM_COLUMNS = 3;
|
||||
const TILE_SIZE = SCREEN_WIDTH / NUM_COLUMNS;
|
||||
|
||||
interface ChooseWalletContentProps {
|
||||
wallets: WalletConfig[];
|
||||
excludeWalletIds?: string[];
|
||||
onChooseWallet: (wallet: WalletConfig, data?: any) => void;
|
||||
}
|
||||
|
||||
export const ChooseWalletContentSquare = ({
|
||||
wallets,
|
||||
excludeWalletIds,
|
||||
onChooseWallet,
|
||||
}: ChooseWalletContentProps) => {
|
||||
const walletsToDisplay = useMemo(() => {
|
||||
return wallets.filter(
|
||||
(w) => !!!excludeWalletIds?.find((ewId) => ewId === w.id),
|
||||
);
|
||||
}, [wallets, excludeWalletIds]);
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Box marginTop="sm" flexDirection="column">
|
||||
{walletsToDisplay.map((wallet) => {
|
||||
if (!wallet.selectUI) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
key={wallet.id}
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
borderRadius="sm"
|
||||
>
|
||||
<wallet.selectUI
|
||||
modalSize="compact"
|
||||
theme={theme}
|
||||
supportedWallets={wallets}
|
||||
onSelect={(data) => {
|
||||
onChooseWallet(wallet, data);
|
||||
}}
|
||||
walletConfig={wallet}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
<FlatList
|
||||
keyExtractor={(item) => item.meta.name}
|
||||
data={walletsToDisplay}
|
||||
numColumns={NUM_COLUMNS}
|
||||
style={{ maxHeight: MAX_HEIGHT }}
|
||||
fadingEdgeLength={10}
|
||||
showsVerticalScrollIndicator={false}
|
||||
renderItem={({ item }) => {
|
||||
return !item.selectUI ? (
|
||||
<WalletButtonSquare
|
||||
walletIconUrl={item.meta.iconURL}
|
||||
name={item.meta.name}
|
||||
size={TILE_SIZE}
|
||||
onPress={() => onChooseWallet(item)}
|
||||
/>
|
||||
) : null;
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
height={60}
|
||||
borderTopColor="border"
|
||||
borderTopWidth={1}
|
||||
borderBottomColor="border"
|
||||
borderBottomWidth={1}
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
>
|
||||
<Text variant="bodySmall">New to wallets?</Text>
|
||||
<Text variant="link">Get started</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -4,6 +4,7 @@ import { useConnectionStatus, useWallets } from "@thirdweb-dev/react-core";
|
||||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
useGlobalTheme,
|
||||
useLocale,
|
||||
useModalState,
|
||||
} from "../../providers/ui-context-provider";
|
||||
import { ThemeProvider, ThemeProviderProps } from "../../styles/ThemeProvider";
|
||||
@@ -45,6 +46,7 @@ export const ConnectWalletButton = ({
|
||||
buttonTitle,
|
||||
theme,
|
||||
}: ConnectWalletButtonProps) => {
|
||||
const l = useLocale();
|
||||
const appTheme = useGlobalTheme();
|
||||
const connectionStatus = useConnectionStatus();
|
||||
const isWalletConnecting = connectionStatus === "connecting";
|
||||
@@ -95,16 +97,18 @@ export const ConnectWalletButton = ({
|
||||
<ThemeProvider theme={theme ? theme : appTheme}>
|
||||
<BaseButton
|
||||
backgroundColor="buttonBackgroundColor"
|
||||
borderColor="buttonBorderColor"
|
||||
borderWidth={1}
|
||||
onPress={onConnectWalletPress}
|
||||
style={styles.connectWalletButton}
|
||||
>
|
||||
<Text variant="bodyLarge" color="buttonTextColor">
|
||||
<Text variant="bodyLargeBold" color="buttonTextColor">
|
||||
{showButtonSpinner ? (
|
||||
<ActivityIndicator size="small" color="buttonTextColor" />
|
||||
) : buttonTitle ? (
|
||||
buttonTitle
|
||||
) : (
|
||||
"Connect Wallet"
|
||||
l.connect_wallet.label
|
||||
)}
|
||||
</Text>
|
||||
</BaseButton>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { walletIds } from "@thirdweb-dev/wallets";
|
||||
import { useColorScheme } from "react-native";
|
||||
import {
|
||||
useGlobalTheme,
|
||||
useLocale,
|
||||
useModalState,
|
||||
} from "../../providers/ui-context-provider";
|
||||
import {
|
||||
@@ -17,6 +18,7 @@ import Box from "../base/Box";
|
||||
import { ThemeProvider } from "../../styles/ThemeProvider";
|
||||
|
||||
export const ConnectWalletFlow = () => {
|
||||
const l = useLocale();
|
||||
const { modalState, setModalState } = useModalState();
|
||||
const {
|
||||
modalTitle,
|
||||
@@ -25,7 +27,6 @@ export const ConnectWalletFlow = () => {
|
||||
termsOfServiceUrl,
|
||||
walletConfig,
|
||||
} = (modalState as ConnectWalletFlowModal).data;
|
||||
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [activeWallet, setActiveWallet] = useState<WalletConfig | undefined>();
|
||||
const [isConnecting, setIsConnecting] = useState(false);
|
||||
@@ -62,8 +63,8 @@ export const ConnectWalletFlow = () => {
|
||||
|
||||
const onChooseWallet = useCallback(
|
||||
(wallet: WalletConfig, data?: any) => {
|
||||
setActiveWallet(wallet);
|
||||
setSelectionData(data);
|
||||
setActiveWallet(wallet);
|
||||
|
||||
// If the wallet has no custom connect UI, then connect it
|
||||
if (!wallet.connectUI) {
|
||||
@@ -147,7 +148,7 @@ export const ConnectWalletFlow = () => {
|
||||
content={
|
||||
activeWallet.id === walletIds.localWallet ? (
|
||||
<Text variant="bodySmallSecondary" mt="md" textAlign="center">
|
||||
Creating, encrypting and securing your device wallet.
|
||||
{l.connecting_wallet.creating_encrypting}
|
||||
</Text>
|
||||
) : undefined
|
||||
}
|
||||
|
||||
+5
-3
@@ -1,3 +1,4 @@
|
||||
import { useLocale } from "../../../providers/ui-context-provider";
|
||||
import WalletLoadingThumbnail from "../../../wallets/wallets/wallet-connect/WalletLoadingThumbnail";
|
||||
import { Box, ImageSvgUri } from "../../base";
|
||||
import Text from "../../base/Text";
|
||||
@@ -23,6 +24,7 @@ export function ConnectingWallet({
|
||||
onClose,
|
||||
onBackPress,
|
||||
}: ConnectingWalletProps) {
|
||||
const l = useLocale();
|
||||
return (
|
||||
<Box paddingHorizontal="xl">
|
||||
<ConnectWalletHeader
|
||||
@@ -30,7 +32,7 @@ export function ConnectingWallet({
|
||||
subHeaderText={subHeaderText}
|
||||
onClose={onClose}
|
||||
/>
|
||||
<WalletLoadingThumbnail imageSize={100}>
|
||||
<WalletLoadingThumbnail imageSize={85}>
|
||||
<ImageSvgUri height={80} width={80} imageUrl={wallet.meta.iconURL} />
|
||||
</WalletLoadingThumbnail>
|
||||
<View style={styles.connectingContainer}>
|
||||
@@ -39,10 +41,10 @@ export function ConnectingWallet({
|
||||
) : (
|
||||
<>
|
||||
<Text variant="header" mt="lg">
|
||||
Connecting your wallet
|
||||
{l.connecting_wallet.connecting_your_wallet}
|
||||
</Text>
|
||||
<Text variant="bodySmallSecondary" mt="lg" textAlign="center">
|
||||
{`Login and connect your wallet through the ${wallet.meta.name} pop-up`}
|
||||
{l.connecting_wallet.connecting_through_pop_up}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
|
||||
+12
-2
@@ -1,5 +1,8 @@
|
||||
import { Icon } from "../../../assets/icon";
|
||||
import { useGlobalTheme } from "../../../providers/ui-context-provider";
|
||||
import {
|
||||
useGlobalTheme,
|
||||
useLocale,
|
||||
} from "../../../providers/ui-context-provider";
|
||||
import Text from "../../base/Text";
|
||||
import { FlexAlignType, StyleSheet, View } from "react-native";
|
||||
|
||||
@@ -14,13 +17,20 @@ interface ConnectWalletHeaderProps {
|
||||
|
||||
export const ConnectWalletHeader = ({
|
||||
headerText,
|
||||
subHeaderText = "Connecting your wallet",
|
||||
subHeaderText,
|
||||
alignHeader = "center",
|
||||
middleContent,
|
||||
onClose,
|
||||
onBackPress,
|
||||
}: ConnectWalletHeaderProps) => {
|
||||
const l = useLocale();
|
||||
const theme = useGlobalTheme();
|
||||
|
||||
subHeaderText =
|
||||
subHeaderText !== undefined
|
||||
? subHeaderText
|
||||
: l.connecting_wallet.connecting_your_wallet;
|
||||
|
||||
return (
|
||||
<>
|
||||
<View style={styles.header}>
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
import { LocalWalletImportModal } from "./LocalWalletImportModal";
|
||||
import { LocalWallet } from "../../wallets/wallets/LocalWallet";
|
||||
import Box from "../base/Box";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
type LocalWalletFlowUIProps = ConnectUIProps<LocalWallet> & {
|
||||
onConnected?: (wallet: WalletInstance) => void;
|
||||
@@ -24,6 +25,7 @@ export function LocalWalletFlow({
|
||||
walletConfig,
|
||||
onConnected,
|
||||
}: LocalWalletFlowUIProps) {
|
||||
const l = useLocale();
|
||||
const [isImportModalVisible, setIsImportModalVisible] = useState(false);
|
||||
const [isCreatingWallet, setIsCreatingWallet] = useState(false);
|
||||
const { setConnectedWallet } = useWalletContext();
|
||||
@@ -58,7 +60,7 @@ export function LocalWalletFlow({
|
||||
<>
|
||||
<ConnectWalletHeader
|
||||
onBackPress={goBack}
|
||||
headerText="Guest Wallet"
|
||||
headerText={l.local_wallet.guest_wallet}
|
||||
alignHeader="flex-start"
|
||||
subHeaderText={""}
|
||||
onClose={connected}
|
||||
@@ -75,7 +77,7 @@ export function LocalWalletFlow({
|
||||
<ActivityIndicator size="small" color="buttonTextColor" />
|
||||
) : (
|
||||
<Text variant="bodyLarge" color="black">
|
||||
Create new wallet
|
||||
{l.local_wallet.create_new_wallet}
|
||||
</Text>
|
||||
)}
|
||||
</BaseButton>
|
||||
@@ -88,7 +90,7 @@ export function LocalWalletFlow({
|
||||
>
|
||||
<Box height={1} flex={1} backgroundColor="border" />
|
||||
<Text variant="subHeader" textAlign="center">
|
||||
OR
|
||||
{l.common.or}
|
||||
</Text>
|
||||
<Box height={1} flex={1} backgroundColor="border" />
|
||||
</Box>
|
||||
|
||||
+13
-10
@@ -16,7 +16,7 @@ import * as FileSystem from "expo-file-system";
|
||||
import { TWModal } from "../base/modal/TWModal";
|
||||
import { localWallet } from "../../wallets/wallets/local-wallet";
|
||||
import { TextInput } from "../base";
|
||||
import { useGlobalTheme } from "../../providers/ui-context-provider";
|
||||
import { useGlobalTheme, useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
export type LocalWalletImportModalProps = {
|
||||
isVisible: boolean;
|
||||
@@ -29,6 +29,7 @@ export const LocalWalletImportModal = ({
|
||||
onClose,
|
||||
onWalletImported,
|
||||
}: LocalWalletImportModalProps) => {
|
||||
const l = useLocale();
|
||||
const [password, setPassword] = useState<string | undefined>();
|
||||
const [privateKeyOrMnemonic, setPrivateKeyOrMnemonic] = useState<
|
||||
string | undefined
|
||||
@@ -107,7 +108,7 @@ export const LocalWalletImportModal = ({
|
||||
}
|
||||
|
||||
if (!localWalletInstance) {
|
||||
setError("Please, double check your password or private key.");
|
||||
setError(l.local_wallet.double_check_password);
|
||||
setIsImporting(false);
|
||||
return;
|
||||
}
|
||||
@@ -147,7 +148,7 @@ export const LocalWalletImportModal = ({
|
||||
setJsonFile(result.uri);
|
||||
setError(undefined);
|
||||
} else {
|
||||
setError("Error accessing the file. Please try again.");
|
||||
setError(l.local_wallet.error_accessing_file);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -169,9 +170,7 @@ export const LocalWalletImportModal = ({
|
||||
onClose={onCloseInternal}
|
||||
/>
|
||||
<Text variant="subHeader" mt="md" textAlign="center">
|
||||
{
|
||||
"The application can authorize any transactions on behalf of the wallet without any approvals. We recommend only connecting to trusted applications."
|
||||
}
|
||||
{l.local_wallet.application_can_authorize_transactions}
|
||||
</Text>
|
||||
<BaseButton
|
||||
backgroundColor="background"
|
||||
@@ -186,7 +185,7 @@ export const LocalWalletImportModal = ({
|
||||
</Text>
|
||||
</BaseButton>
|
||||
<Text variant="bodySmall" textAlign="left" mt="lg" mb="xxs">
|
||||
Password
|
||||
{l.common.password}
|
||||
</Text>
|
||||
<PasswordInput onChangeText={onChangeText} />
|
||||
<Text variant="bodySmall" color="red" mt="xs" textAlign="left">
|
||||
@@ -200,16 +199,20 @@ export const LocalWalletImportModal = ({
|
||||
>
|
||||
<Box height={1} flex={1} backgroundColor="border" />
|
||||
<Text variant="bodySmall" textAlign="center" marginHorizontal="xxs">
|
||||
Or Private key or Mnemonic
|
||||
{l.local_wallet.private_key_mnemonic}
|
||||
</Text>
|
||||
<Box height={1} flex={1} backgroundColor="border" />
|
||||
</Box>
|
||||
<TextInput
|
||||
textInputProps={{
|
||||
secureTextEntry: true,
|
||||
placeholder: "Private key / Mnemonic",
|
||||
placeholder: l.local_wallet.private_key_mnemonic_placeholder,
|
||||
placeholderTextColor: theme.colors.textSecondary,
|
||||
onChangeText: onPrivateKeyEntered,
|
||||
style: {
|
||||
color: theme.colors.textPrimary,
|
||||
fontFamily: theme.textVariants.defaults.fontFamily,
|
||||
},
|
||||
}}
|
||||
containerProps={{ pl: "xxs" }}
|
||||
/>
|
||||
@@ -228,7 +231,7 @@ export const LocalWalletImportModal = ({
|
||||
<ActivityIndicator size="small" color="buttonTextColor" />
|
||||
) : (
|
||||
<Text variant="bodySmall" color="black">
|
||||
Import
|
||||
{l.common.import}
|
||||
</Text>
|
||||
)}
|
||||
</BaseButton>
|
||||
|
||||
+11
-7
@@ -15,7 +15,10 @@ import WalletLoadingThumbnail from "../../../wallets/wallets/wallet-connect/Wall
|
||||
import ImageSvgUri from "../../base/ImageSvgUri";
|
||||
import Box from "../../base/Box";
|
||||
import { ConnectWalletHeader } from "../ConnectingWallet/ConnectingWalletHeader";
|
||||
import { useGlobalTheme } from "../../../providers/ui-context-provider";
|
||||
import {
|
||||
useGlobalTheme,
|
||||
useLocale,
|
||||
} from "../../../providers/ui-context-provider";
|
||||
|
||||
export const SmartWalletFlow = ({
|
||||
connected,
|
||||
@@ -24,6 +27,7 @@ export const SmartWalletFlow = ({
|
||||
personalWalletConfig,
|
||||
...props
|
||||
}: ConnectUIProps<SmartWallet> & { personalWalletConfig: WalletConfig }) => {
|
||||
const l = useLocale();
|
||||
const theme = useGlobalTheme();
|
||||
const [connectedPersonalWallet, setConnectedPersonalWallet] =
|
||||
useState<WalletInstance>();
|
||||
@@ -131,7 +135,7 @@ export const SmartWalletFlow = ({
|
||||
onBackPress={onConnectingBackPress}
|
||||
onClose={onConnectingClosePress}
|
||||
/>
|
||||
<WalletLoadingThumbnail imageSize={100}>
|
||||
<WalletLoadingThumbnail imageSize={85}>
|
||||
<ImageSvgUri
|
||||
height={80}
|
||||
width={80}
|
||||
@@ -141,13 +145,13 @@ export const SmartWalletFlow = ({
|
||||
<View style={styles.connectingContainer}>
|
||||
<>
|
||||
<Text variant="header" mt="lg" textAlign="center">
|
||||
{mismatch ? "Network Mismatch" : "Connecting..."}
|
||||
{mismatch
|
||||
? l.smart_wallet.network_mistmach
|
||||
: `${l.smart_wallet.connecting} ...`}
|
||||
</Text>
|
||||
{mismatch ? (
|
||||
<Text variant="bodySmallSecondary" mt="lg" textAlign="center">
|
||||
{
|
||||
"There's a network mismatch between your contract and your wallet"
|
||||
}
|
||||
{l.connect_wallet_details.network_mismatch}
|
||||
</Text>
|
||||
) : null}
|
||||
</>
|
||||
@@ -173,7 +177,7 @@ export const SmartWalletFlow = ({
|
||||
<ActivityIndicator size="small" color={theme.colors.textPrimary} />
|
||||
) : (
|
||||
<Text variant="bodyLarge" textAlign="center">
|
||||
Switch Network
|
||||
{l.common.switch_network}
|
||||
</Text>
|
||||
)}
|
||||
</BaseButton>
|
||||
|
||||
+3
-1
@@ -1,15 +1,17 @@
|
||||
import { TextInput } from "react-native";
|
||||
import Text from "../../base/Text";
|
||||
import { useLocale } from "../../../providers/ui-context-provider";
|
||||
|
||||
export const UsernameInput = ({
|
||||
onChangeText,
|
||||
}: {
|
||||
onChangeText: TextInput["props"]["onChangeText"];
|
||||
}) => {
|
||||
const l = useLocale();
|
||||
return (
|
||||
<>
|
||||
<Text variant="bodySmall" textAlign="left" mt="lg" mb="xxs">
|
||||
Username
|
||||
{l.common.username}
|
||||
</Text>
|
||||
<TextInput onChangeText={onChangeText} />
|
||||
</>
|
||||
|
||||
@@ -12,7 +12,7 @@ import { TWModal } from "./base/modal/TWModal";
|
||||
import Box from "./base/Box";
|
||||
// import { useAppTheme } from "../styles/hooks";
|
||||
|
||||
const MODAL_HEIGHT = Dimensions.get("window").height * 0.6;
|
||||
const MODAL_HEIGHT = Dimensions.get("window").height * 0.7;
|
||||
const DEVICE_WIDTH = Dimensions.get("window").width;
|
||||
|
||||
export const MainModal = () => {
|
||||
|
||||
@@ -28,7 +28,11 @@ export const PasswordInput = ({
|
||||
pl="xxs"
|
||||
>
|
||||
<TextInput
|
||||
style={{ ...styles.textInput, color: theme.colors.textPrimary }}
|
||||
style={{
|
||||
...styles.textInput,
|
||||
color: theme.colors.textPrimary,
|
||||
fontFamily: theme.textVariants.defaults.fontFamily,
|
||||
}}
|
||||
secureTextEntry={!showPassword}
|
||||
textContentType="none"
|
||||
returnKeyType={"done"}
|
||||
|
||||
@@ -14,9 +14,10 @@ import {
|
||||
import DownloadIcon from "../assets/download";
|
||||
import CopyIcon from "../assets/copy";
|
||||
import QRCode from "react-native-qrcode-svg";
|
||||
import { useGlobalTheme } from "../providers/ui-context-provider";
|
||||
import { useGlobalTheme, useLocale } from "../providers/ui-context-provider";
|
||||
|
||||
export const ReceiveButton = () => {
|
||||
const l = useLocale();
|
||||
const theme = useGlobalTheme();
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
|
||||
@@ -33,7 +34,7 @@ export const ReceiveButton = () => {
|
||||
<IconTextButton
|
||||
flex={1}
|
||||
ml="xs"
|
||||
text="Receive"
|
||||
text={l.common.receive}
|
||||
justifyContent="center"
|
||||
icon={
|
||||
<DownloadIcon
|
||||
@@ -60,6 +61,7 @@ export const ReceiveFundsModal = ({
|
||||
isVisible,
|
||||
onClose,
|
||||
}: ReceiveFundsModalProps) => {
|
||||
const l = useLocale();
|
||||
const theme = useGlobalTheme();
|
||||
const address = useAddress();
|
||||
const [addressCopied, setAddressCopied] = useState(false);
|
||||
@@ -94,7 +96,7 @@ export const ReceiveFundsModal = ({
|
||||
>
|
||||
<ModalHeaderTextClose
|
||||
onClose={onCloseInternal}
|
||||
headerText="Receive Funds"
|
||||
headerText={l.connect_wallet_details.receive_funds}
|
||||
/>
|
||||
<Text
|
||||
variant="bodySmallSecondary"
|
||||
@@ -102,11 +104,10 @@ export const ReceiveFundsModal = ({
|
||||
mt="md"
|
||||
marginHorizontal="xmd"
|
||||
>
|
||||
Copy the wallet address or scan the QR code to send funds to this
|
||||
wallet.
|
||||
{l.connect_wallet_details.copy_address_or_scan}
|
||||
</Text>
|
||||
<Text mt="lg" variant="bodySmallSecondary">
|
||||
Your address
|
||||
{l.connect_wallet_details.your_address}
|
||||
</Text>
|
||||
<BaseButton
|
||||
mt="xs"
|
||||
@@ -127,7 +128,7 @@ export const ReceiveFundsModal = ({
|
||||
<CopyIcon width={14} height={14} color={theme.colors.iconPrimary} />
|
||||
</BaseButton>
|
||||
<Text mt="lg" variant="bodySmallSecondary">
|
||||
QR Code
|
||||
{l.connect_wallet_details.qr_code}
|
||||
</Text>
|
||||
<Box
|
||||
mt="xs"
|
||||
@@ -144,7 +145,7 @@ export const ReceiveFundsModal = ({
|
||||
</Box>
|
||||
|
||||
{addressCopied === true ? (
|
||||
<Toast text={"Address copied to clipboard"} />
|
||||
<Toast text={l.connect_wallet_details.address_copied_clipboard} />
|
||||
) : null}
|
||||
</Box>
|
||||
</KeyboardAvoidingView>
|
||||
|
||||
@@ -2,11 +2,13 @@ import { useBalance, useChain } from "@thirdweb-dev/react-core";
|
||||
import { TokenInfo } from "./defaultTokens";
|
||||
import { BaseButton, Box, ChainIcon, ImageSvgUri, Text } from "../base";
|
||||
import LoadingTextAnimation from "../base/LoadingTextAnimation";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
export function SelectTokenButton(props: {
|
||||
token?: TokenInfo;
|
||||
onPress: () => void;
|
||||
}) {
|
||||
const l = useLocale();
|
||||
const balanceQuery = useBalance(props.token?.address);
|
||||
const chain = useChain();
|
||||
const tokenName = props.token?.name || balanceQuery.data?.name;
|
||||
@@ -27,7 +29,7 @@ export function SelectTokenButton(props: {
|
||||
<Text variant="bodyLarge">{tokenName}</Text>
|
||||
{!balanceQuery.data ? (
|
||||
<LoadingTextAnimation
|
||||
text="Fetching..."
|
||||
text={l.common.fetching}
|
||||
textVariant={"bodySmallSecondary"}
|
||||
/>
|
||||
) : (
|
||||
|
||||
@@ -29,13 +29,14 @@ import { utils } from "ethers";
|
||||
import LoadingTextAnimation from "../base/LoadingTextAnimation";
|
||||
import CheckIcon from "../../assets/check";
|
||||
import { TokenSelector } from "./TokenSelector";
|
||||
import { useGlobalTheme } from "../../providers/ui-context-provider";
|
||||
import { useGlobalTheme, useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
export const SendButton = ({
|
||||
supportedTokens,
|
||||
}: {
|
||||
supportedTokens: SupportedTokens;
|
||||
}) => {
|
||||
const l = useLocale();
|
||||
const theme = useGlobalTheme();
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
|
||||
@@ -51,7 +52,7 @@ export const SendButton = ({
|
||||
<>
|
||||
<IconTextButton
|
||||
flex={1}
|
||||
text="Send"
|
||||
text={l.common.send}
|
||||
justifyContent="center"
|
||||
icon={
|
||||
<SendIcon height={16} width={16} color={theme.colors.textPrimary} />
|
||||
@@ -139,12 +140,13 @@ const SendFundsForm = ({
|
||||
onTokenSelectorPress: () => void;
|
||||
token?: TokenInfo;
|
||||
}) => {
|
||||
const l = useLocale();
|
||||
const theme = useGlobalTheme();
|
||||
const chain = useChain();
|
||||
const wallet = useWallet();
|
||||
const chainId = useChainId();
|
||||
const [receiverAddress, setReceiverAddress] = useState("");
|
||||
const [amount, setAmount] = useState("");
|
||||
const [amount, setAmount] = useState("0");
|
||||
const [showIcon, setShowIcon] = useState(false);
|
||||
const tokenAddress = token?.address;
|
||||
|
||||
@@ -219,9 +221,12 @@ const SendFundsForm = ({
|
||||
borderRadius="md"
|
||||
p="lg"
|
||||
>
|
||||
<ModalHeaderTextClose onClose={onCloseInternal} headerText="Send Funds" />
|
||||
<ModalHeaderTextClose
|
||||
onClose={onCloseInternal}
|
||||
headerText={l.connect_wallet_details.send_funds}
|
||||
/>
|
||||
<Text mt="lg" variant="bodySmallSecondary">
|
||||
Select Token
|
||||
{l.connect_wallet_details.select_token}
|
||||
</Text>
|
||||
|
||||
<BaseButton
|
||||
@@ -251,7 +256,7 @@ const SendFundsForm = ({
|
||||
<Text variant="bodySmall">{tokenName}</Text>
|
||||
{!balanceQuery.data ? (
|
||||
<LoadingTextAnimation
|
||||
text="Fetching..."
|
||||
text={l.common.fetching}
|
||||
textVariant={"bodySmallSecondary"}
|
||||
/>
|
||||
) : (
|
||||
@@ -265,7 +270,7 @@ const SendFundsForm = ({
|
||||
</BaseButton>
|
||||
|
||||
<Text mt="md" variant="bodySmallSecondary">
|
||||
Send to
|
||||
{l.connect_wallet_details.send_to}
|
||||
</Text>
|
||||
<Box
|
||||
mt="xs"
|
||||
@@ -284,6 +289,7 @@ const SendFundsForm = ({
|
||||
onChangeText={setReceiverAddress}
|
||||
style={{
|
||||
color: theme.colors.textPrimary,
|
||||
fontFamily: theme.textVariants.defaults.fontFamily,
|
||||
textAlign: "left",
|
||||
flex: 1,
|
||||
height: 40,
|
||||
@@ -297,7 +303,7 @@ const SendFundsForm = ({
|
||||
/>
|
||||
</Box>
|
||||
<Text mt="md" variant="bodySmallSecondary">
|
||||
Amount
|
||||
{l.common.amount}
|
||||
</Text>
|
||||
<Box
|
||||
mt="xs"
|
||||
@@ -313,17 +319,17 @@ const SendFundsForm = ({
|
||||
editable={!sendTokenMutation.isLoading}
|
||||
returnKeyType={"done"}
|
||||
keyboardType="numeric"
|
||||
value={amount}
|
||||
clearTextOnFocus={false}
|
||||
style={{
|
||||
color: theme.colors.textPrimary,
|
||||
fontFamily: theme.textVariants.defaults.fontFamily,
|
||||
textAlign: "left",
|
||||
flex: 1,
|
||||
height: 40,
|
||||
paddingHorizontal: 16,
|
||||
}}
|
||||
onChangeText={setAmount}
|
||||
placeholder="0"
|
||||
placeholderTextColor={theme.colors.textPrimary}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
/>
|
||||
@@ -348,12 +354,19 @@ const SendFundsForm = ({
|
||||
}}
|
||||
>
|
||||
{sendTokenMutation.isLoading ? (
|
||||
<ActivityIndicator size="small" color={theme.colors.textPrimary} />
|
||||
<ActivityIndicator
|
||||
size="small"
|
||||
color={theme.colors.accentButtonTextColor}
|
||||
/>
|
||||
) : showIcon ? (
|
||||
<CheckIcon width={20} height={13} color={theme.colors.textPrimary} />
|
||||
<CheckIcon
|
||||
width={20}
|
||||
height={13}
|
||||
color={theme.colors.accentButtonTextColor}
|
||||
/>
|
||||
) : (
|
||||
<Text variant="bodySmall" color="accentButtonTextColor" mr="sm">
|
||||
Send
|
||||
{l.common.send}
|
||||
</Text>
|
||||
)}
|
||||
</BaseButton>
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
import { SelectTokenButton } from "./SelectTokenButton";
|
||||
import CloseIcon from "../../assets/close";
|
||||
import Text from "../base/Text";
|
||||
import { useGlobalTheme } from "../../providers/ui-context-provider";
|
||||
import { useGlobalTheme, useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
export function useToken(tokenAddress: string): {
|
||||
isLoading: boolean;
|
||||
@@ -82,6 +82,7 @@ export function TokenSelector(props: {
|
||||
onBack: () => void;
|
||||
supportedTokens: SupportedTokens;
|
||||
}) {
|
||||
const l = useLocale();
|
||||
const theme = useGlobalTheme();
|
||||
const [input, setInput] = useState("");
|
||||
const chainId = useChainId();
|
||||
@@ -120,7 +121,7 @@ export function TokenSelector(props: {
|
||||
<Box>
|
||||
<ModalHeaderTextClose
|
||||
onBackPress={props.onBack}
|
||||
headerText="Select a Token"
|
||||
headerText={l.connect_wallet_details.select_token}
|
||||
/>
|
||||
|
||||
<Box
|
||||
@@ -140,12 +141,13 @@ export function TokenSelector(props: {
|
||||
onChangeText={setInput}
|
||||
style={{
|
||||
color: theme.colors.textPrimary,
|
||||
fontFamily: theme.textVariants.defaults.fontFamily,
|
||||
textAlign: "left",
|
||||
flex: 1,
|
||||
height: 40,
|
||||
paddingHorizontal: 16,
|
||||
}}
|
||||
placeholder="Search or paste token address"
|
||||
placeholder={l.connect_wallet_details.search_or_paste_token}
|
||||
placeholderTextColor={theme.colors.textSecondary}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
@@ -197,8 +199,10 @@ export function TokenSelector(props: {
|
||||
minHeight={150}
|
||||
paddingTop="none"
|
||||
>
|
||||
<CloseIcon width={16} height={16} />
|
||||
<Text variant="bodySmall">No Tokens found</Text>
|
||||
<CloseIcon width={16} height={16} color={theme.colors.border} />
|
||||
<Text variant="bodySmall">
|
||||
{l.connect_wallet_details.no_tokens_found}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
@@ -35,7 +35,7 @@ const ImageSvgUri = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Box style={{ width: width, height: height }}>
|
||||
<Box width={width} height={height}>
|
||||
{error ? (
|
||||
<SvgUri width={width} height={height} uri={resolvedImageUrl} />
|
||||
) : (
|
||||
|
||||
@@ -15,7 +15,7 @@ import Box from "./Box";
|
||||
import { ModalHeaderTextClose } from "./modal/ModalHeaderTextClose";
|
||||
import { TWModal } from "./modal/TWModal";
|
||||
import { Chain } from "@thirdweb-dev/chains";
|
||||
import { useGlobalTheme } from "../../providers/ui-context-provider";
|
||||
import { useGlobalTheme, useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
type NetworkButtonProps = {
|
||||
chain?: Chain;
|
||||
@@ -35,6 +35,7 @@ export const NetworkButton = ({
|
||||
padding,
|
||||
...props
|
||||
}: NetworkButtonProps) => {
|
||||
const l = useLocale();
|
||||
const theme = useGlobalTheme();
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const [switchError, setSwitchError] = useState<string | undefined>();
|
||||
@@ -72,6 +73,7 @@ export const NetworkButton = ({
|
||||
<>
|
||||
<BaseButton
|
||||
p={padding || "sm"}
|
||||
paddingVertical="xs"
|
||||
borderRadius="md"
|
||||
borderWidth={0.5}
|
||||
flexDirection="row"
|
||||
@@ -82,14 +84,11 @@ export const NetworkButton = ({
|
||||
{...props}
|
||||
>
|
||||
<Box flexDirection="row" alignItems="center">
|
||||
<ChainIcon chainIconUrl={chain?.icon?.url} size={32} />
|
||||
<Box
|
||||
ml="md"
|
||||
alignItems="flex-start"
|
||||
justifyContent="center"
|
||||
height={36}
|
||||
>
|
||||
<Text variant="bodyLarge">{chain?.name || "Unknown Network"}</Text>
|
||||
<ChainIcon chainIconUrl={chain?.icon?.url} size={28} />
|
||||
<Box ml="md" alignItems="flex-start" justifyContent="center">
|
||||
<Text variant="bodyLarge">
|
||||
{chain?.name || l.common.unknown_network}
|
||||
</Text>
|
||||
{isSwitching ? (
|
||||
<Box flexDirection="row" alignItems="center">
|
||||
<Text
|
||||
@@ -98,12 +97,12 @@ export const NetworkButton = ({
|
||||
mr="xxs"
|
||||
fontSize={10}
|
||||
>
|
||||
Confirm in your wallet
|
||||
{l.connect_wallet_details.confirm_in_wallet}
|
||||
</Text>
|
||||
<ActivityIndicator size={10} color={theme.colors.linkPrimary} />
|
||||
</Box>
|
||||
) : switchError ? (
|
||||
<Text variant="error">Error switching network</Text>
|
||||
<Text variant="error">{l.common.error_switching_network}</Text>
|
||||
) : null}
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -133,6 +132,7 @@ export const SwitchChainModal = ({
|
||||
isVisible,
|
||||
onClose,
|
||||
}: SwitchChainModalProps) => {
|
||||
const l = useLocale();
|
||||
const supportedChains = useSupportedChains();
|
||||
|
||||
const onCloseInternal = () => {
|
||||
@@ -151,11 +151,11 @@ export const SwitchChainModal = ({
|
||||
>
|
||||
<Box flexDirection="row" justifyContent="space-between" mb="sm">
|
||||
<Text variant="bodyLarge" textAlign="left">
|
||||
Select Network
|
||||
{l.connect_wallet_details.select_network}
|
||||
</Text>
|
||||
<ModalHeaderTextClose flex={1} onClose={onCloseInternal} />
|
||||
</Box>
|
||||
<ScrollView>
|
||||
<ScrollView contentContainerStyle={{ paddingBottom: 10 }}>
|
||||
{supportedChains?.length > 0 ? (
|
||||
supportedChains.map((chain) => {
|
||||
return (
|
||||
@@ -171,7 +171,9 @@ export const SwitchChainModal = ({
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<Text variant="error">No supported chains detected</Text>
|
||||
<Text variant="error">
|
||||
{l.connect_wallet_details.no_supported_chains_detected}
|
||||
</Text>
|
||||
)}
|
||||
</ScrollView>
|
||||
</Box>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user