Skip to content

Commit 62f09a8

Browse files
committed
Release v1.15.0
Origin-SHA: 288babb8fdf08d5296232fcdb46016533553081c
1 parent f0e3115 commit 62f09a8

16 files changed

Lines changed: 510 additions & 66 deletions

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
# @opensea/cli
22

3+
## 1.15.0
4+
5+
### Minor Changes
6+
7+
- bf5874d: Add `opensea tokens account-activity` to query fungible token activity (transfers, swaps, wraps, unwraps) for an account via `GET /api/v2/account/{address}/token-activity`, and `opensea tools activity` to view payment/usage activity for a registered tool via `GET /api/v2/tools/{registry_chain}/{registry_addr}/{tool_id}/activity`.
8+
- bf5874d: Add `opensea tools saved` subcommands for listing, saving, and removing saved tools via the wallet-authenticated `GET/POST/DELETE /api/v2/saved-tools` endpoints.
9+
10+
### Patch Changes
11+
12+
- 9bc9708: Require explicit scopes for private-key CLI login, and add typed SDK helpers for the wallet-authenticated social and saved-tools REST endpoints.
13+
- Updated dependencies [bf5874d]
14+
- Updated dependencies [bf5874d]
15+
- Updated dependencies [9bc9708]
16+
- @opensea/sdk@11.5.0
17+
318
## 1.14.1
419

520
### Patch Changes

