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
@@ -4,32 +4,32 @@ import {
4
4
  encodeDepositAgent,
5
5
  encodeUnwrapAgent,
6
6
  isAgentInVault,
7
- resolveConfiguredOperatorVaultAddress,
8
- OPERATOR_VAULT_ABI,
9
- OPERATOR_VAULT_DEPLOY_BYTECODE,
7
+ resolveConfiguredVaultAddress,
8
+ VAULT_ABI,
9
+ VAULT_DEPLOY_BYTECODE,
10
10
  assertVaultBytecode,
11
- } from '../../../registry/operatorVault.js'
11
+ } from '../../../registry/vault.js'
12
12
  import {
13
13
  createErc8004PublicClient,
14
14
  type Erc8004RegistryConfig,
15
15
  } from '../../../registry/erc8004.js'
16
16
  import type { EthagentIdentity } from '../../../../storage/config.js'
17
- import { readOperatorVaultAddressField, readOwnerAddressField } from '../../../identityCompat.js'
17
+ import { readVaultAddressField, readOwnerAddressField } from '../../../identityCompat.js'
18
18
  import { prepareTransactionGasFee, sendBrowserWalletTransaction } from '../../../wallet/browserWallet.js'
19
19
  import { acquireTxGuard, releaseTxGuard, type TxGuardKind } from '../../txGuard.js'
20
20
  import { awaitConfirmedReceipt } from '../../effects/receipts.js'
21
21
  import type { EffectCallbacks } from '../../effects/types.js'
22
22
  import { readCustodyMode } from '../../model/custody.js'
23
23
 
