Saul  Alaniz

Saul Alaniz

1655776800

Creación De Una Aplicación DeFi De Pila Completa Con Polygon

DeFi es ahora un tema importante de discusión en el espacio de las criptomonedas. DeFi significa "finanzas descentralizadas", lo que significa que no hay una autoridad central que vigile y controle la transferencia de fondos. Esto también significa que las transacciones en DeFi son P2P (peer to peer), lo que significa que ninguna autoridad central es responsable de la transferencia y los fondos se envían directamente de una entidad a otra.

En este artículo, aprenderemos cómo comenzar con DeFi creando una aplicación DeFi de pila completa en la cadena Polygon utilizando Next.js como interfaz. Esta aplicación venderá y comprará OKToken (un token ficticio) del usuario. Sin embargo, cada transacción de compra reduce un token de la cantidad de tokens que puede obtener por MATIC (la venta aumenta este número en uno). Esta no es una demostración ideal, pero de esta manera puede comprender cómo usar su propia lógica en los contratos inteligentes de Solidity y aprender a crear su propia aplicación DeFi de pila completa usando Polygon.

Requisitos

Para comenzar con este tutorial, asegúrese de tener lo siguiente:

Ahora que ha verificado los requisitos, procedamos a crear nuestro proyecto Hardhat para que funcione con nuestros contratos inteligentes de Solidity .

Creación de un proyecto de casco

Navegue a un directorio seguro y ejecute el siguiente comando en la terminal para inicializar su proyecto Hardhat:

npx hardhat

Una vez que ejecute el comando, debería ver el siguiente asistente de inicialización de Hardhat en su terminal.

En la lista, elija Crear un proyecto de ejemplo avanzado . Luego se le preguntará dónde desea inicializar el proyecto Hardhat; no cambie el campo, simplemente presione Entrar para que el proyecto se inicialice en el directorio actual.

Luego se le preguntará si desea o no instalar las dependencias requeridas para que se ejecute su proyecto Hardhat. Presiona y porque necesitaremos estas dependencias, e instalarlas ahora mismo es la mejor idea.

Se iniciará la instalación de las dependencias y puede tardar unos segundos o minutos, según el equipo que esté ejecutando. Ahora, ejecute el siguiente comando en la terminal para instalar otra dependencia que necesitaremos para facilitar el desarrollo de nuestro contrato Solidity:

npm install @openzeppelin/contracts

OpenZeppelin proporciona estándares de contratos inteligentes que podemos usar en nuestros propios contratos inteligentes para crear fácilmente contratos Ownable, ERC-20 y ERC-721, y más.

Una vez que las dependencias se hayan instalado correctamente, abra el directorio en un editor de código. Usaré VS Code para este tutorial.

Crearemos dos contratos inteligentes: el primero será nuestro propio token ERC-20 y el segundo será un contrato de proveedor, lo que facilitará la compra y venta de estos tokens.

Creando nuestros contratos inteligentes

Ahora, vaya a la contractscarpeta y cree un nuevo archivo Solidity llamado OKToken.sol, que contendrá nuestro contrato de token ERC-20.

Use el siguiente código para este archivo:

// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract OKToken is ERC20 {
    constructor() ERC20("OKT", "OKToken"){
        _mint(msg.sender, 10000 * 10 ** 18);
    }
}

En el código anterior, estamos importando el ERC20.solarchivo desde @openzeppelin/contractsel cual nos ayudará a comenzar fácilmente con un token ERC-20. Luego, en el constructor, proporcionamos el símbolo "OKT"y el nombre "OKToken"de nuestro token.

¡Eso es todo por el contrato simbólico! Ahora, trabajemos en el contrato de proveedor. Debajo de la contractscarpeta, cree un nuevo archivo llamado OKVendor.solcon el siguiente código:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "./OKToken.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract OKVendor is Ownable {
  OKToken yourToken;
  uint256 public tokensPerNativeCurrency = 100;
  event BuyTokens(address buyer, uint256 amountOfNativeCurrency, uint256 amountOfTokens);
  constructor(address tokenAddress) {
    yourToken = OKToken(tokenAddress);
  }

  function buyTokens() public payable returns (uint256 tokenAmount) {
    require(msg.value > 0, "You need to send some NativeCurrency to proceed");
    uint256 amountToBuy = msg.value * tokensPerNativeCurrency;

    uint256 vendorBalance = yourToken.balanceOf(address(this));
    require(vendorBalance >= amountToBuy, "Vendor contract has not enough tokens to perform transaction");

    (bool sent) = yourToken.transfer(msg.sender, amountToBuy);
    require(sent, "Failed to transfer token to user");
    tokensPerNativeCurrency = tokensPerNativeCurrency - 1;

    emit BuyTokens(msg.sender, msg.value, amountToBuy);
    return amountToBuy;
  }
  function sellTokens(uint256 tokenAmountToSell) public {

    require(tokenAmountToSell > 0, "Specify an amount of token greater than zero");

    uint256 userBalance = yourToken.balanceOf(msg.sender);
    require(userBalance >= tokenAmountToSell, "You have insufficient tokens");

    uint256 amountOfNativeCurrencyToTransfer = tokenAmountToSell / tokensPerNativeCurrency;
    uint256 ownerNativeCurrencyBalance = address(this).balance;
    require(ownerNativeCurrencyBalance >= amountOfNativeCurrencyToTransfer, "Vendor has insufficient funds");
    (bool sent) = yourToken.transferFrom(msg.sender, address(this), tokenAmountToSell);
    require(sent, "Failed to transfer tokens from user to vendor");

    (sent,) = msg.sender.call{value: amountOfNativeCurrencyToTransfer}("");
    tokensPerNativeCurrency = tokensPerNativeCurrency + 1;
    require(sent, "Failed to send NativeCurrency to the user");
  }
  function getNumberOfTokensInNativeCurrency() public view returns(uint256) {
    return tokensPerNativeCurrency;
  }

  function withdraw() public onlyOwner {
    uint256 ownerBalance = address(this).balance;
    require(ownerBalance > 0, "No NativeCurrency present in Vendor");
    (bool sent,) = msg.sender.call{value: address(this).balance}("");
    require(sent, "Failed to withdraw");
  }
}

Esto nos ayudará a facilitar la compra y venta de tokens.

En el contrato anterior, primero importamos nuestro contrato de token, que necesitamos para interactuar con nuestro contrato de token mediante el contrato de proveedor y las funciones de llamada.

También estamos importando Ownable.soldesde @openzeppelin/contracts. Esto significa que el propietario del contrato inteligente puede transferir su propiedad y tener acceso a funciones exclusivas para propietarios.

