Skip to content
Open
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
164 changes: 164 additions & 0 deletions packages/caip/src/caips/caip-19.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { describe, expect, it } from "vitest"

import {
caip19AssetIdRegex,
caip19AssetNameRegex,
caip19AssetNamespaceRegex,
caip19AssetReferenceRegex,
caip19AssetTypeRegex,
caip19TokenIdRegex,
} from "./index"

describe("caip19AssetNamespaceRegex", () => {
it("matches a valid asset namespace", () => {
expect(caip19AssetNamespaceRegex.test("erc20")).toBe(true)
})

it("matches a namespace with hyphens", () => {
expect(caip19AssetNamespaceRegex.test("erc-20")).toBe(true)
})

it("rejects a namespace shorter than 3 characters", () => {
expect(caip19AssetNamespaceRegex.test("ab")).toBe(false)
})

it("rejects a namespace longer than 8 characters", () => {
expect(caip19AssetNamespaceRegex.test("abcdefghi")).toBe(false)
})

it("rejects uppercase characters", () => {
expect(caip19AssetNamespaceRegex.test("ERC20")).toBe(false)
})
})

describe("caip19AssetReferenceRegex", () => {
it("matches a contract address", () => {
expect(
caip19AssetReferenceRegex.test(
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
),
).toBe(true)
})

it("matches a reference with dots and percent signs", () => {
expect(caip19AssetReferenceRegex.test("token.ref%20")).toBe(true)
})

it("rejects an empty reference", () => {
expect(caip19AssetReferenceRegex.test("")).toBe(false)
})

it("rejects a reference longer than 128 characters", () => {
const longRef = "a".repeat(129)
expect(caip19AssetReferenceRegex.test(longRef)).toBe(false)
})
})

describe("caip19AssetNameRegex", () => {
it("matches a valid ERC-20 asset name", () => {
expect(
caip19AssetNameRegex.test(
"erc20:0xdAC17F958D2ee523a2206206994597C13D831ec7",
),
).toBe(true)
})

it("matches a valid ERC-721 asset name", () => {
expect(
caip19AssetNameRegex.test(
"erc721:0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
),
).toBe(true)
})

it("rejects an asset name without a colon separator", () => {
expect(caip19AssetNameRegex.test("erc20-0xabc")).toBe(false)
})
})

describe("caip19AssetTypeRegex", () => {
it("matches a valid ERC-20 asset type", () => {
expect(
caip19AssetTypeRegex.test(
"eip155:1/erc20:0xdAC17F958D2ee523a2206206994597C13D831ec7",
),
).toBe(true)
})

it("matches a valid asset type on Base", () => {
expect(
caip19AssetTypeRegex.test(
"eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
),
).toBe(true)
})

it("rejects an asset type missing the chain ID", () => {
expect(
caip19AssetTypeRegex.test(
"erc20:0xdAC17F958D2ee523a2206206994597C13D831ec7",
),
).toBe(false)
})

it("rejects an asset type with an invalid namespace", () => {
expect(
caip19AssetTypeRegex.test(
"XX:1/erc20:0xdAC17F958D2ee523a2206206994597C13D831ec7",
),
).toBe(false)
})
})

describe("caip19TokenIdRegex", () => {
it("matches a numeric token ID", () => {
expect(caip19TokenIdRegex.test("1234")).toBe(true)
})

it("matches an alphanumeric token ID", () => {
expect(caip19TokenIdRegex.test("token-1.2")).toBe(true)
})

it("rejects an empty token ID", () => {
expect(caip19TokenIdRegex.test("")).toBe(false)
})

it("rejects a token ID longer than 78 characters", () => {
const longId = "a".repeat(79)
expect(caip19TokenIdRegex.test(longId)).toBe(false)
})
})

describe("caip19AssetIdRegex", () => {
it("matches a valid ERC-721 asset ID with token ID", () => {
expect(
caip19AssetIdRegex.test(
"eip155:1/erc721:0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D/1234",
),
).toBe(true)
})

it("matches a valid asset ID on Arbitrum", () => {
expect(
caip19AssetIdRegex.test(
"eip155:42161/erc721:0xabc123def456abc123def456abc123def456abc1/99",
),
).toBe(true)
})

it("rejects an asset ID without a token ID", () => {
expect(
caip19AssetIdRegex.test(
"eip155:1/erc721:0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
),
).toBe(false)
})

it("rejects an asset ID with an invalid chain namespace", () => {
expect(
caip19AssetIdRegex.test(
"XX:1/erc721:0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D/1234",
),
).toBe(false)
})
})
127 changes: 127 additions & 0 deletions packages/caip/src/caips/caip-2.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { describe, expect, it } from "vitest"

