• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

RootSoft/algoland: Build and deploy Non-Fungible Algorand Tokens with Laravel &a ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

RootSoft/algoland

开源软件地址:

https://github.com/RootSoft/algoland

开源编程语言:

PHP 96.9%

开源软件介绍:

Introduction

Laravel is a web application framework with an expressive, elegant syntax designed to make developing web apps easier and faster through built-in features. Laravel strives to provide an amazing developer experience, while providing powerful features such as thorough dependency injection, an expressive database abstraction layer, queues and scheduled jobs, unit and integration testing, and more.

In our solution, we will be using the TALL stack which is a full-stack development solution which combines a set of tools as a way of easily and quickly building applications. The TALL stack consists of the following:

  • Tailwind CSS - A utility-first CSS framework
  • AlpineJS - A minimal frontend development framework for adding JavaScript behavior to HTML markups
  • Laravel
  • Livewire - Building dynamic interfaces simple, without leaving the comfort of Laravel.

Note that this guide also applies to anyone who wishes to uses another front-end framework like Vue & React while using any PHP framework as your back-end. Inertia.js allows you to create fully client-side rendered, single-page apps, without much of the complexity that comes with modern SPAs. It does this by leveraging existing server-side frameworks, like Laravel and Rails.

Before we get started, I highly recommend you to read this excellent article by Jason Weathersby on the different approaches NFTs can be implemented on the Algorand blockchain. We will be focusing on the primary method to build and deploy an NFT which is by using the ASA (Algorand Standard Assets), a layer 1 primitive that allows an NFT to be created in seconds.

Create collectible

Requirements

  1. PHPStorm (or another PHP-supported IDE)
  2. PHP 7.4 (>=)
  3. Docker Desktop (when using Laravel Sail)
  4. IPFS Desktop
  5. (optional) A PureStake Account, and the corresponding API key OR a locally hosted node

Setting up our development environment

If it's your first time working with Laravel, I recommend you to go through the Getting Started section of the Laravel documentation to learn more about the different features and installation methods Laravel has to offer.

Laravel offers a couple of local development environments like Laravel Sail, Homestead, or Valet that provides you a wonderful development environment without requiring you to install PHP, a web server, and any other server software on your local machine. We are using the latest version of Laravel (at the time of writing 8.0), so we will be using the recommend approach, which is Laravel Sail.

!!!Sail Laravel Sail is a light-weight command-line interface for interacting with Laravel's default Docker development environment and provides a great starting point for building Laravel applications using PHP, MySQL, and Redis without requiring prior Docker experience. Make sure Docker is installed before using Laravel Sail.

Let's get started by cloning the project from Github. Once the project has been cloned, open it with your preferred IDE and open 3 new command prompts.

First we need to install all of our dependencies. None of the application's Composer dependencies, including Sail, will be installed after you clone the application's repository to your local computer. You may install the application's dependencies by navigating to the application's directory and executing the following command.

docker run --rm \
    -u "$(id -u):$(id -g)" \
    -v $(pwd):/opt \
    -w /opt \
    laravelsail/php80-composer:latest \
    composer install --ignore-platform-reqs

This command uses a small Docker container containing PHP and Composer to install the application's dependencies:

In the first terminal window, use the sail up command to start Laravel Sail. This will execute your application within a Docker container and is isolated from your local computer.

./vendor/bin/sail up

Terminal 1

In our second terminal, we will use the npm run watch command. The npm run watch command will continue running in your terminal and watch all relevant CSS and JavaScript files for changes. Webpack will automatically recompile your assets when it detects a change to one of these files:

npm install
npm run watch

Terminal 2

A new browser tab will open and you will be able to use the application. If you receive an error, make sure your dependencies are up to date (see the next step).

!!!BrowserSync BrowserSync is an automation tool that makes web development faster. It makes tweaking and testing faster by synchronizing file changes and interactions across many devices.

Our last terminal is used to perform Composer & Artisan console commands.

Let's do that and update our dependencies:

sail composer update

Terminal 3

Installation

If you wish to start from scratch, you will have to install the Algorand-PHP SDK in your project. We can do this by using the following command:

sail composer require rootsoft/algorand-php

This will install the sdk and all required dependencies in your project. For Laravel developers, I highly recommend to publish the configuration file so we can use the Algorand facade. Facades provide a "static" interface to classes that are available in the application's service container.

sail artisan vendor:publish --provider="Rootsoft\Algorand\AlgorandServiceProvider" --tag="config"

This will create an algorand.php file in your config directory. Open the file and update endpoints for Algod and Indexer to your preferred service.

