@elizaos/plugin-wallet 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +64 -0
- package/auto-enable.ts +76 -0
- package/dist/LpManagementService-BWrQ5-cO.mjs +353 -0
- package/dist/MockLpService-D_Apn4Fd.mjs +99 -0
- package/dist/aerodrome-CfnESC32.mjs +890 -0
- package/dist/chunk-hT5z_Zn9.mjs +35 -0
- package/dist/index.d.mts +34727 -0
- package/dist/index.mjs +21590 -0
- package/dist/lib/server-wallet-trade.d.mts +34 -0
- package/dist/lib/server-wallet-trade.mjs +306 -0
- package/dist/meteora-BPX39hZo.mjs +22640 -0
- package/dist/orca-Bybp1HXO.mjs +249 -0
- package/dist/pancakeswp-CkEXlXti.mjs +604 -0
- package/dist/plugin-ZO_MTyd0.mjs +529 -0
- package/dist/raydium-rfaM9yEf.mjs +539 -0
- package/dist/sdk/index.d.mts +32492 -0
- package/dist/sdk/index.mjs +6415 -0
- package/dist/types-D5252NZk.mjs +487 -0
- package/dist/uniswap-CReXgXVN.mjs +573 -0
- package/dist/wallet-action.d.mts +6 -0
- package/dist/wallet-action.mjs +820 -0
- package/package.json +152 -0
- package/src/actions/failure-codes.ts +79 -0
- package/src/actions/index.ts +1 -0
- package/src/analytics/birdeye/actions/wallet-search-address.ts +9 -0
- package/src/analytics/birdeye/birdeye-task.ts +175 -0
- package/src/analytics/birdeye/birdeye.ts +813 -0
- package/src/analytics/birdeye/constants.ts +74 -0
- package/src/analytics/birdeye/providers/agent-portfolio-provider.ts +18 -0
- package/src/analytics/birdeye/providers/market.ts +227 -0
- package/src/analytics/birdeye/providers/portfolio-factory.test.ts +138 -0
- package/src/analytics/birdeye/providers/portfolio-factory.ts +252 -0
- package/src/analytics/birdeye/providers/trending.ts +365 -0
- package/src/analytics/birdeye/providers/wallet.ts +14 -0
- package/src/analytics/birdeye/search-category.test.ts +207 -0
- package/src/analytics/birdeye/search-category.ts +506 -0
- package/src/analytics/birdeye/service.ts +992 -0
- package/src/analytics/birdeye/tasks/birdeye.ts +232 -0
- package/src/analytics/birdeye/types/api/common.ts +305 -0
- package/src/analytics/birdeye/types/api/defi.ts +220 -0
- package/src/analytics/birdeye/types/api/pair.ts +200 -0
- package/src/analytics/birdeye/types/api/search.ts +86 -0
- package/src/analytics/birdeye/types/api/token.ts +635 -0
- package/src/analytics/birdeye/types/api/trader.ts +76 -0
- package/src/analytics/birdeye/types/api/wallet.ts +181 -0
- package/src/analytics/birdeye/types/shared.ts +106 -0
- package/src/analytics/birdeye/utils.ts +700 -0
- package/src/analytics/dexscreener/errors.ts +28 -0
- package/src/analytics/dexscreener/index.ts +3 -0
- package/src/analytics/dexscreener/search-category.test.ts +49 -0
- package/src/analytics/dexscreener/search-category.ts +42 -0
- package/src/analytics/dexscreener/service.ts +595 -0
- package/src/analytics/dexscreener/types.ts +128 -0
- package/src/analytics/lpinfo/index.d.ts +7 -0
- package/src/analytics/lpinfo/index.ts +52 -0
- package/src/analytics/lpinfo/kamino/README.md +102 -0
- package/src/analytics/lpinfo/kamino/index.ts +24 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoLiquidityProvider.ts +422 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoPoolProvider.ts +365 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoProvider.ts +496 -0
- package/src/analytics/lpinfo/kamino/services/kaminoLiquidityService.ts +1123 -0
- package/src/analytics/lpinfo/kamino/services/kaminoService.ts +758 -0
- package/src/analytics/lpinfo/steer/README.md +169 -0
- package/src/analytics/lpinfo/steer/index.ts +23 -0
- package/src/analytics/lpinfo/steer/providers/steerLiquidityProvider.ts +544 -0
- package/src/analytics/lpinfo/steer/services/steerLiquidityService.ts +1690 -0
- package/src/analytics/lpinfo/steer/steer-display-types.ts +99 -0
- package/src/analytics/news/index.ts +52 -0
- package/src/analytics/news/interfaces/types.ts +222 -0
- package/src/analytics/news/providers/defiNewsProvider.ts +734 -0
- package/src/analytics/news/services/newsDataService.ts +332 -0
- package/src/analytics/news/utils/formatters.ts +151 -0
- package/src/analytics/token-info/action.ts +240 -0
- package/src/analytics/token-info/index.ts +3 -0
- package/src/analytics/token-info/params.ts +215 -0
- package/src/analytics/token-info/providers.ts +681 -0
- package/src/analytics/token-info/service.ts +168 -0
- package/src/analytics/token-info/types.ts +74 -0
- package/src/audit/audit-log.ts +45 -0
- package/src/browser-shim/build-shim.ts +123 -0
- package/src/browser-shim/index.ts +5 -0
- package/src/browser-shim/shim.template.js +563 -0
- package/src/chains/evm/.github/workflows/npm-deploy.yml +112 -0
- package/src/chains/evm/LICENSE +21 -0
- package/src/chains/evm/README.md +106 -0
- package/src/chains/evm/actions/helpers.ts +147 -0
- package/src/chains/evm/actions/swap.ts +839 -0
- package/src/chains/evm/actions/transfer.ts +254 -0
- package/src/chains/evm/biome.json +61 -0
- package/src/chains/evm/bridge-router.ts +660 -0
- package/src/chains/evm/build.ts +89 -0
- package/src/chains/evm/chain-handler.ts +416 -0
- package/src/chains/evm/constants.ts +23 -0
- package/src/chains/evm/contracts/artifacts/OZGovernor.json +1707 -0
- package/src/chains/evm/contracts/artifacts/TimelockController.json +1007 -0
- package/src/chains/evm/contracts/artifacts/VoteToken.json +895 -0
- package/src/chains/evm/dex/aerodrome/index.ts +34 -0
- package/src/chains/evm/dex/aerodrome/services/AerodromeLpService.ts +558 -0
- package/src/chains/evm/dex/aerodrome/types.ts +318 -0
- package/src/chains/evm/dex/pancakeswp/index.ts +35 -0
- package/src/chains/evm/dex/pancakeswp/services/PancakeSwapV3LpService.ts +743 -0
- package/src/chains/evm/dex/pancakeswp/types.ts +65 -0
- package/src/chains/evm/dex/uniswap/index.ts +35 -0
- package/src/chains/evm/dex/uniswap/services/UniswapV3LpService.ts +759 -0
- package/src/chains/evm/dex/uniswap/types.ts +390 -0
- package/src/chains/evm/generated/specs/spec-helpers.ts +73 -0
- package/src/chains/evm/generated/specs/specs.ts +151 -0
- package/src/chains/evm/gov-router.ts +250 -0
- package/src/chains/evm/index.browser.ts +16 -0
- package/src/chains/evm/index.ts +31 -0
- package/src/chains/evm/prompts.ts +193 -0
- package/src/chains/evm/providers/get-balance.ts +123 -0
- package/src/chains/evm/providers/wallet.ts +715 -0
- package/src/chains/evm/routes/sign.ts +333 -0
- package/src/chains/evm/rpc-providers.ts +410 -0
- package/src/chains/evm/service.ts +140 -0
- package/src/chains/evm/templates/index.ts +10 -0
- package/src/chains/evm/types/index.ts +432 -0
- package/src/chains/evm/vitest.config.ts +18 -0
- package/src/chains/registry.ts +668 -0
- package/src/chains/solana/README.md +367 -0
- package/src/chains/wallet-action.ts +533 -0
- package/src/chains/wallet-router.test.ts +296 -0
- package/src/contracts.ts +65 -0
- package/src/core-augmentation.ts +10 -0
- package/src/index.ts +71 -0
- package/src/lib/server-wallet-trade.ts +192 -0
- package/src/lib/wallet-export-guard.ts +330 -0
- package/src/lp/actions/liquidity.ts +827 -0
- package/src/lp/e2e/real-token-tests.ts +428 -0
- package/src/lp/e2e/scenarios.ts +470 -0
- package/src/lp/e2e/test-utils.ts +145 -0
- package/src/lp/lp-manager-entry.ts +303 -0
- package/src/lp/services/ConcentratedLiquidityService.ts +120 -0
- package/src/lp/services/DexInteractionService.ts +226 -0
- package/src/lp/services/LpManagementService.test.ts +148 -0
- package/src/lp/services/LpManagementService.ts +632 -0
- package/src/lp/services/UserLpProfileService.ts +163 -0
- package/src/lp/services/VaultService.ts +153 -0
- package/src/lp/services/YieldOptimizationService.ts +344 -0
- package/src/lp/services/__tests__/MockLpService.ts +146 -0
- package/src/lp/tasks/LpAutoRebalanceTask.ts +117 -0
- package/src/lp/tasks/__tests__/LpAutoRebalanceTask.test.ts +370 -0
- package/src/lp/types.ts +582 -0
- package/src/lp/utils/solanaClient.ts +143 -0
- package/src/plugin.ts +125 -0
- package/src/policy/policy.ts +19 -0
- package/src/providers/canonical-provider.ts +27 -0
- package/src/providers/unified-wallet-provider.ts +79 -0
- package/src/register-routes.ts +11 -0
- package/src/routes/plugin.ts +47 -0
- package/src/routes/wallet-market-overview-route.ts +869 -0
- package/src/sdk/abi.ts +258 -0
- package/src/sdk/bridge/abis.ts +126 -0
- package/src/sdk/bridge/client.ts +518 -0
- package/src/sdk/bridge/index.ts +56 -0
- package/src/sdk/bridge/solana.ts +604 -0
- package/src/sdk/bridge/types.ts +202 -0
- package/src/sdk/convenience.ts +347 -0
- package/src/sdk/escrow/MutualStakeEscrow.ts +480 -0
- package/src/sdk/escrow/types.ts +64 -0
- package/src/sdk/escrow/verifiers.ts +73 -0
- package/src/sdk/identity/erc8004.ts +692 -0
- package/src/sdk/identity/reputation.ts +449 -0
- package/src/sdk/identity/uaid.ts +497 -0
- package/src/sdk/identity/validation.ts +372 -0
- package/src/sdk/index.ts +763 -0
- package/src/sdk/policy/SpendingPolicy.ts +260 -0
- package/src/sdk/policy/UptoBillingPolicy.ts +320 -0
- package/src/sdk/router/PaymentRouter.ts +215 -0
- package/src/sdk/router/index.ts +8 -0
- package/src/sdk/swap/SwapModule.ts +310 -0
- package/src/sdk/swap/abi.ts +117 -0
- package/src/sdk/swap/index.ts +34 -0
- package/src/sdk/swap/types.ts +135 -0
- package/src/sdk/tokens/decimals.ts +140 -0
- package/src/sdk/tokens/registry.ts +911 -0
- package/src/sdk/tokens/solana.ts +419 -0
- package/src/sdk/tokens/transfers.ts +327 -0
- package/src/sdk/types.ts +158 -0
- package/src/sdk/wallet-core.ts +115 -0
- package/src/sdk/x402/budget.ts +168 -0
- package/src/sdk/x402/chains/abstract/index.ts +280 -0
- package/src/sdk/x402/client.ts +320 -0
- package/src/sdk/x402/index.ts +46 -0
- package/src/sdk/x402/middleware.ts +92 -0
- package/src/sdk/x402/multi-asset.ts +144 -0
- package/src/sdk/x402/types.ts +156 -0
- package/src/services/wallet-backend-service.ts +328 -0
- package/src/types/wallet-router.ts +227 -0
- package/src/utils/intent-trajectory.ts +106 -0
- package/src/wallet/backend.ts +62 -0
- package/src/wallet/errors.ts +49 -0
- package/src/wallet/index.ts +27 -0
- package/src/wallet/local-eoa-backend.ts +201 -0
- package/src/wallet/pending.ts +60 -0
- package/src/wallet/select-backend.ts +47 -0
- package/src/wallet/steward-backend.ts +161 -0
- package/src/wallet-action.ts +1 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intent-extraction trajectory helper for plugin-wallet.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `runtime.useModel` calls used for financial-parameter extraction
|
|
5
|
+
* (transfer/swap/bridge/balance intent prompts) with the canonical
|
|
6
|
+
* `recordLlmCall` trajectory recorder so every intent LLM hop lands in
|
|
7
|
+
* the trajectories table for training and audit.
|
|
8
|
+
*
|
|
9
|
+
* Falls back to `logActiveTrajectoryLlmCall` if `recordLlmCall` is not
|
|
10
|
+
* exported by the linked `@elizaos/core` build.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
buildCanonicalSystemPrompt,
|
|
15
|
+
getTrajectoryContext,
|
|
16
|
+
type IAgentRuntime,
|
|
17
|
+
logActiveTrajectoryLlmCall,
|
|
18
|
+
ModelType,
|
|
19
|
+
recordLlmCall,
|
|
20
|
+
} from "@elizaos/core";
|
|
21
|
+
|
|
22
|
+
export type IntentModelType =
|
|
23
|
+
| typeof ModelType.TEXT_LARGE
|
|
24
|
+
| typeof ModelType.TEXT_SMALL;
|
|
25
|
+
|
|
26
|
+
export interface RunIntentModelParams {
|
|
27
|
+
runtime: IAgentRuntime;
|
|
28
|
+
/** Trajectory `actionType` label. Use a dotted call-site identifier. */
|
|
29
|
+
taskName: string;
|
|
30
|
+
/** Logical purpose; financial intent extraction is "action" by default. */
|
|
31
|
+
purpose?: string;
|
|
32
|
+
/** Composed prompt text passed to the model. */
|
|
33
|
+
template: string;
|
|
34
|
+
/** Defaults to TEXT_LARGE. */
|
|
35
|
+
modelType?: IntentModelType;
|
|
36
|
+
maxTokens?: number;
|
|
37
|
+
temperature?: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Run an intent-extraction LLM call and record it on the active trajectory.
|
|
42
|
+
*
|
|
43
|
+
* Returns the raw model text so callers can continue parsing with their
|
|
44
|
+
* existing JSON pipeline. Uses `recordLlmCall` when available; otherwise
|
|
45
|
+
* runs the model and emits a `logActiveTrajectoryLlmCall` entry directly.
|
|
46
|
+
*/
|
|
47
|
+
export async function runIntentModel(
|
|
48
|
+
params: RunIntentModelParams,
|
|
49
|
+
): Promise<string> {
|
|
50
|
+
const {
|
|
51
|
+
runtime,
|
|
52
|
+
taskName,
|
|
53
|
+
template,
|
|
54
|
+
purpose = "action",
|
|
55
|
+
modelType = ModelType.TEXT_LARGE,
|
|
56
|
+
maxTokens,
|
|
57
|
+
temperature,
|
|
58
|
+
} = params;
|
|
59
|
+
|
|
60
|
+
const systemPrompt = buildCanonicalSystemPrompt({
|
|
61
|
+
character: runtime.character,
|
|
62
|
+
userRole: getTrajectoryContext()?.userRole,
|
|
63
|
+
});
|
|
64
|
+
const modelLabel = String(modelType);
|
|
65
|
+
const modelParams = {
|
|
66
|
+
prompt: template,
|
|
67
|
+
system: systemPrompt,
|
|
68
|
+
...(maxTokens !== undefined ? { maxTokens } : {}),
|
|
69
|
+
...(temperature !== undefined ? { temperature } : {}),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
if (typeof recordLlmCall === "function") {
|
|
73
|
+
return recordLlmCall(
|
|
74
|
+
runtime,
|
|
75
|
+
{
|
|
76
|
+
model: modelLabel,
|
|
77
|
+
systemPrompt,
|
|
78
|
+
userPrompt: template,
|
|
79
|
+
temperature: temperature ?? 0,
|
|
80
|
+
maxTokens: maxTokens ?? 0,
|
|
81
|
+
purpose,
|
|
82
|
+
actionType: taskName,
|
|
83
|
+
},
|
|
84
|
+
async () => {
|
|
85
|
+
const response = await runtime.useModel(modelType, modelParams);
|
|
86
|
+
return typeof response === "string" ? response : String(response ?? "");
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const startedAt = Date.now();
|
|
92
|
+
const response = await runtime.useModel(modelType, modelParams);
|
|
93
|
+
const text = typeof response === "string" ? response : String(response ?? "");
|
|
94
|
+
logActiveTrajectoryLlmCall(runtime, {
|
|
95
|
+
model: modelLabel,
|
|
96
|
+
systemPrompt,
|
|
97
|
+
userPrompt: template,
|
|
98
|
+
response: text,
|
|
99
|
+
temperature: temperature ?? 0,
|
|
100
|
+
maxTokens: maxTokens ?? 0,
|
|
101
|
+
purpose,
|
|
102
|
+
actionType: taskName,
|
|
103
|
+
latencyMs: Math.max(0, Date.now() - startedAt),
|
|
104
|
+
});
|
|
105
|
+
return text;
|
|
106
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
PublicKey,
|
|
3
|
+
Transaction,
|
|
4
|
+
VersionedTransaction,
|
|
5
|
+
} from "@solana/web3.js";
|
|
6
|
+
import type { Account, Hex, TypedDataDefinition } from "viem";
|
|
7
|
+
import type { SignResult, SignScope } from "./pending.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Narrow signing surface for Solana venues (swap, LP, transfers).
|
|
11
|
+
*/
|
|
12
|
+
export interface SolanaSigner {
|
|
13
|
+
readonly publicKey: PublicKey;
|
|
14
|
+
signTransaction(
|
|
15
|
+
tx: Transaction | VersionedTransaction,
|
|
16
|
+
): Promise<Transaction | VersionedTransaction>;
|
|
17
|
+
signAllTransactions(
|
|
18
|
+
txs: ReadonlyArray<Transaction | VersionedTransaction>,
|
|
19
|
+
): Promise<Array<Transaction | VersionedTransaction>>;
|
|
20
|
+
/**
|
|
21
|
+
* Detached Ed25519 signature of an opaque message. Returned bytes are 64
|
|
22
|
+
* bytes (raw signature). Used by Wallet-Standard `signMessage` and any
|
|
23
|
+
* non-transaction sign-in flows.
|
|
24
|
+
*/
|
|
25
|
+
signMessage(message: Uint8Array): Promise<Uint8Array>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface WalletAddresses {
|
|
29
|
+
readonly evm: `0x${string}` | null;
|
|
30
|
+
readonly solana: PublicKey | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type WalletBackendKind = "local" | "steward";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Canonical wallet abstraction. Providers and canonical actions reach signing
|
|
37
|
+
* only through this interface — never via raw env reads inside venue code.
|
|
38
|
+
*
|
|
39
|
+
* See docs/architecture/wallet-and-trading.md §A.
|
|
40
|
+
*/
|
|
41
|
+
export interface WalletBackend {
|
|
42
|
+
readonly kind: WalletBackendKind;
|
|
43
|
+
|
|
44
|
+
getAddresses(): WalletAddresses;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Returns true when this backend can satisfy signing for the given hint.
|
|
48
|
+
* Read-only QUERY_* flows may skip wallet checks per spec.
|
|
49
|
+
*/
|
|
50
|
+
canSign(chainHint: "evm" | "solana" | "off-chain"): boolean;
|
|
51
|
+
|
|
52
|
+
getEvmAccount(chainId: number): Account;
|
|
53
|
+
|
|
54
|
+
getSolanaSigner(): SolanaSigner;
|
|
55
|
+
|
|
56
|
+
signMessage(scope: SignScope, message: Hex): Promise<SignResult>;
|
|
57
|
+
|
|
58
|
+
signTypedData(
|
|
59
|
+
scope: SignScope,
|
|
60
|
+
typedData: TypedDataDefinition,
|
|
61
|
+
): Promise<SignResult>;
|
|
62
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { PendingApproval } from "./pending.js";
|
|
2
|
+
|
|
3
|
+
export type WalletBackendNotConfiguredCode =
|
|
4
|
+
| "EVM_PRIVATE_KEY_MISSING"
|
|
5
|
+
| "SOLANA_PRIVATE_KEY_MISSING"
|
|
6
|
+
| "NO_WALLET_CONFIGURED";
|
|
7
|
+
|
|
8
|
+
export class WalletBackendNotConfiguredError extends Error {
|
|
9
|
+
readonly code: WalletBackendNotConfiguredCode;
|
|
10
|
+
|
|
11
|
+
constructor(code: WalletBackendNotConfiguredCode, message?: string) {
|
|
12
|
+
const defaults: Record<WalletBackendNotConfiguredCode, string> = {
|
|
13
|
+
EVM_PRIVATE_KEY_MISSING:
|
|
14
|
+
"EVM private key is not configured. Set EVM_PRIVATE_KEY (or hydrate from the OS keychain) before using EVM wallet actions.",
|
|
15
|
+
SOLANA_PRIVATE_KEY_MISSING:
|
|
16
|
+
"Solana private key is not configured. Set SOLANA_PRIVATE_KEY (base58; or hydrate from the OS keychain) before using Solana wallet actions.",
|
|
17
|
+
NO_WALLET_CONFIGURED:
|
|
18
|
+
"No wallet keys are configured. Set at least EVM_PRIVATE_KEY and/or SOLANA_PRIVATE_KEY (local), or use Steward (cloud).",
|
|
19
|
+
};
|
|
20
|
+
super(message ?? defaults[code]);
|
|
21
|
+
this.name = "WalletBackendNotConfiguredError";
|
|
22
|
+
this.code = code;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class StewardUnavailableError extends Error {
|
|
27
|
+
constructor(message: string) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.name = "StewardUnavailableError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class PendingApprovalError extends Error {
|
|
34
|
+
readonly kind = "pending_approval" as const;
|
|
35
|
+
|
|
36
|
+
constructor(readonly pending: PendingApproval) {
|
|
37
|
+
super(
|
|
38
|
+
`Wallet operation pending approval: ${pending.scope} (${pending.approvalId})`,
|
|
39
|
+
);
|
|
40
|
+
this.name = "PendingApprovalError";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class SolanaPrivateKeyInvalidError extends Error {
|
|
45
|
+
constructor(message: string) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.name = "SolanaPrivateKeyInvalidError";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
SolanaSigner,
|
|
3
|
+
WalletAddresses,
|
|
4
|
+
WalletBackend,
|
|
5
|
+
WalletBackendKind,
|
|
6
|
+
} from "./backend.js";
|
|
7
|
+
export {
|
|
8
|
+
PendingApprovalError,
|
|
9
|
+
SolanaPrivateKeyInvalidError,
|
|
10
|
+
StewardUnavailableError,
|
|
11
|
+
WalletBackendNotConfiguredError,
|
|
12
|
+
} from "./errors.js";
|
|
13
|
+
export { LocalEoaBackend } from "./local-eoa-backend.js";
|
|
14
|
+
export type {
|
|
15
|
+
ApprovalSummary,
|
|
16
|
+
CanonicalHandlerResult,
|
|
17
|
+
PendingApproval,
|
|
18
|
+
SignaturePayload,
|
|
19
|
+
SignResult,
|
|
20
|
+
SignScope,
|
|
21
|
+
ValidateOutcome,
|
|
22
|
+
} from "./pending.js";
|
|
23
|
+
export {
|
|
24
|
+
resolveWalletBackend,
|
|
25
|
+
type WalletBackendMode,
|
|
26
|
+
} from "./select-backend.js";
|
|
27
|
+
export { StewardBackend } from "./steward-backend.js";
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import type { IAgentRuntime } from "@elizaos/core";
|
|
2
|
+
import {
|
|
3
|
+
Keypair,
|
|
4
|
+
type PublicKey,
|
|
5
|
+
Transaction,
|
|
6
|
+
VersionedTransaction,
|
|
7
|
+
} from "@solana/web3.js";
|
|
8
|
+
import bs58 from "bs58";
|
|
9
|
+
import type { Hex, TypedDataDefinition } from "viem";
|
|
10
|
+
import { hexToBytes } from "viem";
|
|
11
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
12
|
+
import type {
|
|
13
|
+
SolanaSigner,
|
|
14
|
+
WalletAddresses,
|
|
15
|
+
WalletBackend,
|
|
16
|
+
} from "./backend.js";
|
|
17
|
+
import {
|
|
18
|
+
SolanaPrivateKeyInvalidError,
|
|
19
|
+
WalletBackendNotConfiguredError,
|
|
20
|
+
} from "./errors.js";
|
|
21
|
+
import type { SignResult, SignScope } from "./pending.js";
|
|
22
|
+
|
|
23
|
+
function readSetting(runtime: IAgentRuntime, key: string): string | undefined {
|
|
24
|
+
const v = runtime.getSetting(key);
|
|
25
|
+
if (typeof v === "string" && v.length > 0) {
|
|
26
|
+
return v;
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function resolveEvmPrivateKey(runtime: IAgentRuntime): Hex | null {
|
|
32
|
+
const raw =
|
|
33
|
+
readSetting(runtime, "EVM_PRIVATE_KEY") ?? process.env.EVM_PRIVATE_KEY;
|
|
34
|
+
if (!raw) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const trimmed = raw.trim();
|
|
38
|
+
if (!/^0x[a-fA-F0-9]{64}$/.test(trimmed)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return trimmed as Hex;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function keypairFromSolanaSecret(raw: string): Keypair {
|
|
45
|
+
const trimmed = raw.trim();
|
|
46
|
+
let decoded: Uint8Array;
|
|
47
|
+
try {
|
|
48
|
+
decoded = bs58.decode(trimmed);
|
|
49
|
+
} catch {
|
|
50
|
+
throw new SolanaPrivateKeyInvalidError(
|
|
51
|
+
"SOLANA_PRIVATE_KEY must be base58-encoded.",
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
if (decoded.length === 64) {
|
|
55
|
+
return Keypair.fromSecretKey(decoded);
|
|
56
|
+
}
|
|
57
|
+
if (decoded.length === 32) {
|
|
58
|
+
return Keypair.fromSeed(decoded);
|
|
59
|
+
}
|
|
60
|
+
throw new SolanaPrivateKeyInvalidError(
|
|
61
|
+
"SOLANA_PRIVATE_KEY decodes to an unexpected length (expected 32-byte seed or 64-byte secret key).",
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function resolveSolanaKeypair(runtime: IAgentRuntime): Keypair | null {
|
|
66
|
+
const raw =
|
|
67
|
+
readSetting(runtime, "SOLANA_PRIVATE_KEY") ??
|
|
68
|
+
process.env.SOLANA_PRIVATE_KEY ??
|
|
69
|
+
readSetting(runtime, "WALLET_PRIVATE_KEY") ??
|
|
70
|
+
process.env.WALLET_PRIVATE_KEY;
|
|
71
|
+
if (!raw) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
return keypairFromSolanaSecret(raw);
|
|
76
|
+
} catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
class LocalSolanaSigner implements SolanaSigner {
|
|
82
|
+
readonly publicKey: PublicKey;
|
|
83
|
+
|
|
84
|
+
constructor(private readonly keypair: Keypair) {
|
|
85
|
+
this.publicKey = keypair.publicKey;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async signTransaction(
|
|
89
|
+
tx: Transaction | VersionedTransaction,
|
|
90
|
+
): Promise<Transaction | VersionedTransaction> {
|
|
91
|
+
if (tx instanceof Transaction) {
|
|
92
|
+
const serialized = tx.serialize({
|
|
93
|
+
requireAllSignatures: false,
|
|
94
|
+
verifySignatures: false,
|
|
95
|
+
});
|
|
96
|
+
const copy = Transaction.from(serialized);
|
|
97
|
+
copy.partialSign(this.keypair);
|
|
98
|
+
return copy;
|
|
99
|
+
}
|
|
100
|
+
const copy = VersionedTransaction.deserialize(tx.serialize());
|
|
101
|
+
copy.sign([this.keypair]);
|
|
102
|
+
return copy;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async signAllTransactions(
|
|
106
|
+
txs: ReadonlyArray<Transaction | VersionedTransaction>,
|
|
107
|
+
): Promise<Array<Transaction | VersionedTransaction>> {
|
|
108
|
+
const out: Array<Transaction | VersionedTransaction> = [];
|
|
109
|
+
for (const tx of txs) {
|
|
110
|
+
out.push(await this.signTransaction(tx));
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async signMessage(message: Uint8Array): Promise<Uint8Array> {
|
|
116
|
+
const nacl = await import("tweetnacl");
|
|
117
|
+
return nacl.default.sign.detached(message, this.keypair.secretKey);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Desktop default: local EOA / keypair signing. **Does not** autogenerate keys.
|
|
123
|
+
*/
|
|
124
|
+
export class LocalEoaBackend implements WalletBackend {
|
|
125
|
+
readonly kind = "local" as const;
|
|
126
|
+
|
|
127
|
+
private readonly evmAccount: ReturnType<typeof privateKeyToAccount> | null;
|
|
128
|
+
|
|
129
|
+
private readonly solanaSigner: SolanaSigner | null;
|
|
130
|
+
|
|
131
|
+
private constructor(evmHex: Hex | null, solanaKeypair: Keypair | null) {
|
|
132
|
+
this.evmAccount = evmHex ? privateKeyToAccount(evmHex) : null;
|
|
133
|
+
this.solanaSigner = solanaKeypair
|
|
134
|
+
? new LocalSolanaSigner(solanaKeypair)
|
|
135
|
+
: null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
static async create(runtime: IAgentRuntime): Promise<LocalEoaBackend> {
|
|
139
|
+
const evm = resolveEvmPrivateKey(runtime);
|
|
140
|
+
const kp = resolveSolanaKeypair(runtime);
|
|
141
|
+
if (!evm && !kp) {
|
|
142
|
+
throw new WalletBackendNotConfiguredError("NO_WALLET_CONFIGURED");
|
|
143
|
+
}
|
|
144
|
+
return new LocalEoaBackend(evm, kp);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
getAddresses(): WalletAddresses {
|
|
148
|
+
return {
|
|
149
|
+
evm: this.evmAccount?.address ?? null,
|
|
150
|
+
solana: this.solanaSigner?.publicKey ?? null,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
canSign(chainHint: "evm" | "solana" | "off-chain"): boolean {
|
|
155
|
+
if (chainHint === "evm") {
|
|
156
|
+
return this.evmAccount !== null;
|
|
157
|
+
}
|
|
158
|
+
if (chainHint === "solana") {
|
|
159
|
+
return this.solanaSigner !== null;
|
|
160
|
+
}
|
|
161
|
+
return this.evmAccount !== null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
getEvmAccount(_chainId: number) {
|
|
165
|
+
void _chainId;
|
|
166
|
+
if (!this.evmAccount) {
|
|
167
|
+
throw new WalletBackendNotConfiguredError("EVM_PRIVATE_KEY_MISSING");
|
|
168
|
+
}
|
|
169
|
+
return this.evmAccount;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
getSolanaSigner(): SolanaSigner {
|
|
173
|
+
if (!this.solanaSigner) {
|
|
174
|
+
throw new WalletBackendNotConfiguredError("SOLANA_PRIVATE_KEY_MISSING");
|
|
175
|
+
}
|
|
176
|
+
return this.solanaSigner;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async signMessage(scope: SignScope, message: Hex): Promise<SignResult> {
|
|
180
|
+
void scope;
|
|
181
|
+
if (!this.evmAccount) {
|
|
182
|
+
throw new WalletBackendNotConfiguredError("EVM_PRIVATE_KEY_MISSING");
|
|
183
|
+
}
|
|
184
|
+
const sig = await this.evmAccount.signMessage({
|
|
185
|
+
message: { raw: hexToBytes(message) },
|
|
186
|
+
});
|
|
187
|
+
return { kind: "signature", signature: sig };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async signTypedData(
|
|
191
|
+
scope: SignScope,
|
|
192
|
+
typedData: TypedDataDefinition,
|
|
193
|
+
): Promise<SignResult> {
|
|
194
|
+
void scope;
|
|
195
|
+
if (!this.evmAccount) {
|
|
196
|
+
throw new WalletBackendNotConfiguredError("EVM_PRIVATE_KEY_MISSING");
|
|
197
|
+
}
|
|
198
|
+
const sig = await this.evmAccount.signTypedData(typedData);
|
|
199
|
+
return { kind: "signature", signature: sig };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ActionFailureCode,
|
|
3
|
+
ValidateFailureCode,
|
|
4
|
+
} from "../actions/failure-codes.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Stable identity for a signing operation. Used by the audit log and the
|
|
8
|
+
* policy module. Format: "<domain>.<operation>".
|
|
9
|
+
*/
|
|
10
|
+
export type SignScope =
|
|
11
|
+
| `hyperliquid.${string}`
|
|
12
|
+
| `polymarket.${string}`
|
|
13
|
+
| `lifi.${string}`
|
|
14
|
+
| `jupiter.${string}`
|
|
15
|
+
| `raydium.${string}`
|
|
16
|
+
| `orca.${string}`
|
|
17
|
+
| `meteora.${string}`
|
|
18
|
+
| `aave.${string}`
|
|
19
|
+
| `morpho.${string}`
|
|
20
|
+
| `lp.${string}`
|
|
21
|
+
| `lp-solana.${string}`
|
|
22
|
+
| `lp-evm.${string}`
|
|
23
|
+
| `clanker.${string}`
|
|
24
|
+
| `mint.${string}`
|
|
25
|
+
| `transfer.${string}`
|
|
26
|
+
| `automation.${string}`
|
|
27
|
+
| `x402.${string}`
|
|
28
|
+
| `cctp.${string}`;
|
|
29
|
+
|
|
30
|
+
export interface ApprovalSummary {
|
|
31
|
+
readonly title: string;
|
|
32
|
+
readonly venue: string;
|
|
33
|
+
readonly chainHint: "evm" | "solana" | "off-chain";
|
|
34
|
+
readonly fields: ReadonlyArray<{ label: string; value: string }>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface PendingApproval {
|
|
38
|
+
readonly kind: "pending_approval";
|
|
39
|
+
readonly approvalId: string;
|
|
40
|
+
readonly scope: SignScope;
|
|
41
|
+
readonly expiresAt: number;
|
|
42
|
+
readonly summary: ApprovalSummary;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface SignaturePayload {
|
|
46
|
+
readonly kind: "signature";
|
|
47
|
+
readonly signature: `0x${string}`;
|
|
48
|
+
readonly raw?: `0x${string}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type SignResult = SignaturePayload | PendingApproval;
|
|
52
|
+
|
|
53
|
+
export type ValidateOutcome =
|
|
54
|
+
| { ok: true }
|
|
55
|
+
| { ok: false; reason: ValidateFailureCode; detail: string };
|
|
56
|
+
|
|
57
|
+
export type CanonicalHandlerResult<TData> =
|
|
58
|
+
| { ok: true; data: TData }
|
|
59
|
+
| { ok: false; error: ActionFailureCode; detail: string }
|
|
60
|
+
| { ok: false; error: "PENDING_APPROVAL"; pending: PendingApproval };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { IAgentRuntime } from "@elizaos/core";
|
|
2
|
+
import type { WalletBackend } from "./backend.js";
|
|
3
|
+
import { LocalEoaBackend } from "./local-eoa-backend.js";
|
|
4
|
+
import { StewardBackend } from "./steward-backend.js";
|
|
5
|
+
|
|
6
|
+
export type WalletBackendMode = "local" | "steward" | "auto";
|
|
7
|
+
|
|
8
|
+
function readMode(runtime: IAgentRuntime): WalletBackendMode {
|
|
9
|
+
const raw =
|
|
10
|
+
runtime.getSetting("ELIZA_WALLET_BACKEND") ??
|
|
11
|
+
process.env.ELIZA_WALLET_BACKEND ??
|
|
12
|
+
"auto";
|
|
13
|
+
if (raw === "local" || raw === "steward" || raw === "auto") {
|
|
14
|
+
return raw;
|
|
15
|
+
}
|
|
16
|
+
return "auto";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function preferStewardInAuto(): boolean {
|
|
20
|
+
if (process.env.ELIZA_WALLET_STEWARD_AUTO === "1") {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return process.env.ELIZA_CLOUD_PROVISIONED === "1";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resolves the active wallet backend.
|
|
28
|
+
*
|
|
29
|
+
* - `local` — env keys only ({@link LocalEoaBackend}).
|
|
30
|
+
* - `steward` — Steward API signing ({@link StewardBackend}).
|
|
31
|
+
* - `auto` — Steward when cloud-provisioned or `ELIZA_WALLET_STEWARD_AUTO=1`, otherwise local.
|
|
32
|
+
*/
|
|
33
|
+
export async function resolveWalletBackend(
|
|
34
|
+
runtime: IAgentRuntime,
|
|
35
|
+
): Promise<WalletBackend> {
|
|
36
|
+
const mode = readMode(runtime);
|
|
37
|
+
if (mode === "steward") {
|
|
38
|
+
return StewardBackend.create(runtime);
|
|
39
|
+
}
|
|
40
|
+
if (mode === "local") {
|
|
41
|
+
return LocalEoaBackend.create(runtime);
|
|
42
|
+
}
|
|
43
|
+
if (preferStewardInAuto()) {
|
|
44
|
+
return StewardBackend.create(runtime);
|
|
45
|
+
}
|
|
46
|
+
return LocalEoaBackend.create(runtime);
|
|
47
|
+
}
|