@hammerock/cca-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/LICENSE +21 -0
- package/README.md +145 -0
- package/dist/chunk-ABCX23D6.js +446 -0
- package/dist/chunk-ABCX23D6.js.map +1 -0
- package/dist/erc20-C3yff839.d.cts +231 -0
- package/dist/erc20-C3yff839.d.ts +231 -0
- package/dist/index.cjs +998 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2717 -0
- package/dist/index.d.ts +2717 -0
- package/dist/index.js +485 -0
- package/dist/index.js.map +1 -0
- package/dist/node.cjs +448 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +97 -0
- package/dist/node.d.ts +97 -0
- package/dist/node.js +277 -0
- package/dist/node.js.map +1 -0
- package/package.json +84 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shubham Singh Shoora
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# @hammerock/cca-sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for [Uniswap Continuous Clearing Auctions](https://github.com/Uniswap/continuous-clearing-auction) (CCA), built on [viem](https://viem.sh).
|
|
4
|
+
|
|
5
|
+
It handles auction discovery, live state, Q96 price math, token metadata, and building `submitBid` transactions correctly. That last part covers the parts of the protocol that are easy to get wrong: ERC-20 bids go through Permit2, and bid prices must sit on a tick boundary.
|
|
6
|
+
|
|
7
|
+
> **Testnet only.** `createBeaconClient` rejects every chain id except Sepolia (11155111), Base Sepolia (84532) and Unichain Sepolia (1301).
|
|
8
|
+
|
|
9
|
+
Built against the `ContinuousClearingAuctionFactory` **v1.1.0** at `0xCCccCcCAE7503Cac057829BF2811De42E16e0bD5`. The ABIs are compiled from upstream tag `v1.1.0`, not hand-written.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @hammerock/cca-sdk viem
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`viem` is a peer dependency, so your app and the SDK share one copy.
|
|
18
|
+
|
|
19
|
+
## Read an auction
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { createBeaconClient, getAuctionSummary, formatTokenAmount } from "@hammerock/cca-sdk";
|
|
23
|
+
|
|
24
|
+
const client = createBeaconClient({
|
|
25
|
+
rpcUrl: "https://ethereum-sepolia-rpc.publicnode.com",
|
|
26
|
+
chainId: 11155111,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const summary = await getAuctionSummary(client, "0x1e40451D6ecabA8640559b7dFbe63B41dA52460d");
|
|
30
|
+
|
|
31
|
+
console.log(summary.status); // "pending" | "live" | "ended"
|
|
32
|
+
console.log(summary.clearingPrice); // human-readable price
|
|
33
|
+
console.log(summary.state.isGraduated);
|
|
34
|
+
console.log(summary.secondsRemaining);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**No lens deployment needed.** Uniswap publishes no `CCALens` address. `getAuctionState` runs `AuctionStateLens` inside a single `eth_call` using a state override, so it works against any standard RPC. If you have deployed a lens yourself, pass `lensAddress` to `createBeaconClient`.
|
|
38
|
+
|
|
39
|
+
## Discover auctions
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { scanAuctions, watchAuctions } from "@hammerock/cca-sdk";
|
|
43
|
+
|
|
44
|
+
const auctions = await scanAuctions(client); // every AuctionCreated since the factory deployed
|
|
45
|
+
const stop = watchAuctions(client, (a) => console.log("new auction", a.auction));
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`eth_getLogs` is always chunked (50,000 blocks by default), halves the chunk size when a provider rejects a range, and re-queries empty chunks. Some public RPCs silently return an empty result for a range that has logs. Alchemy's free tier caps `eth_getLogs` at 10 blocks, so pass a separate `logsRpcUrl` for scanning.
|
|
49
|
+
|
|
50
|
+
## Place a bid
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import {
|
|
54
|
+
buildBidTransactions,
|
|
55
|
+
checkBidReadiness,
|
|
56
|
+
decimalToQ96,
|
|
57
|
+
getAuctionInfo,
|
|
58
|
+
getPrevTickHint,
|
|
59
|
+
} from "@hammerock/cca-sdk";
|
|
60
|
+
|
|
61
|
+
const info = await getAuctionInfo(client, auction);
|
|
62
|
+
const maxPriceQ96 = decimalToQ96("0.00000000000000000006");
|
|
63
|
+
const amount = 1_000_000_000_000_000n; // in the currency's smallest unit
|
|
64
|
+
|
|
65
|
+
const readiness = await checkBidReadiness(client, {
|
|
66
|
+
auction,
|
|
67
|
+
currency: info.currency,
|
|
68
|
+
bidder,
|
|
69
|
+
amount,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const steps = buildBidTransactions({
|
|
73
|
+
auction,
|
|
74
|
+
currency: info.currency,
|
|
75
|
+
maxPriceQ96,
|
|
76
|
+
amount,
|
|
77
|
+
owner: bidder,
|
|
78
|
+
readiness,
|
|
79
|
+
prevTickPriceQ96: await getPrevTickHint(client, auction, maxPriceQ96),
|
|
80
|
+
tickSpacing: info.tickSpacing,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
for (const { label, request } of steps) {
|
|
84
|
+
// Send each with your own wallet client, waiting for approvals to land first.
|
|
85
|
+
await walletClient.sendTransaction({ ...request, account, chain });
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`buildBidTransactions` returns only the steps that are actually needed:
|
|
90
|
+
|
|
91
|
+
| Currency | Transactions |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| Native ETH | `submitBid` with `value` equal to the amount |
|
|
94
|
+
| ERC-20 | `approve(Permit2)` → `Permit2.approve(token, auction)` → `submitBid` with `value` 0, skipping any approval already in place |
|
|
95
|
+
|
|
96
|
+
Things it handles for you, each of which reverts on-chain if done wrong:
|
|
97
|
+
|
|
98
|
+
- **ERC-20 bids go through Permit2.** The auction pulls funds with Permit2's `transferFrom`, so approving the auction directly does nothing.
|
|
99
|
+
- **Bid prices must be a multiple of `tickSpacing`**, or `submitBid` reverts with `TickPriceNotAtBoundary()`. Prices are snapped **down**, so a bidder's ceiling never rises.
|
|
100
|
+
- **Native bids must send `msg.value == amount` exactly**, and ERC-20 bids must send no value.
|
|
101
|
+
|
|
102
|
+
The SDK never signs or broadcasts anything. You send the returned requests with your own wallet.
|
|
103
|
+
|
|
104
|
+
## Q96 prices
|
|
105
|
+
|
|
106
|
+
CCA prices are Q96 fixed-point numbers (value × 2⁹⁶).
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { decimalToQ96, q96ToDecimalString, formatQ96, formatQ96Compact } from "@hammerock/cca-sdk";
|
|
110
|
+
|
|
111
|
+
decimalToQ96("0.0001"); // truncates DOWN - safe for price caps
|
|
112
|
+
q96ToDecimalString(value, 18); // exact, truncating
|
|
113
|
+
formatQ96(value); // rounded for display
|
|
114
|
+
formatQ96Compact(value); // "5.42118e-20" for very small prices
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`cumulativeMps` tracks how much of the supply **schedule** has been released. It is **not** the amount sold: an auction that closes with no bids still reaches 100%. Use `totalCleared` and `currencyRaised` for what actually sold.
|
|
118
|
+
|
|
119
|
+
## Node-only helpers
|
|
120
|
+
|
|
121
|
+
Anything that touches the filesystem is in a separate entry point, so the main entry stays safe for browser bundles:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { JsonAuctionStore, syncAuctions, enrichStore } from "@hammerock/cca-sdk/node";
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## API overview
|
|
128
|
+
|
|
129
|
+
| Area | Exports |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| Client | `createBeaconClient`, `assertSupportedChain`, `assertChainMatches` |
|
|
132
|
+
| Read | `getAuctionState`, `getAuctionInfo`, `getAuctionSummary`, `getAuctionSummaries`, `getAuctionListStates`, `getClearingPrice`, `isGraduated`, `deriveStatus` |
|
|
133
|
+
| Discover | `scanAuctions`, `watchAuctions`, `scanAuctionsForToken`, `auctionCreatedEvent` |
|
|
134
|
+
| Write | `buildBidTransactions`, `encodeSubmitBid`, `checkBidReadiness`, `getPrevTickHint`, `alignPriceToTickBoundary`, `describeBidBlocker`, `encodeApproveErc20ToPermit2`, `encodeApprovePermit2` |
|
|
135
|
+
| Tokens | `getTokenMetadata`, `formatTokenAmount` |
|
|
136
|
+
| Q96 | `decimalToQ96`, `q96ToDecimalString`, `q96ToNumber`, `formatQ96`, `formatQ96Compact`, `mpsToFraction` |
|
|
137
|
+
| Auction config | `encodeAuctionParameters`, `decodeAuctionParameters`, `buildAuctionSteps`, `validateAuctionParameters` |
|
|
138
|
+
| ABIs | `auctionAbi`, `factoryAbi`, `auctionStateLensAbi`, `UPSTREAM_TAG`, `UPSTREAM_COMMIT` |
|
|
139
|
+
| Constants | `FACTORY_ADDRESS`, `PERMIT2_ADDRESS`, `NATIVE_CURRENCY`, `SUPPORTED_CHAINS` |
|
|
140
|
+
|
|
141
|
+
Full source, tests and the apps built on this SDK: [github.com/Shubham-Singh-Shoora/Beacon-](https://github.com/Shubham-Singh-Shoora/Beacon-).
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT
|