!!!note In this solution we are using Rand Labs AlgoExplorer's API. At the time of writing, the note-prefix is disabled in PureStake's API. You can also host your own node or use the sandbox for development & testing on a private network.

Once that's been done, you can use the Algorand facade to easily perform Algorand related operations.

<?php
Algorand::sendPayment($account, $recipient, Algo::toMicroAlgos(10), 'Hi');

Account management

Before we can get started creating our Non-Fungible Token, we need to have an Algorand account in order to approve, authorize and sign transactions.

Accounts are entities on the Algorand blockchain associated with specific onchain data, like a balance. An Algorand Address is the identifier for an Algorand account. Creating an account means creating an Algorand cryptocurrency address that is managed by your mobile wallet, hence an account can be seen as your wallet.

Creating a new account or importing an existing account manages the account on the server, just like a custodial wallet. A custodial wallet is defined as a wallet in which the private keys are held by a third party (in this case, our application), meaning, we have a full control over your funds while you only have to give permission to send or receive payments. We can reverse these roles and give the dApp user full control over all transactions using AlgoSigner and MyAlgo Connect.

wallet

Create a new account

Creating a new account is really easy using the Algorand-PHP sdk. Since we published the algorand.php configuration file and have access to our Facade, we can create a new account using Algorand::accountManager()->createNewAccount();.

<?php
class CreateWalletModal extends Component
{
    public function createWallet(WalletService $walletService) {
        // Create a new account
        $account = Algorand::accountManager()->createNewAccount();

        // Store information in encrypted session
        $walletService->storeAccount('algoland', $account->getPublicAddress(), $account->getSeedPhrase()->words);

        // Navigate back
        return redirect()->route('wallet.index');
    }

    public function render()
    {
        return view('livewire.create-wallet-modal');
    }
}
<div class="text-center">
    <button class="btn mx-auto text-center" wire:click="createWallet()">Create account</button>
</div>

In our solution, we use a Livewire component to show a dialog with a button wired to the createWallet() method. There we create our new account using the Algorand Facade and store the account information in a Session. Once the account is created and our session is prepared, we redirect the user to the index page of our wallet.

!!!Caution In a production environment, you would never store your seed or seedphrase in a Session and expose it to the front-end. In this solution we are doing this for ease of use and demonstration purposes. Use a dedicated secure file management system.

Import an existing account

We can also import an existing account by entering our 25-word passphrase into our application using the restoreAccount() method.

Import account

<?php
class ImportWalletModal extends Component
{

    public $seedphrase;

    public function importWallet(WalletService $walletService)
    {
        try {
            // Restore account from seedphrase
            $account = Algorand::accountManager()->restoreAccount($this->seedphrase);

            // Store information in encrypted session
            $walletService->storeAccount('algoland', $account->getPublicAddress(), $account->getSeedPhrase()->words);

            // Navigate back
            redirect()->route('wallet.index');
        } catch (Exception $ex) {
            session()->flash('errorMessage', $ex->getMessage());
        }
    }

    public function render()
    {
        return view('livewire.import-wallet-modal');
    }
}
<form wire:submit.prevent="importWallet()" class="text-center">
    <input type="text"
           class="border p-2 border-gray-400 w-full rounded-lg text-sm  transition duration-150 ease-in-out focus:outline-none "
           placeholder="Your 25-word passphrase"
           wire:model="seedphrase"/>

    @if (session()->has('errorMessage'))
        <div class="text-red-500">
            {{ session('errorMessage') }}
        </div>
    @endif

    <button type="submit" class="btn mx-auto text-center mt-4">Import account</button>
</form>

Once again, we are using a Livewire component and two-way binding to bind our HTML input to the php variable $seedphrase. Once we click the Import account button, the restoreAccount() method restores your account and gets stored in the session off the application.

Connect with AlgoSigner

AlgoSigner is a blockchain wallet that makes it easy to use Algorand-based applications on the web, while you are still in control of your keys. Simply create or import your Algorand account, visit a compatible dApp, and approve or deny transactions — all from within your browser.

When installing the AlgoSigner extension from the Chrome Web Store, the Javascript is automatically injected in every webpage you visit, so it's not required to install any SDK or package into your application.

AlgoSigner Connect