24
- export function resolveOperatorVaultAddress(
24
+ export function resolveVaultAddress(
25
25
  identity: EthagentIdentity,
26
26
  operatorVaults?: Readonly<Record<string, string>>,
27
27
  ): Address | undefined {
28
- const identityVault = readOperatorVaultAddressField(identity.state as Record<string, unknown> | undefined)
28
+ const identityVault = readVaultAddressField(identity.state as Record<string, unknown> | undefined)
29
29
  if (identityVault) return getAddress(identityVault)
30
30
  if (readCustodyMode(identity.state as Record<string, unknown> | undefined) !== 'advanced') return undefined
31
31
  if (!identity.chainId) return undefined
32
- return resolveConfiguredOperatorVaultAddress(operatorVaults, identity.chainId)
32
+ return resolveConfiguredVaultAddress(operatorVaults, identity.chainId)
33
33
  }
34
34
 
35
35
  async function withTxGuard<T>(kind: TxGuardKind, fn: () => Promise<T>): Promise<T> {
@@ -63,8 +63,8 @@ async function runVaultDeployTransactionInner(args: {
63
63
  const walletAddress = getAddress(args.walletAddress)
64
64
  const registryAddress = getAddress(args.registry.identityRegistryAddress)
65
65
  const deployData = encodeDeployData({
66
- abi: OPERATOR_VAULT_ABI,
67
- bytecode: OPERATOR_VAULT_DEPLOY_BYTECODE,
66
+ abi: VAULT_ABI,
67
+ bytecode: VAULT_DEPLOY_BYTECODE,
68
68
  args: [registryAddress, args.agentId],
69
69
  })
70
70
  const gasFeeClient = createErc8004PublicClient(args.registry)
@@ -86,9 +86,9 @@ async function runVaultDeployTransactionInner(args: {
86
86
  })
87
87
  args.callbacks.onWalletReady(null)
88
88
  const client = args.publicClient ?? createErc8004PublicClient(args.registry)
89
- const receipt = await awaitConfirmedReceipt(client, result.txHash, 'Operator delegation vault deploy', { kind: 'vault-deploy', chainId: args.registry.chainId })
89
+ const receipt = await awaitConfirmedReceipt(client, result.txHash, 'Vault deploy', { kind: 'vault-deploy', chainId: args.registry.chainId })
90
90
  if (!receipt.contractAddress) {
91
- throw new Error('Operator delegation vault deploy receipt is missing contractAddress; the transaction was not a contract creation')
91
+ throw new Error('Vault deploy receipt is missing contractAddress; the transaction was not a contract creation')
92
92
  }
93
93
  const vaultAddress = getAddress(receipt.contractAddress)
94
94
  await assertVaultBytecode(client, vaultAddress, result.txHash)
@@ -114,7 +114,7 @@ async function runVaultDepositTransactionInner(args: {
114
114
  }): Promise<{ txHash: string }> {
115
115
  const { identity, registry, vaultAddress } = args
116
116
  if (!identity.agentId) {
117
- throw new Error('Cannot deposit token to operator delegation vault: agent token ID is missing')
117
+ throw new Error('Cannot deposit token to Vault: agent token ID is missing')
118
118
  }
119
119
  const tokenOwner = getAddress(identity.ownerAddress ?? identity.address)
120
120
  await assertVaultCanAcceptAgent({
@@ -152,7 +152,7 @@ async function runVaultDepositTransactionInner(args: {
152
152
  await awaitConfirmedReceipt(
153
153
  depositClient,
154
154
  result.txHash as Hex,
155
- 'Operator delegation vault deposit',
155
+ 'Vault deposit',
156
156
  { kind: 'vault-deposit', chainId: registry.chainId },
157
157
  )
158
158
  return { txHash: result.txHash }
@@ -168,7 +168,7 @@ async function assertVaultCanAcceptAgent(args: {
168
168
  try {
169
169
  held = await client.readContract({
170
170
  address: getAddress(args.vaultAddress),
171
- abi: OPERATOR_VAULT_ABI,
171
+ abi: VAULT_ABI,
172
172
  functionName: 'heldAgent',
173
173
  }) as readonly [Address, bigint, Address]
174
174
  } catch {
@@ -179,9 +179,9 @@ async function assertVaultCanAcceptAgent(args: {
179
179
  const expectedRegistry = getAddress(args.registry.identityRegistryAddress)
180
180
  const sameAgent = heldRegistry.toLowerCase() === expectedRegistry.toLowerCase() && heldAgentId === args.agentId
181
181
  if (sameAgent) {
182
- throw new Error(`Agent vault ${getAddress(args.vaultAddress)} already holds ERC-8004 token #${args.agentId.toString()}. Publish the pending update instead of depositing again.`)
182
+ throw new Error(`Vault ${getAddress(args.vaultAddress)} already holds ERC-8004 token #${args.agentId.toString()}. Publish the pending update instead of depositing again.`)
183
183
  }
184
- throw new Error(`Agent vault ${getAddress(args.vaultAddress)} already holds ERC-8004 token #${heldAgentId.toString()} for registry ${getAddress(heldRegistry)}. Deploy a fresh vault for this agent.`)
184
+ throw new Error(`Vault ${getAddress(args.vaultAddress)} already holds ERC-8004 token #${heldAgentId.toString()} for registry ${getAddress(heldRegistry)}. Deploy a fresh vault for this agent.`)
185
185
  }
186
186
 
187
187
  export async function runVaultUnwrapTransaction(args: {
@@ -206,7 +206,7 @@ async function runVaultUnwrapTransactionInner(args: {
206
206
  const { identity, registry, vaultAddress } = args
207
207
  const targetAgentId = args.agentId ?? (identity.agentId ? BigInt(identity.agentId) : undefined)
208
208
  if (targetAgentId === undefined) {
209
- throw new Error('Cannot unwrap token from operator delegation vault: agent token ID is missing')
209
+ throw new Error('Cannot unwrap token from Vault: agent token ID is missing')
210
210
  }
211
211
  const baseState = (identity.state ?? {}) as Record<string, unknown>
212
212
  const ownerAddressRaw = readOwnerAddressField(baseState)
@@ -240,7 +240,7 @@ async function runVaultUnwrapTransactionInner(args: {
240
240
  await awaitConfirmedReceipt(
241
241
  publicClient,
242
242
  result.txHash as Hex,
243
- 'Operator delegation vault unwrap',
243
+ 'Vault unwrap',
244
244
  { kind: 'vault-unwrap', chainId: registry.chainId },
245
245
  )
246
246
  await confirmAgentWithdrawnFromVault({
@@ -307,7 +307,7 @@ async function runVaultWithdrawTransactionInner(args: {
307
307
  await awaitConfirmedReceipt(
308
308
  publicClient,
309
309
  result.txHash as Hex,
310
- 'Operator delegation vault withdraw',
310
+ 'Vault withdraw',
311
311
  { kind: 'vault-withdraw', chainId: registry.chainId },
312
312
  )
313
313
  await confirmAgentWithdrawnFromVault({
@@ -1,9 +1,9 @@
1
1
  import type { Address } from 'viem'
2
2
  import { createErc8004PublicClient } from '../../../registry/erc8004.js'
3
- import { discoverPriorVaultFromTokenOwner, isAgentInVault } from '../../../registry/operatorVault.js'
3
+ import { discoverPriorVaultFromTokenOwner, isAgentInVault } from '../../../registry/vault.js'
4
4
  import type { ProfileUpdates, Step } from '../../identityHubReducer.js'
5
5
  import { isCustodyEditStep } from './CustodyEditFlow.js'
6
- import { resolveOperatorVaultAddress } from './custodyEffects.js'
6
+ import { resolveVaultAddress } from './custodyEffects.js'
7
7
  import type { CustodyFlowDeps } from './custodyFlowTypes.js'
8
8
  import { humanOwnerAddress } from './custodyFlowHelpers.js'
9
9
 
@@ -21,7 +21,7 @@ export function createCustodyFlowActions({
21
21
  } {
22
22
  const beginVaultDeposit = (currentStep: Step, returnTo: Step, profileUpdates: ProfileUpdates): void => {
23
23
  if (!isCustodyEditStep(currentStep) || currentStep.kind !== 'custody-advanced-confirm') return
24
- const vaultAddress = resolveOperatorVaultAddress(currentStep.identity, config?.erc8004?.operatorVaults)
24
+ const vaultAddress = resolveVaultAddress(currentStep.identity, config?.erc8004?.operatorVaults)
25
25
  const expectedOwnerForDiscovery = humanOwnerAddress(currentStep.identity)
26
26
  if (!vaultAddress) {
27
27
  const registry = currentStep.registry
@@ -49,7 +49,7 @@ export function createCustodyFlowActions({
49
49
  }
50
50
  if (status.inVault) {
51
51
  handleStepError(
52
- new Error(`Recovered operator delegation vault ${recoveredVault} holds the token, but the vault-level depositor is ${status.ownerAddress ?? 'unknown'}, not your wallet ${expectedOwnerForDiscovery}. Mid-flow recovery requires the original depositor's wallet to call vault.unwrap.`),
52
+ new Error(`Recovered Vault ${recoveredVault} holds the token, but the vault-level depositor is ${status.ownerAddress ?? 'unknown'}, not your wallet ${expectedOwnerForDiscovery}. Mid-flow recovery requires the original depositor's wallet to call vault.unwrap.`),
53
53
  { kind: 'custody-model', identity: currentStep.identity, registry, returnTo },
54
54
  )
55
55
  return
@@ -95,7 +95,7 @@ export function createCustodyFlowActions({
95
95
  }
96
96
  if (status.inVault) {
97
97
  handleStepError(
98
- new Error(`Token is held by the operator delegation vault, but the vault-level owner is ${status.ownerAddress ?? 'unknown'}, not your wallet ${expectedOwner}. Recovery requires that wallet to call vault.unwrap.`),
98
+ new Error(`Token is held by the Vault, but the vault-level owner is ${status.ownerAddress ?? 'unknown'}, not your wallet ${expectedOwner}. Recovery requires that wallet to call vault.unwrap.`),
99
99
  { kind: 'custody-model', identity: currentStep.identity, registry, returnTo },
100
100
  )
101
101
  return
@@ -124,10 +124,10 @@ export function createCustodyFlowActions({
124
124
 
125
125
  const beginWithdrawToken = (currentStep: Step, returnTo: Step): void => {
126
126
  if (!isCustodyEditStep(currentStep)) return
127
- const vaultAddress = resolveOperatorVaultAddress(currentStep.identity, config?.erc8004?.operatorVaults)
127
+ const vaultAddress = resolveVaultAddress(currentStep.identity, config?.erc8004?.operatorVaults)
128
128
  if (!vaultAddress) {
129
129
  handleStepError(
130
- new Error('No agent vault is recorded for this identity. There is nothing to withdraw.'),
130
+ new Error('No Vault is recorded for this identity. There is nothing to withdraw.'),
131
131
  { kind: 'custody-model', identity: currentStep.identity, registry: currentStep.registry, returnTo },
132
132
  )
133
133
  return
@@ -160,7 +160,7 @@ export function createCustodyFlowActions({
160
160
  if (status.inVault) {
161
161
  if (status.ownerAddress && status.ownerAddress.toLowerCase() !== depositor.toLowerCase()) {
162
162
  handleStepError(
163
- new Error(`Agent vault holds token #${activeAgentId} but recorded the depositor as ${status.ownerAddress}, not your wallet ${depositor}. Only the original depositor can withdraw.`),
163
+ new Error(`Vault holds token #${activeAgentId} but recorded the depositor as ${status.ownerAddress}, not your wallet ${depositor}. Only the original depositor can withdraw.`),
164
164
  { kind: 'custody-model', identity: currentStep.identity, registry: currentStep.registry, returnTo },
165
165
  )
166
166
  return
@@ -176,7 +176,7 @@ export function createCustodyFlowActions({
176
176
  return
177
177
  }
178
178
  handleStepError(
179
- new Error(`Token #${activeAgentId} is not currently in the agent vault. There is nothing to withdraw; the token is already with the owner wallet.`),
179
+ new Error(`Token #${activeAgentId} is not currently in the Vault. There is nothing to withdraw; the token is already with the owner wallet.`),
180
180
  { kind: 'custody-model', identity: currentStep.identity, registry: currentStep.registry, returnTo },
181
181
  )
182
182
  } catch (err: unknown) {
@@ -187,7 +187,7 @@ export function createCustodyFlowActions({
187
187
 
188
188
  const beginVaultUnwrap = (currentStep: Step, returnTo: Step, profileUpdates: ProfileUpdates): void => {
189
189
  if (!isCustodyEditStep(currentStep) || currentStep.kind !== 'custody-simple-confirm') return
190
- const vaultAddress = resolveOperatorVaultAddress(currentStep.identity, config?.erc8004?.operatorVaults)
190
+ const vaultAddress = resolveVaultAddress(currentStep.identity, config?.erc8004?.operatorVaults)
191
191
  if (!vaultAddress) {
192
192
  triggerRebackup(returnTo, profileUpdates, { useVault: false })
193
193
  return
@@ -1,6 +1,6 @@
1
1
  import { useEffect } from 'react'
2
2
  import { createErc8004PublicClient } from '../../../registry/erc8004.js'
3
- import { confirmAgentInVault } from '../../../registry/operatorVault.js'
3
+ import { confirmAgentInVault } from '../../../registry/vault.js'
4
4
  import { invalidateOwnershipCache } from '../../reconciliation/index.js'
5
5
  import type { ProfileUpdates } from '../../identityHubReducer.js'
6
6
  import type { CustodyFlowDeps } from './custodyFlowTypes.js'
@@ -25,7 +25,7 @@ export function useCustodyTransactionEffects({
25
25
  let cancelled = false
26
26
  if (!step.identity.agentId) {
27
27
  handleStepError(
28
- new Error('Cannot deploy agent vault: agent token ID is missing'),
28
+ new Error('Cannot deploy Vault: agent token ID is missing'),
29
29
  { kind: 'custody-model', identity: step.identity, registry: step.registry, returnTo: step.returnTo },
30
30
  )
31
31
  return () => { cancelled = true }
@@ -24,8 +24,8 @@ export function renderCustodyStep({
24
24
  if (step.kind === 'custody-vault-deploy-tx') {
25
25
  return (
26
26
  <WalletApprovalScreen
27
- title="Deploy Operator Delegation Vault"
28
- subtitle={`Deploying a dedicated OperatorVault for this ERC-8004 token on ${chainLabel(step.registry.chainId)}.`}
27
+ title="Deploy Vault"
28
+ subtitle={`Deploying a dedicated Vault for this ERC-8004 token on ${chainLabel(step.registry.chainId)}.`}
29
29
  walletSession={walletSession}
30
30
  label="waiting for owner wallet transaction..."
31
31
  onCancel={() => setStep({ kind: 'custody-model', identity: step.identity, registry: step.registry, returnTo: step.returnTo })}
@@ -35,8 +35,8 @@ export function renderCustodyStep({
35
35
  if (step.kind === 'custody-vault-deposit-tx') {
36
36
  return (
37
37
  <WalletApprovalScreen
38
- title="Deposit Token Into Operator Delegation Vault"
39
- subtitle={`Sign one ${chainLabel(step.registry.chainId)} transaction. Sends ERC-8004 token #${step.identity.agentId ?? ''} to its agent vault.`}
38
+ title="Deposit Token Into Vault"
39
+ subtitle={`Sign one ${chainLabel(step.registry.chainId)} transaction. Sends ERC-8004 token #${step.identity.agentId ?? ''} to its Vault.`}
40
40
  walletSession={walletSession}
41
41
  label="waiting for token-owner wallet transaction..."
42
42
  onCancel={() => setStep({ kind: 'custody-model', identity: step.identity, registry: step.registry, returnTo: step.returnTo })}
@@ -49,8 +49,8 @@ export function renderCustodyStep({
49
49
  <Surface
50
50
  title="Checking Vault"
51
51
  subtitle={targetAgentId
52
- ? `Confirming the agent vault holds ERC-8004 token #${targetAgentId} on ${chainLabel(step.registry.chainId)}.`
53
- : `Checking this identity's recorded agent vault on ${chainLabel(step.registry.chainId)}.`}
52
+ ? `Confirming the Vault holds ERC-8004 token #${targetAgentId} on ${chainLabel(step.registry.chainId)}.`
53
+ : `Checking this identity's recorded Vault on ${chainLabel(step.registry.chainId)}.`}
54
54
  footer={<Text color={theme.dim}>esc cancel</Text>}
55
55
  >
56
56
  <Box marginTop={1}>
@@ -64,7 +64,7 @@ export function renderCustodyStep({
64
64
  return (
65
65
  <WalletApprovalScreen
66
66
  title="Withdraw Token"
67
- subtitle={`Unwraps ERC-8004 token #${targetAgentId} from its agent vault to your owner wallet on ${chainLabel(step.registry.chainId)}.`}
67
+ subtitle={`Unwraps ERC-8004 token #${targetAgentId} from its Vault to your owner wallet on ${chainLabel(step.registry.chainId)}.`}
68
68
  walletSession={walletSession}
69
69
  label="waiting for owner wallet transaction..."
70
70
  onCancel={() => setStep({ kind: 'custody-model', identity: step.identity, registry: step.registry, returnTo: step.returnTo })}
@@ -135,7 +135,7 @@ export function renderCustodyStep({
135
135
  return (
136
136
  <Surface
137
137
  title="Token Returned to Owner Wallet"
138
- subtitle={`Token returned to ${shortAddress(step.recipient)} on ${chainLabel(step.registry.chainId)}. The agent vault can be reused for this token.`}
138
+ subtitle={`Token returned to ${shortAddress(step.recipient)} on ${chainLabel(step.registry.chainId)}. The Vault can be reused for this token.`}
139
139
  footer={<Text color={theme.dim}>enter select · esc back</Text>}
140
140
  >
141
141
  <Box flexDirection="column">
@@ -149,7 +149,7 @@ export function renderCustodyStep({
149
149
  <Select<'return-to-vault' | 'keep-out'>
150
150
  options={[
151
151
  { value: 'return-to-vault', role: 'section', label: 'Resume Advanced Custody' },
152
- { value: 'return-to-vault', label: 'Return Token to Vault', hint: 'Redeposit to this agent vault. No redeploy, no operator re-add' },
152
+ { value: 'return-to-vault', label: 'Return Token to Vault', hint: 'Redeposit to this Vault. No redeploy, no operator re-add' },
153
153
  { value: 'keep-out', role: 'section', label: 'Later' },
154
154
  { value: 'keep-out', label: 'Keep Out For Now', hint: 'Token stays with the owner wallet; redeposit any time from Custody Mode', role: 'utility' },
155
155
  ]}
@@ -167,8 +167,8 @@ export function renderCustodyStep({
167
167
  if (step.kind === 'custody-vault-unwrap-tx') {
168
168
  return (
169
169
  <WalletApprovalScreen
170
- title="Unwrap Token From Agent Vault"
171
- subtitle={`Sign one ${chainLabel(step.registry.chainId)} transaction. Calls the agent vault's unwrap function to return ERC-8004 token #${step.identity.agentId ?? ''} to the owner wallet.`}
170
+ title="Unwrap Token From Vault"
171
+ subtitle={`Sign one ${chainLabel(step.registry.chainId)} transaction. Calls the Vault unwrap function to return ERC-8004 token #${step.identity.agentId ?? ''} to the owner wallet.`}
172
172
  walletSession={walletSession}
173
173
  label="waiting for owner wallet transaction..."
174
174
  onCancel={() => setStep({ kind: 'custody-model', identity: step.identity, registry: step.registry, returnTo: step.returnTo })}
@@ -182,11 +182,11 @@ export function renderCustodyStep({
182
182
  return (
183
183
  <Surface
184
184
  title="Advanced Custody Active"
185
- subtitle="Your token is held in its own OperatorVault. Authorized operator wallets can rotate the agent URI onchain without owner signatures."
185
+ subtitle="Your token is held in its own Vault. Authorized operator wallets can rotate the agent URI onchain without owner signatures."
186
186
  footer={<Text color={theme.dim}>enter continues</Text>}
187
187
  >
188
188
  <Box flexDirection="column">
189
- {step.vaultAddress ? <Row label="Agent Vault" value={shortAddress(step.vaultAddress)} /> : null}
189
+ {step.vaultAddress ? <Row label="Vault" value={shortAddress(step.vaultAddress)} /> : null}
190
190
  <Row label="Owner Wallet" value={shortAddress(ownerWallet)} />
191
191
  <Row label="Operator Wallets" value={operatorCount === 1 ? '1 approved' : `${operatorCount} approved`} />
192
192
  <Box marginTop={1}>
@@ -235,5 +235,5 @@ export function renderRebackupSubtitle(
235
235
  vaultRouted: boolean,
236
236
  ): React.ReactNode {
237
237
  if (!vaultRouted) return defaultSubtitle
238
- return <Text color={theme.textSubtle}>{defaultSubtitle} Routed through this token's agent vault.</Text>
238
+ return <Text color={theme.textSubtle}>{defaultSubtitle} Routed through this token's Vault.</Text>
239
239
  }
@@ -89,7 +89,7 @@ export function renderAdvancedEnsPhase({
89
89
  <Box marginTop={1} flexDirection="column">
90
90
  <EnsSetupRow label="Owner wallet" value={`Holds ERC-8004 token #${agentId ?? 'unknown'} and signs ENS records.`} />
91
91
  <EnsSetupRow label="Operator wallet" value="Restores snapshots; never controls the token." />
92
- <EnsSetupRow label="Token moves" value="If the token is in the operator delegation vault, withdraw it first from Custody Mode." />
92
+ <EnsSetupRow label="Token moves" value="If the token is in the Vault, withdraw it first from Custody Mode." />
93
93
  </Box>
94
94
  </Box>
95
95
  <Box marginTop={1}>
@@ -217,7 +217,7 @@ export function renderAdvancedEnsPhase({
217
217
  <Box flexDirection="column">
218
218
  <Text color={theme.dim}>Agent ENS: <Text color={theme.text}>{label}.{rootName}</Text></Text>
219
219
  {phase.registryAction ? <Text color={theme.dim}>{advancedSubdomainStatusText(phase.registryAction)}</Text> : null}
220
- <Text color={theme.dim}>Choose the operator wallet for snapshot restore access and onchain ERC-8004 URI rotation via the operator delegation vault.</Text>
220
+ <Text color={theme.dim}>Choose the operator wallet for snapshot restore access and onchain ERC-8004 URI rotation via the Vault.</Text>
221
221
  <Text color={theme.dim}>The operator wallet has no authority over this ENS subdomain or any token transfer; the owner wallet is the sole signer for both.</Text>
222
222
  <Text color={theme.dim}>We only read the operator's address here so it can be added to the snapshot envelope and vault operator list later.</Text>
223
223
  {savedOperator ? <Text color={theme.dim}>Saved operator wallet: <Text color={theme.text}>{shortAddress(savedOperator)}</Text></Text> : null}
@@ -218,9 +218,9 @@ export const EnsSetupBlockedScreen: React.FC<EnsSetupBlockedScreenProps> = ({
218
218
  ? (
219
219
  <>
220
220
  <Box marginTop={1} flexDirection="column">
221
- <Text color={theme.text}>To proceed: the owner wallet signs ENS records and must hold this token at setup time. Once setup is done you can deposit the token into the operator delegation vault while the ENS subdomain stays with the owner wallet.</Text>
221
+ <Text color={theme.text}>To proceed: the owner wallet signs ENS records and must hold this token at setup time. Once setup is done you can deposit the token into the Vault while the ENS subdomain stays with the owner wallet.</Text>
222
222
  </Box>
223
- <Text color={theme.dim}>Operator wallets have no authority on this name; they only rotate the onchain ERC-8004 URI via the operator delegation vault.</Text>
223
+ <Text color={theme.dim}>Operator wallets have no authority on this name; they only rotate the onchain ERC-8004 URI via the Vault.</Text>
224
224
  </>
225
225
  )
226
226
  : null}
@@ -21,7 +21,7 @@ export function copyableIdentityFields(identity?: EthagentIdentity, config?: Eth
21
21
  const custodyMode = readCustodyMode(identity.state)
22
22
  if (custodyMode === 'advanced') {
23
23
  const vaultAddress = readIdentityStateString(identity.state, 'operatorVaultAddress')
24
- if (vaultAddress) fields.push({ label: 'Agent Vault', value: vaultAddress })
24
+ if (vaultAddress) fields.push({ label: 'Vault', value: vaultAddress })
25
25
  }
26
26
  const activeOperator = readIdentityStateString(identity.state, 'activeOperatorAddress')
27
27
  if (activeOperator) fields.push({ label: 'Operator Wallet', value: activeOperator })
@@ -6,9 +6,9 @@ import {
6
6
  ContinuityTransferSnapshotTargetMismatchError,
7
7
  } from '../../continuity/envelope.js'
8
8
  import {
9
- OperatorVaultBytecodeMismatchError,
10
- formatOperatorVaultBytecodeMismatchDetail,
11
- } from '../../registry/operatorVault.js'
9
+ VaultBytecodeMismatchError,
10
+ formatVaultBytecodeMismatchDetail,
11
+ } from '../../registry/vault.js'
12
12
  import { BrowserWalletError } from '../../wallet/browserWallet.js'
13
13
  import { TxGuardBusyError } from '../txGuard.js'
14
14
  import { shortAddress } from './format.js'
@@ -65,11 +65,11 @@ export function identityHubErrorView(err: unknown): IdentityHubErrorView {
65
65
  hint: `Prepare a new transfer snapshot from ${shortAddress(err.snapshotOwner)} to the intended receiver wallet.`,
66
66
  }
67
67
  }
68
- if (err instanceof OperatorVaultBytecodeMismatchError) {
68
+ if (err instanceof VaultBytecodeMismatchError) {
69
69
  return {
70
70
  title: 'Vault Bytecode Mismatch',
71
- detail: formatOperatorVaultBytecodeMismatchDetail(err),
72
- hint: 'Open the deploy tx on the block explorer and confirm the input data matches the OperatorVault deploy bytecode plus constructor args before retrying. A persistent mismatch usually means the wallet or RPC substituted the create.',
71
+ detail: formatVaultBytecodeMismatchDetail(err),
72
+ hint: 'Open the deploy tx on the block explorer and confirm the input data matches the Vault deploy bytecode plus constructor args before retrying. A persistent mismatch usually means the wallet or RPC substituted the create.',
73
73
  }
74
74
  }
75
75
  if (err instanceof BrowserWalletError) {
@@ -85,7 +85,7 @@ async function runOwnershipPreflight(args: {
85
85
  return {
86
86
  ok: false,
87
87
  reason: 'not-owned',
88
- detail: `Token is held by the operator delegation vault (${directOwner.owner}). Withdraw it first.`,
88
+ detail: `Token is held by the Vault (${directOwner.owner}). Withdraw it first.`,
89
89
  onChainOwner: directOwner.owner,
90
90
  }
91
91
  }
@@ -5,9 +5,9 @@ import {
5
5
  validateErc8004TokenOwner,
6
6
  type Erc8004RegistryConfig,
7
7
  } from '../../../registry/erc8004.js'
8
- import { isAgentInVault, resolveConfiguredOperatorVaultAddress } from '../../../registry/operatorVault.js'
8
+ import { isAgentInVault, resolveConfiguredVaultAddress } from '../../../registry/vault.js'
9
9
  import type { EthagentConfig, EthagentIdentity } from '../../../../storage/config.js'
10
- import { readOperatorVaultAddressField } from '../../../identityCompat.js'
10
+ import { readVaultAddressField } from '../../../identityCompat.js'
11
11
  import { reconcileWalletSetup, type RecordsFixPlan } from '../walletSetup.js'
12
12
  import { readCustodyMode } from '../../model/custody.js'
13
13
  import { continuityWorkingTreeStatus, type ContinuityWorkingTreeStatus } from '../../../continuity/storage.js'
@@ -115,11 +115,11 @@ function resolveReconciliationVaultAddress(
115
115
  identity: EthagentIdentity,
116
116
  operatorVaults?: Readonly<Record<string, string>>,
117
117
  ): Address | undefined {
118
- const identityVault = readOperatorVaultAddressField(identity.state as Record<string, unknown> | undefined)
118
+ const identityVault = readVaultAddressField(identity.state as Record<string, unknown> | undefined)
119
119
  if (identityVault) return getAddress(identityVault)
120
120
  if (readCustodyMode(identity.state as Record<string, unknown> | undefined) !== 'advanced') return undefined
121
121
  if (!identity.chainId) return undefined
122
- return resolveConfiguredOperatorVaultAddress(operatorVaults, identity.chainId)
122
+ return resolveConfiguredVaultAddress(operatorVaults, identity.chainId)
123
123
  }
124
124
 
125
125
  type TokenProbe =
@@ -24,7 +24,7 @@ import type {
24
24
  RestoreProgress,
25
25
  TokenTransferProgress,
26
26
  } from './effects/types.js'
27
- import { resolveOperatorVaultAddress } from './flows/custody/custodyEffects.js'
27
+ import { resolveVaultAddress } from './flows/custody/custodyEffects.js'
28
28
  import { useCustodyFlow } from './flows/custody/useCustodyFlow.js'
29
29
  import { identityHubErrorView } from './model/errors.js'
30
30
  import { readCustodyMode } from './model/custody.js'
@@ -242,7 +242,7 @@ export function useIdentityHubController({
242
242
  }
243
243
  const vaultAddress = options?.useVault === false
244
244
  ? undefined
245
- : options?.vaultAddress ?? resolveOperatorVaultAddress(identity, config?.erc8004?.operatorVaults)
245
+ : options?.vaultAddress ?? resolveVaultAddress(identity, config?.erc8004?.operatorVaults)
246
246
  ;(async () => {
247
247
  const role: 'token-holder' | 'vault-level-owner' = vaultAddress ? 'vault-level-owner' : 'token-holder'
248
248
  const allowed = await guardOwnership(identity, registry, role, backStep)
@@ -260,7 +260,7 @@ export function useIdentityHubController({
260
260
  return
261
261
  }
262
262
  ;(async () => {
263
- const vaultAddress = resolveOperatorVaultAddress(identity, config?.erc8004?.operatorVaults)
263
+ const vaultAddress = resolveVaultAddress(identity, config?.erc8004?.operatorVaults)
264
264
  const allowed = await guardOwnership(identity, registry, 'vault-level-owner', backStep)
265
265
  if (!allowed) return
266
266
  runPublicProfilePreflight(identity, registry, callbacks, profileUpdates, backStep, vaultAddress)
@@ -17,15 +17,15 @@ export function clearOwnerAddressField(target: Record<string, unknown>): void {
17
17
  delete target[LEGACY_OWNER_ADDRESS_KEY]
18
18
  }
19
19
 
20
- export function readOperatorVaultAddressField(input: Record<string, unknown> | null | undefined): string | undefined {
20
+ export function readVaultAddressField(input: Record<string, unknown> | null | undefined): string | undefined {
21
21
  return stringValue(input?.[OPERATOR_VAULT_ADDRESS_KEY])
22
22
  }
23
23
 
24
- export function setOperatorVaultAddressField(target: Record<string, unknown>, value: string): void {
24
+ export function setVaultAddressField(target: Record<string, unknown>, value: string): void {
25
25
  target[OPERATOR_VAULT_ADDRESS_KEY] = value
26
26
  }
27
27
 
28
- export function clearOperatorVaultAddressField(target: Record<string, unknown>): void {
28
+ export function clearVaultAddressField(target: Record<string, unknown>): void {
29
29
  delete target[OPERATOR_VAULT_ADDRESS_KEY]
30
30
  }
31
31
 
@@ -1,7 +1,7 @@
1
1
  import { getAddress, isAddress, type Address, type PublicClient } from 'viem'
2
2
  import { mainnet } from 'viem/chains'
3
3
  import { DEFAULT_IPFS_API_URL } from '../../storage/ipfs.js'
4
- import { isAgentInVault } from '../operatorVault.js'
4
+ import { isAgentInVault } from '../vault.js'
5
5
  import { ERC8004_ABI, TRANSFER_EVENT } from './abi.js'
6
6
  import {
7
7
  SUPPORTED_ERC8004_CHAINS,
@@ -1,5 +1,5 @@
1
1
  import { getAddress, type Address, type PublicClient } from 'viem'
2
- import { OPERATOR_VAULT_ABI } from '../operatorVault.js'
2
+ import { VAULT_ABI } from '../vault.js'
3
3
  import { ERC8004_ABI } from './abi.js'
4
4
  import { createErc8004PublicClient } from './client.js'
5
5
  import type { Erc8004RegistryConfig } from './types.js'
@@ -54,7 +54,7 @@ export async function validateErc8004TokenOwner(args: Erc8004RegistryConfig & {
54
54
  return {
55
55
  ok: false,
56
56
  reason: 'token-owner-lookup-failed',
57
- detail: `ERC-8004 token #${args.agentId.toString()} is still reported at the operator delegation vault, but that vault record is empty. Ownership is still settling; retry shortly.`,
57
+ detail: `ERC-8004 token #${args.agentId.toString()} is still reported at the Vault, but that vault record is empty. Ownership is still settling; retry shortly.`,
58
58
  }
59
59
  }
60
60
  if (vaultOwnerResult.kind === 'error') {
@@ -73,7 +73,7 @@ export async function validateErc8004TokenOwner(args: Erc8004RegistryConfig & {
73
73
  ok: false,
74
74
  reason: 'token-owner-mismatch',
75
75
  ownerAddress: vaultOwner,
76
- detail: `ERC-8004 token #${args.agentId.toString()} is held by the operator delegation vault for ${vaultOwner}`,
76
+ detail: `ERC-8004 token #${args.agentId.toString()} is held by the Vault for ${vaultOwner}`,
77
77
  }
78
78
  }
79
79
  return {
@@ -98,7 +98,7 @@ async function readVaultLevelOwner(args: Erc8004RegistryConfig & {
98
98
  const client = args.publicClient ?? createErc8004PublicClient(args)
99
99
  const vaultOwner = await client.readContract({
100
100
  address: args.vaultAddress,
101
- abi: OPERATOR_VAULT_ABI,
101
+ abi: VAULT_ABI,
102
102
  functionName: 'agentOwner',
103
103
  args: [args.identityRegistryAddress, args.agentId],
104
104
  }) as Address
@@ -1,7 +1,7 @@
1
1
  import { getAddress, keccak256, type Address, type Hex, type PublicClient } from 'viem'
2
- import { OPERATOR_VAULT_RUNTIME_BYTECODE, OPERATOR_VAULT_RUNTIME_BYTECODE_HASH } from './constants.js'
2
+ import { VAULT_RUNTIME_BYTECODE, VAULT_RUNTIME_BYTECODE_HASH } from './constants.js'
3
3
 
4
- export class OperatorVaultBytecodeMismatchError extends Error {
4
+ export class VaultBytecodeMismatchError extends Error {
5
5
  readonly vaultAddress: Address
6
6
  readonly observedHash: Hex | null
7
7
  readonly observedLength: number
@@ -15,22 +15,22 @@ export class OperatorVaultBytecodeMismatchError extends Error {
15
15
  txHash?: Hex,
16
16
  ) {
17
17
  super(
18
- 'Deployed contract bytecode does not match the expected operator delegation vault. The deploy transaction may have been intercepted.',
18
+ 'Deployed contract bytecode does not match the expected Vault. The deploy transaction may have been intercepted.',
19
19
  )
20
- this.name = 'OperatorVaultBytecodeMismatchError'
20
+ this.name = 'VaultBytecodeMismatchError'
21
21
  this.vaultAddress = vaultAddress
22
22
  this.observedHash = observedHash
23
23
  this.observedLength = observedLength
24
- this.expectedHash = OPERATOR_VAULT_RUNTIME_BYTECODE_HASH
25
- this.expectedLength = (OPERATOR_VAULT_RUNTIME_BYTECODE.length - 2) / 2
24
+ this.expectedHash = VAULT_RUNTIME_BYTECODE_HASH
25
+ this.expectedLength = (VAULT_RUNTIME_BYTECODE.length - 2) / 2
26
26
  if (txHash) this.txHash = txHash
27
27
  }
28
28
  }
29
29
 
30
30
  export type AssertVaultBytecodeClient = Pick<PublicClient, 'getBytecode'>
31
31
 
32
- export const OPERATOR_VAULT_POLL_MAX_ATTEMPTS = 5
33
- export const OPERATOR_VAULT_POLL_DELAY_MS = 1500
32
+ export const VAULT_POLL_MAX_ATTEMPTS = 5
33
+ export const VAULT_POLL_DELAY_MS = 1500
34
34
  export function delayMs(ms: number): Promise<void> {
35
35
  return new Promise(resolve => setTimeout(resolve, ms))
36
36
  }
@@ -41,8 +41,8 @@ async function readVaultBytecodeWithPoll(
41
41
  ): Promise<Hex | undefined> {
42
42
  let lastErr: unknown
43
43
  let lastCode: Hex | undefined
44
- for (let attempt = 0; attempt < OPERATOR_VAULT_POLL_MAX_ATTEMPTS; attempt++) {
45
- if (attempt > 0) await delayMs(OPERATOR_VAULT_POLL_DELAY_MS)
44
+ for (let attempt = 0; attempt < VAULT_POLL_MAX_ATTEMPTS; attempt++) {
45
+ if (attempt > 0) await delayMs(VAULT_POLL_DELAY_MS)
46
46
  try {
47
47
  const code = await client.getBytecode({ address })
48
48
  lastErr = undefined
@@ -66,13 +66,13 @@ export async function assertVaultBytecode(
66
66
  const address = getAddress(vaultAddress)
67
67
  const code = await readVaultBytecodeWithPoll(client, address)
68
68
  if (!code || code === '0x') {
69
- throw new OperatorVaultBytecodeMismatchError(address, null, 0, txHash)
69
+ throw new VaultBytecodeMismatchError(address, null, 0, txHash)
70
70
  }
71
71
  const observedLength = (code.length - 2) / 2
72
72
  const observed = keccak256(code).toLowerCase() as Hex
73
- const expected = OPERATOR_VAULT_RUNTIME_BYTECODE_HASH.toLowerCase() as Hex
73
+ const expected = VAULT_RUNTIME_BYTECODE_HASH.toLowerCase() as Hex
74
74
  if (observed !== expected) {
75
- throw new OperatorVaultBytecodeMismatchError(address, observed, observedLength, txHash)
75
+ throw new VaultBytecodeMismatchError(address, observed, observedLength, txHash)
76
76
  }
77
77
  }
78
78
 
@@ -80,8 +80,8 @@ function shortHash(hash: Hex): string {
80
80
  return `${hash.slice(0, 18)}...${hash.slice(-6)}`
81
81
  }
82
82
 
83
- export function formatOperatorVaultBytecodeMismatchDetail(
84
- err: OperatorVaultBytecodeMismatchError,
83
+ export function formatVaultBytecodeMismatchDetail(
84
+ err: VaultBytecodeMismatchError,
85
85
  ): string {
86
86
  const lines = [
87
87
  `Vault address: ${err.vaultAddress}`,