Compare commits

...
Author SHA1 Message Date
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
182a4e7e8f Version Packages (#1528)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-25 09:03:36 -07:00
iketwandGitHub 8b82f3c59c [CLI] Adds support for PWA Vite template (#1538) 2023-08-25 15:38:21 +00:00
YashandGitHub f59b729f8b [SDK] Fix auto-factory deployment: correct bytecode format (#1537) 2023-08-25 14:19:39 +00:00
iketwandGitHub 387dddbd87 [RN] Adds switchToActiveChain to the ConnectWallet button (#1536) 2023-08-25 13:10:17 +00:00
YashandGitHub 911e14fcac [Chains] Add Chiliz Spicy testnet (#1530) 2023-08-24 18:35:05 +00:00
cd6b07b591 feat(sdk): centralize contract reads (#1520)
Co-authored-by: Joaquim Verges <[email protected]>
2023-08-24 04:29:26 +00:00
YashandGitHub 154c55add5 Contracts version 3.9.3-0 (#1527) 2023-08-24 03:33:49 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
f202f597ca Version Packages (#1517)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-23 20:25:07 -07:00
YashandGitHub 91f0245be7 [SDK] Fix getChainProvider (#1526) 2023-08-24 00:00:03 +00:00
Joaquim VergesandGitHub ae74b8ef62 [SDK] separate ERC1155Supply extension from ERC1155 (#1523) 2023-08-23 22:23:17 +00:00
YashandGitHub 5a373a7509 [SDK] Correct polygon rpc for fetching published contract (#1525) 2023-08-23 19:22:16 +00:00
Manan TankandGitHub 088547f763 [react] various ConnectWallet improvements (#1522) 2023-08-23 17:48:04 +00:00
586e91dbe6 [SDK] Publish dynamic contract (#1488)
Co-authored-by: Nacho Iacovino <[email protected]>
2023-08-23 14:27:40 +00:00
Joaquim VergesandGitHub f65578d637 [SDK] Optimize contract resolution + Fallback to bytecode extension detection for un-imported contracts (#1498) 2023-08-23 00:03:52 +00:00
447d984653 [SDK] Airdrops (#1288)
Co-authored-by: Atharva Deosthale <[email protected]>
2023-08-22 13:26:31 +00:00
nkrishangandGitHub 34a3bb8ae3 [SDK][REACT] Update contracts release (#1518) 2023-08-22 04:31:36 +00:00
Joaquim VergesandGitHub bc003c2fef [SDK] Return early for claim checks when possible (#1516) 2023-08-22 00:01:06 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
c88fa57591 Version Packages (#1509)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-21 12:17:36 -07:00
Jonas DanielsandGitHub c12f0874b4 feat(chains): add new chains (#1513) 2023-08-21 18:20:53 +00:00
Jonas DanielsandGitHub 184c325ab2 fix(chains): Update icon URL for chains 37 and 47 (#1508) 2023-08-19 02:19:31 +00:00
046c9ad604 moved res.json() to avoid getting JSON error in console (#1501)
Co-authored-by: Jonas Daniels <[email protected]>
2023-08-19 02:09:58 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
2a7bbf8665 Version Packages (#1507)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-18 18:18:39 -07:00
Jonas DanielsandGitHub f97ddf4c7f [chains] - add xpla chains & update chains (#1506) 2023-08-19 01:01:08 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
66c53360cd Version Packages (#1504)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-18 16:04:05 -07:00
Joaquim VergesandGitHub bd1fcbae32 [SDK] Expose Transaction.populateTransaction() (#1505) 2023-08-18 19:05:05 +00:00
Joaquim VergesandGitHub e196264172 [SDK] Pass custom storage to internal SDK instances (#1503) 2023-08-18 16:21:20 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
c9deda6f4b Version Packages (#1487)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-16 07:44:08 -07:00
b91d3e9901 Small fix for Promise.all() (#1490)
Co-authored-by: Joaquim Verges <[email protected]>
2023-08-15 22:06:07 -07:00
Joaquim VergesandGitHub d248aa2c5a [SDK] Let users pass their own IPFS download timeout and fix gateway fallback logic (#1500) 2023-08-15 19:20:36 -07:00
Mariano FuentesandGitHub 8f3b685ad2 [CLI] Deploy to show public gateway url after upload (#1499) 2023-08-15 22:28:56 +00:00
iketwandGitHub 26349f311d [RN] Improves loading states when disconnecting and loading balances (#1496) 2023-08-14 22:56:26 +00:00
YashandGitHub 2897576513 [SDK] Custom base fee for cronos testnet (#1495) 2023-08-14 22:39:23 +00:00
iketwandGitHub 07fb1b5ffa [RN] Adds support for raw WalletConnect (#1489) 2023-08-13 16:24:11 +00:00
iketwandGitHub 300a3c6f04 [ReactCore] Add better error messages when using hooks outside the <ThirdwebProvider /> (#1486) 2023-08-12 14:21:31 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
26367c04f3 Version Packages (#1483)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-11 16:07:25 -07:00
Joaquim VergesandGitHub 39e2af6f2f [Wallets] correct gas estimation for polygon/mumbai (#1484) 2023-08-11 22:16:29 +00:00
Joaquim VergesandGitHub a5ba9e4fbf [SDK] Separate Account and AccountPermissions extensions (#1480) 2023-08-11 20:31:54 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
c9b0131acd Version Packages (#1478)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-10 15:51:09 -07:00
Joaquim VergesandGitHub 34b315993c [Wallets] use RPCs with no client id when adding to external wallets (#1477) 2023-08-10 22:33:47 +00:00
iketwandGitHub 14d9a71c92 [RN] Deprecates magicWallet in favor of magicLink for consistency (#1479) 2023-08-10 21:22:49 +00:00
YashandGitHub 7f5311222b [SDK] Enable dynamic contract deployment with any evm (#1468) 2023-08-10 19:32:51 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
b4847dd134 Version Packages (#1464)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-09 16:00:33 -07:00
Danny FridayandGitHub cf82c3b58c Improve error logging when authentication fails (#1475) 2023-08-09 21:37:09 +00:00
Adam MajmudarandGitHub a17326634e [Chains] Add back scroll-alpha-testnet (#1474) 2023-08-09 19:24:04 +00:00
70c4a119d6 Add sdk information in headers for various services (#1472)
Co-authored-by: Manan Tank <[email protected]>
2023-08-09 19:22:46 +00:00
Joaquim VergesandGitHub f0443bd989 [SDK] Expose erc721.claimConditions.getSupplyClaimedByWallet() (#1471) 2023-08-09 19:05:11 +00:00
Jonas DanielsandGitHub 73462ef108 [multi] only evaluate auth token if it is a valid string (#1473) 2023-08-09 18:07:26 +00:00
Jonas DanielsandGitHub 27c225a512 feat(urls): add clientId parameter to getGatewayUrlForCid (#1470) 2023-08-09 03:20:53 +00:00
Jonas DanielsandGitHub cb1c9937fa refactor(urls): Simplify authentication strategy handling (#1469) 2023-08-08 21:07:27 +00:00
Kien NgoandGitHub 588b210601 [react, react-native]Add option to hide the "Request Testnet Funds" button (#1458) 2023-08-08 08:38:37 -07:00
Phillip HoandGitHub 7e483ec97f [service-utils] Silence publishUsageEvents() output (#1466) 2023-08-08 00:20:09 +00:00
Joaquim VergesandGitHub c902901cff [All] Added PR template (#1465) 2023-08-07 23:57:31 +00:00
Phillip HoandGitHub 205018f6e1 [service-utils] Add userOpHash field (#1463) 2023-08-07 23:41:43 +00:00
FirekeeperandGitHub 269e68c0a1 Firekeeper/xai and large chainids (#1461) 2023-08-07 23:14:23 +00:00
Jonas DanielsandGitHub 2888efc065 build: Add TW_SECRET_KEY to test and e2e environments (#1462) 2023-08-07 21:14:00 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
c753641570 Version Packages (#1457)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-07 13:21:25 -07:00
Manan TankandGitHub 4b0e63dcc0 [wallets] Save oAuthRedirectResult when auto connecting Magic Link with social login (#1460) 2023-08-07 16:48:02 +00:00
6979810de5 Fix typo in auth error message (#1454)
Co-authored-by: Jonas Daniels <[email protected]>
2023-08-06 04:10:05 +00:00
Jonas DanielsandGitHub 4c37af49aa feat: allow overriding the upload server url for IpfsUploader (#1455) 2023-08-05 21:12:33 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
7858632429 Version Packages (#1451)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-04 18:15:57 -07:00
Phillip HoandGitHub 0647f12498 [service-utils] Remove optional fields in logging (#1453) 2023-08-05 00:24:56 +00:00
3e1c4045e7 chore: Add logHttpRequest helper func (#1448)
Co-authored-by: Danny Friday <[email protected]>
2023-08-04 23:18:54 +00:00
iketwandGitHub 3ba8ba4288 [RN] Upgrade coinbase wallet sdk (#1452) 2023-08-04 22:28:37 +00:00
Adam MajmudarandGitHub dfd120a3a9 [Auth] Split into functions & expose all auth functions on client (#1392) 2023-08-04 22:09:11 +00:00
Joaquim VergesandGitHub 262edc6a46 [SDK] Sanitize shared metadata descriptions strings (#1450) 2023-08-04 19:35:03 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
4f79053ec3 Version Packages (#1446)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-04 10:41:06 -07:00
Joaquim VergesandGitHub 2a91113a76 [SDK] Revert sanitizing inputs (#1449) 2023-08-04 10:31:04 -07:00
Danny FridayandGitHub b103872daf Export extractAuthorizationData for CF Workers (#1447) 2023-08-03 23:54:08 +00:00
Mariano FuentesandGitHub 7f54012ec6 CLI warnings (#1442) 2023-08-03 22:48:25 +00:00
298 changed files with 9319 additions and 2407 deletions
+13
View File
@@ -0,0 +1,13 @@
## Problem solved
Short description of the bug fixed or feature added
## Changes made
- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes
## How to test
- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test
+1
View File
@@ -17,6 +17,7 @@ concurrency:
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TW_SECRET_KEY: ${{ secrets.TW_SECRET_KEY }}
jobs:
build:
+1 -1
View File
@@ -31,7 +31,7 @@
"hotlink-revert": "node ./scripts/hotlink/hotlink-revert.mjs",
"explain:major": "node ./scripts/changeset-explain-major.mjs"
},
"packageManager": "pnpm@8.1.0",
"packageManager": "pnpm@8.6.12",
"dependencies": {
"@changesets/changelog-github": "^0.4.8",
"@changesets/cli": "^2.26.2",
+86
View File
@@ -1,5 +1,91 @@
# @thirdweb-dev/auth
## 3.2.37
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.20
## 3.2.36
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.19
## 3.2.35
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.18
## 3.2.34
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.17
## 3.2.33
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.16
## 3.2.32
### Patch Changes
- Updated dependencies [[`07fb1b5f`](https://github.com/thirdweb-dev/js/commit/07fb1b5ffa4c170e252df31070852ddb9a81dec9)]:
- @thirdweb-dev/wallets@1.1.15
## 3.2.31
### Patch Changes
- Updated dependencies [[`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74)]:
- @thirdweb-dev/wallets@1.1.14
## 3.2.30
### Patch Changes
- Updated dependencies [[`34b31599`](https://github.com/thirdweb-dev/js/commit/34b315993c0abaccb9640a5d5804c2c93af569c2)]:
- @thirdweb-dev/wallets@1.1.13
## 3.2.29
### Patch Changes
- Updated dependencies [[`73462ef1`](https://github.com/thirdweb-dev/js/commit/73462ef10800aeeb5976634e2bc6fb5d3e8501e4), [`70c4a119`](https://github.com/thirdweb-dev/js/commit/70c4a119d691a37ec999d9f6087902d532cc82ed)]:
- @thirdweb-dev/wallets@1.1.12
## 3.2.28
### Patch Changes
- Updated dependencies [[`4b0e63dc`](https://github.com/thirdweb-dev/js/commit/4b0e63dcc0ca871ce9cef76f8a41ff290316741c)]:
- @thirdweb-dev/wallets@1.1.11
## 3.2.27
### Patch Changes
- [#1392](https://github.com/thirdweb-dev/js/pull/1392) [`dfd120a3`](https://github.com/thirdweb-dev/js/commit/dfd120a3a9d1582c8b174265c92bf43dbbaf5c86) Thanks [@adam-maj](https://github.com/adam-maj)! - Expose functions from auth and update useAuth
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.10
## 3.2.26
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.9
## 3.2.25
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "3.2.25",
"version": "3.2.37",
"main": "dist/thirdweb-dev-auth.cjs.js",
"module": "dist/thirdweb-dev-auth.esm.js",
"browser": {
+73 -423
View File
@@ -1,28 +1,28 @@
import {
THIRDWEB_AUTH_DEFAULT_LOGIN_PAYLOAD_DURATION_IN_SECONDS,
THIRDWEB_AUTH_DEFAULT_TOKEN_DURATION_IN_SECONDS,
} from "../constants";
authenticateJWT,
generateJWT,
parseJWT,
refreshJWT,
} from "./functions/jwt";
import {
LoginOptions,
LoginPayload,
GenerateOptions,
LoginPayloadData,
LoginPayloadDataSchema,
AuthenticationPayloadDataSchema,
AuthenticationPayloadData,
VerifyOptionsSchema,
VerifyOptions,
GenerateOptionsSchema,
AuthenticateOptionsSchema,
AuthenticateOptions,
User,
Json,
LoginOptionsSchema,
AuthenticationPayload,
AuthenticationPayloadDataInput,
} from "./schema";
import { isBrowser } from "./utils";
buildAndSignLoginPayload,
buildLoginPayload,
signLoginPayload,
verifyLoginPayload,
} from "./functions/login";
import type { GenericAuthWallet } from "@thirdweb-dev/wallets";
import { Json, User } from "./schema/common";
import {
LoginOptionsWithOptionalDomain,
LoginPayload,
LoginPayloadData,
} from "./schema/login";
import { VerifyOptionsWithOptionalDomain } from "./schema/verify";
import { GenerateOptionsWithOptionalDomain } from "./schema/generate";
import {
AuthenticateOptionsWithOptionalDomain,
AuthenticationPayload,
} from "./schema/authenticate";
export class ThirdwebAuth {
private domain: string;
@@ -37,432 +37,82 @@ export class ThirdwebAuth {
this.wallet = wallet;
}
public async payload(options?: LoginOptions): Promise<LoginPayloadData> {
const parsedOptions = LoginOptionsSchema.parse(options);
let chainId: string | undefined = parsedOptions?.chainId;
if (!chainId && this.wallet.getChainId) {
try {
chainId = (await this.wallet.getChainId()).toString();
} catch {
// ignore error
}
}
return LoginPayloadDataSchema.parse({
type: this.wallet.type,
domain: parsedOptions?.domain || this.domain,
address: parsedOptions?.address || (await this.wallet.getAddress()),
statement: parsedOptions?.statement,
version: parsedOptions?.version,
uri: parsedOptions?.uri,
chain_id: chainId,
nonce: parsedOptions?.nonce,
expiration_time:
parsedOptions?.expirationTime ||
new Date(
Date.now() +
1000 * THIRDWEB_AUTH_DEFAULT_LOGIN_PAYLOAD_DURATION_IN_SECONDS,
),
invalid_before:
parsedOptions?.invalidBefore ||
new Date(
Date.now() -
1000 * THIRDWEB_AUTH_DEFAULT_LOGIN_PAYLOAD_DURATION_IN_SECONDS,
),
resources: parsedOptions?.resources,
public async payload(
options?: LoginOptionsWithOptionalDomain,
): Promise<LoginPayloadData> {
return buildLoginPayload({
wallet: this.wallet,
options: this.formatOptions(options),
});
}
public async loginWithPayload(
payload: LoginPayloadData,
): Promise<LoginPayload> {
const message = this.generateMessage(payload);
const signature = await this.wallet.signMessage(message);
return {
payload,
signature,
};
return signLoginPayload({ wallet: this.wallet, payload });
}
public async login(options?: LoginOptions): Promise<LoginPayload> {
const payloadData = await this.payload(options);
return await this.loginWithPayload(payloadData);
public async login(
options?: LoginOptionsWithOptionalDomain,
): Promise<LoginPayload> {
return buildAndSignLoginPayload({
wallet: this.wallet,
options: this.formatOptions(options),
});
}
public async verify(
payload: LoginPayload,
options?: VerifyOptions,
options?: VerifyOptionsWithOptionalDomain,
): Promise<string> {
const parsedOptions = VerifyOptionsSchema.parse(options);
if (payload.payload.type !== this.wallet.type) {
throw new Error(
`Expected chain type '${this.wallet.type}' does not match chain type on payload '${payload.payload.type}'`,
);
}
// Check that the intended domain matches the domain of the payload
const domain = parsedOptions?.domain || this.domain;
if (payload.payload.domain !== domain) {
throw new Error(
`Expected domain '${domain}' does not match domain on payload '${payload.payload.domain}'`,
);
}
// Check that the payload statement matches the expected statement
if (parsedOptions?.statement) {
if (payload.payload.statement !== parsedOptions.statement) {
throw new Error(
`Expected statement '${parsedOptions.statement}' does not match statement on payload '${payload.payload.statement}'`,
);
}
}
// Check that the intended URI matches the URI of the payload
if (parsedOptions?.uri) {
if (payload.payload.uri !== parsedOptions.uri) {
throw new Error(
`Expected URI '${parsedOptions.uri}' does not match URI on payload '${payload.payload.uri}'`,
);
}
}
// Check that the intended version matches the version of the payload
if (parsedOptions?.version) {
if (payload.payload.version !== parsedOptions.version) {
throw new Error(
`Expected version '${parsedOptions.version}' does not match version on payload '${payload.payload.version}'`,
);
}
}
// Check that the intended chain ID matches the chain ID of the payload
if (parsedOptions?.chainId) {
if (payload.payload.chain_id !== parsedOptions.chainId) {
throw new Error(
`Expected chain ID '${parsedOptions.chainId}' does not match chain ID on payload '${payload.payload.chain_id}'`,
);
}
}
// Check that the payload nonce is valid
if (parsedOptions?.validateNonce !== undefined) {
try {
await parsedOptions.validateNonce(payload.payload.nonce);
} catch (err) {
throw new Error(`Login request nonce is invalid`);
}
}
// Check that it isn't before the invalid before time
const currentTime = new Date();
if (currentTime < new Date(payload.payload.invalid_before)) {
throw new Error(`Login request is not yet valid`);
}
// Check that the payload hasn't expired
if (currentTime > new Date(payload.payload.expiration_time)) {
throw new Error(`Login request has expired`);
}
// Check that the specified resources are present on the payload
if (parsedOptions?.resources) {
const missingResources = parsedOptions.resources.filter(
(resource) => !payload.payload.resources?.includes(resource),
);
if (missingResources.length > 0) {
throw new Error(
`Login request is missing required resources: ${missingResources.join(
", ",
)}`,
);
}
}
// Check that the signing address is the claimed wallet address
const message = this.generateMessage(payload.payload);
const chainId =
this.wallet.type === "evm" && payload.payload.chain_id
? parseInt(payload.payload.chain_id)
: undefined;
const verified = await this.verifySignature(
message,
payload.signature,
payload.payload.address,
chainId,
);
if (!verified) {
throw new Error(
`Signer address does not match payload address '${payload.payload.address.toLowerCase()}'`,
);
}
return payload.payload.address;
return verifyLoginPayload({
wallet: this.wallet,
payload,
options: this.formatOptions(options),
});
}
public async generate(
payload: LoginPayload,
options?: GenerateOptions,
options?: GenerateOptionsWithOptionalDomain,
): Promise<string> {
if (isBrowser()) {
throw new Error(
"Authentication tokens should not be generated in the browser, as they must be signed by a server-side admin wallet.",
);
}
const parsedOptions = GenerateOptionsSchema.parse(options);
const domain = parsedOptions?.domain || this.domain;
const userAddress = await this.verify(payload, {
domain,
...parsedOptions?.verifyOptions,
});
let session: Json | undefined = undefined;
if (typeof parsedOptions?.session === "function") {
const sessionTrigger = (await parsedOptions.session(userAddress)) as Json;
if (sessionTrigger) {
session = sessionTrigger;
}
} else {
session = parsedOptions?.session;
}
const adminAddress = await this.wallet.getAddress();
return this.createToken({
iss: adminAddress,
sub: userAddress,
aud: domain,
nbf: parsedOptions?.invalidBefore || new Date(),
exp:
parsedOptions?.expirationTime ||
new Date(
Date.now() + 1000 * THIRDWEB_AUTH_DEFAULT_TOKEN_DURATION_IN_SECONDS,
),
iat: new Date(),
jti: parsedOptions?.tokenId,
ctx: session,
});
}
public async refresh(token: string, expirationTime?: Date): Promise<string> {
const { payload } = this.parseToken(token);
return this.createToken({
iss: payload.iss,
sub: payload.sub,
aud: payload.aud,
nbf: new Date(),
exp:
expirationTime ||
new Date(
Date.now() + 1000 * THIRDWEB_AUTH_DEFAULT_TOKEN_DURATION_IN_SECONDS,
),
iat: new Date(),
ctx: payload.ctx,
});
}
/**
* Authenticate With Token
* @remarks Server-side function that authenticates the provided JWT token. This function verifies that
* the provided authentication token is valid and returns the address of the authenticated wallet.
*
* @param domain - The domain of the server-side application doing authentication
* @param token - The authentication token being used
* @returns The address of the authenticated wallet
*
* @example
* ```javascript
* const domain = "example.com";
* const loginPayload = await sdk.auth.login(domain);
* const token = await sdk.auth.generateAuthToken(domain, loginPayload);
*
* // Authenticate the token and get the address of authenticating users wallet
* const address = sdk.auth.authenticate(domain, token);
* ```
*/
public async authenticate<TSession extends Json = Json>(
token: string,
options?: AuthenticateOptions,
): Promise<User<TSession>> {
if (isBrowser()) {
throw new Error(
"Should not authenticate tokens in the browser, as they must be verified by the server-side admin wallet.",
);
}
const parsedOptions = AuthenticateOptionsSchema.parse(options);
const domain = parsedOptions?.domain || this.domain;
const { payload, signature } = this.parseToken(token);
// Check that the payload unique ID is valid
if (parsedOptions?.validateTokenId !== undefined) {
try {
await parsedOptions.validateTokenId(payload.jti);
} catch (err) {
throw new Error(`Token ID is invalid`);
}
}
// Check that the token audience matches the domain
if (payload.aud !== domain) {
throw new Error(
`Expected token to be for the domain '${domain}', but found token with domain '${payload.aud}'`,
);
}
// Check that the token is past the invalid before time
const currentTime = Math.floor(new Date().getTime() / 1000);
if (currentTime < payload.nbf) {
throw new Error(
`This token is invalid before epoch time '${payload.nbf}', current epoch time is '${currentTime}'`,
);
}
// Check that the token hasn't expired
if (currentTime > payload.exp) {
throw new Error(
`This token expired at epoch time '${payload.exp}', current epoch time is '${currentTime}'`,
);
}
// Check that the connected wallet matches the token issuer
const connectedAddress = await this.wallet.getAddress();
if (connectedAddress.toLowerCase() !== payload.iss.toLowerCase()) {
throw new Error(
`Expected the connected wallet address '${connectedAddress}' to match the token issuer address '${payload.iss}'`,
);
}
let chainId: number | undefined = undefined;
if (this.wallet.getChainId) {
try {
chainId = await this.wallet.getChainId();
} catch {
// ignore error
}
}
const verified = await this.verifySignature(
JSON.stringify(payload),
signature,
connectedAddress,
chainId,
);
if (!verified) {
throw new Error(
`The connected wallet address '${connectedAddress}' did not sign the token`,
);
}
return {
address: payload.sub,
session: payload.ctx as TSession | undefined,
};
}
public parseToken(token: string): AuthenticationPayload {
const encodedPayload = token.split(".")[1];
const encodedSignature = token.split(".")[2];
const payload: AuthenticationPayloadData = JSON.parse(
Buffer.from(encodedPayload, "base64").toString(),
);
const signature = Buffer.from(encodedSignature, "base64").toString();
return {
return generateJWT({
wallet: this.wallet,
payload,
signature,
};
options: this.formatOptions(options),
});
}
private async createToken(
payload: AuthenticationPayloadDataInput,
): Promise<string> {
const payloadData = AuthenticationPayloadDataSchema.parse(payload);
const message = JSON.stringify(payloadData);
const signature = await this.wallet.signMessage(message);
// Header used for JWT token specifying hash algorithm
const header = {
// Specify ECDSA with SHA-256 for hashing algorithm
alg: "ES256",
typ: "JWT",
};
const encodedHeader = Buffer.from(JSON.stringify(header)).toString(
"base64",
);
const encodedData = Buffer.from(JSON.stringify(payloadData))
.toString("base64")
.replace(/=/g, "");
const encodedSignature = Buffer.from(signature).toString("base64");
// Generate a JWT token with base64 encoded header, payload, and signature
const token = `${encodedHeader}.${encodedData}.${encodedSignature}`;
return token;
public async refresh(jwt: string, expirationTime?: Date): Promise<string> {
return refreshJWT({
wallet: this.wallet,
jwt,
options: { expirationTime },
});
}
private async verifySignature(
message: string,
signature: string,
address: string,
chainId?: number,
) {
return this.wallet.verifySignature(message, signature, address, chainId);
public async authenticate<TSession extends Json = Json>(
jwt: string,
options?: AuthenticateOptionsWithOptionalDomain,
): Promise<User<TSession>> {
return authenticateJWT({
wallet: this.wallet,
jwt,
options: this.formatOptions(options),
});
}
/**
* Generates a EIP-4361 & CAIP-122 compliant message to sign based on the login payload
*/
private generateMessage(payload: LoginPayloadData): string {
const typeField = payload.type === "evm" ? "Ethereum" : "Solana";
const header = `${payload.domain} wants you to sign in with your ${typeField} account:`;
let prefix = [header, payload.address].join("\n");
prefix = [prefix, payload.statement].join("\n\n");
if (payload.statement) {
prefix += "\n";
}
public parseToken(jwt: string): AuthenticationPayload {
return parseJWT(jwt);
}
const suffixArray = [];
if (payload.uri) {
const uriField = `URI: ${payload.uri}`;
suffixArray.push(uriField);
}
const versionField = `Version: ${payload.version}`;
suffixArray.push(versionField);
if (payload.chain_id) {
const chainField = `Chain ID: ` + payload.chain_id || "1";
suffixArray.push(chainField);
}
const nonceField = `Nonce: ${payload.nonce}`;
suffixArray.push(nonceField);
const issuedAtField = `Issued At: ${payload.issued_at}`;
suffixArray.push(issuedAtField);
const expiryField = `Expiration Time: ${payload.expiration_time}`;
suffixArray.push(expiryField);
if (payload.invalid_before) {
const invalidBeforeField = `Not Before: ${payload.invalid_before}`;
suffixArray.push(invalidBeforeField);
}
if (payload.resources) {
suffixArray.push(
[`Resources:`, ...payload.resources.map((x) => `- ${x}`)].join("\n"),
);
}
const suffix = suffixArray.join("\n");
return [prefix, suffix].join("\n");
private formatOptions<TOptions extends { domain?: string }>(
options?: TOptions,
): Omit<TOptions, "domain"> & { domain: string } {
return options
? { ...options, domain: options?.domain || this.domain }
: ({ domain: this.domain } as Omit<TOptions, "domain"> & {
domain: string;
});
}
}
+226
View File
@@ -0,0 +1,226 @@
import {
AuthenticateOptionsSchema,
AuthenticationPayload,
AuthenticationPayloadData,
AuthenticationPayloadDataSchema,
} from "../schema/authenticate";
import { Json, User } from "../schema/common";
import {
BuildJwtParams,
RefreshJwtParams,
GenerateJwtParams,
AuthenticateJwtParams,
} from "../schema/functions";
import { GenerateOptionsSchema } from "../schema/generate";
import { RefreshOptionsSchema } from "../schema/refresh";
import { verifyLoginPayload } from "./login";
function isBrowser() {
return typeof window !== "undefined";
}
function base64encode(data: string): string {
if (isBrowser()) {
return window.btoa(data);
}
return Buffer.from(data).toString("base64").replace(/=/g, "");
}
function base64decode(data: string): string {
if (isBrowser()) {
return window.atob(data);
}
return Buffer.from(data, "base64").toString();
}
/**
* Build JWT token based on the authentication payload
*/
async function buildJWT({ wallet, payload }: BuildJwtParams): Promise<string> {
const payloadData = AuthenticationPayloadDataSchema.parse(payload);
const message = JSON.stringify(payloadData);
const signature = await wallet.signMessage(message);
// Header used for JWT token specifying hash algorithm
const header = {
// Specify ECDSA with SHA-256 for hashing algorithm
alg: "ES256",
typ: "JWT",
};
const encodedHeader = base64encode(JSON.stringify(header));
const encodedData = base64encode(JSON.stringify(payloadData));
const encodedSignature = base64encode(signature);
// Generate a JWT with base64 encoded header, payload, and signature
const jwt = `${encodedHeader}.${encodedData}.${encodedSignature}`;
return jwt;
}
/**
* Generate a new JWT using a login payload
*/
export async function generateJWT({
wallet,
payload,
options,
}: GenerateJwtParams): Promise<string> {
const parsedOptions = GenerateOptionsSchema.parse(options);
const userAddress = await verifyLoginPayload({
wallet,
payload,
options: {
domain: parsedOptions.domain,
...parsedOptions.verifyOptions,
},
});
let session: Json | undefined = undefined;
if (typeof parsedOptions?.session === "function") {
const sessionTrigger = (await parsedOptions.session(userAddress)) as Json;
if (sessionTrigger) {
session = sessionTrigger;
}
} else {
session = parsedOptions?.session;
}
const adminAddress = await wallet.getAddress();
return buildJWT({
wallet,
payload: {
iss: adminAddress,
sub: userAddress,
aud: parsedOptions.domain,
nbf: parsedOptions?.invalidBefore || new Date(),
exp: parsedOptions.expirationTime,
iat: new Date(),
jti: parsedOptions?.tokenId,
ctx: session,
},
});
}
/**
* Parse data from an encoded auth JWT
*/
export function parseJWT(jwt: string): AuthenticationPayload {
const encodedPayload = jwt.split(".")[1];
const encodedSignature = jwt.split(".")[2];
const payload: AuthenticationPayloadData = JSON.parse(
base64decode(encodedPayload),
);
const signature = base64decode(encodedSignature);
return {
payload,
signature,
};
}
/**
* Refresh an existing JWT
*/
export async function refreshJWT({
wallet,
jwt,
options,
}: RefreshJwtParams): Promise<string> {
const { payload } = parseJWT(jwt);
const parsedOptions = RefreshOptionsSchema.parse(options);
return buildJWT({
wallet,
payload: {
iss: payload.iss,
sub: payload.sub,
aud: payload.aud,
nbf: new Date(),
exp: parsedOptions.expirationTime,
iat: new Date(),
ctx: payload.ctx,
},
});
}
/**
* Validate a JWT and extract the user's info
*/
export async function authenticateJWT<TSession extends Json = Json>({
wallet,
jwt,
options,
}: AuthenticateJwtParams): Promise<User<TSession>> {
const parsedOptions = AuthenticateOptionsSchema.parse(options);
const { payload, signature } = parseJWT(jwt);
// Check that the payload unique ID is valid
if (parsedOptions?.validateTokenId !== undefined) {
try {
await parsedOptions.validateTokenId(payload.jti);
} catch (err) {
throw new Error(`Token ID is invalid`);
}
}
// Check that the token audience matches the domain
if (payload.aud !== parsedOptions.domain) {
throw new Error(
`Expected token to be for the domain '${parsedOptions.domain}', but found token with domain '${payload.aud}'`,
);
}
// Check that the token is past the invalid before time
const currentTime = Math.floor(new Date().getTime() / 1000);
if (currentTime < payload.nbf) {
throw new Error(
`This token is invalid before epoch time '${payload.nbf}', current epoch time is '${currentTime}'`,
);
}
// Check that the token hasn't expired
if (currentTime > payload.exp) {
throw new Error(
`This token expired at epoch time '${payload.exp}', current epoch time is '${currentTime}'`,
);
}
// Check that the connected wallet matches the token issuer
const issuerAddress = parsedOptions.issuerAddress
? parsedOptions.issuerAddress
: await wallet.getAddress();
if (issuerAddress.toLowerCase() !== payload.iss.toLowerCase()) {
throw new Error(
`The expected issuer address '${issuerAddress}' did not match the token issuer address '${payload.iss}'`,
);
}
let chainId: number | undefined = undefined;
if (wallet.getChainId) {
try {
chainId = await wallet.getChainId();
} catch {
// ignore error
}
}
const verified = await wallet.verifySignature(
JSON.stringify(payload),
signature,
issuerAddress,
chainId,
);
if (!verified) {
throw new Error(
`The expected signer address '${issuerAddress}' did not sign the token`,
);
}
return {
address: payload.sub,
session: payload.ctx as TSession | undefined,
};
}
+224
View File
@@ -0,0 +1,224 @@
import {
BuildLoginPayloadParams,
SignLoginPayloadParams,
VerifyLoginPayloadParams,
} from "../schema/functions";
import {
LoginOptionsSchema,
LoginPayload,
LoginPayloadData,
LoginPayloadDataSchema,
} from "../schema/login";
import { VerifyOptionsSchema } from "../schema/verify";
/**
* Create an EIP-4361 & CAIP-122 compliant message to sign based on the login payload
*/
function createLoginMessage(payload: LoginPayloadData): string {
const typeField = payload.type === "evm" ? "Ethereum" : "Solana";
const header = `${payload.domain} wants you to sign in with your ${typeField} account:`;
let prefix = [header, payload.address].join("\n");
prefix = [prefix, payload.statement].join("\n\n");
if (payload.statement) {
prefix += "\n";
}
const suffixArray = [];
if (payload.uri) {
const uriField = `URI: ${payload.uri}`;
suffixArray.push(uriField);
}
const versionField = `Version: ${payload.version}`;
suffixArray.push(versionField);
if (payload.chain_id) {
const chainField = `Chain ID: ` + payload.chain_id || "1";
suffixArray.push(chainField);
}
const nonceField = `Nonce: ${payload.nonce}`;
suffixArray.push(nonceField);
const issuedAtField = `Issued At: ${payload.issued_at}`;
suffixArray.push(issuedAtField);
const expiryField = `Expiration Time: ${payload.expiration_time}`;
suffixArray.push(expiryField);
if (payload.invalid_before) {
const invalidBeforeField = `Not Before: ${payload.invalid_before}`;
suffixArray.push(invalidBeforeField);
}
if (payload.resources) {
suffixArray.push(
[`Resources:`, ...payload.resources.map((x) => `- ${x}`)].join("\n"),
);
}
const suffix = suffixArray.join("\n");
return [prefix, suffix].join("\n");
}
export async function buildLoginPayload({
wallet,
options,
}: BuildLoginPayloadParams): Promise<LoginPayloadData> {
const parsedOptions = LoginOptionsSchema.parse(options);
let chainId: string | undefined = parsedOptions?.chainId;
if (!chainId && wallet.getChainId) {
try {
chainId = (await wallet.getChainId()).toString();
} catch {
// ignore error
}
}
return LoginPayloadDataSchema.parse({
type: wallet.type,
domain: parsedOptions.domain,
address: parsedOptions?.address || (await wallet.getAddress()),
statement: parsedOptions?.statement,
version: parsedOptions?.version,
uri: parsedOptions?.uri,
chain_id: chainId,
nonce: parsedOptions?.nonce,
expiration_time: parsedOptions.expirationTime,
invalid_before: parsedOptions.invalidBefore,
resources: parsedOptions?.resources,
});
}
export async function signLoginPayload({
wallet,
payload,
}: SignLoginPayloadParams): Promise<LoginPayload> {
const message = createLoginMessage(payload);
const signature = await wallet.signMessage(message);
return {
payload,
signature,
};
}
export async function buildAndSignLoginPayload({
wallet,
options,
}: BuildLoginPayloadParams): Promise<LoginPayload> {
const payload = await buildLoginPayload({ wallet, options });
return signLoginPayload({ wallet, payload });
}
export async function verifyLoginPayload({
wallet,
payload,
options,
}: VerifyLoginPayloadParams): Promise<string> {
const parsedOptions = VerifyOptionsSchema.parse(options);
if (payload.payload.type !== wallet.type) {
throw new Error(
`Expected chain type '${wallet.type}' does not match chain type on payload '${payload.payload.type}'`,
);
}
// Check that the intended domain matches the domain of the payload
if (payload.payload.domain !== parsedOptions.domain) {
throw new Error(
`Expected domain '${parsedOptions.domain}' does not match domain on payload '${payload.payload.domain}'`,
);
}
// Check that the payload statement matches the expected statement
if (parsedOptions?.statement) {
if (payload.payload.statement !== parsedOptions.statement) {
throw new Error(
`Expected statement '${parsedOptions.statement}' does not match statement on payload '${payload.payload.statement}'`,
);
}
}
// Check that the intended URI matches the URI of the payload
if (parsedOptions?.uri) {
if (payload.payload.uri !== parsedOptions.uri) {
throw new Error(
`Expected URI '${parsedOptions.uri}' does not match URI on payload '${payload.payload.uri}'`,
);
}
}
// Check that the intended version matches the version of the payload
if (parsedOptions?.version) {
if (payload.payload.version !== parsedOptions.version) {
throw new Error(
`Expected version '${parsedOptions.version}' does not match version on payload '${payload.payload.version}'`,
);
}
}
// Check that the intended chain ID matches the chain ID of the payload
if (parsedOptions?.chainId) {
if (payload.payload.chain_id !== parsedOptions.chainId) {
throw new Error(
`Expected chain ID '${parsedOptions.chainId}' does not match chain ID on payload '${payload.payload.chain_id}'`,
);
}
}
// Check that the payload nonce is valid
if (parsedOptions?.validateNonce !== undefined) {
try {
await parsedOptions.validateNonce(payload.payload.nonce);
} catch (err) {
throw new Error(`Login request nonce is invalid`);
}
}
// Check that it isn't before the invalid before time
const currentTime = new Date();
if (currentTime < new Date(payload.payload.invalid_before)) {
throw new Error(`Login request is not yet valid`);
}
// Check that the payload hasn't expired
if (currentTime > new Date(payload.payload.expiration_time)) {
throw new Error(`Login request has expired`);
}
// Check that the specified resources are present on the payload
if (parsedOptions?.resources) {
const missingResources = parsedOptions.resources.filter(
(resource) => !payload.payload.resources?.includes(resource),
);
if (missingResources.length > 0) {
throw new Error(
`Login request is missing required resources: ${missingResources.join(
", ",
)}`,
);
}
}
// Check that the signing address is the claimed wallet address
const message = createLoginMessage(payload.payload);
const chainId =
wallet.type === "evm" && payload.payload.chain_id
? parseInt(payload.payload.chain_id)
: undefined;
const verified = await wallet.verifySignature(
message,
payload.signature,
payload.payload.address,
chainId,
);
if (!verified) {
throw new Error(
`Signer address does not match payload address '${payload.payload.address.toLowerCase()}'`,
);
}
return payload.payload.address;
}
+24 -1
View File
@@ -1,2 +1,25 @@
// Export thirdweb auth class
export { ThirdwebAuth } from "./auth";
export * from "./schema";
// Export individual auth functions
export {
generateJWT,
parseJWT,
refreshJWT,
authenticateJWT,
} from "./functions/jwt";
export {
buildLoginPayload,
signLoginPayload,
buildAndSignLoginPayload,
verifyLoginPayload,
} from "./functions/login";
// Export schema files individually
export * from "./schema/authenticate";
export * from "./schema/common";
export * from "./schema/functions";
export * from "./schema/generate";
export * from "./schema/login";
export * from "./schema/refresh";
export * from "./schema/verify";
-216
View File
@@ -1,216 +0,0 @@
import { utils, BigNumber } from "ethers";
import { v4 as uuidv4 } from "uuid";
import { z } from "zod";
export const AddressSchema = z.string().refine(
(arg) => utils.isAddress(arg),
(out) => {
return {
message: `${out} is not a valid address`,
};
},
);
export const RawDateSchema = z.date().transform((i) => {
return BigNumber.from(Math.floor(i.getTime() / 1000));
});
export const AccountTypeSchema = z.union([
z.literal("evm"),
z.literal("solana"),
]);
const literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
type Literal = z.infer<typeof literalSchema>;
export type Json = Literal | { [key: string]: Json } | Json[];
const JsonSchema: z.ZodType<Json> = z.lazy(
() => z.union([literalSchema, z.array(JsonSchema), z.record(JsonSchema)]),
{ invalid_type_error: "Provided value was not valid JSON" },
);
/**
* @internal
*/
export const LoginOptionsSchema = z
.object({
domain: z.string().optional(),
address: z.string().optional(),
statement: z.string().optional(),
uri: z.string().optional(),
version: z.string().optional(),
chainId: z.string().optional(),
nonce: z.string().optional(),
expirationTime: z.date().optional(),
invalidBefore: z.date().optional(),
resources: z.array(z.string()).optional(),
})
.optional();
/**
* @internal
*/
export const LoginPayloadDataSchema = z.object({
type: AccountTypeSchema,
domain: z.string(),
address: z.string(),
statement: z
.string()
.default(
"Please ensure that the domain above matches the URL of the current website.",
),
uri: z.string().optional(),
version: z.string().default("1"),
chain_id: z.string().optional(),
nonce: z.string().default(uuidv4()),
issued_at: z
.date()
.default(new Date())
.transform((d) => d.toISOString()),
expiration_time: z.date().transform((d) => d.toISOString()),
invalid_before: z
.date()
.default(new Date())
.transform((d) => d.toISOString()),
resources: z.array(z.string()).optional(),
});
/**
* @internal
*/
export const LoginPayloadSchema = z.object({
payload: LoginPayloadDataSchema,
signature: z.string(),
});
/**
* @internal
*/
const VerifyOptionsSchemaRequired = z.object({
domain: z.string().optional(),
statement: z.string().optional(),
uri: z.string().optional(),
version: z.string().optional(),
chainId: z.string().optional(),
validateNonce: z.function().args(z.string()).optional(),
resources: z.array(z.string()).optional(),
});
/**
* @internal
*/
export const VerifyOptionsSchema = VerifyOptionsSchemaRequired.optional();
/**
* @internal
*/
export const GenerateOptionsSchema = z
.object({
domain: z.string().optional(),
tokenId: z.string().optional(),
expirationTime: z.date().optional(),
invalidBefore: z.date().optional(),
session: z.union([JsonSchema, z.function().args(z.string())]).optional(),
verifyOptions: VerifyOptionsSchemaRequired.omit({
domain: true,
}).optional(),
})
.optional();
/**
* @internal
*/
export const AuthenticationPayloadDataSchema = z.object({
iss: z.string(),
sub: z.string(),
aud: z.string(),
exp: RawDateSchema.transform((b) => b.toNumber()),
nbf: RawDateSchema.transform((b) => b.toNumber()),
iat: RawDateSchema.transform((b) => b.toNumber()),
jti: z.string().default(uuidv4()),
ctx: JsonSchema.optional(),
});
/**
* @internal
*/
export const AuthenticationPayloadSchema = z.object({
payload: AuthenticationPayloadDataSchema,
signature: z.string(),
});
/**
* @internal
*/
export const AuthenticateOptionsSchema = z
.object({
domain: z.string().optional(),
validateTokenId: z.function().args(z.string()).optional(),
})
.optional();
/**
* @public
*/
export type LoginOptions = z.input<typeof LoginOptionsSchema>;
/**
* @public
*/
export type LoginPayloadData = z.output<typeof LoginPayloadDataSchema>;
/**
* @public
*/
export type LoginPayload = z.output<typeof LoginPayloadSchema>;
/**
* @public
*/
export type VerifyOptions = z.input<typeof VerifyOptionsSchema>;
/**
* @public
*/
export type GenerateOptions = z.input<typeof GenerateOptionsSchema>;
/**
* @public
*/
export type AuthenticationPayloadData = z.output<
typeof AuthenticationPayloadDataSchema
>;
/**
* @internal
*/
export type AuthenticationPayloadDataInput = z.input<
typeof AuthenticationPayloadDataSchema
>;
/**
* @public
*/
export type AuthenticationPayload = z.output<
typeof AuthenticationPayloadSchema
>;
/**
* @public
*/
export type AuthenticateOptions = z.output<typeof AuthenticateOptionsSchema>;
/**
* @public
*/
export type User<TContext extends Json = Json> = {
address: string;
session?: TContext;
};
export const LoginPayloadOutputSchema = LoginPayloadSchema.extend({
payload: LoginPayloadDataSchema.extend({
issued_at: z.string(),
expiration_time: z.string(),
invalid_before: z.string(),
}),
});
@@ -0,0 +1,46 @@
import { z } from "zod";
import { v4 as uuidv4 } from "uuid";
import { AddressSchema, JsonSchema, RawDateSchema } from "./common";
export const AuthenticationPayloadDataSchema = z.object({
iss: z.string(),
sub: z.string(),
aud: z.string(),
exp: RawDateSchema,
nbf: RawDateSchema,
iat: RawDateSchema,
jti: z.string().default(uuidv4()),
ctx: JsonSchema.optional(),
});
export const AuthenticationPayloadSchema = z.object({
payload: AuthenticationPayloadDataSchema,
signature: z.string(),
});
export const AuthenticateOptionsSchema = z.object({
domain: z.string(),
issuerAddress: AddressSchema.optional(),
validateTokenId: z.function().args(z.string()).optional(),
});
export type AuthenticationPayloadDataInput = z.input<
typeof AuthenticationPayloadDataSchema
>;
export type AuthenticationPayloadData = z.output<
typeof AuthenticationPayloadDataSchema
>;
export type AuthenticationPayload = z.output<
typeof AuthenticationPayloadSchema
>;
export type AuthenticateOptions = z.output<typeof AuthenticateOptionsSchema>;
export type AuthenticateOptionsWithOptionalDomain = Omit<
AuthenticateOptions,
"domain"
> & {
domain?: string;
};
+34
View File
@@ -0,0 +1,34 @@
import { utils } from "ethers";
import { z } from "zod";
const literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
type Literal = z.infer<typeof literalSchema>;
export type Json = Literal | { [key: string]: Json } | Json[];
export const JsonSchema: z.ZodType<Json> = z.lazy(
() => z.union([literalSchema, z.array(JsonSchema), z.record(JsonSchema)]),
{ invalid_type_error: "Provided value was not valid JSON" },
);
export const AddressSchema = z.string().refine(
(arg) => utils.isAddress(arg),
(out) => {
return {
message: `${out} is not a valid address`,
};
},
);
export const RawDateSchema = z.date().transform((i) => {
return Math.floor(i.getTime() / 1000);
});
export const AccountTypeSchema = z.union([
z.literal("evm"),
z.literal("solana"),
]);
export type User<TContext extends Json = Json> = {
address: string;
session?: TContext;
};
@@ -0,0 +1,48 @@
import { GenericAuthWallet } from "@thirdweb-dev/wallets";
import { LoginOptions, LoginPayload, LoginPayloadData } from "./login";
import { VerifyOptions } from "./verify";
import {
AuthenticateOptions,
AuthenticationPayloadDataInput,
} from "./authenticate";
import { RefreshOptions } from "./refresh";
import { GenerateOptions } from "./generate";
export type BuildLoginPayloadParams = {
wallet: GenericAuthWallet;
options: LoginOptions;
};
export type SignLoginPayloadParams = {
wallet: GenericAuthWallet;
payload: LoginPayloadData;
};
export type VerifyLoginPayloadParams = {
wallet: GenericAuthWallet;
payload: LoginPayload;
options: VerifyOptions;
};
export type BuildJwtParams = {
wallet: GenericAuthWallet;
payload: AuthenticationPayloadDataInput;
};
export type GenerateJwtParams = {
wallet: GenericAuthWallet;
payload: LoginPayload;
options: GenerateOptions;
};
export type RefreshJwtParams = {
wallet: GenericAuthWallet;
jwt: string;
options?: RefreshOptions;
};
export type AuthenticateJwtParams = {
wallet: GenericAuthWallet;
jwt: string;
options: AuthenticateOptions;
};
+31
View File
@@ -0,0 +1,31 @@
import { z } from "zod";
import { VerifyOptionsSchema } from "./verify";
import { JsonSchema } from "./common";
import { THIRDWEB_AUTH_DEFAULT_TOKEN_DURATION_IN_SECONDS } from "../../constants";
export const GenerateOptionsSchema = z.object({
domain: z.string(),
tokenId: z.string().optional(),
expirationTime: z
.date()
.default(
() =>
new Date(
Date.now() + 1000 * THIRDWEB_AUTH_DEFAULT_TOKEN_DURATION_IN_SECONDS,
),
),
invalidBefore: z.date().optional(),
session: z.union([JsonSchema, z.function().args(z.string())]).optional(),
verifyOptions: VerifyOptionsSchema.omit({
domain: true,
}).optional(),
});
export type GenerateOptions = z.input<typeof GenerateOptionsSchema>;
export type GenerateOptionsWithOptionalDomain = Omit<
GenerateOptions,
"domain"
> & {
domain?: string;
};
+81
View File
@@ -0,0 +1,81 @@
import { z } from "zod";
import { v4 as uuidv4 } from "uuid";
import { AccountTypeSchema } from "./common";
import { THIRDWEB_AUTH_DEFAULT_LOGIN_PAYLOAD_DURATION_IN_SECONDS } from "../../constants";
export const LoginOptionsSchema = z.object({
domain: z.string(),
address: z.string().optional(),
statement: z.string().optional(),
uri: z.string().optional(),
version: z.string().optional(),
chainId: z.string().optional(),
nonce: z.string().optional(),
expirationTime: z
.date()
.default(
() =>
new Date(
Date.now() +
1000 * THIRDWEB_AUTH_DEFAULT_LOGIN_PAYLOAD_DURATION_IN_SECONDS,
),
),
invalidBefore: z
.date()
.default(
() =>
new Date(
Date.now() -
1000 * THIRDWEB_AUTH_DEFAULT_LOGIN_PAYLOAD_DURATION_IN_SECONDS,
),
),
resources: z.array(z.string()).optional(),
});
export const LoginPayloadDataSchema = z.object({
type: AccountTypeSchema,
domain: z.string(),
address: z.string(),
statement: z
.string()
.default(
"Please ensure that the domain above matches the URL of the current website.",
),
uri: z.string().optional(),
version: z.string().default("1"),
chain_id: z.string().optional(),
nonce: z.string().default(uuidv4()),
issued_at: z
.date()
.default(new Date())
.transform((d) => d.toISOString()),
expiration_time: z.date().transform((d) => d.toISOString()),
invalid_before: z
.date()
.default(new Date())
.transform((d) => d.toISOString()),
resources: z.array(z.string()).optional(),
});
export const LoginPayloadSchema = z.object({
payload: LoginPayloadDataSchema,
signature: z.string(),
});
export const LoginPayloadOutputSchema = LoginPayloadSchema.extend({
payload: LoginPayloadDataSchema.extend({
issued_at: z.string(),
expiration_time: z.string(),
invalid_before: z.string(),
}),
});
export type LoginOptions = z.input<typeof LoginOptionsSchema>;
export type LoginPayloadData = z.output<typeof LoginPayloadDataSchema>;
export type LoginPayload = z.output<typeof LoginPayloadSchema>;
export type LoginOptionsWithOptionalDomain = Omit<LoginOptions, "domain"> & {
domain?: string;
};
+15
View File
@@ -0,0 +1,15 @@
import { z } from "zod";
import { THIRDWEB_AUTH_DEFAULT_TOKEN_DURATION_IN_SECONDS } from "../../constants";
export const RefreshOptionsSchema = z.object({
expirationTime: z
.date()
.default(
() =>
new Date(
Date.now() + 1000 * THIRDWEB_AUTH_DEFAULT_TOKEN_DURATION_IN_SECONDS,
),
),
});
export type RefreshOptions = z.input<typeof RefreshOptionsSchema>;
+17
View File
@@ -0,0 +1,17 @@
import { z } from "zod";
export const VerifyOptionsSchema = z.object({
domain: z.string(),
statement: z.string().optional(),
uri: z.string().optional(),
version: z.string().optional(),
chainId: z.string().optional(),
validateNonce: z.function().args(z.string()).optional(),
resources: z.array(z.string()).optional(),
});
export type VerifyOptions = z.input<typeof VerifyOptionsSchema>;
export type VerifyOptionsWithOptionalDomain = Omit<VerifyOptions, "domain"> & {
domain?: string;
};
-9
View File
@@ -1,9 +0,0 @@
/**
* @internal
*/
export const isBrowser = () => typeof window !== "undefined";
/**
* @internal
*/
export const isNode = () => !isBrowser();
+1 -1
View File
@@ -1,5 +1,5 @@
import { ThirdwebAuth } from "../../core";
import { Json, LoginPayloadOutputSchema, User } from "../../core/schema";
import { Json, LoginPayloadOutputSchema, User } from "../../core";
import type { GenericAuthWallet } from "@thirdweb-dev/wallets";
import { Request } from "express";
import { z } from "zod";
+1 -2
View File
@@ -1,5 +1,4 @@
import { ThirdwebAuth } from "../../core";
import { Json, LoginPayloadOutputSchema, User } from "../../core/schema";
import { Json, LoginPayloadOutputSchema, ThirdwebAuth, User } from "../../core";
import type { GenericAuthWallet } from "@thirdweb-dev/wallets";
import { GetServerSidePropsContext, NextApiRequest } from "next";
import { NextRequest } from "next/server";
+22 -2
View File
@@ -3,7 +3,7 @@ import { EthersWallet } from "@thirdweb-dev/wallets/evm/wallets/ethers";
import { expect } from "chai";
import { Wallet } from "ethers";
describe("Wallet Authentication", async () => {
describe("Wallet Authentication - EVM", async () => {
let adminWallet: any, signerWallet: any, attackerWallet: any;
let auth: ThirdwebAuth;
@@ -272,7 +272,7 @@ describe("Wallet Authentication", async () => {
expect.fail();
} catch (err: any) {
expect(err.message).to.contain(
`Expected the connected wallet address '${await signerWallet.getAddress()}' to match the token issuer address '${await adminWallet.getAddress()}'`,
`The expected issuer address '${await signerWallet.getAddress()}' did not match the token issuer address '${await adminWallet.getAddress()}'`,
);
}
});
@@ -350,4 +350,24 @@ describe("Wallet Authentication", async () => {
role: "admin",
});
});
it("Should authenticate with issuer address", async () => {
const payload = await auth.login();
auth.updateWallet(adminWallet);
const token = await auth.generate(payload);
auth.updateWallet(attackerWallet);
try {
await auth.authenticate(token);
expect.fail();
} catch (err: any) {
expect(err.message).to.contain("The expected issuer address");
}
const user = await auth.authenticate(token, {
issuerAddress: await adminWallet.getAddress(),
});
expect(user.address).to.equal(await signerWallet.getAddress());
});
});
+2 -2
View File
@@ -3,7 +3,7 @@ import { Keypair } from "@solana/web3.js";
import { KeypairWallet } from "@thirdweb-dev/wallets/solana/wallets/keypair";
import { expect } from "chai";
describe("Wallet Authentication", async () => {
describe("Wallet Authentication - Solana", async () => {
let adminWallet: any, signerWallet: any, attackerWallet: any;
let auth: ThirdwebAuth;
@@ -272,7 +272,7 @@ describe("Wallet Authentication", async () => {
expect.fail();
} catch (err: any) {
expect(err.message).to.contain(
`Expected the connected wallet address '${await signerWallet.getAddress()}' to match the token issuer address '${await adminWallet.getAddress()}'`,
`The expected issuer address '${await signerWallet.getAddress()}' did not match the token issuer address '${await adminWallet.getAddress()}'`,
);
}
});
+50
View File
@@ -1,5 +1,55 @@
# @thirdweb-dev/chains
## 0.1.48
### Patch Changes
- [#1530](https://github.com/thirdweb-dev/js/pull/1530) [`911e14fc`](https://github.com/thirdweb-dev/js/commit/911e14fcac743b07fa1a66440c72d662c08e971c) Thanks [@kumaryash90](https://github.com/kumaryash90)! - Add Chiliz Spicy testnet
## 0.1.47
### Patch Changes
- [#1518](https://github.com/thirdweb-dev/js/pull/1518) [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8) Thanks [@nkrishang](https://github.com/nkrishang)! - Update contracts package
## 0.1.46
### Patch Changes
- [#1508](https://github.com/thirdweb-dev/js/pull/1508) [`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f) Thanks [@jnsdls](https://github.com/jnsdls)! - update xpla chain icons
- [#1513](https://github.com/thirdweb-dev/js/pull/1513) [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34) Thanks [@jnsdls](https://github.com/jnsdls)! - add additonal chains
## 0.1.45
### Patch Changes
- [#1506](https://github.com/thirdweb-dev/js/pull/1506) [`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736) Thanks [@jnsdls](https://github.com/jnsdls)! - add xpla chains & update chains
## 0.1.44
### Patch Changes
- [#1499](https://github.com/thirdweb-dev/js/pull/1499) [`8f3b685a`](https://github.com/thirdweb-dev/js/commit/8f3b685ad2bd73cb4d5d8c8aa25c04ffc10fb7cf) Thanks [@Marfuen](https://github.com/Marfuen)! - Update deploy command from CLI to use show a public gateway url temporarily. Updated chains too.
## 0.1.43
### Patch Changes
- [#1469](https://github.com/thirdweb-dev/js/pull/1469) [`cb1c9937`](https://github.com/thirdweb-dev/js/commit/cb1c9937fadb2d06eb148cf9819f2b3601376308) Thanks [@jnsdls](https://github.com/jnsdls)! - update chains
- [#1474](https://github.com/thirdweb-dev/js/pull/1474) [`a1732663`](https://github.com/thirdweb-dev/js/commit/a17326634e758c3bf42f0cc3869b8792f1e18cc9) Thanks [@adam-maj](https://github.com/adam-maj)! - Add back scroll-alpha-testnet
- [#1458](https://github.com/thirdweb-dev/js/pull/1458) [`588b2106`](https://github.com/thirdweb-dev/js/commit/588b21060139a7c0bf5805e2c629a16792ed2c76) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Update chains
- [#1461](https://github.com/thirdweb-dev/js/pull/1461) [`269e68c0`](https://github.com/thirdweb-dev/js/commit/269e68c0a15e8f78cb5b68c9456ca8094b9e1f30) Thanks [@0xFirekeeper](https://github.com/0xFirekeeper)! - add xai-goerli chain and support BigInteger from Unity
## 0.1.42
### Patch Changes
- [#1450](https://github.com/thirdweb-dev/js/pull/1450) [`262edc6a`](https://github.com/thirdweb-dev/js/commit/262edc6a46792da88f49ff6ef0a756a932a6a0cf) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - update chains
## 0.1.41
### Patch Changes
+1
View File
@@ -18,6 +18,7 @@ export default {
"https://gnosis.api.onfinality.io/public",
"https://gnosis.blockpi.network/v1/rpc/public",
"https://web3endpoints.com/gnosischain-mainnet",
"https://gnosis.oat.farm",
"wss://rpc.gnosischain.com/wss"
],
"faucets": [
+29
View File
@@ -0,0 +1,29 @@
import type { Chain } from "../src/types";
export default {
"name": "Japan Open Chain Testnet",
"chain": "JOCT",
"rpc": [
"https://japan-open-chain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-1.testnet.japanopenchain.org:8545",
"https://rpc-2.testnet.japanopenchain.org:8545"
],
"faucets": [],
"nativeCurrency": {
"name": "Japan Open Chain Testnet Token",
"symbol": "JOCT",
"decimals": 18
},
"infoURL": "https://www.japanopenchain.org/",
"shortName": "joct",
"chainId": 10081,
"networkId": 10081,
"explorers": [
{
"name": "Testnet Block Explorer",
"url": "https://explorer.testnet.japanopenchain.org",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "japan-open-chain-testnet"
} as const satisfies Chain;
+38
View File
@@ -0,0 +1,38 @@
import type { Chain } from "../src/types";
export default {
"name": "MaxxChain Mainnet",
"chain": "MaxxChain",
"rpc": [
"https://maxxchain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.maxxchain.org",
"https://rpc1.maxxchain.org",
"https://rpc2.maxxchain.org"
],
"faucets": [
"https://faucet.maxxchain.org"
],
"nativeCurrency": {
"name": "Power",
"symbol": "PWR",
"decimals": 18
},
"icon": {
"url": "ipfs://QmRhQG9TZrXDdbQeTzBmjg3pqgwaD5TKVZj8k4kaz8AoZx",
"width": 1021,
"height": 1021,
"format": "png"
},
"infoURL": "https://www.maxxchain.org/",
"shortName": "PWR",
"chainId": 10201,
"networkId": 10201,
"explorers": [
{
"name": "MaxxChain Block Explorer",
"url": "https://explorer.maxxchain.org",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "maxxchain"
} as const satisfies Chain;
+42
View File
@@ -0,0 +1,42 @@
import type { Chain } from "../src/types";
export default {
"name": "Arthera Testnet",
"chain": "AA",
"icon": {
"url": "ipfs://QmYQp3e52KjkT4bYdAvB6ACEEpXs2D8DozsDitaADRY2Ak",
"width": 1024,
"height": 998,
"format": "png"
},
"rpc": [
"https://arthera-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-test.arthera.net"
],
"faucets": [
"https://faucet.arthera.net"
],
"nativeCurrency": {
"name": "Arthera",
"symbol": "AA",
"decimals": 18
},
"infoURL": "https://docs.arthera.net",
"shortName": "aa",
"chainId": 10243,
"networkId": 10243,
"explorers": [
{
"name": "blockscout",
"url": "https://explorer-test.arthera.net",
"icon": {
"url": "ipfs://QmYtUimyqHkkFxYdbXXRbUqNg2VLPUg6Uu2C2nmFWowiZM",
"width": 551,
"height": 540,
"format": "png"
},
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "arthera-testnet"
} as const satisfies Chain;
+2 -2
View File
@@ -3,7 +3,7 @@ export default {
"name": "Ultron Testnet",
"chain": "Ultron",
"icon": {
"url": "ipfs://QmS4W4kY7XYBA4f52vuuytXh3YaTcNBXF14V9tEY6SNqhz",
"url": "ipfs://QmPC6odFVyAQrXJQaZJVFpEQfRNbzZ5BjDZ7KBKmXPaYDw",
"width": 512,
"height": 512,
"format": "png"
@@ -27,7 +27,7 @@ export default {
"name": "Ultron Testnet Explorer",
"url": "https://explorer.ultron-dev.io",
"icon": {
"url": "ipfs://QmS4W4kY7XYBA4f52vuuytXh3YaTcNBXF14V9tEY6SNqhz",
"url": "ipfs://QmPC6odFVyAQrXJQaZJVFpEQfRNbzZ5BjDZ7KBKmXPaYDw",
"width": 512,
"height": 512,
"format": "png"
+2 -2
View File
@@ -3,7 +3,7 @@ export default {
"name": "Ultron Mainnet",
"chain": "Ultron",
"icon": {
"url": "ipfs://QmS4W4kY7XYBA4f52vuuytXh3YaTcNBXF14V9tEY6SNqhz",
"url": "ipfs://QmPC6odFVyAQrXJQaZJVFpEQfRNbzZ5BjDZ7KBKmXPaYDw",
"width": 512,
"height": 512,
"format": "png"
@@ -27,7 +27,7 @@ export default {
"name": "Ultron Explorer",
"url": "https://ulxscan.com",
"icon": {
"url": "ipfs://QmS4W4kY7XYBA4f52vuuytXh3YaTcNBXF14V9tEY6SNqhz",
"url": "ipfs://QmPC6odFVyAQrXJQaZJVFpEQfRNbzZ5BjDZ7KBKmXPaYDw",
"width": 512,
"height": 512,
"format": "png"
+44
View File
@@ -0,0 +1,44 @@
import type { Chain } from "../src/types";
export default {
"name": "Swisstronik Testnet",
"chain": "SWTR",
"rpc": [
"https://swisstronik-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://json-rpc.testnet.swisstronik.com"
],
"faucets": [
"https://faucet.testnet.swisstronik.com"
],
"nativeCurrency": {
"name": "Swisstronik",
"symbol": "SWTR",
"decimals": 18
},
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"infoURL": "https://www.swisstronik.com",
"shortName": "swtr",
"chainId": 1291,
"networkId": 1291,
"icon": {
"url": "ipfs://bafybeihuintkoipxalwans23vhxajbwjnozpy34ww7ia7ds7nay3rpylzi",
"width": 256,
"height": 256,
"format": "svg"
},
"explorers": [
{
"name": "Swisstronik Scout",
"url": "https://explorer-evm.testnet.swisstronik.com",
"standard": "none"
}
],
"testnet": true,
"slug": "swisstronik-testnet"
} as const satisfies Chain;
+7 -7
View File
@@ -1,10 +1,10 @@
import type { Chain } from "../src/types";
export default {
"name": "Credit Smartchain Mainnet",
"name": "Credit Smart Chain",
"chain": "CREDIT",
"rpc": [
"https://credit-smartchain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://mainnet-rpc.cscscan.io"
"https://credit-smart-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.creditsmartchain.com"
],
"faucets": [],
"nativeCurrency": {
@@ -23,7 +23,7 @@ export default {
"infoURL": "https://creditsmartchain.com",
"shortName": "Credit",
"chainId": 13308,
"networkId": 1,
"networkId": 13308,
"icon": {
"url": "ipfs://bafkreifbso3gd4wu5wxl27xyurxctmuae2jyuy37guqtzx23nga6ba4ag4",
"width": 1000,
@@ -32,8 +32,8 @@ export default {
},
"explorers": [
{
"name": "CSC Scan",
"url": "https://explorer.cscscan.io",
"name": "Creditscan",
"url": "https://scan.creditsmartchain.com",
"icon": {
"url": "ipfs://bafkreifbso3gd4wu5wxl27xyurxctmuae2jyuy37guqtzx23nga6ba4ag4",
"width": 1000,
@@ -44,5 +44,5 @@ export default {
}
],
"testnet": false,
"slug": "credit-smartchain"
"slug": "credit-smart-chain"
} as const satisfies Chain;
+33
View File
@@ -0,0 +1,33 @@
import type { Chain } from "../src/types";
export default {
"name": "Beam Testnet",
"chain": "BEAM",
"rpc": [
"https://beam-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/beam/testnet/rpc"
],
"features": [
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "Merit Circle",
"symbol": "MC",
"decimals": 18
},
"infoURL": "https://gaming.meritcircle.io",
"shortName": "BEAM",
"chainId": 13337,
"networkId": 13337,
"explorers": [
{
"name": "Beam Explorer",
"url": "https://subnets-test.avax.network/beam",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "beam-testnet"
} as const satisfies Chain;
+24
View File
@@ -0,0 +1,24 @@
import type { Chain } from "../src/types";
export default {
"name": "Humanode Testnet 5 Israfel",
"chain": "Humanode Testnet 5",
"rpc": [
"https://humanode-testnet-5-israfel.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://explorer-rpc-http.testnet5.stages.humanode.io"
],
"faucets": [
"https://t.me/HumanodeTestnet5FaucetBot"
],
"nativeCurrency": {
"name": "eHMND",
"symbol": "eHMND",
"decimals": 18
},
"infoURL": "https://humanode.io",
"shortName": "hmnd-t5",
"chainId": 14853,
"networkId": 14853,
"explorers": [],
"testnet": true,
"slug": "humanode-testnet-5-israfel"
} as const satisfies Chain;
+5 -5
View File
@@ -1,10 +1,10 @@
import type { Chain } from "../src/types";
export default {
"name": "Omni Testnet 1",
"name": "Omni Testnet",
"chain": "Omni",
"rpc": [
"https://omni-testnet-1.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet-1.omni.network"
"https://omni-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet.omni.network"
],
"features": [
{
@@ -24,10 +24,10 @@ export default {
"explorers": [
{
"name": "Omni Explorer",
"url": "https://testnet-1.explorer.omni.network",
"url": "https://testnet.explorer.omni.network",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "omni-testnet-1"
"slug": "omni-testnet"
} as const satisfies Chain;
+2 -2
View File
@@ -11,8 +11,8 @@ export default {
},
"rpc": [
"https://horizen-gobi-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://gobi-testnet.horizenlabs.io/ethv1",
"https://rpc.ankr.com/horizen_testnet_evm"
"https://gobi-rpc.horizenlabs.io/ethv1",
"https://rpc.ankr.com/horizen_gobi_testnet"
],
"features": [
{
+44
View File
@@ -0,0 +1,44 @@
import type { Chain } from "../src/types";
export default {
"name": "Holesky",
"chain": "ETH",
"rpc": [
"https://holesky.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.holesky.ethpandaops.io"
],
"faucets": [
"https://faucet.holesky.ethpandaops.io",
"https://holesky-faucet.pk910.de"
],
"nativeCurrency": {
"name": "Testnet ETH",
"symbol": "ETH",
"decimals": 18
},
"infoURL": "https://holesky.ethpandaops.io",
"shortName": "holesky",
"chainId": 17000,
"networkId": 17000,
"icon": {
"url": "ipfs://QmdwQDr6vmBtXmK2TmknkEuZNoaDqTasFdZdu3DRw8b2wt",
"width": 1000,
"height": 1628,
"format": "png"
},
"status": "incubating",
"explorers": [
{
"name": "Holesky Explorer",
"url": "https://holesky.beaconcha.in",
"icon": {
"url": "ipfs://QmdwQDr6vmBtXmK2TmknkEuZNoaDqTasFdZdu3DRw8b2wt",
"width": 1000,
"height": 1628,
"format": "png"
},
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "holesky"
} as const satisfies Chain;
+6 -6
View File
@@ -3,9 +3,9 @@ export default {
"name": "Lightlink Phoenix Mainnet",
"chain": "Lightlink Phoenix Mainnet",
"icon": {
"url": "ipfs://QmNRUoMgx16hurD3au3ou5A9rmTLYmre8WiGmQEPFmP2Vo",
"width": 600,
"height": 600,
"url": "ipfs://QmXMDj6iAFn2ducQcUU1M87PMMdT2jfyL3Tp3Lz5uUD5Lv",
"width": 200,
"height": 200,
"format": "png"
},
"rpc": [
@@ -33,9 +33,9 @@ export default {
"name": "phoenix",
"url": "https://phoenix.lightlink.io",
"icon": {
"url": "ipfs://QmNRUoMgx16hurD3au3ou5A9rmTLYmre8WiGmQEPFmP2Vo",
"width": 600,
"height": 600,
"url": "ipfs://QmXMDj6iAFn2ducQcUU1M87PMMdT2jfyL3Tp3Lz5uUD5Lv",
"width": 200,
"height": 200,
"format": "png"
},
"standard": "EIP3091"
+6 -6
View File
@@ -3,9 +3,9 @@ export default {
"name": "Lightlink Pegasus Testnet",
"chain": "Lightlink Pegasus Testnet",
"icon": {
"url": "ipfs://QmNRUoMgx16hurD3au3ou5A9rmTLYmre8WiGmQEPFmP2Vo",
"width": 600,
"height": 600,
"url": "ipfs://QmXMDj6iAFn2ducQcUU1M87PMMdT2jfyL3Tp3Lz5uUD5Lv",
"width": 200,
"height": 200,
"format": "png"
},
"rpc": [
@@ -35,9 +35,9 @@ export default {
"name": "pegasus",
"url": "https://pegasus.lightlink.io",
"icon": {
"url": "ipfs://QmNRUoMgx16hurD3au3ou5A9rmTLYmre8WiGmQEPFmP2Vo",
"width": 600,
"height": 600,
"url": "ipfs://QmXMDj6iAFn2ducQcUU1M87PMMdT2jfyL3Tp3Lz5uUD5Lv",
"width": 200,
"height": 200,
"format": "png"
},
"standard": "EIP3091"
+34
View File
@@ -0,0 +1,34 @@
import type { Chain } from "../src/types";
export default {
"name": "DeBank Testnet",
"chain": "DeBank",
"rpc": [
"https://debank-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"http://rpc.testnet.debank.com"
],
"faucets": [],
"icon": {
"url": "ipfs://QmW9pBps8WHRRWmyXhjLZrjZJUe8F48hUu7z98bu2RVsjN",
"width": 400,
"height": 400,
"format": "png"
},
"nativeCurrency": {
"name": "DeBank USD",
"symbol": "USD",
"decimals": 18
},
"infoURL": "https://debank.com",
"shortName": "dbk",
"chainId": 2021398,
"networkId": 2021398,
"explorers": [
{
"name": "DeBank Chain Explorer",
"url": "https://explorer.testnet.debank.com",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "debank-testnet"
} as const satisfies Chain;
+35
View File
@@ -0,0 +1,35 @@
import type { Chain } from "../src/types";
export default {
"name": "Centrifuge",
"chain": "CFG",
"rpc": [
"wss://fullnode.parachain.centrifuge.io"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "Centrifuge",
"symbol": "CFG",
"decimals": 18
},
"infoURL": "https://centrifuge.io",
"shortName": "cfg",
"chainId": 2031,
"networkId": 2031,
"explorers": [
{
"name": "subscan",
"url": "https://centrifuge.subscan.io",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "centrifuge"
} as const satisfies Chain;
+28
View File
@@ -0,0 +1,28 @@
import type { Chain } from "../src/types";
export default {
"name": "Catalyst",
"chain": "CFG",
"rpc": [
"wss://fullnode.catalyst.cntrfg.com"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "Catalyst CFG",
"symbol": "NCFG",
"decimals": 18
},
"infoURL": "https://centrifuge.io",
"shortName": "ncfg",
"chainId": 2032,
"networkId": 2032,
"testnet": false,
"slug": "catalyst"
} as const satisfies Chain;
+33
View File
@@ -0,0 +1,33 @@
import type { Chain } from "../src/types";
export default {
"name": "Kiwi Subnet",
"chain": "KIWI",
"rpc": [
"https://kiwi-subnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/kiwi/testnet/rpc"
],
"features": [
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "Shrapgas",
"symbol": "SHRAP",
"decimals": 18
},
"infoURL": "",
"shortName": "kiwi",
"chainId": 2037,
"networkId": 2037,
"explorers": [
{
"name": "KIWI Explorer",
"url": "https://subnets-test.avax.network/kiwi",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "kiwi-subnet"
} as const satisfies Chain;
+31
View File
@@ -0,0 +1,31 @@
import type { Chain } from "../src/types";
export default {
"name": "opBNB Mainnet",
"chain": "opBNB",
"rpc": [
"https://opbnb.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://opbnb-mainnet-rpc.bnbchain.org"
],
"faucets": [
"https://free-online-app.com/faucet-for-eth-evm-chains"
],
"nativeCurrency": {
"name": "BNB Chain Native Token",
"symbol": "BNB",
"decimals": 18
},
"infoURL": "https://opbnb.bnbchain.org/en",
"shortName": "obnb",
"chainId": 204,
"networkId": 204,
"slip44": 714,
"explorers": [
{
"name": "opbnbscan",
"url": "http://mainnet.opbnbscan.com",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "opbnb"
} as const satisfies Chain;
+28
View File
@@ -0,0 +1,28 @@
import type { Chain } from "../src/types";
export default {
"name": "Altair",
"chain": "AIR",
"rpc": [
"wss://fullnode.altair.centrifuge.io"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "Altair",
"symbol": "AIR",
"decimals": 18
},
"infoURL": "https://centrifuge.io",
"shortName": "air",
"chainId": 2088,
"networkId": 2088,
"testnet": false,
"slug": "altair"
} as const satisfies Chain;
+28
View File
@@ -0,0 +1,28 @@
import type { Chain } from "../src/types";
export default {
"name": "Algol",
"chain": "algol",
"rpc": [
"wss://fullnode.algol.cntrfg.com"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "Algol",
"symbol": "ALGL",
"decimals": 18
},
"infoURL": "https://centrifuge.io",
"shortName": "algl",
"chainId": 2089,
"networkId": 2089,
"testnet": false,
"slug": "algol"
} as const satisfies Chain;
+1 -1
View File
@@ -4,7 +4,7 @@ export default {
"chain": "REAP",
"rpc": [
"https://reapchain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://test-rpc.reapchain.org"
"https://test-eth.reapchain.org"
],
"faucets": [
"http://faucet.reapchain.com"
+5 -4
View File
@@ -1,10 +1,11 @@
import type { Chain } from "../src/types";
export default {
"name": "Kava EVM Testnet",
"name": "Kava Testnet",
"chain": "KAVA",
"rpc": [
"https://kava-evm-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"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"
],
"faucets": [
@@ -28,7 +29,7 @@ export default {
"explorers": [
{
"name": "Kava Testnet Explorer",
"url": "https://explorer.testnet.kava.io",
"url": "http://testnet.kavascan.com",
"standard": "EIP3091",
"icon": {
"url": "ipfs://QmdpRTk6oL1HRW9xC6cAc4Rnf9gs6zgdAcr4Z3HcLztusm",
@@ -39,5 +40,5 @@ export default {
}
],
"testnet": true,
"slug": "kava-evm-testnet"
"slug": "kava-testnet"
} as const satisfies Chain;
+6 -4
View File
@@ -1,11 +1,13 @@
import type { Chain } from "../src/types";
export default {
"name": "Kava EVM",
"name": "Kava",
"chain": "KAVA",
"rpc": [
"https://kava-evm.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://kava.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"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"
@@ -29,7 +31,7 @@ export default {
"explorers": [
{
"name": "Kava EVM Explorer",
"url": "https://explorer.kava.io",
"url": "https://kavascan.com",
"standard": "EIP3091",
"icon": {
"url": "ipfs://QmdpRTk6oL1HRW9xC6cAc4Rnf9gs6zgdAcr4Z3HcLztusm",
@@ -40,5 +42,5 @@ export default {
}
],
"testnet": false,
"slug": "kava-evm"
"slug": "kava"
} as const satisfies Chain;
+5 -1
View File
@@ -4,7 +4,11 @@ export default {
"chain": "SOMA",
"rpc": [
"https://soma-network-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://data-testnet-v1.somanetwork.io/"
"https://data-testnet-v1.somanetwork.io/",
"https://testnet-au-server-2.somanetwork.io",
"https://testnet-au-server-1.somanetwork.io",
"https://testnet-sg-server-1.somanetwork.io",
"https://testnet-sg-server-2.somanetwork.io"
],
"faucets": [
"https://faucet.somanetwork.io"
+4 -1
View File
@@ -4,7 +4,10 @@ export default {
"chain": "SOMA",
"rpc": [
"https://soma-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://data-mainnet-v1.somanetwork.io/"
"https://data-mainnet-v1.somanetwork.io/",
"https://id-mainnet.somanetwork.io",
"https://hk-mainnet.somanetwork.io",
"https://sg-mainnet.somanetwork.io"
],
"faucets": [
"https://airdrop.somanetwork.io"
+42
View File
@@ -0,0 +1,42 @@
import type { Chain } from "../src/types";
export default {
"name": "Unicorn Ultra Nebulas Testnet",
"chain": "u2u",
"rpc": [
"https://unicorn-ultra-nebulas-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-nebulas-testnet.uniultra.xyz"
],
"faucets": [
"https://faucet.uniultra.xyz"
],
"nativeCurrency": {
"name": "Unicorn Ultra Nebulas Testnet",
"symbol": "U2U",
"decimals": 18
},
"infoURL": "https://uniultra.xyz",
"shortName": "u2u_nebulas",
"chainId": 2484,
"networkId": 2484,
"icon": {
"url": "ipfs://QmcW64RgqQVHnNbVFyfaMNKt7dJvFqEbfEHZmeyeK8dpEa",
"width": 512,
"height": 512,
"format": "png"
},
"explorers": [
{
"icon": {
"url": "ipfs://QmcW64RgqQVHnNbVFyfaMNKt7dJvFqEbfEHZmeyeK8dpEa",
"width": 512,
"height": 512,
"format": "png"
},
"name": "U2U Explorer",
"url": "https://testnet.u2uscan.xyz",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "unicorn-ultra-nebulas-testnet"
} as const satisfies Chain;
+34
View File
@@ -0,0 +1,34 @@
import type { Chain } from "../src/types";
export default {
"name": "Ancient8 Testnet",
"chain": "Ancient8",
"icon": {
"url": "ipfs://QmSX8sHToRzyFupT8BvPQjVsegRWFYz2mdnLkVnqBFKohY",
"width": 901,
"height": 901,
"format": "png"
},
"rpc": [
"https://ancient8-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-testnet.ancient8.gg"
],
"faucets": [],
"nativeCurrency": {
"name": "Ether",
"symbol": "ETH",
"decimals": 18
},
"infoURL": "https://ancient8.gg/",
"shortName": "a8",
"chainId": 2863311531,
"networkId": 2863311531,
"explorers": [
{
"name": "a8scan-testnet",
"url": "https://testnet.a8scan.io",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "ancient8-testnet"
} as const satisfies Chain;
+6
View File
@@ -5,6 +5,12 @@ export default {
"shortName": "POPTestnet",
"chainId": 331769,
"testnet": true,
"icon": {
"format": "png",
"url": "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
"height": 400,
"width": 400
},
"rpc": [
"https://proofofpepe-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet01.proofofpepe.tech"
+33
View File
@@ -0,0 +1,33 @@
import type { Chain } from "../src/types";
export default {
"name": "POP Mainnet",
"chain": "POP",
"shortName": "POP",
"chainId": 331771,
"testnet": false,
"icon": {
"format": "png",
"url": "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
"height": 400,
"width": 400
},
"rpc": [
"https://pop.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc00.proofofpepe.tech",
"https://rpc01.proofofpepe.tech",
"https://rpc02.proofofpepe.tech"
],
"nativeCurrency": {
"name": "Pepe",
"symbol": "PEPE",
"decimals": 18
},
"explorers": [
{
"name": "Pepescan",
"url": "https://pepescan.app",
"standard": "none"
}
],
"slug": "pop"
} as const satisfies Chain;
+38
View File
@@ -0,0 +1,38 @@
import type { Chain } from "../src/types";
export default {
"name": "Yooldo Verse Mainnet",
"chain": "Yooldo Verse",
"icon": {
"url": "ipfs://QmWvfA2usnYp1ktzLcqFS8eTLgdp4ifrxjiify46KyG9NZ",
"width": 512,
"height": 512,
"format": "png"
},
"rpc": [
"https://yooldo-verse.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.yooldo-verse.xyz/"
],
"faucets": [],
"nativeCurrency": {
"name": "OAS",
"symbol": "OAS",
"decimals": 18
},
"infoURL": "https://yooldo.gg/",
"shortName": "YVM",
"chainId": 345,
"networkId": 345,
"explorers": [
{
"name": "Yooldo Verse Explorer",
"url": "https://explorer.yooldo-verse.xyz",
"standard": "EIP3091"
}
],
"parent": {
"type": "L2",
"chain": "eip155-248"
},
"testnet": false,
"slug": "yooldo-verse"
} as const satisfies Chain;
+23 -15
View File
@@ -1,27 +1,35 @@
import type { Chain } from "../src/types";
export default {
"name": "SeedCoin-Network",
"chain": "SeedCoin-Network",
"name": "Xpla Mainnet",
"chain": "XPLA",
"rpc": [
"https://seedcoin-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://node.seedcoin.network"
"https://xpla-xpla.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://dimension-evm-rpc.xpla.dev"
],
"faucets": [],
"nativeCurrency": {
"name": "SeedCoin",
"symbol": "SEED",
"name": "XPLA",
"symbol": "XPLA",
"decimals": 18
},
"infoURL": "https://www.seedcoin.network/",
"shortName": "SEED",
"infoURL": "https://xpla.io/",
"shortName": "xpla",
"chainId": 37,
"icon": {
"url": "ipfs://QmSchLvCCZjBzcv5n22v1oFDAc2yHJ42NERyjZeL9hBgrh",
"width": 64,
"height": 64,
"url": "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
"width": 512,
"height": 512,
"format": "png"
},
"chainId": 37,
"networkId": 37,
"explorers": [
{
"name": "XPLA Explorer",
"url": "https://explorer.xpla.io",
"standard": "none"
}
],
"testnet": false,
"slug": "seedcoin-network"
"redFlags": [
"reusedChainId"
],
"slug": "xpla-xpla"
} as const satisfies Chain;
+36
View File
@@ -0,0 +1,36 @@
import type { Chain } from "../src/types";
export default {
"name": "Xpla Mainnet",
"chain": "XPLA",
"rpc": [
"https://xpla.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://dimension-rpc.xpla.dev"
],
"faucets": [
"https://faucet.xpla.io/"
],
"nativeCurrency": {
"name": "XPLA",
"symbol": "XPLA",
"decimals": 18
},
"infoURL": "https://xpla.io/",
"shortName": "xpla",
"chainId": 3701,
"networkId": 3701,
"icon": {
"url": "ipfs://Qmf4GoxfpeA5VGqu7KP5eyv1WKaCpNDbvMxq1MjQBwFWxq",
"width": 512,
"height": 512,
"format": "png"
},
"explorers": [
{
"name": "XPLA Explorer",
"url": "https://explorer.xpla.io",
"standard": "none"
}
],
"testnet": false,
"slug": "xpla"
} as const satisfies Chain;
+42
View File
@@ -0,0 +1,42 @@
import type { Chain } from "../src/types";
export default {
"name": "KalyChain Mainnet",
"chain": "KLC",
"icon": {
"url": "ipfs://QmUaXcPewLuQtY5a7xPTzJyVdjkH487VfV7gSR8UXrbxQ3",
"width": 512,
"height": 512,
"format": "png"
},
"rpc": [
"https://kalychain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.kalychain.io/rpc"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "KalyCoin",
"symbol": "KLC",
"decimals": 18
},
"infoURL": "https://kalychain.io",
"shortName": "kalymainnet",
"chainId": 3888,
"networkId": 3888,
"explorers": [
{
"name": "KalyScan",
"url": "https://kalyscan.io",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "kalychain"
} as const satisfies Chain;
+42
View File
@@ -0,0 +1,42 @@
import type { Chain } from "../src/types";
export default {
"name": "KalyChain Testnet",
"chain": "KLC",
"icon": {
"url": "ipfs://QmUaXcPewLuQtY5a7xPTzJyVdjkH487VfV7gSR8UXrbxQ3",
"width": 512,
"height": 512,
"format": "png"
},
"rpc": [
"https://kalychain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnetrpc.kalychain.io/rpc"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "KalyCoin",
"symbol": "KLC",
"decimals": 18
},
"infoURL": "https://kalychain.io",
"shortName": "kalytestnet",
"chainId": 3889,
"networkId": 3889,
"explorers": [
{
"name": "KalyScan",
"url": "https://testnet.kalyscan.io",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "kalychain-testnet"
} as const satisfies Chain;
+43
View File
@@ -0,0 +1,43 @@
import type { Chain } from "../src/types";
export default {
"name": "Alterium L2 Testnet",
"chain": "ALT",
"icon": {
"url": "ipfs://bafkreid3v7ow4c4t3ljya6aouiwvqbtssb2lzmkwt2eghryk234g7yynrq",
"width": 756,
"height": 756,
"format": "png"
},
"rpc": [
"https://alterium-l2-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://l2-testnet-rpc.altscan.org"
],
"faucets": [],
"nativeCurrency": {
"name": "Alterium ETH",
"symbol": "AltETH",
"decimals": 18
},
"infoURL": "https://alteriumprotocol.org",
"shortName": "alterium",
"chainId": 420692,
"networkId": 420692,
"parent": {
"type": "L2",
"chain": "eip155-5",
"bridges": [
{
"url": "https://testnet-bridge.alteriumprotocol.org"
}
]
},
"explorers": [
{
"name": "Alterium L2 Testnet Explorer",
"url": "https://l2-testnet.altscan.org",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "alterium-l2-testnet"
} as const satisfies Chain;
+39
View File
@@ -0,0 +1,39 @@
import type { Chain } from "../src/types";
export default {
"name": "Beam",
"chain": "BEAM",
"rpc": [
"https://beam.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/beam/mainnet/rpc"
],
"features": [
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "Merit Circle",
"symbol": "MC",
"decimals": 18
},
"infoURL": "https://www.onbeam.com",
"shortName": "beam",
"icon": {
"url": "ipfs://QmQJ21NWyGGDraicVEzS1Uqq1yXahM9NCuNZgnfYvtspdt",
"width": 512,
"height": 512,
"format": "png"
},
"chainId": 4337,
"networkId": 4337,
"explorers": [
{
"name": "Beam Explorer",
"url": "https://subnets.avax.network/beam",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "beam"
} as const satisfies Chain;
+39
View File
@@ -0,0 +1,39 @@
import type { Chain } from "../src/types";
export default {
"name": "Orderly Sepolia Testnet",
"chain": "ETH",
"rpc": [
"https://orderly-sepolia-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://l2-orderly-l2-4460-sepolia-8tc3sd7dvy.t.conduit.xyz"
],
"faucets": [],
"nativeCurrency": {
"name": "Sepolia Ether",
"symbol": "ETH",
"decimals": 18
},
"shortName": "orderlyl2",
"chainId": 4460,
"networkId": 4460,
"icon": {
"url": "ipfs://QmSpwp3RAVhZsErAQrCQxEmjnGqJQMigarzZbfqr9Ktakb",
"width": 512,
"height": 512,
"format": "png"
},
"explorers": [
{
"name": "basescout",
"url": "https://explorerl2new-orderly-l2-4460-sepolia-8tc3sd7dvy.t.conduit.xyz",
"icon": {
"url": "ipfs://QmYtUimyqHkkFxYdbXXRbUqNg2VLPUg6Uu2C2nmFWowiZM",
"width": 551,
"height": 540,
"format": "png"
},
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "orderly-sepolia-testnet"
} as const satisfies Chain;
+24 -22
View File
@@ -1,36 +1,38 @@
import type { Chain } from "../src/types";
export default {
"name": "Acria IntelliChain",
"chain": "AIC",
"name": "Xpla Testnet",
"chain": "XPLA",
"rpc": [
"https://acria-intellichain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://aic.acria.ai"
"https://xpla-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://cube-evm-rpc.xpla.dev"
],
"faucets": [],
"nativeCurrency": {
"name": "ACRIA",
"symbol": "ACRIA",
"name": "XPLA",
"symbol": "XPLA",
"decimals": 18
},
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
"faucets": [
"https://faucet.xpla.io/"
],
"infoURL": "https://acria.ai",
"shortName": "aic",
"infoURL": "https://xpla.io/",
"shortName": "xpla-test",
"chainId": 47,
"networkId": 47,
"icon": {
"url": "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
"width": 512,
"height": 512,
"format": "png"
},
"explorers": [
{
"name": "Acria IntelliChain-Explorer",
"url": "https://explorer.acria.ai",
"standard": "EIP3091"
"name": "XPLA Explorer",
"url": "https://explorer.xpla.io/testnet",
"standard": "none"
}
],
"testnet": false,
"slug": "acria-intellichain"
"testnet": true,
"redFlags": [
"reusedChainId"
],
"slug": "xpla-testnet"
} as const satisfies Chain;
+27
View File
@@ -0,0 +1,27 @@
import type { Chain } from "../src/types";
export default {
"name": "Xai Goerli Orbit",
"chain": "Xai Goerli Orbit Testnet",
"shortName": "xai-goerli",
"chainId": 47279324479,
"testnet": true,
"nativeCurrency": {
"name": "Xai Goerli Ether",
"symbol": "ETH",
"decimals": 18
},
"rpc": [
"https://xai-goerli-orbit.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet.xai-chain.net/rpc"
],
"explorers": [
{
"name": "Xai Goerli Testnet Explorer",
"url": "https://testnet-explorer.xai-chain.net",
"standard": "EIP3091"
}
],
"faucets": [],
"infoURL": "https://xai.games/",
"slug": "xai-goerli-orbit"
} as const satisfies Chain;
+2 -2
View File
@@ -8,8 +8,8 @@ export default {
],
"faucets": [],
"nativeCurrency": {
"name": "HMND",
"symbol": "HMND",
"name": "eHMND",
"symbol": "eHMND",
"decimals": 18
},
"infoURL": "https://humanode.io",
+17 -4
View File
@@ -2,8 +2,11 @@ import type { Chain } from "../src/types";
export default {
"name": "Scroll Sepolia Testnet",
"chain": "ETH",
"status": "incubating",
"rpc": [],
"status": "active",
"rpc": [
"https://scroll-sepolia-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://sepolia-rpc.scroll.io/"
],
"faucets": [],
"nativeCurrency": {
"name": "Ether",
@@ -14,11 +17,21 @@ export default {
"shortName": "scr-sepolia",
"chainId": 534351,
"networkId": 534351,
"explorers": [],
"explorers": [
{
"name": "Scroll Sepolia Testnet Block Explorer",
"url": "https://sepolia-blockscout.scroll.io",
"standard": "EIP3091"
}
],
"parent": {
"type": "L2",
"chain": "eip155-11155111",
"bridges": []
"bridges": [
{
"url": "https://scroll.io/bridge"
}
]
},
"testnet": true,
"slug": "scroll-sepolia-testnet"
+16 -3
View File
@@ -3,7 +3,10 @@ export default {
"name": "Scroll",
"chain": "ETH",
"status": "incubating",
"rpc": [],
"rpc": [
"https://scroll.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.scroll.io"
],
"faucets": [],
"nativeCurrency": {
"name": "Ether",
@@ -14,11 +17,21 @@ export default {
"shortName": "scr",
"chainId": 534352,
"networkId": 534352,
"explorers": [],
"explorers": [
{
"name": "Scroll Mainnet Block Explorer",
"url": "https://blockscout.scroll.io",
"standard": "EIP3091"
}
],
"parent": {
"type": "L2",
"chain": "eip155-1",
"bridges": []
"bridges": [
{
"url": "https://scroll.io/bridge"
}
]
},
"testnet": false,
"slug": "scroll"
+2 -7
View File
@@ -2,7 +2,7 @@ import type { Chain } from "../src/types";
export default {
"name": "Scroll Alpha Testnet",
"chain": "ETH",
"status": "active",
"status": "deprecated",
"rpc": [
"https://scroll-alpha-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://alpha-rpc.scroll.io/l2"
@@ -20,12 +20,7 @@ export default {
"explorers": [
{
"name": "Scroll Alpha Testnet Block Explorer",
"url": "https://blockscout.scroll.io",
"standard": "EIP3091"
},
{
"name": "Scroll Alpha Testnet Block Explorer",
"url": "https://scrollscan.co",
"url": "https://alpha-blockscout.scroll.io",
"standard": "EIP3091"
}
],
+28
View File
@@ -0,0 +1,28 @@
import type { Chain } from "../src/types";
export default {
"name": "PAWCHAIN Testnet",
"chain": "PAW",
"rpc": [
"https://pawchain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://pawchainx.com/"
],
"faucets": [],
"nativeCurrency": {
"name": "PAW",
"symbol": "PAW",
"decimals": 18
},
"infoURL": "https://pawchainx.com/",
"shortName": "PAW",
"chainId": 542,
"networkId": 542,
"explorers": [
{
"name": "PAWCHAIN Testnet",
"url": "https://pawscan.io",
"standard": "none"
}
],
"testnet": true,
"slug": "pawchain-testnet"
} as const satisfies Chain;
+23
View File
@@ -0,0 +1,23 @@
import type { Chain } from "../src/types";
export default {
"name": "Tanssi EVM ContainerChain",
"chain": "EVMCC",
"rpc": [
"https://tanssi-evm-containerchain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://fraa-dancebox-3001-rpc.a.dancebox.tanssi.network",
"wss://fraa-dancebox-3001-rpc.a.dancebox.tanssi.network"
],
"faucets": [],
"nativeCurrency": {
"name": "Unit",
"symbol": "Unit",
"decimals": 18
},
"infoURL": "https://tanssi.network",
"shortName": "TanssiCC",
"chainId": 5678,
"networkId": 5678,
"explorers": [],
"testnet": false,
"slug": "tanssi-evm-containerchain"
} as const satisfies Chain;
+36
View File
@@ -0,0 +1,36 @@
import type { Chain } from "../src/types";
export default {
"name": "VELO Labs Mainnet",
"chain": "NOVA chain",
"rpc": [
"https://velo-labs.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://nova.velo.org"
],
"faucets": [
"https://nova-faucet.velo.org"
],
"nativeCurrency": {
"name": "Nova",
"symbol": "NOVA",
"decimals": 18
},
"infoURL": "https://velo.org",
"shortName": "VELO",
"chainId": 56789,
"networkId": 56789,
"icon": {
"url": "ipfs://QmYqvnW2jwPEKUv8BdaV4sbL8Audcwosat6SPn4GqYtKxc",
"width": 225,
"height": 225,
"format": "png"
},
"explorers": [
{
"name": "novascan",
"url": "https://novascan.velo.org",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "velo-labs"
} as const satisfies Chain;
+2 -1
View File
@@ -7,7 +7,8 @@ export default {
"https://rpc.syscoin.org",
"https://rpc.ankr.com/syscoin/${ANKR_API_KEY}",
"https://syscoin.public-rpc.com",
"wss://rpc.syscoin.org/wss"
"wss://rpc.syscoin.org/wss",
"https://syscoin-evm.publicnode.com"
],
"faucets": [
"https://faucet.syscoin.org"
+2 -1
View File
@@ -5,7 +5,8 @@ export default {
"rpc": [
"https://syscoin-tanenbaum-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.tanenbaum.io",
"wss://rpc.tanenbaum.io/wss"
"wss://rpc.tanenbaum.io/wss",
"https://syscoin-tanenbaum-evm.publicnode.com"
],
"faucets": [
"https://faucet.tanenbaum.io"
+42
View File
@@ -0,0 +1,42 @@
import type { Chain } from "../src/types";
export default {
"name": "LAOS Arrakis",
"title": "LAOS Testnet Arrakis",
"chain": "LAOS",
"icon": {
"url": "ipfs://QmZ4YYcvhcaeotMPaGXC5Vab7JFaVkka37V8TiTJpT7Mak",
"width": 586,
"height": 558,
"format": "png"
},
"rpc": [
"https://laos-arrakis.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://arrakis.gorengine.com/own",
"wss://arrakis.gorengine.com/own"
],
"faucets": [],
"nativeCurrency": {
"name": "LAOS",
"symbol": "LAOS",
"decimals": 18
},
"infoURL": "https://www.laosfoundation.io/",
"shortName": "laos",
"chainId": 667,
"networkId": 667,
"explorers": [
{
"name": "blockscout",
"url": "https://arrakis.gorengine.com",
"icon": {
"url": "ipfs://QmZ4YYcvhcaeotMPaGXC5Vab7JFaVkka37V8TiTJpT7Mak",
"width": 586,
"height": 558,
"format": "png"
},
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "laos-arrakis"
} as const satisfies Chain;
+5 -1
View File
@@ -4,7 +4,11 @@ export default {
"chain": "DSC",
"rpc": [
"https://decimal-smart-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://node.decimalchain.com/web3/"
"https://node.decimalchain.com/web3/",
"https://node1-mainnet.decimalchain.com/web3/",
"https://node2-mainnet.decimalchain.com/web3/",
"https://node3-mainnet.decimalchain.com/web3/",
"https://node4-mainnet.decimalchain.com/web3/"
],
"faucets": [],
"nativeCurrency": {
+34
View File
@@ -0,0 +1,34 @@
import type { Chain } from "../src/types";
export default {
"name": "Miexs Smartchain",
"chain": "MiexsSmartchain",
"icon": {
"url": "ipfs://bafkreic6tcc6swh5kzljwqnswj6rlemcm7n6ra7xkgttwv5v3fv7ozj5zu",
"width": 1500,
"height": 1500,
"format": "png"
},
"rpc": [
"https://miexs-smartchain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://mainnet-rpc.miexs.com"
],
"faucets": [],
"nativeCurrency": {
"name": "Miexs Coin",
"symbol": "MIX",
"decimals": 18
},
"infoURL": "https://miexs.com",
"shortName": "Miexs",
"chainId": 761412,
"networkId": 761412,
"explorers": [
{
"name": "Miexs Smartchain Explorer",
"url": "https://miexs.com",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "miexs-smartchain"
} as const satisfies Chain;
+6 -2
View File
@@ -9,7 +9,11 @@ export default {
"https://evm-dataseed3.meerscan.io",
"https://evm-dataseed.meerscan.com",
"https://evm-dataseed1.meerscan.com",
"https://evm-dataseed2.meerscan.com"
"https://evm-dataseed2.meerscan.com",
"https://qng.rpc.qitmeer.io",
"https://mainnet.meerlabs.com",
"https://rpc.dimai.ai",
"https://rpc.woowow.io"
],
"faucets": [],
"nativeCurrency": {
@@ -37,7 +41,7 @@ export default {
"height": 512,
"format": "png"
},
"url": "https://evm.meerscan.com",
"url": "https://qng.meerscan.io",
"standard": "none"
}
],
+10 -3
View File
@@ -2,8 +2,15 @@ import type { Chain } from "../src/types";
export default {
"name": "Qitmeer Network Testnet",
"chain": "MEER",
"rpc": [],
"faucets": [],
"rpc": [
"https://qitmeer-network-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet-qng.rpc.qitmeer.io",
"https://testnet.meerlabs.com",
"https://meer.testnet.meerfans.club"
],
"faucets": [
"https://faucet.qitmeer.io"
],
"nativeCurrency": {
"name": "Qitmeer Testnet",
"symbol": "MEER-T",
@@ -28,7 +35,7 @@ export default {
"height": 512,
"format": "png"
},
"url": "https://testnet.qng.meerscan.io",
"url": "https://qng-testnet.meerscan.io",
"standard": "none"
}
],
+8 -10
View File
@@ -1,19 +1,17 @@
import type { Chain } from "../src/types";
export default {
"name": "BeOne Chain Testnet",
"chain": "BOC",
"name": "Testnet BeOne Chain",
"chain": "tBOC",
"rpc": [
"https://beone-chain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://pre-boc1.beonechain.com",
"https://pre-boc2.beonechain.com",
"https://pre-boc3.beonechain.com"
"https://testnet-beone-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://pre-boc1.beonechain.com"
],
"faucets": [
"https://testnet.beonescan.com/faucet"
],
"nativeCurrency": {
"name": "BeOne Chain Testnet",
"symbol": "BOC",
"name": "Testnet BeOne Chain",
"symbol": "tBOC",
"decimals": 18
},
"infoURL": "https://testnet.beonescan.com",
@@ -28,7 +26,7 @@ export default {
},
"explorers": [
{
"name": "BeOne Chain Testnet",
"name": "Testnet BeOne Chain",
"url": "https://testnet.beonescan.com",
"icon": {
"url": "ipfs://QmbVLQnaMDu86bPyKgCvTGhFBeYwjr15hQnrCcsp1EkAGL",
@@ -40,5 +38,5 @@ export default {
}
],
"testnet": true,
"slug": "beone-chain-testnet"
"slug": "testnet-beone-chain"
} as const satisfies Chain;
+2 -1
View File
@@ -4,7 +4,8 @@ export default {
"chain": "ETH",
"rpc": [
"https://base.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://mainnet.base.org/"
"https://mainnet.base.org/",
"https://developer-access-mainnet.base.org/"
],
"faucets": [],
"nativeCurrency": {
+40
View File
@@ -0,0 +1,40 @@
import type { Chain } from "../src/types";
export default {
"name": "Aerie Network",
"chain": "Aerie",
"rpc": [
"https://aerie-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://mainnet.aerielab.io"
],
"faucets": [],
"nativeCurrency": {
"name": "Aerie",
"symbol": "AER",
"decimals": 18
},
"infoURL": "https://aerielab.io/",
"shortName": "Aerie",
"chainId": 84886,
"networkId": 84886,
"icon": {
"url": "ipfs://bafkreig54jss26xllpjbclmfgwvot72m4ku7qxignhlqei6mijvwi2m4pu",
"width": 1062,
"height": 1069,
"format": "png"
},
"explorers": [
{
"name": "Aerie Explorer",
"url": "https://explorer.aerielab.io",
"icon": {
"url": "ipfs://bafkreig54jss26xllpjbclmfgwvot72m4ku7qxignhlqei6mijvwi2m4pu",
"width": 1062,
"height": 1069,
"format": "png"
},
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "aerie-network"
} as const satisfies Chain;
+36
View File
@@ -0,0 +1,36 @@
import type { Chain } from "../src/types";
export default {
"name": "Spicy Chain",
"chain": "Spicy",
"rpc": [
"https://spicy-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://spicy-rpc.chiliz.com/"
],
"faucets": [
"https://spicy-faucet.chiliz.com/"
],
"nativeCurrency": {
"name": "Chiliz",
"symbol": "CHZ",
"decimals": 18
},
"infoURL": "https://chiliz.com/",
"shortName": "Spicy",
"chainId": 88882,
"networkId": 88882,
"explorers": [
{
"name": "Spicy Explorer",
"url": "http://spicy-explorer.chiliz.com/",
"standard": "none"
}
],
"icon": {
"url": "ipfs://QmTGYofJ8VLkeNY4J69AvXi8e126kmbHmf34wLFoJ1FKAK",
"width": 400,
"height": 400,
"format": "png"
},
"testnet": true,
"slug": "spicy-chain"
} as const satisfies Chain;
+21
View File
@@ -0,0 +1,21 @@
import type { Chain } from "../src/types";
export default {
"name": "Worlds Appchain",
"chain": "WRLDS",
"shortName": "WRLDS",
"chainId": 91003,
"testnet": true,
"rpc": [
"https://worlds-appchain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://api.evm.worlds.dev.eclipsenetwork.xyz/"
],
"nativeCurrency": {
"name": "WRLDS",
"symbol": "WRLDS",
"decimals": 18
},
"faucets": [
"https://faucet.evm.worlds.dev.eclipsenetwork.xyz/request_neon"
],
"slug": "worlds-appchain"
} as const satisfies Chain;
+5 -1
View File
@@ -2,7 +2,11 @@ import type { Chain } from "../src/types";
export default {
"name": "IMPERIUM TESTNET",
"chain": "tIMP",
"rpc": [],
"rpc": [
"https://imperium-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://data-aws-testnet.imperiumchain.com",
"https://data-aws2-testnet.imperiumchain.com"
],
"faucets": [
"https://faucet.imperiumchain.com/"
],
+5 -1
View File
@@ -2,7 +2,11 @@ import type { Chain } from "../src/types";
export default {
"name": "IMPERIUM MAINNET",
"chain": "IMP",
"rpc": [],
"rpc": [
"https://imperium.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://data-aws-mainnet.imperiumchain.com",
"https://data-aws2-mainnet.imperiumchain.com"
],
"faucets": [
"https://faucet.imperiumchain.com/"
],
+2 -1
View File
@@ -10,7 +10,8 @@ export default {
},
"rpc": [
"https://mind-smart-chain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet-msc.mindchain.info/"
"https://testnet-msc.mindchain.info/",
"wss://testnet-msc.mindchain.info/ws"
],
"faucets": [
"https://faucet.mindchain.info/"
+2 -1
View File
@@ -11,7 +11,8 @@ export default {
"rpc": [
"https://mind-smart-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-msc.mindchain.info/",
"https://seednode.mindchain.info"
"https://seednode.mindchain.info",
"wss://seednode.mindchain.info/ws"
],
"faucets": [],
"nativeCurrency": {
@@ -8,6 +8,12 @@ export default {
shortName: "POPTestnet",
chainId: 331769,
testnet: true,
icon: {
format: "png",
url: "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
height: 400,
width: 400,
},
rpc: ["https://testnet01.proofofpepe.tech"],
nativeCurrency: {
name: "POP",
@@ -0,0 +1,30 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "POP Mainnet",
chain: "POP",
shortName: "POP",
chainId: 331771,
testnet: false,
icon: {
format: "png",
url: "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
height: 400,
width: 400,
},
rpc: [
"https://rpc00.proofofpepe.tech",
"https://rpc01.proofofpepe.tech",
"https://rpc02.proofofpepe.tech",
],
nativeCurrency: {
name: "Pepe",
symbol: "PEPE",
decimals: 18,
},
explorers: [
{ name: "Pepescan", url: "https://pepescan.app", standard: "none" },
],
};
+32
View File
@@ -0,0 +1,32 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "Xpla Mainnet",
chain: "XPLA",
rpc: ["https://dimension-evm-rpc.xpla.dev"],
nativeCurrency: {
name: "XPLA",
symbol: "XPLA",
decimals: 18,
},
infoURL: "https://xpla.io/",
shortName: "xpla",
chainId: 37,
icon: {
url: "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
width: 512,
height: 512,
format: "png",
},
explorers: [
{
name: "XPLA Explorer",
url: "https://explorer.xpla.io",
standard: "none",
},
],
testnet: false,
redFlags: ["reusedChainId"],
};
+33
View File
@@ -0,0 +1,33 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "Xpla Testnet",
chain: "XPLA",
rpc: ["https://cube-evm-rpc.xpla.dev"],
nativeCurrency: {
name: "XPLA",
symbol: "XPLA",
decimals: 18,
},
faucets: ["https://faucet.xpla.io/"],
infoURL: "https://xpla.io/",
shortName: "xpla-test",
chainId: 47,
icon: {
url: "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
width: 512,
height: 512,
format: "png",
},
explorers: [
{
name: "XPLA Explorer",
url: "https://explorer.xpla.io/testnet",
standard: "none",
},
],
testnet: true,
redFlags: ["reusedChainId"],
};
@@ -0,0 +1,26 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "Xai Goerli Orbit",
chain: "Xai Goerli Orbit Testnet",
shortName: "xai-goerli",
chainId: 47279324479,
testnet: true,
nativeCurrency: {
name: "Xai Goerli Ether",
symbol: "ETH",
decimals: 18,
},
rpc: ["https://testnet.xai-chain.net/rpc"],
explorers: [
{
name: "Xai Goerli Testnet Explorer",
url: "https://testnet-explorer.xai-chain.net",
standard: "EIP3091",
},
],
faucets: [],
infoURL: "https://xai.games/",
};
+33
View File
@@ -0,0 +1,33 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "Spicy Chain",
chain: "Spicy",
rpc: ["https://spicy-rpc.chiliz.com/"],
faucets: ["https://spicy-faucet.chiliz.com/"],
nativeCurrency: {
name: "Chiliz",
symbol: "CHZ",
decimals: 18,
},
infoURL: "https://chiliz.com/",
shortName: "Spicy",
chainId: 88882,
networkId: 88882,
explorers: [
{
name: "Spicy Explorer",
url: "http://spicy-explorer.chiliz.com/",
standard: "none",
},
],
icon: {
url: "ipfs://QmTGYofJ8VLkeNY4J69AvXi8e126kmbHmf34wLFoJ1FKAK",
width: 400,
height: 400,
format: "png",
},
testnet: true,
};
+18
View File
@@ -0,0 +1,18 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "Worlds Appchain",
chain: "WRLDS",
shortName: "WRLDS",
chainId: 91003,
testnet: true,
rpc: ["https://api.evm.worlds.dev.eclipsenetwork.xyz/"],
nativeCurrency: {
name: "WRLDS",
symbol: "WRLDS",
decimals: 18,
},
faucets: ["https://faucet.evm.worlds.dev.eclipsenetwork.xyz/request_neon"],
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/chains",
"version": "0.1.41",
"version": "0.1.48",
"main": "dist/thirdweb-dev-chains.cjs.js",
"module": "dist/thirdweb-dev-chains.esm.js",
"browser": {
+3 -1
View File
@@ -105,7 +105,8 @@ for (const file of additionalChainsFiles) {
}
chains = chains
.filter((c) => c.status !== "deprecated")
// Keep scroll-alpha-testnet for now even though its deprecated
.filter((c) => c.status !== "deprecated" || c.chainId === 534353)
.map((chain) => {
if (overrides[chain.chainId]) {
chain = merge(chain, overrides[chain.chainId], {
@@ -343,6 +344,7 @@ ${exports.join("\n")}
export * from "./types";
export * from "./utils";
export const defaultChains = [c1, c5, c8453, c84531, c137, c80001, c42161, c421613, c10, c420, c56, c97, c250, c4002, c43114, c43113, c1337];
// @ts-expect-error - TODO: fix this later
export const allChains: Chain[] = [${exportNames.join(", ")}];
type ChainsById = {
File diff suppressed because one or more lines are too long
+108
View File
@@ -1,5 +1,113 @@
# thirdweb
## 0.11.20
### Patch Changes
- [#1538](https://github.com/thirdweb-dev/js/pull/1538) [`8b82f3c5`](https://github.com/thirdweb-dev/js/commit/8b82f3c59cad6bd1167c13cb0b8a1cdc36475ab8) Thanks [@iketw](https://github.com/iketw)! - Adds support for creating PWA Vite apps
You can now run:
```bash
npx thirdweb@nightly create --template pwa-vite-typescript-starter
```
- Updated dependencies [[`f59b729f`](https://github.com/thirdweb-dev/js/commit/f59b729f8b09aa86655b8e8a70fba644fc52009b), [`911e14fc`](https://github.com/thirdweb-dev/js/commit/911e14fcac743b07fa1a66440c72d662c08e971c), [`cd6b07b5`](https://github.com/thirdweb-dev/js/commit/cd6b07b591606d2671794cebebf8edcb59076c32)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.19
### Patch Changes
- Updated dependencies [[`586e91db`](https://github.com/thirdweb-dev/js/commit/586e91dbe610588cc7b24fade59172fed6481074), [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8), [`91f0245b`](https://github.com/thirdweb-dev/js/commit/91f0245be78ae523e1faea26b1032bfb283467d9), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`5a373a75`](https://github.com/thirdweb-dev/js/commit/5a373a75090da7e1e05724ed1a3a3a6aa9f7fd21), [`ae74b8ef`](https://github.com/thirdweb-dev/js/commit/ae74b8ef6200dba8affa8b52e7d834c5552350d0), [`bc003c2f`](https://github.com/thirdweb-dev/js/commit/bc003c2fef33fcf7ce5981d8634911ac4bcaa927), [`447d9846`](https://github.com/thirdweb-dev/js/commit/447d984653f77af6860ae907072e768b584b263d), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.18
### Patch Changes
- Updated dependencies [[`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f), [`046c9ad6`](https://github.com/thirdweb-dev/js/commit/046c9ad604587ff79bf028c4fe7b1f9c94f4ea54), [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.17
### Patch Changes
- Updated dependencies [[`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.16
### Patch Changes
- Updated dependencies [[`e1962641`](https://github.com/thirdweb-dev/js/commit/e19626417218767a0e44c00f440761d7b86d02eb), [`bd1fcbae`](https://github.com/thirdweb-dev/js/commit/bd1fcbae327e788124f5635673511f0b72e9d7ab)]:
- @thirdweb-dev/[email protected]
## 0.11.15
### Patch Changes
- [#1499](https://github.com/thirdweb-dev/js/pull/1499) [`8f3b685a`](https://github.com/thirdweb-dev/js/commit/8f3b685ad2bd73cb4d5d8c8aa25c04ffc10fb7cf) Thanks [@Marfuen](https://github.com/Marfuen)! - Update deploy command from CLI to use show a public gateway url temporarily. Updated chains too.
- Updated dependencies [[`d248aa2c`](https://github.com/thirdweb-dev/js/commit/d248aa2c5a89a297dd2623c961793026de1de346), [`d248aa2c`](https://github.com/thirdweb-dev/js/commit/d248aa2c5a89a297dd2623c961793026de1de346), [`8f3b685a`](https://github.com/thirdweb-dev/js/commit/8f3b685ad2bd73cb4d5d8c8aa25c04ffc10fb7cf), [`28975765`](https://github.com/thirdweb-dev/js/commit/2897576513eb6f497a9f92e3e473182b4fc9681b), [`b91d3e99`](https://github.com/thirdweb-dev/js/commit/b91d3e990198b77dc1358e738c11dc4acaa67491)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.14
### Patch Changes
- Updated dependencies [[`a5ba9e4f`](https://github.com/thirdweb-dev/js/commit/a5ba9e4fbfee228e5b9ac27cd0157187e3a50117), [`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74)]:
- @thirdweb-dev/[email protected]
## 0.11.13
### Patch Changes
- Updated dependencies [[`7f531122`](https://github.com/thirdweb-dev/js/commit/7f5311222b14da04877df056baae36409dff4696)]:
- @thirdweb-dev/[email protected]
## 0.11.12
### Patch Changes
- Updated dependencies [[`73462ef1`](https://github.com/thirdweb-dev/js/commit/73462ef10800aeeb5976634e2bc6fb5d3e8501e4), [`27c225a5`](https://github.com/thirdweb-dev/js/commit/27c225a51221417592b5940887abd1ccb8b67e47), [`cb1c9937`](https://github.com/thirdweb-dev/js/commit/cb1c9937fadb2d06eb148cf9819f2b3601376308), [`70c4a119`](https://github.com/thirdweb-dev/js/commit/70c4a119d691a37ec999d9f6087902d532cc82ed), [`a1732663`](https://github.com/thirdweb-dev/js/commit/a17326634e758c3bf42f0cc3869b8792f1e18cc9), [`f0443bd9`](https://github.com/thirdweb-dev/js/commit/f0443bd989dbba50d0836d1cf274bfb2f44a53fd), [`cb1c9937`](https://github.com/thirdweb-dev/js/commit/cb1c9937fadb2d06eb148cf9819f2b3601376308), [`588b2106`](https://github.com/thirdweb-dev/js/commit/588b21060139a7c0bf5805e2c629a16792ed2c76), [`269e68c0`](https://github.com/thirdweb-dev/js/commit/269e68c0a15e8f78cb5b68c9456ca8094b9e1f30)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.11
### Patch Changes
- Updated dependencies [[`4c37af49`](https://github.com/thirdweb-dev/js/commit/4c37af49aa4fa66beb8ffe8ef556068a29f3c5d4)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.10
### Patch Changes
- Updated dependencies [[`262edc6a`](https://github.com/thirdweb-dev/js/commit/262edc6a46792da88f49ff6ef0a756a932a6a0cf), [`262edc6a`](https://github.com/thirdweb-dev/js/commit/262edc6a46792da88f49ff6ef0a756a932a6a0cf)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.9
### Patch Changes
- [#1442](https://github.com/thirdweb-dev/js/pull/1442) [`7f54012e`](https://github.com/thirdweb-dev/js/commit/7f54012ec648b727b60784990e71b0efb4690934) Thanks [@Marfuen](https://github.com/Marfuen)! - - Warn users on windows to not use the powershell as there are some compatibility issues with it at the moment.
- Warn users if they are pasting a client id instead of a secret key.
- Updated dependencies [[`2a91113a`](https://github.com/thirdweb-dev/js/commit/2a91113a760733fcff2aec90041f69e15de33905)]:
- @thirdweb-dev/[email protected]
## 0.11.8
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.11.8",
"version": "0.11.20",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
+19
View File
@@ -2,6 +2,7 @@ import chalk from "chalk";
import prompts from "prompts";
import Cache, { CacheEntry } from "sync-disk-cache";
import { ApiResponse } from "../lib/types";
import os from "os";
export async function loginUser(
cache: Cache,
@@ -40,6 +41,10 @@ export function getSession(cache: Cache) {
export async function createSession(cache: Cache) {
try {
const isWindows = os.type() === "Windows_NT";
if (isWindows) {
console.log(chalk.yellow("Windows detected: if you are using powershell, there are some known issues with it that we are actively working on, please use git bash or the command prompt. Thank you for your understanding."));
}
const response = await prompts({
type: "invisible",
name: "apiSecretKey",
@@ -48,6 +53,20 @@ export async function createSession(cache: Cache) {
)}`,
});
const keyPassed = response.apiSecretKey;
if (!keyPassed) {
console.log(chalk.red("You need to pass an API secret key"));
process.exit(1);
}
if (keyPassed.length === 32) {
console.log(chalk.red(`This is not a valid secret key. To get your secret key
1. Create an API key at https://thirdweb.com/create-api-key
2. Store and copy your Secret Key. This will be shown only once.
3. Paste it in the CLI when prompted`));
process.exit(1);
}
try {
await validateKey(response.apiSecretKey);
} catch (error) {

Some files were not shown because too many files have changed in this diff Show More