Skip to content

Commit

Permalink
fix: upload client should perform filecoin offer (#1333)
Browse files Browse the repository at this point in the history
In context of storacha-network/project-tracking#25
and storacha-network/w3infra#344 we set the client
to perform filecoin/offer already so that new users, as well as users
that upgrade in the meantime can already perform this, in order to
better prepare us to get rid of bucket event

---------

Co-authored-by: Alan Shaw <alan.shaw@protocol.ai>
  • Loading branch information
vasco-santos and alanshaw committed Mar 21, 2024
1 parent f5bac9d commit 466e3f7
Show file tree
Hide file tree
Showing 11 changed files with 352 additions and 14 deletions.
1 change: 1 addition & 0 deletions packages/upload-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"@ucanto/transport": "^9.1.0",
"@web3-storage/capabilities": "workspace:^",
"@web3-storage/data-segment": "^5.1.0",
"@web3-storage/filecoin-client": "workspace:^",
"ipfs-utils": "^9.0.14",
"multiformats": "^12.1.2",
"p-retry": "^5.1.2",
Expand Down
24 changes: 24 additions & 0 deletions packages/upload-client/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as PieceHasher from '@web3-storage/data-segment/multihash'
import { Storefront } from '@web3-storage/filecoin-client'
import * as Link from 'multiformats/link'
import * as raw from 'multiformats/codecs/raw'
import * as Store from './store.js'
Expand Down Expand Up @@ -129,7 +130,30 @@ async function uploadBlockStream(conf, blocks, options = {}) {
const multihashDigest = await hasher.digest(bytes)
/** @type {import('@web3-storage/capabilities/types').PieceLink} */
const piece = Link.create(raw.code, multihashDigest)

// Invoke store/add and write bytes to write target
const cid = await Store.add(conf, bytes, options)
// Invoke filecoin/offer for data
const result = await Storefront.filecoinOffer(
{
issuer: conf.issuer,
audience: conf.audience,
// Resource of invocation is the issuer did for being self issued
with: conf.issuer.did(),
proofs: conf.proofs,
},
cid,
piece,
options
)

if (result.out.error) {
throw new Error(
'failed to offer piece for aggregation into filecoin deal',
{ cause: result.out.error }
)
}

const { version, roots, size } = car
controller.enqueue({ version, roots, size, cid, piece })
},
Expand Down
3 changes: 2 additions & 1 deletion packages/upload-client/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
UsageReportSuccess,
UsageReportFailure,
} from '@web3-storage/capabilities/types'
import { StorefrontService } from '@web3-storage/filecoin-client/storefront'
import { code as pieceHashCode } from '@web3-storage/data-segment/multihash'

type Override<T, R> = Omit<T, keyof R> & R
Expand Down Expand Up @@ -93,7 +94,7 @@ export interface ProgressStatus extends XHRProgressStatus {

export type ProgressFn = (status: ProgressStatus) => void

export interface Service {
export interface Service extends StorefrontService {
store: {
add: ServiceMethod<StoreAdd, StoreAddSuccess, Failure>
get: ServiceMethod<StoreGet, StoreGetSuccess, StoreGetFailure>
Expand Down
32 changes: 32 additions & 0 deletions packages/upload-client/test/helpers/filecoin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as StorefrontCapabilities from '@web3-storage/capabilities/filecoin/storefront'
import * as Server from '@ucanto/server'

/**
* @param {Server.Signer<`did:${string}:${string}`, Server.API.SigAlg>} id
* @param {import('@web3-storage/data-segment').PieceLink} piece
* @param {Pick<{ content: Server.API.Link<unknown, number, number, 0 | 1>; piece: import('@web3-storage/data-segment').PieceLink; }, 'content' | 'piece'>} args
*/
export async function getFilecoinOfferResponse(id, piece, args) {
// Create effect for receipt with self signed queued operation
const submitfx = await StorefrontCapabilities.filecoinSubmit
.invoke({
issuer: id,
audience: id,
with: id.did(),
nb: args,
expiration: Infinity,
})
.delegate()

const acceptfx = await StorefrontCapabilities.filecoinAccept
.invoke({
issuer: id,
audience: id,
with: id.did(),
nb: args,
expiration: Infinity,
})
.delegate()

return Server.ok({ piece }).fork(submitfx.link()).join(acceptfx.link())
}
7 changes: 7 additions & 0 deletions packages/upload-client/test/helpers/mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const notImplemented = () => {
* store: Partial<import('../../src/types.js').Service['store']>
* upload: Partial<import('../../src/types.js').Service['upload']>
* usage: Partial<import('../../src/types.js').Service['usage']>
* filecoin: Partial<import('@web3-storage/filecoin-client/storefront').StorefrontService['filecoin']>
* }>} impl
*/
export function mockService(impl) {
Expand All @@ -28,6 +29,12 @@ export function mockService(impl) {
usage: {
report: withCallCount(impl.usage?.report ?? notImplemented),
},
filecoin: {
offer: withCallCount(impl.filecoin?.offer ?? notImplemented),
submit: withCallCount(impl.filecoin?.submit ?? notImplemented),
accept: withCallCount(impl.filecoin?.accept ?? notImplemented),
info: withCallCount(impl.filecoin?.info ?? notImplemented),
},
}
}

Expand Down
Loading

0 comments on commit 466e3f7

Please sign in to comment.