Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: generalized url chain id regex check #586

Merged
merged 1 commit into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 45 additions & 18 deletions src/bundler/utils/Utils.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,50 @@
export const extractChainIdFromBundlerUrl = (url: string): number => {
/**
* Extracts the chain ID from a given URL.
*
* @param url - The URL to extract the chain ID from.
* @returns The extracted chain ID as a number.
* @throws {Error} If the chain ID is not found in the URL or is invalid.
*
* @example
* // Returns 80001
* extractChainIdFromUrl("https://example.com/api/v2/80001/rpc")
*/
export const extractChainIdFromUrl = (url: string): number => {
try {
const regex = /\/api\/v2\/(\d+)\/[a-zA-Z0-9.-]+$/
// biome-ignore lint/style/noNonNullAssertion: <explanation>
const match = regex.exec(url)!
return Number.parseInt(match[1])
} catch (error) {
throw new Error("Invalid chain id")
}
}

export const extractChainIdFromPaymasterUrl = (url: string): number => {
try {
const regex = /\/api\/v\d+\/(\d+)\//
const match = regex.exec(url)
const regex = /\/(\d+)\//;
const match = regex.exec(new URL(url).pathname);
if (!match) {
throw new Error("Invalid URL format")
throw new Error("Chain ID not found in URL");
}
return Number.parseInt(match[1])
const chainId = Number.parseInt(match[1], 10);
if (Number.isNaN(chainId)) {
throw new Error("Invalid chain ID");
}
return chainId;
} catch (error) {
throw new Error("Invalid chain id")
if (error instanceof Error) {
throw new Error(`Invalid chain id: ${error.message}`);
}
throw new Error("Invalid chain id");
}
}
};

/**
* Extracts the chain ID from a bundler URL.
*
* @param url - The bundler URL to extract the chain ID from.
* @returns The extracted chain ID as a number.
* @throws {Error} If the chain ID is not found in the URL or is invalid.
*/
export const extractChainIdFromBundlerUrl = (url: string): number =>
extractChainIdFromUrl(url);

/**
* Extracts the chain ID from a paymaster URL.
*
* @param url - The paymaster URL to extract the chain ID from.
* @returns The extracted chain ID as a number.
* @throws {Error} If the chain ID is not found in the URL or is invalid.
*/
export const extractChainIdFromPaymasterUrl = (url: string): number =>
extractChainIdFromUrl(url);
37 changes: 31 additions & 6 deletions tests/bundler/read.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import {
type BiconomySmartAccountV2Config,
compareChainIds,
createSmartAccountClient,
getCustomChain
} from "../../src/account"
import { createBundler } from "../../src/bundler"
import { createBundler, extractChainIdFromUrl } from "../../src/bundler"
import { getBundlerUrl, getConfig } from "../utils"

describe("Bundler:Read", () => {
Expand Down Expand Up @@ -51,11 +50,11 @@ describe("Bundler:Read", () => {
})
)
)
;[smartAccountAddress, smartAccountAddressTwo] = await Promise.all(
[smartAccount, smartAccountTwo].map((account) =>
account.getAccountAddress()
;[smartAccountAddress, smartAccountAddressTwo] = await Promise.all(
[smartAccount, smartAccountTwo].map((account) =>
account.getAccountAddress()
)
)
)
})

test.concurrent(
Expand Down Expand Up @@ -200,4 +199,30 @@ describe("Bundler:Read", () => {
await expect(createAccount).rejects.toThrow()
}
)

test.concurrent('extracts chain ID from various URL structures', () => {
const testCases = [
{ url: "https://example.com/api/v2/1234/endpoint", expected: 1234 },
{ url: "https://api.example.com/v1/5678/resource", expected: 5678 },
{ url: "http://localhost:3000/api/9876/action", expected: 9876 },
{ url: "https://example.com/1234/api/v2/endpoint", expected: 1234 },
{ url: "https://example.com/network/5678/resource/action", expected: 5678 },
{ url: "https://api.example.com/prefix/9876/suffix", expected: 9876 },
{ url: "https://example.com/api/v2/1234/5678/endpoint", expected: 1234 },
{ url: "https://example.com/api/v2/endpoint/1234/", expected: 1234 },
{ url: "https://example.com/api/v2/1234/endpoint?param=value", expected: 1234 },
{ url: "https://example.com/api/v2/1234/endpoint#section", expected: 1234 },
{ url: "https://subdomain.example.com/api/1234/endpoint", expected: 1234 },
{ url: "http://192.168.1.1/api/1234/endpoint", expected: 1234 },
{ url: "https://user:pass@example.com/api/1234/endpoint", expected: 1234 },
{ url: "https://example.com/1234/", expected: 1234 },
{ url: "https://api.example.com/v1/chain/5678/details", expected: 5678 },
{ url: "https://paymaster.biconomy.io/api/v1/80001/-RObQRX9ei.fc6918eb-c582-4417-9d5a-0507b17cfe71", expected: 80001 },
{ url: "https://bundler.biconomy.io/api/v2/80002/nJPK7B3ru.dd7f7861-190d-41bd-af80-6877f74b8f44", expected: 80002 },
];

for (const { url, expected } of testCases) {
expect(extractChainIdFromUrl(url)).toBe(expected);
}
})
})
Loading