Publisher
El publisher guarda un blob en nombre de un cliente que no habla con los nodos de almacenamiento:
codifica los datos, paga el almacenamiento y el gas en IOTA con su propia cuenta, sube los
slivers, certifica el blob y envía el objeto Blob a la dirección que elija el cliente. También
guarda quilts.
URL base: https://publisher.iotastorage.com.
Como el publisher paga con su propio IOTA, el público pide un token
(Authorization: Bearer <token>) y lo usa el proyecto. Sin él, responde 401 UNAUTHENTICATED.
Para guardar tus propios datos, usa la app con tu wallet, o
el cliente de referencia en JavaScript: pagas en IOTA y el Blob es tuyo desde el principio.
Cualquiera puede leer el resultado con el aggregator público.
| Método | Ruta | Cuerpo |
|---|---|---|
PUT | /v1/blobs?<parámetros> | Los bytes del blob. |
PUT | /v1/quilts?<parámetros> | Los archivos, como multipart/form-data. |
Parámetros
| Parámetro | Por defecto | Qué significa |
|---|---|---|
epochs | 1 | Épocas que se guarda el blob: un entero de 1 a 53. |
deletable=true | Guarda un blob borrable (por defecto). | |
permanent=true | Guarda un blob permanente, que no se puede borrar. No junto con deletable=true. | |
send_object_to | el publisher | Dirección de IOTA (0x…) que recibe el objeto Blob. Sin él, el Blob se queda en la cuenta del publisher. |
Guardar un blob
curl -X PUT "https://publisher.iotastorage.com/v1/blobs?epochs=5&send_object_to=0x<tu dirección>" \
-H "Authorization: Bearer $TOKEN" \
--upload-file archivo
La respuesta describe el Blob nuevo. Por ejemplo, para un archivo de 1 MiB guardado 5 épocas
desde la época 1:
{
"newlyCreated": {
"blobObject": {
"id": "0x…",
"registeredEpoch": 1,
"blobId": "<blob ID>",
"size": 1048576,
"encodingType": "RS2",
"certifiedEpoch": 1,
"storage": {
"id": "0x…",
"startEpoch": 1,
"endEpoch": 6,
"storageSize": 5309400
},
"deletable": true
},
"resourceOperation": {
"registerFromScratch": { "encodedLength": 5309400, "epochsAhead": 5 }
},
"cost": 42000
}
}
| Campo | Qué es |
|---|---|
blobObject.id | ID del objeto Blob en IOTA. |
blobObject.blobId | El blob ID, para leerlo con el aggregator. |
blobObject.size | Tamaño de los datos originales, en bytes. |
blobObject.storage | El recurso Storage: épocas y tamaño codificado reservado. |
resourceOperation.registerFromScratch.encodedLength | Tamaño codificado que se pagó. |
cost | Lo que cobró el contrato por el almacenamiento, en nanos de IOTA (sin el gas). |
Guardar un quilt
PUT /v1/quilts guarda varios archivos como un solo quilt. El
cuerpo es multipart/form-data:
- cada campo es un archivo, y el nombre del campo es su identificador en el quilt (no puede
empezar por
_); - un campo
_metadataopcional lleva una lista JSON de{ "identifier", "tags" }con etiquetas de texto para algunos de los archivos.
curl -X PUT "https://publisher.iotastorage.com/v1/quilts?epochs=5" \
-H "Authorization: Bearer $TOKEN" \
-F "index.html=@index.html" \
-F "logo.svg=@logo.svg" \
-F '_metadata=[{"identifier": "logo.svg", "tags": {"kind": "image"}}]'
{
"blobStoreResult": {
"newlyCreated": { "blobObject": { … }, "resourceOperation": { … }, "cost": … }
},
"storedQuiltBlobs": [
{ "identifier": "index.html", "quiltPatchId": "<quilt patch ID>" },
{ "identifier": "logo.svg", "quiltPatchId": "<quilt patch ID>" }
]
}
Después, cada archivo se puede leer con el aggregator por su quilt patch ID. Con 100 shards, un quilt admite hasta 66 archivos.
Límites y comportamiento
- Como mucho 10 MiB por petición (el blob o el cuerpo entero del quilt); la red admite blobs de hasta unos 142 MiB con otros clientes. Un blob vacío se rechaza.
- Las escrituras se atienden de una en una, porque todas pagan con las monedas del publisher.
- No hay respuesta
alreadyCertified: cadaPUTregistra unBlobnuevo, aunque los datos ya estén guardados. - Tiene CORS, y admite las cabeceras
authorizationycontent-typeen las peticiones.
Errores
El mismo formato JSON que el aggregator:
| Código | status | Cuándo |
|---|---|---|
| 400 | INVALID_ARGUMENT | epochs no válido, permanent junto con deletable, send_object_to no válido, blob vacío, cuerpo multipart o _metadata mal formados. |
| 401 | UNAUTHENTICATED | Falta el token o no es el correcto. |
| 405 | METHOD_NOT_ALLOWED | Método equivocado, o un servidor que solo lee. |
| 413 | PAYLOAD_TOO_LARGE | Más grande que el límite del publisher o que el blob más grande de la red. |