timelock-sdk 0.0.18 → 0.0.20

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/dist/client.js CHANGED
@@ -1,4 +1,19 @@
1
- "use client";import{lensAbi as e,optionsMarketAbi as t}from"./optionsMarket-BsJTpwtl.js";import{getErc20 as n,getPriceAtTick as r,getTimelockLens as i,getTimelockMarket as a,getUniswapMathLens as o,roundTickDown as s,timelockLenses as c,token0ToToken1 as l,token1ToToken0 as u,uniswapMathLenses as d,wrapAmount as f,wrapPrice as p}from"./numberUtils-DP-pDRRs.js";import{singleOwnerVaultAbi as m,uniswapV3PoolAbi as h}from"./uniswapV3Pool-Copswrde.js";import{encodeFunctionData as g,erc20Abi as _,maxUint256 as v}from"viem";import y,{createContext as b,useContext as x,useMemo as S}from"react";import{useAccount as C,useChainId as w,useClient as T,useReadContract as E,useWaitForTransactionReceipt as D,useWriteContract as O}from"wagmi";import{GraphQLClient as k}from"graphql-request";import A from"graphql-tag";import{waitForTransactionReceipt as j}from"viem/actions";import{useQuery as M}from"@tanstack/react-query";const N=A`
1
+ 'use client';
2
+
3
+
4
+ import { lensAbi, optionsMarketAbi } from "./optionsMarket-BsJTpwtl.js";
5
+ import { getErc20, getPriceAtTick, getTimelockLens, getTimelockMarket, getUniswapMathLens, roundTickDown, timelockLenses, token0ToToken1, token1ToToken0, uniswapMathLenses, wrapAmount, wrapPrice } from "./numberUtils-DP-pDRRs.js";
6
+ import { singleOwnerVaultAbi, uniswapV3PoolAbi } from "./uniswapV3Pool-Copswrde.js";
7
+ import { encodeFunctionData, erc20Abi, maxUint256 } from "viem";
8
+ import React, { createContext, useContext, useMemo } from "react";
9
+ import { useAccount, useChainId, useClient, useReadContract, useWaitForTransactionReceipt, useWriteContract } from "wagmi";
10
+ import { GraphQLClient } from "graphql-request";
11
+ import gql from "graphql-tag";
12
+ import { waitForTransactionReceipt } from "viem/actions";
13
+ import { useQuery } from "@tanstack/react-query";
14
+
15
+ //#region src/generated/graphql.ts
16
+ const GetActiveUserOptionsDocument = gql`
2
17
  query GetActiveUserOptions($user: String!) {
3
18
  UserOption(
4
19
  where: {ownerAddr: {_eq: $user}, fullyExercised: {_eq: false}}
@@ -29,7 +44,8 @@
29
44
  fullyExercised
30
45
  }
31
46
  }
32
- `,P=A`
47
+ `;
48
+ const GetClosedUserOptionsDocument = gql`
33
49
  query GetClosedUserOptions($user: String!) {
34
50
  UserOption(
35
51
  where: {ownerAddr: {_eq: $user}, fullyExercised: {_eq: true}}
@@ -60,7 +76,8 @@
60
76
  fullyExercised
61
77
  }
62
78
  }
63
- `,F=A`
79
+ `;
80
+ const GetMarketDataDocument = gql`
64
81
  query GetMarketData($marketAddr: String!) {
65
82
  TimelockMarket(where: {id: {_eq: $marketAddr}}, limit: 1) {
66
83
  id
@@ -80,4 +97,649 @@
80
97
  payoutAssetName
81
98
  }
82
99
  }
