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.
Files changed (179) hide show
  1. package/LICENSE.md +201 -0
  2. package/README.md +711 -0
  3. package/dist/esm/abis/IClankerAirdrop.js +443 -0
  4. package/dist/esm/abis/IClankerHookDynamicFee.js +198 -0
  5. package/dist/esm/abis/IClankerHookStaticFee.js +75 -0
  6. package/dist/esm/abis/IClankerLPLocker.js +402 -0
  7. package/dist/esm/abis/IClankerLpLockerMultiple.js +609 -0
  8. package/dist/esm/abis/IClankerToken.js +421 -0
  9. package/dist/esm/abis/LevrFactory_v1.js +608 -0
  10. package/dist/esm/abis/LevrForwarder_v1.js +622 -0
  11. package/dist/esm/abis/LevrGovernor_v1.js +726 -0
  12. package/dist/esm/abis/LevrStakedToken_v1.js +441 -0
  13. package/dist/esm/abis/LevrStaking_v1.js +607 -0
  14. package/dist/esm/abis/LevrTreasury_v1.js +219 -0
  15. package/dist/esm/abis/Permit2.js +29 -0
  16. package/dist/esm/abis/V4Quoter.js +466 -0
  17. package/dist/esm/abis/WETH9.js +153 -0
  18. package/dist/esm/abis/index.js +23 -0
  19. package/dist/esm/balance.js +72 -0
  20. package/dist/esm/balance.js.map +1 -0
  21. package/dist/esm/build-calldatas-v4.js +98 -0
  22. package/dist/esm/build-calldatas-v4.js.map +1 -0
  23. package/dist/esm/build-clanker-v4.js +128 -0
  24. package/dist/esm/build-clanker-v4.js.map +1 -0
  25. package/dist/esm/client/hook/index.js +36 -0
  26. package/dist/esm/client/hook/index.js.map +1 -0
  27. package/dist/esm/client/hook/use-balance.js +56 -0
  28. package/dist/esm/client/hook/use-balance.js.map +1 -0
  29. package/dist/esm/client/hook/use-clanker.js +57 -0
  30. package/dist/esm/client/hook/use-clanker.js.map +1 -0
  31. package/dist/esm/client/hook/use-deploy.js +16 -0
  32. package/dist/esm/client/hook/use-deploy.js.map +1 -0
  33. package/dist/esm/client/hook/use-fee-receivers.js +54 -0
  34. package/dist/esm/client/hook/use-fee-receivers.js.map +1 -0
  35. package/dist/esm/client/hook/use-governance.js +389 -0
  36. package/dist/esm/client/hook/use-governance.js.map +1 -0
  37. package/dist/esm/client/hook/use-prepare.js +47 -0
  38. package/dist/esm/client/hook/use-prepare.js.map +1 -0
  39. package/dist/esm/client/hook/use-project.js +29 -0
  40. package/dist/esm/client/hook/use-project.js.map +1 -0
  41. package/dist/esm/client/hook/use-projects.js +22 -0
  42. package/dist/esm/client/hook/use-projects.js.map +1 -0
  43. package/dist/esm/client/hook/use-proposals.js +31 -0
  44. package/dist/esm/client/hook/use-proposals.js.map +1 -0
  45. package/dist/esm/client/hook/use-register.js +101 -0
  46. package/dist/esm/client/hook/use-register.js.map +1 -0
  47. package/dist/esm/client/hook/use-stake.js +327 -0
  48. package/dist/esm/client/hook/use-stake.js.map +1 -0
  49. package/dist/esm/client/hook/use-swap.js +110 -0
  50. package/dist/esm/client/hook/use-swap.js.map +1 -0
  51. package/dist/esm/client/index.js +4 -0
  52. package/dist/esm/client/index.js.map +1 -0
  53. package/dist/esm/client/levr-provider.js +201 -0
  54. package/dist/esm/client/levr-provider.js.map +1 -0
  55. package/dist/esm/client/query-keys.js +61 -0
  56. package/dist/esm/client/query-keys.js.map +1 -0
  57. package/dist/esm/constants.js +182 -0
  58. package/dist/esm/constants.js.map +1 -0
  59. package/dist/esm/deploy-v4.js +46 -0
  60. package/dist/esm/deploy-v4.js.map +1 -0
  61. package/dist/esm/fee-receivers.js +52 -0
  62. package/dist/esm/fee-receivers.js.map +1 -0
  63. package/dist/esm/governance.js +555 -0
  64. package/dist/esm/governance.js.map +1 -0
  65. package/dist/esm/index.js +18 -0
  66. package/dist/esm/index.js.map +1 -0
  67. package/dist/esm/project.js +146 -0
  68. package/dist/esm/project.js.map +1 -0
  69. package/dist/esm/projects.js +212 -0
  70. package/dist/esm/projects.js.map +1 -0
  71. package/dist/esm/proposals.js +98 -0
  72. package/dist/esm/proposals.js.map +1 -0
  73. package/dist/esm/quote-v4.js +169 -0
  74. package/dist/esm/quote-v4.js.map +1 -0
  75. package/dist/esm/schema/base.schema.js +11 -0
  76. package/dist/esm/schema/base.schema.js.map +1 -0
  77. package/dist/esm/schema/clanker.schema.js +191 -0
  78. package/dist/esm/schema/clanker.schema.js.map +1 -0
  79. package/dist/esm/schema/index.js +4 -0
  80. package/dist/esm/schema/index.js.map +1 -0
  81. package/dist/esm/schema/levr.schema.js +114 -0
  82. package/dist/esm/schema/levr.schema.js.map +1 -0
  83. package/dist/esm/stake.js +384 -0
  84. package/dist/esm/stake.js.map +1 -0
  85. package/dist/esm/swap-v4.js +281 -0
  86. package/dist/esm/swap-v4.js.map +1 -0
  87. package/dist/esm/types.js +2 -0
  88. package/dist/esm/types.js.map +1 -0
  89. package/dist/esm/util.js +19 -0
  90. package/dist/esm/util.js.map +1 -0
  91. package/dist/types/abis/IClankerAirdrop.d.ts +348 -0
  92. package/dist/types/abis/IClankerHookDynamicFee.d.ts +156 -0
  93. package/dist/types/abis/IClankerHookStaticFee.d.ts +58 -0
  94. package/dist/types/abis/IClankerLPLocker.d.ts +316 -0
  95. package/dist/types/abis/IClankerLpLockerMultiple.d.ts +481 -0
  96. package/dist/types/abis/IClankerToken.d.ts +326 -0
  97. package/dist/types/abis/LevrFactory_v1.d.ts +471 -0
  98. package/dist/types/abis/LevrForwarder_v1.d.ts +478 -0
  99. package/dist/types/abis/LevrGovernor_v1.d.ts +562 -0
  100. package/dist/types/abis/LevrStakedToken_v1.d.ts +338 -0
  101. package/dist/types/abis/LevrStaking_v1.d.ts +468 -0
  102. package/dist/types/abis/LevrTreasury_v1.d.ts +169 -0
  103. package/dist/types/abis/Permit2.d.ts +54 -0
  104. package/dist/types/abis/V4Quoter.d.ts +496 -0
  105. package/dist/types/abis/WETH9.d.ts +244 -0
  106. package/dist/types/abis/index.d.ts +15 -0
  107. package/dist/types/balance.d.ts +24 -0
  108. package/dist/types/balance.d.ts.map +1 -0
  109. package/dist/types/build-calldatas-v4.d.ts +20 -0
  110. package/dist/types/build-calldatas-v4.d.ts.map +1 -0
  111. package/dist/types/build-clanker-v4.d.ts +12 -0
  112. package/dist/types/build-clanker-v4.d.ts.map +1 -0
  113. package/dist/types/client/hook/index.d.ts +32 -0
  114. package/dist/types/client/hook/index.d.ts.map +1 -0
  115. package/dist/types/client/hook/use-balance.d.ts +18 -0
  116. package/dist/types/client/hook/use-balance.d.ts.map +1 -0
  117. package/dist/types/client/hook/use-clanker.d.ts +23 -0
  118. package/dist/types/client/hook/use-clanker.d.ts.map +1 -0
  119. package/dist/types/client/hook/use-deploy.d.ts +45 -0
  120. package/dist/types/client/hook/use-deploy.d.ts.map +1 -0
  121. package/dist/types/client/hook/use-fee-receivers.d.ts +26 -0
  122. package/dist/types/client/hook/use-fee-receivers.d.ts.map +1 -0
  123. package/dist/types/client/hook/use-governance.d.ts +145 -0
  124. package/dist/types/client/hook/use-governance.d.ts.map +1 -0
  125. package/dist/types/client/hook/use-prepare.d.ts +21 -0
  126. package/dist/types/client/hook/use-prepare.d.ts.map +1 -0
  127. package/dist/types/client/hook/use-project.d.ts +11 -0
  128. package/dist/types/client/hook/use-project.d.ts.map +1 -0
  129. package/dist/types/client/hook/use-projects.d.ts +6 -0
  130. package/dist/types/client/hook/use-projects.d.ts.map +1 -0
  131. package/dist/types/client/hook/use-proposals.d.ts +16 -0
  132. package/dist/types/client/hook/use-proposals.d.ts.map +1 -0
  133. package/dist/types/client/hook/use-register.d.ts +31 -0
  134. package/dist/types/client/hook/use-register.d.ts.map +1 -0
  135. package/dist/types/client/hook/use-stake.d.ts +195 -0
  136. package/dist/types/client/hook/use-stake.d.ts.map +1 -0
  137. package/dist/types/client/hook/use-swap.d.ts +59 -0
  138. package/dist/types/client/hook/use-swap.d.ts.map +1 -0
  139. package/dist/types/client/index.d.ts +4 -0
  140. package/dist/types/client/index.d.ts.map +1 -0
  141. package/dist/types/client/levr-provider.d.ts +127 -0
  142. package/dist/types/client/levr-provider.d.ts.map +1 -0
  143. package/dist/types/client/query-keys.d.ts +61 -0
  144. package/dist/types/client/query-keys.d.ts.map +1 -0
  145. package/dist/types/constants.d.ts +101 -0
  146. package/dist/types/constants.d.ts.map +1 -0
  147. package/dist/types/deploy-v4.d.ts +13 -0
  148. package/dist/types/deploy-v4.d.ts.map +1 -0
  149. package/dist/types/fee-receivers.d.ts +29 -0
  150. package/dist/types/fee-receivers.d.ts.map +1 -0
  151. package/dist/types/governance.d.ts +205 -0
  152. package/dist/types/governance.d.ts.map +1 -0
  153. package/dist/types/index.d.ts +18 -0
  154. package/dist/types/index.d.ts.map +1 -0
  155. package/dist/types/project.d.ts +51 -0
  156. package/dist/types/project.d.ts.map +1 -0
  157. package/dist/types/projects.d.ts +20 -0
  158. package/dist/types/projects.d.ts.map +1 -0
  159. package/dist/types/proposals.d.ts +20 -0
  160. package/dist/types/proposals.d.ts.map +1 -0
  161. package/dist/types/quote-v4.d.ts +54 -0
  162. package/dist/types/quote-v4.d.ts.map +1 -0
  163. package/dist/types/schema/base.schema.d.ts +5 -0
  164. package/dist/types/schema/base.schema.d.ts.map +1 -0
  165. package/dist/types/schema/clanker.schema.d.ts +104 -0
  166. package/dist/types/schema/clanker.schema.d.ts.map +1 -0
  167. package/dist/types/schema/index.d.ts +4 -0
  168. package/dist/types/schema/index.d.ts.map +1 -0
  169. package/dist/types/schema/levr.schema.d.ts +34 -0
  170. package/dist/types/schema/levr.schema.d.ts.map +1 -0
  171. package/dist/types/stake.d.ts +137 -0
  172. package/dist/types/stake.d.ts.map +1 -0
  173. package/dist/types/swap-v4.d.ts +97 -0
  174. package/dist/types/swap-v4.d.ts.map +1 -0
  175. package/dist/types/types.d.ts +20 -0
  176. package/dist/types/types.d.ts.map +1 -0
  177. package/dist/types/util.d.ts +5 -0
  178. package/dist/types/util.d.ts.map +1 -0
  179. package/package.json +100 -0
