1// Blossom from the outside: the kind 24242 token and an upload.2import { SELF } from "cloudflare:test";3import { sha256 } from "@noble/hashes/sha2.js";4import { bytesToHex } from "../../src/negentropy.ts";5import { ev, now } from "./relay.ts";67// blossomToken mints a kind 24242 token for an action, naming a hash when given.8export const blossomToken = (sk: Uint8Array, action: string, sha?: string) =>9 "Nostr " + btoa(JSON.stringify(ev(sk, 24242, action, [["t", action], ...(sha ? [["x", sha]] : []), ["expiration", String(now() + 300)]])));1011// upload puts a text file and returns its hash with the descriptor, when there is one.12export async function upload(host: string, sk: Uint8Array, text: string) {13 const body = new TextEncoder().encode(text);14 const sha = bytesToHex(sha256(body));15 const resp = await SELF.fetch(`http://${host}/upload`, { method: "PUT", headers: { authorization: blossomToken(sk, "upload", sha), "content-type": "text/plain" }, body });16 const raw = await resp.text();17 let answer: any = null;18 try {19 answer = raw ? JSON.parse(raw) : null;20 } catch {21 answer = raw; // a door that is not there answers with text22 }23 return { status: resp.status, sha, body: answer };24}