irsb-sdk 0.1.0

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 ADDED
@@ -0,0 +1,251 @@
1
+ # @irsb/sdk
2
+
3
+ TypeScript SDK for the IRSB Protocol (Intent Receipts & Solver Bonds).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @irsb/sdk ethers
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { IRSBClient } from '@irsb/sdk';
15
+ import { ethers } from 'ethers';
16
+
17
+ // Connect to Sepolia
18
+ const provider = new ethers.JsonRpcProvider('https://rpc.sepolia.org');
19
+ const signer = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
20
+
21
+ const client = new IRSBClient({
22
+ chain: 'sepolia',
23
+ signer,
24
+ });
25
+
26
+ // Check if registered
27
+ const isActive = await client.isActiveSolver(signer.address);
28
+ console.log('Active solver:', isActive);
29
+ ```
30
+
31
+ ## Solver Registration
32
+
33
+ ```typescript
34
+ // Register with minimum bond (0.1 ETH)
35
+ const tx = await client.register({
36
+ value: ethers.parseEther('0.1'),
37
+ });
38
+ await tx.wait();
39
+ console.log('Registered as solver');
40
+
41
+ // Deposit more bond
42
+ await client.depositBond({
43
+ value: ethers.parseEther('0.5'),
44
+ });
45
+
46
+ // Check bond balance
47
+ const bond = await client.getSolverBond(signer.address);
48
+ console.log('Total bond:', ethers.formatEther(bond), 'ETH');
49
+ ```
50
+
51
+ ## Posting Receipts
52
+
53
+ After executing an intent off-chain, post a receipt:
54
+
55
+ ```typescript
56
+ import { IRSBClient, PostReceiptParams } from '@irsb/sdk';
57
+
58
+ // Prepare receipt data
59
+ const intentHash = ethers.keccak256(ethers.toUtf8Bytes('intent-data'));
60
+ const constraintsHash = ethers.keccak256(ethers.toUtf8Bytes('constraints'));
61
+ const outcomeHash = ethers.keccak256(ethers.toUtf8Bytes('outcome'));
62
+ const evidenceHash = ethers.ZeroHash; // or IPFS hash of proof
63
+ const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600); // 1 hour
64
+
65
+ // Sign the receipt
66
+ const solverSig = await client.signReceipt({
67
+ intentHash,
68
+ constraintsHash,
69
+ outcomeHash,
70
+ evidenceHash,
71
+ deadline,
72
+ });
73
+
74
+ // Post on-chain
75
+ const tx = await client.postReceipt({
76
+ intentHash,
77
+ constraintsHash,
78
+ outcomeHash,
79
+ evidenceHash,
80
+ deadline,
81
+ solverSig,
82
+ });
83
+ await tx.wait();
84
+ console.log('Receipt posted:', tx.hash);
85
+ ```
86
+
87
+ ## Challenging Receipts
88
+
89
+ If you observe a violation:
90
+
91
+ ```typescript
92
+ import { DisputeReason } from '@irsb/sdk';
93
+
94
+ // Calculate required bond (10% of potential slash)
95
+ const slashAmount = ethers.parseEther('0.1');
96
+ const challengerBond = client.calculateChallengerBond(slashAmount);
97
+
98
+ // Submit challenge
99
+ const tx = await client.challengeReceipt(
100
+ intentHash,
101
+ DisputeReason.MinOutViolation,
102
+ { value: challengerBond }
103
+ );
104
+ await tx.wait();
105
+ console.log('Challenge submitted');
106
+ ```
107
+
108
+ ## Withdrawing Bond
109
+
110
+ ```typescript
111
+ // Request withdrawal (starts 7-day cooldown)
112
+ await client.requestWithdrawal(ethers.parseEther('0.1'));
113
+
114
+ // After 7 days, execute withdrawal
115
+ await client.executeWithdrawal();
116
+
117
+ // Or cancel if needed
118
+ await client.cancelWithdrawal();
119
+ ```
120
+
121
+ ## Reading State
122
+
123
+ ```typescript
124
+ // Get solver info
125
+ const solver = await client.getSolver('0x...');
126
+ console.log('Status:', solver.status);
127
+ console.log('Bond:', ethers.formatEther(solver.bondAmount));
128
+ console.log('Reputation:', solver.reputation);
129
+ console.log('Jail count:', solver.jailCount);
130
+
131
+ // Get receipt
132
+ const receipt = await client.getReceipt(intentHash);
133
+ if (receipt) {
134
+ console.log('Solver:', receipt.solver);
135
+ console.log('Status:', receipt.status);
136
+ }
137
+
138
+ // Get challenge
139
+ const challenge = await client.getChallenge(intentHash);
140
+ if (challenge) {
141
+ console.log('Challenger:', challenge.challenger);
142
+ console.log('Reason:', challenge.reason);
143
+ }
144
+ ```
145
+
146
+ ## Types
147
+
148
+ ```typescript
149
+ import {
150
+ SolverStatus,
151
+ ReceiptStatus,
152
+ DisputeReason,
153
+ SolverInfo,
154
+ IntentReceipt,
155
+ CONSTANTS,
156
+ } from '@irsb/sdk';
157
+
158
+ // Enums
159
+ SolverStatus.Active // 1
160
+ ReceiptStatus.Posted // 1
161
+ DisputeReason.Timeout // 0x01
162
+
163
+ // Constants
164
+ CONSTANTS.MINIMUM_BOND // 0.1 ETH
165
+ CONSTANTS.WITHDRAWAL_COOLDOWN // 7 days
166
+ CONSTANTS.CHALLENGE_WINDOW // 1 hour
167
+ ```
168
+
169
+ ## Custom Chain Config
170
+
171
+ ```typescript
172
+ const client = new IRSBClient({
173
+ chain: {
174
+ chainId: 1,
175
+ rpcUrl: 'https://mainnet.infura.io/v3/...',
176
+ solverRegistry: '0x...',
177
+ intentReceiptHub: '0x...',
178
+ disputeModule: '0x...',
179
+ },
180
+ signer,
181
+ });
182
+ ```
183
+
184
+ ## Contract Addresses
185
+
186
+ ### Sepolia Testnet
187
+
188
+ | Contract | Address |
189
+ |----------|---------|
190
+ | SolverRegistry | `0xB6ab964832808E49635fF82D1996D6a888ecB745` |
191
+ | IntentReceiptHub | `0xD66A1e880AA3939CA066a9EA1dD37ad3d01D977c` |
192
+ | DisputeModule | `0x144DfEcB57B08471e2A75E78fc0d2A74A89DB79D` |
193
+
194
+ ## API Reference
195
+
196
+ ### IRSBClient
197
+
198
+ #### Constructor
199
+
200
+ ```typescript
201
+ new IRSBClient(options: {
202
+ chain: string | ChainConfig;
203
+ signer?: Signer;
204
+ provider?: Provider;
205
+ })
206
+ ```
207
+
208
+ #### Solver Registry Methods
209
+
210
+ | Method | Description |
211
+ |--------|-------------|
212
+ | `getSolver(address)` | Get solver info |
213
+ | `isActiveSolver(address)` | Check if active |
214
+ | `getSolverBond(address)` | Get total bond |
215
+ | `getAvailableBond(address)` | Get unlocked bond |
216
+ | `register({ value })` | Register as solver |
217
+ | `depositBond({ value })` | Add to bond |
218
+ | `requestWithdrawal(amount)` | Start withdrawal |
219
+ | `executeWithdrawal()` | Complete withdrawal |
220
+ | `cancelWithdrawal()` | Cancel withdrawal |
221
+ | `unjail({ value })` | Pay to unjail |
222
+
223
+ #### Receipt Hub Methods
224
+
225
+ | Method | Description |
226
+ |--------|-------------|
227
+ | `getReceipt(intentHash)` | Get receipt |
228
+ | `getChallenge(intentHash)` | Get challenge |
229
+ | `postReceipt(params)` | Post receipt |
230
+ | `challengeReceipt(hash, reason, { value })` | Challenge |
231
+ | `finalizeReceipt(intentHash)` | Finalize |
232
+
233
+ #### Dispute Module Methods
234
+
235
+ | Method | Description |
236
+ |--------|-------------|
237
+ | `getDispute(intentHash)` | Get dispute |
238
+ | `submitEvidence(hash, evidenceHash)` | Submit evidence |
239
+ | `escalateToArbitration(intentHash)` | Escalate |
240
+
241
+ #### Utilities
242
+
243
+ | Method | Description |
244
+ |--------|-------------|
245
+ | `signReceipt(params)` | Sign receipt data |
246
+ | `calculateChallengerBond(slashAmount)` | Calculate bond |
247
+ | `getAddresses()` | Get contract addresses |
248
+
249
+ ## License
250
+
251
+ MIT
@@ -0,0 +1,290 @@
1
+ import { Provider, Signer, TransactionResponse } from 'ethers';
2
+
3
+ /**
4
+ * IRSB Protocol Types
5
+ * Matches Solidity contracts in src/libraries/Types.sol
6
+ */
7
+ declare enum SolverStatus {
8
+ Inactive = 0,
9
+ Active = 1,
10
+ Jailed = 2,
11
+ Banned = 3
12
+ }
13
+ declare enum ReceiptStatus {
14
+ None = 0,
15
+ Posted = 1,
16
+ Challenged = 2,
17
+ Finalized = 3,
18
+ Slashed = 4
19
+ }
20
+ declare enum DisputeReason {
21
+ None = 0,
22
+ Timeout = 1,
23
+ MinOutViolation = 2,
24
+ WrongToken = 3,
25
+ WrongChain = 4,
26
+ WrongRecipient = 5,
27
+ ReceiptForgery = 6,
28
+ InvalidSignature = 7
29
+ }
30
+ declare enum DisputeStatus {
31
+ None = 0,
32
+ Open = 1,
33
+ EvidenceSubmitted = 2,
34
+ Escalated = 3,
35
+ Resolved = 4
36
+ }
37
+ declare enum DisputeResolution {
38
+ None = 0,
39
+ SolverWins = 1,
40
+ ChallengerWins = 2,
41
+ Split = 3,
42
+ Timeout = 4
43
+ }
44
+ interface SolverInfo {
45
+ bondAmount: bigint;
46
+ lockedAmount: bigint;
47
+ reputation: bigint;
48
+ registrationTime: bigint;
49
+ lastActiveTime: bigint;
50
+ totalIntents: bigint;
51
+ successfulIntents: bigint;
52
+ jailCount: number;
53
+ status: SolverStatus;
54
+ pendingWithdrawal: bigint;
55
+ withdrawalRequestTime: bigint;
56
+ }
57
+ interface IntentReceipt {
58
+ solver: string;
59
+ intentHash: string;
60
+ constraintsHash: string;
61
+ outcomeHash: string;
62
+ evidenceHash: string;
63
+ postedAt: bigint;
64
+ deadline: bigint;
65
+ solverSig: string;
66
+ status: ReceiptStatus;
67
+ }
68
+ interface Challenge {
69
+ challenger: string;
70
+ reason: DisputeReason;
71
+ bond: bigint;
72
+ timestamp: bigint;
73
+ }
74
+ interface Dispute {
75
+ intentHash: string;
76
+ challenger: string;
77
+ solver: string;
78
+ reason: DisputeReason;
79
+ solverEvidence: string;
80
+ challengerEvidence: string;
81
+ createdAt: bigint;
82
+ evidenceDeadline: bigint;
83
+ status: DisputeStatus;
84
+ resolution: DisputeResolution;
85
+ }
86
+ interface PostReceiptParams {
87
+ intentHash: string;
88
+ constraintsHash: string;
89
+ outcomeHash: string;
90
+ evidenceHash: string;
91
+ deadline: bigint;
92
+ solverSig: string;
93
+ }
94
+ interface ChallengeParams {
95
+ intentHash: string;
96
+ reason: DisputeReason;
97
+ }
98
+ interface ChainConfig {
99
+ chainId: number;
100
+ rpcUrl: string;
101
+ solverRegistry: string;
102
+ intentReceiptHub: string;
103
+ disputeModule: string;
104
+ }
105
+ declare const CHAIN_CONFIGS: Record<string, ChainConfig>;
106
+ declare const CONSTANTS: {
107
+ readonly MINIMUM_BOND: bigint;
108
+ readonly WITHDRAWAL_COOLDOWN: bigint;
109
+ readonly MAX_JAILS: 3;
110
+ readonly CHALLENGE_WINDOW: bigint;
111
+ readonly CHALLENGER_BOND_BPS: 1000;
112
+ readonly EVIDENCE_WINDOW: bigint;
113
+ readonly ARBITRATION_TIMEOUT: bigint;
114
+ };
115
+
116
+ interface IRSBClientConfig {
117
+ /** Chain name ('sepolia') or custom config */
118
+ chain: string | ChainConfig;
119
+ /** Ethers signer for write operations */
120
+ signer?: Signer;
121
+ /** Ethers provider for read operations (optional if signer provided) */
122
+ provider?: Provider;
123
+ }
124
+ /**
125
+ * IRSB Protocol SDK Client
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * import { IRSBClient } from '@irsb/sdk';
130
+ * import { ethers } from 'ethers';
131
+ *
132
+ * const provider = new ethers.JsonRpcProvider('https://rpc.sepolia.org');
133
+ * const signer = new ethers.Wallet(PRIVATE_KEY, provider);
134
+ *
135
+ * const client = new IRSBClient({
136
+ * chain: 'sepolia',
137
+ * signer,
138
+ * });
139
+ *
140
+ * // Register as solver
141
+ * await client.register({ value: ethers.parseEther('0.1') });
142
+ *
143
+ * // Post a receipt
144
+ * await client.postReceipt({
145
+ * intentHash: '0x...',
146
+ * constraintsHash: '0x...',
147
+ * outcomeHash: '0x...',
148
+ * evidenceHash: '0x...',
149
+ * deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
150
+ * solverSig: '0x...',
151
+ * });
152
+ * ```
153
+ */
154
+ declare class IRSBClient {
155
+ readonly config: ChainConfig;
156
+ readonly provider: Provider;
157
+ readonly signer?: Signer;
158
+ private solverRegistry;
159
+ private intentReceiptHub;
160
+ private disputeModule;
161
+ constructor(options: IRSBClientConfig);
162
+ /**
163
+ * Get solver information
164
+ */
165
+ getSolver(address: string): Promise<SolverInfo>;
166
+ /**
167
+ * Check if address is an active solver
168
+ */
169
+ isActiveSolver(address: string): Promise<boolean>;
170
+ /**
171
+ * Get solver's total bond amount
172
+ */
173
+ getSolverBond(address: string): Promise<bigint>;
174
+ /**
175
+ * Get solver's available (unlocked) bond
176
+ */
177
+ getAvailableBond(address: string): Promise<bigint>;
178
+ /**
179
+ * Get minimum bond required for registration
180
+ */
181
+ getMinimumBond(): Promise<bigint>;
182
+ /**
183
+ * Register as a solver with initial bond
184
+ * @param options.value - ETH to deposit as bond (must be >= MINIMUM_BOND)
185
+ */
186
+ register(options: {
187
+ value: bigint;
188
+ }): Promise<TransactionResponse>;
189
+ /**
190
+ * Deposit additional bond
191
+ * @param options.value - ETH to deposit
192
+ */
193
+ depositBond(options: {
194
+ value: bigint;
195
+ }): Promise<TransactionResponse>;
196
+ /**
197
+ * Request withdrawal of bond (starts cooldown)
198
+ * @param amount - Amount to withdraw
199
+ */
200
+ requestWithdrawal(amount: bigint): Promise<TransactionResponse>;
201
+ /**
202
+ * Cancel pending withdrawal
203
+ */
204
+ cancelWithdrawal(): Promise<TransactionResponse>;
205
+ /**
206
+ * Execute withdrawal after cooldown
207
+ */
208
+ executeWithdrawal(): Promise<TransactionResponse>;
209
+ /**
210
+ * Unjail solver by paying penalty
211
+ * @param options.value - Unjail penalty amount
212
+ */
213
+ unjail(options: {
214
+ value: bigint;
215
+ }): Promise<TransactionResponse>;
216
+ /**
217
+ * Get receipt by intent hash
218
+ */
219
+ getReceipt(intentHash: string): Promise<IntentReceipt | null>;
220
+ /**
221
+ * Get challenge for an intent
222
+ */
223
+ getChallenge(intentHash: string): Promise<Challenge | null>;
224
+ /**
225
+ * Get challenge window duration
226
+ */
227
+ getChallengeWindow(): Promise<bigint>;
228
+ /**
229
+ * Post a receipt for an executed intent
230
+ */
231
+ postReceipt(params: PostReceiptParams): Promise<TransactionResponse>;
232
+ /**
233
+ * Challenge a receipt
234
+ * @param intentHash - Hash of the intent to challenge
235
+ * @param reason - Dispute reason code
236
+ * @param options.value - Challenger bond (must meet minimum)
237
+ */
238
+ challengeReceipt(intentHash: string, reason: DisputeReason, options: {
239
+ value: bigint;
240
+ }): Promise<TransactionResponse>;
241
+ /**
242
+ * Finalize a receipt after challenge window
243
+ */
244
+ finalizeReceipt(intentHash: string): Promise<TransactionResponse>;
245
+ /**
246
+ * Get dispute details
247
+ */
248
+ getDispute(intentHash: string): Promise<any | null>;
249
+ /**
250
+ * Submit evidence for a dispute
251
+ */
252
+ submitEvidence(intentHash: string, evidenceHash: string): Promise<TransactionResponse>;
253
+ /**
254
+ * Escalate dispute to arbitration
255
+ */
256
+ escalateToArbitration(intentHash: string): Promise<TransactionResponse>;
257
+ /**
258
+ * Create a signed receipt for posting
259
+ */
260
+ signReceipt(params: {
261
+ intentHash: string;
262
+ constraintsHash: string;
263
+ outcomeHash: string;
264
+ evidenceHash: string;
265
+ deadline: bigint;
266
+ }): Promise<string>;
267
+ /**
268
+ * Calculate required challenger bond for a slash amount
269
+ */
270
+ calculateChallengerBond(slashAmount: bigint): bigint;
271
+ /**
272
+ * Get contract addresses
273
+ */
274
+ getAddresses(): {
275
+ solverRegistry: string;
276
+ intentReceiptHub: string;
277
+ disputeModule: string;
278
+ };
279
+ private requireSigner;
280
+ }
281
+
282
+ /**
283
+ * Contract ABIs for IRSB Protocol
284
+ * Simplified to essential functions for SDK usage
285
+ */
286
+ declare const SOLVER_REGISTRY_ABI: readonly ["function MINIMUM_BOND() view returns (uint256)", "function WITHDRAWAL_COOLDOWN() view returns (uint64)", "function MAX_JAILS() view returns (uint8)", "function solvers(address) view returns (uint256 bondAmount, uint256 lockedAmount, uint256 reputation, uint64 registrationTime, uint64 lastActiveTime, uint64 totalIntents, uint64 successfulIntents, uint8 jailCount, uint8 status, uint256 pendingWithdrawal, uint64 withdrawalRequestTime)", "function isActiveSolver(address solver) view returns (bool)", "function getSolverBond(address solver) view returns (uint256)", "function getAvailableBond(address solver) view returns (uint256)", "function owner() view returns (address)", "function register() payable", "function depositBond() payable", "function requestWithdrawal(uint256 amount)", "function cancelWithdrawal()", "function executeWithdrawal()", "function unjail() payable", "event SolverRegistered(address indexed solver, uint256 bondAmount)", "event BondDeposited(address indexed solver, uint256 amount, uint256 newTotal)", "event WithdrawalRequested(address indexed solver, uint256 amount)", "event WithdrawalExecuted(address indexed solver, uint256 amount)", "event WithdrawalCancelled(address indexed solver)", "event SolverSlashed(address indexed solver, uint256 amount, bytes32 reason)", "event SolverJailed(address indexed solver, uint8 jailCount)", "event SolverUnjailed(address indexed solver)", "event SolverBanned(address indexed solver)"];
287
+ declare const INTENT_RECEIPT_HUB_ABI: readonly ["function challengeWindow() view returns (uint64)", "function challengerBondBps() view returns (uint16)", "function receipts(bytes32) view returns (address solver, bytes32 intentHash, bytes32 constraintsHash, bytes32 outcomeHash, bytes32 evidenceHash, uint64 postedAt, uint64 deadline, bytes solverSig, uint8 status)", "function challenges(bytes32) view returns (address challenger, uint8 reason, uint256 bond, uint64 timestamp)", "function getReceipt(bytes32 intentHash) view returns (tuple(address solver, bytes32 intentHash, bytes32 constraintsHash, bytes32 outcomeHash, bytes32 evidenceHash, uint64 postedAt, uint64 deadline, bytes solverSig, uint8 status))", "function getChallenge(bytes32 intentHash) view returns (tuple(address challenger, uint8 reason, uint256 bond, uint64 timestamp))", "function solverRegistry() view returns (address)", "function postReceipt(bytes32 intentHash, bytes32 constraintsHash, bytes32 outcomeHash, bytes32 evidenceHash, uint64 deadline, bytes solverSig)", "function challengeReceipt(bytes32 intentHash, uint8 reason) payable", "function finalizeReceipt(bytes32 intentHash)", "function resolveDeterministic(bytes32 intentHash, bytes settlementProof)", "event ReceiptPosted(bytes32 indexed intentHash, address indexed solver, uint64 deadline)", "event ReceiptChallenged(bytes32 indexed intentHash, address indexed challenger, uint8 reason, uint256 bond)", "event ReceiptFinalized(bytes32 indexed intentHash)", "event ReceiptSlashed(bytes32 indexed intentHash, address indexed solver, uint256 slashAmount)", "event ChallengeResolved(bytes32 indexed intentHash, bool solverWins)"];
288
+ declare const DISPUTE_MODULE_ABI: readonly ["function evidenceWindow() view returns (uint64)", "function arbitrationTimeout() view returns (uint64)", "function arbitrator() view returns (address)", "function disputes(bytes32) view returns (bytes32 intentHash, address challenger, address solver, uint8 reason, bytes32 solverEvidence, bytes32 challengerEvidence, uint64 createdAt, uint64 evidenceDeadline, uint8 status, uint8 resolution)", "function getDispute(bytes32 intentHash) view returns (tuple(bytes32 intentHash, address challenger, address solver, uint8 reason, bytes32 solverEvidence, bytes32 challengerEvidence, uint64 createdAt, uint64 evidenceDeadline, uint8 status, uint8 resolution))", "function submitEvidence(bytes32 intentHash, bytes32 evidenceHash)", "function escalateToArbitration(bytes32 intentHash)", "function resolveArbitration(bytes32 intentHash, uint8 resolution, uint16 solverShareBps)", "function resolveByTimeout(bytes32 intentHash)", "event DisputeCreated(bytes32 indexed intentHash, address indexed challenger, address indexed solver, uint8 reason)", "event EvidenceSubmitted(bytes32 indexed intentHash, address indexed submitter, bytes32 evidenceHash)", "event DisputeEscalated(bytes32 indexed intentHash)", "event DisputeResolved(bytes32 indexed intentHash, uint8 resolution)"];
289
+
290
+ export { CHAIN_CONFIGS, CONSTANTS, type ChainConfig, type Challenge, type ChallengeParams, DISPUTE_MODULE_ABI, type Dispute, DisputeReason, DisputeResolution, DisputeStatus, INTENT_RECEIPT_HUB_ABI, IRSBClient, type IRSBClientConfig, type IntentReceipt, type PostReceiptParams, ReceiptStatus, SOLVER_REGISTRY_ABI, type SolverInfo, SolverStatus };