Después de inicializar el contrato inteligente, definimos la variable tokensPerNativeCurrencyque indica la cantidad de tokens que se pueden comprar con 1 MATIC. Modificaremos este número en función de las transacciones realizadas.

Luego tenemos un constructor que tomará la dirección del contrato de OKToken para que podamos comunicarnos con el contrato implementado y realizar funciones en él.

En la buyTokens()función, estamos realizando verificaciones para garantizar que se envíe la cantidad adecuada de MATIC al contrato inteligente y que el contrato del proveedor tenga la cantidad requerida de tokens. Luego llamamos a la función transfer()desde la instancia de OKToken que creamos previamente para transferir los tokens al remitente de la solicitud.

En la sellTokens()función, estamos realizando comprobaciones para asegurarnos de que el remitente de la solicitud tenga suficientes tokens y si el contrato del proveedor tiene suficiente MATIC para devolver al remitente de la solicitud. Luego, usamos la transferFrom()función de la instancia de OKToken que creamos previamente para transferir los tokens de la billetera del remitente de la solicitud al contrato inteligente. Sin embargo, el remitente debe aprobar esta transacción; realizamos esta aprobación del lado del cliente antes de realizar la solicitud. Cubriremos esta parte cuando hagamos el front-end de esta aplicación.

Por último, tenemos la withdraw()función, a la que solo puede acceder el propietario de los contratos. Les permite retirar todas las MATIC presentes en el contrato.

Ahora que tenemos listos los contratos inteligentes, ¡vamos a implementarlos en la red de prueba de Polygon Mumbai!

Desplegando nuestros contratos inteligentes

Crearemos un script para implementar nuestro contrato en Polygon Mumbai. Una vez que se implementen los contratos, enviaremos mediante programación todos los tokens almacenados en la billetera del implementador al contrato del proveedor.

Primero vaya a hardhat.config.jsy debajo module.exports, agregue el siguiente objeto para que Hardhat sepa a qué red conectarse:

networks: {
  mumbai: {
    url: "https://matic-mumbai.chainstacklabs.com",
    accounts: ["PRIVATE KEY HERE"],
  }
}

Estamos proporcionando un nombre a la red ( mumbaien este caso) y proporcionando una URL de RPC. La URL de RPC mencionada es para Polygon Mumbai. Si desea utilizar Polygon Mainnet, puede elegir su URL de RPC . Recuerde ingresar su propia clave privada de billetera con alguna prueba MATIC para pagar las tarifas de gas involucradas en el proceso de implementación del contrato inteligente.

Ahora, debajo de la scriptscarpeta, cree un nuevo archivo llamado deploy.js. Pega lo siguiente:

const { BigNumber, utils } = require("ethers");
const hardhat = require("hardhat");
async function main() {
  const OKToken = await hardhat.ethers.getContractFactory("OKToken");
  const oktoken = await OKToken.deploy();
  await oktoken.deployed();
  console.log("[] OKToken deployed to address: " + oktoken.address);
  const OKVendor = await hardhat.ethers.getContractFactory("OKVendor");
  const okvendor = await OKVendor.deploy(oktoken.address);
  console.log("[] OKVendor deployed to address: " + okvendor.address);
  await oktoken.deployed();
  // Transfer oktokens to vendor
  await oktoken.functions.transfer(okvendor.address, utils.parseEther("10000"));
  console.log("[] Tokens transferred to OKVendor");
}
main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
});

En el archivo anterior, le indicamos a Hardhat cómo implementar nuestro contrato. La main()función es el punto de entrada aquí. Primero, obtenemos el OKTokencontrato y lo implementamos. Luego, obtenemos el OKVendorcontrato, proporcionamos OKTokenla dirección del contrato en el constructor e implementamos el contrato. Luego, transferimos todos los fondos de OKTokencontrato a OKVendorcontrato.

Ejecute el siguiente comando en la terminal para ejecutar el script e implementar nuestros contratos en la red de Polygon Mumbai:

npx hardhat run --network mumbai scripts/deploy.js --show-stack-traces

Tenga en cuenta que el nombre de la red debe coincidir con el mencionado en hardhat.config.js. Después de ejecutar el script, los contratos deberían implementarse y debería ver lo siguiente en su terminal:

Si ve un resultado similar a este, sus contratos inteligentes se implementaron y configuraron correctamente. Ahora, procedamos a crear nuestra aplicación Next.js.

Creación de una aplicación DeFi Next.js

En el mismo directorio, ejecute el siguiente comando en la terminal para crear su aplicación Next.js:

npx create-next-app frontend

El comando anterior creará una nueva aplicación e instalará automáticamente las dependencias necesarias.

Navegue a la frontendcarpeta y use el siguiente comando en la terminal para instalar dependencias adicionales, que nos ayudarán a interactuar con nuestros contratos inteligentes:

yarn add @thirdweb-dev/react @thirdweb-dev/sdk ethers web3

Estamos instalando @thirdweb-dev/reacty @thirdweb-dev/sdkpara que podamos autenticar fácilmente al usuario y conectar sus billeteras a nuestra aplicación usando MetaMask . etherses una dependencia necesaria para ThirdWeb, por lo que también debemos instalarla. Finalmente, estamos instalando web3para que podamos interactuar con nuestro contrato inteligente.

Agregar el tercer proveedor web

Para comenzar, debemos envolver nuestra aplicación dentro de un thirdwebProviderpara que Thirdweb pueda funcionar correctamente.

Vaya a su _app.jsarchivo en la pagescarpeta y agregue lo siguiente:

import { thirdwebProvider, ChainId } from "@thirdweb-dev/react";
import "../styles/globals.css";
function MyApp({ Component, pageProps }) {
  return (
    <thirdwebProvider desiredChainId={ChainId.Mumbai}>
      <Component {...pageProps} />
    </thirdwebProvider>
  );
}
export default MyApp;

En el código anterior, estamos importando thirdwebProvidery adjuntando nuestra aplicación dentro de él. También proporcionamos una desiredChainIdidentificación de cadena de Polygon Mumbai. También puede usar la identificación de la cadena para Polygon Mainnet si lo desea.

Cree un nuevo archivo en la raíz de su aplicación Next.js llamado contracts.jsy agregue el siguiente contenido:

