Skip to content

Commit a50054e

Browse files
committed
Release v1.7.0
Origin-SHA: 177a890fa9ab1976057dbe4c712f5179411215db
1 parent 3703b82 commit a50054e

17 files changed

Lines changed: 1058 additions & 9 deletions

CHANGELOG.md

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

3+
## 1.7.0
4+
5+
### Minor Changes
6+
7+
- 051b558: Surface 22 new endpoints added in `@opensea/api-types` 0.4.0 as SDK methods and CLI commands.
8+
9+
**`@opensea/sdk`** — new methods on `OpenSeaAPI` (and the underlying domain clients):
10+
11+
- `getTokensBatch`, `getNFTsBatch`, `getCollectionsBatch` — batch lookups
12+
- `createListingActions` — ordered approval + Seaport-sign actions for new listings
13+
- `deployDropContract`, `getDeployContractReceipt` — drop contract deployment
14+
- `transferAssets` — build transactions to transfer NFTs or tokens
15+
- `getCollectionOfferAggregates`, `getCollectionHolders`, `getCollectionFloorPrices` — collection analytics
16+
- `getTokenPriceHistory`, `getTokenOhlcv`, `getTokenActivity` — token analytics
17+
- `getNFTOwners`, `getNFTAnalytics` — NFT analytics
18+
- `getPortfolioStats`, `getPortfolioHistory`, `getProfileOffers`, `getProfileOffersReceived`, `getProfileListings`, `getProfileFavorites`, `getProfileCollections` — account profile
19+
20+
New internal `AssetsAPI` client; new request/response types re-exported through `@opensea/sdk` (from `@opensea/api-types`).
21+
22+
**`@opensea/cli`** — new commands on the existing `accounts`, `collections`, `nfts`, `tokens`, `listings`, `drops` subcommands, plus a new `assets transfer` subcommand. SDK class methods mirroring the same surface added to `OpenSeaCLI`.
23+
24+
No removed endpoints; pure additive release.
25+
326
## 1.6.0
427

528
### Minor Changes

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.6.0",
3+
"version": "1.7.0",
44
"type": "module",
55
"description": "OpenSea CLI - Query the OpenSea API from the command line or programmatically",
66
"main": "dist/index.js",
@@ -23,7 +23,7 @@
2323
"prepublishOnly": "npm run build"
2424
},
2525
"dependencies": {
26-
"@opensea/api-types": "^0.3.0",
26+
"@opensea/api-types": "^0.4.0",
2727
"@opensea/wallet-adapters": "^0.3.0",
2828
"commander": "^14.0.3",
2929
"zod": "^4.3.6"

src/cli.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Command } from "commander"
22
import { OpenSeaAPIError, OpenSeaClient } from "./client.js"
33
import {
44
accountsCommand,
5+
assetsCommand,
56
authCommand,
67
chainsCommand,
78
collectionsCommand,
@@ -118,6 +119,7 @@ program.hook("preAction", () => {
118119
})
119120
})
120121

122+
program.addCommand(assetsCommand(getClient, getFormat))
121123
program.addCommand(chainsCommand(getClient, getFormat))
122124
program.addCommand(collectionsCommand(getClient, getFormat))
123125
program.addCommand(dropsCommand(getClient, getFormat))

src/commands/accounts.ts

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import { parseIntOption } from "../parse.js"
66
import type {
77
Account,
88
AccountResolveResponse,
9+
Listing,
10+
NFT,
11+
Offer,
12+
PortfolioHistoryResponse,
13+
PortfolioStatsResponse,
14+
ProfileCollectionsResponse,
915
TokenBalancePaginatedResponse,
1016
TokenBalanceSortBy,
1117
} from "../types/index.js"
@@ -84,5 +90,220 @@ export function accountsCommand(
8490
console.log(formatOutput(result, getFormat()))
8591
})
8692

