Skip to content

Commit

Permalink
fix: add receipt endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos committed Jun 4, 2024
1 parent e429ae6 commit d2be2a4
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 4 deletions.
5 changes: 3 additions & 2 deletions can.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ import {

/**
* @param {string} [blobPath]
* @param {import('@web3-storage/w3up-client/types.js').RequestOptions} [options]
*/
export async function blobAdd(blobPath) {
export async function blobAdd(blobPath, options) {
const client = await getClient()

const spinner = ora('Reading data').start()
Expand All @@ -37,7 +38,7 @@ export async function blobAdd(blobPath) {
}

spinner.start('Storing')
const digest = await client.capability.blob.add(blob)
const digest = await client.capability.blob.add(blob, options)
const cid = Link.create(raw.code, digest)
spinner.stopAndPersist({ symbol: '⁂', text: `Stored ${base58btc.encode(digest.bytes)} (${cid})` })
}
Expand Down
8 changes: 7 additions & 1 deletion lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ export function getClient() {
process.env.W3UP_SERVICE_DID || process.env.W3_UPLOAD_SERVICE_DID
const uploadServiceURL =
process.env.W3UP_SERVICE_URL || process.env.W3_UPLOAD_SERVICE_URL
const receiptsEndpointString = (process.env.W3UP_RECEIPTS_ENDPOINT || process.env.W3_UPLOAD_RECEIPTS_URL)
let receiptsEndpoint
if (receiptsEndpointString) {
receiptsEndpoint = new URL(receiptsEndpointString)
}

let serviceConf
if (
accessServiceDID &&
Expand Down Expand Up @@ -134,7 +140,7 @@ export function getClient() {
}

/** @type {import('@web3-storage/w3up-client/types').ClientFactoryOptions} */
const createConfig = { store, serviceConf }
const createConfig = { store, serviceConf, receiptsEndpoint }

const principal = process.env.W3_PRINCIPAL
if (principal) {
Expand Down
2 changes: 2 additions & 0 deletions test/helpers/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,13 @@ export const setup = async () => {
storeName: `w3cli-test-alice-${context.service.did()}`,
servicePrincipal: context.service,
serviceURL: serverURL,
receiptsEndpoint: new URL('receipt', serverURL),
}),
bob: createEnv({
storeName: `w3cli-test-bob-${context.service.did()}`,
servicePrincipal: context.service,
serviceURL: serverURL,
receiptsEndpoint: new URL('receipt', serverURL),
}),
},
})
Expand Down
4 changes: 3 additions & 1 deletion test/helpers/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
* @param {import('@ucanto/interface').Principal} [options.servicePrincipal]
* @param {URL} [options.serviceURL]
* @param {string} [options.storeName]
* @param {URL} [options.receiptsEndpoint]
*/
export function createEnv(options = {}) {
const { servicePrincipal, serviceURL, storeName } = options
const { servicePrincipal, serviceURL, storeName, receiptsEndpoint } = options
const env = { W3_STORE_NAME: storeName ?? 'w3cli-test' }
if (servicePrincipal && serviceURL) {
Object.assign(env, {
W3UP_SERVICE_DID: servicePrincipal.did(),
W3UP_SERVICE_URL: serviceURL.toString(),
W3UP_RECEIPTS_ENDPOINT: receiptsEndpoint?.toString()
})
}
return env
Expand Down
51 changes: 51 additions & 0 deletions test/helpers/http-server.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import http from 'http'
import { once } from 'events'

import { parseLink } from '@ucanto/server'
import * as Signer from '@ucanto/principal/ed25519'
import { Receipt, Message } from '@ucanto/core'
import * as CAR from '@ucanto/transport/car'
import { Assert } from '@web3-storage/content-claims/capability'
import { randomCAR } from './random.js'

/**
* @typedef {import('@ucanto/interface').HTTPRequest<any>} HTTPRequest
* @typedef {import('@ucanto/server').HTTPResponse<any>} HTTPResponse
Expand All @@ -23,6 +30,14 @@ export async function createServer(router) {
* @param {http.ServerResponse} response
*/
const listener = async (request, response) => {
if (request.url?.includes('receipt')) {
const taskCid = request.url?.split('/')[1] ?? ''
const body = await generateReceipt(taskCid)
response.writeHead(200)
response.end(body)
return undefined
}

const chunks = []
for await (const chunk of request) {
chunks.push(chunk)
Expand Down Expand Up @@ -59,3 +74,39 @@ export async function createServer(router) {
serverURL: new URL(`http://127.0.0.1:${server.address().port}`),
}
}

/**
* @param {string} taskCid
*/
const generateReceipt = async (taskCid) => {
const issuer = await Signer.generate()
const content = (await randomCAR(128)).cid
const locationClaim = await Assert.location.delegate({
issuer,
audience: issuer,
with: issuer.toDIDKey(),
nb: {
content,
location: ['http://localhost'],
},
expiration: Infinity,
})

const receipt = await Receipt.issue({
issuer,
fx: {
fork: [locationClaim],
},
ran: parseLink(taskCid),
result: {
ok: {
site: locationClaim.link(),
},
},
})

const message = await Message.build({
receipts: [receipt],
})
return CAR.request.encode(message).body
}
61 changes: 61 additions & 0 deletions test/helpers/random.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { CarWriter } from '@ipld/car'
import * as CAR from '@ucanto/transport/car'
import { CID } from 'multiformats/cid'
import * as raw from 'multiformats/codecs/raw'
import { sha256 } from 'multiformats/hashes/sha2'

/** @param {number} size */
export async function randomBytes(size) {
const bytes = new Uint8Array(size)
while (size) {
const chunk = new Uint8Array(Math.min(size, 65_536))
if (!globalThis.crypto) {
try {
const { webcrypto } = await import('node:crypto')
webcrypto.getRandomValues(chunk)
} catch (err) {
throw new Error(
'unknown environment - no global crypto and not Node.js',
{ cause: err }
)
}
} else {
crypto.getRandomValues(chunk)
}
size -= chunk.length
bytes.set(chunk, size)
}
return bytes
}

/** @param {number} size */
export async function randomCAR(size) {
const bytes = await randomBytes(size)
return toCAR(bytes)
}

/** @param {Uint8Array} bytes */
export async function toBlock(bytes) {
const hash = await sha256.digest(bytes)
const cid = CID.createV1(raw.code, hash)
return { cid, bytes }
}

/**
* @param {Uint8Array} bytes
*/
export async function toCAR(bytes) {
const block = await toBlock(bytes)
const { writer, out } = CarWriter.create(block.cid)
writer.put(block)
writer.close()

const chunks = []
for await (const chunk of out) {
chunks.push(chunk)
}
const blob = new Blob(chunks)
const cid = await CAR.codec.link(new Uint8Array(await blob.arrayBuffer()))

return Object.assign(blob, { cid, roots: [block.cid] })
}

0 comments on commit d2be2a4

Please sign in to comment.