/** * HTTP API: WP_Http_Curl class * * @package WordPress * @subpackage HTTP * @since 4.4.0 */ /** * Core class used to integrate Curl as an HTTP transport. * * HTTP request method uses Curl extension to retrieve the url. * * Requires the Curl extension to be installed. * * @since 2.7.0 * @deprecated 6.4.0 Use WP_Http * @see WP_Http */ #[AllowDynamicProperties] class WP_Http_Curl { /** * Temporary header storage for during requests. * * @since 3.2.0 * @var string */ private $headers = ''; /** * Temporary body storage for during requests. * * @since 3.6.0 * @var string */ private $body = ''; /** * The maximum amount of data to receive from the remote server. * * @since 3.6.0 * @var int|false */ private $max_body_length = false; /** * The file resource used for streaming to file. * * @since 3.6.0 * @var resource|false */ private $stream_handle = false; /** * The total bytes written in the current request. * * @since 4.1.0 * @var int */ private $bytes_written_total = 0; /** * Send a HTTP request to a URI using cURL extension. * * @since 2.7.0 * * @param string $url The request URL. * @param string|array $args Optional. Override the defaults. * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error */ public function request( $url, $args = array() ) { $defaults = array( 'method' => 'GET', 'timeout' => 5, 'redirection' => 5, 'httpversion' => '1.0', 'blocking' => true, 'headers' => array(), 'body' => null, 'cookies' => array(), 'decompress' => false, 'stream' => false, 'filename' => null, ); $parsed_args = wp_parse_args( $args, $defaults ); if ( isset( $parsed_args['headers']['User-Agent'] ) ) { $parsed_args['user-agent'] = $parsed_args['headers']['User-Agent']; unset( $parsed_args['headers']['User-Agent'] ); } elseif ( isset( $parsed_args['headers']['user-agent'] ) ) { $parsed_args['user-agent'] = $parsed_args['headers']['user-agent']; unset( $parsed_args['headers']['user-agent'] ); } // Construct Cookie: header if any cookies are set. WP_Http::buildCookieHeader( $parsed_args ); $handle = curl_init(); // cURL offers really easy proxy support. $proxy = new WP_HTTP_Proxy(); if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { curl_setopt( $handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP ); curl_setopt( $handle, CURLOPT_PROXY, $proxy->host() ); curl_setopt( $handle, CURLOPT_PROXYPORT, $proxy->port() ); if ( $proxy->use_authentication() ) { curl_setopt( $handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY ); curl_setopt( $handle, CURLOPT_PROXYUSERPWD, $proxy->authentication() ); } } $is_local = isset( $parsed_args['local'] ) && $parsed_args['local']; $ssl_verify = isset( $parsed_args['sslverify'] ) && $parsed_args['sslverify']; if ( $is_local ) { /** This filter is documented in wp-includes/class-wp-http-streams.php */ $ssl_verify = apply_filters( 'https_local_ssl_verify', $ssl_verify, $url ); } elseif ( ! $is_local ) { /** This filter is documented in wp-includes/class-wp-http.php */ $ssl_verify = apply_filters( 'https_ssl_verify', $ssl_verify, $url ); } /* * CURLOPT_TIMEOUT and CURLOPT_CONNECTTIMEOUT expect integers. Have to use ceil since. * a value of 0 will allow an unlimited timeout. */ $timeout = (int) ceil( $parsed_args['timeout'] ); curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, $timeout ); curl_setopt( $handle, CURLOPT_TIMEOUT, $timeout ); curl_setopt( $handle, CURLOPT_URL, $url ); curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true ); curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, ( true === $ssl_verify ) ? 2 : false ); curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, $ssl_verify ); if ( $ssl_verify ) { curl_setopt( $handle, CURLOPT_CAINFO, $parsed_args['sslcertificates'] ); } curl_setopt( $handle, CURLOPT_USERAGENT, $parsed_args['user-agent'] ); /* * The option doesn't work with safe mode or when open_basedir is set, and there's * a bug #17490 with redirected POST requests, so handle redirections outside Curl. */ curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, false ); curl_setopt( $handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS ); switch ( $parsed_args['method'] ) { case 'HEAD': curl_setopt( $handle, CURLOPT_NOBODY, true ); break; case 'POST': curl_setopt( $handle, CURLOPT_POST, true ); curl_setopt( $handle, CURLOPT_POSTFIELDS, $parsed_args['body'] ); break; case 'PUT': curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, 'PUT' ); curl_setopt( $handle, CURLOPT_POSTFIELDS, $parsed_args['body'] ); break; default: curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, $parsed_args['method'] ); if ( ! is_null( $parsed_args['body'] ) ) { curl_setopt( $handle, CURLOPT_POSTFIELDS, $parsed_args['body'] ); } break; } if ( true === $parsed_args['blocking'] ) { curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( $this, 'stream_headers' ) ); curl_setopt( $handle, CURLOPT_WRITEFUNCTION, array( $this, 'stream_body' ) ); } curl_setopt( $handle, CURLOPT_HEADER, false ); if ( isset( $parsed_args['limit_response_size'] ) ) { $this->max_body_length = (int) $parsed_args['limit_response_size']; } else { $this->max_body_length = false; } // If streaming to a file open a file handle, and setup our curl streaming handler. if ( $parsed_args['stream'] ) { if ( ! WP_DEBUG ) { $this->stream_handle = @fopen( $parsed_args['filename'], 'w+' ); } else { $this->stream_handle = fopen( $parsed_args['filename'], 'w+' ); } if ( ! $this->stream_handle ) { return new WP_Error( 'http_request_failed', sprintf( /* translators: 1: fopen(), 2: File name. */ __( 'Could not open handle for %1$s to %2$s.' ), 'fopen()', $parsed_args['filename'] ) ); } } else { $this->stream_handle = false; } if ( ! empty( $parsed_args['headers'] ) ) { // cURL expects full header strings in each element. $headers = array(); foreach ( $parsed_args['headers'] as $name => $value ) { $headers[] = "{$name}: $value"; } curl_setopt( $handle, CURLOPT_HTTPHEADER, $headers ); } if ( '1.0' === $parsed_args['httpversion'] ) { curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 ); } else { curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); } /** * Fires before the cURL request is executed. * * Cookies are not currently handled by the HTTP API. This action allows * plugins to handle cookies themselves. * * @since 2.8.0 * * @param resource $handle The cURL handle returned by curl_init() (passed by reference). * @param array $parsed_args The HTTP request arguments. * @param string $url The request URL. */ do_action_ref_array( 'http_api_curl', array( &$handle, $parsed_args, $url ) ); // We don't need to return the body, so don't. Just execute request and return. if ( ! $parsed_args['blocking'] ) { curl_exec( $handle ); $curl_error = curl_error( $handle ); if ( $curl_error ) { if ( PHP_VERSION_ID < 80000 ) { // curl_close() has no effect as of PHP 8.0. curl_close( $handle ); } return new WP_Error( 'http_request_failed', $curl_error ); } if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ), true ) ) { if ( PHP_VERSION_ID < 80000 ) { // curl_close() has no effect as of PHP 8.0. curl_close( $handle ); } return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); } if ( PHP_VERSION_ID < 80000 ) { // curl_close() has no effect as of PHP 8.0. curl_close( $handle ); } return array( 'headers' => array(), 'body' => '', 'response' => array( 'code' => false, 'message' => false, ), 'cookies' => array(), ); } curl_exec( $handle ); $processed_headers = WP_Http::processHeaders( $this->headers, $url ); $body = $this->body; $bytes_written_total = $this->bytes_written_total; $this->headers = ''; $this->body = ''; $this->bytes_written_total = 0; $curl_error = curl_errno( $handle ); // If an error occurred, or, no response. if ( $curl_error || ( 0 === strlen( $body ) && empty( $processed_headers['headers'] ) ) ) { if ( CURLE_WRITE_ERROR /* 23 */ === $curl_error ) { if ( ! $this->max_body_length || $this->max_body_length !== $bytes_written_total ) { if ( $parsed_args['stream'] ) { if ( PHP_VERSION_ID < 80000 ) { // curl_close() has no effect as of PHP 8.0. curl_close( $handle ); } fclose( $this->stream_handle ); return new WP_Error( 'http_request_failed', __( 'Failed to write request to temporary file.' ) ); } else { if ( PHP_VERSION_ID < 80000 ) { // curl_close() has no effect as of PHP 8.0. curl_close( $handle ); } return new WP_Error( 'http_request_failed', curl_error( $handle ) ); } } } else { $curl_error = curl_error( $handle ); if ( $curl_error ) { if ( PHP_VERSION_ID < 80000 ) { // curl_close() has no effect as of PHP 8.0. curl_close( $handle ); } return new WP_Error( 'http_request_failed', $curl_error ); } } if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ), true ) ) { if ( PHP_VERSION_ID < 80000 ) { // curl_close() has no effect as of PHP 8.0. curl_close( $handle ); } return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); } } if ( PHP_VERSION_ID < 80000 ) { // curl_close() has no effect as of PHP 8.0. curl_close( $handle ); } if ( $parsed_args['stream'] ) { fclose( $this->stream_handle ); } $response = array( 'headers' => $processed_headers['headers'], 'body' => null, 'response' => $processed_headers['response'], 'cookies' => $processed_headers['cookies'], 'filename' => $parsed_args['filename'], ); // Handle redirects. $redirect_response = WP_Http::handle_redirects( $url, $parsed_args, $response ); if ( false !== $redirect_response ) { return $redirect_response; } if ( true === $parsed_args['decompress'] && true === WP_Http_Encoding::should_decode( $processed_headers['headers'] ) ) { $body = WP_Http_Encoding::decompress( $body ); } $response['body'] = $body; return $response; } /** * Grabs the headers of the cURL request. * * Each header is sent individually to this callback, and is appended to the `$header` property * for temporary storage. * * @since 3.2.0 * * @param resource $handle cURL handle. * @param string $headers cURL request headers. * @return int Length of the request headers. */ private function stream_headers( $handle, $headers ) { $this->headers .= $headers; return strlen( $headers ); } /** * Grabs the body of the cURL request. * * The contents of the document are passed in chunks, and are appended to the `$body` * property for temporary storage. Returning a length shorter than the length of * `$data` passed in will cause cURL to abort the request with `CURLE_WRITE_ERROR`. * * @since 3.6.0 * * @param resource $handle cURL handle. * @param string $data cURL request body. * @return int Total bytes of data written. */ private function stream_body( $handle, $data ) { $data_length = strlen( $data ); if ( $this->max_body_length && ( $this->bytes_written_total + $data_length ) > $this->max_body_length ) { $data_length = ( $this->max_body_length - $this->bytes_written_total ); $data = substr( $data, 0, $data_length ); } if ( $this->stream_handle ) { $bytes_written = fwrite( $this->stream_handle, $data ); } else { $this->body .= $data; $bytes_written = $data_length; } $this->bytes_written_total += $bytes_written; // Upon event of this function returning less than strlen( $data ) curl will error with CURLE_WRITE_ERROR. return $bytes_written; } /** * Determines whether this class can be used for retrieving a URL. * * @since 2.7.0 * * @param array $args Optional. Array of request arguments. Default empty array. * @return bool False means this class can not be used, true means it can. */ public static function test( $args = array() ) { if ( ! function_exists( 'curl_init' ) || ! function_exists( 'curl_exec' ) ) { return false; } $is_ssl = isset( $args['ssl'] ) && $args['ssl']; if ( $is_ssl ) { $curl_version = curl_version(); // Check whether this cURL version support SSL requests. if ( ! ( CURL_VERSION_SSL & $curl_version['features'] ) ) { return false; } } /** * Filters whether cURL can be used as a transport for retrieving a URL. * * @since 2.7.0 * * @param bool $use_class Whether the class can be used. Default true. * @param array $args An array of request arguments. */ return apply_filters( 'use_curl_transport', true, $args ); } } Colección NFT en OpenSea: mitos, mecanismos y decisiones para quien quiere comprar y entrar al marketplace – Shweta Poddar Weddings Photography

