@wttp/handler
Version:
WTTP handler for fetching data from WTTP sites
354 lines (260 loc) • 10.2 kB
Markdown
# @wttp/handler
A TypeScript/JavaScript client library for the WTTP (Web Three Transfer Protocol) that enables decentralized web hosting on blockchain networks. This package provides fetch-like functionality for retrieving content from WTTP sites deployed on various blockchain networks.
## Features
- 🌐 **WTTP Protocol Support** - Full implementation of WTTP methods (GET, HEAD, OPTIONS, LOCATE)
- 🔗 **Multi-Chain Support** - Works with Ethereum, Sepolia, Polygon, Base, and other EVM networks
- 📍 **wURL Class** - Extended URL class supporting blockchain chain IDs and aliases in the port position
- ⚡ **Fetch-like API** - Familiar interface similar to the native `fetch()` function
- 🔄 **Redirect Handling** - Automatic redirect following with customizable behavior
- 📊 **Rich Response Data** - Access to blockchain-specific metadata and headers
- 🛡️ **TypeScript Support** - Full type definitions for better development experience
## Installation
```bash
npm install @wttp/handler
```
## Quick Start
```typescript
import { WTTPHandler } from '@wttp/handler';
// Create a WTTP client
const wttp = new WTTPHandler();
// Fetch content from a WTTP site
const response = await wttp.fetch('wttp://example.eth:11155111/index.html');
console.log('Status:', response.status);
console.log('Content:', response.body);
console.log('Headers:', response.headers);
```
## Core Classes
### WTTPHandler Class
The main client for interacting with WTTP sites.
#### Constructor
```typescript
const wttp = new WTTPHandler(signer?, defaultChain?);
```
- **signer** (optional): Ethers.js signer for blockchain interactions
- **defaultChain** (optional): Default chain ID or alias (e.g., "sepolia", "mainnet", "11155111")
#### Methods
##### `fetch(url, options?)`
Fetch content from a WTTP site with a familiar fetch-like interface.
```typescript
const response = await wttp.fetch(url, {
method: Method.GET, // GET | HEAD | OPTIONS | LOCATE
headers: {
ifModifiedSince: timestamp,
ifNoneMatch: etag,
rangeChunks: { start: 0n, end: 100n },
rangeBytes: { start: 0n, end: 1024n }
},
signer: customSigner, // Override default signer
gateway: gatewayAddress, // Override default gateway
redirect: "follow" // "follow" | "error" | "manual"
});
```
**Response Object:**
```typescript
{
status: number; // HTTP-like status code
headers: Record<string, string>; // Response headers
body: string | Uint8Array; // Response body
}
```
### wURL Class
Extended URL class that supports blockchain chain IDs and string aliases in the port position.
#### Basic Usage
```typescript
import { wURL } from '@wttp/handler';
// Chain ID in port position (Sepolia testnet)
const chainUrl = new wURL('wttp://contract.eth:11155111/api/data');
console.log(chainUrl.alias); // "11155111"
console.log(chainUrl.hostname); // "contract.eth"
console.log(chainUrl.pathname); // "/api/data"
// String alias in port position
const envUrl = new wURL('https://api.example.com:staging/users');
console.log(envUrl.alias); // "staging"
// Standard port (no alias)
const standardUrl = new wURL('https://api.example.com:8080/data');
console.log(standardUrl.alias); // "8080"
console.log(standardUrl.port); // "8080"
```
#### Relative URL Resolution
```typescript
const base = new wURL('wttp://example.com:sepolia/api/v1/');
const endpoint = new wURL('../v2/users', base);
console.log(endpoint.toString()); // "wttp://example.com:sepolia/api/v2/users"
console.log(endpoint.alias); // "sepolia" (inherited from base)
```
#### Properties
- **alias**: The chain ID or alias extracted from the port position
- All standard URL properties (hostname, pathname, search, hash, etc.)
## Supported HTTP Methods
### GET
Fetch content from a WTTP site:
```typescript
const response = await wttp.fetch('wttp://site.eth:11155111/page.html', {
method: Method.GET
});
```
### HEAD
Get headers without body content:
```typescript
const response = await wttp.fetch('wttp://site.eth:11155111/file.pdf', {
method: Method.HEAD
});
console.log('Content-Length:', response.headers['Content-Length']);
```
### OPTIONS
Discover allowed methods for a resource:
```typescript
const response = await wttp.fetch('wttp://site.eth:11155111/api/', {
method: Method.OPTIONS
});
console.log('Allowed:', response.headers['Allowed-Methods']);
```
### LOCATE
Get metadata and structure information:
```typescript
const response = await wttp.fetch('wttp://site.eth:11155111/data/', {
method: Method.LOCATE
});
// Response body contains JSON structure information
```
## Chain Support
The library supports multiple blockchain networks with convenient aliases:
### Mainnets
- **Ethereum**: `1`, `"ethereum"`, `"mainnet"`, `"eth"`
- **Polygon**: `137`, `"polygon"`, `"matic"`
- **Base**: `8453`, `"base"`
### Testnets
- **Sepolia**: `11155111`, `"sepolia"`, `"testnet"`
- **Localhost**: `31337`, `"localhost"`
### Usage Examples
```typescript
// Using chain ID
const mainnetSite = new wURL('wttp://example.eth:1/index.html');
// Using alias
const sepoliaSite = new wURL('wttp://example.eth:sepolia/index.html');
// Setting default chain
const wttp = new WTTPHandler(undefined, "sepolia");
```
## Advanced Features
### Custom Headers
```typescript
const response = await wttp.fetch('wttp://site.eth:11155111/api/data', {
headers: {
ifModifiedSince: Date.now() - 86400000, // 24 hours ago
ifNoneMatch: 'previous-etag-value',
rangeBytes: { start: 0n, end: 1023n } // First 1KB
}
});
```
### Redirect Handling
```typescript
// Follow redirects automatically (default)
const response = await wttp.fetch(url, { redirect: "follow" });
// Return redirect response without following
const response = await wttp.fetch(url, { redirect: "manual" });
// Throw error on redirect
const response = await wttp.fetch(url, { redirect: "error" });
```
### Custom Signer and Gateway
```typescript
import { ethers } from 'ethers';
const customSigner = new ethers.Wallet('private-key');
const response = await wttp.fetch(url, {
signer: customSigner,
gateway: '0x1234567890abcdef...'
});
```
## Response Headers
WTTP responses include rich metadata:
```typescript
const response = await wttp.fetch('wttp://site.eth:11155111/file.html');
console.log(response.headers);
// {
// "Content-Type": "text/html; charset=utf-8",
// "Content-Length": "1024",
// "Content-Version": "1",
// "Last-Modified": "1640995200",
// "ETag": "0x1234...",
// "Cache-Control": "public, max-age=3600",
// "Allow-Methods": "GET, HEAD, OPTIONS",
// "Location": "" // For redirects
// }
```
## Error Handling
```typescript
try {
const response = await wttp.fetch('wttp://site.eth:11155111/missing.html');
if (response.status === 404) {
console.log('File not found');
}
} catch (error) {
console.error('Network or protocol error:', error);
}
```
## TypeScript Support
The library is written in TypeScript and provides full type definitions:
```typescript
import { WTTPHandler, wURL, Method, WTTPFetchOptions, SimpleResponse } from '@wttp/handler';
const options: WTTPFetchOptions = {
method: Method.GET,
redirect: "follow"
};
const response: SimpleResponse = await wttp.fetch(url, options);
```
## Comparison with Standard fetch()
| Feature | `fetch()` | `wttp.fetch()` |
|---------|-----------|----------------|
| Protocol | HTTP/HTTPS | WTTP |
| Network | Internet | Blockchain |
| URLs | Standard URLs | wURL with chain IDs |
| Caching | Browser cache | Blockchain immutability |
| Authentication | Headers/cookies | Blockchain signatures |
| Decentralization | Centralized servers | Decentralized storage |
## Examples
### Basic Website Fetching
```typescript
import { WTTPHandler } from '@wttp/handler';
const wttp = new WTTPHandler();
// Fetch a webpage
const html = await wttp.fetch('wttp://myblog.eth:sepolia/index.html');
console.log(html.body); // HTML content
// Fetch an API endpoint
const api = await wttp.fetch('wttp://myapi.eth:sepolia/api/users');
const users = JSON.parse(api.body as string);
```
### Working with Different File Types
```typescript
// Text content
const textResponse = await wttp.fetch('wttp://site.eth:11155111/readme.txt');
console.log(textResponse.body); // string
// Binary content (images, PDFs, etc.)
const imageResponse = await wttp.fetch('wttp://site.eth:11155111/logo.png');
console.log(imageResponse.body); // Uint8Array
```
### Chain-Specific Operations
```typescript
// Different chains for dev/staging/prod
const devSite = new wURL('wttp://myapp.eth:localhost/');
const stagingSite = new wURL('wttp://myapp.eth:sepolia/');
const prodSite = new wURL('wttp://myapp.eth:mainnet/');
// Connect to different environments
const wttps = {
dev: new WTTPHandler(undefined, "localhost"),
staging: new WTTPHandler(undefined, "sepolia"),
production: new WTTPHandler(undefined, "mainnet")
};
```
## Contributing
Contributions are welcome! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
## License
This project is licensed under the AGPL-3.0 License - see the [LICENSE](LICENSE) file for details.
## Related Projects
- **[@wttp/core](https://www.npmjs.com/package/@wttp/core)** - Core WTTP protocol definitions
- **[@wttp/gateway](https://www.npmjs.com/package/@wttp/gateway)** - WTTP gateway smart contracts
- **[@wttp/site](https://www.npmjs.com/package/@wttp/site)** - WTTP site deployment tools
## Support
- 📖 [Documentation](https://github.com/TechnicallyWeb3/wttp-handler#readme)
- 🐛 [Issue Tracker](https://github.com/TechnicallyWeb3/wttp-handler/issues)
- 💬 [Discussions](https://github.com/TechnicallyWeb3/wttp-handler/discussions)
---
Built with ❤️ by [TechnicallyWeb3](https://github.com/TechnicallyWeb3)