README.md

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,21 +54,20 @@ Get an API key instantly via the command above, or get a full key at [opensea.io
5454
Wallet-authenticated endpoints also require a scoped token:
5555

5656
```bash
57-
opensea login
58-
opensea auth status
59-
opensea whoami
60-
opensea api request GET /api/v2/account/0xYOUR_WALLET/favorites --params '{"limit":1}'
57+
export OPENSEA_PRIVATE_KEY="..."
58+
opensea login --private-key --scopes read:favorites
59+
WALLET=$(opensea --format json whoami | jq -r '.address')
60+
opensea api request GET "/api/v2/account/$WALLET/favorites" --params '{"limit":1}'
61+
opensea auth revoke
6162
```
6263

63-
Use `--scopes` with `opensea login` to request a narrower scope set. For
64-
server-side agents, set `OPENSEA_PRIVATE_KEY` and pass `--private-key` (or pass
65-
`--private-key <key>`) to authenticate with SIWE instead of OAuth. Using the
66-
environment variable is recommended to keep the key out of shell history. The
67-
`api request` command supports GET, POST, PUT, PATCH, and DELETE plus JSON body
68-
files, so newly published scoped endpoints are available without waiting for a
69-
dedicated command. SIWE logins retain the session needed for session-only PAT
70-
revocation; `opensea auth revoke` refreshes that session before deleting the
71-
token.
64+
Private-key login uses SIWE and requires an explicit `--scopes` list. The
65+
private key signs locally and is not stored. The CLI
66+
keeps the session needed to revoke the personal access token (PAT), and
67+
`api request` sends the stored wallet JWT alongside `OPENSEA_API_KEY`. Use
68+
`opensea auth refresh` after the JWT expires. For interactive login, run
69+
`opensea login` without `--private-key`. See the
70+
[wallet-auth guide](https://docs.opensea.io/reference/auth).
7271

7372
## Quick Start
7473

@@ -109,7 +108,7 @@ opensea --format table collections stats mfers
109108
| `swaps` | Get swap quotes for token trading |
110109
| `accounts` | Get account details |
111110
| `whoami` | Show the current wallet, scopes, and scope source |
112-
| `api request` | Call any API v2 endpoint with the active API key and scoped token |
111+
| `api request` | Call any API v2 endpoint with the active API key and wallet JWT |
113112

114113
Global options: `--api-key`, `--chain` (default: ethereum), `--format` (json/table/toon), `--base-url`
115114

docs/cli-reference.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ only and never authorization data.
2929

3030
```bash
3131
opensea login [--scopes <scopes>] [--client-id <id>] [--device] [--no-browser]
32-
opensea login --private-key [--scopes <scopes>]
33-
opensea login --private-key <key> [--scopes <scopes>]
32+
opensea login --private-key --scopes <scopes>
33+
opensea login --private-key <key> --scopes <scopes>
3434
```
3535

3636
`login` obtains a scoped access token and stores it in `~/.opensea/auth.json`.
@@ -39,7 +39,8 @@ By default it runs the OAuth 2.1 authorization-code flow in a browser. Use
3939
URL. Pass `--private-key` to authenticate with SIWE instead of OAuth, which is
4040
useful for server-side agents. Set `OPENSEA_PRIVATE_KEY` and use `--private-key`
4141
without a value to keep the key out of shell history; a raw key can be passed as
42-
an option value when necessary.
42+
an option value when necessary. Private-key login requires `--scopes` so the
43+
agent's capabilities are always explicit.
4344

4445
## Collections
4546

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opensea/cli",
3-
"version": "1.14.1",
3+
"version": "1.15.0",
44
"type": "module",
55
"description": "OpenSea CLI - Query the OpenSea API from the command line or programmatically",
66
"main": "dist/index.js",
@@ -24,7 +24,7 @@
2424
},
2525
"dependencies": {
2626
"@opensea/api-types": "^0.8.2",
27-
"@opensea/sdk": "^11.4.9",
27+
"@opensea/sdk": "^11.5.0",
2828
"@opensea/wallet-adapters": "^0.3.3",
2929
"commander": "^14.0.3",
3030
"zod": "^4.3.6"

src/commands/auth.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AUTH_SCOPES } from "@opensea/api-types"
2-
import { linkWalletWithSiwx, OPENSEA_SCOPES, OpenSeaOAuth } from "@opensea/sdk"
2+
import { linkWalletWithSiwx, OpenSeaOAuth } from "@opensea/sdk"
33
import {
44
createWalletFromEnv,
55
PrivateKeyAdapter,
@@ -84,14 +84,23 @@ export function authCommand(
8484
"--private-key [key]",
8585
"Use a private key for SIWE login (set OPENSEA_PRIVATE_KEY, or pass the key as the value; using the env var is recommended)",
8686
)
87-
.option(
88-
"--scopes <scopes>",
89-
"Comma-separated scopes to request",
90-
OPENSEA_SCOPES.READ_ELIGIBILITY,
91-
)
92-
.action(async (opts: { privateKey?: string | true; scopes: string }) => {
87+
.option("--scopes <scopes>", "Comma-separated scopes to request")
88+
.action(async (opts: { privateKey?: string | true; scopes?: string }) => {
89+
if (!opts.scopes?.trim()) {
90+
throw new Error(
91+
"Private-key login requires --scopes. Run `opensea auth scopes` to list available scopes.",
92+
)
93+
}
9394
const baseUrl = getBaseUrl() ?? DEFAULT_BASE_URL
94-
const scopes = opts.scopes.split(",").map(s => s.trim())
95+
const scopes = opts.scopes
96+
.split(",")
97+
.map(s => s.trim())
98+
.filter(Boolean)
99+
if (scopes.length === 0) {
100+
throw new Error(
101+
"Private-key login requires --scopes. Run `opensea auth scopes` to list available scopes.",
102+
)
103+
}
95104
const { privateKey, source } = resolvePrivateKey(opts.privateKey)
96105
warnIfInlinePrivateKey(source)
97106

src/commands/login.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ const DEFAULT_BASE_URL = "https://api.opensea.io"
2828
* Zitadel's project roles, which can include deferred or internal roles.
2929
*/
3030
const DEFAULT_SCOPES = AUTH_SCOPES.map(({ name }) => name)
31-
3231
function scopesOutsideRequested(
3332
requestedScopes: string[],
3433
grantedScopes: string[],
@@ -84,14 +83,20 @@ export function loginCommand(
8483
device?: boolean
8584
browser: boolean
8685
}) => {
87-
const scopes = opts.scopes
86+
const requestedScopes = opts.scopes
8887
? opts.scopes
8988
.split(",")
9089
.map(s => s.trim())
9190
.filter(Boolean)
92-
: [...DEFAULT_SCOPES]
91+
: undefined
9392

9493
if (opts.privateKey !== undefined) {
94+
if (!requestedScopes?.length) {
95+
throw new Error(
96+
"Private-key login requires --scopes. Run `opensea auth scopes` to list available scopes.",
97+
)
98+
}
99+
const scopes = requestedScopes
95100
const { privateKey, source } = resolvePrivateKey(opts.privateKey)
96101
warnIfInlinePrivateKey(source)
97102

@@ -159,6 +164,7 @@ export function loginCommand(
159164
const clientId = resolveOAuthClientId(opts.clientId)
160165
const issuer = getAuthBaseUrl?.() ?? DEFAULT_AUTH_BASE_URL
161166
const oauth = new OpenSeaOAuth({ clientId, issuer })
167+
const scopes = requestedScopes ?? [...DEFAULT_SCOPES]
162168

163169
const token = opts.device
164170
? await runDeviceFlow(oauth, scopes)

src/commands/tokens.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,50 @@ export function tokensCommand(
198198
},
199199
)
200200

201+
addPaginationOptions(
202+
cmd
203+
.command("account-activity")
204+
.description(
205+
"Get fungible token activity for an account (transfers, swaps, wraps, unwraps)",
206+
)
207+
.argument("<address>", "Account address")
208+
.option("--chains <chains>", "Comma-separated chains to filter by")
209+
.option(
210+
"--tokens <tokens>",
211+
"Comma-separated token contract addresses to filter by",
212+
)
213+
.option(
214+
"--type <types>",
215+
"Comma-separated activity types (send, receive, swap, wrap, unwrap)",
216+
),
217+
"Number of results per page",
218+
).action(
219+
async (
220+
address: string,
221+
options: {
222+
limit: string
223+
next?: string
224+
chains?: string
225+
tokens?: string
226+
type?: string
227+
},
228+
) => {
229+
const client = getClient()
230+
await outputGet(
231+
client,
232+
getFormat(),
233+
`/api/v2/account/${address}/token-activity`,
234+
{
235+
chains: options.chains,
236+
tokens: options.tokens,
237+
type: options.type,
238+
limit: parseIntOption(options.limit, "--limit"),
239+
next: options.next,
240+
},
241+
)
242+
},
243+
)
244+
201245
addPaginationOptions(
202246
cmd
203247
.command("holders")

0 commit comments

Comments
 (0)