@sherwoodagent/cli 0.19.1 → 0.22.7

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 (65) hide show
  1. package/dist/{chat-WKOSUZXO.js → chat-JYAJMP4D.js} +42 -16
  2. package/dist/chat-JYAJMP4D.js.map +1 -0
  3. package/dist/{chunk-CTLEZZO7.js → chunk-4Y6Y4SVH.js} +43 -33
  4. package/dist/chunk-4Y6Y4SVH.js.map +1 -0
  5. package/dist/chunk-ASJTFFZH.js +485 -0
  6. package/dist/chunk-ASJTFFZH.js.map +1 -0
  7. package/dist/{chunk-SZ5QQJGA.js → chunk-B42ZCCZ7.js} +54 -2
  8. package/dist/chunk-B42ZCCZ7.js.map +1 -0
  9. package/dist/{chunk-QT7BUKWR.js → chunk-G7JQRLQE.js} +141 -37
  10. package/dist/chunk-G7JQRLQE.js.map +1 -0
  11. package/dist/{chunk-LHDWONBI.js → chunk-JR5K5WVR.js} +45 -6
  12. package/dist/chunk-JR5K5WVR.js.map +1 -0
  13. package/dist/{chunk-TAAEMX3L.js → chunk-LVPBJ7MI.js} +2 -2
  14. package/dist/{chunk-XR2ZUO4R.js → chunk-QGZUMIVO.js} +2 -2
  15. package/dist/{chunk-P4J6FKAP.js → chunk-VO6DCRWV.js} +36 -64
  16. package/dist/chunk-VO6DCRWV.js.map +1 -0
  17. package/dist/chunk-W2ZUPR3W.js +64 -0
  18. package/dist/chunk-W2ZUPR3W.js.map +1 -0
  19. package/dist/{chunk-YJAMY25R.js → chunk-Y7LS6DEF.js} +26 -39
  20. package/dist/chunk-Y7LS6DEF.js.map +1 -0
  21. package/dist/{client-3AAXAX4C.js → client-SCIY6SUP.js} +12 -4
  22. package/dist/{config-IDAHD7S3.js → config-BGS5MX4D.js} +10 -2
  23. package/dist/{cron-SKYKVZ6K.js → cron-EOULYO3R.js} +8 -3
  24. package/dist/cron-EOULYO3R.js.map +1 -0
  25. package/dist/{eas-JE3NQCXE.js → eas-X5UIEM6D.js} +14 -8
  26. package/dist/{governor-J3W67NXA.js → governor-ZKRSAHG4.js} +6 -6
  27. package/dist/index.js +1599 -392
  28. package/dist/index.js.map +1 -1
  29. package/dist/{network-DBUZ7GRF.js → network-UTSOP7EF.js} +3 -3
  30. package/dist/research-SJ6D3L2B.js +14 -0
  31. package/dist/{research-47YMVW3N.js → research-ZW6XVTGZ.js} +20 -15
  32. package/dist/research-ZW6XVTGZ.js.map +1 -0
  33. package/dist/session-XAW5UIXP.js +17 -0
  34. package/dist/session-XAW5UIXP.js.map +1 -0
  35. package/dist/{session-Q2WRYXYF.js → session-XZNKLK3I.js} +17 -66
  36. package/dist/session-XZNKLK3I.js.map +1 -0
  37. package/dist/{trade-D6VT5MLQ.js → trade-OJM5HNHL.js} +139 -68
  38. package/dist/trade-OJM5HNHL.js.map +1 -0
  39. package/dist/xmtp-XKHXATPQ.js +278 -0
  40. package/dist/xmtp-XKHXATPQ.js.map +1 -0
  41. package/package.json +7 -2
  42. package/dist/chat-WKOSUZXO.js.map +0 -1
  43. package/dist/chunk-CTLEZZO7.js.map +0 -1
  44. package/dist/chunk-I7CKBBOG.js +0 -129
  45. package/dist/chunk-I7CKBBOG.js.map +0 -1
  46. package/dist/chunk-LHDWONBI.js.map +0 -1
  47. package/dist/chunk-P4J6FKAP.js.map +0 -1
  48. package/dist/chunk-QT7BUKWR.js.map +0 -1
  49. package/dist/chunk-SZ5QQJGA.js.map +0 -1
  50. package/dist/chunk-YJAMY25R.js.map +0 -1
  51. package/dist/cron-SKYKVZ6K.js.map +0 -1
  52. package/dist/research-47YMVW3N.js.map +0 -1
  53. package/dist/research-DZINC4N4.js +0 -14
  54. package/dist/session-Q2WRYXYF.js.map +0 -1
  55. package/dist/trade-D6VT5MLQ.js.map +0 -1
  56. package/dist/xmtp-7DF7UG66.js +0 -367
  57. package/dist/xmtp-7DF7UG66.js.map +0 -1
  58. /package/dist/{chunk-TAAEMX3L.js.map → chunk-LVPBJ7MI.js.map} +0 -0
  59. /package/dist/{chunk-XR2ZUO4R.js.map → chunk-QGZUMIVO.js.map} +0 -0
  60. /package/dist/{client-3AAXAX4C.js.map → client-SCIY6SUP.js.map} +0 -0
  61. /package/dist/{config-IDAHD7S3.js.map → config-BGS5MX4D.js.map} +0 -0
  62. /package/dist/{eas-JE3NQCXE.js.map → eas-X5UIEM6D.js.map} +0 -0
  63. /package/dist/{governor-J3W67NXA.js.map → governor-ZKRSAHG4.js.map} +0 -0
  64. /package/dist/{network-DBUZ7GRF.js.map → network-UTSOP7EF.js.map} +0 -0
  65. /package/dist/{research-DZINC4N4.js.map → research-SJ6D3L2B.js.map} +0 -0
@@ -1,21 +1,21 @@
1
1
  import {
2
- ERC20_ABI,
3
2
  UNISWAP,
4
3
  UNISWAP_QUOTER_V2_ABI
5
- } from "./chunk-LHDWONBI.js";
4
+ } from "./chunk-JR5K5WVR.js";
6
5
  import {
7
6
  getAccount,
8
7
  getPublicClient,
9
- writeContractWithRetry
10
- } from "./chunk-I7CKBBOG.js";
8
+ sendTxWithRetry,
9
+ waitForReceipt
10
+ } from "./chunk-ASJTFFZH.js";
11
11
  import {
12
12
  getChain
13
- } from "./chunk-TAAEMX3L.js";
13
+ } from "./chunk-LVPBJ7MI.js";
14
14
  import {
15
15
  getUniswapApiKey,
16
16
  getVeniceApiKey,
17
17
  setVeniceApiKey
18
- } from "./chunk-SZ5QQJGA.js";
18
+ } from "./chunk-B42ZCCZ7.js";
19
19
 
