paint-brush
Cómo crear un protocolo de pago por visión en cadena en Rootstockpor@nescampos
376 lecturas
376 lecturas

Cómo crear un protocolo de pago por visión en cadena en Rootstock

por Néstor Campos9m2024/11/30
Read on Terminal Reader

Demasiado Largo; Para Leer

Monetizado es un protocolo de pago por visión on-chain que permite monetizar cualquier página web y contenido estático a través de la Web3.0. Se puede utilizar para proteger páginas de forma que solo los suscriptores puedan verlas.
featured image - Cómo crear un protocolo de pago por visión en cadena en Rootstock
Néstor Campos HackerNoon profile picture

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, un protocolo de pago por visión en cadena

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.

Características

Monetizado te permite:

  • Especifique el contenido protegido con una cantidad específica que los usuarios deben pagar para acceder.
  • Revise el contenido protegido que ha creado.
  • A tus seguidores/usuarios, paga para ver tu contenido.
  • Comprueba si un usuario tiene acceso a tu contenido.
  • Cambie el costo de acceso al contenido si es necesario.
  • Desprotege el contenido (si deseas publicarlo para todos durante algún tiempo).
  • Retira el dinero recaudado por tu contenido.

Caso de uso

Puedes usar monetizado para proteger páginas de modo que solo los suscriptores puedan verlas, como en:

  • Portales de noticias.
  • Vídeos.
  • Audios.
  • Archivos
  • Blogs.
  • Redes sociales.
  • Y mucho más.

Pila de desarrollo

Para construir esta plataforma, utilizamos:


  • Solidity, para el contrato inteligente
  • Remezcla, para implementar el contrato inteligente
  • Red de prueba de portainjertos , como red para el proyecto
  • Javascript, para crear un SDK e integrarlo con sitios web.


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.

Cómo utilizar

  1. En la página que quieres monetizar, importa Web3.JS y Ethers.JS. Puedes hacerlo desde CDN, por ejemplo:
 <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>


  1. Descargar e importar monetizadov1.js
 <script src="./monetizado.js"></script>
  1. Crea el contenido protegido usando el contrato inteligente o en el Gerente .


  2. 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:


  • red: Es la red donde se ha protegido el contenido.


  • creator_address: Es la dirección (0x..) del creador del contenido. Puede ser tu dirección si eres el creador.


  • sequence_id: Es el ID con el que se dio por finalizado el contrato cuando se especificó el nuevo contenido protegido (inicia desde 0 en adelante, es numérico).


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.


  1. Utilice la propiedad window.monetizado ( instrucciones aquí ).


Tutorial del proyecto

Este proyecto ya está implementado en Rootstock testnet y puedes explorar los distintos enlaces a continuación, incluidos repositorios y una demostración:

  1. Instrucciones de contrato inteligente: https://github.com/Monetizado/Contracts
  2. SDK de Javascript: https://github.com/Monetizado/monetizadojs
  3. Monetizado Proxy SDK (para permitir monetizar páginas completas utilizando una página intermedia para pagar y verificar): https://github.com/Monetizado/proxyjs
  4. Monetizado Manager (para administrar tu contenido, recolectar el dinero y más sin interactuar con el contrato inteligente): https://monetizado.github.io/manager/
  5. Demostración con portainjerto: <https://monetizado.github.io/demosmonetizado/demo_rootstock.html ](https://monetizado.github.io/demosmonetizado/demo_rootstock.html)
  6. Vídeo de demostración:


Desafíos y soluciones

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.

Conclusión

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.