En la economía de la atención (Web 2.0), los usuarios son "empujados" a pagar suscripciones para acceder a contenido exclusivo (todo tipo de contenido, incluido el contenido para adultos), pero nada asegura que obtengas los beneficios por los que estás pagando, ya sea porque el creador de contenido no sigue creando cosas nuevas o porque tienes que suscribirte por periodos extendidos cuando solo quieres pagar por lo que consumes.
Sin embargo, la Web 3.0, la economía de la intención, trae la oportunidad de que los usuarios paguen sólo por lo que consumen, en lugar de por periodos extendidos, a través de micropagos. A su vez, incentiva a los creadores de contenido a mantenerse actualizados con más creaciones, recibiendo sus ingresos de manera inmediata, con costos muy bajos, sin depender de pasarelas centralizadas.
Monetizado es una plataforma de pago por visión en cadena que te permite monetizar cualquier página web y contenido estático (si no tienes acceso al backend para realizar cambios) a través de Web3.
Puedes implementar Monetizado en sitios de noticias, redes sociales, portales de contenido exclusivo y más. También podrías usarlo para incentivar a los usuarios a pagar y no ver publicidad en tus sitios.
Monetizado te permite:
Puedes usar monetizado para proteger páginas de modo que solo los suscriptores puedan verlas, como en:
Para construir esta plataforma, utilizamos:
Nuestro contrato inteligente es bastante básico y le permite especificar un nombre de contenido a monetizar, una cantidad (en rBTC) y varias funciones para habilitar/deshabilitar contenido, y pagar y recibir pagos, entre otros.
MonetizadoLibrary.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library MonetizadoLibrary { struct ProtectedContent { string name; uint256 accessCost; bool isProtected; uint256 sequenceId; address creator; uint256 amountAvailable; uint256 amountCollected; mapping(address => Subscriber) subscribers; } struct Subscriber { bool paid; uint256 amount; } }
Monetizadov1.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./MonetizadoLibrary.sol"; contract Monetizadov1 { // Struct with info about the protected content (for paying to access) struct ProtectedContentInfo { string name; uint256 accessCost; bool isProtected; uint256 sequenceId; address creator; uint256 amountAvailable; uint256 amountCollected; } mapping(address => bool) private creators; mapping(address => bool) public hosting; mapping(address => MonetizadoLibrary.ProtectedContent[]) private paginasProtegidas; event GrantedAccess(address usuario, address creator, uint256 sequenceId); address private _owner; uint256 private _platformFeePercentage; uint256 private _platformBalance; modifier onlyOwner() { require(msg.sender == _owner, "Only the owner can call this function"); _; } constructor() { _owner = msg.sender; _platformFeePercentage = 0; _platformBalance = 0; } function addProtectedContent(string memory name, uint256 accessCost) public returns (uint256) { uint256 cantidadPaginasCreador = paginasProtegidas[msg.sender].length; MonetizadoLibrary.ProtectedContent[] storage paginas = paginasProtegidas[msg.sender]; MonetizadoLibrary.ProtectedContent storage pagina = paginas.push(); pagina.name = name; pagina.accessCost = accessCost; pagina.isProtected = true; pagina.sequenceId = cantidadPaginasCreador; pagina.creator = msg.sender; pagina.amountCollected = 0; pagina.amountAvailable = 0; creators[msg.sender] = true; return cantidadPaginasCreador; } function getProtectedContentsForCurrentUser() public view returns (ProtectedContentInfo[] memory) { uint256 cantidadPaginasPorCreador = paginasProtegidas[msg.sender].length; ProtectedContentInfo[] memory paginas = new ProtectedContentInfo[](cantidadPaginasPorCreador); for (uint256 i = 0; i < cantidadPaginasPorCreador; i++) { MonetizadoLibrary.ProtectedContent storage pagina = paginasProtegidas[msg.sender][i]; paginas[i] = ProtectedContentInfo(pagina.name, pagina.accessCost, pagina.isProtected, pagina.sequenceId, pagina.creator, pagina.amountAvailable, pagina.amountCollected); } return paginas; } function getProtectedContentByAddressAndId(address creator, uint256 sequenceId) public view returns (ProtectedContentInfo memory) { MonetizadoLibrary.ProtectedContent storage pagina = paginasProtegidas[creator][sequenceId]; ProtectedContentInfo memory paginas = ProtectedContentInfo(pagina.name, pagina.accessCost, pagina.isProtected, pagina.sequenceId, pagina.creator, pagina.amountAvailable, pagina.amountCollected); return paginas; } function payAccess(address creator, uint256 sequenceId) external payable { MonetizadoLibrary.ProtectedContent storage pagina = paginasProtegidas[creator][sequenceId]; require(msg.value == pagina.accessCost, "Incorrect payment amount"); require(pagina.isProtected == true, "The page is not protected and you do not need to pay access"); MonetizadoLibrary.Subscriber storage subscriber = pagina.subscribers[msg.sender]; subscriber.paid = true; subscriber.amount = msg.value; pagina.amountCollected += msg.value; pagina.amountAvailable += msg.value; emit GrantedAccess(msg.sender, creator, sequenceId); } function currentUserHasAccess(address creator, uint256 sequenceId) public view returns(bool) { MonetizadoLibrary.ProtectedContent storage pagina = paginasProtegidas[creator][sequenceId]; return pagina.subscribers[msg.sender].paid; } function changeAccessCost(uint256 sequenceId, uint256 newCost) external { MonetizadoLibrary.ProtectedContent storage pagina = paginasProtegidas[msg.sender][sequenceId]; pagina.accessCost = newCost; } function unprotectContent(uint256 sequenceId) external { MonetizadoLibrary.ProtectedContent storage pagina = paginasProtegidas[msg.sender][sequenceId]; pagina.isProtected = false; } function protectContent(uint256 sequenceId) external { MonetizadoLibrary.ProtectedContent storage pagina = paginasProtegidas[msg.sender][sequenceId]; pagina.isProtected = true; } function changePlatformFee(uint256 feePlatform) external onlyOwner { require(feePlatform <= 100, "The fee should be between 0.01 to 1% (1 - 100 in a 10000 scale)"); _platformFeePercentage = feePlatform; } function withdrawMoneyFromContent(uint256 sequenceId,uint256 amount) external { MonetizadoLibrary.ProtectedContent storage pagina = paginasProtegidas[msg.sender][sequenceId]; require(pagina.amountAvailable >= amount, "Insufficient balance"); uint256 amountForPlatform = amount * _platformFeePercentage / 10000; _platformBalance += amountForPlatform; payable(_owner).transfer(amountForPlatform); payable(msg.sender).transfer(amount - amountForPlatform); pagina.amountAvailable -= amount; } function getPlatformFee() public view returns(uint256) { return _platformFeePercentage; } function getPlatformBalance() public view returns(uint256) { return _platformBalance; } function withdrawMoneyPlatform(uint256 amount) external onlyOwner { require(_platformBalance >= amount, "Insufficient balance"); payable(msg.sender).transfer(amount); _platformBalance -= amount; } }
Además, creamos un SDK de Javascript que permite el uso del contrato inteligente en sitios web, especialmente para usuarios que desean pagar para acceder a contenido específico.
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script> <script src="https://cdn.ethers.io/lib/ethers-5.2.umd.min.js" type="application/javascript"></script>
<script src="./monetizado.js"></script>
Añade una etiqueta de enlace en el head del código HTML de tu página, con el atributo “rel” con el valor “monetized” y en href sigue la siguiente estructura:
Por ejemplo:
<link rel="monetizado" href="rootstock:testnet://0xda3ec0b8bddd2e8bdedede3333fbaf938fcc18c5/0" />
El ejemplo anterior significa que el contenido está protegido (por Id 0), por el creador (0xda3ec0b8bddd2e8bdedede3333fbaf938fcc18c5 por ejemplo), y esa combinación es que se debe realizar el pago para desbloquearlo.
Este proyecto ya está implementado en Rootstock testnet y puedes explorar los distintos enlaces a continuación, incluidos repositorios y una demostración:
Precisamente para esta idea nos planteamos el reto de poder monetizar plataformas Web 2.0 utilizando Web3, sin un gran impacto tanto para el creador de contenidos como para el usuario.
Por lo tanto, tuvimos que crear el SDK en Javascript que permitiera monetizar el contenido con pocos cambios en el sitio web, ya que es muy probable que la mayoría de los creadores de contenido tengan dificultades para editar sus sitios web (o utilicen plataformas externas donde no tienen mucho espacio para editar).
Con esa solución, entonces teníamos que ver cómo identificar el contenido que se estaba monetizando, y ahí aprovechamos la etiqueta de enlace HTML para especificar ese contenido, y el SDK detectaría la cantidad en rBTC, si el usuario ya había pagado y tenía acceso, o tenía que pagar.
Rootstock representa una enorme oportunidad en BitcoinFi, aprovechando sus capacidades y robustez como red descentralizada, para en este contexto realizar micropagos y conectarla con la economía de creación.
Este ejemplo, Monetizado, muestra la simplicidad de utilizar Web3 en plataformas Web2, donde hay un enorme espacio para todo tipo de usuarios, reduciendo la fricción para integrar estas tecnologías.