export const oktoken = {
  contractAddress: "0xE83DD81890C76BB8c4b8Bc6365Ad95E5e71495E5",
  abi: [
    {
      inputs: [],
      stateMutability: "nonpayable",
      type: "constructor",
    },
    {
      anonymous: false,
      inputs: [
        {
          indexed: true,
          internalType: "address",
          name: "owner",
          type: "address",
        },
        {
          indexed: true,
          internalType: "address",
          name: "spender",
          type: "address",
        },
        {
          indexed: false,
          internalType: "uint256",
          name: "value",
          type: "uint256",
        },
      ],
      name: "Approval",
      type: "event",
    },
    {
      anonymous: false,
      inputs: [
        {
          indexed: true,
          internalType: "address",
          name: "from",
          type: "address",
        },
        {
          indexed: true,
          internalType: "address",
          name: "to",
          type: "address",
        },
        {
          indexed: false,
          internalType: "uint256",
          name: "value",
          type: "uint256",
        },
      ],
      name: "Transfer",
      type: "event",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "owner",
          type: "address",
        },
        {
          internalType: "address",
          name: "spender",
          type: "address",
        },
      ],
      name: "allowance",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "spender",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "amount",
          type: "uint256",
        },
      ],
      name: "approve",
      outputs: [
        {
          internalType: "bool",
          name: "",
          type: "bool",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "account",
          type: "address",
        },
      ],
      name: "balanceOf",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "decimals",
      outputs: [
        {
          internalType: "uint8",
          name: "",
          type: "uint8",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "spender",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "subtractedValue",
          type: "uint256",
        },
      ],
      name: "decreaseAllowance",
      outputs: [
        {
          internalType: "bool",
          name: "",
          type: "bool",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "spender",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "addedValue",
          type: "uint256",
        },
      ],
      name: "increaseAllowance",
      outputs: [
        {
          internalType: "bool",
          name: "",
          type: "bool",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [],
      name: "name",
      outputs: [
        {
          internalType: "string",
          name: "",
          type: "string",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "symbol",
      outputs: [
        {
          internalType: "string",
          name: "",
          type: "string",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "totalSupply",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "to",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "amount",
          type: "uint256",
        },
      ],
      name: "transfer",
      outputs: [
        {
          internalType: "bool",
          name: "",
          type: "bool",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "from",
          type: "address",
        },
        {
          internalType: "address",
          name: "to",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "amount",
          type: "uint256",
        },
      ],
      name: "transferFrom",
      outputs: [
        {
          internalType: "bool",
          name: "",
          type: "bool",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
  ],
};
export const okvendor = {
  contractAddress: "0xAa3b8cbB24aF3EF68a0B1760704C969E57c53D7A",
  abi: [
    {
      inputs: [
        {
          internalType: "address",
          name: "tokenAddress",
          type: "address",
        },
      ],
      stateMutability: "nonpayable",
      type: "constructor",
    },
    {
      anonymous: false,
      inputs: [
        {
          indexed: false,
          internalType: "address",
          name: "buyer",
          type: "address",
        },
        {
          indexed: false,
          internalType: "uint256",
          name: "amountOfNativeCurrency",
          type: "uint256",
        },
        {
          indexed: false,
          internalType: "uint256",
          name: "amountOfTokens",
          type: "uint256",
        },
      ],
      name: "BuyTokens",
      type: "event",
    },
    {
      anonymous: false,
      inputs: [
        {
          indexed: true,
          internalType: "address",
          name: "previousOwner",
          type: "address",
        },
        {
          indexed: true,
          internalType: "address",
          name: "newOwner",
          type: "address",
        },
      ],
      name: "OwnershipTransferred",
      type: "event",
    },
    {
      inputs: [],
      name: "buyTokens",
      outputs: [
        {
          internalType: "uint256",
          name: "tokenAmount",
          type: "uint256",
        },
      ],
      stateMutability: "payable",
      type: "function",
    },
    {
      inputs: [],
      name: "getNumberOfTokensInNativeCurrency",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "owner",
      outputs: [
        {
          internalType: "address",
          name: "",
          type: "address",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "renounceOwnership",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "uint256",
          name: "tokenAmountToSell",
          type: "uint256",
        },
      ],
      name: "sellTokens",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [],
      name: "tokensPerNativeCurrency",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "newOwner",
          type: "address",
        },
      ],
      name: "transferOwnership",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [],
      name: "withdraw",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
  ],
};

Recuerde reemplazar las direcciones del contrato con las suyas para que la aplicación Next.js intente conectarse al contrato inteligente correcto.

Ahora comencemos a codificar nuestra aplicación. Abra index.jsel archivo en la pagescarpeta y agregue lo siguiente:

import { useAddress, useContract, useMetamask } from "@thirdweb-dev/react";
import Head from "next/head";
import Image from "next/image";
import { oktoken, okvendor } from "../contracts";
import styles from "../styles/Home.module.css";
import { useEffect, useState } from "react";
import Web3 from "web3";
const web3 = new Web3(Web3.givenProvider);
export default function Home() {
  const [tokensPerCurrency, setTokensPerCurrency] = useState(0);
  const [tokens, setTokens] = useState(0);
  const address = useAddress();
  const connectUsingMetamask = useMetamask();
  const account = web3.defaultAccount;
  const purchase = async () => {
    const contract = new web3.eth.Contract(
      okvendor.abi,
      okvendor.contractAddress
    );
    const ethToSend = tokens / tokensPerCurrency;
    const purchase = await contract.methods.buyTokens().send({
      from: address,
      value: web3.utils.toWei(ethToSend.toString(), "ether"),
    });
    console.log(purchase);
    await fetchPrice();
  };
  const sell = async () => {
    const vendorContract = new web3.eth.Contract(
      okvendor.abi,
      okvendor.contractAddress
    );
    const tokenContract = new web3.eth.Contract(
      oktoken.abi,
      oktoken.contractAddress
    );
    const approve = await tokenContract.methods
      .approve(
        okvendor.contractAddress,
        web3.utils.toWei(tokens.toString(), "ether")
      )
      .send({
        from: address,
      });
    const sellTokens = await vendorContract.methods.sellTokens(tokens).send({
      from: address,
    });
    await fetchPrice();
  };
  const fetchPrice = async () => {
    const contract = new web3.eth.Contract(
      okvendor.abi,
      okvendor.contractAddress
    );
    const priceFromContract = await contract.methods
      .getNumberOfTokensInNativeCurrency()
      .call();
    setTokensPerCurrency(priceFromContract);
  };
  useEffect(() => {
    fetchPrice();
  }, []);
  return (
    <div>
      <Head>
        <title>Exchange OKTokens</title>
      </Head>
      {address ? (
        <div>
          <p>Tokens per currency: {tokensPerCurrency}</p>
          <div>
            <input
              type="number"
              value={tokens}
              onChange={(e) => setTokens(e.target.value)}
            />
          </div>
          <button onClick={purchase}>Purchase</button>
          <button onClick={sell}>Sell</button>
        </div>
      ) : (
        <div>
          <button onClick={connectUsingMetamask}>Connect using MetaMask</button>
        </div>
      )}
    </div>
  );
}

Este es un bloque de código largo, así que veamos qué está haciendo el código paso a paso:

  • Inicializar el web3paquete usando un proveedor configurado por thirdweb
  • Usar enlaces de terceros useMetamask()para autenticarse y useAddress()verificar el estado de autenticación, luego mostrar el botón de inicio de sesión si el usuario no tiene una billetera conectada usando MetaMask
  • Configuración de varios estados para mapear cuadros de texto en nuestra aplicación
  • Crear una fetchPrice()función para interactuar con nuestro contrato inteligente y verificar cuántos tokens puede obtener un MATIC, al mismo tiempo que crea un useEffectpara verificar este precio cada vez que se carga la página
  • Creando una purchase()función, que inicializa nuestro contrato de proveedor y llama a la buyTokens()función desde el contrato, luego envía algo de MATIC junto con esta transacción. Luego, llamamos fetchPrice()para que se muestre el último precio .

Finalmente, estamos creando una sell()función que inicializa tanto el token como el contrato de proveedor. Primero, interactuamos con la approve()función del contrato de token y permitimos que el contrato del proveedor transfiera fondos en nuestro nombre. Luego estamos llamando sellTokens()a la función del contrato del proveedor para finalmente vender los tokens y recibir MATIC. También estamos llamando fetchPrice()para obtener el último precio después de la transacción.

¡Nuestra sencilla aplicación DeFi está completa! Puede ver esta aplicación en su navegador ejecutando el siguiente comando:

yarn dev

Ahora, una vez que visite http://localhost:3000 , debería ver la siguiente pantalla y debería poder realizar transacciones.

Conclusión

Este fue un tutorial simple sobre cómo crear su propia aplicación DeFi de pila completa basada en Polygon. Puede implementar su propia lógica en los contratos inteligentes para hacerlo aún mejor según su organización. Sugiero jugar con el código para que puedas aprender de la mejor manera posible.

Esta historia se publicó originalmente en https://blog.logrocket.com/creating-full-stack-defi-app-polygon/

#defi #polygon #nextjs 

What is GEEK

Buddha Community

Creación De Una Aplicación DeFi De Pila Completa Con Polygon
Saul  Alaniz

Saul Alaniz

1655776800

Creación De Una Aplicación DeFi De Pila Completa Con Polygon

DeFi es ahora un tema importante de discusión en el espacio de las criptomonedas. DeFi significa "finanzas descentralizadas", lo que significa que no hay una autoridad central que vigile y controle la transferencia de fondos. Esto también significa que las transacciones en DeFi son P2P (peer to peer), lo que significa que ninguna autoridad central es responsable de la transferencia y los fondos se envían directamente de una entidad a otra.

En este artículo, aprenderemos cómo comenzar con DeFi creando una aplicación DeFi de pila completa en la cadena Polygon utilizando Next.js como interfaz. Esta aplicación venderá y comprará OKToken (un token ficticio) del usuario. Sin embargo, cada transacción de compra reduce un token de la cantidad de tokens que puede obtener por MATIC (la venta aumenta este número en uno). Esta no es una demostración ideal, pero de esta manera puede comprender cómo usar su propia lógica en los contratos inteligentes de Solidity y aprender a crear su propia aplicación DeFi de pila completa usando Polygon.

Requisitos

Para comenzar con este tutorial, asegúrese de tener lo siguiente:

Ahora que ha verificado los requisitos, procedamos a crear nuestro proyecto Hardhat para que funcione con nuestros contratos inteligentes de Solidity .

Creación de un proyecto de casco

Navegue a un directorio seguro y ejecute el siguiente comando en la terminal para inicializar su proyecto Hardhat:

npx hardhat

Una vez que ejecute el comando, debería ver el siguiente asistente de inicialización de Hardhat en su terminal.

En la lista, elija Crear un proyecto de ejemplo avanzado . Luego se le preguntará dónde desea inicializar el proyecto Hardhat; no cambie el campo, simplemente presione Entrar para que el proyecto se inicialice en el directorio actual.

Luego se le preguntará si desea o no instalar las dependencias requeridas para que se ejecute su proyecto Hardhat. Presiona y porque necesitaremos estas dependencias, e instalarlas ahora mismo es la mejor idea.

Se iniciará la instalación de las dependencias y puede tardar unos segundos o minutos, según el equipo que esté ejecutando. Ahora, ejecute el siguiente comando en la terminal para instalar otra dependencia que necesitaremos para facilitar el desarrollo de nuestro contrato Solidity:

npm install @openzeppelin/contracts

OpenZeppelin proporciona estándares de contratos inteligentes que podemos usar en nuestros propios contratos inteligentes para crear fácilmente contratos Ownable, ERC-20 y ERC-721, y más.

Una vez que las dependencias se hayan instalado correctamente, abra el directorio en un editor de código. Usaré VS Code para este tutorial.

Crearemos dos contratos inteligentes: el primero será nuestro propio token ERC-20 y el segundo será un contrato de proveedor, lo que facilitará la compra y venta de estos tokens.

Creando nuestros contratos inteligentes

Ahora, vaya a la contractscarpeta y cree un nuevo archivo Solidity llamado OKToken.sol, que contendrá nuestro contrato de token ERC-20.

Use el siguiente código para este archivo:

// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract OKToken is ERC20 {
    constructor() ERC20("OKT", "OKToken"){
        _mint(msg.sender, 10000 * 10 ** 18);
    }
}

En el código anterior, estamos importando el ERC20.solarchivo desde @openzeppelin/contractsel cual nos ayudará a comenzar fácilmente con un token ERC-20. Luego, en el constructor, proporcionamos el símbolo "OKT"y el nombre "OKToken"de nuestro token.

¡Eso es todo por el contrato simbólico! Ahora, trabajemos en el contrato de proveedor. Debajo de la contractscarpeta, cree un nuevo archivo llamado OKVendor.solcon el siguiente código:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "./OKToken.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract OKVendor is Ownable {
  OKToken yourToken;
  uint256 public tokensPerNativeCurrency = 100;
  event BuyTokens(address buyer, uint256 amountOfNativeCurrency, uint256 amountOfTokens);
  constructor(address tokenAddress) {
    yourToken = OKToken(tokenAddress);
  }

  function buyTokens() public payable returns (uint256 tokenAmount) {
    require(msg.value > 0, "You need to send some NativeCurrency to proceed");
    uint256 amountToBuy = msg.value * tokensPerNativeCurrency;

    uint256 vendorBalance = yourToken.balanceOf(address(this));
    require(vendorBalance >= amountToBuy, "Vendor contract has not enough tokens to perform transaction");

    (bool sent) = yourToken.transfer(msg.sender, amountToBuy);
    require(sent, "Failed to transfer token to user");
    tokensPerNativeCurrency = tokensPerNativeCurrency - 1;

    emit BuyTokens(msg.sender, msg.value, amountToBuy);
    return amountToBuy;
  }
  function sellTokens(uint256 tokenAmountToSell) public {

    require(tokenAmountToSell > 0, "Specify an amount of token greater than zero");

    uint256 userBalance = yourToken.balanceOf(msg.sender);
    require(userBalance >= tokenAmountToSell, "You have insufficient tokens");

    uint256 amountOfNativeCurrencyToTransfer = tokenAmountToSell / tokensPerNativeCurrency;
    uint256 ownerNativeCurrencyBalance = address(this).balance;
    require(ownerNativeCurrencyBalance >= amountOfNativeCurrencyToTransfer, "Vendor has insufficient funds");
    (bool sent) = yourToken.transferFrom(msg.sender, address(this), tokenAmountToSell);
    require(sent, "Failed to transfer tokens from user to vendor");

    (sent,) = msg.sender.call{value: amountOfNativeCurrencyToTransfer}("");
    tokensPerNativeCurrency = tokensPerNativeCurrency + 1;
    require(sent, "Failed to send NativeCurrency to the user");
  }
  function getNumberOfTokensInNativeCurrency() public view returns(uint256) {
    return tokensPerNativeCurrency;
  }

  function withdraw() public onlyOwner {
    uint256 ownerBalance = address(this).balance;
    require(ownerBalance > 0, "No NativeCurrency present in Vendor");
    (bool sent,) = msg.sender.call{value: address(this).balance}("");
    require(sent, "Failed to withdraw");
  }
}

Esto nos ayudará a facilitar la compra y venta de tokens.

En el contrato anterior, primero importamos nuestro contrato de token, que necesitamos para interactuar con nuestro contrato de token mediante el contrato de proveedor y las funciones de llamada.

También estamos importando Ownable.soldesde @openzeppelin/contracts. Esto significa que el propietario del contrato inteligente puede transferir su propiedad y tener acceso a funciones exclusivas para propietarios.

Después de inicializar el contrato inteligente, definimos la variable tokensPerNativeCurrencyque indica la cantidad de tokens que se pueden comprar con 1 MATIC. Modificaremos este número en función de las transacciones realizadas.

Luego tenemos un constructor que tomará la dirección del contrato de OKToken para que podamos comunicarnos con el contrato implementado y realizar funciones en él.

En la buyTokens()función, estamos realizando verificaciones para garantizar que se envíe la cantidad adecuada de MATIC al contrato inteligente y que el contrato del proveedor tenga la cantidad requerida de tokens. Luego llamamos a la función transfer()desde la instancia de OKToken que creamos previamente para transferir los tokens al remitente de la solicitud.

En la sellTokens()función, estamos realizando comprobaciones para asegurarnos de que el remitente de la solicitud tenga suficientes tokens y si el contrato del proveedor tiene suficiente MATIC para devolver al remitente de la solicitud. Luego, usamos la transferFrom()función de la instancia de OKToken que creamos previamente para transferir los tokens de la billetera del remitente de la solicitud al contrato inteligente. Sin embargo, el remitente debe aprobar esta transacción; realizamos esta aprobación del lado del cliente antes de realizar la solicitud. Cubriremos esta parte cuando hagamos el front-end de esta aplicación.

Por último, tenemos la withdraw()función, a la que solo puede acceder el propietario de los contratos. Les permite retirar todas las MATIC presentes en el contrato.

Ahora que tenemos listos los contratos inteligentes, ¡vamos a implementarlos en la red de prueba de Polygon Mumbai!

Desplegando nuestros contratos inteligentes

Crearemos un script para implementar nuestro contrato en Polygon Mumbai. Una vez que se implementen los contratos, enviaremos mediante programación todos los tokens almacenados en la billetera del implementador al contrato del proveedor.

Primero vaya a hardhat.config.jsy debajo module.exports, agregue el siguiente objeto para que Hardhat sepa a qué red conectarse:

networks: {
  mumbai: {
    url: "https://matic-mumbai.chainstacklabs.com",
    accounts: ["PRIVATE KEY HERE"],
  }
}

Estamos proporcionando un nombre a la red ( mumbaien este caso) y proporcionando una URL de RPC. La URL de RPC mencionada es para Polygon Mumbai. Si desea utilizar Polygon Mainnet, puede elegir su URL de RPC . Recuerde ingresar su propia clave privada de billetera con alguna prueba MATIC para pagar las tarifas de gas involucradas en el proceso de implementación del contrato inteligente.

Ahora, debajo de la scriptscarpeta, cree un nuevo archivo llamado deploy.js. Pega lo siguiente:

const { BigNumber, utils } = require("ethers");
const hardhat = require("hardhat");
async function main() {
  const OKToken = await hardhat.ethers.getContractFactory("OKToken");
  const oktoken = await OKToken.deploy();
  await oktoken.deployed();
  console.log("[] OKToken deployed to address: " + oktoken.address);
  const OKVendor = await hardhat.ethers.getContractFactory("OKVendor");
  const okvendor = await OKVendor.deploy(oktoken.address);
  console.log("[] OKVendor deployed to address: " + okvendor.address);
  await oktoken.deployed();
  // Transfer oktokens to vendor
  await oktoken.functions.transfer(okvendor.address, utils.parseEther("10000"));
  console.log("[] Tokens transferred to OKVendor");
}
main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
});

