Escribiendo tu primera aplicación

Esta guía lo llevará a través de los Bitxor ciclo de desarrollo.

Primero, diseñaremos nuestra solución combinando algunas funciones integradas disponibles en Bitxor, como tokens y accounts. Al final de esta guía, sabrá cómo emitir y monitorear transacciones en la cadena de bloques.

caso de uso

El mercado de boletos secundario, también conocido como mercado de reventa, es el intercambio de boletos que ocurre entre individuos después de haber comprado un boleto de un vendedor inicial. El proveedor inicial podría ser el sitio web del evento, una plataforma de venta de boletos en línea, una tienda o un puesto en la entrada del evento.

Comprar un boleto de alguien que no es el vendedor inicial no significa necesariamente pagar más por el boleto. Existe la posibilidad de ser víctima de comprar un boleto falso o duplicado, donde el proveedor original inicial no puede hacer nada para resolver el problema.

¿Qué queremos resolver?

../_images/bitxor-getting-started.png

Modelo de autorización

Un vendedor de boletos quiere configurar un sistema para:

  1. Identificar cada ticket y cliente.

  2. Evite la reventa de boletos.

  3. Evite tickets no auténticos y duplicados.

¿Por qué Bitxor es la elección correcta?

La tecnología Blockchain tiene sentido en los casos en que:

  • Hay diferentes participantes involucrados.

  • Estos participantes necesitan confiar unos en otros.

  • Es necesario realizar un seguimiento de un conjunto inmutable de eventos.

Bitxor es una flexible blockchain tecnología. En lugar de cargar toda la lógica de la aplicación en la cadena de bloques, puede usar sus funciones probadas a través de API calls para transferir y almacenar valor, autorización, trazabilidad e identificación.

El resto del código permanecerá off-chain. Esto reduce el riesgo de inmutabilidad inherente, ya que podría cambiar el proceso cuando sea necesario.

Creación de una cuenta para cada participante

Primero, identifiquemos los actores involucrados en el caso de uso que queremos resolver:

  • El vendedor de boletos.

  • El cliente.

Hemos decidido representar al proveedor de boletos y al cliente como cuentas por separado. Piense en las cuentas como cajas de depósito en la cadena de bloques, que se pueden modificar con una clave privada adecuada. Cada cuenta es única e identificada por una dirección.

Has cargado una cuenta con test bitxor? En la previous guide, has aprendido a crear una cuenta con Bitxor CLI. esta cuenta representará la ticket vendor cuenta.

  1. Ejecute el siguiente comando para verificar si la cuenta del proveedor del boleto tiene bitxor unidades.

    bitxor-cli account info --profile testnet
    

    Debería ver en su pantalla una línea similar a:

    Account Information
    ┌───────────────────┬────────────────────────────────────────────────┐
    │ PropertyValue                                          │
    ├───────────────────┼────────────────────────────────────────────────┤
    │ Address           │ BXRYXK-VYBMO4-NBCUF3-AXKJMX-CGVSYQ-OS7ZG2-TLI  │
    ├───────────────────┼────────────────────────────────────────────────┤
    │ Address Height    │ 1                                              │
    ├───────────────────┼────────────────────────────────────────────────┤
    │ Public Key        │ 203...C0A                                      │
    ├───────────────────┼────────────────────────────────────────────────┤
    │ Public Key Height │ 3442                                           │
    ├───────────────────┼────────────────────────────────────────────────┤
    │ Importance        │ 0                                              │
    ├───────────────────┼────────────────────────────────────────────────┤
    │ Importance Height │ 0                                              │
    └───────────────────┴────────────────────────────────────────────────┘
    
    Información de saldo
    ┌──────────────────┬─────────────────┬─────────────────┬───────────────────┐
    │ Token Id        │ Relative Amount │ Absolute Amount │ Expiration Height │
    ├──────────────────┼─────────────────┼─────────────────┼───────────────────┤
    │ 5E62990DCAC5BE8A │ 750.0           │ 750000000       │ Never             │
    └──────────────────┴─────────────────┴─────────────────┴───────────────────┘
    

    Esta cuenta posee 750 bitxor unidades relativas. Si su fila después de “Información de saldo” está vacía, siga las previous guide para obtener moneda de prueba.

  2. Cree una segunda cuenta con la CLI para identificar el customer.

    bitxor-cli account generate --network TEST_NET --save \
               --url <NODE_URL> --profile customer
    
    New Account
    
    ┌─────────────┬────────────────────────────────────────────────┐
    │ PropertyValue                                          │
    ├─────────────┼────────────────────────────────────────────────┤
    │ Address     │ BXRBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I  │
    ├─────────────┼────────────────────────────────────────────────┤
    │ Public Key  │ E59...82F                                      │
    ├─────────────┼────────────────────────────────────────────────┤
    │ Private Key │ 111...111                                      │
    └─────────────┴────────────────────────────────────────────────┘
    