@@ -0,0 +1,146 @@
1
+ import { erc20Abi, formatUnits, zeroAddress } from "viem";
2
+ import { IClankerLPLocker, IClankerToken, LevrFactory_v1 } from "./abis/index.js";
3
+ import { GET_LP_LOCKER_ADDRESS } from "./constants.js";
4
+ /**
5
+ * Get project data for a clanker token
6
+ */
7
+ export async function project({ publicClient, factoryAddress, chainId, clankerToken, }) {
8
+ if (Object.values({ publicClient, factoryAddress, chainId, clankerToken }).some((value) => !value)) {
9
+ throw new Error("Invalid project params");
10
+ }
11
+ const { treasury, governor, staking, stakedToken } = await publicClient.readContract({
12
+ address: factoryAddress,
13
+ abi: LevrFactory_v1,
14
+ functionName: "getProjectContracts",
15
+ args: [clankerToken],
16
+ });
17
+ if ([treasury, governor, staking, stakedToken].some((a) => a === zeroAddress))
18
+ return null;
19
+ // Fetch token metadata, forwarder, and treasury stats using multicall
20
+ const [decimals, name, symbol, totalSupply, metadata, imageUrl, forwarder, treasuryBalance, stakingBalance,] = await publicClient.multicall({
21
+ contracts: [
22
+ {
23
+ address: clankerToken,
24
+ abi: erc20Abi,
25
+ functionName: "decimals",
26
+ },
27
+ {
28
+ address: clankerToken,
29
+ abi: erc20Abi,
30
+ functionName: "name",
31
+ },
32
+ {
33
+ address: clankerToken,
34
+ abi: erc20Abi,
35
+ functionName: "symbol",
36
+ },
37
+ {
38
+ address: clankerToken,
39
+ abi: erc20Abi,
40
+ functionName: "totalSupply",
41
+ },
42
+ {
43
+ address: clankerToken,
44
+ abi: IClankerToken,
45
+ functionName: "metadata",
46
+ },
47
+ {
48
+ address: clankerToken,
49
+ abi: IClankerToken,
50
+ functionName: "imageUrl",
51
+ },
52
+ {
53
+ address: factoryAddress,
54
+ abi: LevrFactory_v1,
55
+ functionName: "trustedForwarder",
56
+ },
57
+ // Treasury stats
58
+ {
59
+ address: clankerToken,
60
+ abi: erc20Abi,
61
+ functionName: "balanceOf",
62
+ args: [treasury],
63
+ },
64
+ {
65
+ address: clankerToken,
66
+ abi: erc20Abi,
67
+ functionName: "balanceOf",
68
+ args: [staking],
69
+ },
70
+ ],
71
+ });
72
+ // Parse metadata JSON
73
+ let parsedMetadata = null;
74
+ if (metadata.result && typeof metadata.result === "string") {
75
+ try {
76
+ parsedMetadata = JSON.parse(metadata.result);
77
+ }
78
+ catch {
79
+ // If parsing fails, leave as null
80
+ }
81
+ }
82
+ // Extract pool information from LP locker
83
+ let poolInfo;
84
+ try {
85
+ const lpLockerAddress = GET_LP_LOCKER_ADDRESS(chainId);
86
+ if (lpLockerAddress) {
87
+ // Get actual pool key from token rewards in LP locker
88
+ const tokenRewards = await publicClient.readContract({
89
+ address: lpLockerAddress,
90
+ abi: IClankerLPLocker,
91
+ functionName: "tokenRewards",
92
+ args: [clankerToken],
93
+ });
94
+ const poolKey = tokenRewards.poolKey;
95
+ poolInfo = {
96
+ poolKey,
97
+ feeDisplay: poolKey.fee === 8388608 ? "Dynamic" : `${(poolKey.fee / 10000).toFixed(2)}%`,
98
+ numPositions: tokenRewards.numPositions,
99
+ };
100
+ }
101
+ }
102
+ catch {
103
+ // If reading fails (e.g., token not deployed through Clanker), poolInfo remains undefined
104
+ }
105
+ // Calculate treasury stats
106
+ const tokenDecimals = decimals.result;
107
+ const treasuryBalanceRaw = treasuryBalance.result;
108
+ const stakingBalanceRaw = stakingBalance.result;
109
+ const totalSupplyRaw = totalSupply.result;
110
+ // Total allocated = treasury + staking balances (protocol-controlled tokens)
111
+ const totalAllocatedRaw = treasuryBalanceRaw + stakingBalanceRaw;
112
+ // Utilization = (total allocated / total supply) * 100
113
+ const utilization = totalSupplyRaw > 0n
114
+ ? Number((totalAllocatedRaw * 10000n) / totalSupplyRaw) / 100 // Convert to percentage
115
+ : 0;
116
+ const treasuryStats = {
117
+ balance: {
118
+ raw: treasuryBalanceRaw,
119
+ formatted: formatUnits(treasuryBalanceRaw, tokenDecimals),
120
+ },
121
+ totalAllocated: {
122
+ raw: totalAllocatedRaw,
123
+ formatted: formatUnits(totalAllocatedRaw, tokenDecimals),
124
+ },
125
+ utilization,
126
+ };
127
+ return {
128
+ treasury,
129
+ governor,
130
+ staking,
131
+ stakedToken,
132
+ forwarder: forwarder.result,
133
+ token: {
134
+ address: clankerToken,
135
+ decimals: tokenDecimals,
136
+ name: name.result,
137
+ symbol: symbol.result,
138
+ totalSupply: totalSupplyRaw,
139
+ metadata: parsedMetadata,
140
+ imageUrl: imageUrl.result,
141
+ },
142
+ pool: poolInfo,
143
+ treasuryStats,
144
+ };
145
+ }
146
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,212 @@
1
+ import { erc20Abi, formatUnits, zeroAddress } from "viem";
2
+ import { IClankerToken, LevrFactory_v1 } from "./abis/index.js";
3
+ import { WETH } from "./constants.js";
4
+ const registeredEvent = LevrFactory_v1.find((item) => item.type === "event" && item.name === "Registered");
5
+ /**
6
+ * Get multiple projects data
7
+ */
8
+ export async function projects({ publicClient, factoryAddress, chainId, fromBlock, toBlock = "latest", pageSize = 100, }) {
9
+ if (Object.values({ publicClient, factoryAddress, chainId }).some((value) => !value)) {
10
+ throw new Error("Invalid projects params");
11
+ }
12
+ // Determine block range
13
+ const latestBlock = await publicClient.getBlockNumber();
14
+ const from = fromBlock ?? latestBlock - latestBlock / 10n; // Default to last 10% of blocks
15
+ const to = toBlock === "latest" ? latestBlock : toBlock;
16
+ // Fetch Registered events - indexed events are efficient even across large ranges
17
+ const allLogs = (await publicClient.getLogs({
18
+ address: factoryAddress,
19
+ event: registeredEvent,
20
+ fromBlock: from,
21
+ toBlock: to,
22
+ }));
23
+ // Sort by block number descending (most recent first)
24
+ const logs = allLogs.sort((a, b) => {
25
+ if (a.blockNumber > b.blockNumber)
26
+ return -1;
27
+ if (a.blockNumber < b.blockNumber)
28
+ return 1;
29
+ return 0;
30
+ });
31
+ // Limit to pageSize
32
+ const limitedLogs = logs.slice(0, pageSize);
33
+ if (limitedLogs.length === 0) {
34
+ return {
35
+ projects: [],
36
+ fromBlock: from,
37
+ toBlock: to,
38
+ };
39
+ }
40
+ // Extract unique clanker tokens
41
+ const clankerTokens = limitedLogs.map((log) => log.args.clankerToken);
42
+ // First, get project contracts for all tokens
43
+ const projectContracts = await publicClient.multicall({
44
+ contracts: clankerTokens.map((token) => ({
45
+ address: factoryAddress,
46
+ abi: LevrFactory_v1,
47
+ functionName: "getProjectContracts",
48
+ args: [token],
49
+ })),
50
+ });
51
+ // Filter out unregistered projects and prepare valid tokens with their contracts
52
+ const validTokensWithContracts = clankerTokens
53
+ .map((token, index) => {
54
+ const projectResult = projectContracts[index].result;
55
+ if ([
56
+ projectResult.treasury,
57
+ projectResult.governor,
58
+ projectResult.staking,
59
+ projectResult.stakedToken,
60
+ ].some((a) => a === zeroAddress)) {
61
+ return null;
62
+ }
63
+ return { token, contracts: projectResult };
64
+ })
65
+ .filter(Boolean);
66
+ if (validTokensWithContracts.length === 0) {
67
+ return {
68
+ projects: [],
69
+ fromBlock: from,
70
+ toBlock: to,
71
+ };
72
+ }
73
+ // Batch fetch all token metadata and treasury stats
74
+ const contracts = validTokensWithContracts.flatMap(({ token, contracts }) => [
75
+ // Token metadata
76
+ {
77
+ address: token,
78
+ abi: erc20Abi,
79
+ functionName: "decimals",
80
+ },
81
+ {
82
+ address: token,
83
+ abi: erc20Abi,
84
+ functionName: "name",
85
+ },
86
+ {
87
+ address: token,
88
+ abi: erc20Abi,
89
+ functionName: "symbol",
90
+ },
91
+ {
92
+ address: token,
93
+ abi: erc20Abi,
94
+ functionName: "totalSupply",
95
+ },
96
+ {
97
+ address: token,
98
+ abi: IClankerToken,
99
+ functionName: "metadata",
100
+ },
101
+ {
102
+ address: token,
103
+ abi: IClankerToken,
104
+ functionName: "imageUrl",
105
+ },
106
+ // Treasury stats
107
+ {
108
+ address: token,
109
+ abi: erc20Abi,
110
+ functionName: "balanceOf",
111
+ args: [contracts.treasury],
112
+ },
113
+ {
114
+ address: token,
115
+ abi: erc20Abi,
116
+ functionName: "balanceOf",
117
+ args: [contracts.staking],
118
+ },
119
+ ]);
120
+ const results = await publicClient.multicall({ contracts });
121
+ // Parse results into Project objects
122
+ const projects = [];
123
+ const callsPerProject = 8; // Updated to include treasury and staking balance
124
+ for (let i = 0; i < validTokensWithContracts.length; i++) {
125
+ const { token, contracts: projectContracts } = validTokensWithContracts[i];
126
+ const offset = i * callsPerProject;
127
+ const decimals = results[offset].result;
128
+ const name = results[offset + 1].result;
129
+ const symbol = results[offset + 2].result;
130
+ const totalSupply = results[offset + 3].result;
131
+ const metadataStr = results[offset + 4].result;
132
+ const imageUrl = results[offset + 5].result;
133
+ const treasuryBalance = results[offset + 6].result;
134
+ const stakingBalance = results[offset + 7].result;
135
+ // Parse metadata JSON
136
+ let parsedMetadata = null;
137
+ if (metadataStr) {
138
+ try {
139
+ parsedMetadata = JSON.parse(metadataStr);
140
+ }
141
+ catch {
142
+ // If parsing fails, leave as null
143
+ }
144
+ }
145
+ // Calculate treasury stats
146
+ const totalAllocated = treasuryBalance + stakingBalance;
147
+ const utilization = totalSupply > 0n
148
+ ? Number((totalAllocated * 10000n) / totalSupply) / 100 // Convert to percentage
149
+ : 0;
150
+ const treasuryStats = {
151
+ balance: {
152
+ raw: treasuryBalance,
153
+ formatted: formatUnits(treasuryBalance, decimals),
154
+ },
155
+ totalAllocated: {
156
+ raw: totalAllocated,
157
+ formatted: formatUnits(totalAllocated, decimals),
158
+ },
159
+ utilization,
160
+ };
161
+ // Extract pool information
162
+ // Clanker V4 tokens are always paired with WETH and use the token as the hook
163
+ let poolInfo;
164
+ try {
165
+ const wethAddress = WETH(chainId)?.address;
166
+ if (wethAddress) {
167
+ // Determine currency ordering (currency0 < currency1)
168
+ const isTokenCurrency0 = token.toLowerCase() < wethAddress.toLowerCase();
169
+ // Standard Clanker V4 pool configuration
170
+ const fee = 3000; // 0.3% fee
171
+ const tickSpacing = 60;
172
+ poolInfo = {
173
+ poolKey: {
174
+ currency0: isTokenCurrency0 ? token : wethAddress,
175
+ currency1: isTokenCurrency0 ? wethAddress : token,
176
+ fee,
177
+ tickSpacing,
178
+ hooks: token, // Token acts as the hook in Clanker V4
179
+ },
180
+ feeDisplay: `${(fee / 10000).toFixed(2)}%`,
181
+ numPositions: 0n, // Would need separate query for actual count
182
+ };
183
+ }
184
+ }
185
+ catch {
186
+ // If construction fails, poolInfo remains undefined
187
+ }
188
+ projects.push({
189
+ treasury: projectContracts.treasury,
190
+ governor: projectContracts.governor,
191
+ staking: projectContracts.staking,
192
+ stakedToken: projectContracts.stakedToken,
193
+ token: {
194
+ address: token,
195
+ decimals,
196
+ name,
197
+ symbol,
198
+ totalSupply,
199
+ metadata: parsedMetadata,
200
+ imageUrl,
201
+ },
202
+ pool: poolInfo,
203
+ treasuryStats,
204
+ });
205
+ }
206
+ return {
207
+ projects,
208
+ fromBlock: from,
209
+ toBlock: to,
210
+ };
211
+ }
212
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/projects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import { formatUnits } from "viem";
2
+ import { LevrGovernor_v1 } from "./abis/index.js";
3
+ const proposalCreatedEvent = LevrGovernor_v1.find((item) => item.type === "event" && item.name === "ProposalCreated");
4
+ /**
5
+ * Get multiple proposals data from governor contract
6
+ */
7
+ export async function proposals({ publicClient, governorAddress, tokenDecimals = 18, fromBlock, toBlock = "latest", pageSize = 50, }) {
8
+ if (Object.values({ publicClient, governorAddress }).some((value) => !value)) {
9
+ throw new Error("Invalid proposals params");
10
+ }
11
+ // Determine block range
12
+ const latestBlock = await publicClient.getBlockNumber();
13
+ const from = fromBlock ?? latestBlock - latestBlock / 10n; // Default to last 10% of blocks
14
+ const to = toBlock === "latest" ? latestBlock : toBlock;
15
+ // Fetch ProposalCreated events - indexed events are efficient even across large ranges
16
+ const allLogs = (await publicClient.getLogs({
17
+ address: governorAddress,
18
+ event: proposalCreatedEvent,
19
+ fromBlock: from,
20
+ toBlock: to,
21
+ }));
22
+ // Sort by block number descending (most recent first)
23
+ const logs = allLogs.sort((a, b) => {
24
+ if (a.blockNumber > b.blockNumber)
25
+ return -1;
26
+ if (a.blockNumber < b.blockNumber)
27
+ return 1;
28
+ return 0;
29
+ });
30
+ // Limit to pageSize
31
+ const limitedLogs = logs.slice(0, pageSize);
32
+ if (limitedLogs.length === 0) {
33
+ return {
34
+ proposals: [],
35
+ fromBlock: from,
36
+ toBlock: to,
37
+ };
38
+ }
39
+ // Extract proposal IDs from events
40
+ const proposalIds = limitedLogs.map((log) => log.args.proposalId);
41
+ // Batch fetch all proposal details
42
+ const contracts = proposalIds.map((proposalId) => ({
43
+ address: governorAddress,
44
+ abi: LevrGovernor_v1,
45
+ functionName: "getProposal",
46
+ args: [proposalId],
47
+ }));
48
+ const results = await publicClient.multicall({ contracts });
49
+ // Parse results into FormattedProposalDetails objects
50
+ const proposals = [];
51
+ for (let i = 0; i < proposalIds.length; i++) {
52
+ const result = results[i].result;
53
+ // Skip if proposal data is invalid
54
+ if (!result) {
55
+ continue;
56
+ }
57
+ proposals.push({
58
+ id: result.id,
59
+ proposalType: result.proposalType,
60
+ proposer: result.proposer,
61
+ amount: {
62
+ raw: result.amount,
63
+ formatted: formatUnits(result.amount, tokenDecimals),
64
+ },
65
+ recipient: result.recipient,
66
+ description: result.description,
67
+ createdAt: {
68
+ timestamp: result.createdAt,
69
+ date: new Date(Number(result.createdAt) * 1000),
70
+ },
71
+ votingStartsAt: {
72
+ timestamp: result.votingStartsAt,
73
+ date: new Date(Number(result.votingStartsAt) * 1000),
74
+ },
75
+ votingEndsAt: {
76
+ timestamp: result.votingEndsAt,
77
+ date: new Date(Number(result.votingEndsAt) * 1000),
78
+ },
79
+ yesVotes: {
80
+ raw: result.yesVotes,
81
+ formatted: formatUnits(result.yesVotes, tokenDecimals),
82
+ },
83
+ noVotes: {
84
+ raw: result.noVotes,
85
+ formatted: formatUnits(result.noVotes, tokenDecimals),
86
+ },
87
+ totalBalanceVoted: result.totalBalanceVoted,
88
+ executed: result.executed,
89
+ cycleId: result.cycleId,
90
+ });
91
+ }
92
+ return {
93
+ proposals,
94
+ fromBlock: from,
95
+ toBlock: to,
96
+ };
97
+ }
98
+ //# sourceMappingURL=proposals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proposals.js","sourceRoot":"","sources":["../../src/proposals.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAA;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AA2BxC,MAAM,oBAAoB,GAAG,eAAe,CAAC,IAAI,CAC/C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB,CACnE,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAC9B,YAAY,EACZ,eAAe,EACf,aAAa,GAAG,EAAE,EAClB,SAAS,EACT,OAAO,GAAG,QAAQ,EAClB,QAAQ,GAAG,EAAE,GACG;IAChB,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;IAC7C,CAAC;IAED,wBAAwB;IACxB,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,cAAc,EAAE,CAAA;IACvD,MAAM,IAAI,GAAG,SAAS,IAAI,WAAW,GAAG,WAAW,GAAG,GAAG,CAAA,CAAC,gCAAgC;IAC1F,MAAM,EAAE,GAAG,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAA;IAEvD,uFAAuF;IACvF,MAAM,OAAO,GAAG,CAAC,MAAM,YAAY,CAAC,OAAO,CAAC;QAC1C,OAAO,EAAE,eAAe;QACxB,KAAK,EAAE,oBAAoB;QAC3B,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,EAAE;KACZ,CAAC,CAA2B,CAAA;IAE7B,sDAAsD;IACtD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACjC,IAAI,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;YAAE,OAAO,CAAC,CAAC,CAAA;QAC5C,IAAI,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;YAAE,OAAO,CAAC,CAAA;QAC3C,OAAO,CAAC,CAAA;IACV,CAAC,CAAC,CAAA;IAEF,oBAAoB;IACpB,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;IAE3C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,SAAS,EAAE,EAAE;YACb,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,EAAE;SACZ,CAAA;IACH,CAAC;IAED,mCAAmC;IACnC,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,UAAW,CAAC,CAAA;IAElE,mCAAmC;IACnC,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACjD,OAAO,EAAE,eAAe;QACxB,GAAG,EAAE,eAAe;QACpB,YAAY,EAAE,aAAsB;QACpC,IAAI,EAAE,CAAC,UAAU,CAAC;KACnB,CAAC,CAAC,CAAA;IAEH,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;IAE3D,sDAAsD;IACtD,MAAM,SAAS,GAA+B,EAAE,CAAA;IAEhD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,MAezB,CAAA;QAED,mCAAmC;QACnC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,SAAQ;QACV,CAAC;QAED,SAAS,CAAC,IAAI,CAAC;YACb,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE;gBACN,GAAG,EAAE,MAAM,CAAC,MAAM;gBAClB,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;aACrD;YACD,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,SAAS,EAAE;gBACT,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,IAAI,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;aAChD;YACD,cAAc,EAAE;gBACd,SAAS,EAAE,MAAM,CAAC,cAAc;gBAChC,IAAI,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;aACrD;YACD,YAAY,EAAE;gBACZ,SAAS,EAAE,MAAM,CAAC,YAAY;gBAC9B,IAAI,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;aACnD;YACD,QAAQ,EAAE;gBACR,GAAG,EAAE,MAAM,CAAC,QAAQ;gBACpB,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC;aACvD;YACD,OAAO,EAAE;gBACP,GAAG,EAAE,MAAM,CAAC,OAAO;gBACnB,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC;aACtD;YACD,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;YAC3C,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC,CAAA;IACJ,CAAC;IAED,OAAO;QACL,SAAS;QACT,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,EAAE;KACZ,CAAA;AACH,CAAC"}
@@ -0,0 +1,169 @@
1
+ import { encodeAbiParameters, keccak256 } from "viem";
2
+ import { IClankerHookDynamicFee, IClankerHookStaticFee, V4Quoter } from "./abis/index.js";
3
+ import { UNISWAP_V4_QUOTER } from "./constants.js";
4
+ /**
5
+ * @description Try to get static fees from a Clanker hook using multicall
6
+ * @param publicClient Public client
7
+ * @param hookAddress Hook address
8
+ * @param poolId Pool ID
9
+ * @returns Static fees or undefined
10
+ */
11
+ const tryGetStaticFees = async (publicClient, hookAddress, poolId) => {
12
+ try {
13
+ const results = await publicClient.multicall({
14
+ contracts: [
15
+ {
16
+ address: hookAddress,
17
+ abi: IClankerHookStaticFee,
18
+ functionName: "clankerFee",
19
+ args: [poolId],
20
+ },
21
+ {
22
+ address: hookAddress,
23
+ abi: IClankerHookStaticFee,
24
+ functionName: "pairedFee",
25
+ args: [poolId],
26
+ },
27
+ ],
28
+ });
29
+ if (results[0].status === "success" && results[1].status === "success") {
30
+ return {
31
+ clankerFee: Number(results[0].result),
32
+ pairedFee: Number(results[1].result),
33
+ };
34
+ }
35
+ return undefined;
36
+ }
37
+ catch {
38
+ return undefined;
39
+ }
40
+ };
41
+ /**
42
+ * @description Try to get dynamic fee configuration from a Clanker hook
43
+ * @param publicClient Public client
44
+ * @param hookAddress Hook address
45
+ * @param poolId Pool ID
46
+ * @returns Dynamic fee config or undefined
47
+ */
48
+ const tryGetDynamicFees = async (publicClient, hookAddress, poolId) => {
49
+ try {
50
+ const config = await publicClient.readContract({
51
+ address: hookAddress,
52
+ abi: IClankerHookDynamicFee,
53
+ functionName: "poolConfigVars",
54
+ args: [poolId],
55
+ });
56
+ return {
57
+ baseFee: Number(config.baseFee),
58
+ maxLpFee: Number(config.maxLpFee),
59
+ };
60
+ }
61
+ catch {
62
+ return undefined;
63
+ }
64
+ };
65
+ /**
66
+ * @description Get hook fee information from Clanker hooks
67
+ * @param publicClient Public client
68
+ * @param poolKey Pool key containing hook address
69
+ * @returns Hook fee information or undefined
70
+ */
71
+ const getHookFees = async (publicClient, poolKey) => {
72
+ // Generate pool ID for hook queries (keccak256 of abi.encode(PoolKey))
73
+ const poolId = keccak256(encodeAbiParameters([
74
+ {
75
+ type: "tuple",
76
+ components: [
77
+ { name: "currency0", type: "address" },
78
+ { name: "currency1", type: "address" },
79
+ { name: "fee", type: "uint24" },
80
+ { name: "tickSpacing", type: "int24" },
81
+ { name: "hooks", type: "address" },
82
+ ],
83
+ },
84
+ ], [poolKey]));
85
+ // Try static fees first
86
+ const staticFees = await tryGetStaticFees(publicClient, poolKey.hooks, poolId);
87
+ if (staticFees) {
88
+ return {
89
+ type: "static",
90
+ clankerFee: staticFees.clankerFee,
91
+ pairedFee: staticFees.pairedFee,
92
+ };
93
+ }
94
+ // Try dynamic fees
95
+ const dynamicFees = await tryGetDynamicFees(publicClient, poolKey.hooks, poolId);
96
+ if (dynamicFees) {
97
+ return {
98
+ type: "dynamic",
99
+ baseFee: dynamicFees.baseFee,
100
+ maxLpFee: dynamicFees.maxLpFee,
101
+ };
102
+ }
103
+ return undefined;
104
+ };
105
+ /**
106
+ * @description Get a swap quote from Uniswap V4 Quoter
107
+ * @param params Quote parameters including pool key and amount
108
+ * @returns Quote result with output amount, gas estimate, and hook fees
109
+ *
110
+ * @remarks
111
+ * The V4Quoter uses state-changing calls that are simulated via static call.
112
+ * The quoter returns the expected output amount for the given input.
113
+ *
114
+ * This function works for both native ETH and ERC20 swaps:
115
+ * - Native ETH → Token: Quote uses WETH address, swap router handles wrapping
116
+ * - Token → Native ETH: Quote uses WETH address, swap router handles unwrapping
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * const quote = await quoteV4({
121
+ * publicClient,
122
+ * chainId: base.id,
123
+ * poolKey,
124
+ * zeroForOne: true,
125
+ * amountIn: parseEther('1'),
126
+ * })
127
+ * console.log(`Output: ${formatEther(quote.amountOut)}`)
128
+ * console.log(`Fees:`, quote.hookFees)
129
+ * ```
130
+ */
131
+ export const quoteV4 = async ({ publicClient, chainId, poolKey, zeroForOne, amountIn, hookData = "0x", }) => {
132
+ const quoterAddress = UNISWAP_V4_QUOTER(chainId);
133
+ if (!quoterAddress)
134
+ throw new Error("V4 Quoter address not found for chain");
135
+ // Always fetch hook fee information (in parallel with quote)
136
+ const hookFeesPromise = getHookFees(publicClient, poolKey);
137
+ // Call the quoter using simulateContract (static call simulation)
138
+ // This is equivalent to ethers.js callStatic
139
+ const [{ result }, hookFees] = await Promise.all([
140
+ publicClient.simulateContract({
141
+ address: quoterAddress,
142
+ abi: V4Quoter,
143
+ functionName: "quoteExactInputSingle",
144
+ args: [
145
+ {
146
+ poolKey: {
147
+ currency0: poolKey.currency0,
148
+ currency1: poolKey.currency1,
149
+ fee: poolKey.fee,
150
+ tickSpacing: poolKey.tickSpacing,
151
+ hooks: poolKey.hooks,
152
+ },
153
+ zeroForOne,
154
+ exactAmount: amountIn,
155
+ hookData,
156
+ },
157
+ ],
158
+ }),
159
+ hookFeesPromise,
160
+ ]);
161
+ // The quoter returns [amountOut: bigint, gasEstimate: bigint]
162
+ const [amountOut, gasEstimate] = result;
163
+ return {
164
+ amountOut,
165
+ gasEstimate,
166
+ hookFees,
167
+ };
168
+ };
169
+ //# sourceMappingURL=quote-v4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote-v4.js","sourceRoot":"","sources":["../../src/quote-v4.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Schema } from 'effect';
2
+ export const NonEmptyString = (message) => Schema.String.pipe(Schema.nonEmptyString({ description: message })).annotations({
3
+ description: 'Non-empty string value',
4
+ });
5
+ export const UrlString = Schema.String.pipe(Schema.pattern(/^\w+:\/\/.+/)).annotations({
6
+ description: 'URL string (http(s), ipfs, etc.)',
7
+ });
8
+ export const EthereumAddress = Schema.String.pipe(Schema.pattern(/^0x[a-fA-F0-9]{40}$/)).annotations({
9
+ description: 'Ethereum address (0x...)',
10
+ });
11
+ //# sourceMappingURL=base.schema.js.map