En el archivo anterior, le indicamos a Hardhat cómo implementar nuestro contrato. La main()función es el punto de entrada aquí. Primero, obtenemos el OKTokencontrato y lo implementamos. Luego, obtenemos el OKVendorcontrato, proporcionamos OKTokenla dirección del contrato en el constructor e implementamos el contrato. Luego, transferimos todos los fondos de OKTokencontrato a OKVendorcontrato.

Ejecute el siguiente comando en la terminal para ejecutar el script e implementar nuestros contratos en la red de Polygon Mumbai:

npx hardhat run --network mumbai scripts/deploy.js --show-stack-traces

Tenga en cuenta que el nombre de la red debe coincidir con el mencionado en hardhat.config.js. Después de ejecutar el script, los contratos deberían implementarse y debería ver lo siguiente en su terminal:

Si ve un resultado similar a este, sus contratos inteligentes se implementaron y configuraron correctamente. Ahora, procedamos a crear nuestra aplicación Next.js.

Creación de una aplicación DeFi Next.js

En el mismo directorio, ejecute el siguiente comando en la terminal para crear su aplicación Next.js:

npx create-next-app frontend

El comando anterior creará una nueva aplicación e instalará automáticamente las dependencias necesarias.

Navegue a la frontendcarpeta y use el siguiente comando en la terminal para instalar dependencias adicionales, que nos ayudarán a interactuar con nuestros contratos inteligentes:

yarn add @thirdweb-dev/react @thirdweb-dev/sdk ethers web3

Estamos instalando @thirdweb-dev/reacty @thirdweb-dev/sdkpara que podamos autenticar fácilmente al usuario y conectar sus billeteras a nuestra aplicación usando MetaMask . etherses una dependencia necesaria para ThirdWeb, por lo que también debemos instalarla. Finalmente, estamos instalando web3para que podamos interactuar con nuestro contrato inteligente.

Agregar el tercer proveedor web

Para comenzar, debemos envolver nuestra aplicación dentro de un thirdwebProviderpara que Thirdweb pueda funcionar correctamente.

Vaya a su _app.jsarchivo en la pagescarpeta y agregue lo siguiente:

import { thirdwebProvider, ChainId } from "@thirdweb-dev/react";
import "../styles/globals.css";
function MyApp({ Component, pageProps }) {
  return (
    <thirdwebProvider desiredChainId={ChainId.Mumbai}>
      <Component {...pageProps} />
    </thirdwebProvider>
  );
}
export default MyApp;

En el código anterior, estamos importando thirdwebProvidery adjuntando nuestra aplicación dentro de él. También proporcionamos una desiredChainIdidentificación de cadena de Polygon Mumbai. También puede usar la identificación de la cadena para Polygon Mainnet si lo desea.

