atfi 1.0.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 +453 -0
- package/dist/index.d.mts +1757 -0
- package/dist/index.d.ts +1757 -0
- package/dist/index.js +1410 -0
- package/dist/index.mjs +1369 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
# ATFi SDK
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for interacting with ATFi commitment vaults on Base.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install atfi viem
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { ATFiSDK } from 'atfi';
|
|
15
|
+
import { createPublicClient, createWalletClient, http, custom } from 'viem';
|
|
16
|
+
import { base } from 'viem/chains';
|
|
17
|
+
|
|
18
|
+
// Setup clients
|
|
19
|
+
const publicClient = createPublicClient({
|
|
20
|
+
chain: base,
|
|
21
|
+
transport: http(),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const walletClient = createWalletClient({
|
|
25
|
+
chain: base,
|
|
26
|
+
transport: custom(window.ethereum),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Initialize SDK
|
|
30
|
+
const sdk = new ATFiSDK(publicClient, walletClient);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## How It Works
|
|
34
|
+
|
|
35
|
+
**Every write function returns `{ simulation, execute() }`** - one call gives you everything:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
const action = await sdk.register({ vaultAddress: '0x...' });
|
|
39
|
+
|
|
40
|
+
// 1. Check simulation result (NO wallet popup yet!)
|
|
41
|
+
if (!action.simulation.success) {
|
|
42
|
+
console.error(action.simulation.error.message);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 2. Show user what will happen
|
|
47
|
+
console.log(`Stake: ${action.simulation.stakeAmount} ${action.simulation.tokenSymbol}`);
|
|
48
|
+
console.log(`Your balance: ${action.simulation.userBalance}`);
|
|
49
|
+
console.log(`Gas estimate: ${action.simulation.gasEstimate}`);
|
|
50
|
+
|
|
51
|
+
// 3. User confirms → execute with loading callbacks
|
|
52
|
+
const result = await action.execute({
|
|
53
|
+
onApproving: () => setStatus('Approving token...'),
|
|
54
|
+
onApproved: (hash) => setStatus('Token approved!'),
|
|
55
|
+
onSubmitting: () => setStatus('Submitting...'),
|
|
56
|
+
onSubmitted: (hash) => setStatus(`TX: ${hash}`),
|
|
57
|
+
onConfirming: () => setStatus('Confirming...'),
|
|
58
|
+
});
|
|
59
|
+
console.log('Done!', result.txHash);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Read-Only Mode
|
|
65
|
+
|
|
66
|
+
Show data before user connects wallet:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { ATFiSDK } from 'atfi';
|
|
70
|
+
import { createPublicClient, http } from 'viem';
|
|
71
|
+
import { base } from 'viem/chains';
|
|
72
|
+
|
|
73
|
+
// No wallet needed!
|
|
74
|
+
const publicClient = createPublicClient({
|
|
75
|
+
chain: base,
|
|
76
|
+
transport: http(),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const sdk = ATFiSDK.readOnly(publicClient);
|
|
80
|
+
|
|
81
|
+
// All read functions work
|
|
82
|
+
const events = await sdk.getAllEvents();
|
|
83
|
+
const info = await sdk.getEventInfo('0x...');
|
|
84
|
+
|
|
85
|
+
// Write functions throw helpful error
|
|
86
|
+
await sdk.register({ vaultAddress: '0x...' });
|
|
87
|
+
// Error: "SDK is in read-only mode. Initialize with a walletClient to perform write operations."
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## API Reference
|
|
93
|
+
|
|
94
|
+
### Create Event (Organizer)
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const action = await sdk.createEvent({
|
|
98
|
+
stakeAmount: '10', // 10 USDC
|
|
99
|
+
maxParticipants: 50,
|
|
100
|
+
useYield: true, // Enable Morpho yield
|
|
101
|
+
token: 'USDC', // 'USDC' or 'IDRX'
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (action.simulation.success) {
|
|
105
|
+
console.log('Expected vault ID:', action.simulation.expectedVaultId);
|
|
106
|
+
console.log('Token:', action.simulation.token.symbol);
|
|
107
|
+
console.log('Gas:', action.simulation.gasEstimate);
|
|
108
|
+
|
|
109
|
+
const result = await action.execute({
|
|
110
|
+
onSubmitting: () => showLoader('Creating event...'),
|
|
111
|
+
onConfirming: () => showLoader('Confirming...'),
|
|
112
|
+
});
|
|
113
|
+
console.log('Created:', result.vaultAddress);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Simulation returns:**
|
|
118
|
+
| Field | Type | Description |
|
|
119
|
+
|-------|------|-------------|
|
|
120
|
+
| `expectedVaultId` | bigint | Next vault ID |
|
|
121
|
+
| `token` | object | { address, symbol, decimals } |
|
|
122
|
+
| `stakeAmount` | string | Human readable stake |
|
|
123
|
+
| `maxParticipants` | number | Max allowed |
|
|
124
|
+
| `useYield` | boolean | Yield enabled |
|
|
125
|
+
| `gasEstimate` | bigint | Estimated gas |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
### Register (Participant)
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const action = await sdk.register({ vaultAddress: '0x...' });
|
|
133
|
+
|
|
134
|
+
if (action.simulation.success) {
|
|
135
|
+
console.log(`Stake: ${action.simulation.stakeAmount} ${action.simulation.tokenSymbol}`);
|
|
136
|
+
console.log(`Your balance: ${action.simulation.userBalance}`);
|
|
137
|
+
console.log(`Needs approval: ${action.simulation.needsApproval}`);
|
|
138
|
+
console.log(`Spots left: ${action.simulation.maxParticipants - action.simulation.currentParticipants}`);
|
|
139
|
+
|
|
140
|
+
// Callbacks for loading states (approval + stake transaction)
|
|
141
|
+
const result = await action.execute({
|
|
142
|
+
onApproving: () => showLoader('Approving USDC...'),
|
|
143
|
+
onApproved: (hash) => showToast(`Approved! ${hash}`),
|
|
144
|
+
onSubmitting: () => showLoader('Staking...'),
|
|
145
|
+
onConfirming: () => showLoader('Confirming...'),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Simulation returns:**
|
|
151
|
+
| Field | Type | Description |
|
|
152
|
+
|-------|------|-------------|
|
|
153
|
+
| `stakeAmount` | string | Amount to stake |
|
|
154
|
+
| `tokenSymbol` | string | USDC or IDRX |
|
|
155
|
+
| `userBalance` | string | Your token balance |
|
|
156
|
+
| `currentAllowance` | string | Current approval |
|
|
157
|
+
| `needsApproval` | boolean | Need approve TX first |
|
|
158
|
+
| `currentParticipants` | number | Current count |
|
|
159
|
+
| `maxParticipants` | number | Max allowed |
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### Start Event (Organizer)
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
const action = await sdk.startEvent({ vaultAddress: '0x...' });
|
|
167
|
+
|
|
168
|
+
if (action.simulation.success) {
|
|
169
|
+
console.log(`Total staked: ${action.simulation.totalStaked}`);
|
|
170
|
+
console.log(`Participants: ${action.simulation.participantCount}`);
|
|
171
|
+
console.log(`Has yield: ${action.simulation.hasYield}`);
|
|
172
|
+
|
|
173
|
+
const result = await action.execute();
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
### Verify Participants (Organizer)
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
const action = await sdk.verifyParticipant({
|
|
183
|
+
vaultAddress: '0x...',
|
|
184
|
+
participants: ['0xAddr1', '0xAddr2', '0xAddr3'],
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
if (action.simulation.success) {
|
|
188
|
+
console.log(`Will verify: ${action.simulation.toVerify.length}`);
|
|
189
|
+
console.log(`Already verified: ${action.simulation.alreadyVerified.length}`);
|
|
190
|
+
console.log(`Not staked: ${action.simulation.notStaked.length}`);
|
|
191
|
+
|
|
192
|
+
const result = await action.execute();
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Simulation returns:**
|
|
197
|
+
| Field | Type | Description |
|
|
198
|
+
|-------|------|-------------|
|
|
199
|
+
| `toVerify` | Address[] | Will be verified |
|
|
200
|
+
| `alreadyVerified` | Address[] | Already done |
|
|
201
|
+
| `notStaked` | Address[] | Not registered (will fail) |
|
|
202
|
+
| `currentVerified` | number | Current count |
|
|
203
|
+
| `newVerifiedCount` | number | Count after |
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
### Settle Event (Organizer)
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
const action = await sdk.settleEvent({ vaultAddress: '0x...' });
|
|
211
|
+
|
|
212
|
+
if (action.simulation.success) {
|
|
213
|
+
console.log(`Verified: ${action.simulation.verifiedCount}`);
|
|
214
|
+
console.log(`No-shows: ${action.simulation.noShowCount}`);
|
|
215
|
+
console.log(`Yield earned: ${action.simulation.estimatedYield}`);
|
|
216
|
+
console.log(`Protocol fees: ${action.simulation.estimatedProtocolFees}`);
|
|
217
|
+
console.log(`Reward per attendee: ${action.simulation.estimatedRewardPerParticipant}`);
|
|
218
|
+
|
|
219
|
+
const result = await action.execute();
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Simulation returns:**
|
|
224
|
+
| Field | Type | Description |
|
|
225
|
+
|-------|------|-------------|
|
|
226
|
+
| `totalStaked` | string | Total staked |
|
|
227
|
+
| `verifiedCount` | number | Attendees |
|
|
228
|
+
| `noShowCount` | number | No-shows |
|
|
229
|
+
| `estimatedYield` | string | Yield earned |
|
|
230
|
+
| `estimatedProtocolFees` | string | Protocol fees |
|
|
231
|
+
| `estimatedNoShowFees` | string | No-show fees |
|
|
232
|
+
| `estimatedRewardPerParticipant` | string | Reward each |
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### Claim Rewards (Participant)
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
const action = await sdk.claim({ vaultAddress: '0x...' });
|
|
240
|
+
|
|
241
|
+
if (action.simulation.success) {
|
|
242
|
+
console.log(`Total: ${action.simulation.claimableAmount} ${action.simulation.tokenSymbol}`);
|
|
243
|
+
console.log(`Your stake: ${action.simulation.stakeAmount}`);
|
|
244
|
+
console.log(`Bonus: ${action.simulation.bonusShare}`);
|
|
245
|
+
|
|
246
|
+
const result = await action.execute();
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Simulation returns:**
|
|
251
|
+
| Field | Type | Description |
|
|
252
|
+
|-------|------|-------------|
|
|
253
|
+
| `claimableAmount` | string | Total to claim |
|
|
254
|
+
| `tokenSymbol` | string | Token symbol |
|
|
255
|
+
| `stakeAmount` | string | Original stake |
|
|
256
|
+
| `bonusShare` | string | Bonus from no-shows + yield |
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Read Functions
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// Get event details
|
|
264
|
+
const info = await sdk.getEventInfo('0xVaultAddress');
|
|
265
|
+
|
|
266
|
+
// Get participant status
|
|
267
|
+
const status = await sdk.getParticipantStatus('0xVault', '0xParticipant');
|
|
268
|
+
|
|
269
|
+
// Get all events (batched for performance)
|
|
270
|
+
const events = await sdk.getAllEvents();
|
|
271
|
+
|
|
272
|
+
// Get vault by ID
|
|
273
|
+
const vault = await sdk.getVaultAddress(1);
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Token Balance Helpers
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
// Get single token balance
|
|
282
|
+
const usdcBalance = await sdk.getTokenBalance('0xUserAddress', 'USDC');
|
|
283
|
+
console.log(`USDC: ${usdcBalance}`); // "125.50"
|
|
284
|
+
|
|
285
|
+
// Get all supported token balances
|
|
286
|
+
const balances = await sdk.getAllTokenBalances('0xUserAddress');
|
|
287
|
+
console.log(balances);
|
|
288
|
+
// { USDC: "125.50", IDRX: "1000000.00" }
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## User-Centric Queries
|
|
294
|
+
|
|
295
|
+
Get events filtered by user:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// Events created by user
|
|
299
|
+
const myEvents = await sdk.getEventsByOwner('0xUserAddress');
|
|
300
|
+
|
|
301
|
+
// Events user registered for
|
|
302
|
+
const registered = await sdk.getRegisteredEvents('0xUserAddress');
|
|
303
|
+
|
|
304
|
+
// Events with unclaimed rewards
|
|
305
|
+
const claimable = await sdk.getClaimableEvents('0xUserAddress');
|
|
306
|
+
|
|
307
|
+
// Complete dashboard data (all in one call)
|
|
308
|
+
const dashboard = await sdk.getUserDashboard('0xUserAddress');
|
|
309
|
+
console.log(dashboard);
|
|
310
|
+
// {
|
|
311
|
+
// asOrganizer: [...], // Events user created
|
|
312
|
+
// asParticipant: [...], // Events user joined
|
|
313
|
+
// claimable: [...], // Ready to claim
|
|
314
|
+
// balances: { USDC: "125.50", IDRX: "1000000.00" }
|
|
315
|
+
// }
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Transaction Callbacks
|
|
321
|
+
|
|
322
|
+
All write functions accept callbacks for loading states:
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
interface TransactionCallbacks {
|
|
326
|
+
onApproving?: () => void; // Starting token approval
|
|
327
|
+
onApproved?: (txHash: Hash) => void; // Approval submitted
|
|
328
|
+
onSubmitting?: () => void; // Starting main transaction
|
|
329
|
+
onSubmitted?: (txHash: Hash) => void; // Transaction submitted
|
|
330
|
+
onConfirming?: () => void; // Waiting for confirmation
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Example: Full loading state management
|
|
334
|
+
const result = await action.execute({
|
|
335
|
+
onApproving: () => {
|
|
336
|
+
setStatus('approving');
|
|
337
|
+
setMessage('Please approve token in wallet...');
|
|
338
|
+
},
|
|
339
|
+
onApproved: (hash) => {
|
|
340
|
+
setMessage(`Approved! TX: ${hash.slice(0, 10)}...`);
|
|
341
|
+
},
|
|
342
|
+
onSubmitting: () => {
|
|
343
|
+
setStatus('submitting');
|
|
344
|
+
setMessage('Please confirm transaction in wallet...');
|
|
345
|
+
},
|
|
346
|
+
onSubmitted: (hash) => {
|
|
347
|
+
setMessage(`Submitted! TX: ${hash.slice(0, 10)}...`);
|
|
348
|
+
setTxHash(hash);
|
|
349
|
+
},
|
|
350
|
+
onConfirming: () => {
|
|
351
|
+
setStatus('confirming');
|
|
352
|
+
setMessage('Waiting for blockchain confirmation...');
|
|
353
|
+
},
|
|
354
|
+
});
|
|
355
|
+
setStatus('success');
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Real-Time Event Watching
|
|
361
|
+
|
|
362
|
+
Subscribe to vault events for live UI updates:
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
const unwatch = sdk.watchVault('0xVaultAddress', {
|
|
366
|
+
onParticipantJoined: (address, total) => {
|
|
367
|
+
console.log(`${address} joined! Total: ${total}`);
|
|
368
|
+
updateParticipantList();
|
|
369
|
+
},
|
|
370
|
+
onParticipantVerified: (address, totalVerified) => {
|
|
371
|
+
console.log(`${address} verified!`);
|
|
372
|
+
updateVerifiedCount(totalVerified);
|
|
373
|
+
},
|
|
374
|
+
onSettled: (totalYield, protocolFee) => {
|
|
375
|
+
console.log(`Event settled! Yield: ${totalYield}`);
|
|
376
|
+
showClaimButton();
|
|
377
|
+
},
|
|
378
|
+
onClaimed: (address, amount) => {
|
|
379
|
+
console.log(`${address} claimed ${amount}`);
|
|
380
|
+
},
|
|
381
|
+
onStakingStatusChanged: (isOpen) => {
|
|
382
|
+
updateRegistrationStatus(isOpen);
|
|
383
|
+
},
|
|
384
|
+
onError: (error) => {
|
|
385
|
+
console.error('Watch error:', error);
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// Stop watching when done
|
|
390
|
+
unwatch();
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Error Handling
|
|
396
|
+
|
|
397
|
+
Errors are returned in simulation, not thrown:
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
const action = await sdk.register({ vaultAddress: '0x...' });
|
|
401
|
+
|
|
402
|
+
if (!action.simulation.success) {
|
|
403
|
+
switch (action.simulation.error.code) {
|
|
404
|
+
case 'STAKING_CLOSED':
|
|
405
|
+
showMessage('Registration ended');
|
|
406
|
+
break;
|
|
407
|
+
case 'ALREADY_STAKED':
|
|
408
|
+
showMessage('Already registered');
|
|
409
|
+
break;
|
|
410
|
+
case 'INSUFFICIENT_BALANCE':
|
|
411
|
+
showMessage(`Need ${action.simulation.stakeAmount} ${action.simulation.tokenSymbol}`);
|
|
412
|
+
break;
|
|
413
|
+
case 'MAX_PARTICIPANTS_REACHED':
|
|
414
|
+
showMessage('Event is full');
|
|
415
|
+
break;
|
|
416
|
+
default:
|
|
417
|
+
showMessage(action.simulation.error.message);
|
|
418
|
+
}
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
**Error Codes:**
|
|
424
|
+
- `STAKING_CLOSED` - Registration ended
|
|
425
|
+
- `ALREADY_STAKED` - Already registered
|
|
426
|
+
- `INSUFFICIENT_BALANCE` - Not enough tokens
|
|
427
|
+
- `MAX_PARTICIPANTS_REACHED` - Event full
|
|
428
|
+
- `NOT_OWNER` - Not event owner
|
|
429
|
+
- `EVENT_ALREADY_STARTED` - Already started
|
|
430
|
+
- `VAULT_ALREADY_SETTLED` - Already settled
|
|
431
|
+
- `VAULT_NOT_SETTLED` - Not settled yet
|
|
432
|
+
- `NOT_VERIFIED` - Not verified for attendance
|
|
433
|
+
- `ALREADY_CLAIMED` - Already claimed
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Supported Tokens
|
|
438
|
+
|
|
439
|
+
| Token | Address | Decimals | Yield |
|
|
440
|
+
|-------|---------|----------|-------|
|
|
441
|
+
| USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | 6 | Yes |
|
|
442
|
+
| IDRX | `0x18Bc5bcC660cf2B9cE3cd51a404aFe1a0cBD3C22` | 2 | No |
|
|
443
|
+
|
|
444
|
+
## Contract Addresses (Base Mainnet)
|
|
445
|
+
|
|
446
|
+
| Contract | Address |
|
|
447
|
+
|----------|---------|
|
|
448
|
+
| FactoryATFi | `0x0be05a5fa7116c1b33f2b0036eb0d9690db9075f` |
|
|
449
|
+
| Morpho Vault | `0x050cE30b927Da55177A4914EC73480238BAD56f0` |
|
|
450
|
+
|
|
451
|
+
## License
|
|
452
|
+
|
|
453
|
+
MIT
|