timelock-sdk 0.0.255 → 0.0.257

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.cjs CHANGED
@@ -12,13 +12,15 @@ let viem_actions = require("viem/actions");
12
12
 
13
13
  //#region src/lib/perpsOperator.ts
14
14
  var PerpsOperator = class {
15
- #baseUrl;
15
+ #readUrl;
16
+ #writeUrl;
16
17
  auth;
17
- constructor(baseUrl) {
18
- this.#baseUrl = baseUrl;
18
+ constructor(readUrl, writeUrl) {
19
+ this.#readUrl = readUrl;
20
+ this.#writeUrl = writeUrl;
19
21
  }
20
- #request = async (path, body) => {
21
- const url = new URL(path, this.#baseUrl);
22
+ #request = async (baseUrl, path, body) => {
23
+ const url = new URL(path, baseUrl);
22
24
  const res = await fetch(url, {
23
25
  method: body ? "POST" : "GET",
24
26
  headers: {
@@ -37,19 +39,43 @@ var PerpsOperator = class {
37
39
  const error = JSON.parse(resText);
38
40
  throw new Error(`${res.status} ${res.statusText}: ${error.error}`);
39
41
  } catch (error) {
42
+ console.error(error);
40
43
  throw new Error(`${res.status} ${res.statusText}: ${resText}`);
41
44
  }
42
45
  };
43
- getOperatorAddr = async () => {
44
- const { address } = await this.#request("api/operator/address");
45
- return address;
46
+ #readRequest = async (path, body) => {
47
+ try {
48
+ return await this.#request(this.#readUrl, path, body);
49
+ } catch {
50
+ return await this.#request(this.#writeUrl, path, body);
51
+ }
52
+ };
53
+ #writeRequest = async (path, body) => {
54
+ return this.#request(this.#writeUrl, path, body);
55
+ };
56
+ getOperatorAddresses = async () => {
57
+ const { addresses } = await this.#readRequest("api/operator/addresses");
58
+ return addresses;
59
+ };
60
+ getUserPerps = async (userAddr, marketAddr, type, offset = 0, limit = 1e3) => {
61
+ const params = new URLSearchParams({
62
+ offset: offset.toString(),
63
+ limit: limit.toString()
64
+ });
65
+ if (type) params.append("type", type);
66
+ if (marketAddr) params.append("marketAddr", marketAddr);
67
+ const url = `api/positions/${userAddr}?${params.toString()}`;
68
+ return (await this.#readRequest(url)).map((p) => ({
69
+ ...p,
70
+ optionId: BigInt(p.optionId)
71
+ }));
46
72
  };
47
73
  genAuthMessage = async (userAddr) => {
48
- const { message } = await this.#request("api/auth/gen", { userAddr });
74
+ const { message } = await this.#writeRequest("api/auth/gen", { userAddr });
49
75
  return message;
50
76
  };
51
77
  validateAuthMessage = async (message, signature) => {
52
- const { address, createdAt, validUntil } = await this.#request("api/auth/validate", {
78
+ const { address, createdAt, validUntil } = await this.#writeRequest("api/auth/validate", {
53
79
  message,
54
80
  signature
55
81
  });
@@ -65,22 +91,9 @@ var PerpsOperator = class {
65
91
  signature
66
92
  };
67
93
  };