Monitoreo de la cadena de bloques

Las cuentas cambian el estado de la cadena de bloques a través de transacciones. Una vez que una cuenta anuncia una transacción, el servidor devolverá una respuesta OK si se formó correctamente.

Sin embargo, recibir una respuesta OK no significa que la transacción sea válida o esté incluida en un bloque. Por ejemplo, la transacción podría ser rechazada porque el emisor no tiene suficiente bitxor, el conjunto de mensajes es demasiado grande o la tarifa establecida es demasiado baja.

Una buena práctica es monitor transactions antes de ser anunciados para saber cuándo son confirmados o rechazados por la red.

  1. En una nueva terminal, monitoree las transacciones que involucran la cuenta del proveedor de boletos para saber si son confirmadas o rechazadas por la red.

    bitxor-cli monitor all --address BXRYXK-VYBMO4-NBCUF3-AXKJMX-CGVSYQ-OS7ZG2-TLI
    

Creando el boleto

Estamos representando el ticket con Bitxor tokens. Esta característica se puede usar para representar cualquier activo en la cadena de bloques, como objetos, boletos, cupones, representación de acciones e incluso su criptomoneda.

Los tokens tienen propiedades configurables, que se definen en el momento de su creación. Por ejemplo, optamos por establecer propiedad transferible a falso. Esto significa que el cliente solo puede devolver el boleto al creador del token, evitando la reventa del boleto.

  1. Use la CLI con la cuenta del proveedor del boleto para crear un nuevo token que represente el boleto. Este nuevo token se puede configurar de la siguiente manera:

    Property

    Value

    Description

    Divisibilidad

    0

    Las unidades simbólicas no deben ser divisibles. Nadie debería poder enviar “0.5 boletos”.

    Duración

    1000

    El token se registrará para 1000 bloques.

    Cantidad

    99

    El número de tickets que vas a crear.

    Suministro mutable

    Verdadero

    El suministro de fichas puede cambiar en un momento posterior.

    Transferible

    FALSO

    El token solo se puede transferir de nuevo al creador del token.

    bitxor-cli transaction token --amount 99 --supply-mutable \
               --divisibility 0 --duration 1000 --max-fee 2000000 \
               --sync --profile testnet
    
  2. Después de anunciar la transacción, copie la identificación del token que se muestra en la terminal.

    The new token id is: 7cdf3b117a3c40cc
    

    La transacción debería aparecer como confirmada después de 30 segundos como máximo. Si el terminal genera un error, puede verificar la descripción del código de error here.

Envío del ticket