93+
cmd
94+
.command("portfolio")
95+
.description("Get portfolio stats (net worth, P&L) for an account")
96+
.argument("<address>", "Wallet address")
97+
.option("--timeframe <window>", "P&L window (HOUR, DAY, WEEK, MONTH)")
98+
.action(async (address: string, options: { timeframe?: string }) => {
99+
const client = getClient()
100+
const result = await client.get<PortfolioStatsResponse>(
101+
`/api/v2/account/${address}/portfolio`,
102+
{ timeframe: options.timeframe },
103+
)
104+
console.log(formatOutput(result, getFormat()))
105+
})
106+
107+
cmd
108+
.command("portfolio-history")
109+
.description("Get portfolio net-worth history for an account")
110+
.argument("<address>", "Wallet address")
111+
.option("--timeframe <window>", "History window (HOUR, DAY, WEEK, MONTH)")
112+
.action(async (address: string, options: { timeframe?: string }) => {
113+
const client = getClient()
114+
const result = await client.get<PortfolioHistoryResponse>(
115+
`/api/v2/account/${address}/portfolio/history`,
116+
{ timeframe: options.timeframe },
117+
)
118+
console.log(formatOutput(result, getFormat()))
119+
})
120+
121+
cmd
122+
.command("offers")
123+
.description("Get active offers made by an account")
124+
.argument("<address>", "Wallet address")
125+
.option("--after <cursor>", "Pagination cursor")
126+
.option("--limit <limit>", "Number of results", "20")
127+
.option(
128+
"--collection-slugs <slugs>",
129+
"Comma-separated collection slugs to filter by",
130+
)
131+
.option("--chains <chains>", "Comma-separated chains to filter by")
132+
.option("--sort-by <field>", "Sort by field")
133+
.option("--sort-direction <dir>", "Sort direction (asc, desc)")
134+
.action(
135+
async (
136+
address: string,
137+
options: {
138+
after?: string
139+
limit: string
140+
collectionSlugs?: string
141+
chains?: string
142+
sortBy?: string
143+
sortDirection?: string
144+
},
145+
) => {
146+
const client = getClient()
147+
const result = await client.get<{ offers: Offer[]; next?: string }>(
148+
`/api/v2/account/${address}/offers`,
149+
{
150+
after: options.after,
151+
limit: parseIntOption(options.limit, "--limit"),
152+
collection_slugs: options.collectionSlugs,
153+
chains: options.chains,
154+
sort_by: options.sortBy,
155+
sort_direction: options.sortDirection,
156+
},
157+
)
158+
console.log(formatOutput(result, getFormat()))
159+
},
160+
)
161+
162+
cmd
163+
.command("offers-received")
164+
.description("Get offers received by an account")
165+
.argument("<address>", "Wallet address")
166+
.option("--after <cursor>", "Pagination cursor")
167+
.option("--limit <limit>", "Number of results", "20")
168+
.option(
169+
"--collection-slugs <slugs>",
170+
"Comma-separated collection slugs to filter by",
171+
)
172+
.option("--chains <chains>", "Comma-separated chains to filter by")
173+
.option("--sort-by <field>", "Sort by field")
174+
.option("--sort-direction <dir>", "Sort direction (asc, desc)")
175+
.action(
176+
async (
177+
address: string,
178+
options: {
179+
after?: string
180+
limit: string
181+
collectionSlugs?: string
182+
chains?: string
183+
sortBy?: string
184+
sortDirection?: string
185+
},
186+
) => {
187+
const client = getClient()
188+
const result = await client.get<{ offers: Offer[]; next?: string }>(
189+
`/api/v2/account/${address}/offers_received`,
190+
{
191+
after: options.after,
192+
limit: parseIntOption(options.limit, "--limit"),
193+
collection_slugs: options.collectionSlugs,
194+
chains: options.chains,
195+
sort_by: options.sortBy,
196+
sort_direction: options.sortDirection,
197+
},
198+
)
199+
console.log(formatOutput(result, getFormat()))
200+
},
201+
)
202+
203+
cmd
204+
.command("listings")
205+
.description("Get active listings for an account")
206+
.argument("<address>", "Wallet address")
207+
.option("--after <cursor>", "Pagination cursor")
208+
.option("--limit <limit>", "Number of results", "20")
209+
.option(
210+
"--collection-slugs <slugs>",
211+
"Comma-separated collection slugs to filter by",
212+
)
213+
.option("--chains <chains>", "Comma-separated chains to filter by")
214+
.option("--sort-by <field>", "Sort by field")
215+
.option("--sort-direction <dir>", "Sort direction (asc, desc)")
216+
.action(
217+
async (
218+
address: string,
219+
options: {
220+
after?: string
221+
limit: string
222+
collectionSlugs?: string
223+
chains?: string
224+
sortBy?: string
225+
sortDirection?: string
226+
},
227+
) => {
228+
const client = getClient()
229+
const result = await client.get<{
230+
listings: Listing[]
231+
next?: string
232+
}>(`/api/v2/account/${address}/listings`, {
233+
after: options.after,
234+
limit: parseIntOption(options.limit, "--limit"),
235+
collection_slugs: options.collectionSlugs,
236+
chains: options.chains,
237+
sort_by: options.sortBy,
238+
sort_direction: options.sortDirection,
239+
})
240+
console.log(formatOutput(result, getFormat()))
241+
},
242+
)
243+
244+
cmd
245+
.command("favorites")
246+
.description("Get items favorited by an account")
247+
.argument("<address>", "Wallet address")
248+
.option("--after <cursor>", "Pagination cursor")
249+
.option("--limit <limit>", "Number of results", "20")
250+
.option("--sort-by <field>", "Sort by field")
251+
.option("--sort-direction <dir>", "Sort direction (asc, desc)")
252+
.option("--chains <chains>", "Comma-separated chains to filter by")
253+
.action(
254+
async (
255+
address: string,
256+
options: {
257+
after?: string
258+
limit: string
259+
sortBy?: string
260+
sortDirection?: string
261+
chains?: string
262+
},
263+
) => {
264+
const client = getClient()
265+
const result = await client.get<{ nfts: NFT[]; next?: string }>(
266+
`/api/v2/account/${address}/favorites`,
267+
{
268+
after: options.after,
269+
limit: parseIntOption(options.limit, "--limit"),
270+
sort_by: options.sortBy,
271+
sort_direction: options.sortDirection,
272+
chains: options.chains,
273+
},
274+
)
275+
console.log(formatOutput(result, getFormat()))
276+
},
277+
)
278+
279+
cmd
280+
.command("collections")
281+
.description("Get collections owned by an account")
282+
.argument("<address>", "Wallet address")
283+
.option("--after <cursor>", "Pagination cursor")
284+
.option("--limit <limit>", "Number of results", "20")
285+
.option("--chains <chains>", "Comma-separated chains to filter by")
286+
.action(
287+
async (
288+
address: string,
289+
options: {
290+
after?: string
291+
limit: string
292+
chains?: string
293+
},
294+
) => {
295+
const client = getClient()
296+
const result = await client.get<ProfileCollectionsResponse>(
297+
`/api/v2/account/${address}/collections`,
298+
{
299+
after: options.after,
300+
limit: parseIntOption(options.limit, "--limit"),
301+
chains: options.chains,
302+
},
303+
)
304+
console.log(formatOutput(result, getFormat()))
305+
},
306+
)
307+
87308
return cmd
88309
}

