Skip to content

Commit 8e2c846

Browse files
committed
Add QUIC transport adapter support for React Native
Added FetchAdapter interface to support custom network transports: - ZhtpApiCore accepts optional FetchAdapter in constructor - React Native apps can inject native QUIC fetch implementation - Defaults to standard fetch() for backward compatibility - Exported FetchAdapter type from all entry points This allows React Native/Electron apps to use native QUIC libraries while keeping this TypeScript library transport-agnostic. Added QUIC-TRANSPORT.md with: - Usage examples for HTTP and QUIC transports - Native QUIC implementation guides (Swift/Kotlin) - QUIC connection settings and discovery - Testing and benchmarking examples - Migration guide from HTTP to QUIC Note: JavaScript lacks mature cross-platform QUIC libraries. Mobile apps must implement QUIC in native code (iOS/Android) and bridge to JavaScript. Closes #32
1 parent 2b1f7d3 commit 8e2c846

File tree

17 files changed

+369
-14
lines changed

17 files changed

+369
-14
lines changed

QUIC-TRANSPORT.md

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
# QUIC Transport Support
2+
3+
The Sovereign Network uses QUIC as its primary transport protocol. This library supports custom QUIC implementations through the `FetchAdapter` interface.
4+
5+
## Overview
6+
7+
By default, this library uses the standard `fetch()` API which works over HTTP/HTTPS. For React Native apps that need to connect via QUIC, you can provide a custom fetch implementation that uses native QUIC libraries.
8+
9+
## Architecture
10+
11+
```
12+
React Native App
13+
├── Native QUIC Client (Swift/Kotlin)
14+
│ └── Implements QUIC protocol
15+
├── JavaScript Bridge
16+
│ └── Exposes fetch-like API
17+
└── This TypeScript Library
18+
└── Uses injected fetch adapter
19+
```
20+
21+
## Usage
22+
23+
### 1. Default HTTP/HTTPS (Browser/Node.js)
24+
25+
```typescript
26+
import { ZhtpApi, BrowserConfigProvider } from '@sovereign-net/api-client';
27+
28+
// Uses standard fetch() - works over HTTP/HTTPS
29+
const config = new BrowserConfigProvider({
30+
zhtpNodeUrl: 'https://node.sovereignnet.io',
31+
networkType: 'mainnet',
32+
debugMode: false,
33+
enableBiometrics: false,
34+
});
35+
36+
const api = new ZhtpApi(config);
37+
```
38+
39+
### 2. Custom QUIC Transport (React Native)
40+
41+
```typescript
42+
import { ZhtpApi, ReactNativeConfigProvider, FetchAdapter } from '@sovereign-net/api-client/react-native';
43+
import { NativeModules } from 'react-native';
44+
45+
// Your native QUIC module (implemented in Swift/Kotlin)
46+
const { QuicClient } = NativeModules;
47+
48+
// Create fetch adapter using native QUIC
49+
const quicFetchAdapter: FetchAdapter = async (url, options) => {
50+
const response = await QuicClient.request({
51+
url,
52+
method: options?.method || 'GET',
53+
headers: options?.headers,
54+
body: options?.body,
55+
});
56+
57+
// Return Response-like object
58+
return {
59+
ok: response.status >= 200 && response.status < 300,
60+
status: response.status,
61+
statusText: response.statusText,
62+
headers: new Headers(response.headers),
63+
json: async () => JSON.parse(response.body),
64+
text: async () => response.body,
65+
} as Response;
66+
};
67+
68+
// Initialize API with QUIC transport
69+
const config = new ReactNativeConfigProvider({
70+
zhtpNodeUrl: 'quic://node.sovereignnet.io:9333',
71+
networkType: 'mainnet',
72+
debugMode: true,
73+
enableBiometrics: true,
74+
});
75+
76+
const api = new ZhtpApi(config, quicFetchAdapter);
77+
78+
// Use normally - all requests go over QUIC
79+
const identity = await api.signup({
80+
display_name: 'Alice',
81+
identity_type: 'citizen',
82+
password: 'secure_password',
83+
});
84+
```
85+
86+
## Native QUIC Implementation
87+
88+
### iOS (Swift)
89+
90+
Use a Swift QUIC library like:
91+
- **nw_connection** (Apple's Network.framework with QUIC support)
92+
- **swift-quic** community libraries
93+
94+
```swift
95+
@objc(QuicClient)
96+
class QuicClient: NSObject {
97+
@objc
98+
func request(_ params: NSDictionary,
99+
resolver resolve: @escaping RCTPromiseResolveBlock,
100+
rejecter reject: @escaping RCTPromiseRejectBlock) {
101+
102+
// Establish QUIC connection
103+
let endpoint = NWEndpoint.hostPort(
104+
host: NWEndpoint.Host(params["host"] as! String),
105+
port: NWEndpoint.Port(integerLiteral: 9333)
106+
)
107+
108+
let parameters = NWParameters.quic(alpn: ["zhtp/1.0"])
109+
parameters.allowLocalEndpointReuse = true
110+
111+
let connection = NWConnection(to: endpoint, using: parameters)
112+
connection.start(queue: .global())
113+
114+
// Send HTTP request over QUIC stream
115+
// ... (implement request/response handling)
116+
}
117+
}
118+
```
119+
120+
### Android (Kotlin)
121+
122+
Use a Kotlin QUIC library like:
123+
- **Cronet** (Chromium's network stack with QUIC)
124+
- **kwik** (Pure Kotlin QUIC implementation)
125+
126+
```kotlin
127+
@ReactModule(name = "QuicClient")
128+
class QuicClientModule(reactContext: ReactApplicationContext) :
129+
ReactContextBaseJavaModule(reactContext) {
130+
131+
@ReactMethod
132+
fun request(params: ReadableMap, promise: Promise) {
133+
val url = params.getString("url")
134+
val method = params.getString("method") ?: "GET"
135+
136+
// Use Cronet for QUIC support
137+
val builder = CronetEngine.Builder(reactApplicationContext)
138+
builder.enableQuic(true)
139+
val engine = builder.build()
140+
141+
val requestBuilder = engine.newUrlRequestBuilder(
142+
url,
143+
object : UrlRequest.Callback() {
144+
override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) {
145+
// Handle response
146+
}
147+
},
148+
executorService
149+
)
150+
151+
requestBuilder.build().start()
152+
}
153+
}
154+
```
155+
156+
## QUIC Connection Settings
157+
158+
### Default Port
159+
- **QUIC**: 9333/UDP
160+
- **HTTP Fallback**: 9333/TCP (if QUIC unavailable)
161+
162+
### TLS Configuration
163+
- **TLS 1.3 Required**
164+
- **Self-signed certificates accepted** in development/mesh mode
165+
- **Post-Quantum Cryptography**: Kyber512 + Dilithium2 for mesh connections
166+
167+
### Connection Parameters
168+
```typescript
169+
const quicConfig = {
170+
alpn: ['zhtp/1.0'], // Application protocol
171+
maxIdleTimeout: 30000, // 30 seconds
172+
maxStreamData: 1048576, // 1 MB per stream
173+
initialMaxData: 10485760, // 10 MB total
174+
enableDatagrams: true, // For mesh discovery
175+
};
176+
```
177+
178+
## Protocol Discovery
179+
180+
The unified server supports multiple discovery methods:
181+
182+
| Protocol | Port | Purpose |
183+
|----------|------|---------|
184+
| QUIC | 9333/UDP | Primary transport |
185+
| UDP Multicast | 5353/UDP | LAN discovery |
186+
| mDNS | 5353/UDP | Service discovery (_zhtp._udp.local) |
187+
| WiFi Direct | P2P | Direct peer connections |
188+
| Bluetooth LE | N/A | Mobile discovery |
189+
| LoRaWAN | 868MHz | Long-range mesh |
190+
191+
### Discovery API
192+
193+
```typescript
194+
// Get list of discovered nodes
195+
const nodes = await api.discoverNodes({
196+
methods: ['quic', 'mdns', 'bluetooth'],
197+
timeout: 5000,
198+
});
199+
200+
// Connect to best available node
201+
await api.connectToBestNode(nodes);
202+
```
203+
204+
## Testing
205+
206+
### Test QUIC Connection
207+
208+
```typescript
209+
const testQuicConnection = async () => {
210+
try {
211+
// Test protocol info endpoint
212+
const info = await api.getProtocolInfo();
213+
console.log('✅ QUIC connection successful:', info.protocol);
214+
console.log(' Node:', info.node_id);
215+
console.log(' Uptime:', info.uptime, 'seconds');
216+
} catch (error) {
217+
console.error('❌ QUIC connection failed:', error);
218+
}
219+
};
220+
```
221+
222+
### Benchmark QUIC vs HTTP
223+
224+
```typescript
225+
const benchmark = async () => {
226+
const iterations = 100;
227+
228+
// HTTP timing
229+
const httpStart = Date.now();
230+
for (let i = 0; i < iterations; i++) {
231+
await api.getProtocolHealth();
232+
}
233+
const httpTime = Date.now() - httpStart;
234+
235+
// QUIC timing (with custom adapter)
236+
const quicStart = Date.now();
237+
for (let i = 0; i < iterations; i++) {
238+
await api.getProtocolHealth();
239+
}
240+
const quicTime = Date.now() - quicStart;
241+
242+
console.log(`HTTP: ${httpTime}ms (${httpTime/iterations}ms avg)`);
243+
console.log(`QUIC: ${quicTime}ms (${quicTime/iterations}ms avg)`);
244+
console.log(`Improvement: ${((httpTime - quicTime) / httpTime * 100).toFixed(1)}%`);
245+
};
246+
```
247+
248+
## Troubleshooting
249+
250+
### Connection Fails
251+
- Check QUIC port 9333/UDP is not blocked
252+
- Verify TLS certificate trust (disable verification in dev)
253+
- Try HTTP fallback to test API methods
254+
255+
### Performance Issues
256+
- Enable connection pooling in native QUIC client
257+
- Use 0-RTT resumption for faster reconnects
258+
- Check network latency with `getNetworkStats()`
259+
260+
### Platform-Specific Issues
261+
262+
**iOS**:
263+
- Ensure `Info.plist` allows UDP connections
264+
- Check App Transport Security settings
265+
266+
**Android**:
267+
- Add `INTERNET` permission to `AndroidManifest.xml`
268+
- Enable cleartext traffic for development
269+
270+
## Migration from HTTP
271+
272+
Existing code requires NO changes when switching to QUIC:
273+
274+
```typescript
275+
// Before (HTTP)
276+
const api = new ZhtpApi(config);
277+
278+
// After (QUIC)
279+
const api = new ZhtpApi(config, quicFetchAdapter);
280+
281+
// All methods work identically
282+
await api.signup({ ... });
283+
await api.registerWeb4Domain({ ... });
284+
await api.getWalletList(identityId);
285+
```
286+
287+
## Performance Benefits
288+
289+
QUIC provides:
290+
- **30-50% lower latency** vs TCP (no head-of-line blocking)
291+
- **Faster connection establishment** (0-RTT resumption)
292+
- **Better mobile performance** (connection migration)
293+
- **Improved reliability** (better congestion control)
294+
295+
## Security
296+
297+
QUIC connections use:
298+
- **TLS 1.3 mandatory** (no downgrade attacks)
299+
- **Connection ID encryption** (privacy from network observers)
300+
- **Forward secrecy** (ephemeral keys)
301+
- **Post-quantum cryptography** (Kyber512 + Dilithium2 for mesh)
302+
303+
## References
304+
305+
- [QUIC RFC 9000](https://www.rfc-editor.org/rfc/rfc9000.html)
306+
- [HTTP/3 RFC 9114](https://www.rfc-editor.org/rfc/rfc9114.html)
307+
- [Sovereign Network Protocol Spec](https://github.com/SOVEREIGN-NET/protocol-spec)
308+
- [React Native Native Modules](https://reactnative.dev/docs/native-modules-intro)
309+
- [Cronet QUIC Documentation](https://chromium.googlesource.com/chromium/src/+/master/components/cronet/)

dist/core/zhtp-api-core.d.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,23 @@
33
* Handles request/response, retry logic, and timeouts
44
*/
55
import { ApiConfig } from './types';
6+
/**
7+
* Transport adapter for custom network implementations (e.g., QUIC)
8+
* React Native apps can provide their own fetch implementation using native QUIC
9+
*/
10+
export type FetchAdapter = (url: string, options?: RequestInit) => Promise<Response>;
611
export declare abstract class ZhtpApiCore {
712
protected baseUrl: string;
813
protected config: ApiConfig | null;
914
protected maxRetries: number;
1015
protected requestTimeout: number;
1116
protected retryDelays: number[];
17+
/**
18+
* Custom fetch adapter (e.g., QUIC-based fetch for React Native)
19+
* Defaults to global fetch if not provided
20+
*/
21+
protected fetchAdapter: FetchAdapter;
22+
constructor(fetchAdapter?: FetchAdapter);
1223
/**
1324
* Generic request method with retry logic and timeout
1425
*/

dist/core/zhtp-api-core.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/core/zhtp-api-core.js

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/core/zhtp-api-core.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/core/zhtp-api.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66
import { ConfigProvider } from './config-provider';
77
import { ApiConfig } from './types';
88
import { ZhtpApiMethods } from './zhtp-api-methods';
9+
import { FetchAdapter } from './zhtp-api-core';
910
export declare class ZhtpApi extends ZhtpApiMethods {
1011
private configProvider;
1112
private initPromise;
12-
constructor(configProvider: ConfigProvider);
13+
/**
14+
* @param configProvider - Configuration provider for API settings
15+
* @param fetchAdapter - Optional custom fetch implementation (e.g., QUIC-based for React Native)
16+
*/
17+
constructor(configProvider: ConfigProvider, fetchAdapter?: FetchAdapter);
1318
private initialize;
1419
/**
1520
* Ensure initialization is complete before making requests

dist/core/zhtp-api.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)