ethagent 2.1.0 → 2.2.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/README.md +2 -2
- package/package.json +1 -1
- package/src/auth/openaiOAuth/credentials.ts +47 -0
- package/src/auth/openaiOAuth/crypto.ts +23 -0
- package/src/auth/openaiOAuth/index.ts +238 -0
- package/src/auth/openaiOAuth/landingPage.ts +125 -0
- package/src/auth/openaiOAuth/listener.ts +151 -0
- package/src/auth/openaiOAuth/refresh.ts +70 -0
- package/src/auth/openaiOAuth/shared.ts +115 -0
- package/src/chat/chatSessionState.ts +2 -1
- package/src/chat/commands.ts +2 -1
- package/src/identity/ens/agentRecords.ts +5 -19
- package/src/identity/ens/ensAutomation/setup.ts +0 -1
- package/src/identity/ens/ensAutomation/types.ts +0 -1
- package/src/identity/hub/OperationalRoutes.tsx +2 -11
- package/src/identity/hub/components/IdentitySummary.tsx +8 -3
- package/src/identity/hub/components/MenuScreen.tsx +1 -2
- package/src/identity/hub/components/menuFlagsFromReconciliation.ts +1 -3
- package/src/identity/hub/effects/ens/transactions.ts +15 -15
- package/src/identity/hub/effects/index.ts +0 -1
- package/src/identity/hub/effects/profile/profileState.ts +12 -4
- package/src/identity/hub/effects/publicProfile/runPublicProfileSave.ts +37 -159
- package/src/identity/hub/effects/rebackup/runRebackup.ts +2 -2
- package/src/identity/hub/effects/restoreAdmin.ts +2 -61
- package/src/identity/hub/effects/shared/sync.ts +3 -44
- package/src/identity/hub/flows/custody/CustodyEditFlow.tsx +1 -39
- package/src/identity/hub/flows/custody/custodyFlowActions.ts +5 -3
- package/src/identity/hub/flows/custody/custodyFlowTypes.ts +1 -1
- package/src/identity/hub/flows/ens/EnsEditAdvancedScreens.tsx +80 -175
- package/src/identity/hub/flows/ens/EnsEditFlow.tsx +20 -75
- package/src/identity/hub/flows/ens/EnsEditMaintenanceScreens.tsx +16 -56
- package/src/identity/hub/flows/ens/EnsEditReviewScreens.tsx +0 -18
- package/src/identity/hub/flows/ens/EnsEditRunners.tsx +0 -136
- package/src/identity/hub/flows/ens/EnsEditShared.tsx +5 -4
- package/src/identity/hub/flows/ens/EnsEditSimpleScreens.tsx +56 -205
- package/src/identity/hub/flows/ens/IdentityHubEnsFlow.tsx +7 -0
- package/src/identity/hub/flows/ens/OperatorWalletsScreen.tsx +0 -31
- package/src/identity/hub/flows/ens/ensEditCopy.ts +1 -1
- package/src/identity/hub/flows/ens/ensEditTypes.ts +6 -20
- package/src/identity/hub/flows/profile/EditProfileFlow.tsx +7 -0
- package/src/identity/hub/flows/restore/RestoreFlow.tsx +5 -5
- package/src/identity/hub/reconciliation/agentReconciliation/hook.ts +0 -1
- package/src/identity/hub/reconciliation/agentReconciliation/run.ts +1 -34
- package/src/identity/hub/reconciliation/agentReconciliation/types.ts +0 -4
- package/src/identity/hub/reconciliation/index.ts +0 -7
- package/src/identity/hub/reconciliation/walletSetup.ts +1 -194
- package/src/identity/wallet/browserWallet/types.ts +0 -5
- package/src/identity/wallet/page/copy.ts +1 -31
- package/src/identity/wallet/walletPurposeCompat.ts +0 -2
- package/src/models/ModelPicker.tsx +246 -8
- package/src/models/catalog.ts +28 -1
- package/src/models/modelPickerOptions.ts +15 -1
- package/src/providers/openai-responses-format.ts +156 -0
- package/src/providers/openai-responses.ts +276 -0
- package/src/providers/registry.ts +85 -8
- package/src/runtime/systemPrompt.ts +1 -1
- package/src/runtime/turn.ts +0 -1
- package/src/storage/secrets.ts +4 -1
- package/src/tools/privateContinuityEditTool.ts +6 -0
- package/src/utils/openExternal.ts +20 -10
- package/src/identity/ens/ensRegistration.ts +0 -199
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { Box, Text } from 'ink'
|
|
3
|
-
import {
|
|
3
|
+
import { type Address } from 'viem'
|
|
4
4
|
import { Surface } from '../../../../ui/Surface.js'
|
|
5
5
|
import { Select } from '../../../../ui/Select.js'
|
|
6
6
|
import { TextInput } from '../../../../ui/TextInput.js'
|
|
@@ -12,17 +12,14 @@ import {
|
|
|
12
12
|
} from '../../../ens/ensLookup.js'
|
|
13
13
|
import { isRootEthName } from '../../../ens/ensAutomation.js'
|
|
14
14
|
import type { Erc8004RegistryConfig } from '../../../registry/erc8004.js'
|
|
15
|
-
import type { BrowserWalletReady } from '../../../wallet/browserWallet.js'
|
|
16
15
|
import {
|
|
17
16
|
type CustodyMode,
|
|
18
17
|
} from '../../model/custody.js'
|
|
19
18
|
import { shortAddress } from '../../model/format.js'
|
|
20
|
-
import { WalletApprovalScreen } from '../../components/WalletApprovalScreen.js'
|
|
21
|
-
import { advancedSubdomainStatusText } from './ensEditCopy.js'
|
|
22
19
|
import {
|
|
23
|
-
EnsSetupRow,
|
|
24
20
|
footerHint,
|
|
25
21
|
} from './EnsEditShared.js'
|
|
22
|
+
import { IdentitySummary } from '../../components/IdentitySummary.js'
|
|
26
23
|
import {
|
|
27
24
|
EnsSetupBlockedScreen,
|
|
28
25
|
EnsSetupReviewScreen,
|
|
@@ -32,109 +29,112 @@ import type {
|
|
|
32
29
|
EnsEditProps,
|
|
33
30
|
EnsPhase,
|
|
34
31
|
} from './ensEditTypes.js'
|
|
32
|
+
import type { AgentReconciliation } from '../../reconciliation/index.js'
|
|
35
33
|
|
|
36
34
|
type AdvancedScreenProps = {
|
|
37
35
|
phase: EnsPhase
|
|
36
|
+
identity: EnsEditProps['identity']
|
|
38
37
|
ownerAddress: Address
|
|
39
38
|
agentId: EnsEditProps['identity']['agentId']
|
|
40
|
-
|
|
41
|
-
savedOperator: string
|
|
42
|
-
savedRootName: string
|
|
39
|
+
reconciliation: AgentReconciliation
|
|
43
40
|
savedSubdomainLabel: string
|
|
44
41
|
agentNameSuggestion: string
|
|
45
42
|
currentEnsName: string
|
|
46
43
|
savedCustodyMode: CustodyMode | undefined
|
|
47
44
|
registry: Erc8004RegistryConfig
|
|
48
|
-
operatorWalletSession: BrowserWalletReady | null
|
|
49
45
|
setPhase: (phase: EnsPhase) => void
|
|
50
|
-
|
|
51
|
-
runAdvancedRootCheck: (rootName: string) => void
|
|
46
|
+
runDiscovery: (mode?: 'simple' | 'advanced') => void
|
|
52
47
|
runAdvancedSubdomainCheck: (rootName: string, label: string) => void
|
|
53
|
-
runAdvancedPreflight: (rootName: string, label: string, operatorWallet: Address) => void
|
|
54
48
|
onEnsSetup: EnsEditProps['onEnsSetup']
|
|
55
49
|
onEnsLink: EnsEditProps['onEnsLink']
|
|
50
|
+
onWithdrawToken: () => void
|
|
56
51
|
}
|
|
57
52
|
|
|
58
53
|
export function renderAdvancedEnsPhase({
|
|
59
54
|
phase,
|
|
55
|
+
identity,
|
|
60
56
|
ownerAddress,
|
|
61
57
|
agentId,
|
|
62
|
-
|
|
63
|
-
savedOperator,
|
|
64
|
-
savedRootName,
|
|
58
|
+
reconciliation,
|
|
65
59
|
savedSubdomainLabel,
|
|
66
60
|
agentNameSuggestion,
|
|
67
61
|
currentEnsName,
|
|
68
62
|
savedCustodyMode,
|
|
69
63
|
registry,
|
|
70
|
-
operatorWalletSession,
|
|
71
64
|
setPhase,
|
|
72
|
-
|
|
73
|
-
runAdvancedRootCheck,
|
|
65
|
+
runDiscovery,
|
|
74
66
|
runAdvancedSubdomainCheck,
|
|
75
|
-
runAdvancedPreflight,
|
|
76
67
|
onEnsSetup,
|
|
77
68
|
onEnsLink,
|
|
69
|
+
onWithdrawToken,
|
|
78
70
|
}: AdvancedScreenProps): React.ReactNode | null {
|
|
79
71
|
if (phase.kind === 'advanced-transfer-check') {
|
|
80
|
-
type TransferCheckAction = '
|
|
72
|
+
type TransferCheckAction = 'continue' | 'withdraw' | 'back'
|
|
73
|
+
const custody = reconciliation.custody
|
|
74
|
+
const tokenInVault = custody === 'advanced' || custody === 'mid-flow-uri-pending'
|
|
75
|
+
const tokenInOwnerWallet = custody === 'simple' || custody === 'withdrawn'
|
|
76
|
+
const probePending = custody === 'unknown' && reconciliation.rpc !== 'failing'
|
|
77
|
+
const probeFailed = reconciliation.rpc === 'failing'
|
|
78
|
+
|
|
79
|
+
const options: Array<{ value: TransferCheckAction; role?: 'section' | 'utility'; label: string; hint?: string }> = []
|
|
80
|
+
options.push({ value: 'continue', role: 'section', label: 'Setup' })
|
|
81
|
+
if (tokenInOwnerWallet) {
|
|
82
|
+
options.push({
|
|
83
|
+
value: 'continue',
|
|
84
|
+
label: 'Continue ENS Setup',
|
|
85
|
+
hint: 'Owner wallet holds this token onchain.',
|
|
86
|
+
})
|
|
87
|
+
} else if (tokenInVault) {
|
|
88
|
+
options.push({
|
|
89
|
+
value: 'withdraw',
|
|
90
|
+
label: 'Withdraw Token',
|
|
91
|
+
hint: 'Pull token out to sign ENS records. Redeposit to the Vault any time after.',
|
|
92
|
+
})
|
|
93
|
+
} else if (probePending) {
|
|
94
|
+
options.push({
|
|
95
|
+
value: 'continue',
|
|
96
|
+
label: 'Checking onchain state…',
|
|
97
|
+
hint: 'Try again in a moment.',
|
|
98
|
+
})
|
|
99
|
+
} else if (probeFailed) {
|
|
100
|
+
options.push({
|
|
101
|
+
value: 'continue',
|
|
102
|
+
label: 'Onchain check unavailable',
|
|
103
|
+
hint: 'RPC unreachable. Resolve connectivity, then retry.',
|
|
104
|
+
})
|
|
105
|
+
} else {
|
|
106
|
+
options.push({
|
|
107
|
+
value: 'continue',
|
|
108
|
+
label: 'Token Owner Unknown',
|
|
109
|
+
hint: 'Try again in a moment.',
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
options.push({ value: 'back', role: 'section', label: 'Navigation' })
|
|
113
|
+
options.push({ value: 'back', label: 'Back', hint: 'Return to setup type', role: 'utility' })
|
|
114
|
+
|
|
81
115
|
return (
|
|
82
116
|
<Surface
|
|
83
117
|
title="Token Custody Check"
|
|
84
|
-
subtitle="ENS setup continues only after the owner wallet holds this token."
|
|
118
|
+
subtitle="ENS setup continues only after the owner wallet holds this token onchain."
|
|
85
119
|
footer={footerHint('enter select · esc back')}
|
|
86
120
|
>
|
|
87
|
-
<Box flexDirection="column">
|
|
88
|
-
<Text color={theme.dim}>Current token owner: <Text color={theme.text}>{shortAddress(ownerAddress)}</Text></Text>
|
|
89
|
-
<Box marginTop={1} flexDirection="column">
|
|
90
|
-
<EnsSetupRow label="Owner wallet" value={`Holds ERC-8004 token #${agentId ?? 'unknown'} and signs ENS records.`} />
|
|
91
|
-
<EnsSetupRow label="Operator wallet" value="Restores snapshots; never controls the token." />
|
|
92
|
-
<EnsSetupRow label="Token moves" value="If the token is in the Vault, withdraw it first from Custody Mode." />
|
|
93
|
-
</Box>
|
|
94
|
-
</Box>
|
|
95
121
|
<Box marginTop={1}>
|
|
96
122
|
<Select<TransferCheckAction>
|
|
97
|
-
options={
|
|
98
|
-
{ value: 'skip', role: 'section', label: 'Setup' },
|
|
99
|
-
{ value: 'skip', label: 'Continue ENS Setup', hint: 'The connected wallet is already the owner wallet' },
|
|
100
|
-
{ value: 'back', role: 'section', label: 'Navigation' },
|
|
101
|
-
{ value: 'back', label: 'Back', hint: 'Return to setup type', role: 'utility' },
|
|
102
|
-
]}
|
|
123
|
+
options={options}
|
|
103
124
|
hintLayout="inline"
|
|
104
125
|
onSubmit={choice => {
|
|
105
|
-
if (choice === '
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return (
|
|
117
|
-
<Surface
|
|
118
|
-
title="Root ENS"
|
|
119
|
-
footer={footerHint('enter next · esc back')}
|
|
120
|
-
>
|
|
121
|
-
<Box flexDirection="column">
|
|
122
|
-
<Text color={theme.dim}>Enter the parent .eth name. The owner wallet must manage it and own this ERC-8004 token.</Text>
|
|
123
|
-
{savedOwnerAddress ? <Text color={theme.dim}>Saved owner wallet: <Text color={theme.text}>{shortAddress(savedOwnerAddress)}</Text></Text> : null}
|
|
124
|
-
{phase.error ? <Text color={theme.accentError}>{phase.error}</Text> : null}
|
|
125
|
-
</Box>
|
|
126
|
-
<Box marginTop={1}>
|
|
127
|
-
<TextInput
|
|
128
|
-
key="advanced-root"
|
|
129
|
-
initialValue={phase.rootName || savedRootName}
|
|
130
|
-
placeholder="name.eth"
|
|
131
|
-
validate={value => {
|
|
132
|
-
const root = normalizeEthDomain(value)
|
|
133
|
-
if (!root) return 'Enter a parent .eth name'
|
|
134
|
-
if (!isRootEthName(root)) return 'Enter the parent .eth name, e.g. name.eth'
|
|
135
|
-
return null
|
|
126
|
+
if (choice === 'withdraw') {
|
|
127
|
+
onWithdrawToken()
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
if (choice === 'continue' && tokenInOwnerWallet) {
|
|
131
|
+
runDiscovery('advanced')
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
if (choice === 'back') {
|
|
135
|
+
return setPhase({ kind: 'mode-select' })
|
|
136
|
+
}
|
|
136
137
|
}}
|
|
137
|
-
onSubmit={value => runAdvancedRootCheck(normalizeEthDomain(value))}
|
|
138
138
|
onCancel={() => setPhase({ kind: 'mode-select' })}
|
|
139
139
|
/>
|
|
140
140
|
</Box>
|
|
@@ -161,18 +161,19 @@ export function renderAdvancedEnsPhase({
|
|
|
161
161
|
return (
|
|
162
162
|
<Surface
|
|
163
163
|
title="Agent Subdomain"
|
|
164
|
+
subtitle={`Pick a subdomain label under ${rootName}.`}
|
|
164
165
|
footer={footerHint('enter next · esc back')}
|
|
165
166
|
>
|
|
166
|
-
|
|
167
|
-
<
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
{phase.error ? (
|
|
168
|
+
<Box flexDirection="column">
|
|
169
|
+
<Text color={theme.accentError}>{phase.error}</Text>
|
|
170
|
+
</Box>
|
|
171
|
+
) : null}
|
|
171
172
|
<Box marginTop={1}>
|
|
172
173
|
<TextInput
|
|
173
174
|
key={`advanced-subdomain-${rootName}`}
|
|
174
|
-
initialValue={phase.label || savedSubdomainLabel ||
|
|
175
|
-
placeholder=
|
|
175
|
+
initialValue={phase.label || savedSubdomainLabel || ''}
|
|
176
|
+
placeholder={agentNameSuggestion || 'agent-name'}
|
|
176
177
|
validate={value => {
|
|
177
178
|
const trimmed = value.trim()
|
|
178
179
|
const label = sanitizeSubdomainPrefix(trimmed)
|
|
@@ -182,7 +183,7 @@ export function renderAdvancedEnsPhase({
|
|
|
182
183
|
return null
|
|
183
184
|
}}
|
|
184
185
|
onSubmit={value => runAdvancedSubdomainCheck(rootName, sanitizeSubdomainPrefix(value))}
|
|
185
|
-
onCancel={() => setPhase({ kind: '
|
|
186
|
+
onCancel={() => setPhase({ kind: 'pick-parent', mode: 'advanced' })}
|
|
186
187
|
/>
|
|
187
188
|
</Box>
|
|
188
189
|
</Surface>
|
|
@@ -193,12 +194,9 @@ export function renderAdvancedEnsPhase({
|
|
|
193
194
|
return (
|
|
194
195
|
<Surface
|
|
195
196
|
title="Check Agent Subdomain"
|
|
197
|
+
subtitle={`Verifying ${phase.label}.${phase.rootName} on Ethereum Mainnet.`}
|
|
196
198
|
footer={footerHint('esc back')}
|
|
197
199
|
>
|
|
198
|
-
<Box flexDirection="column">
|
|
199
|
-
<Text color={theme.dim}>Agent ENS: <Text color={theme.text}>{phase.label}.{phase.rootName}</Text></Text>
|
|
200
|
-
<Text color={theme.dim}>Checking whether the subdomain is ready or needs the owner wallet to create it.</Text>
|
|
201
|
-
</Box>
|
|
202
200
|
<Box marginTop={1}>
|
|
203
201
|
<Spinner label="checking agent subdomain..." />
|
|
204
202
|
</Box>
|
|
@@ -207,98 +205,6 @@ export function renderAdvancedEnsPhase({
|
|
|
207
205
|
)
|
|
208
206
|
}
|
|
209
207
|
|
|
210
|
-
if (phase.kind === 'advanced-operator-wallet') {
|
|
211
|
-
const { rootName, label } = phase
|
|
212
|
-
return (
|
|
213
|
-
<Surface
|
|
214
|
-
title="Operator Wallet"
|
|
215
|
-
footer={footerHint('enter select · esc back')}
|
|
216
|
-
>
|
|
217
|
-
<Box flexDirection="column">
|
|
218
|
-
<Text color={theme.dim}>Agent ENS: <Text color={theme.text}>{label}.{rootName}</Text></Text>
|
|
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 Vault.</Text>
|
|
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
|
-
<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
|
-
{savedOperator ? <Text color={theme.dim}>Saved operator wallet: <Text color={theme.text}>{shortAddress(savedOperator)}</Text></Text> : null}
|
|
224
|
-
{phase.error ? <Text color={theme.accentError}>{phase.error}</Text> : null}
|
|
225
|
-
</Box>
|
|
226
|
-
<Box marginTop={1}>
|
|
227
|
-
<Select<'connect' | 'enter' | 'back'>
|
|
228
|
-
options={[
|
|
229
|
-
{ value: 'connect', role: 'section', label: 'Operator Wallet' },
|
|
230
|
-
{ value: 'connect', label: 'Connect Wallet', hint: 'Connect the wallet that will be the operator' },
|
|
231
|
-
{ value: 'enter', label: 'Enter Wallet Address', hint: 'Paste the operator wallet address' },
|
|
232
|
-
{ value: 'back', role: 'section', label: 'Navigation' },
|
|
233
|
-
{ value: 'back', label: 'Back', hint: 'Return to subdomain', role: 'utility' },
|
|
234
|
-
]}
|
|
235
|
-
hintLayout="inline"
|
|
236
|
-
onSubmit={choice => {
|
|
237
|
-
if (choice === 'connect') return connectOperatorWallet(rootName, label)
|
|
238
|
-
if (choice === 'enter') return setPhase({ kind: 'advanced-operator-wallet-manual', rootName, label })
|
|
239
|
-
return setPhase({ kind: 'advanced-subdomain', rootName, label })
|
|
240
|
-
}}
|
|
241
|
-
onCancel={() => setPhase({ kind: 'advanced-subdomain', rootName, label })}
|
|
242
|
-
/>
|
|
243
|
-
</Box>
|
|
244
|
-
</Surface>
|
|
245
|
-
)
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (phase.kind === 'advanced-operator-wallet-manual') {
|
|
249
|
-
const { rootName, label } = phase
|
|
250
|
-
return (
|
|
251
|
-
<Surface
|
|
252
|
-
title="Operator Wallet"
|
|
253
|
-
footer={footerHint('enter next · esc back')}
|
|
254
|
-
>
|
|
255
|
-
<Box flexDirection="column">
|
|
256
|
-
<Text color={theme.dim}>The operator wallet is saved in ERC-8004 metadata for lookup and restore access.</Text>
|
|
257
|
-
<Text color={theme.dim}>It gets no token approval or transfer right.</Text>
|
|
258
|
-
<Text color={theme.dim}>Owner wallet signs the ENS and ERC-8004 transactions after this address is checked.</Text>
|
|
259
|
-
<Text color={theme.dim}>Any future token move still starts with Prepare Token Transfer.</Text>
|
|
260
|
-
{phase.error ? <Text color={theme.accentError}>{phase.error}</Text> : null}
|
|
261
|
-
</Box>
|
|
262
|
-
<Box marginTop={1}>
|
|
263
|
-
<TextInput
|
|
264
|
-
key="advanced-operator-wallet-manual"
|
|
265
|
-
initialValue={savedOperator}
|
|
266
|
-
placeholder="0x..."
|
|
267
|
-
validate={value => /^0x[0-9a-fA-F]{40}$/.test(value.trim()) ? null : 'enter a valid 0x address'}
|
|
268
|
-
onSubmit={value => runAdvancedPreflight(rootName, label, getAddress(value.trim()))}
|
|
269
|
-
onCancel={() => setPhase({ kind: 'advanced-operator-wallet', rootName, label })}
|
|
270
|
-
/>
|
|
271
|
-
</Box>
|
|
272
|
-
</Surface>
|
|
273
|
-
)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (phase.kind === 'advanced-operator-wallet-connecting') {
|
|
277
|
-
return (
|
|
278
|
-
<WalletApprovalScreen
|
|
279
|
-
title="Connect Wallet"
|
|
280
|
-
subtitle="Connect the operator wallet only to read its address for ERC-8004 metadata. It does not sign or submit a transaction."
|
|
281
|
-
walletSession={operatorWalletSession}
|
|
282
|
-
label="waiting for wallet connection..."
|
|
283
|
-
onCancel={() => setPhase({ kind: 'advanced-operator-wallet', rootName: phase.rootName, label: phase.label })}
|
|
284
|
-
/>
|
|
285
|
-
)
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (phase.kind === 'advanced-preflight') {
|
|
289
|
-
return (
|
|
290
|
-
<Surface
|
|
291
|
-
title="Check ENS Setup"
|
|
292
|
-
footer={footerHint('esc back')}
|
|
293
|
-
>
|
|
294
|
-
<Box marginTop={1}>
|
|
295
|
-
<Spinner label="checking ens setup..." />
|
|
296
|
-
</Box>
|
|
297
|
-
<EscCancel onCancel={() => setPhase({ kind: 'advanced-operator-wallet', rootName: phase.rootName, label: phase.label })} />
|
|
298
|
-
</Surface>
|
|
299
|
-
)
|
|
300
|
-
}
|
|
301
|
-
|
|
302
208
|
if (phase.kind === 'advanced-review') {
|
|
303
209
|
return (
|
|
304
210
|
<EnsSetupReviewScreen
|
|
@@ -314,10 +220,9 @@ export function renderAdvancedEnsPhase({
|
|
|
314
220
|
onEnsLink(phase.setup.fullName, {
|
|
315
221
|
mode: 'advanced',
|
|
316
222
|
ownerAddress: phase.setup.ownerAddress,
|
|
317
|
-
operatorWallet: phase.setup.operatorAddress,
|
|
318
223
|
})
|
|
319
224
|
}}
|
|
320
|
-
onBack={() => setPhase({ kind: 'advanced-
|
|
225
|
+
onBack={() => setPhase({ kind: 'advanced-subdomain', rootName: phase.setup.rootName, label: phase.setup.label })}
|
|
321
226
|
/>
|
|
322
227
|
)
|
|
323
228
|
}
|
|
@@ -326,8 +231,8 @@ export function renderAdvancedEnsPhase({
|
|
|
326
231
|
return (
|
|
327
232
|
<EnsSetupBlockedScreen
|
|
328
233
|
fallback={phase.fallback}
|
|
329
|
-
onCheckAgain={() =>
|
|
330
|
-
onBack={() => setPhase({ kind: 'advanced-
|
|
234
|
+
onCheckAgain={() => runAdvancedSubdomainCheck(phase.fallback.rootName, phase.fallback.label)}
|
|
235
|
+
onBack={() => setPhase({ kind: 'advanced-subdomain', rootName: phase.fallback.rootName, label: phase.fallback.label })}
|
|
331
236
|
/>
|
|
332
237
|
)
|
|
333
238
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { getAddress, type Address } from 'viem'
|
|
3
3
|
import type { BrowserWalletReady } from '../../../wallet/browserWallet.js'
|
|
4
|
-
import { requestBrowserWalletAccount } from '../../../wallet/browserWallet.js'
|
|
5
4
|
import {
|
|
6
5
|
AGENT_RECORD_READ_KEY_LIST,
|
|
7
6
|
buildAgentEnsRecords,
|
|
@@ -45,11 +44,13 @@ export type { EnsLinkOptions }
|
|
|
45
44
|
export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
46
45
|
identity,
|
|
47
46
|
registry,
|
|
47
|
+
reconciliation,
|
|
48
48
|
onEnsLink,
|
|
49
49
|
onEnsUnlink,
|
|
50
50
|
onEnsRecordsUpdate,
|
|
51
51
|
onEnsSetup,
|
|
52
52
|
onManageOperatorWalletAccess,
|
|
53
|
+
onWithdrawToken,
|
|
53
54
|
initialView,
|
|
54
55
|
onBack,
|
|
55
56
|
}) => {
|
|
@@ -59,7 +60,6 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
59
60
|
const savedRootName = currentEnsParts?.parent ?? ''
|
|
60
61
|
const savedSubdomainLabel = currentEnsParts?.label ?? ''
|
|
61
62
|
const agentNameSuggestion = sanitizeSubdomainPrefix(readIdentityStateString(identity.state, 'name'))
|
|
62
|
-
const agentCardCid = identity.publicSkills?.agentCardCid
|
|
63
63
|
const savedCustodyMode = readCustodyMode(identity.state)
|
|
64
64
|
const savedOwnerAddress = readIdentityStateString(identity.state, 'ownerAddress')
|
|
65
65
|
const savedOperator = readIdentityStateString(identity.state, 'activeOperatorAddress')
|
|
@@ -76,13 +76,13 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
76
76
|
const [operatorWalletSession, setOperatorWalletSession] = React.useState<BrowserWalletReady | null>(null)
|
|
77
77
|
const discoveryControllerRef = React.useRef<AbortController | null>(null)
|
|
78
78
|
|
|
79
|
-
const runDiscovery = React.useCallback(() => {
|
|
79
|
+
const runDiscovery = React.useCallback((targetMode: 'simple' | 'advanced' = 'simple') => {
|
|
80
80
|
discoveryControllerRef.current?.abort()
|
|
81
81
|
const controller = new AbortController()
|
|
82
82
|
discoveryControllerRef.current = controller
|
|
83
83
|
setDiscovery({ status: 'loading' })
|
|
84
84
|
setDiscoveryStartedAt(Date.now())
|
|
85
|
-
setPhase({ kind: 'discovering' })
|
|
85
|
+
setPhase({ kind: 'discovering', mode: targetMode })
|
|
86
86
|
discoverOwnedEnsNameDetails(ownerAddress, {
|
|
87
87
|
signal: controller.signal,
|
|
88
88
|
budgetMs: 30_000,
|
|
@@ -93,7 +93,7 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
93
93
|
if (discoveryControllerRef.current === controller) discoveryControllerRef.current = null
|
|
94
94
|
if (result.status === 'error') {
|
|
95
95
|
setDiscovery({ status: 'error', message: discoveryErrorMessage(result.errors), names: [] })
|
|
96
|
-
setPhase({ kind: 'pick-parent' })
|
|
96
|
+
setPhase({ kind: 'pick-parent', mode: targetMode })
|
|
97
97
|
return
|
|
98
98
|
}
|
|
99
99
|
setDiscovery({
|
|
@@ -101,13 +101,13 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
101
101
|
names: result.names,
|
|
102
102
|
...(result.status === 'partial' ? { warning: 'Some ENS lookup sources failed; showing root names found so far.' } : {}),
|
|
103
103
|
})
|
|
104
|
-
setPhase({ kind: 'pick-parent' })
|
|
104
|
+
setPhase({ kind: 'pick-parent', mode: targetMode })
|
|
105
105
|
})
|
|
106
106
|
.catch((err: unknown) => {
|
|
107
107
|
if (controller.signal.aborted) return
|
|
108
108
|
if (discoveryControllerRef.current === controller) discoveryControllerRef.current = null
|
|
109
109
|
setDiscovery({ status: 'error', message: err instanceof Error ? err.message : String(err), names: [] })
|
|
110
|
-
setPhase({ kind: 'pick-parent' })
|
|
110
|
+
setPhase({ kind: 'pick-parent', mode: targetMode })
|
|
111
111
|
})
|
|
112
112
|
}, [ownerAddress])
|
|
113
113
|
|
|
@@ -145,7 +145,6 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
145
145
|
chainId: registry.chainId,
|
|
146
146
|
identityRegistryAddress: registry.identityRegistryAddress,
|
|
147
147
|
agentId: identity.agentId,
|
|
148
|
-
agentCardCid,
|
|
149
148
|
})
|
|
150
149
|
const recordsDiff = diffRecords(current, next)
|
|
151
150
|
if (mode === 'simple' && !validation.ok && validation.reason === 'no-owner') {
|
|
@@ -157,36 +156,7 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
157
156
|
setValidationError(err instanceof Error ? err.message : String(err))
|
|
158
157
|
setPhase({ kind: 'pick-parent' })
|
|
159
158
|
}
|
|
160
|
-
}, [ownerAddress, registry, identity.agentId
|
|
161
|
-
|
|
162
|
-
const runAdvancedPreflight = React.useCallback((
|
|
163
|
-
rootName: string,
|
|
164
|
-
label: string,
|
|
165
|
-
operatorWallet: Address,
|
|
166
|
-
): void => {
|
|
167
|
-
setPhase({ kind: 'advanced-preflight', rootName, label, operatorWallet })
|
|
168
|
-
preflightEnsSetup({
|
|
169
|
-
rootName,
|
|
170
|
-
label,
|
|
171
|
-
operatorAddress: operatorWallet,
|
|
172
|
-
registry,
|
|
173
|
-
agentId: identity.agentId,
|
|
174
|
-
agentCardCid,
|
|
175
|
-
}).then(result => {
|
|
176
|
-
if (result.ok) {
|
|
177
|
-
setPhase({ kind: 'advanced-review', setup: result.setup })
|
|
178
|
-
return
|
|
179
|
-
}
|
|
180
|
-
setPhase({ kind: 'advanced-manual', fallback: result.fallback })
|
|
181
|
-
}).catch((err: unknown) => {
|
|
182
|
-
setPhase({
|
|
183
|
-
kind: 'advanced-operator-wallet',
|
|
184
|
-
rootName,
|
|
185
|
-
label,
|
|
186
|
-
error: err instanceof Error ? err.message : String(err),
|
|
187
|
-
})
|
|
188
|
-
})
|
|
189
|
-
}, [agentCardCid, identity.agentId, registry])
|
|
159
|
+
}, [ownerAddress, registry, identity.agentId])
|
|
190
160
|
|
|
191
161
|
const runAdvancedRootCheck = React.useCallback((rootName: string): void => {
|
|
192
162
|
setPhase({ kind: 'advanced-root-check', rootName })
|
|
@@ -197,12 +167,12 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
197
167
|
agentId: identity.agentId,
|
|
198
168
|
}).then(result => {
|
|
199
169
|
if (result.ok) {
|
|
200
|
-
setPhase({ kind: 'advanced-subdomain', rootName, label: savedSubdomainLabel
|
|
170
|
+
setPhase({ kind: 'advanced-subdomain', rootName, label: savedSubdomainLabel })
|
|
201
171
|
return
|
|
202
172
|
}
|
|
203
|
-
setPhase({ kind: '
|
|
173
|
+
setPhase({ kind: 'pick-parent', mode: 'advanced', error: rootErrorMessage(result.reason, result.detail, rootName) })
|
|
204
174
|
}).catch((err: unknown) => {
|
|
205
|
-
setPhase({ kind: '
|
|
175
|
+
setPhase({ kind: 'pick-parent', mode: 'advanced', error: err instanceof Error ? err.message : String(err) })
|
|
206
176
|
})
|
|
207
177
|
}, [agentNameSuggestion, identity.agentId, ownerAddress, registry, savedSubdomainLabel])
|
|
208
178
|
|
|
@@ -215,15 +185,9 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
215
185
|
allowSameOwnerOperator: true,
|
|
216
186
|
registry,
|
|
217
187
|
agentId: identity.agentId,
|
|
218
|
-
agentCardCid,
|
|
219
188
|
}).then(result => {
|
|
220
189
|
if (result.ok) {
|
|
221
|
-
setPhase({
|
|
222
|
-
kind: 'advanced-operator-wallet',
|
|
223
|
-
rootName: result.setup.rootName,
|
|
224
|
-
label: result.setup.label,
|
|
225
|
-
registryAction: result.setup.registryAction,
|
|
226
|
-
})
|
|
190
|
+
setPhase({ kind: 'advanced-review', setup: result.setup })
|
|
227
191
|
return
|
|
228
192
|
}
|
|
229
193
|
setPhase({ kind: 'advanced-manual', fallback: result.fallback })
|
|
@@ -235,7 +199,7 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
235
199
|
error: err instanceof Error ? err.message : String(err),
|
|
236
200
|
})
|
|
237
201
|
})
|
|
238
|
-
}, [
|
|
202
|
+
}, [identity.agentId, ownerAddress, registry])
|
|
239
203
|
|
|
240
204
|
const runSimpleCreatePreflight = React.useCallback((fullName: string): void => {
|
|
241
205
|
const parts = splitSubdomainName(fullName)
|
|
@@ -253,7 +217,6 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
253
217
|
allowSameOwnerOperator: true,
|
|
254
218
|
registry,
|
|
255
219
|
agentId: identity.agentId,
|
|
256
|
-
agentCardCid,
|
|
257
220
|
}).then(result => {
|
|
258
221
|
if (result.ok) {
|
|
259
222
|
setPhase({ kind: 'simple-create-review', setup: result.setup })
|
|
@@ -268,23 +231,7 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
268
231
|
error: err instanceof Error ? err.message : String(err),
|
|
269
232
|
})
|
|
270
233
|
})
|
|
271
|
-
}, [
|
|
272
|
-
|
|
273
|
-
const connectOperatorWallet = React.useCallback((rootName: string, label: string): void => {
|
|
274
|
-
setOperatorWalletSession(null)
|
|
275
|
-
setPhase({ kind: 'advanced-operator-wallet-connecting', rootName, label })
|
|
276
|
-
requestBrowserWalletAccount({
|
|
277
|
-
purpose: 'connect-operator-wallet',
|
|
278
|
-
onReady: ready => setOperatorWalletSession(ready),
|
|
279
|
-
}).then(wallet => {
|
|
280
|
-
const operatorWallet = getAddress(wallet.account)
|
|
281
|
-
setOperatorWalletSession(null)
|
|
282
|
-
runAdvancedPreflight(rootName, label, operatorWallet)
|
|
283
|
-
}).catch((err: unknown) => {
|
|
284
|
-
setOperatorWalletSession(null)
|
|
285
|
-
setPhase({ kind: 'advanced-operator-wallet', rootName, label, error: err instanceof Error ? err.message : String(err) })
|
|
286
|
-
})
|
|
287
|
-
}, [runAdvancedPreflight])
|
|
234
|
+
}, [identity.agentId, ownerAddress, registry])
|
|
288
235
|
|
|
289
236
|
const runDeleteSubdomainPreflight = React.useCallback((fullName: string): void => {
|
|
290
237
|
setValidationError(null)
|
|
@@ -323,6 +270,7 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
323
270
|
|
|
324
271
|
const maintenanceScreen = renderEnsMaintenancePhase({
|
|
325
272
|
phase,
|
|
273
|
+
identity,
|
|
326
274
|
currentEnsName,
|
|
327
275
|
currentEnsCanDelete: Boolean(currentEnsParts),
|
|
328
276
|
savedCustodyMode,
|
|
@@ -340,30 +288,26 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
340
288
|
onBack,
|
|
341
289
|
onEnsUnlink,
|
|
342
290
|
onEnsRecordsUpdate,
|
|
343
|
-
onManageOperatorWalletAccess,
|
|
344
291
|
})
|
|
345
292
|
if (maintenanceScreen) return maintenanceScreen
|
|
346
293
|
|
|
347
294
|
const advancedScreen = renderAdvancedEnsPhase({
|
|
348
295
|
phase,
|
|
296
|
+
identity,
|
|
349
297
|
ownerAddress,
|
|
350
298
|
agentId: identity.agentId,
|
|
351
|
-
|
|
352
|
-
savedOperator,
|
|
353
|
-
savedRootName,
|
|
299
|
+
reconciliation,
|
|
354
300
|
savedSubdomainLabel,
|
|
355
301
|
agentNameSuggestion,
|
|
356
302
|
currentEnsName,
|
|
357
303
|
savedCustodyMode,
|
|
358
304
|
registry,
|
|
359
|
-
operatorWalletSession,
|
|
360
305
|
setPhase,
|
|
361
|
-
|
|
362
|
-
runAdvancedRootCheck,
|
|
306
|
+
runDiscovery,
|
|
363
307
|
runAdvancedSubdomainCheck,
|
|
364
|
-
runAdvancedPreflight,
|
|
365
308
|
onEnsSetup,
|
|
366
309
|
onEnsLink,
|
|
310
|
+
onWithdrawToken,
|
|
367
311
|
})
|
|
368
312
|
if (advancedScreen) return advancedScreen
|
|
369
313
|
|
|
@@ -384,6 +328,7 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
384
328
|
cancelDiscoveryToModeSelect,
|
|
385
329
|
runDiscovery,
|
|
386
330
|
runValidation,
|
|
331
|
+
runAdvancedRootCheck,
|
|
387
332
|
backToSimpleSubdomain,
|
|
388
333
|
runSimpleCreatePreflight,
|
|
389
334
|
onEnsSetup,
|