Skip to content

Commit

Permalink
fix: test blob upload on w3up-client tests
Browse files Browse the repository at this point in the history
  • Loading branch information
joaosa committed May 6, 2024
1 parent dce2972 commit 0a92134
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 17 deletions.
4 changes: 4 additions & 0 deletions packages/access-client/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ import type {
UCANRevoke,
UCANRevokeSuccess,
UCANRevokeFailure,
UCANConclude,
UCANConcludeSuccess,
UCANConcludeFailure,
AccountDID,
ProviderDID,
SpaceDID,
Expand Down Expand Up @@ -132,6 +135,7 @@ export interface Service {
}
ucan: {
revoke: ServiceMethod<UCANRevoke, UCANRevokeSuccess, UCANRevokeFailure>
conclude: ServiceMethod<UCANConclude, UCANConcludeSuccess, UCANConcludeFailure>,
}
plan: {
get: ServiceMethod<PlanGet, PlanGetSuccess, PlanGetFailure>
Expand Down
4 changes: 2 additions & 2 deletions packages/upload-client/src/blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function createUploadProgressHandler(url, handler) {
/**
* @param {import('@ucanto/interface').Invocation} concludeFx
*/
export function getConcludeReceipt(concludeFx) {
function getConcludeReceipt(concludeFx) {
const receiptBlocks = new Map()
for (const block of concludeFx.iterateIPLDBlocks()) {
receiptBlocks.set(`${block.cid}`, block)
Expand All @@ -47,7 +47,7 @@ export function getConcludeReceipt(concludeFx) {
/**
* @param {import('@ucanto/interface').Receipt} receipt
*/
export function parseBlobAddReceiptNext(receipt) {
function parseBlobAddReceiptNext(receipt) {
// Get invocations next
/**
* @type {import('@ucanto/interface').Invocation[]}
Expand Down
3 changes: 2 additions & 1 deletion packages/upload-client/test/helpers/utils.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Receipt } from '@ucanto/core'
import { conclude } from '@web3-storage/capabilities/ucan'
import * as Server from '@ucanto/server'
import * as HTTP from '@web3-storage/capabilities/http'
import * as W3sBlobCapabilities from '@web3-storage/capabilities/web3.storage/blob'
import { W3sBlob } from '@web3-storage/capabilities'
import { createConcludeInvocation } from '../../src/blob.js'
import { createConcludeInvocation } from '../../../upload-client/src/blob.js'

export const validateAuthorization = () => ({ ok: {} })

Expand Down
9 changes: 5 additions & 4 deletions packages/w3up-client/src/service.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { connect } from '@ucanto/client'
import * as client from '@ucanto/client'
import { CAR, HTTP } from '@ucanto/transport'
import * as DID from '@ipld/dag-ucan/did'

export const accessServiceURL = new URL('https://up.web3.storage')
export const accessServicePrincipal = DID.parse('did:web:web3.storage')

export const accessServiceConnection = connect({
export const accessServiceConnection = client.connect({
id: accessServicePrincipal,
codec: CAR.outbound,
channel: HTTP.open({
Expand All @@ -17,7 +17,7 @@ export const accessServiceConnection = connect({
export const uploadServiceURL = new URL('https://up.web3.storage')
export const uploadServicePrincipal = DID.parse('did:web:web3.storage')

export const uploadServiceConnection = connect({
export const uploadServiceConnection = client.connect({
id: uploadServicePrincipal,
codec: CAR.outbound,
channel: HTTP.open({
Expand All @@ -29,7 +29,7 @@ export const uploadServiceConnection = connect({
export const filecoinServiceURL = new URL('https://up.web3.storage')
export const filecoinServicePrincipal = DID.parse('did:web:web3.storage')

export const filecoinServiceConnection = connect({
export const filecoinServiceConnection = client.connect({
id: filecoinServicePrincipal,
codec: CAR.outbound,
channel: HTTP.open({
Expand All @@ -40,6 +40,7 @@ export const filecoinServiceConnection = connect({

/** @type {import('./types.js').ServiceConf} */
export const serviceConf = {
blob: uploadServiceConnection,
access: accessServiceConnection,
upload: uploadServiceConnection,
filecoin: filecoinServiceConnection,
Expand Down
5 changes: 4 additions & 1 deletion packages/w3up-client/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import {
type Service as AccessService,
type AgentDataExport,
} from '@web3-storage/access/types'
import { type Service as UploadService } from '@web3-storage/upload-client/types'
import {
type Service as UploadService,
} from '@web3-storage/upload-client/types'
import type {
ConnectionView,
Signer,
Expand Down Expand Up @@ -31,6 +33,7 @@ export type ProofQuery = Record<Resource, Record<Ability, Unit>>
export type Service = AccessService & UploadService & StorefrontService

export interface ServiceConf {
blob: ConnectionView<UploadService>
access: ConnectionView<AccessService>
upload: ConnectionView<UploadService>
filecoin: ConnectionView<StorefrontService>
Expand Down
22 changes: 13 additions & 9 deletions packages/w3up-client/test/client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '@ucanto/server'
import * as CAR from '@ucanto/transport/car'
import * as Signer from '@ucanto/principal/ed25519'
import * as BlobCapabilities from '@web3-storage/capabilities/store'
import * as StoreCapabilities from '@web3-storage/capabilities/store'
import * as UploadCapabilities from '@web3-storage/capabilities/upload'
import * as UCANCapabilities from '@web3-storage/capabilities/ucan'
Expand All @@ -35,11 +36,12 @@ describe('Client', () => {
let carCID

const service = mockService({
store: {
add: provide(StoreCapabilities.add, ({ invocation, capability }) => {
blob: {
// @ts-ignore Argument of type
add: provide(BlobCapabilities.add, ({ invocation, capability }) => {
assert.equal(invocation.issuer.did(), alice.agent.did())
assert.equal(invocation.capabilities.length, 1)
assert.equal(capability.can, StoreCapabilities.add.can)
assert.equal(capability.can, BlobCapabilities.add.can)
assert.equal(capability.with, alice.currentSpace()?.did())

return {
Expand Down Expand Up @@ -144,11 +146,12 @@ describe('Client', () => {
let carCID

const service = mockService({
store: {
add: provide(StoreCapabilities.add, ({ invocation, capability }) => {
blob: {
// @ts-ignore Argument of type
add: provide(BlobCapabilities.add, ({ invocation, capability }) => {
assert.equal(invocation.issuer.did(), alice.agent.did())
assert.equal(invocation.capabilities.length, 1)
assert.equal(capability.can, StoreCapabilities.add.can)
assert.equal(capability.can, BlobCapabilities.add.can)
assert.equal(capability.with, alice.currentSpace()?.did())
return {
ok: {
Expand Down Expand Up @@ -236,11 +239,12 @@ describe('Client', () => {
let carCID

const service = mockService({
store: {
add: provide(StoreCapabilities.add, ({ invocation, capability }) => {
blob: {
// @ts-ignore Argument of type
add: provide(BlobCapabilities.add, ({ invocation, capability }) => {
assert.equal(invocation.issuer.did(), alice.agent.did())
assert.equal(invocation.capabilities.length, 1)
assert.equal(capability.can, StoreCapabilities.add.can)
assert.equal(capability.can, BlobCapabilities.add.can)
assert.equal(capability.with, space.did())
return {
ok: {
Expand Down
5 changes: 5 additions & 0 deletions packages/w3up-client/test/helpers/mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const notImplemented = () => {

/**
* @param {Partial<{
* blob: Partial<import('@web3-storage/upload-client/types').Service['blob']>
* access: Partial<import('@web3-storage/access/types').Service['access']>
* provider: Partial<import('@web3-storage/access/types').Service['provider']>
* store: Partial<import('@web3-storage/upload-client/types').Service['store']>
Expand All @@ -21,6 +22,9 @@ const notImplemented = () => {
*/
export function mockService(impl) {
return {
blob: {
add: withCallCount(impl.blob?.add ?? notImplemented),
},
store: {
add: withCallCount(impl.store?.add ?? notImplemented),
get: withCallCount(impl.store?.get ?? notImplemented),
Expand Down Expand Up @@ -48,6 +52,7 @@ export function mockService(impl) {
add: withCallCount(impl.provider?.add ?? notImplemented),
},
ucan: {
conclude: withCallCount(impl.ucan?.conclude ?? notImplemented),
revoke: withCallCount(impl.ucan?.revoke ?? notImplemented),
},
filecoin: {
Expand Down
118 changes: 118 additions & 0 deletions packages/w3up-client/test/helpers/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Receipt } from '@ucanto/core'
import * as Server from '@ucanto/server'
import { UCAN } from '@web3-storage/capabilities'
import * as HTTP from '@web3-storage/capabilities/http'
import * as W3sBlobCapabilities from '@web3-storage/capabilities/web3.storage/blob'
import { W3sBlob } from '@web3-storage/capabilities'
import * as Types from '../../src/types.js'

export const validateAuthorization = () => ({ ok: {} })
Expand Down Expand Up @@ -42,3 +46,117 @@ export const createAuthorization = async ({ account, agent, service }) => {

return [authorization, attest]
}

// FIXME this code has been copied over from upload-api
/**
* @param {import('@ucanto/interface').Signer} id
* @param {import('@ucanto/interface').Verifier} serviceDid
* @param {import('@ucanto/interface').Receipt} receipt
*/
function createConcludeInvocation(id, serviceDid, receipt) {
const receiptBlocks = []
const receiptCids = []
for (const block of receipt.iterateIPLDBlocks()) {
receiptBlocks.push(block)
receiptCids.push(block.cid)
}
const concludeAllocatefx = conclude.invoke({
issuer: id,
audience: serviceDid,
with: id.toDIDKey(),
nb: {
receipt: receipt.link(),
},
expiration: Infinity,
facts: [
{
...receiptCids,
},
],
})
for (const block of receiptBlocks) {
concludeAllocatefx.attach(block)
}

return concludeAllocatefx
}

// @ts-ignore
export const setupBlobAddResponse = async function({ issuer, with: space, proofs, audience }, invocation) {
const blob = invocation.capabilities[0].nb.blob
const blobAllocateTask = await W3sBlob.allocate
.invoke({
issuer,
audience,
with: space.did(),
nb: {
blob,
cause: invocation.link(),
space: space.did(),
},
expiration: Infinity,
})
.delegate()
const blobAllocateReceipt = await Receipt.issue({
issuer,
ran: blobAllocateTask.cid,
result: { ok: {} },
})
const blobConcludeAllocate = await createConcludeInvocation(issuer, audience, blobAllocateReceipt).delegate()

const blobPutTask = await HTTP.put
.invoke({
issuer,
audience,
with: space.toDIDKey(),
nb: {
body: blob,
url: {
'ucan/await': ['.out.ok.address.url', blobAllocateTask.link()],
},
headers: {
'ucan/await': ['.out.ok.address.headers', blobAllocateTask.link()],
},
},
facts: [
{
keys: audience.toArchive(),
},
],
expiration: Infinity,
})
.delegate()

const blobAcceptTask = await W3sBlobCapabilities.accept
.invoke({
issuer,
audience,
with: space.did(),
nb: {
blob,
space: space.did(),
_put: { 'ucan/await': ['.out.ok', blobPutTask.link()] },
},
proofs,
})
.delegate()

const blobAcceptReceipt = await Receipt.issue({
issuer,
ran: blobAcceptTask.cid,
result: { ok: {} },
})
const blobConcludeAccept = await createConcludeInvocation(issuer, audience, blobAcceptReceipt).delegate()

return Server
.ok({
site: {
'ucan/await': ['.out.ok.site', blobAcceptTask.link()],
},
})
.fork(blobAllocateTask)
.fork(blobConcludeAllocate)
.fork(blobPutTask)
.join(blobAcceptTask)
.fork(blobConcludeAccept)
}
1 change: 1 addition & 0 deletions packages/w3up-client/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const setup = async () => {
Client.create({
store: new StoreMemory(),
serviceConf: {
blob: context.connection,
access: context.connection,
upload: context.connection,
filecoin: context.connection,
Expand Down

0 comments on commit 0a92134

Please sign in to comment.