levr-sdk 0.0.1
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.md +201 -0
- package/README.md +711 -0
- package/dist/esm/abis/IClankerAirdrop.js +443 -0
- package/dist/esm/abis/IClankerHookDynamicFee.js +198 -0
- package/dist/esm/abis/IClankerHookStaticFee.js +75 -0
- package/dist/esm/abis/IClankerLPLocker.js +402 -0
- package/dist/esm/abis/IClankerLpLockerMultiple.js +609 -0
- package/dist/esm/abis/IClankerToken.js +421 -0
- package/dist/esm/abis/LevrFactory_v1.js +608 -0
- package/dist/esm/abis/LevrForwarder_v1.js +622 -0
- package/dist/esm/abis/LevrGovernor_v1.js +726 -0
- package/dist/esm/abis/LevrStakedToken_v1.js +441 -0
- package/dist/esm/abis/LevrStaking_v1.js +607 -0
- package/dist/esm/abis/LevrTreasury_v1.js +219 -0
- package/dist/esm/abis/Permit2.js +29 -0
- package/dist/esm/abis/V4Quoter.js +466 -0
- package/dist/esm/abis/WETH9.js +153 -0
- package/dist/esm/abis/index.js +23 -0
- package/dist/esm/balance.js +72 -0
- package/dist/esm/balance.js.map +1 -0
- package/dist/esm/build-calldatas-v4.js +98 -0
- package/dist/esm/build-calldatas-v4.js.map +1 -0
- package/dist/esm/build-clanker-v4.js +128 -0
- package/dist/esm/build-clanker-v4.js.map +1 -0
- package/dist/esm/client/hook/index.js +36 -0
- package/dist/esm/client/hook/index.js.map +1 -0
- package/dist/esm/client/hook/use-balance.js +56 -0
- package/dist/esm/client/hook/use-balance.js.map +1 -0
- package/dist/esm/client/hook/use-clanker.js +57 -0
- package/dist/esm/client/hook/use-clanker.js.map +1 -0
- package/dist/esm/client/hook/use-deploy.js +16 -0
- package/dist/esm/client/hook/use-deploy.js.map +1 -0
- package/dist/esm/client/hook/use-fee-receivers.js +54 -0
- package/dist/esm/client/hook/use-fee-receivers.js.map +1 -0
- package/dist/esm/client/hook/use-governance.js +389 -0
- package/dist/esm/client/hook/use-governance.js.map +1 -0
- package/dist/esm/client/hook/use-prepare.js +47 -0
- package/dist/esm/client/hook/use-prepare.js.map +1 -0
- package/dist/esm/client/hook/use-project.js +29 -0
- package/dist/esm/client/hook/use-project.js.map +1 -0
- package/dist/esm/client/hook/use-projects.js +22 -0
- package/dist/esm/client/hook/use-projects.js.map +1 -0
- package/dist/esm/client/hook/use-proposals.js +31 -0
- package/dist/esm/client/hook/use-proposals.js.map +1 -0
- package/dist/esm/client/hook/use-register.js +101 -0
- package/dist/esm/client/hook/use-register.js.map +1 -0
- package/dist/esm/client/hook/use-stake.js +327 -0
- package/dist/esm/client/hook/use-stake.js.map +1 -0
- package/dist/esm/client/hook/use-swap.js +110 -0
- package/dist/esm/client/hook/use-swap.js.map +1 -0
- package/dist/esm/client/index.js +4 -0
- package/dist/esm/client/index.js.map +1 -0
- package/dist/esm/client/levr-provider.js +201 -0
- package/dist/esm/client/levr-provider.js.map +1 -0
- package/dist/esm/client/query-keys.js +61 -0
- package/dist/esm/client/query-keys.js.map +1 -0
- package/dist/esm/constants.js +182 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/deploy-v4.js +46 -0
- package/dist/esm/deploy-v4.js.map +1 -0
- package/dist/esm/fee-receivers.js +52 -0
- package/dist/esm/fee-receivers.js.map +1 -0
- package/dist/esm/governance.js +555 -0
- package/dist/esm/governance.js.map +1 -0
- package/dist/esm/index.js +18 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/project.js +146 -0
- package/dist/esm/project.js.map +1 -0
- package/dist/esm/projects.js +212 -0
- package/dist/esm/projects.js.map +1 -0
- package/dist/esm/proposals.js +98 -0
- package/dist/esm/proposals.js.map +1 -0
- package/dist/esm/quote-v4.js +169 -0
- package/dist/esm/quote-v4.js.map +1 -0
- package/dist/esm/schema/base.schema.js +11 -0
- package/dist/esm/schema/base.schema.js.map +1 -0
- package/dist/esm/schema/clanker.schema.js +191 -0
- package/dist/esm/schema/clanker.schema.js.map +1 -0
- package/dist/esm/schema/index.js +4 -0
- package/dist/esm/schema/index.js.map +1 -0
- package/dist/esm/schema/levr.schema.js +114 -0
- package/dist/esm/schema/levr.schema.js.map +1 -0
- package/dist/esm/stake.js +384 -0
- package/dist/esm/stake.js.map +1 -0
- package/dist/esm/swap-v4.js +281 -0
- package/dist/esm/swap-v4.js.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/util.js +19 -0
- package/dist/esm/util.js.map +1 -0
- package/dist/types/abis/IClankerAirdrop.d.ts +348 -0
- package/dist/types/abis/IClankerHookDynamicFee.d.ts +156 -0
- package/dist/types/abis/IClankerHookStaticFee.d.ts +58 -0
- package/dist/types/abis/IClankerLPLocker.d.ts +316 -0
- package/dist/types/abis/IClankerLpLockerMultiple.d.ts +481 -0
- package/dist/types/abis/IClankerToken.d.ts +326 -0
- package/dist/types/abis/LevrFactory_v1.d.ts +471 -0
- package/dist/types/abis/LevrForwarder_v1.d.ts +478 -0
- package/dist/types/abis/LevrGovernor_v1.d.ts +562 -0
- package/dist/types/abis/LevrStakedToken_v1.d.ts +338 -0
- package/dist/types/abis/LevrStaking_v1.d.ts +468 -0
- package/dist/types/abis/LevrTreasury_v1.d.ts +169 -0
- package/dist/types/abis/Permit2.d.ts +54 -0
- package/dist/types/abis/V4Quoter.d.ts +496 -0
- package/dist/types/abis/WETH9.d.ts +244 -0
- package/dist/types/abis/index.d.ts +15 -0
- package/dist/types/balance.d.ts +24 -0
- package/dist/types/balance.d.ts.map +1 -0
- package/dist/types/build-calldatas-v4.d.ts +20 -0
- package/dist/types/build-calldatas-v4.d.ts.map +1 -0
- package/dist/types/build-clanker-v4.d.ts +12 -0
- package/dist/types/build-clanker-v4.d.ts.map +1 -0
- package/dist/types/client/hook/index.d.ts +32 -0
- package/dist/types/client/hook/index.d.ts.map +1 -0
- package/dist/types/client/hook/use-balance.d.ts +18 -0
- package/dist/types/client/hook/use-balance.d.ts.map +1 -0
- package/dist/types/client/hook/use-clanker.d.ts +23 -0
- package/dist/types/client/hook/use-clanker.d.ts.map +1 -0
- package/dist/types/client/hook/use-deploy.d.ts +45 -0
- package/dist/types/client/hook/use-deploy.d.ts.map +1 -0
- package/dist/types/client/hook/use-fee-receivers.d.ts +26 -0
- package/dist/types/client/hook/use-fee-receivers.d.ts.map +1 -0
- package/dist/types/client/hook/use-governance.d.ts +145 -0
- package/dist/types/client/hook/use-governance.d.ts.map +1 -0
- package/dist/types/client/hook/use-prepare.d.ts +21 -0
- package/dist/types/client/hook/use-prepare.d.ts.map +1 -0
- package/dist/types/client/hook/use-project.d.ts +11 -0
- package/dist/types/client/hook/use-project.d.ts.map +1 -0
- package/dist/types/client/hook/use-projects.d.ts +6 -0
- package/dist/types/client/hook/use-projects.d.ts.map +1 -0
- package/dist/types/client/hook/use-proposals.d.ts +16 -0
- package/dist/types/client/hook/use-proposals.d.ts.map +1 -0
- package/dist/types/client/hook/use-register.d.ts +31 -0
- package/dist/types/client/hook/use-register.d.ts.map +1 -0
- package/dist/types/client/hook/use-stake.d.ts +195 -0
- package/dist/types/client/hook/use-stake.d.ts.map +1 -0
- package/dist/types/client/hook/use-swap.d.ts +59 -0
- package/dist/types/client/hook/use-swap.d.ts.map +1 -0
- package/dist/types/client/index.d.ts +4 -0
- package/dist/types/client/index.d.ts.map +1 -0
- package/dist/types/client/levr-provider.d.ts +127 -0
- package/dist/types/client/levr-provider.d.ts.map +1 -0
- package/dist/types/client/query-keys.d.ts +61 -0
- package/dist/types/client/query-keys.d.ts.map +1 -0
- package/dist/types/constants.d.ts +101 -0
- package/dist/types/constants.d.ts.map +1 -0
- package/dist/types/deploy-v4.d.ts +13 -0
- package/dist/types/deploy-v4.d.ts.map +1 -0
- package/dist/types/fee-receivers.d.ts +29 -0
- package/dist/types/fee-receivers.d.ts.map +1 -0
- package/dist/types/governance.d.ts +205 -0
- package/dist/types/governance.d.ts.map +1 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/project.d.ts +51 -0
- package/dist/types/project.d.ts.map +1 -0
- package/dist/types/projects.d.ts +20 -0
- package/dist/types/projects.d.ts.map +1 -0
- package/dist/types/proposals.d.ts +20 -0
- package/dist/types/proposals.d.ts.map +1 -0
- package/dist/types/quote-v4.d.ts +54 -0
- package/dist/types/quote-v4.d.ts.map +1 -0
- package/dist/types/schema/base.schema.d.ts +5 -0
- package/dist/types/schema/base.schema.d.ts.map +1 -0
- package/dist/types/schema/clanker.schema.d.ts +104 -0
- package/dist/types/schema/clanker.schema.d.ts.map +1 -0
- package/dist/types/schema/index.d.ts +4 -0
- package/dist/types/schema/index.d.ts.map +1 -0
- package/dist/types/schema/levr.schema.d.ts +34 -0
- package/dist/types/schema/levr.schema.d.ts.map +1 -0
- package/dist/types/stake.d.ts +137 -0
- package/dist/types/stake.d.ts.map +1 -0
- package/dist/types/swap-v4.d.ts +97 -0
- package/dist/types/swap-v4.d.ts.map +1 -0
- package/dist/types/types.d.ts +20 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/util.d.ts +5 -0
- package/dist/types/util.d.ts.map +1 -0
- package/package.json +100 -0
package/README.md
ADDED
|
@@ -0,0 +1,711 @@
|
|
|
1
|
+
# Levr SDK
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
[![npm latest package][npm-latest-image]][npm-url]
|
|
6
|
+
[![Build Status][ci-image]][ci-url]
|
|
7
|
+
[![License][license-image]][license-url]
|
|
8
|
+
[![npm downloads][npm-downloads-image]][npm-url]
|
|
9
|
+
[![Follow on Twitter][twitter-image]][twitter-url]
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
TypeScript SDK for interacting with Levr protocol - a decentralized governance, staking, and liquidity management system built on Uniswap v4.
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- 🎯 **Type-Safe** - Full TypeScript support with comprehensive types
|
|
18
|
+
- 🔄 **Centralized Refetch** - 100% coverage with smart cross-domain awareness
|
|
19
|
+
- ⚡ **Zero Duplication** - Optimized query management via React Context
|
|
20
|
+
- 🪝 **React Hooks** - Easy integration with React applications
|
|
21
|
+
- 🔌 **Server & Client** - Works in both server and client environments
|
|
22
|
+
- 📦 **Tree-Shakeable** - Import only what you need
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install levr-sdk
|
|
28
|
+
# or
|
|
29
|
+
bun add levr-sdk
|
|
30
|
+
# or
|
|
31
|
+
yarn add levr-sdk
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
### Client-Side (React) Usage
|
|
37
|
+
|
|
38
|
+
For React applications, use the centralized provider pattern:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// 1. Wrap your app with LevrProvider
|
|
42
|
+
import { LevrProvider } from 'levr-sdk/client'
|
|
43
|
+
|
|
44
|
+
export function App() {
|
|
45
|
+
return (
|
|
46
|
+
<QueryClientProvider client={queryClient}>
|
|
47
|
+
<WagmiConfig config={wagmiConfig}>
|
|
48
|
+
<LevrProvider>
|
|
49
|
+
<YourApp />
|
|
50
|
+
</LevrProvider>
|
|
51
|
+
</WagmiConfig>
|
|
52
|
+
</QueryClientProvider>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 2. Set the active token in your pages
|
|
57
|
+
import { useSetClankerToken, useProject } from 'levr-sdk/client'
|
|
58
|
+
|
|
59
|
+
export function ProjectPage({ clankerToken }: { clankerToken: `0x${string}` }) {
|
|
60
|
+
const setClankerToken = useSetClankerToken()
|
|
61
|
+
const { data: project, isLoading } = useProject()
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
setClankerToken(clankerToken) // Updates global context
|
|
65
|
+
}, [clankerToken, setClankerToken])
|
|
66
|
+
|
|
67
|
+
if (isLoading) return <div>Loading...</div>
|
|
68
|
+
if (!project) return <div>Project not found</div>
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div>
|
|
72
|
+
<h1>{project.token.name}</h1>
|
|
73
|
+
<StakeComponent />
|
|
74
|
+
<SwapComponent />
|
|
75
|
+
<GovernanceComponent />
|
|
76
|
+
</div>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 3. Use hooks in child components - they automatically share queries!
|
|
81
|
+
import { useStake, useBalance } from 'levr-sdk/client'
|
|
82
|
+
|
|
83
|
+
function StakeComponent() {
|
|
84
|
+
const { data: balances } = useBalance()
|
|
85
|
+
const {
|
|
86
|
+
stake,
|
|
87
|
+
stakedBalance,
|
|
88
|
+
needsApproval,
|
|
89
|
+
} = useStake({
|
|
90
|
+
onStakeSuccess: () => {
|
|
91
|
+
toast.success('Staked successfully!')
|
|
92
|
+
// All related data automatically refetches
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<div>
|
|
98
|
+
<p>Balance: {balances?.token?.formatted}</p>
|
|
99
|
+
<p>Staked: {stakedBalance?.formatted}</p>
|
|
100
|
+
<button onClick={() => stake.mutate(amount)}>
|
|
101
|
+
Stake
|
|
102
|
+
</button>
|
|
103
|
+
</div>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Server-Side Usage
|
|
109
|
+
|
|
110
|
+
For server-side operations or scripts:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { project, balance, Stake, Governance } from 'levr-sdk'
|
|
114
|
+
import { createPublicClient, createWalletClient, http } from 'viem'
|
|
115
|
+
import { base } from 'viem/chains'
|
|
116
|
+
|
|
117
|
+
// Initialize clients
|
|
118
|
+
const publicClient = createPublicClient({
|
|
119
|
+
chain: base,
|
|
120
|
+
transport: http(),
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
const walletClient = createWalletClient({
|
|
124
|
+
chain: base,
|
|
125
|
+
transport: http(),
|
|
126
|
+
account: privateKeyToAccount('0x...'),
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
// Get project data
|
|
130
|
+
const projectData = await project({
|
|
131
|
+
publicClient,
|
|
132
|
+
factoryAddress: '0x...',
|
|
133
|
+
chainId: base.id,
|
|
134
|
+
clankerToken: '0x...',
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
// Get balances
|
|
138
|
+
const balances = await balance({
|
|
139
|
+
publicClient,
|
|
140
|
+
address: '0x...',
|
|
141
|
+
tokens: [
|
|
142
|
+
{ address: projectData.token.address, decimals: 18, key: 'token' },
|
|
143
|
+
{ address: '0x...', decimals: 18, key: 'weth' },
|
|
144
|
+
],
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
// Stake tokens
|
|
148
|
+
const stake = new Stake({
|
|
149
|
+
wallet: walletClient,
|
|
150
|
+
publicClient,
|
|
151
|
+
stakingAddress: projectData.staking,
|
|
152
|
+
tokenAddress: projectData.token.address,
|
|
153
|
+
tokenDecimals: 18,
|
|
154
|
+
trustedForwarder: projectData.forwarder,
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
// Approve and stake
|
|
158
|
+
await stake.approve(1000)
|
|
159
|
+
const receipt = await stake.stake(1000)
|
|
160
|
+
|
|
161
|
+
// Governance operations
|
|
162
|
+
const governance = new Governance({
|
|
163
|
+
wallet: walletClient,
|
|
164
|
+
publicClient,
|
|
165
|
+
governorAddress: projectData.governor,
|
|
166
|
+
tokenDecimals: 18,
|
|
167
|
+
clankerToken: projectData.token.address,
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
// Propose a transfer
|
|
171
|
+
const { receipt, proposalId } = await governance.proposeTransfer(
|
|
172
|
+
'0x...', // recipient
|
|
173
|
+
parseUnits('1000', 18), // amount
|
|
174
|
+
'Fund development' // description
|
|
175
|
+
)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Available Hooks (Client)
|
|
179
|
+
|
|
180
|
+
### Simple Query Hooks
|
|
181
|
+
|
|
182
|
+
Direct context accessors for read-only data:
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import {
|
|
186
|
+
useProject, // Project data (token, contracts, pool info)
|
|
187
|
+
useBalance, // Token balances (token, WETH, ETH)
|
|
188
|
+
useProposals, // Proposals list
|
|
189
|
+
useClankerToken, // Token metadata (admin, image, etc.)
|
|
190
|
+
} from 'levr-sdk/client'
|
|
191
|
+
|
|
192
|
+
const { data: project } = useProject()
|
|
193
|
+
const { data: balances } = useBalance()
|
|
194
|
+
const { data: proposals } = useProposals()
|
|
195
|
+
const { data: tokenData } = useClankerToken()
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Mutation Hooks
|
|
199
|
+
|
|
200
|
+
Hooks with both queries and mutations:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import {
|
|
204
|
+
useStake, // Staking operations
|
|
205
|
+
useSwap, // Swap operations
|
|
206
|
+
useGovernance, // Governance operations
|
|
207
|
+
useFeeReceivers, // Fee receiver management
|
|
208
|
+
} from 'levr-sdk/client'
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### `useStake()`
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
const {
|
|
215
|
+
// Mutations
|
|
216
|
+
approve,
|
|
217
|
+
stake,
|
|
218
|
+
unstake,
|
|
219
|
+
claim,
|
|
220
|
+
accrueRewards,
|
|
221
|
+
accrueAllRewards,
|
|
222
|
+
|
|
223
|
+
// Queries
|
|
224
|
+
allowance,
|
|
225
|
+
poolData,
|
|
226
|
+
userData,
|
|
227
|
+
balances,
|
|
228
|
+
wethRewardRate,
|
|
229
|
+
aprBpsWeth,
|
|
230
|
+
|
|
231
|
+
// Convenience accessors
|
|
232
|
+
stakedBalance,
|
|
233
|
+
totalStaked,
|
|
234
|
+
tokenBalance,
|
|
235
|
+
needsApproval,
|
|
236
|
+
|
|
237
|
+
// Loading states
|
|
238
|
+
isLoadingPoolData,
|
|
239
|
+
isLoadingUserData,
|
|
240
|
+
} = useStake({
|
|
241
|
+
onStakeSuccess: (receipt) => console.log('Staked!', receipt),
|
|
242
|
+
onUnstakeSuccess: (receipt) => console.log('Unstaked!', receipt),
|
|
243
|
+
onClaimSuccess: (receipt) => console.log('Claimed!', receipt),
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
// Use mutations
|
|
247
|
+
stake.mutate(1000) // Automatically refetches balances, staking data, project
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### `useSwap()`
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
const {
|
|
254
|
+
// Mutations
|
|
255
|
+
swap,
|
|
256
|
+
|
|
257
|
+
// Queries
|
|
258
|
+
quote,
|
|
259
|
+
balances,
|
|
260
|
+
poolKey,
|
|
261
|
+
|
|
262
|
+
// Convenience
|
|
263
|
+
tokenBalance,
|
|
264
|
+
wethBalance,
|
|
265
|
+
buildSwapConfig,
|
|
266
|
+
} = useSwap({
|
|
267
|
+
quoteParams: {
|
|
268
|
+
zeroForOne: true, // true = token -> WETH, false = WETH -> token
|
|
269
|
+
amountIn: '100',
|
|
270
|
+
amountInDecimals: 18,
|
|
271
|
+
amountOutDecimals: 18,
|
|
272
|
+
},
|
|
273
|
+
onSwapSuccess: (receipt) => console.log('Swapped!', receipt),
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
// Build swap config (poolKey from context)
|
|
277
|
+
const config = buildSwapConfig({
|
|
278
|
+
zeroForOne: true,
|
|
279
|
+
amountIn: 100,
|
|
280
|
+
amountInDecimals: 18,
|
|
281
|
+
minAmountOut: '95',
|
|
282
|
+
})
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### `useGovernance()`
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
const {
|
|
289
|
+
// Mutations
|
|
290
|
+
proposeTransfer,
|
|
291
|
+
proposeBoost,
|
|
292
|
+
vote,
|
|
293
|
+
executeProposal,
|
|
294
|
+
claimAirdrop,
|
|
295
|
+
|
|
296
|
+
// Queries
|
|
297
|
+
currentCycleId,
|
|
298
|
+
addresses,
|
|
299
|
+
airdropStatus,
|
|
300
|
+
proposal,
|
|
301
|
+
|
|
302
|
+
// Convenience accessors
|
|
303
|
+
treasuryAddress,
|
|
304
|
+
isAirdropAvailable,
|
|
305
|
+
|
|
306
|
+
// Loading states
|
|
307
|
+
isProposing,
|
|
308
|
+
isVoting,
|
|
309
|
+
isExecuting,
|
|
310
|
+
} = useGovernance({
|
|
311
|
+
governorAddress: project.governor,
|
|
312
|
+
clankerToken: project.token.address,
|
|
313
|
+
onVoteSuccess: (receipt) => console.log('Voted!', receipt),
|
|
314
|
+
onExecuteProposalSuccess: (receipt) => console.log('Executed!', receipt),
|
|
315
|
+
})
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### `useFeeReceivers()`
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
const {
|
|
322
|
+
query, // Fee receivers data
|
|
323
|
+
mutate, // Update mutation
|
|
324
|
+
} = useFeeReceivers({
|
|
325
|
+
onSuccess: (hash) => console.log('Updated fee receiver', hash),
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
// Use mutation
|
|
329
|
+
mutate.mutate({
|
|
330
|
+
clankerToken: '0x...',
|
|
331
|
+
rewardIndex: 0,
|
|
332
|
+
newRecipient: '0x...',
|
|
333
|
+
})
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Utility Hooks
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
import {
|
|
340
|
+
useSetClankerToken, // Update global token context
|
|
341
|
+
useLevrRefetch, // Manual refetch control
|
|
342
|
+
useClanker, // Clanker SDK instance
|
|
343
|
+
} from 'levr-sdk/client'
|
|
344
|
+
|
|
345
|
+
// Update active token
|
|
346
|
+
const setClankerToken = useSetClankerToken()
|
|
347
|
+
setClankerToken('0x...')
|
|
348
|
+
|
|
349
|
+
// Manual refetch control
|
|
350
|
+
const refetch = useLevrRefetch()
|
|
351
|
+
await refetch.all() // Refetch everything
|
|
352
|
+
await refetch.staking() // Refetch staking data
|
|
353
|
+
await refetch.afterStake() // Smart cross-domain refetch after stake
|
|
354
|
+
|
|
355
|
+
// Get Clanker SDK instance
|
|
356
|
+
const clanker = useClanker()
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Centralized Refetch Coverage
|
|
360
|
+
|
|
361
|
+
The SDK provides **100% refetch coverage** with smart cross-domain awareness:
|
|
362
|
+
|
|
363
|
+
| Action | Auto-Refetches |
|
|
364
|
+
| ------------------------ | ----------------------------------------------------------------- |
|
|
365
|
+
| **Stake/Unstake/Claim** | Balances, All Staking Data, Project (treasury), WETH Rewards |
|
|
366
|
+
| **Swap** | Balances, Project (pool data) |
|
|
367
|
+
| **Propose/Vote/Execute** | Governance, Proposals, Project (treasury), Staking (voting power) |
|
|
368
|
+
| **Wallet/Chain Change** | All Queries |
|
|
369
|
+
|
|
370
|
+
All mutations automatically trigger appropriate refetches - no manual coordination needed!
|
|
371
|
+
|
|
372
|
+
## API Reference
|
|
373
|
+
|
|
374
|
+
### Server-Side APIs
|
|
375
|
+
|
|
376
|
+
#### `project()`
|
|
377
|
+
|
|
378
|
+
Get project data including token, contracts, and pool information:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
import { project } from 'levr-sdk'
|
|
382
|
+
|
|
383
|
+
const projectData = await project({
|
|
384
|
+
publicClient,
|
|
385
|
+
factoryAddress: '0x...',
|
|
386
|
+
chainId: 8453, // Base
|
|
387
|
+
clankerToken: '0x...',
|
|
388
|
+
})
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
#### `balance()`
|
|
392
|
+
|
|
393
|
+
Get token balances for multiple tokens:
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
import { balance } from 'levr-sdk'
|
|
397
|
+
|
|
398
|
+
const balances = await balance({
|
|
399
|
+
publicClient,
|
|
400
|
+
address: '0x...',
|
|
401
|
+
tokens: [
|
|
402
|
+
{ address: '0x...', decimals: 18, key: 'token' },
|
|
403
|
+
{ address: '0x...', decimals: 18, key: 'weth' },
|
|
404
|
+
{ address: zeroAddress, decimals: 18, key: 'eth' }, // Native ETH
|
|
405
|
+
],
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
console.log(balances.token?.formatted) // "1000.0"
|
|
409
|
+
console.log(balances.weth?.formatted) // "5.5"
|
|
410
|
+
console.log(balances.eth?.formatted) // "0.1"
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
#### `Stake` Class
|
|
414
|
+
|
|
415
|
+
Manage staking operations:
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
import { Stake } from 'levr-sdk'
|
|
419
|
+
|
|
420
|
+
const stake = new Stake({
|
|
421
|
+
wallet: walletClient,
|
|
422
|
+
publicClient,
|
|
423
|
+
stakingAddress: '0x...',
|
|
424
|
+
tokenAddress: '0x...',
|
|
425
|
+
tokenDecimals: 18,
|
|
426
|
+
trustedForwarder: '0x...',
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
// Get staking data
|
|
430
|
+
const poolData = await stake.getPoolData()
|
|
431
|
+
const userData = await stake.getUserData()
|
|
432
|
+
const allowance = await stake.getAllowance()
|
|
433
|
+
|
|
434
|
+
// Perform operations
|
|
435
|
+
await stake.approve(amount)
|
|
436
|
+
await stake.stake(amount)
|
|
437
|
+
await stake.unstake({ amount, to: '0x...' })
|
|
438
|
+
await stake.claimRewards()
|
|
439
|
+
await stake.accrueRewards(tokenAddress)
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
#### `Governance` Class
|
|
443
|
+
|
|
444
|
+
Manage governance operations:
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
import { Governance } from 'levr-sdk'
|
|
448
|
+
|
|
449
|
+
const governance = new Governance({
|
|
450
|
+
wallet: walletClient,
|
|
451
|
+
publicClient,
|
|
452
|
+
governorAddress: '0x...',
|
|
453
|
+
tokenDecimals: 18,
|
|
454
|
+
clankerToken: '0x...',
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
// Get governance data
|
|
458
|
+
const cycleId = await governance.getCurrentCycleId()
|
|
459
|
+
const treasury = await governance.getTreasury()
|
|
460
|
+
const airdropStatus = await governance.getAirdropStatus()
|
|
461
|
+
|
|
462
|
+
// Propose actions
|
|
463
|
+
const { receipt, proposalId } = await governance.proposeTransfer(
|
|
464
|
+
'0x...', // recipient
|
|
465
|
+
parseUnits('1000', 18), // amount
|
|
466
|
+
'Fund development' // description
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
// Vote on proposals
|
|
470
|
+
await governance.vote(proposalId, true) // true = support
|
|
471
|
+
|
|
472
|
+
// Execute proposals
|
|
473
|
+
await governance.executeProposal(proposalId)
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
#### `swapV4()` and `quoteV4()`
|
|
477
|
+
|
|
478
|
+
Uniswap v4 swap operations:
|
|
479
|
+
|
|
480
|
+
```typescript
|
|
481
|
+
import { swapV4, quoteV4 } from 'levr-sdk'
|
|
482
|
+
|
|
483
|
+
// Get swap quote
|
|
484
|
+
const quote = await quoteV4({
|
|
485
|
+
publicClient,
|
|
486
|
+
chainId: 8453,
|
|
487
|
+
poolKey: {
|
|
488
|
+
currency0: '0x...',
|
|
489
|
+
currency1: '0x...',
|
|
490
|
+
fee: 500,
|
|
491
|
+
tickSpacing: 10,
|
|
492
|
+
hooks: '0x...',
|
|
493
|
+
},
|
|
494
|
+
zeroForOne: true,
|
|
495
|
+
amountIn: parseUnits('100', 18),
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
console.log(formatUnits(quote.amountOut, 18)) // "95.5"
|
|
499
|
+
|
|
500
|
+
// Execute swap
|
|
501
|
+
const receipt = await swapV4({
|
|
502
|
+
publicClient,
|
|
503
|
+
wallet: walletClient,
|
|
504
|
+
chainId: 8453,
|
|
505
|
+
poolKey,
|
|
506
|
+
zeroForOne: true,
|
|
507
|
+
amountIn: parseUnits('100', 18),
|
|
508
|
+
amountOutMinimum: parseUnits('95', 18),
|
|
509
|
+
})
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
## Architecture: Centralized Provider Pattern
|
|
513
|
+
|
|
514
|
+
The SDK uses a centralized provider pattern that eliminates query duplication and provides 100% refetch coverage:
|
|
515
|
+
|
|
516
|
+
```
|
|
517
|
+
┌─────────────────────────────────────────────────┐
|
|
518
|
+
│ LevrProvider (Global) │
|
|
519
|
+
│ │
|
|
520
|
+
│ ┌───────────────────────────────────────────┐ │
|
|
521
|
+
│ │ Centralized Queries (created once) │ │
|
|
522
|
+
│ │ • Project data │ │
|
|
523
|
+
│ │ • Token balances (token + WETH + ETH) │ │
|
|
524
|
+
│ │ • Staking (all queries) │ │
|
|
525
|
+
│ │ • Governance (global queries) │ │
|
|
526
|
+
│ │ • Proposals │ │
|
|
527
|
+
│ │ • Fee receivers │ │
|
|
528
|
+
│ └───────────────────────────────────────────┘ │
|
|
529
|
+
│ │
|
|
530
|
+
│ ┌───────────────────────────────────────────┐ │
|
|
531
|
+
│ │ Smart Refetch Methods │ │
|
|
532
|
+
│ │ • afterStake() → Balances, Staking, etc. │ │
|
|
533
|
+
│ │ • afterSwap() → Balances, Project │ │
|
|
534
|
+
│ │ • afterGovernance() → Gov, Proposals, etc.│ │
|
|
535
|
+
│ └───────────────────────────────────────────┘ │
|
|
536
|
+
└─────────────────────────────────────────────────┘
|
|
537
|
+
↓ Context shared via hooks
|
|
538
|
+
┌─────────────────────────────────────────────────┐
|
|
539
|
+
│ Components consume without duplication │
|
|
540
|
+
│ • useProject() → Shared query │
|
|
541
|
+
│ • useBalance() → Shared query │
|
|
542
|
+
│ • useStake() → Shared queries + mutations │
|
|
543
|
+
└─────────────────────────────────────────────────┘
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### Benefits
|
|
547
|
+
|
|
548
|
+
✅ **Zero Duplication** - Each query created once, shared across all components
|
|
549
|
+
✅ **100% Refetch Coverage** - Smart cross-domain refetches after mutations
|
|
550
|
+
✅ **Better Performance** - Fewer network requests, better caching
|
|
551
|
+
✅ **Type Safety** - Full TypeScript throughout
|
|
552
|
+
✅ **Easy to Use** - Simple hook API, automatic coordination
|
|
553
|
+
|
|
554
|
+
## Advanced Usage
|
|
555
|
+
|
|
556
|
+
### Dynamic Token Updates
|
|
557
|
+
|
|
558
|
+
```typescript
|
|
559
|
+
import { useSetClankerToken } from 'levr-sdk/client'
|
|
560
|
+
|
|
561
|
+
function TokenSwitcher() {
|
|
562
|
+
const setClankerToken = useSetClankerToken()
|
|
563
|
+
|
|
564
|
+
const switchToToken = (tokenAddress: `0x${string}`) => {
|
|
565
|
+
setClankerToken(tokenAddress)
|
|
566
|
+
// All queries automatically update!
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return (
|
|
570
|
+
<select onChange={(e) => switchToToken(e.target.value as `0x${string}`)}>
|
|
571
|
+
<option value="0x...">Token A</option>
|
|
572
|
+
<option value="0x...">Token B</option>
|
|
573
|
+
</select>
|
|
574
|
+
)
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### Manual Refetch Control
|
|
579
|
+
|
|
580
|
+
```typescript
|
|
581
|
+
import { useLevrRefetch } from 'levr-sdk/client'
|
|
582
|
+
|
|
583
|
+
function RefreshButton() {
|
|
584
|
+
const refetch = useLevrRefetch()
|
|
585
|
+
|
|
586
|
+
return (
|
|
587
|
+
<div>
|
|
588
|
+
<button onClick={() => refetch.all()}>Refresh All</button>
|
|
589
|
+
<button onClick={() => refetch.staking()}>Refresh Staking</button>
|
|
590
|
+
<button onClick={() => refetch.governance()}>Refresh Governance</button>
|
|
591
|
+
</div>
|
|
592
|
+
)
|
|
593
|
+
}
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### Deploying New Tokens
|
|
597
|
+
|
|
598
|
+
```typescript
|
|
599
|
+
import { useDeploy } from 'levr-sdk/client'
|
|
600
|
+
|
|
601
|
+
function DeployToken() {
|
|
602
|
+
const deploy = useDeploy({
|
|
603
|
+
onSuccess: ({ receipt, address }) => {
|
|
604
|
+
console.log('Deployed to:', address)
|
|
605
|
+
},
|
|
606
|
+
})
|
|
607
|
+
|
|
608
|
+
const handleDeploy = () => {
|
|
609
|
+
deploy.mutate({
|
|
610
|
+
name: 'My Token',
|
|
611
|
+
ticker: 'TKN',
|
|
612
|
+
imageUrl: 'ipfs://...',
|
|
613
|
+
description: 'Token description',
|
|
614
|
+
// ... other params
|
|
615
|
+
})
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
return <button onClick={handleDeploy}>Deploy</button>
|
|
619
|
+
}
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
## Query Keys
|
|
623
|
+
|
|
624
|
+
All query keys are centralized and exported:
|
|
625
|
+
|
|
626
|
+
```typescript
|
|
627
|
+
import { queryKeys } from 'levr-sdk/client'
|
|
628
|
+
|
|
629
|
+
// Use in custom queries or invalidations
|
|
630
|
+
queryClient.invalidateQueries({
|
|
631
|
+
queryKey: queryKeys.project(factoryAddress, clankerToken, chainId),
|
|
632
|
+
})
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
## TypeScript Support
|
|
636
|
+
|
|
637
|
+
Full TypeScript support with comprehensive types:
|
|
638
|
+
|
|
639
|
+
```typescript
|
|
640
|
+
import type {
|
|
641
|
+
Project,
|
|
642
|
+
PoolKey,
|
|
643
|
+
ProposalsResult,
|
|
644
|
+
BalanceResult,
|
|
645
|
+
ClaimParams,
|
|
646
|
+
ProposeTransferConfig,
|
|
647
|
+
// ... many more
|
|
648
|
+
} from 'levr-sdk'
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
## Development
|
|
652
|
+
|
|
653
|
+
```bash
|
|
654
|
+
# Install dependencies
|
|
655
|
+
bun install
|
|
656
|
+
|
|
657
|
+
# Type check
|
|
658
|
+
bun run type-check
|
|
659
|
+
|
|
660
|
+
# Run tests
|
|
661
|
+
bun test
|
|
662
|
+
|
|
663
|
+
# Build
|
|
664
|
+
bun run build
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
## Architecture
|
|
668
|
+
|
|
669
|
+
```
|
|
670
|
+
levr-sdk/
|
|
671
|
+
├── src/
|
|
672
|
+
│ ├── index.ts # Server-safe exports
|
|
673
|
+
│ ├── project.ts # Project queries
|
|
674
|
+
│ ├── balance.ts # Balance queries
|
|
675
|
+
│ ├── stake.ts # Stake class
|
|
676
|
+
│ ├── governance.ts # Governance class
|
|
677
|
+
│ ├── swap-v4.ts # Swap functions
|
|
678
|
+
│ ├── quote-v4.ts # Quote functions
|
|
679
|
+
│ └── client/
|
|
680
|
+
│ ├── index.ts # Client-only exports
|
|
681
|
+
│ ├── levr-provider.tsx # Centralized provider
|
|
682
|
+
│ ├── query-keys.ts # Query key registry
|
|
683
|
+
│ └── hook/
|
|
684
|
+
│ ├── index.ts # Public hook exports
|
|
685
|
+
│ ├── use-project.ts
|
|
686
|
+
│ ├── use-balance.ts
|
|
687
|
+
│ ├── use-stake.ts
|
|
688
|
+
│ ├── use-swap.ts
|
|
689
|
+
│ ├── use-governance.ts
|
|
690
|
+
│ └── ... (other hooks)
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
## License
|
|
694
|
+
|
|
695
|
+
Apache v2 - see [LICENSE.md](./LICENSE.md) for details.
|
|
696
|
+
|
|
697
|
+
## Links
|
|
698
|
+
|
|
699
|
+
- [Documentation](https://github.com/quantidexyz/levr)
|
|
700
|
+
- [Twitter](https://twitter.com/levrworld)
|
|
701
|
+
- [npm](https://npmjs.org/package/levr-sdk)
|
|
702
|
+
|
|
703
|
+
[ci-image]: https://badgen.net/github/checks/quantidexyz/levr/main?label=ci
|
|
704
|
+
[ci-url]: https://github.com/quantidexyz/levr/actions/workflows/ci.yaml
|
|
705
|
+
[npm-url]: https://npmjs.org/package/levr-sdk
|
|
706
|
+
[twitter-url]: https://twitter.com/levrworld
|
|
707
|
+
[twitter-image]: https://img.shields.io/twitter/follow/levrworld.svg?label=follow+levr
|
|
708
|
+
[license-image]: https://img.shields.io/badge/License-Apache%20v2-blue
|
|
709
|
+
[license-url]: ./LICENSE.md
|
|
710
|
+
[npm-latest-image]: https://img.shields.io/npm/v/levr-sdk/latest.svg
|
|
711
|
+
[npm-downloads-image]: https://img.shields.io/npm/dm/levr-sdk.svg
|