async signInWithAlgoSigner() {
    // Check if AlgoSigner is installed
    if (!isAlgoSignerInstalled()) {
        console.log('AlgoSigner is not installed');
        return false;
    }
    
    // Check if AlgoSigner is connected
    const connected = await AlgoSigner.connect();

    if (!connected)
        return;

    // Fetch the first account
    const accounts = await AlgoSigner.accounts({ ledger: 'TestNet' });
    const formData = {
        provider: 'algosigner',
        address: accounts[0].address,
    };

    return axios.post('/signin', formData).then((response) => {
        window.location.href = "{{ route('wallet.index')}}";
    }).catch((error) => {
        console.log(error.response);
    });
},
<?php
public function signIn(ConnectWalletRequest $request) {
    // Store the account in the session
    $this->walletService->storeAccount($request->provider, $request->address);

    // Redirect to the installation page
    return redirect()->route('wallet.index');
}

In install-wallet.blade.php, we check if AlgoSigner extension is available and installed in the browser. If it's installed we use the connect() method which will show a dialog in order to give permissions for our dApp. Once permission has been giving, we fetch the first address in our accounts array and send an HTTP Post request to the signin endpoint of our server. This information is then stored in the Session for our user. Note that we provide a provider variable which is used to determine on how we signed in (algoland/our application, algosigner or myalgo).

Connect with MyAlgo Connect

MyAlgo Connect allows WebApp users to review and sign Algorand transactions using accounts secured within their MyAlgo Wallet. This enables Algorand applications to use MyAlgo Wallet to interact with the Algorand blockchain and users to access the applications in a private and secure manner.

The main novelty of MyAlgo Connect lies in the fact that all the process is managed in the user’s browser without the need for any backend service nor downloads, extensions or browser plugins.

!!!installation For MyAlgo connect, you need to install the SDK, which can be done through NPM npm install @randlabs/myalgo-connect

MyAlgo Connect

async signInWithMyAlgo() {
    const accounts = await myAlgoWallet.connect();

    const formData = {
        provider: 'myalgo',
        address: accounts[0].address,
    };

    return axios.post('/signin', formData).then((response) => {
        window.location.href = "{{ route('wallet.index')}}";
    }).catch((error) => {
        console.log(error.response);
    });
}

Funding our account

In order to register our new account on the Algorand ledger, we need to have a minimum balance of atleast 0.1 Algo. Therefore, a transaction that sends funds to a new account (i.e. an account with a 0 balance) must send a minimum of 100,000 microAlgos for the transaction to be valid. Similarly, any sending account must make sure that the amount of algos that they send will keep their remaining balance greater than or equal to 100,000 microAlgos.

In order to create our account onchain, we can use the Algorand dispenser on TestNet to fund our newly created account with some Algo. Just enter your address (using $account->getPublicAddress()) in the target address field and click Dispense. After a couple of seconds, you will see your transaction on AlgoExplorer.

Account information

account information

Now that we have our account connected to our application, we can use the public methods of the Algorand-php SDK to fetch all information about a given Algorand address.

Algorand::accountManager()->getAccountInformation($address); let us fetch all public information about an account including the balance, pending rewards, created assets & applications, and so much more. In our index method ,we pass all relevant information back to our view so it can easily be displayed on our webpage.

<?php
public function index()
{
    // Check if we have a current provider
    if (!request()->session()->has('provider')) {
        return redirect()->route('wallet.install');
    }

    $address = Session::get('address');
    $accountInformation = Algorand::accountManager()->getAccountInformation($address);

    return view('pages.wallet.index-wallet', [
        'provider' => Session::get('provider'),
        'address' => $address,
        'seedphrase' => Session::get('seedphrase'),
        'balance' => $accountInformation->amountWithoutPendingRewards,
    ]);
}
<div class="mt-6 space-y-4">
    <div>
        <p class="text-gray-600 text-center text-base font-bold">Signed in with</p>
        <p class="text-gray-600 text-center text-sm">{{ $provider }}</p>
    </div>

    <div>
        <p class="text-gray-600 text-center text-base font-bold">Your public address</p>
        <p class="text-gray-600 text-center text-sm">{{ $address }}</p>
    </div>

    <div>
        <p class="text-gray-600 text-center text-base font-bold">Balance</p>
        <p class="text-gray-600 text-center text-sm">{{ \Rootsoft\Algorand\Utils\Algo::fromMicroAlgos($balance) }} Algos</p>
    </div>

    @if($seedphrase)
        <div>
            <p class="text-gray-600 text-center text-base font-bold">Word list</p>
            <p class="text-gray-600 text-center text-sm">{{ implode(' ', $seedphrase)}}</p>
        </div>
    @endif
</div>

!!!note There is also a nice utility class, Algo to easily convert and format your microAlgos to Algos.

Create a collectible