import {
caip2ChainIdRegex,
caip2ChainIds,
caip2NamespaceRegex,
caip2Parts,
caip2ReferenceRegex,
} from "./index"

describe("caip2Parts", () => {
it("parses a valid EIP-155 chain ID", () => {
const result = caip2Parts("eip155:1")
expect(result).toEqual({ namespace: "eip155", reference: "1" })
})

it("parses a valid Solana chain ID", () => {
const result = caip2Parts("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")
expect(result).toEqual({
namespace: "solana",
reference: "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
})
})

it("throws for an empty string", () => {
expect(() => caip2Parts("" as `${string}:${string}`)).toThrow(
"Invalid CAIP-2 chain ID",
)
})

it("throws for a string without a colon", () => {
expect(() => caip2Parts("eip155" as `${string}:${string}`)).toThrow(
"Invalid CAIP-2 chain ID",
)
})

it("throws when the reference is missing after the colon", () => {
expect(() => caip2Parts("eip155:" as `${string}:${string}`)).toThrow(
"Invalid CAIP-2 chain ID",
)
})
})

describe("caip2ChainIdRegex", () => {
it("matches a valid EIP-155 chain ID", () => {
expect(caip2ChainIdRegex.test("eip155:1")).toBe(true)
})

it("matches a valid Solana chain ID", () => {
expect(
caip2ChainIdRegex.test("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"),
).toBe(true)
})

it("matches a chain ID with hyphens and underscores in reference", () => {
expect(caip2ChainIdRegex.test("abc:ref_with-chars")).toBe(true)
})

it("rejects a namespace shorter than 3 characters", () => {
expect(caip2ChainIdRegex.test("ab:1")).toBe(false)
})

it("rejects a namespace longer than 8 characters", () => {
expect(caip2ChainIdRegex.test("abcdefghi:1")).toBe(false)
})

it("rejects uppercase characters in namespace", () => {
expect(caip2ChainIdRegex.test("EIP155:1")).toBe(false)
})

it("rejects an empty reference", () => {
expect(caip2ChainIdRegex.test("eip155:")).toBe(false)
})

it("rejects a reference longer than 32 characters", () => {
const longRef = "a".repeat(33)
expect(caip2ChainIdRegex.test(`eip155:${longRef}`)).toBe(false)
})

it("rejects a chain ID without a colon", () => {
expect(caip2ChainIdRegex.test("eip1551")).toBe(false)
})
})

describe("caip2NamespaceRegex", () => {
it("matches a valid namespace", () => {
expect(caip2NamespaceRegex.test("eip155")).toBe(true)
})

it("rejects a namespace with uppercase letters", () => {
expect(caip2NamespaceRegex.test("EIP155")).toBe(false)
})
})

describe("caip2ReferenceRegex", () => {
it("matches a numeric reference", () => {
expect(caip2ReferenceRegex.test("1")).toBe(true)
})

it("matches an alphanumeric reference with hyphens and underscores", () => {
expect(caip2ReferenceRegex.test("my_ref-123")).toBe(true)
})

it("rejects an empty reference", () => {
expect(caip2ReferenceRegex.test("")).toBe(false)
})
})

describe("caip2ChainIds", () => {
it("returns the correct Ethereum mainnet chain ID", () => {
expect(caip2ChainIds.ethereumMainnet).toBe("eip155:1")
})

it("returns the correct Base mainnet chain ID", () => {
expect(caip2ChainIds.baseMainnet).toBe("eip155:8453")
})

it("returns the correct Solana mainnet chain ID", () => {
expect(caip2ChainIds.solanaMainnet).toBe(
"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
)
})

it("returns the correct Arbitrum Sepolia chain ID", () => {
expect(caip2ChainIds.arbitrumSepolia).toBe("eip155:421614")
})
})