Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions cli/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
},
"dependencies": {
"@clack/prompts": "^1.0.0",
"@filoz/synapse-core": "^0.7.0",
"@filoz/synapse-sdk": "^1.1.0",
"@filoz/synapse-core": "^0.8.1",
"@filoz/synapse-sdk": "^1.2.1",
"conf": "^15.0.2",
"incur": "^0.4.19",
"terminal-link": "^5.0.0",
Expand Down
77 changes: 40 additions & 37 deletions cli/src/commands/dataset/details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@ export const detailsCommand = {
.number()
.default(314159)
.describe('Chain ID. 314159 = Calibration, 314 = Mainnet'),
offset: z.coerce
.number()
.default(0)
.describe('Piece offset to start from (for pagination)'),
cursor: z
.string()
.regex(
/^\d+$/,
'must be the decimal nextCursor value from a previous page'
)
.optional()
.describe(
'Resume from a previous page: pass the nextCursor value that page returned (an opaque decimal string). Omit for the first page.'
),
limit: z.coerce
.number()
.default(100)
Expand All @@ -37,7 +43,7 @@ export const detailsCommand = {
live: z.boolean(),
managed: z.boolean(),
terminating: z.boolean(),
activePieceCount: z.string(),
hasActivePieces: z.boolean(),
metadata: z.record(z.string(), z.string()),
}),
pieces: z.array(
Expand All @@ -49,8 +55,12 @@ export const detailsCommand = {
metadata: z.record(z.string(), z.string()),
})
),
hasMore: z.boolean(),
nextOffset: z.number().optional(),
nextCursor: z
.string()
.optional()
.describe(
'Present when more pieces remain — pass it back as --cursor to fetch the next page'
),
}),
async run(c: any) {
const out = new OutputContext(c)
Expand All @@ -71,14 +81,13 @@ export const detailsCommand = {
)
}

const offset = c.options.offset ?? 0
const limit = c.options.limit ?? 100