src/commands/assets.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Command } from "commander"
2+
import type { OpenSeaClient } from "../client.js"
3+
import type { OutputFormat } from "../output.js"
4+
import { formatOutput } from "../output.js"
5+
import { readJsonBodyOption } from "../parse.js"
6+
import type { TransferRequest, TransferResponse } from "../types/index.js"
7+
8+
export function assetsCommand(
9+
getClient: () => OpenSeaClient,
10+
getFormat: () => OutputFormat,
11+
): Command {
12+
const cmd = new Command("assets").description(
13+
"Build asset-movement transactions",
14+
)
15+
16+
cmd
17+
.command("transfer")
18+
.description(
19+
"Build transactions to transfer NFTs or tokens between wallets",
20+
)
21+
.requiredOption(
22+
"--body <path>",
23+
"Path to JSON file with the TransferRequest body",
24+
)
25+
.action(async (options: { body: string }) => {
26+
const client = getClient()
27+
const request = readJsonBodyOption<TransferRequest>(
28+
options.body,
29+
"--body",
30+
)
31+
const result = await client.post<TransferResponse>(
32+
"/api/v2/assets/transfer",
33+
request,
34+
)
35+
console.log(formatOutput(result, getFormat()))
36+
})
37+
38+
return cmd
39+
}

0 commit comments

Comments
 (0)