Contrario a la idea popular, “tener un NFT” no equivale automáticamente a control verdadero sobre una imagen, ni a una inversión líquida ni a una prueba irrevocable de autoría sin matices. Este artículo comienza con esa afirmación a propósito: el ecosistema NFT mezcla propiedad on-chain, metadatos off-chain y mercados con incentivos propios; entender los capas y sus límites es lo que transforma un comprador novato en un participante informado.

Si eres usuario en España, en la comunidad hispanoamericana o migras entre ambas jurisdicciones (US‑ES), aquí verás cómo funciona una colección NFT en OpenSea, qué puedes esperar al iniciar sesión y dónde suelen fallar las expectativas. El objetivo: darte un modelo mental útil para decidir si comprar, cuándo hacerlo y qué señales técnicas y comerciales vigilar después.

Logotipo de OpenSea: marca del marketplace; recordar que la plataforma facilita intercambio on‑chain mientras parte de los metadatos puede estar fuera de la cadena.

Cómo funciona una colección NFT en el nivel de mecanismos

Una “colección” en OpenSea agrupa tokens no fungibles (NFTs) que comparten contrato inteligente, metadatos y, frecuentemente, reglas de minting. Mecanismos clave:

– Contrato inteligente: define la emisión, la propiedad y las transferencias. Es la pieza on‑chain que puedes auditar si sabes leer Solidity o revisar la verificación del contrato.

