Open adamazad opened 2 months ago
Hi there - sorry to hear you're running into trouble!
Could you give us a bit more information about what you're doing? Are you using the CLI or the web console or a custom JS integration? Happy to help track this down, but can't really do anything with the information you've provided so far.
Hi @travis, my setup is explained in #1514. I'm delegating my frontend to upload a file directly to my web3.storage space.
curl 'https://up.web3.storage/' \
-H 'accept: application/vnd.ipld.car' \
-H 'accept-language: en-US,en;q=0.9,ar;q=0.8' \
-H 'cache-control: no-cache' \
-H 'content-type: application/vnd.ipld.car' \
-H 'origin: http://localhost:3000' \
-H 'pragma: no-cache' \
-H 'priority: u=1, i' \
-H 'referer: http://localhost:3000/' \
-H 'sec-ch-ua: "Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: cross-site' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36' \
--data-raw $':¢eroots\u0081Ø*X%\u0000\u0001q\u0012 M\u0007¸òì£ÓÈx\u0095\u0002²8ÿÝòMy\u008a\u0090¡¯%µhÃ\u0019+ð\u0098³\u0091gversion\u0001\u008b\u0006\u0001q\u0012 áw¶6\u009d(ÇZÍ\u009bV×fä\u000cZ]\u008d¿)Ê8Î\u001f{®\u008d\u0095\u0021\u001cK\u0080§asY\u0001\u0006\u0085¤À\u0006\u0080\u0002?˾kí\u0005¹øô¾;tÇ\u0019½2\u0089\u0088ôwª¿ÿg\u00083b*52-ea\u0021µt\u009dÐܨn²å4ncX\u0099\u001d \u0009TÅò}\u0008ª\u0005ÚÇEb\u0011\u0094\u0013gì¥~Ú-DE¨³G*Ó\u0085v©v$ú\u0089\u008a=#©\u009eª\u0088©=Îl\u0009ÿÇËU]\u0091;r<j\u001cþ\u0002C¥ØG£nàªÀ\u0092\u0003±5Ð\u0006=½\u0012@%¤U\u0010Å\u0089Ó\u00916@Ì5Ï¥/\u0008N\u0016æá\nò:Påù\u0005\u008d>M\u0008Î{"â\u000bö\u009déRݾNî|]\u0092óÍ\u0098o«uØæJ~\u001bäzl" ¼\u001f®ðMt\u001e\u0011ac%\u000cÊÚ\u0002RAÈQµ%3\u008b\u0010\u0094á´\u0013\u0002ËÈ\u0011\u0092)¤¨ø\u0087é\u0084\u001dkþä\u000e\u008c;×ôm\u0011¤°8ô#Û\u0011\u0002M+\u008dave0.9.1catt\u0081£bnb¡dblob¢dsize\u001a\u0000\u0095w}fdigestX"\u0012 ü\u009c5?¨æ\u001c\u0099$0p\u0002]X¹Q;:¨m\u0081ã|Y^¦D[\u0004\u009cÖ\u008bccannspace/blob/adddwithx8did:key:z6MkhcFUdVfVTnVPrACYvC29jzQizC6pW6KvmRScxCC6hbr8caudR\u009d\u001aweb:web3.storagecexp\u001af\u007f0McissY\u0001\u0010\u0085$0\u0082\u0001\n\u0002\u0082\u0001\u0001\u0000ß*pêkßL\u0082E\u0098à\u0081,~P\u0080ø\u0011å¡\u009dw&¨à\u0008\u0008¼,äÙd\u000fuÁ\u0004[#¥=\u0093/éÓTÌÛoÊsêS\u00019\u008b\u009dÜýD\u0094\u0005\u0081l´Ä\u008aoÍÎ\u0095\u0000)ùÈ\u000b\u0092\u009b¿æÃtÝ\u0093\u00927ëºa\u001f\u0019J\u001eZgïO]AÕìÞ\u0098B\u008cZi¬¦£b¾{F¢WéB³&\u001fZL\u0091ö\u00817³Pý?i\u0002\u0080ì\u0091¦wË\u0010\u0080\u0008nì\u008båÅ¡w\u007f5®ä\u000b9\u00099³¸P\u008f-\u0021¾J]~^ÞrkWrKD¢4\u0007p\u008fpÍÒ\u0019Ð\u001e\u00117\u0086£¡ã9* u*õù þ\u0009j1\u0010\u0003PÌ\u0085a3TPê»óÝe¢2B\u0007dy\u0081\u0016Çÿ\u0016µ\u0003\u0091\u001eF\u0011³\u0084ß^\u009eû÷`\u009dôk¢;\u0001(\u0001\u001bn\u008cº\u0085\u0002\u0003\u0001\u0000\u0001cprf\u0080m\u0001q\u0012 M\u0007¸òì£ÓÈx\u0095\u0002²8ÿÝòMy\u008a\u0090¡¯%µhÃ\u0019+ð\u0098³\u0091¡tucanto/message@7.0.0¡gexecute\u0081Ø*X%\u0000\u0001q\u0012 áw¶6\u009d(ÇZÍ\u009bV×fä\u000cZ]\u008d¿)Ê8Î\u001f{®\u008d\u0095\u0021\u001cK\u0080'
Thanks - do you have a repository anywhere with this code? #1514 has some basic coding errors so I suspect something similar is happening here, but without the code it's hard to tell.
I fixed the issues in #1514, and the fixed code yields the error above :)
Next.js backend
File: src/app/api/w3up/delegation/route.ts
import * as DID from '@ipld/dag-ucan/did';
import { getWeb3StorageClient } from './getWeb3StorageClient';
export async function GET() {
const web3StorageClient = await getWeb3StorageClient();
const did = web3StorageClient.did();
// Create a delegation for a specific DID
const audience = DID.parse(did);
const abilities = ['upload/add', 'blob/add', 'index/add', 'filecoin/offer'];
const expiration = Math.floor(Date.now() / 1000) + 60 * 60 * 24; // 24 hours from now
const delegation = await web3StorageClient.createDelegation(audience, abilities, {
expiration,
});
// Serialize the delegation and send it to the client
const archive = await delegation.archive();
const u4 = archive.ok;
return new Response(u4, {
status: 200,
});
}
File: src/app/api/w3up/delegation/getWeb3StorageClient.ts
import { CarReader } from '@ipld/car';
import { Block } from '@ipld/car/api';
import { importDAG } from '@ucanto/core/delegation';
import * as Signer from '@ucanto/principal/ed25519'; // Agents on Node should use Ed25519 keys
import * as Client from '@web3-storage/w3up-client';
import { StoreMemory } from '@web3-storage/w3up-client/stores/memory';
let _client: Client.Client | null = null;
/**
* Get a web3.storage client
* @returns {Promise<Client.Client>} A web3.storage client
*/
export async function getWeb3StorageClient() {
if (_client !== null) {
return _client;
}
const web3StorageKey = process.env.WEB3_STORAGE_KEY;
const web3StorageProof = process.env.WEB3_STORAGE_PROOF;
if (!web3StorageKey || !web3StorageProof) {
throw new Error('WEB3_STORAGE_KEY or WEB3_STORAGE_PROOF is not defined');
}
// from "bring your own Agent" example in `Creating a client object" section`
// used command line to generate KEY and PROOF (stored in env variables)
// KEY: `npx ucan-key ed --json` in command line, which returns private key and DID for Agent (the private key is stored in KEY)
// PROOF: w3cli used to run `w3 delegation create <did_from_ucan-key_command_above> --can 'store/add' --can 'upload/add' | base64`, which returns the delegation from Space to the Agent we're using (stored in PROOF)
const principal = Signer.parse(web3StorageKey);
const store = new StoreMemory();
_client = await Client.create({ principal, store });
// now give Agent the delegation from the Space
const proof = await parseProof(web3StorageProof);
const space = await _client.addSpace(proof);
await _client.setCurrentSpace(space.did());
return _client;
}
/** @param {string} data Base64 encoded CAR file */
async function parseProof(data: string) {
const blocks: Block[] = [];
const reader = await CarReader.fromBytes(Buffer.from(data, 'base64'));
for await (const block of reader.blocks()) {
blocks.push(block);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return importDAG(blocks as any);
}
Frontend
File: src/api/hooks/useWeb3StorageClient.ts
import * as Delegation from '@ucanto/core/delegation';
import * as Client from '@web3-storage/w3up-client';
import { useEffect, useState } from 'react';
export async function getWeb3StorageClient(): Promise<{
error: Error | null;
client: Client.Client | null;
}> {
try {
// Fetch the delegation from the backend
const response = await fetch(`/api/w3up/delegation`);
const data = await response.arrayBuffer();
const delegationUint8Array = new Uint8Array(data);
const client = await Client.create();
// Deserialize the delegation
const delegation = await Delegation.extract(delegationUint8Array);
if (!delegation.ok) {
throw delegation.error as Error;
}
// Add proof that this agent has been delegated capabilities on the space
const space = await client.addSpace(delegation.ok);
client.setCurrentSpace(space.did());
return {
error: null,
client,
};
} catch (error) {
return {
error: error as Error,
client: null,
};
}
}
export function useWeb3StorageClient() {
const [ready, setReady] = useState(false);
const [client, setClient] = useState<Client.Client | null>(null);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
if (ready) {
return;
}
getWeb3StorageClient().then(({ error, client }) => {
if (error) {
console.error(error);
setReady(false);
setClient(null);
setError(error);
return;
}
setClient(client);
setReady(true);
setError(null);
});
}, []);
return { ready, client, error };
}
This setup works and I can create a frontend delegated W3up client, but when I try it pin files I get the error in the first message :)
ok thank you! may not be able to get back to this until early next week, but I've checked in with a colleague and we'll get back to you asap
@travis, any update regarding this issue? Thanks!
@travis pinging this again :)
@adamazad I am having problems with the CarReader.fromBytes
function, which package version are you guys using?
This is the following error:
Error: CBOR decode error: too many terminals, data makes no sense
at Module.decode (webpack-internal:///(rsc)/./node_modules/cborg/lib/decode.js:214:11)
And I generated the proof from the following command w3 delegation create <did_from_ucan-key_command_above> --can 'store/add' --can 'upload/add' --base64
@adamazad the error is saying you don't have space/blob/add
capability. Your code looks like it is delegating blob/add
and index/add
and should be delegating space/blob/add
and space/index/add
.
What are these two parameters? const web3StorageKey = process.env.WEB3_STORAGE_KEY; const web3StorageProof = process.env.WEB3_STORAGE_PROOF; I can't find
Hi, I'm getting the following error when trying to pin a blob via delegated agent to use my space: