Skip to content

Commit

Permalink
Encode slot chain id and add testing
Browse files Browse the repository at this point in the history
  • Loading branch information
broody committed Jan 15, 2025
1 parent cec808a commit 45ea9c2
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 22 deletions.
13 changes: 13 additions & 0 deletions packages/controller/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Config } from 'jest';

const config: Config = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: ['**/__tests__/**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
};

export default config;
4 changes: 4 additions & 0 deletions packages/controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"build": "pnpm build:deps",
"format": "prettier --write \"src/**/*.ts\"",
"format:check": "prettier --check \"src/**/*.ts\"",
"test": "jest",
"version": "pnpm pkg get version"
},
"exports": {
Expand Down Expand Up @@ -42,7 +43,10 @@
},
"devDependencies": {
"@cartridge/tsconfig": "workspace:*",
"@types/jest": "^29.5.14",
"@types/node": "^20.6.0",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"typescript": "^5.4.5"
}
}
60 changes: 60 additions & 0 deletions packages/controller/src/__tests__/parseChainId.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { constants, shortString } from "starknet";
import { parseChainId } from "../utils";

describe("parseChainId", () => {
describe("Starknet chains", () => {
test("identifies mainnet", () => {
expect(
parseChainId(new URL("https://api.cartridge.gg/x/starknet/mainnet")),
).toBe(constants.StarknetChainId.SN_MAIN);
});

test("identifies sepolia", () => {
expect(
parseChainId(new URL("https://api.cartridge.gg/x/starknet/sepolia")),
).toBe(constants.StarknetChainId.SN_SEPOLIA);
});
});

describe("Project-specific chains", () => {
test("identifies slot chain", () => {
expect(
parseChainId(new URL("https://api.cartridge.gg/x/slot/katana")),
).toBe(shortString.encodeShortString("WP_SLOT"));
});

test("identifies slot chain on localhost", () => {
expect(parseChainId(new URL("http://localhost:8001/x/slot/katana"))).toBe(
shortString.encodeShortString("WP_SLOT"),
);
});

test("identifies slot chain with hyphenated name", () => {
expect(
parseChainId(
new URL("https://api.cartridge.gg/x/my-slot-chain/katana"),
),
).toBe(shortString.encodeShortString("WP_MY_SLOT_CHAIN"));
});

test("identifies slot mainnet chain", () => {
expect(
parseChainId(new URL("https://api.cartridge.gg/x/slot/mainnet")),
).toBe(shortString.encodeShortString("GG_SLOT"));
});
});

describe("Error cases", () => {
test("throws error for unsupported URL format", () => {
expect(() =>
parseChainId(new URL("https://api.example.com/unsupported")),
).toThrow("Chain https://api.example.com/unsupported not supported");
});

test("throws error for URLs without proper chain identifiers", () => {
expect(() =>
parseChainId(new URL("https://api.example.com/v1/starknet")),
).toThrow("Chain https://api.example.com/v1/starknet not supported");
});
});
});
25 changes: 3 additions & 22 deletions packages/controller/src/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import {
Chain,
} from "./types";
import BaseProvider from "./provider";
import { constants, WalletAccount } from "starknet";
import { WalletAccount } from "starknet";
import { Policy } from "@cartridge/presets";
import { AddStarknetChainParameters, ChainId } from "@starknet-io/types-js";
import { parseChainId } from "./utils";

export default class ControllerProvider extends BaseProvider {
private keychain?: AsyncMethodReturns<Keychain>;
Expand All @@ -34,28 +35,8 @@ export default class ControllerProvider extends BaseProvider {
const chains = new Map<ChainId, Chain>();

for (const chain of options.chains) {
let chainId: ChainId | undefined;
const url = new URL(chain.rpcUrl);
const parts = url.pathname.split("/");
if (parts.includes("starknet")) {
if (parts.includes("mainnet")) {
chainId = constants.StarknetChainId.SN_MAIN;
} else if (parts.includes("sepolia")) {
chainId = constants.StarknetChainId.SN_SEPOLIA;
}
} else if (parts.length >= 3) {
const projectName = parts[2];
if (parts.includes("katana")) {
chainId = `WP_${projectName.toUpperCase()}` as ChainId;
} else if (parts.includes("mainnet")) {
chainId = `GG_${projectName.toUpperCase()}` as ChainId;
}
}

if (!chainId) {
throw new Error(`Chain ${chain.rpcUrl} not supported`);
}

const chainId = parseChainId(url);
chains.set(chainId, chain);
}

Expand Down
28 changes: 28 additions & 0 deletions packages/controller/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import {
addAddressPadding,
Call,
CallData,
constants,
getChecksumAddress,
hash,
shortString,
typedData,
TypedDataRevision,
} from "starknet";
import wasm from "@cartridge/account-wasm/controller";
import { Policies, SessionPolicies } from "@cartridge/presets";
import { ChainId } from "@starknet-io/types-js";

// Whitelist of allowed property names to prevent prototype pollution
const ALLOWED_PROPERTIES = new Set([
Expand Down Expand Up @@ -129,3 +132,28 @@ export function humanizeString(str: string): string {
.replace(/^\w/, (c) => c.toUpperCase())
);
}

export function parseChainId(url: URL): ChainId {
const parts = url.pathname.split("/");

if (parts.includes("starknet")) {
if (parts.includes("mainnet")) {
return constants.StarknetChainId.SN_MAIN;
} else if (parts.includes("sepolia")) {
return constants.StarknetChainId.SN_SEPOLIA;
}
} else if (parts.length >= 3) {
const projectName = parts[2];
if (parts.includes("katana")) {
return shortString.encodeShortString(
`WP_${projectName.toUpperCase().replace(/-/g, "_")}`,
) as ChainId;
} else if (parts.includes("mainnet")) {
return shortString.encodeShortString(
`GG_${projectName.toUpperCase().replace(/-/g, "_")}`,
) as ChainId;
}
}

throw new Error(`Chain ${url.toString()} not supported`);
}
Loading

0 comments on commit 45ea9c2

Please sign in to comment.