@sequence0/sdk 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +36 -6
  2. package/dist/chains/bitcoin.d.ts +15 -3
  3. package/dist/chains/bitcoin.d.ts.map +1 -1
  4. package/dist/chains/bitcoin.js +23 -3
  5. package/dist/chains/bitcoin.js.map +1 -1
  6. package/dist/chains/ethereum.d.ts +3 -0
  7. package/dist/chains/ethereum.d.ts.map +1 -1
  8. package/dist/chains/ethereum.js +108 -16
  9. package/dist/chains/ethereum.js.map +1 -1
  10. package/dist/core/client.d.ts +129 -5
  11. package/dist/core/client.d.ts.map +1 -1
  12. package/dist/core/client.js +497 -44
  13. package/dist/core/client.js.map +1 -1
  14. package/dist/core/types.d.ts +46 -3
  15. package/dist/core/types.d.ts.map +1 -1
  16. package/dist/index.d.ts +11 -4
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +31 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/utils/discovery.d.ts +28 -1
  21. package/dist/utils/discovery.d.ts.map +1 -1
  22. package/dist/utils/discovery.js +76 -10
  23. package/dist/utils/discovery.js.map +1 -1
  24. package/dist/utils/errors.d.ts +26 -0
  25. package/dist/utils/errors.d.ts.map +1 -1
  26. package/dist/utils/errors.js +32 -1
  27. package/dist/utils/errors.js.map +1 -1
  28. package/dist/utils/fee.d.ts +107 -0
  29. package/dist/utils/fee.d.ts.map +1 -0
  30. package/dist/utils/fee.js +220 -0
  31. package/dist/utils/fee.js.map +1 -0
  32. package/dist/utils/http.d.ts +97 -1
  33. package/dist/utils/http.d.ts.map +1 -1
  34. package/dist/utils/http.js +238 -6
  35. package/dist/utils/http.js.map +1 -1
  36. package/dist/utils/logger.d.ts +43 -0
  37. package/dist/utils/logger.d.ts.map +1 -0
  38. package/dist/utils/logger.js +129 -0
  39. package/dist/utils/logger.js.map +1 -0
  40. package/dist/utils/rate-limiter.d.ts +43 -0
  41. package/dist/utils/rate-limiter.d.ts.map +1 -0
  42. package/dist/utils/rate-limiter.js +99 -0
  43. package/dist/utils/rate-limiter.js.map +1 -0
  44. package/dist/utils/validation.d.ts +74 -0
  45. package/dist/utils/validation.d.ts.map +1 -0
  46. package/dist/utils/validation.js +380 -0
  47. package/dist/utils/validation.js.map +1 -0
  48. package/dist/wallet/wallet.d.ts +12 -1
  49. package/dist/wallet/wallet.d.ts.map +1 -1
  50. package/dist/wallet/wallet.js +76 -11
  51. package/dist/wallet/wallet.js.map +1 -1
  52. package/package.json +8 -2
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Fee Manager
3
+ *
4
+ * Reads the FeeCollector contract on the Sequence0 chain to provide fee
5
+ * information and build unsigned fee-payment transactions. The actual fee
6
+ * payment (signing and sending the TX) is the app developer's responsibility
7
+ * -- they must have S0 native tokens on the Sequence0 chain (800801).
8
+ *
9
+ * Fully decentralized: reads directly from on-chain contracts, no backend.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const fee = new FeeManager({
14
+ * rpcUrl: 'https://rpc.sequence0.network',
15
+ * feeCollectorAddress: '0x24963595AdEbf6608Dd20DDBfcEf7D5931a595D9',
16
+ * registryAddress: '0x84E44eD38E30FD1F0ec37D88AbAAE831A90C610E',
17
+ * });
18
+ *
19
+ * // Get the current per-signature fee
20
+ * const feeWei = await fee.getSignatureFee();
21
+ *
22
+ * // Build an unsigned fee TX for a wallet's committee
23
+ * const tx = await fee.buildCollectFeeTx('my-wallet', ['0xAgent1', '0xAgent2']);
24
+ * // => { to, data, value } -- sign and send with your own wallet
25
+ * ```
26
+ */
27
+ export interface FeeManagerOptions {
28
+ /** Sequence0 chain RPC URL */
29
+ rpcUrl: string;
30
+ /** FeeCollector proxy contract address */
31
+ feeCollectorAddress: string;
32
+ /** AgentRegistry proxy contract address (for resolving peer IDs to payment addresses) */
33
+ registryAddress: string;
34
+ /** Fee cache TTL in ms (default: 300000 = 5 minutes) */
35
+ cacheTtl?: number;
36
+ }
37
+ /** Unsigned transaction object that the app developer signs and sends */
38
+ export interface UnsignedFeeTx {
39
+ /** FeeCollector contract address */
40
+ to: string;
41
+ /** ABI-encoded calldata for collectFee(walletId, agents) */
42
+ data: string;
43
+ /** Fee amount in wei (hex string) */
44
+ value: string;
45
+ }
46
+ export declare class FeeManager {
47
+ private rpcUrl;
48
+ private feeCollectorAddress;
49
+ private registryAddress;
50
+ private cacheTtl;
51
+ private feeCache;
52
+ constructor(options: FeeManagerOptions);
53
+ /**
54
+ * Get the current per-signature fee from the FeeCollector contract.
55
+ * Result is cached for 5 minutes (configurable via cacheTtl).
56
+ *
57
+ * @returns Fee in wei as a bigint
58
+ */
59
+ getSignatureFee(): Promise<bigint>;
60
+ /**
61
+ * Build an unsigned collectFee transaction.
62
+ *
63
+ * The app developer must sign and send this transaction on the Sequence0
64
+ * chain (800801) using their own wallet/signer. They need S0 native tokens
65
+ * to cover the fee.
66
+ *
67
+ * @param walletId - The Sequence0 wallet ID being signed for
68
+ * @param agents - Array of agent Ethereum addresses (payment addresses)
69
+ * @returns Unsigned transaction { to, data, value }
70
+ */
71
+ buildCollectFeeTx(walletId: string, agents: string[]): Promise<UnsignedFeeTx>;
72
+ /**
73
+ * Resolve committee peer IDs to their Ethereum payment addresses
74
+ * by reading the AgentRegistry contract.
75
+ *
76
+ * @param peerIds - Array of libp2p peer IDs from a wallet's committee
77
+ * @returns Array of Ethereum payment addresses (same order; empty string if not found)
78
+ */
79
+ resolveAgentPaymentAddresses(peerIds: string[]): Promise<string[]>;
80
+ /**
81
+ * Invalidate the cached fee so the next call re-fetches from chain.
82
+ */
83
+ clearCache(): void;
84
+ /**
85
+ * Look up a single agent's payment address from the AgentRegistry.
86
+ * The `agents(string)` public mapping getter returns the Agent struct.
87
+ *
88
+ * Struct layout:
89
+ * string multiaddr (dynamic, offset at slot 0)
90
+ * address paymentAddress (slot 1)
91
+ * uint256 registeredAt (slot 2)
92
+ * uint256 lastHeartbeat (slot 3)
93
+ * bool isActive (slot 4)
94
+ * uint64 heartbeatCount (packed in slot 4)
95
+ * uint64 signaturesParticipated (packed in slot 4)
96
+ */
97
+ private getAgentPaymentAddress;
98
+ /**
99
+ * ABI-encode calldata for collectFee(string walletId, address[] agents)
100
+ */
101
+ private encodeCollectFee;
102
+ /**
103
+ * Make an eth_call to the Sequence0 chain RPC.
104
+ */
105
+ private ethCall;
106
+ }
107
+ //# sourceMappingURL=fee.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fee.d.ts","sourceRoot":"","sources":["../../src/utils/fee.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAgBH,MAAM,WAAW,iBAAiB;IAC9B,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yFAAyF;IACzF,eAAe,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC1B,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAmD;gBAEvD,OAAO,EAAE,iBAAiB;IAOtC;;;;;OAKG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAsBxC;;;;;;;;;;OAUG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAkBnF;;;;;;OAMG;IACG,4BAA4B,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAYxE;;OAEG;IACH,UAAU,IAAI,IAAI;IAMlB;;;;;;;;;;;;OAYG;YACW,sBAAsB;IAsCpC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA0CxB;;OAEG;YACW,OAAO;CAoBxB"}
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ /**
3
+ * Fee Manager
4
+ *
5
+ * Reads the FeeCollector contract on the Sequence0 chain to provide fee
6
+ * information and build unsigned fee-payment transactions. The actual fee
7
+ * payment (signing and sending the TX) is the app developer's responsibility
8
+ * -- they must have S0 native tokens on the Sequence0 chain (800801).
9
+ *
10
+ * Fully decentralized: reads directly from on-chain contracts, no backend.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const fee = new FeeManager({
15
+ * rpcUrl: 'https://rpc.sequence0.network',
16
+ * feeCollectorAddress: '0x24963595AdEbf6608Dd20DDBfcEf7D5931a595D9',
17
+ * registryAddress: '0x84E44eD38E30FD1F0ec37D88AbAAE831A90C610E',
18
+ * });
19
+ *
20
+ * // Get the current per-signature fee
21
+ * const feeWei = await fee.getSignatureFee();
22
+ *
23
+ * // Build an unsigned fee TX for a wallet's committee
24
+ * const tx = await fee.buildCollectFeeTx('my-wallet', ['0xAgent1', '0xAgent2']);
25
+ * // => { to, data, value } -- sign and send with your own wallet
26
+ * ```
27
+ */
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.FeeManager = void 0;
30
+ const errors_1 = require("./errors");
31
+ /** FeeCollector contract: signatureFee() returns uint256 */
32
+ const SIGNATURE_FEE_SELECTOR = '0x19b234f4';
33
+ /** FeeCollector contract: collectFee(string walletId, address[] agents) */
34
+ const COLLECT_FEE_SELECTOR = '0xddd9c849';
35
+ /** AgentRegistry contract: agents(string peerId) returns Agent struct */
36
+ const AGENTS_SELECTOR = '0xcf6ee0cb';
37
+ /** Cache TTL for the signature fee (5 minutes) */
38
+ const FEE_CACHE_TTL = 5 * 60 * 1000;
39
+ class FeeManager {
40
+ constructor(options) {
41
+ this.feeCache = null;
42
+ this.rpcUrl = options.rpcUrl;
43
+ this.feeCollectorAddress = options.feeCollectorAddress;
44
+ this.registryAddress = options.registryAddress;
45
+ this.cacheTtl = options.cacheTtl ?? FEE_CACHE_TTL;
46
+ }
47
+ /**
48
+ * Get the current per-signature fee from the FeeCollector contract.
49
+ * Result is cached for 5 minutes (configurable via cacheTtl).
50
+ *
51
+ * @returns Fee in wei as a bigint
52
+ */
53
+ async getSignatureFee() {
54
+ if (this.feeCache && Date.now() - this.feeCache.timestamp < this.cacheTtl) {
55
+ return this.feeCache.fee;
56
+ }
57
+ const result = await this.ethCall(this.feeCollectorAddress, SIGNATURE_FEE_SELECTOR);
58
+ if (!result || result === '0x') {
59
+ throw new errors_1.NetworkError('Failed to read signatureFee from FeeCollector contract');
60
+ }
61
+ // Result is a single uint256
62
+ const hex = result.startsWith('0x') ? result.slice(2) : result;
63
+ const fee = BigInt('0x' + hex);
64
+ this.feeCache = { fee, timestamp: Date.now() };
65
+ return fee;
66
+ }
67
+ /**
68
+ * Build an unsigned collectFee transaction.
69
+ *
70
+ * The app developer must sign and send this transaction on the Sequence0
71
+ * chain (800801) using their own wallet/signer. They need S0 native tokens
72
+ * to cover the fee.
73
+ *
74
+ * @param walletId - The Sequence0 wallet ID being signed for
75
+ * @param agents - Array of agent Ethereum addresses (payment addresses)
76
+ * @returns Unsigned transaction { to, data, value }
77
+ */
78
+ async buildCollectFeeTx(walletId, agents) {
79
+ if (!walletId || typeof walletId !== 'string') {
80
+ throw new Error('walletId must be a non-empty string');
81
+ }
82
+ if (!agents || agents.length === 0) {
83
+ throw new Error('agents array must not be empty');
84
+ }
85
+ const fee = await this.getSignatureFee();
86
+ const data = this.encodeCollectFee(walletId, agents);
87
+ return {
88
+ to: this.feeCollectorAddress,
89
+ data,
90
+ value: '0x' + fee.toString(16),
91
+ };
92
+ }
93
+ /**
94
+ * Resolve committee peer IDs to their Ethereum payment addresses
95
+ * by reading the AgentRegistry contract.
96
+ *
97
+ * @param peerIds - Array of libp2p peer IDs from a wallet's committee
98
+ * @returns Array of Ethereum payment addresses (same order; empty string if not found)
99
+ */
100
+ async resolveAgentPaymentAddresses(peerIds) {
101
+ const addresses = [];
102
+ for (const peerId of peerIds) {
103
+ const address = await this.getAgentPaymentAddress(peerId);
104
+ addresses.push(address);
105
+ }
106
+ // Filter out empty/zero addresses
107
+ return addresses.filter((a) => a !== '' && a !== '0x0000000000000000000000000000000000000000');
108
+ }
109
+ /**
110
+ * Invalidate the cached fee so the next call re-fetches from chain.
111
+ */
112
+ clearCache() {
113
+ this.feeCache = null;
114
+ }
115
+ // ── Internals ──
116
+ /**
117
+ * Look up a single agent's payment address from the AgentRegistry.
118
+ * The `agents(string)` public mapping getter returns the Agent struct.
119
+ *
120
+ * Struct layout:
121
+ * string multiaddr (dynamic, offset at slot 0)
122
+ * address paymentAddress (slot 1)
123
+ * uint256 registeredAt (slot 2)
124
+ * uint256 lastHeartbeat (slot 3)
125
+ * bool isActive (slot 4)
126
+ * uint64 heartbeatCount (packed in slot 4)
127
+ * uint64 signaturesParticipated (packed in slot 4)
128
+ */
129
+ async getAgentPaymentAddress(peerId) {
130
+ // ABI-encode: agents(string peerId)
131
+ // Function selector + offset to string data (0x20) + string length + string data
132
+ const peerIdHex = Buffer.from(peerId, 'utf8').toString('hex');
133
+ const peerIdLen = peerId.length.toString(16).padStart(64, '0');
134
+ const peerIdPadded = peerIdHex.padEnd(Math.ceil(peerIdHex.length / 64) * 64, '0');
135
+ const offset = '0000000000000000000000000000000000000000000000000000000000000020';
136
+ const calldata = AGENTS_SELECTOR + offset + peerIdLen + peerIdPadded;
137
+ try {
138
+ const result = await this.ethCall(this.registryAddress, calldata);
139
+ if (!result || result === '0x' || result.length < 130) {
140
+ return '';
141
+ }
142
+ // The return is an ABI-encoded struct. For a Solidity public mapping
143
+ // getter returning the struct, the encoding is:
144
+ // word 0: offset to multiaddr string (dynamic)
145
+ // word 1: paymentAddress (address, right-aligned in 32 bytes)
146
+ // word 2: registeredAt (uint256)
147
+ // word 3: lastHeartbeat (uint256)
148
+ // word 4: isActive + heartbeatCount + signaturesParticipated (packed)
149
+ // ... then the string data for multiaddr
150
+ const data = result.startsWith('0x') ? result.slice(2) : result;
151
+ // paymentAddress is at word index 1 (bytes 64..128)
152
+ const addressWord = data.slice(64, 128);
153
+ // Address is the last 40 hex chars (20 bytes)
154
+ const address = '0x' + addressWord.slice(24);
155
+ return address;
156
+ }
157
+ catch {
158
+ return '';
159
+ }
160
+ }
161
+ /**
162
+ * ABI-encode calldata for collectFee(string walletId, address[] agents)
163
+ */
164
+ encodeCollectFee(walletId, agents) {
165
+ // collectFee has two dynamic params: string and address[]
166
+ // ABI encoding:
167
+ // 4 bytes: selector
168
+ // word 0: offset to walletId string data
169
+ // word 1: offset to agents array data
170
+ // ... walletId string encoding (length + padded data)
171
+ // ... agents array encoding (length + addresses)
172
+ const walletIdHex = Buffer.from(walletId, 'utf8').toString('hex');
173
+ const walletIdLen = walletId.length;
174
+ const walletIdPadded = walletIdHex.padEnd(Math.ceil(walletIdHex.length / 64) * 64, '0');
175
+ const walletIdWords = Math.max(1, Math.ceil(walletIdHex.length / 64));
176
+ // Offset to walletId data: 2 words (for the two offsets) = 0x40
177
+ const offsetWalletId = '0000000000000000000000000000000000000000000000000000000000000040';
178
+ // Offset to agents data: 0x40 + 0x20 (walletId length word) + walletIdWords * 0x20
179
+ const agentsOffset = 64 + 32 + walletIdWords * 32; // in bytes
180
+ const offsetAgents = agentsOffset.toString(16).padStart(64, '0');
181
+ // WalletId encoding: length (32 bytes) + padded string data
182
+ const walletIdLenHex = walletIdLen.toString(16).padStart(64, '0');
183
+ const walletIdEncoded = walletIdLenHex + walletIdPadded;
184
+ // Agents encoding: length (32 bytes) + each address padded to 32 bytes
185
+ const agentsLen = agents.length.toString(16).padStart(64, '0');
186
+ const agentsEncoded = agents.map((addr) => {
187
+ const clean = addr.startsWith('0x') ? addr.slice(2) : addr;
188
+ return clean.toLowerCase().padStart(64, '0');
189
+ }).join('');
190
+ return (COLLECT_FEE_SELECTOR +
191
+ offsetWalletId +
192
+ offsetAgents +
193
+ walletIdEncoded +
194
+ agentsLen +
195
+ agentsEncoded);
196
+ }
197
+ /**
198
+ * Make an eth_call to the Sequence0 chain RPC.
199
+ */
200
+ async ethCall(to, data) {
201
+ const callData = data.startsWith('0x') ? data : '0x' + data;
202
+ const res = await fetch(this.rpcUrl, {
203
+ method: 'POST',
204
+ headers: { 'Content-Type': 'application/json' },
205
+ body: JSON.stringify({
206
+ jsonrpc: '2.0',
207
+ method: 'eth_call',
208
+ params: [{ to, data: callData }, 'latest'],
209
+ id: 1,
210
+ }),
211
+ });
212
+ const json = (await res.json());
213
+ if (json.error) {
214
+ throw new errors_1.NetworkError(`Contract call failed: ${json.error.message}`);
215
+ }
216
+ return json.result;
217
+ }
218
+ }
219
+ exports.FeeManager = FeeManager;
220
+ //# sourceMappingURL=fee.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fee.js","sourceRoot":"","sources":["../../src/utils/fee.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,77 @@
1
1
  /**
2
2
  * Lightweight HTTP client for Sequence0 agent node REST API
3
3
  *
4
- * Uses native fetch works in Node.js 18+ and all modern browsers.
4
+ * Uses native fetch -- works in Node.js 18+ and all modern browsers.
5
+ * Includes client-side rate limiting, automatic retries with exponential
6
+ * backoff, request/response debug logging, response validation, and
7
+ * a per-host circuit breaker to fail fast on unreachable agents.
5
8
  */
9
+ import { Sequence0Error } from './errors';
10
+ import { RateLimiterOptions } from './rate-limiter';
11
+ import { Logger } from './logger';
12
+ export type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
13
+ /**
14
+ * Thrown when a request is rejected because the circuit breaker is OPEN.
15
+ * The caller should select a different agent or wait for the cooldown.
16
+ */
17
+ export declare class CircuitBreakerError extends Sequence0Error {
18
+ host: string;
19
+ timeUntilHalfOpen: number;
20
+ constructor(host: string, timeUntilHalfOpen: number);
21
+ }
22
+ export interface CircuitBreakerOptions {
23
+ /** Consecutive failures before tripping OPEN (default: 3) */
24
+ failureThreshold?: number;
25
+ /** Cooldown in ms before moving from OPEN to HALF_OPEN (default: 30000) */
26
+ cooldownMs?: number;
27
+ }
28
+ /**
29
+ * Per-host circuit breaker.
30
+ *
31
+ * States:
32
+ * CLOSED — normal operation, requests pass through
33
+ * OPEN — failing, requests are rejected immediately
34
+ * HALF_OPEN — testing recovery, one request is allowed through
35
+ *
36
+ * Transitions:
37
+ * CLOSED → OPEN after `failureThreshold` consecutive failures
38
+ * OPEN → HALF_OPEN after `cooldownMs` elapses
39
+ * HALF_OPEN → CLOSED on first success
40
+ * HALF_OPEN → OPEN on first failure
41
+ */
42
+ export declare class CircuitBreaker {
43
+ private states;
44
+ private failureCounts;
45
+ private lastFailureTimes;
46
+ private failureThreshold;
47
+ private cooldownMs;
48
+ constructor(options?: CircuitBreakerOptions);
49
+ /**
50
+ * Check whether a request to the given host is allowed.
51
+ * Throws CircuitBreakerError if the circuit is OPEN and cooldown has not elapsed.
52
+ */
53
+ allowRequest(host: string): void;
54
+ /**
55
+ * Record a successful request. Resets the circuit to CLOSED.
56
+ */
57
+ recordSuccess(host: string): void;
58
+ /**
59
+ * Record a failed request. Increments failure count and may trip the circuit.
60
+ */
61
+ recordFailure(host: string): void;
62
+ /**
63
+ * Get the current state for a host (defaults to CLOSED).
64
+ */
65
+ getState(host: string): CircuitState;
66
+ /**
67
+ * Reset the circuit breaker for a specific host.
68
+ */
69
+ reset(host: string): void;
70
+ /**
71
+ * Reset all circuit breakers.
72
+ */
73
+ resetAll(): void;
74
+ }
6
75
  export interface HttpOptions {
7
76
  /** Base URL of the agent node (e.g. http://3.140.248.117:8080) */
8
77
  baseUrl: string;
@@ -10,14 +79,41 @@ export interface HttpOptions {
10
79
  timeout?: number;
11
80
  /** Additional headers */
12
81
  headers?: Record<string, string>;
82
+ /** Max retry attempts on transient failures (default: 3) */
83
+ maxRetries?: number;
84
+ /** Client-side rate limiting options */
85
+ rateLimiter?: RateLimiterOptions | false;
86
+ /** Enable debug logging (default: false) */
87
+ debug?: boolean;
88
+ /** Custom logger instance (overrides debug flag) */
89
+ logger?: Logger;
90
+ /** Circuit breaker instance (shared across HttpClient instances for per-host tracking) */
91
+ circuitBreaker?: CircuitBreaker;
92
+ /** Enable HTTP keep-alive for connection reuse (default: true) */
93
+ keepAlive?: boolean;
94
+ /** Keep-alive timeout in ms (default: 30000) */
95
+ keepAliveTimeout?: number;
13
96
  }
14
97
  export declare class HttpClient {
15
98
  private baseUrl;
99
+ private host;
16
100
  private timeout;
17
101
  private headers;
102
+ private maxRetries;
103
+ private rateLimiter;
104
+ private logger;
105
+ private circuitBreaker;
18
106
  constructor(options: HttpOptions);
19
107
  get<T>(path: string): Promise<T>;
20
108
  post<T>(path: string, body?: unknown): Promise<T>;
109
+ /**
110
+ * Destroy internal resources (rate limiter timers, etc.)
111
+ */
112
+ destroy(): void;
113
+ /**
114
+ * Request with circuit breaker check, automatic retries, and exponential backoff.
115
+ */
116
+ private requestWithRetry;
21
117
  private request;
22
118
  }
23
119
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/utils/http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,WAAW;IACxB,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAyB;gBAE5B,OAAO,EAAE,WAAW;IAS1B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;YAIzC,OAAO;CAuCxB"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/utils/http.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAA8B,cAAc,EAAE,MAAM,UAAU,CAAC;AACtE,OAAO,EAAe,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,MAAM,EAA2B,MAAM,UAAU,CAAC;AAI3D,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3D;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,cAAc;IAExC,IAAI,EAAE,MAAM;IACZ,iBAAiB,EAAE,MAAM;gBADzB,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,MAAM;CAQvC;AAED,MAAM,WAAW,qBAAqB;IAClC,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,gBAAgB,CAAkC;IAC1D,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,GAAE,qBAA0B;IAK/C;;;OAGG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAmBhC;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKjC;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAoBjC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY;IAIpC;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMzB;;OAEG;IACH,QAAQ,IAAI,IAAI;CAKnB;AAOD,MAAM,WAAW,WAAW;IACxB,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,WAAW,CAAC,EAAE,kBAAkB,GAAG,KAAK,CAAC;IACzC,4CAA4C;IAC5C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,kEAAkE;IAClE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAKD,qBAAa,UAAU;IACnB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAwB;gBAElC,OAAO,EAAE,WAAW;IAiD1B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIvD;;OAEG;IACH,OAAO,IAAI,IAAI;IAMf;;OAEG;YACW,gBAAgB;YAuDhB,OAAO;CA+ExB"}