O curso de desenvolvedor Bitcoin - Crie sua própria carteira Bitcoin! | Humberto Cezar | Skillshare

Velocidade de reprodução


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

O curso de desenvolvedor Bitcoin - Crie sua própria carteira Bitcoin!

teacher avatar Humberto Cezar, Software Developer & Bitcoin Pleb

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Aulas neste curso

    • 1.

      Apresentação

      7:10

    • 2.

      Baixar, configurar e executar o nó Core Bitcoin e o IDE IntelliJ

      6:33

    • 3.

      O que é o Bitcoin?

      3:03

    • 4.

      Transações Bitcoin e chaves privadas

      6:32

    • 5.

      Carteiras Bitcoin, o Blockchain e mineração

      3:51

    • 6.

      A rede Bitcoin, o ecossistema e os princípios

      5:49

    • 7.

      Iniciar o projeto

      2:59

    • 8.

      Configurando o GUI

      9:55

    • 9.

      Criar nosso primeiro teste

      10:18

    • 10.

      Sementes mnemônicas

      2:11

    • 11.

      Criar janela de diálogo com carteira

      11:56

    • 12.

      Criar a semente mnemônica

      7:33

    • 13.

      Crie botões e validações da janela da janela de diálogo com carteira

      10:30

    • 14.

      A Carteira atual Observável

      11:16

    • 15.

      A guia Receber Bitcoin

      8:29

    • 16.

      Endereços Bitcoin e carteiras HD

      13:52

    • 17.

      Criar as chaves públicas estadas da nossa carteira

      16:40

    • 18.

      Gerando endereços do Segwit

      10:19

    • 19.

      Entendendo os endereços do Segwit e introdução aos ambientes de rede Bitcoin

      4:34

    • 20.

      Gerando endereços do Segwit - Parte II

      9:10

    • 21.

      Adicionando suporte para ambientes de teste de rede principal, rede de teste e Reg

      7:41

    • 22.

      Preparar nosso nó Core Bitcoin para se comunicar com nossa carteira

      3:13

    • 23.

      Criar o cliente nó para criar e listar carteiras

      15:06

    • 24.

      Node para carregar uma carteira, obtenha um novo endereço, verificando nossos Bitcoins saldo e mineração

      11:21

    • 25.

      Enviar Bitcoins do nó para o aplicativo

      14:25

    • 26.

      A tabela Endereços

      8:42

    • 27.

      Importando nossos endereços de aplicativo para o nosso nó Bitcoin

      10:18

    • 28.

      Chamando nosso nó Bitcoin com sincronismo

      9:50

    • 29.

      Ouvindo transações do nó com o ZeroMQ

      14:09

    • 30.

      Transações Bitcoin: Entradas, Entradas, Saídas, scripts e o conjunto UTXO

      18:31

    • 31.

      Obtenção de UTXOs do nó e Filtering

      11:46

    • 32.

      Atualizar os endereços atuais da carteira

      11:07

    • 33.

      Mostrando informações de endereço na tabela de endereços

      13:21

    • 34.

      Mais cenários de teste para receber Bitcoins e evitar reutilização de endereços

      14:09

    • 35.

      Melhorando como receber testes Bitcoin Receber mais transações do que endereços.

      10:33

    • 36.

      Gerando mais endereços

      15:50

    • 37.

      Testando confirmações

      7:33

    • 38.

      A tabela de transações

      8:03

    • 39.

      Populando a tabela de transações

      14:03

    • 40.

      Melhorando os testes para a tabela transações e executando nosso aplicativo na rede de teste

      17:10

    • 41.

      Ouvindo blocos e formatando balanceamentos

      12:55

    • 42.

      Equilíbrio da carteira total

      5:50

    • 43.

      Calculando e mostrando o saldo total da carteira

      8:57

    • 44.

      Adicionando mais testes para o recurso saldo total

      3:37

    • 45.

      A guia Enviar Bitcoin

      11:11

    • 46.

      Taxas e tamanhos de transação

      6:48

    • 47.

      Criar a Calculadora tamanho da transação e o cliente de taxa inteligente de estimativa do nó

      13:33

    • 48.

      Seleção de moedas e poeira

      6:08

    • 49.

      Implementando a Calculadora de poeira e outros utilitários

      9:24

    • 50.

      Implementando o seletor de moeda único sorteio aleatório

      8:40

    • 51.

      Como as transações do Segwit são construídas e Validadas

      7:44

    • 52.

      Implementando o Criador de transações

      14:03

    • 53.

      A janela de diálogo Enviar transação

      14:21

    • 54.

      Mostrando dados de transação na janela de diálogo Enviar Bitcoin

      15:43

    • 55.

      Como as assinaturas de transação funcionam

      5:25

    • 56.

      Como nossa carteira e nosso nó lidarão com transações enviadas

      3:25

    • 57.

      Assinar e enviar transações do Segwit

      16:49

    • 58.

      Fixar transações e endereçar tabelas e balanceamentos

      18:13

    • 59.

      Alterar endereços de mudança. Adicionando alertas de erro para senhas erradas

      20:53

    • 60.

      Mais mensagens de erro e testes para o recurso Enviar Bitcoin

      14:55

    • 61.

      Um Refactor necessário

      17:39

    • 62.

      Um Refactor necessário Parte II

      26:45

    • 63.

      Endereços segwit aninhados

      7:50

    • 64.

      Receber Bitcoin em endereços do Segwit aninhados

      17:01

    • 65.

      Enviar Bitcoin para endereços do Segwit aninhados e testar nossa carteira na rede de teste

      9:54

    • 66.

      Enviar Bitcoin para endereços legados

      14:23

    • 67.

      Salvar e criptografar nossa carteira

      16:31

    • 68.

      O menu carteira de carga

      14:03

    • 69.

      Carregando uma carteira

      11:47

    • 70.

      Negação plausível, refatoração e mais testes para o recurso Carregar carteira

      19:08

    • 71.

      Fixar endereços, transações e balanceamentos

      12:13

    • 72.

      Atualizar o número de endereços gerados e otimizar testes

      11:54

    • 73.

      Importando uma carteira com a semente Mnemonic

      19:27

    • 74.

      Validar endereços

      19:24

    • 75.

      Criar uma barra de progresso

      13:27

    • 76.

      Atualizar dependências

      7:17

    • 77.

      Executar nossa carteira no ambiente principal da rede

      7:46

    • 78.

      Extra class - Bitcoin Core v26

      3:14

  • --
  • Nível iniciante
  • Nível intermediário
  • Nível avançado
  • Todos os níveis

Gerado pela comunidade

O nível é determinado pela opinião da maioria dos estudantes que avaliaram este curso. Mostramos a recomendação do professor até que sejam coletadas as respostas de pelo menos 5 estudantes.

90

Estudantes

--

Projeto

Sobre este curso

Bem-vindo ao curso desenvolvedor Bitcoin Meu nome é Humberto, e estou feliz em apresentar você o primeiro e único curso onde você vai aprender Bitcoin construindo uma carteira Bitcoin desktop !

Neste curso, você vai aprender como o Bitcoin funciona de um ponto de vista técnico Mais especificamente, você vai aprender como uma carteira Bitcoin funciona em detalhes. Além disso, você vai aprender como um nó Bitcoin funciona e como executá-lo. Vamos ver como ele interage com nossa carteira e outros nós. Vamos também aprender como a rede Bitcoin funciona e como ela consegue consenso.

Os principais conceitos do Bitcoin vamos aprender como transações, endereços, sementes, chaves, saldos, o blockchain, mineração e carteira.

Como vamos criar um aplicativo de desktop ao longo do curso, o aluno terá a oportunidade de praticar as seguintes habilidades de engenharia de software, que estão em alta demanda no setor de software:

  • O paradigma de programação orientada a objetos, no qual nossa carteira é baseada em.
  • Desenvolvimento orientado por testes (TDD). A maioria dos recursos que vamos construir vai seguir a maneira de fazer as coisas. Como o nome desta abordagem sugere, para cada recurso, vamos construir os testes primeiro, e eles vão guiar o desenvolvimento dos recursos ainda mais.
  • Melhores práticas de segurança de aplicativos Vamos nos preocupar com as melhores práticas de segurança de aplicativos e tratar o aplicativo como um sistema de missão crítica. Pessoalmente, tenho pele no jogo neste aplicativo, e eu ponho muito esforço para minimizar a chance de alguém perder fundos com este aplicativo.
  • Melhores práticas de programação. Princípios SOLID e Código limpo permeiam a cultura do nosso código. Este curso tem muitos exemplos de melhores práticas de programação.

Aprenda fazendo. Cerca de 17% deste curso é composto por teoria. O resto é composto por aulas práticas. O curso é fortemente focado em código, intercalado com algumas apresentações quando necessário. Abaixo cada vídeo, você pode encontrar links adicionais e material de estudo na página Projetos e recursos. Você vai criar uma carteira de Bitcoin no desktop, aprendendo conceitos importantes Bitcoin enquanto o faz.

É recomendável que o aluno tenha um bom conhecimento sobre Programação orientada a objetos antes de fazer este curso. Conhecimento Java ou linguagens similares é necessário. Embora este curso apresenta diferentes conceitos de engenharia de software, nos concentramos em entender o Bitcoin. Se o aluno quiser saber em detalhes alguns dos conceitos de engenharia de software abordados neste curso, eles terão que usar outras fontes no curso para entendê-las melhor.

Conheça seu professor

Teacher Profile Image

Humberto Cezar

Software Developer & Bitcoin Pleb

Professor

I have 5+ years of experience as a Professional Software Developer, working especially in the e-commerce industry.

I’ve been a bitcoin enthusiast since 2016. I’ve been heavily studying Bitcoin since then. I’ve developed the open-source bitcoin-java library.

I’ve built the Bitcoin Education initiative to concentrate on providing Bitcoin education for developers worldwide.

Visualizar o perfil completo

Habilidades relacionadas

Desenvolvimento Desenvolvimento web
Level: Intermediate

Nota do curso

As expectativas foram atingidas?
    Superou!
  • 0%
  • Sim
  • 0%
  • Um pouco
  • 0%
  • Não
  • 0%

Por que fazer parte da Skillshare?

Faça cursos premiados Skillshare Original

Cada curso possui aulas curtas e projetos práticos

Sua assinatura apoia os professores da Skillshare

Aprenda em qualquer lugar

Faça cursos em qualquer lugar com o aplicativo da Skillshare. Assista no avião, no metrô ou em qualquer lugar que funcione melhor para você, por streaming ou download.

Transcrições

1. Apresentação: Olá, bem-vindo ao curso para desenvolvedores de Bitcoin. Meu nome é Alberto e tenho o prazer de apresentar a você o primeiro e único curso em que você aprenderá Bitcoin criando uma carteira Bitcoin para desktop. Então, vamos começar explicando o que você aprenderá neste curso. Resumindo, você aprenderá como Bitcoin funciona do ponto de vista técnico. Mais especificamente, você aprenderá detalhadamente como uma carteira Bitcoin funciona. Além disso, você aprenderá como um nó Bitcoin funciona e como executá-lo. Veremos como ele interage com nossa carteira e outros nós. Também aprenderá como a rede Bitcoin funciona e como ela alcança um consenso. conceitos que aprenderemos incluem transações, endereços , sementes, chaves, saldos , blockchain, mineração e carteira. Como criaremos um aplicativo de desktop ao longo do curso, o aluno terá a oportunidade de praticar as seguintes habilidades de engenharia de software , que são muito procuradas na indústria de software. O paradigma de programação orientada a objetos no qual nossa carteira se baseia. A maioria dos recursos será desenvolvida e seguirá a forma de desenvolvimento orientada por testes de fazer as coisas. Como o nome dessa abordagem sugere, pois cada recurso criará seus testes primeiro e os testes guiarão o recurso, o desenvolvimento posterior também se preocupará muito com aplicação. melhores práticas de segurança e trate o aplicativo como um sistema de missão crítica. Pessoalmente, tenho uma skin no jogo neste aplicativo e me esforcei muito para minimizar a chance de alguém perder fundos com ela. Além disso, este curso tem muitas das melhores práticas de programação, exemplos, princípios sólidos e código limpo que permeiam a cultura do nosso código. Agora, vamos ver como você aprenderá neste curso. Seguiremos a metodologia de aprender fazendo. Cerca de 17% deste curso é composto por teoria, o restante é composto por aulas práticas. Portanto, o curso é altamente focado em código, intercalado com algumas apresentações quando necessário. Abaixo de cada vídeo, você pode encontrar links adicionais e material de estudo na página Projetos e Recursos. Você construirá uma carteira Bitcoin para desktop, aprendendo conceitos importantes de Bitcoin ao mesmo tempo. Agora, vamos listar os requisitos recomendados para fazer esse curso. É recomendável que o aluno tenha um bom conhecimento de programação orientada a objetos. O aluno deve conhecer Java ou linguagens similares antes de fazer este curso. Embora este curso apresente diferentes conceitos de engenharia de software, nosso foco é entender o Bitcoin. Se o aluno quiser conhecer em detalhes alguns dos conceitos de engenharia de software abordados neste curso. Ele terá que usar outras fontes ao longo do curso para entendê-las melhor. Você precisará de um computador com Windows, macOS ou Linux com conexão à Internet. Apresentaremos este curso usando o Windows. Mas como o Java é compatível com várias plataformas, todos os códigos deste curso funcionarão da mesma forma nesses três sistemas operacionais. A única diferença será instalar o software necessário em cada plataforma, mas você pode encontrar facilmente guias para instalá-los nesses sistemas operacionais. Você precisará de pelo menos 30 GB de espaço livre para executar o nó Bitcoin no ambiente de rede de teste. Opcionalmente, se você pretende executar o aplicativo no ambiente de rede principal, precisará de pelo menos 430 GB de espaço em disco para baixar o blockchain da rede principal. Mas não se preocupe, usaremos o ambiente de rede principal somente no último vídeo do curso. Portanto, você terá bastante tempo para baixá-lo antes de precisar dele. Agora, vamos falar um pouco mais sobre a carteira que você construirá ao longo do curso. Vou me referir a essa carteira como BYOD W, um acrônimo para construir sua própria carteira, começará a desenvolver esse aplicativo com o Java 16, mas o atualizaremos mais tarde no curso. Diversion 19 usará a estrutura Spring Boot versão 2.5, 0.4, que fornecerá um contêiner de injeção de dependência e muitos recursos para nos ajudar a criar nosso aplicativo. Posteriormente no curso, vamos atualizá-lo para a versão 2.7, 0.5. Usaremos o Java FX versão 16 no projeto. Vamos atualizá-lo posteriormente para a versão 19. Essa biblioteca fornecerá classes que nos ajudarão a criar a interface gráfica do usuário do aplicativo, também conhecida como pegajosa. Para testes, usaremos o Groovy, a estrutura do Spark e a ética de testes para criar carteiras , endereços iniciais, transações e outras operações de Bitcoin usaremos a biblioteca Bitcoin Java de código aberto, que eu construí especialmente para este curso. Usaremos o Bitcoin Core Node versão 22 para comunicação com o blockchain. Mais tarde no curso, vamos atualizá-lo para a versão 23. Embora o nó Bitcoin Core possa gerar carteiras e endereços, ele será usado apenas para recuperar dados e enviar dados para o blockchain. Operações como geração de sementes, endereços, construção e assinatura de transações serão feitas por nosso aplicativo. A exceção será para os testes. Nesses casos, usaremos a API Bitcoin Core Node RPC para gerar endereços, enviar transações e minerar blocos nos ambientes de teste, portanto, familiarizaremos com os mais importantes Métodos de API RPC do Bitcoin Core Note e crie um cliente para se comunicar com ele a partir de nosso aplicativo. Como o banco de dados usará a implementação SQL Java, o H SQL DB usará sua integração suave com a biblioteca Spring Boot Data JPA para se comunicar com o banco de dados. Finalmente, usaremos o IntelliJ idea como o IDE para construir esse projeto. Todo o código apresentado neste curso é aberto e está disponível em nossa página do GitHub. Para cada aula prática, a página de Projetos e Recursos conterá um link com a diferença de código entre as duas últimas aulas práticas para a conveniência dos alunos. Agora, vamos apresentar quem eu sou. Meu nome é Alberto Salazar e serei seu instrutor neste curso. Tenho mais de cinco anos de experiência como desenvolvedor profissional de software, trabalhando especialmente no setor de comércio eletrônico. Sou entusiasta do Bitcoin desde 2016. Eu estava estudando muito Bitcoins desde então. Eu desenvolvo a biblioteca Bitcoin Java de código aberto, que usaremos neste curso. Eu criei a iniciativa educacional sobre Bitcoin para concentrar meus esforços em fornecer educação sobre Bitcoin para desenvolvedores em todo o mundo. Siga-nos no Twitter para receber nossas atualizações mais recentes. Concentrei todo o código desse curso, incluindo a biblioteca Bitcoin Java em nossa página do GitHub. Também temos um site cujo endereço é www dot bitcoin education dot site. Temos alguns artigos técnicos que podem servir como material de estudo adicional. Confira isso como uma palavra final. Eu gostaria de dizer que muito trabalho foi feito para fazer este curso. Demorou mais de dois anos para ser feito e quase todo o meu tempo livre durante esse período. Então, por favor, se você tiver alguma dificuldade ou encontrar algum problema com este curso, entre em contato comigo antes de dar uma classificação baixa para que possamos ajudá-lo com seu problema. Terei prazer em fazer todo o possível para que você tenha uma ótima experiência de aprendizado. Muito obrigado pela atenção e até o próximo vídeo. 2. 0 Requisitos de instalação Skillshare 2: Neste vídeo, apresentaremos o software necessário que você precisará baixar e instalar antes de prosseguir com os próximos vídeos do curso. Então, vamos começar com o Bitcoin Core Node. O Bitcoin Core Node é a implementação original do Bitcoin. É responsável por se comunicar com o blockchain, criar, receber, enviar e validar transações de Bitcoin, receber blocos e muito mais. Como dissemos no vídeo anterior, as principais funções que dependerão do nó Bitcoin Core são aquelas relacionadas à comunicação com o blockchain. Então, vamos ao site Bitcoin core.org. Instalará o Bitcoin Core versão 22. Você pode perguntar por que não instalar a versão 23? Quando comecei a fazer este curso, a versão mais recente disponível era 22. Há uma pequena diferença na API gRPC na versão 23 que fará com que um método do nosso aplicativo não funcione corretamente. Em um dos vídeos mais recentes do curso, atualizaremos a versão 23 do nó Bitcoin 2 e tornaremos nosso aplicativo compatível com ela. Mas, por enquanto, vamos instalar a versão 22. Para fazer isso, clique no botão de liberação na parte superior da tela e, em seguida, clique no link Bitcoin Core 22. Em seguida, clique neste link na página. Esta página contém arquivos de instalação para cada sistema operacional. Como estou usando o Windows, vou baixar aquele que termina com dot EXE. Se você estiver usando o macOS, você baixará aquele que termina com dot DNG. Para distribuições Linux, escolha o arquivo dot GZ adequado de acordo com a distribuição que você usará na página Projetos e Recursos Há links com instruções de instalação para cada uma sistema operacional. Windows, depois de baixar o arquivo, abra-o e siga as instruções de instalação na tela. Não vou fazer isso porque já o instalei na minha máquina. Mas é um processo simples. Na última fase da instalação, ele perguntará se você deseja abrir o software. Não abra ainda. Interagirá com o nó Bitcoin por meio da interface da linha de comando. Se você abrir o nó clicando em seu ícone, ele abrirá uma interface gráfica de usuário e começará a baixar o blockchain no ambiente de rede principal, que ainda não queremos fazer. Agora, vamos configurar nosso node Bitcoin. Para fazer isso, teremos que criar um arquivo chamado bitcoin.com e a pasta apropriada do aplicativo Bitcoin. localização dessa pasta depende do sistema operacional que você está usando. Este site na tela mostra o local padrão em que você deve criar esse arquivo para cada sistema operacional. Para criá-lo, abra um arquivo de texto e salve-o com o nome bitcoin.com na pasta apropriada para seu sistema operacional. Agora, escreva a mesma configuração que você vê na tela do seu arquivo ou copie e cole o conteúdo da página Projetos e Recursos nela. Não se preocupe, explicaremos o que cada linha desse arquivo significa em um vídeo posterior. Por enquanto, você terá que decidir onde deseja armazenar os dados do blockchain em seu computador, escolher um caminho com acesso a pelo menos 30 GB para o blockchain da rede de teste ou 430 adicionais gb para o blockchain da rede principal. Opcionalmente, defina a configuração DIR de dados para o caminho escolhido nesse arquivo. No meu caso, decidi armazenar os arquivos blockchain na unidade E na pasta de dados do Bitcoin, como você vê na tela. Agora, se executarmos o nó Bitcoin com essa configuração, ele será executado na rede principal e iniciará o download do blockchain da rede principal. Como o próprio nome sugere, o principal ambiente de rede é o principal ambiente de bitcoin, onde o blockchain é grande e os bitcoins têm valor, só executará o ambiente de rede principal no último vídeo do curso. Antes disso, ele será executado no ambiente de rede de teste, que é usado para testes. Para executar nossa nota sobre o ambiente de rede de teste, vamos adicionar uma linha escrita de rede de teste igual a uma no arquivo bitcoin.com. Agora, usando o terminal, vamos para a pasta em que você instalou o Bitcoin Core Node. Dentro da pasta demoníaca, execute o aplicativo Bitcoin D desta forma. Nos registros do console. Observe que estamos rodando de fato no ambiente de rede de teste e todos os seus dados serão armazenados na pasta indicada. Bom, isso significa que nosso node está funcionando com a configuração que definimos no arquivo bitcoin.com. Agora, vamos esperar que nosso node se conecte a outros nós e comece a baixar e validar o blockchain. Ok, as linhas que começam com a dica de atualização de texto indicam que ele começou a baixar o blockchain. Cada uma dessas linhas indica um bloco de transações de Bitcoin baixadas. O progresso em cada linha indica o quanto o blockchain está afundando. No meu caso, isso indica que cerca de 98% do blockchain de teste da rede foi baixado. Quando esse valor é igual a um, isso indica que nossa cópia do blockchain está completamente sincronizada com as de outros nós. Para o ambiente de rede de teste , pode levar algumas horas para que isso aconteça. Você pode deixá-lo afundando enquanto assiste ao resto do curso, pois o usaremos somente após alguns vídeos. Para sair do aplicativo, você pode pressionar Control plus C ou Command plus C se estiver usando o Mac OS Se você iniciar a nota novamente, ela começará a baixar o blockchain onde parou. Depois de terminar de baixar o ambiente de teste da rede, você pode, opcionalmente, alterar o arquivo bitcoin dot conf e começar a baixar o blockchain principal da rede executando a nota no ambiente de rede principal, usará apenas o ambiente de rede principal no último vídeo do curso, então você terá bastante tempo para baixá-lo. O outro requisito inicial deste curso é o IntelliJ idea Java IDE. É o software que usaremos para escrever o código e executar nosso aplicativo. Se você não tiver, acesse o site na tela para fazer o download. Baixe e instale a edição comunitária para seu sistema operacional seguindo as instruções no site. 3. O que é o Bitcoin?: Olá, bem-vindo de volta ao curso para desenvolvedores de Bitcoin. Nesta seção do curso, você terá uma visão geral do Bitcoin. os conceitos apresentados nesta seção, forneceremos o conhecimento básico necessário para entender o que está por vir no restante do curso. Então, vou começar com a pergunta: o que é Bitcoin? O Bitcoin com B maiúsculo é um protocolo de comunicação. Esse protocolo é um conjunto de regras que permite a troca de mensagens entre as entidades participantes da rede Bitcoin. Bitcoin com b minúsculo é uma criptomoeda. Uma criptomoeda é uma forma de moeda digital que podemos trocar por bens ou outros ativos. A parte criptográfica do nome vem da criptografia, que protege transações e outras operações de Bitcoin. O Bitcoin também é um sistema de pagamento. Podemos enviar e receber pagamentos em Bitcoin de e para outros participantes da rede Bitcoin. Falando em redes, Bitcoin também é uma rede ponto a ponto, o que significa que é composta por entidades ou nós que se comunicam diretamente entre eles sem a participação de servidores centralizados. A próxima pergunta é: quando o bitcoin foi inventado? O Bitcoin foi inventado em 2008 por Satoshi Nakamoto com a publicação do livro branco Bitcoin, uh, sistema de caixa eletrônico peer-to-peer. Neste artigo, que eu recomendo fortemente a leitura, Satoshi descreve as partes básicas do Bitcoin. Ninguém sabe quem realmente é Hitoshi Nakamoto, ou se é mesmo um nome verdadeiro ou várias pessoas. Quem quer que seja Satoshi, em 2009, ele publicou o primeiro bloco Bitcoin chamado bloco gênese e colocou a rede Bitcoin em funcionamento. Se você não sabe o que é um bloco de Bitcoin, não se preocupe. Vou explicar resumidamente. Então, o que há de tão bom no Bitcoin? Qual é a inovação do Bitcoin? Bitcoin foi a primeira moeda digital bem sucedida. Antes do Bitcoin, houve algumas tentativas de criar moedas digitais, mas todas falharam devido a problemas que o Bitcoin resolverá posteriormente. Um desses problemas é o problema do gasto duplo, que o bitcoin foi o primeiro a resolver de forma descentralizada. Isso acontece quando uma pessoa gasta duas vezes uma unidade monetária. Portanto, uma das transações é invalidada posteriormente, fazendo com que o destinatário da transação invalidada perca dinheiro. O Bitcoin também foi responsável pela invenção do blockchain, que foi usado para resolver o problema de gastos duplos. O blockchain é uma estrutura de dados responsável por armazenar todas as transações de Bitcoin. Ele permite a validação de todas as suas transações para qualquer pessoa com acesso a ela, mas falaremos mais sobre isso posteriormente. O Bitcoin também introduziu o conceito de escassez digital. Isso significa que, diferentemente dos arquivos em seu computador que podem ser copiados e distribuídos indefinidamente, Bitcoin só pode ser transferido pelo proprietário e não pode ser copiado e distribuído livremente. 4. Transações de Bitcoin e chaves privadas: Agora vamos nos aprofundar um pouco mais nos detalhes internos do Bitcoin. Vou explicar o Bitcoin do micro ao macro. Ou seja, falarei sobre transações de Bitcoin e chaves privadas, depois um pouco sobre blockchain e mineração. Em seguida, terminarei a visão geral explicando o ecossistema Bitcoin. Então, vamos começar com a pergunta: onde estão a criptomoeda e o sistema? Ou, em outras palavras, onde está o Bitcoin com b minúsculo no sistema? A resposta é que está em uma transação. Esta figura mostra uma transação comum de Bitcoin com uma entrada e duas saídas. Uma transação de Bitcoin pode ter muitas entradas e saídas, mas em muitos casos, elas têm apenas uma entrada e duas saídas. Em uma transação de Bitcoin, temos as informações de onde o Bitcoin veio na entrada e para onde o Bitcoin está indo na saída. Neste exemplo, a entrada zero contém uma instrução que diz que essa entrada veio de John, foi assinada por John e continha um Bitcoin. A primeira saída, chamada de saída zero, diz para Mary, contém 0,9 Bitcoin. Na primeira saída, diz que John contém 0,099 Bitcoin. Essa saída é a alteração da transação. Na maioria dos casos, precisamos incluir uma alteração porque quando você gasta Bitcoin em uma transação, você precisa gastar todas as unidades da entrada. Portanto, isso gera a necessidade de criar uma saída adicional, que é a mudança. Portanto, se sua entrada contém mais bitcoins, você deseja enviar para outra pessoa, então você deve criar uma saída adicional, a alteração para você mesmo. Temos o conceito de UTXO, que significa saída de transação não gasta. Um bitcoin está mais especificamente dentro de um UTXO. Uma entrada de transação deve se referir a um UTXO de uma transação anterior para poder gastar esse Bitcoin nessa transação. Se você notar que a soma das quantidades de saídas é menor do que a quantidade na entrada. Por que isso? A diferença se deve à pequena taxa. Cada transação de bitcoin deve separar um valor da taxa menor para que sua transação possa ser incluída no blockchain por um menor. Portanto, o valor da taxa de transação é a diferença entre a soma dos Bitcoins presentes nas saídas e a soma dos Bitcoins presentes nas entradas. Outra informação importante é que o Bitcoin pode ser dividido em 100 milhões de Satoshi. Portanto, neste exemplo de transação, poderíamos dizer que as entradas continham 100 milhões de Satoshi, na saída zero contém 90 milhões de Satoshi e a saída contém 9.900.000 De Satoshi. A taxa menor foi de 100.000 Satoshi. Esses são outros exemplos de transações de Bitcoin. Eu os coloquei aqui apenas para mostrar que você pode ter transações com mais de uma entrada e uma saída. Por exemplo, você pode ter uma transação com duas entradas e uma saída. Essa transação não tem nenhuma alteração. Você pode ter uma transação com duas entradas e duas saídas. Nesse caso, a transação tem entradas de duas pessoas diferentes e saídas para duas pessoas diferentes. Esse tipo específico de transação é chamado de transação Coinjoin, que é um tipo de transação que aumenta a privacidade porque você não pode vincular entradas específicas a saídas específicas. Você pode ter uma transação com três entradas e duas saídas. Há outros tipos de transações, como transações com várias assinaturas, sobre as quais não falaremos agora, mas poderemos incluí-las posteriormente em uma seção extra do curso, se houver demanda suficiente. Vamos ver um pouco mais sobre os detalhes de uma transação. Nesta imagem, há duas transações, transação um e a transação dois. Ambas as transações têm uma entrada e uma saída. A entrada tem três campos, o ID da transação anterior e o número de saída de uma transação anterior e uma assinatura válida. A saída tem dois campos, destino, endereço e quantidade, que se referem à quantidade de Bitcoin dentro da saída. Nesse caso, a entrada da transação dois está gastando a saída zero da transação um. Para fazer isso, insira um da transação para deve se referir ao ID da transação da transação um. Também deve se referir ao número de saída da transação um, que nesse caso é zero. Finalmente, ele deve conter uma assinatura válida produzida com a chave privada usada para derivar o endereço de destino da saída zero. Veremos mais detalhes sobre essa operação no próximo slide. Como você pode notar, as chaves privadas são uma parte fundamental do Bitcoin. As chaves privadas são usadas para receber e enviar bitcoins para receber. As chaves privadas são transformadas em chaves públicas por meio da multiplicação de curvas elípticas. Depois de uma função de hash, as chaves públicas são transformadas em endereços Bitcoin. Esses são os endereços Bitcoin que você pode mostrar a outras pessoas para receber Bitcoins. As chaves privadas também são usadas para atribuir transações de Bitcoin. As assinaturas são necessárias para transferir Bitcoins de um endereço para outro. Nesta imagem, temos uma transação não assinada. Quando combinamos a chave privada com uma transação interna usando o algoritmo de assinatura digital de curva elíptica, ECDSA, produzimos uma assinatura que incluímos nessa transação. Assim, ela se torna uma transação assinada. A mesma chave privada que produziu o endereço referido a uma entrada zero também é usada para desbloquear esses fundos e a transação atual, produzindo a assinatura. Assim, uma chave privada é usada indiretamente para bloquear fundos em um endereço e para desbloquear fundos do mesmo endereço produzindo uma assinatura. O importante sobre chaves privadas e suas transformações é que você não pode produzir uma chave privada a partir de uma chave pública e não pode produzir uma chave pública a partir de um endereço Bitcoin. Você também não pode produzir uma chave privada a partir de uma assinatura. Essas operações são apenas em uma direção, exatamente como mostram essas setas. Outra característica importante das transações de Bitcoin é que qualquer pessoa com acesso a uma transação pode validar assinaturas. Isso é possível porque, se você tiver uma chave pública, a assinatura e a mensagem, que nesse caso é a transação. Você pode verificar se uma assinatura é válida para essa chave pública. E uma assinatura é válida para uma chave pública somente se for produzida com uma chave privada que produziu a mesma chave pública. 5. Carteiras de Bitcoin, o Blockchain e mineração: Agora que você tem um conhecimento básico sobre chaves privadas, podemos começar a falar sobre carteiras. Uma carteira Bitcoin é, em resumo, uma coleção de chaves privadas. Existem muitos tipos e padrões de carteiras. As carteiras têm desenvolvimento independente em relação a outros softwares de Bitcoin , como nós. Uma regra básica para possuir Bitcoin não é o mantra. Suas chaves, seus bitcoins, não suas chaves, não seus Bitcoins. Isso ocorre porque o proprietário de uma chave privada pode transferir Bitcoins bloqueados por sua chave privada e outras transações. O que as carteiras de Bitcoin têm em comum? Eles têm uma maneira segura de gerar e armazenar chaves privadas. Eles podem se comunicar com os nós do Bitcoin. Eles podem criar, assinar e enviar transações de Bitcoin. Eles podem gerar endereços Bitcoin. Observe que a maioria dessas habilidades é possível graças às transformações de chaves privadas. Toda operação que usa chaves privadas pode ser feita offline. Você só precisa estar on-line ao se comunicar com os nós do Bitcoin para obter informações do blockchain e enviar informações para o blockchain. Falando em blockchain, vamos finalmente ver o que essa palavra da moda significa. O blockchain foi usado para resolver o problema de gastos duplos de forma descentralizada. Ele faz isso organizando as transações em uma cadeia de blocos para que blocos válidos não possam conter transações com um UTXO que apareceu no mesmo bloco ou em blocos anteriores. Para entender o que é o blockchain, vamos dar uma olhada nessa figura. Esses blocos representam blocos do blockchain. Alguns de seus dados são representados nesses retângulos menores. Dentro de cada bloco. Um bloco é composto por muitas transações, um campo chamado hash anterior, que, como o nome sugere, é o hash do bloco anterior. Um campo chamado timestamp, que armazena a data em que o bloco foi criado, e um campo chamado nonce, sobre o qual falaremos no próximo slide. Cada bloco produz um hash que é inserido no próximo bloco. Os blocos são criados e adicionados ao blockchain em um processo chamado mineração. mineração é o processo em que os blocos são incluídos no blockchain. Os nós que realizam esse processo são chamados de mineradores. Para incluir blocos no blockchain, os mineradores devem coletar transações e organizá-las em um bloco. Em seguida, os menores devem resolver o Proof of Work, que é um algoritmo necessário para produzir blocos válidos. prova de trabalho é composta pelas seguintes etapas. Primeiro, um bloco é codificado e, em seguida, o número de zeros iniciais do hash resultante é verificado. Se esse número for maior ou igual ao número necessário de zeros para incluir o bloco na blockchain. O bloco está incluído no blockchain. Caso contrário, o menor modifica o nonce e repete o processo. Então essa é a função do nonce. Seu único objetivo é fornecer variabilidade para que um bloco produza diferentes hashes. A prova de trabalho tem uma característica interessante. Quanto mais zeros forem necessários para uma prova de trabalho válida, mais difícil será encontrá-la. Isso torna a dificuldade de mineração facilmente ajustável. No Bitcoin, a dificuldade de mineração é ajustada automaticamente, então o tempo médio para minerar um bloco é de 10 minutos. Quando um menor se importa com um bloco, ele ganha uma recompensa em bloco e todas as taxas de transação do bloco. A recompensa do bloco é a única maneira pela qual novos bitcoins são criados. Ele diminui pela metade a cada quatro anos em um evento chamado ter. Portanto, a cada quatro anos, o fornecimento de novos Bitcoins emitidos fica mais escasso. E calcula-se que o último bitcoin será extraído por volta 21:40, quando o suprimento total de Bitcoin será igual a 21 milhões. 6. A rede de Bitcoin, o ecossistema e os princípios: Agora vamos falar sobre a rede Bitcoin. Vamos ver as etapas básicas de como a rede Bitcoin funciona. Primeiro, novas transações são enviadas aos nós. Cada minerador reúne as transações em um bloco. Cada minerador tenta encontrar uma prova de trabalho em bloco o mais rápido possível. Quando um minerador encontra uma prova de trabalho, o menor transmite seu bloqueio mental para a rede. Outros nós verificam se o bloco é válido. Para que um bloco seja válido, ele deve seguir todas as regras de consenso, como todas as transações, e deve ser válido e o hash do bloco anterior deve ser igual ao cache do último bloco válido. Se o bloco for válido, os nós o adicionarão ao Blockchain. Copiar. Pequeno começo a trabalhar em novos blocos usando o campo hash do bloco mental recente como o hash anterior. Você pode estar se perguntando o que acontece se dois mineradores minerarem um bloco válido ao mesmo tempo. Bem, quando isso acontece, causa uma divisão na rede. Parte dos nós conterá uma versão do blockchain com um bloco de um menor e a outra parte da rede conterá um bloco do outro menor. Mas essa divisão é apenas temporária. Quando o próximo bloco for minerado, os dois grupos de nós considerarão apenas o blockchain com mais blocos, pois o blockchain real e o outro blockchain será descartado, a probabilidade de a divisão da rede persiste diminui com o tempo. Portanto, é seguro presumir que, após seis blocos uma transação é liquidada para sempre no blockchain. A imutabilidade e a segurança das transações de Bitcoin dependem do fato de que é quase impossível produzir um blockchain válido com mais blocos do que o original. Esse feito exigiria uma quantidade imensa de potência computacional necessária para superar a velocidade de geração de blocos da rede original por um tempo suficiente. Agora que aprendemos sobre várias partes do Bitcoin, vamos ver como elas interagem dentro do ecossistema Bitcoin. Usuários de Bitcoin controlam carteiras. As carteiras, como você aprendeu, são coleções de chaves privadas. E essas chaves privadas podem ser usadas para assinar transações e produzir endereços para receber transações. As bolsas podem trocar bitcoins por outras criptomoedas e moedas fiduciárias, como o dólar. Você também pode trocar bitcoins por produtos de comerciantes. Com quem você faz transações, todas as suas transações são enviadas para os nós de Bitcoin. Quando um menor vê sua transação, ele pode incluí-la em um bloco. O minerador cria um bloco com muitas transações e passa a minerar o bloco. Ou seja, ele começa a calcular a prova de trabalho do bloco usando seu hardware. Quando um menor finalmente encontra a prova de funcionamento do bloco, ele transmite o bloco para outros nós de Bitcoin. Os outros nós recebem o bloqueio mental recente e são validados. Se o bloco for válido, os nós o adicionarão à cópia do blockchain. Dessa forma, a rede alcança um consenso sobre o estado atual do blockchain. Vamos falar sobre os princípios do Bitcoin. Os princípios do Bitcoin são importantes para entender as decisões técnicas que foram tomadas durante o desenvolvimento do Bitcoin. Um desses princípios é o fornecimento máximo de Bitcoin de 21 milhões de Bitcoins. Esse limite foi definido no início do projeto. Mudá-lo causaria esses arranjos na economia do Bitcoin. Portanto, é importante manter as coisas assim. resistência à censura é outro princípio importante do Bitcoin. O fato de muitas pessoas poderem executar nós de Bitcoin torna quase impossível que uma autoridade desligue a rede. Os desenvolvedores de Bitcoin valorizam uma alta resistência à censura. Ser de código aberto é outro princípio do Bitcoin. Você pode encontrar o software Bitcoin Core gratuitamente no site do GitHub. Como muitos outros desenvolvedores, você pode verificar o código e verificar se há bugs. Você também pode participar de seu desenvolvimento. O Bitcoin tem uma forte comunidade de desenvolvedores responsáveis por sua segurança e novos recursos. E ser de código aberto é o que permite isso. O Bitcoin não tem permissão, o que significa que qualquer pessoa pode executar um node de Bitcoin, minerar e transacionar Bitcoins. Esse é um dos maiores pontos fortes do Bitcoin e o que o torna tão popular hoje em todo o mundo. As transações de Bitcoin são pseudônimas. Isso significa que nenhuma informação presente em uma transação de Bitcoin pode se conectar sozinha com as pessoas. Ao contrário do exemplo do início da visão geral, pode ter sugerido que as transações de Bitcoin não contêm os nomes e IDs dos destinatários e remetentes. Uma transação de Bitcoin mostra apenas transferências entre endereços de bitcoin, que pareciam coleções aleatórias de caracteres. Se alguém descobrir que um endereço pertence a uma pessoa específica , poderá rastrear a quantidade de Bitcoin e outras transações dessa pessoa. Mas isso é outra história. O Bitcoin visa alta fungibilidade. fungibilidade é uma característica que faz com que uma unidade de uma moeda seja avaliada igualmente como qualquer outra unidade da mesma moeda. Isso significa que, idealmente cada Bitcoin é valorizado e tratado da mesma forma. Costuma-se argumentar que o Bitcoin não é fungível porque Bitcoins de diferentes transações podem ser rastreados e tratados de forma diferente. Eu diria que, embora seja verdade na prática, maioria dos bitcoins é tratada da mesma forma e você tem maneiras de tornar as transações mais privadas e fungíveis. A irreversibilidade das transações é outro princípio do Bitcoin. Depois que uma transação é liquidada no blockchain, ela não pode ser revertida. Esse é um recurso de segurança importante porque torna o Bitcoin difícil de confiscar. Mas também transfere a responsabilidade de uma transação para o centro de Bitcoin. Daí a necessidade de manter suas chaves privadas seguras. 7. 5 Iniciar o skillshare do projeto 2: Neste vídeo, criaremos um novo projeto Spring Boot que será nossa carteira Bitcoin. Para fazer isso, usaremos a ferramenta de inicialização Spring do site start dot spring dot io. Então entre no site. Escolha o projeto Maven. A linguagem é Java, usará essa versão do Spring Boot, mas se não estiver disponível para você, você poderá escolher a padrão como nome do grupo. Você pode definir o nome que quiser. No meu caso, vou defini-la como BYOD w dot wallet. Vou usar BYOD W como nome do artefato, como descrição. Vou usar a carteira Bitcoin. Usaremos a versão mais recente do Java. Se você conhece apenas as versões anteriores do Java, não se preocupe, recursos mais antigos do Java ainda funcionam na versão mais recente, pois o Java é compatível com versões anteriores. Por fim, clique em Gerar para baixar o projeto, abri-lo e extrair seu conteúdo para a pasta que você deseja. Agora, abriremos o projeto usando uma ideia inteligente. Depois de iniciar o programa, clique em Abrir e escolha a pasta que você acabou de extrair. Clique em Trust Project. Espere até que o IntelliJ idea indexe todos os arquivos do projeto. Depois disso, você pode explorar os arquivos que o Spring Initializer criou automaticamente. Para verificar se o projeto foi configurado corretamente. Clique em Maven no lado direito da tela. Em seguida, dentro da pasta do ciclo de vida, clique duas vezes em Testar. Opa, recebemos um erro do Maven. Para resolver esse erro, vamos clicar na caixa de diálogo de configuração. Vamos mudar o caminho inicial do Maven para o pacote Maven 3. Clique em Aplicar então. Ok. Antes de clicar em testar novamente, verificarei se a estrutura do meu projeto foi configurada corretamente. Então, vou clicar em Arquivo. Em seguida, a estrutura do projeto garante que o SDK do projeto tenha a versão Java que você escolheu, o inicializador Spring. Se não for o caso, clique em Adicionar SDK e baixe o SDK, escolha a versão correta do Java e, em uma de suas implementações, clique em baixar. No meu caso, não vou fazer isso porque já tenho a versão correta. Então, vou clicar em Cancelar. Certifique-se de que o nível da linguagem do projeto também esteja definido para a versão correta do Java. Agora, vamos fazer o teste novamente. Espere até que o teste passe. Ótimo. O console indica que o teste foi aprovado. Estamos prontos para começar a trabalhar em nossa carteira. 8. 6 Configurar o compartilhamento de habilidade da GUI 2: Neste vídeo, começaremos a construir a primeira janela da nossa carteira. Para fazer isso, primeiro adicionaremos algumas dependências ao nosso projeto. Abra o arquivo xml de palma na raiz do projeto. O arquivo xml palm dot contém todas as dependências externas do projeto. Vamos adicionar algumas dependências do Java FX. Java FX é uma estrutura responsável pelos recursos da interface gráfica do usuário. É muito conhecido na comunidade Java. A versão é 16. A próxima dependência é JavaFX, FXML. A versão também é 16. Também adicionaremos um plugin. É chamado de plugin Java FX Maven. versão é 0.0, 0.6. Para carregar essas dependências em seu projeto, clique nesse ícone. O projeto carregou todas as dependências. Agora vamos criar o código necessário para inicializar nosso aplicativo. Esse processo requer alguma coordenação entre as formas em que os efeitos Spring Boot e Java são iniciados. Para fazer isso, primeiro criaremos uma nova classe Java chamada aplicação GUI. Essa classe deve estender a classe do aplicativo a partir dos efeitos Java. E devemos implementar o método start da mesma classe. Adicionaremos uma propriedade privada com o tipo de contexto de aplicativo configurável. Usaremos a seguir. Adicionaremos o método init aqui, que é executado antes do método start, durante a inicialização do aplicativo. O código que acabei de digitar é responsável por inicializar nossas dependências injetadas no aplicativo Spring Boot . Agora vamos para a classe de aplicação BYOD W. Vamos modificar o método principal. O método principal dessa classe é o primeiro método chamado quando executamos nosso aplicativo. Quando o código que acabei de digitar for executado, ele chamará primeiro o método init da classe do aplicativo GUI e não o método start da mesma classe. Vamos voltar para a classe de aplicação GUI. Vamos continuar implementando o método start. Agora, chamaremos o método de publicação do evento na propriedade context, passando um novo objeto de evento iniciado pela GUI, que será criado em seguida como argumento. Vamos criar uma aula de eventos bem iniciada. Vamos criá-lo em uma nova pasta de eventos. Devido à forma como criamos essa classe, o ID já sabia qual classe tínhamos que estender e, ao criar automaticamente , o código padronizado precisará ser muito útil, não é? Agora continuaremos implementando nosso construtor. Chamaremos o superconstrutor passando um objeto de aplicação GUI como argumento. E atribuiremos o estágio primário do argumento ao estágio. A propriedade privada também criará um ouvinte para essa classe de evento dentro de um pacote chamado ouvintes. Adicionaremos a anotação do componente a essa classe. Você verá muito essa anotação ao longo do curso. É do Spring Boot e seu objetivo é disponibilizar um objeto de uma classe para injeção, e outros objetos do projeto também implementarão a interface de ouvinte do aplicativo para essa classe, passando o evento gooey started como um parâmetro de tipo. Isso é necessário para que o Spring Boot interprete essa classe como um ouvinte de eventos para um evento iniciado de forma pegajosa. Agora implementaremos o método necessário da interface. Também precisará de um construtor. Esse construtor pegará um objeto de recurso com uma anotação de valor apontando para um arquivo chamado ponto da janela principal FXML, que será adicionado posteriormente ao projeto. O construtor também usará um argumento de contexto do aplicativo. Em seguida, inicializaremos propriedades privadas com o mesmo nome dos argumentos do construtor. Fará com que ambas as propriedades sejam finais. Tudo bem, agora que temos nossas dependências injetadas nessa classe, vamos implementar o código do método de evento do aplicativo. Esse código será responsável por mostrar a janela principal da nossa carteira quando iniciarmos o programa. Então, primeiro instanciaremos um objeto carregador FXML. Em seguida, obteremos o objeto de palco do evento iniciado pela GUI. Para fazer isso, adicionaremos o método gets stage à classe de evento gooey started. Esse método retornará o objeto de palco. Adicionaremos um título à carteira usando o método set title do objeto de palco. Pode ser qualquer string que você quiser. Vou defini-la como carteira BYOD W. Esse texto será exibido na barra superior da janela do programa. Também chamará o método set scene, passando um novo objeto de cena como seu parâmetro instanciado com um objeto retornado por um novo método que criará chamado initialize FXML. Esse método começará a declarar uma variável do tipo parent chamada root. Em seguida, dentro de um bloco try catch usaremos o método set location da variável do carregador FXML passando a localização do URL de nossa propriedade FXML. Definiremos a fábrica de controladores do carregador FXML como uma referência do método good bean da propriedade context. Isso é necessário para que a estrutura JavaFX reconheça as classes do controlador anotadas com a anotação do componente. Também definiremos a variável raiz como resultado da chamada do método de carregamento do carregador FXML, capturaremos uma IOException e a lançaremos em uma exceção de tempo de execução. Nós retornaremos a variável raiz. Finalmente, no método sem aplicação chamará o método show do estágio, que fará com que a janela apareça na tela. Agora, criaremos o arquivo FXML, mas nos referimos à anotação de valor da propriedade FXML do construtor do ouvinte. E o arquivo FXML é um tipo de arquivo usado para codificar elementos de GUI de um aplicativo JavaFX. Como um arquivo HTML, codifica páginas da Web, arquivos FXML e código. As janelas de efeitos Java criarão esse arquivo dentro do novo caminho FXML que será criado. Esse diretório estará localizado dentro do caminho dos recursos. Vamos chamá-la de janela principal de sublinhado dot FXML. Vamos excluir o clichê gerado automaticamente. Vamos adicionar uma tag de painel de borda. Vamos adicionar alguns atributos a ele. Adicionará um ID Fx que permitirá fazer referência à tag do painel de borda dentro de sua classe controladora, que será criada posteriormente. Vamos adicionar alguns atributos para definir o tamanho da janela. Por fim, adicionaremos alguns atributos de metal para definir o esquema do arquivo. É isso mesmo. Vamos executar o aplicativo para ver se tudo correu bem. Dentro da guia Maven, vamos clicar em plug-ins, Spring Boot e Spring Boot run. Ótimo. A primeira janela da nossa carteira apareceu na tela. Bom trabalho. 9. 7 Criar nossa primeira carteira parte 1 skillshare 2: Neste vídeo, começaremos a criar um teste para o primeiro recurso da nossa carteira. O primeiro recurso da nossa carteira será a opção de criar uma carteira. Mais especificamente, criaremos um menu com um botão que, quando clicado, fará com que uma caixa de diálogo apareça na tela. Essa caixa de diálogo conterá inicialmente um TextField onde o usuário definirá o nome da carteira e um botão Criar que, quando clicado, gerará uma semente mnemônica aleatória. Aprenderá o que é a semente mnemônica. No próximo vídeo, criaremos todos os recursos de nossa carteira usando o desenvolvimento orientado por testes ou a abordagem TDD. Essa abordagem consiste em primeiro criar um teste de integração, que é um teste que descreve o que queremos alcançar com esse recurso. Em seguida, implementaremos o recurso e executaremos o teste até que ele seja aprovado. Durante a implementação, podemos encontrar situações em que precisamos criar novas classes ou métodos para nos ajudar a atingir nossos objetivos. Se for esse o caso, criaremos testes unitários para essas classes que eram métodos e os implementaremos usando o TDD. Ao final de cada ciclo de TDD, refatoraremos nosso código, se necessário. Vamos ver como isso funciona na prática. Mas primeiro, vamos adicionar algumas dependências ao nosso projeto. Adicionaremos algumas dependências relacionadas à estrutura do Spark. O framework Spark é um framework de testes em groovy, uma linguagem de programação compatível com Java. Ele contém recursos que facilitam a construção de testes, também usará uma versão do test FX compatível com Spock. Test fx é uma estrutura que fornece recursos para testar aplicativos JavaFX. Agora, vamos adicionar groovy versão 3.0, 0.6 ao nosso arquivo POM. E vamos adicionar Spock Spring a ele. A versão será 2.0, groovy 3.0. Seu escopo será testado. A próxima dependência que será adicionada é o Spark Core. A versão será a mesma de Spock Spring. O escopo será testado. A próxima dependência será testar o FX Spock. Sua versão será 4.0, 0.16 alpha também adicionará um plugin G Maven. Ok, esqueci de colocar o escopo certo e testar a dependência de FX. Também adicionaremos algumas metas no plugin GI Maven. Será necessário que o groovy funcione corretamente. Agora, faremos uma alteração no arquivo de propriedades dos pontos do aplicativo. Spring, por padrão, cria um servidor web, mas não precisaremos de um em nosso aplicativo. Portanto, devemos definir essa propriedade como nenhuma. Portanto, a primavera não criará um servidor web quando for inicializada. Agora vamos criar nosso primeiro teste. Mas primeiro, vamos excluir esse arquivo. O teste do aplicativo BYOD W, que foi gerado automaticamente pelo inicializador spring, criará um pacote nessa pasta chamado gooey que conterá todo o nosso usuário gráfico testes de interface. Dentro desse pacote, vamos criar o teste. Mas primeiro, no arquivo xml de palma, clique no botão carregar alterações do Maven. Agora, o IDE nos permitirá criar classes incríveis. Então, vamos criar um chamado teste de criação de carteira. Adicionaremos a essa classe uma anotação de teste do Spring Boot que estenderá essa classe com a classe de especificação do aplicativo. Isso é necessário para que tanto o Spring Boot quanto o test fx considerem essa classe como uma classe de teste. Todo teste de integração deve conter essa anotação e extensão. Devemos implementar o método de início a partir da especificação do aplicativo. Também implementaremos os métodos de unidade e parada. Dentro do método init, adicionará esse código que é necessário para a inicialização do teste. Dentro do método de parada incluirá um código necessário para interromper o teste. Dentro do método stark, devemos incluir o código necessário para mostrar a primeira tela do nosso aplicativo. Esse código será semelhante ao código presente na classe de ouvinte iniciada pela GUI. Portanto, instanciaremos um carregador FXML passando a URL FXML como argumento e, em seguida, criaremos a propriedade privada FXML com a mesma anotação de valor presente na classe de ouvinte iniciada pela GUI. Groovy transforma cada método com getter definido em uma propriedade de objeto Podemos usar esse URL aqui. Em vez de get URL, definirá a propriedade de fábrica do controlador como a referência do método get bean do contexto. Vamos adicionar o campo de contexto à classe. Acima. Ele colocará a anotação automática com fio. Essa anotação é necessária para que o Spring Boot injete o objeto de contexto do aplicativo de seu contêiner de injeção de dependência nessa variável. Em seguida, criaremos a variável raiz usando o método load do carregador FXML. Em seguida, definiremos o título do palco, a cena e chamaremos o método de show de palco , assim como o código dentro do ouvinte pegajoso iniciado. Ok, estamos prontos para trabalhar no código do nosso primeiro teste. O nome do teste será deve criar carteira. O teste conterá os requisitos do recurso que queremos implementar, usará a palavra-chave ao descrever as ações que o usuário do teste realizará. Então, vamos implementá-lo. O usuário clicará em um botão com o texto conhecido. Em seguida, você clicará em um botão com a carteira de texto. Em seguida, em um campo de texto com um nome de ID FX. Quando queremos nos referir a um ID de câmbio, colocamos o nome do ID após um sinal de libra como este. Em seguida, o usuário escreverá as palavras carteira MyText. Em seguida, ele clicará em um botão com o texto de criação. Em seguida, o teste examinará o conteúdo de um campo da área de texto com um ID de ética de semente mnemônica. Ele atribuirá o conteúdo desse campo à variável de semente mnemônica. Por fim, usaremos a palavra-chave para definir o que esperamos que aconteça depois que o usuário fizer todas as ações dentro do bloco de vento. Esperamos que a variável de semente mnemônica contenha um valor não nulo. Para fazer isso, basta colocar a variável de semente mnemônica dentro do bloco then. Se a semente mnemônica for definida, o bloco será avaliado como verdadeiro e o teste será aprovado. Caso contrário, será avaliado como falso e o teste não será aprovado. Vamos fazer esse teste para ver o que acontece. Primeiro, clicaremos em Construir e depois em reconstruir o projeto para garantir que o IDE carregue todas as alterações que fizemos no código. Em seguida, clicaremos em Testar na guia Configuração do Maven. *****. O IDE reclamou do Maven novamente, vamos corrigir isso rapidamente. Agora. Vamos fazer o teste novamente. O teste falhou conforme o esperado. Você notou que uma janela apareceu rapidamente na tela durante o teste? Mostra nossa janela aberta, pelo menos. Vamos conferir os resultados dos nossos testes no console. Diz que a nova consulta não retorna nenhum nó. O teste abriu nosso aplicativo e, em seguida, tentou encontrar um elemento com o texto conhecido, pois não o encontrou, ele falhou rapidamente e fechou o aplicativo. No próximo vídeo, aprenderemos o que é uma semente mnemônica. Em seguida, no vídeo seguinte, criaremos nossa primeira carteira e faremos com que esse teste seja aprovado. Te vejo. 10. Sementes de mnemônica: Neste vídeo, aprenderemos mais sobre sementes mnemônicas. Então, qual é a semente mnemônica? Uma semente mnemônica é uma frase contendo 121-51-8201 ou 24 palavras. É usado para derivar todas as carteiras, chaves privadas e endereços. As regras de geração mnemônica de sementes que usaremos estão descritas na Proposta de Melhoria do Bitcoin 39 ou BIP 39. Muitas carteiras usaram as regras do BIP 39 para gerar sementes mnemônicas. As sementes mnemônicas são combinadas com a string mnemonic mais uma senha opcional para produzir uma semente raiz representada aqui em formato hexadecimal. A senha opcional geralmente é chamada de frase secreta, mas usaremos a palavra senha para simplificar. Em seguida, usando outros algoritmos, o root seed gera chaves privadas, chaves públicas e endereços, aprenderá os detalhes dessas operações em um vídeo posterior. Agora, vamos nos concentrar em como as sementes mnemônicas são geradas. Para gerar uma semente mnemônica, primeiro, precisamos gerar uma sequência aleatória de bits chamada entropia de comprimento igual a 128 bits. Se quisermos uma semente mnemônica de 12 palavras, 160 bits, se quisermos uma com 15 palavras, 192 bits, se quisermos uma com 18 palavras, 224 bits se quisermos uma com 21 palavras ou 256 bits, se quisermos uma com 24 palavras, em seguida, calculamos a soma de verificação. Para fazer isso, calculamos o comprimento da entropia dividido por 32 e obtemos o tamanho da soma de verificação. Em seguida, obtemos os primeiros bits do tamanho da soma de verificação do hash SHA-256 da entropia. O resultado é a soma de verificação. A soma de verificação é usada para verificar se uma determinada semente mnemônica é válida. Anexamos a soma de verificação ao final da entropia inicial. O resultado é dividido em grupos de 11 bits. Cada grupo de 11 bits é convertido em um número 0-2047. Esses números são usados como índices em uma lista de palavras. As palavras correspondentes formam a semente mnemônica. 11. 9 Criar nossa primeira carteira parte 2 skillshare 2: Neste vídeo, continuaremos implementando o recurso de criação de carteira do nosso aplicativo. O primeiro passo é adicionar um botão com o novo texto escrito nele. Vamos fazer isso. Abra o arquivo FXML da janela principal. De agora em diante, usaremos a ferramenta IDE Scene Builder para criar as janelas do nosso projeto. Scene Builder nos permite criar a interface gráfica do usuário de nosso aplicativo de forma interativa e fácil. Clique no botão Scene Builder na parte inferior da tela. No meu caso, essa janela apareceu. Mas se você não tiver o Java FX ou o Scene Builder instalados, um botão para baixá-los aparecerá na parte superior da tela. Depois de baixá-los e instalá-los, essa janela será exibida. Agora, adicionaremos uma barra de menu superior à janela principal. Para fazer isso, clicaremos nos controles e arrastaremos e soltaremos o componente da barra de menu na parte superior do menu do painel de borda abaixo. Agora teremos uma barra de menu com três itens de menu. Vamos excluir as edições e as de ajuda. Vamos mudar o menu de arquivos denominado dois novos. Ótimo. Agora temos nosso novo botão. Vamos conferir nosso teste para ver o que fazer a seguir. A próxima ação que nosso usuário fará é clicar no botão da carteira. Vamos criá-lo. Volte para a janela principal. Adicionaremos um item de menu dentro do novo menu. Nesse caso, já temos um item de menu. Então, vamos mudar seu rótulo para carteira. Quando o usuário clica no botão da carteira, uma nova janela de diálogo deve aparecer. Vamos implementá-lo no Scene Builder. Clique no item do menu da carteira. Adicionaremos uma ação a esse botão. Clique em Código, digite open create wallet dialog. Se clicarmos no botão Texto na parte inferior da tela e verificarmos o arquivo FXML. Perceberemos que o IDE adicionou o atributo on action na tag do item de menu com o valor que acabamos de digitar. Agora, para criar uma ação para esse botão, será necessário criar um controlador. Mas primeiro, vamos fazer uma refatoração em nosso código. Criaremos um novo pacote dentro do pacote BYOD W. Vamos chamar isso de gooey, transferirá os pacotes de eventos e ouvintes para ele, adicionará todas as classes relacionadas à gráfica do usuário do aplicativo interface gráfica do usuário do aplicativo a este pacote. De volta à janela principal, adicionaremos um atributo de controlador FX à tag do painel de borda e o configuraremos para que o novo controlador que criaremos o crie dentro de um novo pacote de controladores. Dentro da embalagem pegajosa. Seu nome será controlador de janela principal. Cada arquivo FXML pode ter um controlador que é usado para definir as ações que acontecem em resposta às interações do usuário com a janela codificada por esse FXML. Em nosso caso, o controlador da janela principal conterá um código que definirá ações em resposta aos eventos na janela principal. Voltar para a janela principal, coloque o arquivo FXML. Quando clicamos no atributo Abrir caixa de diálogo de criação de carteira e pressionamos Alt e enter, o IDE mostrará a opção de criar um método dentro do controlador da janela principal. Clique nessa opção. O IDE gerou automaticamente o método no controlador da janela principal. Vamos excluir o argumento do evento de ação porque não precisaremos dele. Nesse método, incluirá o código responsável por abrir a caixa de diálogo de criação da carteira. Quando clicamos no item do menu da carteira, primeiro instanciaremos um objeto de diálogo do tipo botão. Em seguida, definiremos as caixas de diálogo em seu proprietário na janela do painel de borda para indicar que a caixa de diálogo pertence ao painel de borda da janela principal. Voltar para a janela principal, coloque o arquivo FXML. Podemos clicar no atributo de ID de ética da tag do painel de borda, pressionar Alt mais Enter e criar a propriedade do painel de borda dentro do controlador da janela principal. O IDE gerou automaticamente a propriedade. Vamos defini-lo como privado e incluir a anotação FXML acima dele para indicar que ele se refere a um componente FXML. Em seguida, definiremos o título do diálogo para criar uma nova carteira. Agora, dentro de um bloco try catch, instanciará um objeto carregador FXML. Passando esses argumentos. Em seguida, criaremos a propriedade de diálogo de criação de carteira e a propriedade de contexto. Em seguida, criaremos um construtor para inicializar as duas propriedades. Ambas as propriedades serão injetadas automaticamente pelo contêiner de injeção de dependência do Spring e adicionará uma anotação de valor ao argumento do construtor de diálogo create wallet passando pelo caminho de um FXML. arquivo que será criado a seguir. Em seguida, definiremos o conteúdo do do diálogo como resultado da chamada do carregamento do método do carregador FXML. Em seguida, capturaremos uma IOException e lançaremos como uma exceção de tempo de execução. Por fim, chamaremos o método de exibição de diálogos e aguardaremos para abrir o diálogo. Não se esqueça de adicionar a anotação do componente a essa classe. Agora, vamos executar nosso aplicativo para ver o que temos até agora. Na guia Maven, dentro de plugins e Spring Boot, clique em Spring Boot run. Temos nossa barra de menu superior com o botão Novo e o botão da carteira. Quando clicamos no botão da carteira, o aplicativo gera uma exceção. Isso porque ele não encontrou o arquivo FXML de ponto da caixa de diálogo de criação de carteira. Vamos criá-lo. Depois de criá-lo, clique em Scene Builder. Vamos excluir esse painel de ancoragem. Arraste a dor do diálogo e solte-a aqui. Bom. Vamos ajustar o tamanho dela. Clique em Layout. Em seguida, no campo pref height, digite 500, no campo pref width, digite 50. Em seguida, defina o tamanho de preparação de uso nos campos largura mínima e altura mínima. Agora vamos adicionar um texto de cabeçalho à janela. No campo de texto do cabeçalho, digite. Dê um nome à sua carteira e clique em Criar. Vamos adicionar um pouco de preenchimento ao redor. Bom. Agora vamos adicionar um painel de grade. Arraste e solte esse componente no painel de diálogo abaixo. Dentro da primeira célula do painel da grade, adicionará um rótulo como este. E esse rótulo conterá o nome da carteira de texto. Também adicionaremos um campo de texto ao painel da grade. Vamos mudar suas coordenadas, definir o índice da coluna como um. Agora vamos adicionar um botão ao painel da grade. Altere o índice da linha para um e o índice da coluna para um. Vamos mudar seu texto para criar. Vamos voltar ao nosso teste para verificar o que mais ele exige. Ele tentará clicar em um componente com um nome de identificação ética. Então, vamos adicionar um nome de ID Fx ao campo de texto. Depois disso, ele tentará escrever minha carteira de texto no campo de texto. Em seguida, ele clicará em um componente com o texto Criar nele, criar com uma letra maiúscula C. Ao clicar nele, o teste pesquisará o conteúdo de uma área de texto com uma ideia FX de semente mnemônica. Então, vamos criar essa área de texto. Arraste-o para o painel da grade abaixo. Em seguida, altere o índice da linha para dois e a extensão da coluna para dois, de forma que o campo de semente mnemônico ocupe o espaço de duas colunas. Bom. Também adicionaremos um rótulo para o campo de sementes mnemônicas. Mas primeiro, vamos adicionar outra linha ao painel da grade. Bom. Vamos aumentar o índice de linha do campo de sementes mnemônico para três. Em seguida, arrastaremos um rótulo para o painel da grade. Ajuste o índice da linha para dois, altere o texto para semente mnemônica. Agora vamos adicionar um ID Fx de velocidade mnemônica à área de texto. Agora, vamos executar nosso aplicativo e ver o que acontece. Primeiro, reconstrua o projeto e clique em Spring Boot run. Ótimo. Mas quando clicamos em Criar, nada acontece. Também devemos lidar com o encerramento do nosso diálogo. Por enquanto, clique em parar. O posicionamento desses campos está me incomodando um pouco. Vamos consertar isso. Clique no botão Texto. Incluímos o painel de grade dentro da tag de cabeçalho da janela de diálogo. O local correto para incluí-lo é na tag de conteúdo. Vamos mudar isso. Vamos verificar sua aparência agora no Scene Builder. Ótimo, agora parece muito melhor. No próximo vídeo, continuaremos implementando o recurso de criação de carteira. vejo. 12. 10 Criar nossa primeira carteira parte 3 skillshare 2: Neste vídeo, continuaremos implementando o recurso de criação de carteira e, finalmente, faremos nosso primeiro teste de GUI. Para fazer isso, vamos adicionar uma dependência ao projeto. Adicionaremos Bitcoin, Java e uma biblioteca de código aberto criada exclusivamente para este curso. Essa biblioteca contém muitos utilitários relacionados ao Bitcoin, como métodos para gerar sementes mnemônicas aleatórias, criar transações e muito mais. Para o funcionamento correto desta biblioteca, devemos adicionar uma meta de plug-in que copiará o arquivo ( lista de palavras) dot (TXT) do Bitcoin Java para o projeto durante a fase de compilação dos aplicativos. processo de construção. O Wordless dot TXT contém todas as palavras válidas para geração de sementes mnemônicas. Agora abra o ponto de diálogo de criação de carteira FXML. Mude para a exibição de texto. Adicionaremos um controlador a esse FXML para adicionar uma ação ao botão Criar. Então, vamos adicionar o atributo do controlador FX à tag de problemas do diálogo. O nome do controlador será criado como controlador de diálogo da carteira e o adicionaremos ao pacote de controladores. Como acontece com todo controlador, adicionará a anotação do componente a ele. Vamos criar a propriedade de semente mnemônica neste controlador. No FXML, adicionaremos uma ação ao botão Criar. Vamos adicioná-lo aqui. Vamos nomear a ação como criar uma semente mnemônica. E nós o criaremos no controlador correspondente. Assim, quando o usuário clicar no botão Criar, esse método será chamado e a área de texto mostrará uma semente mnemônica aleatória. Portanto, definiremos os textos de sementes mnemônicas como o resultado do método de criação que o serviço de sementes mnemônicas criará a seguir. Vamos injetar o serviço de sementes mnemônicas nessa classe. Agora, vamos criar a classe de serviço de semente mnemônica dentro do novo pacote chamado api dot services dentro do pacote BYOD W. Basicamente, todas as classes de negócios não relacionadas à interface gráfica do usuário serão colocadas dentro do pacote da API. Vamos adicionar o método de criação ao serviço de sementes mnemônicas. Adicione a anotação de serviço a essa classe. finalidade é idêntica à anotação do componente, mas é mais adequada às classes de serviço. Agora, vamos inicializar a propriedade do serviço de semente mnemônica no construtor create wallet. Agora, vamos implementar esse método porque estamos usando o TDD para criar nosso aplicativo. Primeiro, criaremos um teste unitário para essa classe. Vamos criar um pacote de API dentro da pasta de teste. Dentro dela, crie uma classe bacana chamada teste mnemônico de serviço de sementes. Como teste unitário, essa classe só precisa estender a classe de especificação de Spock. Agora, criaremos um teste chamado deve retornar uma semente mnemônica aleatória. E esperamos que o serviço de sementes mnemônicas retorne um valor não nulo. Vamos instanciar o serviço de sementes mnemônicas aqui. Vamos fazer esse teste para verificar o que acontece. Falhou conforme o esperado. Vamos implementar esse método. Para fazer isso, usaremos o método generate random da classe mnemônica de geradores de sementes do Bitcoin Java. Devemos passar o número de bits das entropias que queremos que a semente mnemônica tenha como argumento para esse método, que usaremos para 56. Lembre-se de que uma entropia de 256 bits gera uma semente mnemônica de 24 palavras. Por fim, chamaremos o método get sentenced no retorno desse método e retornaremos o resultado. Como acontece com todo trabalho, uma exceção verificada, também precisamos adicionar a frase lança FileNotFoundException à assinatura do método de criação. Precisamos fazer o mesmo com o método de criação de sementes mnemônicas no controlador de diálogo de criação de carteira. Vamos fazer esse teste novamente. Ótimo, o teste foi aprovado. Agora vamos verificar o que acontece quando executamos nosso aplicativo. Opa, e ocorreu um erro. Oh, é sobrescrito por um W maiúsculo nesta tag. Essa etiqueta de ID de grupo também está errada. Na verdade, é apenas o ensino do hífen do Bitcoin. Vamos executar nosso aplicativo novamente. Ótimo. Geramos com sucesso uma semente mnemônica, mas eu quero que seu texto seja embrulhado. Vamos consertar isso. Vamos para a caixa de diálogo de criação de carteira dot FXML. No Scene Builder, clique na área de texto e clique na caixa de seleção The Wrap Text. Vamos executar o projeto novamente. Ok, muito melhor. Agora, vamos fazer todos os nossos testes. Ótimo. Todos eles passaram. 13. 11 Criar nossa primeira carteira parte 4 skillshare 2: Neste vídeo, desenvolveremos ainda mais nosso recurso de criação de carteira de aplicativos. Adicionará um botão OK e um botão de cancelamento à caixa de diálogo de criação de carteira. Quando o usuário clicar no botão OK, sua carteira será criada e o nome da carteira aparecerá na parte superior da tela. Quando ele clica no botão Cancelar, a caixa de diálogo simplesmente fecha. Também adicionaremos uma restrição ao botão OK para que ele seja desativado por padrão e ativado somente quando o nome e os campos de sementes mnemônicos forem preenchidos. Por fim, adicionaremos um campo de senha opcional para que o usuário só possa acessar sua carteira e fazer transações com ela depois de fornecer a senha correta. Vamos adicionar esses novos recursos primeiro em nosso teste de criação de carteira. Primeiro, adicionaremos um clique na ação do botão OK. Então, esperamos que o título do palco seja igual ao nome do nosso aplicativo, traçado com o nome da nossa carteira, que é minha carteira de teste. Agora vamos criar a propriedade do palco. Vamos inicializá-lo no método start. Agora, vamos criar outro teste para verificar o que acontece quando o usuário tenta clicar no botão Cancelar. Para isso, criaremos um teste com o nome deve cancelar a criação da carteira. Portanto, esperamos que, quando o usuário clicar em uma nova carteira e cancelar, nenhuma exceção seja lançada. Vamos fazer esses testes para ver o que acontece. Os testes falharam conforme o esperado. Vamos implementar esses recursos. Vá para o arquivo FXML de pontos da caixa de diálogo de criação de carteira. Clique no painel de diálogo no lado esquerdo. Em seguida, adicione um botão OK e esse campo de tipos de botão. Clique em mais e, em seguida, adicione um botão de cancelamento. Agora, adicionaremos o campo de senha. Mas primeiro, vamos adicionar outra linha no painel da grade. Agora vamos mover o nome, o rótulo e o campo para a primeira linha. Em seguida, adicionaremos um rótulo senha e um campo de senha na próxima linha. Vamos também adicionar uma ideia de senha Fx ao campo de senha. Agora, vamos mudar o texto do cabeçalho do diálogo para o seguinte. Já que estamos nisso, vamos tornar o campo de semente mnemônico não editável. Essa é uma medida de segurança porque não queremos que o usuário altere sua semente mnemônica acidentalmente. Mude para a exibição de texto. Adicionaremos algumas alterações nesses botões, etiquetas no botão OK, adicionaremos uma ideia Fx de ok. O botão Cancelar apagará seu conteúdo e adicionará uma ideia de cancelamento do Fx. Também adicionaremos o valor de cancelado próximo aos dados do botão Atributo. Também adicionaremos a string de cancelamento ao atributo text. Isso é necessário porque, quando usamos o botão de cancelamento padrão, texto é traduzido para o idioma do computador, e não queremos isso. Agora, vamos fazer algumas alterações no controlador de criação de diálogo. Adicionará um método chamado initialize a ele. Mas primeiro, vamos voltar ao FXML e adicionar um ID Fx da dor de diálogo à tag de dor do diálogo. Agora, vamos adicionar as propriedades com um ID FX ao controlador. Fará isso com a senha de propriedades denominada dialog pain, OK e Cancel. Agora, de volta ao método inicializado. Esse método será executado após a inicialização do diálogo. Incluirá um código para definir as ações de cada botão. Primeiro, definiremos a ação do botão Cancelar. Quando um usuário clica nele, o diálogo se oculta. Então, chamaremos o Método do Botão de Pesquisa do diálogo, passando o botão de cancelamento como argumento. Em seguida, adicionaremos um manipulador de eventos a ele, passando o argumento da ação e um retorno de chamada que chamará o método hide da janela de dores de diálogo. Faremos o mesmo com o botão OK. Mas, em vez disso, chamaremos o método create wallet no retorno de chamada. Vamos incluir o mesmo código para ocultar a janela durante o método de criação de carteira por enquanto e executar o aplicativo para ver o que acontece. Quando clicamos no botão Cancelar, a caixa de diálogo se esconde. O mesmo acontece quando clicamos no botão OK. Bom. Mas quando clicamos no X ao lado do diálogo, nada acontece. Vamos corrigir isso. Vá para o controlador da janela principal. Será necessário incluir o código a seguir para fechar a janela de diálogo quando clicarmos no botão X. Agora, vamos executar o aplicativo e tentar novamente. Bom, isso resolveu tudo. Vamos também mudar o método de exibição e espera usado no diálogo para simplesmente mostrar que isso simplifica um pouco as coisas. Agora, execute o aplicativo novamente. Tudo continua funcionando conforme o esperado. Mas há outro problema com o diálogo. Permite a criação de carteiras sem nome e sem semente mnemônica. Queremos que cada carteira tenha um nome e uma semente mnemônica. Portanto, precisamos desativar o botão OK se um não for preenchido. Vamos corrigir isso. Acesse o controlador de diálogo de criação de carteira. Agora, criaremos uma propriedade privada do tipo vinculação booleana chamada todas as entradas necessárias estão cheias. Definiremos essa propriedade no método inicializado com o código a seguir. Aqui, usaremos uma classe Java anônima que estende a vinculação booleana. Em seguida, inicializaremos a classe com o método bind, passando o nome e as propriedades mnemônicas do texto inicial como argumentos. Em seguida, no método de valor computacional incluirá um código que retornará verdadeiro somente se o nome e campos de semente mnemônica não estiverem vazios. Agora, criaremos um método getter para essa propriedade. Por fim, chamaremos o método de propriedade desativado no botão OK. Em seguida, chamaremos bind no resultado e passaremos o método get all required inputs are all required inputs are full chamando o método nele. Vamos fazer uma pequena correção nesse método primeiro, ele deve retornar uma associação booleana. E vamos remover isso, ir atrás dele. Bom. Agora vamos executar nosso aplicativo novamente. Ok, o botão OK está desativado por padrão. Se digitarmos algo no campo do nome da carteira, ele permanecerá desativado. Mas quando clicamos no botão Criar, ele é ativado. Ótimo. Vamos fazer nossos testes novamente. Isso deve ter falhado no teste de criação da carteira porque ainda não implementamos o código para alterar o título do aplicativo. Vamos fazer isso no próximo vídeo. 14. 12 Criar nossa primeira carteira parte 5 skillshare 2: Neste vídeo, implementaremos um recurso que fará com que o aplicativo carregue a carteira e mostre seu nome no título do aplicativo. Depois que o usuário cria, a carteira. Criará um código que será útil posteriormente, quando quisermos mostrar recursos de outras carteiras, como endereços, na tela. Depois de implementarmos esse recurso, esse teste será aprovado porque o título do estágio será igual ao espaço da carteira BYOD W, espaço no painel e nome da carteira. Então, vamos implementá-lo. Primeiro. Vamos até o controlador de criação de carteira. Em seguida, neste método, criará uma carteira usando um novo serviço chamado criar serviço de carteira e um método chamado criar. Passaremos o nome, a senha e a semente mnemônica da carteira para o método. Agora vamos criar a classe de carteira. Vamos adicionar um novo pacote dentro do BYOD W, chamá-lo de domínios. Dentro dele, adicionará um novo registro Java chamado wallet. Por enquanto, vamos apenas adicionar um atributo de string chamado nome a esse registro. Um registro Java é um recurso recente da linguagem. Cada atributo de registro tem um getter e um construtor integrados, então não precisamos adicioná-los. Agora, importe o registro da carteira para o controlador de diálogo de criação de carteira. Agora, injetaremos o serviço de criação de carteira nessa classe. E criaremos essa classe dentro do pacote de serviços da API. Adicionará a anotação do componente a essa classe. Vamos injetar esse serviço no construtor dessa classe. Agora, criaremos o método de criação dentro do serviço de criação de carteira. Por enquanto, retornaremos apenas uma nova carteira passando o nome como parâmetro para o controlador de diálogo Criar carteira. Agora que criamos, a carteira publicará um evento que usará a carteira criada como parâmetro. Esse evento será ouvido por uma classe para que, quando o usuário criar uma carteira, o ouvinte atualize a carteira atual carregada pelo aplicativo. Vamos injetar o contexto do aplicativo nessa classe. Agora, vamos criar o evento de carteira criado dentro do pacote de eventos. Em seguida, chamará o superconstrutor passando pelo controlador de diálogo de criação de carteira. E definiremos um novo campo de carteira, atribuindo o argumento do construtor da carteira a ele também incluirá um getter para esse campo. Agora, vamos criar um ouvinte para esse evento chamado created wallet listener. E vamos criá-lo dentro do pacote de ouvintes. Ele implementará a classe de ouvinte do aplicativo com o evento de carteira criado como parâmetro. Em seguida, implementará o método no evento do aplicativo. Ele chamará um método de um novo serviço chamado serviço de atualização de carteira atual. Esse método chamado atualização usa a carteira de eventos como um parâmetro. Vamos injetar esse novo serviço nessa classe e criar o serviço. Vamos adicioná-lo a um novo pacote de serviços. Dentro da embalagem pegajosa. Em seguida, criará o método de atualização nele. Também adicionaremos uma anotação de serviço a ela. Por enquanto, o método de atualização definirá apenas o nome da carteira atual com o nome da carteira recém-criada. Agora, vamos criar um novo pacote dentro do BYOD W chamado observáveis. Dentro deste pacote, criará a classe de carteira atual. Voltar ao serviço de carteira Update Current instanciará a carteira atual em seu construtor. Na classe de carteira atual incluirá a anotação do componente. Essa classe representará a carteira atual carregada pelo aplicativo. Cada alteração feita pelo aplicativo nessa instância de classe aparecerá na interface gráfica do usuário do aplicativo. Nós o incluímos em um pacote chamado observable, porque todas as propriedades dessa classe não serão observáveis. E observável é um tipo de objeto no qual cada mudança de estado pode ser ouvida executada por outros objetos. A primeira propriedade observável adicionaremos a ela é o nome. Ele terá o tipo de propriedade de string simples. Esse tipo implementa a interface observável e aciona um evento de alteração quando o valor da string muda. Vamos instanciá-lo aqui. E criaremos um getter para esse campo. A ideia Intellij identificou que é observável e criou dois getters. Uma para a propriedade chamada propriedade do nome e a outra para o valor da propriedade chamada getName também criarão um configurador para esse campo para definir o valor da propriedade do nome. Vamos tornar esse campo definitivo. Também farei um teste para essa classe de serviço de criação de carteira. Deveríamos ter criado o teste antes de implementar esse método, já que estamos usando o TDD. Mas considerando que incrementaremos funcionalidade desse método quando perdoada. Vamos criar o teste. Agora. Primeiro, criaremos uma propriedade para o serviço de criação de carteira e instanciaremos dentro do método de configuração que é executado antes de cada teste. Em seguida, criaremos um teste chamado should create wallet. Dado que temos um nome, uma senha e uma semente mnemônica. Quando chamamos o método create a partir do serviço create wallet com esses parâmetros. Então, esperaremos que o nome da carteira seja igual à variável de nome. Vamos fazer o teste. O teste foi aprovado. Agora, vamos recapitular o que fizemos até agora. Quando o usuário clica no botão OK, o método criar carteira do controlador de diálogo de criação de carteira será chamado e a carteira será criada pelo serviço de carteira. Para fazer isso, ele usa o método create, usando o nome, a senha e a semente mnemônica que o usuário escolheu. Por enquanto, esse método retorna apenas uma nova carteira com seu nome. Em seguida, passamos a carteira criada para um novo evento de carteira criada e publicamos esse evento. Quando isso acontecer, ele acionará o método de ouvinte de carteira criado no evento do aplicativo. Ele receberá o evento da carteira criada como parâmetro. Devemos adicionar a anotação do componente a essa classe e injetar o serviço de atualização atual da carteira em seu construtor. Portanto, o método de evento do aplicativo chamará o método de atualização do serviço de atualização da carteira atual, passando a carteira do evento como seu parâmetro. Finalmente, o método de atualização. Definiremos o nome da carteira atual com o nome da carteira recém-criada. Agora, vamos voltar ao controlador da janela principal. Aqui, criará um método inicializado que será executado antes que a janela principal do aplicativo apareça. Dentro dela, adicionará um ouvinte à propriedade atual da carteira. Vamos injetar a carteira atual nessa classe primeiro. Dentro do método ad listener, passará um retorno de chamada que usará três parâmetros e um valor observável e antigo, e um novo valor no corpo do retorno obterá o estágio do Windows e atribua-o à variável de estágio. Devemos lançar seu tipo para o palco. Em seguida, definiremos seu título como BYOD W wallet space, dash space, new value. A nova variável de valor contém o novo valor do nome da carteira atual. Sempre que o nome da carteira atual mudar, essa alteração será ouvida por esse retorno de chamada e o título do palco também mudará para a frase que acabamos de dizer. Vamos executar o aplicativo para verificar se isso funciona. Criaremos uma nova carteira com o teste de nome, depois uma semente mnemônica e clicaremos em “ Ok, ótimo, funcionou”. A mudança do título da janela para BYU OWL é um teste de traço. Vamos criar outra carteira com um nome diferente para ver o que acontece. Como esperado. Ele foi alterado para corresponder à carteira recém-criada. Agora, vamos fazer todos os nossos testes. Ótimo. Todos os testes foram aprovados. Bom trabalho. 15. 13 Criar nossa primeira carteira parte 6 skillshare 2: Neste vídeo, começaremos a implementar um recurso que nos permitirá criar endereços que serão usados posteriormente para receber Bitcoins. A primeira coisa que faremos é criar a guia Receber. Essa guia conterá os endereços derivados de nossa carteira. Então vá para o arquivo FXML da janela principal. No Scene Builder incluirá uma caixa V no centro do painel de borda. Dentro da caixa V incluirá um painel de abas. Excluirá a segunda guia que foi criada automaticamente. Altere o texto das guias restantes para receber. Dentro do menu de configuração do VBox definirá a altura pref para 300. Dentro da guia Receber incluirá um painel de grade. Por alguma razão, não podemos incluir um painel de grade em uma guia usando o Scene Builder. Não tem problema. Faremos isso usando o editor de texto. Em vez disso. Incluiremos um rótulo. Seu texto será igual ao endereço de recebimento. Dentro, ele adicionará algumas tags para definir suas margens. Agora, incluiremos um campo de texto. Não será editável. Ele terá 350, conforme sua largura preferida. E seu índice de coluna será igual a um, incluirá as mesmas tags de margem do painel de grade que usamos anteriormente. O Construtor de cenas não está mais funcionando devido ao painel de grade que incluímos na guia. Não tem problema. Veremos a aparência do aplicativo ao executá-lo. Ótimo, nossa carteira agora está pronta para receber um endereço nesse novo campo que acabamos de criar. Dentro do teste de criação de carteira, incluirá um código para verificar se um endereço foi criado e inserido no campo de endereço de recebimento após a criação da carteira. Então, depois que o teste clicar no botão OK, ele clicará na guia Receber. E o teste pesquisará o conteúdo do campo de endereço de recebimento e armazenará na variável de endereço. Em seguida, o teste afirmará que, se o endereço não for conhecido, vamos fazer o teste para ver o que acontece. O teste falhou conforme o esperado. Agora, vamos fazer uma refatoração e o arquivo FXML da janela principal. Vemos agora que nosso arquivo FXML principal está ficando maior É melhor criar um novo arquivo FXML somente para a guia de recebimento, qual a janela principal se referirá posteriormente. Então, vamos criá-lo. Vamos chamá-la de guia Receber ponto FXML copiará todo o conteúdo da guia para a guia Receber ponto FXML. A única alteração que faremos é na tag da guia. Vamos mudá-lo para f x cólon root. Em seguida, usaremos a classe tab como atributo de tipo. Também precisamos incluir o atributo Meta XML e S colon FX. Agora vamos importar as outras tags. De volta à janela principal, o ponto FXML excluirá a tag da guia e todo o seu conteúdo. Incluirá a tag Receive tab controller, que será criada agora. Vamos criá-lo dentro do pacote de controladores. E vamos importá-lo dentro do ponto FXML da janela principal. Voltar à guia Receber, o controlador adicionará a anotação do componente a essa classe. Criaremos um construtor passando um recurso com uma anotação de valor apontando para a guia Receber. O arquivo FXML também passará o contexto do aplicativo. Aqui, configuraremos uma nova instância do carregador FXML com parâmetros semelhantes aos que usamos para os outros controladores. Em seguida, configuraremos seu controlador para isso. Também definiremos seu caminho para isso. Em seguida, chamaremos o método de carregamento nele. Ok, precisamos fazer mais uma coisa para que funcione. Dentro da classe gooey started listener, adicione o código a seguir aqui. Esse código é necessário para informar ao Java FX como criar componentes personalizados, como o controlador da guia Receber, quando ele vê dentro dos arquivos FXML. Esse código fará com que o Java FX use o contexto para obter o método bean para criar um componente ao ver uma tag controladora da guia Receive. Portanto, sempre que o Java FX precisar criar uma tag controladora da guia Receive, ele usará a classe do controlador da guia Receive para criá-la. Para outras tags, ele usará o construtor Java FX padrão. É isso mesmo. Agora, o Java FX sabe como criar nossa nova tag FXML personalizada. Vamos executar nosso aplicativo para verificar se tudo está indo bem. ***** e ocorreu um erro. Está dizendo que o controlador raiz não é uma instância de guia. Eu sei como consertar isso. Devemos fazer com que o controlador da guia Receber estenda a classe TAP. Agora, vamos ver se funciona. Ok, está funcionando exatamente como antes. Portanto, quando criamos uma nova carteira, esperamos que o campo do endereço de recebimento seja preenchido com o novo endereço Bitcoin. Nos próximos vídeos, entenderemos o processo de derivação de um endereço Bitcoin e implementaremos esse recurso em nossa carteira. Veja, sim. 16. Endereços Bitcoin e carteiras HD: Neste vídeo, aprenderemos sobre carteiras HD e endereços Bitcoin. Então, o que é um endereço Bitcoin? Um endereço bitcoin é uma palavra que codifica uma chave pública, o hash de uma chave pública ou um hash de script. Ele é usado para receber bitcoins em uma transação. Para receber Bitcoins por meio de uma transação de Bitcoin, você mostra seu endereço para outra pessoa que essa pessoa possa enviar bitcoins para o seu endereço. Existem vários tipos de endereços Bitcoin e as regras para gerá-los estão em muitos VIPs, como VIP, VIP 3d2 e BIP 44. Agora vamos falar sobre carteiras HD. As carteiras Hd representam carteiras determinísticas hierárquicas. Eles são hierárquicos porque são compostos de vários níveis de chaves e determinísticos porque uma única semente sempre gerará os mesmos endereços e chaves privadas. E a carteira HD é um tipo de carteira em que, a partir de uma única semente, os blocos de derivação são usados para derivar chaves privadas, chaves públicas e endereços. As especificações das carteiras Hd foram originalmente definidas no BI P32 com outros BIPs estendendo essa especificação. Agora vamos recapitular um slide da nossa última apresentação de ppt. Nesta apresentação, aprendemos como gerar uma semente mnemônica. E mencionamos que combinando uma semente mnemônica com uma frase secreta opcional, poderíamos gerar uma semente raiz usando o algoritmo P vk df two. A partir dessa raiz, poderíamos gerar chaves privadas, chaves públicas e endereços. Nesta apresentação, aprofundaremos os detalhes dessa última parte sobre como chaves e endereços privados e públicos são gerados a partir de uma semente raiz. Então, começando com uma semente raiz, que tem 512 bits de tamanho, aplicando o algoritmo de hash HMAC SHA-512 a ela, obtemos a chave mestra, que também tem 512 bits da chave mestra. Ao aplicar a função CKD, que significa derivação de chave secundária, podemos obter diferentes chaves estendidas usando índices diferentes como parâmetros. Se n for o índice dessa função, então n pode variar de 0 a 2 à potência de 32 menos um. Cada chave estendida pode gerar mais chaves estendidas usando a função CKD e, portanto, ser a mãe de muitas chaves secundárias. Esse esquema de derivação permite a formação de uma árvore de chaves com um número indefinido de gerações. Vamos ver mais detalhes sobre as funções do CKD. Há dois tipos de chaves estendidas. Elas podem ser chaves privadas estendidas ou chaves públicas estendidas. E a chave privada estendida cuja versão serializada começa com x PRV, ou outra letra mais PRV é gerada usando a função privada CKD. Se o índice passado para essa função for igual ou maior que dois elevado a 31, então é uma derivação endurecida. E disse que a chave privada estendida gerada é uma criança endurecida. As chaves reforçadas têm recursos de segurança adicionais que explicaremos em resumo é possível gerar uma chave pública estendida usando a função pública CKD. Chaves públicas atendidas, quando serializadas, começam com x pub ou outra letra mais pub. Também é possível gerar uma chave pública estendida a partir de outra chave pública estendida usando a função pública CKD Duas derivações não são possíveis. Gerar uma chave privada estendida a partir de uma chave pública estendida e uma chave pública estendida reforçada a partir de uma chave pública estendida. Então, como passamos de chaves estendidas para endereços? Começando com uma chave privada estendida, extraímos uma chave privada dela. Uma chave privada faz parte de uma chave privada estendida. Portanto, essa extração é uma operação simples. Então, por meio de uma operação chamada multiplicação de curva elíptica, geramos uma chave pública a partir de uma chave privada. Finalmente, ao fazer o hash e codificar a chave pública, obtemos um endereço Bitcoin. Existem diferentes tipos de hash e codificação de chaves públicas para produzir diferentes tipos de endereços. Aprenderemos mais sobre essas operações nos próximos vídeos. Também usamos chaves privadas para produzir assinaturas de transações transferir Bitcoins para outros endereços. As assinaturas de transações são produzidas usando o algoritmo de assinatura digital Elliptic Curve ou ECDSA. Você também pode gerar endereços com uma chave pública estendida. Você faz isso extraindo a chave pública dela. Em seguida, um endereço bitcoin é gerado a partir da chave pública por meio de hash e codificação, conforme explicado anteriormente. Lembre-se de que uma chave pública não pode ser convertida em uma chave privada. Portanto, ele não pode ser usado para assinar transações e transferir Bitcoins. Agora, vamos entender o conceito de caminhos de derivação, começando com a chave mestra, que tem a profundidade de zero em uma árvore de chaves estendidas. Ao derivar uma chave estendida passando zero como argumento para uma função CKD, obtemos uma chave estendida com uma profundidade de um. Repetindo o processo com a chave estendida recém-gerada, obtemos uma chave estendida com uma profundidade de dois. Em seguida, podemos repetir o processo, passando um como índice e obtendo uma chave estendida com uma profundidade de três. Dessa última chave estendida, podemos extrair uma chave pública e um endereço. Diz-se que esse endereço tem um caminho de derivação de zero barra zero barra um porque, nesse caso, o índice é usado para derivar a chave estendida que gerou esse endereço. Aplicando o mesmo raciocínio. Neste outro exemplo, obtemos um endereço com um caminho de derivação de uma barra zero barra dois. Este outro exemplo mostra que você pode usar outros números como índices para funções CKD em qualquer chave estendida em uma árvore de chaves, permitindo a geração de um número quase infinito de caminhos e endereços de derivação. Este outro exemplo mostra a geração de um filho endurecido usando uma única aspa após o índice Podemos representar índices que geram filhos endurecidos em um caminho de derivação. Zero seguido por uma única aspa representa o primeiro índice endurecido, que é dois elevado a 3011, seguido por uma única aspa é o segundo índice de endurecimento e assim por diante. Essa notação é usada para facilitar a descrição de um caminho de derivação para que possamos usar números pequenos para descrevê-lo. É importante acrescentar isso. Para gastar Bitcoins de um endereço, é necessário produzir uma chave privada com o mesmo caminho de derivação usado para derivar esse endereço. Assim, você pode usar as funções públicas do CKD para produzir chaves e endereços públicos estendidos. Mas, para gastar fundos com esses endereços, você deve usar as funções privadas do CKD para produzir chaves privadas e chaves privadas estendidas. Outra característica das carteiras HD e de seus caminhos de derivação é sua relação com a função de morte. Cada nível em uma árvore de teclas recebe uma função. Bi P32 define a profundidade, um representa a profundidade das contas duas cadeias diferentes, e a profundidade, três endereços diferentes. O Bip 44 veio com diferentes definições que são mais usadas hoje em dia na maioria das carteiras HD. De acordo com uma profundidade de 44, uma tecla estendida endurecida representa propósitos diferentes. Chaves de profundidade para endurecer diferentes tipos de moedas, três chaves reforçadas de profundidade, contas diferentes. profundidade para define se os endereços descendentes devem ser usados para alteração não são booleanos e a morte cinco representa endereços diferentes. Para entender melhor como isso funciona na prática, vamos ver alguns exemplos de caminhos de derivação e suas funções. E abordado com um caminho de derivação de 84 aspas barra barra zero barra zero barra zero tem o propósito de encontrar um BIP A14. Vip 84 define que os endereços com uma finalidade de 84 devem ser endereços P2 WP k h, que significa pagar para testemunhar endereços hash de chave pública. Falaremos sobre diferentes tipos de endereços detalhadamente nos próximos vídeos. Mas, em resumo, P2, WP k, h, também conhecido como segue, os endereços nativos são o tipo de endereço mais comum nas carteiras modernas mais atualizadas. Esse endereço também tem um tipo de moeda com cotação zero, o que significa que é um endereço Bitcoin. Ele também tem uma conta zero, o que significa que faz parte da conta do primeiro usuário. Mudou. O índice está definido como zero, o que significa que não é um endereço de alteração. Finalmente, seu índice de endereço é zero, o que significa que é o primeiro usuário a receber endereço. O próximo exemplo tem um caminho de derivação semelhante ao exemplo anterior, exceto que seu índice de endereço é um. Portanto, é o segundo endereço de recebimento nativo Bitcoin segue da primeira conta do usuário, aplicando o mesmo raciocínio. O terceiro exemplo é o primeiro endereço de mudança nativo Bitcoin segue da primeira conta do usuário. O índice um em profundidade quatro indica que é um endereço de mudança. O último exemplo é semelhante ao primeiro, exceto que seu propósito é 49 sem aspas. Vip 49 define que os endereços com essa finalidade devem ser P2 WP k-th aninhados em endereços SSH P2. Se isso parecer complicado, não se preocupe, aprenderemos detalhes sobre isso nos próximos vídeos. Agora, vamos fazer uma visão geral dos recursos do HD Wallet. Com carteiras HD, podemos gerar facilmente um número quase infinito de endereços a partir de uma única semente. Isso é ótimo, pois podemos evitar reutilização de endereços e a perda de privacidade. As carteiras HD também permitem uma estrutura de várias contas, na qual a chave privada estendida dos pais tem acesso aos principais fundos de seus filhos, mas os filhos podem transferir os fundos dos pais. Esse esquema pode ser útil casos como proprietários de empresas que têm acesso às chaves infantis dos departamentos da empresa. Outro recurso útil que as carteiras HD permitem é a criação de carteiras somente para relógios cujos endereços podem ser gerados e seus fundos auditados usando apenas chaves públicas estendidas, mas onde nenhum fundo pode. ser movido , pois nenhuma transação pode ser assinada. Outro recurso do HD Wallet é a possibilidade de gerar outros endereços de criptomoedas a partir da mesma semente mnemônica. Uma lista de diferentes índices de tipos de moedas é descrita no slip 44, um sistema de proposta semelhante ao BIP da Satoshi labs, a empresa responsável pela treliça ou carteira. Outro recurso das carteiras HD é que seus endereços e chaves privadas podem ser reconstruídos com suas sementes e caminhos de derivação. Isso permite que você importe uma semente mnemônica e uma senha em uma carteira compatível para recuperar todos os seus endereços e chaves privadas. A compartimentação de segurança é outro recurso interessante das carteiras HD. Se uma chave privada estendida vazar por acidente, isso afetaria apenas os fundos bloqueados nos endereços descendentes da chave vazada. Os fundos trancados nas chaves dos pais ou irmãos estariam seguros. Finalmente, as carteiras HD facilitam a geração e a organização de diferentes tipos de endereços Bitcoin. Agora vamos ver por que chaves reforçadas são necessárias. Durante o desenvolvimento do HD Wallet, descobriu-se que se uma chave pública estendida e uma chave privada secundária não Hodgkin do próximo nível vazassem, isso equivaleria a vazar chave privada estendida aparente. Isso pode levar à perda de fundos para cada endereço descendente da chave pública estendida que vazou. Portanto, a derivação do perdão foi criada para evitar que essa exploração aconteça em uma conta e em profundidades mais baixas. Por fim, vamos discutir como implementaremos o esquema de derivação de endereços em nossa carteira. Usaremos o caminho de derivação 84 aspas barra barra zero barra zero para gerar nosso primeiro endereço de recebimento. Depois de receber Bitcoins, o próximo endereço de recebimento será alterado aumentando o índice de endereços em um. Portanto, os próximos endereços de recebimento terão índices de endereço de 123 e assim por diante. Isso nos impede de usar o mesmo endereço para receber Bitcoins mais de uma vez. Usaremos o caminho de derivação 84 aspas barra, barra, barra, barra, uma barra zero para gerar nosso primeiro endereço de alteração. Depois de enviar Bitcoins e receber uma alteração, o endereço da próxima alteração é alterado aumentando o índice de endereços em um. Da mesma forma que faremos para receber endereços. Você pode perguntar por que evitar a reutilização de endereços é importante por dois motivos principais. Primeiro, ao fazer isso, aumentamos nossa privacidade. Ao fazer isso, se um terceiro descobrir que um endereço pertence a nós, essas informações não serão replicadas em outros endereços que usamos. O outro motivo é a segurança. Se, por algum motivo, a chave privada um endereço vazar, isso afetará somente esse endereço. O provérbio que diz: não coloque todos os ovos na mesma cesta se aplica aqui. Dito isso, implementaremos o esquema de derivação gerando primeiro a chave pública estendida com um caminho igual a 84 aspas, barra zero, barra zero, barra zero, para receber endereços. E a chave pública estendida com um caminho igual a 84 aspas barra barra zero barra um para alterar endereços. Em seguida, obteremos chaves públicas e endereços estendidos para seus filhos . Ao fazer isso, gerará todos os endereços de que precisamos sem expor nenhuma chave privada à memória. Portanto, nossa principal política de segurança é evitar a exposição de sementes e chaves privadas à memória, tanto quanto possível. Nossas chaves privadas serão derivadas somente ao assinar transações usando os mesmos blocos de derivação usados para produzir os endereços dos quais essas transações estão gastando Bitcoins. 17. 15 Criar nossa primeira carteira parte 7 skillshare 2: Neste vídeo, criaremos as chaves públicas estendidas que carteira precisará para criar endereços. Como vimos no vídeo mais recente, nossas carteiras inicialmente precisarão de chaves estendidas, que serão a chave estendida para endereços de recebimento de segmentos e a chave estendida para endereços de mudança seguinte. Primeiro, vamos corrigir alguns problemas com nossos testes de GUI. Se você tentar executar o teste de criação de carteira, agora você verá que ele funcionará. Isso se deve em parte a uma instanciação prematura de nossa nova classe de controlador da guia Receber. Para corrigir isso, crie um novo pacote chamado Config dentro do pacote de teste BYOD W. Em seguida, crie uma nova classe chamada test lazy, que contém uma configuração IP. Essa classe implementará o Bean Factory. O pós-processador implementará esse método necessário com esse código. Esse código fará com que todas as classes durante os testes sejam inicializadas lentamente. Há outro código que devemos adicionar em nosso teste de criação de carteira para que ele funcione. Adicionaremos ao carregador FXML no método start, a mesma fábrica de construtores que definimos em nossa classe de ouvinte iniciada pela GUI. Agora vamos executar nossos testes de GUI. Ótimo. Agora os testes estão funcionando. Vemos que somente eles deveriam cancelar os testes aprovados e nos outros ainda temos que fazer com que sejam aprovados. Agora, vamos continuar adicionando as chaves públicas estendidas à nossa carteira. A primeira coisa que faremos é ajustar nosso teste de serviço de criação de carteira passar por uma semente mnemônica válida para essa variável. Você pode obtê-lo na página Projeto e Recursos. Em seguida, verificaremos se a carteira criada tem chaves públicas estendidas. Afirmará se tem duas chaves públicas estendidas, já que cada carteira terá uma chave pública estendida para receber endereços e uma chave pública estendida para alterar endereços. Agora, adicionaremos uma lista de chaves públicas estendidas ao registro da carteira. Vamos criar nossa classe estendida de chaves de pub. Ele terá uma chave e um tipo. Vamos adicioná-los a um construtor. Ambas as propriedades terão um getter. Agora, criaremos uma classe de configuração de endereço. Primeiro, vamos criar um novo pacote de configuração dentro do pacote da API. Em seguida, criaremos a classe de configuração de endereço nela. Adicione a anotação de configuração a ela. Essa anotação é necessária para que o Spring Boot inicialize todos os objetos definidos nessa classe durante a inicialização do aplicativo. Agora, criaremos uma classe de domínio chamada configuração de endereço. Na verdade, será um recorde. Ele terá um tipo de endereço e o caminho de derivação. Em seguida, crie uma enumeração chamada tipo de endereço no mesmo pacote. Ele terá dois tipos, segmentar e seguir com alteração de sublinhado. Agora, de volta à classe de configuração de endereço. Criaremos um feixe para o endereço do nosso segmento. No Spring Boot, um bean é apenas um objeto que pode ser injetado em outras classes de projeto. Instanciará esse bean com esses parâmetros. E adicione a anotação Bean a esse método. Passar a string do segmento como seu parâmetro duplicará esse método e o modificará para ser nossa configuração de endereço de alteração Altere o parâmetro de anotação do Bean para seguir a alteração. O nome do método será segue change config. O tipo de endereço será definido como mudaria. E o caminho de derivação terá um índice de mudança de um. Agora, usaremos essas configurações em nosso serviço de criação de carteira. Então, vamos injetar uma lista de configurações de endereço nessa classe. Ao fazer isso, o Spring Boot identifica automaticamente que há dois beans com o tipo de configuração de endereço e injetará ambos nessa lista. Agora, no método create criará uma variável de semente mnemônica. Primeiro, alteraremos o parâmetro do método de semente mnemônica para a sequência de sementes mnemônicas e, em seguida, instanciaremos um objeto de semente mnemônica passando a string de semente mnemônica como seu parâmetro. Em seguida, criaremos uma chave mestra, que é um tipo de chave privada estendida. Para fazer isso, chamaremos o método de semente mnemônica para a chave mestra e passaremos a senha e essa constante como seus parâmetros. Mas primeiro, precisamos atualizar nossa versão Bitcoin Java para 0,3, 0,0 no arquivo POM. Vamos fazer isso. Agora. Clique em Carregar as alterações do Maven de volta para o método de criação. Agora, ele nos permite importar a constante principal do prefixo de rede passará seu prefixo privado como parâmetro. Agora vamos adicionar esse código e, em seguida, explicarei o que ele faz a seguir. Esse código começa a converter a lista de configuração de endereços em um fluxo. Em Java oito ou superior, os fluxos são usados para aplicar operações funcionais a uma coleção de dados. Nesse caso, cada configuração de endereço da lista está sendo passada para essa função lambda, que usará a chave pub estendida que o serviço de chave pub criará ao lado de retornar um objeto de chave pub estendida. Cada chave de pub estendida devolvida será coletada em uma lista que será armazenada na variável de chaves de pub estendidas e, em seguida, passará a lista de chaves de pub estendidas para a carteira devolvida. Agora, vamos injetar o serviço estendido de chaves de pub nessa classe. Teremos que criá-lo. Agora podemos adicioná-lo ao construtor. Agora criará seu método de criação. Ele retornará uma chave de pub estendida. Seguindo o TDD. É hora de criar um teste para esse método. Vamos fazer isso. Irá criá-lo dentro do pacote da API de teste. Ele deve estender a classe de especificação. Vamos instanciar o serviço estendido de chaves de pub aqui. Também precisamos adicionar esse trecho de código ao método de configuração. E criaremos um teste chamado should create extended key. Quando recebe uma semente mnemônica e uma chave mestra derivada dela. Quando chamamos o método create do serviço estendido de pub key. Então, esperamos que a chave de pub estendida criada seja igual à chave de pub estendida esperada. Ok, então como vamos criar essas variáveis em cinza? Vamos passá-los usando a cláusula where como esta. Você pode perguntar: onde consegui esses valores? Eu os comprei no site de treonina EN Coleman io slash pip. Este site é muito útil para gerar muitos tipos de chaves e endereços estendidos. Vou copiar e colar essa semente mnemônica no campo BIP 39 do site para demonstrar como ela funciona. Imediatamente após colarmos a semente mnemônica, a ferramenta calculou a chave mestra da semente raiz e as chaves estendidas para mostrar o BIP AT derivado para chaves estendidas, clique nesta guia. Vemos que a chave de pub esperada e o teste são iguais a esse valor no site. Ao aplicar a função CKD a essa chave pública estendida com números diferentes, pois os índices obterão posteriormente chaves públicas estendidas, cujas chaves públicas extraídas serão usadas para gerar recebendo endereços usando o mesmo site que criei para mais casos de teste. Vou colá-los aqui e ajustar a formatação. Os dois últimos casos de teste gerarão chaves de pub estendidas que serão usadas para gerar endereços de alteração. Você pode copiá-los dos recursos deste vídeo ou criar seus próprios casos de teste usando o site de Ian Coleman. Usando a cláusula where, o mesmo teste será executado para cada parametrização que criamos. Vamos fazer o teste. O teste falhou conforme o esperado. Agora vamos implementar o método. Primeiro. Criaremos um mapa aqui que não abordará tipos de prefixos de chaves de pub estendidas. Ambos os tipos de endereço serão mapeados para o mesmo prefixo do segmento de rede principal. Ao fazer isso, facilitamos a extensão dessa funcionalidade se precisarmos adicionar mais tipos de endereçamento posteriormente. Agora, no método create retornará uma nova chave pub estendida. passagem desses parâmetros passará o retorno do método CKD da chave mestra, que seguirá um caminho de derivação. Falso, pois não é uma chave privada estendida e o prefixo do tipo de endereço. Em seguida, serializaremos o resultado. E o segundo argumento estendido da chave pub será o tipo de endereço e a forma da string. Por fim, não nos esqueçamos de adicionar a anotação do serviço aqui. Agora, vamos executar o teste estendido do serviço pub key novamente. Ótimo, todos eles passaram. Agora vamos executar nossos testes do serviço de criação de carteira. Mas primeiro, vamos fazer algumas mudanças nesse teste. Devemos adicionar o provedor de segurança, necessário para que as funções de criptografia Bitcoin Java funcionem. Também precisamos definir os argumentos corretos para o serviço. Vamos criar as configurações de endereço e o serviço estendido de chave pub. Agora vamos executá-lo. Ótimo, os testes foram aprovados. Isso significa que nossa carteira foi criada com uma lista de chaves públicas estendidas de tamanho dois. Opa, o índice de mudança aqui é um. Isso não afetará esse teste, pois estamos apenas afirmando que a carteira precisará estender as chaves do pub. Mas vamos mudá-lo para um por uma questão de correção. 18. 16 Criar nossa primeira carteira parte 8 skillshare 2: Neste vídeo, criaremos um vestido para cada chave de pub estendida que a Wallet fabrica. Para fazer isso, cada chave de pub estendida será passada para o método de vestidos gerado, que será criado agora. Esse método definirá uma lista de endereços para o registro estendido da chave pub. Vamos criar esse centro. Essa lista de endereços será criada por um novo serviço gerador sequencial de endereços que será criado. Ele usará um método de geração que usará a chave pub estendida e o tipo de chave pub estendida. O serviço gerador sequencial de endereços terá esse nome porque gerará vestidos com um índice crescente de derivação de endereços. Vamos injetar o gerador sequencial de endereços nessa classe e criá-lo. Agora, vamos criar seu método de geração que retornará uma lista de endereços. Vamos criar o registro de endereço. Esse registro terá um campo de endereço e um campo de índice. Vamos ajustar o método de definição de endereços a partir da tecla pub estendida. Ele pegará uma lista de endereços e definirá o campo estendido de endereços das chaves de pub. Vamos criar um teste para a classe geradora sequencial de endereços. Por enquanto, seu método retornará nulo. A classe de teste estenderá a classe de especificação. Criaremos um teste chamado deve gerar 20 endereços, usaremos o gerador sequencial de endereços no bloco de vento. Então, vamos adicioná-lo como um campo a essa classe. Quando o método generate é chamado com esses parâmetros, essa é uma chave pública estendida no tipo de segmento. Então, esperamos que a devolução dessa lista de vestidos tenha um tamanho de 20. Você pode copiar a chave pública estendida desse teste dos recursos desta lição. Vamos instanciar o gerador sequencial de endereços no método de configuração e executar o teste. Falhou conforme o esperado. Agora, vamos implementar que o serviço declarará uma chave de pub estendida. Em seguida, dentro de um bloco try catch, serializará o parâmetro da chave recebida. O método serializado ANS transforma a chave pub estendida no objeto de chave pub estendida do Bitcoin. Java então envolverá a IOException em uma exceção de tempo de execução no bloco de captura. Agora, usaremos o método de alcance da classe de fluxo de pulmões para passar de zero a uma variável de número inicial de endereços gerados que será definida posteriormente. Vamos injetar essa variável nessa classe. No construtor, definirá uma anotação qualificadora para essa variável, que terá o mesmo nome de variável como parâmetro, mudará seu tipo para hint, mapeará cada índice e chamará o método de geração de endereço. Portanto, para cada índice, chamaremos o método generate address, passando o retorno do método Get de fábrica do gerador de endereços, a chave pub estendida e o índice como seus parâmetros. Por fim, converteremos o resultado em uma lista. Vamos criar o método de geração endereçada. Será necessário um gerador de endereços, uma chave de pub estendida e um índice. O gerador de endereços será passado de uma fábrica de geradores de endereços, que será injetado nessa classe e criado agora. Vamos mudar o parâmetro de tipo para o tipo de endereço. Agora vamos criar o método Get de fábrica do gerador de endereços . Ele retornará uma interface de gerador de endereços que agora retornará ao método generate address a partir do gerador sequencial de endereços. Primeiro, derivaremos uma chave secundária estendida da chave pub estendida usando o método CKD. Esse método aplicará a função de derivação de chave secundária que aprendemos há dois vídeos. Será necessário um índice que definirá o índice de derivação da criança. Agora retornará um novo registro de endereço. Ele obterá o resultado do método de geração do gerador de endereços. Esse método pegará a chave secundária estendida e derivará um endereço dela. O segundo parâmetro de endereço será o índice. Agora, adicionaremos o método generate à interface do gerador de endereços. Agora implementaremos o método get fábrica do gerador de endereços. Ele retornará o resultado do GetMethod de um mapa gerador de endereços. Essa variável será um campo nessa classe e será inicializada nesse construtor de classe. Será um mapa de cadeias de caracteres como chaves e geradores de endereço como valores. No construtor, passará um serviço gerador de endereços de segmento, que será criado. Em seguida, mapearemos cada tipo de endereço para o gerador de endereços do segmento. No mapa do gerador de endereços. O gerador de endereços do segmento implementará a interface do gerador de endereços. Vamos criar o método de interface necessário. Antes de implementá-lo, vamos criar seu teste. Isso estenderá a classe de especificação. Instanciará o gerador de endereços do segmento aqui. No método de configuração, adicionaremos o provedor de segurança, assim como nossos outros testes que precisam dele. Em seguida, criaremos o que deve gerar um teste de endereço de segmento. No bloco fornecido, criará uma chave pub estendida usando a classe de chave pub estendida no método serializado. O método serializado usará uma string de chave pub estendida, que passará no bloco where. Em seguida, criaremos uma creche estendida chamando o método CKD na variável pub key estendida. Para este método, passará um parâmetro de índice que passará pelo bloco da web. Quando o método de geração do gerador de endereço de segmento é chamado com a chave secundária estendida. Então, esperamos que o endereço de devolução seja igual ao endereço esperado. Agora, vamos usar o bloco where para inicializar as variáveis em cinza Vamos usar dados de teste que eles retiraram do site da E and Coleman para isso. Você pode copiar esses parâmetros dos recursos desta lição. Vamos fazer o teste. Falhou conforme o esperado. No próximo vídeo, aprenderemos mais sobre como assinar quais endereços. Em seguida, no vídeo seguinte, implementaremos o gerador de endereços de segmentos e o gerador de endereços sequenciais e sequenciais faremos com que seus testes sejam aprovados. 19. Entendendo os endereços do Segwit e introdução aos ambientes de rede do Bitcoin: Nesta apresentação, aprenderemos mais sobre os endereços do segmento Bitcoin, que será o tipo de endereço padrão que nossa carteira fornecerá. Então, o que é uma sequência de Bitcoin, qual endereço? Os endereços de segmento também são conhecidos como endereços nativos segue para 32 endereços, endereços versão zero do segmento ou endereços P2 WP k-th, onde P2 WP k h significa pagar para testemunhar o hash da chave pública. Cada um desses termos é usado para se referir à mesma coisa. Era o tipo de endereço Bitcoin mais atualizado até novembro de 2021. Depois de novembro de 2021, quando a atualização taproot foi ativada na rede Bitcoin, um novo tipo de endereço Bitcoin chamado endereço taproot, também conhecido como endereço segue versão um , tornou-se disponível. Por enquanto, vamos nos concentrar no endereço do segmento, cuja maioria dos endereços segmentados de suporte de carteiras modernas se tornou disponível em 2017 na rede Bitcoin após a atualização de testemunhas segregadas. Opcionalmente, essa atualização permitiu transações menores, já que a parte dessas transações mais recentes, chamada de testemunha, é enviada separadamente e não está incluída no blockchain. As regras para gerar endereços de segmentos estão descritas no VIP one-seventh three e também são implementadas em métodos da biblioteca Bitcoin Java. Os endereços dos segmentos permitem que os remetentes de Bitcoin paguem as taxas mais baratas por transações comuns. A razão para isso é porque as transações que enviam bitcoins para endereços de segmentos são efetivamente menores em comparação com transações enviadas para outros tipos de endereços. Mas aprenderemos mais detalhes sobre transações de Bitcoin em vídeos futuros. Como os endereços de segmentos são bem suportados pela maioria das carteiras modernas e porque nos permitem enviar transações mais baratas, nós os definiremos como o tipo de endereço padrão de nossa carteira. Agora, vamos recapitular um slide da apresentação anterior sobre teclas estendidas. Nesse vídeo, aprendemos que poderíamos obter uma chave pública a partir de uma chave privada estendida ou de uma chave pública estendida. Então, ao fazer o hash e codificar a chave pública, poderíamos obter um endereço. Agora, vamos ver mais detalhes sobre esse processo de hash e codificação. Começando com uma chave pública obtida conforme explicado anteriormente, aplicando as funções de hash criptográficas SHA-256 e 160 à direita à chave pública, obtemos um hash de chave pública com um tamanho de 20 bytes. O SHA-256, combinado com o 160 do lado direito , é chamado de algoritmo hash 160. Finalmente, o hash da chave pública, combinado com um prefixo e uma versão numérica, gera um endereço de segmento por meio da codificação Beck 32. codificação Back 32 é reversível pelo processo chamado decodificação Beck 32. Ao criar transações, devemos decodificar 32 endereços em hashes de chave pública antes de incluí-los nas saídas da transação. É por isso que esse tipo de endereço também é chamado de pay to witness. O hash de chave pública revisitará esse tópico com mais detalhes ao falar sobre transações para endereços de segmentos. Quando o Beck 32 codifica hashes de chave pública, a versão é definida como zero quando o prefixo é definido como BC unnamed net. Falando sobre a rede principal, vamos rapidamente ter uma visão geral dos ambientes de rede Bitcoin. Cada um desses ambientes é uma rede separada com blockchains e propósitos diferentes, mas com regras semelhantes. A rede Bitcoin pode ser chamada de rede principal do Bitcoin. É onde os bitcoins têm valor. O blockchain é imutável e a dificuldade de mineração é a maior. O ambiente da rede de teste é semelhante à rede principal, mas tem uma menor dificuldade de mineração e onde os bitcoins não têm valor, ele é usado para fazer testes em um ambiente em que os nós interagem enquanto mantendo um blockchain compartilhado. Test Net teve versões diferentes desde que foi criado com diferentes blockchains. Finalmente, o ambiente de teste de registro é uma rede individual que pode ser executada por qualquer usuário do node Bitcoin com um blockchain não compartilhado com outros. Os blocos podem ser gerados instantaneamente, sem esforço e livremente pelo usuário. Ele é usado para fazer testes mais rápidos e automatizados em um ambiente controlado. Os endereços em cada rede têm prefixos diferentes e são válidos somente em seus ambientes. Para endereços de segmentos, esses C são o prefixo usado para vestidos vermelhos na rede principal. Tb é usado para endereços na rede de teste. E BCRP é o prefixo usado para vestidos vermelhos no teste de registro. Como dito anteriormente, a versão zero é usada para endereços de segmentos. A versão um é usada para endereços de raiz principal. 20. 18 Criar nossa primeira carteira parte 9 skillshare 2: Neste vídeo, faremos todos os testes que criamos para isso, implementaremos primeiro o método gerador de endereços de segmentos. Para gerar um endereço de segmento, você converterá uma chave estendida em uma chave pública. Vamos mudar o nome desse parâmetro para chave estendida. Em seguida, a chave pública será convertida em um endereço de segmento usando esse método, pois seu parâmetro passará um prefixo. Vamos passar essa constante por enquanto, que tornará o endereço válido no ambiente principal da rede Bitcoin. Vamos também adicionar a anotação de serviço a essa classe. Agora, vamos executar o teste do gerador de endereços de segmentos. Falhou porque precisamos aumentar a versão do Bitcoin Java para 0,4, 0.0, que contém o método CKD correto para essa operação funcione. Vamos fazer isso. Clique em Carregar alterações do Maven. Vamos fazer o teste novamente. Ótimo, todos os testes foram aprovados. Agora vamos ajustar o teste do gerador sequencial de endereços. Temos dois novos parâmetros de construtor que precisamos passar para o serviço. Primeiro, vamos instanciar a fábrica do gerador de endereços. Passar um novo conjunto seria um gerador de endereços. Em seguida, passaremos 20 como o número inicial de endereços gerados. Agora vamos fazer esse teste novamente. Ok, esquecemos de adicionar o provedor de segurança no método de configuração. Vamos consertar isso. Execute-o novamente. Ok, o teste foi aprovado. Alguns serviços não têm a anotação do serviço. Vamos consertar isso. Ok, agora vamos adicionar um novo Bean, que será o número inicial de endereços gerados para cada chave estendida, definirá arbitrariamente como 20. Agora vamos executar nosso aplicativo para ver como ele está funcionando. Recebemos um erro no console indicando que nosso aplicativo não tem o provedor de segurança. Vamos adicioná-lo ao método principal na classe de aplicativo BYOD W. Vamos executar nosso aplicativo novamente. Ok, o erro não ocorreu, mas o campo do endereço de recebimento ainda não tem um endereço. Vamos mudar isso. Primeiro. Vamos executar todos os nossos testes para verificar quais outros testes precisam ser corrigidos. Os testes do serviço de criação de carteira estão interrompidos. Vamos consertá-los. Primeiro, temos que incluir um objeto gerador sequencial de endereço válido como seu terceiro parâmetro. Vamos instanciá-lo passando 20 como o primeiro parâmetro e uma fábrica de geradores de endereços como o segundo. Em seguida, instanciaremos a fábrica exatamente como no teste anterior. Agora garantirá que o serviço de criação de carteira esteja criando uma carteira com duas chaves de pub estendidas, cada uma com 20 endereços. Afirmará que o primeiro campo estendido de endereços de chaves de pub tem um tamanho de 20. Vamos criar um getter para esse campo. Afirmará o mesmo para a segunda chave de pub estendida. Agora vamos fazer esse teste. Ótimo, já passou. Agora vamos fazer com que o teste de criação de carteira seja aprovado. Lembre-se de que esperamos que o endereço de recebimento TextField contenha um endereço depois de criar uma carteira. Então, vamos para o controlador da guia de recepção. Adicionará um método chamado initialize, que será executado após o aplicativo inicializar esse controlador. Em seguida, injetaremos a carteira atual nessa classe. Na classe de carteira atual, incluirá um novo campo de propriedade de string simples chamado endereço de recebimento, que será inicializado aqui criará setters e getters para ela. Agora, vamos para a guia Receber. O Fxml adicionará um ID Fx ao TextField. Esse ID de ética será chamado de endereço de recebimento e também o adicionaremos ao controlador da guia de recebimento. Agora, no método inicializado vinculará a propriedade de endereço de recebimento da carteira atual a um ouvinte que usará esses três parâmetros em uma função Lambda. No corpo do Lambda, definirá o campo de endereço de recebimento com o novo valor, que será um endereço. Agora, na atualização, o serviço de carteira atual definirá o endereço de recebimento da carteira atual como o primeiro endereço da primeira chave pub estendida da carteira. Agora, quando o endereço de recebimento for alterado dessa forma, ele acionará esse ouvinte que definimos aqui no controlador da guia Receber. E espero que ele adicione o endereço ao campo de endereço de recebimento. Agora, vamos executar esses testes para ver se eles funcionam. Grupos. Falhou. Vamos descobrir o porquê. Ok, o erro aconteceu porque esse método deve ser inicializado, não inicializado. Vamos corrigir isso e executar o aplicativo. Ótimo. A carteira fez o que esperávamos e preencheu o campo de endereço de recebimento depois de criarmos uma carteira. Agora, se apresentarmos esse endereço para alguém, eles poderão enviar bitcoins para ele. Agora, vamos executar todos os testes de aplicativos. Ótimo, todos eles passaram. 21. 19 Criar nossa primeira carteira parte 10 skillshare 2: Neste vídeo, faremos uma refatoração rápida no gerador de endereços do segmento. Em vez de codificar o prefixo do segmento de rede principal como parâmetro para o endereço do segmento a partir do método de chave pública compactada criará um serviço que nos permitirá criar endereços para os ambientes de teste net e reg test. Chamaremos esse prefixo de endereço de serviço de fábrica. Ele terá um método get em que passaremos um tipo de endereço e retornaremos um prefixo de endereço. Esse valor retornado será usado como um parâmetro para o endereço do segmento do método de chave pública compactada. Agora vamos injetar esse serviço nessa classe e criá-lo. Agora vamos criar o método It's GET. Para implementar esse método, será necessário um mapa auxiliar, que mapeará os tipos de endereço para outro mapa, mapeando os três ambientes com seus prefixos de endereço correspondentes. Vamos construí-lo e ficará claro o que eu quis dizer. Agora, vamos mudar o nome desse parâmetro para o tipo de endereço. No GetMethod retornará um prefixo de endereço usando o tipo de endereço como a primeira chave. E uma variável chamada ambiente Bitcoin como a segunda chave do mapa que acabamos de criar. A variável de ambiente Bitcoin será definida posteriormente em nosso arquivo de propriedades do aplicativo e a injetaremos nessa classe. Agora. No construtor, adicionaremos uma anotação de valor antes da variável para injetar seu valor no arquivo de propriedades. Agora, vamos digitar corretamente o campo do mapa do tipo de endereço. Agora vamos adicionar a configuração do ambiente Bitcoin ao arquivo de propriedades do ponto do aplicativo. Vamos configurá-lo para um teste de registro. Agora vamos corrigir alguns arquivos de teste para lidar com as mudanças que fizemos até agora. Começando com o teste do gerador de endereço de segmento, excluirá essa parte e instanciará o gerador de endereços de segmento no método de configuração, passando a fábrica de prefixos de endereço como seu parâmetro. Agora vamos instanciar a fábrica de prefixos de endereço, passando a constante de rede principal como parâmetro. Agora vamos fazer esse teste. Ótimo, continua funcionando. Agora vamos corrigir o teste do serviço de criação de carteira. Faremos o mesmo que no último teste. Basta injetar o prefixo de endereço factory no gerador de endereços do segmento. Vamos fazer o teste. Ótimo, já passou. Agora vamos corrigir o teste do gerador sequencial de endereços. Faremos o mesmo de antes. Agora, vamos fazer o teste. Ótimo, já passou das duas. Agora vamos fazer todos os nossos testes. Alguns testes falharam porque o prefixo de endereço factory tem uma anotação. Vamos consertar isso. Execute os testes novamente. Ótimo. Todos os testes foram aprovados. Agora vamos fazer esse pequeno refator de adicionar importações estáticas para essas constantes. Agora, vamos executar o aplicativo para ver o que fizemos até agora. Lembre-se de que agora esperamos que nossa carteira gere endereços compatíveis com o teste de registro, já que nossa propriedade de ambiente Bitcoin está configurada para teste de registro. Ok, como esperado, nossa carteira gerou endereços começando com BCR t, já que é o prefixo de endereços de segmentos no ambiente de teste de registro. Agora vamos mudar a propriedade do ambiente Bitcoin duas redes principais, e executar o aplicativo novamente. Agora temos endereços que começam com BC, que é o prefixo de endereço do segmento para a rede principal. Finalmente, vamos mudar a propriedade do ambiente Bitcoin para testar a rede e tentar o mesmo. Ok, agora podemos gerar endereços começando com TB, que é o prefixo para testar endereços compatíveis com a rede. Ótimo, agora temos uma maneira fácil de mudar o ambiente de rede compatível com nossa carteira. 22. 20 Preparar o nó para receber bitcoins skillshare 2: Agora temos uma carteira Bitcoin capaz de gerar endereços compatíveis com diferentes ambientes de rede Bitcoin , que são reg, test, test net e main net. Já é possível usar esses endereços para receber Bitcoins. Para fazer isso, basta mostrá-los a outros proprietários de bitcoins, que podem usar suas carteiras para enviar Bitcoins para você, ou provavelmente Satoshi, que são frações de Bitcoin. Mas, por enquanto, nossa carteira está habilitada para detectar esses pagamentos. Portanto, nada acontecerá na interface de usuário de nossas carteiras após uma transação em um de nossos endereços. De agora em diante, pretendemos mudar isso. Começaremos a criar um recurso que nos permitirá ouvir as transações que chegam ao nosso núcleo do Bitcoin. Em seguida, filtraremos as transações com saídas que correspondam aos nossos endereços de carteira atuais. Por fim, modificaremos nossa carteira para mostrar informações sobre a quantidade de Bitcoin que nossa carteira contém. Agora, vamos garantir que nosso node Bitcoin esteja corretamente configurado e preparado para enviar e receber informações de transações para nossa carteira. Para fazer isso, abra o arquivo bitcoin.com. A localização desse arquivo dependerá do sistema operacional que você está usando. Como estou usando o Windows 10, meu arquivo bitcoin.com está localizado no caminho na tela. Abra o arquivo e verifique se ele está assim. Vamos analisar o significado de cada uma dessas configurações. O primeiro parâmetro, reg test, é definido como um para fazer nosso node funcionar nos ambientes de teste de registro. Uma vez que usaremos o ambiente de teste de registro para nos ajudar a desenvolver nosso aplicativo. O segundo parâmetro, os dados , são definidos na pasta em que você deseja que o nó registre as informações do blockchain e da carteira. Eu defino os meus dados de Bitcoin com barra invertida de dois pontos, mas você pode escolher qualquer caminho que preferir. O parâmetro do servidor é definido como um para permitir que nosso nó receba chamadas de API de nosso aplicativo. Os parâmetros de usuário RPC e senha RPC podem ser definidos como você quiser. Por enquanto, vou escolher BYUI W para ambos. Mas ao usar nosso aplicativo de verdade, é altamente recomendável escolher valores mais seguros para esses parâmetros. O índice TX está definido como um. Isso é necessário para permitir que nosso node recupere qualquer informação de transação do blockchain. O parâmetro da taxa de fallback pode ser definido como 0,00 001. Esse valor será usado para taxas de transação que não puderam ser calculadas adequadamente pelo nó. Por fim, definiremos a propriedade z MQ pub Ratti x com esse valor. Essa propriedade define o endereço TCP para onde as informações da transação que vão as informações da transação que chegam ao nó. nosso aplicativo, ouviremos o mesmo endereço TCP e capturaremos novas transações enviadas para um de nossos endereços Bitcoin dessa forma. Agora, vamos executar nosso nó Bitcoin com essas configurações usando o terminal, vá para a pasta em que seu aplicativo Bitcoin está instalado. Isso depende de onde você o instalou e de qual sistema operacional você está usando. Como estou usando o Windows 10, já abri meu terminal e fui até essa pasta na tela. Agora, execute o nó Bitcoin digitando dot slash Bitcoin D e pressionando Enter. Agora, seu nó principal do Bitcoin está funcionando com as configurações. Dissemos anteriormente agora estamos prontos para as próximas aulas. 23. 21 cliente de nó parte 1 skillshare 2: Neste vídeo, criaremos um cliente HTTP que fará algumas chamadas para nosso nó principal do Bitcoin. Esse cliente será necessário posteriormente, quando o usarmos para enviar e receber transações. Primeiro, importaremos uma dependência no arquivo POM. Essa dependência é a web inicial do Spring Boot , necessária para a implementação do cliente HTTP, excluirá uma dependência transitiva dessa biblioteca adicionando uma tag de exclusão. dependência excluída será o Tomcat inicial do Spring Boot. Faremos isso para evitar a inicialização de um servidor web em nosso aplicativo. Agora, clique no botão carregar Maven Changes. Agora vamos criar uma classe de configuração para o cliente node. Crie uma classe chamada configuração do cliente Node dentro do pacote api dot config em uma anotação de configuração para ele. Agora, criaremos algumas propriedades privadas nessa classe, todas precedidas por uma anotação de valor. No primeiro, teremos essa anotação de valor. E será chamado de node RPC URI. O próximo terá essa anotação de valor. E será que o nome de usuário RPC do nó terá outra propriedade com a seguinte anotação de valor com o nome igual node RPC password. Todas essas propriedades serão injetadas a partir de valores adicionados posteriormente no aplicativo. O arquivo de propriedades de pontos também criará um feixe com a classe de modelo restante. Será necessário um Template Builder em repouso como parâmetro. Usaremos esse construtor para retornar um objeto de modelo de prisão com um URI raiz igual à propriedade note RPC URI. Ele terá uma autenticação básica com as propriedades do nome de usuário RPC da nota e da senha RPC da nota. Em seguida, ligaremos para Build e retornaremos. Agora vamos atribuir as propriedades que serão injetadas nessa classe. Vamos para o arquivo de propriedades de pontos do aplicativo. Vamos atribuir à propriedade node dot RPC dot dot URI ao seguinte endereço. Esse URI com a porta 18443 é o URI padrão da API Bitcoin Core Node RPC para o ambiente de teste de registro. Como propriedade de nome de usuário node dot RPC dot, você precisa escolher o mesmo valor que escolheu para a configuração do usuário RPC em seu arquivo bitcoin.com como a propriedade de senha node dot RPC dot, escolha o mesmo valor que você definiu para a configuração da senha RPC em seu bitcoin.com. Agora, dentro do pacote de serviços api dot, crie o pacote node, incited, crie o pacote cliente. Agora vamos criar a classe de cliente node dentro dela. Vamos adicionar a anotação do serviço a ela. Agora, vamos injetar o bean do modelo restante nessa classe. Adicionaremos o método a seguir para fazer solicitações à API Bitcoin RPC. Quanto aos parâmetros, será usado um método de string, uma referência de tipo parametrizada do tipo node client response, que criará em seguida uma URL de string e zero ou mais objetos. Agora vamos criar a resposta flexível do nó dentro do nó de pontos do domínio do pacote. Voltar ao node client, o método instanciará um novo objeto de solicitação do cliente node. Ele usará os argumentos do método e dos parâmetros em seu construtor. Vamos criar essa nova classe dentro dos domínios, esse pacote de nós. Vamos criar seu construtor. Agora, vamos encapsular a solicitação dentro de um objeto de entidade HTTP. Em seguida, retornaremos o resultado dessa chamada de método, que finalmente fará uma solicitação de postagem ao Bitcoin Core Node, ajustará a classe de resposta do cliente do nó transformará em uma gravar e adicionar uma propriedade de resultado a ela fará um ajuste semelhante à solicitação do cliente do nó, transformará em um registro e adicionará esses campos a ela. Esquecemos de colocar um T aqui. Agora, veremos como fazer uma chamada importante para a API Bitcoin Core Node. Acesse este site na tela. É uma referência à chamada RPC core do Bitcoin Create Wallet . Vemos na última linha que essa chamada usa uma chave de método com a carteira de criação de valor em seu corpo. Cada chamada à API Bitcoin tem esse formato com a chave do método contendo o nome do método. As chamadas de API do Bitcoin também têm uma chave de parâmetros contendo vários tipos de dados. Nesse caso, seu valor é uma matriz com apenas um elemento. O nome da carteira, chamada de criação de carteira cria uma carteira dentro do Bitcoin Core e a carrega. Muitas chamadas de API que usaremos posteriormente são necessárias. Mas nosso núcleo do Bitcoin tem uma carteira carregada. De volta ao cliente node. Agora podemos entender por que o método make request cria um objeto de solicitação que usa um argumento de string chamado method e um argumento de tipo variável chamado params. Agora vamos criar uma classe chamada node create wallet client. Vamos adicionar uma anotação de serviço a ela. Injetará o cliente node nele. Agora, criaremos um método chamado create, que usará um parâmetro de string. Agora, faça uma chamada para o método de criação de carteira da API Bitcoin Core. Nós os chamaremos de método make request do cliente node desta forma, seguindo a referência do site Bitcoin Core. Agora vamos testar esse método para isso. Vamos executar nosso Bitcoin Core Node no terminal. Em vez de usar nossa forma tradicional de TDD de fazer as coisas, testaremos esse método de forma diferente. De volta ao node, o cliente create wallet criará um método precedido por uma anotação pós-construção. A anotação de construção Post é útil para executar código quando um aplicativo Spring está sendo iniciado. Também é útil para testes rápidos e aplicativos Spring, quase como criar um método estático principal em uma classe Java, mas com todos os benefícios dos beans gerenciados pelo aplicativo. Dentro desse método, chamará o método create passando qualquer nome de carteira. Vamos executar o aplicativo. Ok, ao observar os registros do Bitcoin Core Node no terminal, vemos que nosso node criou e carregou uma carteira com o nome que dissemos na chamada do método. Com isso, sabemos que nosso método está funcionando e podemos remover esse método de pós-construção. Agora, vamos acessar o site do Bitcoin Core novamente e pesquisar o método DIR da carteira listada. Esse método não usa parâmetros e retorna todas as carteiras de nós criadas até o momento. Ele retorna uma estrutura JSON com um campo de carteiras. Esse campo contém uma matriz de objetos, cada um representando uma carteira existente com um campo de nome. Vamos criar um cliente para esse método. Vamos chamá-la de lista de nós enquanto for cliente. Novamente, vamos injetar o cliente node nessa classe. Em seguida, criaremos o método list all, que retornará uma lista de nomes de carteiras. Dentro desse método, eles os chamarão de make request method do node client passando list wallet DIR como o nome do método. Uma nova referência de tipo parametrizada e um URL vazio. Não passaremos nenhum parâmetro adicional. O objeto retornado será um registro node wallets, que será criado agora, nós o criaremos dentro do pacote domains dot node. Esse registro terá somente um campo. Será uma lista de carteiras node. Seu nome será carteiras. Vamos criar o registro da carteira node no mesmo pacote. único campo será um nome de string. Lembre-se de que estamos modelando esses objetos com base nessa referência do site Bitcoin Core. Mas o campo de carteiras no registro de carteiras de nós corresponde ao nome desse campo na resposta JSON da chamada de API. O mesmo acontece com o campo de nome do registro da carteira node. O campo carteiras da resposta terá uma lista de objetos com o campo de nome. Cada um desses objetos será armazenado como registros do NerdWallet no aplicativo, de volta à lista de nós enquanto ele for cliente. Da lista, todos os métodos retornarão uma lista de nomes de carteiras. Para fazer isso, obteremos as carteiras das carteiras node. Em seguida, chamaremos stream e, em seguida, mapearemos passando uma referência ao campo do nome da carteira do node. Em seguida, converteremos o resultado em uma lista e o retornaremos. Agora, vamos testar o método list all usando um método anotado com a construção Post para imprimir cada elemento retornado pela chamada do método list all. Vemos nessa linha no console que o aplicativo registra o nome da carteira node que criamos. Ótimo. Agora implementaremos outro cliente para chamar o método da API Node chamado list wallets. A diferença entre esse método e a carteira de lista DIR é que as carteiras da lista retornarão somente as carteiras atualmente carregadas pelo nó. Ele também retorna uma lista de nomes de carteiras sem envolvê-los em objetos. Agora vamos criar o método de carregamento da lista. Ele retornará uma lista de nomes de carteiras. Para fazer isso, basta retornar essa chamada de método. Agora vamos testá-lo da mesma forma que testamos a lista. Eu vou ligar. Vemos no console, mas nosso aplicativo registra duas vezes o nome da carteira que criamos. A primeira foi devido à chamada do método list all, e a segunda foi devido à chamada do método carregada na lista. Agora, para ver a diferença entre as duas chamadas de método, vamos fazer o seguinte. Encerre o aplicativo Bitcoin Core Node pressionando Control plus C no terminal. Agora, inicie o Bitcoin Core Note novamente. Agora vamos fazer o mesmo teste. Mas primeiro, adicione essas linhas antes das chamadas do método para diferenciar cada método. No console, vemos que somente a chamada do método list all retornou a carteira criada. Isso demonstra que, depois de iniciarmos o aplicativo Bitcoin Core Node, precisamos carregar a carteira que usaremos, possamos fazer outras chamadas de API que precisem carregar uma carteira de node. Mas veremos como isso funciona na prática nos próximos vídeos. 24. 22 cliente de nó parte 2 skillshare 2: Neste vídeo, continuaremos implementando mais métodos que nos permitirão interagir com nosso node Bitcoin a partir de nosso aplicativo. O primeiro é um método que carregará uma carteira node. Ao executar seu node, você precisa carregar uma carteira para poder chamar muitos outros métodos de node. Então, vamos criar o cliente de carteira node load. Como sempre, em uma anotação de serviço. Agora, injetaremos o cliente node nele. Em seguida, criaremos o método de carregamento, que terá o nome da carteira como parâmetro. Em seguida, simplesmente os chamaremos de método make request do cliente node, assim. Agora, vamos testar esse método usando uma construção de post. Primeiro, vamos remover esse método de pós-construção que criamos anteriormente. Agora chamaremos o método de carregamento passando o nome da carteira que criamos. Antes de executá-lo, vamos executar nosso node Bitcoin no terminal. Ok, nos registros do terminal, vemos que nosso node carregou corretamente nossa carteira. Agora, criaremos um serviço útil para carregar uma carteira node se ela já existir e não estiver carregada. Se uma carteira com esse nome já existir e já estiver carregada pelo node, o método não fará nada e nós retornaremos. Por fim, se uma carteira com esse nome não existir, o método a criará e o nó será carregado automaticamente, pois carrega uma carteira após sua criação. Então, no pacote services dot node, vamos criar um nome de classe node load ou criar um serviço de carteira. Vamos injetar os seguintes clientes nele. O cliente de carteira de criação do node, o cliente da carteira de carregamento e a lista de nós enquanto cliente. Agora vamos criar um método chamado load ou create wallet. Ele usará um nome como parâmetro. Dentro dele, chamará o método list all da lista de nós, o cliente de carteiras armazenará o resultado em uma variável chamada all wallets. Em seguida, chamaremos o método de carregamento da lista do mesmo cliente. E armazenaremos o resultado na variável de carteiras carregadas. Agora, adicionaremos uma instrução if verificando a seguinte condição. Se essa condição for avaliada como verdadeira, significa que a carteira com esse nome já existe e foi carregada pelo nó. Se for esse o caso, não precisamos fazer nada e podemos retornar. Agora, adicionaremos a seguinte declaração if. Se essa afirmação retornar verdadeira, significa que uma carteira com esse nome já existe, mas não foi carregada pelo node. Se for esse o caso, chamaremos o método de carregamento do cliente node load wallet passando o nome da carteira e retornaremos. Por fim, se a execução do código for considerada falsa das declarações IF anteriores, isso significa que uma carteira com esse nome não existe. Nesse caso, simplesmente criamos a carteira, chamando o método create do cliente node create wallet e passando o nome da carteira. Ok, o método está concluído. Vamos usá-lo nos próximos vídeos. Agora vamos criar outro cliente útil. Ele se chamará Node get new address client. Como o próprio nome sugere, ele será usado para gerar um novo endereço a partir de nossa carteira de node carregada. Então, vamos injetar o cliente node nele. Agora, criaremos um método chamado obter novo endereço. Ele retornará o endereço em uma string. E ele usará o nome da carteira como parâmetro. Em seguida, retornaremos para fazer a chamada do método de solicitação do cliente node com esses parâmetros. Observe que definimos o parâmetro URL para a string Wallet e corte o nome da carteira. É assim que dizemos ao nosso node que queremos um endereço dessa carteira específica. Vamos testar esse método. Para isso, criaremos o seguinte método anotado de construção Post que chamará o método get new address, passando o nome de uma carteira que carregamos anteriormente como parâmetro. Se chamarmos esse método sem carregar essa carteira primeiro, ele não funcionará e o nó retornará um erro. Armazenaremos o resultado da chamada do método na variável de endereço e o imprimiremos. Vamos testá-lo. O registro do console mostra que ele gerou e imprimiu um endereço de teste de registro do segmento Bitcoin. Ótimo. Anote o endereço gerado. Vamos usá-lo para testar o método que será implementado a seguir. Agora, criaremos um método que será usado para controlar alguns blocos que produzem Bitcoins em um endereço. Esse método funciona apenas no ambiente de teste de registro e será útil para nós em alguns testes que precisam de um número inicial de moedas para jogar. Vamos criar uma classe chamada no degenerate para abordar o cliente. Como de costume, injetaremos o cliente node nele. Em seguida, criaremos um método chamado generate to address. Ele tomará como parâmetros um nome de carteira, vários blocos e um endereço. Em seguida, vamos chamá-los de método make request do cliente node com os seguintes parâmetros. Novamente, passaremos a string Wallet cortar a variável de nome. Em seguida, passaremos o parâmetro blocks, que indica o número de blocos que você deseja gerar. Por fim, passaremos a variável de endereço, que é o endereço que receberá os Bitcoins gerados. Agora, vamos testar esse método. Primeiro. Vamos remover o método anotado de construção da postagem anterior . Agora, faremos com que esse método de pós-construção chame o método generate to address, passando o nome de uma carteira carregada. Novamente, se você passar o nome de uma carteira que não existe ou não está carregada, o método funcionará. Criaremos 1.000 blocos e passaremos o endereço gerado anteriormente. Vamos executá-lo. Se inspecionarmos nossos registros de nós, veremos que ele mostra algumas linhas indicando que nosso método chamado funcionou. O último cliente criado para este vídeo será chamado de cliente Node get balanced. Ele será usado para verificar o saldo de nossas carteiras. Vamos injetar o cliente node nele. Em seguida, criaremos o método get, que retornará o número de bitcoins que nossa carteira contém. Será usado o nome da carteira como argumento. Em seguida, retornaremos essa chamada de método. Como os métodos anteriores. Esse método fará com que a Carteira reduza o nome da carteira como parâmetro de URL para definir o retorno do saldo dessa carteira específica. Vamos testar esse método usando uma construção de post. Chamará o método get passando o nome de uma carteira carregada anteriormente. Novamente, esse método não funcionará. Se a carteira anterior não for carregada pelo nó, armazenaremos o resultado da chamada em uma variável e a imprimiremos . Vamos testá-lo. Ótimo. A partir dos registros, vemos que agora temos milhares de Bitcoins. Obviamente, esses bitcoins são válidos apenas em nosso ambiente de teste de registro. Nos próximos vídeos, vamos usá-los para testes. 25. 23 cliente de nó parte 3 skillshare 2: Neste vídeo, criaremos um cliente que nos permitirá enviar Bitcoin da nossa carteira node para qualquer outro vestido vermelho que quisermos. Em seguida, usaremos todos os clientes que criamos até agora para criar um teste para receber bitcoins um endereço de nossa carteira de aplicativos. Então, depois de remover qualquer método de construção de post anterior das aulas anteriores, vamos criar uma classe chamada nodes enviada para endereçar o cliente. Agora vamos injetar o cliente node nele. Em seguida, criaremos um método chamado enviar para endereço como parâmetros ou nome e endereço da carteira e um valor. Em seguida, vamos chamá-los de método make request do cliente node passando os seguintes parâmetros. Novamente, passaremos a barra Wallet para cortar a variável do nome da carteira. Será a carteira de onde os bitcoins serão enviados. Também será necessário um endereço para onde os bitcoins serão enviados e um valor, que é o valor transferido em Bitcoins. Vamos testar esse método. Primeiro, certifique-se de que seu node esteja em execução. No meu caso, vou ter que começar. Agora, vamos garantir que nossa carteira node seja financiada com Bitcoins para que possamos enviar bitcoins a partir dela, chamaremos o método get balanced para verificar isso. Mas desta vez vamos ligar do terminal. Cada método de API que podemos chamar de nosso aplicativo pode ser chamado do terminal usando o aplicativo Bitcoin CLI. Abra outra janela do terminal e vá para a mesma pasta em que seu nó está instalado. Em seguida, digite o comando a seguir para carregar uma carteira criada anteriormente e pressione Enter. No meu caso, depois de carregar a carteira, tenho que digitar o nome da carteira de teste, que é o nome da carteira criei entre aspas duplas. Ok, agora que nossa carteira está carregada, podemos inserir outros comandos que a exijam. Então, vamos inserir esse comando para verificar o saldo da nossa carteira. Bem, é equilibrado, é zero. Parece que toda vez que reiniciamos a nota e o ambiente de teste de registro, nossos fundos desaparecem. Não tem problema. Vamos financiar nossa carteira Node. Agora usando a interface de linha de comando. Para fazer isso, primeiro obtemos um novo endereço do nosso nó enquanto ele está assim. Em seguida, chamamos o comando generate to address para gerar 1.000 blocos e direcionamos as recompensas do bloco para o endereço que acabamos de gerar. Agora, vamos chamar o comando Get balanced novamente. Ótimo. Vemos que nossa carteira agora contém milhares de Bitcoins. Novamente. Agora, de volta ao node, envie para o endereço do cliente. Vamos criar um método de pós-construção para testar o método send to address. Chamará o método de envio para endereço, passando o nome da carteira carregada. O segundo parâmetro pode ser qualquer endereço de teste de registro. Usaremos o Bitcoin CLI para gerar um novo endereço. Em seguida, vamos passá-lo como o segundo parâmetro para o método de envio para endereço. Em seguida, escolheremos um como valor. Vamos executá-lo. Ok, se chamarmos o método Get balanced do Bitcoin CLI, veremos que nosso balanceamento quase não mudou. Há uma pequena diferença entre o saldo atual e o saldo anterior. Essa diferença se deve à taxa de transação, pois transferimos um Bitcoin para um endereço da mesma carteira node, se chamarmos o método de receber por endereço da CLI. Passando o endereço, enviamos um Bitcoin para o número zero como segundo parâmetro, o que indica que queremos o saldo, incluindo transações não confirmadas, obtemos o valor um, que é o valor que transferimos para esse endereço. Ok, terminamos nossa CLI jogando por enquanto. Vamos remover o método de construção Post. Agora, dentro do BYOD, um pacote pegajoso criará o teste de recebimento de Bitcoin. Esse teste precisará de muitas coisas em comum com o teste de criação de carteira. Então, vamos fazer com que ele estenda uma classe abstrata que criaremos chamada teste de GUI. Essa classe terá todos os métodos comuns a qualquer teste de GUI de que precisarmos. Então, vamos criá-lo. No teste de criação de carteira, o teste cortará todas as propriedades e métodos, exceto o último, e os transferirá para a classe de teste de GUI. Em seguida, adicionaremos a anotação de teste do Spring Boot a ela e ela estenderá a classe de especificação do aplicativo. Removeremos a mesma anotação do teste de criação de carteira e faremos com que ela estenda a classe de teste de GUI. Vamos remover todas as importações não utilizadas. Agora, protegerá todas as propriedades privadas no teste de GUI e incluirá essa chamada de provedor de adição de pontos de segurança em seu método de início. Finalmente, vamos tornar essa aula abstrata. Agora, vamos testar o teste de criação de carteira para ver se tudo continua funcionando como antes da ocorrência de um erro. Minha intuição diz que é um bug da ideia do IntelliJ. Para resolver isso, vamos chamá-los método de ciclo de vida limpo maven. Vamos também reconstruir o projeto e executar todos os testes do aplicativo. Todos os testes foram aprovados. Portanto, foi apenas um bug do IDE. Agora, vamos continuar construindo nosso teste de recebimento de Bitcoin para injetar os seguintes grãos nele. O nó envia para o cliente de endereço, o nó carrega ou cria o serviço de carteira. O nó fica equilibrado, cliente. E o node obtém um novo cliente de endereço. *****. Parece que esquecemos de adicionar a palavra cliente e o node obter um novo endereço. Vamos renomeá-lo. Agora, vamos criar um método de configuração que será executado antes que essa classe seja testada. Dentro, ele chamará o método load ou create wallet a partir do node load ou create wallet service, pois seu parâmetro passará pela string, testará a carteira e a armazenará na constante. Em seguida, chamaremos o método create balance, se necessário, que será criado em seguida. Neste método, primeiro verificaremos o saldo da carteira de teste usando o cliente node get balanced. Se o saldo for inferior a 100 Bitcoin, obteremos um novo endereço da carteira de teste. Usando o node generate para endereçar o cliente, que esquecemos de injetar nessa classe, e faremos isso agora. Vamos gerar 1.000 blocos, financiando assim nossa carteira. E vamos tornar esse método privado. Com esse método executado antes dos testes, garantimos que sempre teremos Bitcoins que podemos usar em nossos testes. Agora, criaremos um teste chamado deve receber Bitcoin. Quando o bloco for semelhante ao bloco de vento no teste de criação de carteira, chamaremos os seguintes métodos para criar uma nova carteira. Clicaremos na guia Receber. Em seguida, pesquisaremos o valor na entrada do endereço de recebimento, que neste momento conterá o primeiro endereço da nossa carteira. E nós o armazenaremos na variável de endereço. Agora, chamaremos o método de envio para endereço a partir do nó enviado para o cliente de endereço. Como seus parâmetros passarão pelo nome da carteira de teste, pelo endereço que geramos com nossa carteira de aplicativos e pelo valor um. Depois de receber Bitcoins, esperamos que nossa carteira de aplicativos detecte a transação, mas esse processo não será imediato. Levará alguns segundos para que isso aconteça. Por esse motivo, usaremos um método chamado wait-for do test fx. Como seus parâmetros passarão de dez, que será o valor do tempo limite para o peso. O tempo limite nesse contexto é o tempo máximo que o aplicativo aguardará antes de lançar uma exceção de tempo limite. O segundo parâmetro indica a unidade de tempo do parâmetro anterior. Então, vamos escolher os segundos. O último parâmetro será um método de retorno de chamada. Dentro, ele procurará um componente de GUI com um ID de endereços. Tabela, consultará se ela tem um TableView e armazenará seu resultado em uma variável do mesmo tipo. Em seguida, retornaremos a comparação entre o tamanho do item do TableView e um. Esse TableView com uma tabela de ID de endereços será um componente que armazenará uma tabela contendo linhas, cada uma com um endereço financiado de nossa carteira. O método de retorno de chamada será executado em um loop e só será interrompido se a comparação retornar verdadeira ou se o tempo limite for atingido. Em resumo, esse peso para a chamada de método fará o seguinte. Ele verificará se há uma tabela com uma linha preenchida na tela. Isso acontecerá quando nossa carteira detectar que um de seus endereços recebeu uma transação e preencheu uma linha da tabela com essas informações. Esperará 10 s para que isso aconteça ou menos. Se a tabela for preenchida com uma linha antes, copiaremos a linha de pesquisa da visualização da tabela e a colaremos aqui. Em seguida, o bloco verificará novamente se o tamanho do item TableView é igual a um. Vamos armazenar esse valor de tempo limite em uma constante. Agora, vamos fazer o teste. Como esperado. O teste falhou porque não encontrou a tabela de endereços. No próximo vídeo, começaremos a implementar esse recurso em nossa carteira. 26. 24 Receber bitcoin parte 1 skillshare 2: Neste vídeo, criaremos uma tabela mostrando informações sobre nossos endereços. Essa tabela conterá cada endereço financiado, seu valor em Bitcoin e o número mínimo de confirmações que as transações com esses endereços têm. A ideia é preencher essa tabela logo após nossas carteiras detectarem transações enviadas para nossos endereços. Então, na janela principal, pontilhe FXML, se clicarmos na guia Scene Builder, veremos que ela está mostrando uma mensagem para baixar o Java FX, mesmo que o tenhamos baixado antes. Isso está acontecendo porque esse recurso do IDE não lida bem com componentes externos, como o controlador da guia Receber. Então, para poder usar o Scene Builder, criaremos um novo arquivo FXML chamado playground. Neste arquivo, colaremos todo o conteúdo do ponto FXML da janela principal. Mas, em vez de usar componentes externos como o controlador da guia Receber, os embutirá no arquivo. Portanto, dentro do pacote resources dot FXML, crie o arquivo playground dot FXML. Exclua todo o seu conteúdo. Em seguida, copie todo o conteúdo da janela principal com o ponto FXML e cole-o lá. Agora, substituiremos o conteúdo do controlador da guia Receber pelo conteúdo da guia Receber ponto FXML. E modificaremos a tag raiz FX com a tag tag. E vamos excluir seu atributo de tipo. Vamos importar a tag insets. Agora, quando clicamos no Scene Builder, podemos usá-lo normalmente. Agora, vamos adicionar um novo painel de guias ao componente VBox. Agora, vamos excluir uma das guias criadas. Vamos renomear os dois endereços restantes da guia. Vamos dar a ele uma guia de identificação FX de endereços. Agora, dentro da guia Conteúdo, adicionaremos um componente de exibição de tabela. Infelizmente, por motivos de erros, o Scene Builder não nos permite adicionar uma visualização de tabela a uma guia. Não tem problema. Vamos adicioná-lo usando o editor de texto. Vamos também adicionar uma ideia de tabela de endereços do Fx aqui. Vamos voltar para o Scene Builder. Começou a funcionar novamente. Agora temos uma tabela vazia dentro da guia de endereços. Agora vamos adicionar três colunas à tabela. Vamos renomear a primeira coluna para dois endereços, a segunda para balancear e a terceira para duas confirmações. Em seguida, clicaremos na tabela e alteraremos essa configuração para redimensionamento restrito. Agora, todas as colunas têm o mesmo tamanho e ocupam toda a área da tabela. Agora vamos clicar em cada coluna da tabela e desmarcar. São caixas de seleção editáveis e classificáveis. Agora, para cada coluna da tabela definirá sua largura máxima para 100. Esse é apenas um truque necessário para que possamos ajustar seu tamanho. Agora, vamos ajustar o tamanho deles usando o mouse desta forma. A coluna de endereços deve ser maior, pois os endereços ocuparão um espaço maior, as colunas de saldo e confirmação podem ter o mesmo tamanho. De volta ao editor de texto. Vamos mudar o atributo pref height do painel de abas para 355. Voltando ao Scene Builder, podemos ver que ele parece melhor. Vamos também alterar a mensagem do espaço reservado, que mostra quando a tabela está vazia. Para fazer isso, basta adicionar uma tag de etiqueta vazia dentro dessa tag de espaço reservado. Agora que nosso componente de tabela está pronto no playground, vamos criar um FXML para ele. Vamos chamá-la de tabela de endereços. Vamos excluir todo o código padronizado. E vamos copiar todo o conteúdo entre a tag TableView e colá-lo lá. Agora, em vez de usar a tag de visualização em tabela, vamos usar a tag raiz FX faz referência às plantas de visualização da tabela e ao atributo type. Vamos importar as tags restantes. E vamos adicionar esses atributos XML e S aqui. Agora, de volta ao playground FXML. A guia de endereços não tem um ID FX. Vamos acrescentar a isso. Essa ideia já foi usada no componente VBox por engano. Então, vamos removê-lo de lá. Agora, vamos copiar essas quatro linhas e colá-las na janela principal. Agora, vamos adicionar as tags de fechamento e as tags que copiamos. Agora, excluiremos a tag de exibição da tabela e adicionaremos uma tag de conteúdo em seu lugar. Dentro dela, adicionará uma tag controladora de tabela de endereços. Agora vamos criar esse controlador. Vamos adicionar uma anotação de componente a ela. Ele deve estender a classe de exibição de tabela com a classe de endereço como seu parâmetro de tipo. Agora, volte para a janela principal. Vamos importar o controlador criado recentemente. No controlador da tabela de endereços, vamos criar um construtor. Ele usará um parâmetro FXML com uma anotação de valor. A anotação do valor fará referência à tabela de endereços FXML. O segundo parâmetro do construtor será um objeto de contexto do aplicativo. No corpo do construtor, criará um novo objeto carregador FXML, inicializando-o com esses parâmetros. Em seguida, definiremos seu controlador FXML para isso. E estabeleceremos seu caminho para isso. Em seguida, chamaremos de carga sobre ele. E adicionaremos uma declaração throws ao construtor. Precisamos fazer mais uma coisa para que funcione. Dentro dessa instrução if no ouvinte iniciado pela GUI adicione o código a seguir. Isso é necessário para que o Java FX crie a tag do controlador de endereços corretamente. Agora, vamos executar nosso aplicativo para ver como ele está funcionando. Ótimo, tudo bem, a mesa de vestidos está bonita. Nos próximos vídeos, faremos com que funcione para nossas carteiras. 27. 25 Receber bitcoin parte 2 skillshare 2: Neste vídeo, faremos com que nossas carteiras comecem a interagir com nossos nós de Bitcoin para que possamos receber informações sobre transações enviadas para nossos endereços. Lembre-se de que, quando criamos uma carteira, geramos os primeiros 20 endereços para ela. Mas nosso node Bitcoin ainda não sabe quais são os endereços gerados. Are Bitcoin Node deve conhecer nossos endereços para enviar ativamente informações sobre suas transações para nosso aplicativo. Portanto, precisamos importar nossos endereços de carteira para nosso node. Para isso, criaremos um novo cliente node que será responsável por isso. Portanto, dentro do pacote node dot client, criará uma classe chamada node multi import address client. Como outros clientes, ele terá uma anotação de serviço e injetaremos o serviço de cliente node nela. Antes de criarmos seu método, vamos verificar a documentação do site Bitcoin Core Sua API usará o multimétodo de importação da API do nó Bitcoin. Vemos aqui que ele usa uma matriz de objetos como parâmetro. Cada objeto pode ter várias chaves diferentes, mas usaremos apenas três delas. A chave pub do script, que pode assumir como valor e objeto um endereço que o nó importará, um timestamp, que é a data em que o endereço foi gerado. Esse parâmetro é importante para determinar até que ponto no passado o nó pesquisará transações com esse endereço no blockchain também definirá o parâmetro watch only como verdadeiro já que nosso node usará nossos endereços apenas para monitorar transações no blockchain, mas não poderá assinar transações com esses endereços. Somente nossa carteira de aplicativos poderá assinar transações de saída, mas esse é um tópico para vídeos futuros. De volta ao IDE, vamos criar um método chamado endereços de importação. Serão utilizados como parâmetros um nome de carteira, uma lista de endereços e uma data de criação da carteira. Agora, criaremos um objeto params que modelará o multiparâmetro de importação que vimos na documentação do Bitcoin Core. Esse objeto será uma lista de um novo objeto que criaremos chamado node multi reimport dress params. Vamos criá-lo agora. Será um registro e criaremos no pacote domains dot node. Ele terá um novo nó reimportado várias vezes, respire ele script pub key object criará. Ele também terá um campo de registro de data e hora longo e um campo exclusivo para observação booleana. Vamos criar essa classe como um registro. Ele terá somente um campo de endereço. De volta ao cliente de endereços de importação múltipla do node. Como o método de importação de endereços recebe uma lista de endereços, devemos usar o código a seguir para convertê-lo em uma lista de endereços reimportados com vários nós por ohms. Em seguida, usaremos o método make request do cliente node dessa forma. Agora, vamos testar esse código usando um método de pós-construção. Importaremos endereços para a carteira node com o nome da carteira de teste. E usaremos a data atual como a data de criação da carteira. Como os endereços. Usarei esses três endereços de teste de registro, que você pode encontrar nesta classe como recursos. Antes de executar esse código, vamos executar nosso Bitcoin Core Node e carregar a carteira com o mesmo nome que usaremos. Para carregá-lo, usaremos o Bitcoin CLI, assim como fizemos nos vídeos anteriores. Ok, ao examinar os registros dos nós do Bitcoin, parece que funcionou. A última linha do registro mostra que a nova verificação foi concluída. A nova verificação acontece por padrão depois que importamos endereços para o nó. O reescaneamento busca transações no blockchain para os endereços importados recentemente. Nesse processo, o nó pesquisa transações e blocos criados até 2 horas antes da data que passamos como parâmetro de timestamp. Vamos remover o método de construção Post. Agora, dentro do pacote gooey dot listeners, vamos criar uma classe chamada created wallet important listener. Ele terá uma anotação de componente e implementará a classe de ouvinte do aplicativo com um parâmetro do evento de carteira criado. Vamos implementar seu método. Assim como o ouvinte de carteira criado, esse método de classe será chamado após a criação de uma carteira. Vamos injetar a carga do node ou criar um serviço de carteira nele. Agora, no método de evento sem aplicativo chamará o método load ou create wallet a partir do serviço injetado passando o nome da carteira de eventos como parâmetro. Vamos também injetar o cliente de endereços de importação múltipla de nós nele. Vamos finalizar os dois serviços injetados. Agora chamaremos o método de importação de endereços do último serviço injetado. Mas primeiro, vamos criar uma variável para a carteira de eventos e usá-la nesse método. Agora, na chamada de endereços de importação, vamos passar o nome da carteira. O método wallet get addresses, que criará a carteira criada na propriedade, que também criaremos no registro da carteira. Vamos criar a propriedade de data createdAt, vamos criá-la usando o recurso IDE de alteração de assinatura. Vamos usar um valor padrão de nova data. Ao fazer isso, o IDE adicionará automaticamente esse terceiro parâmetro em cada instanciação de uma carteira encontrada no projeto. Vamos clicar em Refactor e importar a classe de data. Se acessarmos o serviço de criação de carteira, veremos que ele adicionou uma nova data como o terceiro parâmetro na instanciação da carteira. Isso fará com que a carteira tenha a data atual como data de criação. O controlador de diálogo de criação de carteira usará a carteira criada na chamada do método de evento público. Isso acionará a chamada do método de evento no aplicativo. Agora vamos criar o método get addresses no registro da carteira. Ele retornará uma lista de endereços obtendo os endereços de suas chaves de pub estendidas, assim. Ao chamar o método flatMap no fluxo de chaves de pub estendidas e retornar a chave de pub estendida, o fluxo de endereços dessa chamada obterá um fluxo de todos os objetos de endereço da carteira. Em seguida, chamaremos o método map para converter o fluxo de objetos de endereço em um fluxo de cadeias de endereço. Por fim, chamaremos o método de duas listas no resultado e retornaremos uma lista de todos os endereços da carteira em formato de string. Ok, agora, depois de criar nossa carteira, esperamos que nossos aplicativos sejam carregados criemos uma carteira com o mesmo nome em nosso node. Depois disso, nosso aplicativo importará todos os endereços gerados para nosso nó. Vamos executar nosso aplicativo para testá-lo. Vamos criar uma nova carteira. Eu cliquei no botão OK, mas parece que nada aconteceu. Vamos verificar os registros dos nós. Ok, depois de algum tempo, diz que a nova digitalização foi concluída e a carteira terminou sua criação. No próximo vídeo, tornaremos esse processo assíncrono executando as chamadas para o nó em outro thread. Ao fazer isso, o pegajoso não ficará preso e a criação da carteira será mais fácil. Cia. 28. 26 Receber bitcoin parte 3 skillshare 2: No último vídeo, fizemos com que nosso node Bitcoin criasse e carregasse nossa carteira de aplicativos e endereços importantes. Mas esse processo estava demorando alguns segundos e bloqueando a interface gráfica do usuário. Neste vídeo, corrigiremos isso fazendo com que a comunicação com o node seja executada em outro thread de forma assíncrona dentro do pacote BYU OWL. Vamos criar um novo pacote chamado Config. Dentro desse pacote, vamos criar uma classe chamada configuração assíncrona. Essa classe conterá todas as configurações relacionadas à execução assíncrona do código no projeto. Vamos adicionar uma anotação de configuração a ela. E uma anotação assíncrona ativada para. Essa anotação é importante para habilitar recursos assíncronos no projeto. Agora, vamos criar um método anotado com a anotação Bean. Ele retornará um ExecutorService. Vamos chamá-lo de serviço de executor padrão. Ele retornará um novo executor de thread único da classe executors. Esse bean fornecerá um thread sempre que quisermos executar código nele. Será um único encadeamento, o que significa que, se duas ou mais seções de código tentarem ser executadas nesse thread simultaneamente, teremos que esperar que a outra termine de ser executada. Optamos por usar um único fio porque isso facilita o controle dos processos em nosso aplicativo e nos permite evitar as condições de corrida com mais facilidade. Agora, vamos fazer uma pequena refatoração de código dentro do pacote de serviços de pontos pegajosos. Vamos criar uma classe chamada serviço de carteira de importação e adicionar a anotação do serviço a ela. Vamos criar um método chamado de importação de carteira. Transferirá o código do ouvinte de importação de carteira criado para o serviço de importação de carteira. Vamos também injetar os serviços necessários nessa classe. E vamos adicionar a carteira como um parâmetro ao método de importação da carteira. Na carteira criada, importe o ouvinte. Vamos remover todo esse código. Vamos injetar o serviço de importação de carteira nele. Agora, no método de evento sem aplicativo, vamos chamar o método de importação da carteira do serviço injetado passando a carteira de eventos como parâmetro. O método de importação da carteira contém o código que queremos executar de forma assíncrona. Para torná-lo assíncrono, basta anotar esse método com a anotação assíncrona, passando o nome do bean do serviço executor que criamos. Também devemos retornar um valor desse método, o que nos permitirá gerenciar essa chamada assíncrona a partir da cor do método. O valor retornado será um futuro. Um parâmetro do tipo void retornará um novo objeto de resultado assíncrono passando null para seu construtor. Agora, vamos testar a criação de uma carteira. Mas primeiro, vamos executar nosso node Bitcoin. Se ainda não estiver em execução. Vemos que nossa carteira foi criada imediatamente, mas quando verificamos os registros dos nós, ela ainda está carregando e importando os endereços da carteira. Ótimo. O nó concluiu a nova digitalização. Portanto, nossos processos de carregamento e importação de carteiras são assíncronos. Agora vamos fazer alguns ajustes finos. Vamos até o ouvinte de importação de carteira criado. No método de evento sem aplicativo registrará o retorno do método de importação da carteira e armazenará na variável de resultado. Faremos dessa variável um campo privado dessa classe. Agora, adicionaremos a seguinte declaração if. Antes de ligar para importar carteira. Se a variável resultante não for nula, chamaremos o método cancel nela, passando true como argumento. Isso é necessário porque, se tentarmos criar outra carteira quando uma ainda não tiver concluído a importação, precisaremos cancelar o processo de importação da primeira carteira criada. Vamos fazer outro ajuste fino na classe do aplicativo GUI para substituir o método stop. Dentro dele, adicionará o seguinte código. Esse código garantirá que o tópico criado pelo nosso ExecutorService padrão seja fechado depois que fecharmos nosso aplicativo. Agora, há outro problema com nosso aplicativo. Quando criamos uma carteira sem nosso nó Bitcoin em execução, as chamadas para criar ou carregar uma carteira e os endereços importantes falharão. Vamos ver como isso funciona na prática fechando nosso node Bitcoin e executando nosso aplicativo. Depois de criar uma carteira, parece que nosso aplicativo está funcionando normalmente, mas isso porque as exceções e outros tópicos não estão sendo relatados. Nossa carteira não poderia ter se comunicado com nosso nó enquanto nosso nó estava desligado. Quando ele tentou fazer isso, uma exceção foi lançada pelo thread e um thread terminou de ser executado. Vamos consertar isso. O que queremos que nosso aplicativo faça ao criar uma carteira é tentar se comunicar indefinidamente com nossa nota. Se, por algum motivo, não conseguir fazer isso após a primeira tentativa, faça-o, usaremos uma anotação do Spring Boot chamada retrial. Essa anotação faz com que o método anotado seja executado novamente, se gerar uma exceção. Para usá-lo, precisamos adicionar as seguintes dependências ao nosso arquivo POM. A primeira é a nova tentativa na primavera, a segunda são os aspectos da primavera. Agora, no método de importação de carteira, vamos adicionar a anotação de nova tentativa também passará alguns parâmetros para ela. A primeira será a expressão de exceção, que será definida como na porta de login, o serviço de carteira dot deve tentar abrir e fechar novamente o parêntese. Isso fará com que o aplicativo seja chamado de método de repetição antes de cada nova tentativa e só tente novamente se essa chamada de método retornar verdadeira. Também adicionaremos o parâmetro de tentativas máximas, definindo-o como a constante inteira do valor máximo. Essa configuração fará com que esse método seja repetido indefinidamente. Por fim, vamos adicionar o parâmetro de recuo, configurando-o como a anotação de recuo, passando o parâmetro de atraso de 1.000. Isso fará com que o aplicativo espere 1.000 milissegundos ou 1 s antes de executar o método em cada tentativa. Agora, vamos criar esse método de repetição. Seu tipo de retorno será um booleano. O método retornará a negação do resultado de uma chamada de método interrompida do thread atual. Essa chamada retornará true se o thread atual não for interrompido ou falsa, caso contrário. Portanto, se o aplicativo for fechado ou se outra carteira for criada entre cada nova tentativa, esse tópico será interrompido e o método de importação da carteira não será mais repetido. Mais uma coisa para que a anotação de nova tentativa funcione, precisamos adicionar a anotação de nova tentativa ativada na classe de configuração assíncrona. Vamos fazer isso. Agora. Vamos executar nosso aplicativo com nosso nó fechado e fazer alguns testes. Vamos criar uma nova carteira. Agora, vamos começar nosso nodo. registros do node, vemos que a carteira criada foi carregada e a nova verificação foi concluída. Agora. Agora vamos criar outra carteira. Vemos nos registros do node que ele também foi criado, carregado e importado com sucesso . Ótimo. 29. 27 Receber bitcoin parte 4 skillshare 2: Neste vídeo, continuaremos a integrar nossa carteira com nosso node. A próxima etapa da integração é ouvir as mensagens que o nó envia quando recebe uma transação em um endereço importado. Para isso, criaremos uma classe chamada node task, que terá um método que será executado em um loop infinito em outro thread após o início do aplicativo. Esse método escutará continuamente as transações que são recebidas pelo node em qualquer um dos endereços atualmente carregados de nossos aplicativos. Quando encontrar um, fará com que nosso aplicativo o trate adequadamente. Então, vamos criar um novo pacote chamado node no pacote BYOD W. Dentro dela, criará uma classe chamada gooey started node listener. Vamos adicionar uma anotação de componente a ela. Essa classe será um ouvinte acionado pelo evento gooey started publicado quando o aplicativo for iniciado. Portanto, ele implementará o ouvinte do aplicativo com esse evento como seu parâmetro de tipo. Vamos implementar seu método. Vamos adicionar o novo node que o serviço de tarefas criará como um campo privado nesta classe. Vamos criar o novo serviço. Agora, vamos injetá-lo no ouvinte do node iniciado pela GUI. No método de evento não relacionado ao aplicativo, chamará o método de execução da tarefa do nó. Vamos criar esse método na tarefa do node. Vamos adicionar a anotação do serviço a essa classe. Agora, adicionaremos uma dependência que a tarefa do node precisará no arquivo POM. Será a biblioteca do herói MQ. Vamos clicar no botão carregar alterações do Maven. Essa biblioteca gerencia a comunicação entre o aplicativo e o zero MQ. Zero MQ é um agente de mensagens que recebe mensagens do node Bitcoin. Essas mensagens serão enviadas para um URL local e coletadas por nosso aplicativo por meio de zero MQ de volta à tarefa do node. Vamos adicionar a anotação assíncrona ao método run. Vamos passar o serviço executor de notas como seu parâmetro. Isso fará com que esse método seja executado forma assíncrona em outro thread gerenciado pelo serviço executor do node que vamos criar na classe de configuração assíncrona, vamos criar o serviço executor do node. Como o serviço de execução padrão, ele será gerenciado por um novo executor de thread único. Agora, vamos injetar o objeto de soquete de zero MQ nessa classe. Esse campo será chamado de assinantes, pois tratará de uma assinatura do agente de mensagens zero MQ. No método de execução, vamos definir o tempo limite de recebimento do assinante para 1.000. Isso adicionará um segundo de atraso cada vez nosso aplicativo consultar zero e Q para pesquisar mensagens. Vamos chamar esse método de subscrição de assinantes, passando os bytes da string rod TX como parâmetro. Isso fará com que nosso aplicativo ouça apenas mensagens relacionadas a transações de roubo de Bitcoin que são enviadas para zero. Mq também chamará o método de conexão dos assinantes, passando a variável z MQ URL para ele. Vamos injetar essa variável nessa classe. Adicionaremos uma anotação de valor ao argumento do construtor, passando essa string como parâmetro. Portanto, o valor dessa variável será injetado nessa classe por meio uma propriedade do aplicativo chamada z e o URL de q ponto será definido agora, o valor dessa variável deve corresponder ao mesmo valor que Eu configurei em nosso arquivo bitcoin.com. Então, vamos copiar o valor definido para a configuração do z MQ pub rock TX bitcoin.com e colá-lo aqui. Agora, voltando ao node, o método de execução de tarefas criará nosso loop contínuo. Vamos criar um loop inteiro. Ele será executado enquanto o thread atual não for interrompido. Dentro do loop, chamaremos os assinantes de destruírem o método STR e armazenaremos o resultado na variável topic. A destruição do método STR consulta zero MQ para qualquer mensagem e retorna uma string se encontrar uma. No nosso caso, essa string conterá o nome do tópico, que será igual a ra TX para transações brutas. Em seguida, adicionaremos um loop if verificando a variável do tópico. Se seu conteúdo for diferente do Ratti x , chamaremos para continuar fazendo o loop funcionar novamente desde o início. Caso contrário, chamaremos o método wreck V dos assinantes e armazenaremos o conteúdo na variável content. A destruição do método é semelhante ao rec VNTR, mas retorna uma matriz de bytes em vez de uma string. Nesse ponto, essa matriz de bytes conterá a transação bruta ou o nó enviado para zero MQ. Agora, converteremos a matriz de bytes no objeto de transação Bitcoin Java. Para fazer isso, usaremos o código a seguir. Devemos adicionar uma instrução throws IOException à assinatura desse método. Na GUI, iniciei o node listener. Também precisamos agrupar a chamada de execução em um bloco try-catch como este. De volta ao método de execução. Agora, usaremos um serviço de aplicativos de editores de eventos para publicar um evento. Vamos injetar esse serviço nessa classe. Primeiro. Passaremos um novo evento de transação recebida para o método de publicação do evento. Para a transação recebida instanciação do evento passará isso e o objeto da transação antes criar a nova classe de evento, vamos adicionar uma peça que falta para que esse método funcione. Vamos criar uma nova classe chamada configuração de nós. Vamos movê-lo para um novo pacote de configuração node dot. Vamos adicionar uma anotação de configuração a ela. Nesta classe, adicionaremos alguns beans para o objeto Socket injetado nas tarefas do node funcione. O primeiro bean será o ser do contexto Z. O segundo feixe será o soquete zero MQ. Ele será chamado de assinante. E adotará em seu método o contexto Z criado acima. Ele retornará os contextos Z para criar uma chamada de método de soquete passando a subconstante do tipo de soquete como seu parâmetro. Agora, de volta ao node, a tarefa criará o evento da transação recebida, criará no pacote de eventos node dot. Passaremos a tarefa do node para o superconstrutor e injetaremos a transação em um campo de transação privada. Também vamos criar um método getter para a transação. Agora, vamos criar um pacote de ouvintes no pacote node. Dentro dela. Vamos criar uma transação recebida pelo ouvinte para esse evento. Vamos adicionar uma anotação de componente a ela. Esse ouvinte será responsável por filtrar as transações recebidas identificando se elas têm endereços pertencentes a uma carteira atualmente carregada. Ele implementará um ouvinte de aplicativo com o evento da transação recebida como seu parâmetro de tipo. Vamos implementar seu método. Nesse método, vamos pegar a transação do evento e armazená-la na variável de transação. Agora, a primeira coisa que faremos é identificar os endereços de saída da transação recebida. Para fazer isso, criará a variável de endereços, que será uma lista de cadeias de caracteres. Em seguida, atribuiremos o resultado da seguinte expressão a ela. Mapeará as saídas da transação passando por um método de análise do analisador de endereços. Agora, vamos injetar e criar o serviço de análise de endereços. Vamos criá-lo no pacote de serviços node dot. Vamos adicionar a anotação do serviço a ela. Agora, vamos criar o método de análise. Ele retornará uma string e tomará uma saída de transação como seu parâmetro. Esse método será responsável por extrair o endereço da saída de uma transação para a transação recebida. O ouvinte converterá o resultado em uma lista. Em seguida, para fins de teste imprimirá todos os endereços analisados. Agora vamos implementar o método de análise. A primeira coisa que faremos é obter a chave pub do script de transação e atribuí-la a essa variável. Não se preocupe, explicaremos o que é uma chave de script pub e outros detalhes da transação. No próximo vídeo, retornaremos o resultado da seguinte instrução switch. Se o tipo da chave pub do script for igual à constante P2 WP k, h, que é o tipo de nossos endereços de carteira atuais. Em seguida, retornaremos a chave pub do script P2, chamada do método de endereço WP k h. Passando a chamada do método Get do prefixo de endereço factory como o parâmetro que passa a constante de Segway para ela. A declaração de caso padrão será uma string vazia. Vamos injetar o prefixo de endereço factory nessa classe. Agora, vamos fazer alguns testes. Meu node Bitcoin já está em execução. Certifique-se de que o seu também seja. Vamos para a aula de teste de recebimento de Bitcoin e executá-la. O teste falhou porque ainda não modificamos nosso teste de GUI para considerar o controlador da tabela de endereços. Lembre-se de que nosso ouvinte iniciado pela GUI lida com o problema de usar essa condição if. Poderíamos usar a mesma condição if em nosso fixo, mas vamos fazer isso de uma forma mais organizada. Vamos ao evento iniciado pela GUI. Vamos mudar o tipo de aplicativo GUI para objeto. Simplesmente publicaremos o evento gooey started em nossa classe de teste de GUI, da mesma forma que fizemos aqui na classe de aplicativos de GUI. Na classe de teste de GUI, vamos remover todo esse código. Agora, vamos copiar essa linha do aplicativo GUI e colá-la aqui. Vamos remover todas essas importações não utilizadas e esse campo privado não utilizado. Agora, vamos fazer o teste de recebimento de Bitcoin novamente. Nosso teste falhou, mas vemos aqui nos registros de teste que são dois endereços impressos pelo aplicativo. Isso aconteceu porque imprimimos os endereços da transação que nosso teste fez um dos endereços de nossa carteira. Um desses endereços é nosso, o outro é um endereço de mudança do remetente. Ótimo. Vemos que o que fizemos até agora funcionou. Vamos fazer uma refatoração na classe de teste de GUI. Vamos remover essas importações não utilizadas. Na classe de aplicação GUI. Vamos incluir essa linha de código que fará com que nosso thread de serviço de executor de notas pare de executado depois que fecharmos nosso aplicativo. No próximo vídeo, aprenderemos mais sobre as transações de Bitcoin para nos preparar para o que vem a seguir. 30. Transações de Bitcoin: Entradas, Saídas, scripts e o conjunto UTXO: Nesta apresentação, aprenderemos alguns conceitos sobre transações de Bitcoin. Será útil entender melhor a implementação do recebimento de Bitcoins em nossa carteira de aplicativos. Vamos recapitular o que aprendemos até agora sobre transações de Bitcoin e gradualmente adicionar complexidade à nossa compreensão delas. Portanto, uma transação de Bitcoin é comumente usada para transferir Bitcoins da pessoa a para a pessoa B. Uma transação de Bitcoin pode ser composta por muitas entradas e muitas saídas. Uma entrada de transação indica o proprietário anterior do Bitcoin ou o remetente da transação. saída de uma transação indica o destinatário das moedas ou o proprietário das moedas após a publicação da transação. Nesta imagem, temos uma transação simples com uma entrada e duas saídas. Diz que um Bitcoin foi transferido de John, que assinou a entrada dessa transação. A saída zero indica que 0,9 Bitcoins foram enviados para casar. Vou colocar que um indica que 0,099 Bitcoins foram enviados de volta para John como a mudança. Os valores de Bitcoin não podem ser divididos em entradas. Como John queria enviar 0,9 Bitcoins para se casar, ele só tinha um Bitcoin. Ele precisava criar uma saída de mudança para si mesmo. Mas seu valor é de 0,099 Bitcoins, não 0,1 Bitcoins, como você poderia esperar. A diferença, que é de 0,001 Bitcoins, é a taxa de transação necessária para que a transação seja incluída no blockchain. Então, a partir dessa imagem, tiramos três lições. A soma dos bitcoins nas entradas não pode ser menor que a soma dos Bitcoins e das saídas. O valor do Bitcoin nas entradas é fixo, embora possa ser escolhido à vontade e nas saídas, desde que atenda à regra anterior. Finalmente, a taxa de transação é a diferença entre a soma dos valores de Bitcoin nas entradas e a soma dos valores e saídas do Bitcoin. Aumentando a complexidade. Também aprendemos sobre os campos que fazem parte de uma entrada e de uma saída de transação. E a entrada sempre se refere a uma saída de uma transação anterior. Ele faz isso usando o ID da transação anterior e o índice de saída da transação anterior. Seria redundante que a entrada tivesse um campo de valor. Esses dois campos são suficientes para identificar qualquer saída de transação no blockchain. Uh, a entrada da transação também deve conter uma assinatura válida produzida usando a mesma chave privada usada para derivar o endereço da saída à qual a entrada se refere. Observe que a entrada de uma transação não tem um campo indicando o valor do Bitcoin. Isso porque o valor é automaticamente igual ao valor de saída ao qual se refere. A saída da transação tem dois campos. Um é o endereço usado para receber bitcoins. E o endereço é uma sequência codificada e, por si só, não revela o dono das moedas. É por isso que consideramos o Bitcoin pseudônimo. O outro campo é a quantidade que indica o valor do Bitcoin bloqueado pelo endereço. Agora, vamos aumentar a complexidade mais uma vez explicando exatamente o que exatamente as entradas e saídas da transação contêm. A entrada da transação tem os seguintes campos. O ID da transação anterior, que é uma sequência hexadecimal exclusiva, é obtido por meio do hashing da transação serializada anterior. O índice de saída da transação anterior é um número inteiro. Como uma transação pode ter muitas saídas, uma saída específica pode ser identificada de forma inequívoca pelo ID da transação e pelo índice de saída. O ScriptSig ou o campo de testemunhas. A assinatura de entrada é adicionada ao campo ScriptSig em transações que não sejam do Segway. Nas transações do Segway, a assinatura é adicionada ao campo de testemunha, que não conta para o tamanho da transação. A saída da transação tem os seguintes campos. A chave do script pub. chave Script pub contém o endereço decodificado e o campo de quantidade que determina a quantidade de Bitcoin bloqueada pelo endereço. Agora, vamos ver como criar uma transação de Bitcoin por meio de um exemplo. Nosso objetivo neste exemplo é enviar 1,5 bitcoins para esse endereço. Antes de começar, temos uma transação confirmada, o que significa que ela já está armazenada no blockchain. Ele tem uma saída com dois bitcoins, que posso gastar, pois tenho uma chave privada que foi usada para criar seu endereço e que pode ser usada para assinar uma entrada de transação em uma nova transação. Então, vamos criar uma nova transação, adicionaremos uma entrada a ela. A entrada será referida à nossa transação por meio do campo de ID da transação anterior. O índice de produção da transação anterior é zero, pois é o índice de saída de nossa produção. O campo ScriptSig é composto por uma assinatura produzida usando a mesma chave privada usada para produzir o endereço de nossa saída. E uma chave pública, que é a mesma chave pública derivada usando nossa chave privada. A transação terá duas saídas. As saídas zero conterão um campo de chave de script pub composto, entre outras coisas, pela chave pública com hash do endereço. Queremos enviar nossos bitcoins para. Esse hash é obtido por Beck 32 decodificando o endereço. Back 32 é o algoritmo usado para codificar o hash de uma chave pública, produzindo em um segundo qual endereço? Base 58 é outro algoritmo usado para fazer o mesmo para endereços que não sejam segmentados. Como estamos enviando bitcoins para um endereço de segmento, devemos usar o Beck 32. O campo de quantidade dessa saída será igual a 1,5, que é a quantidade de Bitcoin que queremos enviar, precisará de uma segunda saída para a alteração. Sua chave de script pub conterá uma chave pública com hash obtida pela decodificação de Beck 32 e um endereço que pertence a nós, derivado de uma chave privada sobre a qual temos controle. quantidade será de 0,49 Bitcoins, o que somado a 1,5 da saída zero é igual a 1,99. Portanto, temos uma diferença de 0,01 entre a soma dos valores de Bitcoin em entradas e saídas. Essa diferença será a taxa de transação necessária para a transação seja incluída no blockchain por um menor. Falamos sobre o ScriptSig e o script pub key, mas ainda não explicamos o que essas coisas realmente são. O Bitcoin tem uma linguagem de contrato inteligente chamada script. Um contrato inteligente é uma forma sofisticada de se referir a um programa escrito em uma transação e executado pela rede Bitcoin. Os campos de chave scriptSig e script pub são criados com código de linguagem de script. Essa linguagem é interpretada combinando o ScriptSig de uma entrada e a chave script pub de uma saída e verificando se o ScriptSig satisfaz as condições codificadas pela chave pub do script. Você pode considerar esse mecanismo como um mecanismo de chave e bloqueio, que o ScriptSig é a chave para desbloquear a chave pub do script, que é a fechadura. Se um ScriptSig for válido para desbloquear uma chave pub de script, você poderá gastar os fundos de saída bloqueados por ela. Um ScriptSig tem esse nome porque geralmente contém uma assinatura que satisfaz uma condição específica da chave de pub do script. Da mesma forma, a chave script pub tem esse nome porque continha uma chave pública nas primeiras transações de Bitcoin. Mas, em teoria, qualquer código de script arbitrário pode ser incluído em ambos os campos. A restrição exclusiva para que um programa de script seja válido é que ele retorne verdadeiro ao final de sua execução. Há muitos tipos de programas de script, também conhecidos como tipos de script. Um deles é o hash de pagamento para chave pública usado em transações simples não sequitur. Vamos ver como isso é executado neste exemplo, todos os scripts de Bitcoin são executados da mesma forma, o que muda entre eles ou o código que está sendo executado? Então, começando com nossa transação confirmada do slide anterior , mostramos aqui apenas sua saída zero com o conteúdo da chave script pub na caixa cinza. Em transações de hash de pagamento para chave pública, o campo script pub key é composto por opcodes e pelo hash de chave pública. E opcode é uma instrução de linguagem de script. Eles são identificados pelas letras OP no início. sublinhado ascendente é igual, por exemplo, compara dois elementos e retorna verdadeiro se eles forem iguais. Cada script de chave pub e scripts de hash de pagamento para chave pública têm essa sequência de código que difere apenas em seus hashes de chave pub. Agora temos nossa nova transação, que é a mesma do slide anterior. Desta vez, mostramos apenas sua entrada aqui. Seu conteúdo do ScriptSig está na caixa cinza. Em scripts de hash de pagamento para chaves públicas. O ScriptSig tem apenas uma assinatura seguida por uma chave pública. Agora vamos ver como os dois campos são combinados e executados. Primeiro, o conteúdo ScriptSig da entrada é concatenado com o conteúdo da chave script pub da saída referenciada pela entrada nesta ordem. Em seguida, cada elemento do script combinado é colocado em uma pilha de execução da esquerda para a direita. Se o elemento for um opcode, ele poderá atuar em outros elementos na pilha, processando-os e adicionando outros elementos à pilha. Então, vamos ver como esse script é executado. A assinatura é o primeiro elemento da esquerda para a direita. Portanto, ele é colocado primeiro na pilha. O próximo elemento é a chave pública, que também é inserida na pilha. O próximo elemento é o opcode up sublinhado. Up, underscore up codifica uma instrução para duplicar o último elemento adicionado à pilha e adicionar a cópia à pilha. O próximo elemento é o opcode op underscore hash 160. Ele remove o último elemento adicionado à pilha, aplica a função hash 160 a ele e adiciona o resultado do hash de volta à pilha. Então, acabamos com o hash da chave pública no topo da pilha de execução. O próximo elemento a ser adicionado à pilha é o hash da chave pública. Em seguida, temos o sublinhado op equal verify opcode. Esse opcode remove dois elementos do topo da pilha de execução e os compara se eles forem iguais ao que o script continua sendo executado. Caso contrário, a execução falha e a transação é invalidada. Essa etapa é importante porque valida que a chave pública do ScriptSig é igual à chave pública usada para gerar o endereço da saída da qual ele está gastando. O último elemento do script é o opcode op underscore check sig. Ele remove dois elementos do topo da pilha de execução e valida se o primeiro elemento é uma assinatura válida para o segundo elemento dessa transação específica, se for uma assinatura válida, um booleano verdadeiro é adicionado à pilha. Se for inválido do que um booleano, false será adicionado à pilha. Finalmente, depois que todos os elementos do script forem adicionados à pilha de execução, a entrada da transação seria considerada válida se o último elemento adicionado fosse verdadeiro. Caso contrário, a entrada da transação é inválida. Esse processo deve ser repetido para cada entrada de transação. Para que uma transação seja considerada válida, todas as suas entradas devem ser válidas. Há muitos tipos de script. O script de pagamento para chave pública foi o primeiro script de Bitcoin criado, mas hoje está obsoleto e raramente é usado. As primeiras transações de Bitcoin contêm o tipo de script. Em vez de usar o hash da chave pública, é a chave pub do script, use a chave pública diretamente. O script de hash de pagamento para chave pública foi exemplificado no último slide. Foi o tipo de script mais usado desde o aumento da relevância das transações de Segway nos últimos anos. Hoje, ainda é comumente usado, então é bom saber sobre isso. O script de hash de chave pública pay to witness é o tipo de script mais usado atualmente em transações de Bitcoin. A razão para isso é que é vantajoso usá-lo, pois as transações com ele são menores e, portanto, têm uma taxa de transação menor. Esse tipo de script tem uma chave de pub de script menor e o conteúdo do ScriptSig é movido para o campo de testemunha, o que não contribui para o tamanho da transação. Por esses motivos, implementaremos primeiro esse tipo de script em nossas carteiras O hash de pagamento para script é outro script usado principalmente para transações com várias assinaturas. As transações com várias assinaturas exigem mais de uma assinatura para gastar uma saída. O hash do script de pagamento para testemunhar é a versão testemunha do script de hash de pagamento para testemunhar. Sua assinatura é movida para o campo da testemunha. Portanto, tem as mesmas vantagens que o script de hash de pagamento para testemunhar uma chave pública tem. O hash de pagamento para testemunhar uma chave pública envolto em um script de hash pago por script também é conhecido como segmento aninhado ou segmento de rap. Também é comumente usado e sua principal função é tornar carteiras antigas que não sejam compatíveis com o segmento nativo, compatíveis com transações da Segway. Aprenderemos mais sobre o tipo de script mais adiante no curso. Finalmente, outro tipo de script é o script root pay to tap. É o tipo de script criado mais recentemente, adicionando mais recursos e privacidade às transações de Bitcoin. Agora, vamos ver um resumo de como criar entradas e saídas de transações do ponto de vista de uma carteira, começando com uma semente mnemônica e uma frase secreta. Por meio de um algoritmo criptográfico, combinamos os dois e obtemos uma semente raiz. Então, por meio de uma série de transformações foram produzidas chaves mestras e chaves estendidas. Obtemos muitas chaves privadas. Aqui, mostramos apenas uma dessas chaves privadas. As mesmas transformações também podem produzir chaves públicas. Uma chave pública também pode ser produzida a partir de uma chave privada específica, que mostramos aqui em nosso exemplo. A partir de uma chave pública, obtemos um endereço usando a função hash 160 e codificando o resultado por meio da codificação Beck 3.2 no caso de endereços de segmentos ou codificação de base 58 no caso de endereços não segmentados. Para receber Bitcoins, você mostra seu endereço para alguém para que alguém possa enviar bitcoins para ela. Quando um remetente coloca seu endereço em sua carteira e envia uma quantia em Bitcoin para ela, sua carteira decodifica o endereço volta para um hash de chave pública. Em seguida, ele criará uma transação com uma saída contendo uma chave pub de script equivalente a esse endereço. O tipo de chave pub do script dependerá do tipo do endereço. Nesse caso, a carteira identificou que o tipo de endereço é compatível com um script de hash de pagamento para chave pública. Depois de receber Bitcoins nesse endereço, o destinatário pode gastá-los por meio de uma nova transação. O conteúdo dos novos campos de entrada da transação dependerá do tipo de chave de pub do script que será gasto. Nesse caso, a carteira criará uma transação com uma entrada contendo um ScriptSig com uma assinatura gerada usando a mesma chave privada que originou a chave pública originada o endereço que recebeu Bitcoins anteriormente. detalhes sobre a assinatura de uma transação Veremos detalhes sobre a assinatura de uma transação em um vídeo futuro. A chave pública citada anteriormente será adicionada após a assinatura no campo ScriptSig. Finalmente, a entrada também fará referência à saída da transação não gasta usando o ID da transação anterior e os campos do índice de saída da transação anterior , conforme explicado anteriormente. Agora vamos aprender o importante conceito do conjunto UTXO. Lembre-se de que UTXO significa saída de transação não gasta. Bitcoin tem a importante característica de não permitir gastos duplos. Em outras palavras, você só pode gastar Bitcoins com saídas de transações não gastas. O conjunto UTXO é o conjunto de todos os UTXOs atualmente existentes. Esse conjunto é armazenado por nós em um banco de dados separado, o que permite uma recuperação rápida por carteiras. O conjunto UTXO está sendo constantemente atualizado com cada nova transação adicionando e removendo saídas de e para o conjunto. Utxos são saídas que ainda não foram referenciadas em nenhuma entrada. Portanto, o conjunto UTXO contém todas as moedas disponíveis para serem gastas. O número de bitcoins em um endereço é igual à soma de todos os Bitcoins de todos os UTXOs cujas chaves de script pub referenciavam o endereço decodificado. Portanto, o Bitcoin Core Node fornece um método de API chamado list unspent que retorna todos os UTXOs que fazem referência aos endereços que você passou como parâmetros para ele. Ao usar o método de lista não gasta, você pode calcular facilmente o saldo de um endereço e as informações da transação descoberta , como o ID e o índice da transação UTXO, bem como seu chave de pub do script. Assim, você pode criar entradas de transação para gastar seus Bitcoins a partir do UTXO. Depois de gastar o UTXO, ele é removido do conjunto UTXO. Agora vamos ver um diagrama explicando como nosso aplicativo detectará as transações recebidas e nos informará sobre os bitcoins que receberão. Esse será o último slide desta apresentação, que introduziu muitas informações complexas. Não se preocupe se você não absorveu tudo no início. Ao longo do curso, reutilizaremos as informações aprendidas para nos aprofundarmos nelas, para que tenhamos muitas oportunidades de compreendê-las melhor. Agora, de volta ao diagrama. Aqui temos retângulos representando o aplicativo, o nó Bitcoin e a rede Bitcoin. As transações são criadas e transmitidas por nós da rede Bitcoin. Essas transações, quando confirmadas, já estão armazenadas no blockchain. Quando não confirmados, eles permanecem no templo, um banco de dados contendo todas as transações não confirmadas. Cada nó tem uma cópia das transações mentais que eventualmente são detectadas por nossos nós , que já importaram nossas carteiras e endereços de aplicativos. Por meio de zero notificações de MQ, as transações são enviadas para nosso aplicativo. Quando nosso aplicativo carrega uma carteira, ele filtra todas as transações recebidas que não contêm nenhum de seus endereços. Em seguida, ele enviará uma lista de chamadas não gastas para o nó, passando como parâmetros todos os endereços das transações recebidas que permaneceram após a filtragem. O nó retornará todos os UTXOs relacionados a esses endereços. Nossa carteira então analisará esses UTXOs para calcular o saldo de Bitcoin para cada um de seus endereços. Em seguida, mostraremos as informações obtidas na tabela de endereços. 31. 29 Receber parte do bitcoin 5 skillshare 2: Neste vídeo, implementaremos a lista de clientes não gastos que nos permitirá coletar informações sobre UTXOs após recebermos transações. Então, dentro do pacote do cliente node dot, vamos criar a lista de nós de clientes não gastos. Vamos adicionar uma anotação de serviço a ela. Vamos também injetar o cliente node nele. Agora vamos criar o método de lista não gasto. Ele retornará uma lista de UTXOs, que é um registro que criaremos. Ele tomará como parâmetros uma lista de endereços e um nome de carteira. Vamos criar o registro UTXO no pacote BYOD w dot domains. O UTXO conterá os seguintes campos. O TX ID, que é um acrônimo para ID da transação. O campo vout, que representa o índice de saída, o endereço, o rótulo, que não usaremos no momento. A chave do script pub. O valor que representa o valor do Bitcoin, as conformações que conterão o número de conformações que a transação UTXOs tem. O número de conformações de uma transação é o número de blocos que foram adicionados ao blockchain depois que a transação foi inserida em um bloco e esse bloco foi adicionado ao blockchain. Esse número inclui o bloco que contém essa transação. Portanto, se uma transação tiver duas confirmações, isso significa que ela já foi incluída em um bloco. Esse bloco foi adicionado ao blockchain e outro bloco foi adicionado depois disso. Vamos adicionar mais dois campos. Esses campos não serão usados por enquanto, mas podem ser úteis em outros tipos de transações que veremos mais adiante no curso. Eles são o roteiro de resgate e o roteiro da testemunha. Agora, de volta à lista de nós, o cliente não gasto chamará o método de solicitação do cliente node e armazenará o resultado na variável de matriz utxOS e passará os seguintes parâmetros para o método. Os últimos três parâmetros farão parte da lista de poemas da API Bitcoin node. O primeiro é o número mínimo de conformações que os UTXOs de retorno devem ter. O segundo é o máximo. Como queremos que todos os UTXOs definam zero como o mínimo e o valor inteiro máximo como o máximo. O terceiro parâmetro é a lista de endereços. Agora, converteremos a matriz resultante em uma lista usando esse código e a retornaremos. Agora, de volta ao ouvinte da transação recebida. Vamos remover essa linha de código porque era só para testes. Vamos testar o cliente não gasto da lista de nós. Vamos obter os UTXOs para esses endereços. Vamos injetar o cliente nessa classe primeiro, o método list unspent passará a variável addresses. O segundo argumento será o nome da carteira do teste de recebimento do Bitcoin. Vamos copiá-lo e usá-lo como segundo parâmetro. Agora, vamos adicionar essa linha para imprimir cada UTXO obtido na tela. Agora, vamos executar nosso node Bitcoin se ele ainda não estiver em execução. Agora, vamos fazer o teste de recebimento de Bitcoin e executá-lo. Nos registros de teste, vemos que ele imprimiu um UTXO com todos os seus dados. Observe que seu endereço é o mesmo que o endereço de recebimento de nossa carteira. Retroceda o vídeo para conferi-lo. O valor é um, que é esperado porque é o mesmo valor de Bitcoin enviado e, no teste, tem zero conformações porque nenhum bloco lembra o nó desde a transação. Agora vamos excluir essas linhas porque elas eram apenas para teste. Vamos também remover o cliente injetado dessa classe. Agora, adicionaremos um filtro a esse stream. Queremos processar somente transações da carteira atualmente carregada pelo aplicativo. Esse filtro será responsável por isso. O filtro verificará se o endereço não está vazio. Se a carteira atual contiver esse endereço. Então, vamos injetar a carteira atual nessa classe. Em seguida, chamaremos os endereços get como método de strings. Em seguida, verificaremos se ele contém o endereço. Oh, uma letra S estava faltando aqui. Agora vamos criar o método get addresses as strings. Ele retornará uma lista de sequências de caracteres. O valor retornado resultará da chamada dos endereços get como método strings no campo de endereços que criaremos. Então, vamos criar esse campo. Ele terá uma nova classe de endereços como seu tipo. E vamos inicializá-lo aqui. Vamos criá-lo no pacote observables. Vamos também criar seus endereços get como método de strings. Primeiro, adicionaremos um campo de endereços privados. Será um mapa em que o tipo de chave será um tipo de endereço e o tipo dos valores será outro mapa. O segundo mapa será um HashMap vinculado com strings como chaves e endereço como o tipo de seus valores. Usaremos essa estrutura de dados para armazenar os endereços. A razão para usar essa estrutura de dados é que ela nos permite separar e consultar os endereços da carteira por tipo de endereço. O segundo mapa é um HashMap vinculado porque esse tipo de mapa mantém a ordem de inserção. Finalmente, o segundo mapa nos permite consultar a lista de objetos de endereço por suas sequências de cadeias de endereço. Agora, no método get addresses as strings, retornará o seguinte código. A função flatMap será usada para obter todos os endereços no segundo conjunto de chaves do mapa e retornar um fluxo contendo todos eles. Em seguida, converteremos a string resultante em uma lista. Ok, agora podemos usar o método get addresses as strings para obter todos os endereços criados para a carteira atual. Mas uma coisa está faltando. Também precisamos preencher o campo de endereços a partir da classe de endereços. Para fazer isso, adicionaremos o código a seguir na atualização. serviço de carteira atual definirá os endereços da carteira atual, passando as chaves pub estendidas da carteira como parâmetro. Agora, vamos criar o método atual de endereços do conjunto de carteiras. Ele chamará o método set addresses do campo de endereços, passando as chaves estendidas como parâmetro. Em seguida, criaremos esse método na classe de endereços. Vamos adicionar o código a seguir a ele. Usaremos a função de coleta para obter um mapa das chaves estendidas do pub. Dentro dela, adicionará uma chamada de método to map. Seu primeiro argumento criará um tipo de endereço usando o campo estendido do tipo de chave pub. Esse argumento define a chave do mapa resultante. O segundo argumento definirá o valor do mapa e conterá o código a seguir. Novamente, ao combinar as funções de coleta e mapeamento , ele será definido como um Hashmap vinculado. As chaves serão as sequências de strings de endereços de chaves pub estendidas sequências de strings e os valores estarão lá objetos de endereço correspondentes. Finalmente, a parte filtrante desse fluxo está concluída. No próximo vídeo, usaremos o que construímos para continuar construindo o recurso C de recebimento de Bitcoins, sim. 32. 30 Receber bitcoin parte 6 skillshare 2: Neste vídeo, processaremos os UTXOs das transações que chegam à nossa carteira. Portanto, no método de evento sem aplicativo, no ouvinte da transação recebida, vamos adicionar a seguinte instrução if. Se a lista de endereços não estiver vazia, chamaremos o método de atualização no serviço utxOS de atualização que criaremos. Esse método usará os endereços e o nome da carteira atual como parâmetros. Vamos injetar esse serviço nessa classe. Agora, vamos criar esse serviço no pacote de serviços de pontos da GUI. Vamos adicionar a anotação do serviço a ela. De volta ao ouvinte da transação recebida. Vamos terminar de injetar o serviço. Agora, vamos criar o método de atualização no serviço de atualização UTXos. Adicionaremos uma anotação assíncrona a esse método e a executaremos no thread de serviço de execução padrão. A razão para executar esse método e outro tópico é que ele chamará o método de API de nós não gastos da lista, que pode ser lento. Então, vamos executá-lo de forma assíncrona para evitar o bloqueio da interface do usuário. No método de atualização, chamará o método list unspent da lista de nós do cliente não gasto. Vamos injetar o cliente nessa classe. Vamos passar os endereços e o nome da carteira como parâmetros para a lista. método não gasto armazenará o resultado da chamada do método na variável utxOS. Agora, injetaremos uma nova atualização, serviço atual de endereços de carteira, nessa classe. Vamos criá-lo no pacote de serviços de pontos da GUI. Vamos terminar de injetar o serviço. Em seguida, chamaremos o método de atualização passando utxOS como parâmetro para ele. Vamos criar esse método. Vamos adicionar a anotação de serviços a ela. Agora, adicionaremos o código a seguir para criar um mapa em que as chaves são endereços e os valores são listas de UTXOs contendo esses endereços. Para fazer isso, chamaremos o método collect no fluxo UTXO passaremos a chamada MyMethod agrupando coletores para ele. Passando o método de endereço UTXO como seu parâmetro. Armazenaremos o valor retornado na variável do grupo UTxOS. Então, para cada grupo par de valores-chave UTXO definirá o saldo de endereço correspondente. São confirmações e o mercado é usado. Vamos implementar o método de equilíbrio definido. Retornará a soma de todos os valores de UTXOs usando esse código. Usando o método map to double no fluxo da lista UTXO, obterá um fluxo com todos os valores de UTXO da lista UTXO. Para obter sua soma basta chamar o método de soma no resultado. Agora, vamos injetar a carteira atual nessa classe. Em seguida, chamaremos o método balanceado de endereços do conjunto de carteiras atual , que criará a passagem do endereço e da soma como seus parâmetros. Vamos criá-lo. Dentro, ele chamará o método balanceado de endereços definidos, passando os mesmos parâmetros para ele. Em seguida, criaremos esse método. Dentro, ele chamará os endereços de obtenção como método de mapa, que criará. Vamos criá-lo. Ele retornará um mapa em que as chaves são endereços, cadeias de caracteres e os valores são endereçados como objetos. Ao usar o código a seguir, retornará um mapa contendo todos os endereços. Ao chamar o método string nos endereços, os valores obterão um fluxo contendo todos os mapas do campo privado dos endereços. Então, com esse método flatMap, a chamada converterá o fluxo de mapas em um fluxo de entradas de mapa. Finalmente, usando o método de coleta no fluxo resultante e o método de dois mapas com esses parâmetros obterá o mapa desejado. No resultado de obter endereços, uma chamada de mapa chamará o método get para obter um objeto de endereço por sua string de endereço. Em seguida, definiremos o saldo do endereço para a variável soma. Agora, vamos criar o método de saldo definido no registro de endereço. Opa, não podemos adicionar configuradores em um registro, então teremos que converter o registro de endereço em uma classe. Vamos fazer isso com uma pequena ajuda do nosso IDE. Vamos remover esses métodos porque não precisaremos deles. Vamos criar o centro de equilíbrio agora. E remova a palavra-chave final aqui. No gerador sequencial de endereços. Vamos adicionar zero como o terceiro parâmetro na instanciação do endereço aqui. Vamos também mudar o nome dos getters, fazendo com que eles comecem com get. Agora, no serviço de atualização de endereços da carteira atual, vamos criar o método de confirmação definida. Confirmação. Nesse caso, nos referiremos ao saldo do endereço e ele será definido como igual ao número de conformações do UTXO com menos conformações para esse endereço. Por exemplo, digamos que um endereço tenha um saldo de dois Bitcoins, com cada Bitcoin vindo de uma transação diferente. Uma dessas transações tem duas confirmações, a outra tem apenas uma. Nesse caso, consideraremos que o saldo dos endereços tem uma conformação. Para fazer isso, usaremos o código a seguir. Obteremos um stream contendo todas as confirmações da lista UTXOs aprovada. Para obter esse fluxo, chamaremos o método map too long no fluxo da lista UTXO, passando a referência do método de confirmações UTXO como seu parâmetro. Em seguida, usando o método Min e o método good is long, retornará o número mínimo de confirmações no fluxo e o armazenará na variável de confirmações. Em seguida, passaremos as confirmações e as variáveis de endereço para a chamada atual do método de confirmação de endereço definido pela carteira. Agora vamos criar esse método na classe de carteira atual. Ele chamará o método de confirmação de endereço definido de endereços , passando os mesmos parâmetros recebidos. Vamos criar esse método na classe de endereços. Usaremos o método get addresses como map para obter o endereço e definir suas conformações. Agora, vamos criar o método de confirmações definidas na classe de endereço. Vamos usá-lo para definir o campo de confirmações que criaremos. Vamos criar esse campo e adicioná-lo ao construtor. Em seguida, vamos adicionar esse parâmetro à classe do gerador sequencial endereços na instanciação do endereço. Finalmente, vamos criar o método mark is used no serviço de atualização de endereços de carteira atuais. Um dos objetivos de nossa carteira e de muitos outros é evitar a reutilização de endereços ao receber Bitcoins. Por motivos de privacidade. Para fazer isso, devemos primeiro comercializar vestidos que tiveram transações com eles conforme usados. O método de marcação como usado será usado para esse insight. Ele chamará a atual roupa do mercado de carteiras. Como método usado, criará a passagem do endereço como seu parâmetro. Vamos criá-lo. Dentro dele, chamará o método mark is used da classe de endereços que passa o endereço para ela. Em seguida, criaremos esse método. Dentro, ele usará os endereços de obtenção como método matemático para obter o endereço e o mercado será usado. Finalmente, vamos criar o método mark is used na classe de endereço. Aqui, basta definir se o combustível usado é verdadeiro. Vamos criar esse campo nesta classe. 33. 31 Receber bitcoin parte 7 skillshare 2: Neste vídeo, finalmente conectaremos tudo o que fizemos nas últimas aulas para exibir informações de nossos endereços na tela. Portanto, no pacote observables criará a classe da linha de endereço. Como o nome sugere, essa classe modelará uma linha na tabela de endereços. Vamos criar os seguintes campos nessa classe, cada um para uma coluna na tabela de endereços. O primeiro campo será uma propriedade de string chamada balance, que será instanciada aqui com uma nova propriedade de string simples. O próximo campo será uma propriedade longa chamada confirmations e será instanciado com uma nova propriedade longa simples. O último campo será uma propriedade de string chamada address. Ele será instanciado com uma nova propriedade de string simples. Agora, com a ajuda do IDE, vamos criar getters para cada propriedade. Observe que, ao criar getters para campos de propriedades Java FX, o IDE cria dois getters, um para a propriedade e outro para o conteúdo da propriedade. Agora, vamos criar o seguinte construtor para essa classe. Ok, agora que modelamos a linha de endereço, criaremos um código para preenchê-la ao atualizar nossos endereços. Para fazer isso, vamos acessar o serviço de atualização de endereços atuais da carteira. No método de atualização, depois de marcar o endereço como usado, vamos chamar o método set address row na carteira atual, passando o endereço como parâmetro. Em seguida, vamos criar o método set address row. Para implementar esse método, adicionará o campo de linhas de endereço a essa classe. Vamos criar a classe de linhas de endereço no pacote observables. Vamos instanciar isso aqui. Agora, chamaremos o método set address row na propriedade address rows passará um objeto de endereço para ele. Esse objeto será obtido do campo de endereços usando o método get address que criaremos passando a string de endereço para ele. Para criar esse método , basta selecionar esse trecho de código e extrair um método dele usando o ID. Vamos substituir todas as ocorrências de código por esse método e tornaremos público o método gerado. Agora, de volta à classe de carteira atual. Vamos criar o método set address row na classe address rows. Para fazer isso, criaremos uma variável de linha de endereço chamando o método na classe da linha de endereço, passando o objeto de endereço como seu parâmetro. Vamos criar o método de formulário na classe da linha de endereço. Ele retornará uma nova linha de endereço, instanciando-a com esses parâmetros. Vamos criar o método de boas confirmações na classe de endereço. E agora podemos usá-lo aqui. Observe que aqui estamos simplesmente criando um objeto de linha de endereço convertendo os valores do campo de endereço nos valores do campo da linha de endereço. Voltar para a classe de linhas de endereço. Criaremos o campo de endereço do conjunto de estradas nesta classe. Será um conjunto observável com a linha de endereço como parâmetro de tipo. Irá instanciá-lo aqui com um novo wrapper de conjunto observável, passando um novo conjunto de hash vinculado para seu construtor. Esse objeto publicará um evento para cada novo endereço inserido ou removido e será necessário atualizar a tabela de endereços medida que a carteira atual receber novas transações. Agora chamaremos o método de remoção do conjunto de linhas de endereço, passando a linha de endereço como seu parâmetro. Em seguida, chamaremos o método add nele, passando a mesma linha de endereço como seu parâmetro. Você pode se perguntar por que estamos removendo e adicionando a mesma linha de endereço no conjunto. Bem, isso é um pouco complicado. Se não removermos a linha de endereço primeiro e inserirmos uma linha de endereço que já esteja no conjunto. O conjunto observável não publicará um evento indicando que uma linha de endereço foi adicionada a ele. Há outra coisa que precisamos fazer para que isso funcione. Quando removemos uma linha de endereço do conjunto usando o método remove, esse método usa o método equals da linha de endereço para definir qual linha de endereço ele removerá do conjunto. Consideraremos que as duas fileiras do I Dress são iguais se tiverem o mesmo endereço. Portanto, devemos implementar o método equals na classe da linha de endereço. Vamos fazer isso. Adicionaremos os métodos de código igual e hash usando esse recurso do IDE. Certifique-se de que essa caixa de seleção esteja marcada para gerar métodos usando getters. Agora, optaremos por usar somente o campo de endereço para gerar o método equals. E o mesmo campo para gerar o método hashCode e selecionar o campo de endereço aqui para defini-lo como não nulo. Ok, o IDE gerou os métodos de código igual e hash. Agora vamos para a tabela de endereços. O Fxml adicionará IDs de FX a cada tag de coluna da tabela. Os endereços. O controlador de tabela precisará desses IDs de FX para vincular e manipular essas colunas posteriormente. Primeiro, o endereço da coluna, depois o saldo da coluna e, finalmente, as conformações da coluna. Agora, vamos até o controlador da tabela de endereços adicionará os seguintes campos, cada um correspondendo a uma tag com um ID de ética na tabela de endereços, FXML. Os nomes desses campos devem ser iguais aos IDs FX das tags. Eles estão vinculados a. Primeiro, a tabela de endereços, depois o endereço da coluna, o saldo da coluna e as confirmações da coluna. Agora, adicionaremos o método inicializado a essa classe. Lembre-se de que os métodos inicializados nos controladores Java FX são chamados Quando a estrutura está inicializando esses controladores. Nesse método, adicionaremos um código que vinculará a tabela de endereços e suas colunas aos nossos observáveis de função de endereço. Para fazer isso, chamaremos o método set items na tabela de endereços, pois seu argumento passará por uma nova lista filtrada. Isso é necessário porque queremos mostrar somente endereços com um balanceado maior que zero na tabela de endereços. Como primeiro parâmetro da lista filtrada, passará pelas linhas de endereço observáveis da carteira atual. Então, vamos injetar a carteira atual nessa classe. Em seguida, chamaremos o método get observable address rows nele. Vamos criar esse método. Ele retornará uma lista observável com a linha de endereço como parâmetro de tipo. Em seguida, retornaremos a boa chamada do método de linhas de endereço observáveis no campo de linhas de endereço. Vamos criar esse método na classe de linhas de endereço. Dentro dele, retornará o campo da lista de linhas de endereços que criaremos. Vamos criá-lo. Esse campo será instanciado aqui com um novo wrapper de lista observável passando uma lista vinculada como seu parâmetro. Agora, temos que fazer com que a lista observável responda às inserções e remoções de linhas de endereço no conjunto de linhas de endereço. Faremos isso no construtor da classe. Primeiro, criaremos uma variável de listener de mudança definida. Vamos defini-la como essa função lambda. O parâmetro de alteração aqui representa uma inserção ou remoção de uma linha de endereço no conjunto. Se a alteração foi uma remoção , removeremos o elemento removido da lista de linhas de endereço. Se a alteração fosse uma inserção. Em seguida, adicionaremos o elemento adicionado à lista de funções de endereço. Por fim, adicionaremos esse ouvinte ao conjunto de linhas de endereço usando esse método. Agora, de volta ao controlador da tabela de endereços. O segundo parâmetro da lista filtrada é usado como condição de filtro para exibir linhas. Será uma função lambda com um parâmetro de endereço rho. O corpo da função será esse código que verificará se o saldo da linha de endereço é maior que zero. Dessa forma, atingimos nosso objetivo de exibir apenas endereços com um balanceado maior que zero. Agora, para cada campo de coluna, precisamos definir uma fábrica de valores de célula que será usada para preencher cada célula da tabela de endereços. Para isso, usaremos o código a seguir. A fábrica de valor da propriedade será usada para obter cada propriedade real de endereço e vincular seu valor à célula correspondente. Ele sabe qual endereço de propriedade real queremos vincular à coluna ao combinar o nome que estamos passando como parâmetro com o nome da propriedade. Há mais uma coisa que devemos fazer para que nosso recurso de recebimento de Bitcoin funcione corretamente. Vamos para a classe de carteira atual no método set addresses, que é chamado quando uma nova carteira é criada Precisamos incluir esse código para garantir que o endereço tenha surgido de um anterior a carteira criada é limpa. Chamaremos o método clear de linhas de endereço , que criará. Para fazer isso, vamos criá-lo. Aqui. Simplesmente chamaremos o método clear no conjunto de linhas de endereço e na lista de linhas de endereço. Agora vamos testar nosso recurso. Certifique-se de que seu nó principal do Bitcoin esteja funcionando. Vamos fazer o teste de recebimento de Bitcoin e executá-lo. Ótimo, funcionou. Observe que a primeira linha da tabela de endereços foi preenchida corretamente com um saldo de um Bitcoin, conforme o esperado. Bom trabalho. Nos próximos vídeos, adicionaremos mais casos de teste para garantir que nosso recurso de recebimento de Bitcoin esteja funcionando corretamente em diferentes cenários. 34. 32 Receber bitcoin parte 8 skillshare 2: Neste vídeo, adicionaremos mais casos de teste para garantir que nosso recurso de recebimento de Bitcoin funcione corretamente em diferentes cenários. No primeiro cenário adicional, testaremos se o mesmo endereço pode receber Bitcoins de duas transações, um Bitcoin de cada. Verificaremos se o saldo do endereço foi atualizado para dois bitcoins. Então, vamos copiar o conteúdo desse método e colá-lo abaixo. Vamos modificar o nome do teste para receber Bitcoins em duas transações no mesmo endereço. Agora, vamos selecionar esse código e extrair um método dele com a ajuda do id. Vamos nomeá-lo, enviar Bitcoin e peso. Chamaremos esse método duas vezes, pois queremos enviar transações para esse endereço. Vamos modificar o método de envio de Bitcoin em peso, incluindo o código a seguir. Verificaremos se o endereço na primeira linha da tabela tem um saldo igual ao parâmetro de valor total esperado. Vamos adicionar esse parâmetro à assinatura do método. Ele terá um valor padrão de 1,0. Nessa chamada de método, vamos adicionar 2.0 como segundo parâmetro, pois esperamos que o saldo do endereço seja igual a dois. Vamos adicionar dois ao nome da carteira. Há um problema com nosso ambiente de teste. No teste de registro, só é possível minerar 15.000 blocos com recompensas em blocos. Portanto, nesse método, é demais minerar 1.000 blocos ao chamar o método generate to address. Vamos chamá-lo apenas se o saldo da carteira de teste for inferior a 50 e gerar apenas 150 blocos para cada chamada. Dessa forma, evitamos a necessidade de redefinir nosso ambiente de teste de registro com muita frequência. Vamos também substituir esse código pelo método de enviar Bitcoin e esperar. Agora, vamos tornar nossos testes um pouco mais resistentes às condições da corrida. Percebi que, às vezes, esses testes enviam bitcoins para nossas carteiras de aplicativos antes de serem totalmente carregados. Portanto, essas transações não foram capturadas pelo aplicativo e os testes falham por esse motivo. Então, depois de criar uma carteira e antes de enviar Bitcoins para ela, vamos chamar o método de sono com esses parâmetros. A chamada do método sleep fará com que o aplicativo espere 10 s antes de enviar Bitcoins, tempo suficiente para que a nova carteira seja carregada completamente. Dependendo do seu computador, talvez seja necessário aumentar a constante de tempo limite. Agora, antes de executar os testes, vou redefinir meu ambiente de teste de registro. Preciso fazer isso porque ele já gerou 15.000 blocos e a geração de blocos não está mais produzindo Bitcoins. Então, vou até a pasta onde a blockchain está armazenada e removerei a pasta reg test dentro dela. No seu caso, você pode descobrir em qual pasta ela está localizada verificando o valor DIR de dados em seu arquivo bitcoin.com. Agora, vamos executar nosso node Bitcoin e executar nossos testes de recebimento de Bitcoin. Ótimo, os testes foram aprovados. Quando recebemos Bitcoins em nossa carteira, queremos que o próximo endereço de recebimento seja alterado. Dessa forma, evitamos a reutilização de endereços. É importante usar apenas um endereço para receber a transação, para que terceiros possam rastrear facilmente quantos Bitcoins você tem e com quais endereços você faz transações. Para cobrir esse cenário, vamos criar o teste a seguir. Copie o último teste e cole-o abaixo. Vamos renomeá-lo para receber Bitcoins em duas transações, dois endereços diferentes. Vamos mudar o nome da carteira criada para minha carteira de teste três. Agora, antes da segunda chamada do método de enviar Bitcoin e esperar, vamos adicionar esse código para consultar o campo de endereço de recebimento novamente e armazenar seu conteúdo na próxima variável de endereço. Agora, altere o primeiro parâmetro desse método para a próxima variável de endereço. E esperamos que o valor total de Bitcoin para esse endereço seja igual a 1,0. Além disso, esperamos que o tamanho dos itens da tabela seja igual a 21 linhas para cada endereço. Então, vamos modificar esse método para aceitar o tamanho esperado da tabela como parâmetro. Vamos adicionar esse parâmetro a ele com um valor padrão de um. Substituirá esse valor aqui para esperar que o número de linhas da tabela seja igual a ele. E substituiremos o índice de itens em pontos da tabela pelo tamanho total esperado menos um para esperar que a última linha no saldo da tabela seja igual ao valor total esperado para aquela linha. Finalmente, vamos parametrizar o terceiro argumento dessa chamada de método para dois. Vamos fazer nossos testes. Como esperado. O terceiro teste falhou porque ainda não implementamos o recurso de alterar o endereço de recebimento depois de usá-lo. Vamos fazer isso agora. Então, vamos para o serviço de atualização de endereços de carteira atuais. Dentro disso, para cada bloco, vamos chamar o método de atualização do endereço de recebimento que criaremos. Ele tomará o endereço como parâmetro. Vamos criá-lo. A primeira coisa que faremos é chamar o método do tipo get address na carteira atual. Passar o endereço como parâmetro armazenará o resultado da chamada do método na variável de tipo de endereço. É importante saber o tipo de endereço do endereço substituído, pois ele precisa ser substituído por um endereço do mesmo tipo. Então, vamos criar esse método na classe de carteira atual. Ele simplesmente chamará o método do tipo get address type. Criaremos a passagem do endereço como seu parâmetro. Vamos criá-lo. Agora. Chamaremos o método get address e retornaremos seu tipo de endereço. Vamos criar o método get address type na classe de endereço. Dentro dele, retornará o campo do tipo de endereço que criaremos. Vamos criar esse campo e adicioná-lo ao construtor. Também vamos corrigir o gerador sequencial de endereços para adicionar o último argumento à instanciação do endereço. Adicionaremos esse tipo de endereço como um parâmetro a esse método. E incluiremos o tipo de endereço nessa chamada de método chamando o valor do método na classe do tipo de endereço. Agora, de volta ao serviço Atualizar endereços da carteira atual , calculará o valor do próximo índice de endereços chamando o método fine next address index na carteira atual, passando o endereço digite como parâmetro armazenará o resultado da chamada do método na próxima variável de índice de endereço. Vamos criar esse método. Aqui. Chamaremos o próximo índice de endereço fino no campo de endereços, passando o tipo de endereço como parâmetro. Vamos criar esse método na classe de endereços com o código a seguir, obteremos o último endereço usado para armazená-lo na variável de endereço. Obterá todos os objetos de vestuário com o tipo de endereço fornecido e obterá um stream a partir deles. Em seguida, classificaremos o fluxo obtido usando o método classificado com os seguintes parâmetros. Usarei o método de comparação de pontos do comparador, passando o método address get indexed como o primeiro parâmetro e o comparador de ordem inversa como o segundo. Dessa forma, obteremos um fluxo de endereços ordenado de forma inversa por seus índices. Agora, filtraremos o fluxo para obter uma string contendo somente endereços usados. Para fazer isso, vamos criar um getter para o campo usado na classe de endereço. Eles usaram getter is called é usado porque é assim que o IDE nomeia os getters booleanos de volta à classe de endereços e passará o método de endereços usados como o prompt para a chamada do método de filtro. Agora, chamaremos o primeiro método fino no resultado. Para obter o primeiro endereço usado e o fluxo ordenado invertido, que é igual ao último usado para endereçar. E se nenhum endereço usado for encontrado. Nesse caso, usaremos o método or else para retornar null. Adicionaremos a seguinte declaração if. Se o endereço obtido for nulo, retornaremos zero como o próximo índice. Caso contrário, retornaremos o último índice de endereço mais um. Agora, de volta ao serviço Atualizar endereços de carteira atuais , obterá o próximo endereço ligando para o método get address ID na carteira atual. Vamos passar o próximo índice de endereço e o tipo de endereço como parâmetros. Vamos criar esse método na carteira atual. Retornarão, eles receberão a chamada do método de identificação de endereço no campo de endereços, passando os mesmos argumentos recebidos de seus parâmetros. Vamos criar esse método na classe de endereços. Receberá todos os objetos de vestuário com o tipo de endereço fornecido. Em seguida, vamos convertê-lo em uma lista. Em seguida, obteremos o endereço por índice. Para fazer isso, precisamos mudar o tipo de índice de endereço para um objeto longo, não apenas para o tipo primitivo. Em seguida, chamaremos o valor int, passando-o como o parâmetro getMethod. Agora, retornaremos a string de endereço do endereço obtido. Agora, de volta ao serviço Atualizar endereços de carteira atuais basta definir o endereço de recebimento da carteira atual como o próximo endereço obtido. Vamos fazer mais uma coisa antes de testar nosso código. Lembre-se de que o códon, essa classe, será executado em um novo thread. No Java FX, é uma boa prática executar código que modifica a interface do usuário somente no thread principal. Para fazer isso, vamos chamar o método dot run later da plataforma passando uma função Lambda para ela. Vamos mover essas duas linhas para o corpo da função lambda, pois elas causam alterações que afetarão a interface do usuário. Agora, vamos executar nossos testes de recebimento de Bitcoin novamente. Ótimo. O campo do endereço de recebimento foi atualizado após recebimento dos fundos e a aprovação dos testes. No próximo vídeo, continuaremos aprimorando nossos testes e adicionaremos mais um cenário de teste. C, sim. 35. 33 Receber Bitcoin parte 9 skillshare 2: Neste vídeo, continuaremos aprimorando nossos testes e adicionaremos mais um cenário de teste importante para o recurso de recebimento de Bitcoin. Uma coisa está faltando em nossos testes. Ainda não sabemos se os endereços corretos estão sendo gerados e se estão respeitando a sequência do índice do caminho de derivação. Para verificar isso, vamos criar o endereço é um método válido. Em seguida, o bloco do primeiro teste chamado endereço é um método válido que passa o endereço, a semente mnemônica e o índice de endereço esperado, que neste caso é zero como seus parâmetros. Vamos criar esse método. Ele retornará um booleano. Vamos definir os nomes corretos dos parâmetros. Aqui. Criaremos um novo objeto de semente mnemônica e o armazenaremos na variável de semente mnemônica. Vamos renomear o parâmetro de semente mnemônica para a sequência de sementes mnemônica. Agora vamos instanciar o objeto de semente mnemônico passando a string de semente mnemônica como parâmetro do construtor. Agora, vamos criar a chave mestra com o código a seguir. Chamará o método de duas chaves mestras no objeto semente mnemônico, passando uma string vazia como o primeiro parâmetro e o prefixo privado da rede principal como o segundo. Agora, vamos criar a string de chave pub estendida com o código a seguir. Usaremos o serviço estendido de chaves de pub. Então, vamos injetá-lo nessa classe. Em seguida, chamaremos o método create nele, passando a chave mestra como seu primeiro parâmetro. O segundo parâmetro será uma concatenação entre parte do caminho de derivação do endereço do segmento e o parâmetro do índice. Vamos mudar o tipo de parâmetro do índice para a classe inteira, para que possamos chamar o método toString nela. O terceiro parâmetro será o tipo de endereço constante de Segway. Em seguida, chamaremos o método get key no resultado. Agora, obteremos o objeto de chave pub estendida da biblioteca Bitcoin Java usando a chave pub estendida no método serializado, passando a string da chave pub estendida conforme seu parâmetro obterá o endereço esperado usando o gerador de endereços de segmentos. Vamos injetá-lo nesta classe. Em seguida, chamaremos o método generate nele, passando a chave pub estendida como seu parâmetro. Por fim, retornaremos o resultado da comparação se o endereço esperado é igual ao parâmetro de endereço. Agora vamos adicionar se o endereço é uma chamada de método válida para verificar os endereços nos outros métodos dessa classe. Neste método, vamos adicioná-lo duas vezes. Na segunda vez, verificaremos se o próximo endereço é igual ao endereço esperado com o índice um. Vamos fazer nossos testes. Ótimo, os testes foram aprovados. Agora sabemos que os endereços estão sendo gerados corretamente. Agora vamos criar outro teste. O próximo teste tentará transferir mais transações do que o número de endereços gerados. Lembre-se de que definimos o número inicial de endereços gerados como 20. Portanto, devemos verificar o que acontece quando todos os endereços gerados inicialmente são usados. Mas fazer um teste com 20 transações levaria muito tempo. Então, alteraremos o número inicial de endereços gerados no ambiente de teste para três posteriormente para acelerar as coisas. Então, vamos copiar esse método e colá-lo abaixo. Mude seu nome para se receber Bitcoin em sete transações para endereços diferentes, com três endereços gerados em nossa carteira e sete transações, neste teste, nossa carteira precisaria para gerar quatro endereços a mais do que o número inicial para que esse teste seja aprovado. Vamos mudar o nome da carteira criada para minha carteira de teste. Por enquanto, criaremos um arquivo de propriedades para o ambiente de teste para alterar o número inicial de endereços gerados para nossos testes. Então, vamos criar um caminho de recursos dentro do pacote de teste. Selecione a opção Recursos abaixo. Dentro dele, criará um arquivo chamado application test dot properties. Copiaremos o conteúdo do arquivo de propriedades do ponto do nosso aplicativo e o colaremos aqui. Agora, vamos definir o número inicial de propriedades de endereços gerados como três. Agora vamos para a classe de configuração de endereço. O número inicial de endereços gerados que está retornando atualmente. 20 injetará esse valor nessa classe a partir do arquivo de propriedades usando essa anotação de valor e esse campo privado. Agora, neste método, apenas retornará o campo criado. Agora, para usar propriedades do aplicativo, teste arquivos de propriedades de pontos em nossos testes. Vamos para a aula de teste de GUI. Adicione essa anotação a ela. Ok, agora todo arquivo de teste que estende o teste da GUI obterá suas propriedades do arquivo de propriedades do ponto de teste do aplicativo. Agora, de volta ao nosso último teste. Vamos mudar o nome dessa variável para o primeiro endereço. O nome dessa variável para o segundo endereço. Agora vamos copiar essas linhas e gerar mais quatro transações para formar mais endereços recém-gerados, modificando seu código adequadamente. Vamos mudar o tamanho esperado da linha da tabela para sete. Vamos copiar essas linhas também para validar todos os endereços gerados no teste. Vamos alterar os parâmetros dos métodos conforme necessário. Agora, vamos fazer nossos testes. Como esperado. O último teste falhou após a terceira transação que aconteceu porque a carteira não conseguiu encontrar o quarto endereço, pois gerou apenas os três primeiros endereços. No próximo vídeo, vamos corrigir isso. Antes de terminar o vídeo, vamos adicionar o número inicial de propriedades de endereços gerados ao arquivo de propriedades de pontos do aplicativo. Vamos configurá-lo para 20 para que a carteira funcione como antes no ambiente sem teste. 36. 34 Receber bitcoin parte 10 skillshare 2: Neste vídeo, faremos nosso último teste criado passar. Para fazer isso, vamos acessar o serviço de atualização de endereços atuais da carteira. Nesse método, vamos adicionar a seguinte instrução if. Depois de calcular o próximo índice de endereço. Dentro da instrução if, nós os chamaremos de método must import addresses passando o próximo índice de endereço e o tipo de endereço. Vamos criar esse método. Só importará endereços se o próximo índice de endereços for igual ao número total de endereços na carteira atual com um determinado tipo de endereço. Se for esse o caso, significa que ficamos sem endereços e, portanto, não podemos preencher o próximo endereço de nossa carteira sem criar mais endereços. Dentro desse método, retornará o resultado da verificação de se o próximo índice de endereço é igual ao da carteira atual. A chamada do método de contagem de endereços passará o tipo de endereço para esse método. E vamos criar esse método. Esse método retornará um int e retornará os endereços, a chamada do método get adresses count, passando o tipo de endereço como seu parâmetro. Vamos criar esse método. Aqui, simplesmente obteremos todos os endereços com o tipo de endereço fornecido em uma lista e retornaremos o tamanho da lista ao serviço Atualizar endereços de carteira atuais. No bloco if, primeiro obterá as chaves de pub estendidas da carteira atual e as armazenará em uma variável. Vamos criar esse método. Aqui. Devolveremos o campo estendido de chaves do pub. Vamos criá-lo. Vamos também adicionar um setter para esse campo. Chamaremos esse conjunto ou, no atualização do serviço de carteira atual, atualizar o método de atualização. Passando as carteiras, estendia as chaves do pub para ela. Agora, de volta ao serviço Atualizar endereços de carteira atuais. Chamaremos o método de adicionar endereços no serviço de endereço ADD. Passar as chaves de pub estendidas obtidas anteriormente como seu primeiro parâmetro e o próximo índice de endereço como seu segundo parâmetro. Vamos injetar esse serviço nessa classe. Vamos criar esse serviço e o pacote de serviços da API. Vamos adicionar a anotação do serviço a ela. Agora, vamos terminar de injetar esse serviço nessa classe. E vamos criar esse método no serviço de endereços de anúncios. Vamos mudar o nome desse parâmetro para do índice. O que planejamos fazer agora é gerar endereços para as chaves de pub estendidas que foram passadas como parâmetros. O número de endereços gerados será igual ao número inicial de endereços gerados no campo injetado. E o primeiro índice de derivação gerado pelo endereço será determinado pela variável de índice firme, por exemplo, suponha que o número inicial de endereços gerados seja igual a 20 e a variável do índice from seja igual a 20. Nesse caso, esse método gerará vestidos com um índice de derivação de 20 a 39. Para fazer isso, para cada chave de pub estendida. Chamaremos o método add addresses, passando a chave e o parâmetro from index. Vamos remover essa letra S. Agora, vamos criar esse método privado de adição de endereços. Ele chamará o método add addresses na chave pub estendida como seu parâmetro. Usaremos o gerador sequencial de endereços. Então, vamos injetá-lo nessa classe. Chamaremos o método generate no gerador sequencial de endereço, passando a chave pub estendida, o tipo de chave pub estendida e a variável de índice from como seus parâmetros. Vamos ver a implementação do método generate. Irá alterá-lo para gerar endereços com índices de derivação usando o parâmetro from index. Então, vamos adicionar do índice como seu terceiro parâmetro. Aqui, na chamada do método range, adicionará a variável de índice from como seu primeiro parâmetro. E a soma do parâmetro from index e do número inicial de endereços gerados como o segundo. Agora, de volta ao serviço de endereço ADD. Vamos criar o método de endereços de anúncios na classe de chave pub estendida. Vamos corrigir esse nome de parâmetro. Aqui. Chamaremos o método address add all passando o parâmetro addresses para ele. Há um problema com esse código. O campo de endereços é do tipo lista, que é imutável. Isso significa que quando tentamos adicionar itens a ele por meio do método adicionar tudo, isso gerará um erro. Então, vamos alterá-lo para o tipo ArrayList, que é mutável. Vamos também torná-lo definitivo e instanciado aqui. Também vamos alterar o getter de endereços e o método addresses para obter e definir uma ArrayList. Também vamos remover o método de endereços definidos , pois não o usaremos mais. Voltar ao serviço de adicionar endereços. Vamos agrupar o resultado da chamada do método generate em uma nova ArrayList, já que o método de endereços de anúncios agora aceita somente uma ArrayList. Agora vamos analisar os fatores que criam o serviço de carteira. Uma vez que fizemos mudanças que afetaram. Primeiro, vamos remover o serviço gerador sequencial de endereços dessa classe. Vamos também remover esse método. Vamos remover essa linha de código. Usaremos o serviço de adição de endereço para adicionar endereços às chaves de pub estendidas. Então, vamos injetá-lo nessa classe. E vamos chamar o método add addresses nele, passando as chaves pub estendidas e zero como seus parâmetros. Vamos terminar de injetá-lo nesta classe. Agora, de volta ao serviço Atualizar endereços de carteira atuais. Chamaremos o método set addresses na carteira atual, passando as chaves de pub estendidas como seu parâmetro. Vamos remover a chamada de método limpa das linhas de endereço nos métodos de conjunto de endereços, pois não queremos remover nenhuma linha da tabela de endereços depois de definir esses endereços. Em vez disso, vamos criar um método chamado linhas de endereço claras, que fará isso. Em seguida, no método de atualização do serviço de atualização da carteira atual, chamaremos esse método para limpar as linhas de endereço somente após adicionar uma nova carteira. Agora, de volta ao serviço Atualizar endereços de carteira atuais , obterá todos os endereços recém-gerados na carteira atual e os armazenará nessa variável. Para obter os endereços, chamaremos o método get addresses as strings na carteira atual. Passando o próximo índice de endereço como seu primeiro parâmetro. E a soma do próximo índice de endereços e do campo do número inicial de endereços gerados como segundo parâmetro. Vamos injetar esse campo nessa classe. Vamos adicionar a anotação do qualificador para usar o bean definido na classe de configuração de endereço para injetar o valor desejado nesse parâmetro. Agora, vamos criar esse método. Vamos mudar esses nomes de parâmetros para do índice dois. Esse método retornará os endereços, obterá endereços como uma chamada de método de cadeias de caracteres passando os mesmos parâmetros recebidos. Vamos criar esse método na classe de endereços. Esse método retornará todos os seus endereços com índices entre os parâmetros do índice dois, mas sem incluir a escada. Para fazer isso, ele retornará o código a seguir. Usaremos o método flatMap para converter todos os endereços em um fluxo de objetos de endereço. Em seguida, filtraremos o fluxo para retornar somente endereços com índice maior ou igual à variável de índice firme e menor que as duas variáveis de índice. Em seguida, chamaremos um mapa no resultado para retornar um fluxo de cadeias de endereço. Por fim, converteremos o resultado uma lista e o retornaremos. Agora, de volta ao serviço Atualizar endereços de carteira atuais , usaremos os clientes de endereços de importação múltipla de nós para importar os endereços recém-gerados em nosso nó Bitcoin. Lembre-se de que isso é necessário porque é necessário que o node conheça nossos endereços para poder enviar transações relacionadas para nossa carteira de aplicativos. Então, vamos injetá-lo nessa classe. Agora, chamaremos o método de endereços de entrada nele, passando o nome da carteira atual, as cadeias de endereço e uma nova data como parâmetros. Ótimo, nosso recurso de rotação de endereços deve funcionar agora, mesmo depois de todos os endereços gerados inicialmente serem usados. Mas vamos lidar com outro problema aqui. Estamos definindo o próximo endereço como o endereço de recebimento em nossa carteira. Mesmo que seja o tipo de endereço, é um endereço de alteração. Vamos corrigir isso. Como queremos apenas endereços com o tipo Segway, não o tipo de mudança de Segway sendo chamado de endereços de recebimento em nossa carteira. Então, adicionaremos esta declaração if. Se o tipo de endereço for igual à constante de endereço principal , isso o definirá como segue. Agora. Em seguida, definiremos o próximo endereço como o próximo endereço de recebimento na carteira atual. Mais uma coisa, vamos remover essa plataforma. A chamada run later chamará o método run later , envolvendo apenas o código que realmente mudará a interface do usuário. Então, vamos usá-lo para encapsular apenas a chamada nominal de endereços do conjunto de carteiras atual. Também vamos usá-lo para encerrar a chamada do método de endereço de recebimento do conjunto atual da carteira. Dessa forma, evitamos bloquear a interface do usuário ao comunicarmos com nosso nó Bitcoin na chamada do método de importação de endereços. Agora vamos para o controlador da tabela de endereços. Percebi que o TableView às vezes não é atualizado para refletir o estado real de suas linhas. Para corrigir isso, vamos adicionar esse código a esse método. Adicionará um ouvinte às linhas de endereços observáveis da carteira atual. No corpo deste lambda, simplesmente chamará o método de atualização na tabela de endereços. Dessa forma, para cada atualização nos endereços de nossa carteira, garantimos que, na visualização da tabela atualizaremos seu estado e mostraremos as informações atuais dos endereços de nossa carteira na tela. Agora, vamos ao teste do gerador sequencial de endereço e adicionar zero como o terceiro parâmetro do método de geração para que esse teste continue funcionando. Também vamos corrigir o teste do serviço de criação de carteira. No método de configuração, vamos instanciar o serviço de endereço ADD, passando o gerador sequencial de endereços como seu parâmetro. E vamos substituir o terceiro parâmetro do serviço de criação de carteira pelo serviço de endereço ADD. Agora, no último teste de recebimento de Bitcoin, vamos fazer uma pequena mudança. Depois de enviar Bitcoin para o terceiro endereço. Vamos adicionar o tempo limite de passagem da chamada do método suspenso e os segundos como argumentos. Vamos também adicionar a mesma chamada depois enviar Bitcoins para o sexto endereço. O motivo dessas chamadas é que, antes enviar Bitcoins para o quarto e sétimo endereços, precisamos gerá-las e importá-las para nossos nós antes de aceitar transações para eles. E o processo de importação leva algum tempo. Vamos finalmente executar todos os nossos testes de aplicativos. Ótimo, todos os testes foram aprovados. Finalmente concluímos o básico sobre o recurso de recebimento de Bitcoin em nossa carteira. Agora, começaremos a implementar a observação de novos blocos que são adicionados ao blockchain para que possamos atualizar o número de conformações que são endereços com C, sim. 37. 35 Receber bloco parte 1 skillshare 2: Neste vídeo, faremos testes para garantir que, quando um bloco for minerado no Blockchain, nossa carteira receba transações atualizadas com conformações crescentes. Então, vamos mover os métodos auxiliares na classe de teste Bitcoin de recebimento para o teste de GUI para que possamos usar esses métodos em outras classes que os estendam. Agora, vamos mover todas essas propriedades para a classe GUI também pelo mesmo motivo. Agora, vamos cortar essas duas linhas e colá-las na carteira de carga e adicionar método balanceado na classe de teste de GUI. No método de configuração na classe de teste recebida, chamaremos esse método. Vamos excluir todas essas importações não utilizadas nessa classe. Na classe de teste de GUI, vamos proteger esses métodos e propriedades. Agora, no pacote de teste da GUI, vamos criar a classe de teste do bloco receptor. Isso estenderá a classe de teste de GUI. Vamos copiar o método de configuração e o teste de recebimento do Bitcoin e colá-lo aqui. Vamos também copiar o primeiro teste no teste de recebimento de Bitcoin e colá-lo na classe de teste do bloco receptor. Ele será usado como um modelo para o próximo teste que criaremos. Vamos mudar o nome da carteira criada para minha carteira de teste cinco. Vamos mudar o nome do tubo de ensaio para receber Bitcoin e adicionar confirmações de hashtag, confirmações para receber esse vestido. As conformações da hashtag serão interpoladas pela variável de teste de confirmações que criaremos. Agora, após o envio, os Bitcoins chamarão o método mine blocks, passando a variável confirmations como seu parâmetro. Vamos criar esse método. Ele usará um int como parâmetro. Neste método, usaremos o node generate para direcionar o cliente aos blocos de mineração. Então, vamos colar um código nele. Na classe de teste da GUI, copie essa linha de código e cole-a aqui. Modifique o nome da variável de endereço para anotar o endereço. Faça o mesmo com essa outra linha. Altere o segundo parâmetro do método de geração para blocos. Portanto, ele usará essa variável para definir o número de blocos que minerará e alterará esse parâmetro para o endereço da nota. Agora, vamos copiar esse peso para uma chamada de método e colar aqui. Exclua essas partes do código. Esse método aguardará até que o valor da célula de confirmação da primeira linha da tabela de endereços seja igual à variável blocks. No bloco Venn, verificará se o valor da célula de confirmação da primeira linha da tabela é igual à variável de confirmações. Vamos incluir uma cláusula where. Aqui. Definiremos que a confirmação é variável para alguns valores de teste. Adicionaremos um espaço reservado para a segunda coluna na WhereClause, porque aparentemente ela só funciona quando tem duas ou mais colunas. Vamos definir os valores das confirmações para 12,3. Agora, vamos executar nosso node Bitcoin e executar nosso novo teste. Ótimo, os testes foram aprovados. Agora, vamos fazer outro teste para o cenário a seguir. Queremos saber o que acontece quando um endereço recebe duas transações. E a segunda transação tem menos conformações do que a primeira. Nesse caso, esperamos que o número de conformações do endereço seja igual ao número de conformações da transação com menos conformações nesse endereço. Então, vamos duplicar o primeiro teste. Vamos mudar seu nome para receber Bitcoin e considerar a transação com menos conformações como confirmações de endereço. Vamos mudar o nome de criação da carteira para minha carteira de teste seis. Agora, vamos duplicar essas linhas de código para enviar bitcoins e minerar blocos novamente. Na segunda chamada de blocos de mina, adicione menos um em seu parâmetro para minerar menos blocos após a segunda transação. No bloco, esperamos confirmações menos uma como o número de confirmações na primeira linha da tabela. Vamos excluir essa linha, pois não queremos esse caso de teste porque ela tentaria evitar zero blocos na segunda chamada de blocos de minas, o que falharia. Vamos fazer nossos testes novamente. Ótimo, os testes foram aprovados. Portanto, concluímos que nossa carteira já está preparada para atualizar o número de conformações de nossos endereços. Isso porque, após cada bloco de mina, o nó envia uma mensagem por meio de zero MQ para nosso aplicativo contendo as transações importadas anteriormente, mas com um número atualizado de confirmações. 38. 36 Receber transação parte 1 skillshare 2: Neste vídeo, começaremos a criar a tabela de transações. Essa tabela será semelhante à tabela de endereços, mas em vez de linhas contendo informações sobre endereços, ela conterá informações sobre cada transação que nossa carteira envia ou recebe. Então, vamos começar a criar um teste de GUI para essa tabela. No pacote de GUI, crie uma classe chamada teste de transação de recebimento. Copie esses métodos do teste do bloco receptor e cole-os aqui. Essa classe estenderá a classe de teste de GUI. Altere o nome do teste para que a transação deve ser recebida. Vamos formatar esse método. Remova o bloco it's where, altere o nome de criação da carteira para meu teste enquanto estiver com sete anos. Exclua essa linha. Agora, depois de chamar o método sleep, vamos fazer o teste clicar em um componente com uma guia de identificação ética das transações. Agora, vamos adicionar outro parâmetro opcional ao método de enviar Bitcoin e esperar. Esse parâmetro será uma string e será chamado de componente de pesquisa. Seu valor padrão será tabela de endereços de hashtag. Vamos substituir esse parâmetro na chamada do método de pesquisa pela variável do componente de pesquisa. Agora, no teste, vamos adicionar esses parâmetros ao método de enviar Bitcoin e esperar. O quarto parâmetro será a tabela de transações de hashtag. Dessa forma, após o envio de uma transação, essa chamada de método aguardará que a tabela de transações seja preenchida com uma linha contendo um saldo de 1,0 Bitcoin. Agora, vamos mudar também o parâmetro do método de pesquisa para a tabela de transações com hashtag. No bloco then, vamos deixar a afirmação de que o tamanho da linha da tabela é igual a um por enquanto. Agora, vamos projetar nossa mesa. Vamos para o playground dot FXML. Vamos copiar todo esse conteúdo entre a tag tab e colá-lo abaixo. Agora, altere sua propriedade de texto para transações e sua ID de ética para a guia de transações. Altere também a ID de ética da etiqueta de visualização para a tabela de transações. Agora vamos mudar o campo de texto da primeira coluna para ID da transação. A tabela também terá uma coluna balanceada e uma coluna de confirmações. Portanto, manteremos essas tags como estão. Vamos duplicar a última tag, alterar seu texto até o momento. Essa coluna conterá a data de criação dessas transações. Agora vamos clicar no Scene Builder para ver a aparência de nossa nova guia e tabela. Ok, está lindo. Agora, vamos criar um novo FXML para esse componente. Vamos chamá-la de tabela de sublinhados de transações. Vamos excluir o código padronizado. Vamos copiar esse conteúdo do ponto FXML do playground e colá-lo aqui. Vamos importar essas tags. Altere essa tag para fx colon route. Exclua esse conteúdo como seu tipo. Vamos definir o caminho do componente de visualização da tabela e definir esse URL como o campo XML NS como a tabela de transações do conjunto de propriedades do ID de ética. Agora exclua essas tags, que não precisávamos copiar. Agora, vamos adicionar esses IDs de ética a essas tags de coluna. Eles serão úteis posteriormente, quando criarmos o controlador da tabela de transações. Agora, na janela principal, pontilhe FXML, vamos duplicar o conteúdo entre essas tags. Vamos mudar o texto da guia para transações e a guia FX ID para transações. Agora, altere essa tag para controlador de tabela de transações. Vamos criar esse controlador no pacote de controladores de pontos GUI. Vamos importar para a janela principal o ponto FXML. Agora, vamos adicionar a anotação do componente ao controlador da tabela de transações. Isso estenderá a classe de visualização de tabela parametrizada com a classe de linha de transação que criaremos. Vamos criar a classe real da transação no pacote observables. Agora, vamos até o controlador da guia Receber, copiar seu construtor e colá-lo aqui, fazendo as modificações apropriadas nele. Vamos alterar sua anotação de valor para apontar para o ponto FXML da tabela de sublinhado de transações. Vamos também injetar a carteira atual nessa classe. Será útil mais tarde. Agora, precisamos incluir o controlador da tabela de transações na lista de componentes personalizados no ouvinte iniciado pela GUI, poderíamos simplesmente adicionar outra cláusula or na instrução if na inicialização Método FXML. Mas vamos refatorar essa classe fazendo o seguinte. Vamos criar um conjunto estático privado de objetos de classe chamados componentes personalizados aqui. Vamos instanciá-lo aqui com a classe de método set. Vamos incluir essas classes de controladores no conjunto. Agora, na instrução if, apenas verificaremos se o conjunto de componentes personalizados contém o tipo fornecido. Agora vamos fazer o teste de recebimento da transação. Agora, vamos executar as metas do Maven de ciclo de vida limpo e compilado. Às vezes, isso é necessário para incluir novos arquivos FXML no projeto compilado. Agora, vamos executar nosso node principal do Bitcoin se ele ainda não estiver em execução. Finalmente, vamos fazer o teste. O teste falhou porque não encontrou uma linha contendo as informações da transação na tabela de transações continuará implementando esse recurso no próximo vídeo. vejo. 39. 37 Receber transação parte 2 skillshare 2: Neste vídeo, concluiremos a implementação da tabela de transações e faremos com que esse teste seja aprovado. Então, vamos para o serviço UTXO de atualização. Se você se lembrar, esse método de atualização é chamado depois que recebemos uma transação do nosso nó A classe de tarefa do nó monitora nosso nó em busca de mensagens de transação. Em seguida, nosso aplicativo publica um evento de transação recebida que é ouvido pelo nosso ouvinte de transações. O ouvinte da transação analisa e filtra a mensagem e chama o método de atualização do serviço UTXO de atualização. Então, depois de recuperar UTXOs e atualizar os endereços atuais da carteira, vamos atualizar as transações atuais da carteira usando esse serviço. Vamos injetá-lo nesta classe. Vamos criá-lo no pacote de serviços GUI dot. Vamos adicionar a anotação do serviço a ela. Agora, vamos terminar de injetá-lo nesta classe. Agora, vamos chamar o método de atualização nesse serviço, passando a variável utxOS como seu parâmetro. Vamos criar esse método. Esse método será executado de forma assíncrona. Então, vamos adicionar a anotação assíncrona usando o serviço executor padrão como parâmetro. Vamos fazer o mesmo com o método de atualização no serviço de atualização de endereços da carteira atual. Agora, vamos implementar o método de atualização e o serviço de transação atual do Wallet de atualização converterá a lista de UTXOs em uma lista de linhas de transação e armazenará o resultado nas linhas de transação. A variável que usa o código a seguir filtrará o fluxo de UTXOs mantendo no fluxo somente os UTXOs com endereços na carteira atual. Então, vamos injetar a carteira atual nessa classe. Agora, no corpo do lambda obterá todos os endereços como strings e verificará se ele contém o endereço UTXO. Agora, chamaremos o método map no fluxo resultante, passando a linha de transação do método como seu parâmetro. Vamos criar esse método. Será um método estático e retornará um objeto de linha de transação. Semelhante à classe da linha de endereço. A classe da linha da transação representará uma linha e a tabela de transações. Então, vamos adicionar as seguintes propriedades a essa classe. Cada propriedade representará uma coluna na tabela de transações. Vamos excluir a palavra-chave final de cada propriedade porque o IDE permite criar automaticamente configuradores para essas propriedades, se forem finais. Agora, usando esse recurso de ID, adicione getters e setters para cada propriedade. Agora podemos adicionar a palavra-chave final a essas propriedades. Agora, vamos criar um construtor. O construtor usará cada propriedade de classe como seus parâmetros. E usaremos os configuradores de propriedades para definir as propriedades no corpo do construtor. Agora, podemos continuar implementando o método. Ele retornará uma nova linha de transação com os seguintes parâmetros. Voltar ao serviço de transação Update Current Wallet. Agora, converteremos a string resultante em uma lista. Agora, adicionaremos a transação obtida rose à carteira atual usando o método de adicionar linhas de transação. Vamos criar esse método. Ele usará o campo de linhas de transação. Então, vamos criá-lo agora. Seu tipo será a transação Rose Class. Vamos criá-lo no pacote observables. Voltar para a carteira atual. Vamos defini-lo e instanciá-lo aqui. Vamos também tornar o campo das linhas de endereço definitivo. No método de linhas de transação ED, vamos chamar o método adicionar linhas de transação no campo de linhas de transação. Passando as linhas de transação fornecidas como seu parâmetro. Vamos criar esse método. Assim como a classe de linhas de endereço é responsável por gerenciar a lista de linhas de endereço mostrada na tabela de endereços. Essa classe fará o mesmo com as linhas de transação e a tabela de transações. Portanto, para cada linha de transação, verificaremos se o campo do roteiro da transação já a contém. Então, vamos criar esse campo. Será um mapa observável em que a chave é uma string e o valor é uma linha de transação. Vamos instanciá-lo aqui com um invólucro de mapa observável, passando um novo HashMap vinculado como seu construtor. Portanto, se o roteiro da transação contiver o ID da linha da transação em suas chaves, definiremos a rotação da transação para a data da transação presente no roteiro da transação da transação contiver o ID da linha da transação em suas chaves, definiremos a rotação da transação para a data da transação presente no roteiro da transação. isso para preservar a data de criação da transação. Em seguida, após a instrução if, removerá a linha de transação do mapa por sua ID e colocará a linha de transação fornecida novamente no roteiro da transação usando sua ID como chave. Novamente, estamos removendo e adicionando a mesma linha de transação para forçar o mapa observável a publicar eventos de alteração que serão ouvidos posteriormente. Agora, vamos criar o campo de lista observável que será usado para vincular as alterações no roteiro da transação ao controlador da tabela. Vamos instanciá-lo aqui usando um wrapper de lista observável instanciado com uma nova lista vinculada. Agora, vamos criar o método get observable transaction row list. Ele retornará a lista de funções da transação. Agora vincularemos o roteiro da transação à lista de funções da transação no construtor, assim como fizemos com o conjunto de linhas de endereço e a lista de linhas de endereço na classe de linhas de endereço. Então, para acelerar as coisas, vamos copiar o construtor de linhas de endereço e colá-lo aqui. Vamos corrigir seu nome. Agora, em vez de chamar métodos na lista de funções de endereço, faremos isso na lista de funções da transação. Em vez de usar um set change, o ouvinte usará um ouvinte de mudança de mapa parametrizado com uma string e uma linha de transação. Além disso, em vez de usar o elemento get removido aqui, usaremos o getValue removido. Aqui. Usaremos o get value-added. E aqui adicionaremos um ouvinte ao roteiro da transação. Mais uma coisa para que isso funcione, temos que implementar o método equals na classe de linha de transação. Isso ocorre porque, na lista de linhas de transação, usaremos o método para decidir qual linha de transação remover de si mesma. Então, vamos implementá-lo usando esse recurso do IDE. Certifique-se de marcar a caixa de seleção usar getters nesta janela para usar somente a propriedade ID para definir a igualdade nessa classe. Além disso, clique na caixa de seleção de ID aqui para que ela não possa ser nula. Ok, o IDE gerou esses métodos conforme o esperado. Voltar para a classe de linhas de transação. Vamos criar o método claro, que será chamado quando uma nova carteira for criada. Dentro, ele chamará o método claro no roteiro da transação e na lista de funções da transação. Na classe de carteira atual, vamos criar o bom método de linhas de transação observáveis. Isso retornará que eles receberão uma chamada de método de lista de linhas de transação observável chamada de método de lista de linhas de transação no campo de linhas de transação. Também vamos criar o método de transações claras aqui. Isso chamará as linhas de transação método claro que acabamos de criar. Agora vamos para o serviço de atualização da carteira atual. Aqui, chamaremos o método atual de transações de compensação de carteira . Ao fazer isso, garantimos que limparemos as linhas de transação após criar uma carteira. Agora, vamos para o controlador da tabela de transações. Vamos adicionar os seguintes campos. Será usado no método inicializado posteriormente para vincular a tabela e suas colunas às linhas de transação observáveis. Agora vamos criar o método inicializado. Aqui, primeiro definiremos itens da tabela de transações para as linhas de transações observáveis da carteira atual. Agora, adicionaremos um ouvinte às linhas de transações observáveis da carteira atual. Chamaremos o método de atualização da tabela de transações no corpo para que cada alteração que ocorra no observável acione um redesenho da tabela. Além disso, vinculará cada campo da coluna ao campo da linha da transação usando a fábrica do valor da célula definida, assim como fizemos no controlador da tabela de endereços. Como parâmetro de fábrica do valor da propriedade, precisamos usar os mesmos nomes de propriedades que usamos na classe real da transação para fazer a vinculação corretamente. Vamos duplicar essa linha três vezes e alterar as colunas que estamos vinculando. Agora vamos para a classe de teste de transação receptora. Verifique se você está executando o Bitcoin Core Node e faça o teste. Boops, o teste falhou. Vamos ver o porquê. Há um problema com o campo de balanceamento de transações da coluna no controlador da tabela de transações. Para corrigir isso, vamos até o ponto FXML da tabela de sublinhado de transações. O problema é que nomeamos incorretamente o saldo, confirmações e os IDs de câmbio de data. Todos os três estão faltando a palavra transação após coluna. Então, vamos corrigi-los e executar o teste novamente. Ótimo, o teste foi aprovado. No próximo vídeo, adicionaremos mais testes para garantir que a tabela de transações esteja funcionando conforme o esperado. C, sim. 40. 38 Receber transação parte 3 skillshare 2: Neste vídeo, adicionaremos mais testes para verificar se nossa tabela de transações funciona para outros cenários. Então, vamos para a aula de teste de bloco receptor. Em cada método, adicionará código para testar se a tabela de transações contém as informações esperadas sobre as transações recebidas. Então, vamos renomear a exibição de tabela neste teste para abordar sua visualização em tabela, para esclarecer seu significado. Agora, chamaremos o método click on passando como parâmetro, a string transactions. Agora vamos copiar a linha com a variável de visualização da tabela de endereços e colá-la abaixo. Vamos mudar o nome dessa variável para a exibição da tabela de transações. No método de pesquisa, vamos substituir esse parâmetro pela tabela de transações de hashtag. Agora vamos copiar essas duas linhas, colá-las abaixo e alterá-las para chamar esses métodos na visualização da tabela de transações. Vamos fazer o mesmo com o outro método de teste. Mas, nesse caso, esperamos que a tabela de transações contenha duas linhas, uma para cada transação. E para a segunda linha, esperamos que o número de confirmações seja igual à variável total de confirmações, que criará o valor total de confirmações igual ao número dos blocos meus até agora, esse número será igual a confirmações mais confirmações menos uma. Como esperamos que a segunda linha contenha informações sobre a primeira transação, isso será confirmado esse número de vezes. Vamos fazer uma pequena correção no método de blocos de minas. Às vezes, essa linha de código gera uma NullPointerException devido ao TableView ter uma propriedade de itens nulos. Para evitar isso, vamos usar o operador seguro nulo antes de cada propriedade na exibição em tabela. Agora, vamos fazer nossos testes. Primeiro, certifique-se de executar seu node Bitcoin. Vamos fazer os testes. Os dois últimos testes falharam. Isso aconteceu porque as transações na tabela não estão ordenadas, seu pedido é aparentemente aleatório. Às vezes, esses testes podem ser aprovados porque podem ser ordenados corretamente por acaso. Então, vamos corrigir isso. Nosso objetivo é classificar as transações por data com as transações mais recentes nas primeiras linhas. Então, vamos para a classe da linha de transação. No método de formulário. Vamos mudar a forma como passamos os dados para a instanciação da linha de transação. Em vez de usar uma nova data, vamos usar o método instant now. Estamos fazendo isso porque a aula instantânea é mais precisa e fácil de classificar por Parson. Agora vamos para o controlador da tabela de transações. Na tabela de transações, defina itens (método call). Vamos passar uma nova lista ordenada como parâmetro. As linhas de transação observáveis da carteira atual serão o primeiro parâmetro a instanciar a lista classificada. O segundo parâmetro será a chamada do método de comparação do comparador. Esse método passará um lambda como o primeiro parâmetro ou uma linha de transação será o parâmetro no corpo do lambda. Vamos chamar o método de análise instantânea, passando a rotação da transação como parâmetro. O método parse gerará um objeto de instância a partir da string de data. O segundo parâmetro do método de comparação será a chamada do método de ordem inversa do comparador. Dessa forma, esperamos que a tabela de transações seja classificada pela data da transação, com as transações mais recentes primeiro. Agora vamos fazer nossos testes novamente. Desta vez, apenas os que falharam. Faremos isso clicando nesse botão. Ótimo, os testes foram aprovados. Agora vamos adicionar testes de tabela de transações à classe de teste de recebimento de Bitcoin. Faremos o mesmo que fizemos na aula de teste de blocos de recebimento. Para cada método, refatoraremos o nome da visualização da tabela, faremos com que o teste clique na guia de transações e faremos afirmações sobre o conteúdo esperado na tabela de transações. Vamos fazer isso. Ok, agora, vamos fazer esses testes. Ótimo, os testes foram aprovados. Agora, usaremos nossa carteira no ambiente de teste da rede pela primeira vez. O ambiente da rede de teste é semelhante ao da rede principal, mas suas moedas não valem nada. É muito mais fácil se preocupar e o tempo de bloqueio é menor. Isso exige que executemos e afundemos nosso nó Bitcoin nesse ambiente. Falamos sobre como fazer isso no guia de configuração do curso. Então, vamos modificar nosso bitcoin.com para executar nosso node no ambiente de teste da rede. Basta alterar essa chave de reg test para test net. Vamos parar de executar nosso node no teste de registro. E vamos rodar nossa nota novamente para começar a afundar nossa nota na rede de teste. Minha nota está quase acabando, então vou levar alguns minutos para ser atualizada. Mas, dependendo da última vez que você o executou , pode levar mais tempo para sincronizarmos , pois o download dos blocos mais recentes levará algum tempo. De qualquer forma, enquanto está afundando, vamos modificar nossos projetos para que possamos executar nosso aplicativo na rede de teste com sucesso. No caminho dos recursos, vamos criar o aplicativo de arquivo test net dot properties. Esse arquivo conterá as propriedades usadas em nosso projeto quando executarmos o aplicativo no ambiente de rede de teste. Vamos copiar o conteúdo do arquivo de propriedades de pontos do aplicativo e colá-lo aqui. Agora, mude o ambiente Bitcoin para testar a rede. E a porta URI sem pontos RPC 218332. Essa é a porta padrão do nosso node quando ele é executado no ambiente de rede de teste. Agora, vamos fazer uma pequena melhoria. Em nossa carteira, seria bom poder copiar o ID da transação mostrado na tabela de transações simplesmente clicando com o botão direito do mouse sobre elas e clicando em Copiar. Vamos implementar esse recurso. Para fazer isso, vamos até a tabela de sublinhado de transações dot FXML. Agora vamos adicionar o código a seguir aqui. Primeiro, vamos adicionar essas tags de menu de contexto dentro dela. Vamos adicionar a tag de itens. Em seguida, a tag dos itens do menu. Nessa propriedade de texto de tags, adicione a cópia da string e ID da transação do café com hashtag como está na propriedade de ação. Isso faz com que o aplicativo chame o método de cópia da ID da transação no controlador da tabela de transações. Depois de clicarmos no item Copiar menu no menu de contexto. O menu de contexto é um menu que aparece depois que clicamos com o botão direito do mouse em algo na tela. Agora, vamos para o controlador da tabela de transações. Vamos criar o método de cópia do ID da transação aqui. Primeiro, obteremos a linha da transação que foi clicada com o botão direito do mouse usando esse código. Agora vamos simplesmente chamar o método de cópia. Criaremos a passagem do ID da linha da transação como seu parâmetro. Para criar esse método, criará primeiro um pacote utils dentro do pacote BYOD W. Dentro dela, vamos criar uma classe chamada Copy. Agora, vamos criar o método de cópia aqui. Como um método estático. Instanciará um objeto de conteúdo da área de transferência, armazenando-o na variável de conteúdo. Em seguida, chamaremos o método put string nele, passando o texto da variável como seu parâmetro. Vamos adicionar essa variável como parâmetro do método de cópia. Por fim, chamaremos o método get system clipboard e definiremos seu conteúdo como o conteúdo variável no controlador da tabela de transações. Vamos importar esse método. Mais uma coisa. Ao executar o nó Bitcoin no ambiente de rede de teste, nosso nó pode receber diferentes tipos de transações que a biblioteca Bitcoin Java ainda não consegue analisar e gerar erros ao tentar fazer isso. . Embora a não análise dessas transações afete nossas carteiras, o erro foi bem gerado. Para evitar isso, na classe de tarefa node, envolva o método de transação do fluxo de bytes em um bloco try-catch. No bloco de captura, vamos usar um registrador para nos avisar sobre o erro. No único método, a chamada passará uma frase indicando o erro e um par de chaves no final. Esses colchetes serão interpolados pelo segundo argumento, que será a variável de conteúdo codificada hexadecimal interpolados pelo segundo argumento, que será a . O terceiro parâmetro será o objeto de exceção. Assim, podemos acessar todo o rastreamento da pilha do erro nos registros. Após o registro, o erro irá diretamente para a próxima iteração do loop while usando a palavra-chave continue. Vamos criar o campo do registrador. Será uma propriedade estática. Vamos instanciá-lo aqui usando a fábrica de registradores. Vamos corrigir a importação da classe logger. Na verdade, temos que importá-lo do pacote 4D dot SELF for J. Agora vamos executar nosso aplicativo no ambiente de rede de teste. Primeiro, vamos verificar se nosso nó está vinculado ao ambiente da rede de teste. Ok, já está afundando porque seu progresso é igual a 1,00. Agora vamos para a classe de aplicação BYOD W. Clique com o botão direito do mouse nesse símbolo e clique em modificar configurações de execução. Agora, clique em modificar opções e verifique se as opções da VM de anúncios estão selecionadas. Agora, defina-o para menos d perfis de pontos de mola, ponto ativo é igual à rede de teste. Clique em OK e clique no botão Executar. Agora vamos criar uma carteira. Observe que o endereço de recebimento começa com TB, indicando que é um endereço de rede de teste. Agora, vamos copiar esse endereço. Usarei uma torneira de rede de teste para obter Bitcoins líquidos de teste. Uma torneira de Bitcoin é um site ou API que oferece Bitcoins gratuitamente. Eles foram muito populares nos primeiros anos do Bitcoin, quando um Bitcoin era muito barato. Atualmente, existem maneiras rápidas de obter moedas líquidas de teste. Vamos acessar o site na tela. É uma torneira de rede de teste. Vamos colar o endereço copiado nesse campo. Escolha um valor e clique nesse botão para nos enviar Bitcoin. Vamos esperar um pouco. Ok, o alerta diz que ele envia alguns Satoshi para nossa carteira. Vamos verificar se o recebemos. Ótimo. Nossa carteira identificou nossa transação e nossa transação e endereço já têm uma conformação. Mas há uma coisa estranha. A balança é formatada em notação científica. Vamos corrigir isso mais tarde. Por enquanto, vamos copiar nosso ID de transação clicando com o botão direito do mouse nele e clicando em Copiar. Verificaremos a transação em um explorador de blockchain de terceiros. Um explorador de blockchain é um site que mostra informações sobre endereços, blocos e transações de Bitcoin de uma forma agradável e organizada. Se você está preocupado com sua privacidade, pesquisar seus vestidos vermelhos e transações no não é aconselhável pesquisar seus vestidos vermelhos e transações no explorador de blockchain de terceiros , pois permite que eles vinculem você aos dados de sua carteira. Mas como o estamos usando apenas para fins de teste, tudo bem. Com isso dito, vamos acessar o site na tela, que é um explorador de blockchain do Bitcoin test net, colar o ID da transação copiada no campo de pesquisa e clicar no botão Pesquisar. Aqui, obteremos algumas informações sobre nossa transação. Observe que ele já tem duas confirmações, mas nossa carteira indica que ele tem apenas uma conformação. Acontece que, no ambiente de teste da rede, nosso node Bitcoin só envia notificações de transação por meio zero MQ quando as transações são enviadas e quando recebem uma confirmação. Depois disso, não importa quantas confirmações sejam recebidas, o nó não notifica nosso aplicativo sobre isso. Precisamos fazer com que nosso aplicativo comece a ouvir as notificações de bloqueio para que possamos resolver esse problema. Começaremos a fazer isso no próximo vídeo. vejo. 41. 39 Receber bloco parte 2 skillshare 2: Neste vídeo, faremos com que nosso aplicativo comece a ouvir mensagens de bloqueio do nó Bitcoin. Dessa forma, poderemos atualizar nossas confirmações de transações corretamente no ambiente de rede de teste. Também modificará a formatação do endereço e dos saldos de transações, pois agora eles não estão sendo exibidos bem nas tabelas. Então, vamos para o arquivo bitcoin.com. Vamos mudar essa chave para o teste de registro. Para começar a ouvir mensagens de bloqueio, vamos adicionar a propriedade de bloco de hash pub Z MQ aqui. Seu valor será o mesmo URL na propriedade acima. Então, vamos colá-lo aqui. Essa configuração fará com que os nós enviem o bloco de hash para nosso aplicativo após detectar um novo bloco, estendendo o blockchain. Depois disso, o código será criado enviará uma solicitação de lista não gasta para o nó contendo todos os endereços atuais da carteira. Em resposta, receberemos uma lista de UTXOs atualizados que serão analisados e usados para atualizar nossos vestidos vermelhos e tabelas de transações. Vamos salvar o arquivo bitcoin.com. Agora, vamos para a classe de tarefas node. Vamos duplicar essa linha. Vamos mudar a string para um bloco de hash. Dessa forma, começaremos a receber mensagens de bloqueio de hash do node. Agora, nesta instrução if, vamos adicionar o código a seguir. Se o tópico for igual a nulo ou se a lista com esses tópicos não contiver o tópico recebido. Em seguida, passaremos para a próxima iteração do loop while. Agora, vamos adicionar uma instrução switch aqui. Caso a variável do tópico seja igual a ra t x. Em seguida, executamos o código para analisar e processar a transação recebida. Vamos mover a linha que publica evento da transação recebida para esse local. Dessa forma, podemos remover essa instrução redundante continue caso a variável tópico seja igual ao bloco de hash. Em seguida, usaremos o editor do evento do aplicativo para publicar um novo bloco de eventos recebidos. Vamos criar esse evento no pacote de eventos da BYU w dot no doubt. Agora vamos criar um ouvinte para esse evento no pacote BYOD w dot, dot listeners. Vamos adicionar uma anotação de componente a ela. Vamos fazer com que ele implemente a interface do ouvinte do aplicativo, passando o evento do bloco recebido como seu parâmetro de tipo. Vamos implementar seu método. Primeiro. Obteremos todos os endereços de carteira atuais usando esse método e os armazenaremos na variável de endereços. Vamos injetar a carteira atual nessa classe. Em seguida, usar uma instrução if verificará se a variável de endereços está vazia. Caso contrário, usaremos o serviço de atualização UTXos para atualizar nossos endereços e transações. Vamos injetá-lo nesta classe. Vamos chamar o método de atualização nele, passando o endereço é variável e o nome da carteira atual como parâmetros. Agora vamos para a transação recebida, o ouvinte otimizará nosso código. Lembre-se de que depois de receber uma confirmação no ambiente de rede de teste e todas as confirmações no ambiente de teste de registro, o nó envia uma mensagem de transação para nosso aplicativo por meio de zero MQ. Como, a partir de agora, nosso ouvinte de blocos recebidos atualizará todos os endereços atuais da carteira quando receber confirmações, não faz sentido atualizar a tabela de endereços e transações no a transação recebeu a classe de ouvinte após recebermos mais mensagens de transação repetidas. Portanto, modificaremos essa classe para processar transações somente se a carteira atual não as contiver. Então, vamos adicionar essa declaração if. Se os IDs de transação atuais da carteira contiverem o ID da transação recebida , simplesmente retornaremos. Vamos criar esse método. Ele retornará uma lista de cadeias de caracteres e retornará as linhas da transação, método get transaction IDs. Vamos criar esse método. Aqui. Retornaremos o código a seguir de um fluxo da lista de funções da transação. Chamaremos o método de mapa passando uma referência ao método getID da linha de transação. Em seguida, converteremos o resultado em uma lista e o devolveremos ao ouvinte da transação recebida. Precisamos agrupar esse código em um bloco de tentativa de captura porque o método de ID da transação gera uma exceção verificada no bloco de captura usará um registrador para imprimir uma mensagem de aviso. Vamos injetar o registrador nessa classe, assim como fizemos na classe de tarefa node. Vamos também adicionar uma declaração de retorno ao bloco de captura. Agora, vamos corrigir o problema de formatação balanceada da linha de endereço. Em vez de usar o método de duas cadeias de caracteres de classe dupla, usaremos o formato Bitcoin ou o método de formato passando o saldo do endereço como parâmetro. Vamos criar essa classe no pacote utils. Agora, vamos criar o método de formatação. Aqui, instanciaremos um novo objeto de símbolos de formato decimal passando a rota local para seu construtor. Em seguida, definiremos o ponto como separador decimal e a vírgula como separador de agrupamento. Em seguida, instanciaremos um novo objeto de formato decimal , pois seu parâmetro construtor passará esse padrão. E a variável dos símbolos. Em seguida, definiremos o formato ou o agrupamento usado como falso. Em seguida, definiremos seus dígitos fracionários mínimos para oito. E é o máximo de dígitos fracionários 282. Por fim, chamaremos o método de formato no formatador, passando o número recebido como parâmetro e o retornaremos. uso desse método formatará qualquer número de passagens para ele com dígitos decimais e sem separadores de agrupamento. Esse tipo de formatação é útil, pois um bitcoin pode ter no máximo oito dígitos fracionários. Essa formatação também facilita a visualização de quantos Satoshi um balanceado contém. Agora vamos para a classe da linha de transação. Vamos usar o formatador Bitcoin aqui para formatar o saldo UTXO no método de quadro. Agora, vamos ajustar nossos testes para cobrir essa nova formatação de balança. Vamos para a classe de teste de GUI no método send Bitcoin in weight, vamos alterar o segundo tipo de parâmetro para o dobro e ajustar seu valor padrão de acordo. Vamos também adicionar esse parâmetro de valor opcional com um valor padrão de 1,0. Agora, vamos substituir esse parâmetro pela variável de quantidade. E aqui vamos agrupar a variável de valor total esperado no formato ou método de formato Bitcoin. Agora, vamos fazer o teste de recebimento de Bitcoin. Vamos modificar isso e o Bitcoin e aguardar a chamada do método para enviar 0,00 001 Bitcoin. Assim, podemos testar a nova formatação quando nossa carteira recebe frações de Bitcoin. Agora, vamos verificar cada uso desse método e modificar sua parametrização do parâmetro de quantidade total esperada para passar um duplo em vez de uma string. Agora, vamos adicionar essas verificações nulas às propriedades de exibição de tabela nesse método para evitar exceções de ponteiro nulo. Agora, vamos executar nosso node e executar todos os testes do projeto. Ótimo, os testes foram aprovados. Agora, vamos executar nosso aplicativo no ambiente de rede de teste. Para fazer isso, vamos ajustar nosso arquivo bitcoin.com. Agora, vamos reiniciar nosso node. Depois de alguns minutos, minha nota está totalmente vazia. Agora, vamos executar nosso aplicativo no ambiente de rede de teste usando nossa configuração de execução modificada anteriormente. Vamos criar uma nova carteira. Agora, vamos copiar nosso endereço e usar uma torneira de rede de teste para receber o de Satoshi, assim como fizemos em um vídeo anterior. Ok, nossas carteiras identificaram com sucesso a transação e ela está balanceada, exatamente como esperávamos. Agora, vamos comer um sanduíche e deixar nossa carteira aberta por um tempo. Depois de alguns minutos serem resolvidos transação já obteve quatro confirmações. Ótimo. 42. 40 Total de saldo parte 1 skillshare 2: Neste vídeo, começaremos a desenvolver o recurso de saldo total. Basicamente, será um texto acima da guia de transações e endereços indicando que o saldo da carteira atualmente carregada mostrará o saldo confirmado, o saldo não confirmado e o saldo total. O saldo confirmado mostrará a soma de todos os UTXOs confirmados. O saldo não confirmado é a soma de todos os UTXOs não confirmados. O saldo total será a soma dos saldos não confirmados e confirmados. Então, vamos ao playground dot FXML para esboçar algo. Após o primeiro fechamento do painel da guia. Vamos adicionar essa etiqueta de etiqueta. Agora, vamos adicionar essa tag de margem de pontos VBox. Dentro dela. Adicione essa tag de inserções. Adicionaremos algumas propriedades de margem aqui. Vamos definir a margem inferior para 10,0, a margem esquerda para 10,0 e a margem superior para zero. Agora, para fins de teste, vamos definir a propriedade de texto desse rótulo como um teste. Vamos ver como fica no Scene Builder. Ok, vemos que os textos balanceados estarão localizados aqui. Vamos remover essa propriedade de texto. Vamos criar um novo arquivo FXML chamado saldo total do sublinhado. Vamos remover esse clichê. Agora, vamos copiar todo o conteúdo e a etiqueta que acabamos de criar no playground. E cole aqui. Vamos também copiar essas duas linhas de importação e colá-las no ponto balanceado total do sublinhado FXML. Agora vamos substituir as tags de rótulo pela tag raiz de dois pontos FX. Ele terá um ID FX de saldo total e um tipo de rótulo de ponto Java FX, ponto de controle de pontos. Vamos também incluir essa propriedade XML e S. Agora, na janela principal, vamos adicionar a etiqueta do controlador de saldo total após o primeiro painel de fechamento da guia. Agora vamos criar esse controlador no pacote de controladores. E vamos importá-lo aqui de volta para o controlador. Vamos fazer com que ele estenda a classe do rótulo e adicione a anotação do componente a ela. Agora, vamos copiar esse construtor e colá-lo aqui, modificando-o adequadamente. O valor do recurso FXML será a localização do ponto balanceado total do sublinhado FXML. Vamos também injetar a carteira atual nessa classe. Agora, no ouvinte iniciado pela GUI, vamos adicionar a classe do controlador de equilíbrio total ao conjunto de componentes personalizados. No controlador de saldo total. Vamos adicionar o método inicializado. Usaremos o método setText herdado para definir o texto do rótulo dinamicamente. Vamos configurá-lo para testar para fins de teste por enquanto. Agora, vamos criar o teste de equilíbrio total no pacote de GUI. Isso estenderá a classe de teste de GUI. Vamos copiar esses dois métodos e colá-los no novo teste. Vamos renomear esse método. Dois devem calcular o saldo total. Agora, vamos fazer alguns ajustes no corpo. O nome da carteira criada será minha validação de teste. Vamos remover essa linha, pois não precisaremos dela. Vamos também remover essas linhas. Com esse código, obterá o texto presente na etiqueta do saldo total e armazenará na variável de texto do rótulo. Em seguida, o bloco verificará se a variável de texto do rótulo é igual à seguinte frase. Depois de receber a transação, esperamos que o conteúdo do rótulo mostre que nossos saldos totais e não confirmados são de um Bitcoin. Esperamos que o saldo confirmado seja zero, pois nossa transação não será incluída em um bloco e mente durante o teste. Antes de executar nosso node, vamos garantir que nosso ambiente Bitcoin dot conf esteja configurado para teste de registro. Agora, vamos executar nosso node. E vamos fazer esse teste. Ele falhou conforme o esperado porque o rótulo do saldo total contém o teste de sequência de caracteres em vez do que queríamos. No próximo vídeo, implementaremos esse recurso e faremos com que esse teste seja aprovado. vejo. 43. 41 balanço total parte 2 skillshare 2: Neste vídeo, concluiremos implementação do recurso de saldo total. Então, vamos para o serviço de atualização UTXos. No método de atualização, adicionará uma nova chamada de método para atualizar o saldo da carteira. Para isso, chamaremos o método de atualização na atualização do saldo da carteira atual que o serviço criará. Vamos injetar esse serviço nessa classe. Vamos criar essa classe no pacote de serviços de pontos da GUI. E vamos terminar de injetá-lo aqui. Agora, vamos criar seu método de atualização. Aqui, primeiro calcularemos saldo não confirmado e o armazenaremos na variável de saldo não confirmado. Para isso, precisaremos injetar a carteira atual nessa classe. Em seguida, obteremos suas linhas de transação observáveis e as converteremos em um fluxo. Em seguida, usaremos o método de filtro no resultado para excluir as linhas da transação com confirmações diferentes de zero. Em seguida, usaremos o método de mapa para converter o fluxo obtido em um fluxo de saldos de linha de transações. Usaremos o método parse double para converter cada string balanceada em uma dupla. Agora usaremos o método reduzido, passando o método de soma dupla para ele, para alguns dos saldos obtidos no fluxo. Finalmente, usaremos o método or else passando 0.0 para ele. Portanto, caso o fluxo obtido esteja vazio, a variável balanceada não confirmada será definida como zero. Agora, vamos duplicar esse bloco de código. Vamos modificá-lo para calcular o saldo confirmado e armazená-lo na variável balanceada confirmada. Só precisamos mudar o sinal de igual e o método de filtro para esse sinal maior que. Com essa simples modificação, obteremos a soma dos saldos de todas as transações com pelo menos uma conformação. Por fim, chamaremos o método de saldos definidos na carteira atual, passando o saldo não confirmado e o saldo confirmado como parâmetros. Como esse código modificará a interface do usuário, vamos agrupá-lo em uma chamada de método posteriormente executada pela plataforma. E vamos criar o método de saldos definidos na classe de carteira atual. Para fazer isso, vamos adicionar o campo de saldos a essa classe. Seu tipo será a classe de saldos que criaremos. Vamos criá-lo no pacote observables. E vamos instanciá-lo aqui. Aqui, chamaremos esse método de saldos definidos no campo saldos, passando os saldos não confirmados e não confirmados como seus parâmetros. Vamos criar esse método. Primeiro. Vamos adicionar alguns campos privados a essa classe. Adicionaremos o campo balanceado não confirmado da propriedade do tipo string. Vamos instanciá-lo aqui com uma nova propriedade de string simples. Vamos duplicar essa linha duas vezes. Vamos alterar esses nomes de campo para confirmar o saldo e o saldo total. Agora, no método set balances, chamará o método set nas propriedades injetadas para definir seus valores. Usaremos o formato ou método de formato Bitcoin para formatar os saldos no formato desejado. Para o saldo total passará a soma dos saldos não confirmados e confirmados. Agora, vamos criar getters para esses campos. Vamos também criar o método claro. Esse método definirá o saldo de cada propriedade como zero. Chamaremos esse método depois de criarmos uma carteira para apagar os valores da carteira carregada anteriormente. Agora, na carteira atual, vamos criar o método de bons saldos. Isso retornará o campo de saldos. E vamos criar o método de balanços claros. Isso chamará o método claro de saldos. No serviço de atualização da carteira atual, que é chamado após a criação de uma carteira, vamos chamar o método de compensação de saldos da carteira atual aqui. Agora, vamos para o controlador de saldo total. Vamos remover essa linha. Obteremos a propriedade balanceada não confirmada dos saldos atuais da carteira. Chamaremos o método do ouvinte de anúncios nele. Passaremos um lambda como parâmetro, onde no corpo chamaremos o método de atualização do texto. Vamos criar esse método. Chamaremos o método setText nele e passaremos uma chamada de método em formato de string como seu parâmetro. O primeiro parâmetro do método de formato será essa frase. Cada sinal de porcentagem seguido pela letra S será interpolado pelos seguintes parâmetros dessa chamada de método. Os próximos parâmetros serão o saldo total atual da carteira. O saldo confirmado da carteira atual. E, finalmente, o saldo atual não confirmado da carteira. Agora, no método inicializado, vamos duplicar essa linha duas vezes. Adicionaremos o mesmo ouvinte à propriedade balanceada confirmada e à propriedade de saldo total. Então, vamos modificar essas linhas adequadamente. Vamos refatorar essa string, incluindo-a em uma constante nessa classe. Vamos chamá-lo de texto equilibrado e torná-lo privado. Agora, vamos fazer uma pequena modificação no serviço de atualização UTXos. Observe que já temos uma anotação assíncrona no método de atualização. Portanto, adicionar a mesma anotação no método é chamado de é redundante. Portanto, vamos removê-los. Primeiro no serviço de atualização de endereços da carteira atual. Em seguida, na atualização do serviço de transação atual da Wallet. Outra coisa que notei é que precisamos agrupar a chamada do método das linhas de transação de anúncios e uma plataforma para aprender mais tarde, uma vez que ela modifica elementos na interface do usuário. Agora vamos ao teste de equilíbrio total. Vamos garantir que nosso node Bitcoin esteja funcionando. E vamos dirigir nossos grupos de teste . O teste falhou. Vamos ver o porquê. Acontece que esqueci de adicionar a anotação de serviços ao serviço de atualização do saldo da carteira atual. Vamos consertar isso. E vamos fazer nosso teste novamente. Ótimo, o teste foi aprovado. No próximo vídeo, adicionaremos testes mais balanceados em nossos outros testes para garantir que estejam funcionando conforme o esperado. 44. 42 Total saldo parte 3 skillshare 2: Neste vídeo, implementaremos mais testes para garantir que o recurso de balança esteja funcionando corretamente. Então, vamos copiar essa linha e o teste de equilíbrio total. Primeiro, adicionaremos algumas afirmações de teste sobre o saldo e o teste do bloco receptor. Então, vamos colar a linha aqui. Vamos também copiar essa linha e colá-la no bloco seguinte deste teste. Neste teste, esperamos que o saldo total seja igual a um Bitcoin. Então, vamos ajustar essa frase adequadamente. Também esperamos que todo o saldo seja confirmado. Vamos fazer o mesmo com esse outro teste. Nesse caso, esperamos que o saldo total seja igual a dois bitcoins, também confirmados. Agora vamos verificar se nosso node está em execução e executar o teste. Os testes foram aprovados. Agora, vamos adicionar algumas afirmações de equilíbrio à classe de teste de Bitcoin recebedor. Nestes testes, espera-se apenas saldos não confirmados. Vamos fazer esses testes. Ótimo, os testes foram aprovados. 45. 43 Enviar parte do bitcoin 1 skillshare 2: Ok, até agora, com nossa carteira, podemos receber Bitcoins usando endereços gerados. Também podemos inspecionar o saldo recebido por cada endereço e verificar as informações sobre nossas transações. Agora, começaremos a implementar a capacidade de gastar esses bitcoins enviando transações para outros endereços que quisermos. Então, vamos começar a criar um teste chamado send Bitcoin test no pacote de teste da GUI. Isso estenderá a classe de teste de GUI. Adicionaremos o mesmo método de configuração. Adicionamos dois outros testes, chamando a carteira de carga e adicionando o método balanceado. Vamos criar um teste chamado should send Bitcoin. Agora no bloco de vento, criará uma nova carteira e enviará um Bitcoin para seu primeiro endereço. O código a seguir será muito semelhante ao código dos outros testes. Depois de enviar um Bitcoin para o endereço da nossa carteira, clicaremos na guia Enviar. Em seguida, clicaremos no campo de valor para definir quanto queremos enviar. Vamos enviar 0,5 Bitcoin, que é metade do nosso saldo neste momento. Agora, clicaremos no campo de endereço para enviar. Neste teste enviará bitcoins para outro endereço. Então, vamos usar o cliente Node get new address para obter um novo endereço de nó. Em seguida, escreveremos o endereço obtido na entrada clicada. Agora, clicaremos no botão Enviar. Depois disso, esperamos que um modal seja aberto com informações sobre a transação e um botão OK para confirmar e enviar a transação. Então, vamos chamar o método click on passando ok, como seu parâmetro. Agora, clicaremos na guia de transações. E com o código a seguir, verificaremos se a tabela de transações tem duas linhas, uma para a transação recebida e outra para a transação que acabamos de enviar. Agora, vamos ao playground dot FXML para criar nossa guia Enviar. Vamos duplicar o código da guia Receber. E vamos mudar seu texto para enviar. Vamos excluir essas linhas para começar com uma nova guia na qual trabalhar. Agora, vamos para o Scene Builder. Vamos clicar na guia Enviar. Vamos clicar no corpo da guia para selecionar o componente do painel de grade dentro dela. Vamos definir sua altura pref para 130 e sua largura pref para 600. Agora, vamos adicionar um controle de rótulo ao painel de grade dentro da guia Enviar. Vamos definir dez em suas margens superior, direita e esquerda. Vamos mudar seu nome para abordar esse fim. Agora, vamos adicionar um campo de texto a esse painel de grade. Vamos mudar o índice da coluna do painel de grade para um. Não está nos permitindo fazer isso. Primeiro, precisamos adicionar uma coluna ao painel da grade. Vamos clicar com o botão direito aqui e adicionar duas linhas e uma coluna ao painel da grade. Agora podemos alterar o índice da coluna TextField para um. Vamos definir dez em suas margens superior, direita e esquerda. Vamos mudar sua largura pref para 350. Vamos também mudar essa largura pref de Collins para 600. Vamos adicionar outro rótulo ao painel da grade. Vamos mudar o índice da linha para um e definir dez para as margens superior, direita e esquerda. Vamos também alterar seu texto para o valor a ser enviado. Vamos adicionar outro campo de texto ao painel da grade. E vamos definir o índice da linha como um e o índice da coluna como um. Vamos definir sua altura pref para 26. E sua largura preferida é 100. Vamos definir dez em suas margens superior, direita e esquerda. Agora vamos colocar o último campo de texto inserido em uma caixa H. Então, vamos adicionar uma caixa H ao painel da grade. E seus índices de linha e coluna são iguais a um. Vamos mover esse campo de texto para a caixa H. Também vamos definir dez para as margens superior, direita e esquerda de oito dólares . Agora vamos adicionar uma etiqueta à caixa H. Vamos também definir essas margens para dez e alterar seu texto para BTC. Na verdade, vamos colocar essas margens de volta a zero. Em vez disso, colocaremos cinco nesses recheios. Agora, vamos adicionar um botão OK ao painel da grade. E vamos definir seu índice de linha como dois. Também vamos definir essas margens para dez. E vamos configurar seu texto para enviar. Agora, vamos copiar todo o conteúdo da guia Enviar que criamos no playground dot FXML. Vamos criar a guia send underscore dot FXML no pacote FXML. E vamos colar o conteúdo copiado nesse arquivo. Vamos mudar a tag tab para a tag ética com cólon raiz. Vamos definir seu tipo para efeitos Java, pontos vistos, controle de pontos, guia de pontos. Agora vamos importar todas as tags restantes. Opa, definimos erroneamente a propriedade de tipo como rótulo. Vamos consertar isso. Agora, vamos definir o ID FX dessas tags. Primeiro, vamos definir esse ID de fax para enviar a guia. Esse ID fx para endereço, para enviar esse ID fx para o valor a ser enviado, esse ID de fax para enviar. Agora vamos para a janela principal de sublinhado dot FXML. Vamos duplicar essa linha e mudar essa tag para enviar o controlador de abas. Vamos criar esse controlador no pacote de controladores. E vamos importá-lo aqui. Isso estenderá a classe de tabulação e adicionará a anotação do componente a ela. Vamos copiar o construtor da guia Receber e colá-lo aqui, ajustando-o adequadamente. Vamos injetar a carteira atual nessa classe. Agora, vamos adicionar a classe do controlador da guia Enviar ao conjunto de componentes personalizados no ouvinte iniciado pela GUI. E vamos alterar o valor desse parâmetro para enviar o ponto FXML da guia de sublinhado. Agora vamos garantir que nosso node Bitcoin esteja funcionando. E vamos fazer nosso teste de envio de Bitcoin. Como esperado, o teste falhou. Nos próximos vídeos, continuaremos implementando esse recurso. C, sim. 46. 44 transações Bitcoin parte 2 skillshare 2: Neste vídeo, aprenderemos mais sobre transações de Bitcoin. Mais especificamente, aprenderemos mais sobre o tamanho e as taxas da transação. Esse conhecimento será necessário posteriormente, quando começarmos a criar transações para transferir Bitcoins de nossas carteiras para outros endereços. Na apresentação anterior, aprendemos que a taxa de transação é igual à soma de Bitcoin em entradas menos a soma de Bitcoins e saídas de uma transação. Lembre-se de que a taxa de transação é o preço que você paga para que um menor escolha sua transação do mental incluído em um bloco e a extraia. Quanto maior a taxa de transação, mais rápido a transação será incluída em um bloco. Com uma pequena taxa de transação, sua transação permanecerá na mente por mais tempo. Portanto, é importante escolher a taxa certa para garantir que sua transação seja confirmada em um prazo razoável, sem pagar demais. A taxa de transação varia muito com o tempo. Seu valor segue a lógica da oferta e da demanda. Quanto maior o número de transações enviadas, maior tende a ser a taxa de transação. E quanto maior o número de mineradores, menor tende a ser a taxa de transação. Este gráfico mostra a taxa média de transação em dólares nos últimos dois anos. Observe que, nesse período, a taxa de transação variou de alguns dólares a mais de $60 por transação. Então, como calculamos a taxa de transação? Considerando que os blocos de transação têm espaço limitado, mas demanda ilimitada, faz sentido que as taxas sejam calculadas pelo tamanho da transação. Existem diferentes maneiras de obter a taxa de transação recomendada. Por exemplo, você pode usar sites como Bitcoin Fees, earned.com. Aqui podemos ver quantas transações têm por taxa nas últimas 24 horas. Na coluna da direita, vemos uma estimativa de quanto tempo seria necessário para confirmar uma transação com essas taxas em blocos e minutos. Se você rolar para baixo, ele fornecerá uma taxa de taxa recomendada para usar. Isso quase garante que sua transação será confirmada no próximo bloco. Men pull dot space é outro site que, junto com gráficos interessantes, mostrando a taxa média de taxa de cada bloco, também mostra a taxa de taxa recomendada para usar em transações de baixa, média e alta prioridade. Quanto maior a prioridade, mais rápida se espera que a transação seja confirmada. Também podemos usar nosso método de taxa inteligente de estimativa RPC do Bitcoin Core Note . De acordo com sua documentação, ele toma como parâmetro uma meta de confirmação, que é o número de blocos que esperamos transacionar com a taxa de devolução necessários para serem confirmados. Também é necessário um parâmetro opcional para definir o modo de estimativa, que pode ser indefinido, econômico ou conservador. A taxa é retornada em Bitcoin por quilo de byte virtual ou byte de KV. Esses exemplos mostram que as taxas recomendadas podem variar muito entre as diferentes ferramentas. Para simplificar, em nossa carteira usaremos as estimativas de chamadas RPC do Bitcoin Core para smartphones, pois não exigirá que consultemos ferramentas externas com uma taxa de taxa. Portanto, podemos calcular a taxa de transação multiplicando o tamanho da transação em v bytes pela taxa em Satoshi is privy bite. Mas espere, o que é um byte virtual? Para calcular as taxas de transação, há dois conceitos importantes a serem entendidos primeiro tamanho virtual e byte virtual. Tamanho virtual, ou tamanho V, é o tamanho da transação em bits virtuais ou v bytes. São conceitos inventados para dar conta do tamanho menor das transações da Segway. O tamanho V é calculado de forma compatível com versões anteriores, para que predefina quais tamanhos de transação são iguais e predefina quais tamanhos de transação V. Para transações de Segway, o tamanho V é igual ao tamanho da parte não testemunha de uma transação mais o tamanho da testemunha dividido por quatro. A testemunha é um campo presente apenas nas transações da Segway. Ele contém os campos que nas transações pré-segmentadas estavam localizados no campo ScriptSig de cada entrada. Essa forma diferente de calcular os tamanhos das transações resulta em tamanhos de transação V menores para Segway em comparação com transações legadas. Por exemplo, para transações com uma entrada e uma saída, as transações do Segway têm 110 v bytes de tamanho, enquanto as transações legadas têm 192 v bytes de tamanho. Para transações com uma entrada e duas saídas, as transações do Segway têm 141 v bytes de tamanho, enquanto as transações legadas têm 226 v bytes. Finalmente, para transações com duas entradas em saídas, as transações do Segway têm 209 v bytes de tamanho, enquanto as transações legadas têm 374 bytes de tamanho. Então, digamos que queremos calcular a taxa para uma transação seguinte com uma entrada e duas saídas com uma taxa de taxa de 19. Satoshi é um byte privado. Para fazer isso, multiplicaríamos o tamanho v da transação, que é de 141 v bytes, pela taxa de taxa, que é de 19 Satoshi por v bytes. Isso daria 2.679 Satoshi em taxas por essa transação. Então, em resumo, para construir uma transação, precisaríamos criar os seguintes itens. Para uma saída, precisaríamos de um endereço e uma quantia para enviar para esse endereço. Se houver necessidade de uma mudança e a maioria das transações sim , precisaríamos criar uma segunda saída contendo um endereço de alteração e um valor. Também precisaríamos de um número variável de entradas cuja soma do valor do Bitcoin deveria ser maior do que a quantia a ser enviada mais a taxa de transação. Lembre-se de que uma entrada se referirá a uma saída não gasta de uma transação anterior enviada para um de seus endereços. Uma alteração será necessária se a soma dos valores de entrada for maior que o valor a ser enviado mais a taxa de transação. Se, por sorte ou por design, a soma dos valores de entrada for igual ao valor a ser enviado mais a taxa de transação a transação não terá um resultado alterado. E o remetente se beneficiará de pagar menos na taxa de transação por uma transação com apenas uma saída. Novamente, para calcular a taxa de transação será necessária a taxa em Satoshi por v bytes. Obteremos esse valor usando a API gRPC estimada do smartphone do Bitcoin Core e converteremos o resultado em por V de Satoshi também precisaremos do tamanho da transação em v bytes. No próximo vídeo, implementaremos as estimativas de notas, taxa inteligente, cliente e serviço para calcular o tamanho da transação. Posteriormente, combinaremos os dois para calcular as taxas de transação. Veja, sim. 47. 45 Enviar bitcoin parte 2 skillshare 2: Neste vídeo, criaremos uma calculadora do tamanho da transação e criaremos o cliente node para o método RPC do nó Bitcoin de alimentação inteligente estimada . No pacote de serviços api dot, vamos criar a classe de calculadora do tamanho da transação. Essa classe será responsável por calcular tamanhos das transações de acordo com seus tipos e números de entradas e saídas. Esses tamanhos serão usados posteriormente para calcular o valor da taxa que devemos incluir em nossas transações. Vamos adicionar uma anotação de serviços a ela. Primeiro, definiremos algumas constantes nessa classe. Essas constantes conterão os tamanhos de cada parte de uma transação. Como estamos trabalhando apenas com transações de Segway no momento, essas constantes se referirão apenas a partes das transações da Segway. Então, vamos começar a definir o tamanho da sobrecarga da transação. A sobrecarga é a parte da transação cujo tamanho não muda com o número de entradas ou saídas. A primeira constante será chamada de inversão, que faz parte da sobrecarga. Ele codifica qual versão a transação tem. Ele tem quatro bytes de tamanho. Em seguida, temos a contagem de entradas, que, como o nome sugere, especifica o número de entradas na transação. Ele tem um número variável de bytes, mas para até 252 entradas, seu tamanho é de um byte. Em seguida, temos o campo de contagem de saída, que tem o mesmo tamanho e regras da contagem de entrada. Como o próprio nome sugere, ele especifica o número de saídas na transação. Em seguida, temos o campo de tempo do lote N, que tem quatro bytes. Às vezes, esse campo é usado para codificar o tempo após o qual a transação pode ser gasta. Depois, temos o marcador e a bandeira do Segway, que estão presentes apenas para transações do Segway. Ele tem dois bytes de tamanho. Agora vamos definir os tamanhos dos campos de entrada, começando com o ponto de saída, que tem 36 bytes de tamanho. O ponto é a combinação do ID da transação anterior e do índice de saída. Ele indica o UTXO usado para essa entrada. Em seguida, temos o campo de comprimento do ScriptSig, que temos até 252 bytes, tem um byte. Ele indica o tamanho do ScriptSig para a entrada. Em seguida, temos o campo ScriptSig. Para transações de Segway. Seu tamanho é zero. Lembre-se de que, para entradas de segmento, o conteúdo do ScriptSig é movido para o campo de testemunha. Agora vamos adicionar o campo de sequência final. Ele tem quatro bytes de tamanho e é usado para definir se a transação é substituível caso o remetente queira alterar sua taxa. Em seguida, vamos adicionar o campo de contagem de testemunhas de até 250 aos itens de testemunhas. Ele tem um byte de tamanho. Em seguida, temos o campo de itens de testemunha, que tem um tamanho de 107 bytes para entradas P2, WP, k, h. Esse campo é composto pela assinatura, que pode ter 71 ou 72 bytes de tamanho, e a chave pública, que tem 33 bytes de tamanho, 72 bytes, é escolhida como o tamanho das assinaturas, já que preferimos superestimar um pouco o tamanho da transação. Portanto, o F0 calculado tem a garantia de ser suficiente para a transação. Os dois bytes restantes que codificam o tamanho da assinatura e da chave pública. Explique o valor constante de 107 do item da testemunha. Agora vamos definir as constantes com os tamanhos de saída. O valor n é a quantidade de bitcoin enviada nessa saída. Ele tem oito bytes de tamanho. Em seguida, temos o comprimento da chave pub do script, que tem um byte de tamanho para até 252 bytes no comprimento da chave do script pub. Em seguida, temos a chave script pub, que tem 22 bytes de tamanho por um segundo, quais endereços? Agora, antes de continuar implementando o cálculo do tamanho da transação, vamos criar o teste da calculadora do tamanho da transação no pacote de teste da API. Isso estenderá a classe de especificação. Vamos adicionar um campo de calculadora de tamanho de transação nessa classe. E vamos usar um método de configuração para instanciá-lo. Agora, vamos criar um nome de teste para calcular o tamanho da transação para saídas e entradas de transação P2, WP k, h. No bloco único, chamaremos o método de cálculo no serviço de calculadora do tamanho da transação e armazenaremos o retorno na variável de resultado. Como parâmetros passarão as entradas e saídas, que definiremos no bloco where. No bloco, verificaremos se o resultado é igual à variável de tamanho esperada. No bloco where, adicionará os seguintes casos de teste. Para as entradas e saídas, as variáveis definirão listas com um número variável de endereços. Como, por enquanto, não nos importamos com o tipo de endereço, simplesmente adicionaremos uma letra representando cada endereço. Os valores de tamanho esperados aqui foram previamente calculados para cada combinação de entradas e saídas e validados usando o Bitcoin Core CLI. Agora, vamos criar o método de cálculo na classe da calculadora do tamanho da transação. Ele retornará um número inteiro grande e receberá como parâmetros uma lista de endereços de entrada e uma lista de endereços de saída. Agora, vamos primeiro calcular o tamanho da sobrecarga. É igual à soma dessas constantes. Lembre-se de que o valor que queremos calcular aqui é o tamanho V. Portanto, os elementos das transações do Segway, como o Segway, o marcador e a bandeira, devem ser divididos por quatro. Dessa forma, vamos dividir essa constante por quatro. Agora, vamos calcular o tamanho da entrada. Será a soma dessas constantes. Agora, vamos calcular o tamanho de todas as entradas multiplicando a variável de entrada pelo número de endereços de entrada. Agora, vamos calcular o tamanho da testemunha adicionando a contagem de testemunhas e as constantes dos itens da testemunha. A seguir, quais elementos? Vamos dividir a soma deles por quatro. O tamanho total da testemunha é igual à variável da testemunha multiplicada pelo tamanho dos endereços de entrada. Agora, vamos calcular o tamanho da saída. Será igual à soma dessas constantes. A variável de todas as saídas será igual ao tamanho da saída vezes o número de saídas. Finalmente, o resultado do tamanho da transação será igual ao BigDecimal, alguns dos valores calculados anteriormente. Também vamos definir a escala do resultado para zero com o modo de arredondamento pela metade. Isso fará com que o resultado tenha zero casas decimais arredondadas para o número inteiro mais próximo. Se o valor decimal do resultado for cinco, ele será arredondado para o número inteiro acima. Agora, retornamos o resultado convertido em um número inteiro grande. Agora, vamos executar o teste da calculadora do tamanho da transação. Ótimo, o teste foi aprovado. Agora vamos criar o cliente node estimate smart Fee no pacote node dot client. Vamos injetar o cliente node nele. E vamos criar o método de estimativa inteligente de taxas. Ele retornará um novo nó que o objeto FI criará e usará um número inteiro como parâmetro. Agora, vamos voltar a fazer a chamada do método de solicitação no cliente node. O nome do método será a taxa inteligente estimada. Seu segundo parâmetro será um novo objeto de referência de tipo parametrizado. A terceira será uma string vazia e seu último parâmetro, a variável blocks. Agora vamos criar o registro node V no pacote domains dot node. Seus campos serão uma taxa dupla e uma lista de erros. Agora, no pacote de serviços api dot, vamos criar uma interface chamada serviço de taxa estimada. Vamos adicionar o método de estimativa a ele. Ele retornará um grande decimal. Agora, vamos criar uma implementação dessa interface. Os nomes anotam a taxa de serviço estimada no mesmo pacote. Vamos implementar seu método. Essa classe será usada posteriormente para estimar a taxa usando o cliente inteligente de taxas de estimativas do node. Se quisermos alterar o método de estimativa de taxas ou adicionar mais opções para fazer isso posteriormente, basta criar outra implementação da interface do serviço de taxa estimada. Primeiro, chamaremos o método de estimativa do smartphone a partir do cliente criado anteriormente e armazenado na variável node V. Vamos injetar esse cliente nessa classe e passar para esse método para que tentemos obter uma taxa que fará com que nossa transação seja confirmada no próximo bloco. Se, por algum motivo, a taxa devolvida for igual a nula, retornaremos a taxa de substituição. Vamos injetar essa variável nessa classe. Irá injetá-lo a partir dos arquivos de propriedades. Então, vamos adicionar essa anotação de valor antes dela. Após a declaração if, retornará o grande valor decimal da taxa da taxa. Agora, vamos adicionar a propriedade da taxa de fallback rate do bitcoin dot a todos os arquivos de propriedades do projeto. Vamos fazer com que seja igual a 0,002. 48. Seleção de moedas e poeira: Nesta apresentação, continuaremos explicando conceitos importantes para entender as transações de Bitcoin e continuar criando nosso recurso de transação pecaminosa. Então, vamos falar sobre seleção de moedas. seleção de moedas é o processo de selecionar UTXOs para criar uma transação. A regra geral para essa seleção é que a soma dos valores de Bitcoin em UTXos deve ser maior que a quantidade de areia mais a taxa de transação mais a alteração, se necessário. Existem muitos métodos diferentes de seleção de moedas. Cada um tem vantagens e desvantagens. O algoritmo que escolheremos para nossa carteira é chamado de sorteio aleatório único. É provavelmente o algoritmo de seleção de moedas mais simples e bom o suficiente para nossos propósitos. Esse algoritmo foi apresentado pela primeira vez em uma tese de mestrado intitulada e avaliação de estratégias de seleção de moedas de Mark Earhart. Eu recomendo a leitura desta tese se você quiser saber mais sobre estratégias de seleção de moedas. Esse método de seleção de moedas foi adicionado ao Bitcoin Core em setembro de 2021 como uma estratégia alternativa de seleção de moedas. Consiste em embaralhar os gastos ou UTXOs e, em seguida, selecionar os UTXOs um por um até que a soma dos valores de UTXOs selecionados seja maior ou igual ao valor a ser enviado mais a taxa de transação mais a mude, se necessário. Se o valor da alteração for menor que o limite de poeira, a saída da alteração será removida da transação e seu valor será adicionado à taxa da transação. Mas espere um momento, o que é poeira? Uma produção de poeira é uma produção cuja quantidade de Bitcoin é menor do que o custo de gastá-la. O exemplo a seguir mostra como as saídas de poeira não são econômicas de gastar. Digamos que você tenha um UTXO contendo 50 Satoshi e queira enviar esses 50 Satoshi para um amigo. Ao criar a transação, você descobre que a taxa de transação necessária para enviá-la é igual a 100 Satoshi. Portanto, não faz sentido gastar o UTXO com 50 Satoshi, pois você pagará mais em taxas do que o valor enviado. Além disso, seu amigo também não se beneficiará de receber um UTXO com 50 Satoshi pois ele teria o mesmo problema de você gastá-lo. Este exemplo mostra que é prejudicial para a rede Bitcoin criar saídas de poeira, já que ninguém na rede se beneficia disso. Portanto, a maioria dos nós de Bitcoin não relaciona transações contendo poeira. Isso ajuda a proteger a rede contra ataques de poeira. ataque de poeira é o processo de enviar poeira maliciosamente aos endereços da carteira para rastrear suas transações. Esse ataque é mostrado neste exemplo. Suponha que a agência governamental envie poeira para o endereço X que pertence à pessoa. Por quê? Quando a carteira eletrônica cria ingenuamente uma transação, ela inclui a saída de poeira e outras cinco como entradas. Agora, a agência governamental sabe por que cinco endereços anteriores e todas as transações anteriores. Além disso, o governo agora sabe o endereço da mudança dessa transação e contrata outras transações com ela. Mas quais são os critérios para considerar uma saída como poeira? O limite de poeira é usado para isso. Cada saída cuja quantidade de Bitcoin é menor que o limite de poeira é considerada poeira. O Bitcoin Core usa a seguinte fórmula para calcular o limite de poeira. O limite de poeira em Satoshi de uma saída de transação é igual ao tamanho da saída da transação mais o tamanho de entrada necessário para gastá-la em v bytes multiplicado pela folha da indústria em Satoshi por KV bytes divididos por 1.000. O resultado representa o custo de saída da transação que o valor de saída de Bitcoin de uma transação deve ser igual ou superior para não ser considerado pó. A taxa de retransmissão de poeira é uma propriedade de configuração do nó Bitcoin. É a taxa de transação usada ao calcular o limite de poeira. A taxa padrão de retransmissão de poeira é definida para 3.000 Satoshi por KV bytes ou três Satoshi por bit de V. Isso faz com que o limite de poeira padrão para saídas seguidas seja igual a 294. De Satoshi. O limite de poeira padrão para não segue quais saídas são iguais a 546 de Satoshi. Para obter mais detalhes sobre como calcular o limite de poeira, este link do código Bitcoin Core tem um comentário explicando como o limite de poeira é calculado. Agora vamos resumir as etapas gerais do algoritmo de sorteio aleatório único. O primeiro passo é agrupar todos os UTXOs da carteira em uma lista. Em seguida, para cada UTXO disponível na lista embaralhada, adicione esse UTXO a uma lista de UTXOs selecionados. Calcule a meta ajustada, que é igual à quantidade de areia mais a taxa de transação mais a alteração, se necessário. Se o valor total de Bitcoin na lista UTXOs selecionada for maior ou igual à meta ajustada. Pare. Finalmente, use os UTXOs selecionados como entradas da transação desejada. Alguns pontos de atenção sobre esse algoritmo, metas ajustadas com e sem a saída de alteração, devem ser calculados para melhor precisão, pois as taxas de transação diferem entre as transações. com saídas de 1,2, se a alteração gerada estiver entre zero e o limite de poeira, interrompemos a iteração, pois não incluiremos uma alteração na transação e, portanto, não precisaremos de mais UTXOs. Isso é necessário para não gerar uma saída de poeira para a mudança por acidente. A desvantagem do algoritmo de sorteio aleatório único aparece em alguns casos patológicos, por exemplo, quando você tem um único UTXO grande e muitos UTXOs pequenos. Uma transação com muitas entradas e uma alta taxa de transação pode ser criada em vez de usar o grande UTXO para evitar a necessidade de muitas entradas. Quando for esse o caso, uma abordagem diferente é recomendada para construir uma transação. Por exemplo, escolha manualmente os UTXOs que farão parte de algumas transações específicas. No próximo vídeo, implementaremos uma calculadora de poeira e o algoritmo de sorteio aleatório único, C, sim. 49. 47 Enviar parte do bitcoin 3 skillshare 2: Neste vídeo, começaremos a implementar uma calculadora de poeira e o algoritmo de sorteio aleatório único. Mas primeiro, vamos refatorar o registro UTXO. Já que faremos muitos cálculos com o campo de valor UTXO. E os cálculos são melhor feitos com números decimais grandes em vez de duplos para alterar a quantidade, tipo dois decimais grandes. Agora, temos que refatorar todos os usos do campo de quantidade no projeto. Então, vamos fazer isso. Vamos mudar o formato ou parâmetro de formato do Bitcoin para BigDecimal e ajustar esse parâmetro de acordo. Vamos fazer o mesmo com todos os métodos que o IDE sinalizou como erros no projeto. Aqui, adicionaremos números decimais grandes usando o método add. E vamos passar o grande valor decimal zero em vez do primitivo zero para essas chamadas de método. Agora, temos que mudar o tipo desse campo balanceado e todos os seus usos. Vamos refatorar esse método para fazer a soma usando grandes valores decimais. Também vamos ajustar esse código para fazer a mesma coisa, mas com grandes valores decimais. Ok, a refatoração está feita. Agora no pacote de serviços api dot. Vamos criar a classe de calculadora de poeira. Vamos adicionar a anotação do serviço a ela. Vamos criar esse método de poeira nele. Como o próprio nome sugere, ele retornará verdadeiro se uma quantidade for considerada falsa, caso contrário, retornará um booleano e tomará um grande número inteiro como parâmetro representando a quantidade em De Satoshi. Esse método avaliará se o valor em Satoshi de uma produção é menor do que o custo de gastá-la. O custo do gasto é igual ao tamanho V da saída mais o tamanho v da entrada necessária para gastá-la, que armazenará nessa constante vezes os pés do relé de poeira em Satoshi por quilo (v bytes). dividido por 1.000. Como trabalharemos apenas com saídas sigmóides por enquanto, nos preocuparemos apenas com o limite de poeira para saídas seguidas. Então, vamos criar essa constante que será igual a 98. Esse valor é retirado diretamente do arquivo dot cpp da política Bitcoin Core mencionado na última apresentação. Vamos também injetar a taxa de relé de poeira nessa classe. Ele estará pronto e seu valor será injetado do arquivo de propriedades. Vamos adicionar a seguinte anotação de valor antes dela. Agora vamos adicionar esse valor a todos os arquivos de propriedades. Vamos defini-lo para 3.000, o mesmo valor padrão usado no Bitcoin Core Node. Agora, no pacote de serviços api dot, vamos criar a interface do seletor de moedas. Criará essa interface para permitir mais flexibilidade. Se quisermos criar mais implementações de seletores de moedas posteriormente. Vamos adicionar o método de seleção a ele. Ele retornará uma lista dos UTXOs selecionados. E precisaremos de parâmetros, uma lista de UTXOs, um número inteiro grande para o valor a ser enviado, um decimal grande para a taxa, endereço a ser enviado e um endereço de alteração. Agora, no mesmo pacote, vamos criar o seletor de moedas de sorteio aleatório único, que implementará essa interface. Vamos implementar seu método e adicionar uma anotação de serviço a ele. Vamos injetar a calculadora do tamanho da transação nessa classe. E vamos injetar a calculadora de poeira nela. Antes de continuar implementando o método de seleção, vamos criar a classe de teste de sorteio aleatório único de um seletor de moedas. Na classe de teste da API. Isso estenderá a classe de especificação. Vamos injetar o único sorteio aleatório nessa classe. E vamos usar o método de configuração para instanciá-lo. Vamos passar pela calculadora do tamanho da transação e pela calculadora de poeira com uma taxa de retransmissão de poeira de 3.000 como parâmetros. Agora, vamos criar um teste. O Tidal deve selecionar n entradas esperadas, moedas para transação com saídas esperadas e saídas. Agora vamos criar uma classe utilitária que nos ajudará a testar e implementar o seletor de moedas de sorteio aleatório único. Vamos chamá-lo de Satoshi e criado no pacote utils. Agora, vamos criar os dois métodos de Satoshi. Ele usará um grande decimal como parâmetro e retornará um número inteiro grande. Esse método converterá uma quantia em Bitcoin na mesma quantia em Satoshi. Para fazer isso, simplesmente retornamos o valor em Bitcoin multiplicado por 100 milhões e convertemos o resultado em um número inteiro grande. Vamos também criar um método para fazer a operação inversa, que é converter Satoshi em Bitcoin. Para isso, retornaremos apenas o valor embrulhado em um novo grande decimal dividido por 100 milhões. No método de divisão passará oito como segundo parâmetro para fazer com que o resultado tenha oito casas decimais. Também passaremos o modo de arredondamento desnecessário como terceiro parâmetro. Agora, vamos criar um método para converter uma taxa em Bitcoins por KV de bicicleta em Satoshi por V byte. Ele será chamado de BTC por KB em vez de Satoshi por byte. Ele retornará um número inteiro grande e tomará como parâmetro um grande decimal. Primeiro, multiplicaremos a taxa por 100 milhões. Em seguida, dividiremos o resultado por 1024 com duas casas decimais e um modo de arredondamento de piso. Em seguida, vamos converter o resultado um número inteiro grande e armazená-lo na variável correta. Se o resultado for menor que um, então o tornaremos igual a um. Finalmente, retornamos a taxa convertida. No próximo vídeo, terminaremos de testar e implementar o seletor de moedas de sorteio aleatório único C. Sim. 50. 48 Enviar parte bitcoin 4 Skillshare 2: Neste vídeo, concluiremos implementação do algoritmo de sorteio aleatório único. No teste do seletor de moedas de sorteio aleatório único em um determinado bloco, primeiro criaremos UTXOs usando esse método e armazenaremos o resultado na variável UTxOS. Esses serão os UTXOs disponíveis que passarão como o primeiro parâmetro para o método testado. Então, vamos criar esse método. Ele usará uma lista de números inteiros grandes como parâmetro, que definirá a quantidade de cada UTXO. Portanto, para cada elemento na lista, chamaremos o método create UTXO para criar um único UTXO. Vamos criar esse método. Vamos instanciar um UTXO com esses parâmetros. Você pode copiar esses valores dos recursos desta lição. Agora, vamos criar um UTXO adicional e adicioná-lo à lista de UTXOs usando esse código. O motivo para adicionar um UTXO extra à lista é que queremos permitir o método select o adicione erroneamente à lista UTXOs selecionada. Se for esse o caso, saberemos que o método testado não está funcionando conforme o esperado. Vamos definir esses dois endereços. Um será o endereço a ser enviado e o outro será o endereço da mudança. Você pode copiá-los da página Projeto e Recursos. Vamos definir a taxa para 0,002. No bloco de vento, chamaremos o método de seleção de sorteio aleatório único com esses parâmetros. No bloco then, verificaremos se o tamanho do UTXOs selecionado é igual ao número esperado de entradas variável no bloco where. Vamos adicionar esses casos de teste. Você pode encontrá-los na página Projeto e Recursos. Esses casos de teste cobriram transações com 12,3 entradas e 1,2 saídas. os valores de entrada para transações com Espera-se que os valores de entrada para transações com uma saída não gerem alterações ou gerem mudanças com poeira, cujo valor é adicionado à taxa. os valores de entrada para transações com Espera-se que os valores de entrada para transações com duas saídas gerem alterações incorretas, que retornam ao remetente por meio de uma segunda saída. Vamos fazer o teste. Falhou conforme o esperado. Agora, vamos implementar o método de seleção de sorteio aleatório único. Primeiro, filtraremos todos os UTXOs recebidos para criar uma lista somente com UTXOs que tenham uma ou mais conformações. Então, vamos criar esse método. Para fazer isso. Chamaremos o método de filtro no stream UTXOs, retornando uma lista com apenas UTXOs confirmados. Agora, vamos criar essa variável para armazenar a taxa de taxa em Satoshi por V byte. Para isso, usaremos o método BTC por KB para Satoshi por bicicleta da classe Satoshi. Agora, vamos armazenar os UTXOs embaralhados nessa variável, atribuindo o retorno dessa chamada de método a ela. Vamos criar esse método. Primeiro, vamos instanciar uma nova ArrayList contendo o conteúdo da lista UTXOs. Em seguida, chamaremos o método de coleta aleatória, passando a nova lista como parâmetro. Em seguida, retornaremos a lista de moedas embaralhadas. Agora vamos instanciar uma ArrayList que armazenará os UTXOs selecionados. E vamos criar essa variável para armazenar o saldo total de entrada. Agora, para cada UTXO da lista de moedas embaralhadas, adicionaremos o UTXO à lista de UTXOs selecionada. E adicionaremos sua quantidade em Satoshi à variável balanceada de entrada total. Se o saldo total de entrada for menor que o valor ascendente, continuaremos a execução a partir da próxima iteração do loop. Após a instrução if, quando o saldo total de entrada exceder o valor a ser enviado, instanciará uma ArrayList com os endereços de saída e adicionará o endereço a ser enviado a essa lista. E criaremos uma lista com os endereços das entradas selecionadas usando esse mapeamento de fluxo. Agora, vamos calcular a taxa total em Satoshi e armazenada nessa variável. Para isso, vamos chamar o método da taxa total, passando a taxa em Satoshi por V, morda os endereços de entrada e os endereços de saída como seus parâmetros. Vamos criar esse método. Dentro, ele retornará a calculadora do tamanho da transação, calcula chamada do método, passando os endereços de entrada e os endereços de saída como seus parâmetros. Em seguida, multiplicaremos o resultado pela taxa de taxa em Satoshi por mordida em V. Agora, criaremos a variável alvo ajustada, que será igual à soma do valor a ser enviado e da taxa total. Agora vamos adicionar o endereço de alteração à lista de endereços de saída. Calcularemos a taxa total com alterações, chamando o método da taxa total e passando esses parâmetros. E calcularemos a meta ajustada com a mudança, que será igual à soma da quantidade de areia e da taxa total com a alteração. Agora, se o resultado do método de transação preenchido com balanceamento de entrada com esses parâmetros for verdadeiro, sairemos do loop usando a palavra-chave break. Vamos criar esse método. Ele retornará o resultado da seguinte declaração. Se o saldo total de entrada for igual ou maior que a meta ajustada e a poeira gerada de mudanças , isso significa que os UTXOs selecionados são suficientes para realizar essa transação. Outra condição para que os UTXOs selecionados cumpram a transação é que a soma dos valores seja igual ou maior do que a meta ajustada com a alteração. Vamos criar a mudança no método de poeira retornará a calculadora de poeira é chamada de método de poeira passando a grande diferença inteira entre o saldo total de entrada e o alvo ajustado como seu parâmetro. Por fim, simplesmente retornaremos os UTXOs selecionados desse método. Agora, vamos fazer o teste do seletor de moedas de sorteio aleatório único teste do seletor de moedas de sorteio aleatório e executar esse teste. Grau. Os testes foram aprovados. 51. Como as transações do Segwit são construídas e Validated: Nesta apresentação, veremos mais detalhes sobre como criar uma transação. Então, digamos que já usamos o seletor de moedas para selecionar alguns UTXOs para gastar como entradas em uma transação. Em nossa carteira, também temos a capacidade de derivar as chaves privadas necessárias para gastar esses UTXOs. Essas chaves privadas serão necessárias para assinar a transação posteriormente. Já escolhemos um endereço para enviar alguns Bitcoins. E temos o endereço de alteração o qual a alteração será enviada. Depois de definir essas coisas, é hora de construir nossa transação. Vamos ver os campos que fazem parte de uma transação de Bitcoin. Primeiro, o campo da versão. É usado para definir as regras que a transação segue. Atualmente, a primeira versão, que usaremos , é para transações comuns. A versão dois é para transações que seguem o BIP 68, que implementa regras para validar uma transação somente após um certo tempo. O campo de vida útil é usado para uma finalidade semelhante. Seu valor pode representar um certo tempo para adicionar uma transação a um bloco ou zero para ignorar essa regra, então temos o sinalizador e o marcador seg would. Está presente apenas nas transações da Segway. Se seu valor for 0001, isso marca essa transação como tendo dito quais entradas, cada transação tem uma ou mais entradas de transação. Cada entrada de transação tem um ID de transação que define uma transação anterior da qual a entrada atual está gastando Bitcoins. O índice de saída indica qual saída da transação anterior. A entrada atual é gastar Bitcoins de. Juntos, o ID da transação e o índice de saída são chamados de ponto de saída. Você pode ver o ponto de saída como uma coordenada para identificar a qual UTXO e entrada se referem. Em seguida, para cada entrada, temos o campo ScriptSig. Em entradas de segmento. Esse campo está vazio e seu conteúdo é movido para o campo da testemunha. Em transações não segmentadas, seu conteúdo é necessário para desbloquear os gastos do UTXO. A entrada está se referindo a. O campo da sequência n define quando a entrada é válida para gastar. Quando esse valor de campo é igual ao valor hexadecimal máximo para seu tamanho, esse campo é ignorado. Uma transação também tem uma ou mais saídas. Cada saída contém uma chave de script pub, que tem um código de script definindo as regras para gastar essa saída em uma transação futura. Cada saída também contém um campo de quantidade que define o número de Satoshi bloqueados nessa saída. Finalmente, as transações também contêm um campo de testemunha. Para transações que não sejam da Segway, esse campo está vazio. Para transações de Segway, a testemunha contém todo o conteúdo que, em transações não sequitur está no ScriptSig de cada entrada. Agora, vamos falar sobre como criar entradas de transação e o campo de testemunho para entradas de segmentos. Para cada UTXO selecionado, precisamos criar uma entrada de transação. O campo ID da transação da entrada da transação será igual ao ID da transação UTXO. O campo do índice de saída será igual ao índice de saída UTXO, também conhecido como Vout na documentação da API Bitcoin Core RPC. O ScriptSig ficará vazio e a sequência final será igual a esse valor hexadecimal, que é o valor máximo permitido para esse campo. Também precisamos criar uma testemunha para cada entrada, o campo da testemunha conterá uma assinatura obtida usando a chave privada usada para derivar o endereço UTXO. E uma chave pública que foi derivada usando a chave privada anterior e que também pode gerar o mesmo endereço UTXO mencionado. Veremos mais detalhes sobre o processo de assinatura em uma apresentação futura. Observe que as assinaturas fictícias e os bupkis, cujos valores podem ser vários zeros, podem ser usados como espaços reservados para criar e assinar transações. Esse truque facilita o cálculo do tamanho da transação antes de assinar as transações. Agora vamos falar sobre como criar uma sequência de resultados. Primeiro. Por outro lado, é possível criar uma transação com diferentes tipos de entradas e saídas, por exemplo, na mesma transação, você pode ter entradas e saídas segmentadas e não segmentadas. De volta ao assunto principal. Geralmente, queremos criar uma saída para o endereço para o qual queremos enviar bitcoins e uma saída para o endereço de alteração. Se a transação precisar de uma alteração. Cada saída de transação tem um campo de chave de script pub. Cada segmento script pub key, também conhecido como pay to witness pub key hash ou P2, WP k H tem uma versão testemunha de zero. A versão de testemunha é para scripts de raiz principal. Novas versões podem ser adicionadas para scripts futuros, se necessário. O segundo item da chave pub do script para saídas sigmóides é um hash de chave pública , obtido por Beck 32 decodificando o endereço dessa saída. A saída da transação também tem um campo de valor no Satoshi representando o valor enviado para esse endereço de saída. Agora, vamos finalizar esta apresentação falando sobre a execução e validação do script do segmento. Quando um nó recebe uma transação, ele começa a validá-la. Para cada entrada em uma transação, o nó combina a testemunha de uma entrada com a chave de script pub do UTXO referenciada pelo outpoint, e a entrada net executa o script combinado e o valida . Vamos ver como isso é feito. Aqui está a chave pub do script de um UTXO e o campo de testemunha que deseja gastar esse UTXO gerando o seguinte script combinado. Você pode estar se perguntando de onde vieram os opcodes do script combinado. Acontece que, quando um nó identifica a versão zero na chave pub do script do segmento, ele aciona uma regra especial que gera parte do código combinado abaixo. Em seguida, o script combinado é executado da mesma forma que os scripts não sequiturs. A partir do script combinado, a assinatura e as chaves públicas são adicionadas a uma pilha de execução. Em seguida, o opcode OPT up duplica a chave pub na pilha de execução. Up hash 160 hashes, a última chave de pub adicionada à pilha. Em seguida, a partir do script combinado, o hash da chave pub é adicionado à pilha. opcode Up equal verify remove os dois últimos elementos da pilha de execução e os compara. Se forem iguais, o script continua sendo executado. Finalmente, o object sig opcode verifica se a assinatura é válida para a chave pub restante na pilha. Se for válido, ele retornará verdadeiro para a pilha de execução. Depois que todos os elementos do script forem adicionados à pilha de execução, a entrada da transação seria considerada válida se o último elemento adicionado fosse verdadeiro. Esse processo deve ser repetido para cada entrada de transação. Para que uma transação seja considerada válida, todas as suas entradas devem ser válidas. Apenas como um lembrete visual, vamos analisar de onde vieram cada elemento na chave do pub do script e da testemunha chave do pub do script e da testemunha durante a construção da transação. O hash da chave pub presente na chave pub do script veio da década de 30 para decodificar o endereço do UTXO que está sendo gasto. A assinatura na testemunha veio com a aplicação do algoritmo ECDSA, que precisa de uma chave privada válida. A chave pública e a testemunha vieram da chave pública derivada da chave privada mencionada. A mesma chave pública foi usada no passado para gerar o endereço do UTXO gasto aplicando sequencialmente o algoritmo hash 160 e a codificação reversa 32. 52. 50 Enviar parte do bitcoin 5 skillshare 2: Neste vídeo, criaremos um serviço de criação de transações. No início, esse serviço lidará apenas com entradas e saídas do segmento, mas mais tarde no curso, vamos melhorá-lo. Então, no pacote de serviços api dot, vamos criar o serviço de criadores de transações. Vamos adicionar a anotação do serviço a ela. Vamos também injetar a calculadora de poeira nela. Agora, no pacote de teste da API, vamos criar a classe de teste do serviço de criadores de transações. Isso estenderá a classe de especificação. Vamos injetar o serviço de criadores de transações nele e instanciá-lo no método de configuração. Será necessário instanciá-lo com uma nova calculadora de poeira que ultrapassa 3.000 como parâmetro de taxa de relé de poeira. Antes de fazer esse teste, vamos fazer o teste do seletor de moedas de sorteio aleatório único para fazer uma pequena refatoração. Vamos recortar esses dois métodos dessa classe e colá-los na nova classe utils que criaremos no pacote de teste BYOD W. Vamos tornar esses dois métodos estáticos. Agora, vamos consertar a única moeda aleatória de drogas. Selecione seu teste para usar esses métodos dessa classe. Agora, vamos fazer o teste do serviço de criadores de transações. Vamos criar um teste chamado should create transaction com hashtag n entradas, entradas e hashtag esperadas n saídas, saídas. No corpo dado. Vamos primeiro criar essa variável utxOS e atribuir a chamada do método utils dot create utxOS retornada a ela, passando a variável de valores de entrada como seu parâmetro. Agora, vamos criar esse endereço para enviar a variável. Seu conteúdo será igual à variável com o mesmo nome no teste do seletor de moedas de sorteio aleatório único . Vamos também criar a variável de alteração de endereço, que será igual à variável com o mesmo nome no único sorteio aleatório de uma moeda, selecione seu teste. Vamos criar a variável de taxa de taxa, que será igual a 0.000 a. Vamos também definir a variável de taxa total esperada, que será igual à variável de tamanho esperada multiplicada pela taxa de taxa em V de Satoshi. Agora, vamos criar a quantidade total de entrada variável. Seu valor será igual ao resultado dessa expressão, que retornará a soma de cada valor de UTXO no de Satoshi. O valor da variável de envio será igual a 100 milhões de Satoshi. Também vamos calcular a quantidade de alteração esperada. Será igual ao valor da entrada menos a quantidade de areia menos a taxa total esperada. No bloco único, chamaremos criador da transação. O método create passará os seguintes parâmetros para esse método. O resultado será armazenado na variável de transação. No bloco then, verificaremos se o tamanho v da transação é igual à variável de tamanho esperada. Mas primeiro, vamos atualizar a versão Bitcoin Java para 0,4, 0,2 para disponibilizar o método get v size. Agora, verificaremos se o número de saídas da transação é igual à variável esperada e de saídas. Também verificaremos se o primeiro valor de saída é igual ao valor a ser enviado pela variável. Agora, se o número esperado de saídas for maior que um, verificaremos se o valor da alteração é igual ao segundo valor de saída na transação. No bloco where. Vamos adicionar os seguintes casos de teste. Você pode copiá-los da página Projeto e Recursos. Esses casos de teste abrangem cenários com e sem saídas de alteração e com quantidades de entrada que geram alterações ou não. Eles também cobriram transações com 12,3 entradas. Agora vamos criar o método de criação do serviço de criadores de transações. Vamos renomear esses parâmetros. Antes de implementar esse método, vamos criar a classe fee no pacote utils. Aqui, criaremos um método para calcular a taxa total de transações no Satoshi, vamos chamá-la de taxa total calculada. Ele receberá uma transação na taxa em Bitcoin por KV. O bit criará o seguinte código dentro de um bloco try catch. Primeiro, converteremos a taxa de Bitcoins por KV de bicicleta em Satoshi em byte privado. Em seguida, retornaremos o resultado multiplicando o tamanho v da transação pela taxa de taxa em Satoshi. A mordida por V capturará uma IOException que pode ser lançada pelo bom método de tamanho V e rápido em uma nova exceção de tempo de execução. De volta ao serviço de criadores de transações. Neste método, primeiro construirá as entradas da transação usando esse método, passando os UTXOs recebidos como seu parâmetro. Vamos criar esse método. Retornaremos o resultado da seguinte transformação do fluxo UTXO caso contrário, o fluxo em uma nova entrada de transação passará o ID UTXO recebido como seu primeiro parâmetro. O grande valor inteiro do UTXO prometido como seu segundo parâmetro. Esses dois parâmetros definem o ponto de saída de entrada da transação. Em seguida, passaremos um novo script instanciado com uma lista vazia. Esse parâmetro é a entrada de transação ScriptSig, que está vazia para entradas de segmentos. Em seguida, passaremos um grande número inteiro instanciado com esses parâmetros, que define a entrada em sequência. Esse valor é o valor máximo permitido para esse campo, fazendo com que os nós o ignorem. Agora, para cada transação, a entrada no stream usará o método de pico para definir a testemunha instanciará a testemunha com uma lista contendo constantes para uma assinatura fictícia e uma chave de pub fictícia. Agora vamos criar essas constantes. A assinatura fictícia será igual à sequência hexadecimal zero repetida 144 vezes, cujo tamanho em bytes é igual a 72. A chave de pub fictícia será igual à string hexadecimal zero repetida 66 vezes, cujo tamanho em bytes é igual a 33, definirá esses valores fictícios porque eles serão necessários para fazer o cálculo do tamanho da transação v, que fará com que, no método de criação, o processo de assinatura seja feito separadamente, posteriormente, quando os valores reais forem substituídos pelos valores fictícios. Por fim, converteremos o stream em um ArrayList e o retornaremos. Agora, criaremos a saída da transação para o endereço a ser enviado usando o método PUT de compilação, passando o endereço a ser enviado e o valor a ser enviado como parâmetros. Vamos criar esse método. Primeiro, analisaremos o prefixo do endereço usando o método parse prefix, que criará. Esse método verificará se o endereço começa com um dos prefixos de segmento válidos e retornará o prefixo do endereço ou uma string vazia se um prefixo válido não for encontrado. Agora, criaremos um objeto de script usando a classe de script P2, método de script WP k h. Como seu parâmetro passará o resultado da chamada do método back 30 para decodificar, passando o prefixo e o endereço para este último. O retorno do método back 30 to decodificar é uma matriz de objetos em que o segundo elemento é o hash da chave pub, que passará para o método de script P2 WP k h. Esse método retornará o equivalente à chave pub do script, em que o primeiro parâmetro é zero e o segundo parâmetro é o hash da chave pub, conforme explicamos na última apresentação. Por fim, retornaremos uma nova saída de transação instanciada com o valor e o script criado. Agora, criaremos uma ArrayList para armazenar as saídas da transação, instanciaremos, adicionando a ela o endereço para enviar a saída que acabamos de criar. Em seguida, criaremos a transação que passará como parâmetro, o número inteiro grande, que é a versão da transação. As entradas da transação, as saídas da transação. O grande número inteiro zero é o tempo de bloqueio que será ignorado. E o booleano é verdadeiro para definir essa transação como uma transação seguinte. Esse parâmetro fará com que a transação tenha o marcador e a bandeira do Segway. Agora, vamos calcular a taxa total da transação usando o método F0 total calculado que criamos anteriormente na classe FI. Vamos considerar a transação e a taxa da taxa como seus parâmetros. Também vamos calcular a zona de entrada para mapear o fluxo UTXO em um fluxo de valores de UTXOs. Em seguida, usaremos o método reduzido para somá-las. Por fim, converteremos o resultado ptose ou zero se os UTXOs não existirem. Em seguida, calcularemos a alteração que será igual à soma de entrada menos a quantidade de areia menos a taxa total. Em seguida, adicionaremos a seguinte declaração if. O uso da calculadora de poeira verificará se a alteração é poeira. Se for, retornaremos a transação como está. Caso contrário, adicionaremos outra saída à transação usando o método build output, passando o endereço de alteração e o número inteiro grande, pois seus parâmetros passarão um para o valor de saída, apenas como um valor de espaço reservado, pois teremos que recalcular a taxa de transação para a transação que agora tem duas saídas, o que exige uma taxa mais alta. Então, vamos recalcular a taxa total usando o método F0 total calculado. Novamente, vamos recalcular a alteração que será igual à soma de entrada menos o valor a ser enviado menos a nova taxa total calculada. Agora, vamos remover a última saída de transação adicionada das saídas da transação ArrayList. Vamos verificar novamente se a nova alteração calculada é poeira. Se for, ele retornará a transação sem alterações. Caso contrário, adicionaremos uma nova saída à transação usando o método build output. Desta vez, passaremos o valor real da alteração da transação com duas saídas para esse método. Por fim, devolveremos a transação. Agora vamos fazer o teste do serviço de criadores de transações e executar esse teste. Ótimo, os testes foram aprovados desde que alteramos anteriormente teste do seletor de moedas de sorteio aleatório único. Vamos também executá-lo novamente para garantir que não tenhamos quebrado nada. Eles são ótimos. Está funcionando normalmente. 53. 51 Enviar bitcoin parte 6 skillshare 2: Neste vídeo, começaremos a criar a janela que aparecerá quando clicarmos no botão Enviar. Essa janela conterá informações sobre a transação. Estamos enviando um campo de senha e um botão OK para confirmar a transmissão da transação. Então, no pacote FXML, vamos criar o arquivo FXML da caixa de diálogo de sublinhado da transação de envio de sublinhado. Vamos apagar o clichê gerado. Agora, vamos criar uma etiqueta problemática no diálogo. Agora, vamos mudar a visualização para o Scene Builder. Vamos definir a altura de preferência do diálogo para 300. E sua largura preferida é 650. E vamos fazer com que a altura mínima seja a largura mínima para usar o tamanho da prensa. Agora, vamos adicionar um painel de grade ao conteúdo da caixa de diálogo. Vamos adicionar mais quatro linhas a esse painel de grade. Agora vamos adicionar um rótulo à primeira linha. Vamos mudar seu texto para enviar o ponto de interrogação da transação. Vamos aumentar o tamanho da fonte para 16 pixels. Para as próximas linhas, a ideia aqui é adicionar rótulos e dados para a transação de envio. Vamos adicionar um rótulo à segunda linha e alterar seu texto para o valor para enviar dois pontos. Na segunda coluna da mesma linha. Vamos adicionar outro rótulo. Desta vez, o texto ficará vazio e adicionaremos um ID Fx para que possamos alterar seu conteúdo dinamicamente posteriormente. Vamos adicionar outro rótulo na terceira linha, desta vez com as taxas totais do texto na célula à direita. Vamos adicionar uma etiqueta vazia com outra ID FX. Na linha abaixo. Vamos adicionar outro par de rótulos para o campo total. Na próxima fila. Vamos adicionar esses rótulos para a taxa de taxa. Agora, vamos fazer o mesmo com o endereço a ser enviado. Na última fila. Vamos adicionar um rótulo para a senha da carteira. Na cela à esquerda. Vamos adicionar um campo de senha. Ele terá um ID FX ou senha da carteira. Os rótulos repentinos não dois pontos no final. Vamos consertá-los. Agora. Vamos acessar a configuração do problema do diálogo e adicionar um botão OK aqui. Vamos também adicionar um botão de cancelamento. O texto do botão Cancelar está no meu idioma nativo. Se esse também for o seu caso, você pode alterá-lo fazendo o seguinte. Vamos para a visualização do editor. Primeiro, vamos adicionar uma ideia Fx de ok ao botão OK. E vamos adicionar uma ideia Fx de cancelar à tag do botão de cancelamento. Agora, vamos remover essa propriedade. Vamos definir a propriedade de dados do botão com esse valor e definir seu texto para cancelar. Agora, no Scene Builder, podemos ver que a mudança entrou em vigor. Agora, vamos para a guia Enviar FXML. No botão Enviar, vamos definir a propriedade de ação hashtag send para que, ao clicarmos nesse botão, o método de envio do controlador da guia Enviar seja chamado. Então, vamos criar esse método. Antes de implementá-lo, vamos criar um registro DTL de transação no pacote de domínios. Ttl significa objeto de transferência de dados e é um padrão de design comum a ser usado para objetos cujo objetivo principal é transferir dados entre classes e métodos. Dessa forma, o DTO da transação será usado para transferir dados de transações entre nossos serviços. Vamos adicionar os seguintes campos a ele. Neste ponto, você pode estar se perguntando qual é a diferença entre a taxa real total e o total calculado v? Chegaremos a isso em breve. Agora, vamos para o controlador da guia Enviar. Vamos adicionar os seguintes campos a ele. Esses campos serão vinculados às tags correspondentes no arquivo FXML da guia Enviar. Agora vamos implementar o método de envio. Primeiro. Converteremos o valor para enviar texto em um grande valor decimal. Agora, criaremos um objeto DTO de transação usando o serviço de criação de transação que criará. Vamos injetar esse serviço nessa classe. Vamos criá-lo no pacote de serviços de pontos da GUI. Agora, vamos terminar de injetá-lo nesta classe. Aqui, chamaremos o método create nele, passando o endereço para enviar o texto e a variável de quantidade. Vamos criar esse método. Agora, usaremos esse método para abrir a janela de diálogo, passando o DTO da transação como seu parâmetro. Vamos criá-lo. Depois de abrir a janela de diálogo, chamaremos o método clear no endereço a ser enviado e a quantidade a ser enviada para apagar o conteúdo dessas entradas. Agora, vamos para o serviço de criação de transações. Vamos adicionar a anotação do serviço a ela. Implementaremos o método de criação. Agora, a ideia aqui é usar muitos dos serviços que criamos nos vídeos anteriores para criar uma transação e alguns dados adicionais para o DTO da transação. Para isso, a primeira coisa que faremos é usar o serviço de taxa estimada para obter a taxa e armazená-la na variável de taxa de taxa. Então, vamos injetar esse serviço nessa classe. E vamos chamar isso de método de estimativa. Agora, obteremos os endereços da carteira atualmente carregada usando o objeto de carteira atual. Então, vamos injetá-lo nessa classe. Em seguida, chamaremos os endereços get como método de strings nele. Em seguida, receberemos todos os UTXOs da nossa carteira. Para isso, usaremos o cliente não gasto da lista de nós. Então, vamos injetá-lo nessa classe. Chamaremos a lista de método não gasto nela, passando os endereços e o nome da carteira atual como parâmetros. Agora, usaremos o seletor de moedas para selecionar os UTXOs que serão usados como entradas em nossa transação. Então, vamos injetar o seletor de moedas nessa classe. Agora, chamaremos o método de seleção , passando os UTXOs, o valor convertido em Satoshi, a taxa da taxa, o endereço a ser enviado e o endereço de alteração da carteira atual, ligando para o o método atual de obtenção de endereço de alteração da carteira, que será criado. Então, vamos criar esse método. Ele simplesmente retornará a propriedade de alteração de endereço. Vamos criar essa propriedade como uma string. Vamos movê-lo para aqui. Vamos também criar um setter para ele. Nós o usaremos mais tarde. Agora, vamos usar o serviço de criadores de transações para criar uma transação. Então, vamos injetar esse serviço nessa classe. Vamos chamar o método create nele, passando os seguintes parâmetros para ele. Agora que temos nossa transação, criaremos dados adicionais para incluir na transação DTL. Próximo. Primeiro, vamos usar o método de taxa real total da classe FI para obter que a taxa real total seja aprovada na transação e nos UTXOs selecionados como seus parâmetros. Vamos criar esse método. A diferença entre o total de pés calculados e a taxa real total é que, para a última, usamos a diferença entre os valores de entradas e saídas para calculá-la. Já para o primeiro, estimamos usando o tamanho da transação e a taxa da taxa. Em teoria, espera-se que os dois valores sejam os mesmos, mas vamos usar como padrão o total de pés reais quando possível, para garantir que estamos mostrando ao usuário a transação real taxa e para permitir que o usuário identifique possíveis erros de três valores. Então, aqui vamos calcular os valores de entrada, alguns em Bitcoin usando a seguinte transformação de fluxo. Mapearemos o fluxo de UTXOs selecionado para produzir um fluxo de valores de UTXOs. Em seguida, use o método reduzido para somar todos os valores no fluxo. E use o método or else para retornar zero se a string estiver vazia. Agora, vamos calcular a saída entre alguns em Satoshi. Faremos a mesma transformação que fizemos para as entradas, mas com as saídas da transação desta vez. Agora, retornaremos a entrada que parte em BTC é convertida em Satoshi menos a saída, parte. Voltar ao serviço Criar transação. Agora, vamos criar a variável total calculada F0 e atribuir a ela o resultado da chamada total calculada do método F0. Desta vez, passaremos a transação e a taxa da taxa como parâmetros. Agora, vamos calcular o total gasto, que, como o nome sugere, é o valor total em Satoshi que o remetente gastou nessa transação. Para isso, vamos usar o método total gasto passando pela transação, a taxa real total e o endereço como parâmetros. Vamos criar esse método. Com esta declaração if. Vamos verificar se o endereço a ser enviado pertence à nossa carteira. Caso contrário, retornaremos a taxa real total mais o valor da saída da primeira transação. Se nossa carteira o contiver, isso significa que estamos transferindo bitcoins para nós mesmos e, portanto, estamos gastando apenas a taxa de transação. Por fim, retornaremos um novo objeto DTO de transação instanciado com esses parâmetros continuaremos a implementar o recurso de janela de diálogo no próximo vídeo. vejo. 54. 52 Enviar bitcoin parte 7 skillshare 2: Neste vídeo, concluiremos implementação da janela de diálogo da transação. Então, vamos para o controlador da guia Enviar. No método de diálogo aberto, vamos instanciar um novo objeto de diálogo como esse. Em seguida, vamos chamar o método proprietário da unidade nele, passando o objeto da janela como seu parâmetro, assim. Vamos definir o título da caixa de diálogo para enviar a transação. Agora, com o código a seguir, definiremos que quando clicarmos no botão Fechar da janela de diálogo, a janela de diálogo será fechada. Em seguida, criaremos um objeto carregador FXML dentro de um bloco try catch. Para instanciá-lo, será necessário injetar o recurso de diálogo FXML nessa classe. Vamos fazer isso. Vamos adicionar uma anotação de valor a esse campo indicando o caminho da caixa de diálogo de transação sin FXML. Aqui, chamaremos o método get URL nele. Em seguida, usaremos null nesses parâmetros. E a referência do método get beam de contexto aqui. Primeiro, vamos criar o objeto de contexto do campo nessa classe e atribuí-lo aqui. Agora, definiremos o conteúdo do problema do diálogo como o resultado da chamada do método de carregamento do carregador FXML. Agora, com o código a seguir, obterá o controlador de diálogo de transação syn do carregador FXML. Vamos criar esse controlador na classe controllers. Por fim, passaremos o objeto DTO da transação para o controlador de diálogo de transação sin usando o método de transação set. Vamos criar esse método. Aqui, capturaremos uma IOException que o carregador FXML pode lançar e agrupá-la em uma nova exceção de tempo de execução. Em seguida, mostraremos o diálogo usando esse método. Agora, antes de implementar o segundo controlador de diálogo de transações, vamos ao serviço de atualização da carteira atual. Quando atualizamos a carteira atual, precisamos definir seu endereço de alteração, que será usado quando enviarmos uma transação. Então, vamos fazer isso. Faremos isso obtendo a segunda chave pública estendida da carteira criada. Lembre-se de que essa chave estendida foi derivada para gerar endereços de alteração. Em seguida, obteremos seu primeiro endereço e definiremos como o endereço de alteração da carteira atual. Agora, vamos para o segundo controlador de diálogo de transação. Vamos definir a anotação do componente para ela. Agora, vamos para a segunda caixa de diálogo de transação FXML. Vamos definir o problema do diálogo FX ID. E vamos definir a propriedade do controlador FX para o caminho do controlador criado recentemente aqui. Agora, definiremos cada tag com um ID de ética neste arquivo, esses campos no segundo controlador de diálogo de transação usando esse recurso interessante do IDE. Agora vamos definir que cada campo aqui é privado. Vamos adicionar a anotação FXML acima de todas elas. Antes de implementar o método Set Transaction, vamos criar o domínio do diálogo da transação no pacote de domínios. Precisarei desse disco em breve. Ele modelará os campos que serão exibidos na caixa de diálogo da transação. Então, vamos criar esses campos. Vamos também criar isso a partir do método. Isso criará um novo diálogo de transação a partir de um DTO de transação. Usaremos o formato ou método de formato Bitcoin para analisar corretamente o valor e enviar a taxa real total, e o total gasto também ultrapassará a taxa da taxa e o endereço da transação. DTO para a instanciação do diálogo da transação. Voltar ao segundo controlador de diálogo de transação. No método de transação definido, vamos definir o campo D TO da transação como o DTO da transação recebida. Vamos criar esse campo nesta classe. Agora, vamos criar o objeto de diálogo da transação usando o método from passando o DTO da transação como seu parâmetro. Em seguida, definiremos o valor a ser enviado para o diálogo da transação. O valor a ser enviado definirá o texto do campo de taxas totais para o diálogo da transação, taxa total. O texto total do campo da caixa de diálogo da transação totaliza o texto do campo da taxa de taxa na caixa de diálogo da transação. Taxa de taxa concatenada com a string BTC slash KV. Mordida. Vamos definir o endereço para enviar os textos de campo para o endereço da caixa de diálogo da transação a ser enviada. Agora vamos criar o método inicializado nessa classe. Aqui, o botão de cancelamento será vinculado a uma ação que fechará a janela de diálogo. Para fazer isso, vamos chamar o método do botão de pesquisa na caixa de diálogo passando o campo de cancelamento para ele. Em seguida, chamaremos esse método para adicionar um manipulador de eventos ao botão de cancelamento. O manipulador receberá um evento de ação e um evento como seus parâmetros. E o corpo do manipulador usará essa instrução para fechar a janela de diálogo. Agora, vamos fazer o teste de envio de Bitcoin. Algo está faltando neste teste. Depois de chamar o método de enviar Bitcoin e esperar, precisamos instruir o node a minerar um bloco para que nosso UTXO seja confirmado e possa ser usado para criar uma transação. Para lidar com isso, vamos chamar o método generate to address no node generate para endereçar o cliente passando esses parâmetros para ele. E vamos mover essa linha de código para aqui. Agora, vamos executar nosso node. E vamos fazer esse teste. Como esperado, o teste falhou, mas a caixa de diálogo da transação foi aberta e preenchida com os dados da transação. Agora, vamos melhorar esse teste. Verificará se os valores na diálogo da transação estão corretos. Mas primeiro, vamos tornar esse teste mais resiliente. Depois de clicar no botão enviar adicionaremos um código para garantir que esperemos que a caixa de diálogo da transação apareça antes de agir na janela de diálogo. Então, vamos criar o peso para o método de diálogo. Aqui, chamaremos o método de peso por método. Passar esses parâmetros para esperar segundos no corpo do lambda causará problemas no diálogo e retornará somente depois que ele não for nulo. Agora, vamos obter o valor de cada rótulo na caixa de diálogo da transação e armazená-lo nas seguintes variáveis. Vamos adicionar o tipo de linha da transação aqui. E vamos mudar o nome da exibição da tabela para tabela de transações. No bloco then, vamos adicionar as seguintes afirmações para verificar se os rótulos na diálogo da transação estão corretos. Agora, no bloco where, vamos adicionar um caso de teste para preencher as variáveis que acabamos de referenciar no bloco then. Está faltando um sinal de igual e igual aqui. Vamos consertar isso. Vamos adicionar outro caso de teste. Agora, vamos remover essas linhas. Adaptará o código para criar transações anteriores acordo com a variável de número UTxOS anterior. Portanto, para cada UTXO definido nessa variável, procurará o endereço de recebimento. Em seguida, chamaremos o método de enviar Bitcoin e esperar com esses parâmetros. Agora, vamos substituir o parâmetro na chamada de método correta pela variável quantidade a ser enviada. Agora, precisamos garantir que a taxa seja igual a 0,002 para que o teste funcione. Para fazer isso, injetaremos o serviço de taxa de estimativa de nessa classe e adicionaremos a anotação simulada de Bean a ela. Em seguida, no método de configuração, vamos adicionar o código a seguir. Isso garantirá que, quando o método de estimativa do serviço for chamado, ele retorne o valor da taxa que desejamos. Esse perímetro do método de pesquisa não tem a letra S no final. São taxas totais. Agora, vamos fazer o teste. Ocorreu uma falha, mas pelo motivo errado, observe que o valor para enviar a etiqueta está vazio. Isso porque há outro rótulo com o mesmo ID FX no controlador da guia Enviar. Também há um campo de endereço para enviar com o mesmo ID FX. Vamos usar o segundo controlador de diálogo de transação para corrigir isso. Vamos renomear esse campo para o valor a ser enviado ao diálogo. E vamos renomear o endereço para enviar campo para endereço para enviar o diálogo. Vamos até a caixa de diálogo de envio de transações FXML para alterar os rótulos FX IDs. Ok, não precisamos, porque o IDE fez esse trabalho para nós. Voltar ao teste de envio de Bitcoin. Vamos atualizar esses parâmetros para procurar os rótulos corretos. Agora, vamos fazer nosso teste. Ok, os testes falharam, mas apenas porque a tabela de transações não contém o número esperado de transações. Isso significa que os rótulos da caixa de diálogo da transação estão corretos. Ótimo. 55. Como as assinaturas de transação funcionam: Nesta apresentação, mostraremos como as assinaturas de transações funcionam. Primeiro, vamos analisar os campos de uma entrada de transação. As entradas da transação têm um campo de ID de transação cujo conteúdo indica de qual transação o UTXO gasto nessa entrada veio. O campo do índice de saída indica qual UTXO da transação anterior a entrada está gastando. Juntos, os dois campos formam um ponto de saída que indica inequivocamente qual UTXO a entrada está gastando. O campo ScriptSig está vazio para entradas de transação segue e contém scripts de desbloqueio para entradas de transação não seguidas. Esses scripts de desbloqueio são uma assinatura e uma chave pública para transações comuns. Finalmente, a entrada da transação contém o campo de sequência final. O campo da sequência final define quando a entrada é válida para gastar. Esse campo é ignorado quando seu valor é igual ao valor hexadecimal máximo para seu tamanho. Para entradas de transação seguintes, o conteúdo que para transações que não são do Segway está no ScriptSig é movido para o campo de testemunha. A assinatura nesse campo é uma assinatura ECDSA obtida usando a chave privada usada para derivar o endereço do UTXO. A contribuição é gastar. O outro campo na testemunha é a chave pública, que é derivada da chave privada à acabamos de nos referir. Mas espere, o que é uma assinatura ECDSA? Ecdsa significa algoritmo de assinatura digital de curva elíptica. É um algoritmo de assinatura que combina uma chave privada e uma mensagem para produzir uma assinatura. E a assinatura ECDSA tem uma propriedade que permite verificar se é válida, ou seja, verificar se uma determinada assinatura foi produzida por uma determinada chave privada e uma mensagem usando a chave pública derivado dessa chave privada, da mensagem e da assinatura. Dessa forma, podemos verificar se uma assinatura é válida sem revelar a chave privada usada para gerá-la. Você pode usar o ECDSA para assinar qualquer mensagem que desejar. No caso de uma assinatura de transação, a mensagem que está sendo assinada é uma versão modificada da transação serializada. Então, vamos ver como as transações de Bitcoin são assinadas. Para assinar uma transação, você precisa assinar cada entrada de transação separadamente. Para cada entrada de transação comece com uma transação insana, que é uma transação em que suas entradas têm script vazio, CIGS e testemunhas. Você cria um hash de assinatura, que é o hash de uma versão modificada da transação serializada. Para fazer isso, você usa um algoritmo de hash de assinatura, que explicaremos no próximo slide. O hash da assinatura será a mensagem a ser assinada com uma chave privada válida para essa entrada e o hash da assinatura usará o ECDSA para gerar a assinatura. Lembre-se de que a chave privada válida para uma entrada é a mesma chave privada usada para gerar o endereço do UTXO que a entrada está gastando. Se a entrada for uma entrada de segmento, adicione a assinatura e a chave pública derivada da referida chave privada à testemunha. Caso contrário, adicione esses elementos ao campo ScriptSig de entrada. Quando os nós recebem uma transação, eles verificam se as assinaturas da transação são válidas. Para fazer isso, eles usam o algoritmo de verificação de assinatura citado no slide anterior. Eles fazem isso durante a execução do script , conforme explicado na última apresentação. Agora, vamos ver como o hash da assinatura é gerado. Existem diferentes algoritmos de hash de assinatura para entradas de transação segue, não segmentar e tap root. No entanto, os três algoritmos modificam a transação de alguma forma e produzem um hash, que é a mensagem que será assinada. Vamos ver o algoritmo de hash de assinatura para entradas de um segmento. Para criar um hash de assinatura para uma determinada entrada de transação, comece com uma string vazia, depois adicione a versão da transação à string concatene todos os pontos de saída das entradas da transação. o hash dos resultados usando o algoritmo hash 256, acrescente o hash resultante à string e, em seguida, concatene todas as entradas e sequências. o hash 256 do resultado e acrescente o hash à string. Agora adicione o ponto de saída da entrada que está sendo assinada à string. Adicione a chave de script pub dos UTXOs gastos pela entrada que está sendo assinada na string. Adicione o valor dos UTXOs gastos pela entrada que está sendo assinada à string. Adicione a sequência final da entrada que está sendo assinada à string concatene todas as saídas da transação. hash 256, o resultado, acrescenta o hash resultante à string adiciona o tempo de bloqueio da transação à string. Adicione o tipo de hash, que é sig hash all para transações comuns, à string. Existem outros tipos de hash, mas eles raramente são usados. Eles definem as entradas e saídas. A entrada que está sendo assinada pode ser incluída em uma transação. Assine o hash. Tudo significa que a assinatura produzida é válida somente em uma transação com todas as entradas e saídas da transação em questão. Finalmente, o hash 256, a string obtida. O resultado é o hash da assinatura da entrada que está sendo assinada. Um hash de assinatura deve ser obtido para cada entrada de transação que está sendo assinada. O processo é replicado pelos nós quando eles verificam as assinaturas da transação. 56. Como nossa carteira e nosso nó lidam com transações enviadas: Esta apresentação explicará o que acontece quando enviamos uma transação para um nó de Bitcoin. Em seguida, veremos como nossa carteira atualmente lida com o recebimento de transações e como planejamos alterá-la para calcular corretamente endereços das transações e os saldos totais da carteira após o envio de uma transação. Então, vamos ver como um node Bitcoin lida com as transações enviadas pela nossa carteira. Nossa carteira enviará transações para nosso node por meio do método RPC de notas chamado enviar transação bruta. Nosso aplicativo enviará a transação de assinatura em formato hexadecimal para nosso nó. Depois de receber a transação, o nó a valida. Se a validação for aprovada, o nó transmitirá a transação para outros nós na rede Bitcoin. Os outros nós fazem o mesmo até que todos os nós da rede reconheçam a transação. A transação permanece na mente por um tempo, esperando que um menor a inclua em um bloco e extraia o bloco com ela. Eventualmente, um menor transmite o bloqueio mental com a transação para outros nós na rede. À medida que os nós recebem o bloqueio mental com a transação, a transação é excluída do mental e considerada confirmada. Cada bloco adicionado após o bloco com a transação adiciona uma confirmação à transação. É recomendável aguardar seis conformações para que uma transação seja considerada irreversível. Agora, vamos ver um modelo ingênuo de como nossa carteira pode lidar com transações de envio. Depois que nossa carteira enviar uma transação para nosso node, o nó será devolvido por meio de zero MQ, a mesma transação para nosso aplicativo. Nosso serviço de tarefas de node detectará a transação e a enviará para nosso ouvinte de transações recebidas. Como a maioria das transações terá um resultado alterado, o ouvinte da transação recebida geralmente verificará se o endereço da alteração é da nossa carteira. E usaremos o serviço de atualização UTXos para atualizar nossos endereços de carteira, transações e saldos, mas contando apenas com a transação recebida pelo ouvinte, como está atualmente para atualizar nossa a carteira levantará alguns problemas. Primeiro, o cálculo do saldo do serviço UTXos de atualização não considera os saldos de entrada. Portanto, teremos que modificar a forma como nossa carteira calcula um vestido e os saldos de transações para descontar os valores de entrada dos valores de alteração. Mas teremos que lidar com um problema maior com esse modelo. E quanto às transações sem alterações? Nesse caso, o ouvinte da transação recebida não considerará que a transação do recibo é nossa, pois verifica apenas os endereços de saída e a saída do perfume não será da nossa carteira. Portanto, nosso aplicativo não seria atualizado. É equilibrado para esses casos, adotará a seguinte estratégia para superar esses problemas ao atualizar nossa carteira após o envio das transações. Depois de enviar a transação para o nosso node, publicará um evento da transação enviada que será capturado por um ouvinte enviado pela transação. Em seguida, o ouvinte de envio de transações usará o serviço de atualização UTXos para atualizar a carteira com a transação para eliminar o problema de não atualizar as transações sem alterações, tanto a transação o ouvinte recebido e o ouvinte de bloqueio de recebimento usarão um cliente de transações da lista de nós para pesquisar todas as transações relacionadas à nossa carteira no nó, esse cliente enviará uma lista de transações RPC ligue para o nosso node, que retornará todas as transações relevantes para o cliente. Em seguida, usando as transações de devolução, o serviço de atualização UTXos atualizará todas as transações em nossa carteira e seus saldos corretamente. 57. 55 Enviar parte 8 skillshare 2: Neste vídeo, criaremos algumas classes e serviços que nos permitirão assinar e enviar transações. Então, primeiro, vamos criar uma classe chamada serviço de signatário de transações no pacote de serviços api dot. Vamos adicionar a anotação do serviço aqui. Agora vamos criar o método de sinal aqui. Será necessário um objeto de transação na semente mnemônica, uma senha e uma lista de DTLs UTXO que uma classe criará. Então, vamos criá-lo no pacote de domínios. Agora, usaremos o método stream range para percorrer cada UTXO DTO. Para cada UTXO DTO, chamaremos o método de sinal passando o parâmetro a, que é o índice da entrada a ser assinada, o UTXO DTO, que será obtido usando o parâmetro i, a transação, a semente mnemônica e a senha da carteira. Vamos criar esse método. Vamos mudar o nome desse parâmetro para string de semente mnemônica para assinar uma entrada de transação. Primeiro, precisamos derivar a chave privada válida para desbloquear o UTXO que a entrada está gastando. Se você quiser se lembrar de como isso é feito com mais detalhes, assista novamente à apresentação de carteiras HD e endereços de Bitcoin. Então, primeiro, vamos instanciar um objeto de semente mnemônico aqui, passando a cadeia de sementes mnemônica e a instanciação. Agora, derivaremos uma chave mestra usando o método mnemônico de semente para chave mestra , pois seus parâmetros passarão a senha. E esse prefixo. Para nosso caso de uso, não há problema em passar o prefixo privado da rede principal, mesmo se o usarmos em outro ambiente, pois isso afeta apenas a serialização da chave mestra, não o processo de derivação. No processo de derivação da chave mestra, esse método de chave mestra primeiro deriva a semente raiz, que é mencionada na apresentação mencionada anteriormente. Agora, derivaremos a chave privada estendida usando o método CKD da chave mestra, pois seu primeiro parâmetro passará pelo caminho de derivação UTXO DTO. Primeiro, vamos criar esse campo no UTXO DTO. E vamos aproveitar a oportunidade para adicionar o campo de valor que será necessário em seguida. O próximo parâmetro será verdadeiro, o que indica que queremos derivar uma chave privada estendida, uma chave pública estendida. O último parâmetro será o prefixo privado da rede principal. Novamente, não há problema em usar o prefixo de rede principal aqui. Observe que a forma como derivamos a chave privada estendida aqui é semelhante à como derivamos a chave pública estendida e o serviço de chave pública estendida. Usamos o mesmo caminho de derivação que usamos para criar a chave pública estendida para derivar o endereço UTXO de nossa carteira. Agora, obteremos a chave privada desejada simplesmente extraindo-a da chave privada estendida por meio do método de duas chaves privadas. Esse método está disponível na próxima versão do Bitcoin Java. Então, vamos ao arquivo POM para atualizá-lo. Agora, dentro de um bloco try catch, podemos finalmente usar o método de assinatura da classe de signatários da transação ECDSA do Bitcoin Java. Esse método pegará a transação, a chave privada, o índice de entrada e o valor UTXO DTO convertido em Satoshi. E o booleano verdadeiro, que indica que essa entrada está segmentada. O mesmo método obterá um hash de assinatura com a chave privada. Usaremos o ECDSA para obter uma assinatura para essa entrada. Em seguida, ele inserirá a assinatura e a chave pública derivada da chave privada anterior na testemunha da transação. O valor UTXO é necessário para o hash da assinatura, e o último parâmetro verdadeiro é necessário para a geração correta do hash da assinatura e para adicionar corretamente a assinatura e a chave pública à testemunha em vez de no ScriptSig, que é o caso de entradas sem segmentos. Finalmente, capturamos uma possível IOException que o método sign pode lançar e envolvê-la em uma nova exceção de tempo de execução. Agora, vamos criar o cliente de transação bruta node send no pacote do cliente node dot. Esse serviço será necessário para enviar nossas transações para nosso node Bitcoin. Vamos adicionar a anotação do serviço a ela. Vamos injetar o cliente node nessa classe. E vamos criar o método de envio. Ele aceitará uma string hexadecimal de transação como seu parâmetro. Aqui, chamaremos o método de solicitação de make do cliente node. Vamos usá-lo para chamar o método RPC do nó Bitcoin de envio bruto . Como de costume, vamos passar um novo objeto de referência de tipo parametrizado. Aqui. O URL está vazio e passaremos o parâmetro hexadecimal da transação como o último parâmetro. Agora, no pacote de serviços de pontos de GUI, vamos criar o segundo serviço de transação. Esse serviço será responsável por assinar e enviar a transação criativa. Depois de clicarmos no botão Enviar na caixa de diálogo da transação, vamos adicionar a anotação do serviço a essa classe. E vamos criar o método de assinatura e envio. Ele retornará um futuro do tipo void. E usará o DTO da transação e a senha da carteira como parâmetros. Agora, primeiro, criaremos uma lista de UTXOs, CTOs, convertendo os UTXOs selecionados do DTO da transação. Chamaremos o mapa do método no fluxo UTXos selecionado e usaremos o construtor UTXO DTO para criar o UTXO d t vai de cada objeto UTXO. Então, vamos injetar o construtor UTXO DTO nessa classe. Vamos criá-lo no pacote de serviços GUI dot. Agora, vamos criar esse método de construção. Ele retornará um UTXO DTO ao serviço de transação central. Aqui retornará o método de lista chamado no fluxo resultante. Vamos refatorar aqui para usar a referência do método em vez de um lambda. Agora, vamos implementar esse método. Primeiro. Vamos adicionar a anotação do serviço a essa classe. Aqui, obteremos o objeto de endereço da carteira atual correspondente ao endereço UTXO recebido. Então, vamos injetar a carteira atual nessa classe primeiro. Agora chamaremos o método get address nele, passando o endereço UTXO como parâmetro. Vamos criar esse método. Ele retornará um objeto de endereço. Aqui retornará o resultado da chamada do método get address no campo de endereços, passando o endereço recebido como parâmetro. Por fim, obteremos o índice atual de endereços da carteira e o armazenaremos na variável de índice de endereço. Agora, obteremos o mesmo endereço da carteira atual e obteremos seu tipo de endereço, armazenando-o na variável de tipo de endereço. Agora, obteremos o caminho de derivação UTXO chamando o método build derivation path com o tipo de endereço e o índice Address. Vamos criar esse método. Aqui. Usaremos o objeto address configs para obter parte do caminho de derivação. Então, vamos injetá-lo nessa classe. Na verdade, será uma lista de configurações de endereço. Vamos consertar isso. Agora, a partir do fluxo de configurações de endereço, usaremos o método de filtro para selecionar a configuração de endereço válida para o tipo de endereço. Em seguida, usaremos o método find first e obteremos a configuração de endereço que queremos. Finalmente, obteremos o caminho de derivação configuração do endereço e o concatenaremos com a seguinte string. Adicionaremos uma barra e, em seguida, adicionaremos o índice de endereços. Aqui retornará um novo UTXO DTO passando o caminho de derivação e o valor de UTXO. Voltar ao serviço de envio de transações. Aqui, precisaremos do serviço de signatário da transação. Então, vamos injetá-lo nessa classe. Agora, chamaremos o mesmo método, pois seus parâmetros passarão pela transação DTO, a semente mnemônica da carteira atual. Então, vamos injetar a carteira atual nessa classe. Vamos criar esse método na carteira atual. Ele retornará uma string. Aqui, retornará o campo de sementes mnemônico. Vamos criar esse campo. E vamos adicionar um setter para esse campo. O terceiro parâmetro desse método é a senha da carteira. O próximo parâmetro é o UTXO ctOS. Agora, em um bloco try-catch, usaremos o cliente de transação bruta de envio node para enviar uma transação assinada ao nosso node. Então, vamos injetá-lo nessa classe. Chamaremos o método de envio nele. Ao passar a transação, a transação serializada de DTLS usando o método serializado capturará uma IOException e a envolverá em uma nova exceção de tempo de execução. Agora vamos usar o aplicativo Event Publisher. Então, vamos injetá-lo nessa classe. Vamos usá-lo para publicar um novo evento de transações enviadas passando por isso e o DTO da transação como seus parâmetros. Então, vamos criar o evento de transação enviada no pacote de eventos de pontos da GUI. Vamos alterar o primeiro parâmetro da assinatura do construtor para aceitar um objeto. E vamos passar esse objeto para o superconstrutor. E vamos definir o campo DTO da transação o DTO da transação recebida. Vamos adicionar esse campo a essa classe. E vamos criar um getter para isso. Usaremos esse evento mais tarde. Voltar ao método sign and send retornará um novo resultado assíncrono aqui, passando null como parâmetro. Vamos adicionar a anotação assíncrona a esse método passando o serviço executor padrão como seu parâmetro. Lembre-se de que estamos fazendo isso para executar esse método de forma assíncrona, que é nossa política ao nos comunicarmos com nosso node. Ok, criamos o campo inicial mnemônico na classe de carteira atual, mas agora precisamos configurá-lo depois de criarmos uma nova carteira. Então, vamos até o registro da carteira e adicionar o campo de semente mnemônico a ele. Agora vamos acessar o serviço de criação de carteira e adicionar a sequência de caracteres mnemônica aqui como o último parâmetro na instanciação da carteira. Agora, no serviço de atualização da carteira atual, vamos definir a semente mnemônica da carteira atual para a semente mnemônica da carteira. Agora vamos para o segundo controlador de diálogo de transação. No método inicializado, vamos chamar o método do Botão de Pesquisa na caixa de diálogo passando o botão OK para ele. Agora, vamos adicionar um manipulador de eventos a esse botão. O primeiro parâmetro é um evento de ação, que define o clique no botão OK como a ação. O segundo parâmetro é um método Lambda que pega um objeto de evento e chama o método de transação de assinatura e envio. Então, vamos criar esse método. Aqui. Precisaremos do segundo serviço de transação. Então, vamos injetá-lo nessa classe. Agora, chamaremos o método de assinatura e envio nele, passando o DTO da transação e o texto da senha da carteira como parâmetros. Por fim, fecharemos a janela de diálogo usando o método hide na janela do painel de diálogo. Vamos executar nosso node. E vamos finalmente testar o que fizemos executando o teste de envio de Bitcoin. Ótimo, os testes foram aprovados. A carteira detectou nossa transação e a adicionou à tabela de transações. Mas espere, há algo estranho. Vou retroceder o vídeo e pausá-lo na visualização da tabela de endereços para verificar alguma coisa. Esta é a tabela de endereços após nossa carteira enviar nossa transação no primeiro caso de teste Observe que a carteira detectou que um de nossos endereços de alteração na segunda linha recebeu Bitcoins. Bom. Mas como o endereço na primeira linha tem seu UTXO na entrada da transação que acabamos de enviar, seu saldo atual deve ser zero porque sua saída foi gasta. E como nossa tabela de endereços mostra apenas vestidos com saldos maiores que zero, essa tabela deve mostrar apenas uma linha com o endereço alterado. Agora, vamos verificar a tabela de transações para o mesmo caso de teste. Opa, o saldo da transação que acabamos de enviar está errado. Deve ser igual a -0,5 bitcoin menos a taxa de transação. O sinal de menos indicaria que enviamos uma transação de nossa carteira. O texto do saldo total também está errado. Deve ser igual a 0,5 menos a taxa de transação. No vídeo a seguir, corrigiremos esses problemas. 58. 56 Enviar parte do bitcoin 9 skillshare 2: Neste vídeo, corrigiremos alguns problemas que tivemos no último vídeo. Um desses problemas é que a tabela de endereços mostra saldos desatualizados para endereços cuja saída foi gasta. Como o endereço usado após ser usado tem saldo zero, ele não deve aparecer na tabela de endereços. Então, vamos ajustar esse teste para verificar se a tabela de endereços tem apenas uma linha e se essa linha tem um equilíbrio igual à mudança esperada em Mount. Aqui, obteremos a tabela de endereços usando o método de pesquisa. E no bloco then verificará se a tabela de endereços tem uma linha. Vamos também verificar se o saldo da primeira linha é igual a essa variável, que definiremos no bloco web. Em seguida, vamos definir o valor da alteração nas capas pretas de desgaste. Outro problema que vimos no último vídeo é que o saldo da transação está errado na tabela de transações. Isso está acontecendo porque, quando nosso aplicativo recebe uma transação do nosso node, ele considera apenas o saldo da alteração como saldo da transação para garantir que o teste detecte esse erro, vamos adicionar a seguinte linha e, em seguida, o bloco verificará se a primeira linha na tabela de transações tem um saldo igual a menos a variável total gasta. O saldo também está errado, pois é igual à soma de todos os saldos da transação. Então, vamos fazer com que nosso teste detecte esse problema. Aqui. Verificaremos se o texto do saldo total está correto. Primeiro, vamos definir essa variável. Será igual ao texto presente na etiqueta do saldo total da janela depois de enviarmos uma transação. Vamos verificar se essa variável é igual ao texto a seguir. E aqui vamos definir a variável de fundos e atualizada no end stream lambda. Agora, vamos executar nosso node. E vamos fazer esse teste. Ok, o teste falhou porque a tabela de endereços tem duas linhas. Vamos corrigir esses problemas. Para fazer isso, vamos criar o ouvinte de transações enviadas. Mas primeiro, vamos consertar algo totalmente não relacionado. O ouvinte do bloco recebido está no pacote node dot events em vez do pacote node dot listeners. Vamos consertar isso. Com isso resolvido, vamos criar um ouvinte de envio de transações no pacote GUI dot listeners. Como o próprio nome sugere, esse ouvinte lidará com o evento da transação enviada que o serviço de transação publicará após o envio de uma transação. Vamos adicionar a anotação do componente a ela. Ele implementará o ouvinte do aplicativo com o tipo de evento das transações enviadas. Vamos implementar seu método. Aqui liderará a atualização do serviço utxOS. Então, vamos injetá-lo nessa classe. Agora, vamos chamar o método de atualização que passa pela transação do evento de DTO. Agora vamos criar esse método. Aqui, obteremos uma lista de UTXOs da transação DTO selecionou UTXOs. Usaremos um mapa no fluxo UTXO selecionado e instanciaremos um novo UTXO para cada UTXO recebido , passaremos por todos os campos UTXO recebidos na instanciação UTXO, exceto o valor que será zero, já que acabamos de gastá-lo. Agora, para atualizar nossos endereços de carteira, chamaremos o método de atualização do serviço de atualização de endereços atuais da carteira, passando os UTXOs para ele. E para atualizar as transações da carteira, vamos chamar o método de atualização no serviço de transação Update Current Wallet e passará o resultado da chamada da linha de transação do método para ela com a transação DTO como seu parâmetro. Por fim, vamos chamar o método de atualização do serviço balanceado da carteira atual método de atualização do serviço balanceado para atualizar o saldo atual da carteira. Vamos criar isso a partir do método na classe da linha de transação. Aqui retornará uma nova linha de transação em um bloco try-catch. Vamos instanciá-lo com o ID da transação DTO da transação. O total de DTO da transação formatada gasto foi negado usando o método de negação. Isso tornará o valor negativo, já que o estamos gastando. Não terá nenhuma confirmação. E sua data será a data atual. Por fim, detectaremos uma IOException que pode ser lançada pelo método de ID da transação e rapidamente em uma nova exceção de tempo de execução. Voltar ao serviço Update UTXos. Agora, vamos criar o método de atualização que receberá uma linha de transação na atualização. O serviço de transação atual do Wallet usará o método de execução posterior da plataforma, pois o código a seguir modifique a interface da carteira. Aqui, passaremos um lambda que chamará o método de adição de linha de transação na carteira atual e passará pelo caminho da transação para esse método. Agora, vamos criar esse método. Vamos mover esse método para esse local próximo ao método de adicionar linhas de transação. Aqui, chamaremos o método de adicionar linha de transação no campo de linhas de transação, passando a linha da transação como seu parâmetro. Vamos criar esse método na classe de linhas de transação. Aqui, colocaremos a transação gravada no roteiro da transação usando o ID da linha da transação como chave. Ok, com essas modificações, esperamos que pelo menos a tabela de endereços seja atualizada. Vamos executar novamente o teste de envio de Bitcoin para verificar isso. Ok, os endereços apresentados agora estão corretos, mas o teste falhou devido à tabela de transações. As transações de envio ainda estão com um saldo desatualizado. Isso aconteceu porque, embora nosso ouvinte de transações pecaminosas esteja atualizando a transação corretamente, quando nossa carteira recebe a mesma transação do nosso node, ela detecta que uma atualização é somente o endereço de alteração UTXO. Isso não desconta a taxa e os insumos que gastamos. Precisamos mudar a forma como atualizamos nossas transações atuais de carteira para corrigir isso. Na atualização do serviço UTXOs, o método de atualização, que é chamado após nosso aplicativo receber uma transação, chamará o método de lista de transações RPC do nó. Esse método retornará todas as transações de nossa carteira, incluindo aquelas que enviamos com inteligência suficiente para devolver transações com saldos negativos se elas forem enviadas de nossa carteira. Com essas transações em mãos, podemos atualizá-las corretamente em nosso aplicativo. Então, vamos usar a lista de nós do cliente de transações para obter todas as transações de nossa carteira e armazená-las na variável de transações do node. Vamos injetar esse serviço nessa classe. E vamos criá-lo no pacote do cliente api dot services dot no dot. Vamos terminar de injetá-lo nesta classe. Agora, vamos criar o registro da transação do nó, que modelará o retorno do método de transações da lista, criará no domínio e iniciará o pacote do nó. Aqui, chamaremos o método de transações da lista, passando o nome da carteira atual. Vamos criar esse método. E vamos adicionar a anotação do serviço aqui. Vamos injetar o cliente node nessa classe. Aqui, obteremos uma matriz do tipo node transaction chamando o método node client make request com os seguintes parâmetros. A string de transação da lista, que é o nome do método RPC do nó, uma nova referência de tipo parametrizado. O URL da carteira concatenado com o nome da carteira. E uma sequência de asterisco, que indica que queremos todas as transações dessa carteira. O valor inteiro máximo, que significa que queremos o número máximo de transações na resposta zero, o que indica ao método que não queremos pular nenhuma transação. E é verdade, o que indica que queremos observar apenas as transações incluídas na resposta. Observe que somente transações são transações. O node não tem a chave privada para gastar. Essa opção faz sentido porque nossa carteira não passa nenhuma chave privada para nosso node. Finalmente, retornamos a matriz de transações convertida em uma lista. Agora, vamos criar o nó. Os campos de registro de transação adicionarão somente os campos que usarão. Eles são o T XID, as confirmações, o valor, o endereço, que é o endereço para o qual o remetente pretende enviar bitcoins, não o endereço de alteração. E a hora, que é a data e hora da criação da transação. Voltar ao serviço Update UTXos. Chamaremos o método de transações do nó de atualização no serviço de transação Update Current Wallet. Como parâmetro, passará as transações do node. Vamos criar esse método. Aqui, obteremos uma lista de linhas de transações a partir de nenhuma transação. Chamaremos o método de filtro no fluxo de transações do node. Como parâmetro, passará por um lambda que pegará uma transação de nó e verificará se a carteira atual contém o endereço da transação do nó. Em seguida, adicionamos um operador or e verificamos se a carteira atual contém uma transação sem o ID da transação. Esse filtro resultará em um fluxo de transações que contém apenas transações endereçadas para envio que são nossas, o que abrange o recebimento de transações. A condição após o operador or fazer o fluxo de transações também inclui transações que nosso aplicativo já possui. Isso significa que as transações que foram adicionadas anteriormente pelo ouvinte de envio da transação terão seu saldo atualizado corretamente com saldos negativos. Agora, não faremos o fluxo resultante usando a linha de transação do método. Vamos criar esse método e movê-lo para aqui. Aqui retornará uma nova linha de transação instanciada com o ID da transação do nó. O valor da transação do nó formatado, as confirmações da transação do nó e o tempo da transação do nó convertido em uma string. Agora, convertemos o fluxo de transações em uma lista. Por fim, usamos o método run later da plataforma e, usando um lambda, chamamos de Adicionar linhas de transação na carteira atual, passando as linhas de transação para ela. Vamos remover esse método, pois não precisaremos mais dele. Também vamos remover esse método na linha de transação pelo mesmo motivo. Mais uma coisa aqui no método de linhas de transação de anúncios na classe de linhas de transação precisamos atualizar o saldo da linha da transação antes que nossas alterações entrem em vigor. Então, vamos incluir o código a seguir para fazer isso. Agora, vamos fazer o teste de envio de Bitcoin. Antes de executá-lo, vamos incluir uma chamada suspensa após o teste clicar no botão OK na segunda caixa de diálogo de transação. Com isso, evitamos que o teste falhe devido às condições de corrida. Agora, vamos fazer nosso teste. Ótimo, os testes foram aprovados. Vamos executar todos os testes de aplicativos para garantir que não quebramos nada em nossas carteiras. Vou acelerar o vídeo agora, já que esses testes levarão alguns minutos para serem executados na realidade. Ótimo. Todos os testes foram aprovados. 59. 57 Enviar parte do bitcoin 10 skillshare 2: Neste vídeo, adicionaremos mais testes para verificar se nossa carteira funciona conforme o esperado ao enviar transações em diferentes cenários. Vamos ver se nossa carteira pode enviar duas transações, uma após a outra. Para fazer isso, vamos duplicar esse teste na classe de teste send Bitcoin. Vamos mudar seu nome para. Deve enviar Bitcoin às vezes. Vamos corrigir sua formatação. Vamos mudar o nome da carteira para o meu teste aos dez anos. Agora vamos extrair essa seção de código para um método. Vamos chamá-lo de enviar Bitcoin. Vamos adicionar o valor a ser enviado como segundo parâmetro. Depois de criar uma transação, clicará no botão OK para enviá-la. Em seguida, usaremos essa linha de código para transformar nosso nó em um bloco. Com isso, esperamos que nossa segunda transação seja confirmada, permitindo usar a alteração UTXO gerada por essa transação como entrada na próxima transação. Agora, clicaremos na guia Enviar. E chamaremos o método de sono com esses parâmetros para aguardar a confirmação de nossa transação. Depois de enviar a primeira transação, esperamos que nosso primeiro endereço de alteração seja exibido na tabela de endereços. Esperamos que um endereço de alteração diferente seja usado na segunda transação porque é importante não reutilizar endereços ao receber Bitcoins por motivos de privacidade. Então, compararemos o endereço de alteração nas duas transações e verificaremos se elas não são iguais. Para fazer isso, vamos pesquisar a tabela de endereços com essa linha de código. Vamos alterar o tipo TableView para a linha de endereço para fins de exatidão. Vamos remover a declaração aqui e aproveitar a oportunidade para corrigir o mesmo problema no método de teste anterior. Armazenará o primeiro endereço de alteração nessa variável, obtendo-o da tabela de endereços. Em seguida, chamaremos o método de envio de Bitcoin novamente para enviar a segunda transação. Após a segunda transação procurará a tabela de endereços novamente. Espero que a primeira linha da tabela contenha o segundo endereço de alteração. Então, vamos consultá-lo novamente e armazenar o endereço da primeira linha e a segunda variável de endereço de alteração. No bloco then, adicionará a seguinte afirmação para verificar se o primeiro endereço de alteração não é igual ao segundo. Aqui, esperamos que o tamanho da tabela de transações seja igual ao número UTXOs anterior mais dois. E vamos mudar essa parte do texto do saldo total. Esperamos que o saldo confirmado seja igual aos fundos menos o total gasto. Vamos remover esse caso de teste, teremos apenas um caso para esse teste. Vamos alterar o valor para enviar 0,25. Vamos atualizar o total gasto adequadamente. E vamos alterar os últimos quatro dígitos do valor da alteração. Esse valor de alteração é a soma dos valores de alteração das duas transações. Agora, vamos executar nosso node. Vamos adicionar a anotação de ignorar ao primeiro teste, pois queremos executar somente o último teste. E vamos executá-lo. O teste falhou porque o primeiro endereço de alteração é igual ao endereço da segunda alteração. Vamos corrigir isso. Vamos até o serviço de atualização dos endereços da carteira atual e moveremos essa linha de código para esse local. Aqui, adicionaremos uma declaração if para verificar se o endereço que está sendo atualizado é um endereço alterado. Vamos adicionar essa constante a essa classe. Será igual ao tipo de endereço que seg mudaria. No corpo da declaração if, definirá o endereço de alteração da carteira atual para o próximo endereço. Vamos também adicionar uma instrução return a esse corpo da declaração if. Vamos executar o teste novamente. Ótimo, o teste foi aprovado. Agora, começaremos a implementar alguns tratamentos de erros em situações em que as coisas não correm bem quando tentamos enviar transações, por exemplo, o que deve acontecer quando usamos a senha errada da carteira quando tentando enviar uma transação. Quando nossa carteira envia uma transação com a senha incorreta, isso faz com que a transação seja construída com assinaturas inválidas. Quando nosso node a recebe, ele tenta validar essa transação. Como suas assinaturas estão erradas, ele retornará uma mensagem de erro e não retransmitirá a transação para outros nós. Atualmente, nossa carteira não está lidando com o erro retornado e falhará silenciosamente. Vamos criar uma solução para essa situação. Nosso node retorna um erro após receber nossa transação mostrará ao usuário um alerta de erro dizendo que a carteira não conseguiu enviar a transação. E y. Primeiro, vamos criar um teste para esse cenário. Na aula de teste de envio de Bitcoin. Vamos duplicar o primeiro método. Vamos renomeá-lo para não enviar Bitcoin com a senha errada. E vamos ajustar sua formatação. Vamos também mudar o nome da carteira para minha carteira de teste 11. Aqui, clicaremos no campo da senha. Vamos definir uma variável para essa senha. Vamos configurá-la como minha senha de teste e escrevê-la no campo de senha. Depois de receber Bitcoins, vamos armazenar o saldo formatado na variável fundos formatados. Como não teremos sucesso no envio de uma transação, esperamos que o saldo final de nossa carteira não mude e continue sendo igual a essa variável. Agora, vamos substituir essa seção de código por uma chamada do método send Bitcoin. Depois que a caixa de diálogo da transação aparecer, clicaremos no campo de senha da carteira. E escreveremos a senha errada. Depois de clicar no botão OK, esperamos que uma mensagem de erro apareça. Vamos definir essa mensagem de erro e armazená-la nessa variável. Em seguida, com esse código, tentará armazenar o nó com essa mensagem na variável de consulta do nó. O alerta de erro terá um botão OK que tentará clicar. No bloco then, verificará se os textos da consulta do nó são iguais à mensagem de erro. Também verificará se o endereço na tabela de endereços tem um saldo igual à variável de fundos formatada. Esperamos que o tamanho da tabela de transações seja igual a um, pois não mostraremos a transação que falhou na tabela. Também vamos alterar o saldo esperado da transação aqui para ser igual aos fundos formatados. Também esperamos que o saldo total e o saldo confirmado sejam iguais à variável de fundos formatados. O saldo esperado não confirmado deve ser igual a zero com oito casas decimais. Vamos remover o segundo caso de teste no bloco where. Agora vamos implementar o recurso de alerta de erro. No segundo serviço de transação. Vamos adicionar uma instrução catch aqui para detectar um erro interno do servidor. Esse é o tipo de erro que o nó retornará se algo der errado quando tentarmos enviar uma transação para ele. Agora, usaremos o registrador para registrar esse erro. Então, vamos adicionar o registrador a essa classe como um campo estático. Irá instanciá-lo usando o método logger factory get logger, passando essa classe como seu parâmetro. Em seguida, chamaremos o método de erro nele, passando o erro get response body como chamada de método string. Em seguida, retornaremos a chamada do método de erro do manipulador de erros do node passando o erro para ele. Vamos injetar o manipulador de erros do node nessa classe. Vamos criar essa classe no pacote de serviços de pontos da GUI. Vamos terminar de injetá-lo nesta classe. Vamos criar esse método nele. Ele retornará um erro de tipo futuro. Voltando ao local que o chamará, vemos que o ID indica um erro de tipo. Para corrigir isso, vamos alterar o tipo de retorno do sinal e o método de envio para o futuro do erro de tipo. Mas primeiro, vamos criar o registro de erro no pacote domains dot node. Vamos copiar essa linha e colá-la aqui. Vamos alterá-la para importar essa classe de erro que acabamos de criar. Se não fizermos isso, o Java usará sua classe de erro embutida. Agora, vamos mudar esse parâmetro de tipo para erro. Vamos passar a linha de importação para essa classe também. Vamos adicionar uma anotação de serviço a ela. Agora, antes de continuarmos implementando o recurso, vamos executar o último teste para verificar o formato da mensagem de erro que o nó retorna nos registros. Primeiro, vamos adicionar a anotação de ignorar a esse teste. Então, só executamos o último teste. Aqui, vemos que o nó retornou à mensagem JSON. A parte importante diz que o script falhou e 0 p é igual à operação de verificação. Isso significa que o nó falhou devido a uma assinatura incorreta ao executar o script combinado para validar a transação. Agora que sabemos o que o nó retorna ao aplicativo quando a senha da carteira está errada, vamos mapear essa resposta para a resposta de senha incorreta que queremos que o usuário veja. No manipulador de erros do node. Vamos adicionar um bloco try-catch converter o erro recebido em um objeto de encapsulamento de erro de nó. Então, vamos criar esse registro no pacote domains dot node. Após a resposta adjacente ao erro do nó, conforme a especificação, adicionará um campo de erro do tipo erro de nó aqui. Então, vamos criar o registro de erro do nó no pacote domains dot node. Ele terá um campo de código e um campo de mensagem. De volta ao node, o manipulador de erros precisará do mapeador de objetos. Então, vamos injetá-lo nessa classe. Agora, chamaremos o método read value no mapeador de objetos pois seus parâmetros passarão o erro get response body as string method call. E a classe node error wrapper. Esse código converterá o erro recebido em um objeto de encapsulamento de erro de nó. Por fim, retornaremos um novo objeto de resultado assíncrono instanciado com um objeto de erro. Para instanciar o objeto de erro, usaremos o erro do método que passa o erro do wrapper de erro do node como parâmetro. Vamos criar o método frontal. Ele retornará um objeto de erro. Vamos adicionar o campo de mensagem a esse registro. O método front retornará um novo objeto de erro instanciado com uma mensagem de erro. Para criar a mensagem de erro, vamos adicionar o campo de mensagens de erro nessa classe. Esse campo será responsável por mapear as mensagens de erro do nó com as mensagens que queremos exibir. Será um mapa de chaves e valores de cadeias de caracteres. Vamos usar o mapa do método para criá-lo. A primeira chave será a mensagem de erro retornada pelo nó, que vimos anteriormente nos registros do aplicativo. O valor será a mensagem de erro que queremos exibir. Para isso, usaremos a senha incorreta constante da classe de mensagens de erro que criaremos. Então, vamos criar essa classe no pacote domains dot node. E vamos adicionar essa constante a ela com a mensagem que queremos exibir. Agora, chamaremos o método Get ou padrão no campo de mensagens de erro no método do formulário Seu primeiro parâmetro será a mensagem de erro. Seu segundo parâmetro será uma mensagem padrão, que definiremos nessa constante. Portanto, se o nó retornar uma mensagem de erro que ainda não mapeamos, a mensagem de erro exibida indicará que ocorreu um erro. De volta ao manipulador de erros do node. Vamos adicionar uma instrução catch aqui para exceção de processamento adjacente que o mapeador de objetos pode gerar. Em seguida, o agrupamos em uma exceção de tempo de execução e o lançamos. Agora vamos para o segundo controlador de diálogo de transação. Aqui, obteremos o resultado do método sign and send e o armazenaremos em uma variável. Apenas certifique-se de importar a classe de erro correta. Agora, precisaremos do serviço de erro de alerta. Então, vamos injetá-lo nessa classe. Esse serviço será responsável por mostrar um alerta com uma mensagem de erro. Vamos criá-lo no pacote de serviços de pontos da GUI. E vamos terminar de injetá-lo nesta classe. Agora, vamos chamar o método de manipulação do erro no erro de alerta ou no objeto de serviço que passa o resultado para ele. Vamos criar esse método. Primeiro. Vamos adicionar a anotação do serviço a essa classe. Aqui, declararemos um objeto de erro. Em seguida, em um bloco try-catch, definirá a variável de erro para a chamada do método dot get resultante. Em seguida, capturaremos uma exceção que o resultado pode gerar e a envolveremos em uma nova exceção de tempo de execução. Agora, nesta instrução if, verificaremos se o erro não é igual a nulo. Caso contrário, chamaremos o método de erro de alerta, passando a mensagem de erro para ele. Vamos criar esse método. Aqui. Criaremos um novo objeto de alerta com um erro de tipo de alerta. Em seguida, definiremos o título do alerta como erro. E definiremos o texto do cabeçalho do alerta como um erro ou dois. Vamos definir o texto do conteúdo do alerta para a variável da mensagem. Finalmente, vamos chamar o método show no objeto de alerta. Agora, vamos executar o teste novamente. Ótimo, o teste foi aprovado. 60. 58 Enviar parte do bitcoin 11 Skillshare 2: Neste vídeo, continuaremos adicionando mais validações e alertas para notificar o usuário sobre tentativas fracassadas de transferência. Primeiro, criaremos alguns casos de teste para esses cenários. Então, vamos duplicar esse teste para adicionar um teste para o cenário em que o usuário deseja enviar uma transação com mais bitcoins do que seus fundos. Vamos renomeá-lo para não enviar Bitcoin sem fundos maiores que valor mais v. Vamos reformatá-lo. E vamos mudar o nome da carteira para o meu teste aos 12 anos. Vamos excluir essas linhas. Aqui. Definiremos uma variável de mensagem de erro para o conteúdo que queremos que o usuário veja em caso de erro A mensagem será não foi possível enviar transação, não há fundos suficientes. Em seguida, com esse código, tentará armazenar o elemento UI com essa mensagem na variável de consulta do nó. E tentaremos clicar no botão OK na caixa de diálogo de alerta. No bloco then, verificaremos se o texto da consulta do nó é igual à mensagem que definimos anteriormente. Vamos excluir essas variáveis no bloco where, pois não precisaremos delas. E vamos criar a variável de valor anterior aqui com o seguinte valor. Vamos duplicar essa linha para criar um segundo caso de teste. Esse valor será um Satoshi menor do que o necessário para enviar 0,5 bitcoin. Agora, vamos deletar essa linha. Vamos substituir esses valores pela variável de valor anterior. Agora, criaremos um cenário de teste semelhante, mas desta vez usando uma carteira sem fundos. Então, vamos duplicar esse teste. Vamos mudar seu nome para não enviar Bitcoin sem fundos. Vamos mudar o nome da carteira para o meu teste aos 13 anos. Vamos remover essas linhas pois não receberemos nenhum fundo. E vamos deixar apenas o valor para enviar a variável e o bloco where. Agora, vamos implementar o recurso na classe de serviço de criação de transações. Vamos armazenar a transação DTO em uma variável aqui. E vamos retornar essa variável. Agora. Antes de retornar, ele chamará o método de validação de fundos, passando a transação DTO como seu parâmetro. Vamos criar esse método. Usarei esse método para validar se a soma dos valores de entrada da transação é maior do que a saída da transação entre alguns. Então, vamos criar essa variável para armazenar a quantidade de entrada. Alguns atribuirão o resultado de chamar a transação de DTO receberão quantidades de método de entrada para ela. Vamos criar esse método. Aqui. Usaremos um mapa no fluxo UTXOs selecionado para criar um fluxo de valores de UTXO. Em seguida, usaremos o método reduzido para somar cada valor obtido. Finalmente, usaremos o método or else para retornar a soma ou zero se nenhum UTXOs estiver disponível. Agora, vamos criar as quantidades de saída do método get output aqui. Usaremos uma estratégia semelhante a alguns dos valores de produção. Mas em vez de usar os UTXOs selecionados, usará um mapa no fluxo de saída da transação. O método de mapa retornará os valores de saída convertidos em Bitcoin. E usaremos o método reduce e Rails da mesma forma que usamos no método anterior. Voltar ao método de validação de fundos. Aqui, criaremos uma variável de saída para armazenar o resultado da chamada dos valores de saída get. Um método que acabamos de criar. Agora, adicionaremos uma instrução if para verificar se a soma de entrada é menor que a soma de saída mais o total calculado F0. Se for, lançaremos uma nova exceção de criação de transação com a mensagem de fundos insuficientes. Vamos criar essa constante na classe de mensagens de erro. Vamos tornar as duas constantes finais. E vamos criar a classe de exceção de transação no pacote de exceções de pontos da GUI. Ele estenderá a exceção de tempo de execução e passará sua mensagem para o superconstrutor. Vamos aproveitar a oportunidade para adicionar outra validação aqui. E se tentarmos enviar uma transação sem uma carteira carregada? Para lidar com esse caso, vamos usar essa instrução if para verificar se a carteira atual tem algum endereço. Caso contrário, lançaremos uma exceção de criação de transação com uma mensagem de carteira não carregada. Vamos criar essa constante para armazenar essa mensagem. Agora, vamos para o controlador da guia Enviar. Vamos agrupar a criação da transação DTL em um bloco try-catch. A chamada do método de diálogo aberto para. Aqui, vamos pegá-lo. Crie uma exceção de transação. Usaremos o erro ou serviço de alerta e o corpo de captura. Então, vamos injetá-lo nessa classe. Em seguida, chamaremos o método de erro de alerta, passando a mensagem de exceção como seu parâmetro. Vamos tornar esse método público. Vamos fazer o teste de envio de Bitcoin. Vamos adicionar a anotação de ignorar ao teste que fizemos no último vídeo. Vamos executar nosso node. Antes de executar o teste, vamos ajustar alguns detalhes. Vamos adicionar um ponto no final das mensagens de erro. No método de envio de Bitcoin. Vamos adicionar esse parâmetro. O padrão será verdadeiro e só chamará o método de diálogo do wafer se for verdadeiro. Agora, vamos configurá-lo como false e essas chamadas, porque o diálogo da transação não aparecerá nesses testes. Finalmente, vamos executar os testes. Nota: os testes foram aprovados. Vamos remover todas as anotações de ignorar dessa classe. Agora, adicionaremos vários testes novos em uma nova classe chamada enviar teste adicional de Bitcoin neste pacote. Mas não se preocupe, desta vez, copiaremos o conteúdo dessa aula da página Projeto e Recursos. Todos esses testes devem ser aprovados. Espero que não precisemos mudar nada em nosso código para isso. Mas eles ajudarão a garantir que nossa carteira envie as transações corretamente e detecte possíveis quebras de código que ocorrerão no futuro. Vamos reformatar todos eles. No primeiro teste, verificaremos se uma carteira com uma senha envia transações corretamente. O próximo teste gerará transações sem a necessidade de alteração e verificará se seus parâmetros estão corretos. Esse teste tentará enviar uma transação para um endereço de nossa própria carteira e verificar se a carteira calcula corretamente seus valores e saldos. Finalmente, o último teste terá muitos casos de teste diferentes com números diferentes de UTXOs e valores anteriores. Para que esses testes funcionem, vamos mover o peso do método de diálogo no teste de envio de Bitcoin para a classe de teste de GUI. Vamos protegê-lo. Vamos remover essas importações no teste de envio de Bitcoin. Mais uma coisa no método de envio de Bitcoin, no teste de envio de Bitcoin, vamos adicionar a superpalavra-chave aqui para garantir que chamaremos o peso correto para o método de diálogo, não o parâmetro com o mesmo nome. Faremos outro teste nesta aula. Desta vez, verificaremos o que acontece quando tentamos enviar uma transação com uma quantidade de poeira. Então, vamos duplicar esse teste. Vamos mudar seu nome para não enviar pó de Bitcoin. Vamos corrigir sua formatação. Vamos mudar o nome da carteira para o meu teste aos 18 anos. Agora, vamos copiar esse código e adicioná-lo ao nosso método para financiar nossa carteira. Vamos alterar a mensagem de erro para Não foi possível enviar valor da transação para enviar é poeira. Vamos mudar o bloco where, adicionando as seguintes variáveis a ele. Escolheremos uma quantia para enviar igual a 293 Satoshi, que sabemos que nosso node não pode aceitar, pois será considerada poeira. Para o valor anterior, escolherá 0,1 bitcoin. Como confiaremos em nossa nota para detectar esse tipo de erro, aguardaremos que a caixa de diálogo da transação apareça depois de clicarmos no botão Enviar. E vamos adicionar o clique na chamada do método do botão OK para confirmar a transação do diálogo. Agora, vamos para a classe de erro. Vamos adicionar a seguinte entrada ao mapa de mensagens de erro o erro de mensagem de poeira recebida do nosso nó para a mensagem presente na constante de poeira na classe de mensagens de erro. Vamos criar essa constante. Será igual à mensagem que acabamos de definir no teste. Vamos adicionar a anotação de ignorar aos outros testes dessa classe e executar nosso novo teste. Ótimo, o teste passou. Vamos excluir todas as anotações de ignorar que adicionamos anteriormente. Neste momento, eu recomendo executar todos os testes do aplicativo. Eu fiz isso e todos eles passaram. Não vou mostrar isso neste vídeo porque levaria vários minutos. Vou deixar isso como um exercício para o aluno. 61. 59 Segwit aninhado parte 1 skillshare 2: Neste vídeo, começaremos a refatorar nosso aplicativo para prepará-lo adicionar suporte para mais tipos de endereço. Será um refator relativamente grande, mas veremos mais tarde que isso nos permitirá adicionar suporte para outros tipos de endereço, como o conjunto aninhado abordaria. A ideia desse reator é centralizar tudo o que específico de um tipo de endereço em um objeto de configuração de endereço. Ao fazer isso, poderemos adicionar mais tipos de endereços às nossas carteiras adicionando novos objetos de configuração de endereço ao projeto. Depois de fazer essa refatoração, adicionaremos um novo tipo de endereço chamado segmento aninhado, cuja importância explicaremos em alguns vídeos. Então, vamos até o registro de configuração do endereço para adicionar alguns campos. Adicionaremos o campo gerador de endereços. Vamos usá-lo para definir o serviço usado para gerar endereços para diferentes tipos de endereço. Um mapa com uma chave de enumeração de ambiente e um valor de string. Usaremos esse campo para registrar os prefixos de endereço para cada ambiente. Então, vamos criar isso o suficiente. No pacote BYU w dot domains. Ele terá as constantes de teste net, test net e reg test. Vamos adicionar o campo de prefixo ki estendido aqui. Como o nome sugere, ele definirá o prefixo da chave estendida que gerará os endereços. O próximo campo será uma string de predicados como parâmetro de tipo. Ele receberá uma função lambda com um endereço como parâmetro e uma expressão que retornará true se o endereço corresponder ao tipo de configuração do endereço e false. Caso contrário, adicionaremos um campo do tipo de chave de pub de script para que possamos identificar qual configuração de endereço usar usando o tipo de chave pub do script. Em seguida, adicionaremos por função com esses parâmetros de tipo usaremos esse campo para definir uma função para analisar um endereço de um determinado script, chave pub e um prefixo. Agora vamos excluir o bean de conflito de endereço para o endereço de alteração do Segway. Nesta refatoração, usará apenas um bean de configuração de endereço para os endereços de alteração do segmento e do segmento. Vamos mudar a anotação do Bean para refletir essa mudança. Agora, vamos alterar essa instanciação de configuração de endereço para incluir cada recurso relacionado a esse tipo de endereço. Alteraremos o campo do caminho de derivação para um mapa em que a chave será um tipo de endereço e o valor será seu caminho de derivação correspondente. Aqui, adicionaremos duas entradas, uma para o tipo de endereço do segmento e seu caminho de derivação inicial e a outra para a alteração do Segway e seu caminho de derivação inicial. Agora, à medida que for abordado, gerador adicionará um novo gerador de endereços de segmento. Para o campo de prefixos de endereço, adicionaremos o mapa a seguir uma entrada para cada ambiente e eles são prefixos de endereço P2, WP k h. O campo de prefixo ki estendido será a principal constante do prefixo net segue. Como o combinador de endereços será usado o combinador de endereços segue com a função Lambda. Então, vamos criar essa classe e o pacote utils. E vamos criar essa função. Será uma função que pegará um endereço e retornará verdadeiro se o endereço começar com um desses três prefixos presentes nos endereços do segmento. O próximo campo será igual à constante do script P2 WP k h. Finalmente, o analisador de endereços será uma referência ao método de endereço do script P2 WP k h. Vamos voltar à configuração do endereço para substituir o tipo do caminho de derivação. Será um mapa com tipos de endereço como chaves e cadeias de caracteres como valores. Agora, vamos criar a classe localizadora de configuração de endereço no pacote api dot services. Usaremos esse serviço como uma forma de recuperar o endereço correto, pode ser falso e outros serviços serão refatorados a seguir. Então, vamos adicionar a anotação de serviços a ela. E vamos injetar uma lista de configurações de endereço aqui. Agora, vamos criar esse método que nos permitirá encontrar uma configuração de endereço por endereço. Seu tipo de retorno será opcional do tipo configuração de endereço. Em seguida, filtraremos um fluxo de configurações de endereço e usaremos o combinador de endereços configuração no filtro lambda. Em seguida, retornaremos a configuração de endereço opcional correspondente ao endereço recebido usando o primeiro método. Agora vamos criar outro método que retornará uma configuração de endereço opcional do tipo. Desta vez, ele encontrará uma configuração de endereço de acordo com seu tipo de script. Será semelhante ao método anterior, mas usaremos o filtro para verificar se a chave pub do script anterior corresponde à da configuração do endereço. Também usaremos o primeiro método definido neste caso. Agora, criaremos um método para encontrar uma configuração de endereço por tipo de endereço. Novamente, usaremos um filtro em um fluxo de configurações de endereço. Desta vez, o filtro conterá um lambda que verificará se o tipo de endereço de configuração do endereço é igual ao tipo de endereço anterior ou se é igual à alteração correspondente tipo de endereço. Desta vez, retornaremos que o endereço pode ser falso sem o objeto opcional usando o método orals throw. Esse método gerará uma exceção se não encontrar a configuração de endereço apropriada. Agora estamos prontos para começar a refatorar outros serviços para usar nossa nova configuração de endereço e localizador de configuração de endereço. Vamos começar com o serviço de criação de carteira. Vamos deletar essas duas linhas. Aqui. Usaremos um FlatMap na lista de configuração de endereços. Em seguida, passaremos um método lambda como parâmetro, retornando no corpo do lambda A transformação a seguir obterá os caminhos de derivação da configuração de endereço recebida. Está faltando uma letra S final. Então, vamos renomear esse campo para caminhos de derivação. Agora, obteremos o conjunto de entrada dos caminhos de derivação. Em seguida, chamaremos o método map no fluxo de entradas do caminho de derivação e retornaremos uma chave pub estendida para cada entrada usando o método de criação do serviço de chave pub estendida. Como seus parâmetros passarão pela chave mestra. O valor de entrada, que será o caminho de derivação, a chave de entrada, que será o tipo de endereço, e o prefixo ki estendido da configuração do endereço. Por fim, convertemos o resultado em uma lista. Agora vamos ao serviço estendido de chaves de pub. Vamos deletar essas linhas. Vamos adicionar um quarto parâmetro a esse método. Será um prefixo ki estendido. Aqui, substituiremos esse argumento pelo prefixo ki estendido, prefixo público. Agora vamos para o gerador de endereços do segmento. Aqui, adicionaremos o prefixo como segundo argumento e o usaremos como um parâmetro aqui. Agora, vamos remover a fábrica de prefixos de endereço dessa classe. E vamos adicionar o segundo argumento a essa interface, gerar o método dois. Agora vamos para o gerador sequencial de endereços. Na chamada do método generate, usaremos o prefixo de endereço factory. Então, vamos injetá-lo nessa classe. Agora vamos chamar o método get nele, passando o tipo de endereço recebido como seu parâmetro. Agora vamos refatorar a fábrica do gerador de endereços. Vamos deletar todas essas linhas. Vamos injetar o localizador de configuração de endereço nessa classe. Aqui, chamaremos a busca por tipo de endereço no localizador de configuração de endereço, passando o tipo de endereço como parâmetro. Em seguida, retornaremos o gerador de endereços de configuração do endereço do telefone. Agora, vamos refatorar a fábrica de prefixos de endereço. Vamos remover todas essas linhas. Então, vamos injetar o endereço que pode pensar no Finder nessa classe. Novamente, encontraremos a configuração do endereço por tipo de endereço usando esse método. Em seguida, obteremos os prefixos de endereço da configuração do endereço encontrado. Por fim, retornaremos o prefixo de endereço correspondente ao ambiente atual do Bitcoin, desta forma. Vamos corrigir os testes para as classes que acabamos de refatorar, começando com o teste do gerador sequencial de endereços. Vamos adicionar o localizador de configuração de endereço como um campo nessa classe. E vamos atribuí-lo a uma simulação dessa aula aqui. Agora, vamos instanciar uma nova configuração de endereço, definindo-a para essa variável. Em seguida, vamos usar um método para definir um objeto retornado quando chamamos o método find by address type no localizador de configuração de endereço. Nesse caso, retornará a configuração do Segway. Então, vamos tornar esse método público na classe de configuração de endereço. Agora vamos mudar esse parâmetro de fábrica do prefixo de endereço para a string de rede principal. E vamos passar o localizador de configuração de endereço para a instanciação da fábrica do gerador de endereços. Vamos fazer esse teste. Opa, a compilação falhou devido a um erro no construtor UTXO DTO. Vamos consertar isso. Aqui. Obteremos a configuração do endereço usando o localizador de configuração de endereço. Então, vamos injetá-lo nessa classe. Vamos excluir a lista de configurações de endereço dessa classe. Agora, encontraremos a configuração do endereço por tipo de endereço aqui. Em seguida, obteremos o caminho de derivação usando o tipo de endereço recebido. Por fim, concatenaremos a barra da string e o índice do endereço ao resultado. Vamos fazer o teste novamente. Ótimo, o teste foi aprovado. Agora vamos corrigir o teste do serviço de criação de carteira. Vamos deletar essas linhas. Instanciará a configuração do endereço aqui. Em seguida, criaremos a lista de configurações de endereço aqui. Adicionar o conjunto configuraria a ele. Vamos remover todas essas linhas. Agora, vamos instanciar os objetos necessários dessa forma. Vamos fazer esse teste. Grau. O teste foi aprovado. Agora vamos corrigir o teste estendido do serviço de chaves de pub. Adicionaremos o prefixo de rede principal que seria o último parâmetro do método create. E vamos fazer esse teste. Ótimo, já passou. Finalmente, vamos corrigir o teste do gerador de endereços de segmentos. Removeremos o prefixo de endereço de fábrica dessa classe. E passaremos o prefixo de endereço principal da rede P2 WP k h como o segundo parâmetro desse método. Vamos fazer esse teste. Grau. O teste foi aprovado. No vídeo a seguir, continuaremos a refatorar nosso aplicativo. 62. 60 Segwit aninhado parte 2 skillshare 2: Neste vídeo, continuaremos a refatorar nosso aplicativo. Então, vamos começar com a classe do analisador de endereços. Vamos injetar o localizador de configuração de endereço nessa classe. Vamos remover esse código. Agora, usaremos o localizador de configuração de endereço para encontrar uma configuração de endereço por tipo de chave pub do script, passando o tipo de chave pub do script para esse método. Em seguida, mapearemos o resultado e aplicaremos o analisador de endereços de configuração de endereço, passando a chave pub do script e o prefixo adequado como seus parâmetros. Agora, usaremos o método URL para retornar uma string vazia se um endereço não puder ser analisado. Vamos devolver essa transformação. Agora, vamos para a classe de carteira atual. Vamos remover o endereço de recebimento e alterar o endereço dessa classe. Em vez de usar um campo para cada endereço de recebimento e alteração, usaremos um campo de endereços de recebimento para modelar os diferentes endereços usados para receber Bitcoins em nossa carteira. Então, vamos adicionar o campo de endereços de recebimento a essa classe. Será um mapa observável com tipos de endereço como chaves e cadeias de caracteres como valores. Irá instanciá-lo aqui com um HashMap observável da classe de coleções FX. Vamos excluir os métodos que usam os campos removidos. Agora vamos criar o método de definir endereços de recebimento. Colocaremos uma entrada no mapa de endereços de recebimento para cada chave de pub estendida. A chave de cada entrada será um tipo de endereço obtido usando o valor do método passando o tipo de chave pub estendida como seu parâmetro. O valor será o primeiro endereço da chave de pub estendida. Agora, vamos criar o método de endereço de recebimento definido. Usaremos esse método para atualizar o endereço de recebimento atual para um tipo de endereço específico. Ele aceitará um índice de endereço e um tipo de endereço como parâmetros. Primeiro, obteremos o próximo endereço usando o método get address ID passando esses parâmetros. Em seguida, colocaremos o endereço obtido nos endereços de recebimento usando o tipo de endereço como chave. Vamos criar o método de obter endereço de recebimento. Ele pegará um tipo de endereço e retornará o endereço de recebimento atual desse tipo e o obterá dos endereços de recebimento usando o tipo de endereço como chave para a recuperação. Agora, vamos criar um getter para os endereços de recebimento. Vamos renomeá-lo para obter endereços de recebimento observáveis. Agora, vamos para o serviço de atualização de endereços da carteira atual. Vamos remover todas essas linhas dentro de uma chamada de execução posterior da plataforma. Vamos adicionar uma função Lambda que usará o endereço de recebimento do conjunto atual da carteira para definir o próximo endereço. Vamos remover esses campos, pois não precisaremos deles. Agora, vamos refatorar o serviço de atualização atual da carteira. Vamos remover essas duas linhas. Em seguida, vamos adicionar uma chamada ao método definido de endereços de recebimento que acabamos de criar na carteira atual. Agora, vamos para o controlador da guia Receber. Vamos remover esse código. Aqui. Obteremos os endereços de recebimento observáveis da carteira atual e adicionaremos um ouvinte a ela. O ouvinte será a seguinte função lambda. Com isso, a declaração if verificará se o endereço de recebimento que foi alterado foi a segue qual endereço? Nesse caso, definiremos o texto do campo do endereço de recebimento como o endereço recém-adicionado. Agora vamos refatorar a forma como o endereço de alteração é usado no projeto. Então, vamos criar uma classe chamada Localizador do tipo de endereço de alteração. Essa classe será responsável por encontrar o tipo de endereço de alteração apropriado para uma determinada saída de endereço. Embora possamos usar diferentes tipos de endereço como saídas em uma transação, é recomendável usar o mesmo tipo para complicar terceiros descubram qual saída foi usada na alteração. Esse serviço nos permitirá resolver essa preocupação. Vamos adicionar a anotação do serviço a essa classe. Vamos injetar o localizador de configuração de endereço nele. Agora vamos criar o método find. Esse método retornará um tipo de endereço e tomará um endereço como parâmetro. Aqui, chamaremos o método find by address no localizador de configuração de endereço. Em seguida, mapearemos o valor obtido para o tipo de endereço de alteração equivalente usando o código a seguir. Finalmente, usamos o método or else para retornar o tipo de endereço seg would change. Se o tipo de endereço não foi encontrado. Usaremos o endereço de mudança do Segway para este caso. Embora permitamos que nosso aplicativo envie transações para a maioria dos tipos de endereço, precisamos fornecer esse recurso porque não implementaremos todos os tipos de endereço como destinatários endereços em nossa carteira. Agora, vamos para o serviço de criação de transações. Devemos refatorar a forma como o endereço de alteração é obtido nessa classe. Vamos adicionar a variável de endereço de alteração aqui. Seu valor será igual ao resultado da chamada do método de endereço de alteração fina com o endereço como parâmetro. Então, vamos criar esse método. Vamos primeiro substituir essas boas chamadas de método de endereço de alteração pela nova variável de endereço de alteração. Aqui, obteremos o tipo de endereço usando o Localizador de tipo de endereço para alterar. Então, vamos injetá-lo nessa classe. Agora, chamaremos o método find no localizador de alteração do tipo de endereço, passando o endereço como parâmetro. Em seguida, retornaremos uma chamada para o método de obter endereço de recebimento, passando o tipo de endereço obtido como parâmetro. Agora, vamos para a classe de configuração de endereço. Adicionaremos campos relacionados à criação da transação. Agora. O primeiro será o construtor de entradas de transações com essa nova classe como seu tipo. Vamos criar essa classe no pacote de serviços da API. Será uma interface. método será chamado de Build, retornará uma entrada de transação e Seu método será chamado de Build, retornará uma entrada de transação e terá um UTXO como parâmetro. Voltar para a configuração do endereço. Adicionaremos o campo de entrada mais o tamanho da saída aqui. Nós o usaremos mais tarde na aula de calculadora de poeira. Vamos também adicionar o campo de tamanho do ScriptSig aqui. Ele será usado na calculadora do tamanho da transação. Agora, vamos também adicionar o campo do signatário da transação. Vamos criar essa classe no pacote de serviços api dot. Será uma interface. Ele terá um método de sinal que terá os seguintes parâmetros. Ele também lançará uma IOException. Agora, na classe de configuração de endereço, vamos definir os novos campos na configuração do endereço do segmento. Adicionaremos um novo construtor de entrada de segmento como o construtor de entrada de transações. Vamos criar essa classe no pacote de serviços api dot. Ele implementará a interface do Builder de entrada de transação interface do Builder de entrada de e implementará o método de construção. Para implementá-lo, vamos copiar o código a seguir dentro do método build inputs na classe do criador da transação e colá-lo aqui. Vamos mudar esse parâmetro para um novo ArrayList. Armazenaremos essa entrada de transação nessa variável. Em seguida, chamaremos o método set witness, passando por uma nova testemunha com os mesmos argumentos que usamos no serviço de criadores de transações. Finalmente, retornamos a entrada da transação. Vamos copiar essas constantes e colá-las no construtor de entrada segue what. E vamos adicionar a anotação do serviço aqui. Voltar para a configuração do endereço. Adicionaremos 98 como tamanho de entrada mais saída, zero como tamanho do ScriptSig e um novo signatário de transações do Segway. Vamos criar essa classe no pacote de serviços api dot. Vamos implementar o método do signatário da transação. Vamos adicionar a anotação do serviço aqui. Vamos ao serviço de signatário da transação. Vamos copiar essa linha e colá-la aqui. Vamos substituir esse parâmetro pela variável de índice. E vamos substituir o valor UTXO pela variável de valor aqui. Nossa configuração de endereço está finalmente pronta. Agora vamos para a calculadora do tamanho da transação. Vamos usar o comando do IDE de código de limpeza para adicionar a palavra-chave final a cada campo dessa classe. Vamos injetar o localizador de configuração de endereço nessa classe. Vamos deletar esse código. Vamos redefinir a variável all inputs para mapear o fluxo de endereços de entrada passando uma referência ao método de tamanho de entrada. Vamos criar esse método. Ele retornará um duplo e tomará um endereço como parâmetro. Aqui retornará um código semelhante ao anterior que define o tamanho da entrada. Mas o parâmetro de tamanho do ScriptSig será obtido ao encontrar a configuração de endereço adequada. Usar o localizador de configuração de endereço gerará uma exceção se não encontrarmos a configuração do endereço. Se o encontrarmos, retiraremos o tamanho do ScriptSig. Em seguida, adicionaremos a sequência a ela. Finalmente, somaremos os resultados do tamanho da entrada usando o método de soma dupla. Se não encontrarmos nenhuma entrada, retornará zero como a soma. Agora, vamos deletar essas linhas. Como o tamanho da entrada. Chamaremos o método map no fluxo de endereços de saída e usaremos o método de tamanho de saída para retornar cada tamanho de saída. Aqui, retornaremos a soma do valor n, o comprimento da chave pub do script e o resultado do método script pub key size passando o endereço como parâmetro. Usar uma instrução if verificará se o endereço é um endereço definido usando o método Segway. Se for, retornamos a constante da chave pub do script. Se não for, lançaremos a seguinte exceção. Lembre-se de que não usaremos a configuração do endereço para calcular o tamanho da saída porque a configuração do endereço se refere apenas aos endereços que podemos aceitar em nossas carteiras. Como planejamos oferecer suporte a mais endereços de saída, então tomaremos como entradas teremos que lidar com a construção da saída sem usar a configuração do endereço. Finalmente, usamos o método reduzido para calcular a soma dos tamanhos das saídas. E existe o método or else para retornar zero sem saídas. Vamos deletar essa constante. Agora. Vamos para a calculadora de poeira. Vamos injetar o localizador de configuração de endereço nessa classe. Vamos adicionar o endereço como um segundo parâmetro a esse método de poeira. Vamos remover essa linha, criaremos a variável de entrada mais tamanho de saída. Usaremos o localizador de configuração de endereço para encontrar a configuração de endereço por endereço. Se uma configuração de endereço não for encontrada. Vamos lançar uma exceção. Se for, obtemos sua propriedade de entrada mais tamanho de saída e a armazenamos em uma variável. Finalmente, retornamos a fórmula para calcular se uma saída é poeira usando a variável que acabamos de definir. Vamos remover essa constante dessa classe. Agora, vamos refatorar o seletor de moedas de sorteio aleatório único adicionar o parâmetro de alteração de endereço a esses métodos. E passamos o endereço de alteração para a chamada do método dust. Vamos refatorar o serviço de criadores de transações. Agora, vamos excluir essas constantes. Vamos injetar uma lista de construtores de chaves do script pub nessa classe. Vamos criar essa classe no caminho de serviços de pontos da API. Será uma interface. Ele terá um método de correspondência que retornará um booleano e tomará como parâmetro e endereço. E ele terá um método de construção que retornará um script e terá um endereço como parâmetro. Vamos terminar de injetar esse campo nessa classe. Vamos também injetar o localizador de configuração de endereço nessa classe. Vamos adicionar o endereço de alteração a essas chamadas de método. Vamos remover esse código desse método, criaremos a variável de script e atribuiremos o resultado da seguinte transformação de fluxo a ela. Filtrará o fluxo do script pub key builders para encontrar aquele que corresponde à variável de endereço. Se não encontrarmos nenhum, lançamos uma exceção. Em seguida, chamamos o método build no script pub key builder encontrado passando o endereço como parâmetro. Finalmente, retornamos a saída da transação contendo o valor e a variável do script. Agora vamos remover esse método usado dessa classe. No método de entrada de compilação, vamos remover esse código. Agora, chamaremos o método de mapa no fluxo de UTXOs. Dentro dele passará o seguinte lambda, encontrará a configuração do endereço usando o endereço UTXO. Se não o encontrarmos, lançamos uma exceção. Em seguida, obtemos o construtor de entrada da transação da configuração do endereço e o chamamos de método derramado, passando o UTXO para ele. Finalmente, usamos o método collect para converter o fluxo resultante em um ArrayList. Vamos criar a classe construtora de scripts P2 WP k h no pacote de serviços api dot. Ele implementará a interface do script pub key Builder. Vamos implementar os métodos de interface. Vamos injetar o prefixo de endereço factory nessa classe. No método match retornará o resultado da chamada do matcher de endereços do método de teste Segway. No método build, primeiro definiremos a variável de prefixo para o prefixo de endereço factory. O resultado da chamada do método Get passará a constante Segway como seu parâmetro. Em seguida, retornamos o resultado da chamada do método de script P2 WP k h pois o parâmetro desse método passará o resultado da chamada do back 30 para decodificar para o método hexadecimal. Primeiro, vamos ao arquivo POM para atualizar a biblioteca Bitcoin Java para a versão 0.4, 0.4, que tem o melhor método 32 de que precisamos. Vamos passar o prefixo e o endereço para esse método. Agora, vamos para a classe de signatários da transação para obter mais refatoração. Vamos injetar o localizador de configuração de endereço nessa classe. Vamos deletar essa linha. Em seu lugar, chamará o mesmo método passando esses parâmetros para ele. Vamos criar esse método criar a variável do signatário da transação. Atribuiremos a ele o resultado da transformação a seguir. Usaremos o localizador de configuração de endereço para encontrar uma configuração de endereço por tipo de endereço que passará o tipo de endereço UTXO DTO para esse método. Mas primeiro, vamos adicionar o campo do tipo de endereço ao registro UTXO DTO. E vamos adicionar o tipo de endereço à instanciação UTXO DTO no construtor UTXO DTO. De volta ao serviço de signatários da transação, obterá o signatário da transação de configuração de endereço a partir da configuração do endereço do telefone. Finalmente, vamos chamar o método de assinatura dos signatários da transação, passando esses parâmetros para ele. Vamos adicionar uma cláusula throws a esse método para indicar que esse método pode gerar uma IOException. A refatoração está concluída. Agora vamos corrigir alguns testes, começando com o teste do seletor de moedas de sorteio aleatório único. Vamos adicionar a configuração do endereço ao método de configuração. Em seguida, vamos adicionar a variável da lista de configurações de endereço com o segmento Config dentro dela. Agora vamos instanciar um novo localizador de configuração de endereço, passando as configurações de endereço para ele. Agora vamos fazer esse teste. Ótimo, já passou. Agora, vamos corrigir o teste do serviço de criadores de transações. Como no teste anterior. Vamos instanciar uma configuração de endereço e criar uma variável de configuração de endereço e uma variável localizadora de configuração de endereço. Também vamos instanciar um prefixo de endereço passando a string de teste reg e o localizador de configuração de endereço para ele. Agora vamos criar a variável script pub key builders que atribuirá uma lista a ela com um novo construtor de scripts P2 WP k h dentro dela. Vamos fazer esse teste. Ótimo, já passou. Agora, vamos corrigir o teste da calculadora do tamanho da transação. Como nos testes anteriores, vamos instanciar uma configuração de endereço e criar uma variável de configuração de endereço e uma variável localizadora de configuração de endereço. Vamos mudar esses testes de caso. Colaremos os casos de teste que você pode encontrar na página Projeto e Recursos. Vamos importar o método das cópias finais. Esses casos de teste são iguais aos anteriores, mas desta vez têm endereços reais, pois agora são importantes para a lógica da calculadora do tamanho da transação. Vamos fazer esse teste. Ótimo, já passou. Agora, vamos para a aula de teste de GUI. Vamos adicionar a constante de prefixo do segmento de rede principal a essa chamada de método. E vamos adicionar a constante de prefixo de endereço reg test P2 WP k h como um parâmetro para essa chamada de método. Agora eu recomendo que você execute todos os testes do aplicativo. Todos eles devem passar. 63. Endereços de Segwit aninhados: Nesta apresentação, falaremos sobre endereços de segmentos aninhados. Então, o que é uma sequência aninhada? Qual endereço? Os endereços de segmentos aninhados também são conhecidos como segmento rap P2, SSH dash p2, WPA e WPA2. E endereços SSH P2. O último nome descreve melhor o que são e endereço que codifica um script hash de pagamento para testemunhar a chave pub. Dentro de um script de hash pago por script. A maioria das carteiras modernas suporta esses endereços. Sua principal vantagem é que eles permitem que carteiras mais antigas, que geralmente suportam endereços de hash pagos por script, mas não oferecem suporte a endereços de segmentos nativos , enviem bitcoins para elas. Portanto, os proprietários de endereços de segmentos aninhados podem se beneficiar de algumas vantagens das transações da Segway, como taxas de transação mais baratas e recebimento de fundos de carteiras antigas. Então, por que a necessidade de seguir endereços nativos? Você pode perguntar. O motivo é que os seguintes endereços nativos tornam as transações ainda menores do que os endereços de segmentos aninhados. Os endereços de segmentos aninhados foram disponibilizados em 2017, após a atualização As regras para gerar endereços de segmentos aninhados foram definidas no BIP 141. Escolhemos endereços de segmentos aninhados como endereços de recebimento secundários de nossas carteiras para permitir o recebimento de Bitcoins de carteiras antigas. Então, para entender os endereços de segmentos aninhados, vamos primeiro entender os endereços SSH P2. P2 SSH é um acrônimo para hash de pagamento por script. endereços SSH P2 são exatamente isso. Eles codificam um hash gerado a partir de um script Bitcoin. Vamos ver o processo para gerar um toucado P2 SH. Começamos com um script de resgate serializado hexadecimal. script I'll Redeem geralmente é um script Bitcoin com várias assinaturas, mas pode ser qualquer outro script de Bitcoin. Usamos o algoritmo hash 160 para gerar um hash de script a partir do script de resgate serializado. Em seguida, combinamos o hash do script com um prefixo e aplicamos o algoritmo de codificação base 58 para produzir um endereço P2 SH por meio da decodificação da base 58 Podemos obter o hash do script de volta de um P 2 endereços SSH, uma sequência aninhada. Qual endereço é simplesmente um script SSH P2 codificado em base 58 era um script de resgate é um script de segmento. Agora vamos aprender como criar uma chave pub de script P2 SH. Lembre-se de que uma chave de script pub faz parte da saída de uma transação e é a forma como o endereço de recebimento está presente em uma transação. Então, começando com um endereço SSH P2, primeiro baseamos 58 decodificado para obter um hash de script. Em seguida, construímos um script que consiste em um opcode OP hash 160, o hash do script e um opcode igual ao OP. Essa é a chave pub do script P2 SH. Para enviar fundos para um endereço SSH P2, você deve colocar esse script na saída da transação junto com o valor de qualquer carteira, mas pode enviar bitcoins para um endereço SSH P2, pode enviar bitcoins para uma sequência aninhada. Qual endereço? Agora, vamos ver como criar uma entrada de transação de segue aninhada, começando com a chave pub válida para um endereço UTXO. Em seguida, aplicamos o algoritmo hash 160 para obter um hash de chave pub. Combinando o hash com um prefixo zero, obtemos um script de segmento. Este é o script de resgate, que será adicionado à entrada da transação posteriormente. Agora assinará uma transação. Para fazer isso, primeiro produzimos um hash de assinatura a partir de uma transação interna usando o mesmo algoritmo de hash de assinatura que usamos para assinar uma transação seguinte. Em seguida, combinamos o hash da assinatura com uma chave privada válida para gerar a assinatura usando o ECDSA. Em seguida, mostramos a entrada da transação de sinal, o índice de saída do ID da transação e, em seguida, os campos de sequência funcionam da mesma forma que outros tipos de transação. Adicionamos o script de resgate no campo ScriptSig e adicionamos a assinatura e a chave pub ao campo de testemunha. Observe que, diferentemente das entradas nativas do seg, o ScriptSig não está vazio. Nesse caso. O campo testemunha das entradas de segmentos aninhados tem os mesmos elementos das entradas de segmentos nativos. Agora vamos ver como um script de segmento aninhado é executado durante a validação da transação pelos nós. A validação de segmentos aninhados requer a validação de dois scripts combinados. Dada uma chave pub de script SSH P2 de algum UTXO e o ScriptSig correspondente de uma entrada de transação. Ambos os scripts são combinados, formando o primeiro script combinado. O script de resgate é passado para o script combinado como um único elemento serializado. Nessa primeira validação, da esquerda para a direita, cada elemento no script combinado é avaliado, começando com o script de resgate, que é adicionado à pilha de execução. Em seguida, aplique o hash 160 do OP e aplique o hash 160 e o script de resgate, transformando-o em um hash de script. Em seguida, o hash do script e o script combinado são adicionados à pilha de execução. Finalmente, o opcode OP igual compara os dois scripts Hashes e retorna true se eles forem iguais. Se não forem iguais, a transação será considerada inválida. Em seguida, um segundo roteiro é formado pela combinação da testemunha e do ScriptSig. Desta vez, o script de resgate no ScriptSig é avaliado em sua totalidade, assim como nas seguintes avaliações de scripts nativos. E, como segue a avaliação do script nativo, o dígito zero inicial no ScriptSig aciona uma regra especial que o converte no script presente no script combinado. De agora em diante, o script combinado é executado da mesma forma que o script combinado das transações nativas do segmento. A partir do script combinado, as chaves de assinatura e pub são adicionadas a uma pilha de execução. Em seguida, o opcode OPT up duplica a chave pub na pilha de execução. Up hash 160 hashes, a última chave de pub adicionada à pilha. Em seguida, a partir do script combinado, o hash da chave pub é adicionado à pilha. opcode Up equal verify remove os dois últimos elementos da pilha de execução e os compara. Se forem iguais, o script continua sendo executado. Finalmente, o object sig opcode verifica se a assinatura é válida para a chave pub restante na pilha. Se for válido, ele retornará verdadeiro para a pilha de execução. Depois que todos os elementos do script forem adicionados à pilha de execução, a entrada da transação será considerada válida. Se o último elemento adicionado for verdadeiro, esse processo deverá ser repetido para cada entrada da transação, todas as suas entradas devem ser válidas para que uma transação seja considerada válida. Apenas como um lembrete visual, vamos analisar de onde cada elemento da chave pub do script, ScriptSig e da testemunha vieram durante a construção da transação. O hash do script presente na chave pub do script veio da base 58, decodificando o endereço do UTXO que está sendo gasto. O hash da chave pub e o ScriptSig vieram do hash 160 de uma chave pública válida. A mesma chave pública está presente na testemunha. A assinatura da testemunha veio aplicando o algoritmo ECDSA, que precisa de uma chave privada válida. A chave pública e a testemunha vieram da chave pública derivada da chave privada mencionada. Agora, vamos ver alguns parâmetros importantes para derivar endereços de segmentos aninhados. Na rede principal do Bitcoin, o prefixo necessário para derivar endereços SSH P2 é C4. Depois que a base 58 codifica um vestido com esse prefixo, comece com o dígito três na rede de teste do Bitcoin e no teste de registro, o prefixo necessário para derivar os endereços SSH P2 é 05. Após a base 58, os endereços de codificação com esse prefixo começam com o dígito para. O caminho de derivação usado para derivar endereços de segmentos aninhados começa com o caminho reforçado 49 para carteiras, seguindo as diretrizes do BIP 49. 64. 62 Nested Segwit parte 3 skillshare 2: Neste vídeo, implementaremos o endereço aninhado que seria em nossa carteira adicionaremos como outra opção para receber Bitcoins em nossa carteira. Vamos primeiro preparar nosso aplicativo para adicionar alguns testes relacionados ao novo tipo de endereço. Então, vamos até o Node, obter um novo cliente de endereço. Precisamos tornar nosso aplicativo capaz de chamar nosso node para gerar endereços SSH P2. Assim, podemos criar testes para enviar Bitcoin para esses endereços. Então, vamos usar a opção de alteração da assinatura IDE para adicionar um novo parâmetro a esse método. O novo parâmetro será uma string, seu nome será do tipo endereçado e seu valor padrão será a string back 32. Vamos adicionar uma string vazia a essa chamada de método. Esse parâmetro é usado se quisermos adicionar um rótulo ao nosso novo endereço, já que não precisaremos dele, vamos defini-lo como uma string vazia. E vamos adicionar o tipo de endereço como seu último parâmetro. Ok, agora podemos pedir ao nosso nó que crie endereços P2 SH se o refator do IDE funcionasse. Agora, as chamadas atuais para esse método terão a string de volta 32, pois são menos parâmetros. Agora, vamos fazer o teste de envio de Bitcoin. Vamos mover esse método para a classe de teste de GUI. Vamos protegê-lo. Em vez de usar a palavra-chave super aqui, vamos usar isso. Agora, vamos para a aula de teste de recebimento de Bitcoin. Vamos copiar todo o código dessa classe. No pacote de teste da GUI. Vamos criar uma nova classe de teste chamada receive Bitcoin nested segue test. E vamos colar o conteúdo nessa aula. Vamos fazer alguns ajustes nessa classe. Vamos mudar o nome da classe para receber o teste Bitcoin Nested Segue. Agora vamos mudar os nomes dos métodos de teste. Vamos adicionar um endereço de segmento aninhado aqui. Vamos fazer o mesmo com todos os outros métodos de teste indicando em seus nomes que receberão Bitcoins em aninhados seguindo quais endereços? Agora, vamos ajustar esse primeiro teste. Vamos ajustar o nome da carteira. Em seguida, vamos modificar o parâmetro de pesquisa aqui. Assim, a variável de endereço é atribuída ao valor do campo em que o segmento aninhado é endereçado. Aqui, em vez de usar o método address is valid, usaremos o endereço do segmento aninhado método válido que criaremos. Vamos corrigir essa formatação de código. Agora, vamos criar o método aninhado segue qual endereço é válido na classe de teste de GUI Usaremos o método válido de endereços como base. Então, vamos duplicá-lo. Vamos corrigir seu nome. Agora. Vamos mudar o tipo de endereço aqui para a constante segway aninhada. E vamos mudar o caminho de derivação aqui para começar com 49. Vamos criar essa constante no tipo de endereço enum. Também vamos criar a sequência aninhada para alterar a constante aqui. Aqui, vamos alterar o prefixo do endereço gerado para o prefixo do endereço SH da rede de teste P2. E em vez de usar o gerador de endereços de segmentos, usará o gerador de endereços de segmentos aninhados. Vamos adicionar esse campo a essa classe. Usaremos a anotação automática com fio para injetá-la nessa classe. Vamos criar essa classe no pacote de serviços api dot. Vou implementá-lo mais tarde. De volta à aula de teste recebida de Bitcoin nested segue. Vamos fazer os mesmos ajustes nos outros métodos de teste. Agora vamos para a classe de configuração de endereço. Vamos duplicar esse bean usá-lo como base para criar a configuração segway aninhada. Vamos alterar esses parâmetros para segmento aninhado e mudar de sequência aninhada. Vamos mudar esse método para chamar a configuração de dois segmentos aninhados. Agora vamos mudar os parâmetros de configuração do endereço. O primeiro parâmetro será o tipo de endereço do conjunto aninhado. No segundo argumento, vamos mudar as chaves do mapa para segmento aninhado e alteração de segmento aninhado. E os dois caminhos de derivação. Começaremos com 49. Usaremos o gerador de endereços de segmentos aninhados como gerador de endereços. Vamos fazer com que ele implemente a interface do gerador de endereços. Vamos adicionar o método de interface. Agora, vamos definir cada prefixo de endereço do ambiente. O principal ambiente de rede. Usaremos a constante de prefixo de endereço SSH P2 da rede principal. Os ambientes de teste net e reg test. Usaremos a constante de prefixo de endereço SH da rede de teste P2. Vamos mudar o prefixo ki estendido para a constante de prefixo do segmento aninhado principal. O combinador de endereços será o predicado as nested segue. Vamos criar esse campo no combinador de endereços. Será semelhante ao predicado do segmento acima. Mas o combinador retornará verdadeiro se o endereço começar com três ou dois. Agora, vamos importá-lo aqui. Vamos usar a constante SSH P2 aqui. Vamos usar o método de endereço de segmento aninhado do script como analisador de scripts. Usará o construtor de entrada de segmentos aninhados como o construtor de entrada da transação. Vamos criar essa classe no pacote de serviços api dot. Vamos adicionar o método de interface. Como a entrada mais o tamanho da saída. Definiremos 180 como o tamanho 23 do ScriptSig. E, como signatário da transação, usará o signatário de transações aninhado do Segway. Vamos criar essa classe no pacote de serviços api dot. E vamos adicionar o método de interface. Nossa configuração de sequência aninhada está pronta. Agora, precisamos implementar o gerador de endereços de segmentos aninhados, construtor de entrada e o signatário da transação. Vamos começar com o gerador de endereços seg would aninhado. Primeiro, vamos adicionar um teste para esse serviço no pacote de teste api dot services. Isso estenderá a classe de especificação. Vamos adicionar o seguinte método de configuração. Vamos adicionar a chamada de método do provedor de anúncios de segurança. Vamos adicionar o gerador de endereços de segmentos aninhados como um campo nessa classe. E vamos instanciá-lo aqui. Agora, vamos ao teste do gerador de endereços do segmento. Vamos copiar esse teste e colá-lo aqui. Vamos usá-lo como base para nosso novo teste. Em vez de usar o gerador de endereços de segmentos, usará o gerador de endereços aninhado seg would aqui. Vamos mudar o prefixo para essa constante. Vamos remover esses casos de teste e colar os válidos para endereços de segmentos aninhados. Eles estão disponíveis na página Projeto e Recursos. Voltar ao gerador de endereços de segmentos aninhados. Eu erroneamente criei essa classe como uma classe bacana. Vamos usar esse recurso do IDE para converter essa classe em Java. Vamos remover esse código. Vamos adicionar a anotação do serviço a essa classe. Aqui, converteremos a chave secundária estendida em uma chave pública. Em seguida, retornaremos o endereço do segmento aninhado da chamada do método de chave pública compactada no objeto get que passa a variável de prefixo para ele. Vamos renomear esse parâmetro para chave estendida. Agora vamos fazer esse teste. Ótimo, já passou. Agora vamos implementar o construtor de entrada aninhado segue qual. Vamos adicionar a anotação do serviço a essa classe. Vamos copiar o método de construção no construtor de entrada de segmento e usá-lo como base para nosso novo método de construção. Vamos também colar essas duas constantes na classe do construtor de entrada segue aninhado. Agora vamos adicionar a constante segwayed aninhada fictícia do ScriptSig no script ArrayList. Vamos criar essa constante. Será igual à sequência zero repetida 44 vezes. Aqui, devemos passar essa constante dentro de uma lista de métodos, na verdade. Agora, vamos implementar o signatário de transações aninhado do Segway. Vamos adicionar a anotação do serviço aqui. Vamos copiar o método de assinatura no signatário de transações do Segway e usá-lo como base para nosso novo método de assinatura. Aqui, em vez de usar o método de assinatura dos signatários da ECDSA da transação, usaremos o método sine nested segue do signatário ECDSA da transação P2 SH. Vamos adicionar o script de resgate como o quarto argumento nesse método. Vamos remover esse último argumento. Vamos criar a variável de script de resgate. Essa variável será igual à chamada do método de script P2 WP k h. Como parâmetro, passará o hash 160 da chave pública compactada correspondente da chave privada recebida. O método sign nested segue se encarregará de adicionar o script de resgate ao campo de testemunha e a chave pública e a assinatura ao campo ScriptSig. Ok, a configuração de segue aninhada está finalmente pronta. Agora vamos adicionar o novo campo de segmento aninhado à guia Receber FXML. Primeiro, vamos alterar o endereço de recebimento e o texto da etiqueta para o endereço do segmento. Agora, vamos duplicar todo esse código e alterar o texto desse rótulo para o endereço aninhado que seg would. Vamos também mudar essa identificação ética dois endereços de recebimento aninhados. Vamos mover esse campo para a segunda linha do contêiner. Para fazer isso, vamos adicionar o atributo de índice de linha do painel de grade a esse campo e defini-lo como um. Vamos fazer o mesmo com esse rótulo. Agora, vamos para o controlador da guia Receber. Vamos duplicar esse bloco if nesta instrução if para verificar se a alteração no endereço é um endereço de segmento aninhado. Nesse caso, definiremos a sequência aninhada conteúdo do endereço de recebimento TextField como a alteração no endereço. Então, vamos adicionar esse campo a essa classe. E vamos adicionar uma anotação FXML a ela. Vamos também adicionar uma declaração de devolução aqui. Agora, vamos fazer alguns testes. Vamos executar nosso node Bitcoin. E vamos fazer esse teste. Ótimo, os testes foram aprovados. No próximo vídeo, terminaremos de adicionar o suporte de segmentos aninhados à nossa carteira. Veja, sim. 65. 63 Nested Segwit parte 4 skillshare 2: Neste vídeo, implementaremos a capacidade de enviar Bitcoin para endereços aninhados seguindo quais endereços. Começaremos criando testes para esse recurso. Então, no pacote de teste da GUI, vamos criar a classe de teste send Bitcoin nested segue. Isso estenderá a classe de teste de GUI. Vamos copiar alguns testes do teste de envio de Bitcoin. Eles servirão como base para nossos novos testes. Vamos copiar esse código e colá-lo aqui. Agora, vamos copiar esse primeiro teste depois colá-lo em nossa nova classe. Vamos fazer o mesmo com esse teste. Vamos fazer o mesmo com o teste do crepúsculo. Agora, vamos ajustar os novos testes. Vamos mudar esse nome de teste para enviar Bitcoin com entradas de segmentos aninhados e seguir quais saídas. Vamos mudar o nome da carteira para o meu teste aos 23 anos. E vamos mudar esse parâmetro de chamada de dois segmentos aninhados do método de pesquisa . Aqui, vamos mudar esse parâmetro para o segmento de hífen SSH P2. Esse parâmetro fará com que o nó retorne um endereço de segmento aninhado para nós, para que possamos enviar Bitcoin para ele. Agora, vamos ajustar os casos de teste. Eu calculei anteriormente as taxas totais esperadas para esses casos. Eles diferem das taxas de transação com as seguintes entradas e saídas nativas porque seus tamanhos de transação são diferentes. Vamos fazer ajustes semelhantes para o próximo teste. Agora, vamos criar o construtor de scripts P2 SH. Ele implementará a interface do script pub key Builder. Vamos implementar seus métodos. No método match, retornará essas chamadas aninhadas do método de teste segue passando o endereço como seu parâmetro. Retornaremos a chamada do método de script P2 SH no método build, pois seu parâmetro passará o endereço decodificado de base 58 desta forma. Vamos adicionar a anotação do serviço a essa classe. Agora, vamos fazer o teste da calculadora do tamanho da transação. Vamos duplicar esse método. Vamos usá-lo como base para criar um teste para verificar o cálculo do tamanho das transações usando entradas e saídas de segmentos aninhados. Então, vamos mudar o nome do método para refletir isso. Vamos remover esses casos de teste e colar os casos de teste disponíveis na página Projeto e Recursos. Agora, no método de configuração, vamos adicionar a configuração aninhada que seg would na lista de configuração de endereços. Agora vamos para a calculadora do tamanho da transação no método script pub key size. Vamos adicionar a seguinte declaração if para testar se o endereço recebido é uma sequência aninhada. Qual endereço? Nesse caso, retornará o script pub key aninhado segwayed constant. Vamos criar essa constante. Seu valor será 23. Agora vamos fazer esse teste. Ótimo, já passou. Agora vamos executar nosso node. E vamos executar o teste send Bitcoin Nested Segue. Ótimo, os testes foram aprovados. Agora, vamos brincar um pouco com nossa carteira no ambiente de teste da rede. Para fazer isso, vamos mudar essa variável no arquivo bitcoin.com para testar a rede. E vamos reiniciar nosso node. Vamos esperar que ele seja sincronizado. Dependendo de quão atualizada sua nota está. Isso pode levar de minutos a horas. Ok, eu pesei a soma de horas. E, finalmente, minha sincronização de avisos. Vamos executar nosso aplicativo. Vamos criar uma carteira. Primeiro. Vamos receber alguns Bitcoins em nosso endereço de segmento aninhado. Para fazer isso, vamos usar essa torneira. Ok, a transação apareceu na minha carteira. Vamos esperar um pouco para que isso confirme. Ok. Agora, a transação tem uma conformação. Agora, vamos enviar alguns fundos para o endereço da torneira. Curiosamente, essa transação não precisou ser alterada e acabamos sem fundos pois gastamos nossa única contribuição. Vamos verificar a última transação no explorador de blocos. Vamos esperar um pouco para que isso confirme. Esperei alguns minutos e agora tem três conformações. O Block Explorer mostra o mesmo. Ótimo. Tudo está funcionando conforme o esperado. Vamos fazer mais um teste. Vamos receber mais Satoshi primeiro em nosso endereço de segmento depois em nosso endereço de conjunto aninhado. Ok, agora que ambas as transações foram confirmadas, vamos enviar alguns fundos para um endereço de segmento aninhado a partir desta página. Agora, a transação gerou a mudança. Como a enviamos para um endereço de segmento aninhado, a alteração gerada também foi enviada para uma sequência aninhada. Qual endereço? Depois de algum tempo, a transação foi confirmada. Ótimo. 66. 64 habilidade: legado 2: Neste vídeo, implementaremos em nossa carteira a capacidade de enviar bitcoins para endereços P2 pKa H, também conhecidos como endereços legados. P2, pk h foi o tipo de roupa mais usado antes do aumento da popularidade dos endereços do segmento nos últimos anos. Hoje em dia, ainda é muito popular. Portanto, é importante que nossa carteira tenha a capacidade de enviar bitcoins para esses endereços. Vamos começar refatorando a forma como nossa carteira cria chaves de script pub para que seja mais fácil adicionar suporte para o envio bitcoins para outros tipos de endereço no futuro. Para isso, vamos criar o registro de configuração do script no pacote de domínios. Semelhante à configuração de endereço, essa classe conterá parâmetros importantes para criar transações com tipos específicos de chave pub de script. Então, vamos adicionar os seguintes campos a ele. O construtor da chave pub do script, o tamanho da chave pub e o predicado do combinador de endereços, que ajudarão a identificar o tipo de configuração do script por endereço. Agora vamos criar a classe de configuração do script no pacote api dot config. Novamente, semelhante à classe de configuração de endereço. Essa classe será responsável por instanciar e definir todas as chaves de script pub quais nossa carteira possa enviar Bitcoin. Vamos adicionar a anotação de configuração a ela. Agora, vamos criar o seguinte método anotado em Bean. Ele retornará uma configuração de script e definirá a configuração P2 WP. Seu construtor de chaves script pub será o construtor de scripts P2 WP k h. O tamanho do script será igual a 22 e seu combinador de endereços será o segmento Lambda. Vamos ao construtor de scripts P2 WP k h. Para facilitar a instanciação, ele removerá o prefixo de endereço factory do serviço. Construirá a variável de prefixo analisando o prefixo da variável de endereço usando o método de prefixo parse. Vamos criar esse método. Primeiro, verificaremos se o endereço começa com a constante de prefixo de endereço net P2 WP k h de teste. Nesse caso, retornaremos essa constante. Em seguida, faremos a mesma declaração, mas usando a constante de prefixo de endereço reg test P2 WP k-th. Por fim, retornaremos a constante principal do prefixo de endereço net P2 WP k h se o código for executado até esse ponto. Agora vamos criar o bean para a configuração do script P2 SH. Ele usará o construtor de scripts P2 SH. Seu tamanho será 23 e seu combinador de endereços será o segmento aninhado lambda. Agora vamos criar a configuração do script para encontrar sua classe no pacote de serviços api dot. Como o próprio nome sugere, esse serviço será responsável por encontrar a configuração de script apropriada para outros serviços. Vamos adicionar a anotação do serviço a ela. Agora, vamos injetar a lista de configurações de script nessa classe. Spring Boot magic injetará todos os beans de configuração de script nessa lista após o início do aplicativo. Agora, vamos criar o método find by address. Ele retornará uma configuração de script e tomará um endereço como parâmetro, retornará a seguinte transformação de fluxo aqui filtrará o script can think stream usando o combinador de endereços de cada script configuração. Usaremos para encontrar o primeiro método para filtrar a primeira configuração do script. Se não encontrarmos nenhum, usaremos o método de lançamento de URLs para gerar uma exceção. Agora, vamos até o serviço de criadores de transações e usaremos o localizador de configuração de scripts para refatorar essa classe. Primeiro, vamos remover a lista de construtores de chaves do script pub dessa classe, pois não a usaremos. E vamos injetar o script que pode pensar em Finder nessa classe. Agora, no método de saída de compilação, vamos remover esse código. Criará essa variável de script usando o localizador de configuração do script, find by address method. Em seguida, chamaremos o script pub key builder de método build no resultado. Agora, vamos refatorar a calculadora do tamanho da transação. Vamos injetar o script config Finder nessa classe. Agora, vamos remover o código no método script pub key size. Em seu lugar, usaremos o script config Finder para encontrar uma configuração de script por endereço e retornar o tamanho da chave pub do script. Vamos remover essas importações e constantes, pois não as usaremos. Agora, vamos para a interface do script pub key Builder. Vamos remover o método match dele e de todas as suas implementações, já que não o usaremos mais. A refatoração está concluída. Agora, antes de adicionar o P2 pKa H Script Config vamos criar o teste send Bitcoin legacy no pacote de teste da GUI. Isso estenderá a classe de teste de GUI. Usaremos essa classe para verificar se nossa carteira está enviando corretamente uma transação para um endereço legado. Vamos copiar o código a seguir do teste de envio de Bitcoin e colá-lo aqui. Vamos usá-lo como base para nosso novo teste. Vamos mudar seu nome para se enviar Bitcoin com entradas de segmento, saída legada e a configuração mudaria. Observe que, embora possamos enviar fundos para um endereço antigo, não poderemos recebê-los um endereço antigo pertencente à nossa carteira. Portanto, usaremos os seguintes endereços nativos para receber alterações nessas transações. E esse nome de teste reflete isso. Vamos mudar o nome da carteira para o meu teste aos 26 anos. Vamos mudar esse parâmetro para legado para que possamos criar um endereço legado qual usaremos para enviar bitcoins. Também vamos alterar os casos de teste usando os seguintes valores calculados anteriormente. Esses valores diferem de outras transações porque as chaves de pub de script P2, pKa e H são um pouco maiores do que as seguintes chaves de pub de script nativo, que afetam o tamanho da transação e o phi. Agora vamos para a classe de configuração do script. Vamos adicionar a palavra-chave pública aqui. Vamos criar o bean de configuração P2 pKa H pois seu construtor de chaves de script pub definirá um novo construtor de scripts p2 pk H, que será criado posteriormente. O tamanho da chave do script pub será 25 e está resolvido. Matcher serão esses Lambda legados que criaremos mais tarde. Vamos criar o construtor de scripts P2 pKa H no pacote de serviços api dot. Vamos implementar o método de interface. No método build, retornará a chamada do método de script P para P k h, pois seu parâmetro passará o endereço decodificado hexadecimal base 58 usando a decodificação base 58 com o método de soma de verificação para hexadecimal. Agora, vamos para a classe de métrica de endereço. Vamos duplicar esse campo. Vamos usá-lo como base para esses lambda legados. Aqui, alteraremos esses parâmetros para um, M e N. Um é o prefixo do legado que aparece na rede principal. M e n são os prefixos válidos para os outros ambientes. Vamos importar esses lambda antigos aqui. Ok, agora nossa carteira pode enviar Bitcoin para endereços antigos. Agora, vamos ajustar alguns testes. Vamos fazer o teste da calculadora do tamanho da transação. No método de configuração, vamos instanciar o localizador de configuração do script. Vamos passar uma lista de configurações de script para ele. Receberá as configurações do script da classe de configuração do script. Então, vamos instanciá-lo aqui. Agora, vamos adicionar o script em forma de figs aqui. Agora, vamos duplicar esse teste. Vamos renomeá-lo para calcular o tamanho da transação para P2 WP k-th entradas de transação e p2 pk cada saída de transação. Esse nome de teste descreve bem o cenário que será testado. Vamos remover esses casos de teste. Colará esses casos de teste aqui, que estão disponíveis na página Projeto e Recursos. Vamos corrigir a formatação desses casos de teste. Vamos fazer esse teste. Grau. Os testes foram aprovados. Agora, vamos corrigir o teste do serviço de criadores de transações. Vamos copiar esse código e colá-lo aqui. Vamos remover a fábrica de prefixos de endereço e os criadores de chaves do script pub. E vamos corrigir a instanciação do serviço aqui. Vamos fazer esse teste. Ótimo, já passou. Agora, vamos corrigir o teste do seletor de moedas de sorteio único aleatório Será necessário esse código novamente. Então, vamos copiá-lo e colá-lo aqui. Certifique-se de que o seletor de moedas de sorteio aleatório único esteja instanciado corretamente. No meu caso, o ID já fez isso. Vamos fazer esse teste. Grau. O teste foi aprovado. Agora, vamos executar nosso node. Antes disso, verifique se o arquivo bitcoin.com tem o ambiente de teste reg configurado. Agora vamos fazer o teste de envio de Bitcoin Legacy. Ótimo, o teste foi aprovado. 67. 65 Salvar skillshare da carteira 2: Nos vídeos anteriores, implementamos um aplicativo totalmente funcional que você já pode usar para criar carteiras e enviar e receber Bitcoins. Mas se fecharmos o aplicativo, perderemos todas as informações sobre as carteiras que criamos neste vídeo e, no próximo, começaremos a implementar a capacidade salvar e carregar carteiras em nosso aplicativo. Para armazenar os dados do nosso aplicativo, usaremos o banco de dados H SQL. Sql é um banco de dados SQL implementado em Java. Escolhemos o H SQL pelos seguintes motivos. Primeiro, é um banco de dados leve. Em segundo lugar, é compatível e fácil de usar com a biblioteca Spring Boot Data JPA. Finalmente, ele pode ser facilmente criptografado, como mostraremos neste vídeo. Vamos acessar o arquivo XML do poem dot para adicionar as dependências do Spring Boot Data JPA e do H SQL DB. Clique nesse botão para carregar as novas dependências. Agora vamos para o arquivo de propriedades de pontos do aplicativo. Definiremos algumas configurações necessárias para o banco de dados. Essa configuração determina que, a cada modificação que fizermos em nossas classes de entidades, atualizaremos nosso banco de dados adequadamente. No Spring Boot, classes anotadas por entidades definiram estruturas de tabelas, como veremos em breve. Vamos duplicar essa linha para usar como base para as outras configurações. Temos que definir a classe do driver chamada config para a seguinte classe. O nome de usuário e a senha. Você pode nos definir o que quiser. Como estou usando apenas para testes, definirei esses campos como Y0 W por enquanto. Mas lembre-se de alterar esses valores para cadeias de caracteres mais seguras antes de usar essa carteira na rede principal. Agora, vamos definir a URL do banco de dados. Como usaremos um banco de dados baseado em arquivos, teremos que definir essa configuração JDBC cólon H SQL DB dois pontos, o caminho em que queremos que os arquivos do banco de dados residam. No meu caso, o caminho começaremos com a pasta BYOD W localizada no assento dr. Raiz. Dentro dessa pasta, quero criar pastas específicas para cada ambiente de rede Bitcoin. Para fazer isso, vou me referir à variável de ambiente Bitcoin neste arquivo de propriedades de pontos do aplicativo, colocando-a entre colchetes e após um sinal de $1 como este. Por fim, usarei a subpasta de dados dentro dessa pasta e nomearei os arquivos do banco de dados como meu banco de dados. E terminamos a linha com ponto e vírgula. Agora, dentro do pacote BYOD W, vamos criar o pacote do banco de dados. Dentro desse pacote, vamos criar o pacote de entidades. E vamos criar a classe de entidade da carteira dentro dela. Nesta classe, modelaremos os registros na tabela do banco de dados da carteira. Para fazer isso, vamos adicionar a anotação da entidade a ela. E a anotação da tabela com seu parâmetro de nome igual ao Wallet. Agora, vamos adicionar alguns campos a essa classe. Em cada campo desta classe, modelaremos uma coluna da tabela da carteira. Nosso objetivo é salvar apenas os campos necessários para obter os mesmos dados da carteira após carregá-la. Então, vamos adicionar o campo ID. Adicionará esse campo para seguir a boa prática de sempre adicionar um identificador de incremento automático a uma tabela de banco de dados relacional. Para fazer isso, vamos adicionar duas anotações a esse campo. A primeira é a anotação de ID, a segunda é a anotação do valor gerado com o seguinte parâmetro. Vamos também adicionar uma anotação de coluna com ID como parâmetro de nome. A anotação da coluna determinará o nome correspondente da coluna vinculada a esse campo na tabela da carteira. Seguiremos o estilo de maiúsculas para os parâmetros do nome da coluna que todas as letras ou minúsculas e sublinhados separam as palavras. Agora vamos criar o campo do nome. Vamos também adicionar a anotação da coluna a esse campo. Além do parâmetro name, vamos também adicionar o parâmetro exclusivo é igual verdadeiro e o parâmetro anulável igual a falso. Esses parâmetros adicionarão as restrições exclusivas e não anuláveis na tabela dessa coluna. Portanto, o aplicativo gerará um erro se você tentar criar um registro sem um nome na tabela da carteira. Vamos também criar o campo de semente mnemônico com a seguinte anotação. O parâmetro length limitará o tamanho máximo desse campo a 500 caracteres. Vamos também adicionar o parâmetro anulável igual a falso a essa anotação. Agora, vamos adicionar o campo de número de endereços gerados com a anotação da coluna seguindo o estilo snake case. O último campo será criado em. Vamos adicionar a anotação da data criada para indicar que esse campo usará a data atual para registrar seus valores. Agora, vamos criar alguns construtores. Primeiro, um construtor vazio , necessário para o Spring Boot instanciar essa classe corretamente. Em seguida, vamos criar um construtor com todos os campos dessa classe, exceto o id. Vamos criar getters para os mesmos campos. Nossa entidade de carteira está pronta. Agora, dentro do pacote do banco de dados, vamos criar o pacote de repositórios. E vamos criar a interface do repositório de carteiras dentro dela. A interface do repositório da carteira será responsável por interagir com o banco de dados recuperando e salvando dados na tabela da carteira. Para conseguir isso, ele estenderá a interface do repositório JPA adicionará parâmetros de tipo a essa extensão. O primeiro teste será a entidade que gerenciaremos esse repositório. Nesse caso, será a classe de entidade da carteira. O segundo deve ser o tipo de ID da entidade. Portanto, será a classe longa. Com essa interface simples, já temos acesso a operações comuns de banco de dados para a tabela da carteira, como inserir registros e localizá-los por ID. Tudo isso é trazido automaticamente para você pela biblioteca Spring Boot Data JPA. Agora vamos criar o pacote de serviços no pacote do banco de dados. Dentro dela, vamos criar a classe de serviço de carteira economizada. Essa classe será responsável por salvar a carteira após sua criação. Vamos adicionar a anotação do serviço a ela. Vamos injetar o repositório da carteira nessa classe. Vamos fazer o mesmo com o campo de número inicial de endereços gerados. Agora, vamos criar o método de salvar carteira. Ele usará um objeto de carteira como parâmetro. Para implementar. Primeiro, ele instanciará um novo objeto de entidade de carteira com os seguintes parâmetros da carteira. Em seguida, chamaremos o método de salvamento do repositório da carteira, passando a entidade da carteira como seu parâmetro. *****. Eu misturei a ordem dos parâmetros aqui. Vamos consertar isso. E vamos adicionar a anotação do qualificador para a injeção correta desse campo aqui. É isso mesmo. Com esse código simples, conseguimos salvar facilmente as informações da carteira no banco de dados SQL. Agora vamos criar o pacote de ouvintes no pacote do banco de dados. E vamos criar uma classe chamada save wallet listener. Dentro dela. Essa aula servirá como ouvinte para o evento de carteira criado. Para que, após o aplicativo criar uma carteira, ele seja responsável por chamar o serviço de salvar carteira para salvar a carteira. Então, vamos adicionar a anotação do componente a ela. Ele implementará o ouvinte do aplicativo com o evento de carteira criado como parâmetro de tipo. Vamos implementar seu método. Aqui, chamaremos o método de salvar carteira, passando a carteira de eventos como seu parâmetro. Vamos criar esse método. Usaremos o serviço de economia de carteira aqui. Então, vamos injetá-lo nessa classe. Em seguida, chamaremos o método de salvar carteira aqui, passando a carteira como parâmetro. Agora, se tudo funcionar corretamente, nosso aplicativo salvará carteiras no banco de dados após sua criação. Então, vamos executar nosso aplicativo para testar esse recurso e testá-lo primeiro no ambiente de teste de registro. Certifique-se de que a opção VM na configuração de execução do aplicativo BYOD W esteja vazia. Para esse teste específico, não precisaremos executar nosso node. Vamos executá-lo. Vamos criar uma carteira. Ok, se tudo funcionou corretamente, a carteira foi salva. Vamos fechar nosso aplicativo. Agora. Vamos ver se os arquivos do banco de dados foram criados na pasta especificada. Ótimo, o aplicativo criou a pasta reg test e os arquivos de banco de dados esperados nela. Vamos abri-los. Arquivo de log de pontos Idb. Aqui podemos ver todas as operações de banco de dados de nossos aplicativos em SQL escritas em texto simples. Podemos ver que ele tem um comando de inserção contendo dados da carteira, incluindo sua semente mnemônica. Bom. Mas isso não foi salvo, pois qualquer pessoa que obtenha esse arquivo pode conhecer todas as nossas carteiras, sementes mnemônicas. Vamos corrigir isso em breve criptografando esses arquivos. Por enquanto, vamos ver os dados salvos da carteira em um formato mais legível. Para fazer isso, vamos acessar este site para baixar o banco de dados H SQL. Clique no link de download para baixar a versão mais recente. Depois de baixá-lo, extraia seu conteúdo em uma pasta. Vamos abrir a pasta bin localizada dentro da pasta extraída. Agora vamos executar o swing do gerenciador de execução em um ponto nesse arquivo. Vamos acessar as propriedades do ponto do aplicativo em nosso aplicativo para copiar a URL do banco de dados. Agora, vamos colar seu conteúdo nesse campo. E vamos substituir essa variável pelo teste de registro. Vamos adicionar aqui o mesmo nome de usuário e senha que definimos no arquivo de propriedades do ponto do nosso aplicativo. Vamos clicar. Ok, ótimo. Conseguimos nos conectar ao nosso banco de dados. Agora, clique com o botão direito na pasta pública da carteira de pontos aqui e clique na instrução SQL select. Vamos executar esse comando clicando nesse botão. Ótimo. Aqui estão os dados da nossa carteira em formato de tabela. Podemos ver que nosso aplicativo salvou com sucesso os dados da carteira. Vamos fechar esse aplicativo. Agora, como eu disse antes, é importante criptografarmos nossos arquivos de banco de dados. Para fazer isso, vamos adicionar o seguinte sufixo ao URL do banco de dados no arquivo de propriedades do ponto do aplicativo. Aqui, definiremos uma chave criptográfica e um tipo de criptografia. O tipo de berço será AES, que é uma criptografia simétrica que o aplicativo usará para criptografar dados antes de salvá-los no banco de dados e descriptografá-los ao recuperá-los. A chave criptográfica será a chave necessária para ambas as operações. Vamos usar o gerenciador de banco de dados SQL novamente para gerar uma chave de criptografia válida. Clique no botão OK aqui. Vamos executar o seguinte comando SQL. Vamos copiar a chave gerada em um editor de texto depois copiá-la novamente para o valor da chave criptografada nas propriedades de ponto do aplicativo. Agora vamos adicionar a mesma configuração de banco de dados aos outros arquivos de propriedades no projeto. Vamos remover a pasta reg test, criar uma distorção nos arquivos do banco de dados. E vamos executar nosso aplicativo novamente. Vamos criar uma nova carteira. Agora, vamos abrir a pasta reg test e o arquivo de log my db dot gerado. Seu conteúdo é totalmente ininteligível agora, que significa que foi criptografado com sucesso. Vamos copiar o URL do banco de dados novamente, incluindo o sufixo de criptografia, e abri-lo usando o gerenciador de banco de dados H SQL. Ótimo, podemos ver os dados salvos da carteira novamente usando o novo URL neste aplicativo. 68. 66 Carregar carteira parte 1 skillshare 2: Neste vídeo, começaremos a implementar a capacidade de carregar carteiras salvas anteriormente em nosso aplicativo. Primeiro, vamos fazer algumas refatorações necessárias. Vamos ao serviço de criação de carteira. Queremos poder criar carteiras com datas e números diferentes de endereços gerados. Então, vamos adicioná-los como parâmetros nesse método. Agora, vamos substituir essa instanciação de data pela variável created at. E vamos adicionar a variável número de endereços gerados como o último parâmetro desse método. Agora, vamos até o controlador de diálogo de criação de carteira para adicionar esses parâmetros à chamada do método create. Vamos injetar o número inicial de endereços gerados nessa classe. Agora, vamos alterar a assinatura do método de endereços ADA para incluir o último parâmetro que acabamos de adicionar a essa chamada. No serviço de endereço ADD, vamos adicionar o número de variáveis de endereços gerados à chamada e assinatura desse método. Vamos também passá-lo como o último parâmetro do método de geração do gerador sequencial de endereços. Vamos alterar a assinatura desse método para incluir esse parâmetro. Agora, vamos excluir o campo do número inicial de endereços gerados dessa classe. E vamos substituí-la aqui pela variável número de endereços gerados. Agora, vamos para o serviço de atualização de endereços da carteira atual e definirá o campo de número inicial de endereços gerados como o último parâmetro dessa chamada de método. Agora vamos criar a classe de teste da carteira de carga no pacote de teste da GUI. Isso estenderá a classe de teste de GUI. Vamos fazer o teste de envio de Bitcoin para copiar essa parte do código, pois precisaremos dela para nosso novo teste. E vamos colá-lo aqui. Agora, vamos para a aula de teste de recebimento de Bitcoin. Vamos copiar esse primeiro teste e usá-lo como base para nosso novo teste. Vamos renomeá-lo para deve carregar carteira e receber Bitcoin. Vamos formatar esse teste. Vamos adicionar um determinado bloco a esse teste. Aqui, vamos definir um nome de carteira e variáveis de senha. Vamos também definir uma variável de semente mnemônica. Usaremos o método de criação do serviço de sementes mnemônico para gerá-lo. Vamos injetar o serviço de semente mnemônica na classe de teste de GUI. Agora, vamos chamar o método de criação de carteira aqui, passando o nome da carteira, a senha e a semente mnemônica como seus parâmetros. Vamos criar esse método na classe de teste da GUI. Aqui, criaremos uma carteira usando o serviço de criação de carteira. Então, vamos injetá-lo nessa classe. Agora, vamos chamar o método create passando esses parâmetros para ele. Agora, usaremos o serviço de economia de carteira. Então, vamos injetá-lo nessa classe. E vamos chamá-lo de método de salvar carteira, passando a carteira como parâmetro. Finalmente, vamos devolver a carteira aqui. De volta ao teste da carteira de carga. Agora que criamos e salvamos uma carteira, tentaremos carregá-la. Então, vamos remover esse código. Vamos chamar o método load wallet, passando o nome da carteira como parâmetro. Vamos criar esse método na classe de teste da GUI. Ele também usará um parâmetro de senha opcional com uma string vazia como valor padrão. Primeiro, tentaremos clicar em um componente com o carregamento dos textos. Esse componente será o botão do menu de carregamento, que estará ao lado do botão Novo no menu na parte superior da janela principal. Em seguida, moveremos o mouse para um componente com a carteira de texto. Depois disso, esperamos que apareça um submenu contendo todos os nomes das carteiras carregadas. Em seguida, clicaremos naquele com o texto igual à carteira chamada variável. Em seguida, esperaremos que uma janela de diálogo apareça com um campo de entrada de senha e um botão OK. Então, clicaremos nesse campo que tem o ID de ética da senha da carteira de carregamento. Agora vamos digitar a senha nesse campo. Em seguida, clicaremos no botão OK. Por fim, vamos chamar o método de hibernação para esperar o carregamento da carteira. Ok, o resto do teste será como os testes da carteira receptora que usamos como base para este teste enviarão Bitcoin para a carteira carregada e esperarão que os endereços e as tabelas de transações sejam preenchido com valores apropriados. Agora, vamos ao arquivo FXML de pontos do playground para criar o menu de carregamento. Vamos adicionar um controle de menu à barra de menu. Vamos mudar seu texto para carregar. Agora, vamos adicionar um controle de menu ao menu de carregamento. Vamos excluir esse item de menu que foi adicionado automaticamente. Vamos mudar os textos desse menu para carteira. E vamos excluir esse item do menu. Agora, na visualização do editor de texto, vamos adicionar um ID Fx a essa tag de menu. Vamos configurá-lo para carregar o menu FXML. Vamos adicioná-lo ao controlador da janela principal. Adicionará uma anotação FXML e a mudará para um campo privado. Agora, vamos adicionar a classe do menu de carregamento no pacote observables. Essa classe será responsável por gerenciar os itens de menu que serão adicionados para cada carteira criarmos em nosso aplicativo. Vamos adicionar uma anotação de componente a ela. Vamos criar o campo de itens do menu aqui. Será um conjunto observável de entidades de carteira do tipo carteira. Vamos instanciá-lo usando um novo wrapper de conjunto observável, passando um novo LinkedHashSet para ele. Agora vamos criar o bom método de itens de menu observáveis aqui. Ele retornará os itens do menu. Agora vamos criar o ouvinte do menu de carregamento no pacote GUI dot listeners. Esse ouvinte será acionado pelo evento gooey started publicado após o início do aplicativo. Vamos usá-lo para carregar todas as carteiras salvas no banco de dados e adicioná-las ao menu de carregamento. Vamos adicionar uma anotação de componente a ela. Ele implementará a classe de ouvinte do aplicativo com o evento iniciado pela GUI como seu parâmetro de tipo. Vamos implementar seu método. Usaremos o repositório da carteira aqui. Então, vamos injetá-lo nessa classe. Vamos também injetar o menu de carregamento nessa classe. Em seguida, chamaremos o método final para carregar todas as carteiras do banco de dados. Para cada carteira, chamará o método de adição de carteira. Vamos criar esse método encapsulado na chamada de execução posterior da plataforma, vamos chamar o método de adição do menu de carregamento, passando a entidade da carteira como seu parâmetro. Vamos criar esse método e a classe do menu de carregamento. Aqui, basta chamar os itens do menu adicionar método passando a entidade da carteira como seu parâmetro. Agora vamos copiar essa linha. Vamos para a classe de serviço Save wallet. Vamos colá-lo aqui. Vamos injetar o menu de carregamento nessa classe. Com esse código, faremos com que nossa carteira recém-salva seja adicionada ao menu de carregamento. Agora, vamos para o playground dot FXML. Vamos copiar essas linhas e colá-las na janela principal FXML. Agora, vamos para o controlador da janela principal. No método inicializado, vinculará todas as alterações no menu de carregamento observáveis ao menu de carregamento. componente Fxml precisará do menu de carregamento aqui. Então, vamos injetá-lo nessa classe. Agora, vamos chamar o método get observable menu items nele. E vamos chamar o método ad listener no resultado como seu parâmetro. Vamos passar pelo seguinte Lambda. O corpo do Lambda adicionará o elemento e o armazenará na variável da carteira dessa forma. Em seguida, usaremos uma instrução if para verificar se o menu contém a carteira dessa forma. Vamos criar esse método. O uso da transformação de fluxo a seguir verificará se o menu de carregamento FXML contém um item de menu com o mesmo nome da variável de entidade da carteira. Aqui, se o menu de carregamento FXML não contiver a carteira, continuaremos a adicioná-la a ela. Instanciará um objeto de item de menu passando como parâmetro, o nome da carteira. Em seguida, adicionaremos o item de menu ao menu de carregamento FXML, assim. Agora, vamos para a classe de teste de GUI no método start antes que cada teste limpe o banco de dados para que carteiras nomes duplicados de madeira não persistam. Dessa forma, evitamos falhas no teste devido à restrição de nome exclusivo na tabela da carteira. Precisaremos do repositório de carteiras aqui. Então, vamos injetá-lo nessa classe. Em seguida, chamaremos o método delete all nele. Agora, vamos executar nosso node. E vamos fazer o teste da carteira de carga. Ok, o teste correu até a parte esperada e falhou. Pudemos ver que nosso menu de carregamento foi criado e preenchido com o nome da carteira criada. Bom. No próximo vídeo, continuaremos implementando esse recurso, C. Sim. 69. 67 Carregar carteira parte 2 skillshare 2: Neste vídeo, continuaremos implementando o recurso de carregamento de carteira. Para começar, criaremos uma janela de diálogo que aparecerá depois de clicarmos no nome da carteira que queremos carregar e no menu de carregamento como base para criá-la Usaremos a caixa de diálogo de criação de carteira. Então, vamos para a caixa de diálogo de criação de carteira FXML. Vamos copiar todo esse conteúdo. Vamos criar o arquivo FXML do diálogo de carregamento da carteira no pacote FXML. E vamos pagar o conteúdo copiado aqui. Vamos mudar o texto do cabeçalho do diálogo para a seguinte frase. Vamos mudar o atributo pref height para 300. Vamos também remover essas linhas. Vamos até o Scene Builder para ver como está. Vamos mudar o texto desse rótulo para a senha da carteira. Na visualização do editor de texto, vamos alterar esse ID fx para carregar a senha da carteira. E vamos mudar o controlador FX da etiqueta de problemas de diálogo para carregar o controlador de diálogo da carteira. Vamos criar esse controlador. Vamos adicionar a anotação do componente a ela. E vamos adicionar todos esses campos FXML ao controlador. Agora, vamos até o controlador da janela principal aqui antes de adicionar o item de menu ao menu de carregamento FXML, chamaremos o método set on action nele, passando o seguinte Lambda para ele. Isso fará com que o aplicativo execute o método de diálogo de carregamento aberto da carteira, passando a carteira como parâmetro após clicarmos nesse item do menu. Então, vamos criar esse método. Vamos copiar o conteúdo do método de diálogo de criação aberta de carteira e usá-lo como base para nosso novo método. Vamos definir o título do diálogo para carregar a carteira. Vamos mudar o primeiro parâmetro de instanciação do carregador FXML para o campo de diálogo da carteira de carregamento. Vamos injetar esse campo nessa classe. Vamos adicionar essa anotação de valor aqui e alterar seu parâmetro para o arquivo FXML da carteira de carregamento. Agora, temos que passar a carteira para o controlador de diálogo de carga da carteira. Para fazer isso, vamos primeiro pegar o controlador do carregador FXML. Então, vamos chamar esse método de carteira definida nele, passando a carteira para ele. Vamos criar esse método. Aqui. Simplesmente definiremos o campo da entidade da carteira como a variável da carteira. Vamos criar esse campo. Agora, vamos criar o método inicializado que será executado depois que a caixa de diálogo aparecer. Vamos copiar esse código e o controlador de diálogo de criação de carteira e colar aqui. Isso definirá a ação de fechar a janela de diálogo com o botão de cancelamento. Também vamos copiar e colar esse código no novo método inicializado. Isso definirá a ação do botão OK. Mas, em vez de chamar o método create wallet, ele chamará o método load wallet. Vamos criá-lo. Primeiro. Recuperaremos uma nova entidade de carteira do banco de dados e a definiremos como o campo da entidade da carteira. Para fazer isso, precisaremos do repositório da carteira. Então, vamos injetá-lo nessa classe. Em seguida, chamaremos o método find by name nele, passando o nome da entidade da carteira para ele. Vamos criar esse método. O método será exatamente assim. Spring Boot Data JPA magic traduzirá automaticamente esse nome de método em uma consulta SQL e recuperará a entidade da carteira com o nome passado como parâmetro do banco de dados. Agora, criaremos um objeto de carteira. Para fazer isso, precisaremos criar um serviço de carteira. Então, vamos injetá-lo nessa classe. Chamaremos o método create passando os seguintes parâmetros. Todos esses parâmetros, exceto a senha da carteira, serão retirados da entidade da carteira encontrada no banco de dados. A senha será retirada do campo de senha da caixa de diálogo. Vamos injetar o objeto de contexto nessa classe. Agora, usar o contexto publicará um evento de carteira carregada passando isso e a carteira criada para ela. Por fim, chamaremos o método hide para fechar a janela de diálogo dessa forma. Vamos criar a classe de eventos da carteira carregada. Passará o parâmetro do controlador de diálogo da carteira de carga para o superconstrutor. E definiremos o campo da carteira com o parâmetro do construtor da carteira. Vamos criar um getter para o campo da carteira. Agora, vamos fazer uma refatoração no ouvinte de importação de carteira criado. Queremos fazer com que ele escute eventos de carteiras carregadas. Mas do jeito que está agora, ele só pode ouvir o evento da carteira criada. Para mudar isso, vamos excluir essa instrução de implementação e essa anotação Override. Vamos alterar o nome desse método para importar a carteira e seu parâmetro para um objeto de carteira. Vamos mudar o parâmetro do método de importação da carteira para Wallet. Agora, vamos criar um método anotado com a anotação do ouvinte do evento. Ele será chamado no evento de carteira criada e receberá um evento de carteira criado como parâmetro. Aqui, chamaremos o método de importação da carteira, passando a carteira de eventos como parâmetro. Essa refatoração continuará fazendo com que as coisas funcionem como antes. Mas agora, se quisermos ouvir outro evento, podemos simplesmente criar outro método anotado pelo ouvinte passando o evento que queremos como parâmetro. Isso é exatamente o que faremos agora O evento load wallet também chamará o método de importação de carteira aqui, passando a carteira de eventos como seu parâmetro. Isso fará com que o nó Bitcoin importe a carteira, assim como quando criamos uma nova carteira. Agora, vamos criar a classe de ouvinte de carteira carregada no pacote de ouvintes. Vamos adicionar a anotação do componente a ela. Vamos criar um método anotado pelo ouvinte de eventos chamado evento de carteira descarregada. Será usado um evento de carteira carregada como parâmetro. Aqui, chamaremos o método de carregamento da carteira passando a carteira de eventos como seu parâmetro. Vamos criar esse método. Aqui. Precisaremos do serviço de atualização atual da carteira. Então, vamos injetá-lo nessa classe. E chamaremos o método de atualização nele. Passar a carteira como parâmetro também precisará do serviço utxOS de atualização. Então, vamos injetá-lo nessa classe. Em seguida, chamaremos o método de atualização nele, passando os endereços e o nome da carteira como parâmetros. Com essas duas linhas de código, esperamos que a carteira atual seja alterada para a carteira carregada e que seus endereços, transações e saldos sejam atualizados adequadamente. Agora vamos corrigir alguns testes. Analisamos os vídeos anteriores no teste do gerador sequencial de endereços. Vamos excluir esse primeiro parâmetro na instanciação do gerador sequencial de endereços. E vamos definir 20 como o último parâmetro desse método. Vamos fazer esse teste. Ótimo, está funcionando conforme o esperado. Vamos fazer o mesmo com o teste do serviço de criação de carteira. Ok, está funcionando. Agora. Vamos executar nosso node. Vamos limpar e compilar o projeto usando esse recurso do IDE Maven. E vamos fazer o teste da carteira de carga. Falhou. O problema está no controlador da janela principal. Aqui, temos que chamar o método get controller do carregador FXML em vez do método load. Vamos fazer o teste novamente. Ótimo, já passou. 70. 68 Carregar carteira parte 3 skillshare 2: Neste vídeo, adicionaremos mais testes e faremos algumas otimizações no recurso de carregamento da carteira. Uma das características que nossa carteira terá é a negação plausível. negação plausível nesse contexto é um recurso de segurança que permitirá que você oculte os endereços de sua carteira digitando uma senha diferente para carregar sua carteira. Isso significa que nossa carteira não terá senhas erradas. Cada senha inserida dará acesso a um conjunto diferente de endereços, mas observar terceiros não conseguirá saber se os endereços da carteira carregada contêm a maior parte de seus fundos. Vamos criar um teste para esse cenário. Vamos duplicar esse teste e usá-lo como base para nosso novo teste. Vamos renomeá-lo para deve carregar a carteira com uma senha diferente e receber Bitcoin. Vamos reformatá-lo. Vamos aumentar a carteira chamada número. Agora, vamos definir essa variável de senha diferente e passá-la para o método load wallet como seu segundo argumento. Vamos também passá-lo como o último parâmetro do método válido do endereço. Vamos definir o parâmetro de senha como um parâmetro opcional para esse método, definindo seu valor padrão como uma string vazia. Vamos substituir a string vazia e o método das duas chaves mestras pela variável de senha. Vamos executar nosso node. Vamos comentar esse método e executar nosso novo teste. Ótimo, já passou. Esse teste mostra que nosso aplicativo já suporta qualquer senha para carregar uma carteira e que cada senha gerará um conjunto separado de endereços. Vamos descomentar esse teste. Considerando nossa maneira de ver uma carteira como tendo vários conjuntos de endereços de acordo com suas senhas. Precisamos corrigir um problema em nosso aplicativo. Quando fazemos chamadas para nosso nó Bitcoin por meio de nosso aplicativo, usamos o nome da nossa carteira. Isso é um problema, pois, para operações como recuperar nossa carteira, transações e UTXOs de nosso node coletarão as mesmas informações para diferentes conjuntos de endereços gerados por diferentes senhas. Para otimizar nossas notas, as chamadas RPC e coletar apenas informações dos endereços gerados com uma determinada senha, usaremos o primeiro endereço de recebimento gerado como o nome da carteira importante para nossa nó. Para fazer isso, vamos até o registro da carteira. Vamos criar o bom método de primeiro endereço aqui. Ele usará o método get addresses para retornar o primeiro endereço da carteira. Agora, temos que substituir cada chamada no campo do nome da carteira que foi feita para nos comunicarmos com nosso node por uma boa chamada de método de primeiro endereço Vamos usar nosso ID para identificar os usos de o campo do nome e faça a refatoração. Agora, vamos acessar o serviço de atualização da carteira atual e definir o primeiro endereço da carteira atual. Vamos criar esse método. Aqui. Definiremos o primeiro campo de endereço para o parâmetro recebido. Vamos criar esse campo. E vamos criar um getter para isso. Agora, vamos substituir as chamadas relevantes do método getName da carteira atual pelas chamadas atuais do método get first address. Agora vamos fazer o teste da carteira de carga, comentar o primeiro teste e executar o teste restante. As coisas boas continuam funcionando como antes. Vamos descomentar esse teste. Agora, vamos para a classe de configuração de endereço. Como agora estamos usando o primeiro endereço de carteira para interagir com nosso node, o primeiro endereço deve ser sempre o mesmo para uma combinação de semente mnemônica e senha. Portanto, temos que garantir que a lista de configurações de endereços e seus endereços estejam sempre na mesma ordem. Para fazer isso, vamos usar a anotação do pedido nos dois feijões. Vamos adicionar a anotação do pedido com zero como argumento neste primeiro Bean. Isso fará com que o Spring injete esse bean nas listas de configuração de endereços como o primeiro elemento. Vamos também mudar o segundo argumento do objeto de configuração de endereço para um Hashmap vinculado. Ao contrário dos mapas gerados pelo mapa do método, o Hashmap vinculado mantém a ordem de inserção, conseguindo isso usando o código a seguir. Agora vamos fazer a mesma refatoração no outro feijão de configuração do vestido vermelho. E vamos adicionar a anotação do pedido aqui usando uma como parâmetro, garantindo que ela será injetada após o primeiro bean se inscrever nas configurações de endereço. Agora, vamos fazer outra otimização. Às vezes, a importação de endereços para nosso node é lenta. Para evitar a importação desnecessária de endereços para nosso node, verificaremos se eles já foram importados. Para fazer isso, vamos criar o nó recebido pelo cliente de endereço no pacote do cliente node dot. Esse cliente recuperará todos os endereços carregados atualmente pelo nosso node. Vamos adicionar a anotação do serviço a ela. E vamos injetar o cliente node nele. Agora, vamos criar o método de lista de endereços aqui. Ele retornará uma lista de objetos de endereço de nós como seus parâmetros. Será necessário um nome de carteira. Amen conf, que definirá o número mínimo de conformações dos endereços retornados. O parâmetro include empty, que definirá se a chamada retornará endereços sem fundos. E o parâmetro include watch only , que dirá ao nó se queremos recuperar endereços que o nó não conhece e suas chaves privadas correspondentes. Vamos criar o registro de endereço do nó no pacote domains dot node. Ele terá somente um campo de endereço. Usando o cliente node. Vamos fazer a chamada de RPC aqui. Ele retornará uma matriz de endereços de nós. O primeiro parâmetro do método make request será a lista recebida pela string de endereço. Em seguida, passaremos um novo objeto de referência de tipo parametrizado. Em seguida, o URL da carteira. Finalmente, descrevemos anteriormente os parâmetros do método de vestimenta listados . Agora retornará uma conversão da matriz de endereços do nó em uma lista de endereços de nós como esta. Agora, vamos ao serviço de importação de carteiras. Aqui, adicionaremos uma declaração if para verificar se os endereços da carteira não foram importados dessa forma. Vamos criar esse método. Dentro do corpo if, usará o método import addresses para importar os endereços somente se eles não tiverem sido importados antes. Vamos implementar o método importante do endereço. Obteremos os endereços importados usando o nó recebido pelo cliente de endereço. Então, vamos injetá-lo nessa classe. Em seguida, chamaremos o método de lista de endereços. Passar os parâmetros a seguir converterá o resultado em um fluxo e usará o método map para extrair todos os endereços de endereço do nó. Em seguida, converteremos o resultado em um conjunto de endereços usando o método collect. Em seguida, converteremos os endereços da carteira em um conjunto como esse. Agora, usando o método de remoção nos endereços da carteira, removerá todos os endereços importados. Por fim, retornaremos que os endereços da carteira são uma chamada de método vazia. Se o resultado for verdadeiro, todos os endereços da carteira já foram importados. Oh, esquecemos de deletar essa linha. Vamos fazer isso. Agora. Vamos fazer o teste de envio de Bitcoin. De agora em diante, adicionaremos algumas afirmações sobre o recurso de carregamento de carteira a alguns testes. Então, se encontrarmos algum bug no processo, o corrigiremos. Vamos começar com o primeiro teste de envio de Bitcoin. Vamos excluir essa linha em seu lugar. Vamos adicionar uma chamada de método de carteira de carga de peso. Usar esse método tentará fazer com que esse teste seja executado mais rápido. Vamos criá-lo na classe de teste de GUI. Aqui, vamos chamar o método da bolacha. Passando esses parâmetros. Em cada iteração desse retorno de chamada, usaremos o método sleep para esperar por 1 s. Em seguida, verificaremos se o primeiro endereço da carteira atual está definido. Então, vamos injetar a carteira atual nessa classe. Usando a lista de nós, o cliente de carteiras verificará se o nó carregou o endereço com o primeiro endereço da carteira atual. Então, vamos injetar esse serviço nessa classe. Com esse código, esperará até que o nó carregue a carteira. Agora, vamos corrigir um problema que às vezes pode causar falhas nos testes. Aqui, o parâmetro de tamanho total esperado é igual à soma do índice de iteração atual mais um. Agora, vamos criar a última variável de endereço de recebimento definir seu valor para o endereço de recebimento presente na janela. Agora, vamos definir algumas outras variáveis que nos ajudarão a comparar os valores na carteira antes e depois de carregá-la. Primeiro, o tamanho da tabela de transações. Em seguida, o saldo da tabela de transações da primeira linha. Agora vamos chamar o método load wallet, passando o nome da carteira como parâmetro. Vamos definir essa variável aqui. Agora, definiremos a tabela de transações após a variável de carregamento. Vamos obtê-lo usando o método de pesquisa exatamente como antes de carregá-lo. Em seguida, clicaremos na guia de endereços e definiremos a tabela de endereços após variável de carregamento da mesma forma. Em seguida, clicaremos na guia Receber e definiremos o último endereço de recebimento, a variável de pós-carregamento e o texto do rótulo após a variável de carregamento. Agora, no bloco then, vamos deletar essas duas linhas. E vamos comparar as últimas variáveis de endereço de recebimento antes e depois de carregar a carteira. Em seguida, vamos definir o tamanho da tabela de endereços e variáveis balanceadas da tabela de endereços da primeira linha aqui. E vamos adicionar essas duas comparações que são iguais às que acabamos de excluir. Agora, vamos comparar os tamanhos da tabela de endereços antes e depois de carregar a carteira. E vamos fazer o mesmo com o saldo da primeira linha da tabela de endereços. Agora vamos excluir essas duas linhas, substituindo-as pelas seguintes linhas, que fazem as mesmas comparações mas usam as variáveis refatoradas. E vamos adicionar as seguintes comparações das variáveis antes e depois de carregar a carteira. Vamos comentar todos os outros testes neste arquivo. E vamos fazer o teste restante. O teste falhou porque o último endereço de recebimento antes e depois do carregamento da carteira é diferente. No próximo vídeo, vamos corrigir isso. 71. 69 Carregar carteira parte 4 skillshare 2: Neste vídeo, corrigiremos o erro de ter endereços de recebimento diferentes antes e depois de carregarmos uma carteira. Isso acontece porque estamos usando o UTXOs para atualizar o índice atual de endereços de recebimento. Depois de carregar a carteira e recuperar os UTXOs da carteira, as saídas antigas usadas para atualizar o endereço de recebimento não fazem mais parte do conjunto UTXO porque já foram gastas. Assim, o endereço de recebimento acaba não sendo atualizado. Vamos corrigir isso transferindo o código responsável por atualizar os endereços de recebimento do serviço de atualização de endereços da carteira atual atualização de endereços da carteira atual para uma nova classe. Na Nova Classe, usaremos as transações recuperadas do nó contendo todas as carteiras e endereços usados para atualizar os endereços de recebimento atuais. Então, vamos criar essa classe que será chamada de atualizar o endereço de recebimento da carteira atual de seu serviço no pacote de serviços de pontos da GUI. Vamos adicionar a anotação do serviço aqui. Agora, vamos copiar e colar alguns códigos do serviço de atualização de endereços da carteira atual para essa classe. Vamos adicionar essa anotação de qualificador. Agora vamos criar o método de atualização aqui. Será necessária uma lista das transações do node. O uso do método de mapa obterá um fluxo de endereços do fluxo de transações do node. Em seguida, filtraremos o stream para que ele contenha apenas endereços na carteira atual. Em seguida, chamaremos o método de marca usada em cada endereço. Vamos usar esse método do serviço de atualização de endereços da carteira atual. Agora, chamaremos o método atual de obter endereços de carteira . Vamos criar esse método. Ele retornará o resultado da chamada do método address get addressed types. Ele retornará um conjunto de tipos de endereço. Vamos criar esse método na classe de endereços. Aqui, simplesmente retornará o conjunto de chaves do campo de endereços. Agora, para cada tipo de endereço, chamaremos o método de atualização do endereço de recebimento. Para fazer isso, o tipo desse parâmetro de método será alterado para o tipo de endereço. E excluiremos essa linha pois não seremos mais necessários. Agora, vamos acessar o serviço de atualização de endereços de carteira atuais para excluir o mesmo código que colamos nossa nova classe e seus usos. Agora, vamos para o serviço de atualização UTXos. Vamos injetar o serviço de atualização atual de endereços de recebimento da carteira nessa classe. E vamos chamar o método de atualização do serviço injetado passando as transações do nó como seu parâmetro. Agora vamos fazer o teste de envio de Bitcoin. Vamos adicionar a chamada do método de hibernação aqui para evitar uma nova condição de corrida que pode acontecer às vezes garante que seu nódulo esteja funcionando. E vamos fazer esse teste. O problema do endereço de recebimento foi corrigido, mas o teste falhou devido a outro bug. O saldo da transação após o carregamento uma carteira não é calculado incorretamente. Vamos corrigir isso. Para resolver esse bug, precisamos entender melhor como a API de transações da lista Bitcoin Core funciona. Aqui está a documentação da lista de transações bitcoin Core API. Observe que, para cada transação, a API retorna somente um campo de endereço. O valor se refere apenas ao valor de Bitcoin enviado para esse endereço ser negativo se não pertencer à nossa carteira e positivo caso contrário. Se a transação tiver uma saída de alteração, a API retornará mais de um registro para cada transação. Cada registro com um campo de endereço da saída da transação. Vamos ver um exemplo do resultado dessa API para uma transação enviada de nossa carteira com uma entrada e duas saídas. Para a mesma transação, a API retornou três registros. Podemos ver que eles se referem à mesma transação examinando seus IDs de transação. Observe que os dois primeiros registros têm o mesmo endereço. Esses registros se referem à saída da alteração. O primeiro tem um valor positivo indicando que é um endereço pertencente à nossa carteira. Esse é o valor da mudança. O segundo registro tem o mesmo valor, mas como negativo. Isso significa que nossas carteiras enviaram uma quantia para esse endereço. Também tem uma taxa negativa, que é a taxa de transação que pagamos na transação. Se somarmos o valor dos dois primeiros registros, acabamos com zero, que é exatamente o saldo que pagamos na transação. Finalmente, o terceiro registro contém um valor negativo indicando que enviamos Bitcoin para esse endereço. Ele também tem uma taxa igual à taxa do segundo registro. Considerando como essa API funciona, a maneira correta de calcular o saldo da transação é somar os valores cadastrais retornados para a mesma transação e a taxa de uma delas registradores, a transação balanceada antes carregar uma carteira está correta porque a estamos calculando de uma forma que considera a segunda transação criada antes de enviá-la ao nosso node. Depois de carregarmos nossa carteira, perdemos as informações da transação que não consideram para calcular o saldo da transação. Então, vamos ao serviço de transação Update Current Wallet para corrigir o problema. Nossa nova solução não precisará mais desse filtro. Então, vamos excluir essa linha em seu lugar. Vamos adicionar uma chamada ao método collect como seu parâmetro. Chamaremos os coletores de agrupamento por método, passando uma referência ao ID TX da transação do nó com esse código, obteremos um mapa em que as chaves serão IDs de transação e os valores serão listas de transações de nós com o mesmo ID de transação. Vamos chamar o método de valores no resultado e não o método stream para obter um fluxo de listas de transações de nós com o mesmo T XID. O resto desse método permanece como está. Vamos criar a transação a partir do método. Ele pegará uma lista de transações do node e retornará uma linha de transação. Vamos mover esse método aqui. Vamos primeiro obter a taxa de transação. Será retirado de um fluxo sem taxas de transação. Vamos criar o campo de taxa na transação do node. Em seguida, filtraremos o stream para ver as taxas nominais. Em seguida, pagaremos a multa primeiro para receber as primeiras e usaremos o método de URLs para retornar zero se nenhuma taxa for encontrada. Agora, vamos calcular o valor. O uso do método map obterá um fluxo contendo todos os valores de transação do nó do fluxo de transações do nó. Em seguida, usaremos o método reduzido, passando a referência do método de adição decimal grande para alguns valores. Por fim, usaremos o método or else para retornar zero sem que nenhuma transação seja encontrada. Agora vamos copiar e colar essa linha aqui. Usaremos o ID TX da transação do primeiro nó como o primeiro parâmetro da instanciação da linha da transação. Em seguida, adicionaremos a taxa de transação obtida ao valor e passaremos o valor como um parâmetro aqui. Por fim, passaremos a confirmação da transação do primeiro nó a tempo como parâmetros de instanciação da última linha de transação . Vamos excluir esse método, pois não precisaremos mais dele. Vamos fazer esse teste de envio de Bitcoin novamente. O primeiro teste foi aprovado, mas o segundo falhou devido a uma condição de corrida. Vamos corrigi-lo rapidamente com a chamada do método de sono aqui. Faremos uma correção melhor para esse erro no próximo vídeo. Por enquanto, vamos comentar esta linha para executar somente a nota do teste reprovada . O teste foi aprovado. Vamos descomentar o resto do teste. 72. 70 Carregar carteira parte 5 skillshare 2 1: Neste vídeo, adicionaremos mais afirmações de teste para verificar se podemos carregar corretamente uma carteira com mais endereços gerados do que a configuração inicial do número de endereços gerados. Mas primeiro, vamos otimizar um método de teste para evitar algumas condições de corrida em alguns testes. Na aula de teste de envio de Bitcoin. Vamos excluir essas duas chamadas do método de suspensão, pois nosso fixo lidará melhor com as condições de corrida após enviarmos bitcoins. Vamos para a aula de teste de GUI. Vamos adicionar esse parâmetro opcional no método de enviar Bitcoin e esperar com o valor padrão igual ao endereço de recebimento da hashtag. Em seguida, vamos adicionar o seguinte e a condição a esse valor de retorno. Com esse código, só parará de esperar se o campo do endereço de recebimento for diferente da variável de endereço. Portanto, evitamos o erro de enviar Bitcoins para o mesmo endereço duas vezes sequencialmente. Agora, vamos fazer o teste de recebimento de Bitcoin. No último teste dessa classe, adicionaremos algumas afirmações para testar se podemos carregar corretamente uma carteira com mais endereços gerados do que a configuração inicial do número de endereços gerados. Então, vamos definir a carteira chamada variável e substituir o parâmetro no método correto para essa variável. Agora, vamos chamar o método da carteira de carga de peso aqui e excluir as chamadas do método de sono desse teste. Agora, depois de receber Bitcoins sete vezes, vamos definir a última variável de endereço de recebimento com o valor presente no campo de endereço de recebimento. Agora, vamos copiar essa linha no teste de areia do Bitcoin e colá-la aqui. Vamos mudar essa variável para abordar sua exibição em tabela. Vamos fazer o mesmo com essa outra linha. Agora, vamos copiar e colar todas essas linhas do teste de envio de Bitcoin para o nosso teste. Também vamos copiar e colar essa linha em nosso novo teste para comparar o último endereço de recebimento antes e depois de carregar a carteira. Vamos adicionar essa linha para comparar o tamanho da tabela de transações antes e depois de carregar a carteira. Nesta linha, faremos o mesmo com tamanho da tabela de endereços. E essa outra linha comparará o texto da etiqueta antes e depois de carregar a carteira. Vamos executar nosso node. Vamos comentar os outros testes desta classe e executar nosso novo teste. O teste falhou devido à diferença entre o último endereço de recebimento antes e depois de carregar a carteira. Além disso, se você notou o número de endereços na tabela de endereços após o carregamento, são apenas três quando o correto seria sete. Isso ocorre porque não estamos salvando o número de endereços gerados depois de gerá-los. Vamos corrigir isso. Vamos até o serviço de atualização de endereços de recebimento da carteira atual . Precisaremos do repositório de carteiras aqui. Então, vamos injetá-lo nessa classe. Agora, chamaremos o método de incremento do número de endereços gerados no repositório da carteira. Como seus parâmetros, passarão o número inicial de endereços gerados e o nome da carteira atual. Vamos criar esse método. Vamos mudar esse parâmetro de tipo para a classe inteira e esse nome de parâmetro para incrementar. Como o próprio nome sugere, esse método incrementará o número de campos de endereços gerados em nossa carteira. Para fazer isso. Vamos adicionar a anotação transacional a ela. Essa anotação é um requisito da biblioteca JPA porque ela executará a operação SQL em duas etapas. Vamos também adicionar a anotação modificadora. Essa anotação é necessária para métodos de repositório que modificam registros e tabelas, o que é o caso. Por fim, vamos adicionar a anotação da consulta a esse método. Essa anotação indicará a operação SQL que queremos fazer como parâmetro. Vamos adicionar a seguinte string. Essa instrução semelhante a SQL adicionará ao número de endereços gerados o valor do incremento passado como o primeiro argumento para o método anotado. A cláusula where fará com que essa operação ocorra somente na carteira com o nome igual ao parâmetro name. Para vincular os parâmetros do método às variáveis SQL. Vamos adicionar essas duas anotações de poemas a esses parâmetros. Agora vamos fazer nosso teste novamente. Ótimo, já passou. Nosso recurso de carteira de carga está pronto. Agora, é importante executar todos os nossos testes de aplicativos para verificar se um bug apareceu. Mas primeiro, corrigiremos e otimizaremos alguns de nossos testes para usar o método de carteira de carga de peso e excluiremos algumas chamadas do método de hibernação que não são mais necessárias. Vamos primeiro invulgar esses testes. E vamos fazer as otimizações mencionadas. Nos testes de segmentos aninhados, como os dessa classe, devemos adicionar alguns parâmetros para enviar Bitcoin e aguardar a chamada do método. Então, vamos fazer isso. O último parâmetro dessas chamadas deve ser o endereço de recebimento do segmento aninhado de hashtag da string. Em alguns métodos como esse, também precisamos definir o ID mais um é o terceiro argumento da chamada do método send Bitcoin and wait. Agora, podemos executar todos os nossos testes de aplicativos. Todos eles devem passar na minha máquina. Eles estão levando meia hora. Então eu deixei isso como um exercício para o aluno. 73. 71 Importar skillshare 2: Neste vídeo, implementaremos a capacidade de importar uma carteira com a semente mnemônica. É importante ter essa opção para recuperar sua carteira e os casos em que você perde, destrói ou não tem acesso ao hardware ou aos arquivos que contêm o aplicativo ou banco de dados com os dados da carteira. Nesses casos, você simplesmente inseriria sua semente de backup e, opcionalmente sua senha no recurso de importação do aplicativo para ter acesso de volta à sua carteira. Mais uma coisa, você não ficará restrito a recuperar sua carteira. Usando este aplicativo, você poderá usar sementes mnemônicas geradas por este aplicativo para recuperar sua carteira e outras carteiras compatíveis com BIP 39. Além disso, você poderá recuperar o acesso aos endereços de sua carteira Bitcoin importando sua semente mnemônica BIP 39 gerada por outras carteiras para este aplicativo. Apenas certifique-se de que os dois aplicativos suportem os blocos de derivação dos endereços que você deseja importar. Então, vamos começar criando o teste da carteira de importação. Isso estenderá a classe de teste de GUI. Vamos copiar esse código do teste de envio de Bitcoin e colá-lo aqui. Agora vamos criar um teste chamado should import wallet and receive Bitcoin. No bloco único, vamos definir a carteira chamada variável. E vamos criar uma semente mnemônica usando o método de criação do serviço de sementes mnemônicas. Agora vamos chamar o método de importação da carteira, passando o nome da carteira e semente mnemônica como parâmetros. Vamos criar esse método. Vamos também adicionar uma senha como um terceiro parâmetro opcional a esse método. Aqui, clicaremos em um menu com a importação de texto. Em seguida, clicaremos no item Menu com a carteira de texto. Agora, clicaremos no componente com um ID FX do nome da carteira. Esse componente será um campo de entrada no qual inseriremos o nome da carteira importada. Em seguida, chamaremos o método de gravação passando a variável name como seu parâmetro para digitar o nome nesse campo. Em seguida, clicaremos no campo de senha, que terá um ID FX da senha da carteira. Em seguida, escreveremos a senha nesse campo. Em seguida, clicaremos no campo de semente mnemônica e escreveremos a variável de semente mnemônica nesse campo. Por fim, clicaremos no botão OK. Vamos também adicionar a chamada do método de hibernação para aguardar o carregamento da carteira. Voltando ao teste da carteira de importação usando o método de pesquisa, vamos recuperar o valor do endereço presente no campo de endereço de recebimento. Usando o método de enviar Bitcoin e esperar, vamos enviar 1.000 Satoshi para o endereço recuperado. Agora, clicaremos na guia de endereços. Em seguida, usando o método de pesquisa, obteremos a tabela de endereços e a armazenaremos em uma variável. Clicaremos na guia de transações, obteremos a tabela de transações e a armazenaremos em uma variável. Além disso, vamos fazer o mesmo com o saldo total rotulado como texto. Agora, vamos definir duas variáveis para armazenar o tamanho da tabela de endereços e o tamanho da tabela de transações. Vamos adicionar as seguintes afirmações nesse bloco para verificar se as variáveis definidas anteriormente têm os valores esperados. Agora vamos duplicar esse teste. Vamos renomeá-lo para importar a carteira usada e o bloco recebido. Neste teste, criaremos uma carteira e receberemos Bitcoins nela antes de importarmos a carteira, depois importaremos a carteira, geraremos um bloco em nossa nota e verificaremos se o aplicativo carrega corretamente e atualiza a carteira importada. Então, vamos criar um determinado bloco aqui, onde criaremos uma carteira e enviaremos um Bitcoin para ela. Agora, vamos deletar essa linha. Vamos mudar o nome dessa variável para importar o nome da carteira e aumentar o número da carteira denominada. Usaremos essa variável para nomear a carteira importada, pois não podemos criar duas carteiras com o mesmo nome. Vamos passar a variável de senha para essa chamada de método. Depois de importar a carteira, vamos gerar um bloco. Para fazer isso, vamos primeiro gerar um endereço de nota usando o cliente node get new address. Em seguida, chamamos o método generate to address, passando o endereço do nó como parâmetro para gerar um bloco. Agora, vamos chamar o método de sono para esperar que o bloco seja minerado. Por fim, vamos alterar o saldo total esperado. Espera-se um saldo de um Bitcoin confirmado e zero Bitcoin não confirmado. O resto do teste permanece como está. Agora. Vamos até o playground dot FXML para criar o menu de recursos de importação. Vamos duplicar a tag do menu de carregamento e seu conteúdo. Vamos alterar esse atributo de texto para importar. Esse ID de correção para importar o menu FXML. Vamos também adicionar o atributo de ação aqui com seu valor referente ao método open end port wallet dialog criará esse método posteriormente para responder a um clique neste item de menu abrindo um janela de diálogo. Vamos até o Scene Builder para ver como fica. Ok, o menu Importar foi adicionado ao lado do menu de carregamento. Agora vamos copiar e colar esse código na janela principal FXML. Vamos criar esse método no controlador da janela principal. Seu código será muito semelhante ao método de diálogo de criação de carteira aberta. Então, vamos copiá-lo e colá-lo aqui. Vamos mudar o título do diálogo para importar a carteira. E vamos substituir o campo de diálogo de carregamento da carteira pelo campo de diálogo de importação da carteira aqui. Vamos criar esse campo e injetá-lo nessa classe. A anotação de valor aqui apontará para a caixa de diálogo de importação da carteira FXML. Agora vamos criar a entrada enquanto um diálogo FXML no pacote FXML. Vamos usar o conteúdo do diálogo de criação de carteira FXML como base para criá-lo. Agora vamos mudar o texto do cabeçalho do diálogo. Em vez de clicar em Criar, vamos pedir ao usuário que insira uma semente mnemônica válida. Em seguida, vamos mudar o controlador FX para importar o controlador de diálogo da carteira. Agora, vamos para o Scene Builder. Vamos excluir o botão Criar. Vamos colocar um rótulo aqui e alterar seu texto para a data de criação. Vamos adicionar um controle de seletor de data à célula. Vamos clicar na área de texto da semente mnemônica e torná-la editável. De volta ao editor de texto. Vamos mudar esse nome Fxi de toilette e esse ID fx para a senha da carteira. Vamos definir o FX ID do seletor de datas para a data de criação. Agora vamos criar o controlador de diálogo de importação da carteira no pacote de controladores. Vamos adicionar a anotação do componente a ela. Vamos adicionar todos esses campos FXML ao controlador. Vamos tornar todos esses campos privados. E vamos adicionar a anotação FXML a eles. Vamos copiar e colar o método inicializado do controlador de diálogo de criação de carteira em nosso novo controlador. E vamos fazer o mesmo com todas as entradas necessárias atendidas. Vamos mudar essa variável de nome para o nome da carteira. Também vamos copiar e colar esse método em nossa nova classe. No manipulador de eventos do botão OK chamaremos o método de importação da carteira. Esse método simplesmente criará uma carteira usando o tipo de dados do usuário. Então, vamos usar o método create wallet do controlador de diálogo Create Wallet como base para criá-la. Vamos injetar o serviço de criação de carteira nessa classe. Vamos mudar essas variáveis para as deste Controlador. E vamos injetar o número inicial de endereços gerados nessa classe. Vamos fazer o mesmo com esse campo de contexto. Agora, em vez de usar uma nova data como parâmetro para esse método, chamará o método de data de cobrança. Vamos criar esse método. Usaremos a seguinte lógica aqui. Se o usuário não escolher uma data, usaremos a data em que o Bitcoin começou a funcionar. Se ele escolher, usaremos a data escolhida. O parâmetro de data definirá até que ponto, no passado iremos encontrar informações sobre os endereços da carteira importada. Quanto mais antigo o estado, mais tempo o nó levará para importar a carteira. Então, vamos usar o método de data padrão para definir a data padrão. Aqui, usaremos o objeto de formato de data simples com o seguinte parâmetro. Em seguida, tentaremos retornar a chamada do método de análise de formato de data simples passando a constante de data padrão como seu parâmetro. Usaremos o bloco catch para agrupar a exceção de análise em uma exceção de tempo de execução. Vamos definir essa constante, que é a data em que o Bitcoin começou a funcionar. Aqui. Se a data de criação não for nula, redefinimos a variável de data com o seguinte valor. Finalmente, retornamos a data. Depois de criar a carteira, publicará o evento da carteira importada. Vamos criá-lo no pacote de eventos de pontos da GUI. Aqui, passaremos esse parâmetro para o superconstrutor e definiremos o campo da carteira como o parâmetro da carteira. Vamos criar um getter para esse campo. Agora, vamos até o ouvinte da carteira Save. Esse ouvinte responderá aos eventos da carteira importada para salvar carteiras importadas. Vamos refatorizá-lo para que ele possa ouvir mais de um evento. Para fazer isso, vamos remover essa declaração de implementos. Vamos mudar esse método chamado evento de carteira não criado. Vamos adicionar a anotação do ouvinte do evento a ela. Agora, vamos criar o método de evento de carteira sem importância, passando o evento importado da carteira como parâmetro. Vamos copiar e colar essa linha aqui. E vamos adicionar a anotação do ouvinte de eventos a esse método. Definir uma anotação de pedido para métodos anotados pelo ouvinte de eventos tornará a ordem de execução desses ouvintes previsível. Quanto menor for o parâmetro de anotação do pedido, maior será a prioridade desse ouvinte executar em comparação com outros ouvintes do mesmo evento. Então, vamos adicionar essa anotação a esse método. Vamos passar zero como parâmetro para tornar esse ouvinte o primeiro desse tipo a ser executado Vamos adicionar a mesma anotação ao método de evento de carteira não criado. Priorizamos salvar a carteira primeiro após sua criação para garantir que, se os ouvintes posteriores falharem, pelo menos salvaremos seu DataFirst. Agora vamos para o ouvinte de importação de carteira criado. Queremos que esse ouvinte importe a carteira importada para o nó Bitcoin. Então, vamos duplicar o método de evento da carteira descarregada. Vamos mudar seu nome para um evento de carteira sem importância e torná-lo exceto o evento apropriado. Agora vamos adicionar a anotação do pedido a esses métodos. Os ouvintes de eventos da carteira importados e criados receberão um como seus parâmetros e o ouvinte de eventos da carteira carregada, zero. Dessa forma, garantimos que, quando a carteira tentar buscar dados do nó , eles já serão importados pelo nó. Agora, vamos até o ouvinte da carteira carregada e adicionar um método de ouvinte para o evento da carteira importada, como acabamos de fazer na aula anterior. Agora, vamos adicionar uma anotação de pedido aos dois métodos, passando para como parâmetro para o evento da carteira sem importância e outra para o método de evento da carteira descarregada para fazer com que esses ouvintes funcionem depois todos os outros para seus eventos. Agora, vamos executar nosso node. E vamos fazer esse teste. O primeiro teste foi aprovado, mas o segundo falhou. Vamos ver o porquê. Ok, uma exceção de violação de restrição ocorreu porque tentamos salvar uma carteira com o mesmo nome duas vezes. Esquecemos de alterar a variável do nome da carteira na chamada do método de importação da carteira para a variável de nome da carteira de importação. Vamos corrigir isso e executar o teste com defeito novamente. Ótimo, já passou. 74. 72 Validar a habilidade: carteira 2: Neste vídeo, implementaremos algumas validações antes de criar uma carteira de importação e tentar enviar transações. A primeira validação impedirá que a criação da carteira continue se o nome da carteira for igual ao nome da carteira criada anteriormente. Então, vamos fazer o teste de criação de carteira para criar um teste para essa condição. Será chamado não deve criar uma carteira com nome repetido. Vamos criar uma carteira no bloco fornecido, criando as variáveis necessárias e usando-as no método create wallet. No bloco único, vamos adicionar um código para criar uma carteira com o mesmo nome da criada no bloco fornecido, mas agora usando a GUI. Depois de tentar criar a carteira, vamos adicionar a chamada do método suspenso aqui Esperamos que o aplicativo mostre uma janela de diálogo de alerta contendo uma mensagem dizendo que o nome da carteira já existe. Então, vamos definir uma variável contendo a mensagem. Agora, usaremos o método de pesquisa para obter um componente com essa mensagem e armazená-lo na variável de consulta do nó. Por fim, clicaremos no botão OK para fechar a janela de diálogo. No bloco de então. Vamos adicionar a comparação a seguir para verificar se mensagem na janela da caixa de diálogo de alerta é igual à variável da mensagem de erro. Agora, vamos para o controlador de diálogo de criação de carteira. No método create wallet, usaremos uma declaração if com um serviço de validação de carteira para verificar se o nome da carteira é válido. Então, vamos injetar esse serviço nessa classe. Vamos criar esse serviço e o pacote de serviços de pontos do banco de dados. E vamos terminar de injetá-lo nesta classe. Na instrução if, vamos chamar o método wallet exists nela, passando o texto do nome como parâmetro. Vamos criar esse método. Usaremos o serviço de erro de alerta e o corpo if. Então, vamos injetá-lo nessa classe. Agora, chamaremos o método de erro de alerta nele como seu parâmetro. Vamos passar essa constante. Vamos criar essa constante na classe de mensagens de erro. Ele terá o mesmo texto que definimos no teste. Vamos importar essa constante aqui e chamar a declaração de retorno. Agora, vamos ao serviço de validação de carteira. Na carteira existe, o método conduzirá o repositório da carteira. Então, vamos injetá-lo nessa classe. Agora, retornaremos a chamada do método exists by name para ele, passando o nome da carteira como parâmetro. Vamos criar esse método apenas com essa assinatura de método. O Spring Data JPA magic já sabe como consultar as informações desejadas do banco de dados. Vamos fazer o teste de criação de carteira. Vamos comentar esses testes. Execute nosso node e execute nosso novo teste. Ótimo, o teste foi aprovado. Vamos descomentar esses testes. Agora, vamos adicionar a mesma validação do nome da carteira no recurso de importação de carteira. Então, vamos copiar esse teste e colá-lo aqui no teste de importação da carteira. Vamos mudar seu nome para não deve importar uma carteira com nome repetido. Vamos fazer algumas adaptações nesse teste. Primeiro, vamos aumentar a carteira chamada número. Em seguida, vamos modificá-lo para importar uma carteira aqui em vez de criá-la. E vamos mudar os parâmetros dessas chamadas de método. Agora, vamos até o controlador de diálogo de criação de carteira e copie-o se bloquear aqui. E vamos colá-lo aqui no controlador de diálogo da carteira. Vamos injetar os serviços necessários nessa classe. Vamos mudar essa variável para o nome da carteira. Agora, vamos comentar esses testes e executar nosso novo teste. Grau. O teste foi aprovado. Vamos descomentar esses testes. Agora, vamos adicionar uma validação de endereço. Ao tentar enviar transações. Atualmente, podemos digitar qualquer coisa no campo de endereço a ser enviado. Se tentarmos enviar uma transação para um endereço inválido e ocorrer um erro e ela for ignorada silenciosamente pelo aplicativo sem que o usuário perceba, implementaremos uma validação que fará uma caixa de diálogo de alerta aparecerá na tela se o endereço a ser enviado for inválido. Primeiro, vamos fazer o teste de envio de Bitcoin para criar um teste para esse cenário. Digamos que não deve enviar Bitcoin para um endereço inválido. Vamos adicionar código para criar uma carteira usando a interface gráfica e o bloco de vento. Vamos aguardar a criação da carteira. Agora, vamos copiar e colar esse código aqui para enviar fundos para a carteira. Vamos criar essa variável de valor anterior aqui e definir seu valor como 0,1. Vamos definir um para o segundo método de intervalo chamado parâmetro. Agora vamos criar um endereço de nó e gerar um bloco para ele. Vamos clicar na guia Enviar e chamar o método de envio de Bitcoin para tentar enviar 0,01 Bitcoin para o endereço para enviar a variável. Como a variável de endereço a ser enviado conterá endereços inválidos, esperamos que uma janela de diálogo de alerta apareça contendo uma mensagem dizendo que o endereço a ser enviado é inválido. Então, vamos criar uma variável de mensagem de erro com a seguinte mensagem. Agora, usaremos o método de pesquisa para obter um componente com essa mensagem e armazená-lo na variável de consulta do nó. Por fim, clicaremos no botão OK para fechar a janela de diálogo. Em seguida, bloqueie, vamos adicionar a comparação a seguir para verificar se a mensagem na janela da caixa de diálogo de alerta é igual à variável da mensagem de erro. Vamos definir o endereço para enviar a variável com alguns casos de teste no bloco where. Aqui, vamos passar nesses casos de teste disponíveis na página Projeto e Recursos. Cada caso de teste tem um erro. As diferentes partes do código serão detectadas. O primeiro caso de teste é uma string com um prefixo inexistente. O segundo caso tem um prefixo de teste de registro correto, mas um endereço inválido restante. Os próximos três endereços seriam endereços de teste de registro válidos, mas seus últimos caracteres foram alterados. Durante a construção do endereço. Parte do endereço usa o restante do endereço a ser criado. Essa parte é a soma de verificação do endereço e sua função é detectar alterações de endereço. Durante a decodificação do endereço, a soma de verificação é verificada e esperaríamos que ocorresse um erro se essa verificação falhar. Os últimos três endereços são válidos, mas não são do ambiente de teste de registro, portanto, devem ser considerados inválidos. Vamos até o localizador de configuração do script. Na chamada do método throw de URLs, vamos passar um lambda cujo corpo retornará uma nova exceção de criação de transação com uma constante de endereço inválida da classe de mensagens de erro. A exceção de criação de transação já foi detectada posteriormente no código e sua mensagem já é exibida em uma janela de diálogo de alerta. Vamos criar essa constante na classe de mensagens de erro. Ele terá o mesmo texto que definimos no teste. Com essa modificação, esperamos que a validação cubra endereços com prefixos inválidos. Agora, vamos ao serviço de criadores de transações. Vamos agrupar o código no método de saída de construção em um bloco try-catch. No bloco de captura, a exceção de criação de transação passará a exceção de criação de transação a constante de endereço inválida. Com essa modificação, esperamos que a validação cubra erros de decodificação de endereços cuja verificação da soma de verificação falhe. Vamos fazer o teste de envio de Bitcoin. Agora, vamos comentar esses testes e executar nosso novo teste. Os últimos três casos de teste falharam. Nossa carteira conseguiu enviar fundos para esses endereços. Isso aconteceu porque a decodificação do endereço descarta os prefixos de endereço. Obviamente, as transações foram enviadas somente no ambiente de teste de registro. Portanto, tornar esses endereços inválidos é importante para evitar situações em que você acha que está administrando sua carteira em um ambiente, mas na verdade ela está sendo executada em outro. Vamos consertar isso. Vamos para a classe de correspondência de endereços. Vamos criar esse método de segmento. Ele retornará um predicado de string. E usará um ambiente suficiente como parâmetro. Agora, criaremos um objeto de mapa com ambientes como chaves e predicados de cadeias de caracteres como valores. Usaremos o mapa do método para criar esse mapa. Para cada ambiente, será definido um Lambda para validar se o parâmetro de endereço tem o prefixo esperado para esse ambiente. Para os seguintes endereços de rede principais, esperamos que eles não comecem com o BCR e comecem com BC endereços de rede de teste do BC. Começaremos com os testes de TB e de registro. Começaremos com BCR t. Em seguida, retornaremos a chamada do método map.get passando o ambiente como seu parâmetro. Agora, vamos duplicar esse método e mudar seu nome para seu segmento aninhado. Nesse caso, muitos endereços de rede. Começaremos com três testes, endereços de teste net e reg. Começaremos com dois. Vamos duplicar esse método e mudar seu nome para seus endereços de rede principais legados. Começaremos com um. Teste os endereços de teste net e reg. Começaremos com M ou N. Agora, vamos remover esses Lambdas dessa classe. Agora vamos para a classe de configuração de endereço. Vamos adicionar esse campo de ambiente Bitcoin. Vamos adicionar uma anotação de valor aqui para injetar o valor desse campo usando a configuração de propriedades de pontos do aplicativo de ambiente Bitcoin . Agora vamos alterar o parâmetro do segmento aqui para chamá-lo como um método e passar o campo de ambiente Bitcoin como seu parâmetro. Vamos fazer o mesmo com esses parâmetros de segmentos aninhados aqui. Agora, vamos para a classe de configuração de script. Faremos a mesma modificação que acabamos de fazer na classe de configuração de endereço. Vamos injetar o ambiente Bitcoin nessa classe e modificar os beans de configuração do script para chamar os métodos adequados de correspondência de endereços. Agora, antes de executar nosso novo teste novamente, vamos corrigir alguns testes. No teste do gerador sequencial de endereços, devemos definir o ambiente Bitcoin na instanciação de configuração de endereço desta forma. Vamos fazer esse teste. Ótimo, ainda está passando. Agora, vamos fazer o mesmo com o teste do serviço de criação de carteira. Ok, ainda está passando. Vamos fazer o mesmo com o teste de sorteio único e aleatório de um seletor de moedas. Desta vez, temos que definir o ambiente Bitcoin na configuração do script como. Vamos executá-lo. Ótimo , ainda está passando. Agora, vamos corrigir o teste do serviço de criadores de transações. Ok, ainda está funcionando. Por fim, vamos fazer o mesmo corrigido no teste da calculadora do tamanho da transação. Mas desta vez, temos que configurar os ambientes Bitcoin para testar a rede. Como usamos endereços de rede de teste neste teste, nota, os testes foram aprovados. Agora vamos fazer o teste de envio de Bitcoin. Vamos comentar esses casos de teste para executar somente os três últimos. Vamos executá-lo. Ótimo, os testes foram aprovados. Vamos descomentar esses testes. E vamos corrigir esse teste chamado letra. Ele envia, não é enviado. 75. 73 skillshare 2: Neste vídeo, adicionaremos uma seção de rodapé à janela principal do nosso aplicativo. O rodapé conterá uma barra de progresso e um rótulo de texto. A barra de progresso estará ativa quando nossa carteira se comunicar com nosso node, o que às vezes pode levar algum tempo. O rótulo de texto mostrará uma breve descrição da atividade que nossa carteira está realizando durante essa comunicação. Então, vamos criar essa seção no ponto FXML do playground. Vamos até o Scene Builder. Primeiro. Vamos adicionar uma caixa H na parte inferior da janela principal. Vamos mudar a largura pref da caixa H para 600 e a altura pref para 19. Agora vamos adicionar uma barra de progresso à caixa H. Vamos também adicionar um rótulo a ele. Definiremos a margem esquerda do rótulo como dez e seu texto como uma string vazia. Agora, no editor de texto, vamos copiar esse código aqui e colá-lo na janela principal, ponto FXML. Agora vamos encapsular a barra de progresso e os componentes rotulados em arquivos FXML. Primeiro, vamos criar a barra de progresso FXML. Vamos excluir esse conteúdo. Vamos criar uma tag raiz ética com um tipo apontando para a classe Java FX da barra de progresso. Agora vamos copiar os atributos da tag e do ponto FXML da janela principal e colá-los em nosso novo FXML. Vamos definir essa tag XML NSF X na janela principal, FXML. Vamos excluir essa barra de progresso em seu lugar. Vamos adicionar a tag do controlador da barra de progresso, que será criada posteriormente. Agora, vamos criar um arquivo FXML de ponto de rodapé para encapsular a tag do rótulo. Vamos deletar esse código. Vamos copiar e colar o código da tag do rótulo da janela principal FXML para o novo FXML. Vamos mudar a tag do rótulo para uma tag raiz ética com um tipo apontando para a classe rotulada Java FX. Vamos adicionar esse atributo XML NSF x à nova tag. Agora vamos adicionar as importações ausentes a esse arquivo. Volte para a janela principal. Vamos substituir a tag do rótulo copiado pela tag do controlador de rodapé. Agora vamos criar o controlador da barra de progresso e importá-lo aqui. Vamos fazer o mesmo com o controlador de rodapé. Agora, vamos para o controlador da barra de progresso. Vamos adicionar a anotação do componente a ela. Vamos usar o construtor do controlador da guia Receber como base para criar o construtor do controlador da barra de progresso. Vamos corrigir sua anotação de nome e valor para apontar para as corretas. E vamos excluir a carteira atual pois não precisaremos dela. Agora, vamos copiar esse construtor e colá-lo no controlador de rodapé. Vamos corrigir o nome do construtor e adicionar a anotação do componente a essa classe. Vamos fazer com que a anotação do valor aponte para o FXML correto. Agora vamos fazer com que essa classe estenda a classe de rótulo. E a classe do controlador da barra de progresso estenderá a classe da barra de progresso. Vamos até a classe de ouvinte da GUI e adicionar os dois controladores ao conjunto para que sejam configurados como componentes personalizados. Agora, vamos criar um observável que modelará o estado do progresso. Será a classe de progresso assíncrona criada no pacote observables. Vamos adicionar uma anotação de componente a ela. Para definir o estado da barra de progresso, criará um campo de propriedade duplo chamado progresso. Vamos instanciá-lo aqui com um novo objeto simples de propriedade dupla usando zero como parâmetro. Posteriormente, o parâmetro zero, que define o estado da barra de progresso como inativo, será passado para a barra de progresso. Agora vamos criar o campo de descrição da tarefa. Será uma propriedade de string e definiremos o texto do rótulo do rodapé. Vamos instanciá-lo usando uma nova propriedade de string simples. Vamos criar getters para ambas as propriedades. O IDE criou dois getters para cada campo, um para a propriedade e outro para o valor da propriedade e precisará somente dos getters para as propriedades. Então, vamos excluir os outros getters. Agora, vamos criar o método de início aqui. Vamos usá-lo para definir o valor do progresso para a constante de progresso indeterminada. O valor dessa constante fará com que a barra de progresso mostre uma barra se movendo para a esquerda e para a direita, indicando que alguma tarefa está sendo executada em segundo plano. Vamos também definir o método stop, que retornará o valor do progresso a zero. Portanto, a barra de progresso ficará inativa, indicando que nenhuma tarefa está sendo executada em segundo plano. Por fim, vamos criar o método de descrição da tarefa definida. Ele usará uma string como parâmetro. E ele definirá o parâmetro de descrição no campo de descrição da tarefa. Agora, para controlar quando a barra de progresso e o rótulo do rodapé mudam, usaremos um aspecto. Vamos criar a classe de aspecto de progresso no pacote de serviços de pontos da GUI. Em Spring Boot. E o aspecto é um modificador de método. Usaremos um aspecto para definir que cada método anotado com uma anotação específica iniciará a barra de progresso para encontrar o texto e o rótulo do rodapé, executar o código no método e reverta o estado da barra de progresso e do rótulo. Para fazer isso, vamos adicionar as anotações de aspectos e componentes a essa classe. Vamos injetar o progresso assíncrono observável nessa classe. Agora vamos criar o método de ativação da barra de progresso. Ele retornará um objeto. Vamos adicionar a anotação circular a esse método, pois seu parâmetro passará uma string com o texto na anotação, abrirá parênteses, ativará a barra de progresso fechará o parêntese. Essa anotação define que o aspecto executará o código antes e depois de seus métodos modificados. No parâmetro de ativação da barra de progresso, definiremos que o aspecto modificará os métodos anotados com uma anotação com esse nome. Agora, vamos adicionar dois parâmetros a esse método. O primeiro será o ponto de junção anterior, que será uma alça para o método anotado. A segunda será a barra de progresso de ativação, que dará acesso aos parâmetros de anotação. Então, vamos criar essa anotação, vamos criá-la em um novo pacote de anotações de GUI. Para fazer disso uma anotação, precisamos modificar essa palavra-chave em uma interface. Vamos adicionar a anotação de destino a esse arquivo, pois seu parâmetro passará a constante do método. Isso fará com que a anotação seja válida somente em métodos, não em classes ou campos. Vamos também adicionar a anotação de retenção passando a constante de tempo de execução como seu parâmetro. Isso tornará essa anotação ativa em tempo de execução. Por fim, vamos adicionar o campo de valor da string a essa anotação. Esse campo será preenchido pelo parâmetro passado para essa chamada de anotação. De volta à classe de aspectos do progresso. Aqui, dentro de uma plataforma, executada posteriormente, uma chamada de método passará um lambda cujo corpo chamará o método assíncrono de descrição da tarefa do conjunto de progresso, passando o valor da barra de progresso de ativação, como seu parâmetro também o fará. chame o método de início de progresso assíncrono aqui. Agora, chamaremos o método proceder do ponto de junção anterior e o objeto retornado de armazenamento na variável de resultado. O método continue fará com que o método anotado seja executado e retornará seu resultado. Agora, encapsulado em uma plataforma, o método de execução posterior mudará novamente os estados dos campos de progresso assíncronos. Mas, desta vez, definiremos a descrição da tarefa como uma string vazia e chamaremos o método stop no progresso assíncrono. Finalmente, retornaremos a variável de resultado contendo o objeto retornado pelo método anotado. Agora vamos para o controlador da barra de progresso. Vamos injetar o progresso assíncrono observável nessa classe. Vinculará o campo de progresso de progresso assíncrono à propriedade de progresso desse controlador no método inicializado. Vamos para o controlador de rodapé. Vamos injetar o progresso assíncrono observável nessa classe. No método inicializado, vinculará o campo de descrição da tarefa de progresso assíncrono à propriedade de texto desse controlador. Agora, para que a barra de progresso funcione, precisamos anotar os métodos que queremos para rastrear o progresso com a anotação da barra de progresso de ativação. Vamos fazer isso primeiro no serviço de importação de carteiras. Vamos passar a string com a carteira de carregamento de textos como parâmetro. Vamos copiar essa anotação e colá-la aqui no método de assinatura e envio do serviço de transação sin. Vamos mudar seu parâmetro para enviar a transação. Vamos também adicionar essa anotação ao atualização das classes de serviço utxOS método de atualização das classes de serviço utxOS de atualização como seu parâmetro. Vamos passar a frase atualizando UTXOs. Agora, vamos executar nosso node. E vamos executar o teste de envio de Bitcoin legado para verificar a barra de progresso em ação. Como vimos, a barra de progresso e o rótulo do rodapé estão funcionando conforme o esperado. Ótimo. 76. 74 Atualizar dependências skillshare 2: Neste vídeo, atualizaremos as dependências do nosso projeto. Manter as dependências de um projeto atualizadas é uma boa prática. Ao fazer isso, nos beneficiamos de bugs e correções de vulnerabilidades de segurança aplicadas às nossas dependências, mantendo nosso aplicativo mais seguro. Então, vamos para o arquivo xml palm dot aumentar a versão de nossas dependências obsoletas. Dependendo de quando você as estiver atualizando, versões mais recentes podem estar disponíveis. Vamos aumentar a versão inicial inicial do Spring Boot. Para mim, a versão mais recente é 2.7. 0.5 aumentará a versão Java para 19. Vamos remover essa versão divertida agora, já que não é mais necessária, sua versão será definida automaticamente. Vamos ver as configurações da estrutura do projeto. Vamos atualizar a versão Java do projeto. Se necessário, a versão Java não está disponível. Você pode clicar em adicionar SDK para baixá-lo. Vamos definir o nível do idioma do projeto para o mais recente disponível. Agora, vamos aumentar a versão dos controles Java FX. Vamos fazer o mesmo com o JavaFX FXML. Agora, vamos atualizar o plug-in Java FX Maven e o plug-in G Maven para verificar a exatidão. Vamos atualizar a versão Bitcoin Java para 0,4, 0,4 na configuração do plug-in de dependência do Maven. Agora vamos clicar no botão carregar alterações do Maven. Agora vamos atualizar a versão do Bitcoin Core Node para 23. Vamos baixá-lo no site Bitcoin core.org. Vamos baixar a versão 23 e instalá-la na mesma pasta da versão anterior. Eu já fiz isso, então vou pular essa parte. Agora. Certifique-se de definir o sinalizador do ambiente de teste reg no arquivo bitcoin.com. Antes de executar nosso node, vamos excluir as pastas de teste de registro dentro da pasta Bitcoin sem dados e da pasta do banco de dados do nosso aplicativo. Faremos isso apenas para limpar nosso ambiente de teste. Agora, vamos executar nosso node examinando o console. Observe que nosso node está executando a versão 23. Bom. Agora, precisamos fazer uma pequena modificação para nossa carteira funcione corretamente com a nova versão do Bitcoin Core Node. Vamos consultar a documentação do método RPC de criação de carteira para entendê-lo melhor. Na versão 23 do Bitcoin Core, o argumento dos descritores do método RPC create wallet é padronizado como verdadeiro, enquanto na versão anterior ele foi definido como falso. Isso faz com que nossa carteira de aplicativos não consiga chamar alguns métodos de RPC que usamos para corrigi-los Isso o definirá manualmente como falso para que a alteração não nos afete mais. Então, vamos ao cliente node create wallet. Vamos adicionar os seguintes parâmetros aqui. Vamos adicioná-los à assinatura do método de criação de carteira. Além disso, o parâmetro de chaves privadas desabilitado será um booleano e definirá se a carteira de nós criada gerará chaves privadas. Quando definido como verdadeiro, o parâmetro blank cria uma carteira de nós sem sementes e chaves. A senha define senha opcional para criptografar o NerdWallet. Como o nome sugere, o parâmetro avoid reuse define uma política para evitar a reutilização de endereços. Finalmente, o parâmetro de descritores define se a carteira de nós criada é uma carteira descritora. Uma carteira descritora é um novo tipo de carteira no Bitcoin Core Node que não usaremos. Agora, vamos para o serviço node load ou create wallet. Vamos adicionar essas variáveis a essa chamada de método. Agora vamos copiar esse código e o cliente node create wallet e colá-lo aqui. Agora vamos ao serviço de carteira. Vamos adicionar os seguintes valores a essa chamada de método. Aqui, definiremos as chaves privadas desativadas e os parâmetros em branco como verdadeiros. Desde nosso aplicativo, embora não exija que o node crie chaves e sementes privadas para nós. A frase secreta será uma string vazia. Definiremos o parâmetro avoid reuse como false, pois nosso nó gerará endereços para nós e o parâmetro dos descritores será falso. Agora, vamos para a aula de teste de GUI. Nessa chamada de método, vamos passar os seguintes valores. Ao contrário do caso anterior, desta vez, queremos gerar chaves e sementes privadas porque usaremos a carteira node para enviar bitcoins em nossos testes. Portanto, os dois primeiros parâmetros serão falsos. A terceira será uma string vazia. O parâmetro de evitar reutilização será definido como verdadeiro. Portanto, o node evitará a reutilização de endereços para nossa carteira de teste e o argumento dos descritores será falso. Agora vamos fazer mais uma modificação por algum motivo após atualizar nossas dependências quando há dois botões ok na tela durante alguns testes, test FX acaba clicando no botão errado. Para corrigir isso, vamos acessar o erro ou serviço de alerta. Adicionará um ID Fx ao botão OK de alerta programaticamente. Para fazer isso, vamos criar a variável ok. aqui. Usaremos o método de pesquisa para obter a referência do botão e atribuí-la à variável ok., dessa forma. Em seguida, configuraremos o ID para alertar. Ok. Agora vamos fazer o teste de criação de carteira. Neste teste, em vez de chamar o método click on com o parâmetro ok, vamos passar uma referência ao botão OK da caixa de diálogo de alerta usando seu ID. Agora, este teste clicará inequivocamente no botão certo de OK. Vamos fazer o mesmo com todos os outros testes com o mesmo problema no projeto. Vamos corrigir o que está no teste da carteira de importação. Agora, vamos fazer isso no teste send Bitcoin Nested Segue. Finalmente, vamos corrigir os testes e enviar o teste de Bitcoin. Agora, como exercício, deixarei que o aluno execute todos os testes de inscrição. 77. 75 Skillshare 2: Neste vídeo, instalaremos e executaremos nosso aplicativo no ambiente de rede principal. Como lidaremos com dinheiro real, é altamente recomendável que você garanta que todos os testes de aplicação sejam aprovados. Além disso, é aconselhável começar a jogar com pequenas quantidades de Bitcoin. Primeiro, vamos atualizar a biblioteca Bitcoin Java para a versão 0.4, 0.5 no arquivo POM. Esta versão corrige um problema ao importar o arquivo da lista de palavras ao executar o aplicativo após instalá-lo. Vamos até o serviço de sementes mnemônicas e remover essas declarações, pois não precisamos mais delas. Vamos fazer o mesmo com esse método de criação de sementes mnemônicas no controlador de diálogo de criação de carteira. Agora, vamos executar nosso node no ambiente de rede principal. Para fazer isso, vamos acessar nosso arquivo bitcoin.com e remover a linha de configuração do reg test, salvar o arquivo e executar o nó Bitcoin. Ok, agora nosso node está sendo executado no ambiente de rede principal. Aí vem a parte triste. Pode levar dias ou semanas para sincronizar nossa nota no ambiente principal da rede, pois, por enquanto, ela tem 436 GB de tamanho. No meu caso, o console indica que o progresso do download do blockchain é de cerca de 52%. Mais adiante neste vídeo, mostrarei o aplicativo em execução na minha outra máquina, que já foi completamente sincronizada. Por enquanto, vamos modificar nosso aplicativo para executá-lo no ambiente de rede principal. No arquivo de propriedades de pontos do aplicativo, vamos modificar o ambiente Bitcoin configurando duas redes principais. Atribuiremos a porta 83 32 à configuração do URI RPC note. Essa é a porta padrão que o node Bitcoin usa para expor sua API RPC na rede principal. Em seguida, vamos definir a chave de criptografia na configuração do URL da fonte de dados spring para essa variável de ambiente que exige que definamos essa variável de ambiente em nosso sistema operacional antes de compilarmos nosso código. Ao fazer isso, aumentamos a segurança do nosso aplicativo, evitando expor as variáveis do banco de dados em nosso código. Vamos fazer o mesmo com os valores das configurações de nome de usuário e senha do Spring Data Source. Agora vamos gerar valores seguros para essas configurações. Para fazer isso, vamos usar o gerenciador de banco de dados SQL para conseguir isso chamando a função de chave criptografada desta forma. Vamos gerar três valores copiá-los e colá-los em um arquivo de texto. É importante que você mantenha esses valores em um local seguro, pois qualquer alteração nesses valores antes de compilar o aplicativo novamente resultará na perda do acesso ao banco de dados. Se isso acontecer, você ainda terá acesso à sua carteira. Se você mantiver suas carteiras, mnemônica e senha , precisará excluir os arquivos do banco de dados e compilar o aplicativo novamente. Agora, vou colar esses valores de variáveis de ambiente diretamente no aplicativo que as propriedades dos pontos podem corrigir. Estou fazendo isso porque, pelo menos na minha máquina Windows, o aplicativo não interpola esses valores com o ambiente do sistema. Primeiro, o mesmo problema não acontece no Linux. Então eu acho que é algum tipo de bug estranho durante a compilação. Diga-me na seção de comentários se você teve o mesmo problema. Assim, podemos encontrar uma solução para esse problema juntos. Por enquanto, podemos seguir em frente com o aplicativo dot properties is, is in the Maven tab. Vamos clicar com o botão direito do mouse no botão Instalar. Clique em modificar a configuração de execução. Na guia do corredor. Vamos ativar a caixa de seleção pular testes para que o comando de instalação do Maven não execute os testes do aplicativo antes de instalar o aplicativo. Se você estiver usando versões mais recentes do IntelliJ AID, essa opção pode estar disponível no ícone de configuração nesta janela. Clique no botão OK. Agora, clique duas vezes na opção de instalação personalizada dentro da seção Executar configuração. Ótimo, o aplicativo foi instalado com sucesso dentro da pasta indicada no console. Antes de executá-lo, certifique-se de instalar o Java SDK com a mesma versão do aplicativo. Vou acessar o site da Oracle para fazer o download e instalá-lo. Depois de instalá-lo, feche e abra o terminal. Agora, copie o caminho em que seu aplicativo instalou o arquivo JAR do aplicativo. Você pode usar o comando java space double hyphen version para garantir que seu terminal execute a versão correta do Java. Agora execute o comando java space, hyphen jar space, o caminho que você acabou de copiar. Ótimo, o aplicativo foi iniciado com sucesso no ambiente de rede principal. Vamos tentar criar uma nova carteira. Ele criou uma nova carteira com sucesso, mas como nosso node ainda está afundando, a barra de progresso do carregamento permaneceria ativa por um longo tempo antes que pudéssemos testá-la. Agora, mostrarei a carteira funcionando no ambiente de rede principal da minha máquina Linux, onde o nó está 100% sincronizado. Então, acabei de instalar o aplicativo da mesma forma que fizemos para o Windows. Isso mostra uma grande vantagem do Java, que é a compatibilidade perfeita entre plataformas. Vamos executar o aplicativo. De agora em diante, vou esconder alguns dados que você verá na tela por motivos de privacidade. Primeiro, eu carrego uma carteira. Eu já o criei corretamente carregado conforme o esperado. Agora, vou criar uma nova carteira. Vou anotar a semente mnemônica usando caneta e papel antes de clicar no botão OK. Agora, vou copiar o endereço e colá-lo em um editor de texto. Agora, vou carregar a carteira anterior, que contém alguns fundos. Agora vamos enviar alguns Satoshi para o endereço que copiamos da tabela de endereços. Podemos ver que um novo endereço de mudança recebeu alguns fundos. Ótimo. Na tabela de transações, vemos que uma nova transação com confirmação zero foi criada. Agora vamos abrir a carteira que recebeu fundos. Podemos ver que tanto a tabela de endereços quanto a tabela de transações têm um novo registro indicando que recebemos alguns Satoshi com sucesso. Ótimo, tudo está funcionando corretamente. 78. Extra class - Bitcoin Core v26: Bem-vindo à nossa primeira aula extra sobre como atualizar nosso aplicativo para se comunicar com a versão 26 do núcleo do Bitcoin. Veremos que há boas razões para se manter atualizado com a versão mais recente do Bitcoin Core. Primeiro, vamos visitar este site para baixar a versão 26 do núcleo do Bitcoin. Clique na versão apropriada para seu sistema operacional. Como estou usando o Windows, vou baixar o arquivo. Essencialmente, substituiremos a versão atual do núcleo Bitcoin que temos Certifique-se de escolher o mesmo caminho de instalação que o atual. No meu caso, não vou continuar com a instalação, pois já a tenho. Mas para você, deve ser tão simples quanto clicar no botão Avançar várias vezes antes de executar a versão recém-instalada. Vamos explorar os benefícios imediatos que ele oferece, começando com a versão 25 do núcleo do Bitcoin. Podemos ver em suas notas de lançamento que ele implementa um novo índice que acelera significativamente as digitalizações Re da carteira Para optar por esse novo filtro, basta adicionar o filtro de bloco igual uma configuração ao nosso arquivo de configuração Bitcoin Ao reiniciar o nó, ele começará a criar esse novo índice Pode levar algumas horas para ser concluído, mas depois perceberemos que carregar uma carteira depois de algum tempo sem executar nosso nó se torna muito mais rápido Agora vamos discutir algumas mudanças introduzidas nas notas de lançamento da versão 26. Descobrimos que, para usar carteiras sem descritores, precisamos definir uma configuração RPC obsoleta em nosso arquivo de configuração Bitcoin Posteriormente, as carteiras sem descritores serão descontinuadas em futuras versões principais. Não se preocupe Demonstraremos como migrar nosso aplicativo para carteiras de descritores na próxima Por enquanto, para garantir que nossas carteiras atuais funcionem com a versão 26 do núcleo do Bitcoin, vamos adicionar essa configuração ao nosso arquivo de configuração do Bitcoin Enquanto isso, vamos também adicionar que o filtro de bloco igual a uma configuração que discutimos anteriormente Agora vamos executar nosso nó principal do Bitcoin no ambiente de teste de registro. Estamos quase terminando, como sempre, com qualquer alteração significativa que fazemos em nosso aplicativo Precisamos executar todos os nossos testes para garantir que tudo esteja funcionando corretamente. Eu já fiz isso do meu lado e descobri que um teste parou de funcionar quando executado na nova versão principal do Bitcoin. Acontece que o teste de não deve enviar Bitcoin com a senha errada da classe de teste de envio de Bitcoin falhou. No entanto, não porque a transação foi enviada com sucesso, mas porque o erro real retornado diferiu do esperado Eu o depurei e descobri que a resposta de erro que o núcleo do Bitcoin envia na nova versão agora contém uma mensagem diferente, que é essa Simplesmente removemos o não do início e adicionamos a falha no final. Agora, o mapeamento entre essa resposta de erro do núcleo e nosso aplicativo deve ser preciso. É isso mesmo. Agora, se você executar nossos testes, todos eles devem passar. Na próxima aula extra, vamos nos aprofundar no que é uma carteira descritora e como adaptar nosso aplicativo para criar esse tipo de vamos nos aprofundar no que é uma carteira descritora e como adaptar nosso aplicativo para criar esse tipo de carteira. Te vejo então.