– Metadatos y activos: la imagen, descripción y atributos muchas veces residen fuera de la cadena (por ejemplo en IPFS o servidores centralizados). El token on‑chain referencia esos datos mediante una URL; si el proveedor borra o cambia el recurso externo, el token puede apuntar a contenido diferente.

– Marketplace/ordenes: OpenSea actúa como libro de órdenes y vehículo de custodia de interfaces para firmar transacciones. La negociación depende de que compradores y vendedores firmen transacciones con sus wallets; el orden, el pago de comisiones y las políticas (por ejemplo verificaciones de colección) influyen en la experiencia de compra.

Iniciar sesión en OpenSea y acceder al sitio oficial: prácticas seguras

Para entrar a OpenSea se utilizan wallets compatibles (MetaMask, WalletConnect, etc.). Nunca debes introducir claves privadas en páginas web; la interacción legítima solicita firmas desde la wallet, no contraseñas. Un control práctico: verifica la URL y considera usar extensiones o bookmarks conocidos para evitar phishing.

Si quieres una guía práctica y el enlace oficial útil para comenzar, visita esta página sobre opensea nft que centraliza pasos de acceso y recordatorios de seguridad pensados para usuarios hispanohablantes.

Un matiz importante: iniciar sesión (conectar tu wallet) no implica delegar control. Firmar una solicitud de conexión es solo permitir que el sitio lea tu dirección pública; firmas de transacción separadas son las que pueden mover fondos o transferir NFTs. Read‑carefully: permiso de “conectar” ≠ permiso para gastar.