20
20
  // src/providers/uniswap.ts
21
21
  import { isAddress } from "viem";
@@ -164,27 +164,14 @@ var UniswapProvider = class {
164
164
  }
165
165
  const data = await res.json();
166
166
  if (data.approval) {
167
- const hash = await writeContractWithRetry({
168
- address: data.approval.to,
169
- abi: ERC20_ABI,
170
- functionName: "approve",
171
- // Decode the approval data — the API returns the full calldata
172
- // but we need to send the raw transaction
173
- args: [],
174
- // unused — we send raw data
175
- account,
176
- chain: getChain()
177
- });
178
- const { getWalletClient } = await import("./client-3AAXAX4C.js");
179
- const wallet = getWalletClient();
180
- const approvalHash = await wallet.sendTransaction({
167
+ const approvalHash = await sendTxWithRetry({
181
168
  to: data.approval.to,
182
169
  data: data.approval.data,
183
170
  value: BigInt(data.approval.value || "0"),
184
171
  account,
185
172
  chain: getChain()
186
173
  });
187
- await client.waitForTransactionReceipt({ hash: approvalHash });
174
+ await waitForReceipt(approvalHash);
188
175
  }
189
176
  }
190
177
  /**
@@ -202,27 +189,27 @@ var UniswapProvider = class {
202
189
  amount: params.amountIn
203
190
  });
204
191
  }
205
- const slippageBps = params.fee;
206
192
  const { quoteResponse } = await this.fullQuote({
207
193
  tokenIn: params.tokenIn,
208
194
  tokenOut: params.tokenOut,
209
195
  amountIn: params.amountIn,
210
- slippageTolerance: 0.5
211
- // 0.5%
196
+ slippageTolerance: params.slippageTolerance ?? 0.5
212
197
  });
213
198
  const quoteRaw = quoteResponse;
214
199
  const { permitData, ...cleanQuote } = quoteRaw;
215
200
  const swapRequest = { ...cleanQuote };
216
- if (isUniswapXRouting(quoteResponse.routing)) {
217
- if (permitData && typeof permitData === "object") {
218
- const typedData = permitData;
219
- const signature = await account.signTypedData({
220
- domain: typedData.domain,
221
- types: typedData.types,
222
- primaryType: Object.keys(typedData.types).find((k) => k !== "EIP712Domain") ?? "PermitWitnessTransferFrom",
223
- message: typedData.values
224
- });
225
- swapRequest.signature = signature;
201
+ if (permitData && typeof permitData === "object") {
202
+ const typedData = permitData;
203
+ const primaryType = Object.keys(typedData.types).find((k) => k !== "EIP712Domain") ?? "PermitSingle";
204
+ const signature = await account.signTypedData({
205
+ domain: typedData.domain,
206
+ types: typedData.types,
207
+ primaryType,
208
+ message: typedData.values
209
+ });
210
+ swapRequest.signature = signature;
211
+ if (!isUniswapXRouting(quoteResponse.routing)) {
212
+ swapRequest.permitData = permitData;
226
213
  }
227
214
  }
228
215
  const swapRes = await fetchWithRetry(`${API_BASE}/swap`, {
@@ -241,16 +228,16 @@ var UniswapProvider = class {
241
228
  if (!isAddress(swapData.swap.to) || !isAddress(swapData.swap.from)) {
242
229
  throw new Error("Invalid address in swap response");
243
230
  }
244
- const { getWalletClient } = await import("./client-3AAXAX4C.js");
245
- const wallet = getWalletClient();
246
- const hash = await wallet.sendTransaction({
231
+ const gasLimit = swapData.swap.gasLimit ? BigInt(swapData.swap.gasLimit) * 150n / 100n : void 0;
232
+ const hash = await sendTxWithRetry({
247
233
  to: swapData.swap.to,
248
234
  data: swapData.swap.data,
249
235
  value: BigInt(swapData.swap.value || "0"),
236
+ gas: gasLimit,
250
237
  account,
251
238
  chain: getChain()
252
239
  });
253
- const receipt = await client.waitForTransactionReceipt({ hash });
240
+ const receipt = await waitForReceipt(hash);
254
241
  return {
255
242
  hash,
256
243
  success: receipt.status === "success",
@@ -462,4 +449,4 @@ export {
462
449
  encodeSwapPath,
463
450
  getMultiHopQuote
464
451
  };
465
- //# sourceMappingURL=chunk-YJAMY25R.js.map
452
+ //# sourceMappingURL=chunk-Y7LS6DEF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/uniswap.ts","../src/lib/venice.ts","../src/lib/quote.ts"],"sourcesContent":["/**\n * Uniswap Trading API provider — swaps on Base via the hosted API.\n *\n * Uses the 3-step flow:\n * 1. POST /check_approval → check/submit token approval\n * 2. POST /quote → get optimal route + executable quote\n * 3. POST /swap → get transaction calldata to sign\n *\n * API key required — set via `sherwood config set --uniswap-api-key <key>`\n * or UNISWAP_API_KEY env var.\n *\n * Docs: https://docs.uniswap.org/api/trading-api\n * Key: https://developers.uniswap.org/\n */\n\nimport type { Address, Hex } from \"viem\";\nimport { isAddress, isHex, formatUnits } from \"viem\";\nimport { base, baseSepolia } from \"viem/chains\";\nimport type { TradingProvider, ProviderInfo, SwapParams, SwapQuoteParams, TxResult, SwapQuote } from \"../types.js\";\nimport { getPublicClient, getAccount, writeContractWithRetry, sendTxWithRetry, waitForReceipt } from \"../lib/client.js\";\nimport { getChain } from \"../lib/network.js\";\nimport { getUniswapApiKey } from \"../lib/config.js\";\n\nconst API_BASE = \"https://trade-api.gateway.uniswap.org/v1\";\n\n// ── API Types ──\n\ninterface ApprovalResponse {\n approval: {\n to: Address;\n from: Address;\n data: Hex;\n value: string;\n chainId: number;\n } | null;\n}\n\n// CLASSIC route quote\ninterface ClassicQuote {\n routing: \"CLASSIC\" | \"WRAP\" | \"UNWRAP\";\n quote: {\n input: { token: string; amount: string };\n output: { token: string; amount: string };\n slippage: number;\n route: unknown[];\n gasFee: string;\n gasFeeUSD: string;\n gasUseEstimate: string;\n };\n permitData: Record<string, unknown> | null;\n}\n\n// UniswapX route quote (PRIORITY on Base)\ninterface UniswapXQuote {\n routing: \"DUTCH_V2\" | \"DUTCH_V3\" | \"PRIORITY\";\n quote: {\n orderInfo: {\n outputs: Array<{\n token: string;\n startAmount: string;\n endAmount: string;\n recipient: string;\n }>;\n input: { token: string; startAmount: string; endAmount: string };\n deadline: number;\n nonce: string;\n };\n encodedOrder: string;\n orderHash: string;\n };\n permitData: Record<string, unknown> | null;\n}\n\ntype QuoteResponse = ClassicQuote | UniswapXQuote;\n\ninterface SwapResponse {\n swap: {\n to: Address;\n from: Address;\n data: Hex;\n value: string;\n chainId: number;\n gasLimit?: string;\n };\n}\n\n// ── Helpers ──\n\nfunction getApiKey(): string {\n const key = getUniswapApiKey();\n if (!key) {\n throw new Error(\n \"Uniswap API key not configured. Run 'sherwood config set --uniswap-api-key <key>' \" +\n \"or set UNISWAP_API_KEY env var.\\n\" +\n \"Get your key at https://developers.uniswap.org/\",\n );\n }\n return key;\n}\n\nfunction apiHeaders(): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": getApiKey(),\n \"x-universal-router-version\": \"2.0\",\n };\n}\n\nfunction isUniswapXRouting(routing: string): boolean {\n return routing === \"DUTCH_V2\" || routing === \"DUTCH_V3\" || routing === \"PRIORITY\";\n}\n\nfunction getOutputAmount(q: QuoteResponse): string {\n if (isUniswapXRouting(q.routing)) {\n const ux = q as UniswapXQuote;\n const firstOutput = ux.quote.orderInfo.outputs[0];\n if (!firstOutput) throw new Error(\"UniswapX quote has no outputs\");\n return firstOutput.startAmount; // best-case fill\n }\n return (q as ClassicQuote).quote.output.amount;\n}\n\nasync function fetchWithRetry(\n url: string,\n init: RequestInit,\n maxRetries = 3,\n): Promise<Response> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(url, {\n ...init,\n signal: AbortSignal.timeout(30_000),\n });\n if (response.status !== 429 && response.status < 500) return response;\n if (attempt === maxRetries) return response;\n\n const delay = Math.min(200 * Math.pow(2, attempt) + Math.random() * 100, 10000);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n throw new Error(\"Unreachable\");\n}\n\n// ── Provider ──\n\nexport class UniswapProvider implements TradingProvider {\n info(): ProviderInfo {\n return {\n name: \"uniswap\",\n type: \"trading\",\n capabilities: [\n \"swap.exact-input\",\n \"swap.quote\",\n \"swap.check-approval\",\n ],\n supportedChains: [base, baseSepolia],\n };\n }\n\n /**\n * Get a quote from the Uniswap Trading API.\n * Returns the optimal route (CLASSIC, PRIORITY, or UniswapX).\n */\n async quote(params: SwapQuoteParams): Promise<SwapQuote> {\n const account = getAccount();\n const chainId = getChain().id;\n\n const body = {\n swapper: account.address,\n tokenIn: params.tokenIn,\n tokenOut: params.tokenOut,\n tokenInChainId: String(chainId),\n tokenOutChainId: String(chainId),\n amount: params.amountIn.toString(),\n type: \"EXACT_INPUT\",\n slippageTolerance: 0.5,\n routingPreference: \"BEST_PRICE\",\n };\n\n const res = await fetchWithRetry(`${API_BASE}/quote`, {\n method: \"POST\",\n headers: apiHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const err = await res.text();\n throw new Error(`Uniswap quote failed (${res.status}): ${err}`);\n }\n\n const data = (await res.json()) as QuoteResponse;\n const amountOut = BigInt(getOutputAmount(data));\n\n return {\n amountOut,\n priceImpact: 0,\n route: `${data.routing}: ${params.tokenIn.slice(0, 8)}→${params.tokenOut.slice(0, 8)}`,\n };\n }\n\n /**\n * Get a full quote response (preserving the raw API response for swap execution).\n */\n async fullQuote(params: {\n tokenIn: Address;\n tokenOut: Address;\n amountIn: bigint;\n slippageTolerance?: number;\n }): Promise<{ quoteResponse: QuoteResponse; amountOut: bigint; routing: string }> {\n const account = getAccount();\n const chainId = getChain().id;\n\n const body = {\n swapper: account.address,\n tokenIn: params.tokenIn,\n tokenOut: params.tokenOut,\n tokenInChainId: String(chainId),\n tokenOutChainId: String(chainId),\n amount: params.amountIn.toString(),\n type: \"EXACT_INPUT\",\n slippageTolerance: params.slippageTolerance ?? 0.5,\n routingPreference: \"BEST_PRICE\",\n };\n\n const res = await fetchWithRetry(`${API_BASE}/quote`, {\n method: \"POST\",\n headers: apiHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const err = await res.text();\n throw new Error(`Uniswap quote failed (${res.status}): ${err}`);\n }\n\n const quoteResponse = (await res.json()) as QuoteResponse;\n const amountOut = BigInt(getOutputAmount(quoteResponse));\n return { quoteResponse, amountOut, routing: quoteResponse.routing };\n }\n\n /**\n * Check and handle token approval for Uniswap.\n * Uses the Trading API's /check_approval endpoint.\n */\n async checkApproval(params: {\n token: Address;\n amount: bigint;\n }): Promise<void> {\n const account = getAccount();\n const chainId = getChain().id;\n const client = getPublicClient();\n\n const res = await fetchWithRetry(`${API_BASE}/check_approval`, {\n method: \"POST\",\n headers: apiHeaders(),\n body: JSON.stringify({\n walletAddress: account.address,\n token: params.token,\n amount: params.amount.toString(),\n chainId,\n }),\n });\n\n if (!res.ok) {\n const err = await res.text();\n throw new Error(`Approval check failed (${res.status}): ${err}`);\n }\n\n const data = (await res.json()) as ApprovalResponse;\n\n if (data.approval) {\n // API returns a ready-to-send transaction — use sendTxWithRetry for nonce safety\n const approvalHash = await sendTxWithRetry({\n to: data.approval.to,\n data: data.approval.data,\n value: BigInt(data.approval.value || \"0\"),\n account,\n chain: getChain(),\n });\n await waitForReceipt(approvalHash);\n }\n }\n\n /**\n * Execute a swap via the Uniswap Trading API.\n *\n * Full flow: check_approval → quote → swap → sign & broadcast.\n */\n async swap(params: SwapParams): Promise<TxResult> {\n const account = getAccount();\n const client = getPublicClient();\n\n // 1. Check approval (skip for native ETH)\n const ETH_ADDRESS = \"0x0000000000000000000000000000000000000000\" as Address;\n if (params.tokenIn !== ETH_ADDRESS) {\n await this.checkApproval({\n token: params.tokenIn,\n amount: params.amountIn,\n });\n }\n\n // 2. Get quote\n const { quoteResponse } = await this.fullQuote({\n tokenIn: params.tokenIn,\n tokenOut: params.tokenOut,\n amountIn: params.amountIn,\n slippageTolerance: params.slippageTolerance ?? 0.5,\n });\n\n // 3. Prepare swap request — routing-aware permitData handling\n const quoteRaw = quoteResponse as unknown as Record<string, unknown>;\n const { permitData, ...cleanQuote } = quoteRaw;\n const swapRequest: Record<string, unknown> = { ...cleanQuote };\n\n // Sign permitData if present (required for both CLASSIC and UniswapX).\n // For CLASSIC routes using Permit2 (PermitSingle): include BOTH permitData + signature.\n // For UniswapX routes: include signature only (order-level signing, no permitData in body).\n if (permitData && typeof permitData === \"object\") {\n const typedData = permitData as {\n domain: Record<string, unknown>;\n types: Record<string, unknown>;\n values: Record<string, unknown>;\n };\n const primaryType =\n Object.keys(typedData.types).find((k) => k !== \"EIP712Domain\") ?? \"PermitSingle\";\n const signature = await account.signTypedData({\n domain: typedData.domain as Record<string, unknown>,\n types: typedData.types as Record<string, Array<{ name: string; type: string }>>,\n primaryType,\n message: typedData.values,\n });\n swapRequest.signature = signature;\n // CLASSIC routes: /swap requires both permitData and signature\n // UniswapX routes: /swap requires signature only (order is in quote body)\n if (!isUniswapXRouting(quoteResponse.routing)) {\n swapRequest.permitData = permitData;\n }\n }\n\n // 4. Get swap transaction\n const swapRes = await fetchWithRetry(`${API_BASE}/swap`, {\n method: \"POST\",\n headers: apiHeaders(),\n body: JSON.stringify(swapRequest),\n });\n\n if (!swapRes.ok) {\n const err = await swapRes.text();\n throw new Error(`Uniswap swap failed (${swapRes.status}): ${err}`);\n }\n\n const swapData = (await swapRes.json()) as SwapResponse;\n\n // 5. Validate before broadcasting\n if (!swapData.swap?.data || swapData.swap.data === (\"\" as Hex) || swapData.swap.data === \"0x\") {\n throw new Error(\"Empty swap data — quote may have expired. Try again.\");\n }\n if (!isAddress(swapData.swap.to) || !isAddress(swapData.swap.from)) {\n throw new Error(\"Invalid address in swap response\");\n }\n\n // 6. Sign and broadcast with retry-aware sender\n // Apply a 1.5x buffer to the API's gasLimit: the Uniswap API under-estimates for WETH\n // and other non-USDC inputs where PermitSingle+transfer adds overhead.\n const gasLimit = swapData.swap.gasLimit\n ? (BigInt(swapData.swap.gasLimit) * 150n) / 100n\n : undefined;\n const hash = await sendTxWithRetry({\n to: swapData.swap.to,\n data: swapData.swap.data,\n value: BigInt(swapData.swap.value || \"0\"),\n gas: gasLimit,\n account,\n chain: getChain(),\n });\n\n const receipt = await waitForReceipt(hash);\n return {\n hash,\n success: receipt.status === \"success\",\n gasUsed: receipt.gasUsed,\n };\n }\n}\n","/**\n * Venice AI API integration — web3 key generation, validation, and inference.\n *\n * Key provisioning flow:\n * 1. GET /api_keys/generate_web3_key → validation token\n * 2. Sign token with agent wallet (EIP-191)\n * 3. POST /api_keys/generate_web3_key → API key\n *\n * Inference:\n * POST /chat/completions with Bearer auth → chat completion response\n *\n * The API key is stored in ~/.sherwood/config.json.\n * Venice requires the signing wallet to hold staked VVV (sVVV).\n */\n\nimport { getAccount } from \"./client.js\";\nimport { setVeniceApiKey, getVeniceApiKey } from \"./config.js\";\n\nconst VENICE_API_BASE = \"https://api.venice.ai/api/v1\";\n\n/**\n * Provision a Venice API key via web3 wallet signature.\n * The wallet must hold sVVV for this to succeed.\n */\nexport async function provisionApiKey(): Promise<string> {\n const account = getAccount();\n\n // 1. Get validation token (requires admin API key)\n const adminKey = process.env.VENICE_ADMIN_KEY;\n if (!adminKey) {\n throw new Error(\n \"VENICE_ADMIN_KEY env var required for autonomous provisioning.\\n\" +\n \" Get an admin key from https://venice.ai/settings/api-keys\\n\" +\n \" Or set a key manually: sherwood config set --venice-api-key <key>\",\n );\n }\n const tokenRes = await fetch(`${VENICE_API_BASE}/api_keys/generate_web3_key`, {\n headers: { Authorization: `Bearer ${adminKey}` },\n signal: AbortSignal.timeout(15_000),\n });\n if (!tokenRes.ok) {\n throw new Error(`Failed to get validation token: ${tokenRes.status} ${tokenRes.statusText}`);\n }\n const tokenData = await tokenRes.json();\n const token = tokenData?.data?.token;\n if (!token) {\n throw new Error(\"Venice API returned no validation token\");\n }\n\n // 2. Sign token with wallet (EIP-191)\n const signature = await account.signMessage({ message: token });\n\n // 3. Generate API key\n const keyRes = await fetch(`${VENICE_API_BASE}/api_keys/generate_web3_key`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n signal: AbortSignal.timeout(15_000),\n body: JSON.stringify({\n address: account.address,\n signature,\n token,\n apiKeyType: \"INFERENCE\",\n description: \"Sherwood syndicate agent\",\n }),\n });\n\n if (!keyRes.ok) {\n const body = await keyRes.text();\n throw new Error(`Failed to generate API key: ${keyRes.status} ${body}`);\n }\n\n const keyData = await keyRes.json();\n const apiKey = keyData?.data?.apiKey;\n if (!apiKey) {\n throw new Error(\"Venice API returned no API key\");\n }\n\n // Store in config\n setVeniceApiKey(apiKey);\n\n return apiKey;\n}\n\n/**\n * Check if the stored Venice API key is still valid.\n */\nexport async function checkApiKeyValid(): Promise<boolean> {\n const apiKey = getVeniceApiKey();\n if (!apiKey) return false;\n\n try {\n const res = await fetch(`${VENICE_API_BASE}/models`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n signal: AbortSignal.timeout(15_000),\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n\n// ── Inference ──\n\nexport interface ChatCompletionMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\nexport interface ChatCompletionOptions {\n model: string;\n messages: ChatCompletionMessage[];\n temperature?: number;\n maxTokens?: number;\n enableWebSearch?: boolean;\n disableThinking?: boolean;\n}\n\nexport interface ChatCompletionResult {\n content: string;\n model: string;\n usage: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n}\n\n/**\n * Call Venice chat completions API for private inference.\n * Requires a provisioned API key (run `sherwood venice provision` first).\n */\nexport async function chatCompletion(opts: ChatCompletionOptions): Promise<ChatCompletionResult> {\n const apiKey = getVeniceApiKey();\n if (!apiKey) {\n throw new Error(\"No Venice API key configured. Run 'sherwood venice provision' first.\");\n }\n\n const body: Record<string, unknown> = {\n model: opts.model,\n messages: opts.messages,\n };\n if (opts.temperature !== undefined) body.temperature = opts.temperature;\n if (opts.maxTokens !== undefined) body.max_tokens = opts.maxTokens;\n\n const veniceParams: Record<string, unknown> = {};\n if (opts.enableWebSearch) veniceParams.enable_web_search = \"on\";\n if (opts.disableThinking) veniceParams.disable_thinking = true;\n if (Object.keys(veniceParams).length > 0) body.venice_parameters = veniceParams;\n\n const res = await fetch(`${VENICE_API_BASE}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n signal: AbortSignal.timeout(120_000), // inference can be slow\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const errBody = await res.text();\n throw new Error(`Venice inference failed: ${res.status} ${errBody}`);\n }\n\n const data = await res.json();\n const choice = data.choices?.[0];\n if (!choice) {\n throw new Error(\"Venice returned no choices\");\n }\n\n return {\n content: choice.message?.content ?? \"\",\n model: data.model ?? opts.model,\n usage: {\n promptTokens: data.usage?.prompt_tokens ?? 0,\n completionTokens: data.usage?.completion_tokens ?? 0,\n totalTokens: data.usage?.total_tokens ?? 0,\n },\n };\n}\n\n/**\n * List available Venice models.\n * Requires a provisioned API key.\n */\nexport async function listModels(): Promise<string[]> {\n const apiKey = getVeniceApiKey();\n if (!apiKey) {\n throw new Error(\"No Venice API key configured. Run 'sherwood venice provision' first.\");\n }\n\n const res = await fetch(`${VENICE_API_BASE}/models`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n signal: AbortSignal.timeout(15_000),\n });\n\n if (!res.ok) {\n throw new Error(`Failed to list Venice models: ${res.status} ${res.statusText}`);\n }\n\n const data = await res.json();\n return (data.data ?? []).map((m: { id: string }) => m.id);\n}\n","/**\n * Uniswap V3 Quoter V2 integration for swap quotes.\n *\n * quoteExactInputSingle is NOT a view function — it reverts internally\n * after computing the quote. Must use eth_call to get the return data.\n */\n\nimport type { Address, Hex } from \"viem\";\nimport { encodeFunctionData, decodeFunctionResult, concat, pad, numberToHex } from \"viem\";\nimport { getPublicClient } from \"./client.js\";\nimport { UNISWAP_QUOTER_V2_ABI } from \"./abis.js\";\nimport { UNISWAP } from \"./addresses.js\";\n\nexport interface QuoteResult {\n amountOut: bigint;\n sqrtPriceX96After: bigint;\n gasEstimate: bigint;\n}\n\n/**\n * Get a swap quote from Uniswap Quoter V2.\n */\nexport async function getQuote(params: {\n tokenIn: Address;\n tokenOut: Address;\n amountIn: bigint;\n fee: number;\n}): Promise<QuoteResult> {\n const client = getPublicClient();\n\n const calldata = encodeFunctionData({\n abi: UNISWAP_QUOTER_V2_ABI,\n functionName: \"quoteExactInputSingle\",\n args: [\n {\n tokenIn: params.tokenIn,\n tokenOut: params.tokenOut,\n amountIn: params.amountIn,\n fee: params.fee,\n sqrtPriceLimitX96: 0n,\n },\n ],\n });\n\n const { data } = await client.call({\n to: UNISWAP().QUOTER_V2,\n data: calldata,\n });\n\n if (!data) {\n throw new Error(\"Quoter returned no data — pool may not exist for this pair/fee\");\n }\n\n const [amountOut, sqrtPriceX96After, , gasEstimate] = decodeFunctionResult({\n abi: UNISWAP_QUOTER_V2_ABI,\n functionName: \"quoteExactInputSingle\",\n data,\n }) as [bigint, bigint, number, bigint];\n\n return { amountOut, sqrtPriceX96After, gasEstimate };\n}\n\n/**\n * Apply slippage tolerance to a quote amount.\n * Returns the minimum acceptable output amount.\n */\nexport function applySlippage(amountOut: bigint, slippageBps: number): bigint {\n return (amountOut * BigInt(10000 - slippageBps)) / 10000n;\n}\n\n/**\n * Encode a Uniswap V3 multi-hop swap path.\n * Format: abi.encodePacked(address, uint24, address, uint24, address, ...)\n */\nexport function encodeSwapPath(tokens: Address[], fees: number[]): Hex {\n if (tokens.length < 2 || fees.length !== tokens.length - 1) {\n throw new Error(\"Invalid path: need at least 2 tokens and (tokens-1) fees\");\n }\n\n const parts: Hex[] = [];\n for (let i = 0; i < tokens.length; i++) {\n // Address: 20 bytes (no padding)\n parts.push(tokens[i].toLowerCase() as Hex);\n if (i < fees.length) {\n // Fee: 3 bytes (uint24), left-padded to 3 bytes\n parts.push(pad(numberToHex(fees[i]), { size: 3 }) as Hex);\n }\n }\n return concat(parts);\n}\n\n/**\n * Get a multi-hop swap quote from Uniswap Quoter V2.\n */\nexport async function getMultiHopQuote(params: {\n path: Hex;\n amountIn: bigint;\n}): Promise<QuoteResult> {\n const client = getPublicClient();\n\n const calldata = encodeFunctionData({\n abi: UNISWAP_QUOTER_V2_ABI,\n functionName: \"quoteExactInput\",\n args: [params.path, params.amountIn],\n });\n\n const { data } = await client.call({\n to: UNISWAP().QUOTER_V2,\n data: calldata,\n });\n\n if (!data) {\n throw new Error(\"Quoter returned no data — pool may not exist for this path\");\n }\n\n const [amountOut, , , gasEstimate] = decodeFunctionResult({\n abi: UNISWAP_QUOTER_V2_ABI,\n functionName: \"quoteExactInput\",\n data,\n }) as [bigint, bigint[], number[], bigint];\n\n return { amountOut, sqrtPriceX96After: 0n, gasEstimate };\n}\n\n/** Token decimals for display purposes. */\nexport const TOKEN_DECIMALS: Record<string, number> = {\n USDC: 6,\n WETH: 18,\n cbETH: 18,\n wstETH: 18,\n cbBTC: 8,\n DAI: 18,\n AERO: 18,\n};\n"],"mappings":"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","names":[]}
@@ -1,21 +1,29 @@
1
1
  import {
2
+ detectStuckNonce,
2
3
  estimateFeesWithBuffer,
4
+ formatContractError,
3
5
  getAccount,
4
6
  getPublicClient,
5
7
  getWalletClient,
6
8
  resetClients,
7
9
  sendTxWithRetry,
10
+ unstickWallet,
11
+ waitForReceipt,
8
12
  writeContractWithRetry
9
- } from "./chunk-I7CKBBOG.js";
10
- import "./chunk-TAAEMX3L.js";
11
- import "./chunk-SZ5QQJGA.js";
13
+ } from "./chunk-ASJTFFZH.js";
14
+ import "./chunk-LVPBJ7MI.js";
15
+ import "./chunk-B42ZCCZ7.js";
12
16
  export {
17
+ detectStuckNonce,
13
18
  estimateFeesWithBuffer,
19
+ formatContractError,
14
20
  getAccount,
15
21
  getPublicClient,
16
22
  getWalletClient,
17
23
  resetClients,
18
24
  sendTxWithRetry,
25
+ unstickWallet,
26
+ waitForReceipt,
19
27
  writeContractWithRetry
20
28
  };
