ethagent 2.0.1 → 2.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.
Files changed (40) hide show
  1. package/README.md +6 -6
  2. package/package.json +1 -1
  3. package/src/chat/ChatScreen.tsx +1 -3
  4. package/src/identity/hub/OperationalRoutes.tsx +3 -3
  5. package/src/identity/hub/components/IdentitySummary.tsx +1 -1
  6. package/src/identity/hub/components/MenuScreen.tsx +2 -2
  7. package/src/identity/hub/effects/index.ts +1 -1
  8. package/src/identity/hub/effects/profile/profileState.ts +32 -32
  9. package/src/identity/hub/effects/publicProfile/runPublicProfileSave.ts +8 -8
  10. package/src/identity/hub/effects/rebackup/runRebackup.ts +2 -2
  11. package/src/identity/hub/effects/rebackup/{operatorVault.ts → vault.ts} +8 -8
  12. package/src/identity/hub/effects/restore/apply.ts +2 -2
  13. package/src/identity/hub/effects/restore/recovery.ts +2 -2
  14. package/src/identity/hub/effects/shared/sync.ts +3 -3
  15. package/src/identity/hub/effects/vault/preflight.ts +8 -8
  16. package/src/identity/hub/flows/create/CreateFlow.tsx +2 -2
  17. package/src/identity/hub/flows/custody/CustodyEditFlow.tsx +11 -11
  18. package/src/identity/hub/flows/custody/custodyEffects.ts +20 -20
  19. package/src/identity/hub/flows/custody/custodyFlowActions.ts +10 -10
  20. package/src/identity/hub/flows/custody/custodyFlowEffects.ts +2 -2
  21. package/src/identity/hub/flows/custody/custodyFlowRoutes.tsx +14 -14
  22. package/src/identity/hub/flows/ens/EnsEditAdvancedScreens.tsx +2 -2
  23. package/src/identity/hub/flows/ens/EnsEditReviewScreens.tsx +2 -2
  24. package/src/identity/hub/model/copy.ts +1 -1
  25. package/src/identity/hub/model/errors.ts +6 -6
  26. package/src/identity/hub/reconciliation/agentReconciliation/ownership.ts +1 -1
  27. package/src/identity/hub/reconciliation/agentReconciliation/run.ts +4 -4
  28. package/src/identity/hub/useIdentityHubController.ts +3 -3
  29. package/src/identity/identityCompat.ts +3 -3
  30. package/src/identity/registry/erc8004/discovery.ts +1 -1
  31. package/src/identity/registry/erc8004/ownership.ts +4 -4
  32. package/src/identity/registry/{operatorVault → vault}/bytecode.ts +15 -15
  33. package/src/identity/registry/vault/constants.ts +38 -0
  34. package/src/identity/registry/{operatorVault → vault}/read.ts +14 -14
  35. package/src/identity/registry/{operatorVault → vault}/transactions.ts +5 -5
  36. package/src/identity/registry/vault.ts +44 -0
  37. package/src/identity/wallet/page/copy.ts +11 -11
  38. package/src/storage/config.ts +3 -3
  39. package/src/identity/registry/operatorVault/constants.ts +0 -38
  40. package/src/identity/registry/operatorVault.ts +0 -44
package/README.md CHANGED
@@ -15,7 +15,7 @@ ethagent binds an AI agent to a wallet-owned ERC-8004 token. Soul and memory sta
15
15
  | --- | --- |
16
16
  | Owner Wallet | Holds and controls the ERC-8004 agent token. Signs custody changes and, in Simple custody, every URI rotation. |
17
17
  | Operator Wallet | Additional wallet authorized to rotate the onchain URI on behalf of the owner. Used in Advanced custody. Never receives token approval. |
18
- | Operator Delegation Vault | Immutable contract deployed per agent token in Advanced custody. Each new vault holds at most one ERC-8004 token. |
18
+ | Vault | Immutable per-agent custody contract used in Advanced custody. Holds at most one ERC-8004 token. |
19
19
  | Snapshot | Encrypted bundle of SOUL.md, MEMORY.md, and session state. Pinned to IPFS; decrypts only against the owner wallet's signature. |
20
20
  | Agent URI | IPFS URI stored in the ERC-8004 `tokenURI`. Resolves to the agent's published metadata. |
21
21
  | Agent Card | Public JSON describing the agent: name, description, capabilities, and skills. Other agents fetch it for discovery. |
@@ -50,7 +50,7 @@ The Identity Hub manages everything portable about the agent:
50
50
 
51
51
  - **Public Profile** edits name, description, icon, and the Agent Card.
52
52
  - **ENS Name** links the agent to a subdomain and authorizes operator wallets to write the subdomain's records.
53
- - **Custody Mode** switches between Simple and Advanced by depositing the token into its agent vault or unwrapping it back out.
53
+ - **Custody Mode** switches between Simple and Advanced by depositing the token into its Vault or unwrapping it back out.
54
54
  - **Prepare Transfer** stages a dual-wallet snapshot before sending the token externally.
