@elisym/sdk 0.24.1 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -527,6 +527,44 @@ interface BuildTransactionOptions {
527
527
  programId?: Address;
528
528
  }
529
529
 
530
+ /** Result of an upload. */
531
+ interface BlobDescriptor {
532
+ /**
533
+ * Publicly GET-able URL. Content-addressed (https://<host>/<sha256>.<ext>) ONLY when
534
+ * `provider === 'blossom'`; on `'fallback'` it is a provider-assigned nostr.build URL
535
+ * that may NOT be addressed by `sha256` (the host may re-encode the bytes).
536
+ */
537
+ url: string;
538
+ /**
539
+ * Lowercase-hex SHA-256 of the bytes the caller uploaded. On `'blossom'` it is also
540
+ * verified to equal what the server stored (integrity check). On `'fallback'` it is the
541
+ * local hash only - do NOT assume `url` resolves to it.
542
+ */
543
+ sha256: string;
544
+ size: number;
545
+ type: string;
546
+ /** Unix seconds; only the Blossom path returns it. */
547
+ uploaded?: number;
548
+ provider: 'blossom' | 'fallback';
549
+ }
550
+ /** Fallback uploader invoked when the Blossom upload fails; returns the stored URL. */
551
+ type BlossomUploadFallback = (identity: ElisymIdentity, file: Blob) => Promise<string>;
552
+ declare class BlossomService {
553
+ private serverUrl;
554
+ private fallback?;
555
+ constructor(serverUrl?: string, fallback?: BlossomUploadFallback | undefined);
556
+ /**
557
+ * Upload a file to the Blossom server, returning its descriptor. On any failure, falls
558
+ * back to the configured uploader (if any) and returns a normalized descriptor with
559
+ * `provider: 'fallback'`. Works with browser File objects and Node.js/Bun Blobs.
560
+ */
561
+ upload(identity: ElisymIdentity, file: Blob): Promise<BlobDescriptor>;
562
+ /** Delete a blob by sha256 (BUD-02). Blossom only - there is no fallback for deletes. */
563
+ delete(identity: ElisymIdentity, sha256: string): Promise<void>;
564
+ private uploadToBlossom;
565
+ private authHeader;
566
+ }
567
+
530
568
  declare class NostrPool {
531
569
  private pool;
532
570
  private relays;
@@ -855,6 +893,8 @@ interface ElisymClientFullConfig extends ElisymClientConfig {
855
893
  payment?: PaymentStrategy;
856
894
  /** Custom upload URL for file uploads (defaults to nostr.build). */
857
895
  uploadUrl?: string;
896
+ /** Custom Blossom server base URL for blob uploads (defaults to files.elisym.network). */
897
+ blossomUrl?: string;
858
898
  }
859
899
  declare class ElisymClient {
860
900
  readonly pool: NostrPool;
@@ -862,6 +902,7 @@ declare class ElisymClient {
862
902
  readonly marketplace: MarketplaceService;
863
903
  readonly ping: PingService;
864
904
  readonly media: MediaService;
905
+ readonly blossom: BlossomService;
865
906
  readonly policies: PoliciesService;
866
907
  readonly payment: PaymentStrategy;
867
908
  constructor(config?: ElisymClientFullConfig);
@@ -1478,6 +1519,7 @@ declare const DEFAULTS: {
1478
1519
  readonly QUERY_MAX_CONCURRENCY: 6;
1479
1520
  readonly VERIFY_SIGNATURE_LIMIT: 25;
1480
1521
  readonly IROH_FETCH_TIMEOUT_MS: 300000;
1522
+ readonly BLOSSOM_UPLOAD_TIMEOUT_MS: 300000;
1481
1523
  };
1482
1524
  /** Protocol limits for input validation. */
1483
1525
  declare const LIMITS: {
@@ -1506,4 +1548,4 @@ declare const LIMITS: {
1506
1548
  */
1507
1549
  declare function utf8ByteLength(value: string): number;
1508
1550
 
1509
- export { type Agent, type AgentPolicy, type AggregateNetworkStatsOptions, Asset, BoundedSet, type BuildTransactionOptions, type CapabilityCard, DEFAULTS, DEFAULT_KIND_OFFSET, DEFAULT_REDACT_PATHS, type DecodedJobPayload, DiscoveryService, ELISYM_PROTOCOL_TAG, ENVELOPE_VERSION, ElisymClient, type ElisymClientConfig, type ElisymClientFullConfig, ElisymIdentity, type EstimatePriorityFeeOptions, type EstimateSolFeeOptions, type FileAttachment, type FileTransport, type GetProtocolConfigOptions, INPUT_REDACT_PATHS, type Job, type JobErrorKind, type JobPayloadEnvelope, type JobStatus, type JobSubscriptionOptions, type JobUpdateCallbacks, JobWaitTimeoutError, KIND_APP_HANDLER, KIND_JOB_FEEDBACK, KIND_JOB_REQUEST, KIND_JOB_REQUEST_BASE, KIND_JOB_RESULT, KIND_JOB_RESULT_BASE, KIND_LONG_FORM_ARTICLE, KIND_PING, KIND_PONG, LAMPORTS_PER_SOL, LIMITS, MarketplaceService, MediaService, type Network, type NetworkBaselineEstimate, type NetworkBaselineOptions, type NetworkStats, type NetworkStatsResult, NostrPool, type OnchainNetworkStats, POLICY_D_TAG_PREFIX, POLICY_TYPE_REGEX, POLICY_T_TAG, PROTOCOL_PROGRAM_ID_DEVNET, type ParseOptions, type ParseResult, type ParsedPaymentRequest, type PaymentAssetRef, type PaymentInfo, type PaymentRequestData, PaymentRequestSchema, type PaymentStrategy, type PaymentValidationCode, type PaymentValidationError, type PingResult, PingService, PoliciesService, type PolicyInput, type ProtocolCluster, type ProtocolConfig, type ProtocolConfigInput, type QuickVerifyReason, type QuickVerifyResult, RELAYS, type RankKey, SECRET_REDACT_PATHS, type Signer, type SolFeeEstimate, SolanaPaymentStrategy, type SubCloser, type SubmitJobOptions, type VerifyOptions, type VerifyResult, aggregateNetworkStats, assertExpiry, assertLamports, buildPaymentInstructions, calculateProtocolFee, classifyJobError, clearPriorityFeeCache, clearProtocolConfigCache, clearQuickVerifyCache, compareAgentsByRank, computeRankKey, createPaymentRequestWithOnchainConfig, decodeJobPayload, encodeJobPayload, estimateNetworkBaseline, estimatePriorityFeeMicroLamports, estimateSolFeeLamports, formatFeeBreakdown, formatNetworkBaseline, formatSol, getNetworkStats, getProtocolConfig, getProtocolProgramId, jobRequestKind, jobResultKind, makeCensor, nip44Decrypt, nip44Encrypt, parsePaymentRequest, pickPercentileFee, timeAgo, toDTag, truncateKey, utf8ByteLength, validateAgentName, validateExpiry, verifyJobPaymentQuick };
1551
+ export { type Agent, type AgentPolicy, type AggregateNetworkStatsOptions, Asset, type BlobDescriptor, BlossomService, type BlossomUploadFallback, BoundedSet, type BuildTransactionOptions, type CapabilityCard, DEFAULTS, DEFAULT_KIND_OFFSET, DEFAULT_REDACT_PATHS, type DecodedJobPayload, DiscoveryService, ELISYM_PROTOCOL_TAG, ENVELOPE_VERSION, ElisymClient, type ElisymClientConfig, type ElisymClientFullConfig, ElisymIdentity, type EstimatePriorityFeeOptions, type EstimateSolFeeOptions, type FileAttachment, type FileTransport, type GetProtocolConfigOptions, INPUT_REDACT_PATHS, type Job, type JobErrorKind, type JobPayloadEnvelope, type JobStatus, type JobSubscriptionOptions, type JobUpdateCallbacks, JobWaitTimeoutError, KIND_APP_HANDLER, KIND_JOB_FEEDBACK, KIND_JOB_REQUEST, KIND_JOB_REQUEST_BASE, KIND_JOB_RESULT, KIND_JOB_RESULT_BASE, KIND_LONG_FORM_ARTICLE, KIND_PING, KIND_PONG, LAMPORTS_PER_SOL, LIMITS, MarketplaceService, MediaService, type Network, type NetworkBaselineEstimate, type NetworkBaselineOptions, type NetworkStats, type NetworkStatsResult, NostrPool, type OnchainNetworkStats, POLICY_D_TAG_PREFIX, POLICY_TYPE_REGEX, POLICY_T_TAG, PROTOCOL_PROGRAM_ID_DEVNET, type ParseOptions, type ParseResult, type ParsedPaymentRequest, type PaymentAssetRef, type PaymentInfo, type PaymentRequestData, PaymentRequestSchema, type PaymentStrategy, type PaymentValidationCode, type PaymentValidationError, type PingResult, PingService, PoliciesService, type PolicyInput, type ProtocolCluster, type ProtocolConfig, type ProtocolConfigInput, type QuickVerifyReason, type QuickVerifyResult, RELAYS, type RankKey, SECRET_REDACT_PATHS, type Signer, type SolFeeEstimate, SolanaPaymentStrategy, type SubCloser, type SubmitJobOptions, type VerifyOptions, type VerifyResult, aggregateNetworkStats, assertExpiry, assertLamports, buildPaymentInstructions, calculateProtocolFee, classifyJobError, clearPriorityFeeCache, clearProtocolConfigCache, clearQuickVerifyCache, compareAgentsByRank, computeRankKey, createPaymentRequestWithOnchainConfig, decodeJobPayload, encodeJobPayload, estimateNetworkBaseline, estimatePriorityFeeMicroLamports, estimateSolFeeLamports, formatFeeBreakdown, formatNetworkBaseline, formatSol, getNetworkStats, getProtocolConfig, getProtocolProgramId, jobRequestKind, jobResultKind, makeCensor, nip44Decrypt, nip44Encrypt, parsePaymentRequest, pickPercentileFee, timeAgo, toDTag, truncateKey, utf8ByteLength, validateAgentName, validateExpiry, verifyJobPaymentQuick };
package/dist/index.d.ts CHANGED
@@ -527,6 +527,44 @@ interface BuildTransactionOptions {
527
527
  programId?: Address;
528
528
  }
529
529
 
530
+ /** Result of an upload. */
531
+ interface BlobDescriptor {
532
+ /**
533
+ * Publicly GET-able URL. Content-addressed (https://<host>/<sha256>.<ext>) ONLY when
534
+ * `provider === 'blossom'`; on `'fallback'` it is a provider-assigned nostr.build URL
535
+ * that may NOT be addressed by `sha256` (the host may re-encode the bytes).
536
+ */
537
+ url: string;
538
+ /**
539
+ * Lowercase-hex SHA-256 of the bytes the caller uploaded. On `'blossom'` it is also
540
+ * verified to equal what the server stored (integrity check). On `'fallback'` it is the
541
+ * local hash only - do NOT assume `url` resolves to it.
542
+ */
543
+ sha256: string;
544
+ size: number;
545
+ type: string;
546
+ /** Unix seconds; only the Blossom path returns it. */
547
+ uploaded?: number;
548
+ provider: 'blossom' | 'fallback';
549
+ }
550
+ /** Fallback uploader invoked when the Blossom upload fails; returns the stored URL. */
551
+ type BlossomUploadFallback = (identity: ElisymIdentity, file: Blob) => Promise<string>;
552
+ declare class BlossomService {
553
+ private serverUrl;
554
+ private fallback?;
555
+ constructor(serverUrl?: string, fallback?: BlossomUploadFallback | undefined);
556
+ /**
557
+ * Upload a file to the Blossom server, returning its descriptor. On any failure, falls
558
+ * back to the configured uploader (if any) and returns a normalized descriptor with
559
+ * `provider: 'fallback'`. Works with browser File objects and Node.js/Bun Blobs.
560
+ */
561
+ upload(identity: ElisymIdentity, file: Blob): Promise<BlobDescriptor>;
562
+ /** Delete a blob by sha256 (BUD-02). Blossom only - there is no fallback for deletes. */
563
+ delete(identity: ElisymIdentity, sha256: string): Promise<void>;
564
+ private uploadToBlossom;
565
+ private authHeader;
566
+ }
567
+
530
568
  declare class NostrPool {
531
569
  private pool;
532
570
  private relays;
@@ -855,6 +893,8 @@ interface ElisymClientFullConfig extends ElisymClientConfig {
855
893
  payment?: PaymentStrategy;
856
894
  /** Custom upload URL for file uploads (defaults to nostr.build). */
857
895
  uploadUrl?: string;
896
+ /** Custom Blossom server base URL for blob uploads (defaults to files.elisym.network). */
897
+ blossomUrl?: string;
858
898
  }
859
899
  declare class ElisymClient {
860
900
  readonly pool: NostrPool;
@@ -862,6 +902,7 @@ declare class ElisymClient {
862
902
  readonly marketplace: MarketplaceService;
863
903
  readonly ping: PingService;
864
904
  readonly media: MediaService;
905
+ readonly blossom: BlossomService;
865
906
  readonly policies: PoliciesService;
866
907
  readonly payment: PaymentStrategy;
867
908
  constructor(config?: ElisymClientFullConfig);
@@ -1478,6 +1519,7 @@ declare const DEFAULTS: {
1478
1519
  readonly QUERY_MAX_CONCURRENCY: 6;
1479
1520
  readonly VERIFY_SIGNATURE_LIMIT: 25;
1480
1521
  readonly IROH_FETCH_TIMEOUT_MS: 300000;
1522
+ readonly BLOSSOM_UPLOAD_TIMEOUT_MS: 300000;
1481
1523
  };
1482
1524
  /** Protocol limits for input validation. */
1483
1525
  declare const LIMITS: {
@@ -1506,4 +1548,4 @@ declare const LIMITS: {
1506
1548
  */
1507
1549
  declare function utf8ByteLength(value: string): number;
1508
1550
 
1509
- export { type Agent, type AgentPolicy, type AggregateNetworkStatsOptions, Asset, BoundedSet, type BuildTransactionOptions, type CapabilityCard, DEFAULTS, DEFAULT_KIND_OFFSET, DEFAULT_REDACT_PATHS, type DecodedJobPayload, DiscoveryService, ELISYM_PROTOCOL_TAG, ENVELOPE_VERSION, ElisymClient, type ElisymClientConfig, type ElisymClientFullConfig, ElisymIdentity, type EstimatePriorityFeeOptions, type EstimateSolFeeOptions, type FileAttachment, type FileTransport, type GetProtocolConfigOptions, INPUT_REDACT_PATHS, type Job, type JobErrorKind, type JobPayloadEnvelope, type JobStatus, type JobSubscriptionOptions, type JobUpdateCallbacks, JobWaitTimeoutError, KIND_APP_HANDLER, KIND_JOB_FEEDBACK, KIND_JOB_REQUEST, KIND_JOB_REQUEST_BASE, KIND_JOB_RESULT, KIND_JOB_RESULT_BASE, KIND_LONG_FORM_ARTICLE, KIND_PING, KIND_PONG, LAMPORTS_PER_SOL, LIMITS, MarketplaceService, MediaService, type Network, type NetworkBaselineEstimate, type NetworkBaselineOptions, type NetworkStats, type NetworkStatsResult, NostrPool, type OnchainNetworkStats, POLICY_D_TAG_PREFIX, POLICY_TYPE_REGEX, POLICY_T_TAG, PROTOCOL_PROGRAM_ID_DEVNET, type ParseOptions, type ParseResult, type ParsedPaymentRequest, type PaymentAssetRef, type PaymentInfo, type PaymentRequestData, PaymentRequestSchema, type PaymentStrategy, type PaymentValidationCode, type PaymentValidationError, type PingResult, PingService, PoliciesService, type PolicyInput, type ProtocolCluster, type ProtocolConfig, type ProtocolConfigInput, type QuickVerifyReason, type QuickVerifyResult, RELAYS, type RankKey, SECRET_REDACT_PATHS, type Signer, type SolFeeEstimate, SolanaPaymentStrategy, type SubCloser, type SubmitJobOptions, type VerifyOptions, type VerifyResult, aggregateNetworkStats, assertExpiry, assertLamports, buildPaymentInstructions, calculateProtocolFee, classifyJobError, clearPriorityFeeCache, clearProtocolConfigCache, clearQuickVerifyCache, compareAgentsByRank, computeRankKey, createPaymentRequestWithOnchainConfig, decodeJobPayload, encodeJobPayload, estimateNetworkBaseline, estimatePriorityFeeMicroLamports, estimateSolFeeLamports, formatFeeBreakdown, formatNetworkBaseline, formatSol, getNetworkStats, getProtocolConfig, getProtocolProgramId, jobRequestKind, jobResultKind, makeCensor, nip44Decrypt, nip44Encrypt, parsePaymentRequest, pickPercentileFee, timeAgo, toDTag, truncateKey, utf8ByteLength, validateAgentName, validateExpiry, verifyJobPaymentQuick };
1551
+ export { type Agent, type AgentPolicy, type AggregateNetworkStatsOptions, Asset, type BlobDescriptor, BlossomService, type BlossomUploadFallback, BoundedSet, type BuildTransactionOptions, type CapabilityCard, DEFAULTS, DEFAULT_KIND_OFFSET, DEFAULT_REDACT_PATHS, type DecodedJobPayload, DiscoveryService, ELISYM_PROTOCOL_TAG, ENVELOPE_VERSION, ElisymClient, type ElisymClientConfig, type ElisymClientFullConfig, ElisymIdentity, type EstimatePriorityFeeOptions, type EstimateSolFeeOptions, type FileAttachment, type FileTransport, type GetProtocolConfigOptions, INPUT_REDACT_PATHS, type Job, type JobErrorKind, type JobPayloadEnvelope, type JobStatus, type JobSubscriptionOptions, type JobUpdateCallbacks, JobWaitTimeoutError, KIND_APP_HANDLER, KIND_JOB_FEEDBACK, KIND_JOB_REQUEST, KIND_JOB_REQUEST_BASE, KIND_JOB_RESULT, KIND_JOB_RESULT_BASE, KIND_LONG_FORM_ARTICLE, KIND_PING, KIND_PONG, LAMPORTS_PER_SOL, LIMITS, MarketplaceService, MediaService, type Network, type NetworkBaselineEstimate, type NetworkBaselineOptions, type NetworkStats, type NetworkStatsResult, NostrPool, type OnchainNetworkStats, POLICY_D_TAG_PREFIX, POLICY_TYPE_REGEX, POLICY_T_TAG, PROTOCOL_PROGRAM_ID_DEVNET, type ParseOptions, type ParseResult, type ParsedPaymentRequest, type PaymentAssetRef, type PaymentInfo, type PaymentRequestData, PaymentRequestSchema, type PaymentStrategy, type PaymentValidationCode, type PaymentValidationError, type PingResult, PingService, PoliciesService, type PolicyInput, type ProtocolCluster, type ProtocolConfig, type ProtocolConfigInput, type QuickVerifyReason, type QuickVerifyResult, RELAYS, type RankKey, SECRET_REDACT_PATHS, type Signer, type SolFeeEstimate, SolanaPaymentStrategy, type SubCloser, type SubmitJobOptions, type VerifyOptions, type VerifyResult, aggregateNetworkStats, assertExpiry, assertLamports, buildPaymentInstructions, calculateProtocolFee, classifyJobError, clearPriorityFeeCache, clearProtocolConfigCache, clearQuickVerifyCache, compareAgentsByRank, computeRankKey, createPaymentRequestWithOnchainConfig, decodeJobPayload, encodeJobPayload, estimateNetworkBaseline, estimatePriorityFeeMicroLamports, estimateSolFeeLamports, formatFeeBreakdown, formatNetworkBaseline, formatSol, getNetworkStats, getProtocolConfig, getProtocolProgramId, jobRequestKind, jobResultKind, makeCensor, nip44Decrypt, nip44Encrypt, parsePaymentRequest, pickPercentileFee, timeAgo, toDTag, truncateKey, utf8ByteLength, validateAgentName, validateExpiry, verifyJobPaymentQuick };
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { getTransferSolInstruction } from '@solana-program/system';
4
4
  import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS, getCreateAssociatedTokenIdempotentInstruction, ASSOCIATED_TOKEN_PROGRAM_ADDRESS, getTransferCheckedInstruction } from '@solana-program/token';
5
5
  import Decimal3 from 'decimal.js-light';
6
6
  import { z } from 'zod';
7
- import { verifyEvent, finalizeEvent, getPublicKey, nip19, generateSecretKey, SimplePool } from 'nostr-tools';
7
+ import { finalizeEvent, verifyEvent, getPublicKey, nip19, generateSecretKey, SimplePool } from 'nostr-tools';
8
8
  import * as nip44 from 'nostr-tools/nip44';
9
9
 
10
10
  // src/constants.ts
@@ -72,7 +72,10 @@ var DEFAULTS = {
72
72
  // Default ceiling for a single iroh file transfer (seed/fetch). A tunable
73
73
  // default, not a protocol constant - the transfer is resumable and its own
74
74
  // budget, decoupled from the result-wait window.
75
- IROH_FETCH_TIMEOUT_MS: 3e5
75
+ IROH_FETCH_TIMEOUT_MS: 3e5,
76
+ // Ceiling for a single Blossom blob upload (PUT /upload). Large blobs (up to
77
+ // LIMITS.MAX_FILE_SIZE) need far more than the 30s used for small media images.
78
+ BLOSSOM_UPLOAD_TIMEOUT_MS: 3e5
76
79
  };
77
80
  var LIMITS = {
78
81
  MAX_INPUT_LENGTH: 1e5,
@@ -1175,6 +1178,124 @@ async function createPaymentRequestWithOnchainConfig(rpc, programId, recipient,
1175
1178
  options
1176
1179
  );
1177
1180
  }
1181
+ var KIND_BLOSSOM_AUTH = 24242;
1182
+ var DEFAULT_BLOSSOM_URL = "https://files.elisym.network";
1183
+ var AUTH_TTL_SECS = 600;
1184
+ var BlossomService = class {
1185
+ constructor(serverUrl = DEFAULT_BLOSSOM_URL, fallback) {
1186
+ this.serverUrl = serverUrl;
1187
+ this.fallback = fallback;
1188
+ }
1189
+ /**
1190
+ * Upload a file to the Blossom server, returning its descriptor. On any failure, falls
1191
+ * back to the configured uploader (if any) and returns a normalized descriptor with
1192
+ * `provider: 'fallback'`. Works with browser File objects and Node.js/Bun Blobs.
1193
+ */
1194
+ async upload(identity, file) {
1195
+ const bytes = new Uint8Array(await file.arrayBuffer());
1196
+ if (bytes.byteLength > LIMITS.MAX_FILE_SIZE) {
1197
+ throw new Error(
1198
+ `File too large: ${bytes.byteLength} bytes exceeds limit of ${LIMITS.MAX_FILE_SIZE}.`
1199
+ );
1200
+ }
1201
+ const hashBuffer = await crypto.subtle.digest("SHA-256", bytes);
1202
+ const hashHex = [...new Uint8Array(hashBuffer)].map((b) => b.toString(16).padStart(2, "0")).join("");
1203
+ try {
1204
+ return await this.uploadToBlossom(identity, bytes, hashHex, file.type);
1205
+ } catch (err) {
1206
+ if (!this.fallback) {
1207
+ throw err;
1208
+ }
1209
+ const url = await this.fallback(identity, file);
1210
+ return {
1211
+ url,
1212
+ sha256: hashHex,
1213
+ size: file.size,
1214
+ type: file.type || "application/octet-stream",
1215
+ provider: "fallback"
1216
+ };
1217
+ }
1218
+ }
1219
+ /** Delete a blob by sha256 (BUD-02). Blossom only - there is no fallback for deletes. */
1220
+ async delete(identity, sha256) {
1221
+ if (!/^[0-9a-f]{64}$/.test(sha256)) {
1222
+ throw new Error("sha256 must be 64 lowercase hex chars.");
1223
+ }
1224
+ const authHeader = this.authHeader(identity, "delete", sha256);
1225
+ const controller = new AbortController();
1226
+ const timer = setTimeout(() => controller.abort(), DEFAULTS.BLOSSOM_UPLOAD_TIMEOUT_MS);
1227
+ try {
1228
+ const res = await fetch(`${this.serverUrl}/${sha256}`, {
1229
+ method: "DELETE",
1230
+ headers: { Authorization: authHeader },
1231
+ signal: controller.signal
1232
+ });
1233
+ if (!res.ok) {
1234
+ throw new Error(`Delete failed: ${res.status} ${res.statusText}`);
1235
+ }
1236
+ } finally {
1237
+ clearTimeout(timer);
1238
+ }
1239
+ }
1240
+ async uploadToBlossom(identity, bytes, hashHex, mime) {
1241
+ const contentType = mime || "application/octet-stream";
1242
+ const authHeader = this.authHeader(identity, "upload", hashHex);
1243
+ const controller = new AbortController();
1244
+ const timer = setTimeout(() => controller.abort(), DEFAULTS.BLOSSOM_UPLOAD_TIMEOUT_MS);
1245
+ try {
1246
+ const res = await fetch(`${this.serverUrl}/upload`, {
1247
+ method: "PUT",
1248
+ headers: { Authorization: authHeader, "Content-Type": contentType },
1249
+ body: bytes,
1250
+ signal: controller.signal
1251
+ });
1252
+ if (!res.ok) {
1253
+ throw new Error(`Upload failed: ${res.status} ${res.statusText}`);
1254
+ }
1255
+ let data;
1256
+ try {
1257
+ data = await res.json();
1258
+ } catch {
1259
+ throw new Error("Invalid response from Blossom server.");
1260
+ }
1261
+ if (!data.url || !data.sha256) {
1262
+ throw new Error("No descriptor returned from Blossom server.");
1263
+ }
1264
+ if (data.sha256 !== hashHex) {
1265
+ throw new Error(
1266
+ `Blossom upload integrity check failed: server returned ${data.sha256}, expected ${hashHex}.`
1267
+ );
1268
+ }
1269
+ return {
1270
+ url: data.url,
1271
+ sha256: data.sha256,
1272
+ size: data.size ?? bytes.byteLength,
1273
+ type: data.type ?? contentType,
1274
+ uploaded: data.uploaded,
1275
+ provider: "blossom"
1276
+ };
1277
+ } finally {
1278
+ clearTimeout(timer);
1279
+ }
1280
+ }
1281
+ authHeader(identity, verb, sha256) {
1282
+ const now = Math.floor(Date.now() / 1e3);
1283
+ const authEvent = finalizeEvent(
1284
+ {
1285
+ kind: KIND_BLOSSOM_AUTH,
1286
+ created_at: now,
1287
+ tags: [
1288
+ ["t", verb],
1289
+ ["x", sha256],
1290
+ ["expiration", String(now + AUTH_TTL_SECS)]
1291
+ ],
1292
+ content: `${verb} blob via elisym SDK`
1293
+ },
1294
+ identity.secretKey
1295
+ );
1296
+ return "Nostr " + btoa(JSON.stringify(authEvent));
1297
+ }
1298
+ };
1178
1299
  var RANKING_ACTIVITY_WINDOW_SECS = 30 * 24 * 60 * 60;
1179
1300
  var RANKING_BUCKET_SIZE_SECS = 60;
1180
1301
  var COLD_START_BUCKET = -Infinity;
@@ -3338,6 +3459,7 @@ var ElisymClient = class {
3338
3459
  marketplace;
3339
3460
  ping;
3340
3461
  media;
3462
+ blossom;
3341
3463
  policies;
3342
3464
  payment;
3343
3465
  constructor(config = {}) {
@@ -3346,6 +3468,10 @@ var ElisymClient = class {
3346
3468
  this.marketplace = new MarketplaceService(this.pool);
3347
3469
  this.ping = new PingService(this.pool);
3348
3470
  this.media = new MediaService(config.uploadUrl);
3471
+ this.blossom = new BlossomService(
3472
+ config.blossomUrl,
3473
+ (identity, file) => this.media.upload(identity, file)
3474
+ );
3349
3475
  this.policies = new PoliciesService(this.pool);
3350
3476
  this.payment = config.payment ?? new SolanaPaymentStrategy();
3351
3477
  }
@@ -3925,6 +4051,6 @@ function makeCensor() {
3925
4051
  };
3926
4052
  }
3927
4053
 
3928
- export { BoundedSet, DEFAULTS, DEFAULT_KIND_OFFSET, DEFAULT_REDACT_PATHS, DiscoveryService, ELISYM_PROTOCOL_TAG, ENVELOPE_VERSION, ElisymClient, ElisymIdentity, GlobalConfigSchema, INPUT_REDACT_PATHS, JobWaitTimeoutError, KIND_APP_HANDLER, KIND_JOB_FEEDBACK, KIND_JOB_REQUEST, KIND_JOB_REQUEST_BASE, KIND_JOB_RESULT, KIND_JOB_RESULT_BASE, KIND_LONG_FORM_ARTICLE, KIND_PING, KIND_PONG, KNOWN_ASSETS, LAMPORTS_PER_SOL, LIMITS, MarketplaceService, MediaService, NATIVE_SOL, NostrPool, POLICY_D_TAG_PREFIX, POLICY_TYPE_REGEX, POLICY_T_TAG, PROTOCOL_PROGRAM_ID_DEVNET, PaymentRequestSchema, PingService, PoliciesService, RELAYS, SECRET_REDACT_PATHS, SessionSpendLimitEntrySchema, SolanaPaymentStrategy, USDC_SOLANA_DEVNET, aggregateNetworkStats, assertExpiry, assertLamports, assetByKey, assetKey, buildPaymentInstructions, calculateProtocolFee, classifyJobError, clearPriorityFeeCache, clearProtocolConfigCache, clearQuickVerifyCache, compareAgentsByRank, computeRankKey, createPaymentRequestWithOnchainConfig, createSlidingWindowLimiter, decodeJobPayload, encodeJobPayload, estimateNetworkBaseline, estimatePriorityFeeMicroLamports, estimateSolFeeLamports, formatAssetAmount, formatFeeBreakdown, formatNetworkBaseline, formatSol, getNetworkStats, getProtocolConfig, getProtocolProgramId, jobRequestKind, jobResultKind, makeCensor, nip44Decrypt, nip44Encrypt, parseAssetAmount, parsePaymentRequest, pickPercentileFee, resolveAssetFromPaymentRequest, resolveKnownAsset, timeAgo, toDTag, truncateKey, utf8ByteLength, validateAgentName, validateExpiry, verifyJobPaymentQuick };
4054
+ export { BlossomService, BoundedSet, DEFAULTS, DEFAULT_KIND_OFFSET, DEFAULT_REDACT_PATHS, DiscoveryService, ELISYM_PROTOCOL_TAG, ENVELOPE_VERSION, ElisymClient, ElisymIdentity, GlobalConfigSchema, INPUT_REDACT_PATHS, JobWaitTimeoutError, KIND_APP_HANDLER, KIND_JOB_FEEDBACK, KIND_JOB_REQUEST, KIND_JOB_REQUEST_BASE, KIND_JOB_RESULT, KIND_JOB_RESULT_BASE, KIND_LONG_FORM_ARTICLE, KIND_PING, KIND_PONG, KNOWN_ASSETS, LAMPORTS_PER_SOL, LIMITS, MarketplaceService, MediaService, NATIVE_SOL, NostrPool, POLICY_D_TAG_PREFIX, POLICY_TYPE_REGEX, POLICY_T_TAG, PROTOCOL_PROGRAM_ID_DEVNET, PaymentRequestSchema, PingService, PoliciesService, RELAYS, SECRET_REDACT_PATHS, SessionSpendLimitEntrySchema, SolanaPaymentStrategy, USDC_SOLANA_DEVNET, aggregateNetworkStats, assertExpiry, assertLamports, assetByKey, assetKey, buildPaymentInstructions, calculateProtocolFee, classifyJobError, clearPriorityFeeCache, clearProtocolConfigCache, clearQuickVerifyCache, compareAgentsByRank, computeRankKey, createPaymentRequestWithOnchainConfig, createSlidingWindowLimiter, decodeJobPayload, encodeJobPayload, estimateNetworkBaseline, estimatePriorityFeeMicroLamports, estimateSolFeeLamports, formatAssetAmount, formatFeeBreakdown, formatNetworkBaseline, formatSol, getNetworkStats, getProtocolConfig, getProtocolProgramId, jobRequestKind, jobResultKind, makeCensor, nip44Decrypt, nip44Encrypt, parseAssetAmount, parsePaymentRequest, pickPercentileFee, resolveAssetFromPaymentRequest, resolveKnownAsset, timeAgo, toDTag, truncateKey, utf8ByteLength, validateAgentName, validateExpiry, verifyJobPaymentQuick };
3929
4055
  //# sourceMappingURL=index.js.map
3930
4056
  //# sourceMappingURL=index.js.map