@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.
- package/README.md +36 -6
- package/dist/chains/bitcoin.d.ts +15 -3
- package/dist/chains/bitcoin.d.ts.map +1 -1
- package/dist/chains/bitcoin.js +23 -3
- package/dist/chains/bitcoin.js.map +1 -1
- package/dist/chains/ethereum.d.ts +3 -0
- package/dist/chains/ethereum.d.ts.map +1 -1
- package/dist/chains/ethereum.js +108 -16
- package/dist/chains/ethereum.js.map +1 -1
- package/dist/core/client.d.ts +129 -5
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +497 -44
- package/dist/core/client.js.map +1 -1
- package/dist/core/types.d.ts +46 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/discovery.d.ts +28 -1
- package/dist/utils/discovery.d.ts.map +1 -1
- package/dist/utils/discovery.js +76 -10
- package/dist/utils/discovery.js.map +1 -1
- package/dist/utils/errors.d.ts +26 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +32 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/fee.d.ts +107 -0
- package/dist/utils/fee.d.ts.map +1 -0
- package/dist/utils/fee.js +220 -0
- package/dist/utils/fee.js.map +1 -0
- package/dist/utils/http.d.ts +97 -1
- package/dist/utils/http.d.ts.map +1 -1
- package/dist/utils/http.js +238 -6
- package/dist/utils/http.js.map +1 -1
- package/dist/utils/logger.d.ts +43 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +129 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +43 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +99 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/validation.d.ts +74 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +380 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/wallet/wallet.d.ts +12 -1
- package/dist/wallet/wallet.d.ts.map +1 -1
- package/dist/wallet/wallet.js +76 -11
- package/dist/wallet/wallet.js.map +1 -1
- 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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"}
|
package/dist/utils/http.d.ts
CHANGED
|
@@ -1,8 +1,77 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Lightweight HTTP client for Sequence0 agent node REST API
|
|
3
3
|
*
|
|
4
|
-
* Uses native fetch
|
|
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
|
package/dist/utils/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/utils/http.ts"],"names":[],"mappings":"AAAA
|
|
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"}
|