68
- getUserPerps = async (userAddr, marketAddr, type, offset = 0, limit = 1e3) => {
69
- const params = new URLSearchParams({
70
- offset: offset.toString(),
71
- limit: limit.toString()
72
- });
73
- if (type) params.append("type", type);
74
- if (marketAddr) params.append("marketAddr", marketAddr);
75
- const url = `api/positions/${userAddr}?${params.toString()}`;
76
- return (await this.#request(url)).map((p) => ({
77
- ...p,
78
- optionId: BigInt(p.optionId)
79
- }));
80
- };
81
94
  mintPerp = async (body) => {
82
95
  if (!this.auth) throw new Error("Authentication required. Call setAuth() with authMessage and signature before exercising perps.");
83
- const { txHash, optionId } = await this.#request("api/positions/mint", {
96
+ const { txHash, optionId } = await this.#writeRequest("api/positions/mint", {
84
97
  ...body,
85
98
  amount: body.amount.toString(),
86
99
  auth: this.auth
@@ -92,7 +105,7 @@ var PerpsOperator = class {
92
105
  };
93
106
  exercisePerp = async (body) => {
94
107
  if (!this.auth) throw new Error("Authentication required. Call setAuth() with authMessage and signature before exercising perps.");
95
- const { txHash, optionId } = await this.#request("api/positions/exercise", {
108
+ const { txHash, optionId } = await this.#writeRequest("api/positions/exercise", {
96
109
  ...body,
97
110
  optionId: body.optionId.toString(),
98
111
  liquidities: body.liquidities.map((l) => l.toString()),
@@ -1113,11 +1126,11 @@ const clearSignature = (userAddr) => {
1113
1126
  };
1114
1127
  const usePerpsOperator = () => {
1115
1128
  const { address: userAddr } = (0, wagmi.useConnection)();
1116
- const { perpsOperatorUrl, perpsOperator: operator } = useTimelockConfig();
1129
+ const { perpsOperator: operator } = useTimelockConfig();
1117
1130
  const { mutateAsync: signMessageAsync } = (0, wagmi.useSignMessage)();
1118
- const { data: address } = (0, _tanstack_react_query.useQuery)({
1119
- queryKey: ["perpsOperatorAddr", perpsOperatorUrl || "--"],
1120
- queryFn: () => operator === null || operator === void 0 ? void 0 : operator.getOperatorAddr(),
1131
+ const { data: addresses } = (0, _tanstack_react_query.useQuery)({
1132
+ queryKey: ["perpsOperatorAddresses", operator || "--"],
1133
+ queryFn: () => operator === null || operator === void 0 ? void 0 : operator.getOperatorAddresses(),
1121
1134
  staleTime: 1e4,
1122
1135
  refetchInterval: 1e4,
1123
1136
  enabled: !!operator
@@ -1125,9 +1138,9 @@ const usePerpsOperator = () => {
1125
1138
  const validateAndSetAuth = async (message, signature) => {
1126
1139
  if (!operator || !userAddr) return;
1127
1140
  try {
1128
- const { address: address$1, validUntil } = await operator.validateAuthMessage(message, signature);
1141
+ const { address, validUntil } = await operator.validateAuthMessage(message, signature);
1129
1142
  if (validUntil < Date.now()) throw new Error("Signature expired");
1130
- if (address$1.toLowerCase() !== userAddr.toLowerCase()) throw new Error("Valid signature but different user address");
1143
+ if (address.toLowerCase() !== userAddr.toLowerCase()) throw new Error("Valid signature but different user address");
1131
1144
  operator.setAuth(message, signature);
1132
1145
  } catch (error) {
1133
1146
  clearSignature(userAddr);
@@ -1142,7 +1155,7 @@ const usePerpsOperator = () => {
1142
1155
  }, [userAddr, operator]);
1143
1156
  return {
1144
1157
  operator,
1145
- address,
1158
+ addresses,
1146
1159
  signMessage: (0, _tanstack_react_query.useMutation)({ mutationFn: async () => {
1147
1160
  if (!operator) throw new Error("Operator not initialized");
1148
1161
  if (!userAddr) throw new Error("Wallet not connected");
@@ -1186,20 +1199,15 @@ const useSetOperatorPerms = (marketAddr) => {
1186
1199
  const client = (0, wagmi.useClient)();
1187
1200
  const { address } = (0, wagmi.useConnection)();
1188
1201
  const { mutateAsync: writeContractAsync } = (0, wagmi.useWriteContract)();
1189
- const setOperatorPerms = async ({ operator, canExtend, canExercise, canTransfer, canMint, spendingApproval }) => {
1202
+ const setOperatorPerms = async ({ operators, perms }) => {
1190
1203
  if (!client || !address) throw new Error("Wallet not connected");
1191
1204
  if (!marketAddr) throw new Error("Market address not available");
1205
+ if (operators.length !== perms.length) throw new Error("Operators and perms arrays must have the same length");
1192
1206
  const hash = await writeContractAsync({
1193
1207
  address: marketAddr,
1194
1208
  abi: require_stateView.optionsMarketAbi,
1195
1209
  functionName: "setOperatorsPerms",
1196
- args: [[operator], [{
1197
- canExtend,
1198
- canExercise,
1199
- canTransfer,
1200
- canMint,
1201
- spendingApproval
1202
- }]]
1210
+ args: [operators, perms]
1203
1211
  });
1204
1212
  await (0, viem_actions.waitForTransactionReceipt)(client, { hash });
1205
1213
  queryClient.invalidateQueries({ queryKey: ["userOperators"] });
@@ -1215,26 +1223,47 @@ const useMintPerp = (marketAddr) => {
1215
1223
  const queryClient = (0, _tanstack_react_query.useQueryClient)();
1216
1224
  const client = (0, wagmi.useClient)();
1217
1225
  const { address } = (0, wagmi.useConnection)();
1218
- const { operator, address: operatorAddr, signMessage: { mutateAsync: signMessage } } = usePerpsOperator();
1226
+ const { operator, addresses: operatorAddresses, signMessage: { mutateAsync: signMessage } } = usePerpsOperator();
1219
1227
  const { poolManager, poolKey, optionAssetIsToken0, payoutAsset } = useMarketData(marketAddr);
1220
1228
  const { tickSpacing } = usePoolData(poolManager, poolKey);
1221
1229
  const { askForApproval } = useApproval();
1222
1230
  const { mutateAsync: setOperatorPerms } = useSetOperatorPerms(marketAddr);
1223
1231
  const { refetch: refetchOperators } = useUserOperators(address, marketAddr);
1224
1232
  const { refetch: refetchCurrentTick } = useCurrentTick(poolManager, poolKey);
1233
+ const updateOperatorPermsIfNeeded = async (requiredSpendingApproval) => {
1234
+ if (!operatorAddresses) return;
1235
+ const { data: operators = [] } = await refetchOperators();
1236
+ const operatorsToUpdate = [];
1237
+ const permsToUpdate = [];
1238
+ for (const operatorAddr of operatorAddresses) {
1239
+ const userPerms = operators.find((o) => o.operatorAddr.toLowerCase() === operatorAddr.toLowerCase());
1240
+ if (!(userPerms && userPerms.canMint && userPerms.canExtend && userPerms.canExercise && userPerms.spendingApproval > requiredSpendingApproval)) {
1241
+ operatorsToUpdate.push(operatorAddr);
1242
+ permsToUpdate.push({
1243
+ canMint: true,
1244
+ canExtend: true,
1245
+ canExercise: true,
1246
+ canTransfer: (userPerms === null || userPerms === void 0 ? void 0 : userPerms.canTransfer) ?? false,
1247
+ spendingApproval: viem.maxUint256
1248
+ });
1249
+ }
1250
+ }
1251
+ if (operatorsToUpdate.length > 0) await setOperatorPerms({
1252
+ operators: operatorsToUpdate,
1253
+ perms: permsToUpdate
1254
+ });
1255
+ };
1225
1256
  const mintPerp = async (data) => {
1226
1257
  const { optionType, amount, duration, strikeTick } = data;
1227
1258
  if (!client || !address) throw new Error("Wallet not connected");
1228
1259
  if (!marketAddr) throw new Error("Market address not found");
1229
1260
  if (!tickSpacing) throw new Error("Pool data not found");
1230
- if (!operator || !operatorAddr) throw new Error("Operator address not found");
1261
+ if (!operator || !operatorAddresses) throw new Error("Operator address not found");
1231
1262
  if (optionAssetIsToken0 === void 0 || !payoutAsset) throw new Error("Market data not found");
1232
1263
  if (!operator.auth) await signMessage();
1233
1264
  const market = require_graphql.getTimelockMarket(marketAddr, client);
1234
1265
  const { data: { currentTick } = {} } = await refetchCurrentTick();
1235
1266
  if (currentTick === void 0) throw new Error("Could not fetch current tick");
1236
- const { data: operators = [] } = await refetchOperators();
1237
- const userPerms = operatorAddr ? operators.find((o) => o.operatorAddr.toLowerCase() === operatorAddr.toLowerCase()) : void 0;
1238
1267
  const validStrikeTick = require_graphql.getNearestValidStrikeTick(optionType, optionAssetIsToken0, tickSpacing, currentTick, strikeTick);
1239
1268
  const [premium, protocolFee] = await market.read.getMintFees([
1240
1269
  optionType === "CALL" ? 0 : 1,
@@ -1244,14 +1273,7 @@ const useMintPerp = (marketAddr) => {
1244
1273
  "0x"
1245
1274
  ]);
1246
1275
  const maxPremium = (premium + protocolFee) * 11n / 10n;
1247
- if (!(userPerms && userPerms.canMint && userPerms.canExtend && userPerms.canExercise && userPerms.spendingApproval > maxPremium)) await setOperatorPerms({
1248
- operator: operatorAddr,
1249
- canMint: true,
1250
- canExtend: true,
1251
- canExercise: true,
1252
- canTransfer: (userPerms === null || userPerms === void 0 ? void 0 : userPerms.canTransfer) || false,
1253
- spendingApproval: viem.maxUint256
1254
- });
1276
+ await updateOperatorPermsIfNeeded(maxPremium);
1255
1277
  await askForApproval(payoutAsset, marketAddr, maxPremium);
1256
1278
  await operator.mintPerp({
1257
1279
  marketAddr,