ethagent 3.3.4 → 4.1.0
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/.claude-plugin/marketplace.json +11 -0
- package/.claude-plugin/plugin.json +35 -0
- package/LICENSE +1 -1
- package/README.md +67 -102
- package/commands/ethagent.md +40 -0
- package/package.json +14 -16
- package/src/app/keybindings/KeybindingProvider.tsx +1 -6
- package/src/app/keybindings/types.ts +1 -6
- package/src/cli/ResetConfirmView.tsx +54 -53
- package/src/cli/demo.ts +86 -0
- package/src/cli/hookIo.ts +45 -0
- package/src/cli/main.tsx +94 -123
- package/src/cli/memoryGuard.ts +49 -0
- package/src/cli/reset.ts +28 -70
- package/src/cli/sessionStart.ts +33 -0
- package/src/cli/status.ts +46 -0
- package/src/cli/sync.ts +167 -0
- package/src/cli/syncAdapters/claude-code.ts +86 -0
- package/src/cli/syncAdapters/codex.ts +66 -0
- package/src/cli/syncAdapters/index.ts +45 -0
- package/src/cli/syncAdapters/managedBlock.ts +175 -0
- package/src/cli/syncAdapters/shared.ts +63 -0
- package/src/identity/continuity/envelopeParse.ts +20 -1
- package/src/identity/continuity/publicSkills.ts +3 -1
- package/src/identity/continuity/skills/publicSkillsSync.ts +2 -1
- package/src/identity/continuity/skills/scaffold.ts +5 -2
- package/src/identity/continuity/snapshots.ts +12 -5
- package/src/identity/continuity/storage/defaults.ts +20 -19
- package/src/identity/continuity/storage/status.ts +1 -1
- package/src/identity/ens/ensLookup/constants.ts +1 -1
- package/src/identity/manager/IdentityManager.tsx +33 -0
- package/src/identity/{hub → manager}/OperationalRoutes.tsx +37 -18
- package/src/identity/{hub → manager}/Routes.tsx +48 -34
- package/src/identity/{hub → manager}/continuity/ContinuityDashboardScreen.tsx +9 -19
- package/src/identity/{hub → manager}/continuity/RebackupStorageScreen.tsx +3 -3
- package/src/identity/manager/continuity/RecoveryConfirmScreen.tsx +102 -0
- package/src/identity/{hub → manager}/continuity/SavePromptScreen.tsx +2 -3
- package/src/identity/{hub → manager}/continuity/completion.ts +1 -1
- package/src/identity/{hub → manager}/continuity/effects.ts +1 -1
- package/src/identity/{hub → manager}/continuity/skills/DeleteSkillConfirmScreen.tsx +2 -2
- package/src/identity/{hub → manager}/continuity/skills/NewSkillScreen.tsx +0 -5
- package/src/identity/{hub → manager}/continuity/skills/NewSkillVisibilityScreen.tsx +4 -4
- package/src/identity/{hub → manager}/continuity/skills/SkillActionsScreen.tsx +6 -22
- package/src/identity/{hub → manager}/continuity/skills/SkillsTreeScreen.tsx +5 -17
- package/src/identity/{hub → manager}/continuity/snapshot.ts +1 -1
- package/src/identity/{hub → manager}/continuity/vault.ts +1 -1
- package/src/identity/{hub → manager}/create/CreateFlow.tsx +59 -32
- package/src/identity/{hub → manager}/create/effects.ts +19 -10
- package/src/identity/manager/create/importScan.ts +122 -0
- package/src/identity/{hub → manager}/custody/CustodyEditFlow.tsx +17 -61
- package/src/identity/{hub → manager}/custody/actions.ts +1 -15
- package/src/identity/{hub → manager}/custody/routes.tsx +20 -40
- package/src/identity/{hub → manager}/custody/transactions.ts +1 -0
- package/src/identity/{hub → manager}/custody/types.ts +1 -2
- package/src/identity/{hub → manager}/custody/useCustodyEffects.ts +1 -1
- package/src/identity/{hub → manager}/ens/EnsEditAdvancedScreens.tsx +2 -2
- package/src/identity/{hub → manager}/ens/EnsEditMaintenanceScreens.tsx +12 -23
- package/src/identity/{hub → manager}/ens/EnsEditReviewScreens.tsx +18 -42
- package/src/identity/{hub → manager}/ens/EnsEditRunners.tsx +1 -1
- package/src/identity/{hub → manager}/ens/EnsEditShared.tsx +0 -2
- package/src/identity/{hub → manager}/ens/EnsEditSimpleScreens.tsx +10 -19
- package/src/identity/{hub → manager}/ens/EnsFlow.tsx +133 -41
- package/src/identity/{hub → manager}/ens/EnsOperatorWalletsScreen.tsx +14 -19
- package/src/identity/{hub → manager}/ens/editCopy.ts +1 -14
- package/src/identity/{hub → manager}/profile/EditProfileFlow.tsx +99 -66
- package/src/identity/{hub → manager}/profile/effects.ts +1 -3
- package/src/identity/{hub → manager}/profile/operatorSave.ts +1 -1
- package/src/identity/{hub → manager}/profile/state.ts +1 -1
- package/src/identity/{hub/identityHubReducer.ts → manager/reducer.ts} +25 -26
- package/src/identity/{hub → manager}/restore/RestoreFlow.tsx +16 -24
- package/src/identity/{hub → manager}/restore/apply.ts +1 -1
- package/src/identity/{hub → manager}/restore/auth.ts +1 -1
- package/src/identity/{hub → manager}/restore/discover.ts +1 -1
- package/src/identity/{hub → manager}/restore/fetch.ts +1 -1
- package/src/identity/{hub → manager}/restore/restoreAdmin.ts +1 -1
- package/src/identity/{hub → manager}/restore/useRestoreEffects.ts +2 -9
- package/src/identity/{hub → manager}/settings/StorageCredentialScreen.tsx +10 -25
- package/src/identity/{hub → manager}/shared/components/DetailsScreen.tsx +5 -7
- package/src/identity/{hub → manager}/shared/components/ErrorScreen.tsx +6 -10
- package/src/identity/{hub → manager}/shared/components/FlowTimeline.tsx +4 -3
- package/src/identity/{hub → manager}/shared/components/IdentitySummary.tsx +19 -59
- package/src/identity/manager/shared/components/LazyMenu.tsx +147 -0
- package/src/identity/manager/shared/components/MenuScreen.tsx +220 -0
- package/src/identity/manager/shared/components/OperationCompleteScreen.tsx +28 -0
- package/src/identity/{hub → manager}/shared/components/UnlinkedIdentityScreen.tsx +9 -10
- package/src/identity/{hub → manager}/shared/components/WalletApprovalScreen.tsx +1 -2
- package/src/identity/manager/shared/components/Wordmark.tsx +54 -0
- package/src/identity/{hub → manager}/shared/components/menuFlagsFromReconciliation.ts +39 -15
- package/src/identity/{hub → manager}/shared/effects/profilePrep.ts +1 -1
- package/src/identity/manager/shared/effects/types.ts +30 -0
- package/src/identity/{hub → manager}/shared/model/copy.ts +0 -4
- package/src/identity/{hub → manager}/shared/model/errors.ts +32 -3
- package/src/identity/{hub → manager}/shared/model/network.ts +2 -2
- package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/hook.ts +5 -0
- package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/run.ts +1 -1
- package/src/identity/{hub/shared/reconciliation/useAgentReconciliation.ts → manager/shared/reconciliation/index.ts} +6 -0
- package/src/identity/{hub → manager}/shared/utils.ts +6 -10
- package/src/identity/{hub → manager}/transfer/TokenTransferFlow.tsx +3 -3
- package/src/identity/{hub → manager}/transfer/TokenTransferScreens.tsx +4 -10
- package/src/identity/{hub → manager}/transfer/effects.ts +1 -1
- package/src/identity/{hub → manager}/types.ts +5 -6
- package/src/identity/{hub/useIdentityHubContinuity.ts → manager/useContinuity.ts} +59 -27
- package/src/identity/{hub/useIdentityHubController.ts → manager/useController.ts} +38 -35
- package/src/identity/{hub/useIdentityHubSideEffects.ts → manager/useSideEffects.ts} +40 -4
- package/src/identity/registry/erc8004/discovery.ts +3 -17
- package/src/identity/registry/erc8004/utils.ts +1 -1
- package/src/identity/storage/ipfs.ts +21 -1
- package/src/identity/wallet/browserWallet/html.ts +10 -2
- package/src/identity/wallet/browserWallet/http.ts +18 -0
- package/src/identity/wallet/browserWallet/requestServer.ts +5 -1
- package/src/identity/wallet/browserWallet/requests.ts +10 -28
- package/src/identity/wallet/browserWallet/session.ts +26 -33
- package/src/identity/wallet/browserWallet/validation.ts +14 -0
- package/src/identity/wallet/browserWallet/walletPageSource.ts +22 -40
- package/src/identity/wallet/page/boot.ts +43 -0
- package/src/identity/wallet/page/config.ts +59 -0
- package/src/identity/wallet/page/constants.ts +12 -0
- package/src/identity/wallet/page/copy.ts +47 -68
- package/src/identity/wallet/page/css.ts +638 -0
- package/src/identity/wallet/page/{errorView.ts → errors.ts} +5 -14
- package/src/identity/wallet/page/{controller.ts → flow.ts} +4 -71
- package/src/identity/wallet/page/markup.ts +44 -34
- package/src/identity/wallet/page/{walletProvider.ts → provider.ts} +0 -3
- package/src/identity/wallet/page/resize.ts +95 -0
- package/src/identity/wallet/page/state.ts +135 -8
- package/src/identity/wallet/page/timeline.ts +161 -0
- package/src/identity/wallet/page/view.ts +22 -302
- package/src/storage/config.ts +30 -80
- package/src/storage/reset.ts +31 -0
- package/src/storage/secrets.ts +1 -16
- package/src/ui/Select.tsx +27 -5
- package/src/ui/Spinner.tsx +16 -15
- package/src/ui/Surface.tsx +21 -17
- package/src/ui/TextArea.tsx +173 -0
- package/src/ui/TextInput.tsx +31 -133
- package/src/ui/theme.ts +22 -13
- package/src/utils/clipboard.ts +0 -140
- package/src/app/FirstRun.tsx +0 -577
- package/src/app/FirstRunTimeline.tsx +0 -51
- package/src/app/firstRunConfig.ts +0 -26
- package/src/app/hooks/useCancelRequest.ts +0 -22
- package/src/app/hooks/useDoublePress.ts +0 -46
- package/src/app/hooks/useExitOnCtrlC.ts +0 -36
- package/src/auth/openaiOAuth/credentials.ts +0 -47
- package/src/auth/openaiOAuth/crypto.ts +0 -23
- package/src/auth/openaiOAuth/index.ts +0 -238
- package/src/auth/openaiOAuth/landingPage.ts +0 -116
- package/src/auth/openaiOAuth/listener.ts +0 -151
- package/src/auth/openaiOAuth/refresh.ts +0 -70
- package/src/auth/openaiOAuth/shared.ts +0 -115
- package/src/chat/ChatBottomPane.tsx +0 -296
- package/src/chat/ChatScreen.tsx +0 -1685
- package/src/chat/ConversationStack.tsx +0 -56
- package/src/chat/MessageList.tsx +0 -638
- package/src/chat/SessionStatus.tsx +0 -53
- package/src/chat/chatEnvironment.ts +0 -16
- package/src/chat/chatScreenUtils.ts +0 -194
- package/src/chat/chatSessionState.ts +0 -146
- package/src/chat/chatTurnContext.ts +0 -50
- package/src/chat/chatTurnOrchestrator.ts +0 -603
- package/src/chat/chatTurnRows.ts +0 -64
- package/src/chat/commands.ts +0 -494
- package/src/chat/continuityEditReview.ts +0 -42
- package/src/chat/display/DiffView.tsx +0 -193
- package/src/chat/display/SyntaxText.tsx +0 -192
- package/src/chat/display/toolCallDisplay.ts +0 -103
- package/src/chat/display/toolResultDisplay.ts +0 -19
- package/src/chat/input/ChatInput.tsx +0 -625
- package/src/chat/input/chatInputHelpers.ts +0 -62
- package/src/chat/input/chatInputState.ts +0 -247
- package/src/chat/input/chatPaste.ts +0 -49
- package/src/chat/input/imageRefs.ts +0 -30
- package/src/chat/input/inputRendering.tsx +0 -93
- package/src/chat/input/textCursor.ts +0 -212
- package/src/chat/messageMarkdown.ts +0 -220
- package/src/chat/messageRows.ts +0 -43
- package/src/chat/planImplementation.ts +0 -62
- package/src/chat/slashCommandHandlers.ts +0 -122
- package/src/chat/slashCommandViews.ts +0 -120
- package/src/chat/transcript/TranscriptView.tsx +0 -184
- package/src/chat/transcript/transcriptViewport.ts +0 -295
- package/src/chat/views/ContextLimitView.tsx +0 -95
- package/src/chat/views/ContinuityEditReviewView.tsx +0 -50
- package/src/chat/views/CopyPicker.tsx +0 -50
- package/src/chat/views/PermissionPrompt.tsx +0 -156
- package/src/chat/views/PermissionsView.tsx +0 -165
- package/src/chat/views/PlanApprovalView.tsx +0 -91
- package/src/chat/views/ResumeView.tsx +0 -273
- package/src/chat/views/RewindView.tsx +0 -412
- package/src/cli/preview.tsx +0 -14
- package/src/cli/updateNotice.ts +0 -54
- package/src/identity/continuity/privateEdit/apply.ts +0 -170
- package/src/identity/continuity/privateEdit/diff.ts +0 -6
- package/src/identity/continuity/privateEdit/files.ts +0 -23
- package/src/identity/continuity/privateEdit/types.ts +0 -28
- package/src/identity/continuity/privateEdit.ts +0 -46
- package/src/identity/hub/IdentityHub.tsx +0 -14
- package/src/identity/hub/continuity/RecoveryConfirmScreen.tsx +0 -104
- package/src/identity/hub/ens/effects.ts +0 -218
- package/src/identity/hub/shared/components/MenuScreen.tsx +0 -241
- package/src/identity/hub/shared/effects/types.ts +0 -53
- package/src/identity/hub/shared/reconciliation/index.ts +0 -14
- package/src/identity/wallet/page/grainient.ts +0 -278
- package/src/identity/wallet/page/html.ts +0 -28
- package/src/identity/wallet/page/styles/base.ts +0 -260
- package/src/identity/wallet/page/styles/components.ts +0 -262
- package/src/identity/wallet/page/styles/index.ts +0 -5
- package/src/identity/wallet/page/styles/responsive.ts +0 -247
- package/src/identity/wallet/page.tsx +0 -38
- package/src/mcp/approvals.ts +0 -113
- package/src/mcp/config.ts +0 -235
- package/src/mcp/manager.ts +0 -482
- package/src/mcp/managerHelpers.ts +0 -70
- package/src/mcp/names.ts +0 -19
- package/src/mcp/output.ts +0 -96
- package/src/models/ModelPicker.tsx +0 -1009
- package/src/models/catalog.ts +0 -327
- package/src/models/huggingface.ts +0 -712
- package/src/models/huggingfaceStorage.ts +0 -136
- package/src/models/llamacpp.ts +0 -848
- package/src/models/llamacppCommands.ts +0 -44
- package/src/models/llamacppConfig.ts +0 -34
- package/src/models/llamacppDiscovery.ts +0 -176
- package/src/models/llamacppOutput.ts +0 -65
- package/src/models/llamacppPreflight.ts +0 -158
- package/src/models/modelDisplay.ts +0 -180
- package/src/models/modelPickerCatalogFlow.ts +0 -56
- package/src/models/modelPickerCredentials.ts +0 -166
- package/src/models/modelPickerData.ts +0 -41
- package/src/models/modelPickerDisplay.tsx +0 -132
- package/src/models/modelPickerHfFlow.ts +0 -192
- package/src/models/modelPickerLocalRunnerFlow.ts +0 -115
- package/src/models/modelPickerOptions.ts +0 -457
- package/src/models/modelPickerTypes.ts +0 -69
- package/src/models/modelPickerUninstallFlow.ts +0 -48
- package/src/models/modelPickerViewHelpers.ts +0 -174
- package/src/models/modelRecommendation.ts +0 -139
- package/src/models/providerDisplay.ts +0 -16
- package/src/models/runtimeDetection.ts +0 -81
- package/src/models/uncensoredCatalog.ts +0 -86
- package/src/providers/anthropic.ts +0 -290
- package/src/providers/contracts.ts +0 -71
- package/src/providers/errors.ts +0 -80
- package/src/providers/gemini.ts +0 -391
- package/src/providers/openai-chat.ts +0 -474
- package/src/providers/openai-responses-format.ts +0 -177
- package/src/providers/openai-responses.ts +0 -306
- package/src/providers/openaiChatWire.ts +0 -124
- package/src/providers/registry.ts +0 -120
- package/src/providers/retry.ts +0 -58
- package/src/providers/sse.ts +0 -93
- package/src/runtime/compaction.ts +0 -395
- package/src/runtime/cwd.ts +0 -43
- package/src/runtime/providerTurn.ts +0 -38
- package/src/runtime/sessionMode.ts +0 -55
- package/src/runtime/systemPrompt.ts +0 -213
- package/src/runtime/textToolParser.ts +0 -161
- package/src/runtime/toolClaimGuards.ts +0 -143
- package/src/runtime/toolExecution.ts +0 -304
- package/src/runtime/toolIntent.ts +0 -143
- package/src/runtime/turn.ts +0 -369
- package/src/runtime/turnNudges.ts +0 -223
- package/src/runtime/turnTypes.ts +0 -86
- package/src/storage/factoryReset.ts +0 -127
- package/src/storage/history.ts +0 -58
- package/src/storage/permissions.ts +0 -76
- package/src/storage/rewind.ts +0 -266
- package/src/storage/sessionExport.ts +0 -49
- package/src/storage/sessions.ts +0 -495
- package/src/tools/bashSafety.ts +0 -186
- package/src/tools/bashTool.ts +0 -140
- package/src/tools/changeDirectoryTool.ts +0 -213
- package/src/tools/contracts.ts +0 -192
- package/src/tools/deleteFileTool.ts +0 -116
- package/src/tools/editTool.ts +0 -165
- package/src/tools/editUtils.ts +0 -170
- package/src/tools/fileDiff.ts +0 -261
- package/src/tools/listDirectoryTool.ts +0 -55
- package/src/tools/listSkillFilesTool.ts +0 -77
- package/src/tools/listSkillsTool.ts +0 -68
- package/src/tools/mcpResourceTools.ts +0 -95
- package/src/tools/permissionRules.ts +0 -85
- package/src/tools/privateContinuityEditTool.ts +0 -187
- package/src/tools/privateContinuityReadTool.ts +0 -106
- package/src/tools/readSkillTool.ts +0 -107
- package/src/tools/readTool.ts +0 -85
- package/src/tools/registry.ts +0 -103
- package/src/tools/writeFileTool.ts +0 -167
- package/src/ui/BrandSplash.tsx +0 -133
- package/src/ui/terminalTitle.ts +0 -30
- package/src/utils/images.ts +0 -140
- package/src/utils/markdownSegments.ts +0 -51
- package/src/utils/messages.ts +0 -37
- package/src/utils/withRetry.ts +0 -324
- /package/src/identity/{hub → manager}/continuity/state.ts +0 -0
- /package/src/identity/{hub → manager}/custody/helpers.ts +0 -0
- /package/src/identity/{hub → manager}/custody/preflight.ts +0 -0
- /package/src/identity/{hub → manager}/custody/state.ts +0 -0
- /package/src/identity/{hub → manager}/custody/useCustodyFlow.tsx +0 -0
- /package/src/identity/{hub → manager}/ens/EnsEditFlow.tsx +0 -0
- /package/src/identity/{hub → manager}/ens/advancedEnsValidation.ts +0 -0
- /package/src/identity/{hub → manager}/ens/state.ts +0 -0
- /package/src/identity/{hub → manager}/ens/transactions.ts +0 -0
- /package/src/identity/{hub → manager}/ens/types.ts +0 -0
- /package/src/identity/{hub → manager}/profile/identity.ts +0 -0
- /package/src/identity/{hub → manager}/restore/envelopes.ts +0 -0
- /package/src/identity/{hub → manager}/restore/helpers.ts +0 -0
- /package/src/identity/{hub → manager}/restore/recovery.ts +0 -0
- /package/src/identity/{hub → manager}/restore/resolve.ts +0 -0
- /package/src/identity/{hub → manager}/shared/components/BusyScreen.tsx +0 -0
- /package/src/identity/{hub → manager}/shared/components/NetworkScreen.tsx +0 -0
- /package/src/identity/{hub → manager}/shared/components/PinataJwtInput.tsx +0 -0
- /package/src/identity/{hub → manager}/shared/effects/receipts.ts +0 -0
- /package/src/identity/{hub → manager}/shared/effects/sync.ts +0 -0
- /package/src/identity/{hub → manager}/shared/model/format.ts +0 -0
- /package/src/identity/{hub → manager}/shared/operatorWallets.ts +0 -0
- /package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/ownership.ts +0 -0
- /package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/types.ts +0 -0
- /package/src/identity/{hub → manager}/shared/reconciliation/walletSetup.ts +0 -0
- /package/src/identity/{hub → manager}/shared/txGuard.ts +0 -0
- /package/src/identity/{hub → manager}/transfer/progress.ts +0 -0
- /package/src/identity/{hub → manager}/transfer/state.ts +0 -0
|
@@ -1,31 +1,3 @@
|
|
|
1
|
-
import { config } from './state.js'
|
|
2
|
-
import type { WalletConfig, WalletTx } from './types.js'
|
|
3
|
-
import { CANCEL_CLOSE_DELAY_MS, CLOSE_DELAY_MS, TX_CLOSE_DELAY_MS } from './constants.js'
|
|
4
|
-
import { shortAddr } from './copy.js'
|
|
5
|
-
import {
|
|
6
|
-
applyFlowChrome,
|
|
7
|
-
approve,
|
|
8
|
-
cancel,
|
|
9
|
-
clearLastWalletError,
|
|
10
|
-
currentState,
|
|
11
|
-
errorSlot,
|
|
12
|
-
getLastWalletError,
|
|
13
|
-
initializeViewElements,
|
|
14
|
-
setState,
|
|
15
|
-
showPreparedMessage,
|
|
16
|
-
statusHint,
|
|
17
|
-
statusText,
|
|
18
|
-
} from './view.js'
|
|
19
|
-
import { serializeWalletError } from './errorView.js'
|
|
20
|
-
import {
|
|
21
|
-
buildTxParams,
|
|
22
|
-
clearCurrentWalletMethod,
|
|
23
|
-
currentWalletMethod,
|
|
24
|
-
setActiveEthereum,
|
|
25
|
-
waitForEthereumProvider,
|
|
26
|
-
walletRequest,
|
|
27
|
-
} from './walletProvider.js'
|
|
28
|
-
|
|
29
1
|
let closeCountdown: ReturnType<typeof setInterval> | null = null
|
|
30
2
|
let handlersAttached = false
|
|
31
3
|
|
|
@@ -162,13 +134,13 @@ export async function cancelFlow(): Promise<void> {
|
|
|
162
134
|
} else {
|
|
163
135
|
await post("/cancel", {}).catch(() => { });
|
|
164
136
|
}
|
|
165
|
-
setState("
|
|
166
|
-
statusText.textContent = lastWalletError ? "Aborted
|
|
137
|
+
setState("cancelled");
|
|
138
|
+
statusText.textContent = lastWalletError ? "Aborted" : "Cancelled";
|
|
167
139
|
closeSoon(CANCEL_CLOSE_DELAY_MS);
|
|
168
140
|
}
|
|
169
141
|
|
|
170
142
|
function escapeAllowed(): boolean {
|
|
171
|
-
return currentState !== "submitting" && currentState !== "done";
|
|
143
|
+
return currentState !== "submitting" && currentState !== "done" && currentState !== "cancelled";
|
|
172
144
|
}
|
|
173
145
|
|
|
174
146
|
export function startSessionMode(): void {
|
|
@@ -199,7 +171,7 @@ export function startSessionMode(): void {
|
|
|
199
171
|
events.close();
|
|
200
172
|
__sessionMode = false;
|
|
201
173
|
setState("done");
|
|
202
|
-
statusText.textContent = "All set
|
|
174
|
+
statusText.textContent = "All set";
|
|
203
175
|
closeSoon();
|
|
204
176
|
});
|
|
205
177
|
events.onerror = () => {
|
|
@@ -210,42 +182,3 @@ export function startSessionMode(): void {
|
|
|
210
182
|
showReconnecting(true);
|
|
211
183
|
};
|
|
212
184
|
}
|
|
213
|
-
|
|
214
|
-
function attachWalletHandlers(): void {
|
|
215
|
-
if (handlersAttached) return
|
|
216
|
-
handlersAttached = true
|
|
217
|
-
approve.onclick = runWalletFlow
|
|
218
|
-
cancel.onclick = cancelFlow
|
|
219
|
-
window.addEventListener('keydown', (e) => {
|
|
220
|
-
if (e.key === 'Escape') {
|
|
221
|
-
if (!escapeAllowed()) { e.preventDefault(); return }
|
|
222
|
-
e.preventDefault()
|
|
223
|
-
cancelFlow()
|
|
224
|
-
} else if (e.key === 'Enter') {
|
|
225
|
-
if (!approve.hidden && !approve.disabled) { e.preventDefault(); runWalletFlow(); return }
|
|
226
|
-
}
|
|
227
|
-
})
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export function bootWallet(): void {
|
|
231
|
-
initializeViewElements()
|
|
232
|
-
attachWalletHandlers()
|
|
233
|
-
applyFlowChrome()
|
|
234
|
-
if (!window.__WALLET_PREVIEW__) {
|
|
235
|
-
if (document.readyState === 'loading') {
|
|
236
|
-
document.addEventListener('DOMContentLoaded', bootWallet, { once: true })
|
|
237
|
-
} else {
|
|
238
|
-
if (config && config.kind === 'session-wait') {
|
|
239
|
-
startSessionMode()
|
|
240
|
-
} else {
|
|
241
|
-
runWalletFlow()
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
} else {
|
|
245
|
-
window.__walletPreview = {
|
|
246
|
-
setState,
|
|
247
|
-
setConfig: (c: Partial<WalletConfig>) => { Object.assign(config, c); applyFlowChrome() },
|
|
248
|
-
}
|
|
249
|
-
runWalletFlow()
|
|
250
|
-
}
|
|
251
|
-
}
|
|
@@ -1,47 +1,57 @@
|
|
|
1
|
-
import { WALLET_CSS } from './styles/index.js'
|
|
2
|
-
|
|
3
1
|
export const CARD_HTML = `
|
|
4
|
-
<canvas id="grainient" class="grainient-canvas" aria-hidden="true"></canvas>
|
|
5
2
|
<main data-flow="sign" id="card">
|
|
6
|
-
<div class="
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<div class="body">
|
|
12
|
-
<div class="splash-wrap"><pre class="splash" id="splash"></pre></div>
|
|
13
|
-
<div class="head"><span class="label" id="prompt-text">signature request</span></div>
|
|
14
|
-
<h2 class="flow-title" id="flow-title">Sign Message</h2>
|
|
15
|
-
<ol class="timeline" id="timeline" hidden aria-label="Wallet flow steps"></ol>
|
|
16
|
-
<div class="details" id="details-block">
|
|
17
|
-
<p class="flow-detail" id="flow-detail">
|
|
18
|
-
<span class="key" id="detail-key">message</span>
|
|
19
|
-
<span id="detail-val"></span>
|
|
20
|
-
</p>
|
|
3
|
+
<div class="card-inner" id="card-inner">
|
|
4
|
+
<div class="chrome">
|
|
5
|
+
<span class="chrome-brand"></span>
|
|
6
|
+
<span class="chrome-title" id="chrome-title"></span>
|
|
7
|
+
<span class="chrome-actions"></span>
|
|
21
8
|
</div>
|
|
22
|
-
<div class="
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
<
|
|
26
|
-
</
|
|
27
|
-
<
|
|
28
|
-
|
|
9
|
+
<div class="body">
|
|
10
|
+
<div class="card-header">
|
|
11
|
+
<h2 class="flow-title" id="flow-title">Sign Message</h2>
|
|
12
|
+
<p class="flow-subtitle" id="flow-subtitle"></p>
|
|
13
|
+
</div>
|
|
14
|
+
<div class="timeline" id="timeline" hidden>
|
|
15
|
+
<div class="timeline-head">
|
|
16
|
+
<span class="timeline-now" id="timeline-now"></span>
|
|
17
|
+
<span class="timeline-count" id="timeline-count"></span>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="timeline-track" id="timeline-track"></div>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="details" id="details-block">
|
|
22
|
+
<p class="flow-detail" id="flow-detail">
|
|
23
|
+
<span class="key" id="detail-key">message</span>
|
|
24
|
+
<span id="detail-val"></span>
|
|
25
|
+
</p>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="status" id="status-block">
|
|
28
|
+
<p class="status-line">
|
|
29
|
+
<span class="marker" id="status-marker"></span>
|
|
30
|
+
<span id="status-text">Connecting to your wallet…</span>
|
|
31
|
+
</p>
|
|
32
|
+
<p class="status-hint" id="status-hint">Open your wallet extension if it doesn't pop up automatically.</p>
|
|
33
|
+
<p class="status-hint" id="reconnect-hint" hidden>Reconnecting to terminal…</p>
|
|
34
|
+
</div>
|
|
35
|
+
<div id="error-block-slot"></div>
|
|
29
36
|
</div>
|
|
30
|
-
<div
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
<span class="key">enter</span><span>retry</span>
|
|
38
|
-
</button>
|
|
37
|
+
<div class="footer">
|
|
38
|
+
<div class="actions">
|
|
39
|
+
<button id="cancel" class="shortcut"><span class="key">esc</span><span>cancel</span></button>
|
|
40
|
+
<button id="approve" class="shortcut primary" hidden>
|
|
41
|
+
<span class="key">enter</span><span>retry</span>
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
39
44
|
</div>
|
|
40
45
|
</div>
|
|
41
46
|
</main>
|
|
42
47
|
`;
|
|
43
48
|
|
|
44
49
|
export function injectStylesAndMarkup(): void {
|
|
50
|
+
const font = document.createElement("link");
|
|
51
|
+
font.rel = "stylesheet";
|
|
52
|
+
font.href = "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap";
|
|
53
|
+
document.head.appendChild(font);
|
|
54
|
+
|
|
45
55
|
const style = document.createElement("style");
|
|
46
56
|
style.id = "wallet-styles";
|
|
47
57
|
style.textContent = WALLET_CSS;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Smoothly animates the card's height whenever its content changes, so the
|
|
2
|
+
// surface glides between states instead of snapping. The animation is the
|
|
3
|
+
// native Web Animations API, with no external library, so it stays lightweight
|
|
4
|
+
// and runs the same on every machine. It falls back to an instant resize when
|
|
5
|
+
// the API is unavailable or the user prefers reduced motion.
|
|
6
|
+
|
|
7
|
+
let cardEl: HTMLElement | null = null;
|
|
8
|
+
let cardInnerEl: HTMLElement | null = null;
|
|
9
|
+
let resizeAnim: Animation | null = null;
|
|
10
|
+
let trackedHeight = 0;
|
|
11
|
+
let measuredOnce = false;
|
|
12
|
+
let cardResizeReady = false;
|
|
13
|
+
|
|
14
|
+
// Snappy ease-out (mirrors --ease-out in css.ts): quick to start, gentle to settle.
|
|
15
|
+
const RESIZE_DURATION_MS = 200;
|
|
16
|
+
const RESIZE_EASING = "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
17
|
+
|
|
18
|
+
function prefersReducedMotion(): boolean {
|
|
19
|
+
try {
|
|
20
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
21
|
+
} catch (_) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function cardHeightCap(): number {
|
|
27
|
+
const compact = window.matchMedia("(max-width: 560px), (max-height: 680px)").matches;
|
|
28
|
+
const margin = compact ? 20 : 32;
|
|
29
|
+
return Math.max(160, window.innerHeight - margin);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function naturalHeight(): number {
|
|
33
|
+
if (!cardInnerEl) return 0;
|
|
34
|
+
return Math.min(cardInnerEl.offsetHeight, cardHeightCap());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function applyHeight(px: number): void {
|
|
38
|
+
if (cardEl) cardEl.style.height = Math.round(px) + "px";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function settleToContent(): void {
|
|
42
|
+
if (!cardEl || !cardInnerEl) return;
|
|
43
|
+
const target = naturalHeight();
|
|
44
|
+
if (!measuredOnce) {
|
|
45
|
+
measuredOnce = true;
|
|
46
|
+
trackedHeight = target;
|
|
47
|
+
applyHeight(target);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (Math.abs(target - trackedHeight) < 1) return;
|
|
51
|
+
const from = cardEl.getBoundingClientRect().height || trackedHeight;
|
|
52
|
+
trackedHeight = target;
|
|
53
|
+
animateHeight(from, target);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function animateHeight(from: number, to: number): void {
|
|
57
|
+
const el = cardEl;
|
|
58
|
+
if (!el) return;
|
|
59
|
+
if (resizeAnim) {
|
|
60
|
+
try { resizeAnim.cancel(); } catch (_) { /* noop */ }
|
|
61
|
+
resizeAnim = null;
|
|
62
|
+
}
|
|
63
|
+
// The rounded inline height is the source of truth: set it first so the card
|
|
64
|
+
// rests at the final size once the animation ends (default fill is none).
|
|
65
|
+
applyHeight(to);
|
|
66
|
+
if (typeof el.animate !== "function" || prefersReducedMotion() || Math.abs(to - from) < 1) return;
|
|
67
|
+
const anim = el.animate(
|
|
68
|
+
[{ height: Math.round(from) + "px" }, { height: Math.round(to) + "px" }],
|
|
69
|
+
{ duration: RESIZE_DURATION_MS, easing: RESIZE_EASING }
|
|
70
|
+
);
|
|
71
|
+
resizeAnim = anim;
|
|
72
|
+
const clear = (): void => { if (resizeAnim === anim) resizeAnim = null; };
|
|
73
|
+
anim.onfinish = clear;
|
|
74
|
+
anim.oncancel = clear;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function setupCardResize(): void {
|
|
78
|
+
if (cardResizeReady) return;
|
|
79
|
+
cardEl = document.getElementById("card");
|
|
80
|
+
cardInnerEl = document.getElementById("card-inner");
|
|
81
|
+
if (!cardEl || !cardInnerEl || typeof ResizeObserver === "undefined") return;
|
|
82
|
+
cardResizeReady = true;
|
|
83
|
+
settleToContent();
|
|
84
|
+
let scheduled = false;
|
|
85
|
+
const observer = new ResizeObserver(() => {
|
|
86
|
+
if (scheduled) return;
|
|
87
|
+
scheduled = true;
|
|
88
|
+
requestAnimationFrame(() => {
|
|
89
|
+
scheduled = false;
|
|
90
|
+
settleToContent();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
observer.observe(cardInnerEl);
|
|
94
|
+
window.addEventListener("resize", () => settleToContent());
|
|
95
|
+
}
|
|
@@ -1,9 +1,136 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
function spinnerText(value: string): string {
|
|
2
|
+
const text = preserveProtocolCaps(value);
|
|
3
|
+
return text.replace(/^(\s*)([a-z])/, (_match, prefix, letter) => `${prefix}${letter.toUpperCase()}`);
|
|
4
|
+
}
|
|
5
|
+
function spinnerHintText(value: string): string { return preserveProtocolCaps(value); }
|
|
6
|
+
function preserveProtocolCaps(value: string): string {
|
|
7
|
+
return String(value || "")
|
|
8
|
+
.replace(/\bapi\b/gi, "API")
|
|
9
|
+
.replace(/\bens\b/gi, "ENS")
|
|
10
|
+
.replace(/\berc-8004\b/gi, "ERC-8004")
|
|
11
|
+
.replace(/\bgguf\b/gi, "GGUF")
|
|
12
|
+
.replace(/\bhugging face\b/gi, "Hugging Face")
|
|
13
|
+
.replace(/\bipfs\b/gi, "IPFS")
|
|
14
|
+
.replace(/\bjson\b/gi, "JSON")
|
|
15
|
+
.replace(/\bjwt\b/gi, "JWT")
|
|
16
|
+
.replace(/\bmemory\.md\b/gi, "MEMORY.md")
|
|
17
|
+
.replace(/\bopenai\b/gi, "OpenAI")
|
|
18
|
+
.replace(/\banthropic\b/gi, "Anthropic")
|
|
19
|
+
.replace(/\bgemini\b/gi, "Gemini")
|
|
20
|
+
.replace(/\bos\b/gi, "OS")
|
|
21
|
+
.replace(/\brpc\b/gi, "RPC")
|
|
22
|
+
.replace(/\bsoul\.md\b/gi, "SOUL.md")
|
|
23
|
+
.replace(/\buri\b/gi, "URI")
|
|
24
|
+
.replace(/\burl\b/gi, "URL");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function setStatus(marker: string, text: string, hint: string, spin: boolean): void {
|
|
28
|
+
const lineEl = statusText.parentElement as HTMLElement;
|
|
29
|
+
const hintEl = statusHint;
|
|
30
|
+
const displayText = spin ? spinnerText(text) : text;
|
|
31
|
+
const displayHint = spin ? spinnerHintText(hint) : hint;
|
|
32
|
+
const apply = () => {
|
|
33
|
+
if (spin) startSpinner();
|
|
34
|
+
else setMarker(marker);
|
|
35
|
+
statusText.textContent = displayText;
|
|
36
|
+
hintEl.textContent = displayHint;
|
|
37
|
+
requestAnimationFrame(() => {
|
|
38
|
+
lineEl.classList.remove("is-changing");
|
|
39
|
+
hintEl.classList.remove("is-changing");
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
if (statusText.textContent === displayText && hintEl.textContent === displayHint) {
|
|
43
|
+
if (spin) startSpinner();
|
|
44
|
+
else setMarker(marker);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
lineEl.classList.add("is-changing");
|
|
48
|
+
hintEl.classList.add("is-changing");
|
|
49
|
+
setTimeout(apply, 260);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export let currentState: string | null = null;
|
|
53
|
+
|
|
54
|
+
export function setState(state: string, payload?: any): void {
|
|
55
|
+
payload = payload || {};
|
|
56
|
+
currentState = state;
|
|
57
|
+
errorSlot.innerHTML = "";
|
|
58
|
+
statusBlock.style.display = "flex";
|
|
59
|
+
statusBlock.dataset.tone = state === "done" ? "success" : state === "cancelled" ? "cancelled" : "pending";
|
|
60
|
+
const terminal = state === "done" || state === "cancelled";
|
|
61
|
+
const cardEl = document.getElementById("card");
|
|
62
|
+
if (cardEl) cardEl.dataset.phase = terminal ? "terminal" : "active";
|
|
63
|
+
setTabTitle(tabTitleForState(state));
|
|
64
|
+
applyTransferTimeline();
|
|
65
|
+
switch (state) {
|
|
66
|
+
case "connecting":
|
|
67
|
+
setStatus("·", "Connecting To Wallet...", "Open your wallet if needed.", true);
|
|
68
|
+
break;
|
|
69
|
+
case "approve":
|
|
70
|
+
if (config.kind === "account") {
|
|
71
|
+
const copy = accountCopy();
|
|
72
|
+
setStatus("·", copy.text, copy.hint, true);
|
|
73
|
+
} else if (config.kind === "sign") {
|
|
74
|
+
const sigCopy = signCopy();
|
|
75
|
+
setStatus("·", sigCopy.text, sigCopy.hint, true);
|
|
76
|
+
} else {
|
|
77
|
+
const txCopy = transactionCopy();
|
|
78
|
+
setStatus("·", txCopy.text, txCopy.hint, true);
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
case "approve-sign":
|
|
82
|
+
{
|
|
83
|
+
const sigCopy = signCopy();
|
|
84
|
+
setStatus("·", sigCopy.text, sigCopy.hint, true);
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
case "preparing-transaction":
|
|
88
|
+
setStatus("·", purposeCopy().prepare!.text, purposeCopy().prepare!.hint, true);
|
|
89
|
+
break;
|
|
90
|
+
case "approve-transaction":
|
|
91
|
+
{
|
|
92
|
+
const txCopy = transactionCopy();
|
|
93
|
+
setStatus("·", txCopy.text, txCopy.hint, true);
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case "submitting":
|
|
97
|
+
if (config.kind === "account") setStatus("·", "Connecting Wallet...", "Returning to terminal.", true);
|
|
98
|
+
else if (config.kind === "sign") setStatus("·", "Verifying Signature...", hasNextLifecyclePrompt() ? nextLifecycleHint() : "Returning to terminal.", true);
|
|
99
|
+
else setStatus("·", "Submitted · Waiting For Confirmation...", "Your wallet accepted the transaction.", true);
|
|
100
|
+
break;
|
|
101
|
+
case "done":
|
|
102
|
+
stopSpinner();
|
|
103
|
+
statusMarker.innerHTML =
|
|
104
|
+
'<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"' +
|
|
105
|
+
' stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
|
|
106
|
+
'<polyline points="20 6 9 17 4 12"></polyline></svg>';
|
|
107
|
+
statusText.textContent =
|
|
108
|
+
config.kind === "account" ? "Connected"
|
|
109
|
+
: config.kind === "sign" ? "Signed"
|
|
110
|
+
: "Submitted";
|
|
111
|
+
statusHint.textContent = payload.txHash
|
|
112
|
+
? (isTransactionFlow() ? "Transaction submitted. Returning." : "This tab will close shortly.")
|
|
113
|
+
: hasNextLifecyclePrompt() ? nextLifecycleHint() : "This tab will close shortly.";
|
|
114
|
+
markActiveTimelineStepDone();
|
|
115
|
+
break;
|
|
116
|
+
case "cancelled":
|
|
117
|
+
stopSpinner();
|
|
118
|
+
statusMarker.innerHTML = "";
|
|
119
|
+
break;
|
|
120
|
+
case "error":
|
|
121
|
+
stopSpinner();
|
|
122
|
+
statusBlock.style.display = "none";
|
|
123
|
+
renderError(payload);
|
|
124
|
+
break;
|
|
9
125
|
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let lastWalletError: WalletErrorPayload | null = null;
|
|
129
|
+
|
|
130
|
+
function renderError(payload: WalletErrorPayload): void {
|
|
131
|
+
errorSlot.innerHTML = walletErrorHtml(payload);
|
|
132
|
+
lastWalletError = payload;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function getLastWalletError(): WalletErrorPayload | null { return lastWalletError }
|
|
136
|
+
export function clearLastWalletError(): void { lastWalletError = null }
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
type LifecycleId =
|
|
2
|
+
| "ens-clear"
|
|
3
|
+
| "ens-link"
|
|
4
|
+
| "ens-update"
|
|
5
|
+
| "ens-register"
|
|
6
|
+
| "custody-switch"
|
|
7
|
+
| "public-profile-vault";
|
|
8
|
+
|
|
9
|
+
const LIFECYCLE_DEFINITIONS: Record<LifecycleId, { steps: string[] }> = {
|
|
10
|
+
"ens-clear": { steps: ["Clear Records on Mainnet", "Save Cleared Snapshot"] },
|
|
11
|
+
"ens-link": { steps: ["Create Subdomain", "Set Records", "Save Snapshot"] },
|
|
12
|
+
"ens-update": { steps: ["Update Records on Mainnet", "Save Updated Snapshot"] },
|
|
13
|
+
"ens-register": { steps: ["Commit ENS Name", "Register ENS Name"] },
|
|
14
|
+
"custody-switch": { steps: ["Deploy Vault", "Deposit Token", "Reconcile Operators"] },
|
|
15
|
+
"public-profile-vault": { steps: ["Sign Profile", "Save Through Vault"] },
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const FLOW_LIFECYCLE: Record<string, LifecycleId> = {
|
|
19
|
+
"ens-clear": "ens-clear",
|
|
20
|
+
"ens-link": "ens-link",
|
|
21
|
+
"ens-update": "ens-update",
|
|
22
|
+
"ens-register": "ens-register",
|
|
23
|
+
"custody-switch": "custody-switch",
|
|
24
|
+
"public-profile-vault": "public-profile-vault",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const PURPOSE_TIMELINE: Record<string, readonly [string, string]> = {
|
|
28
|
+
"create-agent": ["Sign Recovery Access", "Mint Token"],
|
|
29
|
+
"update-snapshot-owner": ["Sign Snapshot", "Save Onchain"],
|
|
30
|
+
"update-snapshot-operator": ["Sign Snapshot", "Save Onchain"],
|
|
31
|
+
"update-snapshot-connected": ["Sign Snapshot", "Save Onchain"],
|
|
32
|
+
"update-profile-owner": ["Sign Profile", "Save Onchain"],
|
|
33
|
+
"update-profile-operator": ["Sign Profile", "Save Onchain"],
|
|
34
|
+
"update-profile-connected": ["Sign Profile", "Save Onchain"],
|
|
35
|
+
"update-operators": ["Sign Operator List", "Publish List"],
|
|
36
|
+
"create-simple-ens-subdomain": ["Sign Request", "Create Subdomain"],
|
|
37
|
+
"set-simple-ens-records": ["Sign Records", "Write Records"],
|
|
38
|
+
"create-agent-ens-subdomain": ["Sign Request", "Create Subdomain"],
|
|
39
|
+
"set-agent-ens-records": ["Sign Records", "Write Records"],
|
|
40
|
+
"rotate-agent-uri-vault-owner": ["Sign", "Save"],
|
|
41
|
+
"rotate-agent-uri-vault-operator": ["Sign", "Save"],
|
|
42
|
+
"update-ens": ["Sign Snapshot", "Save Onchain"],
|
|
43
|
+
"clear-ens": ["Sign Snapshot", "Save Onchain"],
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
function activeLifecycle(): LifecycleId | undefined {
|
|
47
|
+
if (config.flowId && FLOW_LIFECYCLE[config.flowId]) return FLOW_LIFECYCLE[config.flowId];
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let currentTimelineKey: string | null = null;
|
|
52
|
+
|
|
53
|
+
function lifecycleStepIndex(lifecycle: LifecycleId, state: string | null): number {
|
|
54
|
+
const flowStep = typeof config.flowStep === "number" ? config.flowStep : 1;
|
|
55
|
+
const def = LIFECYCLE_DEFINITIONS[lifecycle];
|
|
56
|
+
const steps = def.steps.length;
|
|
57
|
+
if (state === "done") return Math.min(flowStep, steps);
|
|
58
|
+
return Math.max(0, Math.min(flowStep - 1, steps - 1));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function hasNextLifecyclePrompt(): boolean {
|
|
62
|
+
const lifecycle = activeLifecycle();
|
|
63
|
+
if (!lifecycle) return false;
|
|
64
|
+
const flowStep = typeof config.flowStep === "number" ? config.flowStep : 1;
|
|
65
|
+
return flowStep < LIFECYCLE_DEFINITIONS[lifecycle].steps.length;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function nextLifecycleHint(): string {
|
|
69
|
+
return "Keep this page open. The next wallet step will appear here.";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function purposeStepIndex(state: string | null): number {
|
|
73
|
+
if (state === "approve-transaction" || state === "submitting") return 1;
|
|
74
|
+
if (state === "done") return 2;
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function applyTransferTimeline(): void {
|
|
79
|
+
const timeline = document.getElementById("timeline") as HTMLElement | null;
|
|
80
|
+
if (!timeline) return;
|
|
81
|
+
|
|
82
|
+
if (currentState === "error" || currentState === "cancelled") {
|
|
83
|
+
hideTimeline(timeline);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const lifecycle = activeLifecycle();
|
|
88
|
+
let steps: string[] | null = null;
|
|
89
|
+
let activeIndex = 0;
|
|
90
|
+
let key = "";
|
|
91
|
+
|
|
92
|
+
if (lifecycle) {
|
|
93
|
+
steps = LIFECYCLE_DEFINITIONS[lifecycle].steps;
|
|
94
|
+
activeIndex = lifecycleStepIndex(lifecycle, currentState);
|
|
95
|
+
key = "flow:" + lifecycle;
|
|
96
|
+
} else if (config.kind === "sign-transaction") {
|
|
97
|
+
const tuple = PURPOSE_TIMELINE[config.purpose || ""] || (["Sign", "Submit"] as const);
|
|
98
|
+
steps = [tuple[0], tuple[1]];
|
|
99
|
+
activeIndex = purposeStepIndex(currentState);
|
|
100
|
+
key = "purpose:" + (config.purpose || "");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (!steps) {
|
|
104
|
+
hideTimeline(timeline);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
currentTimelineKey = key;
|
|
109
|
+
timeline.hidden = false;
|
|
110
|
+
|
|
111
|
+
const total = steps.length;
|
|
112
|
+
const currentIndex = Math.min(activeIndex, total - 1);
|
|
113
|
+
const stepNumber = Math.min(activeIndex + 1, total);
|
|
114
|
+
|
|
115
|
+
const now = document.getElementById("timeline-now");
|
|
116
|
+
if (now) now.textContent = steps[currentIndex] ?? "";
|
|
117
|
+
const count = document.getElementById("timeline-count");
|
|
118
|
+
if (count) count.textContent = pad(stepNumber) + " / " + pad(total);
|
|
119
|
+
renderTimelineSegments(total, activeIndex);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function hideTimeline(timeline: HTMLElement): void {
|
|
123
|
+
if (!timeline.hidden) timeline.hidden = true;
|
|
124
|
+
currentTimelineKey = null;
|
|
125
|
+
const track = document.getElementById("timeline-track");
|
|
126
|
+
if (track) track.innerHTML = "";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function renderTimelineSegments(total: number, activeIndex: number): void {
|
|
130
|
+
const track = document.getElementById("timeline-track");
|
|
131
|
+
if (!track) return;
|
|
132
|
+
if (track.childElementCount !== total) {
|
|
133
|
+
track.innerHTML = "";
|
|
134
|
+
for (let i = 0; i < total; i++) {
|
|
135
|
+
const seg = document.createElement("span");
|
|
136
|
+
seg.className = "timeline-seg";
|
|
137
|
+
track.appendChild(seg);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const isDone = currentState === "done";
|
|
141
|
+
const children = track.children;
|
|
142
|
+
for (let i = 0; i < children.length; i++) {
|
|
143
|
+
const seg = children[i] as HTMLElement;
|
|
144
|
+
const done = i < activeIndex;
|
|
145
|
+
const active = i === activeIndex && !isDone;
|
|
146
|
+
seg.className = "timeline-seg" + (done ? " is-done" : active ? " is-active" : "");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function pad(value: number): string {
|
|
151
|
+
return String(value).padStart(2, "0");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function markActiveTimelineStepDone(): void {
|
|
155
|
+
const track = document.getElementById("timeline-track");
|
|
156
|
+
if (!track) return;
|
|
157
|
+
const segs = track.querySelectorAll(".timeline-seg.is-active");
|
|
158
|
+
for (let i = 0; i < segs.length; i++) {
|
|
159
|
+
(segs[i] as HTMLElement).className = "timeline-seg is-done";
|
|
160
|
+
}
|
|
161
|
+
}
|