paint-brush
Rootstock でオンチェーン ペイパービュー プロトコルを構築する方法@nescampos
380 測定値
380 測定値

Rootstock でオンチェーン ペイパービュー プロトコルを構築する方法

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

長すぎる; 読むには

Monetizado は、オンチェーンのペイパービュー プロトコルです。Web3.0 を通じて、あらゆる Web ページや静的コンテンツを収益化できます。購読者だけが閲覧できるようにページを保護するために使用できます。
featured image - Rootstock でオンチェーン ペイパービュー プロトコルを構築する方法
Néstor Campos HackerNoon profile picture

アテンション エコノミー (Web 2.0) では、ユーザーは限定コンテンツ (アダルト コンテンツを含むあらゆる種類のコンテンツ) にアクセスするためにサブスクリプション料金を支払うよう「強制」されますが、コンテンツ作成者が新しいコンテンツを作成し続けなかったり、消費した分だけ支払いたいのに長期間サブスクリプションを続けなければならないなどの理由で、支払った分に見合ったメリットが得られる保証はありません。


しかし、Web 3.0 のインテンション エコノミーでは、マイクロペイメントを通じて、ユーザーが長期間ではなく消費した分だけ支払う機会がもたらされます。その結果、コンテンツ クリエイターはより多くの作品を更新し続けるようになり、中央ゲートウェイに依存せずに、非常に低いコストですぐに収入を得ることができます。

Monetizado、オンチェーンペイパービュープロトコル

Monetizado は、Web3 を通じてあらゆる Web ページや静的コンテンツ (変更を加えるためのバックエンドにアクセスできない場合) を収益化できるオンチェーンのペイパービュー プラットフォームです。


Monetizado は、ニュース サイト、ソーシャル ネットワーク、独占コンテンツ ポータルなどに実装できます。また、Monetizado を使用すると、ユーザーに料金を支払ってもらい、サイトで広告が表示されないようにすることもできます。

特徴

Monetizado を使用すると、次のことが可能になります。

  • 保護されたコンテンツに、ユーザーがアクセスするために支払う必要がある特定の金額を指定します。
  • 作成した保護されたコンテンツを確認します。
  • フォロワー/ユーザーに、コンテンツを見るために料金を支払ってもらいます。
  • ユーザーがコンテンツにアクセスできるかどうかを確認します。
  • 必要に応じて、コンテンツへのアクセスコストを変更します。
  • コンテンツの保護を解除します (一定期間、すべてのユーザーに公開する場合)。
  • コンテンツに対して集められたお金を引き出します。

使用事例

次のように、monetized を使用してページを保護し、購読者だけが閲覧できるようにすることができます。

  • ニュースポータル。
  • ビデオ。
  • オーディオ。
  • ファイル
  • ブログ。
  • ソーシャルネットワーク。
  • その他にも多数あります。

開発スタック

このプラットフォームを構築するために、次のものを使用しました。


  • スマートコントラクトのためのSolidity
  • スマートコントラクトを展開するためのRemix
  • プロジェクトのネットワークとしてのRootstockテストネット
  • Javascript を使用して SDK を作成し、Web サイトと統合します。


私たちのスマート コントラクトは非常に基本的なもので、収益化するコンテンツの名前、金額 (rBTC 単位)、コンテンツを有効/無効にしたり、支払いを支払ったり受け取ったりするためのいくつかの機能などを指定できます。


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; } }


マネージメント

// 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; } }


さらに、特に特定のコンテンツにアクセスするために料金を支払いたいユーザー向けに、Web サイト全体でスマート コントラクトを使用できるようにするJavaScript SDKを作成しました。

使い方

  1. 収益化したいページで、Web3.JS と Ethers.JS をインポートします。CDN から実行できます。例:
 <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. monetizadov1.jsをダウンロードしてインポートする
<script src="./monetizado.js"></script>
  1. スマートコントラクトを使用して保護されたコンテンツを作成するまたはマネージャー


  2. ページの HTML コードの先頭に、属性「rel」と値「monetized」を持つリンク タグを追加し、href で次の構造に従います。


  • ネットワーク: コンテンツが保護されているネットワークです。


  • Creator_address: コンテンツ作成者のアドレス (0x..) です。作成者の場合は、自分のアドレスにすることができます。


  • sequence_id: 新しい保護コンテンツを指定したときに契約が終了した ID です (0 から始まる数値です)。


例えば:

 <link rel="monetizado" href="rootstock:testnet://0xda3ec0b8bddd2e8bdedede3333fbaf938fcc18c5/0" />


前の例は、コンテンツが作成者 (たとえば 0xda3ec0b8bddd2e8bdedede3333fbaf938fcc18c5) によって保護されており (ID 0 によって)、その組み合わせでロックを解除するには支払いを行う必要があることを意味します。


  1. window.monetizado プロパティを使用します (手順はこちら)。


プロジェクトウォークスルー

このプロジェクトはすでに Rootstock テストネットにデプロイされており、リポジトリやデモなど、以下のさまざまなリンクを調べることができます。

  1. スマートコントラクトの説明: https://github.com/Monetizado/Contracts
  2. JavaScript SDK: https://github.com/Monetizado/monetizadojs
  3. Monetizado Proxy SDK (支払いと検証のための中間ページを使用してページ全体を収益化できるようにする): https://github.com/Monetizado/proxyjs
  4. Monetizado Manager (スマート コントラクトとやり取りせずに、コンテンツを管理したり、お金を集めたりなどを行う): https://monetizado.github.io/manager/
  5. Rootstock を使用したデモ: <https://monetizado.github.io/demosmonetizado/demo_rootstock.html ](https://monetizado.github.io/demosmonetizado/demo_rootstock.html)
  6. ビデオデモ:


課題と解決策

特にこのアイデアのために、私たちはコンテンツ作成者とユーザーの両方に大きな影響を与えることなく、Web3 を使用して Web 2.0 プラットフォームを収益化できるようにするという課題を自らに課しました。


そのため、ほとんどのコンテンツ作成者は Web サイトの編集に困難を抱えている可能性が高い (または編集スペースがあまりない外部プラットフォームを使用している) ため、Web サイトにほとんど変更を加えずにコンテンツを収益化できる JavaScript の SDK を作成する必要がありました。


このソリューションでは、収益化されているコンテンツを識別する方法を検討する必要があり、そこで HTML リンク タグを利用してそのコンテンツを指定し、ユーザーがすでに支払いを行ってアクセス権を持っている場合、または支払う必要がある場合に、SDK が rBTC の金額を検出しました。

結論

Rootstock は、分散型ネットワークとしての機能と堅牢性を活かし、BitcoinFi に大きなチャンスをもたらします。このコンテキストでは、マイクロペイメントを実現し、それを創造経済と結び付けます。


この「Monetized」の例は、Web2 プラットフォームで Web3 を使用するシンプルさを示しています。Web2 プラットフォームには、あらゆるタイプのユーザーのための巨大なスペースがあり、これらのテクノロジーを統合する際の摩擦が軽減されます。