55
55
  - **Refetch Latest** pulls the most recent published snapshot back to local files.
56
56
  - **Load Agent** accepts either an ENS name or a bare token ID, and loads any agent owned by or linked to the connected wallet.
@@ -79,11 +79,11 @@ Custody comes in two modes. Switch between them anytime from **Custody Mode**.
79
79
 
80
80
  **Simple** relies on one wallet to own the token, sign every snapshot save, and rotate the onchain URI directly. Use Simple when one wallet operates the agent.
81
81
 
82
- **Advanced** splits an owner wallet from one or more operator wallets. The **owner wallet** owns this agent's dedicated OperatorVault; one or more **operator wallets** handle routine URI rotations through that vault. Use Advanced when routine saves should not require an owner signature.
82
+ **Advanced** splits an owner wallet from one or more operator wallets. The **owner wallet** owns this agent's dedicated Vault; one or more **operator wallets** handle routine URI rotations through that vault. Use Advanced when routine saves should not require an owner signature.
83
83
 
84
- Granting an operator wallet ERC-721 approval would let it rotate the URI, but that same approval also lets it transfer the token away. The agent vault holds the token instead and exposes only a URI-rotation lane for that agent. Operators never receive token approval or transfer rights, cannot touch ENS, and cannot grant rights to other operators. The owner still signs to authorize or revoke operators for the agent, withdraw the token, or transfer the agent.
84
+ Granting an operator wallet ERC-721 approval would let it rotate the URI, but that same approval also lets it transfer the token away. The Vault holds the token instead and exposes only a URI-rotation lane for that agent. Operators never receive token approval or transfer rights, cannot touch ENS, and cannot grant rights to other operators. The owner still signs to authorize or revoke operators for the agent, withdraw the token, or transfer the agent.
85
85
 
86
- The vault is an immutable Foundry contract at `contracts/src/OperatorVault.sol`. New vault deployments are dedicated per agent token and reject any other token.
86
+ The vault is an immutable Foundry contract at `contracts/src/Vault.sol`. New vault deployments are dedicated per agent token and reject any other token.
87
87
 
88
88
  ## ENS Names
89
89
 
@@ -95,7 +95,7 @@ Save the token ID + network somewhere safe. ENS records can be cleared and rebui
95
95
 
96
96
  ## Token Transfers
97
97
 
98
- **Prepare Token Transfer** runs before any ERC-8004 token transfer, and only when the token sits directly in your wallet. An agent in Advanced custody has to switch to Simple first from Custody Mode, which unwraps the token from its agent vault back to the owner wallet.
98
+ **Prepare Token Transfer** runs before any ERC-8004 token transfer, and only when the token sits directly in your wallet. An agent in Advanced custody has to switch to Simple first from Custody Mode, which unwraps the token from its Vault back to the owner wallet.
99
99
 
100
100
  - sender signs snapshot access, receiver signs restore access.
101
101
  - Sender publishes the snapshot pointer to the agent URI.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ethagent",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "A privacy-first AI agent with a portable Ethereum identity",
5
5
  "type": "module",
6
6
  "main": "bin/ethagent.js",
@@ -1388,9 +1388,7 @@ export const ChatScreen: React.FC<ChatScreenProps> = ({ config: initialConfig, o
1388
1388
  }, [compactionUi, overlay, projectedUsageForInput, pullInFlight, pushNote, queuedInputs, runStream, showContextLimitForPrompt, streaming])
1389
1389
 
1390
1390
  const contextLine = `${config.provider} · ${formatModelDisplayName(config.provider, config.model, { maxLength: 24 })} · ${compressHome(cwd)}`
1391
- const tipLine = streaming
1392
- ? 'Tip: You can keep typing and press enter to queue the next message · shift+enter for newline'
1393
- : 'Tip: type /help to get started · shift+enter for newline'
1391
+ const tipLine = 'Tip: type /help to get started · shift+enter for newline'
1394
1392
 
1395
1393
  const placeholderHints = useMemo(() => {
1396
1394
  if (compactionUi) return ['compaction in progress · esc to cancel']
@@ -11,7 +11,7 @@ import {
11
11
  import {
12
12
  runPublicProfileStorageSubmit,
13
13
  } from './effects/publicProfile/runPublicProfileSave.js'
14
- import { resolveOperatorVaultAddress } from './flows/custody/custodyEffects.js'
14
+ import { resolveVaultAddress } from './flows/custody/custodyEffects.js'
15
15
  import { WalletApprovalScreen } from './components/WalletApprovalScreen.js'
16
16
  import { RebackupStorageScreen } from './flows/continuity/RebackupStorageScreen.js'
17
17
  import { BusyScreen } from './components/BusyScreen.js'
@@ -222,14 +222,14 @@ export const IdentityHubOperationalRoutes: React.FC<IdentityHubOperationalRoutes
222
222
  <CustodyEditFlow
223
223
  step={step}
224
224
  reconciliation={reconciliation}
225
- vaultAddress={resolveOperatorVaultAddress(step.identity, config?.erc8004?.operatorVaults)}
225
+ vaultAddress={resolveVaultAddress(step.identity, config?.erc8004?.operatorVaults)}
226
226
  onSetStep={setStep}
227
227
  onSwitchToAdvanced={(returnTo, updates) => custodyFlow.beginVaultDeposit(step, returnTo, updates)}
228
228
  onSwitchToSimple={(returnTo, updates) => custodyFlow.beginVaultUnwrap(step, returnTo, updates)}
229
229
  onWithdrawToken={returnTo => custodyFlow.beginWithdrawToken(step, returnTo)}
230
230
  onReturnToVault={(returnTo, vaultAddress) => custodyFlow.beginReturnToVault(step, returnTo, vaultAddress)}
231
231
  onResumeAdvanced={returnTo => {
232
- const vaultAddress = resolveOperatorVaultAddress(step.identity, config?.erc8004?.operatorVaults)
232
+ const vaultAddress = resolveVaultAddress(step.identity, config?.erc8004?.operatorVaults)
233
233
  const updates: ProfileUpdates = {
234
234
  custodyMode: 'advanced',
235
235
  ownerAddress: step.identity.ownerAddress ?? step.identity.address,
@@ -88,7 +88,7 @@ export const IdentitySummary: React.FC<IdentitySummaryProps> = ({ identity, conf
88
88
  if (!vaultAddress) return null
89
89
  return (
90
90
  <Text>
91
- <Text color={theme.dim}>{'Agent Vault'.padEnd(12)}</Text>
91
+ <Text color={theme.dim}>{'Vault'.padEnd(12)}</Text>
92
92
  <Text color={theme.text}>{shortAddress(vaultAddress)}</Text>
93
93
  </Text>
94
94
  )
@@ -91,8 +91,8 @@ export const MenuScreen: React.FC<MenuScreenProps> = ({
91
91
  : null)
92
92
 
93
93
  const walletSetupBaseHint = custodyMode === 'advanced'
94
- ? 'Advanced. Owner wallet, agent vault, authorized operator wallets'
95
- : 'Simple. Switch to Advanced to delegate URI rotation through a dedicated OperatorVault'
94
+ ? 'Advanced. Owner wallet, Vault, authorized operator wallets'
95
+ : 'Simple. Switch to Advanced to delegate URI rotation through a dedicated Vault'
96
96
 
97
97
  const walletSetupLabel = flags?.custodyAsterisk ? 'Custody Mode *' : 'Custody Mode'
98
98
  const walletSetupHint = flags?.custodyModeReason ?? flags?.custodyHint ?? walletSetupBaseHint
@@ -36,7 +36,7 @@ export {
36
36
  } from './restore/restoreEffects.js'
37
37
  export {
38
38
  assertTokenNotInVault,
39
- OperatorVaultUnavailableError,
39
+ VaultUnavailableError,
40
40
  TokenInVaultError,
41
41
  } from './vault/preflight.js'
42
42
  export {
@@ -1,17 +1,17 @@
1
- import { getAddress, isAddress, type Address } from 'viem'
2
- import type { EthagentIdentity } from '../../../../storage/config.js'
3
- import type { Erc8004RegistryConfig } from '../../../registry/erc8004.js'
4
- import { validateAgentEnsLink, type EnsValidation } from '../../../ens/ensLookup.js'
5
- import { clearOwnerAddressField, clearOperatorVaultAddressField, readOwnerAddressField, setOperatorVaultAddressField, setOwnerAddressField } from '../../../identityCompat.js'
6
- import { validateAdvancedEnsRelationship } from '../../advancedEnsValidation.js'
7
- import { readCustodyMode } from '../../model/custody.js'
8
- import { ensValidationReasonText } from '../../model/ens.js'
9
- import type { ProfileUpdates } from '../../identityHubReducer.js'
10
- import {
11
- assertActiveOperatorIsApproved,
12
- mergeApprovedOperatorWallets,
13
- normalizeApprovedOperatorWallets,
14
- upsertApprovedOperatorWallet,
1
+ import { getAddress, isAddress, type Address } from 'viem'
2
+ import type { EthagentIdentity } from '../../../../storage/config.js'
3
+ import type { Erc8004RegistryConfig } from '../../../registry/erc8004.js'
4
+ import { validateAgentEnsLink, type EnsValidation } from '../../../ens/ensLookup.js'
5
+ import { clearOwnerAddressField, clearVaultAddressField, readOwnerAddressField, setVaultAddressField, setOwnerAddressField } from '../../../identityCompat.js'
6
+ import { validateAdvancedEnsRelationship } from '../../advancedEnsValidation.js'
7
+ import { readCustodyMode } from '../../model/custody.js'
8
+ import { ensValidationReasonText } from '../../model/ens.js'
9
+ import type { ProfileUpdates } from '../../identityHubReducer.js'
10
+ import {
11
+ assertActiveOperatorIsApproved,
12
+ mergeApprovedOperatorWallets,
13
+ normalizeApprovedOperatorWallets,
14
+ upsertApprovedOperatorWallet,
15
15
  } from '../../operatorWallets.js'
16
16
  function ensValidationToState(validation: EnsValidation): Record<string, unknown> {
17
17
  const checkedAt = new Date().toISOString()
@@ -26,7 +26,7 @@ function ensValidationToState(validation: EnsValidation): Record<string, unknown
26
26
  }
27
27
  }
28
28
 
29
- export async function validateEnsForProfileUpdate(
29
+ export async function validateEnsForProfileUpdate(
30
30
  fullName: string,
31
31
  walletAccount: Address,
32
32
  profile: ProfileUpdates,
@@ -89,11 +89,11 @@ export function applyOperatorProfileState(
89
89
  baseState: Record<string, unknown>,
90
90
  ): void {
91
91
  const operatorFieldsTouched = profile.custodyMode !== undefined
92
- || profile.ownerAddress !== undefined
93
- || profile.approvedOperatorWallets !== undefined
94
- || profile.activeOperatorAddress !== undefined
95
- || profile.operatorVaultAddress !== undefined
96
- || profile.restoreAccessEpoch !== undefined
92
+ || profile.ownerAddress !== undefined
93
+ || profile.approvedOperatorWallets !== undefined
94
+ || profile.activeOperatorAddress !== undefined
95
+ || profile.operatorVaultAddress !== undefined
96
+ || profile.restoreAccessEpoch !== undefined
97
97
  if (!operatorFieldsTouched) return
98
98
 
99
99
  if (profile.custodyMode === 'simple') {
@@ -107,18 +107,18 @@ export function applyOperatorProfileState(
107
107
  }
108
108
  return
109
109
  }
110
- if (profile.custodyMode === 'advanced') {
111
- state.custodyMode = 'advanced'
112
- delete state.ensMode
113
- }
114
-
115
- if (profile.operatorVaultAddress !== undefined) {
116
- if (typeof profile.operatorVaultAddress === 'string' && profile.operatorVaultAddress.trim()) {
117
- setOperatorVaultAddressField(state, getAddress(profile.operatorVaultAddress))
118
- } else {
119
- clearOperatorVaultAddressField(state)
120
- }
121
- }
110
+ if (profile.custodyMode === 'advanced') {
111
+ state.custodyMode = 'advanced'
112
+ delete state.ensMode
113
+ }
114
+
115
+ if (profile.operatorVaultAddress !== undefined) {
116
+ if (typeof profile.operatorVaultAddress === 'string' && profile.operatorVaultAddress.trim()) {
117
+ setVaultAddressField(state, getAddress(profile.operatorVaultAddress))
118
+ } else {
119
+ clearVaultAddressField(state)
120
+ }
121
+ }
122
122
 
123
123
  if (typeof profile.ownerAddress === 'string' && profile.ownerAddress.trim()) {
124
124
  setOwnerAddressField(state, getAddress(profile.ownerAddress))
@@ -25,9 +25,9 @@ import {
25
25
  type Erc8004RegistryConfig,
26
26
  } from '../../../registry/erc8004.js'
27
27
  import {
28
- OPERATOR_VAULT_ABI,
28
+ VAULT_ABI,
29
29
  encodeRotateAgentURI,
30
- } from '../../../registry/operatorVault.js'
30
+ } from '../../../registry/vault.js'
31
31
  import { resolveValidatedPinataJwt, savePinataJwt } from '../../../storage/pinataJwt.js'
32
32
  import {
33
33
  openBrowserWalletSession,
@@ -435,7 +435,7 @@ async function runOperatorWalletVaultPublicProfileSave(args: {
435
435
 
436
436
  await callbacks.onIdentityComplete(
437
437
  nextIdentity,
438
- 'Profile updated. ERC-8004 metadata published through the operator delegation vault.',
438
+ 'Profile updated. ERC-8004 metadata published through the Vault.',
439
439
  'update',
440
440
  )
441
441
  } finally {
@@ -611,28 +611,28 @@ async function assertVaultSignerCanRotateAgentUri(args: {
611
611
  try {
612
612
  vaultOwner = getAddress(await client.readContract({
613
613
  address: vaultAddress,
614
- abi: OPERATOR_VAULT_ABI,
614
+ abi: VAULT_ABI,
615
615
  functionName: 'agentOwner',
616
616
  args: [registryAddress, args.agentId],
617
617
  }) as Address)
618
618
  } catch (err: unknown) {
619
- throw new Error(`Could not verify operator delegation vault custody for agent #${args.agentId.toString()}: ${err instanceof Error ? err.message : String(err)}`)
619
+ throw new Error(`Could not verify Vault custody for agent #${args.agentId.toString()}: ${err instanceof Error ? err.message : String(err)}`)
620
620
  }
621
621
  if (vaultOwner === '0x0000000000000000000000000000000000000000') {
622
- throw new Error(`Operator delegation vault ${vaultAddress} does not currently hold agent token #${args.agentId.toString()}. Connect the owner wallet and run "Fix Records" or return the token to the vault before retrying.`)
622
+ throw new Error(`Vault ${vaultAddress} does not currently hold agent token #${args.agentId.toString()}. Connect the owner wallet and run "Fix Records" or return the token to the vault before retrying.`)
623
623
  }
624
624
  if (vaultOwner.toLowerCase() === signer.toLowerCase()) return
625
625
 
626
626
  const isOperator = await client.readContract({
627
627
  address: vaultAddress,
628
- abi: OPERATOR_VAULT_ABI,
628
+ abi: VAULT_ABI,
629
629
  functionName: 'metadataOperators',
630
630
  args: [registryAddress, args.agentId, signer],
631
631
  }) as boolean
632
632
  if (isOperator) return
633
633
 
634
634
  throw new Error(
635
- `Operator wallet ${signer} is not yet authorized on the operator delegation vault to rotate this agent's URI. Connect the owner wallet and run "Fix Records" or re-add this operator to grant the permission.`,
635
+ `Operator wallet ${signer} is not yet authorized on the Vault to rotate this agent's URI. Connect the owner wallet and run "Fix Records" or re-add this operator to grant the permission.`,
636
636
  )
637
637
  }
638
638
 
@@ -38,7 +38,7 @@ import {
38
38
  import {
39
39
  encodeRotateAgentURI,
40
40
  isAgentInVault,
41
- } from '../../../registry/operatorVault.js'
41
+ } from '../../../registry/vault.js'
42
42
  import type { Step, ProfileUpdates } from '../../identityHubReducer.js'
43
43
  import { acquireTxGuard, releaseTxGuard } from '../../txGuard.js'
44
44
  import type { EffectCallbacks } from '../types.js'
@@ -65,7 +65,7 @@ import {
65
65
  resolverSyncWarningMessage,
66
66
  syncResolverApprovalsAfterOwnerSave,
67
67
  } from '../shared/sync.js'
68
- import { runOperatorWalletRebackup } from './operatorVault.js'
68
+ import { runOperatorWalletRebackup } from './vault.js'
69
69
 
70
70
  type BackupMetadata = NonNullable<EthagentIdentity['backup']>
71
71
  type PublicSkillsMetadata = NonNullable<EthagentIdentity['publicSkills']>
@@ -24,9 +24,9 @@ import {
24
24
  withEthagentPointers,
25
25
  } from '../../../registry/erc8004.js'
26
26
  import {
27
- OPERATOR_VAULT_ABI,
27
+ VAULT_ABI,
28
28
  encodeRotateAgentURI,
29
- } from '../../../registry/operatorVault.js'
29
+ } from '../../../registry/vault.js'
30
30
  import {
31
31
  requestBrowserWalletSignature,
32
32
  requestBrowserWalletSignatureAndTransaction,
@@ -54,7 +54,7 @@ import { markCurrentContinuityFilesPublished } from '../shared/sync.js'
54
54
  type BackupMetadata = NonNullable<EthagentIdentity['backup']>
55
55
  type PublicSkillsMetadata = NonNullable<EthagentIdentity['publicSkills']>
56
56
 
57
- type OperatorVaultPublishPrepared = {
57
+ type VaultPublishPrepared = {
58
58
  nextIdentity: EthagentIdentity
59
59
  markdownScaffold?: IdentityMarkdownScaffold
60
60
  completionMessage: string
@@ -210,7 +210,7 @@ async function runOperatorWalletVaultPublish(args: {
210
210
  const probeClient = createErc8004PublicClient(step.registry)
211
211
  const isOperator = await probeClient.readContract({
212
212
  address: vaultAddress,
213
- abi: OPERATOR_VAULT_ABI,
213
+ abi: VAULT_ABI,
214
214
  functionName: 'metadataOperators',
215
215
  args: [
216
216
  getAddress(step.registry.identityRegistryAddress),
@@ -220,11 +220,11 @@ async function runOperatorWalletVaultPublish(args: {
220
220
  }) as boolean
221
221
  if (!isOperator) {
222
222
  throw new Error(
223
- `Operator wallet ${expectedSigner} is not yet authorized on the operator delegation vault to rotate this agent's URI. Connect the owner wallet and run "Fix Records" or re-add this operator to grant the permission.`,
223
+ `Operator wallet ${expectedSigner} is not yet authorized on the Vault to rotate this agent's URI. Connect the owner wallet and run "Fix Records" or re-add this operator to grant the permission.`,
224
224
  )
225
225
  }
226
226
 
227
- const result = await requestBrowserWalletSignatureAndTransaction<OperatorVaultPublishPrepared>({
227
+ const result = await requestBrowserWalletSignatureAndTransaction<VaultPublishPrepared>({
228
228
  chainId: step.registry.chainId,
229
229
  messageForAccount: account => createWalletRestoreAccessChallenge({
230
230
  token: walletAccess.token,
@@ -344,8 +344,8 @@ async function runOperatorWalletVaultPublish(args: {
344
344
  }
345
345
 
346
346
  const completionMessage = nextEnsName !== undefined && nextEnsName !== ((step.identity.state as Record<string, unknown> | undefined)?.ensName as string | undefined)
347
- ? 'Snapshot published onchain through the operator delegation vault. ENS records remain owner-signed, switch to the owner wallet to update them.'
348
- : 'Snapshot published onchain through the operator delegation vault.'
347
+ ? 'Snapshot published onchain through the Vault. ENS records remain owner-signed, switch to the owner wallet to update them.'
348
+ : 'Snapshot published onchain through the Vault.'
349
349
 
350
350
  return {
351
351
  to: vaultCall.to,
@@ -8,7 +8,7 @@ import {
8
8
  import { ensureIdentityMarkdownScaffold, writeContinuityFiles } from '../../../continuity/storage.js'
9
9
  import { recordPublishedContinuitySnapshot } from '../../../continuity/snapshots.js'
10
10
  import { requestBrowserWalletSignature } from '../../../wallet/browserWallet.js'
11
- import { setOperatorVaultAddressField } from '../../../identityCompat.js'
11
+ import { setVaultAddressField } from '../../../identityCompat.js'
12
12
  import type { Step } from '../../identityHubReducer.js'
13
13
  import type { EffectCallbacks } from '../types.js'
14
14
  import { isContinuitySnapshotEnvelope } from './envelopes.js'
@@ -76,7 +76,7 @@ export async function runRestoreAuthorize(
76
76
  ...operatorStateFromCandidate(step.candidate),
77
77
  }
78
78
  if (tokenOwnerAddress.toLowerCase() !== step.candidate.ownerAddress.toLowerCase()) {
79
- setOperatorVaultAddressField(restoredState, getAddress(tokenOwnerAddress))
79
+ setVaultAddressField(restoredState, getAddress(tokenOwnerAddress))
80
80
  }
81
81
  const nextIdentity: EthagentIdentity = {
82
82
  source: 'erc8004',
@@ -14,7 +14,7 @@ import {
14
14
  type Erc8004RegistryConfig,
15
15
  } from '../../../registry/erc8004.js'
16
16
  import { requestBrowserWalletSignature } from '../../../wallet/browserWallet.js'
17
- import { setOperatorVaultAddressField } from '../../../identityCompat.js'
17
+ import { setVaultAddressField } from '../../../identityCompat.js'
18
18
  import type { EffectCallbacks } from '../types.js'
19
19
  import { isContinuitySnapshotEnvelope, parseRestorableEnvelope } from './envelopes.js'
20
20
  import { restoreMessageForWallet } from './auth.js'
@@ -98,7 +98,7 @@ export async function runRecoveryRefetch(
98
98
  }
99
99
  const tokenOwnerAddress = candidate.tokenOwnerAddress ?? candidate.ownerAddress
100
100
  if (tokenOwnerAddress.toLowerCase() !== candidate.ownerAddress.toLowerCase()) {
101
- setOperatorVaultAddressField(refreshedState, getAddress(tokenOwnerAddress))
101
+ setVaultAddressField(refreshedState, getAddress(tokenOwnerAddress))
102
102
  }
103
103
  const nextIdentity: EthagentIdentity = {
104
104
  ...identity,
@@ -5,10 +5,10 @@ import {
5
5
  type Erc8004RegistryConfig,
6
6
  } from '../../../registry/erc8004.js'
7
7
  import {
8
- OPERATOR_VAULT_ABI,
8
+ VAULT_ABI,
9
9
  encodeSetMetadataOperator,
10
10
  readMetadataOperators,
11
- } from '../../../registry/operatorVault.js'
11
+ } from '../../../registry/vault.js'
12
12
  import {
13
13
  sendBrowserWalletTransaction,
14
14
  type WalletPurpose,
@@ -117,7 +117,7 @@ export async function syncVaultMetadataOperatorsAfterOwnerSave(args: {
117
117
  try {
118
118
  depositor = await probeClient.readContract({
119
119
  address: vaultAddress,
120
- abi: OPERATOR_VAULT_ABI,
120
+ abi: VAULT_ABI,
121
121
  functionName: 'agentOwner',
122
122
  args: [registryAddress, agentId],
123
123
  }) as Address
@@ -1,20 +1,20 @@
1
1
  import { getAddress, type Address, type PublicClient } from 'viem'
2
2
  import type { EthagentIdentity } from '../../../../storage/config.js'
3
- import { readOperatorVaultAddressField } from '../../../identityCompat.js'
3
+ import { readVaultAddressField } from '../../../identityCompat.js'
4
4
  import { createErc8004PublicClient, type Erc8004RegistryConfig } from '../../../registry/erc8004.js'
5
- import { isAgentInVault, resolveConfiguredOperatorVaultAddress } from '../../../registry/operatorVault.js'
5
+ import { isAgentInVault, resolveConfiguredVaultAddress } from '../../../registry/vault.js'
6
6
  import { readCustodyMode } from '../../model/custody.js'
7
7
 
8
- export class OperatorVaultUnavailableError extends Error {
8
+ export class VaultUnavailableError extends Error {
9
9
  constructor(chainId: number) {
10
- super(`Operator delegation vault is not deployed for chainId ${chainId}. Switching custody mode is unavailable until a deployment is recorded.`)
11
- this.name = 'OperatorVaultUnavailableError'
10
+ super(`Vault is not deployed for chainId ${chainId}. Switching custody mode is unavailable until a deployment is recorded.`)
11
+ this.name = 'VaultUnavailableError'
12
12
  }
13
13
  }
14
14
 
15
15
  export class TokenInVaultError extends Error {
16
16
  constructor(public vaultAddress: Address) {
17
- super('Token is in the operator delegation vault. Withdraw it first to prepare a transfer.')
17
+ super('Token is in the Vault. Withdraw it first to prepare a transfer.')
18
18
  this.name = 'TokenInVaultError'
19
19
  }
20
20
  }
@@ -42,9 +42,9 @@ function vaultAddressForTransferPreflight(
42
42
  identity: EthagentIdentity,
43
43
  operatorVaults?: Readonly<Record<string, string>>,
44
44
  ): Address | undefined {
45
- const identityVault = readOperatorVaultAddressField(identity.state as Record<string, unknown> | undefined)
45
+ const identityVault = readVaultAddressField(identity.state as Record<string, unknown> | undefined)
46
46
  if (identityVault) return getAddress(identityVault)
47
47
  if (readCustodyMode(identity.state as Record<string, unknown> | undefined) !== 'advanced') return undefined
48
48
  if (!identity.chainId) return undefined
49
- return resolveConfiguredOperatorVaultAddress(operatorVaults, identity.chainId)
49
+ return resolveConfiguredVaultAddress(operatorVaults, identity.chainId)
50
50
  }
@@ -128,7 +128,7 @@ export const CreateFlow: React.FC<CreateFlowProps> = ({
128
128
  { value: 'simple', role: 'section', label: 'Simple (Recommended)' },
129
129
  { value: 'simple', label: 'Simple', hint: 'One wallet owns the token, signs every save, and rotates the URI directly' },
130
130
  { value: 'advanced', role: 'section', label: 'Advanced' },
131
- { value: 'advanced', label: 'Advanced', hint: 'Operator delegation vault holds the token; owner wallet controls vault, operator wallets get URI-rotation permission' },
131
+ { value: 'advanced', label: 'Advanced', hint: 'Vault holds the token; owner wallet controls vault, operator wallets get URI-rotation permission' },
132
132
  ]}
133
133
  hintLayout="inline"
134
134
  onSubmit={onCustodySubmit}
@@ -182,7 +182,7 @@ export const CreateFlow: React.FC<CreateFlowProps> = ({
182
182
  title={isAdvanced ? 'Connect Owner Wallet' : 'Sign in Wallet'}
183
183
  subtitle={
184
184
  isAdvanced
185
- ? 'This wallet will own the agent token and control the delegation vault. Operator wallets are configured after minting.'
185
+ ? 'This wallet will own the agent token and control the Vault. Operator wallets are configured after minting.'
186
186
  : 'One browser flow signs, saves the IPFS backup, and submits the token transaction.'
187
187
  }
188
188
  walletSession={walletSession}
@@ -95,7 +95,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
95
95
  const isAdvanced = onChainCustody === 'advanced' || midFlow || custodyMode === 'advanced'
96
96
  const vaultHolds = onChainCustody === 'advanced' || midFlow
97
97
  const subtitle = midFlow
98
- ? 'Advanced setup pending. This agent vault holds your token. Finish by publishing the first onchain update.'
98
+ ? 'Advanced setup pending. This Vault holds your token. Finish by publishing the first onchain update.'
99
99
  : isAdvanced
100
100
  ? 'Advanced is active. Authorized operator wallets publish updates for this agent without an owner signature each time.'
101
101
  : 'Simple is active. One wallet owns the token and signs every update.'
@@ -106,7 +106,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
106
106
  options.push({
107
107
  value: 'resume-advanced',
108
108
  label: 'Resume Advanced Setup',
109
- hint: 'Sign once to publish onchain and finish the agent-vault switch.',
109
+ hint: 'Sign once to publish onchain and finish the Vault switch.',
110
110
  })
111
111
  options.push({
112
112
  value: 'cancel-advanced',
@@ -119,7 +119,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
119
119
  options.push({
120
120
  value: 'switch-advanced',
121
121
  label: 'Switch to Advanced',
122
- hint: 'Deposit this token into its own OperatorVault so operator wallets can publish updates onchain.',
122
+ hint: 'Deposit this token into its own Vault so operator wallets can publish updates onchain.',
123
123
  })
124
124
  } else {
125
125
  if (!midFlow) {
@@ -139,7 +139,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
139
139
  options.push({
140
140
  value: 'return-to-vault',
141
141
  label: 'Return Token to Vault',
142
- hint: 'Redeposit this token to its agent vault. No redeploy, no operator re-add.',
142
+ hint: 'Redeposit this token to its Vault. No redeploy, no operator re-add.',
143
143
  })
144
144
  }
145
145
  options.push({ value: 'manage-operator-wallets', role: 'section', label: 'Operators' })
@@ -184,7 +184,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
184
184
  })()}
185
185
  <Row label="Custody" value={modeLabel} />
186
186
  <Row label="Owner" value={shortAddress(ownerAddress || tokenOwner)} />
187
- {isAdvanced && vaultAddress ? <Row label="Agent Vault" value={shortAddress(vaultAddress)} /> : null}
187
+ {isAdvanced && vaultAddress ? <Row label="Vault" value={shortAddress(vaultAddress)} /> : null}
188
188
  {isAdvanced ? (
189
189
  <Row
190
190
  label="Operators"
@@ -251,14 +251,14 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
251
251
  return (
252
252
  <Surface
253
253
  title="Switch to Advanced"
254
- subtitle="Move this token into its own OperatorVault so authorized operator wallets can update this agent onchain without your signature each time."
254
+ subtitle="Move this token into its own Vault so authorized operator wallets can update this agent onchain without your signature each time."
255
255
  footer={footerHint('enter confirm, esc back')}
256
256
  >
257
257
  <Box flexDirection="column">
258
258
  <Row label="Token" value={tokenLabel} />
259
259
  {agentName ? <Row label="Name" value={agentName} /> : null}
260
260
  <Row label="Owner Wallet" value={shortAddress(ownerAddress || tokenOwner)} />
261
- <Text color={theme.textSubtle}>You sign once now to deposit token #{identity.agentId ?? 'unknown'} into a dedicated OperatorVault.</Text>
261
+ <Text color={theme.textSubtle}>You sign once now to deposit token #{identity.agentId ?? 'unknown'} into a dedicated Vault.</Text>
262
262
  <Text color={theme.textSubtle}>This vault can hold only this ERC-8004 token.</Text>
263
263
  <Text color={theme.textSubtle}>Other agent tokens use their own vaults.</Text>
264
264
  <Text color={theme.textSubtle}>After that, operator wallets you authorize can publish updates for this agent.</Text>
@@ -271,7 +271,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
271
271
  <Select<Action>
272
272
  options={[
273
273
  { value: 'confirm', role: 'section', label: 'Confirm' },
274
- { value: 'confirm', label: 'Yes, Switch to Advanced', hint: `Sign with ${shortAddress(ownerAddress || tokenOwner)} to deposit this token into its agent vault` },
274
+ { value: 'confirm', label: 'Yes, Switch to Advanced', hint: `Sign with ${shortAddress(ownerAddress || tokenOwner)} to deposit this token into its Vault` },
275
275
  { value: 'transfer', role: 'section', label: 'Move Token First' },
276
276
  { value: 'transfer', label: 'Prepare Token Transfer', hint: 'Move the token to a different wallet first, with snapshot handoff' },
277
277
  { value: 'back', role: 'section', label: 'Cancel' },
@@ -300,7 +300,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
300
300
  return (
301
301
  <Surface
302
302
  title="Switch to Simple"
303
- subtitle="Unwraps this ERC-8004 token from its agent vault and returns it directly to the owner wallet."
303
+ subtitle="Unwraps this ERC-8004 token from its Vault and returns it directly to the owner wallet."
304
304
  footer={footerHint('enter confirm · esc back')}
305
305
  >
306
306
  <Box flexDirection="column">
@@ -309,13 +309,13 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
309
309
  <Text> </Text>
310
310
  <Text color={theme.accentBlue}>Operators lose decrypt access on future snapshots immediately.</Text>
311
311
  <Text color={theme.textSubtle}>Operator approvals are cleared from local state for future snapshots. Revoke onchain via Manage Operators first if needed.</Text>
312
- <Text color={theme.textSubtle}>This switch calls the agent vault's unwrap function for this token, so the owner wallet must sign the transaction.</Text>
312
+ <Text color={theme.textSubtle}>This switch calls the Vault unwrap function for this token, so the owner wallet must sign the transaction.</Text>
313
313
  </Box>
314
314
  <Box marginTop={1}>
315
315
  <Select<Action>
316
316
  options={[
317
317
  { value: 'confirm', role: 'section', label: 'Confirm' },
318
- { value: 'confirm', label: 'Yes, Switch to Simple', hint: `Sign with the owner wallet to unwrap ${tokenLabel} from its agent vault` },
318
+ { value: 'confirm', label: 'Yes, Switch to Simple', hint: `Sign with the owner wallet to unwrap ${tokenLabel} from its Vault` },
319
319
  { value: 'back', role: 'section', label: 'Cancel' },
320
320
  { value: 'back', label: 'No, Go Back', hint: 'Return without changing custody', role: 'utility' },
321
321
  ]}