Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: router #11

Merged
merged 12 commits into from
Nov 5, 2024
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/w3up-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
node-version: ${{ matrix.node_version }}
registry-url: https://registry.npmjs.org/
cache: 'pnpm'
- run: pnpm --filter '@storacha/client' install
- run: pnpm --filter '@storacha/client...' install
- run: pnpm --filter '@storacha/client' attw
- uses: ./packages/w3up-client/.github/actions/test
with:
Expand Down
6 changes: 3 additions & 3 deletions packages/access-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,15 @@
"@ipld/car": "^5.1.1",
"@ipld/dag-ucan": "^3.4.0",
"@scure/bip39": "^1.2.1",
"@storacha/capabilities": "workspace:^",
"@storacha/did-mailto": "workspace:^",
"@storacha/one-webcrypto": "^1.0.1",
"@ucanto/client": "^9.0.1",
"@ucanto/core": "^10.0.1",
"@ucanto/interface": "^10.0.1",
"@ucanto/principal": "^9.0.1",
"@ucanto/transport": "^9.1.1",
"@ucanto/validator": "^9.0.2",
"@storacha/capabilities": "workspace:^",
"@storacha/did-mailto": "workspace:^",
"bigint-mod-arith": "^3.1.2",
"conf": "11.0.2",
"multiformats": "^12.1.2",
Expand All @@ -118,6 +118,7 @@
"uint8arrays": "^4.0.6"
},
"devDependencies": {
"@storacha/eslint-config": "workspace:^",
"@types/assert": "^1.5.6",
"@types/inquirer": "^9.0.4",
"@types/mocha": "^10.0.1",
Expand All @@ -126,7 +127,6 @@
"@types/varint": "^6.0.1",
"@types/ws": "^8.5.4",
"@ucanto/server": "^10.0.0",
"@storacha/eslint-config": "workspace:^",
"assert": "^2.0.0",
"mocha": "^10.2.0",
"playwright-test": "^12.3.4",
Expand Down
2 changes: 1 addition & 1 deletion packages/access-client/src/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ export class Agent {
// @ts-ignore
capability: cap.create({
with: space,
nb: options.nb,
nb: 'nb' in options ? options.nb : undefined,
}),
issuer: this.issuer,
proofs: [...proofs],
Expand Down
2 changes: 1 addition & 1 deletion packages/access-client/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export type InvokeOptions<
Match<{ can: A; with: R & Resource; nb: Caveats }, UnknownMatch>
>
> = UCANBasicOptions &
InferNb<InferInvokedCapability<CAP>['nb']> & {
Omit<InferInvokedCapability<CAP>, 'can' | 'with'> & {
/**
* Resource for the capability, normally a Space DID
* Defaults to the current selected Space
Expand Down
4 changes: 2 additions & 2 deletions packages/blob-index/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@
},
"dependencies": {
"@ipld/dag-cbor": "^9.0.6",
"@storacha/capabilities": "workspace:^",
"@storacha/one-webcrypto": "^1.0.1",
"@ucanto/core": "^10.0.1",
"@ucanto/interface": "^10.0.1",
"@storacha/capabilities": "workspace:^",
"carstream": "^2.1.0",
"multiformats": "^13.0.1",
"uint8arrays": "^5.0.3"
},
"devDependencies": {
"@ucanto/transport": "^9.1.1",
"@storacha/eslint-config": "workspace:^",
"@ucanto/transport": "^9.1.1",
"c8": "^7.14.0",
"entail": "^2.1.2",
"typescript": "5.2.2"
Expand Down
16 changes: 12 additions & 4 deletions packages/capabilities/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
"types": "./dist/test/helpers/*.d.ts",
"import": "./test/helpers/*.js"
},
"./blob": {
"types": "./dist/src/blob.d.ts",
"import": "./src/blob.js"
},
"./filecoin": {
"types": "./dist/src/filecoin/index.d.ts",
"import": "./src/filecoin/index.js"
Expand All @@ -57,9 +61,13 @@
"types": "./dist/src/filecoin/dealer.d.ts",
"import": "./src/filecoin/dealer.js"
},
"./index": {
"types": "./dist/src/index/index.d.ts",
"import": "./src/index/index.js"
"./space/index": {
"types": "./dist/src/space/index.d.ts",
"import": "./src/space/index.js"
},
"./space/blob": {
"types": "./dist/src/space/blob.d.ts",
"import": "./src/space/blob.js"
},
"./web3.storage/blob": {
"types": "./dist/src/web3.storage/blob.d.ts",
Expand Down Expand Up @@ -101,10 +109,10 @@
"uint8arrays": "^5.0.3"
},
"devDependencies": {
"@storacha/eslint-config": "workspace:^",
"@types/assert": "^1.5.6",
"@types/mocha": "^10.0.0",
"@types/node": "^20.8.4",
"@storacha/eslint-config": "workspace:^",
"assert": "^2.0.0",
"mocha": "^10.2.0",
"playwright-test": "^12.3.4",
Expand Down
2 changes: 1 addition & 1 deletion packages/capabilities/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import * as Filecoin from '@storacha/capabilities/filecoin'
import * as Aggregator from '@storacha/capabilities/filecoin/aggregator'
import * as DealTracker from '@storacha/capabilities/filecoin/deal-tracker'
import * as Dealer from '@storacha/capabilities/filecoin/dealer'
import * as Index from '@storacha/capabilities/index'
import * as Index from '@storacha/capabilities/space/index'

// This package has a "main" entrypoint but we recommend the usage of the specific imports above
```
Expand Down
200 changes: 56 additions & 144 deletions packages/capabilities/src/blob.js
Original file line number Diff line number Diff line change
@@ -1,177 +1,89 @@
/**
* Blob Capabilities.
*
* Blob is a fixed size byte array addressed by the multihash.
* Usually blobs are used to represent set of IPLD blocks at different byte ranges.
* The blob protocol allows authorized agents allocate memory space on a storage
* node and subsequently verify the content has been accepted by / delivered to
* said node.
*
* These can be imported directly with:
* ```js
* import * as Blob from '@storacha/capabilities/blob'
* import * as Index from '@storacha/capabilities/blob'
* ```
*
* @module
* @see https://github.com/storacha/specs/blob/main/w3-blob.md
*/
import { equals } from 'uint8arrays/equals'
import { capability, Schema, fail, ok } from '@ucanto/validator'
import { equalBlob, equalWith, SpaceDID } from './utils.js'

/**
* Agent capabilities for Blob protocol
*/
import { capability, Schema, Link, ok } from '@ucanto/validator'
import { content } from './space/blob.js'
import {
equalBlob,
equalWith,
SpaceDID,
and,
equal,
checkLink,
Await,
} from './utils.js'

/**
* Capability can only be delegated (but not invoked) allowing audience to
* derived any `space/blob/` prefixed capability for the (memory) space identified
* by DID in the `with` field.
* derive any `blob/` prefixed capability.
*/
export const blob = capability({
can: 'space/blob/*',
/**
* DID of the (memory) space where Blob is intended to
* be stored.
*/
with: SpaceDID,
can: 'blob/*',
/** Storage provider DID. */
with: Schema.did(),
derives: equalWith,
})

/**
* Blob description for being ingested by the service.
*/
export const content = Schema.struct({
/**
* A multihash digest of the blob payload bytes, uniquely identifying blob.
*/
digest: Schema.bytes(),
/**
* Number of bytes contained by this blob. Service will provision write target
* for this exact size. Attempt to write a larger Blob file will fail.
*/
size: Schema.integer(),
})

/**
* `space/blob/add` capability allows agent to store a Blob into a (memory) space
* identified by did:key in the `with` field. Agent should compute blob multihash
* and size and provide it under `nb.blob` field, allowing a service to provision
* a write location for the agent to PUT desired Blob into.
* The `blob/allocate` capability can be invoked to create a memory address on a
* storage node where blob content can be written via a HTTP PUT request.
*/
export const add = capability({
can: 'space/blob/add',
/**
* DID of the (memory) space where Blob is intended to
* be stored.
*/
with: SpaceDID,
export const allocate = capability({
can: 'blob/allocate',
/** Storage provider DID. */
with: Schema.did(),
nb: Schema.struct({
/**
* Blob to be added on the space.
*/
/** Blob to allocate. */
blob: content,
/** Link to the add blob task that initiated the allocation. */
cause: Schema.link({ version: 1 }),
/** DID of the user space where the allocation takes place. */
space: SpaceDID,
}),
derives: equalBlob,
})

/**
* Capability can be used to remove the stored Blob from the (memory)
* space identified by `with` field.
*/
export const remove = capability({
can: 'space/blob/remove',
/**
* DID of the (memory) space where Blob is stored.
*/
with: SpaceDID,
nb: Schema.struct({
/**
* A multihash digest of the blob payload bytes, uniquely identifying blob.
*/
digest: Schema.bytes(),
}),
derives: (claimed, delegated) => {
if (claimed.with !== delegated.with) {
return fail(
`Expected 'with: "${delegated.with}"' instead got '${claimed.with}'`
)
} else if (
delegated.nb.digest &&
!equals(delegated.nb.digest, claimed.nb.digest)
) {
return fail(
`Link ${
claimed.nb.digest ? `${claimed.nb.digest}` : ''
} violates imposed ${delegated.nb.digest} constraint.`
)
}
return ok({})
},
})

/**
* Capability can be invoked to request a list of stored Blobs in the
* (memory) space identified by `with` field.
*/
export const list = capability({
can: 'space/blob/list',
/**
* DID of the (memory) space where Blobs to be listed are stored.
*/
with: SpaceDID,
nb: Schema.struct({
/**
* A pointer that can be moved back and forth on the list.
* It can be used to paginate a list for instance.
*/
cursor: Schema.string().optional(),
/**
* Maximum number of items per page.
*/
size: Schema.integer().optional(),
}),
derives: (claimed, delegated) => {
if (claimed.with !== delegated.with) {
return fail(
`Expected 'with: "${delegated.with}"' instead got '${claimed.with}'`
)
}
return ok({})
},
derives: (claimed, delegated) =>
and(equalWith(claimed, delegated)) ||
and(equalBlob(claimed, delegated)) ||
and(checkLink(claimed.nb.cause, delegated.nb.cause, 'cause')) ||
and(equal(claimed.nb.space, delegated.nb.space, 'space')) ||
ok({}),
})

/**
* Capability can be used to get the stored Blob from the (memory)
* space identified by `with` field.
* The `blob/accept` capability invocation should either succeed when content is
* delivered on allocated address or fail if no content is allocation expires
* without content being delivered.
*/
export const get = capability({
can: 'space/blob/get/0/1',
/**
* DID of the (memory) space where Blob is stored.
*/
with: SpaceDID,
export const accept = capability({
can: 'blob/accept',
/** Storage provider DID. */
with: Schema.did(),
nb: Schema.struct({
/**
* A multihash digest of the blob payload bytes, uniquely identifying blob.
*/
digest: Schema.bytes(),
/** Blob to accept. */
blob: content,
/** DID of the user space where allocation took place. */
space: SpaceDID,
/** This task is blocked on `http/put` receipt available */
_put: Await,
}),
derives: (claimed, delegated) => {
if (claimed.with !== delegated.with) {
return fail(
`Expected 'with: "${delegated.with}"' instead got '${claimed.with}'`
)
} else if (
delegated.nb.digest &&
!equals(delegated.nb.digest, claimed.nb.digest)
) {
return fail(
`Link ${
claimed.nb.digest ? `${claimed.nb.digest}` : ''
} violates imposed ${delegated.nb.digest} constraint.`
)
}
return ok({})
},
derives: (claimed, delegated) =>
and(equalWith(claimed, delegated)) ||
and(equalBlob(claimed, delegated)) ||
and(equal(claimed.nb.space, delegated.nb.space, 'space')) ||
ok({}),
})

// ⚠️ We export imports here so they are not omitted in generated typedefs
// @see https://github.com/microsoft/TypeScript/issues/51548
export { Schema }
export { Schema, Link }
2 changes: 1 addition & 1 deletion packages/capabilities/src/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* @module
*/
import { capability, Schema, ok } from '@ucanto/validator'
import { content } from './blob.js'
import { content } from './space/blob.js'
import { equal, equalBody, equalWith, SpaceDID, Await, and } from './utils.js'

/**
Expand Down
Loading
Loading