83
- `,I=(e,t,n,r)=>e();function L(e,t=I){return{GetActiveUserOptions(n,r,i){return t(t=>e.request({document:N,variables:n,requestHeaders:{...r,...t},signal:i}),`GetActiveUserOptions`,`query`,n)},GetClosedUserOptions(n,r,i){return t(t=>e.request({document:P,variables:n,requestHeaders:{...r,...t},signal:i}),`GetClosedUserOptions`,`query`,n)},GetMarketData(n,r,i){return t(t=>e.request({document:F,variables:n,requestHeaders:{...r,...t},signal:i}),`GetMarketData`,`query`,n)}}}const R=b(void 0),z=({children:e,marketData:t,envioGraphqlUrl:n})=>{let r=w(),i=c[r],a=d[r];return y.createElement(R.Provider,{value:{marketData:t||{},lensAddr:i,uniswapMathLensAddr:a,envioGraphqlUrl:n}},e)},B=()=>{let e=x(R);if(e===void 0)throw Error(`useCurrentMarket must be used within a TimelockMarketProvider`);return e.marketData},V=()=>{let e=x(R);if(e===void 0)throw Error(`useConfig must be used within a TimelockMarketProvider`);return{lensAddr:e.lensAddr,uniswapMathLensAddr:e.uniswapMathLensAddr,envioGraphqlUrl:e.envioGraphqlUrl,graphqlClient:e.envioGraphqlUrl?L(new k(e.envioGraphqlUrl)):void 0}},H=e=>{let{graphqlClient:t}=V(),{data:n}=M({queryKey:[`marketData`,e||`--`],queryFn:()=>t.GetMarketData({marketAddr:e.toLowerCase()}),select:e=>({...e.TimelockMarket[0],pool:e.TimelockMarket[0].pool,vault:e.TimelockMarket[0].vault,optionAsset:e.TimelockMarket[0].optionAsset,payoutAsset:e.TimelockMarket[0].payoutAsset,optionsCount:BigInt(e.TimelockMarket[0].optionsCount),tradersCount:BigInt(e.TimelockMarket[0].tradersCount)}),enabled:!!e&&!!t});return n||{}},U=e=>{let{vault:n}=H(e),r=T(),{data:i}=E({address:n,abi:m,functionName:`lowestTick`}),{writeContractAsync:a,data:o,isPending:s,error:c}=O(),{isLoading:l,isSuccess:u}=D({hash:o});return{exerciseOption:async(n,o)=>{if(!r)throw Error(`Wallet not connected`);if(i===void 0||!e)throw Error(`Lowest tick lower not available`);let s=await a({address:e,abi:t,functionName:`exerciseOption`,args:[n,o,0n,i]});return await j(r,{hash:s}),s},hash:o,isPending:s,isConfirming:l,isSuccess:u,error:c,isLoading:s||l}},W=()=>{let e=T(),t=e?i(e):void 0;return{uniswapLens:e?o(e):void 0,timelockLens:t}},G=(t,n,r=100)=>{let{timelockLens:i}=W(),{optionAssetDecimals:a}=H(t),{data:o,refetch:s}=E({address:i==null?void 0:i.address,abi:e,functionName:`getMaxPositionSizeAtCurrentTick`,args:[t,r],query:{enabled:!!t&&!!i},gas:100000000n}),{data:c,refetch:l}=E({address:i==null?void 0:i.address,abi:e,functionName:`getMaxPositionSize`,args:[t,n,r],query:{enabled:!!t&&!!i&&n!==void 0},gas:100000000n}),u=n===void 0?o:c,{maxCallSize:d,maxPutSize:p}=S(()=>u&&a?{maxCallSize:f(u[0],a),maxPutSize:f(u[1],a)}:{},[u,a]);return{maxCallSize:d,maxPutSize:p,refetch:()=>{s(),l()}}},K=t=>{let{timelockLens:n}=W(),r=T(),{data:i}=E({address:n==null?void 0:n.address,abi:e,functionName:`getPoolData`,args:t?[t]:void 0,query:{enabled:!!t&&!!r}});return i||{}},q=e=>{let{tickSpacing:t}=K(e),{data:n}=E({address:e,abi:h,functionName:`slot0`,args:[]}),r=n==null?void 0:n[1];return{exact:r,rounded:r&&t?Math.floor(r/t)*t:void 0}},J=e=>{let{timelockLens:r}=W(),{payoutAsset:i,vault:o,pool:c,optionAssetIsToken0:l}=H(e),{tickSpacing:u}=K(c),{exact:d}=q(c),f=T(),{address:p}=C(),{writeContractAsync:m,data:h,isPending:g,error:y}=O(),{isLoading:b,isSuccess:x}=D({hash:h}),S=async t=>{if(!f||!p)throw Error(`Wallet not connected`);if(!i||!e)throw Error(`Tokens not available`);await n(i,f).read.allowance([p,e])<t&&await j(f,{hash:await m({address:i,abi:_,functionName:`approve`,args:[e,v]})})};return{mintOption:async(n,i,c,p)=>{if(!f)throw Error(`Wallet not connected`);if(!r||!o||!e||!d||!u)throw Error(`Lowest tick lower not available`);p=s(p??d,u),(n===`CALL`&&l||n===`PUT`&&!l)&&(p+=u),await S(await a(e,f).read.calculatePremium([n===`CALL`?0:1,i,p,BigInt(c)]));let h=await m({address:e,abi:t,functionName:`mintOption`,args:[n===`CALL`?0:1,i,p,BigInt(c),BigInt(1e69),await r.read.getRefTick([o,p])]});return await j(f,{hash:h}),h},hash:h,isPending:g,isConfirming:b,isSuccess:x,error:y,isLoading:g||b}},ee=e=>{let{marketAddr:t,optionType:n,entryTick:r,positionSizeCurrent:i}=e,{pool:a,optionAssetIsToken0:o,payoutAssetDecimals:s}=H(t),{exact:c}=q(a),{displayPnl:d,unrealizedPayout:p}=S(()=>{if(o===void 0||c===void 0||!i||!s)return{};let e=o?l(i,c)-l(i,r):u(i,c)-u(i,r),t=f(n===`CALL`?e:-e,s);return{unrealizedPayout:f(t.scaled<0?0n:t.scaled,s),displayPnl:t}},[e,o,c,i]);return{displayPnl:d,unrealizedPayout:p}},te=(e,n,r,i)=>{let{pool:a,payoutAssetDecimals:o}=H(e),{tickSpacing:s}=K(a),c=q(a),l=S(()=>{if(!(c.rounded===void 0||s===void 0))return n===`CALL`?c.rounded+s:c.rounded},[c.rounded,s,n]),{data:u}=E({address:e,abi:t,functionName:`calculatePremium`,args:l===void 0?void 0:[n===`CALL`?0:1,r,l,BigInt(i)],query:{enabled:c.rounded!==void 0&&o!==void 0&&s!==void 0&&l!==void 0}});return S(()=>{if(!(u===void 0||o===void 0))return f(u,o)},[u,o])},Y=(e,t=!1)=>{let{graphqlClient:n}=V(),{data:r,...i}=M({queryKey:[`userTrades`,e||`--`,t],queryFn:()=>t?n==null?void 0:n.GetActiveUserOptions({user:e.toLowerCase()}):n==null?void 0:n.GetClosedUserOptions({user:e.toLowerCase()}),select:e=>{var t;return e==null||(t=e.UserOption)==null?void 0:t.map(e=>({...e,id:BigInt(e.id),marketAddr:e.marketAddr,optionType:e.optionType,createdAt:new Date(Number(e.createdAt)*1e3),expiresAt:new Date(Number(e.expiresAt)*1e3),premiumPaid:BigInt(e.premiumPaid),realizedPayout:BigInt(e.realizedPayout),liquiditiesAtOpen:e.liquiditiesAtOpen.map(e=>BigInt(e)),liquiditiesCurrent:e.liquiditiesCurrent.map(e=>BigInt(e)),positionSizeAtOpen:BigInt(e.positionSizeAtOpen),positionSizeCurrent:BigInt(e.positionSizeCurrent),strikePrice:BigInt(e.strikePrice),entryPrice:BigInt(e.entryPrice)}))},enabled:!!e&&!!n});return{data:S(()=>(r==null?void 0:r.sort((e,t)=>t.createdAt.getTime()-e.createdAt.getTime()))||[],[r]),...i}},ne=e=>Y(e,!0),re=e=>Y(e,!1),X=(e,t)=>{let{token0Decimals:n,token1Decimals:i}=K(t);return S(()=>e&&n&&i?p(r(e),n,i):void 0,[e,n,i])},Z=e=>{let t=q(e);return{currentPrice:X(t.exact,e),currentTick:t}},Q=e=>{let{data:t}=E({address:e,abi:m,functionName:`pool`});return{pool:t}},ie=e=>{let t=T(),{pool:n}=Q(e),r=q(n),{timelockLens:i}=W(),{writeContractAsync:a,data:o,isPending:s,error:c}=O(),{isLoading:l,isSuccess:u}=D({hash:o}),d=async(n,r,o)=>{if(!t)throw Error(`Wallet not connected`);if(!e||!i)throw Error(`Vault/lens not available`);let s=await a({address:e,abi:m,functionName:`burn`,args:[n,r,o,await i.read.getRefTick([e,n])]});return await j(t,{hash:s}),s};return{burnMultiple:async n=>{if(!t)throw Error(`Wallet not connected`);if(!r.exact)throw Error(`Current tick not available`);if(n.length===0)throw Error(`No positions to burn`);if(!i||!e)throw Error(`Vault/lens not available`);if(n.length===1)await d(n[0].tickLower,n[0].tickUpper,n[0].liquidity);else{let r=await i.read.batchGetRefTick([e,n.map(e=>e.tickLower)]);await j(t,{hash:await a({address:e,abi:m,functionName:`multicall`,args:[n.map((e,t)=>g({abi:m,functionName:`burn`,args:[e.tickLower,e.tickUpper,e.liquidity,r[t]]}))]})})}},burn:d,hash:o,isPending:s,isConfirming:l,isSuccess:u,error:c,isLoading:s||l}},ae=e=>{let{timelockLens:t}=W(),{pool:n}=Q(e),{token0Decimals:r,token1Decimals:i}=K(n),{currentPrice:a}=Z(n),{data:o=[],refetch:s}=M({queryKey:[`liquidityBlocks`,e],queryFn:()=>t.read.getAllBlocks([e]),enabled:!!e&&!!t}),{totalAmount0:c,totalAmount1:l,borrowedAmount0:u,borrowedAmount1:d}=S(()=>({totalAmount0:r?f(o.reduce((e,t)=>e+t.totalAmount0,0n),r):void 0,totalAmount1:i?f(o.reduce((e,t)=>e+t.totalAmount1,0n),i):void 0,borrowedAmount0:r?f(o.reduce((e,t)=>e+t.borrowedAmount0,0n),r):void 0,borrowedAmount1:i?f(o.reduce((e,t)=>e+t.borrowedAmount1,0n),i):void 0}),[o,r,i]);return{tvl1:S(()=>{if(!c||!l||!a||!i)return;let e=c.scaled*a.scaled/10n**18n,t=l.scaled;return f(e+t,i)},[c,l,a,i]),blocks:o,totalAmount0:c,totalAmount1:l,borrowedAmount0:u,borrowedAmount1:d,refetch:s}},$=async(e,t,n,r,i)=>{let a=Array(t.length).fill(i),o=await e.read.batchGetAmountsForLiquidityTicks([a,t,n,r]),s=0n,c=0n,l=[],u=[];for(let e of o[0])s+=e,l.push(e);for(let e of o[1])c+=e,u.push(e);return{totalAmount0:s,totalAmount1:c,amounts0:l,amounts1:u}},oe=e=>{let t=T(),{address:r}=C(),{pool:i}=Q(e),{timelockLens:a,uniswapLens:o}=W(),s=q(i),{token0:c,token1:l}=K(i),{writeContractAsync:u,data:d,isPending:f,error:p}=O(),{isLoading:h,isSuccess:y}=D({hash:d}),b=async i=>{if(!r||!t)throw Error(`Wallet not connected`);if(s.exact===void 0||!c||!l||!e||!o)throw Error(`Current tick not available`);let{totalAmount0:a,totalAmount1:d}=await $(o,i.map(e=>e.tickLower),i.map(e=>e.tickUpper),i.map(e=>e.liquidity),s.exact),[f,p]=await Promise.all([n(c,t).read.allowance([r,e]),n(l,t).read.allowance([r,e])]),m=[];if(f<=a){let n=await u({address:c,abi:_,functionName:`approve`,args:[e,v]});m.push(j(t,{hash:n}))}if(p<=d){let n=await u({address:l,abi:_,functionName:`approve`,args:[e,v]});m.push(j(t,{hash:n}))}m.length>0&&await Promise.all(m)},x=async(n,r,i)=>{if(!t)throw Error(`Wallet not connected`);if(!e||!a)throw Error(`Vault/lens not available`);await b([{tickLower:n,tickUpper:r,liquidity:i}]);let o=await u({address:e,abi:m,functionName:`mint`,args:[n,r,i,await a.read.getRefTick([e,n])]});return await j(t,{hash:o}),o};return{mintMultiple:async n=>{if(!t)throw Error(`Wallet not connected`);if(!s.exact)throw Error(`Current tick not available`);if(n.length===0)throw Error(`No positions to mint`);if(!a||!e)throw Error(`Vault/lens not available`);if(n.length===1)await x(n[0].tickLower,n[0].tickUpper,n[0].liquidity);else{await b(n);let r=await a.read.batchGetRefTick([e,n.map(e=>e.tickLower)]);await j(t,{hash:await u({address:e,abi:m,functionName:`multicall`,args:[n.map((e,t)=>g({abi:m,functionName:`mint`,args:[e.tickLower,e.tickUpper,e.liquidity,r[t]]}))]})})}},mint:x,hash:d,isPending:f,isConfirming:h,isSuccess:y,error:p,isLoading:f||h}},se=t=>{let{timelockLens:n}=W(),{pool:r}=Q(t),{token0Decimals:i,token1Decimals:a}=K(r),{data:o,refetch:s}=E({address:n==null?void 0:n.address,abi:e,functionName:`getVaultTVL`,args:[t],query:{enabled:!!t&&!!n}}),c=o&&i?f(o[0],i):void 0,l=o&&a?f(o[1],a):void 0,u=o&&i?f(o[2],i):void 0,d=o&&a?f(o[3],a):void 0;return{tvl0:o&&i?f(o[4],i):void 0,tvl1:o&&a?f(o[5],a):void 0,totalAmount0:c,totalAmount1:l,borrowedAmount0:u,borrowedAmount1:d,refetch:s}};export{z as TimelockMarketProvider,$ as batchGetAmountsFromLiquidity,ne as useActiveUserOptions,ie as useBurnLiquidity,re as useClosedUserOptions,B as useCurrentMarket,Z as useCurrentPrice,q as useCurrentTick,U as useExerciseOption,W as useLens,ae as useLiquidityBlocks,H as useMarketData,G as useMaxPositionSize,oe as useMintLiquidity,J as useMintOption,ee as useOptionPnl,te as useOptionPremium,K as usePoolData,X as usePriceAtTick,V as useTimelockConfig,Q as useVaultData,se as useVaultTVL};
100
+ `;
101
+ const defaultWrapper = (action, _operationName, _operationType, _variables) => action();
102
+ function getSdk(client, withWrapper = defaultWrapper) {
103
+ return {
104
+ GetActiveUserOptions(variables, requestHeaders, signal) {
105
+ return withWrapper((wrappedRequestHeaders) => client.request({
106
+ document: GetActiveUserOptionsDocument,
107
+ variables,
108
+ requestHeaders: {
109
+ ...requestHeaders,
110
+ ...wrappedRequestHeaders
111
+ },
112
+ signal
113
+ }), "GetActiveUserOptions", "query", variables);
114
+ },
115
+ GetClosedUserOptions(variables, requestHeaders, signal) {
116
+ return withWrapper((wrappedRequestHeaders) => client.request({
117
+ document: GetClosedUserOptionsDocument,
118
+ variables,
119
+ requestHeaders: {
120
+ ...requestHeaders,
121
+ ...wrappedRequestHeaders
122
+ },
123
+ signal
124
+ }), "GetClosedUserOptions", "query", variables);
125
+ },
126
+ GetMarketData(variables, requestHeaders, signal) {
127
+ return withWrapper((wrappedRequestHeaders) => client.request({
128
+ document: GetMarketDataDocument,
129
+ variables,
130
+ requestHeaders: {
131
+ ...requestHeaders,
132
+ ...wrappedRequestHeaders
133
+ },
134
+ signal
135
+ }), "GetMarketData", "query", variables);
136
+ }
137
+ };
138
+ }
139
+
140
+ //#endregion
141
+ //#region src/providers/TimelockMarketProvider.tsx
142
+ const TimelockMarketContext = createContext(void 0);
143
+ const TimelockMarketProvider = ({ children, marketData, envioGraphqlUrl }) => {
144
+ const chainId = useChainId();
145
+ const lensAddr = timelockLenses[chainId];
146
+ const uniswapMathLensAddr = uniswapMathLenses[chainId];
147
+ return /* @__PURE__ */ React.createElement(TimelockMarketContext.Provider, { value: {
148
+ marketData: marketData || {},
149
+ lensAddr,
150
+ uniswapMathLensAddr,
151
+ envioGraphqlUrl
152
+ } }, children);
153
+ };
154
+ const useCurrentMarket = () => {
155
+ const context = useContext(TimelockMarketContext);
156
+ if (context === void 0) throw new Error("useCurrentMarket must be used within a TimelockMarketProvider");
157
+ return context.marketData;
158
+ };
159
+ const useTimelockConfig = () => {
160
+ const context = useContext(TimelockMarketContext);
161
+ if (context === void 0) throw new Error("useConfig must be used within a TimelockMarketProvider");
162
+ return {
163
+ lensAddr: context.lensAddr,
164
+ uniswapMathLensAddr: context.uniswapMathLensAddr,
165
+ envioGraphqlUrl: context.envioGraphqlUrl,
166
+ graphqlClient: context.envioGraphqlUrl ? getSdk(new GraphQLClient(context.envioGraphqlUrl)) : void 0
167
+ };
168
+ };
169
+
170
+ //#endregion
171
+ //#region src/hooks/market/useMarketData.ts
172
+ const useMarketData = (marketAddr) => {
173
+ const { graphqlClient } = useTimelockConfig();
174
+ const { data } = useQuery({
175
+ queryKey: ["marketData", marketAddr || "--"],
176
+ queryFn: () => graphqlClient.GetMarketData({ marketAddr: marketAddr.toLowerCase() }),
177
+ select: (data$1) => ({
178
+ ...data$1.TimelockMarket[0],
179
+ pool: data$1.TimelockMarket[0].pool,
180
+ vault: data$1.TimelockMarket[0].vault,
181
+ optionAsset: data$1.TimelockMarket[0].optionAsset,
182
+ payoutAsset: data$1.TimelockMarket[0].payoutAsset,
183
+ optionsCount: BigInt(data$1.TimelockMarket[0].optionsCount),
184
+ tradersCount: BigInt(data$1.TimelockMarket[0].tradersCount)
185
+ }),
186
+ enabled: !!marketAddr && !!graphqlClient
187
+ });
188
+ return data || {};
189
+ };
190
+
191
+ //#endregion
192
+ //#region src/hooks/market/useExerciseOption.ts
193
+ const useExerciseOption = (marketAddr) => {
194
+ const { vault } = useMarketData(marketAddr);
195
+ const client = useClient();
196
+ const { data: lowestTick } = useReadContract({
197
+ address: vault,
198
+ abi: singleOwnerVaultAbi,
199
+ functionName: "lowestTick"
200
+ });
201
+ const { writeContractAsync, data: hash, isPending, error } = useWriteContract();
202
+ const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash });
203
+ const exerciseOption = async (optionId, liquidities) => {
204
+ if (!client) throw new Error("Wallet not connected");
205
+ if (lowestTick === void 0 || !marketAddr) throw new Error("Lowest tick lower not available");
206
+ const hash$1 = await writeContractAsync({
207
+ address: marketAddr,
208
+ abi: optionsMarketAbi,
209
+ functionName: "exerciseOption",
210
+ args: [
211
+ optionId,
212
+ liquidities,
213
+ 0n,
214
+ lowestTick
215
+ ]
216
+ });
217
+ await waitForTransactionReceipt(client, { hash: hash$1 });
218
+ return hash$1;
219
+ };
220
+ return {
221
+ exerciseOption,
222
+ hash,
223
+ isPending,
224
+ isConfirming,
225
+ isSuccess,
226
+ error,
227
+ isLoading: isPending || isConfirming
228
+ };
229
+ };
230
+
231
+ //#endregion
232
+ //#region src/hooks/useLens.ts
233
+ const useLens = () => {
234
+ const client = useClient();
235
+ const timelockLens = useMemo(() => client ? getTimelockLens(client) : void 0, [client]);
236
+ return {
237
+ uniswapLens: useMemo(() => client ? getUniswapMathLens(client) : void 0, [client]),
238
+ timelockLens
239
+ };
240
+ };
241
+
242
+ //#endregion
243
+ //#region src/hooks/market/useMaxPositionSize.ts
244
+ const useMaxPositionSize = (marketAddr, strikeTick, maxBorrowableRange = 100) => {
245
+ const { timelockLens } = useLens();
246
+ const { optionAssetDecimals } = useMarketData(marketAddr);
247
+ const { data: data0, refetch: refetch0 } = useReadContract({
248
+ address: timelockLens === null || timelockLens === void 0 ? void 0 : timelockLens.address,
249
+ abi: lensAbi,
250
+ functionName: "getMaxPositionSizeAtCurrentTick",
251
+ args: [marketAddr, maxBorrowableRange],
252
+ query: { enabled: !!marketAddr && !!timelockLens },
253
+ gas: 100000000n
254
+ });
255
+ const { data: data1, refetch: refetch1 } = useReadContract({
256
+ address: timelockLens === null || timelockLens === void 0 ? void 0 : timelockLens.address,
257
+ abi: lensAbi,
258
+ functionName: "getMaxPositionSize",
259
+ args: [
260
+ marketAddr,
261
+ strikeTick,
262
+ maxBorrowableRange
263
+ ],
264
+ query: { enabled: !!marketAddr && !!timelockLens && strikeTick !== void 0 },
265
+ gas: 100000000n
266
+ });
267
+ const data = strikeTick !== void 0 ? data1 : data0;
268
+ const { maxCallSize, maxPutSize } = useMemo(() => data && optionAssetDecimals ? {
269
+ maxCallSize: wrapAmount(data[0], optionAssetDecimals),
270
+ maxPutSize: wrapAmount(data[1], optionAssetDecimals)
271
+ } : {}, [data, optionAssetDecimals]);
272
+ const refetch = () => {
273
+ refetch0();
274
+ refetch1();
275
+ };
276
+ return {
277
+ maxCallSize,
278
+ maxPutSize,
279
+ refetch
280
+ };
281
+ };
282
+
283
+ //#endregion
284
+ //#region src/hooks/pool/usePoolData.ts
285
+ const usePoolData = (poolAddr) => {
286
+ const { timelockLens } = useLens();
287
+ const client = useClient();
288
+ const { data } = useReadContract({
289
+ address: timelockLens === null || timelockLens === void 0 ? void 0 : timelockLens.address,
290
+ abi: lensAbi,
291
+ functionName: "getPoolData",
292
+ args: poolAddr ? [poolAddr] : void 0,
293
+ query: { enabled: !!poolAddr && !!client }
294
+ });
295
+ return data || {};
296
+ };
297
+
298
+ //#endregion
299
+ //#region src/hooks/pool/useCurrentTick.ts
300
+ const useCurrentTick = (poolAddr) => {
301
+ const { tickSpacing } = usePoolData(poolAddr);
302
+ const { data } = useReadContract({
303
+ address: poolAddr,
304
+ abi: uniswapV3PoolAbi,
305
+ functionName: "slot0",
306
+ args: []
307
+ });
308
+ const exact = data === null || data === void 0 ? void 0 : data[1];
309
+ return {
310
+ exact,
311
+ rounded: exact && tickSpacing ? Math.floor(exact / tickSpacing) * tickSpacing : void 0
312
+ };
313
+ };
314
+
315
+ //#endregion
316
+ //#region src/hooks/market/useMintOption.ts
317
+ const useMintOption = (marketAddr) => {
318
+ const { timelockLens } = useLens();
319
+ const { payoutAsset, vault, pool, optionAssetIsToken0 } = useMarketData(marketAddr);
320
+ const { tickSpacing } = usePoolData(pool);
321
+ const { exact: currentTick } = useCurrentTick(pool);
322
+ const client = useClient();
323
+ const { address } = useAccount();
324
+ const { writeContractAsync, data: hash, isPending, error } = useWriteContract();
325
+ const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash });
326
+ const askForApproval = async (premiumAmount) => {
327
+ if (!client || !address) throw new Error("Wallet not connected");
328
+ if (!payoutAsset || !marketAddr) throw new Error("Tokens not available");
329
+ if (await getErc20(payoutAsset, client).read.allowance([address, marketAddr]) < premiumAmount) await waitForTransactionReceipt(client, { hash: await writeContractAsync({
330
+ address: payoutAsset,
331
+ abi: erc20Abi,
332
+ functionName: "approve",
333
+ args: [marketAddr, maxUint256]
334
+ }) });
335
+ };
336
+ const mintOption = async (optionType, amount, duration, strikeTick) => {
337
+ if (!client) throw new Error("Wallet not connected");
338
+ if (!timelockLens || !vault || !marketAddr || !currentTick || !tickSpacing) throw new Error("Lowest tick lower not available");
339
+ strikeTick = roundTickDown(strikeTick ?? currentTick, tickSpacing);
340
+ if (optionType === "CALL" && optionAssetIsToken0 || optionType === "PUT" && !optionAssetIsToken0) strikeTick += tickSpacing;
341
+ await askForApproval(await getTimelockMarket(marketAddr, client).read.calculatePremium([
342
+ optionType === "CALL" ? 0 : 1,
343
+ amount,
344
+ strikeTick,
345
+ BigInt(duration)
346
+ ]));
347
+ const hash$1 = await writeContractAsync({
348
+ address: marketAddr,
349
+ abi: optionsMarketAbi,
350
+ functionName: "mintOption",
351
+ args: [
352
+ optionType === "CALL" ? 0 : 1,
353
+ amount,
354
+ strikeTick,
355
+ BigInt(duration),
356
+ BigInt(1e69),
357
+ await timelockLens.read.getRefTick([vault, strikeTick])
358
+ ]
359
+ });
360
+ await waitForTransactionReceipt(client, { hash: hash$1 });
361
+ return hash$1;
362
+ };
363
+ return {
364
+ mintOption,
365
+ hash,
366
+ isPending,
367
+ isConfirming,
368
+ isSuccess,
369
+ error,
370
+ isLoading: isPending || isConfirming
371
+ };
372
+ };
373
+
374
+ //#endregion
375
+ //#region src/hooks/market/useOptionPnl.ts
376
+ const useOptionPnl = (optionData) => {
377
+ const { marketAddr, optionType, entryTick, positionSizeCurrent } = optionData;
378
+ const { pool, optionAssetIsToken0, payoutAssetDecimals } = useMarketData(marketAddr);
379
+ const { exact: currentTick } = useCurrentTick(pool);
380
+ const { displayPnl, unrealizedPayout } = useMemo(() => {
381
+ if (optionAssetIsToken0 === void 0 || currentTick === void 0 || !positionSizeCurrent || !payoutAssetDecimals) return {};
382
+ const delta = optionAssetIsToken0 ? token0ToToken1(positionSizeCurrent, currentTick) - token0ToToken1(positionSizeCurrent, entryTick) : token1ToToken0(positionSizeCurrent, currentTick) - token1ToToken0(positionSizeCurrent, entryTick);
383
+ const displayPnl$1 = wrapAmount(optionType === "CALL" ? delta : -delta, payoutAssetDecimals);
384
+ return {
385
+ unrealizedPayout: wrapAmount(displayPnl$1.scaled < 0 ? 0n : displayPnl$1.scaled, payoutAssetDecimals),
386
+ displayPnl: displayPnl$1
387
+ };
388
+ }, [
389
+ optionType,
390
+ optionAssetIsToken0,
391
+ entryTick,
392
+ currentTick,
393
+ positionSizeCurrent,
394
+ payoutAssetDecimals
395
+ ]);
396
+ return {
397
+ displayPnl,
398
+ unrealizedPayout
399
+ };
400
+ };
401
+
402
+ //#endregion
403
+ //#region src/hooks/market/useOptionPremium.ts
404
+ const useOptionPremium = (marketAddr, optionType, optionAmount, duration) => {
405
+ const { pool, payoutAssetDecimals } = useMarketData(marketAddr);
406
+ const { tickSpacing } = usePoolData(pool);
407
+ const currentTick = useCurrentTick(pool);
408
+ const strikeTick = useMemo(() => {
409
+ if (currentTick.rounded === void 0 || tickSpacing === void 0) return;
410
+ return optionType === "CALL" ? currentTick.rounded + tickSpacing : currentTick.rounded;
411
+ }, [
412
+ currentTick.rounded,
413
+ tickSpacing,
414
+ optionType
415
+ ]);
416
+ const { data: premiumData } = useReadContract({
417
+ address: marketAddr,
418
+ abi: optionsMarketAbi,
419
+ functionName: "calculatePremium",
420
+ args: strikeTick !== void 0 ? [
421
+ optionType === "CALL" ? 0 : 1,
422
+ optionAmount,
423
+ strikeTick,
424
+ BigInt(duration)
425
+ ] : void 0,
426
+ query: { enabled: currentTick.rounded !== void 0 && payoutAssetDecimals !== void 0 && tickSpacing !== void 0 && strikeTick !== void 0 }
427
+ });
428
+ return useMemo(() => {
429
+ if (premiumData === void 0 || payoutAssetDecimals === void 0) return;
430
+ return wrapAmount(premiumData, payoutAssetDecimals);
431
+ }, [premiumData, payoutAssetDecimals]);
432
+ };
433
+
434
+ //#endregion
435
+ //#region src/hooks/market/useUserOptions.ts
436
+ const useUserOptions = (user, active = false) => {
437
+ const { graphqlClient } = useTimelockConfig();
438
+ const { data: options,...rest } = useQuery({
439
+ queryKey: [
440
+ "userTrades",
441
+ user || "--",
442
+ active
443
+ ],
444
+ queryFn: () => active ? graphqlClient === null || graphqlClient === void 0 ? void 0 : graphqlClient.GetActiveUserOptions({ user: user.toLowerCase() }) : graphqlClient === null || graphqlClient === void 0 ? void 0 : graphqlClient.GetClosedUserOptions({ user: user.toLowerCase() }),
445
+ select: (data) => {
446
+ var _data$UserOption;
447
+ return data === null || data === void 0 || (_data$UserOption = data.UserOption) === null || _data$UserOption === void 0 ? void 0 : _data$UserOption.map((option) => ({
448
+ ...option,
449
+ id: BigInt(option.id),
450
+ marketAddr: option.marketAddr,
451
+ optionType: option.optionType,
452
+ createdAt: /* @__PURE__ */ new Date(Number(option.createdAt) * 1e3),
453
+ expiresAt: /* @__PURE__ */ new Date(Number(option.expiresAt) * 1e3),
454
+ premiumPaid: BigInt(option.premiumPaid),
455
+ realizedPayout: BigInt(option.realizedPayout),
456
+ liquiditiesAtOpen: option.liquiditiesAtOpen.map((liquidity) => BigInt(liquidity)),
457
+ liquiditiesCurrent: option.liquiditiesCurrent.map((liquidity) => BigInt(liquidity)),
458
+ positionSizeAtOpen: BigInt(option.positionSizeAtOpen),
459
+ positionSizeCurrent: BigInt(option.positionSizeCurrent),
460
+ strikePrice: BigInt(option.strikePrice),
461
+ entryPrice: BigInt(option.entryPrice)
462
+ }));
463
+ },
464
+ enabled: !!user && !!graphqlClient
465
+ });
466
+ return {
467
+ data: useMemo(() => (options === null || options === void 0 ? void 0 : options.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())) || [], [options]),
468
+ ...rest
469
+ };
470
+ };
471
+ const useActiveUserOptions = (user) => {
472
+ return useUserOptions(user, true);
473
+ };
474
+ const useClosedUserOptions = (user) => {
475
+ return useUserOptions(user, false);
476
+ };
477
+
478
+ //#endregion
479
+ //#region src/hooks/pool/usePriceAtTick.ts
480
+ const usePriceAtTick = (tick, poolAddr) => {
481
+ const { token0Decimals, token1Decimals } = usePoolData(poolAddr);
482
+ const priceBigInt = useMemo(() => tick ? getPriceAtTick(tick) : void 0, [tick]);
483
+ return useMemo(() => priceBigInt && token0Decimals && token1Decimals ? wrapPrice(priceBigInt, token0Decimals, token1Decimals) : void 0, [
484
+ priceBigInt,
485
+ token0Decimals,
486
+ token1Decimals
487
+ ]);
488
+ };
489
+
490
+ //#endregion
491
+ //#region src/hooks/pool/useCurrentPrice.ts
492
+ const useCurrentPrice = (poolAddr) => {
493
+ const currentTick = useCurrentTick(poolAddr);
494
+ return {
495
+ currentPrice: usePriceAtTick(currentTick.exact, poolAddr),
496
+ currentTick
497
+ };
498
+ };
499
+
500
+ //#endregion
501
+ //#region src/hooks/vault/useVaultData.ts
502
+ const useVaultData = (vaultAddr) => {
503
+ const { data } = useReadContract({
504
+ address: vaultAddr,
505
+ abi: singleOwnerVaultAbi,
506
+ functionName: "pool"
507
+ });
508
+ return { pool: data };
509
+ };
510
+
511
+ //#endregion
512
+ //#region src/hooks/vault/useBurnLiquidity.ts
513
+ const useBurnLiquidity = (vaultAddr) => {
514
+ const client = useClient();
515
+ const { timelockLens } = useLens();
516
+ const { pool } = useVaultData(vaultAddr);
517
+ const currentTick = useCurrentTick(pool);
518
+ const { writeContractAsync, data: hash, isPending, error } = useWriteContract();
519
+ const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash });
520
+ const burn = async (tickLower, tickUpper, liquidity) => {
521
+ if (!client) throw new Error("Wallet not connected");
522
+ if (!vaultAddr || !timelockLens) throw new Error("Vault/lens not available");
523
+ const hash$1 = await writeContractAsync({
524
+ address: vaultAddr,
525
+ abi: singleOwnerVaultAbi,
526
+ functionName: "burn",
527
+ args: [
528
+ tickLower,
529
+ tickUpper,
530
+ liquidity,
531
+ await timelockLens.read.getRefTick([vaultAddr, tickLower])
532
+ ]
533
+ });
534
+ await waitForTransactionReceipt(client, { hash: hash$1 });
535
+ return hash$1;
536
+ };
537
+ const burnMultiple = async (positions) => {
538
+ if (!client) throw new Error("Wallet not connected");
539
+ if (!currentTick.exact) throw new Error("Current tick not available");
540
+ if (positions.length === 0) throw new Error("No positions to burn");
541
+ if (!timelockLens || !vaultAddr) throw new Error("Vault/lens not available");
542
+ if (positions.length === 1) await burn(positions[0].tickLower, positions[0].tickUpper, positions[0].liquidity);
543
+ else {
544
+ const refTicks = await timelockLens.read.batchGetRefTick([vaultAddr, positions.map((position) => position.tickLower)]);
545
+ await waitForTransactionReceipt(client, { hash: await writeContractAsync({
546
+ address: vaultAddr,
547
+ abi: singleOwnerVaultAbi,
548
+ functionName: "multicall",
549
+ args: [positions.map((p, i) => encodeFunctionData({
550
+ abi: singleOwnerVaultAbi,
551
+ functionName: "burn",
552
+ args: [
553
+ p.tickLower,
554
+ p.tickUpper,
555
+ p.liquidity,
556
+ refTicks[i]
557
+ ]
558
+ }))]
559
+ }) });
560
+ }
561
+ };
562
+ return {
563
+ burnMultiple,
564
+ burn,
565
+ hash,
566
+ isPending,
567
+ isConfirming,
568
+ isSuccess,
569
+ error,
570
+ isLoading: isPending || isConfirming
571
+ };
572
+ };
573
+
574
+ //#endregion
575
+ //#region src/hooks/vault/useLiquidityBlocks.ts
576
+ const useLiquidityBlocks = (vaultAddr) => {
577
+ const { timelockLens } = useLens();
578
+ const { data: blocks = [],...rest } = useReadContract({
579
+ address: timelockLens === null || timelockLens === void 0 ? void 0 : timelockLens.address,
580
+ abi: lensAbi,
581
+ functionName: "getAllBlocks",
582
+ args: [vaultAddr],
583
+ query: { enabled: !!vaultAddr && !!timelockLens }
584
+ });
585
+ return {
586
+ data: blocks,
587
+ ...rest
588
+ };
589
+ };
590
+
591
+ //#endregion
592
+ //#region src/hooks/vault/useMintLiquidity.ts
593
+ const batchGetAmountsFromLiquidity = async (lens, tickLower, tickUpper, liquidity, currentTick) => {
594
+ const currentTicksArray = new Array(tickLower.length).fill(currentTick);
595
+ const amounts = await lens.read.batchGetAmountsForLiquidityTicks([
596
+ currentTicksArray,
597
+ tickLower,
598
+ tickUpper,
599
+ liquidity
600
+ ]);
601
+ let totalAmount0 = 0n;
602
+ let totalAmount1 = 0n;
603
+ const amounts0 = [];
604
+ const amounts1 = [];
605
+ for (const scaled of amounts[0]) {
606
+ totalAmount0 += scaled;
607
+ amounts0.push(scaled);
608
+ }
609
+ for (const scaled of amounts[1]) {
610
+ totalAmount1 += scaled;
611
+ amounts1.push(scaled);
612
+ }
613
+ return {
614
+ totalAmount0,
615
+ totalAmount1,
616
+ amounts0,
617
+ amounts1
618
+ };
619
+ };
620
+ const useMintLiquidity = (vaultAddr) => {
621
+ const client = useClient();
622
+ const { address } = useAccount();
623
+ const { pool } = useVaultData(vaultAddr);
624
+ const { timelockLens, uniswapLens } = useLens();
625
+ const currentTick = useCurrentTick(pool);
626
+ const { token0, token1 } = usePoolData(pool);
627
+ const { writeContractAsync, data: hash, isPending, error } = useWriteContract();
628
+ const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash });
629
+ const askForApproval = async (params) => {
630
+ if (!address || !client) throw new Error("Wallet not connected");
631
+ if (currentTick.exact === void 0 || !token0 || !token1 || !vaultAddr || !uniswapLens) throw new Error("Current tick not available");
632
+ const { totalAmount0, totalAmount1 } = await batchGetAmountsFromLiquidity(uniswapLens, params.map((p) => p.tickLower), params.map((p) => p.tickUpper), params.map((p) => p.liquidity), currentTick.exact);
633
+ const [allowance0, allowance1] = await Promise.all([getErc20(token0, client).read.allowance([address, vaultAddr]), getErc20(token1, client).read.allowance([address, vaultAddr])]);
634
+ const approvalPromises = [];
635
+ if (allowance0 <= totalAmount0) {
636
+ const approvalHash = await writeContractAsync({
637
+ address: token0,
638
+ abi: erc20Abi,
639
+ functionName: "approve",
640
+ args: [vaultAddr, maxUint256]
641
+ });
642
+ approvalPromises.push(waitForTransactionReceipt(client, { hash: approvalHash }));
643
+ }
644
+ if (allowance1 <= totalAmount1) {
645
+ const approvalHash1 = await writeContractAsync({
646
+ address: token1,
647
+ abi: erc20Abi,
648
+ functionName: "approve",
649
+ args: [vaultAddr, maxUint256]
650
+ });
651
+ approvalPromises.push(waitForTransactionReceipt(client, { hash: approvalHash1 }));
652
+ }
653
+ if (approvalPromises.length > 0) await Promise.all(approvalPromises);
654
+ };
655
+ const mint = async (tickLower, tickUpper, liquidity) => {
656
+ if (!client) throw new Error("Wallet not connected");
657
+ if (!vaultAddr || !timelockLens) throw new Error("Vault/lens not available");
658
+ await askForApproval([{
659
+ tickLower,
660
+ tickUpper,
661
+ liquidity
662
+ }]);
663
+ const hash$1 = await writeContractAsync({
664
+ address: vaultAddr,
665
+ abi: singleOwnerVaultAbi,
666
+ functionName: "mint",
667
+ args: [
668
+ tickLower,
669
+ tickUpper,
670
+ liquidity,
671
+ await timelockLens.read.getRefTick([vaultAddr, tickLower])
672
+ ]
673
+ });
674
+ await waitForTransactionReceipt(client, { hash: hash$1 });
675
+ return hash$1;
676
+ };
677
+ const mintMultiple = async (positions) => {
678
+ if (!client) throw new Error("Wallet not connected");
679
+ if (!currentTick.exact) throw new Error("Current tick not available");
680
+ if (positions.length === 0) throw new Error("No positions to mint");
681
+ if (!timelockLens || !vaultAddr) throw new Error("Vault/lens not available");
682
+ if (positions.length === 1) await mint(positions[0].tickLower, positions[0].tickUpper, positions[0].liquidity);
683
+ else {
684
+ await askForApproval(positions);
685
+ const refTicks = await timelockLens.read.batchGetRefTick([vaultAddr, positions.map((position) => position.tickLower)]);
686
+ await waitForTransactionReceipt(client, { hash: await writeContractAsync({
687
+ address: vaultAddr,
688
+ abi: singleOwnerVaultAbi,
689
+ functionName: "multicall",
690
+ args: [positions.map((p, i) => encodeFunctionData({
691
+ abi: singleOwnerVaultAbi,
692
+ functionName: "mint",
693
+ args: [
694
+ p.tickLower,
695
+ p.tickUpper,
696
+ p.liquidity,
697
+ refTicks[i]
698
+ ]
699
+ }))]
700
+ }) });
701
+ }
702
+ };
703
+ return {
704
+ mintMultiple,
705
+ mint,
706
+ hash,
707
+ isPending,
708
+ isConfirming,
709
+ isSuccess,
710
+ error,
711
+ isLoading: isPending || isConfirming
712
+ };
713
+ };
714
+
715
+ //#endregion
716
+ //#region src/hooks/vault/useVaultTVL.ts
717
+ const useVaultTVL = (vaultAddr) => {
718
+ const { timelockLens } = useLens();
719
+ const { pool } = useVaultData(vaultAddr);
720
+ const { token0Decimals, token1Decimals } = usePoolData(pool);
721
+ const { data, refetch } = useReadContract({
722
+ address: timelockLens === null || timelockLens === void 0 ? void 0 : timelockLens.address,
723
+ abi: lensAbi,
724
+ functionName: "getVaultTVL",
725
+ args: [vaultAddr],
726
+ query: { enabled: !!vaultAddr && !!timelockLens }
727
+ });
728
+ const totalAmount0 = data && token0Decimals ? wrapAmount(data[0], token0Decimals) : void 0;
729
+ const totalAmount1 = data && token1Decimals ? wrapAmount(data[1], token1Decimals) : void 0;
730
+ const borrowedAmount0 = data && token0Decimals ? wrapAmount(data[2], token0Decimals) : void 0;
731
+ const borrowedAmount1 = data && token1Decimals ? wrapAmount(data[3], token1Decimals) : void 0;
732
+ return {
733
+ tvl0: data && token0Decimals ? wrapAmount(data[4], token0Decimals) : void 0,
734
+ tvl1: data && token1Decimals ? wrapAmount(data[5], token1Decimals) : void 0,
735
+ totalAmount0,
736
+ totalAmount1,
737
+ borrowedAmount0,
738
+ borrowedAmount1,
739
+ refetch
740
+ };
741
+ };
742
+
743
+ //#endregion
744
+ export { TimelockMarketProvider, batchGetAmountsFromLiquidity, useActiveUserOptions, useBurnLiquidity, useClosedUserOptions, useCurrentMarket, useCurrentPrice, useCurrentTick, useExerciseOption, useLens, useLiquidityBlocks, useMarketData, useMaxPositionSize, useMintLiquidity, useMintOption, useOptionPnl, useOptionPremium, usePoolData, usePriceAtTick, useTimelockConfig, useVaultData, useVaultTVL };
745
+ //# sourceMappingURL=client.js.map