@agentlayer.tech/wallet 0.1.66 → 0.1.68

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.
@@ -2,7 +2,7 @@
2
2
  "id": "agent-wallet",
3
3
  "name": "Agent Wallet",
4
4
  "description": "Plugin-friendly wallet backend for OpenClaw agents with safe wallet tools and runtime instructions across Solana, local BTC, and local EVM.",
5
- "version": "0.1.66",
5
+ "version": "0.1.68",
6
6
  "skills": ["skills/wallet-operator"],
7
7
  "configSchema": {
8
8
  "type": "object",
@@ -119,7 +119,7 @@
119
119
  },
120
120
  "kaminoBaseUrl": {
121
121
  "type": "string",
122
- "description": "Optional Kamino REST API base URL for lending reads and transaction building."
122
+ "description": "Optional Kamino REST API base URL for lending and Earn reads plus transaction building."
123
123
  },
124
124
  "kaminoProgramId": {
125
125
  "type": "string",
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "openclaw-agent-wallet"
7
- version = "0.1.66"
7
+ version = "0.1.68"
8
8
  description = "Plugin-friendly wallet backend for OpenClaw agents"
9
9
  requires-python = ">=3.10"
10
10
  dependencies = [
@@ -16,7 +16,7 @@ dependencies = [
16
16
  "python-dotenv>=1.0.0",
17
17
  "solana>=0.36.0",
18
18
  "solders>=0.27.0",
19
- "x402[httpx,svm,evm]>=2.10.0",
19
+ "x402[httpx,svm,evm,extensions]>=2.10.0",
20
20
  ]
21
21
 
22
22
  [project.optional-dependencies]
@@ -29,6 +29,10 @@ LEGACY_ALLOWLIST_TOOLS = [
29
29
  "set_wallet_backend",
30
30
  "get_wallet_portfolio",
31
31
  "get_solana_token_prices",
32
+ "get_kamino_portfolio",
33
+ "get_kamino_vaults",
34
+ "get_kamino_earn_positions",
35
+ "get_kamino_liquidity_positions",
32
36
  "get_kamino_lend_markets",
33
37
  "get_kamino_lend_market_reserves",
34
38
  "get_kamino_lend_user_obligations",
@@ -37,6 +41,8 @@ LEGACY_ALLOWLIST_TOOLS = [
37
41
  "kamino_lend_withdraw",
38
42
  "kamino_lend_borrow",
39
43
  "kamino_lend_repay",
44
+ "kamino_earn_deposit",
45
+ "kamino_earn_withdraw",
40
46
  "sign_wallet_message",
41
47
  "transfer_sol",
42
48
  "transfer_btc",
@@ -30,7 +30,7 @@ Use this skill before calling OpenClaw wallet tools. It is the routing guide for
30
30
  - EVM transfers: `transfer_evm_native`, `transfer_evm_token`.
31
31
  - BTC transfer: `transfer_btc`.
32
32
  - Solana staking: `stake_sol_native`, `deactivate_solana_stake`, `withdraw_solana_stake`.
33
- - Kamino: `kamino_lend_deposit`, `kamino_lend_withdraw`, `kamino_lend_borrow`, `kamino_lend_repay`.
33
+ - Kamino: `get_kamino_portfolio`, `get_kamino_vaults`, `get_kamino_earn_positions`, `get_kamino_liquidity_positions`, `kamino_lend_deposit`, `kamino_lend_withdraw`, `kamino_lend_borrow`, `kamino_lend_repay`, `kamino_earn_deposit`, `kamino_earn_withdraw`.
34
34
  - Bags: `launch_bags_token`.
35
35
 
36
36
  ## Common Token IDs
@@ -118,8 +118,10 @@ Use this skill before calling OpenClaw wallet tools. It is the routing guide for
118
118
  - `stake_sol_native`: `vote_account`, `amount` in SOL, `mode`, `purpose`.
119
119
  - `deactivate_solana_stake`: `stake_account`, `mode`, `purpose`.
120
120
  - `withdraw_solana_stake`: `stake_account`, `amount` in SOL, optional `recipient`, `mode`, `purpose`.
121
- - Before Kamino writes, use `get_kamino_lend_markets`, `get_kamino_lend_market_reserves`, `get_kamino_lend_user_obligations`, and `get_kamino_lend_user_rewards`.
122
- - Kamino write params: `market`, `reserve`, `amount_ui` decimal string, `mode`, `purpose`.
121
+ - Before Kamino lend writes, use `get_kamino_lend_markets`, `get_kamino_lend_market_reserves`, `get_kamino_lend_user_obligations`, and `get_kamino_lend_user_rewards`.
122
+ - For broader Kamino read coverage, prefer `get_kamino_portfolio` first, then drill into `get_kamino_vaults`, `get_kamino_earn_positions`, or `get_kamino_liquidity_positions` as needed.
123
+ - Kamino lend write params: `market`, `reserve`, `amount_ui` decimal string, `mode`, `purpose`.
124
+ - Kamino Earn write params: `kvault`, `amount_ui` decimal string, `mode`, `purpose`.
123
125
  - `launch_bags_token`: `name`, `symbol`, `description`, `base_mint`, `claimers`, `basis_points`, `initial_buy_sol`, `mode`, `purpose`; optional socials/image/config type.
124
126
  - `close_empty_token_accounts`: `limit`, `mode` (`preview` or `execute`), `purpose`.
125
127
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-wallet",
3
3
  "displayName": "Agent Wallet",
4
- "version": "0.1.66",
4
+ "version": "0.1.68",
5
5
  "description": "Claude Code bridge for the existing AgentLayer wallet runtime. Connects to Solana, Bitcoin, and EVM wallets without creating a new one.",
6
6
  "author": {
7
7
  "name": "AgentLayer"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-wallet",
3
- "version": "0.1.66",
3
+ "version": "0.1.68",
4
4
  "description": "Codex plugin bridge for the AgentLayer wallet runtime.",
5
5
  "author": {
6
6
  "name": "AgentLayer"
@@ -1,5 +1,5 @@
1
1
  name: agent-wallet
2
- version: 0.1.66
2
+ version: 0.1.68
3
3
  description: Thin Hermes Agent bridge to the existing AgentLayer/OpenClaw wallet backend
4
4
  provides_tools:
5
5
  - agent_wallet_tools
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentlayer.tech/wallet",
3
- "version": "0.1.66",
3
+ "version": "0.1.68",
4
4
  "description": "NPM installer for the OpenClaw Agent Wallet local runtime.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdk-btc-wallet",
3
- "version": "0.1.66",
3
+ "version": "0.1.68",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Separate BTC-only wallet service built on Tether WDK.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdk-evm-wallet",
3
- "version": "0.1.66",
3
+ "version": "0.1.68",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Separate EVM wallet service built on Tether WDK.",
@@ -649,6 +649,12 @@ async function handleRequest(request, response) {
649
649
  return sendJson(response, 200, { ok: true, data });
650
650
  }
651
651
 
652
+ if (method === "POST" && url.pathname === "/v1/evm/message/sign") {
653
+ const body = await withResolvedNetwork(await withResolvedSeed(await readJsonBody(request)));
654
+ const data = await service.signPersonalMessage(body);
655
+ return sendJson(response, 200, { ok: true, data });
656
+ }
657
+
652
658
  return notFound(response);
653
659
  } catch (error) {
654
660
  const shaped = toErrorResponse(error, new URL(request.url || "/", "http://localhost").pathname, 400);
@@ -94,8 +94,38 @@ const LIFI_CHAIN_ALIASES = {
94
94
  sol: "1151111081099710",
95
95
  solana: "1151111081099710",
96
96
  };
97
- const MORPHO_DEFAULT_LIST_LIMIT = 100;
97
+ // Default is deliberately small: list responses land in an LLM agent's
98
+ // context window (a 100-item vault list is ~80 KB of JSON). Agents can raise
99
+ // the limit explicitly when they really need more.
100
+ const MORPHO_DEFAULT_LIST_LIMIT = 20;
98
101
  const MORPHO_MAX_LIST_LIMIT = 500;
102
+ // Discovery lists/details only — never user positions. APY/TVL drift over
103
+ // two minutes is below the indexer's own aggregation noise.
104
+ const MORPHO_DISCOVERY_CACHE_TTL_MS = 120_000;
105
+ const MORPHO_DISCOVERY_CACHE_MAX_ENTRIES = 64;
106
+ const morphoDiscoveryCache = new Map();
107
+
108
+ function morphoDiscoveryCacheGet(key) {
109
+ const entry = morphoDiscoveryCache.get(key);
110
+ if (!entry) {
111
+ return null;
112
+ }
113
+ if (entry.expiresAt <= Date.now()) {
114
+ morphoDiscoveryCache.delete(key);
115
+ return null;
116
+ }
117
+ return JSON.parse(entry.payload);
118
+ }
119
+
120
+ function morphoDiscoveryCacheSet(key, payload) {
121
+ if (morphoDiscoveryCache.size >= MORPHO_DISCOVERY_CACHE_MAX_ENTRIES) {
122
+ morphoDiscoveryCache.delete(morphoDiscoveryCache.keys().next().value);
123
+ }
124
+ morphoDiscoveryCache.set(key, {
125
+ expiresAt: Date.now() + MORPHO_DISCOVERY_CACHE_TTL_MS,
126
+ payload: JSON.stringify(payload),
127
+ });
128
+ }
99
129
  const MORPHO_VAULT_LIST_QUERY = `
100
130
  query MorphoVaultV2List($first: Int!, $where: VaultV2sFilters, $orderBy: VaultV2OrderBy, $orderDirection: OrderDirection) {
101
131
  vaultV2s(first: $first, where: $where, orderBy: $orderBy, orderDirection: $orderDirection) {
@@ -112,6 +142,7 @@ const MORPHO_VAULT_LIST_QUERY = `
112
142
  idleAssets
113
143
  idleAssetsUsd
114
144
  sharePrice
145
+ netApy
115
146
  avgNetApy
116
147
  avgNetApyExcludingRewards
117
148
  performanceFee
@@ -666,6 +697,17 @@ function normalizeMorphoSearch(value) {
666
697
  return value.trim() || null;
667
698
  }
668
699
 
700
+ function normalizeOptionalNonNegativeNumber(value, fieldName) {
701
+ if (value === undefined || value === null || value === "") {
702
+ return null;
703
+ }
704
+ const num = Number(value);
705
+ if (!Number.isFinite(num) || num < 0) {
706
+ throw new Error(`${fieldName} must be a non-negative number.`);
707
+ }
708
+ return num;
709
+ }
710
+
669
711
  function normalizeOptionalAddressFilter(value, fieldName) {
670
712
  if (value === undefined || value === null || value === "") {
671
713
  return null;
@@ -1925,21 +1967,29 @@ export class WdkEvmWalletService {
1925
1967
  limit,
1926
1968
  listedOnly = true,
1927
1969
  assetAddress = null,
1970
+ minTotalAssetsUsd = null,
1971
+ minNetApy = null,
1928
1972
  orderBy,
1929
1973
  orderDirection,
1930
1974
  }) {
1931
1975
  const runtimeConfig = this.#resolveRuntimeConfig(network);
1932
1976
  assertMorphoSupportedNetwork(runtimeConfig.network);
1933
1977
  if (vaultAddress !== null && vaultAddress !== undefined && String(vaultAddress).trim()) {
1978
+ const address = normalizeAddress(vaultAddress, "vaultAddress");
1979
+ const cacheKey = JSON.stringify(["vault", runtimeConfig.chainId, address]);
1980
+ const cached = morphoDiscoveryCacheGet(cacheKey);
1981
+ if (cached) {
1982
+ return cached;
1983
+ }
1934
1984
  const data = await this.#morphoGraphqlRequest({
1935
1985
  query: MORPHO_VAULT_BY_ADDRESS_QUERY,
1936
1986
  variables: {
1937
- address: normalizeAddress(vaultAddress, "vaultAddress"),
1987
+ address,
1938
1988
  chainId: runtimeConfig.chainId,
1939
1989
  },
1940
1990
  operationName: "MorphoVaultV2ByAddress",
1941
1991
  });
1942
- return {
1992
+ const result = {
1943
1993
  network: runtimeConfig.network,
1944
1994
  chainId: runtimeConfig.chainId,
1945
1995
  protocol: "morpho",
@@ -1947,10 +1997,17 @@ export class WdkEvmWalletService {
1947
1997
  found: Boolean(data.vaultV2ByAddress),
1948
1998
  source: "morpho-api",
1949
1999
  };
2000
+ morphoDiscoveryCacheSet(cacheKey, result);
2001
+ return result;
1950
2002
  }
1951
2003
  const first = normalizeMorphoListLimit(limit);
1952
2004
  const onlyListed = normalizeMorphoListedOnly(listedOnly);
1953
2005
  const assetAddressFilter = normalizeOptionalAddressFilter(assetAddress, "assetAddress");
2006
+ const minTotalAssetsUsdFilter = normalizeOptionalNonNegativeNumber(
2007
+ minTotalAssetsUsd,
2008
+ "minTotalAssetsUsd"
2009
+ );
2010
+ const minNetApyFilter = normalizeOptionalNonNegativeNumber(minNetApy, "minNetApy");
1954
2011
  const resolvedOrderBy = normalizeMorphoOrderBy(
1955
2012
  orderBy,
1956
2013
  MORPHO_VAULT_ORDER_LOOKUP,
@@ -1964,18 +2021,30 @@ export class WdkEvmWalletService {
1964
2021
  if (assetAddressFilter) {
1965
2022
  where.assetAddress_in = assetAddressFilter;
1966
2023
  }
2024
+ if (minTotalAssetsUsdFilter !== null) {
2025
+ where.totalAssetsUsd_gte = minTotalAssetsUsdFilter;
2026
+ }
2027
+ if (minNetApyFilter !== null) {
2028
+ where.netApy_gte = minNetApyFilter;
2029
+ }
2030
+ const variables = {
2031
+ first,
2032
+ where,
2033
+ orderBy: resolvedOrderBy,
2034
+ orderDirection: resolvedOrderDirection,
2035
+ };
2036
+ const cacheKey = JSON.stringify(["vaults", variables]);
2037
+ const cached = morphoDiscoveryCacheGet(cacheKey);
2038
+ if (cached) {
2039
+ return cached;
2040
+ }
1967
2041
  const data = await this.#morphoGraphqlRequest({
1968
2042
  query: MORPHO_VAULT_LIST_QUERY,
1969
- variables: {
1970
- first,
1971
- where,
1972
- orderBy: resolvedOrderBy,
1973
- orderDirection: resolvedOrderDirection,
1974
- },
2043
+ variables,
1975
2044
  operationName: "MorphoVaultV2List",
1976
2045
  });
1977
2046
  const vaults = Array.isArray(data?.vaultV2s?.items) ? data.vaultV2s.items : [];
1978
- return {
2047
+ const result = {
1979
2048
  network: runtimeConfig.network,
1980
2049
  chainId: runtimeConfig.chainId,
1981
2050
  protocol: "morpho",
@@ -1984,10 +2053,14 @@ export class WdkEvmWalletService {
1984
2053
  orderBy: resolvedOrderBy,
1985
2054
  orderDirection: resolvedOrderDirection,
1986
2055
  assetAddressFilter,
2056
+ minTotalAssetsUsd: minTotalAssetsUsdFilter,
2057
+ minNetApy: minNetApyFilter,
1987
2058
  vaultCount: vaults.length,
1988
2059
  vaults,
1989
2060
  source: "morpho-api",
1990
2061
  };
2062
+ morphoDiscoveryCacheSet(cacheKey, result);
2063
+ return result;
1991
2064
  }
1992
2065
 
1993
2066
  async getMorphoMarkets({
@@ -1998,21 +2071,29 @@ export class WdkEvmWalletService {
1998
2071
  search,
1999
2072
  collateralAssetAddress = null,
2000
2073
  loanAssetAddress = null,
2074
+ minSupplyAssetsUsd = null,
2075
+ minNetSupplyApy = null,
2001
2076
  orderBy,
2002
2077
  orderDirection,
2003
2078
  }) {
2004
2079
  const runtimeConfig = this.#resolveRuntimeConfig(network);
2005
2080
  assertMorphoSupportedNetwork(runtimeConfig.network);
2006
2081
  if (marketId !== null && marketId !== undefined && String(marketId).trim()) {
2082
+ const normalizedMarketId = assertMorphoMarketId(marketId, "marketId");
2083
+ const cacheKey = JSON.stringify(["market", runtimeConfig.chainId, normalizedMarketId]);
2084
+ const cached = morphoDiscoveryCacheGet(cacheKey);
2085
+ if (cached) {
2086
+ return cached;
2087
+ }
2007
2088
  const data = await this.#morphoGraphqlRequest({
2008
2089
  query: MORPHO_MARKET_BY_ID_QUERY,
2009
2090
  variables: {
2010
- marketId: assertMorphoMarketId(marketId, "marketId"),
2091
+ marketId: normalizedMarketId,
2011
2092
  chainId: runtimeConfig.chainId,
2012
2093
  },
2013
2094
  operationName: "MorphoMarketById",
2014
2095
  });
2015
- return {
2096
+ const result = {
2016
2097
  network: runtimeConfig.network,
2017
2098
  chainId: runtimeConfig.chainId,
2018
2099
  protocol: "morpho",
@@ -2020,6 +2101,8 @@ export class WdkEvmWalletService {
2020
2101
  found: Boolean(data.marketById),
2021
2102
  source: "morpho-api",
2022
2103
  };
2104
+ morphoDiscoveryCacheSet(cacheKey, result);
2105
+ return result;
2023
2106
  }
2024
2107
  const first = normalizeMorphoListLimit(limit);
2025
2108
  const onlyListed = normalizeMorphoListedOnly(listedOnly);
@@ -2029,6 +2112,14 @@ export class WdkEvmWalletService {
2029
2112
  "collateralAssetAddress"
2030
2113
  );
2031
2114
  const loanFilter = normalizeOptionalAddressFilter(loanAssetAddress, "loanAssetAddress");
2115
+ const minSupplyAssetsUsdFilter = normalizeOptionalNonNegativeNumber(
2116
+ minSupplyAssetsUsd,
2117
+ "minSupplyAssetsUsd"
2118
+ );
2119
+ const minNetSupplyApyFilter = normalizeOptionalNonNegativeNumber(
2120
+ minNetSupplyApy,
2121
+ "minNetSupplyApy"
2122
+ );
2032
2123
  const resolvedOrderBy = normalizeMorphoOrderBy(
2033
2124
  orderBy,
2034
2125
  MORPHO_MARKET_ORDER_LOOKUP,
@@ -2048,18 +2139,30 @@ export class WdkEvmWalletService {
2048
2139
  if (loanFilter) {
2049
2140
  where.loanAssetAddress_in = loanFilter;
2050
2141
  }
2142
+ if (minSupplyAssetsUsdFilter !== null) {
2143
+ where.supplyAssetsUsd_gte = minSupplyAssetsUsdFilter;
2144
+ }
2145
+ if (minNetSupplyApyFilter !== null) {
2146
+ where.netSupplyApy_gte = minNetSupplyApyFilter;
2147
+ }
2148
+ const variables = {
2149
+ first,
2150
+ where,
2151
+ orderBy: resolvedOrderBy,
2152
+ orderDirection: resolvedOrderDirection,
2153
+ };
2154
+ const cacheKey = JSON.stringify(["markets", variables]);
2155
+ const cached = morphoDiscoveryCacheGet(cacheKey);
2156
+ if (cached) {
2157
+ return cached;
2158
+ }
2051
2159
  const data = await this.#morphoGraphqlRequest({
2052
2160
  query: MORPHO_MARKET_LIST_QUERY,
2053
- variables: {
2054
- first,
2055
- where,
2056
- orderBy: resolvedOrderBy,
2057
- orderDirection: resolvedOrderDirection,
2058
- },
2161
+ variables,
2059
2162
  operationName: "MorphoMarketList",
2060
2163
  });
2061
2164
  const markets = Array.isArray(data?.markets?.items) ? data.markets.items : [];
2062
- return {
2165
+ const result = {
2063
2166
  network: runtimeConfig.network,
2064
2167
  chainId: runtimeConfig.chainId,
2065
2168
  protocol: "morpho",
@@ -2070,10 +2173,14 @@ export class WdkEvmWalletService {
2070
2173
  search: searchTerm,
2071
2174
  collateralAssetFilter: collateralFilter,
2072
2175
  loanAssetFilter: loanFilter,
2176
+ minSupplyAssetsUsd: minSupplyAssetsUsdFilter,
2177
+ minNetSupplyApy: minNetSupplyApyFilter,
2073
2178
  marketCount: markets.length,
2074
2179
  markets,
2075
2180
  source: "morpho-api",
2076
2181
  };
2182
+ morphoDiscoveryCacheSet(cacheKey, result);
2183
+ return result;
2077
2184
  }
2078
2185
 
2079
2186
  async getMorphoPositions({ seedPhrase, address, accountIndex = 0, network }) {
@@ -3961,6 +4068,29 @@ export class WdkEvmWalletService {
3961
4068
  });
3962
4069
  }
3963
4070
 
4071
+ async signPersonalMessage({
4072
+ seedPhrase,
4073
+ accountIndex = 0,
4074
+ network,
4075
+ message,
4076
+ }) {
4077
+ return this.#withAccount({ seedPhrase, accountIndex, network }, async (account, runtimeConfig) => {
4078
+ if (typeof message !== "string" || message.length === 0) {
4079
+ throw new Error("message must be a non-empty string.");
4080
+ }
4081
+ const signerAddress = normalizeAddress(await account.getAddress(), "accountAddress");
4082
+ const signature = await account.sign(message);
4083
+ return {
4084
+ network: runtimeConfig.network,
4085
+ chainId: runtimeConfig.chainId,
4086
+ accountIndex,
4087
+ address: signerAddress,
4088
+ signature,
4089
+ source: "wdk-wallet-evm",
4090
+ };
4091
+ });
4092
+ }
4093
+
3964
4094
  #resolveRuntimeConfig(networkOverride) {
3965
4095
  const network = assertValidNetwork(networkOverride) || this.config.network;
3966
4096
  const profile = this.config.networkProfiles?.[network];