21
- //# sourceMappingURL=client-3AAXAX4C.js.map
29
+ //# sourceMappingURL=client-SCIY6SUP.js.map
@@ -1,11 +1,14 @@
1
1
  import {
2
+ addSyndicate,
2
3
  cacheGroupId,
3
4
  getAgentId,
4
5
  getCachedGroupId,
5
6
  getChainContracts,
6
7
  getConfigRpcUrl,
7
8
  getNotifyTo,
9
+ getPrimarySyndicate,
8
10
  getPrivateKey,
11
+ getSyndicates,
9
12
  getUniswapApiKey,
10
13
  getVeniceApiKey,
11
14
  loadConfig,
@@ -14,18 +17,22 @@ import {
14
17
  setChainContract,
15
18
  setConfigRpcUrl,
16
19
  setNotifyTo,
20
+ setPrimarySyndicate,
17
21
  setPrivateKey,
18
22
  setUniswapApiKey,
19
23
  setVeniceApiKey
20
- } from "./chunk-SZ5QQJGA.js";
24
+ } from "./chunk-B42ZCCZ7.js";
21
25
  export {
26
+ addSyndicate,
22
27
  cacheGroupId,
23
28
  getAgentId,
24
29
  getCachedGroupId,
25
30
  getChainContracts,
26
31
  getConfigRpcUrl,
27
32
  getNotifyTo,
33
+ getPrimarySyndicate,
28
34
  getPrivateKey,
35
+ getSyndicates,
29
36
  getUniswapApiKey,
30
37
  getVeniceApiKey,
31
38
  loadConfig,
@@ -34,8 +41,9 @@ export {
34
41
  setChainContract,
35
42
  setConfigRpcUrl,
36
43
  setNotifyTo,
44
+ setPrimarySyndicate,
37
45
  setPrivateKey,
38
46
  setUniswapApiKey,
39
47
  setVeniceApiKey
40
48
  };
41
- //# sourceMappingURL=config-IDAHD7S3.js.map
49
+ //# sourceMappingURL=config-BGS5MX4D.js.map
@@ -28,13 +28,15 @@ function silentPrompt(subdomain, testnet) {
28
28
  `You are a sherwood syndicate member. Your syndicate: ${subdomain}.sherwoodagent.eth`,
29
29
  "",
30
30
  `Step 1: Run \`${envPrefix}sherwood session check ${subdomain}${chainFlag}\``,
31
- "Step 2: Parse the JSON output.",
32
- " - If the output shows 0 messages and 0 events, you may still be pending approval.",
31
+ "Step 2: Parse the JSON output. The output is a single JSON object with fields: syndicate, messages[], events[], meta{}.",
32
+ " - If the command fails or returns an error, reply HEARTBEAT_ERROR with the error message.",
33
+ " - If meta.newMessages === 0 and meta.newEvents === 0, you may still be pending approval.",
33
34
  " Check: `" + envPrefix + "sherwood vault info" + chainFlag + "`",
34
35
  " If your wallet is not listed as a registered agent, you are still pending. Reply HEARTBEAT_OK.",
35
36
  " If you ARE registered but this is your first time seeing it, alert your human that you've been approved and are now active.",
36
37
  " - If there are new messages from OTHER agents, respond thoughtfully via:",
37
38
  ` \`${envPrefix}sherwood chat ${subdomain} send "<response>"${chainFlag}\``,
39
+ " - If there are on-chain events (proposals, votes, settlements), acknowledge them in chat if relevant.",
38
40
  "Step 3: If you responded to anything, summarize what you did (for your own session log).",
39
41
  " If nothing happened, reply HEARTBEAT_OK",
40
42
  "",
@@ -53,6 +55,9 @@ function summaryPrompt(subdomain, testnet) {
53
55
  "",
54
56
  `Run: \`${envPrefix}sherwood session check ${subdomain}${chainFlag}\``,
55
57
  "",
58
+ "The output is a single JSON object with fields: syndicate, messages[], events[], meta{}.",
59
+ "If the command fails, report the error to your human.",
60
+ "",
56
61
  "If there was activity (messages, events, proposals) since last check:",
57
62
  " Send a brief summary \u2014 who said what, any decisions made, any actions you took.",
58
63
  " Keep it to 3-5 lines max.",
@@ -204,4 +209,4 @@ export {
204
209
  registerSyndicateCrons,
205
210
  unregisterSyndicateCrons
206
211
  };
207
- //# sourceMappingURL=cron-SKYKVZ6K.js.map
212
+ //# sourceMappingURL=cron-EOULYO3R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/cron.ts"],"sourcesContent":["/**\n * OpenClaw cron integration — auto-register participation crons for syndicate agents.\n *\n * When an agent creates or joins a syndicate, the CLI registers two cron jobs:\n * 1. Silent check (every 15m) — processes messages/events, responds autonomously\n * 2. Human summary (every 1h) — brief activity report delivered to the human's channel\n *\n * Non-OpenClaw agents skip silently — the caller prints guidance instead.\n */\n\nimport { execFileSync } from \"node:child_process\";\n\n// ── OpenClaw detection (cached per process) ──\n\nlet _isOpenClaw: boolean | null = null;\n\nexport function isOpenClaw(): boolean {\n if (_isOpenClaw !== null) return _isOpenClaw;\n try {\n execFileSync(\"openclaw\", [\"cron\", \"list\"], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n _isOpenClaw = true;\n } catch {\n _isOpenClaw = false;\n }\n return _isOpenClaw;\n}\n\n// ── Types ──\n\nexport interface CronResult {\n registered: boolean;\n isOpenClaw: boolean;\n cronNames: string[];\n}\n\nexport interface CronStatus {\n isOpenClaw: boolean;\n crons: { name: string; every: string; lastRun?: string }[];\n}\n\n// ── Cron naming ──\n\nfunction cronName(subdomain: string, testnet: boolean): string {\n return `sherwood-${subdomain}${testnet ? \"-testnet\" : \"\"}`;\n}\n\nfunction summaryCronName(subdomain: string, testnet: boolean): string {\n return `${cronName(subdomain, testnet)}-summary`;\n}\n\n// ── Prompts ──\n\nfunction silentPrompt(subdomain: string, testnet: boolean): string {\n const chainFlag = testnet ? \" --chain base-sepolia\" : \"\";\n const envPrefix = testnet ? \"ENABLE_TESTNET=true \" : \"\";\n return [\n `You are a sherwood syndicate member. Your syndicate: ${subdomain}.sherwoodagent.eth`,\n \"\",\n `Step 1: Run \\`${envPrefix}sherwood session check ${subdomain}${chainFlag}\\``,\n \"Step 2: Parse the JSON output. The output is a single JSON object with fields: syndicate, messages[], events[], meta{}.\",\n \" - If the command fails or returns an error, reply HEARTBEAT_ERROR with the error message.\",\n \" - If meta.newMessages === 0 and meta.newEvents === 0, you may still be pending approval.\",\n \" Check: `\" + envPrefix + \"sherwood vault info\" + chainFlag + \"`\",\n \" If your wallet is not listed as a registered agent, you are still pending. Reply HEARTBEAT_OK.\",\n \" If you ARE registered but this is your first time seeing it, alert your human that you've been approved and are now active.\",\n \" - If there are new messages from OTHER agents, respond thoughtfully via:\",\n ` \\`${envPrefix}sherwood chat ${subdomain} send \"<response>\"${chainFlag}\\``,\n \" - If there are on-chain events (proposals, votes, settlements), acknowledge them in chat if relevant.\",\n \"Step 3: If you responded to anything, summarize what you did (for your own session log).\",\n \" If nothing happened, reply HEARTBEAT_OK\",\n \"\",\n \"Rules:\",\n \"- Be a real syndicate member — discuss strategies, share opinions, ask questions\",\n \"- Keep responses concise and on-topic\",\n \"- Do NOT alert your human unless something requires their approval (or you were just approved)\",\n `- You can use \\`sherwood research\\` commands if you need data to back up your response`,\n ].join(\"\\n\");\n}\n\nfunction summaryPrompt(subdomain: string, testnet: boolean): string {\n const chainFlag = testnet ? \" --chain base-sepolia\" : \"\";\n const envPrefix = testnet ? \"ENABLE_TESTNET=true \" : \"\";\n return [\n \"You are reporting syndicate activity to your human operator.\",\n \"\",\n `Run: \\`${envPrefix}sherwood session check ${subdomain}${chainFlag}\\``,\n \"\",\n \"The output is a single JSON object with fields: syndicate, messages[], events[], meta{}.\",\n \"If the command fails, report the error to your human.\",\n \"\",\n \"If there was activity (messages, events, proposals) since last check:\",\n \" Send a brief summary — who said what, any decisions made, any actions you took.\",\n \" Keep it to 3-5 lines max.\",\n \"\",\n \"If there was no activity:\",\n \" Reply HEARTBEAT_OK\",\n \"\",\n \"Only escalate (flag as urgent) if:\",\n \"- A proposal needs human sign-off\",\n \"- An agent left the syndicate\",\n \"- Risk alert or health factor warning\",\n \"- Human was directly asked for input\",\n ].join(\"\\n\");\n}\n\n// ── Helpers ──\n\n/** Parse `openclaw cron list --json` and return job names. */\nfunction listCronNames(): string[] {\n try {\n const raw = execFileSync(\"openclaw\", [\"cron\", \"list\", \"--json\"], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n const parsed = JSON.parse(raw);\n const jobs: { name: string }[] = parsed.jobs || parsed || [];\n return jobs.map((j) => j.name);\n } catch {\n return [];\n }\n}\n\n/** Parse `openclaw cron list --json` with full details for status display. */\nfunction listCronDetails(): { name: string; every: string; lastRun?: string }[] {\n try {\n const raw = execFileSync(\"openclaw\", [\"cron\", \"list\", \"--json\"], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n const parsed = JSON.parse(raw);\n const jobs: { name: string; every?: string; interval?: string; lastRun?: string }[] =\n parsed.jobs || parsed || [];\n return jobs.map((j) => ({\n name: j.name,\n every: j.every || j.interval || \"unknown\",\n lastRun: j.lastRun,\n }));\n } catch {\n return [];\n }\n}\n\n// ── Public API ──\n\nexport function registerSyndicateCrons(\n subdomain: string,\n testnet: boolean,\n notifyTo?: string,\n): CronResult {\n if (!isOpenClaw()) {\n return { registered: false, isOpenClaw: false, cronNames: [] };\n }\n\n const checkName = cronName(subdomain, testnet);\n const summaryName = summaryCronName(subdomain, testnet);\n const existing = listCronNames();\n const created: string[] = [];\n\n // Cron 1: Silent participation check (every 15m)\n if (!existing.includes(checkName)) {\n try {\n execFileSync(\"openclaw\", [\n \"cron\", \"create\",\n \"--name\", checkName,\n \"--every\", \"15m\",\n \"--session\", \"isolated\",\n \"--timeout-seconds\", \"120\",\n \"--no-deliver\",\n \"--message\", silentPrompt(subdomain, testnet),\n ], {\n encoding: \"utf8\",\n timeout: 30_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n created.push(checkName);\n } catch (err) {\n console.warn(`Could not create silent cron: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n // Cron 2: Human summary (every 1h)\n if (!existing.includes(summaryName)) {\n try {\n const args = [\n \"cron\", \"create\",\n \"--name\", summaryName,\n \"--every\", \"1h\",\n \"--session\", \"isolated\",\n \"--timeout-seconds\", \"90\",\n \"--announce\",\n ];\n\n // Use explicit destination if configured, otherwise auto-route via --channel last\n if (notifyTo) {\n args.push(\"--to\", notifyTo);\n } else {\n args.push(\"--channel\", \"last\");\n }\n\n args.push(\"--message\", summaryPrompt(subdomain, testnet));\n\n execFileSync(\"openclaw\", args, {\n encoding: \"utf8\",\n timeout: 30_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n created.push(summaryName);\n } catch (err) {\n console.warn(`Could not create summary cron: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n return {\n registered: created.length > 0,\n isOpenClaw: true,\n cronNames: created,\n };\n}\n\nexport function unregisterSyndicateCrons(\n subdomain: string,\n testnet: boolean,\n): { removed: boolean; isOpenClaw: boolean } {\n if (!isOpenClaw()) {\n return { removed: false, isOpenClaw: false };\n }\n\n const names = [cronName(subdomain, testnet), summaryCronName(subdomain, testnet)];\n let removed = false;\n\n for (const name of names) {\n try {\n execFileSync(\"openclaw\", [\"cron\", \"remove\", \"--name\", name], {\n encoding: \"utf8\",\n timeout: 10_000,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n removed = true;\n } catch {\n // Cron may not exist — that's fine\n }\n }\n\n return { removed, isOpenClaw: true };\n}\n\nexport function getSyndicateCronStatus(\n subdomain: string,\n testnet: boolean,\n): CronStatus {\n if (!isOpenClaw()) {\n return { isOpenClaw: false, crons: [] };\n }\n\n const prefix = cronName(subdomain, testnet);\n const all = listCronDetails();\n const matching = all.filter((c) => c.name.startsWith(prefix));\n\n return { isOpenClaw: true, crons: matching };\n}\n"],"mappings":"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","names":[]}
@@ -5,15 +5,18 @@ import {
5
5
  createTradeAttestation,
6
6
  createVeniceInferenceAttestation,
7
7
  createVeniceProvisionAttestation,
8
+ formatMessageWithRef,
8
9
  getEasScanUrl,
10
+ parseReferrer,
9
11
  queryApprovals,
10
12
  queryJoinRequests,
11
- revokeAttestation
12
- } from "./chunk-CTLEZZO7.js";
13
- import "./chunk-LHDWONBI.js";
14
- import "./chunk-I7CKBBOG.js";
15
- import "./chunk-TAAEMX3L.js";
16
- import "./chunk-SZ5QQJGA.js";
13
+ revokeAttestation,
14
+ stripReferrerPrefix
15
+ } from "./chunk-4Y6Y4SVH.js";
16
+ import "./chunk-JR5K5WVR.js";
17
+ import "./chunk-ASJTFFZH.js";
18
+ import "./chunk-LVPBJ7MI.js";
19
+ import "./chunk-B42ZCCZ7.js";
17
20
  export {
18
21
  createApproval,
19
22
  createJoinRequest,
@@ -21,9 +24,12 @@ export {
21
24
  createTradeAttestation,
22
25
  createVeniceInferenceAttestation,
23
26
  createVeniceProvisionAttestation,
27
+ formatMessageWithRef,
24
28
  getEasScanUrl,
29
+ parseReferrer,
25
30
  queryApprovals,
26
31
  queryJoinRequests,
27
- revokeAttestation
32
+ revokeAttestation,
33
+ stripReferrerPrefix
28
34
  };
29
- //# sourceMappingURL=eas-JE3NQCXE.js.map
35
+ //# sourceMappingURL=eas-X5UIEM6D.js.map
@@ -34,11 +34,11 @@ import {
34
34
  settleProposal,
35
35
  vetoProposal,
36
36
  vote
37
- } from "./chunk-P4J6FKAP.js";
38
- import "./chunk-LHDWONBI.js";
39
- import "./chunk-I7CKBBOG.js";
40
- import "./chunk-TAAEMX3L.js";
41
- import "./chunk-SZ5QQJGA.js";
37
+ } from "./chunk-VO6DCRWV.js";
38
+ import "./chunk-JR5K5WVR.js";
39
+ import "./chunk-ASJTFFZH.js";
40
+ import "./chunk-LVPBJ7MI.js";
41
+ import "./chunk-B42ZCCZ7.js";
42
42
  export {
43
43
  PROPOSAL_STATE,
44
44
  PROPOSAL_STATES,
@@ -76,4 +76,4 @@ export {
76
76
  vetoProposal,
77
77
  vote
78
78
  };
79
- //# sourceMappingURL=governor-J3W67NXA.js.map
79
+ //# sourceMappingURL=governor-ZKRSAHG4.js.map