Mitos frecuentes y correcciones basadas en mecanismos

Mito 1 — “Un NFT en OpenSea es inmutable para siempre”: Falso. La propiedad on‑chain es permanente, pero los metadatos y la representación visual pueden ser cambiables si el creador configuró la metadata como actualizable o la hospedó en servidores que pueden modificarse. Siempre revisa si la colección usa IPFS (más resistente) o URLs centralizadas.

Mito 2 — “Comprar un NFT garantiza liquidez”: No necesariamente. Liquidez depende del interés de mercado, de la notoriedad de la colección y de la dinámica de precios. Una pieza puede ser muy cara para vender si no hay demanda; el mercado secundario es la variable crítica.

Mito 3 — “Comprobar la insignia de verificación en OpenSea es suficiente para seguridad”: La verificación ayuda, pero no es garantía absoluta. Existen clones de colección, falsos contratos o listados erróneos. Verifica la dirección del contrato y, si procede, mira el historial de mints y volumen on‑chain.

Comparación: OpenSea frente a otras vías para comprar NFTs (2–3 alternativas)

Marketplace centralizado (OpenSea): ventajas — gran liquidez relativa, interfaz amigable y descubrimiento. Sacrifica: dependencia de la plataforma para listados, riesgos de políticas y fricciones por tarifas de la red.