NFTs are tokens that are unique and cannot be replaced with something else. Because of this, it’s perfect for digital collectibles, art, luxury goods and all sorts of other physical and digital products that can be verified on the blockchain. An example of an NFT could be the Mona Lisa. Even though someone can make a copy of it, there will always only be one Mona Lisa.

Create collectible

Quoting Jason Weathersby article, Building NFTs on Algorand:

The primary method a developer or Algorand user can use to build and deploy an NFT is by using the ASA feature. This feature is a layer 1 primitive that allows an NFT or FT to be created in seconds. These assets require no smart contract code. It only takes one transaction on the Algorand blockchain to create an NFT.

The required parameters are the Creator field which is automatically populated by the sender of the initial creation transaction, the Total number of the asset which represents a unit count for NFTs this should be set to 1, implied Decimals which allow each unit of an FT to be subdivided, and DefaultFrozen which specifies whether the token can be traded by default.

Creating an NFT on the Algorand blockchain is really easy, and you can actually create an NFT with one line of code using the Algorand-php SDK:

Algorand::assetManager()->createNewAsset($account, 'Mona Lisa', 'Mona Lisa', 1,0);

This lets us create an Algorand Standard Asset on the Algorand blockchain with the asset name Mona Lisa and unit name Mona Lisa. The total amount of Mona Lisa's to create is 1 and it cannot be divisible, hence the decimal field is 0. Now you might think, I just copy this code 5 times and create 5 Mona Lisa's? That’s basically true but what makes this asset unique is that the Algorand network generated a unique assetId for your NFT when your transaction was confirmed by the network, which in many collector’s and artists their minds the art holds value because of its unique ID on the blockchain. Similar to holding a physical (1/1) edition of a painting.

Now for our solution, we can only use the one-liner above for our server managed accounts, but since we want to also use AlgoSigner and MyAlgo Connect to sign our transactions we need to look for a different approach.

IPFS

When smart contracts and NFTs were being created, people quickly realized that it's really expensive to deploy a lot of data to the blockchain and since having creative art means you have to store this information somewhere. We could host the data ourselves on our own server using the excellent Media Library by Spatie, but this will break the decentralized approach that we are trying to achieve. Another solution would be storing our data off-chain using a decentralized file system like IPFS.

IPFS (Interplanetary File System) is a versioned file system which can store files and track version changes over time, similar to Git. In addition to storing files, IPFS acts as a distributed file system, much like BitTorrent. IPFS uses a content-addressed protocol to transfer content. This is done using a cryptographic hash on a file as the address.

A content identifier, or CID, is a label used to point to material in IPFS. It doesn't indicate where the content is stored, but it forms a kind of address based on the content itself. CIDs are short, regardless of the size of their underlying content.

For illustration purposes, here’s how a cat file looks on HTTP and IPFS:

Installation

Let's start by installing IPFS Desktop. IPFS Desktop bundles an IPFS node, file manager, peer manager, and content explorer into a single, easy to use application.

Open IPFS Desktop and wait until you are connected with the IPFS network.

IPFS Desktop

If your IPFS node is running, inspect the ipfs.php file in the config folder. This file is published from the Laravel-IPFS service provider. In the github sample, the connection with our sail instance is already provided.

!!!note Addresses using TCP port 4001 are known as "swarm addresses" that your local daemon will listen on for connections from other IPFS peers. Make sure to bind to another port if you are using the Sandbox environment

** IPFS Pinning Service **

When an IPFS node retrieves data from the network it keeps a local cache of that data for future usage, taking up space on that particular IPFS node. IPFS nodes frequently clear this cache out in order to make room for new content. If your node is not online, you might also not able to serve content

But, what happens if you want to make sure that certain content will never be deleted? The act of saving data on an IPFS node is often referred to as “pinning”. An IPFS pinning service is an IPFS node or collection of IPFS nodes dedicated to pinning other peoples’ and apps’ content on IPFS.

IPFS pinning services have IPFS nodes that are always online. Because these nodes are usually cloud hosted, they act as a reliable way of keeping your data available even if your own IPFS node isn’t always online. This allows you and your users to access your content anywhere at any time, regardless of device.

Pinata is an example of an IPFS Pinning Service and provides secure and verifiable files for your NFTs. Whether you are a platform, creator, or collector, simply upload through Pinata, copy your IPFS CID, and attach to your NFT before minting to have secure and verifiable NFT files.

!!!note If you want to know more about IPFS, check out this great article.

Adding metadata

People also also wanted a lightweight way to store attributes about an NFT – and this is where the metadata come into play. Metadata describes how our


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap