liquid-sdk 1.7.3 → 1.7.4
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/AGENT_README.md +112 -46
- package/CHANGELOG.md +10 -0
- package/README.md +239 -119
- package/dist/index.d.mts +55 -26
- package/dist/index.d.ts +55 -26
- package/dist/index.js +46 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +43 -2
- package/dist/index.mjs.map +1 -1
- package/llms.txt +6 -6
- package/package.json +1 -1
- package/skills/deploy-token.md +1 -1
- package/skills/index-tokens.md +2 -2
- package/skills/sdk-overview.md +8 -8
package/AGENT_README.md
CHANGED
|
@@ -35,7 +35,7 @@ No API keys, no backend, no database. The SDK talks directly to Base mainnet con
|
|
|
35
35
|
Liquid Protocol deploys ERC-20 tokens on Base with:
|
|
36
36
|
- Uniswap V4 liquidity pools (automatic)
|
|
37
37
|
- LP fee collection and reward distribution
|
|
38
|
-
- MEV protection via
|
|
38
|
+
- MEV protection via sniper auction
|
|
39
39
|
- Optional extensions: dev buy, vault lockup/vesting, airdrops
|
|
40
40
|
|
|
41
41
|
Every token gets 100 billion supply (18 decimals), a Uniswap V4 pool, and locked liquidity with configurable reward splits.
|
|
@@ -54,7 +54,7 @@ Requires wallet. Creates the token, pool, locks LP, and optionally buys tokens a
|
|
|
54
54
|
const result = await sdk.deployToken({
|
|
55
55
|
name: "My Token",
|
|
56
56
|
symbol: "MTK",
|
|
57
|
-
image: "
|
|
57
|
+
image: "ipfs://QmYourImageCID", // optional, IPFS recommended
|
|
58
58
|
metadata: '{"description":"A cool token"}', // optional, JSON string
|
|
59
59
|
context: '{"platform":"my-app"}', // optional, tracking/attribution
|
|
60
60
|
|
|
@@ -100,27 +100,27 @@ const ext = sdk.buildDevBuyExtension({
|
|
|
100
100
|
|
|
101
101
|
Tokens generate LP fees from Uniswap V4 trading. These accrue in the Fee Locker and can be claimed by the fee owner.
|
|
102
102
|
|
|
103
|
-
#### `sdk.getAvailableFees(feeOwner,
|
|
103
|
+
#### `sdk.getAvailableFees(feeOwner, tokenAddress)` — Check total unlocked fees
|
|
104
104
|
|
|
105
105
|
```typescript
|
|
106
|
-
const fees = await sdk.getAvailableFees(ownerAddress);
|
|
107
|
-
// fees: bigint — total fees available,
|
|
106
|
+
const fees = await sdk.getAvailableFees(ownerAddress, tokenAddress);
|
|
107
|
+
// fees: bigint — total fees available (in token's paired asset, usually WETH)
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
-
#### `sdk.getFeesToClaim(feeOwner,
|
|
110
|
+
#### `sdk.getFeesToClaim(feeOwner, tokenAddress)` — Check claimable fees
|
|
111
111
|
|
|
112
112
|
```typescript
|
|
113
|
-
const claimable = await sdk.getFeesToClaim(ownerAddress);
|
|
114
|
-
// claimable: bigint — fees ready to claim right now
|
|
113
|
+
const claimable = await sdk.getFeesToClaim(ownerAddress, tokenAddress);
|
|
114
|
+
// claimable: bigint — fees ready to claim right now
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
-
#### `sdk.claimFees(feeOwner,
|
|
117
|
+
#### `sdk.claimFees(feeOwner, tokenAddress)` — Claim fees
|
|
118
118
|
|
|
119
119
|
Requires wallet.
|
|
120
120
|
|
|
121
121
|
```typescript
|
|
122
122
|
if (claimable > 0n) {
|
|
123
|
-
const txHash = await sdk.claimFees(ownerAddress);
|
|
123
|
+
const txHash = await sdk.claimFees(ownerAddress, tokenAddress);
|
|
124
124
|
await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
125
125
|
}
|
|
126
126
|
```
|
|
@@ -161,7 +161,7 @@ const txHash = await sdk.collectRewardsWithoutUnlock(tokenAddress);
|
|
|
161
161
|
await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
**Important:** After deployment, the
|
|
164
|
+
**Important:** After deployment, the sniper auction MEV module may block early reward collection. If `collectRewardsWithoutUnlock` reverts with `ManagerLocked`, wait for the auction period to end.
|
|
165
165
|
|
|
166
166
|
#### `sdk.updateRewardRecipient(tokenAddress, rewardIndex, newRecipient)` — Change reward recipient
|
|
167
167
|
|
|
@@ -284,6 +284,49 @@ const deploy = await sdk.getDeploymentInfo(tokenAddress);
|
|
|
284
284
|
|
|
285
285
|
---
|
|
286
286
|
|
|
287
|
+
### Token Discovery
|
|
288
|
+
|
|
289
|
+
#### `sdk.getTokens(options?)` — Query all deployed tokens
|
|
290
|
+
|
|
291
|
+
Query TokenCreated events with optional filtering. For wallet integrations, token listings, and indexing.
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
// Get all tokens
|
|
295
|
+
const allTokens = await sdk.getTokens();
|
|
296
|
+
|
|
297
|
+
// Get tokens by deployer
|
|
298
|
+
const myTokens = await sdk.getTokens({ deployer: myAddress });
|
|
299
|
+
|
|
300
|
+
// Paginate with block ranges
|
|
301
|
+
const page1 = await sdk.getTokens({ fromBlock: 20000000n, toBlock: 20100000n });
|
|
302
|
+
const page2 = await sdk.getTokens({ fromBlock: 20100001n });
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Each result includes full on-chain event data: name, symbol, image, metadata, context, poolId, hook, locker, extensions, and `blockNumber` for cursor-based pagination.
|
|
306
|
+
|
|
307
|
+
#### `sdk.getTokenEvent(tokenAddress)` — Look up a single token's event data
|
|
308
|
+
|
|
309
|
+
Fast lookup by contract address (tokenAddress is indexed on-chain = single RPC call).
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
const event = await sdk.getTokenEvent(tokenAddress);
|
|
313
|
+
// event.tokenName, event.tokenSymbol, event.tokenImage
|
|
314
|
+
// event.tokenMetadata — parse with parseMetadata()
|
|
315
|
+
// event.tokenContext — parse with parseContext()
|
|
316
|
+
// event.poolId, event.poolHook, event.locker, event.extensions
|
|
317
|
+
// event.blockNumber
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### `sdk.getDeployedTokens(deployer, fromBlock?, toBlock?)` — Get tokens by deployer
|
|
321
|
+
|
|
322
|
+
Convenience wrapper around `getTokens({ deployer })`.
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
const tokens = await sdk.getDeployedTokens(deployerAddress);
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
287
330
|
### Token Metadata Updates
|
|
288
331
|
|
|
289
332
|
#### `sdk.updateImage(tokenAddress, newImageUrl)` — Update token image
|
|
@@ -385,27 +428,50 @@ const maxRounds = await sdk.getAuctionMaxRounds();
|
|
|
385
428
|
```typescript
|
|
386
429
|
const gasPrice = await sdk.getAuctionGasPriceForBid(
|
|
387
430
|
auction.gasPeg,
|
|
388
|
-
parseEther("
|
|
431
|
+
parseEther("0.001"), // desired bid
|
|
389
432
|
);
|
|
390
433
|
```
|
|
391
434
|
|
|
435
|
+
#### `sdk.bidInAuction(params, gasPrice)` — Bid in auction and swap tokens
|
|
436
|
+
|
|
437
|
+
Requires wallet. Auto-wraps ETH → WETH and approves SniperUtilV2 if needed. Sets gas manually (800K) and both `maxFeePerGas`/`maxPriorityFeePerGas` to the auction gas price.
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
const rewards = await sdk.getTokenRewards(tokenAddress);
|
|
441
|
+
const zeroForOne = rewards.poolKey.currency0.toLowerCase() === EXTERNAL.WETH.toLowerCase();
|
|
442
|
+
|
|
443
|
+
const result = await sdk.bidInAuction({
|
|
444
|
+
poolKey: rewards.poolKey,
|
|
445
|
+
zeroForOne, // depends on token sort order vs WETH
|
|
446
|
+
amountIn: parseEther("0.001"), // WETH to swap (auto-wrapped from ETH)
|
|
447
|
+
amountOutMinimum: 0n, // set slippage in production
|
|
448
|
+
round: auction.round, // must match current on-chain round
|
|
449
|
+
bidAmount: parseEther("0.0005"), // ETH bid (sent as msg.value)
|
|
450
|
+
}, gasPrice);
|
|
451
|
+
// result.txHash — transaction hash
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
**Important:** The bid is valid only at `nextAuctionBlock`. Submit when `currentBlock === nextAuctionBlock - 1`. The `amountIn` is pulled from your WETH balance (separate from the bid's `msg.value`). Auction runs 5 rounds, every 2 blocks, starting 2 blocks after deployment.
|
|
455
|
+
|
|
392
456
|
---
|
|
393
457
|
|
|
394
|
-
### MEV
|
|
458
|
+
### MEV Descending Fees
|
|
395
459
|
|
|
396
|
-
#### `sdk.
|
|
460
|
+
#### `sdk.getMevDescendingFeesBlockDelay()` — Configured block delay
|
|
397
461
|
|
|
398
462
|
```typescript
|
|
399
|
-
const delay = await sdk.
|
|
400
|
-
// delay: bigint — number of blocks
|
|
463
|
+
const delay = await sdk.getMevDescendingFeesBlockDelay();
|
|
464
|
+
// delay: bigint — number of blocks the MEV module fee window covers
|
|
401
465
|
```
|
|
402
466
|
|
|
403
|
-
|
|
467
|
+
`sdk.getMevBlockDelay()` is a deprecated alias for the same call.
|
|
468
|
+
|
|
469
|
+
#### `sdk.getPoolUnlockTime(poolId)` — When MEV lock expires
|
|
404
470
|
|
|
405
471
|
```typescript
|
|
406
472
|
const unlockTime = await sdk.getPoolUnlockTime(poolId);
|
|
407
|
-
// unlockTime
|
|
408
|
-
//
|
|
473
|
+
// If Date.now()/1000 < unlockTime, the pool is still inside the MEV window
|
|
474
|
+
// and writes that go through the MevDescendingFees hook may revert with ManagerLocked.
|
|
409
475
|
```
|
|
410
476
|
|
|
411
477
|
---
|
|
@@ -442,20 +508,20 @@ When calling `deployToken`, all fields except `name` and `symbol` are optional.
|
|
|
442
508
|
| `salt` | `keccak256(name + symbol + timestamp)` | Unique per deploy |
|
|
443
509
|
| `image` | `""` | Empty string |
|
|
444
510
|
| `metadata` | `""` | Empty string |
|
|
445
|
-
| `context` | `""` |
|
|
446
|
-
| `hook` | `ADDRESSES.
|
|
511
|
+
| `context` | `'{"interface":"SDK"}'` | Auto-set via `buildContext()` |
|
|
512
|
+
| `hook` | `ADDRESSES.HOOK_STATIC_FEE_V2` | Static 1% buy + 1% sell |
|
|
447
513
|
| `pairedToken` | `EXTERNAL.WETH` | Base WETH |
|
|
448
|
-
| `tickIfToken0IsLiquid` | `-
|
|
449
|
-
| `tickSpacing` | `
|
|
450
|
-
| `poolData` | `
|
|
451
|
-
| `locker` | `ADDRESSES.
|
|
514
|
+
| `tickIfToken0IsLiquid` | `-230400` | ≈10 ETH market cap |
|
|
515
|
+
| `tickSpacing` | `200` | Uniswap V4 tick spacing |
|
|
516
|
+
| `poolData` | `encodeStaticFeePoolData(100, 100)` | 1% sell, 1% buy |
|
|
517
|
+
| `locker` | `ADDRESSES.LP_LOCKER_FEE_CONVERSION` | LP locker with fee conversion to ETH |
|
|
452
518
|
| `rewardAdmins` | `[walletAddress]` | Deployer is admin |
|
|
453
519
|
| `rewardRecipients` | `[walletAddress]` | Deployer gets rewards |
|
|
454
520
|
| `rewardBps` | `[10000]` | 100% to deployer |
|
|
455
|
-
| `tickLower` | `[-
|
|
456
|
-
| `tickUpper` | `[
|
|
457
|
-
| `positionBps` | `[
|
|
458
|
-
| `mevModule` | `ADDRESSES.
|
|
521
|
+
| `tickLower` | `[-230400, -216000, -202000, -155000, -141000]` | 5-position Liquid layout |
|
|
522
|
+
| `tickUpper` | `[-216000, -155000, -155000, -120000, -120000]` | 5-position Liquid layout |
|
|
523
|
+
| `positionBps` | `[1000, 5000, 1500, 2000, 500]` | 10% / 50% / 15% / 20% / 5% |
|
|
524
|
+
| `mevModule` | `ADDRESSES.SNIPER_AUCTION_V2` | 80%→40% over 20s |
|
|
459
525
|
| `extensions` | `[]` | No extensions |
|
|
460
526
|
|
|
461
527
|
---
|
|
@@ -468,19 +534,18 @@ All addresses are exported as `ADDRESSES` and `EXTERNAL`:
|
|
|
468
534
|
import { ADDRESSES, EXTERNAL } from "liquid-sdk";
|
|
469
535
|
|
|
470
536
|
// Liquid Protocol contracts
|
|
471
|
-
ADDRESSES.FACTORY //
|
|
472
|
-
ADDRESSES.
|
|
473
|
-
ADDRESSES.FEE_LOCKER //
|
|
474
|
-
ADDRESSES.VAULT //
|
|
475
|
-
ADDRESSES.HOOK_DYNAMIC_FEE_V2 //
|
|
476
|
-
ADDRESSES.HOOK_STATIC_FEE_V2 //
|
|
477
|
-
ADDRESSES.AIRDROP_V2 //
|
|
478
|
-
ADDRESSES.SNIPER_AUCTION_V2 //
|
|
479
|
-
ADDRESSES.SNIPER_UTIL_V2 //
|
|
480
|
-
ADDRESSES.
|
|
481
|
-
ADDRESSES.UNIV4_ETH_DEV_BUY //
|
|
482
|
-
ADDRESSES.POOL_EXTENSION_ALLOWLIST //
|
|
483
|
-
ADDRESSES.LIQUID_DEPLOYER_LIB // 0x00000f88b2d37A2006F2F0C8552d22E0b8945202
|
|
537
|
+
ADDRESSES.FACTORY // 0x04F1a284168743759BE6554f607a10CEBdB77760
|
|
538
|
+
ADDRESSES.LP_LOCKER_FEE_CONVERSION // 0x77247fCD1d5e34A3703AcA898A591Dc7422435f3
|
|
539
|
+
ADDRESSES.FEE_LOCKER // 0xF7d3BE3FC0de76fA5550C29A8F6fa53667B876FF
|
|
540
|
+
ADDRESSES.VAULT // 0xdFCCC93257c20519A9005A2281CFBdF84836d50E
|
|
541
|
+
ADDRESSES.HOOK_DYNAMIC_FEE_V2 // 0x80E2F7dC8C2C880BbC4BDF80A5Fb0eB8B1DB68CC
|
|
542
|
+
ADDRESSES.HOOK_STATIC_FEE_V2 // 0x9811f10Cd549c754Fa9E5785989c422A762c28cc
|
|
543
|
+
ADDRESSES.AIRDROP_V2 // 0x1423974d48f525462f1c087cBFdCC20BDBc33CdD
|
|
544
|
+
ADDRESSES.SNIPER_AUCTION_V2 // 0x187e8627c02c58F31831953C1268e157d3BfCefd
|
|
545
|
+
ADDRESSES.SNIPER_UTIL_V2 // 0x2B6cd5Be183c388Dd0074d53c52317df1414cd9f
|
|
546
|
+
ADDRESSES.MEV_DESCENDING_FEES // 0x8D6B080e48756A99F3893491D556B5d6907b6910
|
|
547
|
+
ADDRESSES.UNIV4_ETH_DEV_BUY // 0x5934097864dC487D21A7B4e4EEe201A39ceF728D
|
|
548
|
+
ADDRESSES.POOL_EXTENSION_ALLOWLIST // 0xb614167d79aDBaA9BA35d05fE1d5542d7316Ccaa
|
|
484
549
|
|
|
485
550
|
// External (Uniswap V4 / Base)
|
|
486
551
|
EXTERNAL.POOL_MANAGER // 0x498581fF718922c3f8e6A244956aF099B2652b2b
|
|
@@ -524,7 +589,8 @@ import {
|
|
|
524
589
|
LiquidSniperUtilV2Abi,
|
|
525
590
|
LiquidAirdropV2Abi,
|
|
526
591
|
LiquidPoolExtensionAllowlistAbi,
|
|
527
|
-
|
|
592
|
+
LiquidMevDescendingFeesAbi,
|
|
593
|
+
LiquidMevBlockDelayAbi, // deprecated alias — prefer LiquidMevDescendingFeesAbi
|
|
528
594
|
LiquidLpLockerAbi,
|
|
529
595
|
ERC20Abi,
|
|
530
596
|
} from "liquid-sdk";
|
|
@@ -579,7 +645,7 @@ const sdk = new LiquidSDK({ publicClient, walletClient });
|
|
|
579
645
|
const result = await sdk.deployToken({
|
|
580
646
|
name: "Agent Token",
|
|
581
647
|
symbol: "AGENT",
|
|
582
|
-
image: "
|
|
648
|
+
image: "ipfs://QmYourImageCID",
|
|
583
649
|
metadata: JSON.stringify({ description: "Deployed by an AI agent" }),
|
|
584
650
|
devBuy: {
|
|
585
651
|
ethAmount: parseEther("0.01"),
|
|
@@ -618,11 +684,11 @@ if (now < unlockTime) {
|
|
|
618
684
|
### 3. Check and claim fees
|
|
619
685
|
|
|
620
686
|
```typescript
|
|
621
|
-
const fees = await sdk.getFeesToClaim(ownerAddress);
|
|
687
|
+
const fees = await sdk.getFeesToClaim(ownerAddress, tokenAddress);
|
|
622
688
|
console.log("Claimable fees:", fees);
|
|
623
689
|
|
|
624
690
|
if (fees > 0n) {
|
|
625
|
-
const txHash = await sdk.claimFees(ownerAddress);
|
|
691
|
+
const txHash = await sdk.claimFees(ownerAddress, tokenAddress);
|
|
626
692
|
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
627
693
|
console.log("Fees claimed in tx:", receipt.transactionHash);
|
|
628
694
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `liquid-sdk` will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.7.4] - 2026-04-23
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- `EXTERNAL.DIEM` — the DIEM token address on Base, for DIEM-paired token launches.
|
|
9
|
+
- `shiftPositions(positions, shiftBy)` — re-anchor a fixed-shape position layout to a different starting tick, preserving `positionBps`.
|
|
10
|
+
- `createLiquidPositionsUSD(startingMarketCapUSD, pairedTokenPriceUSD, tickSpacing?)` — the canonical 5-position "Liquid" layout re-anchored to a starting market cap, denominated in the *paired token's* USD price. Works for any pair token (WETH or DIEM); unlike `createDefaultPositions` (3-tranche), it preserves the exact `POOL_POSITIONS.Liquid` curve `deployToken()` uses by default.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- `deployToken` gas estimation no longer silently swallows on-chain revert errors. Previously a failing `eth_estimateGas` (e.g., insufficient msg.value, paused factory, pre-flight check revert) would be caught and replaced with a 6M fallback, causing the tx to be broadcast and burn real gas for nothing. Now a revert-shaped error bubbles to the caller; only transport-level failures fall back. Non-revert fallbacks log a warning via `console.warn`.
|
|
14
|
+
|
|
5
15
|
## [1.7.3] - 2026-04-22
|
|
6
16
|
|
|
7
17
|
### Added
|