Compra directa del creador (mint en la web del proyecto): ventajas — menor competencia inicial, potencialmente menor tarifa, apoyo directo a creadores. Sacrifica: riesgo de phishing si el sitio no es legítimo, y posible falta de protección del comprador si el proyecto no es profesional.

Mercados especializados o marketplaces descentralizados: ventajas — mayor control sobre custodia y, a veces, mejores condiciones económicas; sacrifican: menor tráfico, experiencias UX más complejas y menor protección comercial.

Límites, trade‑offs y señales que deberías verificar antes de comprar

Limites técnicos: si la metadata no está en IPFS o el smart contract permite actualizaciones arbitrarias por el creador, la “obra” puede cambiar. Trade‑off práctico: flexibilidad del creador vs. inmutabilidad del token.

Señales útiles (heurísticos): volumen reciente de ventas, número activo de holders, presencia en redes y transparencia del contrato. No hay una medida única; construye una “lista de comprobación” mínima: contrato verificado, metadata inmutable (o explicado), ruta clara del mint, y comunidad activa.

Condición legal y fiscal: en España y Latinoamérica las reglas fiscales están en evolución. No asumas deducciones o tratamiento especial; registra compras y ventas y consulta a un asesor fiscal local si las cantidades son relevantes.

Qué observar en las próximas semanas y por qué importa

OpenSea se describe esta semana como “exchange everything” con intención de facilitar intercambios de tokens y NFTs; si la plataforma acelera integraciones on‑chain, eso puede reducir fricciones para traders y creadores. Sin embargo, atención a cómo cambien las comisiones, las reglas de verificación y las integraciones de wallets: esos cambios alteran la economía de una colección.

Señales que cambian el valor esperado: mejoras técnicas en la custodia y en la transparencia del contrato, mayores controles anti‑fraude, o un repentino descenso en actividad por parte de grandes colecciones. Cada uno de estos eventos altera el premio de liquidez y el riesgo de custodia.

Preguntas frecuentes

¿Necesito conocer Solidity o herramientas técnicas para comprar en OpenSea?

No es imprescindible, pero entender lo básico ayuda a evitar errores comunes. Saber distinguir una dirección de contrato verificada, verificar si los metadatos están en IPFS y comprobar el historial de transacciones minimiza riesgo. Si no dominas esos pasos, sigue guías confiables y utiliza wallets con buenas prácticas de seguridad.

¿Puedo recuperar un NFT si el proveedor del archivo lo borra?

Si el NFT referencia contenido alojado en servidores centralizados y ese contenido se borra, el token seguirá existiendo on‑chain pero la imagen o los metadatos pueden perderse o cambiar. Si el contenido estaba en IPFS o similar, la probabilidad de pérdida es menor. Siempre revisa dónde residen los activos antes de comprar.

¿Cómo afecta el coste del gas y las comisiones mi decisión de comprar?

El coste del gas puede hacer que compras de bajo importe no sean rentables. Considera comprar cuando la actividad de la red sea menor o focalizarte en colecciones con minting en cadenas con tarifas más bajas. El trade‑off es que cadenas alternativas pueden tener menos compradores potenciales.

¿Qué debo vigilar para evitar fraudes y listas falsas?

Verifica la URL oficial del proyecto, la dirección del contrato en el listado, y busca comunicación oficial del creador. Desconfía de mensajes que piden firmar transacciones raras (como aprobar transferencias masivas). Usa bookmarks y herramientas de reputación y mantén tu wallet y claves privadas fuera de formularios web.

Conclusión práctica: comprar en OpenSea y participar en una colección puede ser tanto una experiencia creativa como un riesgo financiero. La mejora inmediata para cualquier comprador hispanohablante es simple: aprenda a leer la capa de contrato y la capa de metadatos, exija transparencia en ambas y trate la decisión como una evaluación de activos con liquidez incierta. Esa disciplina reduce sorpresas y convierte un gesto digital en una decisión con sentido.

Uncategorized

Leave a Comment

Your email address will not be published. Required fields are marked *