Ahora que hemos definido el token, enviaremos una unidad de ticket a un cliente anunciando un TransferTransaction.

  1. Abra un nuevo archivo y defina un TransferTransaction con los siguientes valores.

    Property

    Value

    Description

    Deadline

    Predeterminado (2 horas)

    La cantidad máxima de tiempo de espera para que la transacción se incluya en la cadena de bloques. Una transacción se cancelará si permanece sin confirmar después de este período de tiempo. El parámetro se define en horas y debe estar en el rango de 1 a 6 (1 a 48 for Agregado Enlazado transacciones).

    Recipient

    BXRBDE…32I

    La dirección de la cuenta del destinatario. En este caso, la dirección del cliente.

    Tokens

    [1 7cdf3b117a3c40cc]

    La matriz de tokens para enviar.

    Mensaje

    disfruta de tu entrada

    El mensaje adjunto.

    Network

    TEST_NET

    El tipo de red.

    // replace with token id
    const tokenIdHex = '7cdf3b117a3c40cc';
    const tokenId = new TokenId(tokenIdHex);
    // replace with customer address
    const rawAddress = 'BXRBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I';
    const recipientAddress = Address.createFromRawAddress(rawAddress);
    // replace with network type
    const networkType = NetworkType.TEST_NET;
    
    const transferTransaction = TransferTransaction.create(
      Deadline.create(epochAdjustment),
      recipientAddress,
      [new Token(tokenId, UInt64.fromUint(1))],
      PlainMessage.create('enjoy your ticket'),
      networkType,
      UInt64.fromUint(2000000),
    );
    
    // replace with token id
    const tokenIdHex = '7cdf3b117a3c40cc';
    const tokenId = new bitxor_sdk_1.TokenId(tokenIdHex);
    // replace with customer address
    const rawAddress = 'BXRBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I';
    const recipientAddress = bitxor_sdk_1.Address.createFromRawAddress(rawAddress);
    // replace with network type
    const networkType = bitxor_sdk_1.NetworkType.TEST_NET;
    const transferTransaction = bitxor_sdk_1.TransferTransaction.create(
        bitxor_sdk_1.Deadline.create(epochAdjustment),
        recipientAddress, [new bitxor_sdk_1.Token(tokenId, bitxor_sdk_1.UInt64.fromUint(1))],
        bitxor_sdk_1.PlainMessage.create('enjoy your ticket'),
        networkType,
        bitxor_sdk_1.UInt64.fromUint(2000000),
    );
    
            // replace with node endpoint
            try (final RepositoryFactory repositoryFactory = new RepositoryFactoryVertxImpl(
                    "NODE_URL")) {
                // replace with token id
                final String tokenIdHex = "7cdf3b117a3c40cc";
                final TokenId tokenId = new TokenId(tokenIdHex);
    
                // replace with customer address
                final String rawAddress = "BXRBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I";
                final UnresolvedAddress recipientAddress = Address.createFromRawAddress(rawAddress);
                final NetworkType networkType = repositoryFactory.getNetworkType().toFuture().get();
    
                final Token token = new Token(tokenId, BigInteger.valueOf(1));
                final TransferTransaction transferTransaction = TransferTransactionFactory
                        .create(
                                networkType,
                                recipientAddress,
                                Collections.singletonList(token),
                                PlainMessage.create("Enjoy your ticket"))
                        .maxFee(BigInteger.valueOf(2000000)).build();
    

    Si bien la transacción está definida, aún no ha sido anunciada a la red.

  2. Firme la transacción con el ticket vendor account, para que la red pueda verificar la autenticidad de la transacción.

    Note

    Incluya el hash de generación de red para que la transacción solo sea válida para su red. Abrir NODE_URL /node/info en una nueva pestaña del navegador y copie el meta.networkGenerationHash value.

    // replace with ticket vendor private key
    const privateKey =
      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
    const account = Account.createFromPrivateKey(privateKey, networkType);
    // replace with meta.networkGenerationHash (nodeUrl + '/node/info')
    const networkGenerationHash =
      '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
    const signedTransaction = account.sign(
      transferTransaction,
      networkGenerationHash,
    );
    
    // replace with ticket vendor private key
    const privateKey =
        'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
    const account = bitxor_sdk_1.Account.createFromPrivateKey(
        privateKey,
        networkType,
    );
    // replace with meta.networkGenerationHash (nodeUrl + '/node/info')
    const networkGenerationHash =
        '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
    const signedTransaction = account.sign(
        transferTransaction,
        networkGenerationHash,
    );
    
                // replace with ticket vendor private key
                final String privateKey = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
                // replace with network generation hash
                final String generationHash = repositoryFactory.getGenerationHash().toFuture().get();
    
                final Account account = Account
                        .createFromPrivateKey(privateKey, networkType);
                final SignedTransaction signedTransaction = account
                        .sign(transferTransaction, generationHash);
    
  3. Una vez firmado, anuncia la transacción a la red.

    // replace with node endpoint
    const nodeUrl = 'NODE_URL';
    const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
    
    const transactionHttp = repositoryFactory.createTransactionRepository();
    
    transactionHttp.announce(signedTransaction).subscribe(
      (x) => console.log(x),
      (err) => console.error(err),
    );
    
    // replace with node endpoint
    const nodeUrl = 'NODE_URL';
    const repositoryFactory = new bitxor_sdk_1.RepositoryFactoryHttp(nodeUrl);
    const transactionHttp = repositoryFactory.createTransactionRepository();
    transactionHttp.announce(signedTransaction).subscribe(
        (x) => console.log(x),
        (err) => console.error(err),
    );
    
                final TransactionRepository transactionRepository = repositoryFactory
                        .createTransactionRepository();
                transactionRepository.announce(signedTransaction).toFuture().get();
            }
    
    bitxor-cli transaction transfer --recipient-address BXRBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I --tokens 7cdf3b117a3c40cc::1 --message enjoy_your_ticket --max-fee 2000000 --sync
    
  4. Mire la ventana de la terminal donde está monitoreando las transacciones. Cuando la transacción aparece como confirmada, puedes comprobar si el cliente ha recibido el ticket con el siguiente comando.

    bitxor-cli account info --profile customer
    

¿Resolvimos el caso de uso?

  • ✅ Identificar a cada cliente: Crear Bitxor cuentas de cada cliente.

  • ✅ Evite la reventa de boletos: Creando un token intransferible.

  • ✅ Evite los boletos no auténticos y los duplicados: Creando un token único.

Continuar aprendiendo sobre más sobre Bitxor características integradas.