out.step('Fetching pieces and metadata')
const { pieces, hasMore } = await getPiecesWithMetadata(client, {
const { items, nextCursor } = await getPiecesWithMetadata(client, {
dataSet: ds,
address: client.account.address,
offset: BigInt(offset),
cursor: BigInt(c.options.cursor ?? 0),
limit: BigInt(limit),
})

Expand All @@ -91,11 +100,11 @@ export const detailsCommand = {
live: !!ds.live,
managed: !!ds.managed,
terminating: ds.pdpEndEpoch > 0n,
activePieceCount: ds.activePieceCount,
hasActivePieces: ds.hasActivePieces,
metadata: ds.metadata,
}

const piecesList = pieces.map((piece: any) => {
const piecesList = items.map((piece: any) => {
const cid = piece.cid.toString()
return {
id: piece.id,
Expand All @@ -106,37 +115,31 @@ export const detailsCommand = {
}
})

const nextOffset = offset + piecesList.length
const totalPieces = Number(ds.activePieceCount)
const nextPage = hasMore
? [
{
command: 'dataset details',
options: {
dataSetId: c.options.dataSetId,
offset: nextOffset,
limit,
},
description: `Show the next page of pieces (offset ${nextOffset})`,
},
{
command: 'dataset details',
options: {
dataSetId: c.options.dataSetId,
offset: 0,
limit: totalPieces,
// Cursors are opaque continuation values; there is no total piece count
// any more (synapse-core 0.8 dropped activePieceCount), so "fetch all"
// means following nextCursor pages until it stops appearing.
const nextPage =
nextCursor !== undefined
? [
{
command: 'dataset details',
options: {
dataSetId: c.options.dataSetId,
cursor: nextCursor.toString(),
limit,
},
description: `Show the next page of pieces (cursor ${nextCursor})`,
},
description: `Fetch all ${totalPieces} pieces in one call`,
},
]
: []
]
: []

return out.done(
{
dataset,
pieces: piecesList,
hasMore,
...(hasMore ? { nextOffset } : {}),
...(nextCursor !== undefined
? { nextCursor: nextCursor.toString() }
: {}),
},
{
cta: chainCta(c.options.chain, {
Expand Down
9 changes: 8 additions & 1 deletion cli/src/commands/dataset/list.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { paginate } from '@filoz/synapse-core'
import { getPdpDataSets } from '@filoz/synapse-core/warm-storage'
import { z } from 'incur'
import { getBlockNumber } from 'viem/actions'
Expand Down Expand Up @@ -42,8 +43,14 @@ export const listCommand = {

try {
out.step('Listing data sets')
// getPdpDataSets returns bounded pages (default 100); walk every page so
// the listing stays complete for wallets with many datasets.
const [dataSets, blockNumber] = await Promise.all([
getPdpDataSets(client, { address: client.account.address }),
Array.fromAsync(
paginate(({ cursor }) =>
getPdpDataSets(client, { address: client.account.address, cursor })
)
),
getBlockNumber(client),
])

Expand Down
66 changes: 36 additions & 30 deletions cli/src/commands/piece/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@ export const listCommand = {
.number()
.default(314159)
.describe('Chain ID. 314159 = Calibration, 314 = Mainnet'),
offset: z.coerce
.number()
.default(0)
.describe('Piece offset to start from (for pagination)'),
cursor: z
.string()
.regex(
/^\d+$/,
'must be the decimal nextCursor value from a previous page'
)
.optional()
.describe(
'Resume from a previous page: pass the nextCursor value that page returned (an opaque decimal string). Omit for the first page.'
),
limit: z.coerce
.number()
.default(100)
Expand All @@ -40,8 +46,12 @@ export const listCommand = {
metadata: z.record(z.string(), z.string()),
})
),
hasMore: z.boolean(),
nextOffset: z.number().optional(),
nextCursor: z
.string()
.optional()
.describe(
'Present when more pieces remain — pass it back as --cursor to fetch the next page'
),
}),
examples: [
{ args: { dataSetId: 42 }, description: 'List pieces in dataset #42' },
Expand All @@ -60,18 +70,17 @@ export const listCommand = {
if (!dataSet)
return out.fail('NOT_FOUND', `Dataset ${c.args.dataSetId} not found`)

const offset = c.options.offset ?? 0
const limit = c.options.limit ?? 100

out.step('Fetching pieces')
const { pieces, hasMore } = await getPiecesWithMetadata(client, {
const { items, nextCursor } = await getPiecesWithMetadata(client, {
dataSet,
address: client.account.address,
offset: BigInt(offset),
cursor: BigInt(c.options.cursor ?? 0),
limit: BigInt(limit),
})

const piecesList = pieces.map((piece: any) => {
const piecesList = items.map((piece: any) => {
const cid = piece.cid.toString()
return {
id: piece.id,
Expand All @@ -81,32 +90,29 @@ export const listCommand = {
}
})

const nextOffset = offset + piecesList.length
const totalPieces = Number(dataSet.activePieceCount)
const nextPage = hasMore
? [
{
command: 'piece list',
args: { dataSetId: c.args.dataSetId },
options: { offset: nextOffset, limit },
description: `Show the next page of pieces (offset ${nextOffset})`,
},
{
command: 'piece list',
args: { dataSetId: c.args.dataSetId },
options: { offset: 0, limit: totalPieces },
description: `Fetch all ${totalPieces} pieces in one call`,
},
]
: []
// Cursors are opaque continuation values; there is no total piece count
// any more (synapse-core 0.8 dropped activePieceCount), so "fetch all"
// means following nextCursor pages until it stops appearing.
const nextPage =
nextCursor !== undefined
? [
{
command: 'piece list',
args: { dataSetId: c.args.dataSetId },
options: { cursor: nextCursor.toString(), limit },
description: `Show the next page of pieces (cursor ${nextCursor})`,
},
]
: []

return out.done(
{
dataSetId: c.args.dataSetId.toString(),
datasetScannerUrl: datasetScannerUrl(c.args.dataSetId, chain),
pieces: piecesList,
hasMore,
...(hasMore ? { nextOffset } : {}),
...(nextCursor !== undefined
? { nextCursor: nextCursor.toString() }
: {}),
},
{
cta: chainCta(c.options.chain, {
Expand Down
11 changes: 8 additions & 3 deletions cli/src/commands/wallet/costs.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { paginate } from '@filoz/synapse-core'
import { formatBalance } from '@filoz/synapse-core/utils'
import { getPdpDataSets } from '@filoz/synapse-core/warm-storage'
import { z } from 'incur'
Expand Down Expand Up @@ -58,9 +59,13 @@ export const costsCommand = {
out.step('Getting costs')

const copies = c.options.copies ?? 2
const dataSets = await getPdpDataSets(client, {
address: client.account.address,
})
// Paged since synapse-core 0.8: walk every page so reuse still sees all
// active datasets, not just the first hundred.
const dataSets = await Array.fromAsync(
paginate(({ cursor }) =>
getPdpDataSets(client, { address: client.account.address, cursor })
)
)
// Active, non-terminating datasets only. Contexts are created one at a
// time via createContext — the plural createContexts rejects datasets
// sharing a provider.
Expand Down
17 changes: 10 additions & 7 deletions cli/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { homedir } from 'node:os'
import { resolve } from 'node:path'
import type { Chain } from '@filoz/synapse-core/chains'
import type { FilecoinChain } from '@filoz/synapse-core/chains'
import terminalLink from 'terminal-link'

/**
Expand All @@ -15,27 +15,30 @@ export function expandHome(path: string): string {
return path
}

function networkSlug(chain: Chain): string {
function networkSlug(chain: FilecoinChain): string {
return chain.id === 314 ? 'mainnet' : 'calibration'
}

export function hashLink(hash: string, chain: Chain) {
export function hashLink(hash: string, chain: FilecoinChain) {
return terminalLink(hash, `${chain.blockExplorers?.default?.url}/tx/${hash}`)
}

export function datasetScannerUrl(dataSetId: string | bigint, chain: Chain) {
export function datasetScannerUrl(
dataSetId: string | bigint,
chain: FilecoinChain
) {
return `https://pdp.vxb.ai/${networkSlug(chain)}/dataset/${dataSetId.toString()}`
}

export function pieceScannerUrl(pieceCid: string, chain: Chain) {
export function pieceScannerUrl(pieceCid: string, chain: FilecoinChain) {
return `https://pdp.vxb.ai/${networkSlug(chain)}/piece/${pieceCid}`
}

export function txExplorerUrl(hash: string, chain: Chain) {
export function txExplorerUrl(hash: string, chain: FilecoinChain) {
return `${chain.blockExplorers?.default?.url}/tx/${hash}`
}

export function dealbotDashboardUrl(chain: Chain) {
export function dealbotDashboardUrl(chain: FilecoinChain) {
return chain.id === 314
? 'https://dealbot.filoz.org'
: 'https://staging.dealbot.filoz.org'
Expand Down
Loading
Loading