Cree un nuevo archivo en la raíz de su aplicación Next.js llamado contracts.jsy agregue el siguiente contenido:

export const oktoken = {
  contractAddress: "0xE83DD81890C76BB8c4b8Bc6365Ad95E5e71495E5",
  abi: [
    {
      inputs: [],
      stateMutability: "nonpayable",
      type: "constructor",
    },
    {
      anonymous: false,
      inputs: [
        {
          indexed: true,
          internalType: "address",
          name: "owner",
          type: "address",
        },
        {
          indexed: true,
          internalType: "address",
          name: "spender",
          type: "address",
        },
        {
          indexed: false,
          internalType: "uint256",
          name: "value",
          type: "uint256",
        },
      ],
      name: "Approval",
      type: "event",
    },
    {
      anonymous: false,
      inputs: [
        {
          indexed: true,
          internalType: "address",
          name: "from",
          type: "address",
        },
        {
          indexed: true,
          internalType: "address",
          name: "to",
          type: "address",
        },
        {
          indexed: false,
          internalType: "uint256",
          name: "value",
          type: "uint256",
        },
      ],
      name: "Transfer",
      type: "event",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "owner",
          type: "address",
        },
        {
          internalType: "address",
          name: "spender",
          type: "address",
        },
      ],
      name: "allowance",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "spender",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "amount",
          type: "uint256",
        },
      ],
      name: "approve",
      outputs: [
        {
          internalType: "bool",
          name: "",
          type: "bool",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "account",
          type: "address",
        },
      ],
      name: "balanceOf",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "decimals",
      outputs: [
        {
          internalType: "uint8",
          name: "",
          type: "uint8",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "spender",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "subtractedValue",
          type: "uint256",
        },
      ],
      name: "decreaseAllowance",
      outputs: [
        {
          internalType: "bool",
          name: "",
          type: "bool",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "spender",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "addedValue",
          type: "uint256",
        },
      ],
      name: "increaseAllowance",
      outputs: [
        {
          internalType: "bool",
          name: "",
          type: "bool",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [],
      name: "name",
      outputs: [
        {
          internalType: "string",
          name: "",
          type: "string",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "symbol",
      outputs: [
        {
          internalType: "string",
          name: "",
          type: "string",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "totalSupply",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "to",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "amount",
          type: "uint256",
        },
      ],
      name: "transfer",
      outputs: [
        {
          internalType: "bool",
          name: "",
          type: "bool",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "from",
          type: "address",
        },
        {
          internalType: "address",
          name: "to",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "amount",
          type: "uint256",
        },
      ],
      name: "transferFrom",
      outputs: [
        {
          internalType: "bool",
          name: "",
          type: "bool",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
  ],
};
export const okvendor = {
  contractAddress: "0xAa3b8cbB24aF3EF68a0B1760704C969E57c53D7A",
  abi: [
    {
      inputs: [
        {
          internalType: "address",
          name: "tokenAddress",
          type: "address",
        },
      ],
      stateMutability: "nonpayable",
      type: "constructor",
    },
    {
      anonymous: false,
      inputs: [
        {
          indexed: false,
          internalType: "address",
          name: "buyer",
          type: "address",
        },
        {
          indexed: false,
          internalType: "uint256",
          name: "amountOfNativeCurrency",
          type: "uint256",
        },
        {
          indexed: false,
          internalType: "uint256",
          name: "amountOfTokens",
          type: "uint256",
        },
      ],
      name: "BuyTokens",
      type: "event",
    },
    {
      anonymous: false,
      inputs: [
        {
          indexed: true,
          internalType: "address",
          name: "previousOwner",
          type: "address",
        },
        {
          indexed: true,
          internalType: "address",
          name: "newOwner",
          type: "address",
        },
      ],
      name: "OwnershipTransferred",
      type: "event",
    },
    {
      inputs: [],
      name: "buyTokens",
      outputs: [
        {
          internalType: "uint256",
          name: "tokenAmount",
          type: "uint256",
        },
      ],
      stateMutability: "payable",
      type: "function",
    },
    {
      inputs: [],
      name: "getNumberOfTokensInNativeCurrency",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "owner",
      outputs: [
        {
          internalType: "address",
          name: "",
          type: "address",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "renounceOwnership",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "uint256",
          name: "tokenAmountToSell",
          type: "uint256",
        },
      ],
      name: "sellTokens",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [],
      name: "tokensPerNativeCurrency",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "newOwner",
          type: "address",
        },
      ],
      name: "transferOwnership",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [],
      name: "withdraw",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
  ],
};

Recuerde reemplazar las direcciones del contrato con las suyas para que la aplicación Next.js intente conectarse al contrato inteligente correcto.

Ahora comencemos a codificar nuestra aplicación. Abra index.jsel archivo en la pagescarpeta y agregue lo siguiente:

import { useAddress, useContract, useMetamask } from "@thirdweb-dev/react";
import Head from "next/head";
import Image from "next/image";
import { oktoken, okvendor } from "../contracts";
import styles from "../styles/Home.module.css";
import { useEffect, useState } from "react";
import Web3 from "web3";
const web3 = new Web3(Web3.givenProvider);
export default function Home() {
  const [tokensPerCurrency, setTokensPerCurrency] = useState(0);
  const [tokens, setTokens] = useState(0);
  const address = useAddress();
  const connectUsingMetamask = useMetamask();
  const account = web3.defaultAccount;
  const purchase = async () => {
    const contract = new web3.eth.Contract(
      okvendor.abi,
      okvendor.contractAddress
    );
    const ethToSend = tokens / tokensPerCurrency;
    const purchase = await contract.methods.buyTokens().send({
      from: address,
      value: web3.utils.toWei(ethToSend.toString(), "ether"),
    });
    console.log(purchase);
    await fetchPrice();
  };
  const sell = async () => {
    const vendorContract = new web3.eth.Contract(
      okvendor.abi,
      okvendor.contractAddress
    );
    const tokenContract = new web3.eth.Contract(
      oktoken.abi,
      oktoken.contractAddress
    );
    const approve = await tokenContract.methods
      .approve(
        okvendor.contractAddress,
        web3.utils.toWei(tokens.toString(), "ether")
      )
      .send({
        from: address,
      });
    const sellTokens = await vendorContract.methods.sellTokens(tokens).send({
      from: address,
    });
    await fetchPrice();
  };
  const fetchPrice = async () => {
    const contract = new web3.eth.Contract(
      okvendor.abi,
      okvendor.contractAddress
    );
    const priceFromContract = await contract.methods
      .getNumberOfTokensInNativeCurrency()
      .call();
    setTokensPerCurrency(priceFromContract);
  };
  useEffect(() => {
    fetchPrice();
  }, []);
  return (
    <div>
      <Head>
        <title>Exchange OKTokens</title>
      </Head>
      {address ? (
        <div>
          <p>Tokens per currency: {tokensPerCurrency}</p>
          <div>
            <input
              type="number"
              value={tokens}
              onChange={(e) => setTokens(e.target.value)}
            />
          </div>
          <button onClick={purchase}>Purchase</button>
          <button onClick={sell}>Sell</button>
        </div>
      ) : (
        <div>
          <button onClick={connectUsingMetamask}>Connect using MetaMask</button>
        </div>
      )}
    </div>
  );
}

Este es un bloque de código largo, así que veamos qué está haciendo el código paso a paso:

  • Inicializar el web3paquete usando un proveedor configurado por thirdweb
  • Usar enlaces de terceros useMetamask()para autenticarse y useAddress()verificar el estado de autenticación, luego mostrar el botón de inicio de sesión si el usuario no tiene una billetera conectada usando MetaMask
  • Configuración de varios estados para mapear cuadros de texto en nuestra aplicación
  • Crear una fetchPrice()función para interactuar con nuestro contrato inteligente y verificar cuántos tokens puede obtener un MATIC, al mismo tiempo que crea un useEffectpara verificar este precio cada vez que se carga la página
  • Creando una purchase()función, que inicializa nuestro contrato de proveedor y llama a la buyTokens()función desde el contrato, luego envía algo de MATIC junto con esta transacción. Luego, llamamos fetchPrice()para que se muestre el último precio .

Finalmente, estamos creando una sell()función que inicializa tanto el token como el contrato de proveedor. Primero, interactuamos con la approve()función del contrato de token y permitimos que el contrato del proveedor transfiera fondos en nuestro nombre. Luego estamos llamando sellTokens()a la función del contrato del proveedor para finalmente vender los tokens y recibir MATIC. También estamos llamando fetchPrice()para obtener el último precio después de la transacción.

¡Nuestra sencilla aplicación DeFi está completa! Puede ver esta aplicación en su navegador ejecutando el siguiente comando:

yarn dev

Ahora, una vez que visite http://localhost:3000 , debería ver la siguiente pantalla y debería poder realizar transacciones.

Conclusión

Este fue un tutorial simple sobre cómo crear su propia aplicación DeFi de pila completa basada en Polygon. Puede implementar su propia lógica en los contratos inteligentes para hacerlo aún mejor según su organización. Sugiero jugar con el código para que puedas aprender de la mejor manera posible.

Esta historia se publicó originalmente en https://blog.logrocket.com/creating-full-stack-defi-app-polygon/

#defi #polygon #nextjs 

Mikel  Okuneva

Mikel Okuneva

1600549200

Oracles in DeFi Systems: Off-Chain Aggregation vs Centralized Solutions

DeFi projects are changing the way we’re interacting with digital funds. We’re taking real money and transforming them into digital assets that can be used in blockchain-powered applications. Anyway, as much as we want to think that the cryptocurrency world is one that is separated from the actual real-world, it is not. Otherwise, why are you checking the USD price of your tokens?

We are changing the way we are interacting with each other financially, but we are not changing the way we are interacting with the world. Real-world events are influencing our lives and our digital funds. However, blockchain seems to have its own peace. Yes, the price of a token is going up or down. But one ETH will always be one ETH on its blockchain. A block on the blockchain doesn’t know the time. It’s just a block with a number. But blockchain blocks are generated faster or slower based on the external world miners activity.

#defi #cryptocurrency #crypto #oracles-in-defi #off-chain-aggregating-defi #community-curated-oracle-defi #blockchain-oracles #bridge-defi-provable-defi

Avail Defi wallet development services to ensure efficient fund management

DeFi wallet development services are used for storing the crypto coins and tokens of the users safely. There is no third party involved in the platform. The users need not disclose their personal identity or submit any personal information to register themselves on the wallet. It is non-custodial, easily compatible, utilizes fully encrypted private keys, easy to access, and is completely decentralized. Top-notch security measures are taken to safeguard the users’ funds and data. The different types of DeFi wallets are single-currency, multi-currency, business wallets, web, mobile, hardware, and desktop wallets.

**The typical features of a DeFi wallet are **

Safety measures such as two-factor authentication, biometric authentication, DDoS mitigation, anti-phishing software, SSL implementation, HSM implementation, browser detection security, and multi-signature wallets.
An inbuilt QR code scanner for quick execution of payments.
Whitelisting and blacklisting of wallet addresses.
Merchant integration services.
Seamless integration with numerous payment gateways.
Can be used for the transfer of funds, peer-to-peer payments, preparing invoices, and bill payments.
Is compatible across web, mobile, and desktop.
Protection from inflation, economic downturn, and a market crash,
Auto-denial of duplicate payments helps to prevent chargeback fraud.

Make full use of professional DeFi wallet development services and improve your financial position in no time.

#defi wallet development services, #defi wallet development company, #defi wallet developers, #defi wallet development, #defi wallet development solution, #build your defi wallet,

Best DeFi Projects 2021 | Top DeFi DEX Projects

DeFi DEX Clone Script

BlockchainAppsDeveloper is the leading DeFi DEX Clone Script Development Company, which provides DeFi based Decentralized Exchange Development Services that include exchange, Staking, Yield Farming, Lending & Borrowing development, and more.

FREE DeFi DEX Clone Script Demo

Top 7 DeFi Decentralized Exchanges 2021

In a rapidly developing DeFi market, it’s important to ensure crypto users are trading on a Decentralized based trusted cryptocurrency exchange. Below you can get Top 7 DEX Exchange details.

Pancakeswap Exchange

PancakeSwap Exchange is operated by a single entity. The single entity is corporate and uses decentralized exchanges for cryptocurrency trading. The DEX platform has highly competition with Ethereum decentralized exchanges and works on Binance smart chain blockchain network. Pancakeswap Exchange uses a CAKE token. Ethereum Blockchain may have kickstarted the DeFi trend, but initiatives like PancakeSwap Exchange like platform suggest that the wave of innovation is destined to spread to other blockchain networks.

Thinking to start your own DeFi based DEX exchange on Binance Smart Chain? Read our highly secured and customized Pancakeswap Clone Script features and functionalities.

Get FREE Pancakeswap Clone Script Demo!

Uniswap DEX

Uniswap provides a simple single-click interface to swap any 2 Ethereum assets against an underlying crypto liquidity pool.

Get FREE Uniswap Clone Script Demo!

SushiSwap Exchange

Sushiswap is a decentralized exchange (DEX) where you can swap various tokens/?cryptocurrencies. This is an AMM decentralized exchange running on the Ethereum Blockchain Network. On the main design of the Uniswap Exchange, makers of Sushiswap added community-based trading features to offer further benefits to the crypto traders and investors.

Here you can get a FREE SushiSwap Exchange Clone Script Demo!

KyberSwap Exchange

Kyber Network is a topmost leading liquidity protocol that incentivizes Reserve Managers to significantly contribute to an aggregated pool of liquidity for a pro-rata share of 0.3% crypto trading fees.

Here you can get a FREE KyberSwap Exchange Clone Script Demo!

1inch Exchange

As a Decentralized Exchange (DEX) aggregator, 1inch exchange pulls liquidity from a number of various DEXs to provide limited slippage on large orders. 1inch Exchange permits capital to be pulled in a benefits fashion for the cryptocurrency trader, ultimately providing them the best price for their order.

Here you can get a FREE 1inch Exchange Clone Script Demo!

BakerySwap Exchange

BakerySwap is the 1st-ever made cryptocurrency trading platform on Binance smart chain (BSC). It is also a decentralized protocol and unique token to do the DEXs, which are highly termed as Bake. This was built after the uniswap exchange, which aimed to develop the cryptocurrency trade faster & cheaper.
Here you can get a FREE BakerySwap Exchange Clone Script Demo!

Yearn.Finance Exchange

Yearn Finance is a suite of items in Decentralized Finance that highly offers yield generation, lending aggregation, and insurance on the Ethereum network. The DeFi protocol is maintained by different kind of independent developers and is governed by YFI containers.

Here you can get a FREE Yearn.Finance Exchange Clone Script Demo!

DeFi DEX Development Company - BlockchainAppsDeveloper

BlockchainAppsDeveloper is the leading DeFi Development Company that provides DeFi based Decentralized Exchange (DEX) Development Services that include Exchange, Staking, Yield Farming, Lending & Borrowing development, and more.

Get Instant Quote For DeFi Services

#best defi projects 2021 #top defi dex projects #defi projects 2021 #defi dex development #defi dex

joe biden

1617257581

Software de restauración de Exchange para restaurar sin problemas PST en Exchange Server

¿Quiere restaurar los buzones de correo de PST a Exchange Server? Entonces, estás en la página correcta. Aquí, lo guiaremos sobre cómo puede restaurar fácilmente mensajes y otros elementos de PST a MS Exchange Server.

Muchas veces, los usuarios necesitan restaurar los elementos de datos de PST en Exchange Server, pero debido a la falta de disponibilidad de una solución confiable, los usuarios no pueden obtener la solución. Háganos saber primero sobre el archivo PST y MS Exchange Server.

Conozca PST y Exchange Server

PST es un formato de archivo utilizado por MS Outlook, un cliente de correo electrónico de Windows y muy popular entre los usuarios domésticos y comerciales.

Por otro lado, Exchange Server es un poderoso servidor de correo electrónico donde todos los datos se almacenan en un archivo EDB. Los usuarios generalmente guardan la copia de seguridad de los buzones de correo de Exchange en el archivo PST, pero muchas veces, los usuarios deben restaurar los datos del archivo PST en Exchange. Para resolver este problema, estamos aquí con una solución profesional que discutiremos en la siguiente sección de esta publicación.

Un método profesional para restaurar PST a Exchange Server

No le recomendamos que elija una solución al azar para restaurar los datos de PST en Exchange Server. Por lo tanto, al realizar varias investigaciones, estamos aquí con una solución inteligente y conveniente, es decir, Exchange Restore Software. Es demasiado fácil de manejar por todos los usuarios y restaurar cómodamente todos los datos del archivo PST a Exchange Server.

Funciones principales ofrecidas por Exchange Restore Software

El software es demasiado simple de usar y se puede instalar fácilmente en todas las versiones de Windows. Con unos pocos clics, la herramienta puede restaurar los elementos del buzón de Exchange.

No es necesario que MS Outlook restaure los datos PST en Exchange. Todos los correos electrónicos, contactos, notas, calendarios, etc. se restauran desde el archivo PST a Exchange Server.

Todas las versiones de Outlook son compatibles con la herramienta, como Outlook 2019, 2016, 2013, 2010, 2007, etc. La herramienta proporciona varios filtros mediante los cuales se pueden restaurar los datos deseados desde un archivo PST a Exchange Server. El programa se puede instalar en todas las versiones de Windows como Windows 10, 8.1, 8, 7, XP, Vista, etc.

Descargue la versión de demostración del software de restauración de Exchange y analice el funcionamiento del software restaurando los primeros 50 elementos por carpeta.

Líneas finales

No existe una solución manual para restaurar los buzones de correo de Exchange desde el archivo PST. Por lo tanto, hemos explicado una solución fácil e inteligente para restaurar datos de archivos PST en Exchange Server. Simplemente puede usar este software y restaurar todos los datos de PST a Exchange Server.

Más información:- https://www.datavare.com/software/exchange-restore.html

#intercambio de software de restauración #intercambio de restauración #buzón del servidor de intercambio #herramienta de restauración de intercambio