auramaxx 1.0.0-alpha.4
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 +26 -0
- package/README.md +112 -0
- package/bin/aurawallet.js +121 -0
- package/docs/ADAPTERS.md +467 -0
- package/docs/API.md +2679 -0
- package/docs/APPS.md +198 -0
- package/docs/ARCHITECTURE.md +350 -0
- package/docs/AUTH.md +698 -0
- package/docs/BEST-PRACTICES.md +121 -0
- package/docs/CLI.md +61 -0
- package/docs/DEVELOPING-APPS.md +452 -0
- package/docs/EXTENSION.md +97 -0
- package/docs/JOBS.md +33 -0
- package/docs/MCP.md +76 -0
- package/docs/PROTOCOL.md +142 -0
- package/docs/SETUP.md +219 -0
- package/docs/WORKSPACE.md +672 -0
- package/docs/agent-auth.md +63 -0
- package/docs/aura-file.md +48 -0
- package/docs/credentials.md +53 -0
- package/docs/external/getting-started.md +65 -0
- package/docs/external/overview.md +45 -0
- package/docs/external/use-cases.md +48 -0
- package/docs/external/why-aura.md +35 -0
- package/docs/jobs/connect-agent.md +77 -0
- package/docs/jobs/migrate-from-dotenv.md +79 -0
- package/docs/jobs/recover-from-lockout.md +72 -0
- package/docs/jobs/secure-ci.md +63 -0
- package/docs/oauth2.md +42 -0
- package/docs/passkeys.md +60 -0
- package/docs/security.md +540 -0
- package/docs/specs/aura-open-protocol.md +61 -0
- package/docs/specs/aura-provider-plugin.md +24 -0
- package/docs/specs/aura-registry-model.md +31 -0
- package/docs/specs/fixtures/invalid-bad-key.aura +1 -0
- package/docs/specs/fixtures/invalid-bad-unicode-escape.aura +1 -0
- package/docs/specs/fixtures/invalid-duplicate-key.aura +2 -0
- package/docs/specs/fixtures/valid-basic.aura +4 -0
- package/docs/specs/fixtures/valid-provider-ref.aura +1 -0
- package/docs/specs/fixtures/valid-quoted-escapes.aura +2 -0
- package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -0
- package/docs/totp.md +40 -0
- package/docs/wallet/AI.md +508 -0
- package/docs/wallet/DEVELOPING-STRATEGIES.md +713 -0
- package/docs/wallet/README.md +47 -0
- package/docs/wallet/STRATEGY.md +89 -0
- package/next.config.ts +21 -0
- package/package.json +151 -0
- package/postcss.config.mjs +8 -0
- package/prisma/migrations/20260214170000_baseline/migration.sql +511 -0
- package/prisma/migrations/20260216214537_add_passkey_model/migration.sql +18 -0
- package/prisma/migrations/20260217150500_add_credential_access_audit/migration.sql +31 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +447 -0
- package/public/logo-chevron.svg +31 -0
- package/public/logo-concentric.svg +31 -0
- package/public/logo-crosshatch.svg +39 -0
- package/public/logo-dashed.svg +39 -0
- package/public/logo-horizontal.svg +31 -0
- package/public/logo-m56.svg +64 -0
- package/public/logo.webp +0 -0
- package/scripts/add-app.js +245 -0
- package/scripts/init.sh +57 -0
- package/scripts/migrate-apikeys-to-credentials.ts +35 -0
- package/scripts/sandbox-agent-flow.sh +235 -0
- package/scripts/sandbox.sh +175 -0
- package/scripts/validate-job-docs.mjs +125 -0
- package/server/abi/SwapHelper.json +438 -0
- package/server/cli/approval.ts +447 -0
- package/server/cli/commands/app.ts +204 -0
- package/server/cli/commands/cron.ts +24 -0
- package/server/cli/commands/doctor.ts +1007 -0
- package/server/cli/commands/env.ts +456 -0
- package/server/cli/commands/init.ts +752 -0
- package/server/cli/commands/mcp.ts +125 -0
- package/server/cli/commands/restore.ts +314 -0
- package/server/cli/commands/shell-hook.ts +468 -0
- package/server/cli/commands/start.ts +62 -0
- package/server/cli/commands/status.ts +59 -0
- package/server/cli/commands/stop.ts +14 -0
- package/server/cli/commands/token.ts +180 -0
- package/server/cli/commands/unlock.ts +49 -0
- package/server/cli/commands/vault.ts +417 -0
- package/server/cli/index.ts +328 -0
- package/server/cli/lib/aura-parser.ts +64 -0
- package/server/cli/lib/credential-create.ts +74 -0
- package/server/cli/lib/credential-resolve.ts +254 -0
- package/server/cli/lib/dotenv-migrate.ts +116 -0
- package/server/cli/lib/dotenv-parser.ts +146 -0
- package/server/cli/lib/http.ts +91 -0
- package/server/cli/lib/init-steps.ts +76 -0
- package/server/cli/lib/local-agent-trust.ts +45 -0
- package/server/cli/lib/process.ts +136 -0
- package/server/cli/lib/prompt.ts +85 -0
- package/server/cli/lib/theme.ts +240 -0
- package/server/cli/socket.ts +570 -0
- package/server/cli/transport-client.ts +50 -0
- package/server/cron/index.ts +137 -0
- package/server/cron/job.ts +31 -0
- package/server/cron/jobs/balance-sync.ts +436 -0
- package/server/cron/jobs/incoming-scan.ts +506 -0
- package/server/cron/jobs/native-price.ts +70 -0
- package/server/cron/jobs/orphan-cleanup.ts +40 -0
- package/server/cron/jobs/strategy-runner.ts +175 -0
- package/server/cron/scheduler.ts +125 -0
- package/server/index.ts +406 -0
- package/server/lib/adapters/factory.ts +110 -0
- package/server/lib/adapters/index.ts +19 -0
- package/server/lib/adapters/router.ts +297 -0
- package/server/lib/adapters/telegram.ts +645 -0
- package/server/lib/adapters/types.ts +89 -0
- package/server/lib/adapters/webhook.ts +95 -0
- package/server/lib/address.ts +49 -0
- package/server/lib/agent-auth/contracts.ts +1194 -0
- package/server/lib/agent-profiles.ts +328 -0
- package/server/lib/ai.ts +285 -0
- package/server/lib/api-registry/contracts.ts +86 -0
- package/server/lib/api-registry/validation.ts +172 -0
- package/server/lib/apikey-migration.ts +189 -0
- package/server/lib/app-installer.ts +505 -0
- package/server/lib/app-tokens.ts +247 -0
- package/server/lib/auth.ts +314 -0
- package/server/lib/batch.ts +242 -0
- package/server/lib/cold.ts +874 -0
- package/server/lib/config.ts +381 -0
- package/server/lib/credential-access-audit.ts +85 -0
- package/server/lib/credential-access-policy.ts +110 -0
- package/server/lib/credential-health.ts +343 -0
- package/server/lib/credential-import.ts +487 -0
- package/server/lib/credential-scope.ts +87 -0
- package/server/lib/credential-shares.ts +190 -0
- package/server/lib/credential-transport.ts +342 -0
- package/server/lib/credential-vault.ts +77 -0
- package/server/lib/credentials.ts +333 -0
- package/server/lib/crypto.ts +8 -0
- package/server/lib/db.ts +15 -0
- package/server/lib/defaults.ts +366 -0
- package/server/lib/dex/index.ts +80 -0
- package/server/lib/dex/relay.ts +235 -0
- package/server/lib/dex/types.ts +59 -0
- package/server/lib/dex/uniswap.ts +370 -0
- package/server/lib/e2e-agent/artifacts.ts +36 -0
- package/server/lib/e2e-agent/contracts.ts +112 -0
- package/server/lib/e2e-agent/validation.ts +135 -0
- package/server/lib/encrypt.ts +128 -0
- package/server/lib/error.ts +20 -0
- package/server/lib/events.ts +205 -0
- package/server/lib/hot.ts +357 -0
- package/server/lib/key-fingerprint.ts +28 -0
- package/server/lib/logger.ts +331 -0
- package/server/lib/network.ts +137 -0
- package/server/lib/notifications.ts +219 -0
- package/server/lib/oauth2-refresh.ts +241 -0
- package/server/lib/oursecret.ts +54 -0
- package/server/lib/passkey-credential.ts +360 -0
- package/server/lib/passkey.ts +68 -0
- package/server/lib/permissions.ts +248 -0
- package/server/lib/pino.ts +24 -0
- package/server/lib/policy-preview.ts +138 -0
- package/server/lib/price.ts +338 -0
- package/server/lib/prices.ts +34 -0
- package/server/lib/project-scope.ts +239 -0
- package/server/lib/resolve-action.ts +427 -0
- package/server/lib/resolve.ts +36 -0
- package/server/lib/sessions.ts +632 -0
- package/server/lib/solana/connection.ts +26 -0
- package/server/lib/solana/jupiter.ts +128 -0
- package/server/lib/solana/transfer.ts +108 -0
- package/server/lib/solana/wallet.ts +136 -0
- package/server/lib/strategy/emits.ts +21 -0
- package/server/lib/strategy/engine.ts +1305 -0
- package/server/lib/strategy/executor.ts +115 -0
- package/server/lib/strategy/hook-context.ts +158 -0
- package/server/lib/strategy/hooks.ts +990 -0
- package/server/lib/strategy/index.ts +28 -0
- package/server/lib/strategy/installer.ts +305 -0
- package/server/lib/strategy/loader.ts +256 -0
- package/server/lib/strategy/message.ts +235 -0
- package/server/lib/strategy/repository.ts +218 -0
- package/server/lib/strategy/session-logger.ts +693 -0
- package/server/lib/strategy/sources.ts +288 -0
- package/server/lib/strategy/state.ts +189 -0
- package/server/lib/strategy/templates.ts +403 -0
- package/server/lib/strategy/tick.ts +404 -0
- package/server/lib/strategy/types.ts +230 -0
- package/server/lib/swap.ts +3 -0
- package/server/lib/temp.ts +86 -0
- package/server/lib/token-metadata.ts +86 -0
- package/server/lib/token-safety.ts +200 -0
- package/server/lib/token-search.ts +444 -0
- package/server/lib/totp.ts +194 -0
- package/server/lib/transactions.ts +123 -0
- package/server/lib/transport.ts +75 -0
- package/server/lib/txhistory/decoder.ts +262 -0
- package/server/lib/txhistory/enricher.ts +652 -0
- package/server/lib/txhistory/index.ts +391 -0
- package/server/lib/txhistory/signatures.ts +59 -0
- package/server/lib/verified-summary.ts +421 -0
- package/server/mcp/profile-policy.ts +30 -0
- package/server/mcp/server.ts +619 -0
- package/server/mcp/tools.ts +523 -0
- package/server/middleware/auth.ts +119 -0
- package/server/middleware/requestLogger.ts +84 -0
- package/server/routes/actions.ts +459 -0
- package/server/routes/adapters.ts +703 -0
- package/server/routes/addressbook.ts +113 -0
- package/server/routes/ai.ts +34 -0
- package/server/routes/apikeys.ts +295 -0
- package/server/routes/apps.ts +601 -0
- package/server/routes/auth.ts +457 -0
- package/server/routes/backup.ts +340 -0
- package/server/routes/batch.ts +270 -0
- package/server/routes/bookmarks.ts +162 -0
- package/server/routes/credential-shares.ts +198 -0
- package/server/routes/credential-vaults.ts +154 -0
- package/server/routes/credentials.ts +1290 -0
- package/server/routes/dashboard.ts +71 -0
- package/server/routes/defaults.ts +124 -0
- package/server/routes/fund.ts +229 -0
- package/server/routes/import.ts +352 -0
- package/server/routes/launch.ts +665 -0
- package/server/routes/lock.ts +54 -0
- package/server/routes/logs.ts +68 -0
- package/server/routes/nuke.ts +111 -0
- package/server/routes/passkey-credentials.ts +99 -0
- package/server/routes/passkey.ts +346 -0
- package/server/routes/portfolio.ts +217 -0
- package/server/routes/price.ts +63 -0
- package/server/routes/resolve.ts +31 -0
- package/server/routes/security.ts +45 -0
- package/server/routes/send-evm.ts +241 -0
- package/server/routes/send-solana.ts +281 -0
- package/server/routes/send.ts +178 -0
- package/server/routes/setup.ts +210 -0
- package/server/routes/strategy.ts +894 -0
- package/server/routes/swap-evm.ts +353 -0
- package/server/routes/swap-solana.ts +177 -0
- package/server/routes/swap.ts +356 -0
- package/server/routes/token.ts +247 -0
- package/server/routes/unlock.ts +403 -0
- package/server/routes/wallet-assets.ts +361 -0
- package/server/routes/wallet-transactions.ts +515 -0
- package/server/routes/wallet.ts +710 -0
- package/server/types.ts +146 -0
- package/skills/aurawallet/SKILL.md +739 -0
- package/skills/aurawallet-setup/SKILL.md +74 -0
- package/skills/security-review/SKILL.md +148 -0
- package/src/app/api/agent-requests/route.ts +30 -0
- package/src/app/api/apps/install/route.ts +126 -0
- package/src/app/api/apps/manifests/route.ts +16 -0
- package/src/app/api/apps/static/[...path]/route.ts +57 -0
- package/src/app/api/events/route.ts +92 -0
- package/src/app/api/page.tsx +212 -0
- package/src/app/api/workspace/[id]/apps/[wid]/route.ts +119 -0
- package/src/app/api/workspace/[id]/apps/route.ts +81 -0
- package/src/app/api/workspace/[id]/export/route.ts +67 -0
- package/src/app/api/workspace/[id]/route.ts +168 -0
- package/src/app/api/workspace/auth.ts +34 -0
- package/src/app/api/workspace/config/route.ts +106 -0
- package/src/app/api/workspace/import/route.ts +127 -0
- package/src/app/api/workspace/route.ts +116 -0
- package/src/app/app/page.tsx +2122 -0
- package/src/app/apple-icon.png +0 -0
- package/src/app/docs/page.tsx +178 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +572 -0
- package/src/app/health/page.tsx +5 -0
- package/src/app/hello/page.tsx +15 -0
- package/src/app/icon.png +0 -0
- package/src/app/layout.tsx +34 -0
- package/src/app/page.tsx +986 -0
- package/src/app/providers.tsx +90 -0
- package/src/app/share/[token]/page.tsx +295 -0
- package/src/components/ChainSelector.tsx +144 -0
- package/src/components/HumanActionBar.tsx +695 -0
- package/src/components/NotificationDrawer.tsx +129 -0
- package/src/components/apps/AgentKeysApp.tsx +490 -0
- package/src/components/apps/App.tsx +153 -0
- package/src/components/apps/AppGrid.tsx +15 -0
- package/src/components/apps/DetailedAddressDrawer.tsx +325 -0
- package/src/components/apps/DraggableApp.tsx +562 -0
- package/src/components/apps/IFrameApp.tsx +73 -0
- package/src/components/apps/LogsApp.tsx +360 -0
- package/src/components/apps/SendApp.tsx +394 -0
- package/src/components/apps/SetupWizardApp.tsx +1004 -0
- package/src/components/apps/SystemDefaultsApp.tsx +845 -0
- package/src/components/apps/ThirdPartyApp.tsx +428 -0
- package/src/components/apps/TokenApp.tsx +319 -0
- package/src/components/apps/TransactionsApp.tsx +438 -0
- package/src/components/apps/WalletDetailApp.tsx +1505 -0
- package/src/components/apps/index.ts +13 -0
- package/src/components/design-system/Button.tsx +53 -0
- package/src/components/design-system/ChainIndicator.tsx +65 -0
- package/src/components/design-system/ChainSelector.tsx +137 -0
- package/src/components/design-system/ConfirmationModal.tsx +106 -0
- package/src/components/design-system/ConfirmationPopover.tsx +81 -0
- package/src/components/design-system/Drawer.tsx +123 -0
- package/src/components/design-system/FilterDropdown.tsx +72 -0
- package/src/components/design-system/Modal.tsx +206 -0
- package/src/components/design-system/Popover.tsx +142 -0
- package/src/components/design-system/TextInput.tsx +85 -0
- package/src/components/design-system/Toggle.tsx +58 -0
- package/src/components/design-system/index.ts +11 -0
- package/src/components/docs/DocsThemeToggle.tsx +49 -0
- package/src/components/health/CredentialHealthDashboard.tsx +214 -0
- package/src/components/icons/ChainIcons.tsx +72 -0
- package/src/components/layout/AppStoreDrawer.tsx +369 -0
- package/src/components/layout/ContentArea.tsx +21 -0
- package/src/components/layout/TabBar.tsx +278 -0
- package/src/components/layout/WalletSidebar.tsx +1033 -0
- package/src/components/layout/index.ts +4 -0
- package/src/components/marketing/AuraWalletSpecOverlay.tsx +635 -0
- package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
- package/src/components/vault/ApiKeysConsole.tsx +1080 -0
- package/src/components/vault/AuditConsole.tsx +584 -0
- package/src/components/vault/CredentialDetail.tsx +455 -0
- package/src/components/vault/CredentialEmpty.tsx +55 -0
- package/src/components/vault/CredentialField.tsx +361 -0
- package/src/components/vault/CredentialForm.tsx +1212 -0
- package/src/components/vault/CredentialList.tsx +165 -0
- package/src/components/vault/CredentialRow.tsx +97 -0
- package/src/components/vault/CredentialShareModal.tsx +178 -0
- package/src/components/vault/CredentialVault.tsx +754 -0
- package/src/components/vault/CredentialWalletWidget.tsx +103 -0
- package/src/components/vault/ImportCredentialsModal.tsx +515 -0
- package/src/components/vault/LargeTypeModal.tsx +64 -0
- package/src/components/vault/PasswordGenerator.tsx +224 -0
- package/src/components/vault/TOTPDisplay.tsx +123 -0
- package/src/components/vault/VaultSidebar.tsx +413 -0
- package/src/components/vault/types.ts +54 -0
- package/src/context/AuthContext.tsx +337 -0
- package/src/context/PriceContext.tsx +113 -0
- package/src/context/ThemeContext.tsx +164 -0
- package/src/context/WebSocketContext.tsx +269 -0
- package/src/context/WorkspaceContext.tsx +668 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useAgentActions.ts +368 -0
- package/src/hooks/useBalance.ts +103 -0
- package/src/hooks/useBalances.ts +129 -0
- package/src/instrumentation.ts +12 -0
- package/src/lib/api.ts +449 -0
- package/src/lib/app-loader.ts +148 -0
- package/src/lib/app-registry.ts +178 -0
- package/src/lib/app-sdk.ts +157 -0
- package/src/lib/audit-console-adapter.ts +151 -0
- package/src/lib/auth-client.ts +75 -0
- package/src/lib/config.ts +74 -0
- package/src/lib/crypto.ts +112 -0
- package/src/lib/db.ts +21 -0
- package/src/lib/docs.ts +390 -0
- package/src/lib/events.ts +361 -0
- package/src/lib/pino.ts +24 -0
- package/src/lib/theme-handlers.ts +168 -0
- package/src/lib/theme.ts +351 -0
- package/src/lib/tokenData.ts +378 -0
- package/src/lib/vault-crypto.ts +129 -0
- package/src/lib/websocket-server.ts +302 -0
- package/src/lib/websocket-setup.ts +79 -0
- package/src/lib/wordlist.ts +2050 -0
- package/src/lib/workspace-handlers.ts +285 -0
- package/start.sh +80 -0
- package/tailwind.config.ts +99 -0
- package/tsconfig.json +42 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Connection, VersionedTransaction, PublicKey } from '@solana/web3.js';
|
|
2
|
+
|
|
3
|
+
const JUPITER_API = 'https://quote-api.jup.ag/v6';
|
|
4
|
+
|
|
5
|
+
export interface JupiterQuote {
|
|
6
|
+
inputMint: string;
|
|
7
|
+
outputMint: string;
|
|
8
|
+
inAmount: string;
|
|
9
|
+
outAmount: string;
|
|
10
|
+
otherAmountThreshold: string;
|
|
11
|
+
swapMode: string;
|
|
12
|
+
slippageBps: number;
|
|
13
|
+
priceImpactPct: string;
|
|
14
|
+
routePlan: Array<{
|
|
15
|
+
swapInfo: {
|
|
16
|
+
ammKey: string;
|
|
17
|
+
label: string;
|
|
18
|
+
inputMint: string;
|
|
19
|
+
outputMint: string;
|
|
20
|
+
inAmount: string;
|
|
21
|
+
outAmount: string;
|
|
22
|
+
feeAmount: string;
|
|
23
|
+
feeMint: string;
|
|
24
|
+
};
|
|
25
|
+
percent: number;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface JupiterSwapResult {
|
|
30
|
+
swapTransaction: string; // base64-encoded VersionedTransaction
|
|
31
|
+
lastValidBlockHeight: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get a swap quote from Jupiter.
|
|
36
|
+
*/
|
|
37
|
+
export async function getJupiterQuote(
|
|
38
|
+
inputMint: string,
|
|
39
|
+
outputMint: string,
|
|
40
|
+
amount: string,
|
|
41
|
+
slippageBps: number
|
|
42
|
+
): Promise<JupiterQuote> {
|
|
43
|
+
const params = new URLSearchParams({
|
|
44
|
+
inputMint,
|
|
45
|
+
outputMint,
|
|
46
|
+
amount,
|
|
47
|
+
slippageBps: slippageBps.toString(),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const response = await fetch(`${JUPITER_API}/quote?${params}`);
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
const text = await response.text();
|
|
53
|
+
throw new Error(`Jupiter quote failed: ${response.status} ${text}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return response.json();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get a swap transaction from Jupiter.
|
|
61
|
+
* Returns a serialized VersionedTransaction ready to sign.
|
|
62
|
+
*/
|
|
63
|
+
export async function getJupiterSwapTransaction(
|
|
64
|
+
quote: JupiterQuote,
|
|
65
|
+
userPublicKey: string
|
|
66
|
+
): Promise<JupiterSwapResult> {
|
|
67
|
+
const response = await fetch(`${JUPITER_API}/swap`, {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
headers: { 'Content-Type': 'application/json' },
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
quoteResponse: quote,
|
|
72
|
+
userPublicKey,
|
|
73
|
+
wrapAndUnwrapSol: true,
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
const text = await response.text();
|
|
79
|
+
throw new Error(`Jupiter swap failed: ${response.status} ${text}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return response.json();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Deserialize a Jupiter swap transaction.
|
|
87
|
+
*/
|
|
88
|
+
export function deserializeJupiterTransaction(swapTransaction: string): VersionedTransaction {
|
|
89
|
+
const txBuf = Buffer.from(swapTransaction, 'base64');
|
|
90
|
+
return VersionedTransaction.deserialize(txBuf);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Execute a full Jupiter swap: quote → swap tx → sign → send.
|
|
95
|
+
*/
|
|
96
|
+
export async function executeJupiterSwap(
|
|
97
|
+
connection: Connection,
|
|
98
|
+
inputMint: string,
|
|
99
|
+
outputMint: string,
|
|
100
|
+
amount: string,
|
|
101
|
+
slippageBps: number,
|
|
102
|
+
userPublicKey: PublicKey,
|
|
103
|
+
signTransaction: (tx: VersionedTransaction) => Promise<VersionedTransaction>
|
|
104
|
+
): Promise<{ signature: string; quote: JupiterQuote }> {
|
|
105
|
+
// Get quote
|
|
106
|
+
const quote = await getJupiterQuote(inputMint, outputMint, amount, slippageBps);
|
|
107
|
+
|
|
108
|
+
// Get swap transaction
|
|
109
|
+
const { swapTransaction } = await getJupiterSwapTransaction(
|
|
110
|
+
quote,
|
|
111
|
+
userPublicKey.toBase58()
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// Deserialize and sign
|
|
115
|
+
const tx = deserializeJupiterTransaction(swapTransaction);
|
|
116
|
+
const signedTx = await signTransaction(tx);
|
|
117
|
+
|
|
118
|
+
// Send
|
|
119
|
+
const signature = await connection.sendRawTransaction(signedTx.serialize(), {
|
|
120
|
+
skipPreflight: false,
|
|
121
|
+
maxRetries: 2,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Confirm
|
|
125
|
+
await connection.confirmTransaction(signature, 'confirmed');
|
|
126
|
+
|
|
127
|
+
return { signature, quote };
|
|
128
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Connection,
|
|
3
|
+
Keypair,
|
|
4
|
+
PublicKey,
|
|
5
|
+
SystemProgram,
|
|
6
|
+
Transaction,
|
|
7
|
+
} from '@solana/web3.js';
|
|
8
|
+
import {
|
|
9
|
+
createTransferInstruction,
|
|
10
|
+
getAssociatedTokenAddress,
|
|
11
|
+
createAssociatedTokenAccountInstruction,
|
|
12
|
+
getAccount,
|
|
13
|
+
TokenAccountNotFoundError,
|
|
14
|
+
} from '@solana/spl-token';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Build a native SOL transfer transaction.
|
|
18
|
+
* @param amountLamports - Amount in lamports (1 SOL = 1e9 lamports)
|
|
19
|
+
*/
|
|
20
|
+
export async function buildSolTransfer(
|
|
21
|
+
connection: Connection,
|
|
22
|
+
from: PublicKey,
|
|
23
|
+
to: PublicKey,
|
|
24
|
+
amountLamports: number | bigint
|
|
25
|
+
): Promise<Transaction> {
|
|
26
|
+
const lamports = Number(amountLamports);
|
|
27
|
+
|
|
28
|
+
const tx = new Transaction().add(
|
|
29
|
+
SystemProgram.transfer({
|
|
30
|
+
fromPubkey: from,
|
|
31
|
+
toPubkey: to,
|
|
32
|
+
lamports,
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
tx.feePayer = from;
|
|
37
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
38
|
+
tx.recentBlockhash = blockhash;
|
|
39
|
+
|
|
40
|
+
return tx;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Build an SPL token transfer transaction.
|
|
45
|
+
* Creates the recipient's associated token account if it doesn't exist.
|
|
46
|
+
*/
|
|
47
|
+
export async function buildSplTransfer(
|
|
48
|
+
connection: Connection,
|
|
49
|
+
from: PublicKey,
|
|
50
|
+
to: PublicKey,
|
|
51
|
+
mint: PublicKey,
|
|
52
|
+
amount: bigint,
|
|
53
|
+
decimals: number
|
|
54
|
+
): Promise<Transaction> {
|
|
55
|
+
const tx = new Transaction();
|
|
56
|
+
|
|
57
|
+
// Get associated token accounts
|
|
58
|
+
const fromAta = await getAssociatedTokenAddress(mint, from);
|
|
59
|
+
const toAta = await getAssociatedTokenAddress(mint, to);
|
|
60
|
+
|
|
61
|
+
// Check if recipient's ATA exists, create if not
|
|
62
|
+
try {
|
|
63
|
+
await getAccount(connection, toAta);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
if (err instanceof TokenAccountNotFoundError) {
|
|
66
|
+
tx.add(
|
|
67
|
+
createAssociatedTokenAccountInstruction(
|
|
68
|
+
from, // payer
|
|
69
|
+
toAta,
|
|
70
|
+
to,
|
|
71
|
+
mint
|
|
72
|
+
)
|
|
73
|
+
);
|
|
74
|
+
} else {
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
tx.add(
|
|
80
|
+
createTransferInstruction(
|
|
81
|
+
fromAta,
|
|
82
|
+
toAta,
|
|
83
|
+
from,
|
|
84
|
+
amount
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
tx.feePayer = from;
|
|
89
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
90
|
+
tx.recentBlockhash = blockhash;
|
|
91
|
+
|
|
92
|
+
return tx;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Sign and send a Solana transaction.
|
|
97
|
+
* Returns the transaction signature.
|
|
98
|
+
*/
|
|
99
|
+
export async function sendSolanaTransaction(
|
|
100
|
+
connection: Connection,
|
|
101
|
+
tx: Transaction,
|
|
102
|
+
signer: Keypair
|
|
103
|
+
): Promise<string> {
|
|
104
|
+
tx.sign(signer);
|
|
105
|
+
const signature = await connection.sendRawTransaction(tx.serialize());
|
|
106
|
+
await connection.confirmTransaction(signature, 'confirmed');
|
|
107
|
+
return signature;
|
|
108
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { Keypair, Transaction, VersionedTransaction } from '@solana/web3.js';
|
|
2
|
+
import { derivePath } from 'ed25519-hd-key';
|
|
3
|
+
import * as bip39 from 'bip39';
|
|
4
|
+
import { EncryptedData } from '../../types';
|
|
5
|
+
import { encryptWithSeed, decryptWithSeed } from '../encrypt';
|
|
6
|
+
import { getMnemonic, getVaultMnemonic } from '../cold';
|
|
7
|
+
import { prisma } from '../db';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Derive a Solana keypair from a mnemonic using SLIP-0010.
|
|
11
|
+
* Path: m/44'/501'/{index}'/0'
|
|
12
|
+
*/
|
|
13
|
+
export function deriveSolanaKeypair(mnemonic: string, index: number = 0): Keypair {
|
|
14
|
+
const seed = bip39.mnemonicToSeedSync(mnemonic);
|
|
15
|
+
const path = `m/44'/501'/${index}'/0'`;
|
|
16
|
+
const derived = derivePath(path, seed.toString('hex'));
|
|
17
|
+
return Keypair.fromSeed(derived.key);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Derive the cold (master) Solana keypair.
|
|
22
|
+
* Path: m/44'/501'/0'/0'
|
|
23
|
+
*/
|
|
24
|
+
export function deriveSolanaColdKeypair(mnemonic: string): Keypair {
|
|
25
|
+
return deriveSolanaKeypair(mnemonic, 0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface CreateSolanaHotWalletOptions {
|
|
29
|
+
tokenHash: string;
|
|
30
|
+
chain?: string;
|
|
31
|
+
name?: string;
|
|
32
|
+
color?: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
emoji?: string;
|
|
35
|
+
hidden?: boolean;
|
|
36
|
+
coldWalletId?: string; // Which vault to encrypt with (null = primary)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Create a new Solana hot wallet with a random keypair.
|
|
41
|
+
* The secret key is encrypted with the cold wallet mnemonic.
|
|
42
|
+
*/
|
|
43
|
+
export async function createSolanaHotWallet(options: CreateSolanaHotWalletOptions) {
|
|
44
|
+
const { coldWalletId } = options;
|
|
45
|
+
const mnemonic = coldWalletId ? getVaultMnemonic(coldWalletId) : getMnemonic();
|
|
46
|
+
if (!mnemonic) {
|
|
47
|
+
const target = coldWalletId ? `Vault ${coldWalletId}` : 'Cold wallet';
|
|
48
|
+
throw new Error(`${target} must be unlocked to create Solana hot wallets`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const { tokenHash, chain = 'solana', name, color, description, emoji, hidden = false } = options;
|
|
52
|
+
|
|
53
|
+
// Generate random Solana keypair
|
|
54
|
+
const keypair = Keypair.generate();
|
|
55
|
+
const address = keypair.publicKey.toBase58();
|
|
56
|
+
|
|
57
|
+
// Encrypt secret key with mnemonic
|
|
58
|
+
const secretKeyHex = Buffer.from(keypair.secretKey).toString('hex');
|
|
59
|
+
const encrypted = encryptWithSeed(secretKeyHex, mnemonic);
|
|
60
|
+
|
|
61
|
+
// Store in DB (with coldWalletId reference)
|
|
62
|
+
const hotWallet = await prisma.hotWallet.create({
|
|
63
|
+
data: {
|
|
64
|
+
address, // Solana addresses are case-sensitive, no toLowerCase
|
|
65
|
+
encryptedPrivateKey: JSON.stringify(encrypted),
|
|
66
|
+
tokenHash,
|
|
67
|
+
coldWalletId: coldWalletId || null,
|
|
68
|
+
name,
|
|
69
|
+
color,
|
|
70
|
+
description,
|
|
71
|
+
emoji,
|
|
72
|
+
hidden,
|
|
73
|
+
chain,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
address: hotWallet.address,
|
|
79
|
+
tier: 'hot' as const,
|
|
80
|
+
chain: hotWallet.chain,
|
|
81
|
+
createdAt: hotWallet.createdAt.toISOString(),
|
|
82
|
+
name: hotWallet.name || undefined,
|
|
83
|
+
color: hotWallet.color || undefined,
|
|
84
|
+
description: hotWallet.description || undefined,
|
|
85
|
+
emoji: hotWallet.emoji || undefined,
|
|
86
|
+
hidden: hotWallet.hidden,
|
|
87
|
+
tokenHash: hotWallet.tokenHash,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get a Solana keypair from a stored hot wallet.
|
|
93
|
+
* Requires cold wallet to be unlocked for decryption.
|
|
94
|
+
*/
|
|
95
|
+
export async function getSolanaKeypair(address: string): Promise<Keypair> {
|
|
96
|
+
const wallet = await prisma.hotWallet.findUnique({
|
|
97
|
+
where: { address },
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if (!wallet) {
|
|
101
|
+
throw new Error(`Solana hot wallet not found: ${address}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Get mnemonic from the vault this hot wallet belongs to
|
|
105
|
+
const mnemonic = wallet.coldWalletId
|
|
106
|
+
? getVaultMnemonic(wallet.coldWalletId)
|
|
107
|
+
: getMnemonic();
|
|
108
|
+
if (!mnemonic) {
|
|
109
|
+
const target = wallet.coldWalletId ? `Vault ${wallet.coldWalletId}` : 'Cold wallet';
|
|
110
|
+
throw new Error(`${target} must be unlocked to access Solana hot wallet`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const encrypted: EncryptedData = JSON.parse(wallet.encryptedPrivateKey);
|
|
114
|
+
const secretKeyHex = decryptWithSeed(encrypted, mnemonic);
|
|
115
|
+
const secretKey = Uint8Array.from(Buffer.from(secretKeyHex, 'hex'));
|
|
116
|
+
return Keypair.fromSecretKey(secretKey);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Sign a Solana transaction with a hot wallet keypair.
|
|
121
|
+
* Returns the transaction signature (base58).
|
|
122
|
+
*/
|
|
123
|
+
export async function signSolanaTransaction(
|
|
124
|
+
address: string,
|
|
125
|
+
tx: Transaction | VersionedTransaction
|
|
126
|
+
): Promise<Uint8Array> {
|
|
127
|
+
const keypair = await getSolanaKeypair(address);
|
|
128
|
+
|
|
129
|
+
if (tx instanceof VersionedTransaction) {
|
|
130
|
+
tx.sign([keypair]);
|
|
131
|
+
} else {
|
|
132
|
+
tx.partialSign(keypair);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return tx.serialize();
|
|
136
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook Emit Processor
|
|
3
|
+
* ===================
|
|
4
|
+
* Broadcasts hook emit events as app:emit WS events so the dashboard
|
|
5
|
+
* can forward them to the correct app iframe via postMessage.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { HookResult, HookEmit } from './types';
|
|
9
|
+
import { emitWalletEvent } from '../events';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Broadcast hook emit(s) as app:emit events.
|
|
13
|
+
* Called after tick, result, and message hooks.
|
|
14
|
+
*/
|
|
15
|
+
export function processEmits(strategyId: string, hookResult: HookResult): void {
|
|
16
|
+
if (!hookResult.emit) return;
|
|
17
|
+
const emits: HookEmit[] = Array.isArray(hookResult.emit) ? hookResult.emit : [hookResult.emit];
|
|
18
|
+
for (const e of emits) {
|
|
19
|
+
emitWalletEvent('app:emit', { strategyId, channel: e.channel, data: e.data });
|
|
20
|
+
}
|
|
21
|
+
}
|