You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: workspace/BOOTSTRAP.md
+86-74Lines changed: 86 additions & 74 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,19 +13,27 @@ There is no memory yet on a totally fresh deploy. That's normal: `memory/` and m
13
13
14
14
## Helper: locate the Pinata Platform CLI
15
15
16
-
Phases 0, 1, and 2 use the bundled Pinata Platform skill to attach secrets and restart. Find it once at the top of any session that needs it:
16
+
Phase 0 uses the bundled Pinata Platform skill to attach secrets and restart. Find it once at the top of any session that needs it:
17
17
18
18
```bash
19
19
PINATA_CLI=$(find skills -path '*pinata*platform*/cli.mjs'2>/dev/null | head -1)
20
20
```
21
21
22
22
If `PINATA_CLI` is empty, the skill didn't mount. Tell the user, point at `manifest.json` → `skills`, and stop.
23
23
24
-
## Phase 0 — Auto-provision the OpenSea API key
24
+
## Phase 0 — Provision all secrets in one restart
25
+
26
+
**Skip if:** all of `OPENSEA_API_KEY`, `PRIVY_APP_ID`, `PRIVY_APP_SECRET`, `PRIVY_WALLET_ID`, `PRIVY_AUTH_SIGNING_KEY` are set.
27
+
28
+
This phase batches every secret-attach into a single Pinata restart. Each `restart` ends the conversation and forces a cold resume, so the goal here is to make the user paste their Privy credentials exactly once, do all the auto-provisioning in the same shell session using inline env, then attach everything and restart together.
29
+
30
+
Walk through 0a–0d in order. Each sub-step has its own skip check so partial state from a previous attempt resumes cleanly.
31
+
32
+
### 0a — OPENSEA_API_KEY
25
33
26
34
**Skip if:**`OPENSEA_API_KEY` is set.
27
35
28
-
Otherwise:
36
+
Otherwise auto-fetch a free-tier instant key:
29
37
30
38
```bash
31
39
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST https://api.opensea.io/api/v2/auth/keys)
@@ -37,139 +45,143 @@ if [ "$STATUS" = "429" ]; then
> "I've fetched a free-tier OpenSea API key and attached it. Restarting now — I'll come back as a fresh session (no chat memory) and pick up from `IDENTITY.md` + env."
Stop. The conversation ends here; you'll resume cold and the env will have `OPENSEA_API_KEY`.
52
+
Hold the value in the shell var. Don't `--attach` yet — that happens at the end of the phase in 0d.
57
53
58
-
##Phase 1 — Collect Privy app credentials
54
+
### 0b — PRIVY_APP_ID + PRIVY_APP_SECRET
59
55
60
56
**Skip if:** both `PRIVY_APP_ID` and `PRIVY_APP_SECRET` are set.
61
57
62
-
Otherwise, ask the user:
63
-
64
-
> "I need a Privy application before I can create your wallet. Create one at https://dashboard.privy.io (free tier is fine), then either paste your App ID and App Secret here and I'll attach them, or add them via Pinata's env UI yourself and restart."
> "I need a Privy application before I can create your wallet. Create one at https://dashboard.privy.io (free tier is fine), then paste your **App ID** and **App Secret** here. I'll create the wallet, generate my own signer, and attach all the secrets in a single batch — only one restart at the end of this phase."
73
61
74
-
Stop. The agent comes back as a fresh session and resumes at Phase 2.
62
+
When the user pastes them, capture into shell vars (`PRIVY_APP_ID=...`, `PRIVY_APP_SECRET=...`). Do not echo `PRIVY_APP_SECRET` back to chat or to logs.
75
63
76
-
If the user adds them via PinataUI directly, ask them to restart from the UI — same outcome.
64
+
If the user prefers to add them via Pinata's env UI directly, ask them to do that and restart from the UI. After restart, this sub-step will see them in env and skip.
77
65
78
-
##Phase 2 — Auto-provision wallet ID + additional_signer keypair
66
+
### 0c — Wallet ID + additional_signer keypair
79
67
80
68
**Skip if:** both `PRIVY_WALLET_ID` and `PRIVY_AUTH_SIGNING_KEY` are set.
Capture `privateKey` (PKCS8 base64) and `publicKey` (SPKI base64) from the output. Do **not** echo `privateKey` to the chat or to logs — pass it directly to Pinata in the next step.
80
+
Do **not** echo `PRIVY_AUTH_SIGNING_KEY` to chat or logs.
91
81
92
-
Create the wallet without an owner (it will be hardened in Phase 3):
82
+
Create the wallet without an owner (it will be hardened in Phase 1). Pass the Privy creds **inline** as subprocess env so this works in the same shell session that just collected them — no restart needed before the call:
Capture the wallet `id` from the output. The CLI will print a loud `WARNING: created without --owner-public-key` to stderr — that's expected; we register the owner in the off-machine ceremony in Phase 3. The brief unhardened window between wallet creation and owner registration is acceptable because the wallet has zero balance and no policy attached during this window — there is nothing to lose if the credentials in env were misused. Phase 3 refuses to advance to any signing-capable step until owner gating is verified.
99
-
100
-
Attach both secrets:
91
+
The CLI will print a loud `WARNING: created without --owner-public-key` to stderr — that's expected; we register the owner and attach the spend policy together in the off-machine ceremony in Phase 1. The brief unhardened window between wallet creation and that ceremony is acceptable because the wallet has zero balance and no policy attached during this window — there is nothing to lose if the credentials in env were misused. Phase 1 refuses to advance until owner gating AND policy are both confirmed.
If `opensea wallet create` fails with an auth error, the Privy credentials the user pasted are wrong. Tell the user, ask them to recheck the dashboard, and re-collect 0b. **Don't proceed to 0d** with bad creds — you'd attach them, restart, and discover the failure cold next session.
106
94
107
95
Record in `IDENTITY.md` under `## Wallet`:
108
96
109
-
-`Address: <address>`
110
-
-`Wallet ID: <id>`
111
-
-`Additional-signer pubkey (SPKI base64): <publicKey>` — Phase 3 needs to re-show this to the user across restarts.
97
+
-`Address: <WALLET_ADDRESS>`
98
+
-`Wallet ID: <PRIVY_WALLET_ID>`
99
+
-`Additional-signer pubkey (SPKI base64): <ADDITIONAL_SIGNER_PUBKEY>` — Phase 1 needs to re-show this to the user across restarts.
112
100
-`hardening_status: pending_owner_registration`
113
101
102
+
### 0d — Attach everything and restart once
103
+
104
+
Attach each secret you provisioned in 0a–0c (skip the line for any secret that was already in env coming into this phase — those are already persisted):
> "Wallet `<address>` created. I generated my own additional_signer keypair and stored the private half as `PRIVY_AUTH_SIGNING_KEY`. Restarting now — I'll come back as a fresh session and walk you through the one-time off-machine ceremony to register an owner key."
116
+
> "All set: OpenSea key fetched, Privy app credentials saved, wallet `<WALLET_ADDRESS>` created, and my additional_signer keypair generated (private half stored as `PRIVY_AUTH_SIGNING_KEY`). Restarting now — I'll come back as a fresh session and walk you through the one-time off-machine ceremony to register your owner key and attach a spend policy."
117
117
118
118
```bash
119
119
node "$PINATA_CLI" restart
120
120
```
121
121
122
-
Stop. Resume cold from Phase 3.
122
+
Stop. The conversation ends here; you'll resume cold from Phase 1.
This phase bundles the three off-machine actions that all require the user's owner private key into one focused session, so the user only has to bring out their owner key once.
131
+
130
132
Check current posture:
131
133
132
134
```bash
133
135
opensea wallet info --format json
134
136
```
135
137
136
-
If the output shows `ownerEnforcesAuthKey: true` AND `additionalSignerCount >= 1`, hardening is complete. Update `IDENTITY.md`:
If all three pass, the ceremony is complete. Update `IDENTITY.md`:
137
145
138
146
-`hardening_status: confirmed`
139
147
-`auth_key_gating: yes`
148
+
- Policy template: *Agent Trading — Conservative*
149
+
- Per-tx cap: `<cap from earlier conversation, if known — otherwise note "see policy"`>
140
150
141
-
Then advance to Phase 4.
151
+
Then advance to Phase 2.
142
152
143
-
Otherwise (most likely on first arrival here), tell the user:
153
+
Otherwise (most likely on first arrival here), walk the user through the combined ceremony. First, settle the per-tx cap conversationally so they can plug it into the policy template before going off-machine:
144
154
145
-
> "Wallet is at `<address>` (id `<wallet_id>`). Before I can sign anything, two things need to happen on YOUR machine — never here:
155
+
1. Ask them their per-tx cap in ETH (no example — they choose). Convert to wei: `0.05 ETH = 50000000000000000 wei`.
156
+
2. Show them the *Agent Trading — Conservative* template from `skills/opensea/references/wallet-policies.md`, with their cap substituted into the `value lte` rule. Use the chain allowlist and Seaport destination from the same reference, verbatim.
157
+
158
+
Then tell them:
159
+
160
+
> "Wallet is at `<address>` (id `<wallet_id>`). Before I can sign anything, three things need to happen on YOUR machine — never here. Get them all out of the way in one session with your owner key:
161
+
>
162
+
> 1.**Generate your owner keypair locally.** Easiest path: install the OpenSea CLI locally (`npm install -g @opensea/cli`) and run `opensea wallet generate-auth-key`. Or use any P-256 keygen (e.g. `openssl ecparam -name prime256v1 -genkey -noout -out owner.pem` and convert to SPKI base64). Keep the private key on your machine — never paste it to me, never put it in env, never check it into anything.
146
163
>
147
-
> 1. Generate your own owner keypair. Easiest path: install the OpenSea CLI locally (`npm install -g @opensea/cli`) and run `opensea wallet generate-auth-key`. Or use any P-256 keygen (e.g. `openssl ecparam -name prime256v1 -genkey -noout -out owner.pem` and convert to SPKI base64). Keep the private key on your machine — never paste it to me, never put it in env, never check it into anything.
164
+
> 2.**Register two keys on the wallet:** your owner public key as `owner_id`, AND my additional_signer public key (`<additional_signer_pubkey from IDENTITY.md>`) as a signer.
148
165
>
149
-
> 2. Register both keys on the wallet: your owner public key as `owner_id`, AND my additional_signer public key (`<additional_signer_pubkey from IDENTITY.md>`) as a signer. Both via the Node script in https://github.com/ProjectOpenSea/opensea-skill/blob/main/docs/policy-administration.md.
166
+
> 3.**Attach the spend policy** I just showed you (with your `<cap>` ETH cap), so the per-tx ceiling is enforced in Privy's TEE.
167
+
>
168
+
> Steps 2 and 3 are both done with the Node script in https://github.com/ProjectOpenSea/opensea-skill/blob/main/docs/policy-administration.md, signed by your owner key (off-machine). Do them in order: register first, attach policy second — once owner gating is on, the policy attach also requires the owner signature.
150
169
>
151
170
> After this one-time ceremony, the day-to-day is asymmetric: I sign every trade with my additional_signer key (lives in env, scoped to `/rpc` only). Your owner key only comes out when you decide to change the policy itself — raise the cap, edit the chain allowlist, etc. You don't need to be online with the owner key for me to trade.
152
171
>
153
-
> Once both keys are registered, type 'done' and I'll verify."
154
-
155
-
When user says done, re-run `opensea wallet info`. If the checks pass, record `hardening_status: confirmed` and advance. If not, surface the actual `ownerEnforcesAuthKey` and `additionalSignerCount` values from the JSON and ask the user to confirm both off-machine steps completed.
172
+
> Once all three are done, type 'done' and I'll verify."
156
173
157
-
**Refuse to advance to Phase 4 until hardening is confirmed.** Do not proceed to spend-policy attachment, balance checks, watchlist calibration, or any signing-capable operation while `ownerEnforcesAuthKey` is false. If the user pushes back, explain: without owner gating, the credentials in env can rewrite the policy that's supposed to constrain spending — there's no real ceiling.
174
+
When the user says done, re-run `opensea wallet info`. Verify each property and surface specifically which (if any) failed:
Don't advance with partial state. Once all three pass, record the IDENTITY.md fields above and advance to Phase 2.
162
181
163
-
**Precondition:**`hardening_status: confirmed`.
164
-
165
-
Walk the user through choosing and applying a per-tx policy:
166
-
167
-
1. Ask them their per-tx cap in ETH (no example — they choose). Convert to wei: `0.05 ETH = 50000000000000000 wei`.
168
-
2. Show them the *Agent Trading — Conservative* template from `skills/opensea/references/wallet-policies.md`, with their cap substituted into the `value lte` rule. Use the chain allowlist and Seaport destination from the same reference, verbatim.
169
-
3. Tell them to attach it via the Node script in https://github.com/ProjectOpenSea/opensea-skill/blob/main/docs/policy-administration.md. They'll need their owner private key (off-machine) to sign the request. Do NOT construct or run the `PATCH` request from here.
170
-
4. When they say done, re-run `opensea wallet info`. Confirm `policyIds.length > 0`. Record the policy template and per-tx cap in `IDENTITY.md`.
182
+
**Refuse to advance to Phase 2 (funding) until all three pass.** Without owner gating, the credentials in env can rewrite the policy that's supposed to constrain spending. Without a policy, there is no per-tx ceiling. Funding before either is in place creates a window where env credentials could drain the wallet. If the user pushes back, explain the order and offer to keep waiting.
171
183
172
-
## Phase 5 — Hot-wallet funding
184
+
## Phase 2 — Hot-wallet funding
173
185
174
186
**Skip if:**`IDENTITY.md` already has a `float_per_chain` entry.
175
187
@@ -187,7 +199,7 @@ Record in `IDENTITY.md` under `## Wallet`:
187
199
188
200
For each funded chain, do a quick balance check (use the native-balance path from `skills/opensea/references/wallet-setup.md` or `eth_getBalance` via a public RPC). If a target chain shows 0, note it — you can still track floors there, you just can't buy.
189
201
190
-
## Phase 6 — Conversation, identity, watchlist
202
+
## Phase 3 — Conversation, identity, watchlist
191
203
192
204
Don't interrogate. Just talk. Start with something like:
Copy file name to clipboardExpand all lines: workspace/IDENTITY.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,7 @@
15
15
-**Policy template:**
16
16
-**Spending limit (per tx):**_(ETH / wei — record both for clarity, e.g. "0.05 ETH / 50000000000000000 wei")_
17
17
-**hardening_status:**_(pending_creation | pending_owner_registration | pending_policy | confirmed — used by BOOTSTRAP for resumability across restarts)_
18
-
-**additional_signer_pubkey:**_(SPKI base64; the public half of `PRIVY_AUTH_SIGNING_KEY`. Persisted so BOOTSTRAP Phase 3 can re-show it to the user across cold restarts.)_
19
-
-**auth_key_gating:**_(yes | no — captured from `opensea wallet info` after Phase 3 verifies `ownerEnforcesAuthKey: true`)_
18
+
-**additional_signer_pubkey:**_(SPKI base64; the public half of `PRIVY_AUTH_SIGNING_KEY`. Persisted so BOOTSTRAP Phase 1 can re-show it to the user across cold restarts.)_
19
+
-**auth_key_gating:**_(yes | no — captured from `opensea wallet info` after Phase 1 verifies `ownerEnforcesAuthKey: true`)_
20
20
-**float_per_chain:**_(mirrored from `TOOLS.md` → `floatPerChain`; the real aggregate ceiling)_
21
21
-**funding_wallet:**_(optional — user's cold/funding wallet address, so the agent can recognize replenishment events in `events by-account` streams)_
0 commit comments