Skip to content
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
73 changes: 73 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# CLAUDE.md

This file provides guidance to Claude Code when working with code in this repository.

## Project Overview

ATXP SDK is a TypeScript monorepo providing client and server libraries for the ATXP payment protocol. It supports multiple blockchain networks (Solana, Base, World Chain, Polygon) and integrates with MCP (Model Context Protocol) for AI agent payments.

## Common Commands

```bash
# Install dependencies
npm ci

# Build all packages
npm run build

# Type check all packages
npm run typecheck

# Lint all packages
npm run lint
```

## Testing

**IMPORTANT:** Run tests package-by-package because the root level `npm run test` tends to hide test failures.

```bash
# Run tests for a specific package
npm test -w packages/atxp-common
npm test -w packages/atxp-client
npm test -w packages/atxp-server
npm test -w packages/atxp-express
npm test -w packages/atxp-x402
# etc.

# Run all package tests individually (recommended for CI validation)
for pkg in packages/*/; do
echo "Testing $pkg..."
npm test -w "$pkg" || exit 1
done
```

## Architecture

This is an npm workspaces monorepo with the following packages:

- `packages/atxp-common` - Shared types and utilities
- `packages/atxp-client` - Client-side SDK for making payments
- `packages/atxp-server` - Server-side SDK for receiving payments
- `packages/atxp-express` - Express.js middleware integration
- `packages/atxp-cloudflare` - Cloudflare Workers integration
- `packages/atxp-base` - Base chain support
- `packages/atxp-solana` - Solana chain support
- `packages/atxp-polygon` - Polygon chain support
- `packages/atxp-worldchain` - World Chain support
- `packages/atxp-x402` - X402 payment protocol support
- `packages/atxp-sqlite` - SQLite storage for OAuth tokens
- `packages/atxp-redis` - Redis storage for OAuth tokens

## Key Patterns

### Workspace Dependencies

Packages depend on each other via workspace references. When adding new types or exports to `@atxp/common`, ensure:
1. The type is exported from `src/index.ts`
2. Run `npm run build -w packages/atxp-common` to regenerate dist files
3. Other packages will pick up changes via TypeScript project references

### Package Lock Issues

If you see TypeScript errors about missing properties in workspace packages, check `package-lock.json` for nested `node_modules/@atxp/*` entries that point to npm registry versions instead of local workspace versions. Remove these entries and run `npm ci` again.
39 changes: 0 additions & 39 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions packages/atxp-base/src/baseAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,12 @@ export class BaseAccount implements Account {
walletType: 'eoa'
}];
}

/**
* Create a spend permission for the given resource URL.
* Base accounts don't support spend permissions, so this returns null.
*/
async createSpendPermission(_resourceUrl: string): Promise<string | null> {
return null;
}
}
8 changes: 8 additions & 0 deletions packages/atxp-base/src/baseAppAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,12 @@ export class BaseAppAccount implements Account {

cache.delete(this.toCacheKey(userWalletAddress));
}

/**
* Create a spend permission for the given resource URL.
* BaseAppAccount doesn't support spend permissions, so this returns null.
*/
async createSpendPermission(_resourceUrl: string): Promise<string | null> {
return null;
}
}
3 changes: 2 additions & 1 deletion packages/atxp-client/src/atxpClient.buildConfig.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ describe('buildConfig', () => {
account: {
getAccountId: async () => 'bdj' as any,
paymentMakers: [],
getSources: async () => []
getSources: async () => [],
createSpendPermission: async () => null
}
});
expect(config.oAuthChannelFetch).toBe(fetchFn);
Expand Down
12 changes: 8 additions & 4 deletions packages/atxp-client/src/atxpClient.events.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ describe('atxpClient events', () => {
const account = {
getAccountId: vi.fn().mockResolvedValue('bdj'),
paymentMakers: [paymentMaker],
getSources: vi.fn().mockResolvedValue([])
getSources: vi.fn().mockResolvedValue([]),
createSpendPermission: vi.fn().mockResolvedValue(null)
};
const client = await atxpClient({
mcpServer: 'https://example.com/mcp',
Expand Down Expand Up @@ -70,7 +71,8 @@ describe('atxpClient events', () => {
const account = {
getAccountId: vi.fn().mockResolvedValue('bdj'),
paymentMakers: [paymentMaker],
getSources: vi.fn().mockResolvedValue([])
getSources: vi.fn().mockResolvedValue([]),
createSpendPermission: vi.fn().mockResolvedValue(null)
};

// The client initialization or callTool will throw an error due to OAuth failure
Expand Down Expand Up @@ -114,7 +116,8 @@ describe('atxpClient events', () => {
const account = {
getAccountId: vi.fn().mockResolvedValue('bdj'),
paymentMakers: [paymentMaker],
getSources: vi.fn().mockResolvedValue([])
getSources: vi.fn().mockResolvedValue([]),
createSpendPermission: vi.fn().mockResolvedValue(null)
};
const client = await atxpClient({
mcpServer: 'https://example.com/mcp',
Expand Down Expand Up @@ -160,7 +163,8 @@ describe('atxpClient events', () => {
const account = {
getAccountId: vi.fn().mockResolvedValue('bdj'),
paymentMakers: [paymentMaker],
getSources: vi.fn().mockResolvedValue([])
getSources: vi.fn().mockResolvedValue([]),
createSpendPermission: vi.fn().mockResolvedValue(null)
};
const client = await atxpClient({
mcpServer: 'https://example.com/mcp',
Expand Down
9 changes: 6 additions & 3 deletions packages/atxp-client/src/atxpClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ describe('atxpClient', () => {
const account = {
getAccountId: vi.fn().mockResolvedValue('bdj'),
paymentMakers: [paymentMaker],
getSources: vi.fn().mockResolvedValue([])
getSources: vi.fn().mockResolvedValue([]),
createSpendPermission: vi.fn().mockResolvedValue(null)
};
const client = await atxpClient({
mcpServer: 'https://example.com/mcp',
Expand Down Expand Up @@ -66,7 +67,8 @@ describe('atxpClient', () => {
const account = {
getAccountId: vi.fn().mockResolvedValue('bdj'),
paymentMakers: [paymentMaker],
getSources: vi.fn().mockResolvedValue([])
getSources: vi.fn().mockResolvedValue([]),
createSpendPermission: vi.fn().mockResolvedValue(null)
};
const client = await atxpClient({
mcpServer: 'https://example.com/mcp',
Expand Down Expand Up @@ -116,7 +118,8 @@ describe('atxpClient', () => {
const account = {
getAccountId: vi.fn().mockResolvedValue('bdj'),
paymentMakers: [paymentMaker],
getSources: vi.fn().mockResolvedValue([])
getSources: vi.fn().mockResolvedValue([]),
createSpendPermission: vi.fn().mockResolvedValue(null)
};
const client = await atxpClient({
mcpServer: 'https://example.com/mcp',
Expand Down
Loading