> ## Documentation Index
> Fetch the complete documentation index at: https://frenglish.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Gestión de metadatos de colecciones

> Cómo almacenar archivos multimedia usando la API de Sequence Collections con Cloudflare Workers, así como leer desde la Metadata API para mostrar imágenes.

Tiempo estimado: 20 minutos

En esta guía le mostraremos cómo almacenar archivos multimedia usando la API de Sequence Collections con [Cloudflare Workers](https://www.cloudflare.com/), así como leer desde la Metadata API para mostrar imágenes.

Esto se puede lograr en 8 pasos

1. [Obtenga una clave API secreta](/guides/metadata-guide#1-obtain-a-secret-api-key) desde el [Sequence Builder Console](https://sequence.build)
2. [Cree una colección](/guides/metadata-guide#2-create-collection-from-a-curl-request) mediante una solicitud cURL una sola vez
3. [Cree un token](/guides/metadata-guide#3-create-token-using-tokenid) usando un tokenID
4. [Cree un asset](/guides/metadata-guide#4-create-asset-using-tokenid) usando un assetID
5. [Almacene una imagen](/guides/metadata-guide#5-store-image-asset) procese y almacene una imagen
6. [Actualice a no privado](/guides/metadata-guide#6-update-non-private-token) cambie un asset a no privado
7. [Publique la colección](/guides/metadata-guide#7-publish-collection-from-a-curl-request) mediante una solicitud cURL una sola vez
8. [Renderice el asset desde la API](/guides/metadata-guide#8-render-asset-from-api-publicly) mediante una solicitud cURL una sola vez

Primero siga [esta sección de la Guía de Servicio de Minteo de Coleccionables](/guides/mint-collectibles-serverless#1-setup-cloudflare-environment-with-wrangler-cli-and-deploy-a-test) para crear un Cloudflare Worker

## 1. Obtenga una clave API secreta

Para utilizar el servicio backend, debe obtener una `Secret API` Key para autenticar las solicitudes a su proyecto.

Primero, acceda a la configuración y seleccione las claves API desde el [Sequence Builder Console](https://sequence.build/)

<Frame>
  <img src="https://mintcdn.com/frenglish/HG-orp76LeGEg_IA/images/builder/builder_settings_access_keys.png?fit=max&auto=format&n=HG-orp76LeGEg_IA&q=85&s=011b7eb42e7df37722bbc5b64e7054dd" alt="builder settings access keys" width="1757" height="771" data-path="images/builder/builder_settings_access_keys.png" />
</Frame>

Desplácese hacia abajo y seleccione `+ Add Service Account`

<Frame>
  <img src="https://mintcdn.com/frenglish/HG-orp76LeGEg_IA/images/builder/builder_settings_add_service_account.png?fit=max&auto=format&n=HG-orp76LeGEg_IA&q=85&s=48fbd0a901ca441db88e6089f2404bfd" alt="builder settings add service account" width="2033" height="805" data-path="images/builder/builder_settings_add_service_account.png" />
</Frame>

Luego cambie el acceso a `write` y `confirm`

<Frame>
  <img src="https://mintcdn.com/frenglish/HG-orp76LeGEg_IA/images/builder/builder_settings_add_service_account_confirm.png?fit=max&auto=format&n=HG-orp76LeGEg_IA&q=85&s=adcd5c96435a562f72c2cf4f78dbae7c" alt="builder settings add service account" width="2033" height="771" data-path="images/builder/builder_settings_add_service_account_confirm.png" />
</Frame>

Finalmente, `copie` la clave y guárdela en su `wrangler.toml` como `JWT_ACCESS_KEY`, ya que no podrá acceder a ella en el futuro desde el Sequence Builder Console.

## 2. Crear una colección desde una solicitud cURL

Como requisito previo para subir medios al servicio, primero debe crear una colección. Utilice la `Secret API Key` y el `projectID` obtenidos desde el [Builder Console](https://sequence.build/)

Llamamos al servicio para obtener un `collectionID`

```shell theme={null}
curl --location 'https://metadata.sequence.app/rpc/Collections/CreateCollection' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <secret_API_key or jwt_access_key>' \
--data '{
    "projectId": <project_id>,
    "collection": {
        "metadata": {
            "name": "<collection_name>",
            "description": "<description>",
            "external_link" : "<https://link>"
        },
        "image": "",
        "decimals": <decimals_typically_as_0>,
        "properties": null,
        "attributes": null
    }
}'
```

Luego, establecemos el `collectionID` de la respuesta recibida en el `wrangler.toml` como `COLLECTION_ID`

## 3. Crear un token usando TokenID

<Note>
  Si usa un worker de Cloudflare, asegúrese de agregar `node_compat = true` a su `wrangler.toml` para que el objeto window esté disponible para el paquete `@0xsequence/metadata`
</Note>

Instale el paquete de metadata para usar `SequenceCollections` con `pnpm install @0xsequence/metadata`

```typescript theme={null}
import { SequenceCollections } from '@0xsequence/metadata'
import { ethers } from 'ethers'
...
const METADATA_URL = 'https://metadata.sequence.app'
const collectionsService = new SequenceCollections(METADATA_URL, JWT_ACCESS_KEY)

const randomTokenIDSpace = ethers.BigNumber.from(ethers.hexlify(ethers.randomBytes(20)))

const res1 = await collectionsService.createToken({
	projectId: projectID,
	collectionId: collectionID,
	token: {
		tokenId: String(randomTokenIDSpace),
		name: name,
		description: description,
		decimals: 0,
		attributes: attributes // can leave blank
	}
})

```

## 4. Crear un asset usando TokenID

En la solicitud, establezca el `metadadaField` (assetType) en `image`, completando los otros campos necesarios para obtener una respuesta de asset que se usará en el siguiente paso

```typescript theme={null}
const jsonCreateAsset = await collectionsService.createAsset({
	projectId: projectID,
	asset: {
		id: Number(String(randomTokenIDSpace).slice(0,10)),
		collectionId: collectionID,
		tokenId: String(randomTokenIDSpace),
		metadataField: "image"
	}
})

```

## 5. Almacenar el asset de imagen

Con el `asset.id` proporcionado del objeto `jsonCreateAsset` anterior

```typescript theme={null}
	...
	const uploadAsset = async (env: Env, projectID: any, collectionID: any, assetID: any, tokenID: any, url: any) => {
		const response = await fetch(url);
		if (!response.ok) throw new Error(`Failed to fetch file from ${url}: ${response.statusText}`);
		const arrayBuffer = await response.arrayBuffer();
		const blob = new Blob([arrayBuffer]);

		const formData = new FormData();
		
		formData.append('file', blob, `image.png`); // You might want to dynamically determine the filename
		
		let METADATA_URL = 'https://metadata.sequence.app'

		// Construct the endpoint URL
		const endpointURL = `${METADATA_URL}/projects/${projectID}/collections/${collectionID}/tokens/${tokenID}/upload/${assetID}`;

		try {
			// Use fetch to make the request
			const fetchResponse = await fetch(endpointURL, {
				method: 'PUT',
				body: formData,
				headers: {
					'X-Access-Key': env.PROJECT_ACCESS_KEY,
					'Authorization': `Bearer ${env.JWT_ACCESS_KEY}`, // Put your token here
				},
			});
		
			// Assuming the response is JSON
			const data = await fetchResponse.json();

			return data;
		}catch(err){
			console.log(err)
		}
	}
	...
	const uploadAssetRes = await uploadAsset(env, projectID, collectionID, jsonCreateAsset.asset.id, String(randomTokenIDSpace), imageUrl)
	...
```

Donde el `uploadAssetRes.url` devuelto es la URL del archivo multimedia alojado en los servidores de Sequence

## 6. Actualizar token no privado

Ahora, hacemos que el token sea no privado estableciendo el booleano `private` en `false`

```typescript theme={null}
const res3 = await collectionsService.updateToken({
	projectId: projectID,
	collectionId: collectionID,
	private: false,
	tokenId: String(randomTokenIDSpace),
	token: {
		name: name,
		attributes: attributes,
		tokenId: String(randomTokenIDSpace),
	}
})
```

***

## 7. Publicar colección desde una solicitud cURL

Finalmente, también como una solicitud única, publicamos la colección usando el `projectID` y el `collectionID` ejecutando el siguiente comando

```shell theme={null}
curl --location 'https://metadata.sequence.app/rpc/Collections/PublishCollection' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <secrect_API_key or jwt_access_key> \
--data '{
    "projectId": <project_id>,
    "collectionId": <collection_id>
}'
```

Esto hará que la colección y todos los tokens con la propiedad `private` establecida en `false` sean accesibles públicamente, mientras que los demás permanecerán ocultos hasta que se cambie su estado

## 8. Renderizar asset desde la API públicamente

Puede probar su trabajo anterior llamando a esta solicitud cURL con las variables actualizadas, lo que descargará el archivo en su terminal local.

O puede copiar y pegar la URL en un navegador y ver la imagen

Si usó el mismo código, el `<file_name>` será `image.png`

```shell [cURL] theme={null}
curl --location 'https://metadata.sequence.app/projects/<project_id>/collections/<collection_id>/tokens/<token_id>/<file_name>' --output stored_file.png
```

Y si estaba usando la colección para el `baseURI` de un `ERC721` o `ERC1155`, escribiría en un smart contract `setBaseMetadataURI` la siguiente `URI`

```
https://metadata.sequence.app/projects/<project_id>/collections/<collection_id>/tokens/
```

Y el smart contract agregará automáticamente el `tokenID` al final

Pruébelo usted mismo

```shell [cURL] theme={null}
curl https://metadata.sequence.app/projects/1229/collections/40/tokens/457657099779485875855215293997335918990635014431
```

O en un [navegador](https://metadata.sequence.app/projects/1229/collections/40/tokens/457657099779485875855215293997335918990635014431)

### Renderizar asset desde la API de forma privada

Alternativamente, puede decidir mantener sus assets almacenados como privados, pero aún así renderizar los datos pasando una clave secreta de API en el `header` junto con los parámetros completos; para esta guía el `metadata_field` está configurado como `image`

```shell [cURL] theme={null}
curl --location 'https://metadata.sequence.app/projects/<project_id>/collections/<collection_id>/tokens/<token_id>/asset/<metadada_field>' \
--header 'Authorization: Bearer <secret_api_key or jwt_access_key>' \
--output stored_file.png
```

<Note>
  El código completo para esta guía se encuentra [aquí](https://github.com/0xsequence-demos/template-cloudflare-worker-collections-api/tree/master)
</Note>
